Added better mouse functionality and save.
This commit is contained in:
parent
8e8b8d3302
commit
cf2a670e0b
|
@ -0,0 +1,63 @@
|
|||
package nl.andrewlalis.erme.control.actions;
|
||||
|
||||
import lombok.Setter;
|
||||
import nl.andrewlalis.erme.model.MappingModel;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.io.*;
|
||||
|
||||
public class SaveAction extends AbstractAction {
|
||||
private static SaveAction instance;
|
||||
|
||||
public static SaveAction getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new SaveAction();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private File lastSelectedFile;
|
||||
|
||||
@Setter
|
||||
private MappingModel model;
|
||||
|
||||
public SaveAction() {
|
||||
super("Save");
|
||||
this.putValue(SHORT_DESCRIPTION, "Save the current diagram to a file.");
|
||||
this.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JFileChooser fileChooser = new JFileChooser(this.lastSelectedFile);
|
||||
FileNameExtensionFilter filter = new FileNameExtensionFilter(
|
||||
"ERME Serialized Files",
|
||||
"erme"
|
||||
);
|
||||
fileChooser.setFileFilter(filter);
|
||||
int choice = fileChooser.showSaveDialog((Component) e.getSource());
|
||||
if (choice == JFileChooser.APPROVE_OPTION) {
|
||||
File chosenFile = fileChooser.getSelectedFile();
|
||||
if (chosenFile == null || chosenFile.isDirectory()) {
|
||||
JOptionPane.showMessageDialog(fileChooser, "The selected file cannot be written to.", "Invalid File", JOptionPane.WARNING_MESSAGE);
|
||||
return;
|
||||
}
|
||||
if (!chosenFile.exists() && !chosenFile.getName().endsWith(".erme")) {
|
||||
chosenFile = new File(chosenFile.getParent(), chosenFile.getName() + ".erme");
|
||||
}
|
||||
// TODO: Check for confirm before overwriting.
|
||||
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(chosenFile))) {
|
||||
oos.writeObject(this.model);
|
||||
this.lastSelectedFile = chosenFile;
|
||||
JOptionPane.showMessageDialog(fileChooser, "File saved successfully.", "Success", JOptionPane.INFORMATION_MESSAGE);
|
||||
} catch (IOException ex) {
|
||||
JOptionPane.showMessageDialog(fileChooser, "An error occurred and the file could not be saved:\n" + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,23 +18,32 @@ public class DiagramMouseListener extends MouseAdapter {
|
|||
this.model = model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles mouse presses. This is what should happen:
|
||||
* - If the click occurs outside of the bounds of any relation, deselect all
|
||||
* relations, if CTRL is not held down.
|
||||
* - If the click occurs within at least one relation, select the first one,
|
||||
* and deselect all others if CTRL is not held down.
|
||||
* @param e The mouse event.
|
||||
*/
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
DiagramPanel panel = (DiagramPanel) e.getSource();
|
||||
final Graphics2D g2d = panel.getGraphics2D();
|
||||
this.mouseDragStart = e.getPoint();
|
||||
if ((e.getModifiers() & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK) {
|
||||
boolean hit = false;
|
||||
for (Relation r : this.model.getRelations()) {
|
||||
if (r.getViewModel().getBounds(g2d).contains(e.getX(), e.getY())) {
|
||||
r.setSelected(!r.isSelected());
|
||||
hit = true;
|
||||
}
|
||||
}
|
||||
if (!hit) {
|
||||
this.model.getRelations().forEach(r -> r.setSelected(false));
|
||||
|
||||
boolean isCtrlDown = (e.getModifiers() & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK;
|
||||
|
||||
if (!isCtrlDown) {
|
||||
this.model.getRelations().forEach(r -> r.setSelected(false));
|
||||
}
|
||||
for (Relation r : this.model.getRelations()) {
|
||||
if (r.getViewModel().getBounds(g2d).contains(e.getX(), e.getY())) {
|
||||
r.setSelected(!r.isSelected());
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.model.fireChangedEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -46,11 +55,16 @@ public class DiagramMouseListener extends MouseAdapter {
|
|||
public void mouseDragged(MouseEvent e) {
|
||||
int dx = this.mouseDragStart.x - e.getX();
|
||||
int dy = this.mouseDragStart.y - e.getY();
|
||||
boolean changed = false;
|
||||
for (Relation r : this.model.getRelations()) {
|
||||
if (r.isSelected()) {
|
||||
r.setPosition(new Point(r.getPosition().x - dx, r.getPosition().y - dy));
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
this.model.fireChangedEvent();
|
||||
}
|
||||
this.mouseDragStart = e.getPoint();
|
||||
}
|
||||
|
||||
|
|
|
@ -2,13 +2,14 @@ package nl.andrewlalis.erme.model;
|
|||
|
||||
import lombok.Getter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A single value that belongs to a relation.
|
||||
*/
|
||||
@Getter
|
||||
public class Attribute {
|
||||
public class Attribute implements Serializable {
|
||||
private final Relation relation;
|
||||
private AttributeType type;
|
||||
private String name;
|
||||
|
|
|
@ -2,6 +2,7 @@ package nl.andrewlalis.erme.model;
|
|||
|
||||
import lombok.Getter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
@ -10,11 +11,11 @@ import java.util.Set;
|
|||
* This model contains all the information about a single mapping diagram,
|
||||
* including each mapped table and the links between them.
|
||||
*/
|
||||
public class MappingModel {
|
||||
public class MappingModel implements Serializable {
|
||||
@Getter
|
||||
private final Set<Relation> relations;
|
||||
|
||||
private final Set<ModelChangeListener> changeListeners;
|
||||
private transient final Set<ModelChangeListener> changeListeners;
|
||||
|
||||
public MappingModel() {
|
||||
this.relations = new HashSet<>();
|
||||
|
@ -38,7 +39,7 @@ public class MappingModel {
|
|||
listener.onModelChanged();
|
||||
}
|
||||
|
||||
protected final void fireChangedEvent() {
|
||||
public final void fireChangedEvent() {
|
||||
this.changeListeners.forEach(ModelChangeListener::onModelChanged);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import lombok.Getter;
|
|||
import nl.andrewlalis.erme.view.view_models.RelationViewModel;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
@ -12,7 +13,7 @@ import java.util.Objects;
|
|||
* Represents a single "relation" or table in the diagram.
|
||||
*/
|
||||
@Getter
|
||||
public class Relation {
|
||||
public class Relation implements Serializable {
|
||||
private final MappingModel model;
|
||||
private Point position;
|
||||
private String name;
|
||||
|
@ -30,24 +31,15 @@ public class Relation {
|
|||
}
|
||||
|
||||
public void setPosition(Point position) {
|
||||
if (!this.position.equals(position)) {
|
||||
this.position = position;
|
||||
this.model.fireChangedEvent();
|
||||
}
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
if (!this.name.equals(name)) {
|
||||
this.name = name;
|
||||
this.model.fireChangedEvent();
|
||||
}
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setSelected(boolean selected) {
|
||||
if (selected != this.selected) {
|
||||
this.selected = selected;
|
||||
this.model.fireChangedEvent();
|
||||
}
|
||||
this.selected = selected;
|
||||
}
|
||||
|
||||
public void addAttribute(Attribute attribute) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package nl.andrewlalis.erme.view;
|
||||
|
||||
import lombok.Getter;
|
||||
import nl.andrewlalis.erme.control.actions.SaveAction;
|
||||
import nl.andrewlalis.erme.control.diagram.DiagramMouseListener;
|
||||
import nl.andrewlalis.erme.model.MappingModel;
|
||||
import nl.andrewlalis.erme.model.ModelChangeListener;
|
||||
|
@ -35,6 +36,7 @@ public class DiagramPanel extends JPanel implements ModelChangeListener {
|
|||
DiagramMouseListener listener = new DiagramMouseListener(newModel);
|
||||
this.addMouseListener(listener);
|
||||
this.addMouseMotionListener(listener);
|
||||
SaveAction.getInstance().setModel(newModel);
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
package nl.andrewlalis.erme.view;
|
||||
|
||||
import nl.andrewlalis.erme.control.actions.ExitAction;
|
||||
import nl.andrewlalis.erme.control.actions.ExportToImageAction;
|
||||
import nl.andrewlalis.erme.control.actions.RedoAction;
|
||||
import nl.andrewlalis.erme.control.actions.UndoAction;
|
||||
import nl.andrewlalis.erme.control.actions.*;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
|
@ -18,6 +15,8 @@ public class EditorMenuBar extends JMenuBar {
|
|||
|
||||
private JMenu buildFileMenu() {
|
||||
JMenu menu = new JMenu("File");
|
||||
JMenuItem saveItem = new JMenuItem(SaveAction.getInstance());
|
||||
menu.add(saveItem);
|
||||
JMenuItem exportAsImageItem = new JMenuItem(ExportToImageAction.getInstance());
|
||||
menu.add(exportAsImageItem);
|
||||
JMenuItem exitItem = new JMenuItem(ExitAction.getInstance());
|
||||
|
|
|
@ -29,10 +29,8 @@ public class RelationViewModel implements ViewModel {
|
|||
}
|
||||
if (this.relation.isSelected()) {
|
||||
g.setColor(Color.BLUE);
|
||||
} else {
|
||||
g.setColor(Color.CYAN);
|
||||
g.drawRect(bounds.x, bounds.y, bounds.width, bounds.height);
|
||||
}
|
||||
g.drawRect(bounds.x, bounds.y, bounds.width, bounds.height);
|
||||
}
|
||||
|
||||
public Rectangle getBounds(Graphics2D g) {
|
||||
|
|
Loading…
Reference in New Issue