added dashed/dotted lines

added 5 and 7-point curves
This commit is contained in:
Branislav Stojkovic
2018-12-18 00:20:33 +01:00
parent ce64cb46e7
commit e1c30b93ec
15 changed files with 1150 additions and 971 deletions
@@ -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 <http://www.gnu.org/licenses/>.
*/
package org.diylc.common;
public enum LineStyle {
SOLID, DASHED, DOTTED;
@Override
public String toString() {
return name().substring(0, 1) + name().substring(1).toLowerCase();
}
}
@@ -1,29 +1,26 @@
/* /*
*
DIY Layout Creator (DIYLC). * DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
Copyright (c) 2009-2018 held jointly by the individual authors. *
* This file is part of DIYLC.
This file is part of DIYLC. *
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
DIYLC is free software: you can redistribute it and/or modify * General Public License as published by the Free Software Foundation, either version 3 of the
it under the terms of the GNU General Public License as published by * License, or (at your option) any later version.
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
DIYLC is distributed in the hope that it will be useful, * Public License for more details.
but WITHOUT ANY WARRANTY; without even the implied warranty of *
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * You should have received a copy of the GNU General Public License along with DIYLC. If not, see
GNU General Public License for more details. * <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.diylc.common; package org.diylc.common;
import java.awt.AlphaComposite; import java.awt.AlphaComposite;
import java.awt.BasicStroke; import java.awt.BasicStroke;
import java.awt.Stroke; import java.awt.Stroke;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@@ -46,6 +43,7 @@ public class ObjectCache {
private ObjectCache() {} private ObjectCache() {}
private Map<Float, Stroke> basicStrokeMap = new HashMap<Float, Stroke>(); private Map<Float, Stroke> basicStrokeMap = new HashMap<Float, Stroke>();
private Map<String, Stroke> dashStrokeMap = new HashMap<String, Stroke>();
public Stroke fetchBasicStroke(float width) { public Stroke fetchBasicStroke(float width) {
if (basicStrokeMap.containsKey(width)) { if (basicStrokeMap.containsKey(width)) {
@@ -55,4 +53,14 @@ public class ObjectCache {
basicStrokeMap.put(width, stroke); basicStrokeMap.put(width, stroke);
return 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;
}
} }
@@ -1,23 +1,19 @@
/* /*
*
DIY Layout Creator (DIYLC). * DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
Copyright (c) 2009-2018 held jointly by the individual authors. *
* This file is part of DIYLC.
This file is part of DIYLC. *
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
DIYLC is free software: you can redistribute it and/or modify * General Public License as published by the Free Software Foundation, either version 3 of the
it under the terms of the GNU General Public License as published by * License, or (at your option) any later version.
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
DIYLC is distributed in the hope that it will be useful, * Public License for more details.
but WITHOUT ANY WARRANTY; without even the implied warranty of *
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * You should have received a copy of the GNU General Public License along with DIYLC. If not, see
GNU General Public License for more details. * <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.diylc.components; package org.diylc.components;
@@ -27,7 +23,9 @@ import java.awt.Composite;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Point; import java.awt.Point;
import java.awt.geom.CubicCurve2D; import java.awt.geom.CubicCurve2D;
import java.awt.geom.Path2D;
import org.diylc.common.LineStyle;
import org.diylc.common.ObjectCache; import org.diylc.common.ObjectCache;
import org.diylc.core.ComponentState; import org.diylc.core.ComponentState;
import org.diylc.core.IDrawingObserver; import org.diylc.core.IDrawingObserver;
@@ -45,13 +43,20 @@ public abstract class AbstractCurvedComponent<T> extends AbstractTransparentComp
public static Color GUIDELINE_COLOR = Color.blue; public static Color GUIDELINE_COLOR = Color.blue;
public static Size DEFAULT_SIZE = new Size(1d, SizeUnit.in); public static Size DEFAULT_SIZE = new Size(1d, SizeUnit.in);
protected Point[] controlPoints = new Point[] {new Point(0, 0), // 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), 0),
new Point((int) (DEFAULT_SIZE.convertToPixels() / 2), (int) (DEFAULT_SIZE.convertToPixels())), new Point((int) (DEFAULT_SIZE.convertToPixels() / 2), (int) (DEFAULT_SIZE.convertToPixels())),
new Point((int) DEFAULT_SIZE.convertToPixels(), (int) DEFAULT_SIZE.convertToPixels())}; new Point((int) DEFAULT_SIZE.convertToPixels(), (int) DEFAULT_SIZE.convertToPixels())};
protected Color color = getDefaultColor(); protected Color color = getDefaultColor();
protected PointCount pointCount = PointCount.FOUR; protected PointCount pointCount = PointCount.FOUR;
protected LineStyle style = LineStyle.SOLID;
protected Boolean smooth = true;
private int lastUpdatePointIndex = -1;
/** /**
* Draws the specified curve onto graphics. * Draws the specified curve onto graphics.
@@ -61,7 +66,8 @@ public abstract class AbstractCurvedComponent<T> extends AbstractTransparentComp
* @param componentState * @param componentState
* @param theme * @param theme
*/ */
protected abstract void drawCurve(CubicCurve2D curve, Graphics2D g2d, ComponentState componentState, IDrawingObserver drawingObserver); protected abstract void drawCurve(Path2D curve, Graphics2D g2d, ComponentState componentState,
IDrawingObserver drawingObserver);
/** /**
* @return default color. * @return default color.
@@ -86,31 +92,60 @@ public abstract class AbstractCurvedComponent<T> extends AbstractTransparentComp
if (checkPointsClipped(g2d.getClip())) { if (checkPointsClipped(g2d.getClip())) {
return; 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) { if (componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING) {
// Do not track guidelines. // Do not track guidelines.
drawingObserver.stopTracking(); drawingObserver.stopTracking();
g2d.setStroke(Constants.DASHED_STROKE); g2d.setStroke(Constants.DASHED_STROKE);
g2d.setColor(GUIDELINE_COLOR); g2d.setColor(GUIDELINE_COLOR);
g2d.drawLine(controlPoints[0].x, controlPoints[0].y, controlPoints[1].x, controlPoints[1].y); for (int i = 0; i < p.length - 1; i++) {
g2d.drawLine(controlPoints[1].x, controlPoints[1].y, controlPoints[2].x, controlPoints[2].y); g2d.drawLine(p[i].x, p[i].y, p[i + 1].x, p[i + 1].y);
g2d.drawLine(controlPoints[2].x, controlPoints[2].y, controlPoints[3].x, controlPoints[3].y); }
drawingObserver.startTracking(); drawingObserver.startTracking();
} }
CubicCurve2D curve =
new CubicCurve2D.Double(controlPoints[0].x, controlPoints[0].y, controlPoints[1].x, controlPoints[1].y, Path2D path = new Path2D.Double();
controlPoints[2].x, controlPoints[2].y, controlPoints[3].x, controlPoints[3].y); 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(); Composite oldComposite = g2d.getComposite();
if (alpha < MAX_ALPHA) { if (alpha < MAX_ALPHA) {
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA)); g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
} }
// g2d.setColor(color.darker());
// g2d.setStroke(new BasicStroke(thickness)); drawCurve(path, g2d, componentState, drawingObserver);
// g2d.draw(path);
// g2d.setColor(color);
// g2d.setStroke(new BasicStroke(thickness - 2));
// g2d.draw(path);
drawCurve(curve, g2d, componentState, drawingObserver);
g2d.setComposite(oldComposite); g2d.setComposite(oldComposite);
} }
@@ -122,25 +157,83 @@ public abstract class AbstractCurvedComponent<T> extends AbstractTransparentComp
return pointCount; return pointCount;
} }
public void setPointCount(PointCount pointCount) { protected Point[] getControlPoints() {
this.pointCount = pointCount; if (this.controlPoints != null) {
// Reset control points. // ensure backward compatibility by copying points from the old structure to the new one
for (int i = 0; i < getControlPointCount(); i++) { switch (getPointCount()) {
setControlPoint(getControlPoint(i), i); 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 @Override
public int getControlPointCount() { public int getControlPointCount() {
switch (getPointCount()) { return getControlPoints().length;
case TWO:
return 2;
case THREE:
return 3;
case FOUR:
return 4;
}
return 0;
} }
@Override @Override
@@ -155,91 +248,37 @@ public abstract class AbstractCurvedComponent<T> extends AbstractTransparentComp
@Override @Override
public boolean canControlPointOverlap(int index) { public boolean canControlPointOverlap(int index) {
// Only shape control points may overlap. return index > 0 && index < getControlPointCount() - 1;
switch (getPointCount()) {
case TWO:
return false;
case THREE:
return index == 1;
case FOUR:
return index == 1 || index == 2;
}
return false;
} }
@Override @Override
public Point getControlPoint(int index) { public Point getControlPoint(int index) {
if (index == 0) { return getControlPoints()[index];
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 @Override
public void setControlPoint(Point point, int index) { public void setControlPoint(Point point, int index) {
if (index == 0) { Point[] p = getControlPoints();
controlPoints[0].setLocation(point); p[index].setLocation(point);
} else { this.lastUpdatePointIndex = index;
switch (getPointCount()) { // if (getSmooth()) {
case TWO: // if (getPointCount() == PointCount.FIVE && (index == 1 || index == 2)) {
switch (index) { // p[3] = findThirdPoint(p[2], p[1]);
case 1: // }
Point center = new Point((point.x + controlPoints[0].x) / 2, (point.y + controlPoints[0].y) / 2); // if (getPointCount() == PointCount.FIVE && index == 3) {
controlPoints[1].setLocation(center); // p[1] = findThirdPoint(p[2], p[3]);
controlPoints[2].setLocation(center); // }
controlPoints[3].setLocation(point); // if (getPointCount() == PointCount.SEVEN && (index == 2 || index == 3)) {
break; // p[4] = findThirdPoint(p[3], p[2]);
} // }
break; // if (getPointCount() == PointCount.SEVEN && index == 4) {
case THREE: // p[2] = findThirdPoint(p[3], p[4]);
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;
}
} }
private Point findThirdPoint(Point p0, Point p) {
return new Point(2 * p0.x - p.x, 2 * p0.y - p.y);
} }
@EditableProperty(name = "Color") @EditableProperty(name = "Color")
@@ -251,8 +290,46 @@ public abstract class AbstractCurvedComponent<T> extends AbstractTransparentComp
this.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 { enum PointCount {
TWO, THREE, FOUR; TWO(2), THREE(3), FOUR(4), FIVE(5), SEVEN(7);
private int count;
private PointCount(int count) {
this.count = count;
}
@Override @Override
public String toString() { public String toString() {
@@ -1,23 +1,19 @@
/* /*
*
DIY Layout Creator (DIYLC). * DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
Copyright (c) 2009-2018 held jointly by the individual authors. *
* This file is part of DIYLC.
This file is part of DIYLC. *
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
DIYLC is free software: you can redistribute it and/or modify * General Public License as published by the Free Software Foundation, either version 3 of the
it under the terms of the GNU General Public License as published by * License, or (at your option) any later version.
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
DIYLC is distributed in the hope that it will be useful, * Public License for more details.
but WITHOUT ANY WARRANTY; without even the implied warranty of *
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * You should have received a copy of the GNU General Public License along with DIYLC. If not, see
GNU General Public License for more details. * <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.diylc.components; package org.diylc.components;
@@ -29,6 +25,7 @@ import java.awt.Graphics2D;
import java.awt.Point; import java.awt.Point;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.Shape; import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D; import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
@@ -36,6 +33,7 @@ import java.awt.geom.Rectangle2D;
import org.diylc.appframework.miscutils.ConfigurationManager; import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.common.Display; import org.diylc.common.Display;
import org.diylc.common.IPlugInPort; import org.diylc.common.IPlugInPort;
import org.diylc.common.LineStyle;
import org.diylc.common.ObjectCache; import org.diylc.common.ObjectCache;
import org.diylc.core.ComponentState; import org.diylc.core.ComponentState;
import org.diylc.core.IDrawingObserver; import org.diylc.core.IDrawingObserver;
@@ -146,9 +144,9 @@ public abstract class AbstractLeadedComponent<T> extends AbstractTransparentComp
double leadLength = (distance - calculatePinSpacing(shapeRect)) / 2; double leadLength = (distance - calculatePinSpacing(shapeRect)) / 2;
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
Color leadColor = shouldShadeLeads() ? Color leadColor =
getLeadColorForPainting(componentState).darker() : shouldShadeLeads() ? getLeadColorForPainting(componentState).darker()
getLeadColorForPainting(componentState); : getLeadColorForPainting(componentState);
g2d.setColor(leadColor); g2d.setColor(leadColor);
drawLeads(g2d, theta, leadLength); drawLeads(g2d, theta, leadLength);
@@ -202,50 +200,6 @@ public abstract class AbstractLeadedComponent<T> extends AbstractTransparentComp
g2d.setColor(finalBorderColor); g2d.setColor(finalBorderColor);
g2d.draw(shape); 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. // Draw label.
g2d.setFont(project.getFont()); g2d.setFont(project.getFont());
if (useShapeRectAsPosition()) { if (useShapeRectAsPosition()) {
@@ -300,7 +254,23 @@ public abstract class AbstractLeadedComponent<T> extends AbstractTransparentComp
private void drawLead(Graphics2D g2d, ComponentState componentState, IDrawingObserver observer, boolean isCopperArea) { private void drawLead(Graphics2D g2d, ComponentState componentState, IDrawingObserver observer, boolean isCopperArea) {
if (isCopperArea) if (isCopperArea)
observer.startTrackingContinuityArea(true); observer.startTrackingContinuityArea(true);
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(getLeadThickness()));
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 = Color leadColor =
shouldShadeLeads() ? getLeadColorForPainting(componentState).darker() : getLeadColorForPainting(componentState); shouldShadeLeads() ? getLeadColorForPainting(componentState).darker() : getLeadColorForPainting(componentState);
g2d.setColor(leadColor); g2d.setColor(leadColor);
@@ -310,13 +280,30 @@ public abstract class AbstractLeadedComponent<T> extends AbstractTransparentComp
observer.stopTrackingContinuityArea(); observer.stopTrackingContinuityArea();
if (shouldShadeLeads()) { if (shouldShadeLeads()) {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(getLeadThickness() - 2)); 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); leadColor = getLeadColorForPainting(componentState);
g2d.setColor(leadColor); g2d.setColor(leadColor);
g2d.drawLine(points[0].x, points[0].y, points[1].x, points[1].y); 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) { protected void decorateComponentBody(Graphics2D g2d, boolean outlineMode) {
// Do nothing. // Do nothing.
} }
@@ -200,9 +200,18 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
if (!drawingComponent || !trackingAllowed || s.equals(lastShape)) { if (!drawingComponent || !trackingAllowed || s.equals(lastShape)) {
return; return;
} }
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)); appendShape(getStroke().createStrokedShape(s));
} }
} else {
appendShape(getStroke().createStrokedShape(s));
}
}
@Override @Override
public void addRenderingHints(Map<?, ?> hints) { public void addRenderingHints(Map<?, ?> hints) {
Binary file not shown.
@@ -48,7 +48,7 @@ public class EyeletBoard extends AbstractBoard {
private static final long serialVersionUID = 1L; 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 BORDER_COLOR = BOARD_COLOR.darker();
public static Color EYELET_COLOR = Color.decode("#C3E4ED"); public static Color EYELET_COLOR = Color.decode("#C3E4ED");
@@ -1,33 +1,29 @@
/* /*
*
DIY Layout Creator (DIYLC). * DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
Copyright (c) 2009-2018 held jointly by the individual authors. *
* This file is part of DIYLC.
This file is part of DIYLC. *
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
DIYLC is free software: you can redistribute it and/or modify * General Public License as published by the Free Software Foundation, either version 3 of the
it under the terms of the GNU General Public License as published by * License, or (at your option) any later version.
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
DIYLC is distributed in the hope that it will be useful, * Public License for more details.
but WITHOUT ANY WARRANTY; without even the implied warranty of *
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * You should have received a copy of the GNU General Public License along with DIYLC. If not, see
GNU General Public License for more details. * <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.diylc.components.connectivity; package org.diylc.components.connectivity;
import java.awt.Color; import java.awt.Color;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.geom.CubicCurve2D; import java.awt.geom.Path2D;
import org.diylc.common.SimpleComponentTransformer;
import org.diylc.common.ObjectCache; import org.diylc.common.ObjectCache;
import org.diylc.common.PCBLayer; import org.diylc.common.PCBLayer;
import org.diylc.common.SimpleComponentTransformer;
import org.diylc.components.AbstractCurvedComponent; import org.diylc.components.AbstractCurvedComponent;
import org.diylc.core.ComponentState; import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent; import org.diylc.core.IDIYComponent;
@@ -59,7 +55,7 @@ public class CurvedTrace extends AbstractCurvedComponent<Void> {
} }
@Override @Override
protected void drawCurve(CubicCurve2D curve, Graphics2D g2d, ComponentState componentState, IDrawingObserver drawingObserver) { protected void drawCurve(Path2D curve, Graphics2D g2d, ComponentState componentState, IDrawingObserver drawingObserver) {
float thickness = (float) size.convertToPixels(); float thickness = (float) size.convertToPixels();
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(thickness)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(thickness));
Color curveColor = Color curveColor =
@@ -1,29 +1,26 @@
/* /*
*
DIY Layout Creator (DIYLC). * DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
Copyright (c) 2009-2018 held jointly by the individual authors. *
* This file is part of DIYLC.
This file is part of DIYLC. *
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
DIYLC is free software: you can redistribute it and/or modify * General Public License as published by the Free Software Foundation, either version 3 of the
it under the terms of the GNU General Public License as published by * License, or (at your option) any later version.
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
DIYLC is distributed in the hope that it will be useful, * Public License for more details.
but WITHOUT ANY WARRANTY; without even the implied warranty of *
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * You should have received a copy of the GNU General Public License along with DIYLC. If not, see
GNU General Public License for more details. * <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.diylc.components.connectivity; package org.diylc.components.connectivity;
import java.awt.Color; import java.awt.Color;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.geom.CubicCurve2D; import java.awt.Stroke;
import java.awt.geom.Path2D;
import org.diylc.common.ObjectCache; import org.diylc.common.ObjectCache;
import org.diylc.common.SimpleComponentTransformer; import org.diylc.common.SimpleComponentTransformer;
@@ -55,18 +52,43 @@ public class HookupWire extends AbstractCurvedComponent<Void> {
} }
@Override @Override
protected void drawCurve(CubicCurve2D curve, Graphics2D g2d, ComponentState componentState, IDrawingObserver drawingObserver) { protected void drawCurve(Path2D curve, Graphics2D g2d, ComponentState componentState, IDrawingObserver drawingObserver) {
int thickness = int thickness =
(int) (Math.pow(Math.E, -1.12436 - 0.11594 * gauge.getValue()) * Constants.PIXELS_PER_INCH * (1 + 2 * INSULATION_THICKNESS_PCT)); (int) (Math.pow(Math.E, -1.12436 - 0.11594 * gauge.getValue()) * Constants.PIXELS_PER_INCH * (1 + 2 * INSULATION_THICKNESS_PCT));
Color curveColor = Color curveColor =
componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: color.darker(); : color.darker();
g2d.setColor(curveColor); g2d.setColor(curveColor);
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(thickness)); 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); g2d.draw(curve);
if (componentState == ComponentState.NORMAL) { if (componentState == ComponentState.NORMAL) {
g2d.setColor(color); g2d.setColor(color);
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(thickness - 2)); 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); g2d.draw(curve);
} }
} }
@@ -26,6 +26,7 @@ import java.awt.Graphics2D;
import java.awt.Shape; import java.awt.Shape;
import org.diylc.common.Display; import org.diylc.common.Display;
import org.diylc.common.LineStyle;
import org.diylc.common.ObjectCache; import org.diylc.common.ObjectCache;
import org.diylc.common.SimpleComponentTransformer; import org.diylc.common.SimpleComponentTransformer;
import org.diylc.components.AbstractLeadedComponent; import org.diylc.components.AbstractLeadedComponent;
@@ -49,6 +50,7 @@ public class Jumper extends AbstractLeadedComponent<Void> {
@Deprecated @Deprecated
private Color color; private Color color;
protected LineStyle style = LineStyle.SOLID;
public Jumper() { public Jumper() {
super(); super();
@@ -80,6 +82,17 @@ public class Jumper extends AbstractLeadedComponent<Void> {
return super.getLeadColor(); 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() { public Color getBodyColor() {
return super.getBodyColor(); return super.getBodyColor();
} }
@@ -24,8 +24,10 @@ package org.diylc.components.connectivity;
import java.awt.Color; import java.awt.Color;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Shape; import java.awt.Shape;
import java.awt.Stroke;
import org.diylc.common.Display; import org.diylc.common.Display;
import org.diylc.common.LineStyle;
import org.diylc.common.ObjectCache; import org.diylc.common.ObjectCache;
import org.diylc.common.SimpleComponentTransformer; import org.diylc.common.SimpleComponentTransformer;
import org.diylc.components.AbstractLeadedComponent; import org.diylc.components.AbstractLeadedComponent;
@@ -50,6 +52,7 @@ public class Line extends AbstractLeadedComponent<Void> {
public static Color COLOR = Color.black; public static Color COLOR = Color.black;
private Color color = COLOR; private Color color = COLOR;
protected LineStyle style = LineStyle.SOLID;
@Override @Override
public void drawIcon(Graphics2D g2d, int width, int height) { public void drawIcon(Graphics2D g2d, int width, int height) {
@@ -61,7 +64,20 @@ public class Line extends AbstractLeadedComponent<Void> {
@Override @Override
public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
IDrawingObserver drawingObserver) { IDrawingObserver drawingObserver) {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1)); 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.setColor(color);
g2d.drawLine(getControlPoint(0).x, getControlPoint(0).y, getControlPoint(1).x, getControlPoint(1).y); g2d.drawLine(getControlPoint(0).x, getControlPoint(0).y, getControlPoint(1).x, getControlPoint(1).y);
} }
@@ -86,6 +102,17 @@ public class Line extends AbstractLeadedComponent<Void> {
this.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() { public Color getBodyColor() {
return super.getBodyColor(); return super.getBodyColor();
} }
+1 -1
View File
@@ -7,7 +7,7 @@
<property name="jar.dir" value="${build.dir}/jar" /> <property name="jar.dir" value="${build.dir}/jar" />
<property name="report.dir" value="${build.dir}/junitreport" /> <property name="report.dir" value="${build.dir}/junitreport" />
<property name="main.class" value="org.diylc.DIYLCStarter" /> <property name="main.class" value="org.diylc.DIYLCStarter" />
<property name="diylc.version" value="3.42.2" /> <property name="diylc.version" value="3.43.0" />
<property name="classes.dir" value="${build.dir}/temp/${ant.project.name}/classes" /> <property name="classes.dir" value="${build.dir}/temp/${ant.project.name}/classes" />
<property name="test.classes.dir" value="${build.dir}/temp/${ant.project.name}/test.classes" /> <property name="test.classes.dir" value="${build.dir}/temp/${ant.project.name}/test.classes" />
Binary file not shown.
Binary file not shown.
+10 -2
View File
@@ -1932,12 +1932,20 @@
<org.diylc.appframework.update.Version> <org.diylc.appframework.update.Version>
<versionNumber> <versionNumber>
<major>3</major> <major>3</major>
<minor>42</minor> <minor>43</minor>
<build>2</build> <build>0</build>
</versionNumber> </versionNumber>
<releaseDate>2018-12-17 00:00:00.000 CET</releaseDate> <releaseDate>2018-12-17 00:00:00.000 CET</releaseDate>
<name></name> <name></name>
<changes> <changes>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added "Dashed" and "Dotted" style to "Hookup Wire", "Jumper" and "Line" components</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added five and seven control point options to curved components for more flexibility (literally)</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change> <org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType> <changeType>NEW_FEATURE</changeType>
<description>Added "Turret Lug" component</description> <description>Added "Turret Lug" component</description>