Cleaned up singleton actions, updated instructions, etc.

This commit is contained in:
Andrew Lalis 2021-10-28 12:06:50 +02:00
parent 0be31c84ac
commit 1019654e76
30 changed files with 241 additions and 503 deletions

View File

@ -6,7 +6,7 @@
<groupId>nl.andrewlalis</groupId> <groupId>nl.andrewlalis</groupId>
<artifactId>EntityRelationMappingEditor</artifactId> <artifactId>EntityRelationMappingEditor</artifactId>
<version>1.6.1</version> <version>1.6.2</version>
<build> <build>
<plugins> <plugins>
<plugin> <plugin>

View File

@ -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
);
}
}

View File

@ -1,7 +1,5 @@
package nl.andrewlalis.erme.control.actions; 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.model.Relation;
import nl.andrewlalis.erme.view.DiagramPanel; import nl.andrewlalis.erme.view.DiagramPanel;
import nl.andrewlalis.erme.view.OrderableListPanel; 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 * 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 * 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 MARGIN = 10;
private final static int PADDING = 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() { public AutoPositionAction(DiagramPanel diagramPanel) {
if (instance == null) { super("Align Relations", diagramPanel);
instance = new AutoPositionAction(); this.putValue(SHORT_DESCRIPTION, "Automatically Align Relations");
}
return instance;
} }
@Override @Override
public void actionPerformed(ActionEvent actionEvent) { public void actionPerformed(ActionEvent actionEvent) {
if (model.getRelations().size() == 0) { if (getDiagramPanel().getModel().getRelations().size() == 0) {
JOptionPane.showMessageDialog( JOptionPane.showMessageDialog(
this.diagramPanel, getDiagramPanel(),
"Cannot position all relations when there are no relations present", "Cannot position all relations when there are no relations present",
"Relations Required", "Relations Required",
JOptionPane.WARNING_MESSAGE JOptionPane.WARNING_MESSAGE
@ -50,7 +37,7 @@ public class AutoPositionAction extends AbstractAction {
} }
String[] choices = new String[]{"Alphabeticaly", "Custom Order"}; String[] choices = new String[]{"Alphabeticaly", "Custom Order"};
String choice = (String) JOptionPane.showInputDialog( String choice = (String) JOptionPane.showInputDialog(
this.diagramPanel, getDiagramPanel(),
"Select how to sort the relations", "Select how to sort the relations",
"Position Relations", "Position Relations",
JOptionPane.PLAIN_MESSAGE, JOptionPane.PLAIN_MESSAGE,
@ -62,14 +49,14 @@ public class AutoPositionAction extends AbstractAction {
positionRelations(getAlphabeticRelationList()); positionRelations(getAlphabeticRelationList());
} else if (choice.equals(choices[1])) { } else if (choice.equals(choices[1])) {
JOptionPane.showConfirmDialog( JOptionPane.showConfirmDialog(
this.diagramPanel, getDiagramPanel(),
OrderableListPanel.getInstance(), OrderableListPanel.getInstance(),
"teststring", "teststring",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.OK_CANCEL_OPTION,
JOptionPane.PLAIN_MESSAGE); JOptionPane.PLAIN_MESSAGE);
this.positionRelations(OrderableListPanel.getInstance().getOrderList()); this.positionRelations(OrderableListPanel.getInstance().getOrderList());
} }
diagramPanel.repaint(); getDiagramPanel().repaint();
} }
/** /**
@ -80,23 +67,20 @@ public class AutoPositionAction extends AbstractAction {
if (orderList.isEmpty()) return; if (orderList.isEmpty()) return;
AtomicInteger vertSpace = new AtomicInteger(0); AtomicInteger vertSpace = new AtomicInteger(0);
orderList.forEach(r -> { 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.set(Math.max(vertSpace.get(), height));
}); });
vertSpace.addAndGet(PADDING); vertSpace.addAndGet(PADDING);
AtomicInteger vertPos = new AtomicInteger(MARGIN); AtomicInteger vertPos = new AtomicInteger(MARGIN);
orderList.forEach(r -> { orderList.forEach(r -> r.setPosition(new Point(MARGIN, vertPos.getAndAdd(vertSpace.get()))));
r.setPosition(new Point(MARGIN, vertPos.getAndAdd(vertSpace.get()))); getDiagramPanel().centerModel();
});
diagramPanel.centerModel();
} }
/** /**
* Creates an orderList by grabbing all relations and sorting them * Creates an orderList by grabbing all relations and sorting them
*/ */
private ArrayList<Relation> getAlphabeticRelationList() { private ArrayList<Relation> getAlphabeticRelationList() {
ArrayList<Relation> relationList = new ArrayList<>(model.getRelations()); ArrayList<Relation> relationList = new ArrayList<>(getDiagramPanel().getModel().getRelations());
Collections.sort(relationList); Collections.sort(relationList);
return relationList; return relationList;
} }

View File

@ -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;
}
}

View File

@ -1,29 +1,15 @@
package nl.andrewlalis.erme.control.actions; package nl.andrewlalis.erme.control.actions;
import lombok.Setter;
import nl.andrewlalis.erme.view.DiagramPanel; import nl.andrewlalis.erme.view.DiagramPanel;
import javax.swing.*; import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.InputEvent; import java.awt.event.InputEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
public class ExitAction extends AbstractAction { public class ExitAction extends DiagramPanelAction {
private static ExitAction instance; public ExitAction(DiagramPanel diagramPanel) {
super("Exit", diagramPanel);
public static ExitAction getInstance() {
if (instance == null) {
instance = new ExitAction();
}
return instance;
}
@Setter
private DiagramPanel diagramPanel;
public ExitAction() {
super("Exit");
this.putValue(Action.SHORT_DESCRIPTION, "Exit the program."); 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)); 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 @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
int choice = JOptionPane.showConfirmDialog( int choice = JOptionPane.showConfirmDialog(
this.diagramPanel, getDiagramPanel(),
"Are you sure you want to quit?\nAll unsaved data will be lost.", "Are you sure you want to quit?\nAll unsaved data will be lost.",
"Confirm Exit", "Confirm Exit",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.OK_CANCEL_OPTION,

View File

@ -1,6 +1,5 @@
package nl.andrewlalis.erme.control.actions; package nl.andrewlalis.erme.control.actions;
import lombok.Setter;
import nl.andrewlalis.erme.model.MappingModel; import nl.andrewlalis.erme.model.MappingModel;
import nl.andrewlalis.erme.model.Relation; import nl.andrewlalis.erme.model.Relation;
import nl.andrewlalis.erme.view.DiagramPanel; import nl.andrewlalis.erme.view.DiagramPanel;
@ -20,33 +19,21 @@ import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.prefs.Preferences; 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 final String LAST_EXPORT_LOCATION_KEY = "lastExportLocation";
private static ExportToImageAction instance; public ExportToImageAction(DiagramPanel diagramPanel) {
public static ExportToImageAction getInstance() { super("Export to Image", diagramPanel);
if (instance == null) {
instance = new ExportToImageAction();
}
return instance;
}
@Setter
private MappingModel model;
@Setter
private DiagramPanel diagramPanel;
public ExportToImageAction() {
super("Export to Image");
this.putValue(Action.SHORT_DESCRIPTION, "Export the current diagram to an image."); 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)); this.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.CTRL_DOWN_MASK));
} }
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (this.model.getRelations().isEmpty()) { DiagramPanel dp = getDiagramPanel();
if (dp.getModel().getRelations().isEmpty()) {
JOptionPane.showMessageDialog( JOptionPane.showMessageDialog(
this.diagramPanel, dp,
"Model is empty. Add some relations before exporting to an image.", "Model is empty. Add some relations before exporting to an image.",
"Model Empty", "Model Empty",
JOptionPane.WARNING_MESSAGE JOptionPane.WARNING_MESSAGE
@ -62,11 +49,11 @@ public class ExportToImageAction extends AbstractAction {
if (path != null) { if (path != null) {
fileChooser.setSelectedFile(new File(path)); fileChooser.setSelectedFile(new File(path));
} }
int choice = fileChooser.showSaveDialog(this.diagramPanel); int choice = fileChooser.showSaveDialog(dp);
if (choice == JFileChooser.APPROVE_OPTION) { if (choice == JFileChooser.APPROVE_OPTION) {
File chosenFile = fileChooser.getSelectedFile(); File chosenFile = fileChooser.getSelectedFile();
if (chosenFile == null || chosenFile.isDirectory()) { 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; return;
} }
int i = chosenFile.getName().lastIndexOf('.'); int i = chosenFile.getName().lastIndexOf('.');
@ -76,13 +63,13 @@ public class ExportToImageAction extends AbstractAction {
} else { } else {
chosenFile = new File(chosenFile.getParent(), chosenFile.getName() + '.' + extension); 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; float scale;
try { try {
scale = Float.parseFloat(input); scale = Float.parseFloat(input);
if (scale <= 0.0f || scale > 64.0f) throw new IllegalArgumentException(); if (scale <= 0.0f || scale > 64.0f) throw new IllegalArgumentException();
} catch (Exception ex) { } 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; return;
} }
try { try {
@ -92,7 +79,7 @@ public class ExportToImageAction extends AbstractAction {
ImageIO.write(render, extension, chosenFile); ImageIO.write(render, extension, chosenFile);
prefs.put(LAST_EXPORT_LOCATION_KEY, chosenFile.getAbsolutePath()); prefs.put(LAST_EXPORT_LOCATION_KEY, chosenFile.getAbsolutePath());
JOptionPane.showMessageDialog( JOptionPane.showMessageDialog(
this.diagramPanel, dp,
"Image export completed in " + String.format("%.4f", durationSeconds) + " seconds.\n" + "Image export completed in " + String.format("%.4f", durationSeconds) + " seconds.\n" +
"Resolution: " + render.getWidth() + "x" + render.getHeight(), "Resolution: " + render.getWidth() + "x" + render.getHeight(),
"Image Export Complete", "Image Export Complete",
@ -111,11 +98,12 @@ public class ExportToImageAction extends AbstractAction {
* @return The image which was rendered. * @return The image which was rendered.
*/ */
private BufferedImage renderModel(float scale) { 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. // 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); BufferedImage bufferedImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bufferedImage.createGraphics(); Graphics2D g2d = bufferedImage.createGraphics();
DiagramPanel.prepareGraphics(g2d); DiagramPanel.prepareGraphics(g2d);
final Rectangle bounds = this.model.getViewModel().getBounds(g2d); final Rectangle bounds = model.getViewModel().getBounds(g2d);
bounds.width *= scale; bounds.width *= scale;
bounds.height *= scale; bounds.height *= scale;
@ -134,13 +122,13 @@ public class ExportToImageAction extends AbstractAction {
DiagramPanel.prepareGraphics(g2d); DiagramPanel.prepareGraphics(g2d);
// Render the model. // Render the model.
boolean lolcat = LolcatAction.getInstance().isLolcatEnabled(); // save previous lolcat mode boolean lolcat = model.isLolcatEnabled(); // save previous lolcat mode
LolcatAction.getInstance().setLolcatEnabled(false); model.setLolcatEnabled(false);
List<Relation> selectedRelations = this.model.getSelectedRelations(); List<Relation> selectedRelations = model.getSelectedRelations();
this.model.getSelectedRelations().forEach(r -> r.setSelected(false)); model.getSelectedRelations().forEach(r -> r.setSelected(false));
new MappingModelViewModel(this.model).draw(g2d); new MappingModelViewModel(model).draw(g2d);
this.model.getRelations().forEach(r -> r.setSelected(selectedRelations.contains(r))); model.getRelations().forEach(r -> r.setSelected(selectedRelations.contains(r)));
LolcatAction.getInstance().setLolcatEnabled(lolcat); // revert previous lolcat mode model.setLolcatEnabled(lolcat); // revert previous lolcat mode
// Revert to the normal image space, and render a watermark. // Revert to the normal image space, and render a watermark.
g2d.setTransform(originalTransform); g2d.setTransform(originalTransform);

View File

@ -1,6 +1,5 @@
package nl.andrewlalis.erme.control.actions; package nl.andrewlalis.erme.control.actions;
import lombok.Setter;
import nl.andrewlalis.erme.view.DiagramPanel; import nl.andrewlalis.erme.view.DiagramPanel;
import javax.swing.*; import javax.swing.*;
@ -16,27 +15,24 @@ import java.net.URISyntaxException;
/** /**
* An action which, when performed, opens a view that displays an HTML document. * 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 String resourceFileName;
private final Dialog.ModalityType modalityType; private final Dialog.ModalityType modalityType;
public HtmlDocumentViewerAction(String name, String resourceFileName) { public HtmlDocumentViewerAction(String name, String resourceFileName, DiagramPanel diagramPanel) {
this(name, resourceFileName, Dialog.ModalityType.APPLICATION_MODAL); this(name, resourceFileName, Dialog.ModalityType.APPLICATION_MODAL, diagramPanel);
} }
public HtmlDocumentViewerAction(String name, String resourceFileName, Dialog.ModalityType modalityType) { public HtmlDocumentViewerAction(String name, String resourceFileName, Dialog.ModalityType modalityType, DiagramPanel diagramPanel) {
super(name); super(name, diagramPanel);
this.resourceFileName = resourceFileName; this.resourceFileName = resourceFileName;
this.modalityType = modalityType; this.modalityType = modalityType;
} }
@Setter
private DiagramPanel diagramPanel;
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
JDialog dialog = new JDialog( JDialog dialog = new JDialog(
SwingUtilities.getWindowAncestor(this.diagramPanel), SwingUtilities.getWindowAncestor(getDiagramPanel()),
(String) this.getValue(NAME), (String) this.getValue(NAME),
this.modalityType this.modalityType
); );
@ -63,7 +59,7 @@ public abstract class HtmlDocumentViewerAction extends AbstractAction {
} catch (IOException ex) { } catch (IOException ex) {
ex.printStackTrace(); ex.printStackTrace();
JOptionPane.showMessageDialog( JOptionPane.showMessageDialog(
this.diagramPanel, getDiagramPanel(),
"An error occured:\n" + ex.getMessage(), "An error occured:\n" + ex.getMessage(),
"Error", "Error",
JOptionPane.ERROR_MESSAGE JOptionPane.ERROR_MESSAGE
@ -77,7 +73,7 @@ public abstract class HtmlDocumentViewerAction extends AbstractAction {
dialog.setMaximumSize(new Dimension(600, 800)); dialog.setMaximumSize(new Dimension(600, 800));
dialog.setPreferredSize(new Dimension(600, 800)); dialog.setPreferredSize(new Dimension(600, 800));
dialog.pack(); dialog.pack();
dialog.setLocationRelativeTo(this.diagramPanel); dialog.setLocationRelativeTo(getDiagramPanel());
dialog.setVisible(true); dialog.setVisible(true);
} }

View File

@ -1,15 +1,10 @@
package nl.andrewlalis.erme.control.actions; package nl.andrewlalis.erme.control.actions;
import nl.andrewlalis.erme.view.DiagramPanel;
public class InstructionsAction extends HtmlDocumentViewerAction { public class InstructionsAction extends HtmlDocumentViewerAction {
private static InstructionsAction instance; public InstructionsAction(DiagramPanel diagramPanel) {
super("Instructions", "html/instructions.html", diagramPanel);
public static InstructionsAction getInstance() {
if (instance == null) instance = new InstructionsAction();
return instance;
}
public InstructionsAction() {
super("Instructions", "html/instructions.html");
this.putValue(SHORT_DESCRIPTION, "Instructions for how to use this program."); this.putValue(SHORT_DESCRIPTION, "Instructions for how to use this program.");
} }
} }

View File

@ -6,7 +6,6 @@ import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper; import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.Setter;
import nl.andrewlalis.erme.model.MappingModel; import nl.andrewlalis.erme.model.MappingModel;
import nl.andrewlalis.erme.view.DiagramPanel; import nl.andrewlalis.erme.view.DiagramPanel;
@ -19,22 +18,11 @@ import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.util.prefs.Preferences; 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 final String LAST_LOAD_LOCATION_KEY = "lastLoadLocation";
private static LoadAction instance; public LoadAction(DiagramPanel diagramPanel) {
public static LoadAction getInstance() { super("Load", diagramPanel);
if (instance == null) {
instance = new LoadAction();
}
return instance;
}
@Setter
private DiagramPanel diagramPanel;
public LoadAction() {
super("Load");
this.putValue(SHORT_DESCRIPTION, "Load a saved diagram."); this.putValue(SHORT_DESCRIPTION, "Load a saved diagram.");
this.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK)); 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) { if (path != null) {
fileChooser.setSelectedFile(new File(path)); fileChooser.setSelectedFile(new File(path));
} }
int choice = fileChooser.showOpenDialog(this.diagramPanel); int choice = fileChooser.showOpenDialog(getDiagramPanel());
if (choice == JFileChooser.APPROVE_OPTION) { if (choice == JFileChooser.APPROVE_OPTION) {
File chosenFile = fileChooser.getSelectedFile(); File chosenFile = fileChooser.getSelectedFile();
if (chosenFile == null || chosenFile.isDirectory() || !chosenFile.exists() || !chosenFile.canRead()) { if (chosenFile == null || chosenFile.isDirectory() || !chosenFile.exists() || !chosenFile.canRead()) {
@ -65,7 +53,7 @@ public class LoadAction extends AbstractAction {
.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true) .configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true)
.build(); .build();
JsonNode data = mapper.readValue(fis, JsonNode.class); 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()); prefs.put(LAST_LOAD_LOCATION_KEY, chosenFile.getAbsolutePath());
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();

View File

@ -1,28 +1,14 @@
package nl.andrewlalis.erme.control.actions; package nl.andrewlalis.erme.control.actions;
import lombok.Setter;
import nl.andrewlalis.erme.model.*; import nl.andrewlalis.erme.model.*;
import nl.andrewlalis.erme.view.DiagramPanel; import nl.andrewlalis.erme.view.DiagramPanel;
import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
public class LoadSampleModelAction extends AbstractAction { public class LoadSampleModelAction extends DiagramPanelAction {
private static LoadSampleModelAction instance; public LoadSampleModelAction(DiagramPanel diagramPanel) {
super("Load Sample Model", diagramPanel);
public static LoadSampleModelAction getInstance() {
if (instance == null) {
instance = new LoadSampleModelAction();
}
return instance;
}
@Setter
private DiagramPanel diagramPanel;
public LoadSampleModelAction() {
super("Load Sample Model");
this.putValue(SHORT_DESCRIPTION, "Loads a sample ER-mapping model."); 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 Attribute(r1, AttributeType.PLAIN, "purchasedAt"));
r1.addAttribute(new ForeignKeyAttribute(r1, AttributeType.PLAIN, "typeName", "AirplaneType", "name")); r1.addAttribute(new ForeignKeyAttribute(r1, AttributeType.PLAIN, "typeName", "AirplaneType", "name"));
model.addRelation(r1); model.addRelation(r1);
this.diagramPanel.setModel(model); getDiagramPanel().setModel(model);
} }
} }

View File

@ -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;
}
}

View File

@ -1,37 +1,20 @@
package nl.andrewlalis.erme.control.actions; package nl.andrewlalis.erme.control.actions;
import lombok.Getter;
import lombok.Setter;
import nl.andrewlalis.erme.view.DiagramPanel; import nl.andrewlalis.erme.view.DiagramPanel;
import javax.swing.*; import javax.swing.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
public class LolcatAction extends AbstractAction { public class LolcatAction extends DiagramPanelAction {
private static LolcatAction instance; public LolcatAction(DiagramPanel diagramPanel) {
super("Toggle Lolcat Mode", diagramPanel);
@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");
this.putValue(SHORT_DESCRIPTION, "Does some wacky color stuff."); this.putValue(SHORT_DESCRIPTION, "Does some wacky color stuff.");
} }
@Override @Override
public void actionPerformed(ActionEvent actionEvent) { public void actionPerformed(ActionEvent actionEvent) {
lolcatEnabled = ((AbstractButton)actionEvent.getSource()).getModel().isSelected(); boolean lolcatEnabled = ((AbstractButton)actionEvent.getSource()).getModel().isSelected();
diagramPanel.repaint(); getDiagramPanel().getModel().setLolcatEnabled(lolcatEnabled);
getDiagramPanel().repaint();
} }
} }

View File

@ -1,19 +1,12 @@
package nl.andrewlalis.erme.control.actions; package nl.andrewlalis.erme.control.actions;
import nl.andrewlalis.erme.view.DiagramPanel;
import java.awt.*; import java.awt.*;
public class MappingAlgorithmHelpAction extends HtmlDocumentViewerAction { public class MappingAlgorithmHelpAction extends HtmlDocumentViewerAction {
private static MappingAlgorithmHelpAction instance; public MappingAlgorithmHelpAction(DiagramPanel diagramPanel) {
super("Mapping Algorithm Help", "html/er_mapping_algorithm.html", Dialog.ModalityType.DOCUMENT_MODAL, diagramPanel);
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);
this.putValue(SHORT_DESCRIPTION, "Shows a quick guide on how to map from an ER model to a schema."); this.putValue(SHORT_DESCRIPTION, "Shows a quick guide on how to map from an ER model to a schema.");
} }
} }

View File

@ -1,6 +1,5 @@
package nl.andrewlalis.erme.control.actions; package nl.andrewlalis.erme.control.actions;
import lombok.Setter;
import nl.andrewlalis.erme.model.MappingModel; import nl.andrewlalis.erme.model.MappingModel;
import nl.andrewlalis.erme.view.DiagramPanel; import nl.andrewlalis.erme.view.DiagramPanel;
@ -9,27 +8,15 @@ import java.awt.event.ActionEvent;
import java.awt.event.InputEvent; import java.awt.event.InputEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
public class NewModelAction extends AbstractAction { public class NewModelAction extends DiagramPanelAction {
private static NewModelAction instance; public NewModelAction(DiagramPanel diagramPanel) {
super("New Model", diagramPanel);
public static NewModelAction getInstance() {
if (instance == null) {
instance = new NewModelAction();
}
return instance;
}
@Setter
private DiagramPanel diagramPanel;
public NewModelAction() {
super("New Model");
this.putValue(SHORT_DESCRIPTION, "Create a new model."); this.putValue(SHORT_DESCRIPTION, "Create a new model.");
this.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_DOWN_MASK)); this.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_DOWN_MASK));
} }
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
this.diagramPanel.setModel(new MappingModel()); getDiagramPanel().setModel(new MappingModel());
} }
} }

View File

@ -4,8 +4,6 @@ import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.json.JsonMapper; import com.fasterxml.jackson.databind.json.JsonMapper;
import lombok.Setter;
import nl.andrewlalis.erme.model.MappingModel;
import nl.andrewlalis.erme.view.DiagramPanel; import nl.andrewlalis.erme.view.DiagramPanel;
import javax.swing.*; import javax.swing.*;
@ -18,25 +16,11 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.prefs.Preferences; 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 final String LAST_SAVE_LOCATION_KEY = "lastSaveLocation";
private static SaveAction instance; public SaveAction(DiagramPanel diagramPanel) {
public static SaveAction getInstance() { super("Save", diagramPanel);
if (instance == null) {
instance = new SaveAction();
}
return instance;
}
@Setter
private MappingModel model;
@Setter
private DiagramPanel diagramPanel;
public SaveAction() {
super("Save");
this.putValue(SHORT_DESCRIPTION, "Save the current diagram to a file."); this.putValue(SHORT_DESCRIPTION, "Save the current diagram to a file.");
this.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK)); 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) { if (path != null) {
fileChooser.setSelectedFile(new File(path)); fileChooser.setSelectedFile(new File(path));
} }
int choice = fileChooser.showSaveDialog(this.diagramPanel); DiagramPanel dp = getDiagramPanel();
int choice = fileChooser.showSaveDialog(dp);
if (choice == JFileChooser.APPROVE_OPTION) { if (choice == JFileChooser.APPROVE_OPTION) {
File chosenFile = fileChooser.getSelectedFile(); File chosenFile = fileChooser.getSelectedFile();
if (chosenFile == null || chosenFile.isDirectory()) { 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; return;
} }
if (!chosenFile.exists() && !chosenFile.getName().endsWith(".json")) { if (!chosenFile.exists() && !chosenFile.getName().endsWith(".json")) {
chosenFile = new File(chosenFile.getParent(), chosenFile.getName() + ".json"); chosenFile = new File(chosenFile.getParent(), chosenFile.getName() + ".json");
} else if (chosenFile.exists()) { } 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) { if (result == JOptionPane.NO_OPTION) {
return; return;
} }
@ -74,12 +59,12 @@ public class SaveAction extends AbstractAction {
.configure(SerializationFeature.INDENT_OUTPUT, true) .configure(SerializationFeature.INDENT_OUTPUT, true)
.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true) .configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true)
.build(); .build();
mapper.writeValue(fos, this.model.toJson(mapper)); mapper.writeValue(fos, dp.getModel().toJson(mapper));
prefs.put(LAST_SAVE_LOCATION_KEY, chosenFile.getAbsolutePath()); 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) { } catch (IOException ex) {
ex.printStackTrace(); 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);
} }
} }
} }

View File

@ -1,37 +1,19 @@
package nl.andrewlalis.erme.control.actions; package nl.andrewlalis.erme.control.actions;
import lombok.Getter;
import lombok.Setter;
import nl.andrewlalis.erme.view.DiagramPanel; import nl.andrewlalis.erme.view.DiagramPanel;
import javax.swing.*; import javax.swing.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
public class VisualizeReferencesAction extends AbstractAction { public class VisualizeReferencesAction extends DiagramPanelAction {
private static VisualizeReferencesAction instance; public VisualizeReferencesAction(DiagramPanel diagramPanel) {
super("Toggle Reference Visualization", diagramPanel);
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");
this.putValue(SHORT_DESCRIPTION, "Shows/hides visualization of the references between attributes."); this.putValue(SHORT_DESCRIPTION, "Shows/hides visualization of the references between attributes.");
} }
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
referenceVisualizationEnabled = ((AbstractButton)e.getSource()).getModel().isSelected(); getDiagramPanel().getModel().setReferenceVisualizationEnabled(((AbstractButton)e.getSource()).getModel().isSelected());
diagramPanel.repaint(); getDiagramPanel().repaint();
} }
} }

View File

@ -1,6 +1,6 @@
package nl.andrewlalis.erme.control.actions.edits; 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.model.*;
import nl.andrewlalis.erme.view.DiagramPanel; import nl.andrewlalis.erme.view.DiagramPanel;
@ -10,36 +10,23 @@ import java.awt.event.ActionEvent;
import java.awt.event.InputEvent; import java.awt.event.InputEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.stream.Stream; import java.util.stream.Stream;
public class AddAttributeAction extends AbstractAction { public class AddAttributeAction extends DiagramPanelAction {
private static AddAttributeAction instance; public AddAttributeAction(DiagramPanel diagramPanel) {
super("Add Attribute", diagramPanel);
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");
this.putValue(SHORT_DESCRIPTION, "Add an attribute to the selected relation."); this.putValue(SHORT_DESCRIPTION, "Add an attribute to the selected relation.");
this.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.CTRL_DOWN_MASK)); this.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.CTRL_DOWN_MASK));
} }
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
List<Relation> selectedRelations = this.model.getSelectedRelations(); DiagramPanel dp = getDiagramPanel();
MappingModel model = dp.getModel();
List<Relation> selectedRelations = model.getSelectedRelations();
if (selectedRelations.size() != 1) { if (selectedRelations.size() != 1) {
JOptionPane.showMessageDialog( JOptionPane.showMessageDialog(
this.diagramPanel, dp,
"A single relation must be selected to add an attribute.", "A single relation must be selected to add an attribute.",
"Single Relation Required", "Single Relation Required",
JOptionPane.WARNING_MESSAGE JOptionPane.WARNING_MESSAGE
@ -48,11 +35,10 @@ public class AddAttributeAction extends AbstractAction {
} }
Relation r = selectedRelations.get(0); Relation r = selectedRelations.get(0);
Attribute createdAttribute; Attribute createdAttribute;
Component source = this.diagramPanel; String name = JOptionPane.showInputDialog(dp, "Enter the name of the attribute.", "Attribute Name", JOptionPane.PLAIN_MESSAGE);
String name = JOptionPane.showInputDialog(source, "Enter the name of the attribute.", "Attribute Name", JOptionPane.PLAIN_MESSAGE);
if (name == null) return; if (name == null) return;
Integer index = (Integer) JOptionPane.showInputDialog( Integer index = (Integer) JOptionPane.showInputDialog(
source, dp,
"Select the index to insert this attribute at.", "Select the index to insert this attribute at.",
"Attribute Index", "Attribute Index",
JOptionPane.PLAIN_MESSAGE, JOptionPane.PLAIN_MESSAGE,
@ -62,7 +48,7 @@ public class AddAttributeAction extends AbstractAction {
); );
if (index == null) return; if (index == null) return;
AttributeType type = (AttributeType) JOptionPane.showInputDialog( AttributeType type = (AttributeType) JOptionPane.showInputDialog(
source, dp,
"Select the type this attribute is.", "Select the type this attribute is.",
"Attribute Type", "Attribute Type",
JOptionPane.PLAIN_MESSAGE, JOptionPane.PLAIN_MESSAGE,
@ -72,7 +58,7 @@ public class AddAttributeAction extends AbstractAction {
); );
if (type == null) return; if (type == null) return;
boolean shouldUseForeignKey = ((String) JOptionPane.showInputDialog( boolean shouldUseForeignKey = ((String) JOptionPane.showInputDialog(
source, dp,
"Is this attribute a foreign key?", "Is this attribute a foreign key?",
"Foreign Key", "Foreign Key",
JOptionPane.PLAIN_MESSAGE, JOptionPane.PLAIN_MESSAGE,
@ -81,27 +67,27 @@ public class AddAttributeAction extends AbstractAction {
"No" "No"
)).equalsIgnoreCase("yes"); )).equalsIgnoreCase("yes");
if (shouldUseForeignKey) { if (shouldUseForeignKey) {
if (this.model.getRelations().size() < 2) { if (model.getRelations().size() < 2) {
JOptionPane.showMessageDialog(source, "There should be at least 2 relations present in the model.", "Not Enough Relations", JOptionPane.WARNING_MESSAGE); JOptionPane.showMessageDialog(dp, "There should be at least 2 relations present in the model.", "Not Enough Relations", JOptionPane.WARNING_MESSAGE);
return; return;
} }
Relation fkRelation = (Relation) JOptionPane.showInputDialog( Relation fkRelation = (Relation) JOptionPane.showInputDialog(
source, dp,
"Select the relation that this foreign key references.", "Select the relation that this foreign key references.",
"Foreign Key Relation Reference", "Foreign Key Relation Reference",
JOptionPane.PLAIN_MESSAGE, JOptionPane.PLAIN_MESSAGE,
null, null,
this.model.getRelations().toArray(new Relation[0]), model.getRelations().toArray(new Relation[0]),
this.model.getRelations().stream().findFirst().orElse(null) model.getRelations().stream().findFirst().orElse(null)
); );
if (fkRelation == null) return; if (fkRelation == null) return;
List<Attribute> eligibleAttributes = fkRelation.getAttributes(); List<Attribute> eligibleAttributes = fkRelation.getAttributes();
if (eligibleAttributes.isEmpty()) { 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; return;
} }
Attribute fkAttribute = (Attribute) JOptionPane.showInputDialog( Attribute fkAttribute = (Attribute) JOptionPane.showInputDialog(
source, dp,
"Select the attribute that this foreign key references.", "Select the attribute that this foreign key references.",
"Foreign Key Attribute Reference", "Foreign Key Attribute Reference",
JOptionPane.PLAIN_MESSAGE, JOptionPane.PLAIN_MESSAGE,

View File

@ -1,7 +1,6 @@
package nl.andrewlalis.erme.control.actions.edits; package nl.andrewlalis.erme.control.actions.edits;
import lombok.Setter; import nl.andrewlalis.erme.control.actions.DiagramPanelAction;
import nl.andrewlalis.erme.control.actions.LocalAction;
import nl.andrewlalis.erme.model.MappingModel; import nl.andrewlalis.erme.model.MappingModel;
import nl.andrewlalis.erme.model.Relation; import nl.andrewlalis.erme.model.Relation;
import nl.andrewlalis.erme.view.DiagramPanel; import nl.andrewlalis.erme.view.DiagramPanel;
@ -12,57 +11,45 @@ import java.awt.event.ActionEvent;
import java.awt.event.InputEvent; import java.awt.event.InputEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
public class AddRelationAction extends LocalAction { public class AddRelationAction extends DiagramPanelAction {
private static AddRelationAction instance; public AddRelationAction(DiagramPanel diagramPanel) {
public static AddRelationAction getInstance() { super("Add Relation", diagramPanel);
if (instance == null) {
instance = new AddRelationAction();
}
return instance;
}
@Setter
private MappingModel model;
@Setter
private DiagramPanel diagramPanel;
public AddRelationAction() {
super("Add Relation");
this.putValue(SHORT_DESCRIPTION, "Add a new relation to the diagram."); this.putValue(SHORT_DESCRIPTION, "Add a new relation to the diagram.");
this.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_DOWN_MASK)); this.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_DOWN_MASK));
} }
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
DiagramPanel dp = getDiagramPanel();
MappingModel model = dp.getModel();
String name = JOptionPane.showInputDialog( String name = JOptionPane.showInputDialog(
this.diagramPanel, dp,
"Enter the name of the relation.", "Enter the name of the relation.",
"Add Relation", "Add Relation",
JOptionPane.PLAIN_MESSAGE JOptionPane.PLAIN_MESSAGE
); );
if (name != null) { if (name != null) {
final boolean isFirstRelation = this.model.getRelations().isEmpty(); final boolean isFirstRelation = model.getRelations().isEmpty();
Point p; Point p;
if (this.hasLocation()) { if (model.getLastInteractionPoint() != null) {
p = new Point( p = new Point(
this.getLocation().x - this.diagramPanel.getPanningTranslation().x, model.getLastInteractionPoint().x - dp.getPanningTranslation().x,
this.getLocation().y - this.diagramPanel.getPanningTranslation().y model.getLastInteractionPoint().y - dp.getPanningTranslation().y
); );
} else if (isFirstRelation) { } else if (isFirstRelation) {
p = new Point(100, 100); p = new Point(100, 100);
} else { } else {
Rectangle bounds = this.model.getRelationBounds(); Rectangle bounds = model.getRelationBounds();
p = new Point(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2); p = new Point(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2);
} }
Relation r = new Relation(this.model, p, name); Relation r = new Relation(model, p, name);
this.model.getSelectedRelations().forEach(rl -> rl.setSelected(false)); model.getSelectedRelations().forEach(rl -> rl.setSelected(false));
r.setSelected(true); r.setSelected(true);
this.model.addRelation(r); model.addRelation(r);
if (isFirstRelation) { if (isFirstRelation) {
this.model.normalizeRelationPositions(); model.normalizeRelationPositions();
this.diagramPanel.centerModel(); dp.centerModel();
this.diagramPanel.repaint(); dp.repaint();
} }
} }
} }

View File

@ -1,8 +1,7 @@
package nl.andrewlalis.erme.control.actions.edits; 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.Attribute;
import nl.andrewlalis.erme.model.MappingModel;
import nl.andrewlalis.erme.model.Relation; import nl.andrewlalis.erme.model.Relation;
import nl.andrewlalis.erme.view.DiagramPanel; import nl.andrewlalis.erme.view.DiagramPanel;
@ -12,33 +11,19 @@ import java.awt.event.InputEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.util.List; import java.util.List;
public class RemoveAttributeAction extends AbstractAction { public class RemoveAttributeAction extends DiagramPanelAction {
private static RemoveAttributeAction instance; public RemoveAttributeAction(DiagramPanel diagramPanel) {
super("Remove Attribute", diagramPanel);
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");
this.putValue(SHORT_DESCRIPTION, "Remove an attribute from a relation."); 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)); this.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK));
} }
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
List<Relation> selectedRelations = this.model.getSelectedRelations(); List<Relation> selectedRelations = getDiagramPanel().getModel().getSelectedRelations();
if (selectedRelations.size() != 1 || selectedRelations.get(0).getAttributes().isEmpty()) { if (selectedRelations.size() != 1 || selectedRelations.get(0).getAttributes().isEmpty()) {
JOptionPane.showMessageDialog( JOptionPane.showMessageDialog(
this.diagramPanel, getDiagramPanel(),
"A single relation with at least one attribute must be selected to remove an attribute.", "A single relation with at least one attribute must be selected to remove an attribute.",
"Single Relation With Attribute Required", "Single Relation With Attribute Required",
JOptionPane.WARNING_MESSAGE JOptionPane.WARNING_MESSAGE
@ -47,7 +32,7 @@ public class RemoveAttributeAction extends AbstractAction {
} }
Relation r = selectedRelations.get(0); Relation r = selectedRelations.get(0);
Attribute attribute = (Attribute) JOptionPane.showInputDialog( Attribute attribute = (Attribute) JOptionPane.showInputDialog(
this.diagramPanel, getDiagramPanel(),
"Select the attribute to remove.", "Select the attribute to remove.",
"Select Attribute", "Select Attribute",
JOptionPane.PLAIN_MESSAGE, JOptionPane.PLAIN_MESSAGE,

View File

@ -1,50 +1,36 @@
package nl.andrewlalis.erme.control.actions.edits; 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.MappingModel;
import nl.andrewlalis.erme.model.Relation; import nl.andrewlalis.erme.model.Relation;
import nl.andrewlalis.erme.view.DiagramPanel; import nl.andrewlalis.erme.view.DiagramPanel;
import javax.swing.*; import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.InputEvent; import java.awt.event.InputEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
public class RemoveRelationAction extends AbstractAction { public class RemoveRelationAction extends DiagramPanelAction {
private static RemoveRelationAction instance; public RemoveRelationAction(DiagramPanel diagramPanel) {
super("Remove Relation", diagramPanel);
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");
this.putValue(SHORT_DESCRIPTION, "Remove a relation from the diagram."); 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)); this.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK));
} }
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (this.model.getSelectedRelations().isEmpty()) { MappingModel model = getDiagramPanel().getModel();
if (model.getSelectedRelations().isEmpty()) {
JOptionPane.showMessageDialog( JOptionPane.showMessageDialog(
this.diagramPanel, getDiagramPanel(),
"No relations selected. Select at least one relation to remove.", "No relations selected. Select at least one relation to remove.",
"No Relations Selected", "No Relations Selected",
JOptionPane.WARNING_MESSAGE JOptionPane.WARNING_MESSAGE
); );
return; return;
} }
for (Relation r : this.model.getSelectedRelations()) { for (Relation r : model.getSelectedRelations()) {
this.model.removeRelation(r); model.removeRelation(r);
} }
} }
} }

View File

@ -11,11 +11,11 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
public class DiagramMouseListener extends MouseAdapter { public class DiagramMouseListener extends MouseAdapter {
private final MappingModel model; private final DiagramPanel diagramPanel;
private Point mouseDragStart; private Point mouseDragStart;
public DiagramMouseListener(MappingModel model) { public DiagramMouseListener(DiagramPanel diagramPanel) {
this.model = model; 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 isCtrlDown = (e.getModifiers() & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK;
final boolean isShiftDown = (e.getModifiers() & ActionEvent.SHIFT_MASK) == ActionEvent.SHIFT_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. 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. 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)) { if (r.getViewModel().getBounds(g).contains(modelX, modelY)) {
r.setSelected(!r.isSelected()); r.setSelected(!r.isSelected());
break; break;
@ -54,11 +55,12 @@ public class DiagramMouseListener extends MouseAdapter {
// If the user right-clicked, show a popup menu. // If the user right-clicked, show a popup menu.
if (e.getButton() == MouseEvent.BUTTON3) { 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()); popupMenu.show(panel, e.getX(), e.getY());
} }
this.model.fireChangedEvent(); model.fireChangedEvent();
} }
@Override @Override
@ -72,13 +74,14 @@ public class DiagramMouseListener extends MouseAdapter {
final int dy = this.mouseDragStart.y - e.getY(); final int dy = this.mouseDragStart.y - e.getY();
final boolean isShiftDown = (e.getModifiers() & ActionEvent.SHIFT_MASK) == ActionEvent.SHIFT_MASK; final boolean isShiftDown = (e.getModifiers() & ActionEvent.SHIFT_MASK) == ActionEvent.SHIFT_MASK;
boolean changed = false; boolean changed = false;
MappingModel model = this.diagramPanel.getModel();
if (isShiftDown) { if (isShiftDown) {
final DiagramPanel panel = (DiagramPanel) e.getSource(); System.out.println(e);
panel.translate(-dx, -dy); this.diagramPanel.translate(-dx, -dy);
panel.repaint(); this.diagramPanel.repaint();
} else { } else {
for (Relation r : this.model.getRelations()) { for (Relation r : model.getRelations()) {
if (r.isSelected()) { if (r.isSelected()) {
r.setPosition(new Point(r.getPosition().x - dx, r.getPosition().y - dy)); r.setPosition(new Point(r.getPosition().x - dx, r.getPosition().y - dy));
changed = true; changed = true;
@ -87,7 +90,7 @@ public class DiagramMouseListener extends MouseAdapter {
} }
if (changed) { if (changed) {
this.model.fireChangedEvent(); model.fireChangedEvent();
} }
this.mouseDragStart = e.getPoint(); this.mouseDragStart = e.getPoint();
} }

View File

@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.Getter; import lombok.Getter;
import lombok.Setter;
import nl.andrewlalis.erme.view.view_models.MappingModelViewModel; import nl.andrewlalis.erme.view.view_models.MappingModelViewModel;
import nl.andrewlalis.erme.view.view_models.ViewModel; import nl.andrewlalis.erme.view.view_models.ViewModel;
@ -23,6 +24,16 @@ public class MappingModel implements Viewable {
private transient final Set<ModelChangeListener> changeListeners; private transient final Set<ModelChangeListener> changeListeners;
@Getter
@Setter
private transient Point lastInteractionPoint = null;
@Getter
@Setter
private transient boolean lolcatEnabled = false;
@Getter
@Setter
private transient boolean referenceVisualizationEnabled = false;
public MappingModel() { public MappingModel() {
this.relations = new HashSet<>(); this.relations = new HashSet<>();
this.changeListeners = new HashSet<>(); this.changeListeners = new HashSet<>();

View File

@ -1,11 +1,6 @@
package nl.andrewlalis.erme.view; package nl.andrewlalis.erme.view;
import lombok.Getter; 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.control.diagram.DiagramMouseListener;
import nl.andrewlalis.erme.model.MappingModel; import nl.andrewlalis.erme.model.MappingModel;
import nl.andrewlalis.erme.model.ModelChangeListener; 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. * The main panel in which the ER Mapping diagram is displayed.
*/ */
public class DiagramPanel extends JPanel implements ModelChangeListener { 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 @Getter
private MappingModel model; private MappingModel model;
@ -60,10 +59,10 @@ public class DiagramPanel extends JPanel implements ModelChangeListener {
for (MouseMotionListener listener : this.getMouseMotionListeners()) { for (MouseMotionListener listener : this.getMouseMotionListeners()) {
this.removeMouseMotionListener(listener); this.removeMouseMotionListener(listener);
} }
DiagramMouseListener listener = new DiagramMouseListener(newModel); DiagramMouseListener listener = new DiagramMouseListener(this);
this.addMouseListener(listener); this.addMouseListener(listener);
this.addMouseMotionListener(listener); this.addMouseMotionListener(listener);
this.updateActionModels(); this.updateActionModels(); // TODO: remove this once OrderableListPanel is cleaned up.
newModel.addChangeListener(OrderableListPanel.getInstance()); newModel.addChangeListener(OrderableListPanel.getInstance());
this.centerModel(); this.centerModel();
this.repaint(); this.repaint();
@ -79,6 +78,9 @@ public class DiagramPanel extends JPanel implements ModelChangeListener {
this.panningTranslation.y = 0; this.panningTranslation.y = 0;
} }
/**
* Centers the model in the panel, by adjusting the panning translation.
*/
public void centerModel() { public void centerModel() {
if (this.getGraphics() == null) { if (this.getGraphics() == null) {
return; return;
@ -120,30 +122,7 @@ public class DiagramPanel extends JPanel implements ModelChangeListener {
* TODO: Clean this up somehow! * TODO: Clean this up somehow!
*/ */
private void updateActionModels() { 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); 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) { public static void prepareGraphics(Graphics2D g) {

View File

@ -2,28 +2,27 @@ package nl.andrewlalis.erme.view;
import nl.andrewlalis.erme.control.actions.edits.AddAttributeAction; import nl.andrewlalis.erme.control.actions.edits.AddAttributeAction;
import nl.andrewlalis.erme.control.actions.edits.AddRelationAction; 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.actions.edits.RemoveRelationAction;
import nl.andrewlalis.erme.model.MappingModel;
import nl.andrewlalis.erme.model.Relation; import nl.andrewlalis.erme.model.Relation;
import javax.swing.*; import javax.swing.*;
import java.awt.event.MouseEvent;
import java.util.List; import java.util.List;
public class DiagramPopupMenu extends JPopupMenu { public class DiagramPopupMenu extends JPopupMenu {
public DiagramPopupMenu(MappingModel model, MouseEvent e) { public DiagramPopupMenu(DiagramPanel diagramPanel) {
List<Relation> selectedRelations = model.getSelectedRelations(); List<Relation> selectedRelations = diagramPanel.getModel().getSelectedRelations();
AddRelationAction.getInstance().setLocation(e.getPoint());
if (selectedRelations.size() == 0) { if (selectedRelations.size() == 0) {
this.add(AddRelationAction.getInstance()); this.add(new AddRelationAction(diagramPanel));
} }
if (selectedRelations.size() > 0) { if (selectedRelations.size() > 0) {
this.add(RemoveRelationAction.getInstance()); this.add(new RemoveRelationAction(diagramPanel));
} }
if (selectedRelations.size() == 1) { if (selectedRelations.size() == 1) {
this.add(AddAttributeAction.getInstance()); Relation relation = selectedRelations.get(0);
this.add(RemoveAttributeAction.getInstance()); this.add(new AddAttributeAction(diagramPanel));
if (!relation.getAttributes().isEmpty()) {
this.add(new RemoveRelationAction(diagramPanel));
}
} }
} }
} }

View File

@ -14,8 +14,9 @@ import java.io.InputStream;
public class EditorFrame extends JFrame { public class EditorFrame extends JFrame {
public EditorFrame() { public EditorFrame() {
super("ER-Mapping Editor"); super("ER-Mapping Editor");
this.setContentPane(new DiagramPanel(new MappingModel())); DiagramPanel diagramPanel = new DiagramPanel(new MappingModel());
this.setJMenuBar(new EditorMenuBar()); this.setContentPane(diagramPanel);
this.setJMenuBar(new EditorMenuBar(diagramPanel));
try { try {
InputStream is = getClass().getClassLoader().getResourceAsStream("icon.png"); InputStream is = getClass().getClassLoader().getResourceAsStream("icon.png");
if (is == null) { if (is == null) {
@ -26,7 +27,7 @@ public class EditorFrame extends JFrame {
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
this.setMinimumSize(new Dimension(400, 400)); this.setMinimumSize(new Dimension(300, 300));
this.setPreferredSize(new Dimension(800, 800)); this.setPreferredSize(new Dimension(800, 800));
this.pack(); this.pack();
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

View File

@ -3,7 +3,6 @@ package nl.andrewlalis.erme.view;
import nl.andrewlalis.erme.control.actions.*; import nl.andrewlalis.erme.control.actions.*;
import nl.andrewlalis.erme.control.actions.edits.AddAttributeAction; import nl.andrewlalis.erme.control.actions.edits.AddAttributeAction;
import nl.andrewlalis.erme.control.actions.edits.AddRelationAction; 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.actions.edits.RemoveRelationAction;
import javax.swing.*; import javax.swing.*;
@ -12,51 +11,47 @@ import javax.swing.*;
* The menu bar that's visible atop the application. * The menu bar that's visible atop the application.
*/ */
public class EditorMenuBar extends JMenuBar { public class EditorMenuBar extends JMenuBar {
public EditorMenuBar() { public EditorMenuBar(DiagramPanel diagramPanel) {
this.add(this.buildFileMenu()); this.add(this.buildFileMenu(diagramPanel));
this.add(this.buildEditMenu()); this.add(this.buildEditMenu(diagramPanel));
this.add(this.buildViewMenu()); this.add(this.buildViewMenu(diagramPanel));
this.add(this.buildHelpMenu()); this.add(this.buildHelpMenu(diagramPanel));
} }
private JMenu buildFileMenu() { private JMenu buildFileMenu(DiagramPanel diagramPanel) {
JMenu menu = new JMenu("File"); JMenu menu = new JMenu("File");
menu.add(NewModelAction.getInstance()); menu.add(new NewModelAction(diagramPanel));
menu.add(SaveAction.getInstance()); menu.add(new SaveAction(diagramPanel));
menu.add(LoadAction.getInstance()); menu.add(new LoadAction(diagramPanel));
menu.addSeparator(); menu.addSeparator();
menu.add(ExportToImageAction.getInstance()); menu.add(new ExportToImageAction(diagramPanel));
menu.addSeparator(); menu.addSeparator();
menu.add(ExitAction.getInstance()); menu.add(new ExitAction(diagramPanel));
return menu; return menu;
} }
private JMenu buildEditMenu() { private JMenu buildEditMenu(DiagramPanel diagramPanel) {
JMenu menu = new JMenu("Edit"); JMenu menu = new JMenu("Edit");
menu.add(AddRelationAction.getInstance()); menu.add(new AddRelationAction(diagramPanel));
menu.add(RemoveRelationAction.getInstance()); menu.add(new RemoveRelationAction(diagramPanel));
menu.add(AddAttributeAction.getInstance()); menu.add(new AddAttributeAction(diagramPanel));
menu.add(RemoveAttributeAction.getInstance()); menu.add(new RemoveRelationAction(diagramPanel));
menu.add(AutoPositionAction.getInstance()); menu.add(new AutoPositionAction(diagramPanel));
menu.addSeparator();
menu.add(UndoAction.getInstance());
menu.add(RedoAction.getInstance());
return menu; return menu;
} }
private JMenu buildViewMenu() { private JMenu buildViewMenu(DiagramPanel diagramPanel) {
JMenu menu = new JMenu("View"); JMenu menu = new JMenu("View");
menu.add(new JCheckBoxMenuItem(LolcatAction.getInstance())); menu.add(new JCheckBoxMenuItem(new LolcatAction(diagramPanel)));
menu.add(new JCheckBoxMenuItem(VisualizeReferencesAction.getInstance())); menu.add(new JCheckBoxMenuItem(new VisualizeReferencesAction(diagramPanel)));
return menu; return menu;
} }
private JMenu buildHelpMenu() { private JMenu buildHelpMenu(DiagramPanel diagramPanel) {
JMenu menu = new JMenu("Help"); JMenu menu = new JMenu("Help");
menu.add(InstructionsAction.getInstance()); menu.add(new InstructionsAction(diagramPanel));
menu.add(MappingAlgorithmHelpAction.getInstance()); menu.add(new MappingAlgorithmHelpAction(diagramPanel));
menu.add(LoadSampleModelAction.getInstance()); menu.add(new LoadSampleModelAction(diagramPanel));
menu.add(AboutAction.getInstance());
return menu; return menu;
} }
} }

View File

@ -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 * 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. * 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 { public class OrderableListPanel extends JPanel implements ModelChangeListener {
private static OrderableListPanel instance; private static OrderableListPanel instance;

View File

@ -1,6 +1,5 @@
package nl.andrewlalis.erme.view.view_models; 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.Attribute;
import nl.andrewlalis.erme.model.AttributeType; import nl.andrewlalis.erme.model.AttributeType;
import nl.andrewlalis.erme.model.ForeignKeyAttribute; import nl.andrewlalis.erme.model.ForeignKeyAttribute;
@ -46,7 +45,7 @@ public class AttributeViewModel implements ViewModel {
} }
private Color getBackgroundColor(int x, int y, Graphics2D g) { 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(); Point offset = g.getClipBounds().getLocation();
g.translate(offset.x, offset.y); g.translate(offset.x, offset.y);
Dimension viewportSize = g.getClipBounds().getSize(); Dimension viewportSize = g.getClipBounds().getSize();

View File

@ -1,13 +1,11 @@
package nl.andrewlalis.erme.view.view_models; 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.Attribute;
import nl.andrewlalis.erme.model.ForeignKeyAttribute; import nl.andrewlalis.erme.model.ForeignKeyAttribute;
import nl.andrewlalis.erme.model.MappingModel; import nl.andrewlalis.erme.model.MappingModel;
import nl.andrewlalis.erme.model.Relation; import nl.andrewlalis.erme.model.Relation;
import java.awt.*; import java.awt.*;
import java.awt.color.ColorSpace;
import java.util.Random; import java.util.Random;
/** /**
@ -22,9 +20,7 @@ public class MappingModelViewModel implements ViewModel {
@Override @Override
public void draw(Graphics2D g) { public void draw(Graphics2D g) {
if (VisualizeReferencesAction.getInstance().isReferenceVisualizationEnabled()) { if (model.isReferenceVisualizationEnabled()) visualizeReferences(g);
visualizeReferences(g);
}
for (Relation r : this.model.getRelations()) { for (Relation r : this.model.getRelations()) {
r.getViewModel().draw(g); r.getViewModel().draw(g);
} }

View File

@ -7,9 +7,13 @@
<body> <body>
<h1>Entity-Relation Mapping Editor</h1> <h1>Entity-Relation Mapping Editor</h1>
<p>Created by <a href="https://github.com/andrewlalis">@andrewlalis</a></p>
<p><em>A simple UI for editing entity-relation mapping diagrams.</em></p> <p><em>A simple UI for editing entity-relation mapping diagrams.</em></p>
<p>Created by <a href="https://github.com/andrewlalis">Andrew Lalis</a></p>
<p>And with generous contributions by</p>
<ul>
<li><a href="https://github.com/bjornpijnacker">Bjorn Pijnacker</a></li>
</ul>
<p> <p>
Have you noticed any unexpected behavior? Is there something you think would make a good addition to this application? Have you noticed any unexpected behavior? Is there something you think would make a good addition to this application?
@ -27,6 +31,9 @@
<li> <li>
The <em>Edit</em> menu contains options for making changes to the current model, such as adding or removing relations and attributes, or undoing/redoing actions. The <em>Edit</em> menu contains options for making changes to the current model, such as adding or removing relations and attributes, or undoing/redoing actions.
</li> </li>
<li>
The <em>View</em> menu contains options for changing how the model is viewed.
</li>
<li> <li>
The <em>Help</em> menu contains some items with additional information about the application, like this help page and a simple <em>About</em> popup with version information. There's also a <em>Load Sample Model</em> option, which will load a very basic sample model into the application that you are free to mess around with. The <em>Help</em> menu contains some items with additional information about the application, like this help page and a simple <em>About</em> popup with version information. There's also a <em>Load Sample Model</em> option, which will load a very basic sample model into the application that you are free to mess around with.
</li> </li>