Improved precision of rendering

This commit is contained in:
Bane Stojkovic
2026-06-10 17:19:21 +02:00
parent 9179086bd5
commit 1d7dd87d85
57 changed files with 1505 additions and 1460 deletions
@@ -386,8 +386,8 @@ public class DrawingManager {
g2dWrapper.setColor(CONTROL_POINT_COLOR); g2dWrapper.setColor(CONTROL_POINT_COLOR);
Point2D controlPoint = component.getControlPoint(i); Point2D controlPoint = component.getControlPoint(i);
int pointSize = CONTROL_POINT_SIZE - 2; int pointSize = CONTROL_POINT_SIZE - 2;
g2dWrapper.fillOval((int) (controlPoint.getX() - pointSize / 2), g2dWrapper.fillOval((int) Math.round(controlPoint.getX() - pointSize / 2),
(int) (controlPoint.getY() - pointSize / 2), pointSize, pointSize); (int) Math.round(controlPoint.getY() - pointSize / 2), pointSize, pointSize);
} }
} }
} }
@@ -403,11 +403,11 @@ public class DrawingManager {
int pointSize = CONTROL_POINT_SIZE; int pointSize = CONTROL_POINT_SIZE;
g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR.darker()); g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR.darker());
g2dWrapper.fillOval((int) (controlPoint.getX() - pointSize / 2), g2dWrapper.fillOval((int) Math.round(controlPoint.getX() - pointSize / 2),
(int) (controlPoint.getY() - pointSize / 2), pointSize, pointSize); (int) Math.round(controlPoint.getY() - pointSize / 2), pointSize, pointSize);
g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR); g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR);
g2dWrapper.fillOval((int) (controlPoint.getX() - CONTROL_POINT_SIZE / 2 + 1), g2dWrapper.fillOval((int) Math.round(controlPoint.getX() - CONTROL_POINT_SIZE / 2 + 1),
(int) (controlPoint.getY() - CONTROL_POINT_SIZE / 2 + 1), CONTROL_POINT_SIZE - 2, (int) Math.round(controlPoint.getY() - CONTROL_POINT_SIZE / 2 + 1), CONTROL_POINT_SIZE - 2,
CONTROL_POINT_SIZE - 2); CONTROL_POINT_SIZE - 2);
} }
} }
@@ -437,12 +437,12 @@ public class DrawingManager {
for (Point2D point : controlPointSlot) { for (Point2D point : controlPointSlot) {
if (point != null) { if (point != null) {
g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR.darker()); g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR.darker());
g2dWrapper.fillOval((int) (point.getX() - CONTROL_POINT_SIZE / 2), g2dWrapper.fillOval((int) Math.round(point.getX() - CONTROL_POINT_SIZE / 2),
(int) (point.getY() - CONTROL_POINT_SIZE / 2), CONTROL_POINT_SIZE, (int) Math.round(point.getY() - CONTROL_POINT_SIZE / 2), CONTROL_POINT_SIZE,
CONTROL_POINT_SIZE); CONTROL_POINT_SIZE);
g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR); g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR);
g2dWrapper.fillOval((int) (point.getX() - CONTROL_POINT_SIZE / 2 + 1), g2dWrapper.fillOval((int) Math.round(point.getX() - CONTROL_POINT_SIZE / 2 + 1),
(int) (point.getY() - CONTROL_POINT_SIZE / 2 + 1), CONTROL_POINT_SIZE - 2, (int) Math.round(point.getY() - CONTROL_POINT_SIZE / 2 + 1), CONTROL_POINT_SIZE - 2,
CONTROL_POINT_SIZE - 2); CONTROL_POINT_SIZE - 2);
} }
} }
@@ -1289,8 +1289,8 @@ public class Presenter implements IPlugInPort {
// If there's no selection, the only thing to do is update the // If there's no selection, the only thing to do is update the
// selection rectangle and refresh. // selection rectangle and refresh.
Rectangle oldSelectionRect = selectionRect == null ? null : new Rectangle(selectionRect); Rectangle oldSelectionRect = selectionRect == null ? null : new Rectangle(selectionRect);
this.selectionRect = Utils.createRectangle(new Point((int)scaledPoint.getX(), (int)scaledPoint.getY()), this.selectionRect = Utils.createRectangle(new Point((int) Math.round(scaledPoint.getX()), (int) Math.round(scaledPoint.getY())),
new Point((int)previousDragPoint.getX(), (int)previousDragPoint.getY())); new Point((int) Math.round(previousDragPoint.getX()), (int) Math.round(previousDragPoint.getY())));
if (selectionRect.equals(oldSelectionRect)) { if (selectionRect.equals(oldSelectionRect)) {
return true; return true;
} }
@@ -1621,8 +1621,8 @@ public class Presenter implements IPlugInPort {
// If there's no selection finalize selectionRect and see which // If there's no selection finalize selectionRect and see which
// components intersect with it. // components intersect with it.
if (scaledPoint != null && previousDragPoint != null) { if (scaledPoint != null && previousDragPoint != null) {
this.selectionRect = Utils.createRectangle(new Point((int)scaledPoint.getX(), (int)scaledPoint.getY()), this.selectionRect = Utils.createRectangle(new Point((int) Math.round(scaledPoint.getX()), (int) Math.round(scaledPoint.getY())),
new Point((int)previousDragPoint.getX(), (int)previousDragPoint.getY()));; new Point((int) Math.round(previousDragPoint.getX()), (int) Math.round(previousDragPoint.getY())));;
} }
List<IDIYComponent<?>> newSelection = new ArrayList<IDIYComponent<?>>(); List<IDIYComponent<?>> newSelection = new ArrayList<IDIYComponent<?>>();
if (operationMode != OperationMode.HIGHLIGHT_CONNECTED_AREAS) if (operationMode != OperationMode.HIGHLIGHT_CONNECTED_AREAS)
@@ -32,6 +32,8 @@ import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import org.diylc.utils.MathUtils;
/** /**
* Serializes {@link Area} objects by converting coordinates from pixels to inches, thus avoiding * Serializes {@link Area} objects by converting coordinates from pixels to inches, thus avoiding
* the resolution to affect point placement. * the resolution to affect point placement.
@@ -66,7 +68,7 @@ public class AreaConverter implements Converter {
} }
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
writer.startNode("coordinate"); writer.startNode("coordinate");
writer.setValue(String.valueOf(coord[i])); writer.setValue(MathUtils.formatDouble(coord[i]));
writer.endNode(); writer.endNode();
} }
writer.endNode(); writer.endNode();
@@ -87,7 +89,7 @@ public class AreaConverter implements Converter {
List<java.lang.Double> values = new ArrayList<java.lang.Double>(); List<java.lang.Double> values = new ArrayList<java.lang.Double>();
while (reader.hasMoreChildren()) { while (reader.hasMoreChildren()) {
reader.moveDown(); reader.moveDown();
values.add(java.lang.Double.parseDouble(reader.getValue())); values.add(MathUtils.parseDouble(reader.getValue()));
reader.moveUp(); reader.moveUp();
} }
java.lang.Double[] coord = values.toArray(new java.lang.Double[0]); java.lang.Double[] coord = values.toArray(new java.lang.Double[0]);
@@ -30,6 +30,7 @@ import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import org.diylc.utils.Constants; import org.diylc.utils.Constants;
import org.diylc.utils.MathUtils;
/** /**
* Serializes {@link Point2D} objects by converting coordinates from pixels to inches, thus avoiding * Serializes {@link Point2D} objects by converting coordinates from pixels to inches, thus avoiding
@@ -42,26 +43,27 @@ public class PointConverter implements Converter {
@Override @Override
public void marshal(Object object, HierarchicalStreamWriter writer, MarshallingContext context) { public void marshal(Object object, HierarchicalStreamWriter writer, MarshallingContext context) {
Point2D point = (Point2D) object; Point2D point = (Point2D) object;
writer.addAttribute("x", Double.toString(1d * point.getX() / Constants.PIXELS_PER_INCH)); writer.addAttribute("x", MathUtils.formatDouble(1d * point.getX() / Constants.PIXELS_PER_INCH));
writer.addAttribute("y", Double.toString(1d * point.getY() / Constants.PIXELS_PER_INCH)); writer.addAttribute("y", MathUtils.formatDouble(1d * point.getY() / Constants.PIXELS_PER_INCH));
} }
@Override @Override
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
double x; double x;
double y; double y;
if (reader.hasMoreChildren()) { if (reader.hasMoreChildren()) {
reader.moveDown(); reader.moveDown();
x = Double.parseDouble(reader.getValue()); x = MathUtils.parseDouble(reader.getValue());
reader.moveUp(); reader.moveUp();
reader.moveDown(); reader.moveDown();
y = Double.parseDouble(reader.getValue()); y = MathUtils.parseDouble(reader.getValue());
reader.moveUp(); reader.moveUp();
return new Point2D.Double(x, y); return new Point2D.Double(x, y);
} else { } else {
x = Double.parseDouble(reader.getAttribute("x")); x = MathUtils.round(Double.parseDouble(reader.getAttribute("x")) * Constants.PIXELS_PER_INCH);
y = Double.parseDouble(reader.getAttribute("y")); y = MathUtils.round(Double.parseDouble(reader.getAttribute("y")) * Constants.PIXELS_PER_INCH);
return new Point2D.Double(x * Constants.PIXELS_PER_INCH, y * Constants.PIXELS_PER_INCH); return new Point2D.Double(x, y);
} }
} }
@@ -0,0 +1,37 @@
/*
DIY Layout Creator (DIYLC).
Copyright (c) 2009-2025 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.utils;
public class MathUtils {
public static String formatDouble(double value) {
return Double.toString(Math.round(value * 1e8) / 1e8);
}
public static Double round(double value) {
return Math.round(value * 1e8) / 1e8;
}
public static double parseDouble(String str) {
return Math.round(Double.parseDouble(str) * 1e8) / 1e8;
}
}
@@ -397,6 +397,10 @@
<changeType>NEW_FEATURE</changeType> <changeType>NEW_FEATURE</changeType>
<description>Detect the style of a treble bleed based on the topology and component values (e.g. Fender, DiMarzio, Kinman, etc)</description> <description>Detect the style of a treble bleed based on the topology and component values (e.g. Fender, DiMarzio, Kinman, etc)</description>
</org.diylc.appframework.update.Change> </org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Improved precision of rendering, in some cases there was a sub-pixel misalignment between the lines that should meet exactly</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change> <org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType> <changeType>BUG_FIX</changeType>
<description>Tone capacitor mistaken for treble bleed when connected to the input lug of the volume pot</description> <description>Tone capacitor mistaken for treble bleed when connected to the input lug of the volume pot</description>
@@ -1,173 +1,173 @@
/* /*
DIY Layout Creator (DIYLC). DIY Layout Creator (DIYLC).
Copyright (c) 2009-2025 held jointly by the individual authors. Copyright (c) 2009-2025 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 DIYLC is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
DIYLC is distributed in the hope that it will be useful, DIYLC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with DIYLC. If not, see <http://www.gnu.org/licenses/>. along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.diylc.testcomponents; package org.diylc.testcomponents;
import java.awt.Color; import java.awt.Color;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Point; import java.awt.Point;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import org.diylc.components.AbstractComponent; import org.diylc.components.AbstractComponent;
import org.diylc.core.ComponentState; import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent; import org.diylc.core.IDIYComponent;
import org.diylc.core.IDrawingObserver; import org.diylc.core.IDrawingObserver;
import org.diylc.core.Project; import org.diylc.core.Project;
import org.diylc.core.VisibilityPolicy; import org.diylc.core.VisibilityPolicy;
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.measures.Capacitance; import org.diylc.core.measures.Capacitance;
import org.diylc.core.measures.CapacitanceUnit; import org.diylc.core.measures.CapacitanceUnit;
import org.diylc.core.measures.Resistance; import org.diylc.core.measures.Resistance;
import org.diylc.core.measures.ResistanceUnit; import org.diylc.core.measures.ResistanceUnit;
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 = "Mock", author = "bancika", category = "Sample", instanceNamePrefix = "M", @ComponentDescriptor(name = "Mock", author = "bancika", category = "Sample", instanceNamePrefix = "M",
description = "test", zOrder = IDIYComponent.COMPONENT) description = "test", zOrder = IDIYComponent.COMPONENT)
public class MockDIYComponent extends AbstractComponent<Capacitance> { public class MockDIYComponent extends AbstractComponent<Capacitance> {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private String testField = "Hello World"; private String testField = "Hello World";
private Capacitance c = new Capacitance(100d, CapacitanceUnit.uF); private Capacitance c = new Capacitance(100d, CapacitanceUnit.uF);
private Resistance r = new Resistance(123d, ResistanceUnit.K); private Resistance r = new Resistance(123d, ResistanceUnit.K);
private Size s = new Size(1d, SizeUnit.cm); private Size s = new Size(1d, SizeUnit.cm);
private Color color = Color.green; private Color color = Color.green;
private Point2D leftTopCorner = new Point(0, 0); private Point2D leftTopCorner = new Point(0, 0);
private String name = "something"; private String name = "something";
public MockDIYComponent(String testField, Capacitance c, Resistance r, Size s, Color color, Point leftTopCorner) { public MockDIYComponent(String testField, Capacitance c, Resistance r, Size s, Color color, Point leftTopCorner) {
super(); super();
this.testField = testField; this.testField = testField;
this.c = c; this.c = c;
this.r = r; this.r = r;
this.s = s; this.s = s;
this.color = color; this.color = color;
this.leftTopCorner = leftTopCorner; this.leftTopCorner = leftTopCorner;
} }
public MockDIYComponent() { public MockDIYComponent() {
super(); super();
} }
@Override @Override
public boolean canControlPointOverlap(int index) { public boolean canControlPointOverlap(int index) {
return false; return false;
} }
@EditableProperty @EditableProperty
public String getName() { public String getName() {
return name; return name;
} }
public void setName(String name) { public void setName(String name) {
this.name = name; this.name = name;
} }
@Override @Override
public int getControlPointCount() { public int getControlPointCount() {
return 1; return 1;
} }
@Override @Override
public boolean isControlPointSticky(int index) { public boolean isControlPointSticky(int index) {
return false; return false;
} }
@Override @Override
public VisibilityPolicy getControlPointVisibilityPolicy(int index) { public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
return VisibilityPolicy.WHEN_SELECTED; return VisibilityPolicy.WHEN_SELECTED;
} }
@Override @Override
public Point2D getControlPoint(int index) { public Point2D getControlPoint(int index) {
return leftTopCorner; return leftTopCorner;
} }
@Override @Override
public void setControlPoint(Point2D point, int index) { public void setControlPoint(Point2D point, int index) {
leftTopCorner.setLocation(point); leftTopCorner.setLocation(point);
} }
@EditableProperty(name = "Test Field") @EditableProperty(name = "Test Field")
public String getTestField() { public String getTestField() {
return testField; return testField;
} }
public void setTestField(String testField) { public void setTestField(String testField) {
this.testField = testField; this.testField = testField;
} }
@EditableProperty(defaultable = true) @EditableProperty(defaultable = true)
public Capacitance getValue() { public Capacitance getValue() {
return c; return c;
} }
public void setValue(Capacitance c) { public void setValue(Capacitance c) {
this.c = c; this.c = c;
} }
@EditableProperty(defaultable = true) @EditableProperty(defaultable = true)
public Color getColor() { public Color getColor() {
return color; return color;
} }
public void setColor(Color color) { public void setColor(Color color) {
this.color = color; this.color = color;
} }
@EditableProperty @EditableProperty
public Resistance getR() { public Resistance getR() {
return r; return r;
} }
// Setter is commented out, ClassProcessor should ignore this property. // Setter is commented out, ClassProcessor should ignore this property.
// public void setR(Resistance r) { // public void setR(Resistance r) {
// this.r = r; // this.r = r;
// } // }
// No annotation, so this property should be ignored. // No annotation, so this property should be ignored.
public Size getS() { public Size getS() {
return s; return s;
} }
public void setS(Size s) { public void setS(Size s) {
this.s = s; this.s = s;
} }
@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.setColor(componentState.equals(ComponentState.SELECTED) ? color : color.darker()); g2d.setColor(componentState.equals(ComponentState.SELECTED) ? color : color.darker());
g2d.fillRect((int)leftTopCorner.getX(), (int)leftTopCorner.getY(), 200, 50); g2d.fillRect((int) Math.round(leftTopCorner.getX()), (int) Math.round(leftTopCorner.getY()), 200, 50);
} }
@Override @Override
public void drawIcon(Graphics2D g2d, int width, int height) { public void drawIcon(Graphics2D g2d, int width, int height) {
g2d.drawString("X", 10, 10); g2d.drawString("X", 10, 10);
} }
@Override @Override
public String getControlPointNodeName(int index) { public String getControlPointNodeName(int index) {
return null; return null;
} }
} }
@@ -90,7 +90,7 @@ public abstract class AbstractBoard extends AbstractTransparentComponent<String>
Composite oldComposite = applyAlpha(g2d, componentState); Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(boardColor); g2d.setColor(boardColor);
g2d.fillRect((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(finalSecondPoint.getX() - firstPoint.getX()), (int)(finalSecondPoint.getY() - firstPoint.getY())); g2d.fillRect((int) Math.round(firstPoint.getX()), (int) Math.round(firstPoint.getY()), (int)(finalSecondPoint.getX() - firstPoint.getX()), (int)(finalSecondPoint.getY() - firstPoint.getY()));
g2d.setComposite(oldComposite); g2d.setComposite(oldComposite);
// Do not track any changes that follow because the whole board has been // Do not track any changes that follow because the whole board has been
@@ -98,7 +98,7 @@ public abstract class AbstractBoard extends AbstractTransparentComponent<String>
drawingObserver.stopTracking(); drawingObserver.stopTracking();
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: borderColor); : borderColor);
g2d.drawRect((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(finalSecondPoint.getX() - firstPoint.getX()), (int)(finalSecondPoint.getY() - firstPoint.getY())); g2d.drawRect((int) Math.round(firstPoint.getX()), (int) Math.round(firstPoint.getY()), (int)(finalSecondPoint.getX() - firstPoint.getX()), (int)(finalSecondPoint.getY() - firstPoint.getY()));
} }
protected Point2D getFinalSecondPoint() { protected Point2D getFinalSecondPoint() {
@@ -178,7 +178,7 @@ public abstract class AbstractBoard extends AbstractTransparentComponent<String>
HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM); HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
if (getCoordinateDisplay() == CoordinateDisplay.Both_Sides) { if (getCoordinateDisplay() == CoordinateDisplay.Both_Sides) {
StringUtils.drawCenteredText(g2d, label, StringUtils.drawCenteredText(g2d, label,
x, (int) (finalSecondPoint.getY() - COORDINATE_FONT_SIZE), x, (int) Math.round(finalSecondPoint.getY() - COORDINATE_FONT_SIZE),
HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM); HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
} }
} }
@@ -73,9 +73,9 @@ public class BlankBoard extends AbstractBoard {
Composite oldComposite = applyAlpha(g2d, componentState); Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(boardColor); g2d.setColor(boardColor);
if (getType() == Type.SQUARE) if (getType() == Type.SQUARE)
g2d.fillRect((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(finalSecondPoint.getX() - firstPoint.getX()), (int)(finalSecondPoint.getY() - firstPoint.getY())); g2d.fillRect((int) Math.round(firstPoint.getX()), (int) Math.round(firstPoint.getY()), (int)(finalSecondPoint.getX() - firstPoint.getX()), (int)(finalSecondPoint.getY() - firstPoint.getY()));
else else
g2d.fillOval((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(finalSecondPoint.getX() - firstPoint.getX()), (int)(finalSecondPoint.getY() - firstPoint.getY())); g2d.fillOval((int) Math.round(firstPoint.getX()), (int) Math.round(firstPoint.getY()), (int)(finalSecondPoint.getX() - firstPoint.getX()), (int)(finalSecondPoint.getY() - firstPoint.getY()));
g2d.setComposite(oldComposite); g2d.setComposite(oldComposite);
// } // }
// Do not track any changes that follow because the whole board has been // Do not track any changes that follow because the whole board has been
@@ -84,9 +84,9 @@ public class BlankBoard extends AbstractBoard {
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: borderColor); : borderColor);
if (getType() == Type.SQUARE) if (getType() == Type.SQUARE)
g2d.drawRect((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(finalSecondPoint.getX() - firstPoint.getX()), (int)(finalSecondPoint.getY() - firstPoint.getY())); g2d.drawRect((int) Math.round(firstPoint.getX()), (int) Math.round(firstPoint.getY()), (int)(finalSecondPoint.getX() - firstPoint.getX()), (int)(finalSecondPoint.getY() - firstPoint.getY()));
else else
g2d.drawOval((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(finalSecondPoint.getX() - firstPoint.getX()), (int)(finalSecondPoint.getY() - firstPoint.getY())); g2d.drawOval((int) Math.round(firstPoint.getX()), (int) Math.round(firstPoint.getY()), (int)(finalSecondPoint.getX() - firstPoint.getX()), (int)(finalSecondPoint.getY() - firstPoint.getY()));
} }
@Override @Override
@@ -1,387 +1,387 @@
/* /*
DIY Layout Creator (DIYLC). DIY Layout Creator (DIYLC).
Copyright (c) 2009-2025 held jointly by the individual authors. Copyright (c) 2009-2025 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 DIYLC is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
DIYLC is distributed in the hope that it will be useful, DIYLC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with DIYLC. If not, see <http://www.gnu.org/licenses/>. along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.diylc.components.boards; package org.diylc.components.boards;
import java.awt.AlphaComposite; import java.awt.AlphaComposite;
import java.awt.Color; import java.awt.Color;
import java.awt.Composite; import java.awt.Composite;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Shape; import java.awt.Shape;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D; import java.awt.geom.RoundRectangle2D;
import org.diylc.awt.StringUtils; import org.diylc.awt.StringUtils;
import org.diylc.common.HorizontalAlignment; import org.diylc.common.HorizontalAlignment;
import org.diylc.common.ObjectCache; import org.diylc.common.ObjectCache;
import org.diylc.common.VerticalAlignment; import org.diylc.common.VerticalAlignment;
import org.diylc.components.transform.ProtoBoardTransformer; import org.diylc.components.transform.ProtoBoardTransformer;
import org.diylc.core.ComponentState; import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent; import org.diylc.core.IDIYComponent;
import org.diylc.core.IDrawingObserver; import org.diylc.core.IDrawingObserver;
import org.diylc.core.Project; import org.diylc.core.Project;
import org.diylc.core.VisibilityPolicy; import org.diylc.core.VisibilityPolicy;
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 = "Breadboard", category = "Boards", author = "Branislav Stojkovic", @ComponentDescriptor(name = "Breadboard", category = "Boards", author = "Branislav Stojkovic",
description = "Prototyping solderless breadboard", instanceNamePrefix = "BB", description = "Prototyping solderless breadboard", instanceNamePrefix = "BB",
zOrder = IDIYComponent.BOARD, bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, zOrder = IDIYComponent.BOARD, bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME,
keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, enableCache = true, transformer = ProtoBoardTransformer.class) keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, enableCache = true, transformer = ProtoBoardTransformer.class)
public class Breadboard extends AbstractProtoBoard { public class Breadboard extends AbstractProtoBoard {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public static Color FILL_COLOR = Color.white; public static Color FILL_COLOR = Color.white;
public static Color BORDER_COLOR = Color.black; public static Color BORDER_COLOR = Color.black;
public static Size BODY_ARC = new Size(3d, SizeUnit.mm); public static Size BODY_ARC = new Size(3d, SizeUnit.mm);
public static Size SPACING = new Size(0.1d, SizeUnit.in); public static Size SPACING = new Size(0.1d, SizeUnit.in);
public static Color SELECTION_COLOR = Color.red; public static Color SELECTION_COLOR = Color.red;
public static Color HOLE_COLOR = Color.decode("#EEEEEE"); public static Color HOLE_COLOR = Color.decode("#EEEEEE");
public static Color PLUS_COLOR = Color.red; public static Color PLUS_COLOR = Color.red;
public static Color MINUS_COLOR = Color.blue; public static Color MINUS_COLOR = Color.blue;
public static float COORDINATE_FONT_SIZE = 9f; public static float COORDINATE_FONT_SIZE = 9f;
public static Color COORDINATE_COLOR = Color.gray.brighter(); public static Color COORDINATE_COLOR = Color.gray.brighter();
public static Size HOLE_SIZE = new Size(1.5, SizeUnit.mm); public static Size HOLE_SIZE = new Size(1.5, SizeUnit.mm);
public static Size HOLE_ARC = new Size(1d, SizeUnit.mm); public static Size HOLE_ARC = new Size(1d, SizeUnit.mm);
protected Point2D point = new Point2D.Double(0, 0); protected Point2D point = new Point2D.Double(0, 0);
protected BreadboardSize breadboardSize; protected BreadboardSize breadboardSize;
protected PowerStripPosition powerStripPosition; protected PowerStripPosition powerStripPosition;
@SuppressWarnings("incomplete-switch") @SuppressWarnings("incomplete-switch")
@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) {
if (checkPointsClipped(g2d.getClip())) { if (checkPointsClipped(g2d.getClip())) {
return; return;
} }
// adjust the angle // adjust the angle
double theta = 0; double theta = 0;
switch (getOrientation()) { switch (getOrientation()) {
case _90: case _90:
theta = Math.PI / 2; theta = Math.PI / 2;
break; break;
case _180: case _180:
theta = Math.PI; theta = Math.PI;
break; break;
case _270: case _270:
theta = Math.PI * 3 / 2; theta = Math.PI * 3 / 2;
break; break;
} }
if (theta != 0) { if (theta != 0) {
g2d.rotate(theta, point.getX(), point.getY()); g2d.rotate(theta, point.getX(), point.getY());
} }
int bodyArc = (int) BODY_ARC.convertToPixels(); int bodyArc = (int) BODY_ARC.convertToPixels();
double spacing = SPACING.convertToPixels(); double spacing = SPACING.convertToPixels();
int holeCount = getBreadboardSize() == BreadboardSize.Full ? 63 : 30; int holeCount = getBreadboardSize() == BreadboardSize.Full ? 63 : 30;
// draw body // draw body
g2d.setColor(FILL_COLOR); g2d.setColor(FILL_COLOR);
int width = (int) (23 * SPACING.convertToPixels()); int width = (int) (23 * SPACING.convertToPixels());
int height = (int) ((holeCount + 1) * SPACING.convertToPixels()); int height = (int) ((holeCount + 1) * SPACING.convertToPixels());
Shape rect = new RoundRectangle2D.Double(point.getX(), point.getY(), width, height, bodyArc, bodyArc); Shape rect = new RoundRectangle2D.Double(point.getX(), point.getY(), width, height, bodyArc, bodyArc);
g2d.fill(rect); g2d.fill(rect);
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: BORDER_COLOR); : BORDER_COLOR);
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
g2d.draw(rect); g2d.draw(rect);
drawingObserver.stopTracking(); drawingObserver.stopTracking();
// draw lines // draw lines
g2d.setColor(PLUS_COLOR); g2d.setColor(PLUS_COLOR);
g2d.drawLine((int) (point.getX() + spacing), (int) (point.getY() + spacing), (int) (point.getX() + spacing), g2d.drawLine((int) Math.round(point.getX() + spacing), (int) Math.round(point.getY() + spacing), (int) Math.round(point.getX() + spacing),
(int) (point.getY() + holeCount * spacing)); (int) Math.round(point.getY() + holeCount * spacing));
g2d.drawLine((int) (point.getX() + 19 * spacing), (int) (point.getY() + spacing), (int) (point.getX() + 19 * spacing), g2d.drawLine((int) Math.round(point.getX() + 19 * spacing), (int) Math.round(point.getY() + spacing), (int) Math.round(point.getX() + 19 * spacing),
(int) (point.getY() + holeCount * spacing)); (int) Math.round(point.getY() + holeCount * spacing));
g2d.setColor(MINUS_COLOR); g2d.setColor(MINUS_COLOR);
g2d.drawLine((int) (point.getX() + 4 * spacing), (int) (point.getY() + spacing), (int) (point.getX() + 4 * spacing), g2d.drawLine((int) Math.round(point.getX() + 4 * spacing), (int) Math.round(point.getY() + spacing), (int) Math.round(point.getX() + 4 * spacing),
(int) (point.getY() + holeCount * spacing)); (int) Math.round(point.getY() + holeCount * spacing));
g2d.drawLine((int) (point.getX() + 22 * spacing), (int) (point.getY() + spacing), (int) (point.getX() + 22 * spacing), g2d.drawLine((int) Math.round(point.getX() + 22 * spacing), (int) Math.round(point.getY() + spacing), (int) Math.round(point.getX() + 22 * spacing),
(int) (point.getY() + holeCount * spacing)); (int) Math.round(point.getY() + holeCount * spacing));
int holeSize = getClosestOdd(HOLE_SIZE.convertToPixels()); int holeSize = getClosestOdd(HOLE_SIZE.convertToPixels());
int holeArc = (int) HOLE_ARC.convertToPixels(); int holeArc = (int) HOLE_ARC.convertToPixels();
g2d.setFont(LABEL_FONT.deriveFont(COORDINATE_FONT_SIZE)); g2d.setFont(LABEL_FONT.deriveFont(COORDINATE_FONT_SIZE));
byte a = "a".getBytes()[0]; byte a = "a".getBytes()[0];
// draw main holes // draw main holes
for (int section = 0; section <= 1; section++) { for (int section = 0; section <= 1; section++) {
double offset = section * 7 * spacing; double offset = section * 7 * spacing;
for (int y = 0; y < holeCount; y++) { for (int y = 0; y < holeCount; y++) {
g2d.setColor(COORDINATE_COLOR); g2d.setColor(COORDINATE_COLOR);
int coordinateX; int coordinateX;
if (section == 0) { if (section == 0) {
coordinateX = (int) (point.getX() + offset + 5.5 * spacing); coordinateX = (int) Math.round(point.getX() + offset + 5.5 * spacing);
} else { } else {
coordinateX = (int) (point.getX() + offset + 10.5 * spacing); coordinateX = (int) Math.round(point.getX() + offset + 10.5 * spacing);
} }
StringUtils.drawCenteredText(g2d, String.valueOf(y + 1), coordinateX, (int) (point.getY() + (y + 1) * spacing), StringUtils.drawCenteredText(g2d, String.valueOf(y + 1), coordinateX, (int) (point.getY() + (y + 1) * spacing),
section == 0 ? HorizontalAlignment.RIGHT : HorizontalAlignment.LEFT, VerticalAlignment.CENTER); section == 0 ? HorizontalAlignment.RIGHT : HorizontalAlignment.LEFT, VerticalAlignment.CENTER);
for (int x = 0; x < 5; x++) { for (int x = 0; x < 5; x++) {
int holeX = (int) (point.getX() + offset + (x + 6) * spacing); int holeX = (int) (point.getX() + offset + (x + 6) * spacing);
int holeY = (int) (point.getY() + (y + 1) * spacing); int holeY = (int) (point.getY() + (y + 1) * spacing);
g2d.setColor(HOLE_COLOR); g2d.setColor(HOLE_COLOR);
g2d.fillRoundRect(holeX - holeSize / 2, holeY - holeSize / 2, holeSize, holeSize, holeArc, holeArc); g2d.fillRoundRect(holeX - holeSize / 2, holeY - holeSize / 2, holeSize, holeSize, holeArc, holeArc);
g2d.setColor(BORDER_COLOR); g2d.setColor(BORDER_COLOR);
g2d.drawRoundRect(holeX - holeSize / 2, holeY - holeSize / 2, holeSize, holeSize, holeArc, holeArc); g2d.drawRoundRect(holeX - holeSize / 2, holeY - holeSize / 2, holeSize, holeSize, holeArc, holeArc);
// Draw horizontal labels // Draw horizontal labels
if (y == 0) { if (y == 0) {
g2d.setColor(COORDINATE_COLOR); g2d.setColor(COORDINATE_COLOR);
StringUtils.drawCenteredText(g2d, new String(new byte[] {(byte) (a + x + 5 * section)}), holeX, (int) (point.getY() + COORDINATE_FONT_SIZE), StringUtils.drawCenteredText(g2d, new String(new byte[] {(byte) (a + x + 5 * section)}), holeX, (int) Math.round(point.getY() + COORDINATE_FONT_SIZE),
HorizontalAlignment.CENTER, VerticalAlignment.TOP); HorizontalAlignment.CENTER, VerticalAlignment.TOP);
StringUtils.drawCenteredText(g2d, new String(new byte[] {(byte) (a + x + 5 * section)}), holeX, (int) (point.getY() StringUtils.drawCenteredText(g2d, new String(new byte[] {(byte) (a + x + 5 * section)}), holeX, (int) Math.round(point.getY()
+ spacing * 31 - COORDINATE_FONT_SIZE / 2), HorizontalAlignment.CENTER, VerticalAlignment.TOP); + spacing * 31 - COORDINATE_FONT_SIZE / 2), HorizontalAlignment.CENTER, VerticalAlignment.TOP);
} }
} }
} }
} }
double powerOffset = double powerOffset =
getPowerStripPosition() == PowerStripPosition.Inline ? (getBreadboardSize() == BreadboardSize.Full ? 2d : 1d) getPowerStripPosition() == PowerStripPosition.Inline ? (getBreadboardSize() == BreadboardSize.Full ? 2d : 1d)
: (getBreadboardSize() == BreadboardSize.Full ? 1.5d : 0.5d); : (getBreadboardSize() == BreadboardSize.Full ? 1.5d : 0.5d);
int psHoleCount = Math.round(holeCount / 10f) * 10; int psHoleCount = Math.round(holeCount / 10f) * 10;
// draw power strip holes // draw power strip holes
for (int section = 0; section <= 1; section++) { for (int section = 0; section <= 1; section++) {
double offset = section * 18 * spacing; double offset = section * 18 * spacing;
for (int y = 0; y < psHoleCount - 1; y++) { for (int y = 0; y < psHoleCount - 1; y++) {
for (int x = 0; x < 2; x++) { for (int x = 0; x < 2; x++) {
if ((y + 1) % 6 == 0) if ((y + 1) % 6 == 0)
continue; continue;
int holeX = (int) (point.getX() + offset + (x + 2) * spacing); int holeX = (int) (point.getX() + offset + (x + 2) * spacing);
int holeY = (int) (point.getY() + (y + 1 + powerOffset) * spacing); int holeY = (int) (point.getY() + (y + 1 + powerOffset) * spacing);
g2d.setColor(HOLE_COLOR); g2d.setColor(HOLE_COLOR);
g2d.fillRoundRect(holeX - holeSize / 2, holeY - holeSize / 2, holeSize, holeSize, holeArc, holeArc); g2d.fillRoundRect(holeX - holeSize / 2, holeY - holeSize / 2, holeSize, holeSize, holeArc, holeArc);
g2d.setColor(BORDER_COLOR); g2d.setColor(BORDER_COLOR);
g2d.drawRoundRect(holeX - holeSize / 2, holeY - holeSize / 2, holeSize, holeSize, holeArc, holeArc); g2d.drawRoundRect(holeX - holeSize / 2, holeY - holeSize / 2, holeSize, holeSize, holeArc, holeArc);
} }
} }
} }
// draw transparent connections just to designate connections // draw transparent connections just to designate connections
drawingObserver.startTrackingContinuityArea(true); drawingObserver.startTrackingContinuityArea(true);
Composite oldComposite = g2d.getComposite(); Composite oldComposite = g2d.getComposite();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.0f)); g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.0f));
for (int section = 0; section <= 1; section++) { for (int section = 0; section <= 1; section++) {
double offset = section * 18 * spacing; double offset = section * 18 * spacing;
for (int x = 0; x < 2; x++) { for (int x = 0; x < 2; x++) {
int holeX = (int) (point.getX() + offset + (x + 2) * spacing); int holeX = (int) (point.getX() + offset + (x + 2) * spacing);
int holeY1 = (int) (point.getY() + (1 + powerOffset) * spacing); int holeY1 = (int) (point.getY() + (1 + powerOffset) * spacing);
int holeY2 = (int) (point.getY() + (psHoleCount -1 + powerOffset) * spacing); int holeY2 = (int) (point.getY() + (psHoleCount -1 + powerOffset) * spacing);
g2d.setColor(HOLE_COLOR); g2d.setColor(HOLE_COLOR);
g2d.fillRoundRect(holeX - holeSize / 2, holeY1 - holeSize / 2, holeSize, holeSize + holeY2 - holeY1, holeArc, holeArc); g2d.fillRoundRect(holeX - holeSize / 2, holeY1 - holeSize / 2, holeSize, holeSize + holeY2 - holeY1, holeArc, holeArc);
} }
} }
for (int section = 0; section <= 1; section++) { for (int section = 0; section <= 1; section++) {
double offset = section * 7 * spacing; double offset = section * 7 * spacing;
for (int y = 0; y < holeCount; y++) { for (int y = 0; y < holeCount; y++) {
g2d.setColor(COORDINATE_COLOR); g2d.setColor(COORDINATE_COLOR);
int coordinateX; int coordinateX;
if (section == 0) { if (section == 0) {
coordinateX = (int) (point.getX() + offset + 5.5 * spacing); coordinateX = (int) Math.round(point.getX() + offset + 5.5 * spacing);
} else { } else {
coordinateX = (int) (point.getX() + offset + 10.5 * spacing); coordinateX = (int) Math.round(point.getX() + offset + 10.5 * spacing);
} }
StringUtils.drawCenteredText(g2d, String.valueOf(y + 1), coordinateX, (int) (point.getY() + (y + 1) * spacing), StringUtils.drawCenteredText(g2d, String.valueOf(y + 1), coordinateX, (int) (point.getY() + (y + 1) * spacing),
section == 0 ? HorizontalAlignment.RIGHT : HorizontalAlignment.LEFT, VerticalAlignment.CENTER); section == 0 ? HorizontalAlignment.RIGHT : HorizontalAlignment.LEFT, VerticalAlignment.CENTER);
// for (int x = 0; x < 5; x++) { // for (int x = 0; x < 5; x++) {
int holeX1 = (int) (point.getX() + offset + 6 * spacing); int holeX1 = (int) Math.round(point.getX() + offset + 6 * spacing);
int holeX2 = (int) (point.getX() + offset + 10 * spacing); int holeX2 = (int) Math.round(point.getX() + offset + 10 * spacing);
int holeY = (int) (point.getY() + (y + 1) * spacing); int holeY = (int) (point.getY() + (y + 1) * spacing);
g2d.setColor(HOLE_COLOR); g2d.setColor(HOLE_COLOR);
g2d.fillRoundRect(holeX1 - holeSize / 2, holeY - holeSize / 2, holeSize + holeX2 - holeX1, holeSize, holeArc, holeArc); g2d.fillRoundRect(holeX1 - holeSize / 2, holeY - holeSize / 2, holeSize + holeX2 - holeX1, holeSize, holeArc, holeArc);
// } // }
} }
// } // }
} }
g2d.setComposite(oldComposite); g2d.setComposite(oldComposite);
drawingObserver.stopTrackingContinuityArea(); drawingObserver.stopTrackingContinuityArea();
} }
@Override @Override
public void drawIcon(Graphics2D g2d, int width, int height) { public void drawIcon(Graphics2D g2d, int width, int height) {
int factor = 32 / width; int factor = 32 / width;
int arc = 4 / factor; int arc = 4 / factor;
g2d.setColor(FILL_COLOR); g2d.setColor(FILL_COLOR);
g2d.fillRect(2 / factor, 2 / factor, width - 4 / factor, height - 4 / factor); g2d.fillRect(2 / factor, 2 / factor, width - 4 / factor, height - 4 / factor);
g2d.setColor(BORDER_COLOR); g2d.setColor(BORDER_COLOR);
g2d.drawRect(2 / factor, 2 / factor, width - 4 / factor, height - 4 / factor); g2d.drawRect(2 / factor, 2 / factor, width - 4 / factor, height - 4 / factor);
g2d.setColor(HOLE_COLOR); g2d.setColor(HOLE_COLOR);
g2d.fillRoundRect(width / 3 - 2 / factor, width / 3 - 2 / factor, getClosestOdd(5.0 / factor), g2d.fillRoundRect(width / 3 - 2 / factor, width / 3 - 2 / factor, getClosestOdd(5.0 / factor),
getClosestOdd(5.0 / factor), arc, arc); getClosestOdd(5.0 / factor), arc, arc);
g2d.setColor(BORDER_COLOR); g2d.setColor(BORDER_COLOR);
g2d.drawRoundRect(width / 3 - 2 / factor, width / 3 - 2 / factor, getClosestOdd(5.0 / factor), g2d.drawRoundRect(width / 3 - 2 / factor, width / 3 - 2 / factor, getClosestOdd(5.0 / factor),
getClosestOdd(5.0 / factor), arc, arc); getClosestOdd(5.0 / factor), arc, arc);
g2d.setColor(HOLE_COLOR); g2d.setColor(HOLE_COLOR);
g2d.fillRoundRect(2 * width / 3 - 2 / factor, width / 3 - 2 / factor, getClosestOdd(5.0 / factor), g2d.fillRoundRect(2 * width / 3 - 2 / factor, width / 3 - 2 / factor, getClosestOdd(5.0 / factor),
getClosestOdd(5.0 / factor), arc, arc); getClosestOdd(5.0 / factor), arc, arc);
g2d.setColor(BORDER_COLOR); g2d.setColor(BORDER_COLOR);
g2d.drawRoundRect(2 * width / 3 - 2 / factor, width / 3 - 2 / factor, getClosestOdd(5.0 / factor), g2d.drawRoundRect(2 * width / 3 - 2 / factor, width / 3 - 2 / factor, getClosestOdd(5.0 / factor),
getClosestOdd(5.0 / factor), arc, arc); getClosestOdd(5.0 / factor), arc, arc);
g2d.setColor(HOLE_COLOR); g2d.setColor(HOLE_COLOR);
g2d.fillRoundRect(width / 3 - 2 / factor, 2 * width / 3 - 2 / factor, getClosestOdd(5.0 / factor), g2d.fillRoundRect(width / 3 - 2 / factor, 2 * width / 3 - 2 / factor, getClosestOdd(5.0 / factor),
getClosestOdd(5.0 / factor), arc, arc); getClosestOdd(5.0 / factor), arc, arc);
g2d.setColor(BORDER_COLOR); g2d.setColor(BORDER_COLOR);
g2d.drawRoundRect(width / 3 - 2 / factor, 2 * width / 3 - 2 / factor, getClosestOdd(5.0 / factor), g2d.drawRoundRect(width / 3 - 2 / factor, 2 * width / 3 - 2 / factor, getClosestOdd(5.0 / factor),
getClosestOdd(5.0 / factor), arc, arc); getClosestOdd(5.0 / factor), arc, arc);
g2d.setColor(HOLE_COLOR); g2d.setColor(HOLE_COLOR);
g2d.fillRoundRect(2 * width / 3 - 2 / factor, 2 * width / 3 - 2 / factor, getClosestOdd(5.0 / factor), g2d.fillRoundRect(2 * width / 3 - 2 / factor, 2 * width / 3 - 2 / factor, getClosestOdd(5.0 / factor),
getClosestOdd(5.0 / factor), arc, arc); getClosestOdd(5.0 / factor), arc, arc);
g2d.setColor(BORDER_COLOR); g2d.setColor(BORDER_COLOR);
g2d.drawRoundRect(2 * width / 3 - 2 / factor, 2 * width / 3 - 2 / factor, getClosestOdd(5.0 / factor), g2d.drawRoundRect(2 * width / 3 - 2 / factor, 2 * width / 3 - 2 / factor, getClosestOdd(5.0 / factor),
getClosestOdd(5.0 / factor), arc, arc); getClosestOdd(5.0 / factor), arc, arc);
g2d.setColor(MINUS_COLOR); g2d.setColor(MINUS_COLOR);
g2d.drawLine(width / 2, 2 / factor, width / 2, height - 4 / factor); g2d.drawLine(width / 2, 2 / factor, width / 2, height - 4 / factor);
} }
@EditableProperty(name = "Size") @EditableProperty(name = "Size")
public BreadboardSize getBreadboardSize() { public BreadboardSize getBreadboardSize() {
if (breadboardSize == null) if (breadboardSize == null)
breadboardSize = BreadboardSize.Half; breadboardSize = BreadboardSize.Half;
return breadboardSize; return breadboardSize;
} }
public void setBreadboardSize(BreadboardSize breadboardSize) { public void setBreadboardSize(BreadboardSize breadboardSize) {
this.breadboardSize = breadboardSize; this.breadboardSize = breadboardSize;
} }
@EditableProperty(name = "Power Strip") @EditableProperty(name = "Power Strip")
public PowerStripPosition getPowerStripPosition() { public PowerStripPosition getPowerStripPosition() {
if (powerStripPosition == null) if (powerStripPosition == null)
powerStripPosition = PowerStripPosition.Inline; powerStripPosition = PowerStripPosition.Inline;
return powerStripPosition; return powerStripPosition;
} }
public void setPowerStripPosition(PowerStripPosition powerStripPosition) { public void setPowerStripPosition(PowerStripPosition powerStripPosition) {
this.powerStripPosition = powerStripPosition; this.powerStripPosition = powerStripPosition;
} }
@Override @Override
public int getControlPointCount() { public int getControlPointCount() {
return 2; return 2;
} }
@Override @Override
public boolean canPointMoveFreely(int pointIndex) { public boolean canPointMoveFreely(int pointIndex) {
return false; return false;
} }
@SuppressWarnings("incomplete-switch") @SuppressWarnings("incomplete-switch")
@Override @Override
public Point2D getControlPoint(int index) { public Point2D getControlPoint(int index) {
if (index == 0) if (index == 0)
return point; return point;
// create a synthetic second control point for clipping check and to make sure that we cannot drag the right side of the board off the screen // create a synthetic second control point for clipping check and to make sure that we cannot drag the right side of the board off the screen
double spacing = SPACING.convertToPixels(); double spacing = SPACING.convertToPixels();
int holeCount = getBreadboardSize() == BreadboardSize.Full ? 63 : 30; int holeCount = getBreadboardSize() == BreadboardSize.Full ? 63 : 30;
// adjust the angle // adjust the angle
double theta = 0; double theta = 0;
switch (getOrientation()) { switch (getOrientation()) {
case _90: case _90:
theta = Math.PI / 2; theta = Math.PI / 2;
break; break;
case _180: case _180:
theta = Math.PI; theta = Math.PI;
break; break;
case _270: case _270:
theta = Math.PI * 3 / 2; theta = Math.PI * 3 / 2;
break; break;
} }
Point2D secondPoint = new Point2D.Double(point.getX() + 23 * spacing, point.getY() + (holeCount + 1) * spacing); Point2D secondPoint = new Point2D.Double(point.getX() + 23 * spacing, point.getY() + (holeCount + 1) * spacing);
if (theta != 0) { if (theta != 0) {
AffineTransform tx = AffineTransform.getRotateInstance(theta, point.getX(), point.getY()); AffineTransform tx = AffineTransform.getRotateInstance(theta, point.getX(), point.getY());
tx.transform(secondPoint, secondPoint); tx.transform(secondPoint, secondPoint);
} }
return secondPoint; return secondPoint;
} }
@Override @Override
public boolean isControlPointSticky(int index) { public boolean isControlPointSticky(int index) {
return false; return false;
} }
@Override @Override
public VisibilityPolicy getControlPointVisibilityPolicy(int index) { public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
return VisibilityPolicy.NEVER; return VisibilityPolicy.NEVER;
} }
@Override @Override
public void setControlPoint(Point2D point, int index) { public void setControlPoint(Point2D point, int index) {
if (index == 0) if (index == 0)
this.point.setLocation(point); this.point.setLocation(point);
} }
@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 String getControlPointNodeName(int index) { public String getControlPointNodeName(int index) {
return null; return null;
} }
@Override @Override
public Rectangle2D getCachingBounds() { public Rectangle2D getCachingBounds() {
Point2D finalSecondPoint = getControlPoint(1); Point2D finalSecondPoint = getControlPoint(1);
return new Rectangle2D.Double(Math.min(point.getX(), finalSecondPoint.getX()) - 2, Math.min(point.getY(), finalSecondPoint.getY()) - 2, return new Rectangle2D.Double(Math.min(point.getX(), finalSecondPoint.getX()) - 2, Math.min(point.getY(), finalSecondPoint.getY()) - 2,
Math.abs(finalSecondPoint.getX() - point.getX()) + 4, Math.abs(finalSecondPoint.getY() - point.getY()) + 4); Math.abs(finalSecondPoint.getX() - point.getX()) + 4, Math.abs(finalSecondPoint.getY() - point.getY()) + 4);
} }
public enum BreadboardSize { public enum BreadboardSize {
Half, Full Half, Full
} }
public enum PowerStripPosition { public enum PowerStripPosition {
Inline, Offset Inline, Offset
} }
} }
@@ -329,9 +329,9 @@ public class EurorackStripboard extends AbstractProtoBoard {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(padSize / 4)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(padSize / 4));
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
for (Point2D[] trace : potTraces) { for (Point2D[] trace : potTraces) {
int padX1 = (int) (x0 + trace[0].getX() * spacing); int padX1 = (int) Math.round(x0 + trace[0].getX() * spacing);
int padY1 = (int) (y0 + (trace[0].getY() + 8 * i) * spacing); int padY1 = (int) (y0 + (trace[0].getY() + 8 * i) * spacing);
int padX2 = (int) (x0 + trace[1].getX() * spacing); int padX2 = (int) Math.round(x0 + trace[1].getX() * spacing);
int padY2 = (int) (y0 + (trace[1].getY() + 8 * i) * spacing); int padY2 = (int) (y0 + (trace[1].getY() + 8 * i) * spacing);
g2d.drawLine(padX1, padY1, padX2, padY2); g2d.drawLine(padX1, padY1, padX2, padY2);
} }
@@ -225,12 +225,12 @@ public class ProtoBoard extends AbstractProtoBoard {
g2d.setColor(traceColor); g2d.setColor(traceColor);
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(padSize / 4)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(padSize / 4));
drawingObserver.startTrackingContinuityArea(true); drawingObserver.startTrackingContinuityArea(true);
g2d.drawLine((int) (point.getX() + (1 + SEGMENTS_SUM[3] + 0.5) * spacing), (int) (point.getY() + 1 * spacing), g2d.drawLine((int) (point.getX() + (1 + SEGMENTS_SUM[3] + 0.5) * spacing), (int) Math.round(point.getY() + 1 * spacing),
(int) (point.getX() + (1 + SEGMENTS_SUM[3] + 0.5) * spacing), (int) (point.getY() + 3.5 * spacing)); (int) (point.getX() + (1 + SEGMENTS_SUM[3] + 0.5) * spacing), (int) Math.round(point.getY() + 3.5 * spacing));
g2d.drawLine((int) (point.getX() + (1 + SEGMENTS_SUM[3] + 1.5) * spacing + miniPadSize / 2), (int) (point.getY() + 1 * spacing), g2d.drawLine((int) (point.getX() + (1 + SEGMENTS_SUM[3] + 1.5) * spacing + miniPadSize / 2), (int) Math.round(point.getY() + 1 * spacing),
(int) (point.getX() + (1 + SEGMENTS_SUM[3] + 1.5) * spacing + miniPadSize / 2), (int) (point.getY() + 3.5 * spacing)); (int) (point.getX() + (1 + SEGMENTS_SUM[3] + 1.5) * spacing + miniPadSize / 2), (int) Math.round(point.getY() + 3.5 * spacing));
g2d.drawLine((int) (point.getX() + (1 + SEGMENTS_SUM[3] + 2.5) * spacing), (int) (point.getY() + 1 * spacing), g2d.drawLine((int) (point.getX() + (1 + SEGMENTS_SUM[3] + 2.5) * spacing), (int) Math.round(point.getY() + 1 * spacing),
(int) (point.getX() + (1 + SEGMENTS_SUM[3] + 2.5) * spacing), (int) (point.getY() + 3.5 * spacing)); (int) (point.getX() + (1 + SEGMENTS_SUM[3] + 2.5) * spacing), (int) Math.round(point.getY() + 3.5 * spacing));
drawingObserver.stopTrackingContinuityArea(); drawingObserver.stopTrackingContinuityArea();
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
@@ -335,12 +335,12 @@ public class ProtoBoard extends AbstractProtoBoard {
g2d.setColor(SEPARATOR_COLOR); g2d.setColor(SEPARATOR_COLOR);
g2d.draw(new Rectangle2D.Double(point.getX() + width - 5.5 * spacing, point.getY() + 2, 5 * spacing, 2 * spacing)); g2d.draw(new Rectangle2D.Double(point.getX() + width - 5.5 * spacing, point.getY() + 2, 5 * spacing, 2 * spacing));
g2d.drawLine((int) (point.getX() + width - 5.5 * spacing), (int) (point.getY() + 2 * spacing) + 8, g2d.drawLine((int) Math.round(point.getX() + width - 5.5 * spacing), (int) Math.round(point.getY() + 2 * spacing) + 8,
(int) (point.getX() + width - 5.5 * spacing), (int) (point.getY() + 3.5 * spacing)); (int) Math.round(point.getX() + width - 5.5 * spacing), (int) Math.round(point.getY() + 3.5 * spacing));
g2d.drawLine((int) (point.getX() + width - 4.5 * spacing), (int) (point.getY() + 2 * spacing + 8), g2d.drawLine((int) Math.round(point.getX() + width - 4.5 * spacing), (int) Math.round(point.getY() + 2 * spacing + 8),
(int) (point.getX() + width - 4.5 * spacing), (int) (point.getY() + 3.5 * spacing)); (int) Math.round(point.getX() + width - 4.5 * spacing), (int) Math.round(point.getY() + 3.5 * spacing));
g2d.drawLine((int) (point.getX() + width - 1.5 * spacing), (int) (point.getY() + 2 * spacing + 8), g2d.drawLine((int) Math.round(point.getX() + width - 1.5 * spacing), (int) Math.round(point.getY() + 2 * spacing + 8),
(int) (point.getX() + width - 1.5 * spacing), (int) (point.getY() + 3.5 * spacing)); (int) Math.round(point.getX() + width - 1.5 * spacing), (int) Math.round(point.getY() + 3.5 * spacing));
g2d.setColor(traceColor); g2d.setColor(traceColor);
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(padSize / 4)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(padSize / 4));
@@ -348,8 +348,8 @@ public class ProtoBoard extends AbstractProtoBoard {
drawingObserver.startTrackingContinuityArea(true); drawingObserver.startTrackingContinuityArea(true);
// Draw two horizontal traces in the top-right section // Draw two horizontal traces in the top-right section
g2d.drawLine((int) (point.getX() + width - 4 * spacing), (int) (point.getY() + 0.5 * spacing), (int) (point.getX() + width - (2) * spacing), (int) (point.getY() + 0.5 * spacing)); g2d.drawLine((int) Math.round(point.getX() + width - 4 * spacing), (int) Math.round(point.getY() + 0.5 * spacing), (int) (point.getX() + width - (2) * spacing), (int) Math.round(point.getY() + 0.5 * spacing));
g2d.drawLine((int) (point.getX() + width - 4 * spacing), (int) (point.getY() + 1.5 * spacing), (int) (point.getX() + width - (2) * spacing), (int) (point.getY() + 1.5 * spacing)); g2d.drawLine((int) Math.round(point.getX() + width - 4 * spacing), (int) Math.round(point.getY() + 1.5 * spacing), (int) (point.getX() + width - (2) * spacing), (int) Math.round(point.getY() + 1.5 * spacing));
// Draw top-right pads // Draw top-right pads
for (int x = 0; x < 6; x++) { for (int x = 0; x < 6; x++) {
@@ -357,7 +357,7 @@ public class ProtoBoard extends AbstractProtoBoard {
g2d.setColor(traceColor); g2d.setColor(traceColor);
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(padSize / 4)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(padSize / 4));
g2d.drawLine(padX, (int) (point.getY() + 0.5 * spacing), padX, (int) (point.getY() + 3 * spacing)); g2d.drawLine(padX, (int) Math.round(point.getY() + 0.5 * spacing), padX, (int) Math.round(point.getY() + 3 * spacing));
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
@@ -433,22 +433,22 @@ public class ProtoBoard extends AbstractProtoBoard {
g2d.setColor(textColor); g2d.setColor(textColor);
// Draw top labels // Draw top labels
StringUtils.drawCenteredText(g2d, "+5V", (int) (point.getX() + (1 + SEGMENTS_SUM[3] - 0.3) * spacing), (int) (point.getY() + 1 * spacing) + 1, StringUtils.drawCenteredText(g2d, "+5V", (int) (point.getX() + (1 + SEGMENTS_SUM[3] - 0.3) * spacing), (int) Math.round(point.getY() + 1 * spacing) + 1,
HorizontalAlignment.RIGHT, VerticalAlignment.CENTER); HorizontalAlignment.RIGHT, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, "+12V", (int) (point.getX() + (1 + SEGMENTS_SUM[3] - 0.3) * spacing), (int) (point.getY() + 1.5 * spacing) + 1, StringUtils.drawCenteredText(g2d, "+12V", (int) (point.getX() + (1 + SEGMENTS_SUM[3] - 0.3) * spacing), (int) Math.round(point.getY() + 1.5 * spacing) + 1,
HorizontalAlignment.RIGHT, VerticalAlignment.CENTER); HorizontalAlignment.RIGHT, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, "GND", (int) (point.getX() + (1 + SEGMENTS_SUM[3] - 0.3) * spacing), (int) (point.getY() + 2 * spacing) + 1, StringUtils.drawCenteredText(g2d, "GND", (int) (point.getX() + (1 + SEGMENTS_SUM[3] - 0.3) * spacing), (int) Math.round(point.getY() + 2 * spacing) + 1,
HorizontalAlignment.RIGHT, VerticalAlignment.CENTER); HorizontalAlignment.RIGHT, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, "-12V", (int) (point.getX() + (1 + SEGMENTS_SUM[3] - 0.3) * spacing), (int) (point.getY() + 2.5 * spacing) + 1, StringUtils.drawCenteredText(g2d, "-12V", (int) (point.getX() + (1 + SEGMENTS_SUM[3] - 0.3) * spacing), (int) Math.round(point.getY() + 2.5 * spacing) + 1,
HorizontalAlignment.RIGHT, VerticalAlignment.CENTER); HorizontalAlignment.RIGHT, VerticalAlignment.CENTER);
// Draw top-right labels // Draw top-right labels
int labelY = (int) (point.getY() + 3.8 * spacing) + 1; int labelY = (int) Math.round(point.getY() + 3.8 * spacing) + 1;
StringUtils.drawCenteredText(g2d, "+5V", (int) (point.getX() + width - 6 * spacing), labelY, HorizontalAlignment.CENTER, VerticalAlignment.TOP); StringUtils.drawCenteredText(g2d, "+5V", (int) Math.round(point.getX() + width - 6 * spacing), labelY, HorizontalAlignment.CENTER, VerticalAlignment.TOP);
StringUtils.drawCenteredText(g2d, "+", (int) (point.getX() + width - 5 * spacing) - 6, labelY, HorizontalAlignment.CENTER, VerticalAlignment.TOP); StringUtils.drawCenteredText(g2d, "+", (int) Math.round(point.getX() + width - 5 * spacing) - 6, labelY, HorizontalAlignment.CENTER, VerticalAlignment.TOP);
StringUtils.drawCenteredText(g2d, " 12V", (int) (point.getX() + width - 5 * spacing) + 2, labelY, HorizontalAlignment.CENTER, VerticalAlignment.TOP); StringUtils.drawCenteredText(g2d, " 12V", (int) Math.round(point.getX() + width - 5 * spacing) + 2, labelY, HorizontalAlignment.CENTER, VerticalAlignment.TOP);
StringUtils.drawCenteredText(g2d, "GND", (int) (point.getX() + width - 3 * spacing), labelY, HorizontalAlignment.CENTER, VerticalAlignment.TOP); StringUtils.drawCenteredText(g2d, "GND", (int) Math.round(point.getX() + width - 3 * spacing), labelY, HorizontalAlignment.CENTER, VerticalAlignment.TOP);
StringUtils.drawCenteredText(g2d, "-12V", (int) (point.getX() + width - 1 * spacing), labelY, HorizontalAlignment.CENTER, VerticalAlignment.TOP); StringUtils.drawCenteredText(g2d, "-12V", (int) Math.round(point.getX() + width - 1 * spacing), labelY, HorizontalAlignment.CENTER, VerticalAlignment.TOP);
// Draw vertical labels // Draw vertical labels
byte A = "A".getBytes()[0]; byte A = "A".getBytes()[0];
@@ -460,14 +460,14 @@ public class ProtoBoard extends AbstractProtoBoard {
label = new String(new byte[] {(byte) (a + y - 26)}); label = new String(new byte[] {(byte) (a + y - 26)});
else else
label = new String(new byte[] {(byte) (A + y)}); label = new String(new byte[] {(byte) (A + y)});
StringUtils.drawCenteredText(g2d, label, (int) (point.getX() + spacing * 0.35), padY, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); StringUtils.drawCenteredText(g2d, label, (int) Math.round(point.getX() + spacing * 0.35), padY, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, label, (int) (point.getX() + width - spacing * 0.35), padY, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); StringUtils.drawCenteredText(g2d, label, (int) Math.round(point.getX() + width - spacing * 0.35), padY, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
} }
g2d.setColor(textColor); g2d.setColor(textColor);
g2d.setFont(LABEL_FONT.deriveFont(COORDINATE_FONT_SIZE + 2)); g2d.setFont(LABEL_FONT.deriveFont(COORDINATE_FONT_SIZE + 2));
StringUtils.drawCenteredText(g2d, "P-0+o by:\nKristian Bl�sol 2019", (int) (point.getX() + width * 0.70d), (int) (point.getY() + (yOffset + ROW_COUNT + 0.9) * spacing), StringUtils.drawCenteredText(g2d, "P-0+o by:\nKristian Bl�sol 2019", (int) Math.round(point.getX() + width * 0.70d), (int) (point.getY() + (yOffset + ROW_COUNT + 0.9) * spacing),
HorizontalAlignment.LEFT, VerticalAlignment.TOP); HorizontalAlignment.LEFT, VerticalAlignment.TOP);
// draw central mini pads // draw central mini pads
@@ -150,14 +150,14 @@ public class ProtoBoard780 extends AbstractProtoBoard {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(padSize - 2f)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(padSize - 2f));
g2d.setColor(traceColor); g2d.setColor(traceColor);
int padX = (int) (point.getX() + width / 2 - 7 * spacing + i * spacing); int padX = (int) Math.round(point.getX() + width / 2 - 7 * spacing + i * spacing);
drawingObserver.startTrackingContinuityArea(true); drawingObserver.startTrackingContinuityArea(true);
g2d.drawLine(padX, (int) (point.getY() + offsetY), padX, g2d.drawLine(padX, (int) Math.round(point.getY() + offsetY), padX,
(int) (point.getY() + spacing + offsetY)); (int) Math.round(point.getY() + spacing + offsetY));
drawingObserver.stopTrackingContinuityArea(); drawingObserver.stopTrackingContinuityArea();
for (int j = 0; j < 2; j++) { for (int j = 0; j < 2; j++) {
int padY = (int) (point.getY() + spacing * j + offsetY); int padY = (int) Math.round(point.getY() + spacing * j + offsetY);
g2d.setColor(padColor); g2d.setColor(padColor);
@@ -180,8 +180,8 @@ public class ProtoBoard780 extends AbstractProtoBoard {
g2d.setColor(textColor); g2d.setColor(textColor);
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
int x = i == 0 ? 1 : i * 5; int x = i == 0 ? 1 : i * 5;
int padX = (int) (point.getX() + width / 2 - 8 * spacing + x * spacing); int padX = (int) Math.round(point.getX() + width / 2 - 8 * spacing + x * spacing);
int padY = (int) (point.getY() + spacing * 2); int padY = (int) Math.round(point.getY() + spacing * 2);
// // flip the coordinates for MPJA // // flip the coordinates for MPJA
// if (type == ProtoBoard780Type.MPJA) { // if (type == ProtoBoard780Type.MPJA) {
@@ -201,38 +201,38 @@ public class ProtoBoard780 extends AbstractProtoBoard {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(padSize - 2f)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(padSize - 2f));
// the outer bus // the outer bus
g2d.drawLine((int) (point.getX() + width / 2 - 13 * spacing), g2d.drawLine((int) Math.round(point.getX() + width / 2 - 13 * spacing),
(int) (point.getY() - 2 * spacing + offsetY), (int) Math.round(point.getY() - 2 * spacing + offsetY),
(int) (point.getX() + width / 2 + 13 * spacing), (int) Math.round(point.getX() + width / 2 + 13 * spacing),
(int) (point.getY() - 2 * spacing + offsetY)); (int) Math.round(point.getY() - 2 * spacing + offsetY));
g2d.drawLine((int) (point.getX() + width / 2 - 13 * spacing), g2d.drawLine((int) Math.round(point.getX() + width / 2 - 13 * spacing),
(int) (point.getY() - 2 * spacing + offsetY), (int) Math.round(point.getY() - 2 * spacing + offsetY),
(int) (point.getX() + width / 2 - 13 * spacing), (int) Math.round(point.getX() + width / 2 - 13 * spacing),
(int) (point.getY() + (29 + (type == ProtoBoard780Type.RS ? 2 : 0)) * spacing + offsetY)); (int) (point.getY() + (29 + (type == ProtoBoard780Type.RS ? 2 : 0)) * spacing + offsetY));
g2d.drawLine((int) (point.getX() + width / 2 + 13 * spacing), g2d.drawLine((int) Math.round(point.getX() + width / 2 + 13 * spacing),
(int) (point.getY() - 2 * spacing + offsetY), (int) Math.round(point.getY() - 2 * spacing + offsetY),
(int) (point.getX() + width / 2 + 13 * spacing), (int) Math.round(point.getX() + width / 2 + 13 * spacing),
(int) (point.getY() + (29 + (type == ProtoBoard780Type.RS ? 2 : 0)) * spacing + offsetY)); (int) (point.getY() + (29 + (type == ProtoBoard780Type.RS ? 2 : 0)) * spacing + offsetY));
// horizontal long traces // horizontal long traces
g2d.drawLine((int) (point.getX() + width / 2 - 12 * spacing), (int) (point.getY() + offsetY), g2d.drawLine((int) Math.round(point.getX() + width / 2 - 12 * spacing), (int) Math.round(point.getY() + offsetY),
(int) (point.getX() + width / 2 + 12 * spacing), (int) (point.getY() + offsetY)); (int) Math.round(point.getX() + width / 2 + 12 * spacing), (int) Math.round(point.getY() + offsetY));
g2d.drawLine((int) (point.getX() + width / 2 - 12 * spacing), g2d.drawLine((int) Math.round(point.getX() + width / 2 - 12 * spacing),
(int) (point.getY() + spacing * 29 + offsetY), (int) Math.round(point.getY() + spacing * 29 + offsetY),
(int) (point.getX() + width / 2 + 12 * spacing), (int) Math.round(point.getX() + width / 2 + 12 * spacing),
(int) (point.getY() + spacing * 29 + offsetY)); (int) Math.round(point.getY() + spacing * 29 + offsetY));
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
int padX = (int) (point.getX() + width / 2 - 12 * spacing + (i * 5 + 1) * spacing); int padX = (int) (point.getX() + width / 2 - 12 * spacing + (i * 5 + 1) * spacing);
// vertical traces // vertical traces
g2d.drawLine((int) (padX - spacing), (int) (point.getY() + offsetY), (int) (padX - spacing), g2d.drawLine((int) (padX - spacing), (int) Math.round(point.getY() + offsetY), (int) (padX - spacing),
(int) (point.getY() + spacing * 28 + offsetY)); (int) Math.round(point.getY() + spacing * 28 + offsetY));
g2d.drawLine((int) (padX + 3 * spacing), (int) (point.getY() + spacing + offsetY), g2d.drawLine((int) (padX + 3 * spacing), (int) Math.round(point.getY() + spacing + offsetY),
(int) (padX + 3 * spacing), (int) (point.getY() + spacing * 29 + offsetY)); (int) (padX + 3 * spacing), (int) Math.round(point.getY() + spacing * 29 + offsetY));
for (int j = 1; j < 29; j++) { for (int j = 1; j < 29; j++) {
int padY = (int) (point.getY() + spacing * j + offsetY); int padY = (int) Math.round(point.getY() + spacing * j + offsetY);
// 3-pad traces // 3-pad traces
g2d.drawLine(padX, padY, (int) (padX + 2 * spacing), padY); g2d.drawLine(padX, padY, (int) (padX + 2 * spacing), padY);
@@ -245,14 +245,14 @@ public class ProtoBoard780 extends AbstractProtoBoard {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(padSize - 2f)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(padSize - 2f));
g2d.setColor(padColor); g2d.setColor(padColor);
int padX = (int) (point.getX() + width / 2 - 12 * spacing + i * spacing); int padX = (int) Math.round(point.getX() + width / 2 - 12 * spacing + i * spacing);
// drawingObserver.startTrackingContinuityArea(true); // drawingObserver.startTrackingContinuityArea(true);
// g2d.drawLine(padX, (int)(point.getY() + offsetY), padX, (int)(point.getY() + spacing + // g2d.drawLine(padX, (int) Math.round(point.getY() + offsetY), padX, (int) Math.round(point.getY() + spacing +
// offsetY)); // offsetY));
// drawingObserver.stopTrackingContinuityArea(); // drawingObserver.stopTrackingContinuityArea();
for (int j = 0; j < 30; j++) { for (int j = 0; j < 30; j++) {
int padY = (int) (point.getY() + spacing * j + offsetY); int padY = (int) Math.round(point.getY() + spacing * j + offsetY);
g2d.setColor(padColor); g2d.setColor(padColor);
@@ -277,8 +277,8 @@ public class ProtoBoard780 extends AbstractProtoBoard {
// horizontal coordinates // horizontal coordinates
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
int x = i == 0 ? 1 : i * 5; int x = i == 0 ? 1 : i * 5;
int padX = (int) (point.getX() + width / 2 - 13 * spacing + x * spacing); int padX = (int) Math.round(point.getX() + width / 2 - 13 * spacing + x * spacing);
int padY = (int) (point.getY() - spacing + offsetY); int padY = (int) Math.round(point.getY() - spacing + offsetY);
String label = String.valueOf((char) ('A' + i)); String label = String.valueOf((char) ('A' + i));
@@ -293,7 +293,7 @@ public class ProtoBoard780 extends AbstractProtoBoard {
for (int i = 0; i < 7; i++) { for (int i = 0; i < 7; i++) {
int y = i == 0 ? 1 : i * 5; int y = i == 0 ? 1 : i * 5;
int padX = (int) (point.getX() + width / 2 - 14 * spacing); int padX = (int) Math.round(point.getX() + width / 2 - 14 * spacing);
int padY = (int) (point.getY() + spacing * (y - 1) + offsetY); int padY = (int) (point.getY() + spacing * (y - 1) + offsetY);
StringUtils.drawCenteredText(g2d, Integer.toString(y), padX, padY, HorizontalAlignment.LEFT, StringUtils.drawCenteredText(g2d, Integer.toString(y), padX, padY, HorizontalAlignment.LEFT,
@@ -302,8 +302,8 @@ public class ProtoBoard780 extends AbstractProtoBoard {
// model name // model name
g2d.setFont(LABEL_FONT.deriveFont(COORDINATE_FONT_SIZE * 1.8f)); g2d.setFont(LABEL_FONT.deriveFont(COORDINATE_FONT_SIZE * 1.8f));
int x = (int) (point.getX() + width / 2); int x = (int) Math.round(point.getX() + width / 2);
int y = (int) (point.getY() + length - spacing * 1.5); int y = (int) Math.round(point.getY() + length - spacing * 1.5);
StringUtils.drawCenteredText(g2d, StringUtils.drawCenteredText(g2d,
type == ProtoBoard780Type.RS ? "Radio Shack 276-168B" : "MPJA.COM 33304 PB", x, y, type == ProtoBoard780Type.RS ? "Radio Shack 276-168B" : "MPJA.COM 33304 PB", x, y,
HorizontalAlignment.CENTER, VerticalAlignment.CENTER); HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
@@ -315,32 +315,32 @@ public class ProtoBoard780 extends AbstractProtoBoard {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
g2d.setColor(HOLE_COLOR); g2d.setColor(HOLE_COLOR);
g2d.fillOval((int) (point.getX() + width / 2) - dx - mountingHoleSize / 2, g2d.fillOval((int) Math.round(point.getX() + width / 2) - dx - mountingHoleSize / 2,
holeY - mountingHoleSize / 2, mountingHoleSize, mountingHoleSize); holeY - mountingHoleSize / 2, mountingHoleSize, mountingHoleSize);
g2d.fillOval((int) (point.getX() + width / 2) + dx - mountingHoleSize / 2, g2d.fillOval((int) Math.round(point.getX() + width / 2) + dx - mountingHoleSize / 2,
holeY - mountingHoleSize / 2, mountingHoleSize, mountingHoleSize); holeY - mountingHoleSize / 2, mountingHoleSize, mountingHoleSize);
g2d.setColor(finalBorderColor); g2d.setColor(finalBorderColor);
g2d.drawOval((int) (point.getX() + width / 2) - dx - mountingHoleSize / 2, g2d.drawOval((int) Math.round(point.getX() + width / 2) - dx - mountingHoleSize / 2,
holeY - mountingHoleSize / 2, mountingHoleSize, mountingHoleSize); holeY - mountingHoleSize / 2, mountingHoleSize, mountingHoleSize);
g2d.drawOval((int) (point.getX() + width / 2) + dx - mountingHoleSize / 2, g2d.drawOval((int) Math.round(point.getX() + width / 2) + dx - mountingHoleSize / 2,
holeY - mountingHoleSize / 2, mountingHoleSize, mountingHoleSize); holeY - mountingHoleSize / 2, mountingHoleSize, mountingHoleSize);
holeY = (int) (point.getY() + length - spacing); holeY = (int) Math.round(point.getY() + length - spacing);
g2d.setColor(HOLE_COLOR); g2d.setColor(HOLE_COLOR);
g2d.fillOval((int) (point.getX() + width / 2) - dx - mountingHoleSize / 2, g2d.fillOval((int) Math.round(point.getX() + width / 2) - dx - mountingHoleSize / 2,
holeY - mountingHoleSize / 2, mountingHoleSize, mountingHoleSize); holeY - mountingHoleSize / 2, mountingHoleSize, mountingHoleSize);
g2d.fillOval((int) (point.getX() + width / 2) + dx - mountingHoleSize / 2, g2d.fillOval((int) Math.round(point.getX() + width / 2) + dx - mountingHoleSize / 2,
holeY - mountingHoleSize / 2, mountingHoleSize, mountingHoleSize); holeY - mountingHoleSize / 2, mountingHoleSize, mountingHoleSize);
g2d.setColor(finalBorderColor); g2d.setColor(finalBorderColor);
g2d.drawOval((int) (point.getX() + width / 2) - dx - mountingHoleSize / 2, g2d.drawOval((int) Math.round(point.getX() + width / 2) - dx - mountingHoleSize / 2,
holeY - mountingHoleSize / 2, mountingHoleSize, mountingHoleSize); holeY - mountingHoleSize / 2, mountingHoleSize, mountingHoleSize);
g2d.drawOval((int) (point.getX() + width / 2) + dx - mountingHoleSize / 2, g2d.drawOval((int) Math.round(point.getX() + width / 2) + dx - mountingHoleSize / 2,
holeY - mountingHoleSize / 2, mountingHoleSize, mountingHoleSize); holeY - mountingHoleSize / 2, mountingHoleSize, mountingHoleSize);
} }
@@ -73,10 +73,10 @@ public class VeroBoard extends AbstractVeroBoard implements ILayeredComponent {
y += spacing; y += spacing;
g2d.setColor(stripColor); g2d.setColor(stripColor);
drawingObserver.startTrackingContinuityArea(true); drawingObserver.startTrackingContinuityArea(true);
g2d.fillRect((int)(x + spacing / 2), (int)(y - stripSize / 2), (int)(finalSecondPoint.getX() - spacing - x), stripSize); g2d.fillRect((int)(x + spacing / 2), (int)(y - stripSize / 2), (int) Math.round(finalSecondPoint.getX() - spacing - x), stripSize);
drawingObserver.stopTrackingContinuityArea(); drawingObserver.stopTrackingContinuityArea();
g2d.setColor(stripColor.darker()); g2d.setColor(stripColor.darker());
g2d.drawRect((int)(x + spacing / 2), (int)(y - stripSize / 2), (int)(finalSecondPoint.getX() - spacing - x), stripSize); g2d.drawRect((int)(x + spacing / 2), (int)(y - stripSize / 2), (int) Math.round(finalSecondPoint.getX() - spacing - x), stripSize);
while (x < finalSecondPoint.getX() - spacing - holeSize) { while (x < finalSecondPoint.getX() - spacing - holeSize) {
x += spacing; x += spacing;
g2d.setColor(Constants.CANVAS_COLOR); g2d.setColor(Constants.CANVAS_COLOR);
@@ -91,10 +91,10 @@ public class VeroBoard extends AbstractVeroBoard implements ILayeredComponent {
y = firstPoint.getY(); y = firstPoint.getY();
g2d.setColor(stripColor); g2d.setColor(stripColor);
drawingObserver.startTrackingContinuityArea(true); drawingObserver.startTrackingContinuityArea(true);
g2d.fillRect((int)(x - stripSize / 2), (int)(y + spacing / 2), stripSize, (int)(finalSecondPoint.getY() - spacing - y)); g2d.fillRect((int)(x - stripSize / 2), (int)(y + spacing / 2), stripSize, (int) Math.round(finalSecondPoint.getY() - spacing - y));
drawingObserver.stopTrackingContinuityArea(); drawingObserver.stopTrackingContinuityArea();
g2d.setColor(stripColor.darker()); g2d.setColor(stripColor.darker());
g2d.drawRect((int)(x - stripSize / 2), (int)(y + spacing / 2), stripSize, (int)(finalSecondPoint.getY() - spacing - y)); g2d.drawRect((int)(x - stripSize / 2), (int)(y + spacing / 2), stripSize, (int) Math.round(finalSecondPoint.getY() - spacing - y));
while (y < finalSecondPoint.getY() - spacing - holeSize) { while (y < finalSecondPoint.getY() - spacing - holeSize) {
y += spacing; y += spacing;
g2d.setColor(Constants.CANVAS_COLOR); g2d.setColor(Constants.CANVAS_COLOR);
@@ -62,11 +62,11 @@ public class ChassisPanel extends AbstractShape {
Composite oldComposite = applyAlpha(g2d, componentState); Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(color); g2d.setColor(color);
if (radius == 0) { if (radius == 0) {
g2d.fillRect((int) firstPoint.getX(), (int) firstPoint.getY(), g2d.fillRect((int) Math.round(firstPoint.getX()), (int) Math.round(firstPoint.getY()),
(int) (secondPoint.getX() - firstPoint.getX()), (int) (secondPoint.getX() - firstPoint.getX()),
(int) (secondPoint.getY() - firstPoint.getY())); (int) (secondPoint.getY() - firstPoint.getY()));
} else { } else {
g2d.fillRoundRect((int) firstPoint.getX(), (int) firstPoint.getY(), g2d.fillRoundRect((int) Math.round(firstPoint.getX()), (int) Math.round(firstPoint.getY()),
(int) (secondPoint.getX() - firstPoint.getX()), (int) (secondPoint.getX() - firstPoint.getX()),
(int) (secondPoint.getY() - firstPoint.getY()), radius, radius); (int) (secondPoint.getY() - firstPoint.getY()), radius, radius);
} }
@@ -78,11 +78,11 @@ public class ChassisPanel extends AbstractShape {
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: borderColor); : borderColor);
if (radius == 0) { if (radius == 0) {
g2d.drawRect((int) (firstPoint.getX()), (int) (firstPoint.getY()), g2d.drawRect((int) Math.round(firstPoint.getX()), (int) Math.round(firstPoint.getY()),
(int) (secondPoint.getX() - firstPoint.getX()), (int) (secondPoint.getX() - firstPoint.getX()),
(int) (secondPoint.getY() - firstPoint.getY())); (int) (secondPoint.getY() - firstPoint.getY()));
} else { } else {
g2d.drawRoundRect((int) (firstPoint.getX()), (int) (firstPoint.getY()), g2d.drawRoundRect((int) Math.round(firstPoint.getX()), (int) Math.round(firstPoint.getY()),
(int) (secondPoint.getX() - firstPoint.getX()), (int) (secondPoint.getX() - firstPoint.getX()),
(int) (secondPoint.getY() - firstPoint.getY()), radius, radius); (int) (secondPoint.getY() - firstPoint.getY()), radius, radius);
} }
@@ -50,7 +50,7 @@ public class EllipticalCutout extends AbstractShape {
if (componentState != ComponentState.DRAGGING) { if (componentState != ComponentState.DRAGGING) {
Composite oldComposite = applyAlpha(g2d, componentState); Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(color); g2d.setColor(color);
g2d.fillOval((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(secondPoint.getX() - firstPoint.getX()), (int)(secondPoint.getY() - firstPoint.getY())); g2d.fillOval((int) Math.round(firstPoint.getX()), (int) Math.round(firstPoint.getY()), (int)(secondPoint.getX() - firstPoint.getX()), (int)(secondPoint.getY() - firstPoint.getY()));
g2d.setComposite(oldComposite); g2d.setComposite(oldComposite);
} }
// Do not track any changes that follow because the whole oval has been // Do not track any changes that follow because the whole oval has been
@@ -58,7 +58,7 @@ public class EllipticalCutout extends AbstractShape {
drawingObserver.stopTracking(); drawingObserver.stopTracking();
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: borderColor); : borderColor);
g2d.drawOval((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(secondPoint.getX() - firstPoint.getX()), (int)(secondPoint.getY() - firstPoint.getY())); g2d.drawOval((int) Math.round(firstPoint.getX()), (int) Math.round(firstPoint.getY()), (int)(secondPoint.getX() - firstPoint.getX()), (int)(secondPoint.getY() - firstPoint.getY()));
} }
@Override @Override
@@ -56,7 +56,7 @@ public class RectangularCutout extends AbstractShape {
if (componentState != ComponentState.DRAGGING) { if (componentState != ComponentState.DRAGGING) {
Composite oldComposite = applyAlpha(g2d, componentState); Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(color); g2d.setColor(color);
g2d.fillRoundRect((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(secondPoint.getX() - firstPoint.getX()), (int)(secondPoint.getY() - firstPoint.getY()), radius, g2d.fillRoundRect((int) Math.round(firstPoint.getX()), (int) Math.round(firstPoint.getY()), (int)(secondPoint.getX() - firstPoint.getX()), (int)(secondPoint.getY() - firstPoint.getY()), radius,
radius); radius);
g2d.setComposite(oldComposite); g2d.setComposite(oldComposite);
} }
@@ -65,7 +65,7 @@ public class RectangularCutout extends AbstractShape {
drawingObserver.stopTracking(); drawingObserver.stopTracking();
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: borderColor); : borderColor);
g2d.drawRoundRect((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(secondPoint.getX() - firstPoint.getX()), (int)(secondPoint.getY() - firstPoint.getY()), radius, g2d.drawRoundRect((int) Math.round(firstPoint.getX()), (int) Math.round(firstPoint.getY()), (int)(secondPoint.getX() - firstPoint.getX()), (int)(secondPoint.getY() - firstPoint.getY()), radius,
radius); radius);
} }
@@ -67,9 +67,9 @@ public class CutLine extends AbstractTransparentComponent<Void> {
Composite oldComposite = applyAlpha(g2d); Composite oldComposite = applyAlpha(g2d);
if (getOrientation() == OrientationHV.HORIZONTAL) if (getOrientation() == OrientationHV.HORIZONTAL)
g2d.drawLine((int)point.getX(), (int)point.getY(), (int)point.getX() + l, (int)point.getY()); g2d.drawLine((int) Math.round(point.getX()), (int) Math.round(point.getY()), (int) Math.round(point.getX()) + l, (int) Math.round(point.getY()));
else else
g2d.drawLine((int)point.getX(), (int)point.getY(), (int)point.getX(), (int)point.getY() + l); g2d.drawLine((int) Math.round(point.getX()), (int) Math.round(point.getY()), (int) Math.round(point.getX()), (int) Math.round(point.getY()) + l);
g2d.setComposite(oldComposite); g2d.setComposite(oldComposite);
} }
@@ -77,16 +77,16 @@ public class Eyelet extends AbstractTransparentComponent<String> {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f));
g2d.setColor(color); g2d.setColor(color);
drawingObserver.startTrackingContinuityArea(true); drawingObserver.startTrackingContinuityArea(true);
g2d.fillOval((int)(point.getX() - diameter / 2), (int)(point.getY() - diameter / 2), diameter, diameter); g2d.fillOval((int) Math.round(point.getX() - diameter / 2), (int) Math.round(point.getY() - diameter / 2), diameter, diameter);
drawingObserver.stopTrackingContinuityArea(); drawingObserver.stopTrackingContinuityArea();
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: color.darker()); : color.darker());
g2d.drawOval((int)(point.getX() - diameter / 2), (int)(point.getY() - diameter / 2), diameter, diameter); g2d.drawOval((int) Math.round(point.getX() - diameter / 2), (int) Math.round(point.getY() - diameter / 2), diameter, diameter);
g2d.setColor(Constants.CANVAS_COLOR); g2d.setColor(Constants.CANVAS_COLOR);
g2d.fillOval((int)(point.getX() - holeDiameter / 2), (int)(point.getY() - holeDiameter / 2), holeDiameter, holeDiameter); g2d.fillOval((int) Math.round(point.getX() - holeDiameter / 2), (int) Math.round(point.getY() - holeDiameter / 2), holeDiameter, holeDiameter);
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: color.darker()); : color.darker());
g2d.drawOval((int)(point.getX() - holeDiameter / 2), (int)(point.getY() - holeDiameter / 2), holeDiameter, holeDiameter); g2d.drawOval((int) Math.round(point.getX() - holeDiameter / 2), (int) Math.round(point.getY() - holeDiameter / 2), holeDiameter, holeDiameter);
g2d.setComposite(oldComposite); g2d.setComposite(oldComposite);
} }
@@ -130,7 +130,7 @@ public class Line extends AbstractLeadedComponent<Void> {
interpolate(endPoint, startPoint, getArrowSize().convertToPixels() * 0.9 / distance, endPoint); interpolate(endPoint, startPoint, getArrowSize().convertToPixels() * 0.9 / distance, endPoint);
} }
g2d.drawLine((int)startPoint.getX(), (int)startPoint.getY(), (int)endPoint.getX(), (int)endPoint.getY()); g2d.drawLine((int) Math.round(startPoint.getX()), (int) Math.round(startPoint.getY()), (int) Math.round(endPoint.getX()), (int) Math.round(endPoint.getY()));
} }
private void interpolate(Point2D p1, Point2D p2, double t, Point2D p) { private void interpolate(Point2D p1, Point2D p2, double t, Point2D p) {
@@ -82,7 +82,7 @@ public class MultimeterProbe extends AbstractTransparentComponent<Color> {
g2d.setColor(Constants.TRANSPARENT_COLOR); g2d.setColor(Constants.TRANSPARENT_COLOR);
drawingObserver.startTrackingContinuityArea(true); drawingObserver.startTrackingContinuityArea(true);
double sensitivity = SENSITIVITY.convertToPixels(); double sensitivity = SENSITIVITY.convertToPixels();
g2d.fillOval((int) (point.getX() - sensitivity), (int) (point.getY() - sensitivity), g2d.fillOval((int) Math.round(point.getX() - sensitivity), (int) Math.round(point.getY() - sensitivity),
(int) (sensitivity * 2), (int) (sensitivity * 2)); (int) (sensitivity * 2), (int) (sensitivity * 2));
drawingObserver.stopTrackingContinuityArea(); drawingObserver.stopTrackingContinuityArea();
@@ -240,14 +240,14 @@ public class PCBTerminalBlock extends AbstractTransparentComponent<PCBTerminalBl
if (outlineMode) { if (outlineMode) {
// g2d.setColor(Constants.TRANSPARENT_COLOR); // g2d.setColor(Constants.TRANSPARENT_COLOR);
// drawingObserver.startTrackingContinuityArea(true); // drawingObserver.startTrackingContinuityArea(true);
// g2d.fillRect((int)(p.getX() - lugWidth / 2), (int)(p.getY() - lugHeight / 2), lugWidth, // g2d.fillRect((int) Math.round(p.getX() - lugWidth / 2), (int) Math.round(p.getY() - lugHeight / 2), lugWidth,
// lugHeight); // lugHeight);
// drawingObserver.stopTrackingContinuityArea(); // drawingObserver.stopTrackingContinuityArea();
g2d.setColor(theme.getOutlineColor()); g2d.setColor(theme.getOutlineColor());
} else { } else {
g2d.setColor(CIRCLE_COLOR); g2d.setColor(CIRCLE_COLOR);
g2d.fillOval((int) (p.getX() - circleDiameter / 2), (int) (p.getY() - circleDiameter / 2), g2d.fillOval((int) Math.round(p.getX() - circleDiameter / 2), (int) Math.round(p.getY() - circleDiameter / 2),
circleDiameter, circleDiameter); circleDiameter, circleDiameter);
g2d.setColor(CIRCLE_COLOR.darker()); g2d.setColor(CIRCLE_COLOR.darker());
@@ -89,22 +89,22 @@ public class TraceCut extends AbstractTransparentComponent<Void> implements ILay
: getBoardColor()); : getBoardColor());
drawingObserver.startTrackingContinuityArea(false); drawingObserver.startTrackingContinuityArea(false);
if (getOrientation() == OrientationHV.VERTICAL) if (getOrientation() == OrientationHV.VERTICAL)
g2d.fillRect((int)(point.getX() - holeSpacing / 2 - cutWidth / 2), (int)(point.getY() - size / 2 - 1), cutWidth, size + 2); g2d.fillRect((int) Math.round(point.getX() - holeSpacing / 2 - cutWidth / 2), (int) Math.round(point.getY() - size / 2 - 1), cutWidth, size + 2);
else else
g2d.fillRect((int)(point.getX() - size / 2 - 1), (int)(point.getY() - holeSpacing / 2 - cutWidth / 2), size + 2, cutWidth); g2d.fillRect((int) Math.round(point.getX() - size / 2 - 1), (int) Math.round(point.getY() - holeSpacing / 2 - cutWidth / 2), size + 2, cutWidth);
drawingObserver.stopTrackingContinuityArea(); drawingObserver.stopTrackingContinuityArea();
} else { } else {
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: getBoardColor()); : getBoardColor());
drawingObserver.startTrackingContinuityArea(false); drawingObserver.startTrackingContinuityArea(false);
g2d.fillRoundRect((int)(point.getX() - size / 2), (int)(point.getY() - size / 2), size, size, size, size); g2d.fillRoundRect((int) Math.round(point.getX() - size / 2), (int) Math.round(point.getY() - size / 2), size, size, size, size);
drawingObserver.stopTrackingContinuityArea(); drawingObserver.stopTrackingContinuityArea();
g2d.setColor(Constants.CANVAS_COLOR); g2d.setColor(Constants.CANVAS_COLOR);
int holeSize = getClosestOdd((int) HOLE_SIZE.convertToPixels()); int holeSize = getClosestOdd((int) HOLE_SIZE.convertToPixels());
g2d.fillOval((int)(point.getX() - holeSize / 2), (int)(point.getY() - holeSize / 2), holeSize, holeSize); g2d.fillOval((int) Math.round(point.getX() - holeSize / 2), (int) Math.round(point.getY() - holeSize / 2), holeSize, holeSize);
g2d.setColor(getBoardColor().darker()); g2d.setColor(getBoardColor().darker());
g2d.drawOval((int)(point.getX() - holeSize / 2), (int)(point.getY() - holeSize / 2), holeSize, holeSize); g2d.drawOval((int) Math.round(point.getX() - holeSize / 2), (int) Math.round(point.getY() - holeSize / 2), holeSize, holeSize);
} }
g2d.setComposite(oldComposite); g2d.setComposite(oldComposite);
} }
@@ -73,16 +73,16 @@ public class Turret extends AbstractTransparentComponent<String> {
g2d.setColor(color); g2d.setColor(color);
g2d.setStroke(ObjectCache.getInstance().fetchZoomableStroke(1f)); g2d.setStroke(ObjectCache.getInstance().fetchZoomableStroke(1f));
drawingObserver.startTrackingContinuityArea(true); drawingObserver.startTrackingContinuityArea(true);
g2d.fillOval((int)(point.getX() - diameter / 2), (int)(point.getY() - diameter / 2), diameter, diameter); g2d.fillOval((int) Math.round(point.getX() - diameter / 2), (int) Math.round(point.getY() - diameter / 2), diameter, diameter);
drawingObserver.stopTrackingContinuityArea(); drawingObserver.stopTrackingContinuityArea();
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: color.darker()); : color.darker());
g2d.drawOval((int)(point.getX() - diameter / 2), (int)(point.getY() - diameter / 2), diameter, diameter); g2d.drawOval((int) Math.round(point.getX() - diameter / 2), (int) Math.round(point.getY() - diameter / 2), diameter, diameter);
g2d.setColor(Constants.CANVAS_COLOR); g2d.setColor(Constants.CANVAS_COLOR);
g2d.fillOval((int)(point.getX() - holeDiameter / 2), (int)(point.getY() - holeDiameter / 2), holeDiameter, holeDiameter); g2d.fillOval((int) Math.round(point.getX() - holeDiameter / 2), (int) Math.round(point.getY() - holeDiameter / 2), holeDiameter, holeDiameter);
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: color.darker()); : color.darker());
g2d.drawOval((int)(point.getX() - holeDiameter / 2), (int)(point.getY() - holeDiameter / 2), holeDiameter, holeDiameter); g2d.drawOval((int) Math.round(point.getX() - holeDiameter / 2), (int) Math.round(point.getY() - holeDiameter / 2), holeDiameter, holeDiameter);
g2d.setComposite(oldComposite); g2d.setComposite(oldComposite);
} }
@@ -338,10 +338,10 @@ public class DIPSwitch extends AbstractTransparentComponent<String> implements I
int pinHeight = getClosestOdd(pinSize int pinHeight = getClosestOdd(pinSize
/ (getOrientation() == Orientation.DEFAULT || getOrientation() == Orientation._180 ? 1f / (getOrientation() == Orientation.DEFAULT || getOrientation() == Orientation._180 ? 1f
: 2f)); : 2f));
g2d.fillRect((int) (point.getX() - pinWidth / 2), (int) (point.getY() - pinHeight / 2), g2d.fillRect((int) Math.round(point.getX() - pinWidth / 2), (int) Math.round(point.getY() - pinHeight / 2),
pinWidth, pinHeight); pinWidth, pinHeight);
g2d.setColor(PIN_BORDER_COLOR); g2d.setColor(PIN_BORDER_COLOR);
g2d.drawRect((int) (point.getX() - pinWidth / 2), (int) (point.getY() - pinHeight / 2), g2d.drawRect((int) Math.round(point.getX() - pinWidth / 2), (int) Math.round(point.getY() - pinHeight / 2),
pinWidth, pinHeight); pinWidth, pinHeight);
} }
} }
@@ -213,10 +213,10 @@ public class FuseHolderPanel extends AbstractMultiPartComponent<String> {
for (Point2D p : controlPoints) { for (Point2D p : controlPoints) {
if (outlineMode) { if (outlineMode) {
g2d.setColor(theme.getOutlineColor()); g2d.setColor(theme.getOutlineColor());
g2d.drawRect((int)(p.getX() - lugWidth / 2), (int)(p.getY() - lugHeight / 2), lugWidth, lugHeight); g2d.drawRect((int) Math.round(p.getX() - lugWidth / 2), (int) Math.round(p.getY() - lugHeight / 2), lugWidth, lugHeight);
} else { } else {
g2d.setColor(METAL_COLOR); g2d.setColor(METAL_COLOR);
g2d.fillRect((int)(p.getX() - lugWidth / 2), (int)(p.getY() - lugHeight / 2), lugWidth, lugHeight); g2d.fillRect((int) Math.round(p.getX() - lugWidth / 2), (int) Math.round(p.getY() - lugHeight / 2), lugWidth, lugHeight);
} }
} }
@@ -236,10 +236,10 @@ public class IECSocket extends AbstractMultiPartComponent<String> {
for (Point2D p : controlPoints) { for (Point2D p : controlPoints) {
if (outlineMode) { if (outlineMode) {
g2d.setColor(theme.getOutlineColor()); g2d.setColor(theme.getOutlineColor());
g2d.drawRect((int)(p.getX() - lugWidth / 2), (int)(p.getY() - lugHeight / 2), lugWidth, lugHeight); g2d.drawRect((int) Math.round(p.getX() - lugWidth / 2), (int) Math.round(p.getY() - lugHeight / 2), lugWidth, lugHeight);
} else { } else {
g2d.setColor(METAL_COLOR); g2d.setColor(METAL_COLOR);
g2d.fillRect((int)(p.getX() - lugWidth / 2), (int)(p.getY() - lugHeight / 2), lugWidth, lugHeight); g2d.fillRect((int) Math.round(p.getX() - lugWidth / 2), (int) Math.round(p.getY() - lugHeight / 2), lugWidth, lugHeight);
} }
} }
@@ -302,7 +302,7 @@ public class IECSocket extends AbstractMultiPartComponent<String> {
Point2D[] cutoutPoints = new Point2D[] { Point2D[] cutoutPoints = new Point2D[] {
new Point2D.Double(firstPoint.getX(), firstPoint.getY() + vSpacing / 2 - cutoutWidth / 2), new Point2D.Double(firstPoint.getX(), firstPoint.getY() + vSpacing / 2 - cutoutWidth / 2),
new Point2D.Double(firstPoint.getX() + cutoutLength / 2 - cutoutSlant, (int) (firstPoint.getY() + vSpacing / 2 - cutoutWidth / 2)), new Point2D.Double(firstPoint.getX() + cutoutLength / 2 - cutoutSlant, (int) Math.round(firstPoint.getY() + vSpacing / 2 - cutoutWidth / 2)),
new Point2D.Double(firstPoint.getX() + cutoutLength / 2, firstPoint.getY() + vSpacing / 2 - cutoutWidth / 2 + cutoutSlant), new Point2D.Double(firstPoint.getX() + cutoutLength / 2, firstPoint.getY() + vSpacing / 2 - cutoutWidth / 2 + cutoutSlant),
new Point2D.Double(firstPoint.getX() + cutoutLength / 2, firstPoint.getY() + vSpacing / 2 + cutoutWidth / 2), new Point2D.Double(firstPoint.getX() + cutoutLength / 2, firstPoint.getY() + vSpacing / 2 + cutoutWidth / 2),
new Point2D.Double(firstPoint.getX() - cutoutLength / 2, firstPoint.getY() + vSpacing / 2 + cutoutWidth / 2), new Point2D.Double(firstPoint.getX() - cutoutLength / 2, firstPoint.getY() + vSpacing / 2 + cutoutWidth / 2),
@@ -311,10 +311,10 @@ public class MiniRelay extends AbstractLabeledComponent<String> implements IGerb
for (Point2D point : controlPoints) { for (Point2D point : controlPoints) {
if (!outlineMode) { if (!outlineMode) {
g2d.setColor(PIN_COLOR); g2d.setColor(PIN_COLOR);
g2d.fillOval((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize); g2d.fillOval((int) Math.round(point.getX() - pinSize / 2), (int) Math.round(point.getY() - pinSize / 2), pinSize, pinSize);
} }
g2d.setColor(outlineMode ? theme.getOutlineColor() : PIN_BORDER_COLOR); g2d.setColor(outlineMode ? theme.getOutlineColor() : PIN_BORDER_COLOR);
g2d.drawOval((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize); g2d.drawOval((int) Math.round(point.getX() - pinSize / 2), (int) Math.round(point.getY() - pinSize / 2), pinSize, pinSize);
} }
Color finalBorderColor; Color finalBorderColor;
@@ -317,21 +317,21 @@ public class MiniToggleSwitch extends AbstractTransparentComponent<ToggleSwitchT
if (outlineMode) { if (outlineMode) {
// g2d.setColor(Constants.TRANSPARENT_COLOR); // g2d.setColor(Constants.TRANSPARENT_COLOR);
// drawingObserver.startTrackingContinuityArea(true); // drawingObserver.startTrackingContinuityArea(true);
// g2d.fillRect((int)(p.getX() - lugWidth / 2), (int)(p.getY() - lugHeight / 2), lugWidth, lugHeight); // g2d.fillRect((int) Math.round(p.getX() - lugWidth / 2), (int) Math.round(p.getY() - lugHeight / 2), lugWidth, lugHeight);
// drawingObserver.stopTrackingContinuityArea(); // drawingObserver.stopTrackingContinuityArea();
g2d.setColor(theme.getOutlineColor()); g2d.setColor(theme.getOutlineColor());
g2d.drawRect((int)(p.getX() - lugWidth / 2d), (int)(p.getY() - lugHeight / 2d), lugWidth, lugHeight); g2d.drawRect((int) Math.round(p.getX() - lugWidth / 2d), (int) Math.round(p.getY() - lugHeight / 2d), lugWidth, lugHeight);
} else { } else {
g2d.setColor(getTerminalPadColor().darker()); g2d.setColor(getTerminalPadColor().darker());
g2d.drawOval((int)(p.getX() - circleDiameter / 2d), (int)(p.getY() - circleDiameter / 2d), circleDiameter, circleDiameter); g2d.drawOval((int) Math.round(p.getX() - circleDiameter / 2d), (int) Math.round(p.getY() - circleDiameter / 2d), circleDiameter, circleDiameter);
g2d.setColor(getTerminalPadColor()); g2d.setColor(getTerminalPadColor());
g2d.fillOval((int)(p.getX() - circleDiameter / 2d), (int)(p.getY() - circleDiameter / 2d), circleDiameter, circleDiameter); g2d.fillOval((int) Math.round(p.getX() - circleDiameter / 2d), (int) Math.round(p.getY() - circleDiameter / 2d), circleDiameter, circleDiameter);
g2d.setColor(getTerminalColor()); g2d.setColor(getTerminalColor());
// drawingObserver.startTrackingContinuityArea(true); // drawingObserver.startTrackingContinuityArea(true);
g2d.fillRect((int)(p.getX() - lugWidth / 2d), (int)(p.getY() - lugHeight / 2d), lugWidth, lugHeight); g2d.fillRect((int) Math.round(p.getX() - lugWidth / 2d), (int) Math.round(p.getY() - lugHeight / 2d), lugWidth, lugHeight);
// drawingObserver.stopTrackingContinuityArea(); // drawingObserver.stopTrackingContinuityArea();
} }
} }
@@ -168,7 +168,7 @@ public class OpenJack1_4 extends AbstractMultiPartComponent<OpenJackType> {
int springLength = (int) SPRING_LENGTH.convertToPixels(); int springLength = (int) SPRING_LENGTH.convertToPixels();
int holeToEdge = (int) HOLE_TO_EDGE.convertToPixels(); int holeToEdge = (int) HOLE_TO_EDGE.convertToPixels();
double centerY = controlPoints[0].getY() + springLength - holeToEdge; double centerY = controlPoints[0].getY() + springLength - holeToEdge;
Point2D tipLabel = new Point2D.Double(controlPoints[0].getX(), (int) (controlPoints[0].getY() + holeToEdge * 1.25)); Point2D tipLabel = new Point2D.Double(controlPoints[0].getX(), (int) Math.round(controlPoints[0].getY() + holeToEdge * 1.25));
AffineTransform ringTransform = AffineTransform.getRotateInstance(getValue() == OpenJackType.SWITCHED ? SWITCH_THETA : RING_THETA, controlPoints[0].getX(), centerY); AffineTransform ringTransform = AffineTransform.getRotateInstance(getValue() == OpenJackType.SWITCHED ? SWITCH_THETA : RING_THETA, controlPoints[0].getX(), centerY);
AffineTransform sleeveTransform = AffineTransform.getRotateInstance(getValue() == OpenJackType.SWITCHED ? SLEEVE_SWITCHED_THETA : SLEEVE_THETA, controlPoints[0].getX(), centerY); AffineTransform sleeveTransform = AffineTransform.getRotateInstance(getValue() == OpenJackType.SWITCHED ? SLEEVE_SWITCHED_THETA : SLEEVE_THETA, controlPoints[0].getX(), centerY);
Point2D ringOrSwitchLabel = new Point2D.Double(0, 0); Point2D ringOrSwitchLabel = new Point2D.Double(0, 0);
@@ -161,7 +161,7 @@ public class OpenJack1_8 extends AbstractMultiPartComponent<OpenJackType> {
int springLength = (int) SPRING_LENGTH.convertToPixels(); int springLength = (int) SPRING_LENGTH.convertToPixels();
int holeToEdge = (int) HOLE_TO_EDGE.convertToPixels(); int holeToEdge = (int) HOLE_TO_EDGE.convertToPixels();
double centerY = controlPoints[0].getY() + springLength - holeToEdge; double centerY = controlPoints[0].getY() + springLength - holeToEdge;
Point2D tipLabel = new Point2D.Double(controlPoints[0].getX(), (int) (controlPoints[0].getY() + holeToEdge * 1.25)); Point2D tipLabel = new Point2D.Double(controlPoints[0].getX(), (int) Math.round(controlPoints[0].getY() + holeToEdge * 1.25));
AffineTransform ringTransform = AffineTransform.getRotateInstance(getValue() == OpenJackType.SWITCHED ? SWITCH_THETA : RING_THETA, controlPoints[0].getX(), centerY); AffineTransform ringTransform = AffineTransform.getRotateInstance(getValue() == OpenJackType.SWITCHED ? SWITCH_THETA : RING_THETA, controlPoints[0].getX(), centerY);
AffineTransform sleeveTransform = AffineTransform.getRotateInstance(getValue() == OpenJackType.SWITCHED ? SLEEVE_SWITCHED_THETA : SLEEVE_THETA, controlPoints[0].getX(), centerY); AffineTransform sleeveTransform = AffineTransform.getRotateInstance(getValue() == OpenJackType.SWITCHED ? SLEEVE_SWITCHED_THETA : SLEEVE_THETA, controlPoints[0].getX(), centerY);
Point2D ringOrSwitchLabel = new Point2D.Double(0, 0); Point2D ringOrSwitchLabel = new Point2D.Double(0, 0);
@@ -239,10 +239,10 @@ public class PinHeader extends AbstractTransparentComponent<Void> {
for (Point2D point : controlPoints) { for (Point2D point : controlPoints) {
if (!outlineMode) { if (!outlineMode) {
g2d.setColor(PIN_COLOR); g2d.setColor(PIN_COLOR);
g2d.fillRect((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize); g2d.fillRect((int) Math.round(point.getX() - pinSize / 2), (int) Math.round(point.getY() - pinSize / 2), pinSize, pinSize);
} }
g2d.setColor(outlineMode ? theme.getOutlineColor() : PIN_BORDER_COLOR); g2d.setColor(outlineMode ? theme.getOutlineColor() : PIN_BORDER_COLOR);
g2d.drawRect((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize); g2d.drawRect((int) Math.round(point.getX() - pinSize / 2), (int) Math.round(point.getY() - pinSize / 2), pinSize, pinSize);
} }
Color finalBorderColor; Color finalBorderColor;
@@ -284,14 +284,14 @@ public class SlideSwitch extends AbstractTransparentComponent<SlideSwitchType> i
Point2D p = controlPoints[i]; Point2D p = controlPoints[i];
if (outlineMode) { if (outlineMode) {
g2d.setColor(theme.getOutlineColor()); g2d.setColor(theme.getOutlineColor());
g2d.drawRect((int) (p.getX() - lugWidth / 2d), (int) (p.getY() - lugHeight / 2d), lugWidth, g2d.drawRect((int) Math.round(p.getX() - lugWidth / 2d), (int) Math.round(p.getY() - lugHeight / 2d), lugWidth,
lugHeight); lugHeight);
} else { } else {
g2d.setColor(TERMINAL_COLOR); g2d.setColor(TERMINAL_COLOR);
g2d.fillRect((int) (p.getX() - lugWidth / 2d), (int) (p.getY() - lugHeight / 2d), lugWidth, g2d.fillRect((int) Math.round(p.getX() - lugWidth / 2d), (int) Math.round(p.getY() - lugHeight / 2d), lugWidth,
lugHeight); lugHeight);
g2d.setColor(TERMINAL_COLOR.darker()); g2d.setColor(TERMINAL_COLOR.darker());
g2d.drawRect((int) (p.getX() - lugWidth / 2d), (int) (p.getY() - lugHeight / 2d), lugWidth, g2d.drawRect((int) Math.round(p.getX() - lugWidth / 2d), (int) Math.round(p.getY() - lugHeight / 2d), lugWidth,
lugHeight); lugHeight);
} }
} }
@@ -134,7 +134,7 @@ public class SwitchLatchingSymbol
Math.atan2(endPoint.getY() - startPoint.getY(), endPoint.getX() - startPoint.getX()); Math.atan2(endPoint.getY() - startPoint.getY(), endPoint.getX() - startPoint.getX());
int startAngle = (int) Math.toDegrees(-latchAngle) - ARC_ANGLE / 2; int startAngle = (int) Math.toDegrees(-latchAngle) - ARC_ANGLE / 2;
g2d.drawArc((int) (startPoint.getX() - d), (int) (startPoint.getY() - d), (int) (d * 2), g2d.drawArc((int) Math.round(startPoint.getX() - d), (int) Math.round(startPoint.getY() - d), (int) (d * 2),
(int) (d * 2), startAngle, ARC_ANGLE); (int) (d * 2), startAngle, ARC_ANGLE);
} }
} }
@@ -188,9 +188,9 @@ public class TactileMicroSwitch extends AbstractLabeledComponent<String> impleme
throw new RuntimeException("Unexpected orientation: " + orientation); throw new RuntimeException("Unexpected orientation: " + orientation);
} }
controlPoints[i] = controlPoints[i] =
new Point2D.Double((int) (firstPoint.getX() + dx1), (int) (firstPoint.getY() + dy1)); new Point2D.Double((int) Math.round(firstPoint.getX() + dx1), (int) Math.round(firstPoint.getY() + dy1));
controlPoints[i + PIN_COUNT / 2] = controlPoints[i + PIN_COUNT / 2] =
new Point2D.Double((int) (firstPoint.getX() + dx2), (int) (firstPoint.getY() + dy2)); new Point2D.Double((int) Math.round(firstPoint.getX() + dx2), (int) Math.round(firstPoint.getY() + dy2));
} }
} }
@@ -369,7 +369,7 @@ public class ThonkJack3_5 extends AbstractTransparentComponent<String> {
rotation.transform(textCenter, textCenter); rotation.transform(textCenter, textCenter);
} }
int drawX = (int) (textCenter.getX() - textWidth / 2); int drawX = (int) Math.round(textCenter.getX() - textWidth / 2);
int drawY = (int) (textCenter.getY() - textHeight / 2 + fontMetrics.getAscent()); int drawY = (int) (textCenter.getY() - textHeight / 2 + fontMetrics.getAscent());
g2d.drawString(label, drawX, drawY); g2d.drawString(label, drawX, drawY);
@@ -187,16 +187,16 @@ public class S1Switch extends AbstractTransparentComponent<Void> implements ISwi
Point2D p = controlPoints[i]; Point2D p = controlPoints[i];
if (outlineMode) { if (outlineMode) {
g2d.setColor(theme.getOutlineColor()); g2d.setColor(theme.getOutlineColor());
g2d.drawOval((int)(p.getX() - padDiameter / 2), (int)(p.getY() - padDiameter / 2), padDiameter, padDiameter); g2d.drawOval((int) Math.round(p.getX() - padDiameter / 2), (int) Math.round(p.getY() - padDiameter / 2), padDiameter, padDiameter);
} else { } else {
g2d.setColor(PAD_COLOR); g2d.setColor(PAD_COLOR);
drawingObserver.startTrackingContinuityArea(true); drawingObserver.startTrackingContinuityArea(true);
g2d.fillOval((int)(p.getX() - padDiameter / 2), (int)(p.getY() - padDiameter / 2), padDiameter, padDiameter); g2d.fillOval((int) Math.round(p.getX() - padDiameter / 2), (int) Math.round(p.getY() - padDiameter / 2), padDiameter, padDiameter);
drawingObserver.stopTrackingContinuityArea(); drawingObserver.stopTrackingContinuityArea();
g2d.setColor(PAD_COLOR.darker()); g2d.setColor(PAD_COLOR.darker());
g2d.drawOval((int)(p.getX() - padDiameter / 2), (int)(p.getY() - padDiameter / 2), padDiameter, padDiameter); g2d.drawOval((int) Math.round(p.getX() - padDiameter / 2), (int) Math.round(p.getY() - padDiameter / 2), padDiameter, padDiameter);
g2d.setColor(HOLE_COLOR); g2d.setColor(HOLE_COLOR);
g2d.fillOval((int)(p.getX() - holeDiameter / 2), (int)(p.getY() - holeDiameter / 2), holeDiameter, holeDiameter); g2d.fillOval((int) Math.round(p.getX() - holeDiameter / 2), (int) Math.round(p.getY() - holeDiameter / 2), holeDiameter, holeDiameter);
} }
if (!showMarkers || i % 3 == 2) { if (!showMarkers || i % 3 == 2) {
@@ -213,8 +213,8 @@ public class S1Switch extends AbstractTransparentComponent<Void> implements ISwi
Stroke stroke = g2d.getStroke(); Stroke stroke = g2d.getStroke();
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(2f)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(2f));
g2d.setColor(LINE_COLOR); g2d.setColor(LINE_COLOR);
g2d.drawLine((int)(p.getX() - padDiameter / 3), (int)(p.getY() + dy * padDiameter * 4 / 5), g2d.drawLine((int) Math.round(p.getX() - padDiameter / 3), (int) Math.round(p.getY() + dy * padDiameter * 4 / 5),
(int)(p.getX() + padDiameter / 3), (int)(p.getY() + dy * padDiameter * 4 / 5)); (int) Math.round(p.getX() + padDiameter / 3), (int) Math.round(p.getY() + dy * padDiameter * 4 / 5));
g2d.setStroke(stroke); g2d.setStroke(stroke);
} }
@@ -1,226 +1,226 @@
/* /*
DIY Layout Creator (DIYLC). DIY Layout Creator (DIYLC).
Copyright (c) 2009-2025 held jointly by the individual authors. Copyright (c) 2009-2025 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 DIYLC is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
DIYLC is distributed in the hope that it will be useful, DIYLC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with DIYLC. If not, see <http://www.gnu.org/licenses/>. along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.diylc.components.misc; package org.diylc.components.misc;
import java.awt.Color; import java.awt.Color;
import java.awt.Font; import java.awt.Font;
import java.awt.FontMetrics; import java.awt.FontMetrics;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import org.diylc.components.AbstractComponent; import org.diylc.components.AbstractComponent;
import org.diylc.core.ComponentState; import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent; import org.diylc.core.IDIYComponent;
import org.diylc.core.IDrawingObserver; import org.diylc.core.IDrawingObserver;
import org.diylc.core.Project; import org.diylc.core.Project;
import org.diylc.core.VisibilityPolicy; import org.diylc.core.VisibilityPolicy;
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.measures.Size; import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit; import org.diylc.core.measures.SizeUnit;
import org.diylc.utils.BomEntry; import org.diylc.utils.BomEntry;
import org.diylc.utils.BomMaker; import org.diylc.utils.BomMaker;
@ComponentDescriptor(name = "Bill of Materials", author = "Branislav Stojkovic", category = "Misc", description = "", @ComponentDescriptor(name = "Bill of Materials", author = "Branislav Stojkovic", category = "Misc", description = "",
instanceNamePrefix = "BOM", zOrder = IDIYComponent.TEXT, bomPolicy = BomPolicy.NEVER_SHOW, instanceNamePrefix = "BOM", zOrder = IDIYComponent.TEXT, bomPolicy = BomPolicy.NEVER_SHOW,
autoEdit = false) autoEdit = false)
public class BOM extends AbstractComponent<Void> { public class BOM extends AbstractComponent<Void> {
public static Size DEFAULT_SIZE = new Size(10d, SizeUnit.cm); public static Size DEFAULT_SIZE = new Size(10d, SizeUnit.cm);
public static Size SPACING = new Size(0.1d, SizeUnit.in); public static Size SPACING = new Size(0.1d, SizeUnit.in);
public static Color COLOR = Color.black; public static Color COLOR = Color.black;
public static String DEFAULT_TEXT = "No components to show in the Bill of Materials"; public static String DEFAULT_TEXT = "No components to show in the Bill of Materials";
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private Size size = DEFAULT_SIZE; private Size size = DEFAULT_SIZE;
private Point2D.Double point = new Point2D.Double(0, 0); private Point2D.Double point = new Point2D.Double(0, 0);
private Color color = COLOR; private Color color = COLOR;
@Override @Override
public String getControlPointNodeName(int index) { public String getControlPointNodeName(int index) {
return null; return null;
} }
@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) {
List<BomEntry> bom = BomMaker.getInstance().createBom(project.getComponents()); List<BomEntry> bom = BomMaker.getInstance().createBom(project.getComponents());
// Cleanup entries that do not have a value set. // Cleanup entries that do not have a value set.
Iterator<BomEntry> iterator = bom.iterator(); Iterator<BomEntry> iterator = bom.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
BomEntry entry = iterator.next(); BomEntry entry = iterator.next();
if (entry.getValue() == null || entry.getName().toLowerCase().contains("bom")) { if (entry.getValue() == null || entry.getName().toLowerCase().contains("bom")) {
iterator.remove(); iterator.remove();
} }
} }
g2d.setFont(project.getFont()); g2d.setFont(project.getFont());
g2d.setColor(componentState == ComponentState.DRAGGING || componentState == ComponentState.SELECTED ? SELECTION_COLOR g2d.setColor(componentState == ComponentState.DRAGGING || componentState == ComponentState.SELECTED ? SELECTION_COLOR
: getColor()); : getColor());
// Determine maximum name length and maximum value length to calculate // Determine maximum name length and maximum value length to calculate
// number of columns. // number of columns.
FontMetrics fontMetrics = g2d.getFontMetrics(); FontMetrics fontMetrics = g2d.getFontMetrics();
int maxNameWidth = 0; int maxNameWidth = 0;
int maxValueWidth = 0; int maxValueWidth = 0;
int maxHeight = 0; int maxHeight = 0;
for (BomEntry entry : bom) { for (BomEntry entry : bom) {
String valueStr; String valueStr;
if (entry.getValue() == null || entry.getValue().trim().isEmpty()) { if (entry.getValue() == null || entry.getValue().trim().isEmpty()) {
valueStr = "qty " + entry.getQuantity().toString(); valueStr = "qty " + entry.getQuantity().toString();
} else { } else {
valueStr = entry.getValue().toString(); valueStr = entry.getValue().toString();
} }
Rectangle2D stringBounds = fontMetrics.getStringBounds(entry.getName(), g2d); Rectangle2D stringBounds = fontMetrics.getStringBounds(entry.getName(), g2d);
if (stringBounds.getWidth() > maxNameWidth) { if (stringBounds.getWidth() > maxNameWidth) {
maxNameWidth = (int) stringBounds.getWidth(); maxNameWidth = (int) stringBounds.getWidth();
} }
if (stringBounds.getHeight() > maxHeight) { if (stringBounds.getHeight() > maxHeight) {
maxHeight = (int) stringBounds.getHeight(); maxHeight = (int) stringBounds.getHeight();
} }
stringBounds = fontMetrics.getStringBounds(valueStr, g2d); stringBounds = fontMetrics.getStringBounds(valueStr, g2d);
if (stringBounds.getWidth() > maxValueWidth) { if (stringBounds.getWidth() > maxValueWidth) {
maxValueWidth = (int) stringBounds.getWidth(); maxValueWidth = (int) stringBounds.getWidth();
} }
if (stringBounds.getHeight() > maxHeight) { if (stringBounds.getHeight() > maxHeight) {
maxHeight = (int) stringBounds.getHeight(); maxHeight = (int) stringBounds.getHeight();
} }
} }
// Calculate maximum entry size. // Calculate maximum entry size.
int maxEntrySize = maxNameWidth + maxValueWidth + 2 * (int) SPACING.convertToPixels(); int maxEntrySize = maxNameWidth + maxValueWidth + 2 * (int) SPACING.convertToPixels();
int columnCount = (int) size.convertToPixels() / maxEntrySize; int columnCount = (int) size.convertToPixels() / maxEntrySize;
if (columnCount == 0) if (columnCount == 0)
columnCount = 1; columnCount = 1;
int columnWidth = (int) size.convertToPixels() / columnCount; int columnWidth = (int) size.convertToPixels() / columnCount;
int entriesPerColumn = (int) Math.ceil(1.d * bom.size() / columnCount); int entriesPerColumn = (int) Math.ceil(1.d * bom.size() / columnCount);
if (entriesPerColumn == 0) { if (entriesPerColumn == 0) {
g2d.drawString(DEFAULT_TEXT, (int)point.getX(), (int)point.getY()); g2d.drawString(DEFAULT_TEXT, (int) Math.round(point.getX()), (int) Math.round(point.getY()));
return; return;
} }
for (int i = 0; i < bom.size(); i++) { for (int i = 0; i < bom.size(); i++) {
String valueStr; String valueStr;
BomEntry entry = bom.get(i); BomEntry entry = bom.get(i);
if (entry.getValue() == null || entry.getValue().trim().isEmpty()) { if (entry.getValue() == null || entry.getValue().trim().isEmpty()) {
valueStr = "qty " + entry.getQuantity().toString(); valueStr = "qty " + entry.getQuantity().toString();
} else { } else {
valueStr = entry.getValue().toString(); valueStr = entry.getValue().toString();
} }
int columnIndex = i / entriesPerColumn; int columnIndex = i / entriesPerColumn;
int rowIndex = i % entriesPerColumn; int rowIndex = i % entriesPerColumn;
int x = (int)(point.getX() + columnIndex * columnWidth); int x = (int) Math.round(point.getX() + columnIndex * columnWidth);
int y = (int)(point.getY() + rowIndex * maxHeight); int y = (int) Math.round(point.getY() + rowIndex * maxHeight);
g2d.drawString(entry.getName(), x, y); g2d.drawString(entry.getName(), x, y);
x += maxNameWidth + SPACING.convertToPixels(); x += maxNameWidth + SPACING.convertToPixels();
g2d.drawString(valueStr, x, y); g2d.drawString(valueStr, x, y);
} }
} }
@Override @Override
public void drawIcon(Graphics2D g2d, int width, int height) { public void drawIcon(Graphics2D g2d, int width, int height) {
g2d.setColor(Color.white); g2d.setColor(Color.white);
g2d.fillRect(width / 8, 0, 6 * width / 8, height - 1); g2d.fillRect(width / 8, 0, 6 * width / 8, height - 1);
g2d.setColor(Color.black); g2d.setColor(Color.black);
g2d.drawRect(width / 8, 0, 6 * width / 8, height - 1); g2d.drawRect(width / 8, 0, 6 * width / 8, height - 1);
g2d.setFont(LABEL_FONT.deriveFont(1f * 9 * width / 32).deriveFont(Font.PLAIN)); g2d.setFont(LABEL_FONT.deriveFont(1f * 9 * width / 32).deriveFont(Font.PLAIN));
FontMetrics fontMetrics = g2d.getFontMetrics(); FontMetrics fontMetrics = g2d.getFontMetrics();
Rectangle2D rect = fontMetrics.getStringBounds("BOM", g2d); Rectangle2D rect = fontMetrics.getStringBounds("BOM", g2d);
int textHeight = (int) (rect.getHeight()); int textHeight = (int) (rect.getHeight());
int textWidth = (int) (rect.getWidth()); int textWidth = (int) (rect.getWidth());
// Center text horizontally and vertically. // Center text horizontally and vertically.
int x = (width - textWidth) / 2 + 1; int x = (width - textWidth) / 2 + 1;
int y = textHeight + 2; int y = textHeight + 2;
g2d.drawString("BOM", x, y); g2d.drawString("BOM", x, y);
g2d.setFont(g2d.getFont().deriveFont(1f * 5 * width / 32)); g2d.setFont(g2d.getFont().deriveFont(1f * 5 * width / 32));
fontMetrics = g2d.getFontMetrics(); fontMetrics = g2d.getFontMetrics();
rect = fontMetrics.getStringBounds("resistors", g2d); rect = fontMetrics.getStringBounds("resistors", g2d);
x = (width - textWidth) / 2 + 1; x = (width - textWidth) / 2 + 1;
y = height / 2 + 2; y = height / 2 + 2;
g2d.drawString("resistors", x, y); g2d.drawString("resistors", x, y);
y += rect.getHeight() - 1; y += rect.getHeight() - 1;
g2d.drawString("tubes", x, y); g2d.drawString("tubes", x, y);
y += rect.getHeight() - 1; y += rect.getHeight() - 1;
g2d.drawString("diodes", x, y); g2d.drawString("diodes", x, y);
} }
@Override @Override
public int getControlPointCount() { public int getControlPointCount() {
return 1; return 1;
} }
@Override @Override
public Point2D getControlPoint(int index) { public Point2D getControlPoint(int index) {
return point; return point;
} }
@Override @Override
public boolean isControlPointSticky(int index) { public boolean isControlPointSticky(int index) {
return false; return false;
} }
@Override @Override
public VisibilityPolicy getControlPointVisibilityPolicy(int index) { public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
return VisibilityPolicy.NEVER; return VisibilityPolicy.NEVER;
} }
@Override @Override
public void setControlPoint(Point2D point, int index) { public void setControlPoint(Point2D point, int index) {
this.point.setLocation(point); this.point.setLocation(point);
} }
@EditableProperty(name = "Width") @EditableProperty(name = "Width")
public Size getSize() { public Size getSize() {
return size; return size;
} }
public void setSize(Size size) { public void setSize(Size size) {
this.size = size; this.size = size;
} }
@EditableProperty @EditableProperty
public Color getColor() { public Color getColor() {
if (color == null) { if (color == null) {
color = COLOR; color = COLOR;
} }
return color; return color;
} }
public void setColor(Color color) { public void setColor(Color color) {
this.color = color; this.color = color;
} }
@Override @Override
public Void getValue() { public Void getValue() {
return null; return null;
} }
@Override @Override
public void setValue(Void value) {} public void setValue(Void value) {}
} }
@@ -161,7 +161,7 @@ public class Image extends AbstractTransparentComponent<Void> {
@Override @Override
public void drawIcon(Graphics2D g2d, int width, int height) { public void drawIcon(Graphics2D g2d, int width, int height) {
g2d.drawImage(ICON.getImage(), (int)point.getX(), (int)point.getY(), null); g2d.drawImage(ICON.getImage(), (int) Math.round(point.getX()), (int) Math.round(point.getY()), null);
} }
@Override @Override
@@ -75,7 +75,7 @@ public class Loadline extends AbstractBoard {
Composite oldComposite = applyAlpha(g2d, componentState); Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(boardColor); g2d.setColor(boardColor);
g2d.fillRect((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(finalSecondPoint.getX() - firstPoint.getX()), g2d.fillRect((int) Math.round(firstPoint.getX()), (int) Math.round(firstPoint.getY()), (int)(finalSecondPoint.getX() - firstPoint.getX()),
(int)(finalSecondPoint.getY() - firstPoint.getY())); (int)(finalSecondPoint.getY() - firstPoint.getY()));
g2d.setComposite(oldComposite); g2d.setComposite(oldComposite);
@@ -88,7 +88,7 @@ public class Loadline extends AbstractBoard {
? SELECTION_COLOR ? SELECTION_COLOR
: borderColor); : borderColor);
g2d.drawRect((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(finalSecondPoint.getX() - firstPoint.getX()), g2d.drawRect((int) Math.round(firstPoint.getX()), (int) Math.round(firstPoint.getY()), (int)(finalSecondPoint.getX() - firstPoint.getX()),
(int)(finalSecondPoint.getY() - firstPoint.getY())); (int)(finalSecondPoint.getY() - firstPoint.getY()));
} }
@@ -212,8 +212,8 @@ public class AudioTransformer extends AbstractMultiPartComponent<String> impleme
body = new Area[2]; body = new Area[2];
double leadSpacing = this.leadSpacing.convertToPixels(); double leadSpacing = this.leadSpacing.convertToPixels();
double windingSpacing = this.windingSpacing.convertToPixels(); double windingSpacing = this.windingSpacing.convertToPixels();
double centerX = (int) (controlPoints[0].getX() + windingSpacing / 2); double centerX = (int) Math.round(controlPoints[0].getX() + windingSpacing / 2);
double centerY = (int) (controlPoints[0].getY() + leadSpacing); double centerY = (int) Math.round(controlPoints[0].getY() + leadSpacing);
int coreWidth = getClosestOdd(this.coreWidth.convertToPixels()); int coreWidth = getClosestOdd(this.coreWidth.convertToPixels());
int coreThickness = getClosestOdd(this.coreThickness.convertToPixels()); int coreThickness = getClosestOdd(this.coreThickness.convertToPixels());
int coilWidth = getClosestOdd(this.coilWidth.convertToPixels()); int coilWidth = getClosestOdd(this.coilWidth.convertToPixels());
@@ -271,9 +271,9 @@ public class AudioTransformer extends AbstractMultiPartComponent<String> impleme
int pinSize = (int) PIN_SIZE.convertToPixels() / 2 * 2; int pinSize = (int) PIN_SIZE.convertToPixels() / 2 * 2;
for (Point2D point : controlPoints) { for (Point2D point : controlPoints) {
g2d.setColor(PIN_COLOR); g2d.setColor(PIN_COLOR);
g2d.fillOval((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize); g2d.fillOval((int) Math.round(point.getX() - pinSize / 2), (int) Math.round(point.getY() - pinSize / 2), pinSize, pinSize);
g2d.setColor(PIN_BORDER_COLOR); g2d.setColor(PIN_BORDER_COLOR);
g2d.drawOval((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize); g2d.drawOval((int) Math.round(point.getX() - pinSize / 2), (int) Math.round(point.getY() - pinSize / 2), pinSize, pinSize);
} }
} }
Composite oldComposite = applyAlpha(g2d, componentState); Composite oldComposite = applyAlpha(g2d, componentState);
@@ -176,7 +176,7 @@ public class BoxTrimmer extends AbstractTransparentComponent<Resistance> {
// Draw pins // Draw pins
g2d.setColor(outlineMode ? theme.getOutlineColor() : PIN_COLOR); g2d.setColor(outlineMode ? theme.getOutlineColor() : PIN_COLOR);
for (Point2D p : controlPoints) { for (Point2D p : controlPoints) {
g2d.fillOval((int) p.getX() - 2, (int) p.getY() - 2, 4, 4); g2d.fillOval((int) Math.round(p.getX()) - 2, (int) Math.round(p.getY()) - 2, 4, 4);
} }
// Draw label - position outside body for readability // Draw label - position outside body for readability
@@ -425,7 +425,7 @@ public class MiniaturePotentiometer extends AbstractPotentiometer {
int x = (panelWidth - textWidth) / 2; int x = (panelWidth - textWidth) / 2;
int y = (panelHeight - textHeight) / 2 + fontMetrics.getAscent(); int y = (panelHeight - textHeight) / 2 + fontMetrics.getAscent();
g2d.drawString(label, (int) (bodyRect.getX() + x), (int) (bodyRect.getY() + y)); g2d.drawString(label, (int) Math.round(bodyRect.getX() + x), (int) Math.round(bodyRect.getY() + y));
} }
@Override @Override
@@ -381,10 +381,10 @@ public class MultiSectionCapacitor extends AbstractLabeledComponent<Capacitance[
for (Point2D point : controlPoints) { for (Point2D point : controlPoints) {
if (!outlineMode) { if (!outlineMode) {
g2d.setColor(pinColor); g2d.setColor(pinColor);
g2d.fillOval((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize); g2d.fillOval((int) Math.round(point.getX() - pinSize / 2), (int) Math.round(point.getY() - pinSize / 2), pinSize, pinSize);
} }
g2d.setColor(outlineMode ? theme.getOutlineColor() : pinColor.darker()); g2d.setColor(outlineMode ? theme.getOutlineColor() : pinColor.darker());
g2d.drawOval((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize); g2d.drawOval((int) Math.round(point.getX() - pinSize / 2), (int) Math.round(point.getY() - pinSize / 2), pinSize, pinSize);
} }
// Draw label. // Draw label.
@@ -345,7 +345,7 @@ public class PotentiometerPanel extends AbstractPotentiometer implements ILayere
int x = (panelWidth - textWidth) / 2; int x = (panelWidth - textWidth) / 2;
int y = panelHeight / 2 - textHeight + fontMetrics.getAscent(); int y = panelHeight / 2 - textHeight + fontMetrics.getAscent();
g2d.drawString(getName(), (int) (bodyRect.getX() + x), (int) (bodyRect.getY() + y)); g2d.drawString(getName(), (int) Math.round(bodyRect.getX() + x), (int) Math.round(bodyRect.getY() + y));
// Draw value. // Draw value.
rect = fontMetrics.getStringBounds(getValueForDisplay(), g2d); rect = fontMetrics.getStringBounds(getValueForDisplay(), g2d);
@@ -356,7 +356,7 @@ public class PotentiometerPanel extends AbstractPotentiometer implements ILayere
x = (panelWidth - textWidth) / 2; x = (panelWidth - textWidth) / 2;
y = panelHeight / 2 + fontMetrics.getAscent(); y = panelHeight / 2 + fontMetrics.getAscent();
g2d.drawString(getValueForDisplay(), (int) (bodyRect.getX() + x), (int) (bodyRect.getY() + y)); g2d.drawString(getValueForDisplay(), (int) Math.round(bodyRect.getX() + x), (int) Math.round(bodyRect.getY() + y));
// Draw markers if enabled. // Draw markers if enabled.
if (getShowMarkers()) { if (getShowMarkers()) {
@@ -1,182 +1,182 @@
/* /*
DIY Layout Creator (DIYLC). DIY Layout Creator (DIYLC).
Copyright (c) 2009-2025 held jointly by the individual authors. Copyright (c) 2009-2025 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 DIYLC is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
DIYLC is distributed in the hope that it will be useful, DIYLC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with DIYLC. If not, see <http://www.gnu.org/licenses/>. along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.diylc.components.passive; package org.diylc.components.passive;
import java.awt.Color; import java.awt.Color;
import java.awt.FontMetrics; import java.awt.FontMetrics;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Polygon; import java.awt.Polygon;
import java.awt.Shape; import java.awt.Shape;
import java.awt.geom.GeneralPath; import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import org.diylc.components.Abstract3LegSymbol; import org.diylc.components.Abstract3LegSymbol;
import org.diylc.components.semiconductors.SymbolFlipping; import org.diylc.components.semiconductors.SymbolFlipping;
import org.diylc.components.transform.ThreeLegTransformer; import org.diylc.components.transform.ThreeLegTransformer;
import org.diylc.core.IDIYComponent; import org.diylc.core.IDIYComponent;
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;
@ComponentDescriptor(name = "Potentiometer", author = "MCbx", category = "Schematic Symbols", @ComponentDescriptor(name = "Potentiometer", author = "MCbx", category = "Schematic Symbols",
instanceNamePrefix = "VR", description = "Potentiometer symbol", instanceNamePrefix = "VR", description = "Potentiometer symbol",
zOrder = IDIYComponent.COMPONENT, transformer = ThreeLegTransformer.class, keywordPolicy = KeywordPolicy.SHOW_TAG, zOrder = IDIYComponent.COMPONENT, transformer = ThreeLegTransformer.class, keywordPolicy = KeywordPolicy.SHOW_TAG,
keywordTag = "Schematic") keywordTag = "Schematic")
public class PotentiometerSymbol extends Abstract3LegSymbol { public class PotentiometerSymbol extends Abstract3LegSymbol {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private DrawStyle drawStyle = DrawStyle.ANSI; private DrawStyle drawStyle = DrawStyle.ANSI;
public PotentiometerSymbol() { public PotentiometerSymbol() {
this.color = Color.blue; this.color = Color.blue;
} }
@EditableProperty(name = "Draw Standard") @EditableProperty(name = "Draw Standard")
public DrawStyle getDrawStandard() { public DrawStyle getDrawStandard() {
if (drawStyle == null) { if (drawStyle == null) {
drawStyle = DrawStyle.ANSI; drawStyle = DrawStyle.ANSI;
} }
return drawStyle; return drawStyle;
} }
public void setDrawStandard(DrawStyle drawStyle) { public void setDrawStandard(DrawStyle drawStyle) {
this.drawStyle = drawStyle; this.drawStyle = drawStyle;
body = null; body = null;
} }
public Shape[] getBody() { public Shape[] getBody() {
Shape[] body = new Shape[3]; Shape[] body = new Shape[3];
Point2D[] controlPoints = getControlPoints(); Point2D[] controlPoints = getControlPoints();
double x = controlPoints[0].getX(); double x = controlPoints[0].getX();
double y = controlPoints[0].getY(); double y = controlPoints[0].getY();
int pinSpacing = (int) PIN_SPACING.convertToPixels(); int pinSpacing = (int) PIN_SPACING.convertToPixels();
GeneralPath polyline = new GeneralPath(); GeneralPath polyline = new GeneralPath();
// Draw lead in // Draw lead in
polyline.moveTo(x + pinSpacing * 2, y - pinSpacing * 2); polyline.moveTo(x + pinSpacing * 2, y - pinSpacing * 2);
polyline.lineTo(x + pinSpacing * 2, y - pinSpacing * 2 + pinSpacing / 2); polyline.lineTo(x + pinSpacing * 2, y - pinSpacing * 2 + pinSpacing / 2);
if (getDrawStandard() == DrawStyle.ANSI) { if (getDrawStandard() == DrawStyle.ANSI) {
// Draw ZigZag and lead out // Draw ZigZag and lead out
polyline.lineTo(x + pinSpacing * 2 - pinSpacing / 4, (y - pinSpacing * 2) + pinSpacing / 2 + pinSpacing / 4); polyline.lineTo(x + pinSpacing * 2 - pinSpacing / 4, (y - pinSpacing * 2) + pinSpacing / 2 + pinSpacing / 4);
polyline.lineTo(x + pinSpacing * 2 + pinSpacing / 4, (y - pinSpacing * 2) + 2 * pinSpacing / 2); polyline.lineTo(x + pinSpacing * 2 + pinSpacing / 4, (y - pinSpacing * 2) + 2 * pinSpacing / 2);
polyline.lineTo(x + pinSpacing * 2 - pinSpacing / 4, (y - pinSpacing * 2) + 3 * pinSpacing / 2 - pinSpacing / 8); polyline.lineTo(x + pinSpacing * 2 - pinSpacing / 4, (y - pinSpacing * 2) + 3 * pinSpacing / 2 - pinSpacing / 8);
polyline.lineTo(x + pinSpacing * 2 + pinSpacing / 4, (y - pinSpacing * 2) + 4 * pinSpacing / 2 - pinSpacing / 4); polyline.lineTo(x + pinSpacing * 2 + pinSpacing / 4, (y - pinSpacing * 2) + 4 * pinSpacing / 2 - pinSpacing / 4);
polyline.lineTo(x + pinSpacing * 2 - pinSpacing / 4, (y - pinSpacing * 2) + 5 * pinSpacing / 2 - pinSpacing / 3 polyline.lineTo(x + pinSpacing * 2 - pinSpacing / 4, (y - pinSpacing * 2) + 5 * pinSpacing / 2 - pinSpacing / 3
- pinSpacing / 16); - pinSpacing / 16);
polyline.lineTo(x + pinSpacing * 2 + pinSpacing / 4, (y - pinSpacing * 2) + 6 * pinSpacing / 2 - pinSpacing / 2 polyline.lineTo(x + pinSpacing * 2 + pinSpacing / 4, (y - pinSpacing * 2) + 6 * pinSpacing / 2 - pinSpacing / 2
+ pinSpacing / 16); + pinSpacing / 16);
polyline.lineTo(x + pinSpacing * 2 - pinSpacing / 4, (y - pinSpacing * 2) + 7 * pinSpacing / 2 - pinSpacing / 2 polyline.lineTo(x + pinSpacing * 2 - pinSpacing / 4, (y - pinSpacing * 2) + 7 * pinSpacing / 2 - pinSpacing / 2
- pinSpacing / 16); - pinSpacing / 16);
polyline.lineTo(x + pinSpacing * 2 + pinSpacing / 4, (y - pinSpacing * 2) + 7 * pinSpacing / 2 - pinSpacing / 2 polyline.lineTo(x + pinSpacing * 2 + pinSpacing / 4, (y - pinSpacing * 2) + 7 * pinSpacing / 2 - pinSpacing / 2
+ pinSpacing / 4); + pinSpacing / 4);
polyline.lineTo(x + pinSpacing * 2, (y - pinSpacing * 2) + 7 * pinSpacing / 2); polyline.lineTo(x + pinSpacing * 2, (y - pinSpacing * 2) + 7 * pinSpacing / 2);
polyline.lineTo(x + pinSpacing * 2, y + pinSpacing * 2); polyline.lineTo(x + pinSpacing * 2, y + pinSpacing * 2);
} else { } else {
// Draw a rect and lead out // Draw a rect and lead out
polyline.moveTo(x + pinSpacing * 1.7, y - pinSpacing * 2 + pinSpacing / 2); polyline.moveTo(x + pinSpacing * 1.7, y - pinSpacing * 2 + pinSpacing / 2);
polyline.lineTo(x + pinSpacing * 2.3, y - pinSpacing * 2 + pinSpacing / 2); polyline.lineTo(x + pinSpacing * 2.3, y - pinSpacing * 2 + pinSpacing / 2);
polyline.lineTo(x + pinSpacing * 2.3, y + pinSpacing * 2 - pinSpacing / 2); polyline.lineTo(x + pinSpacing * 2.3, y + pinSpacing * 2 - pinSpacing / 2);
polyline.lineTo(x + pinSpacing * 1.7, y + pinSpacing * 2 - pinSpacing / 2); polyline.lineTo(x + pinSpacing * 1.7, y + pinSpacing * 2 - pinSpacing / 2);
polyline.lineTo(x + pinSpacing * 1.7, y - pinSpacing * 2 + pinSpacing / 2); polyline.lineTo(x + pinSpacing * 1.7, y - pinSpacing * 2 + pinSpacing / 2);
polyline.moveTo(x + pinSpacing * 2, y + pinSpacing * 2 - pinSpacing / 2); polyline.moveTo(x + pinSpacing * 2, y + pinSpacing * 2 - pinSpacing / 2);
polyline.lineTo(x + pinSpacing * 2, y + pinSpacing * 2); polyline.lineTo(x + pinSpacing * 2, y + pinSpacing * 2);
} }
// The control line // The control line
polyline.moveTo(x, y); polyline.moveTo(x, y);
polyline.lineTo(x + pinSpacing * 2 - pinSpacing / 2, y); polyline.lineTo(x + pinSpacing * 2 - pinSpacing / 2, y);
body[1] = polyline; body[1] = polyline;
polyline = new GeneralPath(); polyline = new GeneralPath();
body[0] = polyline; body[0] = polyline;
// Arrow // Arrow
polyline = new GeneralPath(); polyline = new GeneralPath();
polyline.moveTo(x + pinSpacing * 2 - pinSpacing / 3, y); polyline.moveTo(x + pinSpacing * 2 - pinSpacing / 3, y);
polyline.lineTo(x + pinSpacing * 2 - pinSpacing * 2 / 3, y - pinSpacing / 3); polyline.lineTo(x + pinSpacing * 2 - pinSpacing * 2 / 3, y - pinSpacing / 3);
polyline.lineTo(x + pinSpacing * 2 - pinSpacing * 2 / 3, y + pinSpacing / 3); polyline.lineTo(x + pinSpacing * 2 - pinSpacing * 2 / 3, y + pinSpacing / 3);
polyline.lineTo(x + pinSpacing * 2 - pinSpacing / 3, y); polyline.lineTo(x + pinSpacing * 2 - pinSpacing / 3, y);
body[2] = polyline; body[2] = polyline;
return body; return body;
} }
@Override @Override
protected double getLabelX(Rectangle2D shapeRect, Rectangle2D textRect, FontMetrics fontMetrics, boolean outlineMode) { protected double getLabelX(Rectangle2D shapeRect, Rectangle2D textRect, FontMetrics fontMetrics, boolean outlineMode) {
double x = super.getLabelX(shapeRect, textRect, fontMetrics, outlineMode); double x = super.getLabelX(shapeRect, textRect, fontMetrics, outlineMode);
if (getFlip() == SymbolFlipping.X) if (getFlip() == SymbolFlipping.X)
return x - (int) (PIN_SPACING.convertToPixels() / 2); return x - (int) (PIN_SPACING.convertToPixels() / 2);
return x + (int) PIN_SPACING.convertToPixels(); return x + (int) PIN_SPACING.convertToPixels();
} }
// @Override // @Override
// protected int getLabelX(Rectangle2D shapeRect, Rectangle2D textRect, FontMetrics fontMetrics, // protected int getLabelX(Rectangle2D shapeRect, Rectangle2D textRect, FontMetrics fontMetrics,
// boolean outlineMode) { // boolean outlineMode) {
// int pinSpacing = (int) PIN_SPACING.convertToPixels(); // int pinSpacing = (int) PIN_SPACING.convertToPixels();
// if (controlPoints[0].x < controlPoints[1].x && controlPoints[0].x < controlPoints[2].x) // if (controlPoints[0].x < controlPoints[1].x && controlPoints[0].x < controlPoints[2].x)
// return controlPoints[1].x + pinSpacing / 3; // return controlPoints[1].x + pinSpacing / 3;
// if (controlPoints[0].y < controlPoints[1].y && controlPoints[0].y < controlPoints[2].y) // if (controlPoints[0].y < controlPoints[1].y && controlPoints[0].y < controlPoints[2].y)
// return controlPoints[0].x - (int) (textRect.getWidth() / 2); // return controlPoints[0].x - (int) (textRect.getWidth() / 2);
// if (controlPoints[0].x > controlPoints[1].x && controlPoints[0].x > controlPoints[2].x) // if (controlPoints[0].x > controlPoints[1].x && controlPoints[0].x > controlPoints[2].x)
// return controlPoints[1].x - pinSpacing / 2 - (int) textRect.getWidth(); // return controlPoints[1].x - pinSpacing / 2 - (int) textRect.getWidth();
// if (controlPoints[0].y > controlPoints[1].y && controlPoints[0].y > controlPoints[2].y) // if (controlPoints[0].y > controlPoints[1].y && controlPoints[0].y > controlPoints[2].y)
// return controlPoints[0].x - (int) (textRect.getWidth() / 2); // return controlPoints[0].x - (int) (textRect.getWidth() / 2);
// return 2 * ((int) (shapeRect.getWidth() - textRect.getWidth()) / 2 + (int) shapeRect.getX()); // return 2 * ((int) (shapeRect.getWidth() - textRect.getWidth()) / 2 + (int) Math.round(shapeRect.getX()));
// } // }
// //
// @Override // @Override
// protected int getLabelY(Rectangle2D shapeRect, Rectangle2D textRect, FontMetrics fontMetrics, // protected int getLabelY(Rectangle2D shapeRect, Rectangle2D textRect, FontMetrics fontMetrics,
// boolean outlineMode) { // boolean outlineMode) {
// int pinSpacing = (int) PIN_SPACING.convertToPixels(); // int pinSpacing = (int) PIN_SPACING.convertToPixels();
// if (controlPoints[0].x < controlPoints[1].x && controlPoints[0].x < controlPoints[2].x) // if (controlPoints[0].x < controlPoints[1].x && controlPoints[0].x < controlPoints[2].x)
// return controlPoints[0].y; // return controlPoints[0].y;
// if (controlPoints[0].y < controlPoints[1].y && controlPoints[0].y < controlPoints[2].y) // if (controlPoints[0].y < controlPoints[1].y && controlPoints[0].y < controlPoints[2].y)
// return controlPoints[1].y + pinSpacing * 2 / 3; // return controlPoints[1].y + pinSpacing * 2 / 3;
// if (controlPoints[0].x > controlPoints[1].x && controlPoints[0].x > controlPoints[2].x) // if (controlPoints[0].x > controlPoints[1].x && controlPoints[0].x > controlPoints[2].x)
// return controlPoints[0].y; // return controlPoints[0].y;
// if (controlPoints[0].y > controlPoints[1].y && controlPoints[0].y > controlPoints[2].y) // if (controlPoints[0].y > controlPoints[1].y && controlPoints[0].y > controlPoints[2].y)
// return controlPoints[1].y - pinSpacing * 2 / 3; // return controlPoints[1].y - pinSpacing * 2 / 3;
// return 2 * ((int) (shapeRect.getHeight() - textRect.getHeight()) / 2 + fontMetrics.getAscent() // return 2 * ((int) (shapeRect.getHeight() - textRect.getHeight()) / 2 + fontMetrics.getAscent()
// + (int) shapeRect // + (int) shapeRect
// .getY()); // .getY());
// } // }
@Override @Override
public void drawIcon(Graphics2D g2d, int width, int height) { public void drawIcon(Graphics2D g2d, int width, int height) {
g2d.rotate(-Math.PI / 4, width / 2, height / 2); g2d.rotate(-Math.PI / 4, width / 2, height / 2);
g2d.setColor(Color.blue); g2d.setColor(Color.blue);
g2d.drawLine(0, height / 2, 4, height / 2); g2d.drawLine(0, height / 2, 4, height / 2);
g2d.drawLine(width - 4, height / 2, width, height / 2); g2d.drawLine(width - 4, height / 2, width, height / 2);
g2d.drawPolyline(new int[] {4, 6, 10, 14, 18, 22, 26, 28}, new int[] {height / 2, height / 2 + 2, height / 2 - 2, g2d.drawPolyline(new int[] {4, 6, 10, 14, 18, 22, 26, 28}, new int[] {height / 2, height / 2 + 2, height / 2 - 2,
height / 2 + 2, height / 2 - 2, height / 2 + 2, height / 2 - 2, height / 2}, 8); height / 2 + 2, height / 2 - 2, height / 2 + 2, height / 2 - 2, height / 2}, 8);
g2d.drawPolyline(new int[] {width / 2, width / 2 - 2}, new int[] {height, height / 2 + 2}, 2); g2d.drawPolyline(new int[] {width / 2, width / 2 - 2}, new int[] {height, height / 2 + 2}, 2);
g2d.fill(new Polygon(new int[] {width / 2 - 4, width / 2 + 2, width / 2 - 2}, new int[] {height / 2 + 6, g2d.fill(new Polygon(new int[] {width / 2 - 4, width / 2 + 2, width / 2 - 2}, new int[] {height / 2 + 6,
height / 2 + 6, height / 2 + 2}, 3)); height / 2 + 6, height / 2 + 2}, 3));
} }
public enum DrawStyle { public enum DrawStyle {
ANSI, IEC ANSI, IEC
} }
} }
@@ -405,10 +405,10 @@ public class TrimmerPotentiometer extends AbstractPotentiometer {
for (Point2D point : controlPoints) { for (Point2D point : controlPoints) {
if (!outlineMode) { if (!outlineMode) {
g2d.setColor(PIN_COLOR); g2d.setColor(PIN_COLOR);
g2d.fillOval((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize); g2d.fillOval((int) Math.round(point.getX() - pinSize / 2), (int) Math.round(point.getY() - pinSize / 2), pinSize, pinSize);
} }
g2d.setColor(outlineMode ? theme.getOutlineColor() : PIN_BORDER_COLOR); g2d.setColor(outlineMode ? theme.getOutlineColor() : PIN_BORDER_COLOR);
g2d.drawOval((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize); g2d.drawOval((int) Math.round(point.getX() - pinSize / 2), (int) Math.round(point.getY() - pinSize / 2), pinSize, pinSize);
} }
// Draw label. // Draw label.
@@ -451,7 +451,7 @@ public class TrimmerPotentiometer extends AbstractPotentiometer {
int x = (panelWidth - textWidth) / 2; int x = (panelWidth - textWidth) / 2;
int y = (panelHeight - textHeight) / 2 + fontMetrics.getAscent(); int y = (panelHeight - textHeight) / 2 + fontMetrics.getAscent();
g2d.drawString(label, (int) (bodyRect.getX() + x), (int) (bodyRect.getY() + y)); g2d.drawString(label, (int) Math.round(bodyRect.getX() + x), (int) Math.round(bodyRect.getY() + y));
} }
@Override @Override
@@ -237,9 +237,9 @@ public class DIL_IC extends AbstractLabeledComponent<String> implements IGerberC
throw new RuntimeException("Unexpected orientation: " + orientation); throw new RuntimeException("Unexpected orientation: " + orientation);
} }
controlPoints[i] = controlPoints[i] =
new Point2D.Double((int) (firstPoint.getX() + dx1), (int) (firstPoint.getY() + dy1)); new Point2D.Double((int) Math.round(firstPoint.getX() + dx1), (int) Math.round(firstPoint.getY() + dy1));
controlPoints[i + pinCount.getValue() / 2] = controlPoints[i + pinCount.getValue() / 2] =
new Point2D.Double((int) (firstPoint.getX() + dx2), (int) (firstPoint.getY() + dy2)); new Point2D.Double((int) Math.round(firstPoint.getX() + dx2), (int) Math.round(firstPoint.getY() + dy2));
} }
} }
@@ -431,10 +431,10 @@ public class DIL_IC extends AbstractLabeledComponent<String> implements IGerberC
Point2D point = controlPoints[i]; Point2D point = controlPoints[i];
// determine points relative to rotation // determine points relative to rotation
int textX1 = (int) (point.getX() - 2 * pinSize); int textX1 = (int) Math.round(point.getX() - 2 * pinSize);
int textY1 = (int) (point.getY() + pinSize / 2); int textY1 = (int) Math.round(point.getY() + pinSize / 2);
int textX2 = (int) (point.getX() + pinSize); int textX2 = (int) Math.round(point.getX() + pinSize);
int textY2 = (int) (point.getY() + pinSize / 2); int textY2 = (int) Math.round(point.getY() + pinSize / 2);
if (orientation == Orientation._90) { if (orientation == Orientation._90) {
textX2 = textX2 - pinSize - pinSize / 2; textX2 = textX2 - pinSize - pinSize / 2;
textY2 = textY2 + pinSize; textY2 = textY2 + pinSize;
@@ -202,7 +202,7 @@ public class MultiwattIC extends AbstractTransparentComponent<String> implements
default: default:
throw new RuntimeException("Unexpected orientation: " + orientation); throw new RuntimeException("Unexpected orientation: " + orientation);
} }
controlPoints[i] = new Point2D.Double((int) (firstPoint.getX() + dx1), (int) (firstPoint.getY() + dy1)); controlPoints[i] = new Point2D.Double((int) Math.round(firstPoint.getX() + dx1), (int) Math.round(firstPoint.getY() + dy1));
} }
// Right side pins (second row, staggered - offset by half pin spacing) // Right side pins (second row, staggered - offset by half pin spacing)
@@ -227,7 +227,7 @@ public class MultiwattIC extends AbstractTransparentComponent<String> implements
default: default:
throw new RuntimeException("Unexpected orientation: " + orientation); throw new RuntimeException("Unexpected orientation: " + orientation);
} }
controlPoints[i + pinsLeft] = new Point2D.Double((int) (firstPoint.getX() + dx2), (int) (firstPoint.getY() + dy2)); controlPoints[i + pinsLeft] = new Point2D.Double((int) Math.round(firstPoint.getX() + dx2), (int) Math.round(firstPoint.getY() + dy2));
} }
} }
@@ -216,7 +216,7 @@ public class SIL_IC extends AbstractTransparentComponent<String> implements IGer
default: default:
throw new RuntimeException("Unexpected orientation: " + orientation); throw new RuntimeException("Unexpected orientation: " + orientation);
} }
controlPoints[i] = new Point2D.Double((int) (firstPoint.getX() + dx1), (int) (firstPoint.getY() + dy1)); controlPoints[i] = new Point2D.Double((int) Math.round(firstPoint.getX() + dx1), (int) Math.round(firstPoint.getY() + dy1));
} }
} }
@@ -293,9 +293,9 @@ public class SIL_IC extends AbstractTransparentComponent<String> implements IGer
int pinSize = (int) PIN_SIZE.convertToPixels() / 2 * 2; int pinSize = (int) PIN_SIZE.convertToPixels() / 2 * 2;
for (Point2D point : controlPoints) { for (Point2D point : controlPoints) {
g2d.setColor(PIN_COLOR); g2d.setColor(PIN_COLOR);
g2d.fillOval((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize); g2d.fillOval((int) Math.round(point.getX() - pinSize / 2), (int) Math.round(point.getY() - pinSize / 2), pinSize, pinSize);
g2d.setColor(PIN_BORDER_COLOR); g2d.setColor(PIN_BORDER_COLOR);
g2d.drawOval((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize); g2d.drawOval((int) Math.round(point.getX() - pinSize / 2), (int) Math.round(point.getY() - pinSize / 2), pinSize, pinSize);
} }
} }
@@ -236,10 +236,10 @@ public class TransistorTO3 extends AbstractLabeledComponent<String> {
for (Point2D point : controlPoints) { for (Point2D point : controlPoints) {
if (!outlineMode) { if (!outlineMode) {
g2d.setColor(PIN_COLOR); g2d.setColor(PIN_COLOR);
g2d.fillOval((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize); g2d.fillOval((int) Math.round(point.getX() - pinSize / 2), (int) Math.round(point.getY() - pinSize / 2), pinSize, pinSize);
} }
g2d.setColor(outlineMode ? theme.getOutlineColor() : PIN_BORDER_COLOR); g2d.setColor(outlineMode ? theme.getOutlineColor() : PIN_BORDER_COLOR);
g2d.drawOval((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize); g2d.drawOval((int) Math.round(point.getX() - pinSize / 2), (int) Math.round(point.getY() - pinSize / 2), pinSize, pinSize);
} }
Area mainArea = getBody()[0]; Area mainArea = getBody()[0];
@@ -49,7 +49,7 @@ public class Ellipse extends AbstractShapeWithDimensions {
Composite oldComposite = applyAlpha(g2d, componentState); Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(color); g2d.setColor(color);
g2d.fillOval((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(secondPoint.getX() - firstPoint.getX()), (int)(secondPoint.getY() - firstPoint.getY())); g2d.fillOval((int) Math.round(firstPoint.getX()), (int) Math.round(firstPoint.getY()), (int)(secondPoint.getX() - firstPoint.getX()), (int)(secondPoint.getY() - firstPoint.getY()));
g2d.setComposite(oldComposite); g2d.setComposite(oldComposite);
// Do not track any changes that follow because the whole oval has been // Do not track any changes that follow because the whole oval has been
@@ -57,7 +57,7 @@ public class Ellipse extends AbstractShapeWithDimensions {
drawingObserver.stopTracking(); drawingObserver.stopTracking();
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: borderColor); : borderColor);
g2d.drawOval((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(secondPoint.getX() - firstPoint.getX()), (int)(secondPoint.getY() - firstPoint.getY())); g2d.drawOval((int) Math.round(firstPoint.getX()), (int) Math.round(firstPoint.getY()), (int)(secondPoint.getX() - firstPoint.getX()), (int)(secondPoint.getY() - firstPoint.getY()));
} }
@Override @Override
@@ -55,7 +55,7 @@ public class Rectangle extends AbstractShapeWithDimensions {
Composite oldComposite = applyAlpha(g2d, componentState); Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(color); g2d.setColor(color);
g2d.fillRoundRect((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(secondPoint.getX() - firstPoint.getX()), (int)(secondPoint.getY() - firstPoint.getY()), radius, g2d.fillRoundRect((int) Math.round(firstPoint.getX()), (int) Math.round(firstPoint.getY()), (int)(secondPoint.getX() - firstPoint.getX()), (int)(secondPoint.getY() - firstPoint.getY()), radius,
radius); radius);
g2d.setComposite(oldComposite); g2d.setComposite(oldComposite);
@@ -64,7 +64,7 @@ public class Rectangle extends AbstractShapeWithDimensions {
drawingObserver.stopTracking(); drawingObserver.stopTracking();
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: borderColor); : borderColor);
g2d.drawRoundRect((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(secondPoint.getX() - firstPoint.getX()), (int)(secondPoint.getY() - firstPoint.getY()), radius, g2d.drawRoundRect((int) Math.round(firstPoint.getX()), (int) Math.round(firstPoint.getY()), (int)(secondPoint.getX() - firstPoint.getX()), (int)(secondPoint.getY() - firstPoint.getY()), radius,
radius); radius);
} }
@@ -158,11 +158,11 @@ public class TapeMeasure extends AbstractLeadedComponent<String> {
int legLength = (int) (getPoints()[0].distance(getPoints()[1]) - strWidth) / 2 - 6; int legLength = (int) (getPoints()[0].distance(getPoints()[1]) - strWidth) / 2 - 6;
// draw legs around the enter text // draw legs around the enter text
g2d.drawLine((int)startPoint.getX(), (int)startPoint.getY(), g2d.drawLine((int) Math.round(startPoint.getX()), (int) Math.round(startPoint.getY()),
(int)Math.round(startPoint.getX() + Math.cos(theta) * legLength), (int)Math.round(startPoint.getX() + Math.cos(theta) * legLength),
(int)Math.round(startPoint.getY() + Math.sin(theta) * legLength)); (int)Math.round(startPoint.getY() + Math.sin(theta) * legLength));
g2d.drawLine((int)endPoint.getX(), (int)endPoint.getY(), g2d.drawLine((int) Math.round(endPoint.getX()), (int) Math.round(endPoint.getY()),
(int)Math.round(endPoint.getX() - Math.cos(theta) * legLength), (int)Math.round(endPoint.getX() - Math.cos(theta) * legLength),
(int)Math.round(endPoint.getY() - Math.sin(theta) * legLength)); (int)Math.round(endPoint.getY() - Math.sin(theta) * legLength));
@@ -365,43 +365,43 @@ public class SubminiTube extends AbstractLabeledComponent<String> {
case DEFAULT: case DEFAULT:
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
g2d.setColor(finalPinBorderColor); g2d.setColor(finalPinBorderColor);
g2d.drawLine((int)point.getX(), (int)point.getY(), (int)(point.getX() - leadLength - leadThickness / 2), (int)(startY + increment * i)); g2d.drawLine((int) Math.round(point.getX()), (int) Math.round(point.getY()), (int) Math.round(point.getX() - leadLength - leadThickness / 2), (int)(startY + increment * i));
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2));
g2d.setColor(finalPinColor); g2d.setColor(finalPinColor);
g2d.drawLine((int)point.getX(), (int)point.getY(), (int)(point.getX() - leadLength - leadThickness / 2), (int)(startY + increment * i)); g2d.drawLine((int) Math.round(point.getX()), (int) Math.round(point.getY()), (int) Math.round(point.getX() - leadLength - leadThickness / 2), (int)(startY + increment * i));
break; break;
case _90: case _90:
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
g2d.setColor(finalPinBorderColor); g2d.setColor(finalPinBorderColor);
g2d.drawLine((int)point.getX(), (int)point.getY(), (int)(startX + increment * i), (int)(point.getY() - leadLength)); g2d.drawLine((int) Math.round(point.getX()), (int) Math.round(point.getY()), (int)(startX + increment * i), (int) Math.round(point.getY() - leadLength));
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2));
g2d.setColor(finalPinColor); g2d.setColor(finalPinColor);
g2d.drawLine((int)point.getX(), (int)point.getY(), (int)(startX + increment * i), (int)(point.getY() - leadLength)); g2d.drawLine((int) Math.round(point.getX()), (int) Math.round(point.getY()), (int)(startX + increment * i), (int) Math.round(point.getY() - leadLength));
break; break;
case _180: case _180:
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
g2d.setColor(finalPinBorderColor); g2d.setColor(finalPinBorderColor);
g2d.drawLine((int)point.getX(), (int)point.getY(), (int)(point.getX() + leadLength - leadThickness / 2), (int)(startY + increment * i)); g2d.drawLine((int) Math.round(point.getX()), (int) Math.round(point.getY()), (int) Math.round(point.getX() + leadLength - leadThickness / 2), (int)(startY + increment * i));
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2));
g2d.setColor(finalPinColor); g2d.setColor(finalPinColor);
g2d.drawLine((int)point.getX(), (int)point.getY(), (int)(point.getX() + leadLength - leadThickness / 2), (int)(startY + increment * i)); g2d.drawLine((int) Math.round(point.getX()), (int) Math.round(point.getY()), (int) Math.round(point.getX() + leadLength - leadThickness / 2), (int)(startY + increment * i));
break; break;
case _270: case _270:
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
g2d.setColor(finalPinBorderColor); g2d.setColor(finalPinBorderColor);
g2d.drawLine((int)point.getX(), (int)point.getY(), (int)(startX + increment * i), (int)(point.getY() + leadLength - leadThickness / 2)); g2d.drawLine((int) Math.round(point.getX()), (int) Math.round(point.getY()), (int)(startX + increment * i), (int) Math.round(point.getY() + leadLength - leadThickness / 2));
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2));
g2d.setColor(finalPinColor); g2d.setColor(finalPinColor);
g2d.drawLine((int)point.getX(), (int)point.getY(), (int)(startX + increment * i), (int)(point.getY() + leadLength - leadThickness / 2)); g2d.drawLine((int) Math.round(point.getX()), (int) Math.round(point.getY()), (int)(startX + increment * i), (int) Math.round(point.getY() + leadLength - leadThickness / 2));
break; break;
} }
} }
if (getTopLead()) { if (getTopLead()) {
Point2D point = controlPoints[controlPoints.length - 1]; Point2D point = controlPoints[controlPoints.length - 1];
g2d.setColor(PIN_COLOR); g2d.setColor(PIN_COLOR);
g2d.fillOval((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize); g2d.fillOval((int) Math.round(point.getX() - pinSize / 2), (int) Math.round(point.getY() - pinSize / 2), pinSize, pinSize);
g2d.setColor(outlineMode ? theme.getOutlineColor() : PIN_BORDER_COLOR); g2d.setColor(outlineMode ? theme.getOutlineColor() : PIN_BORDER_COLOR);
g2d.drawOval((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize); g2d.drawOval((int) Math.round(point.getX() - pinSize / 2), (int) Math.round(point.getY() - pinSize / 2), pinSize, pinSize);
} }
} else { } else {
if (!outlineMode) { if (!outlineMode) {
@@ -409,9 +409,9 @@ public class SubminiTube extends AbstractLabeledComponent<String> {
: 0; i < controlPoints.length; i++) { : 0; i < controlPoints.length; i++) {
Point2D point = controlPoints[i]; Point2D point = controlPoints[i];
g2d.setColor(PIN_COLOR); g2d.setColor(PIN_COLOR);
g2d.fillOval((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize); g2d.fillOval((int) Math.round(point.getX() - pinSize / 2), (int) Math.round(point.getY() - pinSize / 2), pinSize, pinSize);
g2d.setColor(outlineMode ? theme.getOutlineColor() : PIN_BORDER_COLOR); g2d.setColor(outlineMode ? theme.getOutlineColor() : PIN_BORDER_COLOR);
g2d.drawOval((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize); g2d.drawOval((int) Math.round(point.getX() - pinSize / 2), (int) Math.round(point.getY() - pinSize / 2), pinSize, pinSize);
} }
} }
} }
@@ -1,275 +1,275 @@
package org.diylc.editor; package org.diylc.editor;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import org.diylc.common.IProjectEditor; import org.diylc.common.IProjectEditor;
import org.diylc.common.Orientation; import org.diylc.common.Orientation;
import org.diylc.components.AbstractLeadedComponent; import org.diylc.components.AbstractLeadedComponent;
import org.diylc.components.AbstractCurvedComponent.PointCount; import org.diylc.components.AbstractCurvedComponent.PointCount;
import org.diylc.components.connectivity.AWG; import org.diylc.components.connectivity.AWG;
import org.diylc.components.connectivity.HookupWire; import org.diylc.components.connectivity.HookupWire;
import org.diylc.components.guitar.AbstractGuitarPickup; import org.diylc.components.guitar.AbstractGuitarPickup;
import org.diylc.components.guitar.SingleCoilPickup; import org.diylc.components.guitar.SingleCoilPickup;
import org.diylc.components.passive.PotentiometerPanel; import org.diylc.components.passive.PotentiometerPanel;
import org.diylc.components.passive.PotentiometerPanel.Type; import org.diylc.components.passive.PotentiometerPanel.Type;
import org.diylc.components.semiconductors.AbstractTransistorPackage; import org.diylc.components.semiconductors.AbstractTransistorPackage;
import org.diylc.components.semiconductors.TransistorTO126; import org.diylc.components.semiconductors.TransistorTO126;
import org.diylc.components.semiconductors.TransistorTO220; import org.diylc.components.semiconductors.TransistorTO220;
import org.diylc.components.tube.TubeSocket; import org.diylc.components.tube.TubeSocket;
import org.diylc.components.tube.TubeSocket.Mount; import org.diylc.components.tube.TubeSocket.Mount;
import org.diylc.core.IDIYComponent; import org.diylc.core.IDIYComponent;
import org.diylc.core.Project; import org.diylc.core.Project;
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.presenter.InstantiationManager; import org.diylc.presenter.InstantiationManager;
public class FlexibleLeadsEditor implements IProjectEditor { public class FlexibleLeadsEditor implements IProjectEditor {
private InstantiationManager instantiationManager; private InstantiationManager instantiationManager;
@Override @Override
public Set<IDIYComponent<?>> edit(Project project, Set<IDIYComponent<?>> selection) { public Set<IDIYComponent<?>> edit(Project project, Set<IDIYComponent<?>> selection) {
Set<IDIYComponent<?>> newSelection = new HashSet<IDIYComponent<?>>(selection); Set<IDIYComponent<?>> newSelection = new HashSet<IDIYComponent<?>>(selection);
for (IDIYComponent<?> c : selection) { for (IDIYComponent<?> c : selection) {
if (c instanceof AbstractLeadedComponent<?>) if (c instanceof AbstractLeadedComponent<?>)
addLeads((AbstractLeadedComponent<?>) c, project, newSelection); addLeads((AbstractLeadedComponent<?>) c, project, newSelection);
else if (c instanceof AbstractTransistorPackage) else if (c instanceof AbstractTransistorPackage)
addLeads((AbstractTransistorPackage) c, project, newSelection); addLeads((AbstractTransistorPackage) c, project, newSelection);
else if (c instanceof PotentiometerPanel) else if (c instanceof PotentiometerPanel)
addLeads((PotentiometerPanel) c, project, newSelection); addLeads((PotentiometerPanel) c, project, newSelection);
else if (c instanceof TubeSocket) else if (c instanceof TubeSocket)
addLeads((TubeSocket) c, project, newSelection); addLeads((TubeSocket) c, project, newSelection);
else if (c instanceof AbstractGuitarPickup) else if (c instanceof AbstractGuitarPickup)
addLeads((AbstractGuitarPickup) c, project, newSelection); addLeads((AbstractGuitarPickup) c, project, newSelection);
} }
return newSelection; return newSelection;
} }
private void addLeads(AbstractLeadedComponent<?> leaded, Project project, Set<IDIYComponent<?>> newSelection) { private void addLeads(AbstractLeadedComponent<?> leaded, Project project, Set<IDIYComponent<?>> newSelection) {
Size l = leaded.getLength(); Size l = leaded.getLength();
// do not apply to jumpers, etc // do not apply to jumpers, etc
if (l == null) if (l == null)
return; return;
Point2D p1 = (Point2D) leaded.getControlPoint(0).clone(); Point2D p1 = (Point2D) leaded.getControlPoint(0).clone();
Point2D p2 = (Point2D) leaded.getControlPoint(1).clone(); Point2D p2 = (Point2D) leaded.getControlPoint(1).clone();
double d = p1.distance(p2); double d = p1.distance(p2);
double len = l.convertToPixels() + 2; double len = l.convertToPixels() + 2;
double diff = (d - len) / 2; double diff = (d - len) / 2;
if (diff < 20) if (diff < 20)
return; return;
// find the center and angle // find the center and angle
double centerX = (p1.getX() + p2.getX()) / 2.0; double centerX = (p1.getX() + p2.getX()) / 2.0;
double centerY = (p1.getY() + p2.getY()) / 2.0; double centerY = (p1.getY() + p2.getY()) / 2.0;
double theta = Math.atan2(p2.getY() - p1.getY(), p2.getX() - p1.getX()); double theta = Math.atan2(p2.getY() - p1.getY(), p2.getX() - p1.getX());
// shorten the component to match the size of the body // shorten the component to match the size of the body
Point2D newP1 = new Point2D.Double((int)Math.round(centerX - Math.cos(theta) * len / 2), (int)Math.round(centerY - Math.sin(theta) * len / 2)); Point2D newP1 = new Point2D.Double((int)Math.round(centerX - Math.cos(theta) * len / 2), (int)Math.round(centerY - Math.sin(theta) * len / 2));
Point2D newP2 = new Point2D.Double((int)Math.round(centerX + Math.cos(theta) * len / 2), (int)Math.round(centerY + Math.sin(theta) * len / 2)); Point2D newP2 = new Point2D.Double((int)Math.round(centerX + Math.cos(theta) * len / 2), (int)Math.round(centerY + Math.sin(theta) * len / 2));
leaded.setControlPoint(newP1, 0); leaded.setControlPoint(newP1, 0);
leaded.setControlPoint(newP2, 1); leaded.setControlPoint(newP2, 1);
// make the standard leads go away // make the standard leads go away
leaded.setHideShortLeads(true); leaded.setHideShortLeads(true);
// create leads // create leads
HookupWire w1 = new HookupWire(); HookupWire w1 = new HookupWire();
getInstantiationManager().fillWithDefaultProperties(w1, null); getInstantiationManager().fillWithDefaultProperties(w1, null);
w1.setValue(AWG._26); w1.setValue(AWG._26);
w1.setLeadColor(leaded.getLeadColor()); w1.setLeadColor(leaded.getLeadColor());
// w1.setPointCount(PointCount.THREE); // w1.setPointCount(PointCount.THREE);
w1.setControlPoint(p1, 0); w1.setControlPoint(p1, 0);
for (int i = 1; i < w1.getControlPointCount() - 1; i++) { for (int i = 1; i < w1.getControlPointCount() - 1; i++) {
double r = diff * i / (w1.getControlPointCount() - 1); double r = diff * i / (w1.getControlPointCount() - 1);
w1.setControlPoint(new Point2D.Double((int)Math.round(p1.getX() + Math.cos(theta) * r), (int)Math.round(p1.getY() + Math.sin(theta) * r)), i); w1.setControlPoint(new Point2D.Double((int)Math.round(p1.getX() + Math.cos(theta) * r), (int)Math.round(p1.getY() + Math.sin(theta) * r)), i);
} }
w1.setControlPoint(newP1, w1.getControlPointCount() - 1); w1.setControlPoint(newP1, w1.getControlPointCount() - 1);
newSelection.add(w1); newSelection.add(w1);
HookupWire w2 = new HookupWire(); HookupWire w2 = new HookupWire();
getInstantiationManager().fillWithDefaultProperties(w2, null); getInstantiationManager().fillWithDefaultProperties(w2, null);
w2.setValue(AWG._26); w2.setValue(AWG._26);
w2.setLeadColor(leaded.getLeadColor()); w2.setLeadColor(leaded.getLeadColor());
// w2.setPointCount(PointCount.THREE); // w2.setPointCount(PointCount.THREE);
w2.setControlPoint(p2, 0); w2.setControlPoint(p2, 0);
for (int i = 1; i < w2.getControlPointCount() - 1; i++) { for (int i = 1; i < w2.getControlPointCount() - 1; i++) {
double r = diff * i / (w2.getControlPointCount() - 1); double r = diff * i / (w2.getControlPointCount() - 1);
w2.setControlPoint(new Point2D.Double((int)Math.round(p2.getX() - Math.cos(theta) * r), (int)Math.round(p2.getY() - Math.sin(theta) * r)), i); w2.setControlPoint(new Point2D.Double((int)Math.round(p2.getX() - Math.cos(theta) * r), (int)Math.round(p2.getY() - Math.sin(theta) * r)), i);
} }
w2.setControlPoint(newP2, w2.getControlPointCount() - 1); w2.setControlPoint(newP2, w2.getControlPointCount() - 1);
newSelection.add(w2); newSelection.add(w2);
// inject leads right before the component // inject leads right before the component
int index = project.getComponents().indexOf(leaded); int index = project.getComponents().indexOf(leaded);
project.getComponents().add(index, w1); project.getComponents().add(index, w1);
project.getComponents().add(index, w2); project.getComponents().add(index, w2);
} }
private void addLeads(AbstractTransistorPackage c, Project project, Set<IDIYComponent<?>> newSelection) { private void addLeads(AbstractTransistorPackage c, Project project, Set<IDIYComponent<?>> newSelection) {
Size offsetX = new Size(0.4d, SizeUnit.in); Size offsetX = new Size(0.4d, SizeUnit.in);
Size offsetY = new Size(0.1d, SizeUnit.in); Size offsetY = new Size(0.1d, SizeUnit.in);
// create leads // create leads
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
Point2D p0 = c.getControlPoint(i); Point2D p0 = c.getControlPoint(i);
double dx = -offsetX.convertToPixels(); double dx = -offsetX.convertToPixels();
double dy = offsetY.convertToPixels() * (i - 1); double dy = offsetY.convertToPixels() * (i - 1);
// calculate lead position // calculate lead position
Point2D p1 = new Point2D.Double((int)(p0.getX() + dx / 2), (int)(p0.getY() + dy / 2)); Point2D p1 = new Point2D.Double((int) Math.round(p0.getX() + dx / 2), (int) Math.round(p0.getY() + dy / 2));
Point2D p2 = new Point2D.Double((int)(p0.getX() + dx), (int)(p0.getY() + dy)); Point2D p2 = new Point2D.Double((int) Math.round(p0.getX() + dx), (int) Math.round(p0.getY() + dy));
if (c.getOrientation() != Orientation.DEFAULT) { if (c.getOrientation() != Orientation.DEFAULT) {
AffineTransform tx = AffineTransform.getRotateInstance(c.getOrientation().toRadians(), p0.getX(), p0.getY()); AffineTransform tx = AffineTransform.getRotateInstance(c.getOrientation().toRadians(), p0.getX(), p0.getY());
tx.transform(p1, p1); tx.transform(p1, p1);
tx.transform(p2, p2); tx.transform(p2, p2);
} }
HookupWire w = new HookupWire(); HookupWire w = new HookupWire();
getInstantiationManager().fillWithDefaultProperties(w, null); getInstantiationManager().fillWithDefaultProperties(w, null);
// make the leads thicker for TO220 and TO126 // make the leads thicker for TO220 and TO126
if (c instanceof TransistorTO220 || c instanceof TransistorTO126) if (c instanceof TransistorTO220 || c instanceof TransistorTO126)
w.setValue(AWG._24); w.setValue(AWG._24);
else else
w.setValue(AWG._26); w.setValue(AWG._26);
w.setLeadColor(AbstractTransistorPackage.METAL_COLOR); w.setLeadColor(AbstractTransistorPackage.METAL_COLOR);
w.setPointCount(PointCount.THREE); w.setPointCount(PointCount.THREE);
w.setControlPoint(p0, 0); w.setControlPoint(p0, 0);
w.setControlPoint(p1, 1); w.setControlPoint(p1, 1);
w.setControlPoint(p2, 2); w.setControlPoint(p2, 2);
newSelection.add(w); newSelection.add(w);
// inject leads right before the component // inject leads right before the component
int index = project.getComponents().indexOf(c); int index = project.getComponents().indexOf(c);
project.getComponents().add(index, w); project.getComponents().add(index, w);
} }
if (c instanceof TransistorTO220) { if (c instanceof TransistorTO220) {
TransistorTO220 t = (TransistorTO220)c; TransistorTO220 t = (TransistorTO220)c;
if (t.getFolded()) if (t.getFolded())
t.setLeadLength(new Size(0d, SizeUnit.mm)); t.setLeadLength(new Size(0d, SizeUnit.mm));
} }
else if (c instanceof TransistorTO126) { else if (c instanceof TransistorTO126) {
TransistorTO126 t = (TransistorTO126)c; TransistorTO126 t = (TransistorTO126)c;
if (t.getFolded()) if (t.getFolded())
t.setLeadLength(new Size(0d, SizeUnit.mm)); t.setLeadLength(new Size(0d, SizeUnit.mm));
} }
} }
private void addLeads(PotentiometerPanel c, Project project, Set<IDIYComponent<?>> newSelection) { private void addLeads(PotentiometerPanel c, Project project, Set<IDIYComponent<?>> newSelection) {
Size offsetY = new Size(0.5d, SizeUnit.in); Size offsetY = new Size(0.5d, SizeUnit.in);
// don't do it for PCB type // don't do it for PCB type
if (c.getType() == Type.PCB) if (c.getType() == Type.PCB)
return; return;
// create leads // create leads
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
Point2D p0 = c.getControlPoint(i); Point2D p0 = c.getControlPoint(i);
double dx = 0; double dx = 0;
double dy = offsetY.convertToPixels(); double dy = offsetY.convertToPixels();
AffineTransform tx = null; AffineTransform tx = null;
if (c.getOrientation() != Orientation.DEFAULT) if (c.getOrientation() != Orientation.DEFAULT)
tx = AffineTransform.getRotateInstance(c.getOrientation().toRadians(), p0.getX(), p0.getY()); tx = AffineTransform.getRotateInstance(c.getOrientation().toRadians(), p0.getX(), p0.getY());
HookupWire w = new HookupWire(); HookupWire w = new HookupWire();
getInstantiationManager().fillWithDefaultProperties(w, null); getInstantiationManager().fillWithDefaultProperties(w, null);
for (int j = 0; j < w.getControlPointCount(); j++) { for (int j = 0; j < w.getControlPointCount(); j++) {
Point2D p = new Point2D.Double((int)(p0.getX() + dx * j), (int)(p0.getY() + dy * j)); Point2D p = new Point2D.Double((int) Math.round(p0.getX() + dx * j), (int) Math.round(p0.getY() + dy * j));
if (tx != null) if (tx != null)
tx.transform(p, p); tx.transform(p, p);
w.setControlPoint(p, j); w.setControlPoint(p, j);
} }
newSelection.add(w); newSelection.add(w);
// inject leads right before the component // inject leads right before the component
int index = project.getComponents().indexOf(c); int index = project.getComponents().indexOf(c);
project.getComponents().add(index + 1, w); project.getComponents().add(index + 1, w);
} }
} }
private void addLeads(TubeSocket c, Project project, Set<IDIYComponent<?>> newSelection) { private void addLeads(TubeSocket c, Project project, Set<IDIYComponent<?>> newSelection) {
Point2D center = c.getControlPoint(0); Point2D center = c.getControlPoint(0);
// don't do it for PCB type // don't do it for PCB type
if (c.getMount() == Mount.PCB) if (c.getMount() == Mount.PCB)
return; return;
// create leads // create leads
for (int i = 1; i < c.getControlPointCount(); i++) { for (int i = 1; i < c.getControlPointCount(); i++) {
Point2D p = c.getControlPoint(i); Point2D p = c.getControlPoint(i);
double dx = p.getX() - center.getX(); double dx = p.getX() - center.getX();
double dy = p.getY() - center.getY(); double dy = p.getY() - center.getY();
// calculate lead position // calculate lead position
HookupWire w = new HookupWire(); HookupWire w = new HookupWire();
getInstantiationManager().fillWithDefaultProperties(w, null); getInstantiationManager().fillWithDefaultProperties(w, null);
for (int j = 0; j < w.getControlPointCount(); j++) { for (int j = 0; j < w.getControlPointCount(); j++) {
Point2D pw = new Point2D.Double((int)(p.getX() + dx * j), (int)(p.getY() + dy * j)); Point2D pw = new Point2D.Double((int) Math.round(p.getX() + dx * j), (int) Math.round(p.getY() + dy * j));
w.setControlPoint(pw, j); w.setControlPoint(pw, j);
} }
newSelection.add(w); newSelection.add(w);
// inject leads right before the component // inject leads right before the component
int index = project.getComponents().indexOf(c); int index = project.getComponents().indexOf(c);
project.getComponents().add(index + 1, w); project.getComponents().add(index + 1, w);
} }
} }
private void addLeads(AbstractGuitarPickup c, Project project, Set<IDIYComponent<?>> newSelection) { private void addLeads(AbstractGuitarPickup c, Project project, Set<IDIYComponent<?>> newSelection) {
Size offset = new Size(1d, SizeUnit.in); Size offset = new Size(1d, SizeUnit.in);
// create leads // create leads
for (int i = 0; i < c.getControlPointCount(); i++) { for (int i = 0; i < c.getControlPointCount(); i++) {
if (!c.isControlPointSticky(i)) if (!c.isControlPointSticky(i))
continue; continue;
Point2D p0 = c.getControlPoint(i); Point2D p0 = c.getControlPoint(i);
double dx = 0; double dx = 0;
double dy = 0; double dy = 0;
if (c instanceof SingleCoilPickup) if (c instanceof SingleCoilPickup)
dy = offset.convertToPixels(); dy = offset.convertToPixels();
else else
dx = offset.convertToPixels(); dx = offset.convertToPixels();
AffineTransform tx = null; AffineTransform tx = null;
if (c.getOrientation() != Orientation.DEFAULT) if (c.getOrientation() != Orientation.DEFAULT)
tx = AffineTransform.getRotateInstance(c.getOrientation().toRadians(), p0.getX(), p0.getY()); tx = AffineTransform.getRotateInstance(c.getOrientation().toRadians(), p0.getX(), p0.getY());
HookupWire w = new HookupWire(); HookupWire w = new HookupWire();
w.setValue(AWG._24); w.setValue(AWG._24);
getInstantiationManager().fillWithDefaultProperties(w, null); getInstantiationManager().fillWithDefaultProperties(w, null);
for (int j = 0; j < w.getControlPointCount(); j++) { for (int j = 0; j < w.getControlPointCount(); j++) {
Point2D p = new Point2D.Double((int)(p0.getX() + dx * j), (int)(p0.getY() + dy * j)); Point2D p = new Point2D.Double((int) Math.round(p0.getX() + dx * j), (int) Math.round(p0.getY() + dy * j));
if (tx != null) if (tx != null)
tx.transform(p, p); tx.transform(p, p);
w.setControlPoint(p, j); w.setControlPoint(p, j);
} }
newSelection.add(w); newSelection.add(w);
// inject leads right before the component // inject leads right before the component
int index = project.getComponents().indexOf(c); int index = project.getComponents().indexOf(c);
project.getComponents().add(index + 1, w); project.getComponents().add(index + 1, w);
} }
} }
@Override @Override
public String getEditAction() { public String getEditAction() {
return "Add Flexible Leads"; return "Add Flexible Leads";
} }
public InstantiationManager getInstantiationManager() { public InstantiationManager getInstantiationManager() {
if (instantiationManager == null) if (instantiationManager == null)
instantiationManager = new InstantiationManager(); instantiationManager = new InstantiationManager();
return instantiationManager; return instantiationManager;
} }
} }
@@ -444,10 +444,10 @@ public class CanvasPlugin implements IPlugIn{
// center to cursor // center to cursor
int relativeX = (int) (mousePosBefore.getX() + locationBefore.getX()); int relativeX = (int) (mousePosBefore.getX() + locationBefore.getX());
int relativeY = (int) (mousePosBefore.getY() + locationBefore.getY()); int relativeY = (int) (mousePosBefore.getY() + locationBefore.getY());
Point desiredPos = new Point((int) (1d * mousePosBefore.getX() / oldZoom * newZoom), Point desiredPos = new Point((int) Math.round(1d * mousePosBefore.getX() / oldZoom * newZoom),
(int) (1d * mousePosBefore.getY() / oldZoom * newZoom)); (int) Math.round(1d * mousePosBefore.getY() / oldZoom * newZoom));
int newHorizontalPos = (int) (desiredPos.getX() - relativeX); int newHorizontalPos = (int) Math.round(desiredPos.getX() - relativeX);
int newVerticalPos = (int) (desiredPos.getY() - relativeY); int newVerticalPos = (int) Math.round(desiredPos.getY() - relativeY);
horizontal.setValue(newHorizontalPos < 0 ? 0 : newHorizontalPos); horizontal.setValue(newHorizontalPos < 0 ? 0 : newHorizontalPos);
vertical.setValue(newVerticalPos < 0 ? 0 : newVerticalPos); vertical.setValue(newVerticalPos < 0 ? 0 : newVerticalPos);
} else { } else {