From 1019654e76db63f30ac6720013f85fcc20ca774a Mon Sep 17 00:00:00 2001 From: Andrew Lalis Date: Thu, 28 Oct 2021 12:06:50 +0200 Subject: [PATCH] Cleaned up singleton actions, updated instructions, etc. --- pom.xml | 2 +- .../erme/control/actions/AboutAction.java | 41 -------------- .../control/actions/AutoPositionAction.java | 42 +++++---------- .../control/actions/DiagramPanelAction.java | 17 ++++++ .../erme/control/actions/ExitAction.java | 22 ++------ .../control/actions/ExportToImageAction.java | 52 +++++++----------- .../actions/HtmlDocumentViewerAction.java | 20 +++---- .../control/actions/InstructionsAction.java | 13 ++--- .../erme/control/actions/LoadAction.java | 22 ++------ .../actions/LoadSampleModelAction.java | 22 ++------ .../erme/control/actions/LocalAction.java | 26 --------- .../erme/control/actions/LolcatAction.java | 29 +++------- .../actions/MappingAlgorithmHelpAction.java | 15 ++---- .../erme/control/actions/NewModelAction.java | 21 ++------ .../erme/control/actions/SaveAction.java | 35 ++++-------- .../actions/VisualizeReferencesAction.java | 28 ++-------- .../actions/edits/AddAttributeAction.java | 52 +++++++----------- .../actions/edits/AddRelationAction.java | 49 +++++++---------- .../actions/edits/RemoveAttributeAction.java | 29 +++------- .../actions/edits/RemoveRelationAction.java | 32 ++++------- .../control/diagram/DiagramMouseListener.java | 27 +++++----- .../andrewlalis/erme/model/MappingModel.java | 11 ++++ .../andrewlalis/erme/view/DiagramPanel.java | 39 ++++---------- .../erme/view/DiagramPopupMenu.java | 19 ++++--- .../nl/andrewlalis/erme/view/EditorFrame.java | 7 +-- .../andrewlalis/erme/view/EditorMenuBar.java | 53 +++++++++---------- .../erme/view/OrderableListPanel.java | 1 + .../view/view_models/AttributeViewModel.java | 3 +- .../view_models/MappingModelViewModel.java | 6 +-- src/main/resources/html/instructions.html | 9 +++- 30 files changed, 241 insertions(+), 503 deletions(-) delete mode 100644 src/main/java/nl/andrewlalis/erme/control/actions/AboutAction.java create mode 100644 src/main/java/nl/andrewlalis/erme/control/actions/DiagramPanelAction.java delete mode 100644 src/main/java/nl/andrewlalis/erme/control/actions/LocalAction.java diff --git a/pom.xml b/pom.xml index 3c66625..308441d 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ nl.andrewlalis EntityRelationMappingEditor - 1.6.1 + 1.6.2 diff --git a/src/main/java/nl/andrewlalis/erme/control/actions/AboutAction.java b/src/main/java/nl/andrewlalis/erme/control/actions/AboutAction.java deleted file mode 100644 index 87fbce5..0000000 --- a/src/main/java/nl/andrewlalis/erme/control/actions/AboutAction.java +++ /dev/null @@ -1,41 +0,0 @@ -package nl.andrewlalis.erme.control.actions; - -import lombok.Setter; -import nl.andrewlalis.erme.EntityRelationMappingEditor; -import nl.andrewlalis.erme.view.DiagramPanel; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; - -public class AboutAction extends AbstractAction { - private static AboutAction instance; - - public static AboutAction getInstance() { - if (instance == null) instance = new AboutAction(); - return instance; - } - - @Setter - private DiagramPanel diagramPanel; - - public AboutAction() { - super("About"); - this.putValue(SHORT_DESCRIPTION, "Show some information about this program."); - } - - @Override - public void actionPerformed(ActionEvent e) { - JOptionPane.showMessageDialog( - this.diagramPanel, - "Entity-Relation Mapping Editor\n" + - "by Andrew Lalis\n" + - "Version " + EntityRelationMappingEditor.VERSION + "\n" + - "To report bugs or make suggestions, please visit the GitHub\n" + - "repository for this application and create a new issue.\n\n" + - "Thank you for using the ERME!", - "About ERME", - JOptionPane.INFORMATION_MESSAGE - ); - } -} diff --git a/src/main/java/nl/andrewlalis/erme/control/actions/AutoPositionAction.java b/src/main/java/nl/andrewlalis/erme/control/actions/AutoPositionAction.java index cfe5d56..d95ce8a 100644 --- a/src/main/java/nl/andrewlalis/erme/control/actions/AutoPositionAction.java +++ b/src/main/java/nl/andrewlalis/erme/control/actions/AutoPositionAction.java @@ -1,7 +1,5 @@ package nl.andrewlalis.erme.control.actions; -import lombok.Setter; -import nl.andrewlalis.erme.model.MappingModel; import nl.andrewlalis.erme.model.Relation; import nl.andrewlalis.erme.view.DiagramPanel; import nl.andrewlalis.erme.view.OrderableListPanel; @@ -17,31 +15,20 @@ import java.util.concurrent.atomic.AtomicInteger; * A class that implements an AutoPositionAction. This automatically (vertically) positions all relations in the model * based either on alphabetic ordering (by name) or an order that's set by the user */ -public class AutoPositionAction extends AbstractAction { +public class AutoPositionAction extends DiagramPanelAction { private final static int MARGIN = 10; private final static int PADDING = 10; - private static AutoPositionAction instance; - @Setter - private DiagramPanel diagramPanel; - @Setter - private MappingModel model; - public AutoPositionAction() { - super("Align Relations"); - this.putValue(SHORT_DESCRIPTION, "Automatically Align Relations"); - } - public static AutoPositionAction getInstance() { - if (instance == null) { - instance = new AutoPositionAction(); - } - return instance; + public AutoPositionAction(DiagramPanel diagramPanel) { + super("Align Relations", diagramPanel); + this.putValue(SHORT_DESCRIPTION, "Automatically Align Relations"); } @Override public void actionPerformed(ActionEvent actionEvent) { - if (model.getRelations().size() == 0) { + if (getDiagramPanel().getModel().getRelations().size() == 0) { JOptionPane.showMessageDialog( - this.diagramPanel, + getDiagramPanel(), "Cannot position all relations when there are no relations present", "Relations Required", JOptionPane.WARNING_MESSAGE @@ -50,7 +37,7 @@ public class AutoPositionAction extends AbstractAction { } String[] choices = new String[]{"Alphabeticaly", "Custom Order"}; String choice = (String) JOptionPane.showInputDialog( - this.diagramPanel, + getDiagramPanel(), "Select how to sort the relations", "Position Relations", JOptionPane.PLAIN_MESSAGE, @@ -62,14 +49,14 @@ public class AutoPositionAction extends AbstractAction { positionRelations(getAlphabeticRelationList()); } else if (choice.equals(choices[1])) { JOptionPane.showConfirmDialog( - this.diagramPanel, + getDiagramPanel(), OrderableListPanel.getInstance(), "teststring", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); this.positionRelations(OrderableListPanel.getInstance().getOrderList()); } - diagramPanel.repaint(); + getDiagramPanel().repaint(); } /** @@ -80,23 +67,20 @@ public class AutoPositionAction extends AbstractAction { if (orderList.isEmpty()) return; AtomicInteger vertSpace = new AtomicInteger(0); orderList.forEach(r -> { - int height = (int) r.getViewModel().getBounds(diagramPanel.getGraphics2D()).getHeight(); + int height = (int) r.getViewModel().getBounds(getDiagramPanel().getGraphics2D()).getHeight(); vertSpace.set(Math.max(vertSpace.get(), height)); }); vertSpace.addAndGet(PADDING); AtomicInteger vertPos = new AtomicInteger(MARGIN); - orderList.forEach(r -> { - r.setPosition(new Point(MARGIN, vertPos.getAndAdd(vertSpace.get()))); - }); - - diagramPanel.centerModel(); + orderList.forEach(r -> r.setPosition(new Point(MARGIN, vertPos.getAndAdd(vertSpace.get())))); + getDiagramPanel().centerModel(); } /** * Creates an orderList by grabbing all relations and sorting them */ private ArrayList getAlphabeticRelationList() { - ArrayList relationList = new ArrayList<>(model.getRelations()); + ArrayList relationList = new ArrayList<>(getDiagramPanel().getModel().getRelations()); Collections.sort(relationList); return relationList; } diff --git a/src/main/java/nl/andrewlalis/erme/control/actions/DiagramPanelAction.java b/src/main/java/nl/andrewlalis/erme/control/actions/DiagramPanelAction.java new file mode 100644 index 0000000..c668532 --- /dev/null +++ b/src/main/java/nl/andrewlalis/erme/control/actions/DiagramPanelAction.java @@ -0,0 +1,17 @@ +package nl.andrewlalis.erme.control.actions; + +import lombok.AccessLevel; +import lombok.Getter; +import nl.andrewlalis.erme.view.DiagramPanel; + +import javax.swing.*; + +public abstract class DiagramPanelAction extends AbstractAction { + @Getter(AccessLevel.PROTECTED) + private final DiagramPanel diagramPanel; + + public DiagramPanelAction(String name, DiagramPanel diagramPanel) { + super(name); + this.diagramPanel = diagramPanel; + } +} diff --git a/src/main/java/nl/andrewlalis/erme/control/actions/ExitAction.java b/src/main/java/nl/andrewlalis/erme/control/actions/ExitAction.java index 42ecead..94662e8 100644 --- a/src/main/java/nl/andrewlalis/erme/control/actions/ExitAction.java +++ b/src/main/java/nl/andrewlalis/erme/control/actions/ExitAction.java @@ -1,29 +1,15 @@ package nl.andrewlalis.erme.control.actions; -import lombok.Setter; import nl.andrewlalis.erme.view.DiagramPanel; import javax.swing.*; -import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; -public class ExitAction extends AbstractAction { - private static ExitAction instance; - - public static ExitAction getInstance() { - if (instance == null) { - instance = new ExitAction(); - } - return instance; - } - - @Setter - private DiagramPanel diagramPanel; - - public ExitAction() { - super("Exit"); +public class ExitAction extends DiagramPanelAction { + public ExitAction(DiagramPanel diagramPanel) { + super("Exit", diagramPanel); this.putValue(Action.SHORT_DESCRIPTION, "Exit the program."); this.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK)); } @@ -31,7 +17,7 @@ public class ExitAction extends AbstractAction { @Override public void actionPerformed(ActionEvent e) { int choice = JOptionPane.showConfirmDialog( - this.diagramPanel, + getDiagramPanel(), "Are you sure you want to quit?\nAll unsaved data will be lost.", "Confirm Exit", JOptionPane.OK_CANCEL_OPTION, diff --git a/src/main/java/nl/andrewlalis/erme/control/actions/ExportToImageAction.java b/src/main/java/nl/andrewlalis/erme/control/actions/ExportToImageAction.java index c106ebb..9fe74ac 100644 --- a/src/main/java/nl/andrewlalis/erme/control/actions/ExportToImageAction.java +++ b/src/main/java/nl/andrewlalis/erme/control/actions/ExportToImageAction.java @@ -1,6 +1,5 @@ package nl.andrewlalis.erme.control.actions; -import lombok.Setter; import nl.andrewlalis.erme.model.MappingModel; import nl.andrewlalis.erme.model.Relation; import nl.andrewlalis.erme.view.DiagramPanel; @@ -20,33 +19,21 @@ import java.io.IOException; import java.util.List; import java.util.prefs.Preferences; -public class ExportToImageAction extends AbstractAction { +public class ExportToImageAction extends DiagramPanelAction { private static final String LAST_EXPORT_LOCATION_KEY = "lastExportLocation"; - private static ExportToImageAction instance; - public static ExportToImageAction getInstance() { - if (instance == null) { - instance = new ExportToImageAction(); - } - return instance; - } - - @Setter - private MappingModel model; - @Setter - private DiagramPanel diagramPanel; - - public ExportToImageAction() { - super("Export to Image"); + public ExportToImageAction(DiagramPanel diagramPanel) { + super("Export to Image", diagramPanel); this.putValue(Action.SHORT_DESCRIPTION, "Export the current diagram to an image."); this.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.CTRL_DOWN_MASK)); } @Override public void actionPerformed(ActionEvent e) { - if (this.model.getRelations().isEmpty()) { + DiagramPanel dp = getDiagramPanel(); + if (dp.getModel().getRelations().isEmpty()) { JOptionPane.showMessageDialog( - this.diagramPanel, + dp, "Model is empty. Add some relations before exporting to an image.", "Model Empty", JOptionPane.WARNING_MESSAGE @@ -62,11 +49,11 @@ public class ExportToImageAction extends AbstractAction { if (path != null) { fileChooser.setSelectedFile(new File(path)); } - int choice = fileChooser.showSaveDialog(this.diagramPanel); + int choice = fileChooser.showSaveDialog(dp); 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); + JOptionPane.showMessageDialog(dp, "The selected file cannot be written to.", "Invalid File", JOptionPane.WARNING_MESSAGE); return; } int i = chosenFile.getName().lastIndexOf('.'); @@ -76,13 +63,13 @@ public class ExportToImageAction extends AbstractAction { } else { chosenFile = new File(chosenFile.getParent(), chosenFile.getName() + '.' + extension); } - String input = JOptionPane.showInputDialog(this.diagramPanel, "Choose a scale for the image.", "3.0"); + String input = JOptionPane.showInputDialog(dp, "Choose a scale for the image.", "3.0"); float scale; try { scale = Float.parseFloat(input); if (scale <= 0.0f || scale > 64.0f) throw new IllegalArgumentException(); } catch (Exception ex) { - JOptionPane.showMessageDialog(this.diagramPanel, "Invalid scale value. Should be a positive number less than 64.", "Invalid Scale", JOptionPane.WARNING_MESSAGE); + JOptionPane.showMessageDialog(dp, "Invalid scale value. Should be a positive number less than 64.", "Invalid Scale", JOptionPane.WARNING_MESSAGE); return; } try { @@ -92,7 +79,7 @@ public class ExportToImageAction extends AbstractAction { ImageIO.write(render, extension, chosenFile); prefs.put(LAST_EXPORT_LOCATION_KEY, chosenFile.getAbsolutePath()); JOptionPane.showMessageDialog( - this.diagramPanel, + dp, "Image export completed in " + String.format("%.4f", durationSeconds) + " seconds.\n" + "Resolution: " + render.getWidth() + "x" + render.getHeight(), "Image Export Complete", @@ -111,11 +98,12 @@ public class ExportToImageAction extends AbstractAction { * @return The image which was rendered. */ private BufferedImage renderModel(float scale) { + MappingModel model = getDiagramPanel().getModel(); // Prepare a tiny sample image that we can use to determine the bounds of the model in a graphics context. BufferedImage bufferedImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); Graphics2D g2d = bufferedImage.createGraphics(); DiagramPanel.prepareGraphics(g2d); - final Rectangle bounds = this.model.getViewModel().getBounds(g2d); + final Rectangle bounds = model.getViewModel().getBounds(g2d); bounds.width *= scale; bounds.height *= scale; @@ -134,13 +122,13 @@ public class ExportToImageAction extends AbstractAction { DiagramPanel.prepareGraphics(g2d); // Render the model. - boolean lolcat = LolcatAction.getInstance().isLolcatEnabled(); // save previous lolcat mode - LolcatAction.getInstance().setLolcatEnabled(false); - List selectedRelations = this.model.getSelectedRelations(); - this.model.getSelectedRelations().forEach(r -> r.setSelected(false)); - new MappingModelViewModel(this.model).draw(g2d); - this.model.getRelations().forEach(r -> r.setSelected(selectedRelations.contains(r))); - LolcatAction.getInstance().setLolcatEnabled(lolcat); // revert previous lolcat mode + boolean lolcat = model.isLolcatEnabled(); // save previous lolcat mode + model.setLolcatEnabled(false); + List selectedRelations = model.getSelectedRelations(); + model.getSelectedRelations().forEach(r -> r.setSelected(false)); + new MappingModelViewModel(model).draw(g2d); + model.getRelations().forEach(r -> r.setSelected(selectedRelations.contains(r))); + model.setLolcatEnabled(lolcat); // revert previous lolcat mode // Revert to the normal image space, and render a watermark. g2d.setTransform(originalTransform); diff --git a/src/main/java/nl/andrewlalis/erme/control/actions/HtmlDocumentViewerAction.java b/src/main/java/nl/andrewlalis/erme/control/actions/HtmlDocumentViewerAction.java index 640238e..f4d6c34 100644 --- a/src/main/java/nl/andrewlalis/erme/control/actions/HtmlDocumentViewerAction.java +++ b/src/main/java/nl/andrewlalis/erme/control/actions/HtmlDocumentViewerAction.java @@ -1,6 +1,5 @@ package nl.andrewlalis.erme.control.actions; -import lombok.Setter; import nl.andrewlalis.erme.view.DiagramPanel; import javax.swing.*; @@ -16,27 +15,24 @@ import java.net.URISyntaxException; /** * An action which, when performed, opens a view that displays an HTML document. */ -public abstract class HtmlDocumentViewerAction extends AbstractAction { +public abstract class HtmlDocumentViewerAction extends DiagramPanelAction { private final String resourceFileName; private final Dialog.ModalityType modalityType; - public HtmlDocumentViewerAction(String name, String resourceFileName) { - this(name, resourceFileName, Dialog.ModalityType.APPLICATION_MODAL); + public HtmlDocumentViewerAction(String name, String resourceFileName, DiagramPanel diagramPanel) { + this(name, resourceFileName, Dialog.ModalityType.APPLICATION_MODAL, diagramPanel); } - public HtmlDocumentViewerAction(String name, String resourceFileName, Dialog.ModalityType modalityType) { - super(name); + public HtmlDocumentViewerAction(String name, String resourceFileName, Dialog.ModalityType modalityType, DiagramPanel diagramPanel) { + super(name, diagramPanel); this.resourceFileName = resourceFileName; this.modalityType = modalityType; } - @Setter - private DiagramPanel diagramPanel; - @Override public void actionPerformed(ActionEvent e) { JDialog dialog = new JDialog( - SwingUtilities.getWindowAncestor(this.diagramPanel), + SwingUtilities.getWindowAncestor(getDiagramPanel()), (String) this.getValue(NAME), this.modalityType ); @@ -63,7 +59,7 @@ public abstract class HtmlDocumentViewerAction extends AbstractAction { } catch (IOException ex) { ex.printStackTrace(); JOptionPane.showMessageDialog( - this.diagramPanel, + getDiagramPanel(), "An error occured:\n" + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE @@ -77,7 +73,7 @@ public abstract class HtmlDocumentViewerAction extends AbstractAction { dialog.setMaximumSize(new Dimension(600, 800)); dialog.setPreferredSize(new Dimension(600, 800)); dialog.pack(); - dialog.setLocationRelativeTo(this.diagramPanel); + dialog.setLocationRelativeTo(getDiagramPanel()); dialog.setVisible(true); } diff --git a/src/main/java/nl/andrewlalis/erme/control/actions/InstructionsAction.java b/src/main/java/nl/andrewlalis/erme/control/actions/InstructionsAction.java index 258df91..9e7ab91 100644 --- a/src/main/java/nl/andrewlalis/erme/control/actions/InstructionsAction.java +++ b/src/main/java/nl/andrewlalis/erme/control/actions/InstructionsAction.java @@ -1,15 +1,10 @@ package nl.andrewlalis.erme.control.actions; +import nl.andrewlalis.erme.view.DiagramPanel; + public class InstructionsAction extends HtmlDocumentViewerAction { - private static InstructionsAction instance; - - public static InstructionsAction getInstance() { - if (instance == null) instance = new InstructionsAction(); - return instance; - } - - public InstructionsAction() { - super("Instructions", "html/instructions.html"); + public InstructionsAction(DiagramPanel diagramPanel) { + super("Instructions", "html/instructions.html", diagramPanel); this.putValue(SHORT_DESCRIPTION, "Instructions for how to use this program."); } } diff --git a/src/main/java/nl/andrewlalis/erme/control/actions/LoadAction.java b/src/main/java/nl/andrewlalis/erme/control/actions/LoadAction.java index d4e18c7..3d3d074 100644 --- a/src/main/java/nl/andrewlalis/erme/control/actions/LoadAction.java +++ b/src/main/java/nl/andrewlalis/erme/control/actions/LoadAction.java @@ -6,7 +6,6 @@ import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.json.JsonMapper; import com.fasterxml.jackson.databind.node.ObjectNode; -import lombok.Setter; import nl.andrewlalis.erme.model.MappingModel; import nl.andrewlalis.erme.view.DiagramPanel; @@ -19,22 +18,11 @@ import java.io.File; import java.io.FileInputStream; import java.util.prefs.Preferences; -public class LoadAction extends AbstractAction { +public class LoadAction extends DiagramPanelAction { private static final String LAST_LOAD_LOCATION_KEY = "lastLoadLocation"; - private static LoadAction instance; - public static LoadAction getInstance() { - if (instance == null) { - instance = new LoadAction(); - } - return instance; - } - - @Setter - private DiagramPanel diagramPanel; - - public LoadAction() { - super("Load"); + public LoadAction(DiagramPanel diagramPanel) { + super("Load", diagramPanel); this.putValue(SHORT_DESCRIPTION, "Load a saved diagram."); this.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK)); } @@ -52,7 +40,7 @@ public class LoadAction extends AbstractAction { if (path != null) { fileChooser.setSelectedFile(new File(path)); } - int choice = fileChooser.showOpenDialog(this.diagramPanel); + int choice = fileChooser.showOpenDialog(getDiagramPanel()); if (choice == JFileChooser.APPROVE_OPTION) { File chosenFile = fileChooser.getSelectedFile(); if (chosenFile == null || chosenFile.isDirectory() || !chosenFile.exists() || !chosenFile.canRead()) { @@ -65,7 +53,7 @@ public class LoadAction extends AbstractAction { .configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true) .build(); JsonNode data = mapper.readValue(fis, JsonNode.class); - this.diagramPanel.setModel(MappingModel.fromJson((ObjectNode) data)); + getDiagramPanel().setModel(MappingModel.fromJson((ObjectNode) data)); prefs.put(LAST_LOAD_LOCATION_KEY, chosenFile.getAbsolutePath()); } catch (Exception ex) { ex.printStackTrace(); diff --git a/src/main/java/nl/andrewlalis/erme/control/actions/LoadSampleModelAction.java b/src/main/java/nl/andrewlalis/erme/control/actions/LoadSampleModelAction.java index 7c7b42e..6e5d6e3 100644 --- a/src/main/java/nl/andrewlalis/erme/control/actions/LoadSampleModelAction.java +++ b/src/main/java/nl/andrewlalis/erme/control/actions/LoadSampleModelAction.java @@ -1,28 +1,14 @@ package nl.andrewlalis.erme.control.actions; -import lombok.Setter; import nl.andrewlalis.erme.model.*; import nl.andrewlalis.erme.view.DiagramPanel; -import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; -public class LoadSampleModelAction extends AbstractAction { - private static LoadSampleModelAction instance; - - public static LoadSampleModelAction getInstance() { - if (instance == null) { - instance = new LoadSampleModelAction(); - } - return instance; - } - - @Setter - private DiagramPanel diagramPanel; - - public LoadSampleModelAction() { - super("Load Sample Model"); +public class LoadSampleModelAction extends DiagramPanelAction { + public LoadSampleModelAction(DiagramPanel diagramPanel) { + super("Load Sample Model", diagramPanel); this.putValue(SHORT_DESCRIPTION, "Loads a sample ER-mapping model."); } @@ -38,6 +24,6 @@ public class LoadSampleModelAction extends AbstractAction { r1.addAttribute(new Attribute(r1, AttributeType.PLAIN, "purchasedAt")); r1.addAttribute(new ForeignKeyAttribute(r1, AttributeType.PLAIN, "typeName", "AirplaneType", "name")); model.addRelation(r1); - this.diagramPanel.setModel(model); + getDiagramPanel().setModel(model); } } diff --git a/src/main/java/nl/andrewlalis/erme/control/actions/LocalAction.java b/src/main/java/nl/andrewlalis/erme/control/actions/LocalAction.java deleted file mode 100644 index 2b490f8..0000000 --- a/src/main/java/nl/andrewlalis/erme/control/actions/LocalAction.java +++ /dev/null @@ -1,26 +0,0 @@ -package nl.andrewlalis.erme.control.actions; - -import lombok.Getter; -import lombok.Setter; - -import javax.swing.*; -import java.awt.*; - -public abstract class LocalAction extends AbstractAction { - @Setter - @Getter - private Point location; - - public LocalAction(String name, Point location) { - super(name); - this.location = location; - } - - public LocalAction(String name) { - this(name, null); - } - - public boolean hasLocation() { - return this.location != null; - } -} diff --git a/src/main/java/nl/andrewlalis/erme/control/actions/LolcatAction.java b/src/main/java/nl/andrewlalis/erme/control/actions/LolcatAction.java index 5b10809..4e3aa41 100644 --- a/src/main/java/nl/andrewlalis/erme/control/actions/LolcatAction.java +++ b/src/main/java/nl/andrewlalis/erme/control/actions/LolcatAction.java @@ -1,37 +1,20 @@ package nl.andrewlalis.erme.control.actions; -import lombok.Getter; -import lombok.Setter; import nl.andrewlalis.erme.view.DiagramPanel; import javax.swing.*; import java.awt.event.ActionEvent; -public class LolcatAction extends AbstractAction { - private static LolcatAction instance; - - @Getter - @Setter - private boolean lolcatEnabled = false; - - public static LolcatAction getInstance() { - if (instance == null) { - instance = new LolcatAction(); - } - return instance; - } - - @Setter - private DiagramPanel diagramPanel; - - public LolcatAction() { - super("Toggle Lolcat Mode"); +public class LolcatAction extends DiagramPanelAction { + public LolcatAction(DiagramPanel diagramPanel) { + super("Toggle Lolcat Mode", diagramPanel); this.putValue(SHORT_DESCRIPTION, "Does some wacky color stuff."); } @Override public void actionPerformed(ActionEvent actionEvent) { - lolcatEnabled = ((AbstractButton)actionEvent.getSource()).getModel().isSelected(); - diagramPanel.repaint(); + boolean lolcatEnabled = ((AbstractButton)actionEvent.getSource()).getModel().isSelected(); + getDiagramPanel().getModel().setLolcatEnabled(lolcatEnabled); + getDiagramPanel().repaint(); } } diff --git a/src/main/java/nl/andrewlalis/erme/control/actions/MappingAlgorithmHelpAction.java b/src/main/java/nl/andrewlalis/erme/control/actions/MappingAlgorithmHelpAction.java index bd3f790..274674b 100644 --- a/src/main/java/nl/andrewlalis/erme/control/actions/MappingAlgorithmHelpAction.java +++ b/src/main/java/nl/andrewlalis/erme/control/actions/MappingAlgorithmHelpAction.java @@ -1,19 +1,12 @@ package nl.andrewlalis.erme.control.actions; +import nl.andrewlalis.erme.view.DiagramPanel; + import java.awt.*; public class MappingAlgorithmHelpAction extends HtmlDocumentViewerAction { - private static MappingAlgorithmHelpAction instance; - - public static MappingAlgorithmHelpAction getInstance() { - if (instance == null) { - instance = new MappingAlgorithmHelpAction(); - } - return instance; - } - - public MappingAlgorithmHelpAction() { - super("Mapping Algorithm Help", "html/er_mapping_algorithm.html", Dialog.ModalityType.DOCUMENT_MODAL); + public MappingAlgorithmHelpAction(DiagramPanel diagramPanel) { + super("Mapping Algorithm Help", "html/er_mapping_algorithm.html", Dialog.ModalityType.DOCUMENT_MODAL, diagramPanel); this.putValue(SHORT_DESCRIPTION, "Shows a quick guide on how to map from an ER model to a schema."); } } diff --git a/src/main/java/nl/andrewlalis/erme/control/actions/NewModelAction.java b/src/main/java/nl/andrewlalis/erme/control/actions/NewModelAction.java index 517ccbb..df86a4e 100644 --- a/src/main/java/nl/andrewlalis/erme/control/actions/NewModelAction.java +++ b/src/main/java/nl/andrewlalis/erme/control/actions/NewModelAction.java @@ -1,6 +1,5 @@ package nl.andrewlalis.erme.control.actions; -import lombok.Setter; import nl.andrewlalis.erme.model.MappingModel; import nl.andrewlalis.erme.view.DiagramPanel; @@ -9,27 +8,15 @@ import java.awt.event.ActionEvent; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; -public class NewModelAction extends AbstractAction { - private static NewModelAction instance; - - public static NewModelAction getInstance() { - if (instance == null) { - instance = new NewModelAction(); - } - return instance; - } - - @Setter - private DiagramPanel diagramPanel; - - public NewModelAction() { - super("New Model"); +public class NewModelAction extends DiagramPanelAction { + public NewModelAction(DiagramPanel diagramPanel) { + super("New Model", diagramPanel); this.putValue(SHORT_DESCRIPTION, "Create a new model."); this.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_DOWN_MASK)); } @Override public void actionPerformed(ActionEvent e) { - this.diagramPanel.setModel(new MappingModel()); + getDiagramPanel().setModel(new MappingModel()); } } diff --git a/src/main/java/nl/andrewlalis/erme/control/actions/SaveAction.java b/src/main/java/nl/andrewlalis/erme/control/actions/SaveAction.java index 7c8d261..b296fc6 100644 --- a/src/main/java/nl/andrewlalis/erme/control/actions/SaveAction.java +++ b/src/main/java/nl/andrewlalis/erme/control/actions/SaveAction.java @@ -4,8 +4,6 @@ import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.json.JsonMapper; -import lombok.Setter; -import nl.andrewlalis.erme.model.MappingModel; import nl.andrewlalis.erme.view.DiagramPanel; import javax.swing.*; @@ -18,25 +16,11 @@ import java.io.FileOutputStream; import java.io.IOException; import java.util.prefs.Preferences; -public class SaveAction extends AbstractAction { +public class SaveAction extends DiagramPanelAction { private static final String LAST_SAVE_LOCATION_KEY = "lastSaveLocation"; - private static SaveAction instance; - public static SaveAction getInstance() { - if (instance == null) { - instance = new SaveAction(); - } - return instance; - } - - @Setter - private MappingModel model; - - @Setter - private DiagramPanel diagramPanel; - - public SaveAction() { - super("Save"); + public SaveAction(DiagramPanel diagramPanel) { + super("Save", diagramPanel); this.putValue(SHORT_DESCRIPTION, "Save the current diagram to a file."); this.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK)); } @@ -54,17 +38,18 @@ public class SaveAction extends AbstractAction { if (path != null) { fileChooser.setSelectedFile(new File(path)); } - int choice = fileChooser.showSaveDialog(this.diagramPanel); + DiagramPanel dp = getDiagramPanel(); + int choice = fileChooser.showSaveDialog(dp); if (choice == JFileChooser.APPROVE_OPTION) { File chosenFile = fileChooser.getSelectedFile(); if (chosenFile == null || chosenFile.isDirectory()) { - JOptionPane.showMessageDialog(this.diagramPanel, "The selected file cannot be written to.", "Invalid File", JOptionPane.WARNING_MESSAGE); + JOptionPane.showMessageDialog(dp, "The selected file cannot be written to.", "Invalid File", JOptionPane.WARNING_MESSAGE); return; } if (!chosenFile.exists() && !chosenFile.getName().endsWith(".json")) { chosenFile = new File(chosenFile.getParent(), chosenFile.getName() + ".json"); } else if (chosenFile.exists()) { - int result = JOptionPane.showConfirmDialog(this.diagramPanel, "Are you sure you want overwrite this file?", "Overwrite", JOptionPane.YES_NO_OPTION); + int result = JOptionPane.showConfirmDialog(dp, "Are you sure you want overwrite this file?", "Overwrite", JOptionPane.YES_NO_OPTION); if (result == JOptionPane.NO_OPTION) { return; } @@ -74,12 +59,12 @@ public class SaveAction extends AbstractAction { .configure(SerializationFeature.INDENT_OUTPUT, true) .configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true) .build(); - mapper.writeValue(fos, this.model.toJson(mapper)); + mapper.writeValue(fos, dp.getModel().toJson(mapper)); prefs.put(LAST_SAVE_LOCATION_KEY, chosenFile.getAbsolutePath()); - JOptionPane.showMessageDialog(fileChooser, "File saved successfully.", "Success", JOptionPane.INFORMATION_MESSAGE); + JOptionPane.showMessageDialog(dp, "File saved successfully.", "Success", JOptionPane.INFORMATION_MESSAGE); } catch (IOException ex) { ex.printStackTrace(); - JOptionPane.showMessageDialog(fileChooser, "An error occurred and the file could not be saved:\n" + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); + JOptionPane.showMessageDialog(dp, "An error occurred and the file could not be saved:\n" + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); } } } diff --git a/src/main/java/nl/andrewlalis/erme/control/actions/VisualizeReferencesAction.java b/src/main/java/nl/andrewlalis/erme/control/actions/VisualizeReferencesAction.java index 9473d17..1f95d56 100644 --- a/src/main/java/nl/andrewlalis/erme/control/actions/VisualizeReferencesAction.java +++ b/src/main/java/nl/andrewlalis/erme/control/actions/VisualizeReferencesAction.java @@ -1,37 +1,19 @@ package nl.andrewlalis.erme.control.actions; -import lombok.Getter; -import lombok.Setter; import nl.andrewlalis.erme.view.DiagramPanel; import javax.swing.*; import java.awt.event.ActionEvent; -public class VisualizeReferencesAction extends AbstractAction { - private static VisualizeReferencesAction instance; - - public static VisualizeReferencesAction getInstance() { - if (instance == null) { - instance = new VisualizeReferencesAction(); - } - return instance; - } - - @Getter - @Setter - private boolean referenceVisualizationEnabled = false; - - @Setter - private DiagramPanel diagramPanel; - - public VisualizeReferencesAction() { - super("Toggle Reference Visualization"); +public class VisualizeReferencesAction extends DiagramPanelAction { + public VisualizeReferencesAction(DiagramPanel diagramPanel) { + super("Toggle Reference Visualization", diagramPanel); this.putValue(SHORT_DESCRIPTION, "Shows/hides visualization of the references between attributes."); } @Override public void actionPerformed(ActionEvent e) { - referenceVisualizationEnabled = ((AbstractButton)e.getSource()).getModel().isSelected(); - diagramPanel.repaint(); + getDiagramPanel().getModel().setReferenceVisualizationEnabled(((AbstractButton)e.getSource()).getModel().isSelected()); + getDiagramPanel().repaint(); } } diff --git a/src/main/java/nl/andrewlalis/erme/control/actions/edits/AddAttributeAction.java b/src/main/java/nl/andrewlalis/erme/control/actions/edits/AddAttributeAction.java index df59ec9..949faa8 100644 --- a/src/main/java/nl/andrewlalis/erme/control/actions/edits/AddAttributeAction.java +++ b/src/main/java/nl/andrewlalis/erme/control/actions/edits/AddAttributeAction.java @@ -1,6 +1,6 @@ package nl.andrewlalis.erme.control.actions.edits; -import lombok.Setter; +import nl.andrewlalis.erme.control.actions.DiagramPanelAction; import nl.andrewlalis.erme.model.*; import nl.andrewlalis.erme.view.DiagramPanel; @@ -10,36 +10,23 @@ import java.awt.event.ActionEvent; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.util.List; -import java.util.Set; import java.util.stream.Stream; -public class AddAttributeAction extends AbstractAction { - private static AddAttributeAction instance; - - public static AddAttributeAction getInstance() { - if (instance == null) { - instance = new AddAttributeAction(); - } - return instance; - } - - @Setter - private MappingModel model; - @Setter - private DiagramPanel diagramPanel; - - public AddAttributeAction() { - super("Add Attribute"); +public class AddAttributeAction extends DiagramPanelAction { + public AddAttributeAction(DiagramPanel diagramPanel) { + super("Add Attribute", diagramPanel); this.putValue(SHORT_DESCRIPTION, "Add an attribute to the selected relation."); this.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.CTRL_DOWN_MASK)); } @Override public void actionPerformed(ActionEvent e) { - List selectedRelations = this.model.getSelectedRelations(); + DiagramPanel dp = getDiagramPanel(); + MappingModel model = dp.getModel(); + List selectedRelations = model.getSelectedRelations(); if (selectedRelations.size() != 1) { JOptionPane.showMessageDialog( - this.diagramPanel, + dp, "A single relation must be selected to add an attribute.", "Single Relation Required", JOptionPane.WARNING_MESSAGE @@ -48,11 +35,10 @@ public class AddAttributeAction extends AbstractAction { } Relation r = selectedRelations.get(0); Attribute createdAttribute; - Component source = this.diagramPanel; - String name = JOptionPane.showInputDialog(source, "Enter the name of the attribute.", "Attribute Name", JOptionPane.PLAIN_MESSAGE); + String name = JOptionPane.showInputDialog(dp, "Enter the name of the attribute.", "Attribute Name", JOptionPane.PLAIN_MESSAGE); if (name == null) return; Integer index = (Integer) JOptionPane.showInputDialog( - source, + dp, "Select the index to insert this attribute at.", "Attribute Index", JOptionPane.PLAIN_MESSAGE, @@ -62,7 +48,7 @@ public class AddAttributeAction extends AbstractAction { ); if (index == null) return; AttributeType type = (AttributeType) JOptionPane.showInputDialog( - source, + dp, "Select the type this attribute is.", "Attribute Type", JOptionPane.PLAIN_MESSAGE, @@ -72,7 +58,7 @@ public class AddAttributeAction extends AbstractAction { ); if (type == null) return; boolean shouldUseForeignKey = ((String) JOptionPane.showInputDialog( - source, + dp, "Is this attribute a foreign key?", "Foreign Key", JOptionPane.PLAIN_MESSAGE, @@ -81,27 +67,27 @@ public class AddAttributeAction extends AbstractAction { "No" )).equalsIgnoreCase("yes"); if (shouldUseForeignKey) { - if (this.model.getRelations().size() < 2) { - JOptionPane.showMessageDialog(source, "There should be at least 2 relations present in the model.", "Not Enough Relations", JOptionPane.WARNING_MESSAGE); + if (model.getRelations().size() < 2) { + JOptionPane.showMessageDialog(dp, "There should be at least 2 relations present in the model.", "Not Enough Relations", JOptionPane.WARNING_MESSAGE); return; } Relation fkRelation = (Relation) JOptionPane.showInputDialog( - source, + dp, "Select the relation that this foreign key references.", "Foreign Key Relation Reference", JOptionPane.PLAIN_MESSAGE, null, - this.model.getRelations().toArray(new Relation[0]), - this.model.getRelations().stream().findFirst().orElse(null) + model.getRelations().toArray(new Relation[0]), + model.getRelations().stream().findFirst().orElse(null) ); if (fkRelation == null) return; List eligibleAttributes = fkRelation.getAttributes(); if (eligibleAttributes.isEmpty()) { - JOptionPane.showMessageDialog(source, "There are no referencable attributes in the selected relation.", "No Referencable Attributes", JOptionPane.WARNING_MESSAGE); + JOptionPane.showMessageDialog(dp, "There are no referencable attributes in the selected relation.", "No Referencable Attributes", JOptionPane.WARNING_MESSAGE); return; } Attribute fkAttribute = (Attribute) JOptionPane.showInputDialog( - source, + dp, "Select the attribute that this foreign key references.", "Foreign Key Attribute Reference", JOptionPane.PLAIN_MESSAGE, diff --git a/src/main/java/nl/andrewlalis/erme/control/actions/edits/AddRelationAction.java b/src/main/java/nl/andrewlalis/erme/control/actions/edits/AddRelationAction.java index 1f882ab..d711eb4 100644 --- a/src/main/java/nl/andrewlalis/erme/control/actions/edits/AddRelationAction.java +++ b/src/main/java/nl/andrewlalis/erme/control/actions/edits/AddRelationAction.java @@ -1,7 +1,6 @@ package nl.andrewlalis.erme.control.actions.edits; -import lombok.Setter; -import nl.andrewlalis.erme.control.actions.LocalAction; +import nl.andrewlalis.erme.control.actions.DiagramPanelAction; import nl.andrewlalis.erme.model.MappingModel; import nl.andrewlalis.erme.model.Relation; import nl.andrewlalis.erme.view.DiagramPanel; @@ -12,57 +11,45 @@ import java.awt.event.ActionEvent; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; -public class AddRelationAction extends LocalAction { - private static AddRelationAction instance; - public static AddRelationAction getInstance() { - if (instance == null) { - instance = new AddRelationAction(); - } - return instance; - } - - @Setter - private MappingModel model; - - @Setter - private DiagramPanel diagramPanel; - - public AddRelationAction() { - super("Add Relation"); +public class AddRelationAction extends DiagramPanelAction { + public AddRelationAction(DiagramPanel diagramPanel) { + super("Add Relation", diagramPanel); this.putValue(SHORT_DESCRIPTION, "Add a new relation to the diagram."); this.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_DOWN_MASK)); } @Override public void actionPerformed(ActionEvent e) { + DiagramPanel dp = getDiagramPanel(); + MappingModel model = dp.getModel(); String name = JOptionPane.showInputDialog( - this.diagramPanel, + dp, "Enter the name of the relation.", "Add Relation", JOptionPane.PLAIN_MESSAGE ); if (name != null) { - final boolean isFirstRelation = this.model.getRelations().isEmpty(); + final boolean isFirstRelation = model.getRelations().isEmpty(); Point p; - if (this.hasLocation()) { + if (model.getLastInteractionPoint() != null) { p = new Point( - this.getLocation().x - this.diagramPanel.getPanningTranslation().x, - this.getLocation().y - this.diagramPanel.getPanningTranslation().y + model.getLastInteractionPoint().x - dp.getPanningTranslation().x, + model.getLastInteractionPoint().y - dp.getPanningTranslation().y ); } else if (isFirstRelation) { p = new Point(100, 100); } else { - Rectangle bounds = this.model.getRelationBounds(); + Rectangle bounds = model.getRelationBounds(); p = new Point(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2); } - Relation r = new Relation(this.model, p, name); - this.model.getSelectedRelations().forEach(rl -> rl.setSelected(false)); + Relation r = new Relation(model, p, name); + model.getSelectedRelations().forEach(rl -> rl.setSelected(false)); r.setSelected(true); - this.model.addRelation(r); + model.addRelation(r); if (isFirstRelation) { - this.model.normalizeRelationPositions(); - this.diagramPanel.centerModel(); - this.diagramPanel.repaint(); + model.normalizeRelationPositions(); + dp.centerModel(); + dp.repaint(); } } } diff --git a/src/main/java/nl/andrewlalis/erme/control/actions/edits/RemoveAttributeAction.java b/src/main/java/nl/andrewlalis/erme/control/actions/edits/RemoveAttributeAction.java index 6f74d6a..4eb16d7 100644 --- a/src/main/java/nl/andrewlalis/erme/control/actions/edits/RemoveAttributeAction.java +++ b/src/main/java/nl/andrewlalis/erme/control/actions/edits/RemoveAttributeAction.java @@ -1,8 +1,7 @@ package nl.andrewlalis.erme.control.actions.edits; -import lombok.Setter; +import nl.andrewlalis.erme.control.actions.DiagramPanelAction; import nl.andrewlalis.erme.model.Attribute; -import nl.andrewlalis.erme.model.MappingModel; import nl.andrewlalis.erme.model.Relation; import nl.andrewlalis.erme.view.DiagramPanel; @@ -12,33 +11,19 @@ import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.util.List; -public class RemoveAttributeAction extends AbstractAction { - private static RemoveAttributeAction instance; - - public static RemoveAttributeAction getInstance() { - if (instance == null) { - instance = new RemoveAttributeAction(); - } - return instance; - } - - @Setter - private MappingModel model; - @Setter - private DiagramPanel diagramPanel; - - public RemoveAttributeAction() { - super("Remove Attribute"); +public class RemoveAttributeAction extends DiagramPanelAction { + public RemoveAttributeAction(DiagramPanel diagramPanel) { + super("Remove Attribute", diagramPanel); this.putValue(SHORT_DESCRIPTION, "Remove an attribute from a relation."); this.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)); } @Override public void actionPerformed(ActionEvent e) { - List selectedRelations = this.model.getSelectedRelations(); + List selectedRelations = getDiagramPanel().getModel().getSelectedRelations(); if (selectedRelations.size() != 1 || selectedRelations.get(0).getAttributes().isEmpty()) { JOptionPane.showMessageDialog( - this.diagramPanel, + getDiagramPanel(), "A single relation with at least one attribute must be selected to remove an attribute.", "Single Relation With Attribute Required", JOptionPane.WARNING_MESSAGE @@ -47,7 +32,7 @@ public class RemoveAttributeAction extends AbstractAction { } Relation r = selectedRelations.get(0); Attribute attribute = (Attribute) JOptionPane.showInputDialog( - this.diagramPanel, + getDiagramPanel(), "Select the attribute to remove.", "Select Attribute", JOptionPane.PLAIN_MESSAGE, diff --git a/src/main/java/nl/andrewlalis/erme/control/actions/edits/RemoveRelationAction.java b/src/main/java/nl/andrewlalis/erme/control/actions/edits/RemoveRelationAction.java index 321093f..cf9b6c1 100644 --- a/src/main/java/nl/andrewlalis/erme/control/actions/edits/RemoveRelationAction.java +++ b/src/main/java/nl/andrewlalis/erme/control/actions/edits/RemoveRelationAction.java @@ -1,50 +1,36 @@ package nl.andrewlalis.erme.control.actions.edits; -import lombok.Setter; +import nl.andrewlalis.erme.control.actions.DiagramPanelAction; import nl.andrewlalis.erme.model.MappingModel; import nl.andrewlalis.erme.model.Relation; import nl.andrewlalis.erme.view.DiagramPanel; import javax.swing.*; -import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; -public class RemoveRelationAction extends AbstractAction { - private static RemoveRelationAction instance; - - public static RemoveRelationAction getInstance() { - if (instance == null) { - instance = new RemoveRelationAction(); - } - return instance; - } - - @Setter - private MappingModel model; - @Setter - private DiagramPanel diagramPanel; - - public RemoveRelationAction() { - super("Remove Relation"); +public class RemoveRelationAction extends DiagramPanelAction { + public RemoveRelationAction(DiagramPanel diagramPanel) { + super("Remove Relation", diagramPanel); this.putValue(SHORT_DESCRIPTION, "Remove a relation from the diagram."); this.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)); } @Override public void actionPerformed(ActionEvent e) { - if (this.model.getSelectedRelations().isEmpty()) { + MappingModel model = getDiagramPanel().getModel(); + if (model.getSelectedRelations().isEmpty()) { JOptionPane.showMessageDialog( - this.diagramPanel, + getDiagramPanel(), "No relations selected. Select at least one relation to remove.", "No Relations Selected", JOptionPane.WARNING_MESSAGE ); return; } - for (Relation r : this.model.getSelectedRelations()) { - this.model.removeRelation(r); + for (Relation r : model.getSelectedRelations()) { + model.removeRelation(r); } } } diff --git a/src/main/java/nl/andrewlalis/erme/control/diagram/DiagramMouseListener.java b/src/main/java/nl/andrewlalis/erme/control/diagram/DiagramMouseListener.java index cc20d24..f9b013c 100644 --- a/src/main/java/nl/andrewlalis/erme/control/diagram/DiagramMouseListener.java +++ b/src/main/java/nl/andrewlalis/erme/control/diagram/DiagramMouseListener.java @@ -11,11 +11,11 @@ import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; public class DiagramMouseListener extends MouseAdapter { - private final MappingModel model; + private final DiagramPanel diagramPanel; private Point mouseDragStart; - public DiagramMouseListener(MappingModel model) { - this.model = model; + public DiagramMouseListener(DiagramPanel diagramPanel) { + this.diagramPanel = diagramPanel; } /** @@ -38,13 +38,14 @@ public class DiagramMouseListener extends MouseAdapter { final boolean isCtrlDown = (e.getModifiers() & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK; final boolean isShiftDown = (e.getModifiers() & ActionEvent.SHIFT_MASK) == ActionEvent.SHIFT_MASK; + MappingModel model = this.diagramPanel.getModel(); if (!isShiftDown && !isCtrlDown) {// A simple click anywhere should reset selection. - this.model.getRelations().forEach(r -> r.setSelected(false)); + model.getRelations().forEach(r -> r.setSelected(false)); } if (!isShiftDown) {// If the user clicked or CTRL+clicked, try and select the relation they clicked on. - for (Relation r : this.model.getRelations()) { + for (Relation r : model.getRelations()) { if (r.getViewModel().getBounds(g).contains(modelX, modelY)) { r.setSelected(!r.isSelected()); break; @@ -54,11 +55,12 @@ public class DiagramMouseListener extends MouseAdapter { // If the user right-clicked, show a popup menu. if (e.getButton() == MouseEvent.BUTTON3) { - DiagramPopupMenu popupMenu = new DiagramPopupMenu(this.model, e); + model.setLastInteractionPoint(e.getPoint()); + DiagramPopupMenu popupMenu = new DiagramPopupMenu(this.diagramPanel); popupMenu.show(panel, e.getX(), e.getY()); } - this.model.fireChangedEvent(); + model.fireChangedEvent(); } @Override @@ -72,13 +74,14 @@ public class DiagramMouseListener extends MouseAdapter { final int dy = this.mouseDragStart.y - e.getY(); final boolean isShiftDown = (e.getModifiers() & ActionEvent.SHIFT_MASK) == ActionEvent.SHIFT_MASK; boolean changed = false; + MappingModel model = this.diagramPanel.getModel(); if (isShiftDown) { - final DiagramPanel panel = (DiagramPanel) e.getSource(); - panel.translate(-dx, -dy); - panel.repaint(); + System.out.println(e); + this.diagramPanel.translate(-dx, -dy); + this.diagramPanel.repaint(); } else { - for (Relation r : this.model.getRelations()) { + for (Relation r : model.getRelations()) { if (r.isSelected()) { r.setPosition(new Point(r.getPosition().x - dx, r.getPosition().y - dy)); changed = true; @@ -87,7 +90,7 @@ public class DiagramMouseListener extends MouseAdapter { } if (changed) { - this.model.fireChangedEvent(); + model.fireChangedEvent(); } this.mouseDragStart = e.getPoint(); } diff --git a/src/main/java/nl/andrewlalis/erme/model/MappingModel.java b/src/main/java/nl/andrewlalis/erme/model/MappingModel.java index 545ff92..7b34f62 100644 --- a/src/main/java/nl/andrewlalis/erme/model/MappingModel.java +++ b/src/main/java/nl/andrewlalis/erme/model/MappingModel.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.Getter; +import lombok.Setter; import nl.andrewlalis.erme.view.view_models.MappingModelViewModel; import nl.andrewlalis.erme.view.view_models.ViewModel; @@ -23,6 +24,16 @@ public class MappingModel implements Viewable { private transient final Set changeListeners; + @Getter + @Setter + private transient Point lastInteractionPoint = null; + @Getter + @Setter + private transient boolean lolcatEnabled = false; + @Getter + @Setter + private transient boolean referenceVisualizationEnabled = false; + public MappingModel() { this.relations = new HashSet<>(); this.changeListeners = new HashSet<>(); diff --git a/src/main/java/nl/andrewlalis/erme/view/DiagramPanel.java b/src/main/java/nl/andrewlalis/erme/view/DiagramPanel.java index c28cb17..25a3d0e 100644 --- a/src/main/java/nl/andrewlalis/erme/view/DiagramPanel.java +++ b/src/main/java/nl/andrewlalis/erme/view/DiagramPanel.java @@ -1,11 +1,6 @@ package nl.andrewlalis.erme.view; import lombok.Getter; -import nl.andrewlalis.erme.control.actions.*; -import nl.andrewlalis.erme.control.actions.edits.AddAttributeAction; -import nl.andrewlalis.erme.control.actions.edits.AddRelationAction; -import nl.andrewlalis.erme.control.actions.edits.RemoveAttributeAction; -import nl.andrewlalis.erme.control.actions.edits.RemoveRelationAction; import nl.andrewlalis.erme.control.diagram.DiagramMouseListener; import nl.andrewlalis.erme.model.MappingModel; import nl.andrewlalis.erme.model.ModelChangeListener; @@ -21,6 +16,10 @@ import java.awt.event.MouseMotionListener; * The main panel in which the ER Mapping diagram is displayed. */ public class DiagramPanel extends JPanel implements ModelChangeListener { + /** + * The model for the application. This is the main location from which to + * obtain the model for use in actions. + */ @Getter private MappingModel model; @@ -60,10 +59,10 @@ public class DiagramPanel extends JPanel implements ModelChangeListener { for (MouseMotionListener listener : this.getMouseMotionListeners()) { this.removeMouseMotionListener(listener); } - DiagramMouseListener listener = new DiagramMouseListener(newModel); + DiagramMouseListener listener = new DiagramMouseListener(this); this.addMouseListener(listener); this.addMouseMotionListener(listener); - this.updateActionModels(); + this.updateActionModels(); // TODO: remove this once OrderableListPanel is cleaned up. newModel.addChangeListener(OrderableListPanel.getInstance()); this.centerModel(); this.repaint(); @@ -79,6 +78,9 @@ public class DiagramPanel extends JPanel implements ModelChangeListener { this.panningTranslation.y = 0; } + /** + * Centers the model in the panel, by adjusting the panning translation. + */ public void centerModel() { if (this.getGraphics() == null) { return; @@ -120,30 +122,7 @@ public class DiagramPanel extends JPanel implements ModelChangeListener { * TODO: Clean this up somehow! */ private void updateActionModels() { - NewModelAction.getInstance().setDiagramPanel(this); - SaveAction.getInstance().setModel(this.model); - LoadAction.getInstance().setDiagramPanel(this); - ExportToImageAction.getInstance().setModel(this.model); - ExportToImageAction.getInstance().setDiagramPanel(this); - AddRelationAction.getInstance().setModel(this.model); - AddRelationAction.getInstance().setDiagramPanel(this); - RemoveRelationAction.getInstance().setModel(this.model); - RemoveRelationAction.getInstance().setDiagramPanel(this); - AddAttributeAction.getInstance().setModel(this.model); - AddAttributeAction.getInstance().setDiagramPanel(this); - RemoveAttributeAction.getInstance().setModel(this.model); - RemoveAttributeAction.getInstance().setDiagramPanel(this); - LoadSampleModelAction.getInstance().setDiagramPanel(this); - LolcatAction.getInstance().setDiagramPanel(this); - VisualizeReferencesAction.getInstance().setDiagramPanel(this); - AutoPositionAction.getInstance().setDiagramPanel(this); - AutoPositionAction.getInstance().setModel(this.model); OrderableListPanel.getInstance().setModel(this.model); - AboutAction.getInstance().setDiagramPanel(this); - ExitAction.getInstance().setDiagramPanel(this); - InstructionsAction.getInstance().setDiagramPanel(this); - MappingAlgorithmHelpAction.getInstance().setDiagramPanel(this); - SaveAction.getInstance().setDiagramPanel(this); } public static void prepareGraphics(Graphics2D g) { diff --git a/src/main/java/nl/andrewlalis/erme/view/DiagramPopupMenu.java b/src/main/java/nl/andrewlalis/erme/view/DiagramPopupMenu.java index c6bd5e9..c980f68 100644 --- a/src/main/java/nl/andrewlalis/erme/view/DiagramPopupMenu.java +++ b/src/main/java/nl/andrewlalis/erme/view/DiagramPopupMenu.java @@ -2,28 +2,27 @@ package nl.andrewlalis.erme.view; import nl.andrewlalis.erme.control.actions.edits.AddAttributeAction; import nl.andrewlalis.erme.control.actions.edits.AddRelationAction; -import nl.andrewlalis.erme.control.actions.edits.RemoveAttributeAction; import nl.andrewlalis.erme.control.actions.edits.RemoveRelationAction; -import nl.andrewlalis.erme.model.MappingModel; import nl.andrewlalis.erme.model.Relation; import javax.swing.*; -import java.awt.event.MouseEvent; import java.util.List; public class DiagramPopupMenu extends JPopupMenu { - public DiagramPopupMenu(MappingModel model, MouseEvent e) { - List selectedRelations = model.getSelectedRelations(); - AddRelationAction.getInstance().setLocation(e.getPoint()); + public DiagramPopupMenu(DiagramPanel diagramPanel) { + List selectedRelations = diagramPanel.getModel().getSelectedRelations(); if (selectedRelations.size() == 0) { - this.add(AddRelationAction.getInstance()); + this.add(new AddRelationAction(diagramPanel)); } if (selectedRelations.size() > 0) { - this.add(RemoveRelationAction.getInstance()); + this.add(new RemoveRelationAction(diagramPanel)); } if (selectedRelations.size() == 1) { - this.add(AddAttributeAction.getInstance()); - this.add(RemoveAttributeAction.getInstance()); + Relation relation = selectedRelations.get(0); + this.add(new AddAttributeAction(diagramPanel)); + if (!relation.getAttributes().isEmpty()) { + this.add(new RemoveRelationAction(diagramPanel)); + } } } } diff --git a/src/main/java/nl/andrewlalis/erme/view/EditorFrame.java b/src/main/java/nl/andrewlalis/erme/view/EditorFrame.java index 1f8435d..20f9600 100644 --- a/src/main/java/nl/andrewlalis/erme/view/EditorFrame.java +++ b/src/main/java/nl/andrewlalis/erme/view/EditorFrame.java @@ -14,8 +14,9 @@ import java.io.InputStream; public class EditorFrame extends JFrame { public EditorFrame() { super("ER-Mapping Editor"); - this.setContentPane(new DiagramPanel(new MappingModel())); - this.setJMenuBar(new EditorMenuBar()); + DiagramPanel diagramPanel = new DiagramPanel(new MappingModel()); + this.setContentPane(diagramPanel); + this.setJMenuBar(new EditorMenuBar(diagramPanel)); try { InputStream is = getClass().getClassLoader().getResourceAsStream("icon.png"); if (is == null) { @@ -26,7 +27,7 @@ public class EditorFrame extends JFrame { } catch (IOException e) { e.printStackTrace(); } - this.setMinimumSize(new Dimension(400, 400)); + this.setMinimumSize(new Dimension(300, 300)); this.setPreferredSize(new Dimension(800, 800)); this.pack(); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); diff --git a/src/main/java/nl/andrewlalis/erme/view/EditorMenuBar.java b/src/main/java/nl/andrewlalis/erme/view/EditorMenuBar.java index 96a7604..8be07c0 100644 --- a/src/main/java/nl/andrewlalis/erme/view/EditorMenuBar.java +++ b/src/main/java/nl/andrewlalis/erme/view/EditorMenuBar.java @@ -3,7 +3,6 @@ package nl.andrewlalis.erme.view; import nl.andrewlalis.erme.control.actions.*; import nl.andrewlalis.erme.control.actions.edits.AddAttributeAction; import nl.andrewlalis.erme.control.actions.edits.AddRelationAction; -import nl.andrewlalis.erme.control.actions.edits.RemoveAttributeAction; import nl.andrewlalis.erme.control.actions.edits.RemoveRelationAction; import javax.swing.*; @@ -12,51 +11,47 @@ import javax.swing.*; * The menu bar that's visible atop the application. */ public class EditorMenuBar extends JMenuBar { - public EditorMenuBar() { - this.add(this.buildFileMenu()); - this.add(this.buildEditMenu()); - this.add(this.buildViewMenu()); - this.add(this.buildHelpMenu()); + public EditorMenuBar(DiagramPanel diagramPanel) { + this.add(this.buildFileMenu(diagramPanel)); + this.add(this.buildEditMenu(diagramPanel)); + this.add(this.buildViewMenu(diagramPanel)); + this.add(this.buildHelpMenu(diagramPanel)); } - private JMenu buildFileMenu() { + private JMenu buildFileMenu(DiagramPanel diagramPanel) { JMenu menu = new JMenu("File"); - menu.add(NewModelAction.getInstance()); - menu.add(SaveAction.getInstance()); - menu.add(LoadAction.getInstance()); + menu.add(new NewModelAction(diagramPanel)); + menu.add(new SaveAction(diagramPanel)); + menu.add(new LoadAction(diagramPanel)); menu.addSeparator(); - menu.add(ExportToImageAction.getInstance()); + menu.add(new ExportToImageAction(diagramPanel)); menu.addSeparator(); - menu.add(ExitAction.getInstance()); + menu.add(new ExitAction(diagramPanel)); return menu; } - private JMenu buildEditMenu() { + private JMenu buildEditMenu(DiagramPanel diagramPanel) { JMenu menu = new JMenu("Edit"); - menu.add(AddRelationAction.getInstance()); - menu.add(RemoveRelationAction.getInstance()); - menu.add(AddAttributeAction.getInstance()); - menu.add(RemoveAttributeAction.getInstance()); - menu.add(AutoPositionAction.getInstance()); - menu.addSeparator(); - menu.add(UndoAction.getInstance()); - menu.add(RedoAction.getInstance()); + menu.add(new AddRelationAction(diagramPanel)); + menu.add(new RemoveRelationAction(diagramPanel)); + menu.add(new AddAttributeAction(diagramPanel)); + menu.add(new RemoveRelationAction(diagramPanel)); + menu.add(new AutoPositionAction(diagramPanel)); return menu; } - private JMenu buildViewMenu() { + private JMenu buildViewMenu(DiagramPanel diagramPanel) { JMenu menu = new JMenu("View"); - menu.add(new JCheckBoxMenuItem(LolcatAction.getInstance())); - menu.add(new JCheckBoxMenuItem(VisualizeReferencesAction.getInstance())); + menu.add(new JCheckBoxMenuItem(new LolcatAction(diagramPanel))); + menu.add(new JCheckBoxMenuItem(new VisualizeReferencesAction(diagramPanel))); return menu; } - private JMenu buildHelpMenu() { + private JMenu buildHelpMenu(DiagramPanel diagramPanel) { JMenu menu = new JMenu("Help"); - menu.add(InstructionsAction.getInstance()); - menu.add(MappingAlgorithmHelpAction.getInstance()); - menu.add(LoadSampleModelAction.getInstance()); - menu.add(AboutAction.getInstance()); + menu.add(new InstructionsAction(diagramPanel)); + menu.add(new MappingAlgorithmHelpAction(diagramPanel)); + menu.add(new LoadSampleModelAction(diagramPanel)); return menu; } } diff --git a/src/main/java/nl/andrewlalis/erme/view/OrderableListPanel.java b/src/main/java/nl/andrewlalis/erme/view/OrderableListPanel.java index 7731e65..433ec6a 100644 --- a/src/main/java/nl/andrewlalis/erme/view/OrderableListPanel.java +++ b/src/main/java/nl/andrewlalis/erme/view/OrderableListPanel.java @@ -15,6 +15,7 @@ import java.util.Set; /** * A panel to be used in a popup that has a OrderableListModel implemented. Implements ModelChangeListener to be able * to update the list of relations when new ones are added or ones are removed. + * TODO: Refactor this to not use static singleton instance. */ public class OrderableListPanel extends JPanel implements ModelChangeListener { private static OrderableListPanel instance; diff --git a/src/main/java/nl/andrewlalis/erme/view/view_models/AttributeViewModel.java b/src/main/java/nl/andrewlalis/erme/view/view_models/AttributeViewModel.java index ab104fa..ca45ed2 100644 --- a/src/main/java/nl/andrewlalis/erme/view/view_models/AttributeViewModel.java +++ b/src/main/java/nl/andrewlalis/erme/view/view_models/AttributeViewModel.java @@ -1,6 +1,5 @@ package nl.andrewlalis.erme.view.view_models; -import nl.andrewlalis.erme.control.actions.LolcatAction; import nl.andrewlalis.erme.model.Attribute; import nl.andrewlalis.erme.model.AttributeType; import nl.andrewlalis.erme.model.ForeignKeyAttribute; @@ -46,7 +45,7 @@ public class AttributeViewModel implements ViewModel { } private Color getBackgroundColor(int x, int y, Graphics2D g) { - if (!LolcatAction.getInstance().isLolcatEnabled()) return BACKGROUND_COLOR; + if (!attribute.getRelation().getModel().isLolcatEnabled()) return BACKGROUND_COLOR; Point offset = g.getClipBounds().getLocation(); g.translate(offset.x, offset.y); Dimension viewportSize = g.getClipBounds().getSize(); diff --git a/src/main/java/nl/andrewlalis/erme/view/view_models/MappingModelViewModel.java b/src/main/java/nl/andrewlalis/erme/view/view_models/MappingModelViewModel.java index dff8df8..c54bd7d 100644 --- a/src/main/java/nl/andrewlalis/erme/view/view_models/MappingModelViewModel.java +++ b/src/main/java/nl/andrewlalis/erme/view/view_models/MappingModelViewModel.java @@ -1,13 +1,11 @@ package nl.andrewlalis.erme.view.view_models; -import nl.andrewlalis.erme.control.actions.VisualizeReferencesAction; import nl.andrewlalis.erme.model.Attribute; import nl.andrewlalis.erme.model.ForeignKeyAttribute; import nl.andrewlalis.erme.model.MappingModel; import nl.andrewlalis.erme.model.Relation; import java.awt.*; -import java.awt.color.ColorSpace; import java.util.Random; /** @@ -22,9 +20,7 @@ public class MappingModelViewModel implements ViewModel { @Override public void draw(Graphics2D g) { - if (VisualizeReferencesAction.getInstance().isReferenceVisualizationEnabled()) { - visualizeReferences(g); - } + if (model.isReferenceVisualizationEnabled()) visualizeReferences(g); for (Relation r : this.model.getRelations()) { r.getViewModel().draw(g); } diff --git a/src/main/resources/html/instructions.html b/src/main/resources/html/instructions.html index b5b5bb0..9b04d1c 100644 --- a/src/main/resources/html/instructions.html +++ b/src/main/resources/html/instructions.html @@ -7,9 +7,13 @@

Entity-Relation Mapping Editor

-

Created by @andrewlalis

A simple UI for editing entity-relation mapping diagrams.

+

Created by Andrew Lalis

+

And with generous contributions by

+

Have you noticed any unexpected behavior? Is there something you think would make a good addition to this application? @@ -27,6 +31,9 @@

  • The Edit menu contains options for making changes to the current model, such as adding or removing relations and attributes, or undoing/redoing actions.
  • +
  • + The View menu contains options for changing how the model is viewed. +
  • The Help menu contains some items with additional information about the application, like this help page and a simple About popup with version information. There's also a Load Sample Model option, which will load a very basic sample model into the application that you are free to mess around with.