diff --git a/diylc/diylc-core/src/org/diylc/common/LineStyle.java b/diylc/diylc-core/src/org/diylc/common/LineStyle.java
new file mode 100644
index 00000000..ae19e84e
--- /dev/null
+++ b/diylc/diylc-core/src/org/diylc/common/LineStyle.java
@@ -0,0 +1,32 @@
+/*
+
+ DIY Layout Creator (DIYLC).
+ Copyright (c) 2009-2018 held jointly by the individual authors.
+
+ This file is part of DIYLC.
+
+ DIYLC is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ DIYLC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DIYLC. If not, see .
+
+*/
+package org.diylc.common;
+
+public enum LineStyle {
+
+ SOLID, DASHED, DOTTED;
+
+ @Override
+ public String toString() {
+ return name().substring(0, 1) + name().substring(1).toLowerCase();
+ }
+}
diff --git a/diylc/diylc-core/src/org/diylc/common/ObjectCache.java b/diylc/diylc-core/src/org/diylc/common/ObjectCache.java
index 6ea25d57..f6a67504 100644
--- a/diylc/diylc-core/src/org/diylc/common/ObjectCache.java
+++ b/diylc/diylc-core/src/org/diylc/common/ObjectCache.java
@@ -1,58 +1,66 @@
/*
+ *
+ * DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
+ *
+ * This file is part of DIYLC.
+ *
+ * DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with DIYLC. If not, see
+ * .
+ */
+package org.diylc.common;
- DIY Layout Creator (DIYLC).
- Copyright (c) 2009-2018 held jointly by the individual authors.
+import java.awt.AlphaComposite;
+import java.awt.BasicStroke;
+import java.awt.Stroke;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
- This file is part of DIYLC.
+/**
+ * Repository for object that may be reused, such as {@link Stroke} or {@link AlphaComposite}.
+ *
+ * @author Branislav Stojkovic
+ */
+public class ObjectCache {
- DIYLC is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+ private static ObjectCache instance;
- DIYLC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ public static ObjectCache getInstance() {
+ if (instance == null) {
+ instance = new ObjectCache();
+ }
+ return instance;
+ }
- You should have received a copy of the GNU General Public License
- along with DIYLC. If not, see .
+ private ObjectCache() {}
-*/
-package org.diylc.common;
-
-import java.awt.AlphaComposite;
-import java.awt.BasicStroke;
-import java.awt.Stroke;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Repository for object that may be reused, such as {@link Stroke} or {@link AlphaComposite}.
- *
- * @author Branislav Stojkovic
- */
-public class ObjectCache {
-
- private static ObjectCache instance;
-
- public static ObjectCache getInstance() {
- if (instance == null) {
- instance = new ObjectCache();
- }
- return instance;
- }
-
- private ObjectCache() {}
-
- private Map basicStrokeMap = new HashMap();
-
- public Stroke fetchBasicStroke(float width) {
- if (basicStrokeMap.containsKey(width)) {
- return basicStrokeMap.get(width);
- }
- Stroke stroke = new BasicStroke(width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
- basicStrokeMap.put(width, stroke);
- return stroke;
- }
-}
+ private Map basicStrokeMap = new HashMap();
+ private Map dashStrokeMap = new HashMap();
+
+ public Stroke fetchBasicStroke(float width) {
+ if (basicStrokeMap.containsKey(width)) {
+ return basicStrokeMap.get(width);
+ }
+ Stroke stroke = new BasicStroke(width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
+ basicStrokeMap.put(width, stroke);
+ return stroke;
+ }
+
+ public Stroke fetchStroke(float width, float[] dash, float phase) {
+ String key = width + "|" + Arrays.toString(dash) + "|" + phase;
+ if (dashStrokeMap.containsKey(key)) {
+ return dashStrokeMap.get(key);
+ }
+ Stroke stroke = new BasicStroke(width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 0, dash, phase);
+ dashStrokeMap.put(key, stroke);
+ return stroke;
+ }
+}
diff --git a/diylc/diylc-core/src/org/diylc/components/AbstractCurvedComponent.java b/diylc/diylc-core/src/org/diylc/components/AbstractCurvedComponent.java
index 1d5b040f..58c27a0c 100644
--- a/diylc/diylc-core/src/org/diylc/components/AbstractCurvedComponent.java
+++ b/diylc/diylc-core/src/org/diylc/components/AbstractCurvedComponent.java
@@ -1,262 +1,339 @@
/*
+ *
+ * DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
+ *
+ * This file is part of DIYLC.
+ *
+ * DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with DIYLC. If not, see
+ * .
+ */
+package org.diylc.components;
- DIY Layout Creator (DIYLC).
- Copyright (c) 2009-2018 held jointly by the individual authors.
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.geom.CubicCurve2D;
+import java.awt.geom.Path2D;
- This file is part of DIYLC.
+import org.diylc.common.LineStyle;
+import org.diylc.common.ObjectCache;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.VisibilityPolicy;
+import org.diylc.core.annotations.EditableProperty;
+import org.diylc.core.measures.Size;
+import org.diylc.core.measures.SizeUnit;
+import org.diylc.utils.Constants;
- DIYLC is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+public abstract class AbstractCurvedComponent extends AbstractTransparentComponent {
- DIYLC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ private static final long serialVersionUID = 1L;
- You should have received a copy of the GNU General Public License
- along with DIYLC. If not, see .
+ public static Color GUIDELINE_COLOR = Color.blue;
+ public static Size DEFAULT_SIZE = new Size(1d, SizeUnit.in);
-*/
-package org.diylc.components;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-import java.awt.Point;
-import java.awt.geom.CubicCurve2D;
-
-import org.diylc.common.ObjectCache;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.VisibilityPolicy;
-import org.diylc.core.annotations.EditableProperty;
-import org.diylc.core.measures.Size;
-import org.diylc.core.measures.SizeUnit;
-import org.diylc.utils.Constants;
-
-public abstract class AbstractCurvedComponent extends AbstractTransparentComponent {
-
- private static final long serialVersionUID = 1L;
-
- public static Color GUIDELINE_COLOR = Color.blue;
- public static Size DEFAULT_SIZE = new Size(1d, SizeUnit.in);
-
- protected Point[] controlPoints = new Point[] {new Point(0, 0),
- new Point((int) (DEFAULT_SIZE.convertToPixels() / 2), 0),
- new Point((int) (DEFAULT_SIZE.convertToPixels() / 2), (int) (DEFAULT_SIZE.convertToPixels())),
- new Point((int) DEFAULT_SIZE.convertToPixels(), (int) DEFAULT_SIZE.convertToPixels())};
-
- protected Color color = getDefaultColor();
- protected PointCount pointCount = PointCount.FOUR;
-
- /**
- * Draws the specified curve onto graphics.
- *
- * @param curve
- * @param g2d
- * @param componentState
- * @param theme
- */
- protected abstract void drawCurve(CubicCurve2D curve, Graphics2D g2d, ComponentState componentState, IDrawingObserver drawingObserver);
-
- /**
- * @return default color.
- */
- protected abstract Color getDefaultColor();
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- g2d.setColor(getDefaultColor().darker());
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(3));
- CubicCurve2D curve =
- new CubicCurve2D.Double(1, height - 1, width / 4, height / 3, 3 * width / 4, 2 * height / 3, width - 1, 1);
- g2d.draw(curve);
- g2d.setColor(getDefaultColor());
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
- g2d.draw(curve);
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- if (checkPointsClipped(g2d.getClip())) {
- return;
- }
- if (componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING) {
- // Do not track guidelines.
- drawingObserver.stopTracking();
- g2d.setStroke(Constants.DASHED_STROKE);
- g2d.setColor(GUIDELINE_COLOR);
- g2d.drawLine(controlPoints[0].x, controlPoints[0].y, controlPoints[1].x, controlPoints[1].y);
- g2d.drawLine(controlPoints[1].x, controlPoints[1].y, controlPoints[2].x, controlPoints[2].y);
- g2d.drawLine(controlPoints[2].x, controlPoints[2].y, controlPoints[3].x, controlPoints[3].y);
- drawingObserver.startTracking();
- }
- CubicCurve2D curve =
- new CubicCurve2D.Double(controlPoints[0].x, controlPoints[0].y, controlPoints[1].x, controlPoints[1].y,
- controlPoints[2].x, controlPoints[2].y, controlPoints[3].x, controlPoints[3].y);
-
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- // g2d.setColor(color.darker());
- // g2d.setStroke(new BasicStroke(thickness));
- // g2d.draw(path);
- // g2d.setColor(color);
- // g2d.setStroke(new BasicStroke(thickness - 2));
- // g2d.draw(path);
- drawCurve(curve, g2d, componentState, drawingObserver);
- g2d.setComposite(oldComposite);
- }
-
- @EditableProperty(name = "Point Count")
- public PointCount getPointCount() {
- if (pointCount == null) {
- pointCount = PointCount.FOUR;
- }
- return pointCount;
- }
-
- public void setPointCount(PointCount pointCount) {
- this.pointCount = pointCount;
- // Reset control points.
- for (int i = 0; i < getControlPointCount(); i++) {
- setControlPoint(getControlPoint(i), i);
- }
- }
-
- @Override
- public int getControlPointCount() {
- switch (getPointCount()) {
- case TWO:
- return 2;
- case THREE:
- return 3;
- case FOUR:
- return 4;
- }
- return 0;
- }
-
- @Override
- public boolean isControlPointSticky(int index) {
- return index == 0 || index == getControlPointCount() - 1;
- }
-
- @Override
- public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
- return VisibilityPolicy.WHEN_SELECTED;
- }
-
- @Override
- public boolean canControlPointOverlap(int index) {
- // Only shape control points may overlap.
- switch (getPointCount()) {
- case TWO:
- return false;
- case THREE:
- return index == 1;
- case FOUR:
- return index == 1 || index == 2;
- }
- return false;
- }
-
- @Override
- public Point getControlPoint(int index) {
- if (index == 0) {
- return controlPoints[0];
- }
- switch (getPointCount()) {
- case TWO:
- switch (index) {
- case 1:
- return controlPoints[3];
- }
- case THREE:
- switch (index) {
- case 1:
- return controlPoints[1];
- case 2:
- return controlPoints[3];
- }
- case FOUR:
- switch (index) {
- case 1:
- return controlPoints[1];
- case 2:
- return controlPoints[2];
- case 3:
- return controlPoints[3];
- }
- }
- return controlPoints[index];
- }
-
- @Override
- public void setControlPoint(Point point, int index) {
- if (index == 0) {
- controlPoints[0].setLocation(point);
- } else {
- switch (getPointCount()) {
- case TWO:
- switch (index) {
- case 1:
- Point center = new Point((point.x + controlPoints[0].x) / 2, (point.y + controlPoints[0].y) / 2);
- controlPoints[1].setLocation(center);
- controlPoints[2].setLocation(center);
- controlPoints[3].setLocation(point);
- break;
- }
- break;
- case THREE:
- switch (index) {
- case 1:
- controlPoints[1].setLocation(point);
- controlPoints[2].setLocation(point);
- break;
- case 2:
- controlPoints[3].setLocation(point);
- break;
- }
- break;
- case FOUR:
- switch (index) {
- case 1:
- controlPoints[1].setLocation(point);
- break;
- case 2:
- controlPoints[2].setLocation(point);
- break;
- case 3:
- controlPoints[3].setLocation(point);
- break;
- }
- break;
- }
- }
- }
-
- @EditableProperty(name="Color")
- public Color getLeadColor() {
- return color;
- }
-
- public void setLeadColor(Color color) {
- this.color = color;
- }
-
- enum PointCount {
- TWO, THREE, FOUR;
-
- @Override
- public String toString() {
- return name().substring(0, 1) + name().substring(1).toLowerCase();
- }
- }
-}
+ // for backward compatibility
+ protected Point[] controlPoints = null;
+
+ protected Point[] controlPoints2 = new Point[] {new Point(0, 0),
+ new Point((int) (DEFAULT_SIZE.convertToPixels() / 2), 0),
+ new Point((int) (DEFAULT_SIZE.convertToPixels() / 2), (int) (DEFAULT_SIZE.convertToPixels())),
+ new Point((int) DEFAULT_SIZE.convertToPixels(), (int) DEFAULT_SIZE.convertToPixels())};
+
+ protected Color color = getDefaultColor();
+ protected PointCount pointCount = PointCount.FOUR;
+ protected LineStyle style = LineStyle.SOLID;
+ protected Boolean smooth = true;
+
+ private int lastUpdatePointIndex = -1;
+
+ /**
+ * Draws the specified curve onto graphics.
+ *
+ * @param curve
+ * @param g2d
+ * @param componentState
+ * @param theme
+ */
+ protected abstract void drawCurve(Path2D curve, Graphics2D g2d, ComponentState componentState,
+ IDrawingObserver drawingObserver);
+
+ /**
+ * @return default color.
+ */
+ protected abstract Color getDefaultColor();
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ g2d.setColor(getDefaultColor().darker());
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(3));
+ CubicCurve2D curve =
+ new CubicCurve2D.Double(1, height - 1, width / 4, height / 3, 3 * width / 4, 2 * height / 3, width - 1, 1);
+ g2d.draw(curve);
+ g2d.setColor(getDefaultColor());
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+ g2d.draw(curve);
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ if (checkPointsClipped(g2d.getClip())) {
+ return;
+ }
+
+ Point[] p = getControlPoints();
+
+ // smoothen the curve if needed
+ if (getSmooth() && lastUpdatePointIndex >= 0) {
+ if (getPointCount() == PointCount.FIVE && (lastUpdatePointIndex == 1 || lastUpdatePointIndex == 2)) {
+ p[3] = findThirdPoint(p[2], p[1]);
+ }
+ if (getPointCount() == PointCount.FIVE && lastUpdatePointIndex == 3) {
+ p[1] = findThirdPoint(p[2], p[3]);
+ }
+ if (getPointCount() == PointCount.SEVEN && (lastUpdatePointIndex == 2 || lastUpdatePointIndex == 3)) {
+ p[4] = findThirdPoint(p[3], p[2]);
+ }
+ if (getPointCount() == PointCount.SEVEN && lastUpdatePointIndex == 4) {
+ p[2] = findThirdPoint(p[3], p[4]);
+ }
+ lastUpdatePointIndex = -1;
+ }
+
+ if (componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING) {
+ // Do not track guidelines.
+ drawingObserver.stopTracking();
+ g2d.setStroke(Constants.DASHED_STROKE);
+ g2d.setColor(GUIDELINE_COLOR);
+ for (int i = 0; i < p.length - 1; i++) {
+ g2d.drawLine(p[i].x, p[i].y, p[i + 1].x, p[i + 1].y);
+ }
+ drawingObserver.startTracking();
+ }
+
+ Path2D path = new Path2D.Double();
+ path.moveTo(p[0].x, p[0].y);
+ if (getPointCount() == PointCount.TWO) {
+ path.lineTo(p[1].x, p[1].y);
+ } else if (getPointCount() == PointCount.THREE) {
+ path.quadTo(p[1].x, p[1].y, p[2].x, p[2].y);
+ } else if (getPointCount() == PointCount.FOUR) {
+ path.curveTo(p[1].x, p[1].y, p[2].x, p[2].y, p[3].x, p[3].y);
+ } else if (getPointCount() == PointCount.FIVE) {
+ path.quadTo(p[1].x, p[1].y, p[2].x, p[2].y);
+ path.quadTo(p[3].x, p[3].y, p[4].x, p[4].y);
+ } else if (getPointCount() == PointCount.SEVEN) {
+ path.curveTo(p[1].x, p[1].y, p[2].x, p[2].y, p[3].x, p[3].y);
+ path.curveTo(p[4].x, p[4].y, p[5].x, p[5].y, p[6].x, p[6].y);
+ }
+
+ Composite oldComposite = g2d.getComposite();
+ if (alpha < MAX_ALPHA) {
+ g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
+ }
+
+ drawCurve(path, g2d, componentState, drawingObserver);
+
+ g2d.setComposite(oldComposite);
+ }
+
+ @EditableProperty(name = "Point Count")
+ public PointCount getPointCount() {
+ if (pointCount == null) {
+ pointCount = PointCount.FOUR;
+ }
+ return pointCount;
+ }
+
+ protected Point[] getControlPoints() {
+ if (this.controlPoints != null) {
+ // ensure backward compatibility by copying points from the old structure to the new one
+ switch (getPointCount()) {
+ case TWO:
+ this.controlPoints2 = new Point[2];
+ this.controlPoints2[0] = this.controlPoints[0];
+ this.controlPoints2[1] = this.controlPoints[3];
+ break;
+ case THREE:
+ this.controlPoints2 = new Point[3];
+ this.controlPoints2[0] = this.controlPoints[0];
+ this.controlPoints2[1] = this.controlPoints[1];
+ this.controlPoints2[2] = this.controlPoints[3];
+ break;
+ case FOUR:
+ this.controlPoints2 = new Point[4];
+ this.controlPoints2[0] = this.controlPoints[0];
+ this.controlPoints2[1] = this.controlPoints[1];
+ this.controlPoints2[2] = this.controlPoints[2];
+ this.controlPoints2[3] = this.controlPoints[3];
+ break;
+ default: // shouldn't happen
+ this.controlPoints2 = this.controlPoints;
+ }
+ // we don't need old points anymore
+ this.controlPoints = null;
+ }
+ return this.controlPoints2;
+ }
+
+ public void setPointCount(PointCount pointCount) {
+ Point[] p = getControlPoints();
+ Point[] newPoints = new Point[pointCount.count];
+ newPoints[0] = p[0];
+ newPoints[pointCount.count - 1] = p[p.length - 1];
+
+ if (pointCount == PointCount.THREE) {
+ newPoints[1] =
+ new Point((newPoints[pointCount.count - 1].x + newPoints[0].x) / 2,
+ (newPoints[pointCount.count - 1].y + newPoints[0].y) / 2);
+ } else if (pointCount == PointCount.FOUR) {
+ newPoints[1] =
+ new Point((newPoints[pointCount.count - 1].x + newPoints[0].x) / 2,
+ (newPoints[pointCount.count - 1].y + newPoints[0].y) / 2);
+ newPoints[2] =
+ new Point((newPoints[pointCount.count - 1].x + newPoints[0].x) / 2,
+ (newPoints[pointCount.count - 1].y + newPoints[0].y) / 2);
+ } else if (pointCount == PointCount.FIVE) {
+ newPoints[2] =
+ new Point((newPoints[pointCount.count - 1].x + newPoints[0].x) / 2,
+ (newPoints[pointCount.count - 1].y + newPoints[0].y) / 2);
+ newPoints[1] = new Point((newPoints[2].x + newPoints[0].x) / 2, (newPoints[2].y + newPoints[0].y) / 2);
+ newPoints[3] =
+ new Point((newPoints[pointCount.count - 1].x + newPoints[2].x) / 2,
+ (newPoints[pointCount.count - 1].y + newPoints[2].y) / 2);
+ } else if (pointCount == PointCount.SEVEN) {
+ newPoints[3] =
+ new Point((newPoints[pointCount.count - 1].x + newPoints[0].x) / 2,
+ (newPoints[pointCount.count - 1].y + newPoints[0].y) / 2);
+ newPoints[2] = new Point((newPoints[3].x + newPoints[0].x) / 2, (newPoints[3].y + newPoints[0].y) / 2);
+ newPoints[1] = new Point((newPoints[3].x + newPoints[0].x) / 2, (newPoints[3].y + newPoints[0].y) / 2);
+ newPoints[4] =
+ new Point((newPoints[pointCount.count - 1].x + newPoints[3].x) / 2,
+ (newPoints[pointCount.count - 1].y + newPoints[3].y) / 2);
+ newPoints[5] =
+ new Point((newPoints[pointCount.count - 1].x + newPoints[3].x) / 2,
+ (newPoints[pointCount.count - 1].y + newPoints[3].y) / 2);
+ }
+
+ this.controlPoints2 = newPoints;
+ this.pointCount = pointCount;
+ }
+
+ @Override
+ public int getControlPointCount() {
+ return getControlPoints().length;
+ }
+
+ @Override
+ public boolean isControlPointSticky(int index) {
+ return index == 0 || index == getControlPointCount() - 1;
+ }
+
+ @Override
+ public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
+ return VisibilityPolicy.WHEN_SELECTED;
+ }
+
+ @Override
+ public boolean canControlPointOverlap(int index) {
+ return index > 0 && index < getControlPointCount() - 1;
+ }
+
+ @Override
+ public Point getControlPoint(int index) {
+ return getControlPoints()[index];
+ }
+
+ @Override
+ public void setControlPoint(Point point, int index) {
+ Point[] p = getControlPoints();
+ p[index].setLocation(point);
+ this.lastUpdatePointIndex = index;
+ // if (getSmooth()) {
+ // if (getPointCount() == PointCount.FIVE && (index == 1 || index == 2)) {
+ // p[3] = findThirdPoint(p[2], p[1]);
+ // }
+ // if (getPointCount() == PointCount.FIVE && index == 3) {
+ // p[1] = findThirdPoint(p[2], p[3]);
+ // }
+ // if (getPointCount() == PointCount.SEVEN && (index == 2 || index == 3)) {
+ // p[4] = findThirdPoint(p[3], p[2]);
+ // }
+ // if (getPointCount() == PointCount.SEVEN && index == 4) {
+ // p[2] = findThirdPoint(p[3], p[4]);
+ // }
+ // }
+ }
+
+ private Point findThirdPoint(Point p0, Point p) {
+ return new Point(2 * p0.x - p.x, 2 * p0.y - p.y);
+ }
+
+ @EditableProperty(name = "Color")
+ public Color getLeadColor() {
+ return color;
+ }
+
+ public void setLeadColor(Color color) {
+ this.color = color;
+ }
+
+ @EditableProperty(name = "Style")
+ public LineStyle getStyle() {
+ if (style == null)
+ style = LineStyle.SOLID;
+ return style;
+ }
+
+ public void setStyle(LineStyle style) {
+ this.style = style;
+ }
+
+ @EditableProperty
+ public Boolean getSmooth() {
+ if (smooth == null)
+ this.smooth = true;
+ return this.smooth;
+ }
+
+ public void setSmooth(Boolean smooth) {
+ this.smooth = smooth;
+ // make the current curve smooth if needed
+ // Point[] p = getControlPoints();
+ // if (smooth) {
+ // if (getPointCount() == PointCount.FIVE) {
+ // p[3] = findThirdPoint(p[2], p[1]);
+ // }
+ // if (getPointCount() == PointCount.SEVEN) {
+ // p[4] = findThirdPoint(p[3], p[2]);
+ // }
+ // }
+ }
+
+ enum PointCount {
+ TWO(2), THREE(3), FOUR(4), FIVE(5), SEVEN(7);
+
+ private int count;
+
+ private PointCount(int count) {
+ this.count = count;
+ }
+
+ @Override
+ public String toString() {
+ return name().substring(0, 1) + name().substring(1).toLowerCase();
+ }
+ }
+}
diff --git a/diylc/diylc-core/src/org/diylc/components/AbstractLeadedComponent.java b/diylc/diylc-core/src/org/diylc/components/AbstractLeadedComponent.java
index f1202ae6..9dd8c536 100644
--- a/diylc/diylc-core/src/org/diylc/components/AbstractLeadedComponent.java
+++ b/diylc/diylc-core/src/org/diylc/components/AbstractLeadedComponent.java
@@ -1,26 +1,22 @@
/*
+ *
+ * DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
+ *
+ * This file is part of DIYLC.
+ *
+ * DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with DIYLC. If not, see
+ * .
+ */
+package org.diylc.components;
- DIY Layout Creator (DIYLC).
- Copyright (c) 2009-2018 held jointly by the individual authors.
-
- This file is part of DIYLC.
-
- DIYLC is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- DIYLC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with DIYLC. If not, see .
-
-*/
-package org.diylc.components;
-
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
@@ -29,6 +25,7 @@ import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
+import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
@@ -36,6 +33,7 @@ import java.awt.geom.Rectangle2D;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.common.Display;
import org.diylc.common.IPlugInPort;
+import org.diylc.common.LineStyle;
import org.diylc.common.ObjectCache;
import org.diylc.core.ComponentState;
import org.diylc.core.IDrawingObserver;
@@ -46,450 +44,439 @@ import org.diylc.core.annotations.EditableProperty;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
import org.diylc.utils.Constants;
-
-/**
- * Base class for all leaded components such as resistors or capacitors. Has two control points and
- * draws leads between them. Also, it positions and draws the shape of the component as specified by
- * a child class.
- *
- * @author Branislav Stojkovic
- */
-public abstract class AbstractLeadedComponent extends AbstractTransparentComponent {
-
- private static final long serialVersionUID = 1L;
-
- public static Color LEAD_COLOR = Color.decode("#CCCCCC");
- public static Color LEAD_COLOR_ICON = LEAD_COLOR.darker().darker();
- public static Size LEAD_THICKNESS = new Size(0.6d, SizeUnit.mm);
- public static Size DEFAULT_SIZE = new Size(1d, SizeUnit.in);
-
- protected Size length;
- protected Size width;
- protected Point[] points = new Point[] {new Point((int) (-DEFAULT_SIZE.convertToPixels() / 2), 0),
- new Point((int) (DEFAULT_SIZE.convertToPixels() / 2), 0)};
- protected Color bodyColor = Color.white;
- protected Color borderColor = Color.black;
- protected Color labelColor = LABEL_COLOR;
- protected Color leadColor = LEAD_COLOR;
- protected Display display = Display.NAME;
- private boolean flipStanding = false;
-
- protected AbstractLeadedComponent() {
- super();
- try {
- this.length = getDefaultLength().clone();
- this.width = getDefaultWidth().clone();
- } catch (CloneNotSupportedException e) {
- // This should never happen because Size supports cloning.
- } catch (NullPointerException e) {
- // This will happen if components do not have any shape.
- }
+
+/**
+ * Base class for all leaded components such as resistors or capacitors. Has two control points and
+ * draws leads between them. Also, it positions and draws the shape of the component as specified by
+ * a child class.
+ *
+ * @author Branislav Stojkovic
+ */
+public abstract class AbstractLeadedComponent extends AbstractTransparentComponent {
+
+ private static final long serialVersionUID = 1L;
+
+ public static Color LEAD_COLOR = Color.decode("#CCCCCC");
+ public static Color LEAD_COLOR_ICON = LEAD_COLOR.darker().darker();
+ public static Size LEAD_THICKNESS = new Size(0.6d, SizeUnit.mm);
+ public static Size DEFAULT_SIZE = new Size(1d, SizeUnit.in);
+
+ protected Size length;
+ protected Size width;
+ protected Point[] points = new Point[] {new Point((int) (-DEFAULT_SIZE.convertToPixels() / 2), 0),
+ new Point((int) (DEFAULT_SIZE.convertToPixels() / 2), 0)};
+ protected Color bodyColor = Color.white;
+ protected Color borderColor = Color.black;
+ protected Color labelColor = LABEL_COLOR;
+ protected Color leadColor = LEAD_COLOR;
+ protected Display display = Display.NAME;
+ private boolean flipStanding = false;
+
+ protected AbstractLeadedComponent() {
+ super();
+ try {
+ this.length = getDefaultLength().clone();
+ this.width = getDefaultWidth().clone();
+ } catch (CloneNotSupportedException e) {
+ // This should never happen because Size supports cloning.
+ } catch (NullPointerException e) {
+ // This will happen if components do not have any shape.
+ }
}
-
+
protected boolean IsCopperArea() {
return false;
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- double distance = points[0].distance(points[1]);
- Shape shape = getBodyShape();
- // If there's no body, just draw the line connecting the ending points.
- if (shape == null) {
- drawLead(g2d, componentState, drawingObserver, IsCopperArea());
- } else if (supportsStandingMode() && length.convertToPixels() > points[0].distance(points[1])) {
- // When ending points are too close draw the component in standing
- // mode.
- int width = getClosestOdd(this.width.convertToPixels());
- Shape body =
- new Ellipse2D.Double((getFlipStanding() ? points[1] : points[0]).x - width / 2,
- (getFlipStanding() ? points[1] : points[0]).y - width / 2, width, width);
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getStandingBodyColor());
- g2d.fill(body);
- g2d.setComposite(oldComposite);
- Color finalBorderColor;
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : borderColor;
- }
-
- g2d.setColor(finalBorderColor);
- g2d.draw(body);
- if (!outlineMode) {
- drawLead(g2d, componentState, drawingObserver, false);
- }
- } else {
- // Normal mode with component body in the center and two lead parts.
- Rectangle shapeRect = shape.getBounds();
- double theta = Math.atan2(points[1].y - points[0].y, points[1].x - points[0].x);
- // Go back to the original transformation to draw leads.
- if (!outlineMode) {
- AffineTransform textTransform = g2d.getTransform();
- // if (length.convertToPixels() > points[0].distance(points[1]))
- // {
- // g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
- // 0.5f));
- // }
- float leadThickness = getLeadThickness();
- double leadLength = (distance - calculatePinSpacing(shapeRect)) / 2;
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
- Color leadColor = shouldShadeLeads() ?
- getLeadColorForPainting(componentState).darker() :
- getLeadColorForPainting(componentState);
- g2d.setColor(leadColor);
- drawLeads(g2d, theta, leadLength);
-
- if (shouldShadeLeads()) {
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2));
- leadColor = getLeadColorForPainting(componentState);
- g2d.setColor(leadColor);
- drawLeads(g2d, theta, leadLength);
- }
- g2d.setTransform(textTransform);
- }
- // Transform graphics to draw the body in the right place and at the
- // right angle.
- AffineTransform oldTransform = null;
- double width;
- double length;
- if (useShapeRectAsPosition()) {
- width = shapeRect.getHeight();
- length = shapeRect.getWidth();
- } else {
- width = getWidth().convertToPixels();
- length = getLength().convertToPixels();
- }
- oldTransform = g2d.getTransform();
- g2d.translate((points[0].x + points[1].x - length) / 2, (points[0].y + points[1].y - width) / 2);
- g2d.rotate(theta, length / 2, width / 2);
- // Draw body.
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- if (bodyColor != null) {
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor);
- g2d.fill(shape);
- }
- decorateComponentBody(g2d, outlineMode);
- g2d.setComposite(oldComposite);
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
- Color finalBorderColor;
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : borderColor;
- }
- g2d.setColor(finalBorderColor);
- g2d.draw(shape);
-
- // // Go back to the original transformation to draw leads.
- // if (!outlineMode) {
- // AffineTransform textTransform = g2d.getTransform();
- // g2d.setTransform(oldTransform);
- // if (length.convertToPixels() > points[0].distance(points[1])) {
- // g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
- // 0.5f));
- // }
- // int leadThickness = getClosestOdd(getLeadThickness());
- // double leadLength = (distance - calculatePinSpacing(shapeRect)) /
- // 2 - leadThickness / 2;
- // g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
- // Color leadColor = shouldShadeLeads() ?
- // getLeadColor(componentState).darker()
- // : getLeadColor(componentState);
- // g2d.setColor(leadColor);
- // int endX = (int) (points[0].x + Math.cos(theta) * leadLength);
- // int endY = (int) Math.round(points[0].y + Math.sin(theta) *
- // leadLength);
- // g2d.drawLine(points[0].x, points[0].y, endX, endY);
- // endX = (int) (points[1].x + Math.cos(theta - Math.PI) *
- // leadLength);
- // endY = (int) Math.round(points[1].y + Math.sin(theta - Math.PI) *
- // leadLength);
- // g2d.drawLine(points[1].x, points[1].y, endX, endY);
- // if (shouldShadeLeads()) {
- // g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness
- // - 2));
- // leadColor = getLeadColor(componentState);
- // g2d.setColor(leadColor);
- // g2d.drawLine(points[0].x, points[0].y, (int) (points[0].x +
- // Math.cos(theta)
- // * leadLength), (int) (points[0].y + Math.sin(theta) *
- // leadLength));
- // g2d.drawLine(points[1].x, points[1].y, (int) (points[1].x +
- // Math.cos(theta
- // - Math.PI)
- // * leadLength), (int) (points[1].y + Math.sin(theta - Math.PI)
- // * leadLength));
- // }
- // g2d.setComposite(oldComposite);
- // g2d.setTransform(textTransform);
- // }
-
- // Draw label.
- g2d.setFont(project.getFont());
- if (useShapeRectAsPosition()) {
- g2d.translate(shapeRect.x, shapeRect.y);
- }
- Color finalLabelColor;
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : theme.getOutlineColor();
- } else {
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : labelColor;
- }
- g2d.setColor(finalLabelColor);
- FontMetrics fontMetrics = g2d.getFontMetrics();
- String label = "";
- label = display == Display.NAME ? getName() : (getValue() == null ? "" : getValue().toString());
- if (display == Display.NONE) {
- label = "";
- }
- if (display == Display.BOTH) {
- label = getName() + " " + (getValue() == null ? "" : getValue().toString());
- }
- Rectangle2D textRect = fontMetrics.getStringBounds(label, g2d);
- // Don't offset in outline mode.
- int offset = outlineMode ? 0 : getLabelOffset((int) length, (int) textRect.getWidth());
- // Adjust label angle if needed to make sure that it's readable.
- if ((theta >= Math.PI / 2 && theta <= Math.PI) || (theta < -Math.PI / 2 && theta > -Math.PI)) {
- g2d.rotate(Math.PI, length / 2, width / 2);
- offset = -offset;
- }
- g2d.drawString(label, (int) (length - textRect.getWidth()) / 2 + offset,
- calculateLabelYCoordinate(shapeRect, textRect, fontMetrics));
- g2d.setTransform(oldTransform);
- }
- }
-
- private void drawLeads(Graphics2D g2d, double theta, double leadLength) {
- int endX = (int) (points[0].x + Math.cos(theta) * leadLength);
- int endY = (int) (points[0].y + Math.sin(theta) * leadLength);
- g2d.drawLine(points[0].x, points[0].y, endX, endY);
-
- endX = (int) (points[1].x + Math.cos(theta - Math.PI) * leadLength);
- endY = (int) (points[1].y + Math.sin(theta - Math.PI) * leadLength);
- g2d.drawLine(points[1].x, points[1].y, endX, endY);
- }
-
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ double distance = points[0].distance(points[1]);
+ Shape shape = getBodyShape();
+ // If there's no body, just draw the line connecting the ending points.
+ if (shape == null) {
+ drawLead(g2d, componentState, drawingObserver, IsCopperArea());
+ } else if (supportsStandingMode() && length.convertToPixels() > points[0].distance(points[1])) {
+ // When ending points are too close draw the component in standing
+ // mode.
+ int width = getClosestOdd(this.width.convertToPixels());
+ Shape body =
+ new Ellipse2D.Double((getFlipStanding() ? points[1] : points[0]).x - width / 2,
+ (getFlipStanding() ? points[1] : points[0]).y - width / 2, width, width);
+ Composite oldComposite = g2d.getComposite();
+ if (alpha < MAX_ALPHA) {
+ g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
+ }
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getStandingBodyColor());
+ g2d.fill(body);
+ g2d.setComposite(oldComposite);
+ Color finalBorderColor;
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : borderColor;
+ }
+
+ g2d.setColor(finalBorderColor);
+ g2d.draw(body);
+ if (!outlineMode) {
+ drawLead(g2d, componentState, drawingObserver, false);
+ }
+ } else {
+ // Normal mode with component body in the center and two lead parts.
+ Rectangle shapeRect = shape.getBounds();
+ double theta = Math.atan2(points[1].y - points[0].y, points[1].x - points[0].x);
+ // Go back to the original transformation to draw leads.
+ if (!outlineMode) {
+ AffineTransform textTransform = g2d.getTransform();
+ // if (length.convertToPixels() > points[0].distance(points[1]))
+ // {
+ // g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
+ // 0.5f));
+ // }
+ float leadThickness = getLeadThickness();
+ double leadLength = (distance - calculatePinSpacing(shapeRect)) / 2;
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
+ Color leadColor =
+ shouldShadeLeads() ? getLeadColorForPainting(componentState).darker()
+ : getLeadColorForPainting(componentState);
+ g2d.setColor(leadColor);
+ drawLeads(g2d, theta, leadLength);
+
+ if (shouldShadeLeads()) {
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2));
+ leadColor = getLeadColorForPainting(componentState);
+ g2d.setColor(leadColor);
+ drawLeads(g2d, theta, leadLength);
+ }
+ g2d.setTransform(textTransform);
+ }
+ // Transform graphics to draw the body in the right place and at the
+ // right angle.
+ AffineTransform oldTransform = null;
+ double width;
+ double length;
+ if (useShapeRectAsPosition()) {
+ width = shapeRect.getHeight();
+ length = shapeRect.getWidth();
+ } else {
+ width = getWidth().convertToPixels();
+ length = getLength().convertToPixels();
+ }
+ oldTransform = g2d.getTransform();
+ g2d.translate((points[0].x + points[1].x - length) / 2, (points[0].y + points[1].y - width) / 2);
+ g2d.rotate(theta, length / 2, width / 2);
+ // Draw body.
+ Composite oldComposite = g2d.getComposite();
+ if (alpha < MAX_ALPHA) {
+ g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
+ }
+ if (bodyColor != null) {
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor);
+ g2d.fill(shape);
+ }
+ decorateComponentBody(g2d, outlineMode);
+ g2d.setComposite(oldComposite);
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+ Color finalBorderColor;
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : borderColor;
+ }
+ g2d.setColor(finalBorderColor);
+ g2d.draw(shape);
+
+ // Draw label.
+ g2d.setFont(project.getFont());
+ if (useShapeRectAsPosition()) {
+ g2d.translate(shapeRect.x, shapeRect.y);
+ }
+ Color finalLabelColor;
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : theme.getOutlineColor();
+ } else {
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : labelColor;
+ }
+ g2d.setColor(finalLabelColor);
+ FontMetrics fontMetrics = g2d.getFontMetrics();
+ String label = "";
+ label = display == Display.NAME ? getName() : (getValue() == null ? "" : getValue().toString());
+ if (display == Display.NONE) {
+ label = "";
+ }
+ if (display == Display.BOTH) {
+ label = getName() + " " + (getValue() == null ? "" : getValue().toString());
+ }
+ Rectangle2D textRect = fontMetrics.getStringBounds(label, g2d);
+ // Don't offset in outline mode.
+ int offset = outlineMode ? 0 : getLabelOffset((int) length, (int) textRect.getWidth());
+ // Adjust label angle if needed to make sure that it's readable.
+ if ((theta >= Math.PI / 2 && theta <= Math.PI) || (theta < -Math.PI / 2 && theta > -Math.PI)) {
+ g2d.rotate(Math.PI, length / 2, width / 2);
+ offset = -offset;
+ }
+ g2d.drawString(label, (int) (length - textRect.getWidth()) / 2 + offset,
+ calculateLabelYCoordinate(shapeRect, textRect, fontMetrics));
+ g2d.setTransform(oldTransform);
+ }
+ }
+
+ private void drawLeads(Graphics2D g2d, double theta, double leadLength) {
+ int endX = (int) (points[0].x + Math.cos(theta) * leadLength);
+ int endY = (int) (points[0].y + Math.sin(theta) * leadLength);
+ g2d.drawLine(points[0].x, points[0].y, endX, endY);
+
+ endX = (int) (points[1].x + Math.cos(theta - Math.PI) * leadLength);
+ endY = (int) (points[1].y + Math.sin(theta - Math.PI) * leadLength);
+ g2d.drawLine(points[1].x, points[1].y, endX, endY);
+ }
+
private void drawLead(Graphics2D g2d, ComponentState componentState, IDrawingObserver observer, boolean isCopperArea) {
if (isCopperArea)
- observer.startTrackingContinuityArea(true);
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(getLeadThickness()));
- Color leadColor =
- shouldShadeLeads() ? getLeadColorForPainting(componentState).darker() : getLeadColorForPainting(componentState);
- g2d.setColor(leadColor);
+ observer.startTrackingContinuityArea(true);
+
+ float thickness = getLeadThickness();
+ Stroke stroke = null;
+ switch (getStyle()) {
+ case SOLID:
+ stroke = ObjectCache.getInstance().fetchBasicStroke(thickness);
+ break;
+ case DASHED:
+ stroke =
+ ObjectCache.getInstance().fetchStroke(thickness, new float[] {thickness * 2, thickness * 4}, thickness * 4);
+ break;
+ case DOTTED:
+ stroke = ObjectCache.getInstance().fetchStroke(thickness, new float[] {thickness / 4, thickness * 4}, 0);
+ break;
+ }
+
+ g2d.setStroke(stroke);
+ Color leadColor =
+ shouldShadeLeads() ? getLeadColorForPainting(componentState).darker() : getLeadColorForPainting(componentState);
+ g2d.setColor(leadColor);
g2d.drawLine(points[0].x, points[0].y, points[1].x, points[1].y);
-
+
if (isCopperArea)
- observer.stopTrackingContinuityArea();
-
- if (shouldShadeLeads()) {
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(getLeadThickness() - 2));
- leadColor = getLeadColorForPainting(componentState);
- g2d.setColor(leadColor);
- g2d.drawLine(points[0].x, points[0].y, points[1].x, points[1].y);
- }
- }
-
- protected void decorateComponentBody(Graphics2D g2d, boolean outlineMode) {
- // Do nothing.
- }
-
- protected int calculateLabelYCoordinate(Rectangle2D shapeRect, Rectangle2D textRect, FontMetrics fontMetrics) {
- return (int) (shapeRect.getHeight() - textRect.getHeight()) / 2 + fontMetrics.getAscent();
- }
-
- protected boolean shouldShadeLeads() {
- return true;
- }
-
- protected boolean supportsStandingMode() {
- return false;
- }
-
- protected int getLabelOffset(int bodyWidth, int labelWidth) {
- return 0;
- }
-
- /**
- * @return default component length.
- */
- protected abstract Size getDefaultLength();
-
- /**
- * Returns default component width.
- *
- * @return
- */
- protected abstract Size getDefaultWidth();
-
- /**
- * @return shape that represents component body. Shape should not be transformed and should be
- * referenced to (0, 0).
- */
- protected abstract Shape getBodyShape();
-
- /**
- * Controls how component shape should be placed relative to start and end point.
- *
- * @return true if shape rect should be used to center the component or false
- * to place the component relative to length and width values.
- */
- protected boolean useShapeRectAsPosition() {
- return true;
- }
-
- /**
- * @return default lead thickness. Override this method to change it.
- */
- protected float getLeadThickness() {
- return getClosestOdd(LEAD_THICKNESS.convertToPixels());
- }
-
- /**
- * @return default lead color. Override this method to change it.
- */
- protected Color getLeadColorForPainting(ComponentState componentState) {
- return componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : getLeadColor();
- }
-
- @EditableProperty(name = "Lead color")
- public Color getLeadColor() {
- if (leadColor == null) {
- leadColor = LEAD_COLOR_ICON;
- }
- return leadColor;
- }
-
- public void setLeadColor(Color leadColor) {
- this.leadColor = leadColor;
- }
-
- protected int calculatePinSpacing(Rectangle shapeRect) {
- return shapeRect.width;
- }
-
- @Override
- public int getControlPointCount() {
- return points.length;
- }
-
- @Override
- public Point getControlPoint(int index) {
- return (Point) points[index];
- }
-
- @Override
- public boolean isControlPointSticky(int index) {
- return true;
- }
-
- @Override
- public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
- return VisibilityPolicy.ALWAYS;
- }
-
- @Override
- public void setControlPoint(Point point, int index) {
- points[index].setLocation(point);
- }
-
- @EditableProperty(name = "Color")
- public Color getBodyColor() {
- return bodyColor;
- }
-
- public void setBodyColor(Color bodyColor) {
- this.bodyColor = bodyColor;
- }
-
- public Color getStandingBodyColor() {
- return bodyColor;
- }
-
- @EditableProperty(name = "Border")
- public Color getBorderColor() {
- return borderColor;
- }
-
- public void setBorderColor(Color borderColor) {
- this.borderColor = borderColor;
- }
-
- @EditableProperty(name = "Length", defaultable = true)
- public Size getLength() {
- return length;
- }
-
- public void setLength(Size length) {
- this.length = length;
- }
-
- @EditableProperty(name = "Width", defaultable = true)
- public Size getWidth() {
- return width;
- }
-
- public void setWidth(Size width) {
- this.width = width;
- }
-
- @EditableProperty
- public Display getDisplay() {
- return display;
- }
-
- public void setDisplay(Display display) {
- this.display = display;
- }
-
- @EditableProperty(name = "Label color")
- public Color getLabelColor() {
- return labelColor;
- }
-
- public void setLabelColor(Color labelColor) {
- this.labelColor = labelColor;
- }
-
- /**
- * Override this method with @EditableProperty annotation in child classes where standing mode is
- * supported
- *
- * @return
- */
- public boolean getFlipStanding() {
- return flipStanding;
- }
-
- public void setFlipStanding(boolean flipStanding) {
- this.flipStanding = flipStanding;
- }
-}
+ observer.stopTrackingContinuityArea();
+
+ if (shouldShadeLeads()) {
+ switch (getStyle()) {
+ case SOLID:
+ stroke = ObjectCache.getInstance().fetchBasicStroke(thickness - 2);
+ break;
+ case DASHED:
+ stroke =
+ ObjectCache.getInstance().fetchStroke(thickness - 2, new float[] {thickness * 2, thickness * 4},
+ thickness * 4);
+ break;
+ case DOTTED:
+ stroke = ObjectCache.getInstance().fetchStroke(thickness - 2, new float[] {thickness / 4, thickness * 4}, 0);
+ break;
+ }
+ g2d.setStroke(stroke);
+ leadColor = getLeadColorForPainting(componentState);
+ g2d.setColor(leadColor);
+ g2d.drawLine(points[0].x, points[0].y, points[1].x, points[1].y);
+ }
+ }
+
+ protected LineStyle getStyle() {
+ return LineStyle.SOLID;
+ }
+
+ protected void decorateComponentBody(Graphics2D g2d, boolean outlineMode) {
+ // Do nothing.
+ }
+
+ protected int calculateLabelYCoordinate(Rectangle2D shapeRect, Rectangle2D textRect, FontMetrics fontMetrics) {
+ return (int) (shapeRect.getHeight() - textRect.getHeight()) / 2 + fontMetrics.getAscent();
+ }
+
+ protected boolean shouldShadeLeads() {
+ return true;
+ }
+
+ protected boolean supportsStandingMode() {
+ return false;
+ }
+
+ protected int getLabelOffset(int bodyWidth, int labelWidth) {
+ return 0;
+ }
+
+ /**
+ * @return default component length.
+ */
+ protected abstract Size getDefaultLength();
+
+ /**
+ * Returns default component width.
+ *
+ * @return
+ */
+ protected abstract Size getDefaultWidth();
+
+ /**
+ * @return shape that represents component body. Shape should not be transformed and should be
+ * referenced to (0, 0).
+ */
+ protected abstract Shape getBodyShape();
+
+ /**
+ * Controls how component shape should be placed relative to start and end point.
+ *
+ * @return true if shape rect should be used to center the component or false
+ * to place the component relative to length and width values.
+ */
+ protected boolean useShapeRectAsPosition() {
+ return true;
+ }
+
+ /**
+ * @return default lead thickness. Override this method to change it.
+ */
+ protected float getLeadThickness() {
+ return getClosestOdd(LEAD_THICKNESS.convertToPixels());
+ }
+
+ /**
+ * @return default lead color. Override this method to change it.
+ */
+ protected Color getLeadColorForPainting(ComponentState componentState) {
+ return componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : getLeadColor();
+ }
+
+ @EditableProperty(name = "Lead color")
+ public Color getLeadColor() {
+ if (leadColor == null) {
+ leadColor = LEAD_COLOR_ICON;
+ }
+ return leadColor;
+ }
+
+ public void setLeadColor(Color leadColor) {
+ this.leadColor = leadColor;
+ }
+
+ protected int calculatePinSpacing(Rectangle shapeRect) {
+ return shapeRect.width;
+ }
+
+ @Override
+ public int getControlPointCount() {
+ return points.length;
+ }
+
+ @Override
+ public Point getControlPoint(int index) {
+ return (Point) points[index];
+ }
+
+ @Override
+ public boolean isControlPointSticky(int index) {
+ return true;
+ }
+
+ @Override
+ public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
+ return VisibilityPolicy.ALWAYS;
+ }
+
+ @Override
+ public void setControlPoint(Point point, int index) {
+ points[index].setLocation(point);
+ }
+
+ @EditableProperty(name = "Color")
+ public Color getBodyColor() {
+ return bodyColor;
+ }
+
+ public void setBodyColor(Color bodyColor) {
+ this.bodyColor = bodyColor;
+ }
+
+ public Color getStandingBodyColor() {
+ return bodyColor;
+ }
+
+ @EditableProperty(name = "Border")
+ public Color getBorderColor() {
+ return borderColor;
+ }
+
+ public void setBorderColor(Color borderColor) {
+ this.borderColor = borderColor;
+ }
+
+ @EditableProperty(name = "Length", defaultable = true)
+ public Size getLength() {
+ return length;
+ }
+
+ public void setLength(Size length) {
+ this.length = length;
+ }
+
+ @EditableProperty(name = "Width", defaultable = true)
+ public Size getWidth() {
+ return width;
+ }
+
+ public void setWidth(Size width) {
+ this.width = width;
+ }
+
+ @EditableProperty
+ public Display getDisplay() {
+ return display;
+ }
+
+ public void setDisplay(Display display) {
+ this.display = display;
+ }
+
+ @EditableProperty(name = "Label color")
+ public Color getLabelColor() {
+ return labelColor;
+ }
+
+ public void setLabelColor(Color labelColor) {
+ this.labelColor = labelColor;
+ }
+
+ /**
+ * Override this method with @EditableProperty annotation in child classes where standing mode is
+ * supported
+ *
+ * @return
+ */
+ public boolean getFlipStanding() {
+ return flipStanding;
+ }
+
+ public void setFlipStanding(boolean flipStanding) {
+ this.flipStanding = flipStanding;
+ }
+}
diff --git a/diylc/diylc-core/src/org/diylc/presenter/G2DWrapper.java b/diylc/diylc-core/src/org/diylc/presenter/G2DWrapper.java
index a3c1515e..81e267c2 100644
--- a/diylc/diylc-core/src/org/diylc/presenter/G2DWrapper.java
+++ b/diylc/diylc-core/src/org/diylc/presenter/G2DWrapper.java
@@ -200,8 +200,17 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
if (!drawingComponent || !trackingAllowed || s.equals(lastShape)) {
return;
}
-
- appendShape(getStroke().createStrokedShape(s));
+ Stroke stroke = getStroke();
+ if (stroke instanceof BasicStroke) {
+ BasicStroke bstroke = (BasicStroke) stroke;
+ if (bstroke.getLineWidth() < 3) {
+ appendShape(ObjectCache.getInstance().fetchBasicStroke(3).createStrokedShape(s));
+ } else {
+ appendShape(getStroke().createStrokedShape(s));
+ }
+ } else {
+ appendShape(getStroke().createStrokedShape(s));
+ }
}
@Override
diff --git a/diylc/diylc-library/lib/diylc-core.jar b/diylc/diylc-library/lib/diylc-core.jar
index be9d92c8..3dfcd2f7 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/boards/EyeletBoard.java b/diylc/diylc-library/src/org/diylc/components/boards/EyeletBoard.java
index 6da1220e..a1a9fab0 100644
--- a/diylc/diylc-library/src/org/diylc/components/boards/EyeletBoard.java
+++ b/diylc/diylc-library/src/org/diylc/components/boards/EyeletBoard.java
@@ -48,7 +48,7 @@ public class EyeletBoard extends AbstractBoard {
private static final long serialVersionUID = 1L;
- public static Color BOARD_COLOR = Color.decode("#CCFFCC");
+ public static Color BOARD_COLOR = Color.decode("#E3EAB4");
public static Color BORDER_COLOR = BOARD_COLOR.darker();
public static Color EYELET_COLOR = Color.decode("#C3E4ED");
diff --git a/diylc/diylc-library/src/org/diylc/components/connectivity/CurvedTrace.java b/diylc/diylc-library/src/org/diylc/components/connectivity/CurvedTrace.java
index 9d5f8388..59419ed8 100644
--- a/diylc/diylc-library/src/org/diylc/components/connectivity/CurvedTrace.java
+++ b/diylc/diylc-library/src/org/diylc/components/connectivity/CurvedTrace.java
@@ -1,112 +1,108 @@
/*
+ *
+ * DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
+ *
+ * This file is part of DIYLC.
+ *
+ * DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with DIYLC. If not, see
+ * .
+ */
+package org.diylc.components.connectivity;
- DIY Layout Creator (DIYLC).
- Copyright (c) 2009-2018 held jointly by the individual authors.
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.geom.Path2D;
- This file is part of DIYLC.
-
- DIYLC is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- DIYLC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with DIYLC. If not, see .
-
-*/
-package org.diylc.components.connectivity;
-
-import java.awt.Color;
-import java.awt.Graphics2D;
-import java.awt.geom.CubicCurve2D;
-
-import org.diylc.common.SimpleComponentTransformer;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.PCBLayer;
-import org.diylc.components.AbstractCurvedComponent;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.PCBLayer;
+import org.diylc.common.SimpleComponentTransformer;
+import org.diylc.components.AbstractCurvedComponent;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
import org.diylc.core.IDrawingObserver;
-import org.diylc.core.annotations.BomPolicy;
-import org.diylc.core.annotations.ComponentDescriptor;
-import org.diylc.core.annotations.EditableProperty;
-import org.diylc.core.annotations.KeywordPolicy;
-import org.diylc.core.measures.Size;
-import org.diylc.core.measures.SizeUnit;
-
-@ComponentDescriptor(name = "Curved Trace", author = "Branislav Stojkovic", category = "Connectivity",
- instanceNamePrefix = "Trace", description = "Curved copper trace with two control points",
- zOrder = IDIYComponent.TRACE, bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false,
- keywordPolicy = KeywordPolicy.SHOW_TAG, keywordTag = "PCB", transformer = SimpleComponentTransformer.class)
-public class CurvedTrace extends AbstractCurvedComponent {
-
- private static final long serialVersionUID = 1L;
-
- public static Color COLOR = Color.black;
- public static Size SIZE = new Size(1d, SizeUnit.mm);
-
- protected Size size = SIZE;
- private PCBLayer layer = PCBLayer._1;
-
- @Override
- protected Color getDefaultColor() {
- return COLOR;
- }
-
- @Override
- protected void drawCurve(CubicCurve2D curve, Graphics2D g2d, ComponentState componentState, IDrawingObserver drawingObserver) {
- float thickness = (float) size.convertToPixels();
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(thickness));
- Color curveColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : color;
+import org.diylc.core.annotations.BomPolicy;
+import org.diylc.core.annotations.ComponentDescriptor;
+import org.diylc.core.annotations.EditableProperty;
+import org.diylc.core.annotations.KeywordPolicy;
+import org.diylc.core.measures.Size;
+import org.diylc.core.measures.SizeUnit;
+
+@ComponentDescriptor(name = "Curved Trace", author = "Branislav Stojkovic", category = "Connectivity",
+ instanceNamePrefix = "Trace", description = "Curved copper trace with two control points",
+ zOrder = IDIYComponent.TRACE, bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false,
+ keywordPolicy = KeywordPolicy.SHOW_TAG, keywordTag = "PCB", transformer = SimpleComponentTransformer.class)
+public class CurvedTrace extends AbstractCurvedComponent {
+
+ private static final long serialVersionUID = 1L;
+
+ public static Color COLOR = Color.black;
+ public static Size SIZE = new Size(1d, SizeUnit.mm);
+
+ protected Size size = SIZE;
+ private PCBLayer layer = PCBLayer._1;
+
+ @Override
+ protected Color getDefaultColor() {
+ return COLOR;
+ }
+
+ @Override
+ protected void drawCurve(Path2D curve, Graphics2D g2d, ComponentState componentState, IDrawingObserver drawingObserver) {
+ float thickness = (float) size.convertToPixels();
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(thickness));
+ Color curveColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : color;
g2d.setColor(curveColor);
- drawingObserver.startTrackingContinuityArea(true);
+ drawingObserver.startTrackingContinuityArea(true);
g2d.draw(curve);
- drawingObserver.stopTrackingContinuityArea();
- }
-
- @EditableProperty(name = "Width")
- public Size getThickness() {
- return size;
- }
-
- public void setThickness(Size size) {
- this.size = size;
- }
-
- @EditableProperty
- public PCBLayer getLayer() {
- if (layer == null) {
- layer = PCBLayer._1;
- }
- return layer;
- }
-
- public void setLayer(PCBLayer layer) {
- this.layer = layer;
- }
-
- @Override
- public Void getValue() {
- return null;
- }
-
- @Override
- public void setValue(Void value) {}
-
- @Override
- public Byte getAlpha() {
- return super.getAlpha();
- }
-
- @Override
- public void setAlpha(Byte alpha) {
- super.setAlpha(alpha);
- }
-}
+ drawingObserver.stopTrackingContinuityArea();
+ }
+
+ @EditableProperty(name = "Width")
+ public Size getThickness() {
+ return size;
+ }
+
+ public void setThickness(Size size) {
+ this.size = size;
+ }
+
+ @EditableProperty
+ public PCBLayer getLayer() {
+ if (layer == null) {
+ layer = PCBLayer._1;
+ }
+ return layer;
+ }
+
+ public void setLayer(PCBLayer layer) {
+ this.layer = layer;
+ }
+
+ @Override
+ public Void getValue() {
+ return null;
+ }
+
+ @Override
+ public void setValue(Void value) {}
+
+ @Override
+ public Byte getAlpha() {
+ return super.getAlpha();
+ }
+
+ @Override
+ public void setAlpha(Byte alpha) {
+ super.setAlpha(alpha);
+ }
+}
diff --git a/diylc/diylc-library/src/org/diylc/components/connectivity/HookupWire.java b/diylc/diylc-library/src/org/diylc/components/connectivity/HookupWire.java
index b1d6dd9c..f5fa2d07 100644
--- a/diylc/diylc-library/src/org/diylc/components/connectivity/HookupWire.java
+++ b/diylc/diylc-library/src/org/diylc/components/connectivity/HookupWire.java
@@ -1,90 +1,112 @@
/*
+ *
+ * DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
+ *
+ * This file is part of DIYLC.
+ *
+ * DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with DIYLC. If not, see
+ * .
+ */
+package org.diylc.components.connectivity;
- DIY Layout Creator (DIYLC).
- Copyright (c) 2009-2018 held jointly by the individual authors.
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Stroke;
+import java.awt.geom.Path2D;
- This file is part of DIYLC.
-
- DIYLC is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- DIYLC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with DIYLC. If not, see .
-
-*/
-package org.diylc.components.connectivity;
-
-import java.awt.Color;
-import java.awt.Graphics2D;
-import java.awt.geom.CubicCurve2D;
-
-import org.diylc.common.ObjectCache;
-import org.diylc.common.SimpleComponentTransformer;
-import org.diylc.components.AbstractCurvedComponent;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.SimpleComponentTransformer;
+import org.diylc.components.AbstractCurvedComponent;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
import org.diylc.core.IDrawingObserver;
-import org.diylc.core.annotations.BomPolicy;
-import org.diylc.core.annotations.ComponentDescriptor;
-import org.diylc.core.annotations.EditableProperty;
-import org.diylc.utils.Constants;
-
-@ComponentDescriptor(name = "Hookup Wire", author = "Branislav Stojkovic", category = "Connectivity",
- instanceNamePrefix = "W", description = "Flexible wire with two control points", zOrder = IDIYComponent.COMPONENT,
- flexibleZOrder = true, bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false,
- transformer = SimpleComponentTransformer.class, continuity = true)
-public class HookupWire extends AbstractCurvedComponent {
-
- private static final long serialVersionUID = 1L;
-
- public static Color COLOR = Color.green;
- public static double INSULATION_THICKNESS_PCT = 0.3;
-
- protected AWG gauge = AWG._22;
-
- @Override
- protected Color getDefaultColor() {
- return COLOR;
- }
-
- @Override
- protected void drawCurve(CubicCurve2D curve, Graphics2D g2d, ComponentState componentState, IDrawingObserver drawingObserver) {
- int thickness =
- (int) (Math.pow(Math.E, -1.12436 - 0.11594 * gauge.getValue()) * Constants.PIXELS_PER_INCH * (1 + 2 * INSULATION_THICKNESS_PCT));
- Color curveColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : color.darker();
- g2d.setColor(curveColor);
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(thickness));
- g2d.draw(curve);
- if (componentState == ComponentState.NORMAL) {
- g2d.setColor(color);
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(thickness - 2));
- g2d.draw(curve);
- }
- }
-
- @EditableProperty(name = "AWG")
- public AWG getGauge() {
- return gauge;
- }
-
- public void setGauge(AWG gauge) {
- this.gauge = gauge;
- }
-
- @Override
- public Void getValue() {
- return null;
- }
-
- @Override
- public void setValue(Void value) {}
-}
+import org.diylc.core.annotations.BomPolicy;
+import org.diylc.core.annotations.ComponentDescriptor;
+import org.diylc.core.annotations.EditableProperty;
+import org.diylc.utils.Constants;
+
+@ComponentDescriptor(name = "Hookup Wire", author = "Branislav Stojkovic", category = "Connectivity",
+ instanceNamePrefix = "W", description = "Flexible wire with two control points", zOrder = IDIYComponent.COMPONENT,
+ flexibleZOrder = true, bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false,
+ transformer = SimpleComponentTransformer.class, continuity = true)
+public class HookupWire extends AbstractCurvedComponent {
+
+ private static final long serialVersionUID = 1L;
+
+ public static Color COLOR = Color.green;
+ public static double INSULATION_THICKNESS_PCT = 0.3;
+
+ protected AWG gauge = AWG._22;
+
+ @Override
+ protected Color getDefaultColor() {
+ return COLOR;
+ }
+
+ @Override
+ protected void drawCurve(Path2D curve, Graphics2D g2d, ComponentState componentState, IDrawingObserver drawingObserver) {
+ int thickness =
+ (int) (Math.pow(Math.E, -1.12436 - 0.11594 * gauge.getValue()) * Constants.PIXELS_PER_INCH * (1 + 2 * INSULATION_THICKNESS_PCT));
+ Color curveColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : color.darker();
+ g2d.setColor(curveColor);
+ Stroke stroke = null;
+ switch (getStyle()) {
+ case SOLID:
+ stroke = ObjectCache.getInstance().fetchBasicStroke(thickness);
+ break;
+ case DASHED:
+ stroke =
+ ObjectCache.getInstance().fetchStroke(thickness, new float[] {thickness * 2, thickness * 3}, thickness * 4);
+ break;
+ case DOTTED:
+ stroke = ObjectCache.getInstance().fetchStroke(thickness, new float[] {thickness / 4, thickness * 3}, 0);
+ break;
+ }
+ g2d.setStroke(stroke);
+ g2d.draw(curve);
+ if (componentState == ComponentState.NORMAL) {
+ g2d.setColor(color);
+ switch (getStyle()) {
+ case SOLID:
+ stroke = ObjectCache.getInstance().fetchBasicStroke(thickness - 2);
+ break;
+ case DASHED:
+ stroke =
+ ObjectCache.getInstance().fetchStroke(thickness - 2, new float[] {thickness * 2, thickness * 3},
+ thickness * 4);
+ break;
+ case DOTTED:
+ stroke = ObjectCache.getInstance().fetchStroke(thickness - 2, new float[] {thickness / 4, thickness * 3}, 0);
+ }
+ g2d.setStroke(stroke);
+ g2d.draw(curve);
+ }
+ }
+
+ @EditableProperty(name = "AWG")
+ public AWG getGauge() {
+ return gauge;
+ }
+
+ public void setGauge(AWG gauge) {
+ this.gauge = gauge;
+ }
+
+ @Override
+ public Void getValue() {
+ return null;
+ }
+
+ @Override
+ public void setValue(Void value) {}
+}
diff --git a/diylc/diylc-library/src/org/diylc/components/connectivity/Jumper.java b/diylc/diylc-library/src/org/diylc/components/connectivity/Jumper.java
index 95670911..c2c6b64d 100644
--- a/diylc/diylc-library/src/org/diylc/components/connectivity/Jumper.java
+++ b/diylc/diylc-library/src/org/diylc/components/connectivity/Jumper.java
@@ -24,8 +24,9 @@ package org.diylc.components.connectivity;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Shape;
-
+
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;
@@ -48,7 +49,8 @@ public class Jumper extends AbstractLeadedComponent {
public static Color COLOR = Color.blue;
@Deprecated
- private Color color;
+ private Color color;
+ protected LineStyle style = LineStyle.SOLID;
public Jumper() {
super();
@@ -78,6 +80,17 @@ public class Jumper extends AbstractLeadedComponent {
this.leadColor = color;
}
return super.getLeadColor();
+ }
+
+ @EditableProperty(name = "Style")
+ public LineStyle getStyle() {
+ if (style == null)
+ style = LineStyle.SOLID;
+ return style;
+ }
+
+ public void setStyle(LineStyle style) {
+ this.style = style;
}
public Color getBodyColor() {
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 2d8427fc..0fc799a2 100644
--- a/diylc/diylc-library/src/org/diylc/components/connectivity/Line.java
+++ b/diylc/diylc-library/src/org/diylc/components/connectivity/Line.java
@@ -24,8 +24,10 @@ package org.diylc.components.connectivity;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Shape;
-
+import java.awt.Stroke;
+
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;
@@ -49,7 +51,8 @@ public class Line extends AbstractLeadedComponent {
public static Color COLOR = Color.black;
- private Color color = COLOR;
+ private Color color = COLOR;
+ protected LineStyle style = LineStyle.SOLID;
@Override
public void drawIcon(Graphics2D g2d, int width, int height) {
@@ -60,8 +63,21 @@ public class Line extends AbstractLeadedComponent {
@Override
public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+ IDrawingObserver drawingObserver) {
+ float thickness = 1f;
+ Stroke stroke = null;
+ switch (getStyle()) {
+ case SOLID:
+ stroke = ObjectCache.getInstance().fetchBasicStroke(thickness);
+ break;
+ case DASHED:
+ stroke = ObjectCache.getInstance().fetchStroke(thickness, new float[] {thickness * 2}, thickness * 4);
+ break;
+ case DOTTED:
+ stroke = ObjectCache.getInstance().fetchStroke(thickness, new float[] {thickness / 4, thickness * 3}, 0);
+ break;
+ }
+ g2d.setStroke(stroke);
g2d.setColor(color);
g2d.drawLine(getControlPoint(0).x, getControlPoint(0).y, getControlPoint(1).x, getControlPoint(1).y);
}
@@ -84,6 +100,17 @@ public class Line extends AbstractLeadedComponent {
public void setColor(Color color) {
this.color = color;
+ }
+
+ @EditableProperty(name = "Style")
+ public LineStyle getStyle() {
+ if (style == null)
+ style = LineStyle.SOLID;
+ return style;
+ }
+
+ public void setStyle(LineStyle style) {
+ this.style = style;
}
public Color getBodyColor() {
diff --git a/diylc/diylc-swing/build.xml b/diylc/diylc-swing/build.xml
index 0cf3f168..9c64b72c 100644
--- a/diylc/diylc-swing/build.xml
+++ b/diylc/diylc-swing/build.xml
@@ -7,7 +7,7 @@
-
+
diff --git a/diylc/diylc-swing/lib/diylc-core.jar b/diylc/diylc-swing/lib/diylc-core.jar
index be9d92c8..3dfcd2f7 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 e970987c..d6548915 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 f0c793cc..99834eb1 100644
--- a/diylc/diylc-swing/update.xml
+++ b/diylc/diylc-swing/update.xml
@@ -1932,12 +1932,20 @@
3
- 42
- 2
+ 43
+ 0
2018-12-17 00:00:00.000 CET
+
+ NEW_FEATURE
+ Added "Dashed" and "Dotted" style to "Hookup Wire", "Jumper" and "Line" components
+
+
+ NEW_FEATURE
+ Added five and seven control point options to curved components for more flexibility (literally)
+
NEW_FEATURE
Added "Turret Lug" component