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