diff --git a/src/main/java/nl/andrewlalis/erme/EntityRelationMappingEditor.java b/src/main/java/nl/andrewlalis/erme/EntityRelationMappingEditor.java index 6099536..e50e30b 100644 --- a/src/main/java/nl/andrewlalis/erme/EntityRelationMappingEditor.java +++ b/src/main/java/nl/andrewlalis/erme/EntityRelationMappingEditor.java @@ -7,25 +7,30 @@ import nl.andrewlalis.erme.view.EditorFrame; import java.nio.charset.StandardCharsets; public class EntityRelationMappingEditor { - public static final String VERSION = "1.3.1"; + public static final String VERSION = "1.3.1"; + private static EditorFrame frame; - public static void main(String[] args) { - if (!FlatLightLaf.install()) { - System.err.println("Could not install FlatLight Look and Feel."); - } - final boolean includeAdminActions = shouldIncludeAdminActions(args); - if (includeAdminActions) { - System.out.println("Admin actions have been enabled."); - } - final EditorFrame frame = new EditorFrame(includeAdminActions); - frame.setVisible(true); - } + public static EditorFrame getFrame() { + return frame; + } - private static boolean shouldIncludeAdminActions(String[] args) { - if (args.length < 1) { - return false; - } - byte[] pw = args[0].getBytes(StandardCharsets.UTF_8); - return Hash.matches(pw, "admin_hash.txt"); - } + public static void main(String[] args) { + if (!FlatLightLaf.install()) { + System.err.println("Could not install FlatLight Look and Feel."); + } + final boolean includeAdminActions = shouldIncludeAdminActions(args); + if (includeAdminActions) { + System.out.println("Admin actions have been enabled."); + } + frame = new EditorFrame(includeAdminActions); + frame.setVisible(true); + } + + private static boolean shouldIncludeAdminActions(String[] args) { + if (args.length < 1) { + return false; + } + byte[] pw = args[0].getBytes(StandardCharsets.UTF_8); + return Hash.matches(pw, "admin_hash.txt"); + } } 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 96c6fba..7ddeb19 100644 --- a/src/main/java/nl/andrewlalis/erme/control/actions/ExportToImageAction.java +++ b/src/main/java/nl/andrewlalis/erme/control/actions/ExportToImageAction.java @@ -4,6 +4,7 @@ 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.view_models.AttributeViewModel; import nl.andrewlalis.erme.view.view_models.MappingModelViewModel; import javax.imageio.ImageIO; @@ -113,10 +114,13 @@ public class ExportToImageAction extends AbstractAction { DiagramPanel.prepareGraphics(g2d); // Render the model. + boolean lolcat = AttributeViewModel.getLolcatMode(); // save previous lolcat mode + AttributeViewModel.setLolcatMode(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))); + AttributeViewModel.setLolcatMode(lolcat); // revert previous lolcat mode // Revert back to the normal image space, and render a watermark. g2d.setTransform(originalTransform); diff --git a/src/main/java/nl/andrewlalis/erme/control/actions/LolcatAction.java b/src/main/java/nl/andrewlalis/erme/control/actions/LolcatAction.java new file mode 100644 index 0000000..7fc7d94 --- /dev/null +++ b/src/main/java/nl/andrewlalis/erme/control/actions/LolcatAction.java @@ -0,0 +1,27 @@ +package nl.andrewlalis.erme.control.actions; + +import nl.andrewlalis.erme.EntityRelationMappingEditor; +import nl.andrewlalis.erme.view.view_models.AttributeViewModel; + +import javax.swing.*; +import java.awt.event.ActionEvent; + +public class LolcatAction extends AbstractAction { + private static LolcatAction instance; + public static LolcatAction getInstance() { + if (instance == null) { + instance = new LolcatAction(); + } + return instance; + } + + public LolcatAction() { + super("Toggle Lolcat Mode"); + } + + @Override + public void actionPerformed(ActionEvent actionEvent) { + AttributeViewModel.setLolcatMode(((AbstractButton)actionEvent.getSource()).getModel().isSelected()); + EntityRelationMappingEditor.getFrame().getContentPane().repaint(); + } +} diff --git a/src/main/java/nl/andrewlalis/erme/view/EditorMenuBar.java b/src/main/java/nl/andrewlalis/erme/view/EditorMenuBar.java index f2a5770..8710c3d 100644 --- a/src/main/java/nl/andrewlalis/erme/view/EditorMenuBar.java +++ b/src/main/java/nl/andrewlalis/erme/view/EditorMenuBar.java @@ -39,6 +39,7 @@ public class EditorMenuBar extends JMenuBar { menu.add(RemoveRelationAction.getInstance()); menu.add(AddAttributeAction.getInstance()); menu.add(RemoveAttributeAction.getInstance()); + menu.add(new JCheckBoxMenuItem(LolcatAction.getInstance())); menu.addSeparator(); menu.add(UndoAction.getInstance()); menu.add(RedoAction.getInstance()); 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 6612554..e82d6c6 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,8 +1,10 @@ package nl.andrewlalis.erme.view.view_models; +import nl.andrewlalis.erme.EntityRelationMappingEditor; import nl.andrewlalis.erme.model.Attribute; import nl.andrewlalis.erme.model.AttributeType; import nl.andrewlalis.erme.model.ForeignKeyAttribute; +import nl.andrewlalis.erme.view.DiagramPanel; import java.awt.*; import java.awt.font.TextAttribute; @@ -13,72 +15,98 @@ import java.text.AttributedString; * View model for rendering a single attribute of a relation. */ public class AttributeViewModel implements ViewModel { - public static final int PADDING_X = 5; - public static final int PADDING_Y = 5; - public static final Color BACKGROUND_COLOR = Color.LIGHT_GRAY; - public static final Color FONT_COLOR = Color.BLACK; - public static final float FK_FONT_SIZE = 11.0f; + public static final int PADDING_X = 5; + public static final int PADDING_Y = 5; + public static final Color BACKGROUND_COLOR = Color.LIGHT_GRAY; + public static final Color FONT_COLOR = Color.BLACK; + public static final float FK_FONT_SIZE = 11.0f; + private static final float LOLCAT_SAT = 0.75f; + private static final float LOLCAT_BRIGHT = 1f; + private static boolean lolcatMode; + private final Attribute attribute; - private final Attribute attribute; + public AttributeViewModel(Attribute attribute) { + this.attribute = attribute; + } - public AttributeViewModel(Attribute attribute) { - this.attribute = attribute; - } + public static boolean getLolcatMode() { + return lolcatMode; + } - @Override - public void draw(Graphics2D g) { - AttributedString as = this.getAttributedString(g); - Rectangle r = this.getBounds(g, as); - g.setColor(BACKGROUND_COLOR); - g.fillRect(r.x, r.y, r.width, r.height); - g.setColor(FONT_COLOR); - g.drawRect(r.x, r.y, r.width, r.height); - g.drawString(as.getIterator(), r.x + PADDING_X, r.y + (r.height - PADDING_Y)); - if (this.attribute instanceof ForeignKeyAttribute) { - ForeignKeyAttribute fkAttribute = (ForeignKeyAttribute) this.attribute; - Font originalFont = g.getFont(); - g.setFont(g.getFont().deriveFont(Font.ITALIC, FK_FONT_SIZE)); - g.drawString(fkAttribute.getFullReferenceName(), r.x + PADDING_X, r.y - PADDING_Y); - g.setFont(originalFont); - } - } + public static void setLolcatMode(boolean lolcatMode) { + AttributeViewModel.lolcatMode = lolcatMode; + } - @Override - public Rectangle getBounds(Graphics2D g) { - return this.getBounds(g, this.getAttributedString(g)); - } + @Override + public void draw(Graphics2D g) { + AttributedString as = this.getAttributedString(g); + Rectangle r = this.getBounds(g, as); + g.setColor(this.getBackgroundColor(r.x + r.width / 2, r.y + r.height / 2, g)); + g.fillRect(r.x, r.y, r.width, r.height); + g.setColor(FONT_COLOR); + g.drawRect(r.x, r.y, r.width, r.height); + g.drawString(as.getIterator(), r.x + PADDING_X, r.y + (r.height - PADDING_Y)); + if (this.attribute instanceof ForeignKeyAttribute) { + ForeignKeyAttribute fkAttribute = (ForeignKeyAttribute) this.attribute; + Font originalFont = g.getFont(); + g.setFont(g.getFont().deriveFont(Font.ITALIC, FK_FONT_SIZE)); + g.drawString(fkAttribute.getFullReferenceName(), r.x + PADDING_X, r.y - PADDING_Y); + g.setFont(originalFont); + } + } - private Rectangle getBounds(Graphics2D g, AttributedString as) { - final RelationViewModel relationViewModel = (RelationViewModel) this.attribute.getRelation().getViewModel(); - int x = this.attribute.getRelation().getPosition().x + RelationViewModel.PADDING_X; - int y = this.attribute.getRelation().getPosition().y + relationViewModel.getNameBounds(g).height + RelationViewModel.ATTRIBUTE_SEPARATION; - int i = 0; - while (!this.attribute.getRelation().getAttributes().get(i).equals(this.attribute)) { - x += this.attribute.getRelation().getAttributes().get(i).getViewModel().getBounds(g).width; - i++; - } - Rectangle2D nameRect = g.getFontMetrics().getStringBounds(as.getIterator(), 0, this.attribute.getName().length(), g); - int width = (int) nameRect.getWidth() + (2 * PADDING_X); - int height = (int) nameRect.getHeight() + (2 * PADDING_Y); - if (this.attribute instanceof ForeignKeyAttribute) { - ForeignKeyAttribute fkAttribute = (ForeignKeyAttribute) this.attribute; - Font originalFont = g.getFont(); - g.setFont(g.getFont().deriveFont(Font.ITALIC, FK_FONT_SIZE)); - Rectangle referenceNameBounds = g.getFontMetrics().getStringBounds(fkAttribute.getFullReferenceName(), g).getBounds(); - g.setFont(originalFont); - width = Math.max(width, referenceNameBounds.width + (2 * PADDING_X)); - } - return new Rectangle(x, y, width, height); - } + private Color getBackgroundColor(int x, int y, Graphics2D g) { + if (!lolcatMode) return BACKGROUND_COLOR; + Dimension viewportSize = ((DiagramPanel)EntityRelationMappingEditor.getFrame().getContentPane()).getModel().getRelationBounds().getSize(); - private AttributedString getAttributedString(Graphics2D g) { - AttributedString as = new AttributedString(this.attribute.getName()); - as.addAttribute(TextAttribute.FONT, g.getFont()); - if (this.attribute.getType().equals(AttributeType.ID_KEY)) { - as.addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON); - } else if (this.attribute.getType().equals(AttributeType.PARTIAL_ID_KEY)) { - as.addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_LOW_DASHED); - } - return as; - } + double dx = viewportSize.width; + double dy = viewportSize.height; + double mag = Math.sqrt(dx * dx + dy * dy); + dx /= mag; + dy /= mag; + + double lambda = (dx * x + dy * y); + double diag_val = Math.sqrt(Math.pow(dx * lambda, 2) + Math.pow(dy * lambda, 2)) / mag; + + return Color.getHSBColor((float) diag_val, LOLCAT_SAT, LOLCAT_BRIGHT); + } + + @Override + public Rectangle getBounds(Graphics2D g) { + return this.getBounds(g, this.getAttributedString(g)); + } + + private Rectangle getBounds(Graphics2D g, AttributedString as) { + final RelationViewModel relationViewModel = (RelationViewModel) this.attribute.getRelation().getViewModel(); + int x = this.attribute.getRelation().getPosition().x + RelationViewModel.PADDING_X; + int y = this.attribute.getRelation().getPosition().y + relationViewModel.getNameBounds(g).height + RelationViewModel.ATTRIBUTE_SEPARATION; + int i = 0; + while (!this.attribute.getRelation().getAttributes().get(i).equals(this.attribute)) { + x += this.attribute.getRelation().getAttributes().get(i).getViewModel().getBounds(g).width; + i++; + } + Rectangle2D nameRect = g.getFontMetrics().getStringBounds(as.getIterator(), 0, this.attribute.getName().length(), g); + int width = (int) nameRect.getWidth() + (2 * PADDING_X); + int height = (int) nameRect.getHeight() + (2 * PADDING_Y); + if (this.attribute instanceof ForeignKeyAttribute) { + ForeignKeyAttribute fkAttribute = (ForeignKeyAttribute) this.attribute; + Font originalFont = g.getFont(); + g.setFont(g.getFont().deriveFont(Font.ITALIC, FK_FONT_SIZE)); + Rectangle referenceNameBounds = g.getFontMetrics().getStringBounds(fkAttribute.getFullReferenceName(), g).getBounds(); + g.setFont(originalFont); + width = Math.max(width, referenceNameBounds.width + (2 * PADDING_X)); + } + return new Rectangle(x, y, width, height); + } + + private AttributedString getAttributedString(Graphics2D g) { + AttributedString as = new AttributedString(this.attribute.getName()); + as.addAttribute(TextAttribute.FONT, g.getFont()); + if (this.attribute.getType().equals(AttributeType.ID_KEY)) { + as.addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON); + } else if (this.attribute.getType().equals(AttributeType.PARTIAL_ID_KEY)) { + as.addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_LOW_DASHED); + } + return as; + } }