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
@@ -90,7 +90,7 @@ public abstract class AbstractBoard extends AbstractTransparentComponent<String>
Composite oldComposite = applyAlpha(g2d, componentState);
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);
// 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();
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: 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() {
@@ -178,7 +178,7 @@ public abstract class AbstractBoard extends AbstractTransparentComponent<String>
HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
if (getCoordinateDisplay() == CoordinateDisplay.Both_Sides) {
StringUtils.drawCenteredText(g2d, label,
x, (int) (finalSecondPoint.getY() - COORDINATE_FONT_SIZE),
x, (int) Math.round(finalSecondPoint.getY() - COORDINATE_FONT_SIZE),
HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
}
}
@@ -73,9 +73,9 @@ public class BlankBoard extends AbstractBoard {
Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(boardColor);
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
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);
// }
// 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
: borderColor);
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
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
@@ -1,387 +1,387 @@
/*
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.components.boards;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import org.diylc.awt.StringUtils;
import org.diylc.common.HorizontalAlignment;
import org.diylc.common.ObjectCache;
import org.diylc.common.VerticalAlignment;
import org.diylc.components.transform.ProtoBoardTransformer;
import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent;
import org.diylc.core.IDrawingObserver;
import org.diylc.core.Project;
import org.diylc.core.VisibilityPolicy;
import org.diylc.core.annotations.BomPolicy;
import org.diylc.core.annotations.ComponentDescriptor;
import org.diylc.core.annotations.EditableProperty;
import org.diylc.core.annotations.KeywordPolicy;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
@ComponentDescriptor(name = "Breadboard", category = "Boards", author = "Branislav Stojkovic",
description = "Prototyping solderless breadboard", instanceNamePrefix = "BB",
zOrder = IDIYComponent.BOARD, bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME,
keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, enableCache = true, transformer = ProtoBoardTransformer.class)
public class Breadboard extends AbstractProtoBoard {
private static final long serialVersionUID = 1L;
public static Color FILL_COLOR = Color.white;
public static Color BORDER_COLOR = Color.black;
public static Size BODY_ARC = new Size(3d, SizeUnit.mm);
public static Size SPACING = new Size(0.1d, SizeUnit.in);
public static Color SELECTION_COLOR = Color.red;
public static Color HOLE_COLOR = Color.decode("#EEEEEE");
public static Color PLUS_COLOR = Color.red;
public static Color MINUS_COLOR = Color.blue;
public static float COORDINATE_FONT_SIZE = 9f;
public static Color COORDINATE_COLOR = Color.gray.brighter();
public static Size HOLE_SIZE = new Size(1.5, SizeUnit.mm);
public static Size HOLE_ARC = new Size(1d, SizeUnit.mm);
protected Point2D point = new Point2D.Double(0, 0);
protected BreadboardSize breadboardSize;
protected PowerStripPosition powerStripPosition;
@SuppressWarnings("incomplete-switch")
@Override
public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
IDrawingObserver drawingObserver) {
if (checkPointsClipped(g2d.getClip())) {
return;
}
// adjust the angle
double theta = 0;
switch (getOrientation()) {
case _90:
theta = Math.PI / 2;
break;
case _180:
theta = Math.PI;
break;
case _270:
theta = Math.PI * 3 / 2;
break;
}
if (theta != 0) {
g2d.rotate(theta, point.getX(), point.getY());
}
int bodyArc = (int) BODY_ARC.convertToPixels();
double spacing = SPACING.convertToPixels();
int holeCount = getBreadboardSize() == BreadboardSize.Full ? 63 : 30;
// draw body
g2d.setColor(FILL_COLOR);
int width = (int) (23 * SPACING.convertToPixels());
int height = (int) ((holeCount + 1) * SPACING.convertToPixels());
Shape rect = new RoundRectangle2D.Double(point.getX(), point.getY(), width, height, bodyArc, bodyArc);
g2d.fill(rect);
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: BORDER_COLOR);
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
g2d.draw(rect);
drawingObserver.stopTracking();
// draw lines
g2d.setColor(PLUS_COLOR);
g2d.drawLine((int) (point.getX() + spacing), (int) (point.getY() + spacing), (int) (point.getX() + spacing),
(int) (point.getY() + holeCount * spacing));
g2d.drawLine((int) (point.getX() + 19 * spacing), (int) (point.getY() + spacing), (int) (point.getX() + 19 * spacing),
(int) (point.getY() + holeCount * spacing));
g2d.setColor(MINUS_COLOR);
g2d.drawLine((int) (point.getX() + 4 * spacing), (int) (point.getY() + spacing), (int) (point.getX() + 4 * spacing),
(int) (point.getY() + holeCount * spacing));
g2d.drawLine((int) (point.getX() + 22 * spacing), (int) (point.getY() + spacing), (int) (point.getX() + 22 * spacing),
(int) (point.getY() + holeCount * spacing));
int holeSize = getClosestOdd(HOLE_SIZE.convertToPixels());
int holeArc = (int) HOLE_ARC.convertToPixels();
g2d.setFont(LABEL_FONT.deriveFont(COORDINATE_FONT_SIZE));
byte a = "a".getBytes()[0];
// draw main holes
for (int section = 0; section <= 1; section++) {
double offset = section * 7 * spacing;
for (int y = 0; y < holeCount; y++) {
g2d.setColor(COORDINATE_COLOR);
int coordinateX;
if (section == 0) {
coordinateX = (int) (point.getX() + offset + 5.5 * spacing);
} else {
coordinateX = (int) (point.getX() + offset + 10.5 * spacing);
}
StringUtils.drawCenteredText(g2d, String.valueOf(y + 1), coordinateX, (int) (point.getY() + (y + 1) * spacing),
section == 0 ? HorizontalAlignment.RIGHT : HorizontalAlignment.LEFT, VerticalAlignment.CENTER);
for (int x = 0; x < 5; x++) {
int holeX = (int) (point.getX() + offset + (x + 6) * spacing);
int holeY = (int) (point.getY() + (y + 1) * spacing);
g2d.setColor(HOLE_COLOR);
g2d.fillRoundRect(holeX - holeSize / 2, holeY - holeSize / 2, holeSize, holeSize, holeArc, holeArc);
g2d.setColor(BORDER_COLOR);
g2d.drawRoundRect(holeX - holeSize / 2, holeY - holeSize / 2, holeSize, holeSize, holeArc, holeArc);
// Draw horizontal labels
if (y == 0) {
g2d.setColor(COORDINATE_COLOR);
StringUtils.drawCenteredText(g2d, new String(new byte[] {(byte) (a + x + 5 * section)}), holeX, (int) (point.getY() + COORDINATE_FONT_SIZE),
HorizontalAlignment.CENTER, VerticalAlignment.TOP);
StringUtils.drawCenteredText(g2d, new String(new byte[] {(byte) (a + x + 5 * section)}), holeX, (int) (point.getY()
+ spacing * 31 - COORDINATE_FONT_SIZE / 2), HorizontalAlignment.CENTER, VerticalAlignment.TOP);
}
}
}
}
double powerOffset =
getPowerStripPosition() == PowerStripPosition.Inline ? (getBreadboardSize() == BreadboardSize.Full ? 2d : 1d)
: (getBreadboardSize() == BreadboardSize.Full ? 1.5d : 0.5d);
int psHoleCount = Math.round(holeCount / 10f) * 10;
// draw power strip holes
for (int section = 0; section <= 1; section++) {
double offset = section * 18 * spacing;
for (int y = 0; y < psHoleCount - 1; y++) {
for (int x = 0; x < 2; x++) {
if ((y + 1) % 6 == 0)
continue;
int holeX = (int) (point.getX() + offset + (x + 2) * spacing);
int holeY = (int) (point.getY() + (y + 1 + powerOffset) * spacing);
g2d.setColor(HOLE_COLOR);
g2d.fillRoundRect(holeX - holeSize / 2, holeY - holeSize / 2, holeSize, holeSize, holeArc, holeArc);
g2d.setColor(BORDER_COLOR);
g2d.drawRoundRect(holeX - holeSize / 2, holeY - holeSize / 2, holeSize, holeSize, holeArc, holeArc);
}
}
}
// draw transparent connections just to designate connections
drawingObserver.startTrackingContinuityArea(true);
Composite oldComposite = g2d.getComposite();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.0f));
for (int section = 0; section <= 1; section++) {
double offset = section * 18 * spacing;
for (int x = 0; x < 2; x++) {
int holeX = (int) (point.getX() + offset + (x + 2) * spacing);
int holeY1 = (int) (point.getY() + (1 + powerOffset) * spacing);
int holeY2 = (int) (point.getY() + (psHoleCount -1 + powerOffset) * spacing);
g2d.setColor(HOLE_COLOR);
g2d.fillRoundRect(holeX - holeSize / 2, holeY1 - holeSize / 2, holeSize, holeSize + holeY2 - holeY1, holeArc, holeArc);
}
}
for (int section = 0; section <= 1; section++) {
double offset = section * 7 * spacing;
for (int y = 0; y < holeCount; y++) {
g2d.setColor(COORDINATE_COLOR);
int coordinateX;
if (section == 0) {
coordinateX = (int) (point.getX() + offset + 5.5 * spacing);
} else {
coordinateX = (int) (point.getX() + offset + 10.5 * spacing);
}
StringUtils.drawCenteredText(g2d, String.valueOf(y + 1), coordinateX, (int) (point.getY() + (y + 1) * spacing),
section == 0 ? HorizontalAlignment.RIGHT : HorizontalAlignment.LEFT, VerticalAlignment.CENTER);
// for (int x = 0; x < 5; x++) {
int holeX1 = (int) (point.getX() + offset + 6 * spacing);
int holeX2 = (int) (point.getX() + offset + 10 * spacing);
int holeY = (int) (point.getY() + (y + 1) * spacing);
g2d.setColor(HOLE_COLOR);
g2d.fillRoundRect(holeX1 - holeSize / 2, holeY - holeSize / 2, holeSize + holeX2 - holeX1, holeSize, holeArc, holeArc);
// }
}
// }
}
g2d.setComposite(oldComposite);
drawingObserver.stopTrackingContinuityArea();
}
@Override
public void drawIcon(Graphics2D g2d, int width, int height) {
int factor = 32 / width;
int arc = 4 / factor;
g2d.setColor(FILL_COLOR);
g2d.fillRect(2 / factor, 2 / factor, width - 4 / factor, height - 4 / factor);
g2d.setColor(BORDER_COLOR);
g2d.drawRect(2 / factor, 2 / factor, width - 4 / factor, height - 4 / factor);
g2d.setColor(HOLE_COLOR);
g2d.fillRoundRect(width / 3 - 2 / factor, width / 3 - 2 / factor, getClosestOdd(5.0 / factor),
getClosestOdd(5.0 / factor), arc, arc);
g2d.setColor(BORDER_COLOR);
g2d.drawRoundRect(width / 3 - 2 / factor, width / 3 - 2 / factor, getClosestOdd(5.0 / factor),
getClosestOdd(5.0 / factor), arc, arc);
g2d.setColor(HOLE_COLOR);
g2d.fillRoundRect(2 * width / 3 - 2 / factor, width / 3 - 2 / factor, getClosestOdd(5.0 / factor),
getClosestOdd(5.0 / factor), arc, arc);
g2d.setColor(BORDER_COLOR);
g2d.drawRoundRect(2 * width / 3 - 2 / factor, width / 3 - 2 / factor, getClosestOdd(5.0 / factor),
getClosestOdd(5.0 / factor), arc, arc);
g2d.setColor(HOLE_COLOR);
g2d.fillRoundRect(width / 3 - 2 / factor, 2 * width / 3 - 2 / factor, getClosestOdd(5.0 / factor),
getClosestOdd(5.0 / factor), arc, arc);
g2d.setColor(BORDER_COLOR);
g2d.drawRoundRect(width / 3 - 2 / factor, 2 * width / 3 - 2 / factor, getClosestOdd(5.0 / factor),
getClosestOdd(5.0 / factor), arc, arc);
g2d.setColor(HOLE_COLOR);
g2d.fillRoundRect(2 * width / 3 - 2 / factor, 2 * width / 3 - 2 / factor, getClosestOdd(5.0 / factor),
getClosestOdd(5.0 / factor), arc, arc);
g2d.setColor(BORDER_COLOR);
g2d.drawRoundRect(2 * width / 3 - 2 / factor, 2 * width / 3 - 2 / factor, getClosestOdd(5.0 / factor),
getClosestOdd(5.0 / factor), arc, arc);
g2d.setColor(MINUS_COLOR);
g2d.drawLine(width / 2, 2 / factor, width / 2, height - 4 / factor);
}
@EditableProperty(name = "Size")
public BreadboardSize getBreadboardSize() {
if (breadboardSize == null)
breadboardSize = BreadboardSize.Half;
return breadboardSize;
}
public void setBreadboardSize(BreadboardSize breadboardSize) {
this.breadboardSize = breadboardSize;
}
@EditableProperty(name = "Power Strip")
public PowerStripPosition getPowerStripPosition() {
if (powerStripPosition == null)
powerStripPosition = PowerStripPosition.Inline;
return powerStripPosition;
}
public void setPowerStripPosition(PowerStripPosition powerStripPosition) {
this.powerStripPosition = powerStripPosition;
}
@Override
public int getControlPointCount() {
return 2;
}
@Override
public boolean canPointMoveFreely(int pointIndex) {
return false;
}
@SuppressWarnings("incomplete-switch")
@Override
public Point2D getControlPoint(int index) {
if (index == 0)
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
double spacing = SPACING.convertToPixels();
int holeCount = getBreadboardSize() == BreadboardSize.Full ? 63 : 30;
// adjust the angle
double theta = 0;
switch (getOrientation()) {
case _90:
theta = Math.PI / 2;
break;
case _180:
theta = Math.PI;
break;
case _270:
theta = Math.PI * 3 / 2;
break;
}
Point2D secondPoint = new Point2D.Double(point.getX() + 23 * spacing, point.getY() + (holeCount + 1) * spacing);
if (theta != 0) {
AffineTransform tx = AffineTransform.getRotateInstance(theta, point.getX(), point.getY());
tx.transform(secondPoint, secondPoint);
}
return secondPoint;
}
@Override
public boolean isControlPointSticky(int index) {
return false;
}
@Override
public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
return VisibilityPolicy.NEVER;
}
@Override
public void setControlPoint(Point2D point, int index) {
if (index == 0)
this.point.setLocation(point);
}
@Override
public Void getValue() {
return null;
}
@Override
public void setValue(Void value) {}
@Override
public String getControlPointNodeName(int index) {
return null;
}
@Override
public Rectangle2D getCachingBounds() {
Point2D finalSecondPoint = getControlPoint(1);
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);
}
public enum BreadboardSize {
Half, Full
}
public enum PowerStripPosition {
Inline, Offset
}
}
/*
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.components.boards;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import org.diylc.awt.StringUtils;
import org.diylc.common.HorizontalAlignment;
import org.diylc.common.ObjectCache;
import org.diylc.common.VerticalAlignment;
import org.diylc.components.transform.ProtoBoardTransformer;
import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent;
import org.diylc.core.IDrawingObserver;
import org.diylc.core.Project;
import org.diylc.core.VisibilityPolicy;
import org.diylc.core.annotations.BomPolicy;
import org.diylc.core.annotations.ComponentDescriptor;
import org.diylc.core.annotations.EditableProperty;
import org.diylc.core.annotations.KeywordPolicy;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
@ComponentDescriptor(name = "Breadboard", category = "Boards", author = "Branislav Stojkovic",
description = "Prototyping solderless breadboard", instanceNamePrefix = "BB",
zOrder = IDIYComponent.BOARD, bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME,
keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, enableCache = true, transformer = ProtoBoardTransformer.class)
public class Breadboard extends AbstractProtoBoard {
private static final long serialVersionUID = 1L;
public static Color FILL_COLOR = Color.white;
public static Color BORDER_COLOR = Color.black;
public static Size BODY_ARC = new Size(3d, SizeUnit.mm);
public static Size SPACING = new Size(0.1d, SizeUnit.in);
public static Color SELECTION_COLOR = Color.red;
public static Color HOLE_COLOR = Color.decode("#EEEEEE");
public static Color PLUS_COLOR = Color.red;
public static Color MINUS_COLOR = Color.blue;
public static float COORDINATE_FONT_SIZE = 9f;
public static Color COORDINATE_COLOR = Color.gray.brighter();
public static Size HOLE_SIZE = new Size(1.5, SizeUnit.mm);
public static Size HOLE_ARC = new Size(1d, SizeUnit.mm);
protected Point2D point = new Point2D.Double(0, 0);
protected BreadboardSize breadboardSize;
protected PowerStripPosition powerStripPosition;
@SuppressWarnings("incomplete-switch")
@Override
public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
IDrawingObserver drawingObserver) {
if (checkPointsClipped(g2d.getClip())) {
return;
}
// adjust the angle
double theta = 0;
switch (getOrientation()) {
case _90:
theta = Math.PI / 2;
break;
case _180:
theta = Math.PI;
break;
case _270:
theta = Math.PI * 3 / 2;
break;
}
if (theta != 0) {
g2d.rotate(theta, point.getX(), point.getY());
}
int bodyArc = (int) BODY_ARC.convertToPixels();
double spacing = SPACING.convertToPixels();
int holeCount = getBreadboardSize() == BreadboardSize.Full ? 63 : 30;
// draw body
g2d.setColor(FILL_COLOR);
int width = (int) (23 * SPACING.convertToPixels());
int height = (int) ((holeCount + 1) * SPACING.convertToPixels());
Shape rect = new RoundRectangle2D.Double(point.getX(), point.getY(), width, height, bodyArc, bodyArc);
g2d.fill(rect);
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: BORDER_COLOR);
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
g2d.draw(rect);
drawingObserver.stopTracking();
// draw lines
g2d.setColor(PLUS_COLOR);
g2d.drawLine((int) Math.round(point.getX() + spacing), (int) Math.round(point.getY() + spacing), (int) Math.round(point.getX() + spacing),
(int) Math.round(point.getY() + holeCount * spacing));
g2d.drawLine((int) Math.round(point.getX() + 19 * spacing), (int) Math.round(point.getY() + spacing), (int) Math.round(point.getX() + 19 * spacing),
(int) Math.round(point.getY() + holeCount * spacing));
g2d.setColor(MINUS_COLOR);
g2d.drawLine((int) Math.round(point.getX() + 4 * spacing), (int) Math.round(point.getY() + spacing), (int) Math.round(point.getX() + 4 * spacing),
(int) Math.round(point.getY() + holeCount * spacing));
g2d.drawLine((int) Math.round(point.getX() + 22 * spacing), (int) Math.round(point.getY() + spacing), (int) Math.round(point.getX() + 22 * spacing),
(int) Math.round(point.getY() + holeCount * spacing));
int holeSize = getClosestOdd(HOLE_SIZE.convertToPixels());
int holeArc = (int) HOLE_ARC.convertToPixels();
g2d.setFont(LABEL_FONT.deriveFont(COORDINATE_FONT_SIZE));
byte a = "a".getBytes()[0];
// draw main holes
for (int section = 0; section <= 1; section++) {
double offset = section * 7 * spacing;
for (int y = 0; y < holeCount; y++) {
g2d.setColor(COORDINATE_COLOR);
int coordinateX;
if (section == 0) {
coordinateX = (int) Math.round(point.getX() + offset + 5.5 * spacing);
} else {
coordinateX = (int) Math.round(point.getX() + offset + 10.5 * spacing);
}
StringUtils.drawCenteredText(g2d, String.valueOf(y + 1), coordinateX, (int) (point.getY() + (y + 1) * spacing),
section == 0 ? HorizontalAlignment.RIGHT : HorizontalAlignment.LEFT, VerticalAlignment.CENTER);
for (int x = 0; x < 5; x++) {
int holeX = (int) (point.getX() + offset + (x + 6) * spacing);
int holeY = (int) (point.getY() + (y + 1) * spacing);
g2d.setColor(HOLE_COLOR);
g2d.fillRoundRect(holeX - holeSize / 2, holeY - holeSize / 2, holeSize, holeSize, holeArc, holeArc);
g2d.setColor(BORDER_COLOR);
g2d.drawRoundRect(holeX - holeSize / 2, holeY - holeSize / 2, holeSize, holeSize, holeArc, holeArc);
// Draw horizontal labels
if (y == 0) {
g2d.setColor(COORDINATE_COLOR);
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);
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);
}
}
}
}
double powerOffset =
getPowerStripPosition() == PowerStripPosition.Inline ? (getBreadboardSize() == BreadboardSize.Full ? 2d : 1d)
: (getBreadboardSize() == BreadboardSize.Full ? 1.5d : 0.5d);
int psHoleCount = Math.round(holeCount / 10f) * 10;
// draw power strip holes
for (int section = 0; section <= 1; section++) {
double offset = section * 18 * spacing;
for (int y = 0; y < psHoleCount - 1; y++) {
for (int x = 0; x < 2; x++) {
if ((y + 1) % 6 == 0)
continue;
int holeX = (int) (point.getX() + offset + (x + 2) * spacing);
int holeY = (int) (point.getY() + (y + 1 + powerOffset) * spacing);
g2d.setColor(HOLE_COLOR);
g2d.fillRoundRect(holeX - holeSize / 2, holeY - holeSize / 2, holeSize, holeSize, holeArc, holeArc);
g2d.setColor(BORDER_COLOR);
g2d.drawRoundRect(holeX - holeSize / 2, holeY - holeSize / 2, holeSize, holeSize, holeArc, holeArc);
}
}
}
// draw transparent connections just to designate connections
drawingObserver.startTrackingContinuityArea(true);
Composite oldComposite = g2d.getComposite();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.0f));
for (int section = 0; section <= 1; section++) {
double offset = section * 18 * spacing;
for (int x = 0; x < 2; x++) {
int holeX = (int) (point.getX() + offset + (x + 2) * spacing);
int holeY1 = (int) (point.getY() + (1 + powerOffset) * spacing);
int holeY2 = (int) (point.getY() + (psHoleCount -1 + powerOffset) * spacing);
g2d.setColor(HOLE_COLOR);
g2d.fillRoundRect(holeX - holeSize / 2, holeY1 - holeSize / 2, holeSize, holeSize + holeY2 - holeY1, holeArc, holeArc);
}
}
for (int section = 0; section <= 1; section++) {
double offset = section * 7 * spacing;
for (int y = 0; y < holeCount; y++) {
g2d.setColor(COORDINATE_COLOR);
int coordinateX;
if (section == 0) {
coordinateX = (int) Math.round(point.getX() + offset + 5.5 * spacing);
} else {
coordinateX = (int) Math.round(point.getX() + offset + 10.5 * spacing);
}
StringUtils.drawCenteredText(g2d, String.valueOf(y + 1), coordinateX, (int) (point.getY() + (y + 1) * spacing),
section == 0 ? HorizontalAlignment.RIGHT : HorizontalAlignment.LEFT, VerticalAlignment.CENTER);
// for (int x = 0; x < 5; x++) {
int holeX1 = (int) Math.round(point.getX() + offset + 6 * spacing);
int holeX2 = (int) Math.round(point.getX() + offset + 10 * spacing);
int holeY = (int) (point.getY() + (y + 1) * spacing);
g2d.setColor(HOLE_COLOR);
g2d.fillRoundRect(holeX1 - holeSize / 2, holeY - holeSize / 2, holeSize + holeX2 - holeX1, holeSize, holeArc, holeArc);
// }
}
// }
}
g2d.setComposite(oldComposite);
drawingObserver.stopTrackingContinuityArea();
}
@Override
public void drawIcon(Graphics2D g2d, int width, int height) {
int factor = 32 / width;
int arc = 4 / factor;
g2d.setColor(FILL_COLOR);
g2d.fillRect(2 / factor, 2 / factor, width - 4 / factor, height - 4 / factor);
g2d.setColor(BORDER_COLOR);
g2d.drawRect(2 / factor, 2 / factor, width - 4 / factor, height - 4 / factor);
g2d.setColor(HOLE_COLOR);
g2d.fillRoundRect(width / 3 - 2 / factor, width / 3 - 2 / factor, getClosestOdd(5.0 / factor),
getClosestOdd(5.0 / factor), arc, arc);
g2d.setColor(BORDER_COLOR);
g2d.drawRoundRect(width / 3 - 2 / factor, width / 3 - 2 / factor, getClosestOdd(5.0 / factor),
getClosestOdd(5.0 / factor), arc, arc);
g2d.setColor(HOLE_COLOR);
g2d.fillRoundRect(2 * width / 3 - 2 / factor, width / 3 - 2 / factor, getClosestOdd(5.0 / factor),
getClosestOdd(5.0 / factor), arc, arc);
g2d.setColor(BORDER_COLOR);
g2d.drawRoundRect(2 * width / 3 - 2 / factor, width / 3 - 2 / factor, getClosestOdd(5.0 / factor),
getClosestOdd(5.0 / factor), arc, arc);
g2d.setColor(HOLE_COLOR);
g2d.fillRoundRect(width / 3 - 2 / factor, 2 * width / 3 - 2 / factor, getClosestOdd(5.0 / factor),
getClosestOdd(5.0 / factor), arc, arc);
g2d.setColor(BORDER_COLOR);
g2d.drawRoundRect(width / 3 - 2 / factor, 2 * width / 3 - 2 / factor, getClosestOdd(5.0 / factor),
getClosestOdd(5.0 / factor), arc, arc);
g2d.setColor(HOLE_COLOR);
g2d.fillRoundRect(2 * width / 3 - 2 / factor, 2 * width / 3 - 2 / factor, getClosestOdd(5.0 / factor),
getClosestOdd(5.0 / factor), arc, arc);
g2d.setColor(BORDER_COLOR);
g2d.drawRoundRect(2 * width / 3 - 2 / factor, 2 * width / 3 - 2 / factor, getClosestOdd(5.0 / factor),
getClosestOdd(5.0 / factor), arc, arc);
g2d.setColor(MINUS_COLOR);
g2d.drawLine(width / 2, 2 / factor, width / 2, height - 4 / factor);
}
@EditableProperty(name = "Size")
public BreadboardSize getBreadboardSize() {
if (breadboardSize == null)
breadboardSize = BreadboardSize.Half;
return breadboardSize;
}
public void setBreadboardSize(BreadboardSize breadboardSize) {
this.breadboardSize = breadboardSize;
}
@EditableProperty(name = "Power Strip")
public PowerStripPosition getPowerStripPosition() {
if (powerStripPosition == null)
powerStripPosition = PowerStripPosition.Inline;
return powerStripPosition;
}
public void setPowerStripPosition(PowerStripPosition powerStripPosition) {
this.powerStripPosition = powerStripPosition;
}
@Override
public int getControlPointCount() {
return 2;
}
@Override
public boolean canPointMoveFreely(int pointIndex) {
return false;
}
@SuppressWarnings("incomplete-switch")
@Override
public Point2D getControlPoint(int index) {
if (index == 0)
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
double spacing = SPACING.convertToPixels();
int holeCount = getBreadboardSize() == BreadboardSize.Full ? 63 : 30;
// adjust the angle
double theta = 0;
switch (getOrientation()) {
case _90:
theta = Math.PI / 2;
break;
case _180:
theta = Math.PI;
break;
case _270:
theta = Math.PI * 3 / 2;
break;
}
Point2D secondPoint = new Point2D.Double(point.getX() + 23 * spacing, point.getY() + (holeCount + 1) * spacing);
if (theta != 0) {
AffineTransform tx = AffineTransform.getRotateInstance(theta, point.getX(), point.getY());
tx.transform(secondPoint, secondPoint);
}
return secondPoint;
}
@Override
public boolean isControlPointSticky(int index) {
return false;
}
@Override
public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
return VisibilityPolicy.NEVER;
}
@Override
public void setControlPoint(Point2D point, int index) {
if (index == 0)
this.point.setLocation(point);
}
@Override
public Void getValue() {
return null;
}
@Override
public void setValue(Void value) {}
@Override
public String getControlPointNodeName(int index) {
return null;
}
@Override
public Rectangle2D getCachingBounds() {
Point2D finalSecondPoint = getControlPoint(1);
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);
}
public enum BreadboardSize {
Half, Full
}
public enum PowerStripPosition {
Inline, Offset
}
}
@@ -329,9 +329,9 @@ public class EurorackStripboard extends AbstractProtoBoard {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(padSize / 4));
for (int i = 0; i < 5; i++) {
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 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);
g2d.drawLine(padX1, padY1, padX2, padY2);
}
@@ -225,12 +225,12 @@ public class ProtoBoard extends AbstractProtoBoard {
g2d.setColor(traceColor);
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(padSize / 4));
drawingObserver.startTrackingContinuityArea(true);
g2d.drawLine((int) (point.getX() + (1 + SEGMENTS_SUM[3] + 0.5) * spacing), (int) (point.getY() + 1 * spacing),
(int) (point.getX() + (1 + SEGMENTS_SUM[3] + 0.5) * spacing), (int) (point.getY() + 3.5 * spacing));
g2d.drawLine((int) (point.getX() + (1 + SEGMENTS_SUM[3] + 1.5) * spacing + miniPadSize / 2), (int) (point.getY() + 1 * spacing),
(int) (point.getX() + (1 + SEGMENTS_SUM[3] + 1.5) * spacing + miniPadSize / 2), (int) (point.getY() + 3.5 * spacing));
g2d.drawLine((int) (point.getX() + (1 + SEGMENTS_SUM[3] + 2.5) * spacing), (int) (point.getY() + 1 * spacing),
(int) (point.getX() + (1 + SEGMENTS_SUM[3] + 2.5) * spacing), (int) (point.getY() + 3.5 * 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) Math.round(point.getY() + 3.5 * 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) Math.round(point.getY() + 3.5 * 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) Math.round(point.getY() + 3.5 * spacing));
drawingObserver.stopTrackingContinuityArea();
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
@@ -335,12 +335,12 @@ public class ProtoBoard extends AbstractProtoBoard {
g2d.setColor(SEPARATOR_COLOR);
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,
(int) (point.getX() + width - 5.5 * spacing), (int) (point.getY() + 3.5 * spacing));
g2d.drawLine((int) (point.getX() + width - 4.5 * spacing), (int) (point.getY() + 2 * spacing + 8),
(int) (point.getX() + width - 4.5 * spacing), (int) (point.getY() + 3.5 * spacing));
g2d.drawLine((int) (point.getX() + width - 1.5 * spacing), (int) (point.getY() + 2 * spacing + 8),
(int) (point.getX() + width - 1.5 * spacing), (int) (point.getY() + 3.5 * spacing));
g2d.drawLine((int) Math.round(point.getX() + width - 5.5 * spacing), (int) Math.round(point.getY() + 2 * spacing) + 8,
(int) Math.round(point.getX() + width - 5.5 * spacing), (int) Math.round(point.getY() + 3.5 * spacing));
g2d.drawLine((int) Math.round(point.getX() + width - 4.5 * spacing), (int) Math.round(point.getY() + 2 * spacing + 8),
(int) Math.round(point.getX() + width - 4.5 * spacing), (int) Math.round(point.getY() + 3.5 * spacing));
g2d.drawLine((int) Math.round(point.getX() + width - 1.5 * spacing), (int) Math.round(point.getY() + 2 * spacing + 8),
(int) Math.round(point.getX() + width - 1.5 * spacing), (int) Math.round(point.getY() + 3.5 * spacing));
g2d.setColor(traceColor);
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(padSize / 4));
@@ -348,8 +348,8 @@ public class ProtoBoard extends AbstractProtoBoard {
drawingObserver.startTrackingContinuityArea(true);
// 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) (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() + 0.5 * spacing), (int) (point.getX() + width - (2) * spacing), (int) Math.round(point.getY() + 0.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
for (int x = 0; x < 6; x++) {
@@ -357,7 +357,7 @@ public class ProtoBoard extends AbstractProtoBoard {
g2d.setColor(traceColor);
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));
@@ -433,22 +433,22 @@ public class ProtoBoard extends AbstractProtoBoard {
g2d.setColor(textColor);
// 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);
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);
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);
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);
// Draw top-right labels
int labelY = (int) (point.getY() + 3.8 * spacing) + 1;
StringUtils.drawCenteredText(g2d, "+5V", (int) (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, " 12V", (int) (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, "-12V", (int) (point.getX() + width - 1 * spacing), labelY, HorizontalAlignment.CENTER, VerticalAlignment.TOP);
int labelY = (int) Math.round(point.getY() + 3.8 * spacing) + 1;
StringUtils.drawCenteredText(g2d, "+5V", (int) Math.round(point.getX() + width - 6 * spacing), 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) Math.round(point.getX() + width - 5 * spacing) + 2, 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) Math.round(point.getX() + width - 1 * spacing), labelY, HorizontalAlignment.CENTER, VerticalAlignment.TOP);
// Draw vertical labels
byte A = "A".getBytes()[0];
@@ -460,14 +460,14 @@ public class ProtoBoard extends AbstractProtoBoard {
label = new String(new byte[] {(byte) (a + y - 26)});
else
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) (point.getX() + width - 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) Math.round(point.getX() + width - spacing * 0.35), padY, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
}
g2d.setColor(textColor);
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);
// draw central mini pads
@@ -150,14 +150,14 @@ public class ProtoBoard780 extends AbstractProtoBoard {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(padSize - 2f));
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);
g2d.drawLine(padX, (int) (point.getY() + offsetY), padX,
(int) (point.getY() + spacing + offsetY));
g2d.drawLine(padX, (int) Math.round(point.getY() + offsetY), padX,
(int) Math.round(point.getY() + spacing + offsetY));
drawingObserver.stopTrackingContinuityArea();
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);
@@ -180,8 +180,8 @@ public class ProtoBoard780 extends AbstractProtoBoard {
g2d.setColor(textColor);
for (int i = 0; i < 4; i++) {
int x = i == 0 ? 1 : i * 5;
int padX = (int) (point.getX() + width / 2 - 8 * spacing + x * spacing);
int padY = (int) (point.getY() + spacing * 2);
int padX = (int) Math.round(point.getX() + width / 2 - 8 * spacing + x * spacing);
int padY = (int) Math.round(point.getY() + spacing * 2);
// // flip the coordinates for MPJA
// if (type == ProtoBoard780Type.MPJA) {
@@ -201,38 +201,38 @@ public class ProtoBoard780 extends AbstractProtoBoard {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(padSize - 2f));
// the outer bus
g2d.drawLine((int) (point.getX() + width / 2 - 13 * spacing),
(int) (point.getY() - 2 * spacing + offsetY),
(int) (point.getX() + width / 2 + 13 * spacing),
(int) (point.getY() - 2 * spacing + offsetY));
g2d.drawLine((int) (point.getX() + width / 2 - 13 * spacing),
(int) (point.getY() - 2 * spacing + offsetY),
(int) (point.getX() + width / 2 - 13 * spacing),
g2d.drawLine((int) Math.round(point.getX() + width / 2 - 13 * spacing),
(int) Math.round(point.getY() - 2 * spacing + offsetY),
(int) Math.round(point.getX() + width / 2 + 13 * spacing),
(int) Math.round(point.getY() - 2 * spacing + offsetY));
g2d.drawLine((int) Math.round(point.getX() + width / 2 - 13 * spacing),
(int) Math.round(point.getY() - 2 * spacing + offsetY),
(int) Math.round(point.getX() + width / 2 - 13 * spacing),
(int) (point.getY() + (29 + (type == ProtoBoard780Type.RS ? 2 : 0)) * spacing + offsetY));
g2d.drawLine((int) (point.getX() + width / 2 + 13 * spacing),
(int) (point.getY() - 2 * spacing + offsetY),
(int) (point.getX() + width / 2 + 13 * spacing),
g2d.drawLine((int) Math.round(point.getX() + width / 2 + 13 * spacing),
(int) Math.round(point.getY() - 2 * spacing + offsetY),
(int) Math.round(point.getX() + width / 2 + 13 * spacing),
(int) (point.getY() + (29 + (type == ProtoBoard780Type.RS ? 2 : 0)) * spacing + offsetY));
// horizontal long traces
g2d.drawLine((int) (point.getX() + width / 2 - 12 * spacing), (int) (point.getY() + offsetY),
(int) (point.getX() + width / 2 + 12 * spacing), (int) (point.getY() + offsetY));
g2d.drawLine((int) (point.getX() + width / 2 - 12 * spacing),
(int) (point.getY() + spacing * 29 + offsetY),
(int) (point.getX() + width / 2 + 12 * spacing),
(int) (point.getY() + spacing * 29 + offsetY));
g2d.drawLine((int) Math.round(point.getX() + width / 2 - 12 * spacing), (int) Math.round(point.getY() + offsetY),
(int) Math.round(point.getX() + width / 2 + 12 * spacing), (int) Math.round(point.getY() + offsetY));
g2d.drawLine((int) Math.round(point.getX() + width / 2 - 12 * spacing),
(int) Math.round(point.getY() + spacing * 29 + offsetY),
(int) Math.round(point.getX() + width / 2 + 12 * spacing),
(int) Math.round(point.getY() + spacing * 29 + offsetY));
for (int i = 0; i < 5; i++) {
int padX = (int) (point.getX() + width / 2 - 12 * spacing + (i * 5 + 1) * spacing);
// vertical traces
g2d.drawLine((int) (padX - spacing), (int) (point.getY() + offsetY), (int) (padX - spacing),
(int) (point.getY() + spacing * 28 + offsetY));
g2d.drawLine((int) (padX + 3 * spacing), (int) (point.getY() + spacing + offsetY),
(int) (padX + 3 * spacing), (int) (point.getY() + spacing * 29 + offsetY));
g2d.drawLine((int) (padX - spacing), (int) Math.round(point.getY() + offsetY), (int) (padX - spacing),
(int) Math.round(point.getY() + spacing * 28 + offsetY));
g2d.drawLine((int) (padX + 3 * spacing), (int) Math.round(point.getY() + spacing + offsetY),
(int) (padX + 3 * spacing), (int) Math.round(point.getY() + spacing * 29 + offsetY));
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
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.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);
// 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));
// drawingObserver.stopTrackingContinuityArea();
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);
@@ -277,8 +277,8 @@ public class ProtoBoard780 extends AbstractProtoBoard {
// horizontal coordinates
for (int i = 0; i < 6; i++) {
int x = i == 0 ? 1 : i * 5;
int padX = (int) (point.getX() + width / 2 - 13 * spacing + x * spacing);
int padY = (int) (point.getY() - spacing + offsetY);
int padX = (int) Math.round(point.getX() + width / 2 - 13 * spacing + x * spacing);
int padY = (int) Math.round(point.getY() - spacing + offsetY);
String label = String.valueOf((char) ('A' + i));
@@ -293,7 +293,7 @@ public class ProtoBoard780 extends AbstractProtoBoard {
for (int i = 0; i < 7; i++) {
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);
StringUtils.drawCenteredText(g2d, Integer.toString(y), padX, padY, HorizontalAlignment.LEFT,
@@ -302,8 +302,8 @@ public class ProtoBoard780 extends AbstractProtoBoard {
// model name
g2d.setFont(LABEL_FONT.deriveFont(COORDINATE_FONT_SIZE * 1.8f));
int x = (int) (point.getX() + width / 2);
int y = (int) (point.getY() + length - spacing * 1.5);
int x = (int) Math.round(point.getX() + width / 2);
int y = (int) Math.round(point.getY() + length - spacing * 1.5);
StringUtils.drawCenteredText(g2d,
type == ProtoBoard780Type.RS ? "Radio Shack 276-168B" : "MPJA.COM 33304 PB", x, y,
HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
@@ -315,32 +315,32 @@ public class ProtoBoard780 extends AbstractProtoBoard {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
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);
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);
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);
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 = (int) (point.getY() + length - spacing);
holeY = (int) Math.round(point.getY() + length - spacing);
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);
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);
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);
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);
}
@@ -73,10 +73,10 @@ public class VeroBoard extends AbstractVeroBoard implements ILayeredComponent {
y += spacing;
g2d.setColor(stripColor);
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();
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) {
x += spacing;
g2d.setColor(Constants.CANVAS_COLOR);
@@ -91,10 +91,10 @@ public class VeroBoard extends AbstractVeroBoard implements ILayeredComponent {
y = firstPoint.getY();
g2d.setColor(stripColor);
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();
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) {
y += spacing;
g2d.setColor(Constants.CANVAS_COLOR);
@@ -62,11 +62,11 @@ public class ChassisPanel extends AbstractShape {
Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(color);
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.getY() - firstPoint.getY()));
} 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.getY() - firstPoint.getY()), radius, radius);
}
@@ -78,11 +78,11 @@ public class ChassisPanel extends AbstractShape {
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: borderColor);
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.getY() - firstPoint.getY()));
} 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.getY() - firstPoint.getY()), radius, radius);
}
@@ -50,7 +50,7 @@ public class EllipticalCutout extends AbstractShape {
if (componentState != ComponentState.DRAGGING) {
Composite oldComposite = applyAlpha(g2d, componentState);
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);
}
// Do not track any changes that follow because the whole oval has been
@@ -58,7 +58,7 @@ public class EllipticalCutout extends AbstractShape {
drawingObserver.stopTracking();
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: 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
@@ -56,7 +56,7 @@ public class RectangularCutout extends AbstractShape {
if (componentState != ComponentState.DRAGGING) {
Composite oldComposite = applyAlpha(g2d, componentState);
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);
g2d.setComposite(oldComposite);
}
@@ -65,7 +65,7 @@ public class RectangularCutout extends AbstractShape {
drawingObserver.stopTracking();
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: 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);
}
@@ -67,9 +67,9 @@ public class CutLine extends AbstractTransparentComponent<Void> {
Composite oldComposite = applyAlpha(g2d);
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
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);
}
@@ -77,16 +77,16 @@ public class Eyelet extends AbstractTransparentComponent<String> {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f));
g2d.setColor(color);
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();
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: 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.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
: 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);
}
@@ -130,7 +130,7 @@ public class Line extends AbstractLeadedComponent<Void> {
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) {
@@ -82,7 +82,7 @@ public class MultimeterProbe extends AbstractTransparentComponent<Color> {
g2d.setColor(Constants.TRANSPARENT_COLOR);
drawingObserver.startTrackingContinuityArea(true);
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));
drawingObserver.stopTrackingContinuityArea();
@@ -240,14 +240,14 @@ public class PCBTerminalBlock extends AbstractTransparentComponent<PCBTerminalBl
if (outlineMode) {
// g2d.setColor(Constants.TRANSPARENT_COLOR);
// 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);
// drawingObserver.stopTrackingContinuityArea();
g2d.setColor(theme.getOutlineColor());
} else {
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);
g2d.setColor(CIRCLE_COLOR.darker());
@@ -89,22 +89,22 @@ public class TraceCut extends AbstractTransparentComponent<Void> implements ILay
: getBoardColor());
drawingObserver.startTrackingContinuityArea(false);
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
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();
} else {
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: getBoardColor());
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();
g2d.setColor(Constants.CANVAS_COLOR);
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.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);
}
@@ -73,16 +73,16 @@ public class Turret extends AbstractTransparentComponent<String> {
g2d.setColor(color);
g2d.setStroke(ObjectCache.getInstance().fetchZoomableStroke(1f));
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();
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: 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.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
: 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);
}
@@ -338,10 +338,10 @@ public class DIPSwitch extends AbstractTransparentComponent<String> implements I
int pinHeight = getClosestOdd(pinSize
/ (getOrientation() == Orientation.DEFAULT || getOrientation() == Orientation._180 ? 1f
: 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);
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);
}
}
@@ -213,10 +213,10 @@ public class FuseHolderPanel extends AbstractMultiPartComponent<String> {
for (Point2D p : controlPoints) {
if (outlineMode) {
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 {
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) {
if (outlineMode) {
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 {
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[] {
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),
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) {
if (!outlineMode) {
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.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;
@@ -317,21 +317,21 @@ public class MiniToggleSwitch extends AbstractTransparentComponent<ToggleSwitchT
if (outlineMode) {
// g2d.setColor(Constants.TRANSPARENT_COLOR);
// 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();
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 {
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.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());
// 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();
}
}
@@ -168,7 +168,7 @@ public class OpenJack1_4 extends AbstractMultiPartComponent<OpenJackType> {
int springLength = (int) SPRING_LENGTH.convertToPixels();
int holeToEdge = (int) HOLE_TO_EDGE.convertToPixels();
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 sleeveTransform = AffineTransform.getRotateInstance(getValue() == OpenJackType.SWITCHED ? SLEEVE_SWITCHED_THETA : SLEEVE_THETA, controlPoints[0].getX(), centerY);
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 holeToEdge = (int) HOLE_TO_EDGE.convertToPixels();
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 sleeveTransform = AffineTransform.getRotateInstance(getValue() == OpenJackType.SWITCHED ? SLEEVE_SWITCHED_THETA : SLEEVE_THETA, controlPoints[0].getX(), centerY);
Point2D ringOrSwitchLabel = new Point2D.Double(0, 0);
@@ -239,10 +239,10 @@ public class PinHeader extends AbstractTransparentComponent<Void> {
for (Point2D point : controlPoints) {
if (!outlineMode) {
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.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;
@@ -284,14 +284,14 @@ public class SlideSwitch extends AbstractTransparentComponent<SlideSwitchType> i
Point2D p = controlPoints[i];
if (outlineMode) {
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);
} else {
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);
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);
}
}
@@ -134,7 +134,7 @@ public class SwitchLatchingSymbol
Math.atan2(endPoint.getY() - startPoint.getY(), endPoint.getX() - startPoint.getX());
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);
}
}
@@ -188,9 +188,9 @@ public class TactileMicroSwitch extends AbstractLabeledComponent<String> impleme
throw new RuntimeException("Unexpected orientation: " + orientation);
}
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] =
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);
}
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());
g2d.drawString(label, drawX, drawY);
@@ -187,16 +187,16 @@ public class S1Switch extends AbstractTransparentComponent<Void> implements ISwi
Point2D p = controlPoints[i];
if (outlineMode) {
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 {
g2d.setColor(PAD_COLOR);
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();
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.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) {
@@ -213,8 +213,8 @@ public class S1Switch extends AbstractTransparentComponent<Void> implements ISwi
Stroke stroke = g2d.getStroke();
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(2f));
g2d.setColor(LINE_COLOR);
g2d.drawLine((int)(p.getX() - padDiameter / 3), (int)(p.getY() + dy * padDiameter * 4 / 5),
(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) Math.round(p.getX() + padDiameter / 3), (int) Math.round(p.getY() + dy * padDiameter * 4 / 5));
g2d.setStroke(stroke);
}
@@ -1,226 +1,226 @@
/*
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.components.misc;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Iterator;
import java.util.List;
import org.diylc.components.AbstractComponent;
import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent;
import org.diylc.core.IDrawingObserver;
import org.diylc.core.Project;
import org.diylc.core.VisibilityPolicy;
import org.diylc.core.annotations.BomPolicy;
import org.diylc.core.annotations.ComponentDescriptor;
import org.diylc.core.annotations.EditableProperty;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
import org.diylc.utils.BomEntry;
import org.diylc.utils.BomMaker;
@ComponentDescriptor(name = "Bill of Materials", author = "Branislav Stojkovic", category = "Misc", description = "",
instanceNamePrefix = "BOM", zOrder = IDIYComponent.TEXT, bomPolicy = BomPolicy.NEVER_SHOW,
autoEdit = false)
public class BOM extends AbstractComponent<Void> {
public static Size DEFAULT_SIZE = new Size(10d, SizeUnit.cm);
public static Size SPACING = new Size(0.1d, SizeUnit.in);
public static Color COLOR = Color.black;
public static String DEFAULT_TEXT = "No components to show in the Bill of Materials";
private static final long serialVersionUID = 1L;
private Size size = DEFAULT_SIZE;
private Point2D.Double point = new Point2D.Double(0, 0);
private Color color = COLOR;
@Override
public String getControlPointNodeName(int index) {
return null;
}
@Override
public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
IDrawingObserver drawingObserver) {
List<BomEntry> bom = BomMaker.getInstance().createBom(project.getComponents());
// Cleanup entries that do not have a value set.
Iterator<BomEntry> iterator = bom.iterator();
while (iterator.hasNext()) {
BomEntry entry = iterator.next();
if (entry.getValue() == null || entry.getName().toLowerCase().contains("bom")) {
iterator.remove();
}
}
g2d.setFont(project.getFont());
g2d.setColor(componentState == ComponentState.DRAGGING || componentState == ComponentState.SELECTED ? SELECTION_COLOR
: getColor());
// Determine maximum name length and maximum value length to calculate
// number of columns.
FontMetrics fontMetrics = g2d.getFontMetrics();
int maxNameWidth = 0;
int maxValueWidth = 0;
int maxHeight = 0;
for (BomEntry entry : bom) {
String valueStr;
if (entry.getValue() == null || entry.getValue().trim().isEmpty()) {
valueStr = "qty " + entry.getQuantity().toString();
} else {
valueStr = entry.getValue().toString();
}
Rectangle2D stringBounds = fontMetrics.getStringBounds(entry.getName(), g2d);
if (stringBounds.getWidth() > maxNameWidth) {
maxNameWidth = (int) stringBounds.getWidth();
}
if (stringBounds.getHeight() > maxHeight) {
maxHeight = (int) stringBounds.getHeight();
}
stringBounds = fontMetrics.getStringBounds(valueStr, g2d);
if (stringBounds.getWidth() > maxValueWidth) {
maxValueWidth = (int) stringBounds.getWidth();
}
if (stringBounds.getHeight() > maxHeight) {
maxHeight = (int) stringBounds.getHeight();
}
}
// Calculate maximum entry size.
int maxEntrySize = maxNameWidth + maxValueWidth + 2 * (int) SPACING.convertToPixels();
int columnCount = (int) size.convertToPixels() / maxEntrySize;
if (columnCount == 0)
columnCount = 1;
int columnWidth = (int) size.convertToPixels() / columnCount;
int entriesPerColumn = (int) Math.ceil(1.d * bom.size() / columnCount);
if (entriesPerColumn == 0) {
g2d.drawString(DEFAULT_TEXT, (int)point.getX(), (int)point.getY());
return;
}
for (int i = 0; i < bom.size(); i++) {
String valueStr;
BomEntry entry = bom.get(i);
if (entry.getValue() == null || entry.getValue().trim().isEmpty()) {
valueStr = "qty " + entry.getQuantity().toString();
} else {
valueStr = entry.getValue().toString();
}
int columnIndex = i / entriesPerColumn;
int rowIndex = i % entriesPerColumn;
int x = (int)(point.getX() + columnIndex * columnWidth);
int y = (int)(point.getY() + rowIndex * maxHeight);
g2d.drawString(entry.getName(), x, y);
x += maxNameWidth + SPACING.convertToPixels();
g2d.drawString(valueStr, x, y);
}
}
@Override
public void drawIcon(Graphics2D g2d, int width, int height) {
g2d.setColor(Color.white);
g2d.fillRect(width / 8, 0, 6 * width / 8, height - 1);
g2d.setColor(Color.black);
g2d.drawRect(width / 8, 0, 6 * width / 8, height - 1);
g2d.setFont(LABEL_FONT.deriveFont(1f * 9 * width / 32).deriveFont(Font.PLAIN));
FontMetrics fontMetrics = g2d.getFontMetrics();
Rectangle2D rect = fontMetrics.getStringBounds("BOM", g2d);
int textHeight = (int) (rect.getHeight());
int textWidth = (int) (rect.getWidth());
// Center text horizontally and vertically.
int x = (width - textWidth) / 2 + 1;
int y = textHeight + 2;
g2d.drawString("BOM", x, y);
g2d.setFont(g2d.getFont().deriveFont(1f * 5 * width / 32));
fontMetrics = g2d.getFontMetrics();
rect = fontMetrics.getStringBounds("resistors", g2d);
x = (width - textWidth) / 2 + 1;
y = height / 2 + 2;
g2d.drawString("resistors", x, y);
y += rect.getHeight() - 1;
g2d.drawString("tubes", x, y);
y += rect.getHeight() - 1;
g2d.drawString("diodes", x, y);
}
@Override
public int getControlPointCount() {
return 1;
}
@Override
public Point2D getControlPoint(int index) {
return point;
}
@Override
public boolean isControlPointSticky(int index) {
return false;
}
@Override
public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
return VisibilityPolicy.NEVER;
}
@Override
public void setControlPoint(Point2D point, int index) {
this.point.setLocation(point);
}
@EditableProperty(name = "Width")
public Size getSize() {
return size;
}
public void setSize(Size size) {
this.size = size;
}
@EditableProperty
public Color getColor() {
if (color == null) {
color = COLOR;
}
return color;
}
public void setColor(Color color) {
this.color = color;
}
@Override
public Void getValue() {
return null;
}
@Override
public void setValue(Void value) {}
}
/*
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.components.misc;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Iterator;
import java.util.List;
import org.diylc.components.AbstractComponent;
import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent;
import org.diylc.core.IDrawingObserver;
import org.diylc.core.Project;
import org.diylc.core.VisibilityPolicy;
import org.diylc.core.annotations.BomPolicy;
import org.diylc.core.annotations.ComponentDescriptor;
import org.diylc.core.annotations.EditableProperty;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
import org.diylc.utils.BomEntry;
import org.diylc.utils.BomMaker;
@ComponentDescriptor(name = "Bill of Materials", author = "Branislav Stojkovic", category = "Misc", description = "",
instanceNamePrefix = "BOM", zOrder = IDIYComponent.TEXT, bomPolicy = BomPolicy.NEVER_SHOW,
autoEdit = false)
public class BOM extends AbstractComponent<Void> {
public static Size DEFAULT_SIZE = new Size(10d, SizeUnit.cm);
public static Size SPACING = new Size(0.1d, SizeUnit.in);
public static Color COLOR = Color.black;
public static String DEFAULT_TEXT = "No components to show in the Bill of Materials";
private static final long serialVersionUID = 1L;
private Size size = DEFAULT_SIZE;
private Point2D.Double point = new Point2D.Double(0, 0);
private Color color = COLOR;
@Override
public String getControlPointNodeName(int index) {
return null;
}
@Override
public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
IDrawingObserver drawingObserver) {
List<BomEntry> bom = BomMaker.getInstance().createBom(project.getComponents());
// Cleanup entries that do not have a value set.
Iterator<BomEntry> iterator = bom.iterator();
while (iterator.hasNext()) {
BomEntry entry = iterator.next();
if (entry.getValue() == null || entry.getName().toLowerCase().contains("bom")) {
iterator.remove();
}
}
g2d.setFont(project.getFont());
g2d.setColor(componentState == ComponentState.DRAGGING || componentState == ComponentState.SELECTED ? SELECTION_COLOR
: getColor());
// Determine maximum name length and maximum value length to calculate
// number of columns.
FontMetrics fontMetrics = g2d.getFontMetrics();
int maxNameWidth = 0;
int maxValueWidth = 0;
int maxHeight = 0;
for (BomEntry entry : bom) {
String valueStr;
if (entry.getValue() == null || entry.getValue().trim().isEmpty()) {
valueStr = "qty " + entry.getQuantity().toString();
} else {
valueStr = entry.getValue().toString();
}
Rectangle2D stringBounds = fontMetrics.getStringBounds(entry.getName(), g2d);
if (stringBounds.getWidth() > maxNameWidth) {
maxNameWidth = (int) stringBounds.getWidth();
}
if (stringBounds.getHeight() > maxHeight) {
maxHeight = (int) stringBounds.getHeight();
}
stringBounds = fontMetrics.getStringBounds(valueStr, g2d);
if (stringBounds.getWidth() > maxValueWidth) {
maxValueWidth = (int) stringBounds.getWidth();
}
if (stringBounds.getHeight() > maxHeight) {
maxHeight = (int) stringBounds.getHeight();
}
}
// Calculate maximum entry size.
int maxEntrySize = maxNameWidth + maxValueWidth + 2 * (int) SPACING.convertToPixels();
int columnCount = (int) size.convertToPixels() / maxEntrySize;
if (columnCount == 0)
columnCount = 1;
int columnWidth = (int) size.convertToPixels() / columnCount;
int entriesPerColumn = (int) Math.ceil(1.d * bom.size() / columnCount);
if (entriesPerColumn == 0) {
g2d.drawString(DEFAULT_TEXT, (int) Math.round(point.getX()), (int) Math.round(point.getY()));
return;
}
for (int i = 0; i < bom.size(); i++) {
String valueStr;
BomEntry entry = bom.get(i);
if (entry.getValue() == null || entry.getValue().trim().isEmpty()) {
valueStr = "qty " + entry.getQuantity().toString();
} else {
valueStr = entry.getValue().toString();
}
int columnIndex = i / entriesPerColumn;
int rowIndex = i % entriesPerColumn;
int x = (int) Math.round(point.getX() + columnIndex * columnWidth);
int y = (int) Math.round(point.getY() + rowIndex * maxHeight);
g2d.drawString(entry.getName(), x, y);
x += maxNameWidth + SPACING.convertToPixels();
g2d.drawString(valueStr, x, y);
}
}
@Override
public void drawIcon(Graphics2D g2d, int width, int height) {
g2d.setColor(Color.white);
g2d.fillRect(width / 8, 0, 6 * width / 8, height - 1);
g2d.setColor(Color.black);
g2d.drawRect(width / 8, 0, 6 * width / 8, height - 1);
g2d.setFont(LABEL_FONT.deriveFont(1f * 9 * width / 32).deriveFont(Font.PLAIN));
FontMetrics fontMetrics = g2d.getFontMetrics();
Rectangle2D rect = fontMetrics.getStringBounds("BOM", g2d);
int textHeight = (int) (rect.getHeight());
int textWidth = (int) (rect.getWidth());
// Center text horizontally and vertically.
int x = (width - textWidth) / 2 + 1;
int y = textHeight + 2;
g2d.drawString("BOM", x, y);
g2d.setFont(g2d.getFont().deriveFont(1f * 5 * width / 32));
fontMetrics = g2d.getFontMetrics();
rect = fontMetrics.getStringBounds("resistors", g2d);
x = (width - textWidth) / 2 + 1;
y = height / 2 + 2;
g2d.drawString("resistors", x, y);
y += rect.getHeight() - 1;
g2d.drawString("tubes", x, y);
y += rect.getHeight() - 1;
g2d.drawString("diodes", x, y);
}
@Override
public int getControlPointCount() {
return 1;
}
@Override
public Point2D getControlPoint(int index) {
return point;
}
@Override
public boolean isControlPointSticky(int index) {
return false;
}
@Override
public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
return VisibilityPolicy.NEVER;
}
@Override
public void setControlPoint(Point2D point, int index) {
this.point.setLocation(point);
}
@EditableProperty(name = "Width")
public Size getSize() {
return size;
}
public void setSize(Size size) {
this.size = size;
}
@EditableProperty
public Color getColor() {
if (color == null) {
color = COLOR;
}
return color;
}
public void setColor(Color color) {
this.color = color;
}
@Override
public Void getValue() {
return null;
}
@Override
public void setValue(Void value) {}
}
@@ -161,7 +161,7 @@ public class Image extends AbstractTransparentComponent<Void> {
@Override
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
@@ -75,7 +75,7 @@ public class Loadline extends AbstractBoard {
Composite oldComposite = applyAlpha(g2d, componentState);
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()));
g2d.setComposite(oldComposite);
@@ -88,7 +88,7 @@ public class Loadline extends AbstractBoard {
? SELECTION_COLOR
: 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()));
}
@@ -212,8 +212,8 @@ public class AudioTransformer extends AbstractMultiPartComponent<String> impleme
body = new Area[2];
double leadSpacing = this.leadSpacing.convertToPixels();
double windingSpacing = this.windingSpacing.convertToPixels();
double centerX = (int) (controlPoints[0].getX() + windingSpacing / 2);
double centerY = (int) (controlPoints[0].getY() + leadSpacing);
double centerX = (int) Math.round(controlPoints[0].getX() + windingSpacing / 2);
double centerY = (int) Math.round(controlPoints[0].getY() + leadSpacing);
int coreWidth = getClosestOdd(this.coreWidth.convertToPixels());
int coreThickness = getClosestOdd(this.coreThickness.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;
for (Point2D point : controlPoints) {
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.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);
@@ -176,7 +176,7 @@ public class BoxTrimmer extends AbstractTransparentComponent<Resistance> {
// Draw pins
g2d.setColor(outlineMode ? theme.getOutlineColor() : PIN_COLOR);
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
@@ -425,7 +425,7 @@ public class MiniaturePotentiometer extends AbstractPotentiometer {
int x = (panelWidth - textWidth) / 2;
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
@@ -381,10 +381,10 @@ public class MultiSectionCapacitor extends AbstractLabeledComponent<Capacitance[
for (Point2D point : controlPoints) {
if (!outlineMode) {
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.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.
@@ -345,7 +345,7 @@ public class PotentiometerPanel extends AbstractPotentiometer implements ILayere
int x = (panelWidth - textWidth) / 2;
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.
rect = fontMetrics.getStringBounds(getValueForDisplay(), g2d);
@@ -356,7 +356,7 @@ public class PotentiometerPanel extends AbstractPotentiometer implements ILayere
x = (panelWidth - textWidth) / 2;
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.
if (getShowMarkers()) {
@@ -1,182 +1,182 @@
/*
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.components.passive;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.Shape;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import org.diylc.components.Abstract3LegSymbol;
import org.diylc.components.semiconductors.SymbolFlipping;
import org.diylc.components.transform.ThreeLegTransformer;
import org.diylc.core.IDIYComponent;
import org.diylc.core.annotations.ComponentDescriptor;
import org.diylc.core.annotations.EditableProperty;
import org.diylc.core.annotations.KeywordPolicy;
@ComponentDescriptor(name = "Potentiometer", author = "MCbx", category = "Schematic Symbols",
instanceNamePrefix = "VR", description = "Potentiometer symbol",
zOrder = IDIYComponent.COMPONENT, transformer = ThreeLegTransformer.class, keywordPolicy = KeywordPolicy.SHOW_TAG,
keywordTag = "Schematic")
public class PotentiometerSymbol extends Abstract3LegSymbol {
private static final long serialVersionUID = 1L;
private DrawStyle drawStyle = DrawStyle.ANSI;
public PotentiometerSymbol() {
this.color = Color.blue;
}
@EditableProperty(name = "Draw Standard")
public DrawStyle getDrawStandard() {
if (drawStyle == null) {
drawStyle = DrawStyle.ANSI;
}
return drawStyle;
}
public void setDrawStandard(DrawStyle drawStyle) {
this.drawStyle = drawStyle;
body = null;
}
public Shape[] getBody() {
Shape[] body = new Shape[3];
Point2D[] controlPoints = getControlPoints();
double x = controlPoints[0].getX();
double y = controlPoints[0].getY();
int pinSpacing = (int) PIN_SPACING.convertToPixels();
GeneralPath polyline = new GeneralPath();
// Draw lead in
polyline.moveTo(x + pinSpacing * 2, y - pinSpacing * 2);
polyline.lineTo(x + pinSpacing * 2, y - pinSpacing * 2 + pinSpacing / 2);
if (getDrawStandard() == DrawStyle.ANSI) {
// 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) + 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) + 4 * pinSpacing / 2 - pinSpacing / 4);
polyline.lineTo(x + pinSpacing * 2 - pinSpacing / 4, (y - pinSpacing * 2) + 5 * pinSpacing / 2 - pinSpacing / 3
- pinSpacing / 16);
polyline.lineTo(x + pinSpacing * 2 + pinSpacing / 4, (y - pinSpacing * 2) + 6 * pinSpacing / 2 - pinSpacing / 2
+ pinSpacing / 16);
polyline.lineTo(x + pinSpacing * 2 - pinSpacing / 4, (y - pinSpacing * 2) + 7 * pinSpacing / 2 - pinSpacing / 2
- pinSpacing / 16);
polyline.lineTo(x + pinSpacing * 2 + pinSpacing / 4, (y - pinSpacing * 2) + 7 * pinSpacing / 2 - pinSpacing / 2
+ pinSpacing / 4);
polyline.lineTo(x + pinSpacing * 2, (y - pinSpacing * 2) + 7 * pinSpacing / 2);
polyline.lineTo(x + pinSpacing * 2, y + pinSpacing * 2);
} else {
// Draw a rect and lead out
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 * 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.lineTo(x + pinSpacing * 2, y + pinSpacing * 2);
}
// The control line
polyline.moveTo(x, y);
polyline.lineTo(x + pinSpacing * 2 - pinSpacing / 2, y);
body[1] = polyline;
polyline = new GeneralPath();
body[0] = polyline;
// Arrow
polyline = new GeneralPath();
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 / 3, y);
body[2] = polyline;
return body;
}
@Override
protected double getLabelX(Rectangle2D shapeRect, Rectangle2D textRect, FontMetrics fontMetrics, boolean outlineMode) {
double x = super.getLabelX(shapeRect, textRect, fontMetrics, outlineMode);
if (getFlip() == SymbolFlipping.X)
return x - (int) (PIN_SPACING.convertToPixels() / 2);
return x + (int) PIN_SPACING.convertToPixels();
}
// @Override
// protected int getLabelX(Rectangle2D shapeRect, Rectangle2D textRect, FontMetrics fontMetrics,
// boolean outlineMode) {
// int pinSpacing = (int) PIN_SPACING.convertToPixels();
// if (controlPoints[0].x < controlPoints[1].x && controlPoints[0].x < controlPoints[2].x)
// return controlPoints[1].x + pinSpacing / 3;
// if (controlPoints[0].y < controlPoints[1].y && controlPoints[0].y < controlPoints[2].y)
// return controlPoints[0].x - (int) (textRect.getWidth() / 2);
// if (controlPoints[0].x > controlPoints[1].x && controlPoints[0].x > controlPoints[2].x)
// return controlPoints[1].x - pinSpacing / 2 - (int) textRect.getWidth();
// if (controlPoints[0].y > controlPoints[1].y && controlPoints[0].y > controlPoints[2].y)
// return controlPoints[0].x - (int) (textRect.getWidth() / 2);
// return 2 * ((int) (shapeRect.getWidth() - textRect.getWidth()) / 2 + (int) shapeRect.getX());
// }
//
// @Override
// protected int getLabelY(Rectangle2D shapeRect, Rectangle2D textRect, FontMetrics fontMetrics,
// boolean outlineMode) {
// int pinSpacing = (int) PIN_SPACING.convertToPixels();
// if (controlPoints[0].x < controlPoints[1].x && controlPoints[0].x < controlPoints[2].x)
// return controlPoints[0].y;
// if (controlPoints[0].y < controlPoints[1].y && controlPoints[0].y < controlPoints[2].y)
// return controlPoints[1].y + pinSpacing * 2 / 3;
// if (controlPoints[0].x > controlPoints[1].x && controlPoints[0].x > controlPoints[2].x)
// return controlPoints[0].y;
// if (controlPoints[0].y > controlPoints[1].y && controlPoints[0].y > controlPoints[2].y)
// return controlPoints[1].y - pinSpacing * 2 / 3;
// return 2 * ((int) (shapeRect.getHeight() - textRect.getHeight()) / 2 + fontMetrics.getAscent()
// + (int) shapeRect
// .getY());
// }
@Override
public void drawIcon(Graphics2D g2d, int width, int height) {
g2d.rotate(-Math.PI / 4, width / 2, height / 2);
g2d.setColor(Color.blue);
g2d.drawLine(0, height / 2, 4, 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,
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.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));
}
public enum DrawStyle {
ANSI, IEC
}
}
/*
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.components.passive;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.Shape;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import org.diylc.components.Abstract3LegSymbol;
import org.diylc.components.semiconductors.SymbolFlipping;
import org.diylc.components.transform.ThreeLegTransformer;
import org.diylc.core.IDIYComponent;
import org.diylc.core.annotations.ComponentDescriptor;
import org.diylc.core.annotations.EditableProperty;
import org.diylc.core.annotations.KeywordPolicy;
@ComponentDescriptor(name = "Potentiometer", author = "MCbx", category = "Schematic Symbols",
instanceNamePrefix = "VR", description = "Potentiometer symbol",
zOrder = IDIYComponent.COMPONENT, transformer = ThreeLegTransformer.class, keywordPolicy = KeywordPolicy.SHOW_TAG,
keywordTag = "Schematic")
public class PotentiometerSymbol extends Abstract3LegSymbol {
private static final long serialVersionUID = 1L;
private DrawStyle drawStyle = DrawStyle.ANSI;
public PotentiometerSymbol() {
this.color = Color.blue;
}
@EditableProperty(name = "Draw Standard")
public DrawStyle getDrawStandard() {
if (drawStyle == null) {
drawStyle = DrawStyle.ANSI;
}
return drawStyle;
}
public void setDrawStandard(DrawStyle drawStyle) {
this.drawStyle = drawStyle;
body = null;
}
public Shape[] getBody() {
Shape[] body = new Shape[3];
Point2D[] controlPoints = getControlPoints();
double x = controlPoints[0].getX();
double y = controlPoints[0].getY();
int pinSpacing = (int) PIN_SPACING.convertToPixels();
GeneralPath polyline = new GeneralPath();
// Draw lead in
polyline.moveTo(x + pinSpacing * 2, y - pinSpacing * 2);
polyline.lineTo(x + pinSpacing * 2, y - pinSpacing * 2 + pinSpacing / 2);
if (getDrawStandard() == DrawStyle.ANSI) {
// 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) + 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) + 4 * pinSpacing / 2 - pinSpacing / 4);
polyline.lineTo(x + pinSpacing * 2 - pinSpacing / 4, (y - pinSpacing * 2) + 5 * pinSpacing / 2 - pinSpacing / 3
- pinSpacing / 16);
polyline.lineTo(x + pinSpacing * 2 + pinSpacing / 4, (y - pinSpacing * 2) + 6 * pinSpacing / 2 - pinSpacing / 2
+ pinSpacing / 16);
polyline.lineTo(x + pinSpacing * 2 - pinSpacing / 4, (y - pinSpacing * 2) + 7 * pinSpacing / 2 - pinSpacing / 2
- pinSpacing / 16);
polyline.lineTo(x + pinSpacing * 2 + pinSpacing / 4, (y - pinSpacing * 2) + 7 * pinSpacing / 2 - pinSpacing / 2
+ pinSpacing / 4);
polyline.lineTo(x + pinSpacing * 2, (y - pinSpacing * 2) + 7 * pinSpacing / 2);
polyline.lineTo(x + pinSpacing * 2, y + pinSpacing * 2);
} else {
// Draw a rect and lead out
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 * 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.lineTo(x + pinSpacing * 2, y + pinSpacing * 2);
}
// The control line
polyline.moveTo(x, y);
polyline.lineTo(x + pinSpacing * 2 - pinSpacing / 2, y);
body[1] = polyline;
polyline = new GeneralPath();
body[0] = polyline;
// Arrow
polyline = new GeneralPath();
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 / 3, y);
body[2] = polyline;
return body;
}
@Override
protected double getLabelX(Rectangle2D shapeRect, Rectangle2D textRect, FontMetrics fontMetrics, boolean outlineMode) {
double x = super.getLabelX(shapeRect, textRect, fontMetrics, outlineMode);
if (getFlip() == SymbolFlipping.X)
return x - (int) (PIN_SPACING.convertToPixels() / 2);
return x + (int) PIN_SPACING.convertToPixels();
}
// @Override
// protected int getLabelX(Rectangle2D shapeRect, Rectangle2D textRect, FontMetrics fontMetrics,
// boolean outlineMode) {
// int pinSpacing = (int) PIN_SPACING.convertToPixels();
// if (controlPoints[0].x < controlPoints[1].x && controlPoints[0].x < controlPoints[2].x)
// return controlPoints[1].x + pinSpacing / 3;
// if (controlPoints[0].y < controlPoints[1].y && controlPoints[0].y < controlPoints[2].y)
// return controlPoints[0].x - (int) (textRect.getWidth() / 2);
// if (controlPoints[0].x > controlPoints[1].x && controlPoints[0].x > controlPoints[2].x)
// return controlPoints[1].x - pinSpacing / 2 - (int) textRect.getWidth();
// if (controlPoints[0].y > controlPoints[1].y && controlPoints[0].y > controlPoints[2].y)
// return controlPoints[0].x - (int) (textRect.getWidth() / 2);
// return 2 * ((int) (shapeRect.getWidth() - textRect.getWidth()) / 2 + (int) Math.round(shapeRect.getX()));
// }
//
// @Override
// protected int getLabelY(Rectangle2D shapeRect, Rectangle2D textRect, FontMetrics fontMetrics,
// boolean outlineMode) {
// int pinSpacing = (int) PIN_SPACING.convertToPixels();
// if (controlPoints[0].x < controlPoints[1].x && controlPoints[0].x < controlPoints[2].x)
// return controlPoints[0].y;
// if (controlPoints[0].y < controlPoints[1].y && controlPoints[0].y < controlPoints[2].y)
// return controlPoints[1].y + pinSpacing * 2 / 3;
// if (controlPoints[0].x > controlPoints[1].x && controlPoints[0].x > controlPoints[2].x)
// return controlPoints[0].y;
// if (controlPoints[0].y > controlPoints[1].y && controlPoints[0].y > controlPoints[2].y)
// return controlPoints[1].y - pinSpacing * 2 / 3;
// return 2 * ((int) (shapeRect.getHeight() - textRect.getHeight()) / 2 + fontMetrics.getAscent()
// + (int) shapeRect
// .getY());
// }
@Override
public void drawIcon(Graphics2D g2d, int width, int height) {
g2d.rotate(-Math.PI / 4, width / 2, height / 2);
g2d.setColor(Color.blue);
g2d.drawLine(0, height / 2, 4, 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,
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.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));
}
public enum DrawStyle {
ANSI, IEC
}
}
@@ -405,10 +405,10 @@ public class TrimmerPotentiometer extends AbstractPotentiometer {
for (Point2D point : controlPoints) {
if (!outlineMode) {
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.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.
@@ -451,7 +451,7 @@ public class TrimmerPotentiometer extends AbstractPotentiometer {
int x = (panelWidth - textWidth) / 2;
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
@@ -237,9 +237,9 @@ public class DIL_IC extends AbstractLabeledComponent<String> implements IGerberC
throw new RuntimeException("Unexpected orientation: " + orientation);
}
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] =
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];
// determine points relative to rotation
int textX1 = (int) (point.getX() - 2 * pinSize);
int textY1 = (int) (point.getY() + pinSize / 2);
int textX2 = (int) (point.getX() + pinSize);
int textY2 = (int) (point.getY() + pinSize / 2);
int textX1 = (int) Math.round(point.getX() - 2 * pinSize);
int textY1 = (int) Math.round(point.getY() + pinSize / 2);
int textX2 = (int) Math.round(point.getX() + pinSize);
int textY2 = (int) Math.round(point.getY() + pinSize / 2);
if (orientation == Orientation._90) {
textX2 = textX2 - pinSize - pinSize / 2;
textY2 = textY2 + pinSize;
@@ -202,7 +202,7 @@ public class MultiwattIC extends AbstractTransparentComponent<String> implements
default:
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)
@@ -227,7 +227,7 @@ public class MultiwattIC extends AbstractTransparentComponent<String> implements
default:
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:
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;
for (Point2D point : controlPoints) {
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.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) {
if (!outlineMode) {
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.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];
@@ -49,7 +49,7 @@ public class Ellipse extends AbstractShapeWithDimensions {
Composite oldComposite = applyAlpha(g2d, componentState);
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);
// Do not track any changes that follow because the whole oval has been
@@ -57,7 +57,7 @@ public class Ellipse extends AbstractShapeWithDimensions {
drawingObserver.stopTracking();
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: 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
@@ -55,7 +55,7 @@ public class Rectangle extends AbstractShapeWithDimensions {
Composite oldComposite = applyAlpha(g2d, componentState);
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);
g2d.setComposite(oldComposite);
@@ -64,7 +64,7 @@ public class Rectangle extends AbstractShapeWithDimensions {
drawingObserver.stopTracking();
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: 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);
}
@@ -158,11 +158,11 @@ public class TapeMeasure extends AbstractLeadedComponent<String> {
int legLength = (int) (getPoints()[0].distance(getPoints()[1]) - strWidth) / 2 - 6;
// 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.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.getY() - Math.sin(theta) * legLength));
@@ -365,43 +365,43 @@ public class SubminiTube extends AbstractLabeledComponent<String> {
case DEFAULT:
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
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.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;
case _90:
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
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.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;
case _180:
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
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.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;
case _270:
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
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.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;
}
}
if (getTopLead()) {
Point2D point = controlPoints[controlPoints.length - 1];
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.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 {
if (!outlineMode) {
@@ -409,9 +409,9 @@ public class SubminiTube extends AbstractLabeledComponent<String> {
: 0; i < controlPoints.length; i++) {
Point2D point = controlPoints[i];
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.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;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.util.HashSet;
import java.util.Set;
import org.diylc.common.IProjectEditor;
import org.diylc.common.Orientation;
import org.diylc.components.AbstractLeadedComponent;
import org.diylc.components.AbstractCurvedComponent.PointCount;
import org.diylc.components.connectivity.AWG;
import org.diylc.components.connectivity.HookupWire;
import org.diylc.components.guitar.AbstractGuitarPickup;
import org.diylc.components.guitar.SingleCoilPickup;
import org.diylc.components.passive.PotentiometerPanel;
import org.diylc.components.passive.PotentiometerPanel.Type;
import org.diylc.components.semiconductors.AbstractTransistorPackage;
import org.diylc.components.semiconductors.TransistorTO126;
import org.diylc.components.semiconductors.TransistorTO220;
import org.diylc.components.tube.TubeSocket;
import org.diylc.components.tube.TubeSocket.Mount;
import org.diylc.core.IDIYComponent;
import org.diylc.core.Project;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
import org.diylc.presenter.InstantiationManager;
public class FlexibleLeadsEditor implements IProjectEditor {
private InstantiationManager instantiationManager;
@Override
public Set<IDIYComponent<?>> edit(Project project, Set<IDIYComponent<?>> selection) {
Set<IDIYComponent<?>> newSelection = new HashSet<IDIYComponent<?>>(selection);
for (IDIYComponent<?> c : selection) {
if (c instanceof AbstractLeadedComponent<?>)
addLeads((AbstractLeadedComponent<?>) c, project, newSelection);
else if (c instanceof AbstractTransistorPackage)
addLeads((AbstractTransistorPackage) c, project, newSelection);
else if (c instanceof PotentiometerPanel)
addLeads((PotentiometerPanel) c, project, newSelection);
else if (c instanceof TubeSocket)
addLeads((TubeSocket) c, project, newSelection);
else if (c instanceof AbstractGuitarPickup)
addLeads((AbstractGuitarPickup) c, project, newSelection);
}
return newSelection;
}
private void addLeads(AbstractLeadedComponent<?> leaded, Project project, Set<IDIYComponent<?>> newSelection) {
Size l = leaded.getLength();
// do not apply to jumpers, etc
if (l == null)
return;
Point2D p1 = (Point2D) leaded.getControlPoint(0).clone();
Point2D p2 = (Point2D) leaded.getControlPoint(1).clone();
double d = p1.distance(p2);
double len = l.convertToPixels() + 2;
double diff = (d - len) / 2;
if (diff < 20)
return;
// find the center and angle
double centerX = (p1.getX() + p2.getX()) / 2.0;
double centerY = (p1.getY() + p2.getY()) / 2.0;
double theta = Math.atan2(p2.getY() - p1.getY(), p2.getX() - p1.getX());
// 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 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(newP2, 1);
// make the standard leads go away
leaded.setHideShortLeads(true);
// create leads
HookupWire w1 = new HookupWire();
getInstantiationManager().fillWithDefaultProperties(w1, null);
w1.setValue(AWG._26);
w1.setLeadColor(leaded.getLeadColor());
// w1.setPointCount(PointCount.THREE);
w1.setControlPoint(p1, 0);
for (int i = 1; i < w1.getControlPointCount() - 1; i++) {
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(newP1, w1.getControlPointCount() - 1);
newSelection.add(w1);
HookupWire w2 = new HookupWire();
getInstantiationManager().fillWithDefaultProperties(w2, null);
w2.setValue(AWG._26);
w2.setLeadColor(leaded.getLeadColor());
// w2.setPointCount(PointCount.THREE);
w2.setControlPoint(p2, 0);
for (int i = 1; i < w2.getControlPointCount() - 1; i++) {
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(newP2, w2.getControlPointCount() - 1);
newSelection.add(w2);
// inject leads right before the component
int index = project.getComponents().indexOf(leaded);
project.getComponents().add(index, w1);
project.getComponents().add(index, w2);
}
private void addLeads(AbstractTransistorPackage c, Project project, Set<IDIYComponent<?>> newSelection) {
Size offsetX = new Size(0.4d, SizeUnit.in);
Size offsetY = new Size(0.1d, SizeUnit.in);
// create leads
for (int i = 0; i < 3; i++) {
Point2D p0 = c.getControlPoint(i);
double dx = -offsetX.convertToPixels();
double dy = offsetY.convertToPixels() * (i - 1);
// calculate lead position
Point2D p1 = new Point2D.Double((int)(p0.getX() + dx / 2), (int)(p0.getY() + dy / 2));
Point2D p2 = new Point2D.Double((int)(p0.getX() + dx), (int)(p0.getY() + dy));
if (c.getOrientation() != Orientation.DEFAULT) {
AffineTransform tx = AffineTransform.getRotateInstance(c.getOrientation().toRadians(), p0.getX(), p0.getY());
tx.transform(p1, p1);
tx.transform(p2, p2);
}
HookupWire w = new HookupWire();
getInstantiationManager().fillWithDefaultProperties(w, null);
// make the leads thicker for TO220 and TO126
if (c instanceof TransistorTO220 || c instanceof TransistorTO126)
w.setValue(AWG._24);
else
w.setValue(AWG._26);
w.setLeadColor(AbstractTransistorPackage.METAL_COLOR);
w.setPointCount(PointCount.THREE);
w.setControlPoint(p0, 0);
w.setControlPoint(p1, 1);
w.setControlPoint(p2, 2);
newSelection.add(w);
// inject leads right before the component
int index = project.getComponents().indexOf(c);
project.getComponents().add(index, w);
}
if (c instanceof TransistorTO220) {
TransistorTO220 t = (TransistorTO220)c;
if (t.getFolded())
t.setLeadLength(new Size(0d, SizeUnit.mm));
}
else if (c instanceof TransistorTO126) {
TransistorTO126 t = (TransistorTO126)c;
if (t.getFolded())
t.setLeadLength(new Size(0d, SizeUnit.mm));
}
}
private void addLeads(PotentiometerPanel c, Project project, Set<IDIYComponent<?>> newSelection) {
Size offsetY = new Size(0.5d, SizeUnit.in);
// don't do it for PCB type
if (c.getType() == Type.PCB)
return;
// create leads
for (int i = 0; i < 3; i++) {
Point2D p0 = c.getControlPoint(i);
double dx = 0;
double dy = offsetY.convertToPixels();
AffineTransform tx = null;
if (c.getOrientation() != Orientation.DEFAULT)
tx = AffineTransform.getRotateInstance(c.getOrientation().toRadians(), p0.getX(), p0.getY());
HookupWire w = new HookupWire();
getInstantiationManager().fillWithDefaultProperties(w, null);
for (int j = 0; j < w.getControlPointCount(); j++) {
Point2D p = new Point2D.Double((int)(p0.getX() + dx * j), (int)(p0.getY() + dy * j));
if (tx != null)
tx.transform(p, p);
w.setControlPoint(p, j);
}
newSelection.add(w);
// inject leads right before the component
int index = project.getComponents().indexOf(c);
project.getComponents().add(index + 1, w);
}
}
private void addLeads(TubeSocket c, Project project, Set<IDIYComponent<?>> newSelection) {
Point2D center = c.getControlPoint(0);
// don't do it for PCB type
if (c.getMount() == Mount.PCB)
return;
// create leads
for (int i = 1; i < c.getControlPointCount(); i++) {
Point2D p = c.getControlPoint(i);
double dx = p.getX() - center.getX();
double dy = p.getY() - center.getY();
// calculate lead position
HookupWire w = new HookupWire();
getInstantiationManager().fillWithDefaultProperties(w, null);
for (int j = 0; j < w.getControlPointCount(); j++) {
Point2D pw = new Point2D.Double((int)(p.getX() + dx * j), (int)(p.getY() + dy * j));
w.setControlPoint(pw, j);
}
newSelection.add(w);
// inject leads right before the component
int index = project.getComponents().indexOf(c);
project.getComponents().add(index + 1, w);
}
}
private void addLeads(AbstractGuitarPickup c, Project project, Set<IDIYComponent<?>> newSelection) {
Size offset = new Size(1d, SizeUnit.in);
// create leads
for (int i = 0; i < c.getControlPointCount(); i++) {
if (!c.isControlPointSticky(i))
continue;
Point2D p0 = c.getControlPoint(i);
double dx = 0;
double dy = 0;
if (c instanceof SingleCoilPickup)
dy = offset.convertToPixels();
else
dx = offset.convertToPixels();
AffineTransform tx = null;
if (c.getOrientation() != Orientation.DEFAULT)
tx = AffineTransform.getRotateInstance(c.getOrientation().toRadians(), p0.getX(), p0.getY());
HookupWire w = new HookupWire();
w.setValue(AWG._24);
getInstantiationManager().fillWithDefaultProperties(w, null);
for (int j = 0; j < w.getControlPointCount(); j++) {
Point2D p = new Point2D.Double((int)(p0.getX() + dx * j), (int)(p0.getY() + dy * j));
if (tx != null)
tx.transform(p, p);
w.setControlPoint(p, j);
}
newSelection.add(w);
// inject leads right before the component
int index = project.getComponents().indexOf(c);
project.getComponents().add(index + 1, w);
}
}
@Override
public String getEditAction() {
return "Add Flexible Leads";
}
public InstantiationManager getInstantiationManager() {
if (instantiationManager == null)
instantiationManager = new InstantiationManager();
return instantiationManager;
}
}
package org.diylc.editor;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.util.HashSet;
import java.util.Set;
import org.diylc.common.IProjectEditor;
import org.diylc.common.Orientation;
import org.diylc.components.AbstractLeadedComponent;
import org.diylc.components.AbstractCurvedComponent.PointCount;
import org.diylc.components.connectivity.AWG;
import org.diylc.components.connectivity.HookupWire;
import org.diylc.components.guitar.AbstractGuitarPickup;
import org.diylc.components.guitar.SingleCoilPickup;
import org.diylc.components.passive.PotentiometerPanel;
import org.diylc.components.passive.PotentiometerPanel.Type;
import org.diylc.components.semiconductors.AbstractTransistorPackage;
import org.diylc.components.semiconductors.TransistorTO126;
import org.diylc.components.semiconductors.TransistorTO220;
import org.diylc.components.tube.TubeSocket;
import org.diylc.components.tube.TubeSocket.Mount;
import org.diylc.core.IDIYComponent;
import org.diylc.core.Project;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
import org.diylc.presenter.InstantiationManager;
public class FlexibleLeadsEditor implements IProjectEditor {
private InstantiationManager instantiationManager;
@Override
public Set<IDIYComponent<?>> edit(Project project, Set<IDIYComponent<?>> selection) {
Set<IDIYComponent<?>> newSelection = new HashSet<IDIYComponent<?>>(selection);
for (IDIYComponent<?> c : selection) {
if (c instanceof AbstractLeadedComponent<?>)
addLeads((AbstractLeadedComponent<?>) c, project, newSelection);
else if (c instanceof AbstractTransistorPackage)
addLeads((AbstractTransistorPackage) c, project, newSelection);
else if (c instanceof PotentiometerPanel)
addLeads((PotentiometerPanel) c, project, newSelection);
else if (c instanceof TubeSocket)
addLeads((TubeSocket) c, project, newSelection);
else if (c instanceof AbstractGuitarPickup)
addLeads((AbstractGuitarPickup) c, project, newSelection);
}
return newSelection;
}
private void addLeads(AbstractLeadedComponent<?> leaded, Project project, Set<IDIYComponent<?>> newSelection) {
Size l = leaded.getLength();
// do not apply to jumpers, etc
if (l == null)
return;
Point2D p1 = (Point2D) leaded.getControlPoint(0).clone();
Point2D p2 = (Point2D) leaded.getControlPoint(1).clone();
double d = p1.distance(p2);
double len = l.convertToPixels() + 2;
double diff = (d - len) / 2;
if (diff < 20)
return;
// find the center and angle
double centerX = (p1.getX() + p2.getX()) / 2.0;
double centerY = (p1.getY() + p2.getY()) / 2.0;
double theta = Math.atan2(p2.getY() - p1.getY(), p2.getX() - p1.getX());
// 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 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(newP2, 1);
// make the standard leads go away
leaded.setHideShortLeads(true);
// create leads
HookupWire w1 = new HookupWire();
getInstantiationManager().fillWithDefaultProperties(w1, null);
w1.setValue(AWG._26);
w1.setLeadColor(leaded.getLeadColor());
// w1.setPointCount(PointCount.THREE);
w1.setControlPoint(p1, 0);
for (int i = 1; i < w1.getControlPointCount() - 1; i++) {
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(newP1, w1.getControlPointCount() - 1);
newSelection.add(w1);
HookupWire w2 = new HookupWire();
getInstantiationManager().fillWithDefaultProperties(w2, null);
w2.setValue(AWG._26);
w2.setLeadColor(leaded.getLeadColor());
// w2.setPointCount(PointCount.THREE);
w2.setControlPoint(p2, 0);
for (int i = 1; i < w2.getControlPointCount() - 1; i++) {
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(newP2, w2.getControlPointCount() - 1);
newSelection.add(w2);
// inject leads right before the component
int index = project.getComponents().indexOf(leaded);
project.getComponents().add(index, w1);
project.getComponents().add(index, w2);
}
private void addLeads(AbstractTransistorPackage c, Project project, Set<IDIYComponent<?>> newSelection) {
Size offsetX = new Size(0.4d, SizeUnit.in);
Size offsetY = new Size(0.1d, SizeUnit.in);
// create leads
for (int i = 0; i < 3; i++) {
Point2D p0 = c.getControlPoint(i);
double dx = -offsetX.convertToPixels();
double dy = offsetY.convertToPixels() * (i - 1);
// calculate lead position
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) Math.round(p0.getX() + dx), (int) Math.round(p0.getY() + dy));
if (c.getOrientation() != Orientation.DEFAULT) {
AffineTransform tx = AffineTransform.getRotateInstance(c.getOrientation().toRadians(), p0.getX(), p0.getY());
tx.transform(p1, p1);
tx.transform(p2, p2);
}
HookupWire w = new HookupWire();
getInstantiationManager().fillWithDefaultProperties(w, null);
// make the leads thicker for TO220 and TO126
if (c instanceof TransistorTO220 || c instanceof TransistorTO126)
w.setValue(AWG._24);
else
w.setValue(AWG._26);
w.setLeadColor(AbstractTransistorPackage.METAL_COLOR);
w.setPointCount(PointCount.THREE);
w.setControlPoint(p0, 0);
w.setControlPoint(p1, 1);
w.setControlPoint(p2, 2);
newSelection.add(w);
// inject leads right before the component
int index = project.getComponents().indexOf(c);
project.getComponents().add(index, w);
}
if (c instanceof TransistorTO220) {
TransistorTO220 t = (TransistorTO220)c;
if (t.getFolded())
t.setLeadLength(new Size(0d, SizeUnit.mm));
}
else if (c instanceof TransistorTO126) {
TransistorTO126 t = (TransistorTO126)c;
if (t.getFolded())
t.setLeadLength(new Size(0d, SizeUnit.mm));
}
}
private void addLeads(PotentiometerPanel c, Project project, Set<IDIYComponent<?>> newSelection) {
Size offsetY = new Size(0.5d, SizeUnit.in);
// don't do it for PCB type
if (c.getType() == Type.PCB)
return;
// create leads
for (int i = 0; i < 3; i++) {
Point2D p0 = c.getControlPoint(i);
double dx = 0;
double dy = offsetY.convertToPixels();
AffineTransform tx = null;
if (c.getOrientation() != Orientation.DEFAULT)
tx = AffineTransform.getRotateInstance(c.getOrientation().toRadians(), p0.getX(), p0.getY());
HookupWire w = new HookupWire();
getInstantiationManager().fillWithDefaultProperties(w, null);
for (int j = 0; j < w.getControlPointCount(); j++) {
Point2D p = new Point2D.Double((int) Math.round(p0.getX() + dx * j), (int) Math.round(p0.getY() + dy * j));
if (tx != null)
tx.transform(p, p);
w.setControlPoint(p, j);
}
newSelection.add(w);
// inject leads right before the component
int index = project.getComponents().indexOf(c);
project.getComponents().add(index + 1, w);
}
}
private void addLeads(TubeSocket c, Project project, Set<IDIYComponent<?>> newSelection) {
Point2D center = c.getControlPoint(0);
// don't do it for PCB type
if (c.getMount() == Mount.PCB)
return;
// create leads
for (int i = 1; i < c.getControlPointCount(); i++) {
Point2D p = c.getControlPoint(i);
double dx = p.getX() - center.getX();
double dy = p.getY() - center.getY();
// calculate lead position
HookupWire w = new HookupWire();
getInstantiationManager().fillWithDefaultProperties(w, null);
for (int j = 0; j < w.getControlPointCount(); j++) {
Point2D pw = new Point2D.Double((int) Math.round(p.getX() + dx * j), (int) Math.round(p.getY() + dy * j));
w.setControlPoint(pw, j);
}
newSelection.add(w);
// inject leads right before the component
int index = project.getComponents().indexOf(c);
project.getComponents().add(index + 1, w);
}
}
private void addLeads(AbstractGuitarPickup c, Project project, Set<IDIYComponent<?>> newSelection) {
Size offset = new Size(1d, SizeUnit.in);
// create leads
for (int i = 0; i < c.getControlPointCount(); i++) {
if (!c.isControlPointSticky(i))
continue;
Point2D p0 = c.getControlPoint(i);
double dx = 0;
double dy = 0;
if (c instanceof SingleCoilPickup)
dy = offset.convertToPixels();
else
dx = offset.convertToPixels();
AffineTransform tx = null;
if (c.getOrientation() != Orientation.DEFAULT)
tx = AffineTransform.getRotateInstance(c.getOrientation().toRadians(), p0.getX(), p0.getY());
HookupWire w = new HookupWire();
w.setValue(AWG._24);
getInstantiationManager().fillWithDefaultProperties(w, null);
for (int j = 0; j < w.getControlPointCount(); j++) {
Point2D p = new Point2D.Double((int) Math.round(p0.getX() + dx * j), (int) Math.round(p0.getY() + dy * j));
if (tx != null)
tx.transform(p, p);
w.setControlPoint(p, j);
}
newSelection.add(w);
// inject leads right before the component
int index = project.getComponents().indexOf(c);
project.getComponents().add(index + 1, w);
}
}
@Override
public String getEditAction() {
return "Add Flexible Leads";
}
public InstantiationManager getInstantiationManager() {
if (instantiationManager == null)
instantiationManager = new InstantiationManager();
return instantiationManager;
}
}