diff --git a/diylc/diylc-core/src/org/diylc/core/measures/SizeUnit.java b/diylc/diylc-core/src/org/diylc/core/measures/SizeUnit.java index 9d094d9b..b9475a71 100644 --- a/diylc/diylc-core/src/org/diylc/core/measures/SizeUnit.java +++ b/diylc/diylc-core/src/org/diylc/core/measures/SizeUnit.java @@ -20,10 +20,12 @@ */ package org.diylc.core.measures; + +import org.diylc.utils.Constants; public enum SizeUnit implements Unit { - mm(1d), cm(10d), m(1e4d), in(25.4d), ft(25.4d * 12), yd(9144d); + px(25.4d / Constants.PIXELS_PER_INCH), mm(1d), cm(10d), m(1e4d), in(25.4d), ft(25.4d * 12), yd(9144d); double factor; diff --git a/diylc/diylc-library/lib/diylc-core.jar b/diylc/diylc-library/lib/diylc-core.jar index 6f43ecf6..b809eef0 100644 Binary files a/diylc/diylc-library/lib/diylc-core.jar and b/diylc/diylc-library/lib/diylc-core.jar differ diff --git a/diylc/diylc-library/src/org/diylc/components/connectivity/Line.java b/diylc/diylc-library/src/org/diylc/components/connectivity/Line.java index 7765d3b6..31cca983 100644 --- a/diylc/diylc-library/src/org/diylc/components/connectivity/Line.java +++ b/diylc/diylc-library/src/org/diylc/components/connectivity/Line.java @@ -21,38 +21,48 @@ */ package org.diylc.components.connectivity; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Shape; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Polygon; +import java.awt.Shape; import java.awt.Stroke; +import java.awt.geom.AffineTransform; -import org.diylc.common.Display; +import org.diylc.common.Display; import org.diylc.common.LineStyle; -import org.diylc.common.ObjectCache; -import org.diylc.common.SimpleComponentTransformer; -import org.diylc.components.AbstractLeadedComponent; -import org.diylc.core.ComponentState; -import org.diylc.core.CreationMethod; -import org.diylc.core.IDIYComponent; -import org.diylc.core.IDrawingObserver; -import org.diylc.core.Project; -import org.diylc.core.annotations.BomPolicy; -import org.diylc.core.annotations.ComponentDescriptor; -import org.diylc.core.annotations.EditableProperty; -import org.diylc.core.measures.Size; +import org.diylc.common.ObjectCache; +import org.diylc.common.SimpleComponentTransformer; +import org.diylc.components.AbstractLeadedComponent; +import org.diylc.core.ComponentState; +import org.diylc.core.CreationMethod; +import org.diylc.core.IDIYComponent; +import org.diylc.core.IDrawingObserver; +import org.diylc.core.Project; +import org.diylc.core.annotations.BomPolicy; +import org.diylc.core.annotations.ComponentDescriptor; +import org.diylc.core.annotations.EditableProperty; +import org.diylc.core.measures.Size; +import org.diylc.core.measures.SizeUnit; @ComponentDescriptor(name = "Line", author = "Branislav Stojkovic", category = "Shapes", - creationMethod = CreationMethod.POINT_BY_POINT, instanceNamePrefix = "LN", description = "", + creationMethod = CreationMethod.POINT_BY_POINT, instanceNamePrefix = "LN", description = "Line with optional arrows", zOrder = IDIYComponent.COMPONENT, bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false, transformer = SimpleComponentTransformer.class) public class Line extends AbstractLeadedComponent { private static final long serialVersionUID = 1L; - public static Color COLOR = Color.black; + public static Color COLOR = Color.black; private Color color = COLOR; - protected LineStyle style = LineStyle.SOLID; + protected LineStyle style = LineStyle.SOLID; + private Size thickness = new Size(1d, SizeUnit.px); + private Size arrowSize = new Size(5d, SizeUnit.px); + private Polygon arrow = null; + private AffineTransform arrowTx = new AffineTransform(); + private boolean arrowStart = false; + private boolean arrowEnd = false; @Override public void drawIcon(Graphics2D g2d, int width, int height) { @@ -64,11 +74,11 @@ public class Line extends AbstractLeadedComponent { @Override public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, IDrawingObserver drawingObserver) { - float thickness = 1f; + float thickness = (float) getThickness().convertToPixels(); Stroke stroke = null; switch (getStyle()) { case SOLID: - stroke = ObjectCache.getInstance().fetchBasicStroke(thickness); + stroke = ObjectCache.getInstance().fetchZoomableStroke(thickness); break; case DASHED: stroke = ObjectCache.getInstance().fetchStroke(thickness, new float[] {thickness * 2, thickness * 4}, thickness * 4); @@ -78,14 +88,87 @@ public class Line extends AbstractLeadedComponent { break; } g2d.setStroke(stroke); - g2d.setColor(color); - g2d.drawLine(getControlPoint(0).x, getControlPoint(0).y, getControlPoint(1).x, getControlPoint(1).y); + g2d.setColor(componentState == ComponentState.SELECTED ? SELECTION_COLOR : color); + + Point startPoint = new Point(getControlPoint(0)); + Point endPoint = new Point(getControlPoint(1)); + + if (arrowStart) { + arrowTx.setToIdentity(); + double angle = Math.atan2(getControlPoint(1).y - getControlPoint(0).y, getControlPoint(1).x - getControlPoint(0).x); + arrowTx.translate(getControlPoint(0).x, getControlPoint(0).y); + arrowTx.rotate((angle + Math.PI / 2d)); + AffineTransform oldTx = g2d.getTransform(); + g2d.transform(arrowTx); + g2d.fill(getArrow()); + g2d.setTransform(oldTx); + + double distance = distance(startPoint, endPoint); + interpolate(startPoint, endPoint, getArrowSize().convertToPixels() * 0.9 / distance, startPoint); + } + if (arrowEnd) { + arrowTx.setToIdentity(); + double angle = Math.atan2(getControlPoint(1).y - getControlPoint(0).y, getControlPoint(1).x - getControlPoint(0).x); + arrowTx.translate(getControlPoint(1).x, getControlPoint(1).y); + arrowTx.rotate((angle - Math.PI / 2d)); + AffineTransform oldTx = g2d.getTransform(); + g2d.transform(arrowTx); + g2d.fill(getArrow()); + g2d.setTransform(oldTx); + + double distance = distance(startPoint, endPoint); + interpolate(endPoint, startPoint, getArrowSize().convertToPixels() * 0.9 / distance, endPoint); + } + + g2d.drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y); + } + + private void interpolate(Point p1, Point p2, double t, Point p) { + p.setLocation((int)Math.round(p1.x * (1-t) + p2.x * t), (int)Math.round(p1.y * (1-t) + p2.y * t)); + } + + private double distance(Point p1, Point p2) { + return Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)); } @Override public Color getLeadColorForPainting(ComponentState componentState) { return componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR : color; + } + + public Polygon getArrow() { + if (arrow == null) { + arrow = new Polygon(); + int t = (int) getArrowSize().convertToPixels(); + arrow.addPoint(0, 0); + arrow.addPoint(-t, -t * 2); + arrow.addPoint(t, -t * 2); + } + return arrow; + } + + @EditableProperty + public Size getThickness() { + if (thickness == null) + thickness = new Size(1d, SizeUnit.px); + return thickness; + } + + public void setThickness(Size thickness) { + this.thickness = thickness; + } + + @EditableProperty + public Size getArrowSize() { + if (arrowSize == null) + arrowSize = thickness = new Size(1d, SizeUnit.px); + return arrowSize; + } + + public void setArrowSize(Size arrowSize) { + this.arrowSize = arrowSize; + arrow = null; } @Override @@ -111,8 +194,26 @@ public class Line extends AbstractLeadedComponent { public void setStyle(LineStyle style) { this.style = style; - } - + } + + @EditableProperty(name = "Start Arrow") + public boolean getArrowStart() { + return arrowStart; + } + + public void setArrowStart(boolean arrowStart) { + this.arrowStart = arrowStart; + } + + @EditableProperty(name = "End Arrow") + public boolean getArrowEnd() { + return arrowEnd; + } + + public void setArrowEnd(boolean arrowEnd) { + this.arrowEnd = arrowEnd; + } + public Color getBodyColor() { return super.getBodyColor(); } @@ -176,5 +277,11 @@ public class Line extends AbstractLeadedComponent { @Override public Display getDisplay() { return super.getDisplay(); + } + + @Deprecated + @Override + public org.diylc.components.AbstractLeadedComponent.LabelOriantation getLabelOriantation() { + return super.getLabelOriantation(); } } diff --git a/diylc/diylc-swing/lib/diylc-core.jar b/diylc/diylc-swing/lib/diylc-core.jar index 6f43ecf6..b809eef0 100644 Binary files a/diylc/diylc-swing/lib/diylc-core.jar and b/diylc/diylc-swing/lib/diylc-core.jar differ diff --git a/diylc/diylc-swing/library/main.jar b/diylc/diylc-swing/library/main.jar index c9fb5a4e..f17986d5 100644 Binary files a/diylc/diylc-swing/library/main.jar and b/diylc/diylc-swing/library/main.jar differ diff --git a/diylc/diylc-swing/update.xml b/diylc/diylc-swing/update.xml index 3fe7c6a9..4ec68e6c 100644 --- a/diylc/diylc-swing/update.xml +++ b/diylc/diylc-swing/update.xml @@ -2196,6 +2196,22 @@ https://github.com/bancika/diy-layout-creator/releases + + + + 3 + 49 + 0 + + 2018-12-26 00:00:00.000 CET + + + + NEW_FEATURES + Added optional arrow to the "Line" component together with configurable thickness + + + https://github.com/bancika/diy-layout-creator/releases