Added visualization of relations, transparent selection and attribute backgrounds

This commit is contained in:
Andrew Lalis 2021-10-27 17:31:18 +02:00
parent bc464ba42b
commit fa87c32591
7 changed files with 80 additions and 8 deletions

View File

@ -7,8 +7,9 @@ This program is distributed as an executable **jar** file. You can find the late
Simply double-click on the jar file, or execute `java -jar <jar file>` from the command line (where `<jar file>` is replaced with the path to your actual jar file). Simply double-click on the jar file, or execute `java -jar <jar file>` from the command line (where `<jar file>` is replaced with the path to your actual jar file).
![window screenshot](https://raw.githubusercontent.com/andrewlalis/EntityRelationMappingEditor/main/design/main_interface.PNG) ![window screenshot](https://raw.githubusercontent.com/andrewlalis/EntityRelationMappingEditor/main/design/main_interface.PNG)
> The above image shows the application's user-interface.
## How to Use ## Instructions
The interface and menus should be pretty self-explanatory, but here are some tips to get you started: The interface and menus should be pretty self-explanatory, but here are some tips to get you started:
* Click on a relation to select it. * Click on a relation to select it.
* You can CTRL + click to select multiple relations. * You can CTRL + click to select multiple relations.
@ -16,7 +17,7 @@ The interface and menus should be pretty self-explanatory, but here are some tip
* Right-click on different areas to access context menus with some helpful actions. * Right-click on different areas to access context menus with some helpful actions.
* When exporting the model to an image, be sure to add the desired image file extension (`.png`, `.jpg`, `.bmp`, etc.), or the application will default to `.png`. * When exporting the model to an image, be sure to add the desired image file extension (`.png`, `.jpg`, `.bmp`, etc.), or the application will default to `.png`.
## Sample Exported Image ## Contributing
Here's a sample of an exported diagram. This is an open-source project, and gladly accepts contributions in terms of new features, bug fixes, suggestions, bug reports, and more.
* [Create a new issue](https://github.com/andrewlalis/EntityRelationMappingEditor/issues) if you'd like to make a suggestion, or report a bug.
![sample diagram export](https://raw.githubusercontent.com/andrewlalis/EntityRelationMappingEditor/main/design/sample_export.png) * Fork the repository, make your changes, and submit them as a pull request.

View File

@ -0,0 +1,37 @@
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");
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();
}
}

View File

@ -135,6 +135,7 @@ public class DiagramPanel extends JPanel implements ModelChangeListener {
RemoveAttributeAction.getInstance().setDiagramPanel(this); RemoveAttributeAction.getInstance().setDiagramPanel(this);
LoadSampleModelAction.getInstance().setDiagramPanel(this); LoadSampleModelAction.getInstance().setDiagramPanel(this);
LolcatAction.getInstance().setDiagramPanel(this); LolcatAction.getInstance().setDiagramPanel(this);
VisualizeReferencesAction.getInstance().setDiagramPanel(this);
AutoPositionAction.getInstance().setDiagramPanel(this); AutoPositionAction.getInstance().setDiagramPanel(this);
AutoPositionAction.getInstance().setModel(this.model); AutoPositionAction.getInstance().setModel(this.model);
OrderableListPanel.getInstance().setModel(this.model); OrderableListPanel.getInstance().setModel(this.model);

View File

@ -15,6 +15,7 @@ public class EditorMenuBar extends JMenuBar {
public EditorMenuBar() { public EditorMenuBar() {
this.add(this.buildFileMenu()); this.add(this.buildFileMenu());
this.add(this.buildEditMenu()); this.add(this.buildEditMenu());
this.add(this.buildViewMenu());
this.add(this.buildHelpMenu()); this.add(this.buildHelpMenu());
} }
@ -36,7 +37,6 @@ public class EditorMenuBar extends JMenuBar {
menu.add(RemoveRelationAction.getInstance()); menu.add(RemoveRelationAction.getInstance());
menu.add(AddAttributeAction.getInstance()); menu.add(AddAttributeAction.getInstance());
menu.add(RemoveAttributeAction.getInstance()); menu.add(RemoveAttributeAction.getInstance());
menu.add(new JCheckBoxMenuItem(LolcatAction.getInstance()));
menu.add(AutoPositionAction.getInstance()); menu.add(AutoPositionAction.getInstance());
menu.addSeparator(); menu.addSeparator();
menu.add(UndoAction.getInstance()); menu.add(UndoAction.getInstance());
@ -44,6 +44,13 @@ public class EditorMenuBar extends JMenuBar {
return menu; return menu;
} }
private JMenu buildViewMenu() {
JMenu menu = new JMenu("View");
menu.add(new JCheckBoxMenuItem(LolcatAction.getInstance()));
menu.add(new JCheckBoxMenuItem(VisualizeReferencesAction.getInstance()));
return menu;
}
private JMenu buildHelpMenu() { private JMenu buildHelpMenu() {
JMenu menu = new JMenu("Help"); JMenu menu = new JMenu("Help");
menu.add(InstructionsAction.getInstance()); menu.add(InstructionsAction.getInstance());

View File

@ -16,7 +16,7 @@ import java.text.AttributedString;
public class AttributeViewModel implements ViewModel { public class AttributeViewModel implements ViewModel {
public static final int PADDING_X = 5; public static final int PADDING_X = 5;
public static final int PADDING_Y = 5; public static final int PADDING_Y = 5;
public static final Color BACKGROUND_COLOR = Color.LIGHT_GRAY; public static final Color BACKGROUND_COLOR = new Color(192, 192, 192, 127);
public static final Color FONT_COLOR = Color.BLACK; public static final Color FONT_COLOR = Color.BLACK;
public static final float FK_FONT_SIZE = 11.0f; public static final float FK_FONT_SIZE = 11.0f;
private static final float LOLCAT_SAT = 0.75f; private static final float LOLCAT_SAT = 0.75f;

View File

@ -1,5 +1,8 @@
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.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;
@ -17,11 +20,34 @@ public class MappingModelViewModel implements ViewModel {
@Override @Override
public void draw(Graphics2D g) { public void draw(Graphics2D g) {
if (VisualizeReferencesAction.getInstance().isReferenceVisualizationEnabled()) {
visualizeReferences(g);
}
for (Relation r : this.model.getRelations()) { for (Relation r : this.model.getRelations()) {
r.getViewModel().draw(g); r.getViewModel().draw(g);
} }
} }
private void visualizeReferences(Graphics2D g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setColor(Color.BLUE);
Stroke dashedStroke = new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 0, new float[]{5}, 0);
g2.setStroke(dashedStroke);
for (Relation r : this.model.getRelations()) {
for (Attribute a : r.getAttributes()) {
if (a instanceof ForeignKeyAttribute) {
ForeignKeyAttribute fk = (ForeignKeyAttribute) a;
Rectangle sourceBounds = fk.getViewModel().getBounds(g);
Rectangle targetBounds = fk.getReference().getViewModel().getBounds(g);
Point sourcePoint = new Point(sourceBounds.x + sourceBounds.width / 2, sourceBounds.y);
Point targetPoint = new Point(targetBounds.x + targetBounds.width / 2, targetBounds.y + targetBounds.height);
g2.drawLine(sourcePoint.x, sourcePoint.y, targetPoint.x, targetPoint.y);
}
}
}
g2.dispose();
}
@Override @Override
public Rectangle getBounds(Graphics2D g) { public Rectangle getBounds(Graphics2D g) {
int minX = Integer.MAX_VALUE; int minX = Integer.MAX_VALUE;

View File

@ -27,7 +27,7 @@ public class RelationViewModel implements ViewModel {
*/ */
public static final int ATTRIBUTE_SEPARATION = 10; public static final int ATTRIBUTE_SEPARATION = 10;
public static final Color SELECTED_COLOR = new Color(204, 224, 255); public static final Color SELECTED_COLOR = new Color(204, 224, 255, 127);
public static final Color NAME_COLOR = Color.BLACK; public static final Color NAME_COLOR = Color.BLACK;
private final Relation relation; private final Relation relation;