diff --git a/diylc/diylc-core/src/main/java/org/diylc/common/Percentage.java b/diylc/diylc-core/src/main/java/org/diylc/common/Percentage.java
new file mode 100644
index 000000000..57370cfc5
--- /dev/null
+++ b/diylc/diylc-core/src/main/java/org/diylc/common/Percentage.java
@@ -0,0 +1,75 @@
+/*
+
+ 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 .
+
+*/
+package org.diylc.common;
+
+import java.io.Serializable;
+
+public class Percentage implements Serializable, Cloneable {
+
+ private static final long serialVersionUID = 1L;
+
+ private int value;
+
+ public Percentage(int value) {
+ this.value = value;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public void setValue(int value) {
+ this.value = value;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + value;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Percentage other = (Percentage) obj;
+ if (value != other.value)
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return value + "%";
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+}
diff --git a/diylc/diylc-core/src/main/java/org/diylc/components/AbstractCurvedComponent.java b/diylc/diylc-core/src/main/java/org/diylc/components/AbstractCurvedComponent.java
index b6c181433..6233b1eb0 100644
--- a/diylc/diylc-core/src/main/java/org/diylc/components/AbstractCurvedComponent.java
+++ b/diylc/diylc-core/src/main/java/org/diylc/components/AbstractCurvedComponent.java
@@ -149,10 +149,7 @@ public abstract class AbstractCurvedComponent extends AbstractTransparentComp
path.curveTo(p[4].getX(), p[4].getY(), p[5].getX(), p[5].getY(), p[6].getX(), p[6].getY());
}
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
drawCurve(path, g2d, componentState, drawingObserver);
diff --git a/diylc/diylc-core/src/main/java/org/diylc/components/AbstractTransparentComponent.java b/diylc/diylc-core/src/main/java/org/diylc/components/AbstractTransparentComponent.java
index 46a3c3d17..1de45f740 100644
--- a/diylc/diylc-core/src/main/java/org/diylc/components/AbstractTransparentComponent.java
+++ b/diylc/diylc-core/src/main/java/org/diylc/components/AbstractTransparentComponent.java
@@ -22,24 +22,46 @@
package org.diylc.components;
import org.diylc.core.annotations.EditableProperty;
+import org.diylc.core.ComponentState;
+import org.diylc.common.Percentage;
+
+import java.awt.*;
public abstract class AbstractTransparentComponent extends AbstractComponent {
private static final long serialVersionUID = 1L;
- public static byte MAX_ALPHA = 127;
+ public static byte MAX_ALPHA_LEGACY = Byte.MAX_VALUE;
+ public static int MAX_ALPHA = 100;
- protected Byte alpha = MAX_ALPHA;
+ @Deprecated
+ protected Byte alpha;
- @EditableProperty
- public Byte getAlpha() {
- if (alpha == null) {
- alpha = MAX_ALPHA;
+ protected Percentage alphaPercent = new Percentage(100);
+
+ @EditableProperty(name = "Alpha")
+ public Percentage getAlpha() {
+ if (alphaPercent == null) {
+ if (alpha != null) {
+ alphaPercent = new Percentage(Math.round(100f * alpha / MAX_ALPHA_LEGACY));
+ alpha = null;
+ } else {
+ alphaPercent = new Percentage(100);
+ }
}
- return alpha;
+ return alphaPercent;
}
- public void setAlpha(Byte alpha) {
- this.alpha = alpha;
+ public void setAlpha(Percentage alphaPercent) {
+ this.alphaPercent = alphaPercent;
+ }
+
+ public Composite applyAlpha(Graphics2D g2d, ComponentState componentState) {
+ Composite oldComposite = g2d.getComposite();
+ int alpha = componentState == ComponentState.DRAGGING ? 0 : getAlpha().getValue();
+ if (alpha < MAX_ALPHA) {
+ g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha / 100f));
+ }
+ return oldComposite;
}
}
diff --git a/diylc/diylc-core/src/main/java/org/diylc/core/annotations/PercentEditor.java b/diylc/diylc-core/src/main/java/org/diylc/core/annotations/PercentEditor.java
index 0961e073c..6ce553b93 100644
--- a/diylc/diylc-core/src/main/java/org/diylc/core/annotations/PercentEditor.java
+++ b/diylc/diylc-core/src/main/java/org/diylc/core/annotations/PercentEditor.java
@@ -27,5 +27,7 @@ import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface PercentEditor {
- public byte _100PercentValue();
+ public int minValue() default 0;
+
+ public int maxValue() default 100;
}
diff --git a/diylc/diylc-core/src/main/java/org/diylc/presenter/DrawingManager.java b/diylc/diylc-core/src/main/java/org/diylc/presenter/DrawingManager.java
index 6cccc0766..936d2ffb1 100644
--- a/diylc/diylc-core/src/main/java/org/diylc/presenter/DrawingManager.java
+++ b/diylc/diylc-core/src/main/java/org/diylc/presenter/DrawingManager.java
@@ -68,7 +68,7 @@ import org.diylc.utils.Constants;
public class DrawingManager {
private static final Logger LOG = Logger.getLogger(DrawingManager.class);
- public static final byte MIRROR_ALPHA = 64;
+ public static final Percentage MIRROR_ALPHA = new Percentage(50);
public static int CONTROL_POINT_SIZE = 7;
public static double EXTRA_SPACE = 0.25;
diff --git a/diylc/diylc-core/src/main/resources/update.xml b/diylc/diylc-core/src/main/resources/update.xml
index 3e2732e80..a5f02ad08 100644
--- a/diylc/diylc-core/src/main/resources/update.xml
+++ b/diylc/diylc-core/src/main/resources/update.xml
@@ -317,6 +317,10 @@
NEW_FEATURE
Added more ceramic resistor variants to 'Resistor' component
+
+ IMPROVEMENT
+ Improved data model for storing transparency alpha and other properties that are edited using a slider widget; as a result, the editing is more precise and does not randomly change to neighboring values
+
IMPROVEMENT
Improved editing experience of integer properties (e.g. number of terminals on a tag strip) by using the spinner text field
diff --git a/diylc/diylc-core/src/test/java/org/diylc/presenter/CalcUtilsTest.java b/diylc/diylc-core/src/test/java/org/diylc/presenter/CalcUtilsTest.java
index f0542ff65..75c1c8c8c 100644
--- a/diylc/diylc-core/src/test/java/org/diylc/presenter/CalcUtilsTest.java
+++ b/diylc/diylc-core/src/test/java/org/diylc/presenter/CalcUtilsTest.java
@@ -235,7 +235,7 @@ public class CalcUtilsTest {
assertEquals(Color.BLACK.getRed(), result.getRed());
assertEquals(Color.BLACK.getGreen(), result.getGreen());
assertEquals(Color.BLACK.getBlue(), result.getBlue());
- assertEquals(128, result.getAlpha());
+ assertEquals(128, result.getAlpha().getValue());
// Test light color with alpha - should become WHITE
Color transparentLight = new Color(255, 255, 200, 128);
@@ -243,16 +243,16 @@ public class CalcUtilsTest {
assertEquals(Color.WHITE.getRed(), result.getRed());
assertEquals(Color.WHITE.getGreen(), result.getGreen());
assertEquals(Color.WHITE.getBlue(), result.getBlue());
- assertEquals(128, result.getAlpha());
+ assertEquals(128, result.getAlpha().getValue());
// Test fully transparent color
Color transparent = new Color(100, 150, 200, 0);
result = CalcUtils.convertToMonochrome(transparent);
- assertEquals(0, result.getAlpha());
+ assertEquals(0, result.getAlpha().getValue());
// Test opaque color - alpha should remain 255
Color opaque = new Color(50, 50, 50);
result = CalcUtils.convertToMonochrome(opaque);
- assertEquals(255, result.getAlpha());
+ assertEquals(255, result.getAlpha().getValue());
}
}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/AbstractLeadedComponent.java b/diylc/diylc-library/src/main/java/org/diylc/components/AbstractLeadedComponent.java
index 62170423d..b17b9200b 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/AbstractLeadedComponent.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/AbstractLeadedComponent.java
@@ -165,10 +165,7 @@ public abstract class AbstractLeadedComponent extends AbstractLabeledComponen
new Ellipse2D.Double((getFlipStanding() ? getPoints()[1] : getPoints()[0]).getX() - width / 2,
(getFlipStanding() ? getPoints()[1] : getPoints()[0]).getY() - width / 2, width, width);
shapeRect = body.getBounds();
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getStandingBodyColor());
g2d.fill(body);
g2d.setComposite(oldComposite);
@@ -255,10 +252,7 @@ public abstract class AbstractLeadedComponent extends AbstractLabeledComponen
g2d.translate((getPoints()[0].getX() + getPoints()[1].getX() - length) / 2, (getPoints()[0].getY() + getPoints()[1].getY() - width) / 2);
g2d.rotate(theta, length / 2, width / 2);
// Draw body.
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
if (getBodyColor() != null) {
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getBodyColor());
@@ -440,10 +434,7 @@ public abstract class AbstractLeadedComponent extends AbstractLabeledComponen
break;
}
- Composite oldComposite = g2d.getComposite();
- if (getAlpha() < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * getAlpha() / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
if (shouldShadeLeads()) {
Shape lineShape = stroke.createStrokedShape(line);
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/boards/AbstractBoard.java b/diylc/diylc-library/src/main/java/org/diylc/components/boards/AbstractBoard.java
index f52883ad8..a2f59a8e1 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/boards/AbstractBoard.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/boards/AbstractBoard.java
@@ -88,12 +88,7 @@ public abstract class AbstractBoard extends AbstractTransparentComponent
Point2D finalSecondPoint = getFinalSecondPoint();
- Composite oldComposite = g2d.getComposite();
- // render as transparent when dragging
- int alpha = componentState == ComponentState.DRAGGING ? 0 : this.alpha;
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ 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.setComposite(oldComposite);
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/boards/BlankBoard.java b/diylc/diylc-library/src/main/java/org/diylc/components/boards/BlankBoard.java
index 7ee0a538c..f899ec5b0 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/boards/BlankBoard.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/boards/BlankBoard.java
@@ -70,10 +70,7 @@ public class BlankBoard extends AbstractBoard {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
// if (componentState != ComponentState.DRAGGING) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ 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()));
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/boards/EyeletBoard.java b/diylc/diylc-library/src/main/java/org/diylc/components/boards/EyeletBoard.java
index 02efe9e8e..216570df6 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/boards/EyeletBoard.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/boards/EyeletBoard.java
@@ -78,9 +78,7 @@ public class EyeletBoard extends AbstractBoard {
}
super.draw(g2d, componentState, outlineMode, project, drawingObserver);
if (componentState != ComponentState.DRAGGING) {
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ applyAlpha(g2d, componentState);
double x = firstPoint.getX();
double y = firstPoint.getY();
int diameter = getClosestOdd((int) EYELET_SIZE.convertToPixels());
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/boards/MarshallPerfBoard.java b/diylc/diylc-library/src/main/java/org/diylc/components/boards/MarshallPerfBoard.java
index b494f45b2..fafb79760 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/boards/MarshallPerfBoard.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/boards/MarshallPerfBoard.java
@@ -76,9 +76,7 @@ public class MarshallPerfBoard extends AbstractBoard {
}
super.draw(g2d, componentState, outlineMode, project, drawingObserver);
if (componentState != ComponentState.DRAGGING) {
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ applyAlpha(g2d, componentState);
double x = firstPoint.getX();
double y = firstPoint.getY();
int holeDiameter = getClosestOdd((int) HOLE_SIZE.convertToPixels());
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/boards/PerfBoard.java b/diylc/diylc-library/src/main/java/org/diylc/components/boards/PerfBoard.java
index 1ba54c459..1780fe905 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/boards/PerfBoard.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/boards/PerfBoard.java
@@ -72,9 +72,7 @@ public class PerfBoard extends AbstractBoard implements ILayeredComponent {
}
super.draw(g2d, componentState, outlineMode, project, drawingObserver);
if (componentState != ComponentState.DRAGGING) {
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ applyAlpha(g2d, componentState);
double x = firstPoint.getX();
double y = firstPoint.getY();
int diameter = getClosestOdd((int) PAD_SIZE.convertToPixels());
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/boards/TagStrip.java b/diylc/diylc-library/src/main/java/org/diylc/components/boards/TagStrip.java
index 5bd1111fc..da01e2971 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/boards/TagStrip.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/boards/TagStrip.java
@@ -1,412 +1,409 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.boards;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-import java.awt.geom.Area;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.Orientation;
-import org.diylc.components.AbstractTransparentComponent;
-import org.diylc.components.transform.TagStripTransformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IContinuity;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-import org.diylc.core.VisibilityPolicy;
-import org.diylc.core.annotations.ComponentDescriptor;
-import org.diylc.core.annotations.EditableProperty;
-import org.diylc.core.annotations.KeywordPolicy;
-import org.diylc.core.annotations.PositiveNonZeroMeasureValidator;
-import org.diylc.core.measures.Size;
-import org.diylc.core.measures.SizeUnit;
-import org.diylc.utils.Constants;
-
-@ComponentDescriptor(name = "Tag Strip", author = "Branislav Stojkovic", category = "Boards",
- instanceNamePrefix = "TS", description = "Row of terminals for point-to-point construction",
- zOrder = IDIYComponent.BOARD, keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, transformer = TagStripTransformer.class)
-public class TagStrip extends AbstractTransparentComponent implements IContinuity {
-
- private static final long serialVersionUID = 1L;
-
- public static Color BOARD_COLOR = PHENOLIC_DARK_COLOR;
- public static Color TERMINAL_COLOR = Color.lightGray;
- public static Color TERMINAL_BORDER_COLOR = TERMINAL_COLOR.darker();
- public static int EDGE_RADIUS = 2;
- public static Size MOUNTING_HOLE_SIZE = new Size(0.07d, SizeUnit.in);
- public static Size MOUNTING_HOLE_DISTANCE = new Size(0.25d, SizeUnit.in);
- public static Size TERMINAL_THICKNESS = new Size(0.04d, SizeUnit.in);
-
- private String value = "";
- private Orientation orientation = Orientation.DEFAULT;
- private int terminalCount = 7;
- private static Size BOARD_THICKNESS = new Size(0.05d, SizeUnit.in);
- private Size terminalSpacing = new Size(0.375d, SizeUnit.in);
- private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0)};
- private Color boardColor = BOARD_COLOR;
-
- private TagStripMount mount = TagStripMount.Central;
-
- transient private Area[] body;
-
- public TagStrip() {
- super();
- updateControlPoints();
- }
-
- @EditableProperty
- public String getValue() {
- return value;
- }
-
- public void setValue(String value) {
- this.value = value;
- }
-
- @EditableProperty
- public Orientation getOrientation() {
- return orientation;
- }
-
- public void setOrientation(Orientation orientation) {
- this.orientation = orientation;
- updateControlPoints();
- // Reset body shape.
- body = null;
- }
-
- @EditableProperty(name = "Terminals")
- public int getTerminalCount() {
- return terminalCount;
- }
-
- public void setTerminalCount(int terminalCount) {
- this.terminalCount = terminalCount;
- updateControlPoints();
- // Reset body shape;
- body = null;
- }
-
- @EditableProperty(name = "Terminal Spacing", validatorClass = PositiveNonZeroMeasureValidator.class)
- public Size getTerminalSpacing() {
- return terminalSpacing;
- }
-
- public void setTerminalSpacing(Size pinSpacing) {
- this.terminalSpacing = pinSpacing;
- updateControlPoints();
- // Reset body shape;
- body = null;
- }
-
- @Override
- public int getControlPointCount() {
- return controlPoints.length;
- }
-
- @Override
- public Point2D getControlPoint(int index) {
- return controlPoints[index];
- }
-
- @Override
- public boolean isControlPointSticky(int index) {
- return true;
- }
-
- @Override
- public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
- return VisibilityPolicy.NEVER;
- }
-
- @Override
- public void setControlPoint(Point2D point, int index) {
- controlPoints[index].setLocation(point);
- body = null;
- }
-
- private void updateControlPoints() {
- Point2D firstPoint = controlPoints[0];
- controlPoints = new Point2D[getTerminalCount()];
- controlPoints[0] = firstPoint;
- int pinSpacing = (int) this.terminalSpacing.convertToPixels();
- // Update control points.
- int dx1;
- int dy1;
- for (int i = 0; i < getTerminalCount(); i++) {
- switch (orientation) {
- case DEFAULT:
- dx1 = 0;
- dy1 = i * pinSpacing;
- break;
- case _90:
- dx1 = -i * pinSpacing;
- dy1 = 0;
- break;
- case _180:
- dx1 = 0;
- dy1 = -i * pinSpacing;
- break;
- case _270:
- dx1 = i * pinSpacing;
- dy1 = 0;
- break;
- default:
- throw new RuntimeException("Unexpected orientation: " + orientation);
- }
- controlPoints[i] = new Point2D.Double(firstPoint.getX() + dx1, firstPoint.getY() + dy1);
- }
- }
-
- public Area[] getBody() {
- if (body == null) {
- body = new Area[1 + getTerminalCount()];
- double x = controlPoints[0].getX();
- double y = controlPoints[0].getY();
- int width;
- int height;
- int terminalSpacing = (int) getTerminalSpacing().convertToPixels();
- int boardThickness = getClosestOdd(BOARD_THICKNESS.convertToPixels());
- int boardLength = (int) ((getTerminalCount() - 0.5) * terminalSpacing + 2 * boardThickness);
- int holeSize = getClosestOdd(MOUNTING_HOLE_SIZE.convertToPixels());
- int terminalThickness = (int) TERMINAL_THICKNESS.convertToPixels();
- int terminalSize = terminalSpacing / 2;
- int holeDistance = terminalSize / 2 + terminalThickness / 2 + 1;
- int terminalWidth;
- int terminalHeight;
- int holeDx;
- int holeDy;
- switch (orientation) {
- case DEFAULT:
- width = boardThickness;
- height = boardLength;
- terminalWidth = terminalThickness;
- terminalHeight = terminalSize;
- x -= boardThickness + terminalThickness / 2;
- y -= terminalSize / 2 + boardThickness;
- holeDx = holeDistance;
- holeDy = 0;
- break;
- case _90:
- width = boardLength;
- height = boardThickness;
- terminalWidth = terminalSize;
- terminalHeight = terminalThickness;
- x += boardThickness - boardLength + terminalSize / 2;
- y -= boardThickness + terminalThickness / 2;
- holeDx = 0;
- holeDy = holeDistance;
- break;
- case _180:
- width = boardThickness;
- height = boardLength;
- terminalWidth = terminalThickness;
- terminalHeight = terminalSize;
- x += terminalThickness / 2;
- y += boardThickness - boardLength + terminalSize / 2;
- holeDx = -holeDistance;
- holeDy = 0;
- break;
- case _270:
- width = boardLength;
- height = boardThickness;
- terminalWidth = terminalSize;
- terminalHeight = terminalThickness;
- x -= terminalSize / 2 + boardThickness;
- y -= -terminalThickness / 2;
- holeDx = 0;
- holeDy = -holeDistance;
- break;
- default:
- throw new RuntimeException("Unexpected orientation: " + orientation);
- }
- Area bodyArea = new Area(new Rectangle2D.Double(x, y, width, height));
- body[0] = bodyArea;
-
- for (int i = 0; i < getTerminalCount(); i++) {
- Point2D p1 = getControlPoint(i);
- Area terminal =
- new Area(new Rectangle2D.Double(p1.getX() - terminalWidth/ 2, p1.getY() - terminalHeight / 2, terminalWidth, terminalHeight));
-
- body[1 + i] = terminal;
-
- if ((getMount() == TagStripMount.Central && i == getTerminalCount() / 2) || (getMount() == TagStripMount.Outside && (i == 0 || i == getTerminalCount() - 1))) {
- Area mount = new Area(new Rectangle2D.Double(p1.getX() + holeDx - terminalSize / 2, p1.getY() + holeDy - terminalSize / 2, terminalSize, terminalSize));
- mount.subtract(new Area(new Ellipse2D.Double(p1.getX() + holeDx - holeSize / 2, p1.getY() + holeDy - holeSize / 2, holeSize, holeSize)));
- body[1 + i].add(mount);
- }
- }
- }
- return body;
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- if (checkPointsClipped(g2d.getClip())) {
- return;
- }
- Area[] area = getBody();
- Area mainArea = area[0];
-
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getBoardColor());
- g2d.fill(mainArea);
-
- Color finalBorderColor;
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : getBoardColor().darker();
- }
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
-
- g2d.setColor(finalBorderColor);
- g2d.draw(mainArea);
-
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : TERMINAL_COLOR);
- drawingObserver.startTrackingContinuityArea(true);
- for (int i = 1; i < body.length; i++)
- g2d.fill(body[i]);
- drawingObserver.stopTrackingContinuityArea();
-
- Color finalTerminalBorderColor;
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalTerminalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalTerminalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : TERMINAL_BORDER_COLOR;
- }
-
- g2d.setColor(finalTerminalBorderColor);
- for (int i = 1; i < body.length; i++)
- g2d.draw(body[i]);
-
- g2d.setComposite(oldComposite);
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- g2d.rotate(-Math.PI / 4, width / 2, height / 2);
- g2d.setColor(BOARD_COLOR);
- int thickness = 2 * width / 32;
- g2d.fillRect(0, height / 2 - thickness / 2, width, thickness);
- g2d.setColor(TERMINAL_COLOR.darker());
- int terminalWidth = 7 * width / 32;
- g2d.fillRect(2, height / 2 + thickness / 2, terminalWidth, thickness);
- g2d.fillRect((int) (2 + terminalWidth * 1.5), height / 2 + thickness / 2, terminalWidth, thickness);
- g2d.fillRect((int) (2 + terminalWidth * 3), height / 2 + thickness / 2, terminalWidth, thickness);
- g2d.setColor(TERMINAL_COLOR);
- g2d.fillRect((int) (2 + terminalWidth * 1.5), height / 2 + thickness / 2 + 1, terminalWidth, terminalWidth);
- g2d.setColor(Color.white);
- g2d.fillOval((int) (2 + terminalWidth * 1.75), height / 2 + thickness / 2 + 1 + terminalWidth / 2, terminalWidth / 2, terminalWidth / 2);
-// int radius = 6 * width / 32;
-// int holeSize = 3 * width / 32;
-// g2d.setColor(BOARD_COLOR);
-// g2d.fillRect(width / 4, 1, width / 2, height - 4);
-// g2d.setColor(BORDER_COLOR);
-// g2d.drawRect(width / 4, 1, width / 2, height - 4);
-// int terminalSize = getClosestOdd(height / 5);
-// Area terminal =
-// new Area(new RoundRectangle2D.Double(2 * width / 32, height / 5, width - 4 * width / 32, terminalSize, radius,
-// radius));
-// terminal.subtract(new Area(new Ellipse2D.Double(2 * width / 32 + holeSize, height * 3 / 10 - holeSize / 2, holeSize, holeSize)));
-// terminal.subtract(new Area(new Ellipse2D.Double(width - 2 * width / 32 - holeSize * 2, height * 3 / 10 - holeSize / 2, holeSize, holeSize)));
-//
-// g2d.setColor(TERMINAL_COLOR);
-// g2d.fill(terminal);
-// g2d.setColor(TERMINAL_BORDER_COLOR);
-// g2d.draw(terminal);
-// g2d.translate(0, height * 2 / 5);
-// g2d.setColor(TERMINAL_COLOR);
-// g2d.fill(terminal);
-// g2d.setColor(TERMINAL_BORDER_COLOR);
-// g2d.draw(terminal);
- }
-
- @EditableProperty(name = "Board")
- public Color getBoardColor() {
- if (boardColor == null) {
- boardColor = BOARD_COLOR;
- }
- return boardColor;
- }
-
- public void setBoardColor(Color bodyColor) {
- this.boardColor = bodyColor;
- }
-
- @Override
- public String getControlPointNodeName(int index) {
- return "TerminalStrip" + index;
- }
-
- @EditableProperty(name = "Mounting Lugs")
- public TagStripMount getMount() {
- return mount;
- }
-
- public void setMount(TagStripMount mount) {
- this.mount = mount;
- updateControlPoints();
- // Reset body shape;
- body = null;
- }
-
- @Override
- public boolean arePointsConnected(int index1, int index2) {
- return false;
- }
-
- @Override
- public boolean canPointMoveFreely(int pointIndex) {
- return false;
- }
-
- public enum TagStripMount {
- Central, Outside;
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.boards;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Graphics2D;
+import java.awt.geom.Area;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.common.IPlugInPort;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.Orientation;
+import org.diylc.components.AbstractTransparentComponent;
+import org.diylc.components.transform.TagStripTransformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IContinuity;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+import org.diylc.core.VisibilityPolicy;
+import org.diylc.core.annotations.ComponentDescriptor;
+import org.diylc.core.annotations.EditableProperty;
+import org.diylc.core.annotations.KeywordPolicy;
+import org.diylc.core.annotations.PositiveNonZeroMeasureValidator;
+import org.diylc.core.measures.Size;
+import org.diylc.core.measures.SizeUnit;
+import org.diylc.utils.Constants;
+
+@ComponentDescriptor(name = "Tag Strip", author = "Branislav Stojkovic", category = "Boards",
+ instanceNamePrefix = "TS", description = "Row of terminals for point-to-point construction",
+ zOrder = IDIYComponent.BOARD, keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, transformer = TagStripTransformer.class)
+public class TagStrip extends AbstractTransparentComponent implements IContinuity {
+
+ private static final long serialVersionUID = 1L;
+
+ public static Color BOARD_COLOR = PHENOLIC_DARK_COLOR;
+ public static Color TERMINAL_COLOR = Color.lightGray;
+ public static Color TERMINAL_BORDER_COLOR = TERMINAL_COLOR.darker();
+ public static int EDGE_RADIUS = 2;
+ public static Size MOUNTING_HOLE_SIZE = new Size(0.07d, SizeUnit.in);
+ public static Size MOUNTING_HOLE_DISTANCE = new Size(0.25d, SizeUnit.in);
+ public static Size TERMINAL_THICKNESS = new Size(0.04d, SizeUnit.in);
+
+ private String value = "";
+ private Orientation orientation = Orientation.DEFAULT;
+ private int terminalCount = 7;
+ private static Size BOARD_THICKNESS = new Size(0.05d, SizeUnit.in);
+ private Size terminalSpacing = new Size(0.375d, SizeUnit.in);
+ private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0)};
+ private Color boardColor = BOARD_COLOR;
+
+ private TagStripMount mount = TagStripMount.Central;
+
+ transient private Area[] body;
+
+ public TagStrip() {
+ super();
+ updateControlPoints();
+ }
+
+ @EditableProperty
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ @EditableProperty
+ public Orientation getOrientation() {
+ return orientation;
+ }
+
+ public void setOrientation(Orientation orientation) {
+ this.orientation = orientation;
+ updateControlPoints();
+ // Reset body shape.
+ body = null;
+ }
+
+ @EditableProperty(name = "Terminals")
+ public int getTerminalCount() {
+ return terminalCount;
+ }
+
+ public void setTerminalCount(int terminalCount) {
+ this.terminalCount = terminalCount;
+ updateControlPoints();
+ // Reset body shape;
+ body = null;
+ }
+
+ @EditableProperty(name = "Terminal Spacing", validatorClass = PositiveNonZeroMeasureValidator.class)
+ public Size getTerminalSpacing() {
+ return terminalSpacing;
+ }
+
+ public void setTerminalSpacing(Size pinSpacing) {
+ this.terminalSpacing = pinSpacing;
+ updateControlPoints();
+ // Reset body shape;
+ body = null;
+ }
+
+ @Override
+ public int getControlPointCount() {
+ return controlPoints.length;
+ }
+
+ @Override
+ public Point2D getControlPoint(int index) {
+ return controlPoints[index];
+ }
+
+ @Override
+ public boolean isControlPointSticky(int index) {
+ return true;
+ }
+
+ @Override
+ public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
+ return VisibilityPolicy.NEVER;
+ }
+
+ @Override
+ public void setControlPoint(Point2D point, int index) {
+ controlPoints[index].setLocation(point);
+ body = null;
+ }
+
+ private void updateControlPoints() {
+ Point2D firstPoint = controlPoints[0];
+ controlPoints = new Point2D[getTerminalCount()];
+ controlPoints[0] = firstPoint;
+ int pinSpacing = (int) this.terminalSpacing.convertToPixels();
+ // Update control points.
+ int dx1;
+ int dy1;
+ for (int i = 0; i < getTerminalCount(); i++) {
+ switch (orientation) {
+ case DEFAULT:
+ dx1 = 0;
+ dy1 = i * pinSpacing;
+ break;
+ case _90:
+ dx1 = -i * pinSpacing;
+ dy1 = 0;
+ break;
+ case _180:
+ dx1 = 0;
+ dy1 = -i * pinSpacing;
+ break;
+ case _270:
+ dx1 = i * pinSpacing;
+ dy1 = 0;
+ break;
+ default:
+ throw new RuntimeException("Unexpected orientation: " + orientation);
+ }
+ controlPoints[i] = new Point2D.Double(firstPoint.getX() + dx1, firstPoint.getY() + dy1);
+ }
+ }
+
+ public Area[] getBody() {
+ if (body == null) {
+ body = new Area[1 + getTerminalCount()];
+ double x = controlPoints[0].getX();
+ double y = controlPoints[0].getY();
+ int width;
+ int height;
+ int terminalSpacing = (int) getTerminalSpacing().convertToPixels();
+ int boardThickness = getClosestOdd(BOARD_THICKNESS.convertToPixels());
+ int boardLength = (int) ((getTerminalCount() - 0.5) * terminalSpacing + 2 * boardThickness);
+ int holeSize = getClosestOdd(MOUNTING_HOLE_SIZE.convertToPixels());
+ int terminalThickness = (int) TERMINAL_THICKNESS.convertToPixels();
+ int terminalSize = terminalSpacing / 2;
+ int holeDistance = terminalSize / 2 + terminalThickness / 2 + 1;
+ int terminalWidth;
+ int terminalHeight;
+ int holeDx;
+ int holeDy;
+ switch (orientation) {
+ case DEFAULT:
+ width = boardThickness;
+ height = boardLength;
+ terminalWidth = terminalThickness;
+ terminalHeight = terminalSize;
+ x -= boardThickness + terminalThickness / 2;
+ y -= terminalSize / 2 + boardThickness;
+ holeDx = holeDistance;
+ holeDy = 0;
+ break;
+ case _90:
+ width = boardLength;
+ height = boardThickness;
+ terminalWidth = terminalSize;
+ terminalHeight = terminalThickness;
+ x += boardThickness - boardLength + terminalSize / 2;
+ y -= boardThickness + terminalThickness / 2;
+ holeDx = 0;
+ holeDy = holeDistance;
+ break;
+ case _180:
+ width = boardThickness;
+ height = boardLength;
+ terminalWidth = terminalThickness;
+ terminalHeight = terminalSize;
+ x += terminalThickness / 2;
+ y += boardThickness - boardLength + terminalSize / 2;
+ holeDx = -holeDistance;
+ holeDy = 0;
+ break;
+ case _270:
+ width = boardLength;
+ height = boardThickness;
+ terminalWidth = terminalSize;
+ terminalHeight = terminalThickness;
+ x -= terminalSize / 2 + boardThickness;
+ y -= -terminalThickness / 2;
+ holeDx = 0;
+ holeDy = -holeDistance;
+ break;
+ default:
+ throw new RuntimeException("Unexpected orientation: " + orientation);
+ }
+ Area bodyArea = new Area(new Rectangle2D.Double(x, y, width, height));
+ body[0] = bodyArea;
+
+ for (int i = 0; i < getTerminalCount(); i++) {
+ Point2D p1 = getControlPoint(i);
+ Area terminal =
+ new Area(new Rectangle2D.Double(p1.getX() - terminalWidth/ 2, p1.getY() - terminalHeight / 2, terminalWidth, terminalHeight));
+
+ body[1 + i] = terminal;
+
+ if ((getMount() == TagStripMount.Central && i == getTerminalCount() / 2) || (getMount() == TagStripMount.Outside && (i == 0 || i == getTerminalCount() - 1))) {
+ Area mount = new Area(new Rectangle2D.Double(p1.getX() + holeDx - terminalSize / 2, p1.getY() + holeDy - terminalSize / 2, terminalSize, terminalSize));
+ mount.subtract(new Area(new Ellipse2D.Double(p1.getX() + holeDx - holeSize / 2, p1.getY() + holeDy - holeSize / 2, holeSize, holeSize)));
+ body[1 + i].add(mount);
+ }
+ }
+ }
+ return body;
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ if (checkPointsClipped(g2d.getClip())) {
+ return;
+ }
+ Area[] area = getBody();
+ Area mainArea = area[0];
+
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getBoardColor());
+ g2d.fill(mainArea);
+
+ Color finalBorderColor;
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : getBoardColor().darker();
+ }
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+
+ g2d.setColor(finalBorderColor);
+ g2d.draw(mainArea);
+
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : TERMINAL_COLOR);
+ drawingObserver.startTrackingContinuityArea(true);
+ for (int i = 1; i < body.length; i++)
+ g2d.fill(body[i]);
+ drawingObserver.stopTrackingContinuityArea();
+
+ Color finalTerminalBorderColor;
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalTerminalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalTerminalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : TERMINAL_BORDER_COLOR;
+ }
+
+ g2d.setColor(finalTerminalBorderColor);
+ for (int i = 1; i < body.length; i++)
+ g2d.draw(body[i]);
+
+ g2d.setComposite(oldComposite);
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ g2d.rotate(-Math.PI / 4, width / 2, height / 2);
+ g2d.setColor(BOARD_COLOR);
+ int thickness = 2 * width / 32;
+ g2d.fillRect(0, height / 2 - thickness / 2, width, thickness);
+ g2d.setColor(TERMINAL_COLOR.darker());
+ int terminalWidth = 7 * width / 32;
+ g2d.fillRect(2, height / 2 + thickness / 2, terminalWidth, thickness);
+ g2d.fillRect((int) (2 + terminalWidth * 1.5), height / 2 + thickness / 2, terminalWidth, thickness);
+ g2d.fillRect((int) (2 + terminalWidth * 3), height / 2 + thickness / 2, terminalWidth, thickness);
+ g2d.setColor(TERMINAL_COLOR);
+ g2d.fillRect((int) (2 + terminalWidth * 1.5), height / 2 + thickness / 2 + 1, terminalWidth, terminalWidth);
+ g2d.setColor(Color.white);
+ g2d.fillOval((int) (2 + terminalWidth * 1.75), height / 2 + thickness / 2 + 1 + terminalWidth / 2, terminalWidth / 2, terminalWidth / 2);
+// int radius = 6 * width / 32;
+// int holeSize = 3 * width / 32;
+// g2d.setColor(BOARD_COLOR);
+// g2d.fillRect(width / 4, 1, width / 2, height - 4);
+// g2d.setColor(BORDER_COLOR);
+// g2d.drawRect(width / 4, 1, width / 2, height - 4);
+// int terminalSize = getClosestOdd(height / 5);
+// Area terminal =
+// new Area(new RoundRectangle2D.Double(2 * width / 32, height / 5, width - 4 * width / 32, terminalSize, radius,
+// radius));
+// terminal.subtract(new Area(new Ellipse2D.Double(2 * width / 32 + holeSize, height * 3 / 10 - holeSize / 2, holeSize, holeSize)));
+// terminal.subtract(new Area(new Ellipse2D.Double(width - 2 * width / 32 - holeSize * 2, height * 3 / 10 - holeSize / 2, holeSize, holeSize)));
+//
+// g2d.setColor(TERMINAL_COLOR);
+// g2d.fill(terminal);
+// g2d.setColor(TERMINAL_BORDER_COLOR);
+// g2d.draw(terminal);
+// g2d.translate(0, height * 2 / 5);
+// g2d.setColor(TERMINAL_COLOR);
+// g2d.fill(terminal);
+// g2d.setColor(TERMINAL_BORDER_COLOR);
+// g2d.draw(terminal);
+ }
+
+ @EditableProperty(name = "Board")
+ public Color getBoardColor() {
+ if (boardColor == null) {
+ boardColor = BOARD_COLOR;
+ }
+ return boardColor;
+ }
+
+ public void setBoardColor(Color bodyColor) {
+ this.boardColor = bodyColor;
+ }
+
+ @Override
+ public String getControlPointNodeName(int index) {
+ return "TerminalStrip" + index;
+ }
+
+ @EditableProperty(name = "Mounting Lugs")
+ public TagStripMount getMount() {
+ return mount;
+ }
+
+ public void setMount(TagStripMount mount) {
+ this.mount = mount;
+ updateControlPoints();
+ // Reset body shape;
+ body = null;
+ }
+
+ @Override
+ public boolean arePointsConnected(int index1, int index2) {
+ return false;
+ }
+
+ @Override
+ public boolean canPointMoveFreely(int pointIndex) {
+ return false;
+ }
+
+ public enum TagStripMount {
+ Central, Outside;
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/boards/TerminalStrip.java b/diylc/diylc-library/src/main/java/org/diylc/components/boards/TerminalStrip.java
index 55ffd4a5f..4c689f24d 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/boards/TerminalStrip.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/boards/TerminalStrip.java
@@ -360,10 +360,7 @@ public class TerminalStrip extends AbstractTransparentComponent implemen
Area[] body = getBody();
Area mainArea = getBody()[0];
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getBoardColor());
g2d.fill(mainArea);
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/boards/TriPadBoard.java b/diylc/diylc-library/src/main/java/org/diylc/components/boards/TriPadBoard.java
index abebdd5d1..6da376d54 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/boards/TriPadBoard.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/boards/TriPadBoard.java
@@ -1,213 +1,210 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.boards;
-
-import java.awt.AlphaComposite;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-import java.awt.Shape;
-import java.awt.geom.Point2D;
-
-import org.diylc.common.OrientationHV;
-import org.diylc.components.transform.VeroBoardTransformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.ILayeredComponent;
-import org.diylc.core.Project;
-import org.diylc.core.annotations.ComponentDescriptor;
-import org.diylc.core.annotations.EditableProperty;
-import org.diylc.core.annotations.KeywordPolicy;
-import org.diylc.utils.Constants;
-
-@ComponentDescriptor(name = "TriPad Board", category = "Boards", author = "Hauke Juhls", zOrder = IDIYComponent.BOARD,
- instanceNamePrefix = "Board",
- description = "Perforated FR4 board with copper strips connecting 3 holes in a row (aka TriPad Board)",
- keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, transformer = VeroBoardTransformer.class, enableCache = true)
-public class TriPadBoard extends AbstractVeroBoard implements ILayeredComponent {
-
- private static final long serialVersionUID = 1L;
-
- protected int stripSpan = 3; // determines how many holes are covered by a
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- Point2D finalSecondPoint = getFinalSecondPoint();
-
- Shape clip = g2d.getClip();
- if (checkPointsClipped(clip) && !clip.contains(firstPoint.getX(), finalSecondPoint.getY())
- && !clip.contains(finalSecondPoint.getX(), firstPoint.getY())) {
- return;
- }
- super.draw(g2d, componentState, outlineMode, project, drawingObserver);
- if (componentState != ComponentState.DRAGGING) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- double x = firstPoint.getX();
- double y = firstPoint.getY();
- int stripSize = getClosestOdd((int) STRIP_SIZE.convertToPixels());
- int holeSize = getClosestOdd((int) HOLE_SIZE.convertToPixels());
- double spacing = this.spacing.convertToPixels();
-
- if (orientation == OrientationHV.HORIZONTAL) {
- while (y < finalSecondPoint.getY() - spacing - stripSize / 2) {
- x = firstPoint.getX();
- y += spacing;
-
- while (x + spacing < finalSecondPoint.getX()) {
-
- double remainingSpace = finalSecondPoint.getX() - x;
- double spacesToDraw = stripSpan;
-
- if (remainingSpace < (stripSize + (stripSpan * spacing))) {
- spacesToDraw = (remainingSpace - stripSize) / spacing;
- }
-
- g2d.setColor(stripColor);
- drawingObserver.startTrackingContinuityArea(true);
- g2d.fillRect((int)(x + spacing - stripSize / 2), (int)(y - stripSize / 2), (int)(spacing * (spacesToDraw - 1) + stripSize),
- stripSize);
- drawingObserver.stopTrackingContinuityArea();
- g2d.setColor(stripColor.darker());
-
- g2d.drawRect((int)(x + spacing - stripSize / 2), (int)(y - stripSize / 2), (int)(spacing * (spacesToDraw - 1) + stripSize),
- stripSize);
-
- x += spacing * spacesToDraw;
- }
-
- // draw holes
- x = firstPoint.getX();
-
- while (x < finalSecondPoint.getX() - spacing - holeSize) {
- x += spacing;
- g2d.setColor(Constants.CANVAS_COLOR);
- g2d.fillOval((int)(x - holeSize / 2), (int)(y - holeSize / 2), holeSize, holeSize);
- g2d.setColor(stripColor.darker());
- g2d.drawOval((int)(x - holeSize / 2), (int)(y - holeSize / 2), holeSize, holeSize);
- }
- }
- } else {
- while (x < finalSecondPoint.getX() - spacing) {
- x += spacing;
- y = firstPoint.getY();
-
- while (y + spacing < finalSecondPoint.getY()) {
-
- double remainingSpace = finalSecondPoint.getY() - y;
- double spacesToDraw = stripSpan;
-
- if (remainingSpace < (stripSize + (stripSpan * spacing))) {
- spacesToDraw = (remainingSpace - stripSize) / spacing;
- }
-
- g2d.setColor(stripColor);
- drawingObserver.startTrackingContinuityArea(true);
- g2d.fillRect((int)(x - stripSize / 2), (int)(y + spacing - stripSize / 2), stripSize, (int)(spacing * (spacesToDraw - 1)
- + stripSize));
- drawingObserver.stopTrackingContinuityArea();
- g2d.setColor(stripColor.darker());
- g2d.drawRect((int)(x - stripSize / 2), (int)(y + spacing - stripSize / 2), stripSize, (int)(spacing * (spacesToDraw - 1)
- + stripSize));
-
- y += spacing * spacesToDraw;
- }
-
- // draw holes
- y = firstPoint.getY();
-
- while (y < finalSecondPoint.getY() - spacing - holeSize) {
- y += spacing;
- g2d.setColor(Constants.CANVAS_COLOR);
- g2d.fillOval((int)(x - holeSize / 2), (int)(y - holeSize / 2), holeSize, holeSize);
- g2d.setColor(stripColor.darker());
- g2d.drawOval((int)(x - holeSize / 2), (int)(y - holeSize / 2), holeSize, holeSize);
- }
- }
- }
- g2d.setComposite(oldComposite);
-
- super.drawCoordinates(g2d, spacing, project);
- }
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- g2d.setColor(PHENOLIC_COLOR);
- g2d.fillRect(0, 0, width, height);
-
- final int horizontalSpacing = width / 5;
- final int horizontalIndent = horizontalSpacing / 2;
-
- final int verticalSpacing = height / 5;
- final int verticalIndent = verticalSpacing / 2;
-
- for (int row = 0; row < 5; row++) {
- g2d.setColor(COPPER_COLOR);
- g2d.fillRect(0, row * verticalSpacing + 2, horizontalIndent / 2 + horizontalSpacing, verticalSpacing - 1);
-
- g2d.setColor(COPPER_COLOR);
- g2d.fillRect(horizontalSpacing + 2, row * verticalSpacing + 2, horizontalSpacing * 3 - 1, verticalSpacing - 1);
-
- g2d.fillRect(horizontalSpacing * 4 + 2, row * verticalSpacing + 2, horizontalIndent / 2 + horizontalSpacing,
- verticalSpacing - 1);
- }
-
- // draw dots
- for (int row = 0; row < 5; row++) {
- int y = (verticalSpacing * row) + verticalIndent;
- for (int col = 0; col < 5; col++) {
- int x = (horizontalSpacing * col) + horizontalIndent;
- g2d.setColor(Constants.CANVAS_COLOR);
- g2d.fillOval(x, y, 2, 2);
- g2d.setColor(COPPER_COLOR.darker());
- g2d.drawOval(x, y, 2, 2);
- }
- }
- }
-
- @EditableProperty(name = "Holes Per Strip")
- public int getStripSpan() {
- return stripSpan;
- }
-
- public void setStripSpan(int stripSpan) {
- if (stripSpan < 1) {
- this.stripSpan = 1;
- } else {
- this.stripSpan = stripSpan;
- }
- }
-
- @Override
- public String getControlPointNodeName(int index) {
- return null;
- }
-
- @Override
- public int getLayerId() {
- return 1;
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.boards;
+
+import java.awt.AlphaComposite;
+import java.awt.Composite;
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.geom.Point2D;
+
+import org.diylc.common.OrientationHV;
+import org.diylc.components.transform.VeroBoardTransformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.ILayeredComponent;
+import org.diylc.core.Project;
+import org.diylc.core.annotations.ComponentDescriptor;
+import org.diylc.core.annotations.EditableProperty;
+import org.diylc.core.annotations.KeywordPolicy;
+import org.diylc.utils.Constants;
+
+@ComponentDescriptor(name = "TriPad Board", category = "Boards", author = "Hauke Juhls", zOrder = IDIYComponent.BOARD,
+ instanceNamePrefix = "Board",
+ description = "Perforated FR4 board with copper strips connecting 3 holes in a row (aka TriPad Board)",
+ keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, transformer = VeroBoardTransformer.class, enableCache = true)
+public class TriPadBoard extends AbstractVeroBoard implements ILayeredComponent {
+
+ private static final long serialVersionUID = 1L;
+
+ protected int stripSpan = 3; // determines how many holes are covered by a
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ Point2D finalSecondPoint = getFinalSecondPoint();
+
+ Shape clip = g2d.getClip();
+ if (checkPointsClipped(clip) && !clip.contains(firstPoint.getX(), finalSecondPoint.getY())
+ && !clip.contains(finalSecondPoint.getX(), firstPoint.getY())) {
+ return;
+ }
+ super.draw(g2d, componentState, outlineMode, project, drawingObserver);
+ if (componentState != ComponentState.DRAGGING) {
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ double x = firstPoint.getX();
+ double y = firstPoint.getY();
+ int stripSize = getClosestOdd((int) STRIP_SIZE.convertToPixels());
+ int holeSize = getClosestOdd((int) HOLE_SIZE.convertToPixels());
+ double spacing = this.spacing.convertToPixels();
+
+ if (orientation == OrientationHV.HORIZONTAL) {
+ while (y < finalSecondPoint.getY() - spacing - stripSize / 2) {
+ x = firstPoint.getX();
+ y += spacing;
+
+ while (x + spacing < finalSecondPoint.getX()) {
+
+ double remainingSpace = finalSecondPoint.getX() - x;
+ double spacesToDraw = stripSpan;
+
+ if (remainingSpace < (stripSize + (stripSpan * spacing))) {
+ spacesToDraw = (remainingSpace - stripSize) / spacing;
+ }
+
+ g2d.setColor(stripColor);
+ drawingObserver.startTrackingContinuityArea(true);
+ g2d.fillRect((int)(x + spacing - stripSize / 2), (int)(y - stripSize / 2), (int)(spacing * (spacesToDraw - 1) + stripSize),
+ stripSize);
+ drawingObserver.stopTrackingContinuityArea();
+ g2d.setColor(stripColor.darker());
+
+ g2d.drawRect((int)(x + spacing - stripSize / 2), (int)(y - stripSize / 2), (int)(spacing * (spacesToDraw - 1) + stripSize),
+ stripSize);
+
+ x += spacing * spacesToDraw;
+ }
+
+ // draw holes
+ x = firstPoint.getX();
+
+ while (x < finalSecondPoint.getX() - spacing - holeSize) {
+ x += spacing;
+ g2d.setColor(Constants.CANVAS_COLOR);
+ g2d.fillOval((int)(x - holeSize / 2), (int)(y - holeSize / 2), holeSize, holeSize);
+ g2d.setColor(stripColor.darker());
+ g2d.drawOval((int)(x - holeSize / 2), (int)(y - holeSize / 2), holeSize, holeSize);
+ }
+ }
+ } else {
+ while (x < finalSecondPoint.getX() - spacing) {
+ x += spacing;
+ y = firstPoint.getY();
+
+ while (y + spacing < finalSecondPoint.getY()) {
+
+ double remainingSpace = finalSecondPoint.getY() - y;
+ double spacesToDraw = stripSpan;
+
+ if (remainingSpace < (stripSize + (stripSpan * spacing))) {
+ spacesToDraw = (remainingSpace - stripSize) / spacing;
+ }
+
+ g2d.setColor(stripColor);
+ drawingObserver.startTrackingContinuityArea(true);
+ g2d.fillRect((int)(x - stripSize / 2), (int)(y + spacing - stripSize / 2), stripSize, (int)(spacing * (spacesToDraw - 1)
+ + stripSize));
+ drawingObserver.stopTrackingContinuityArea();
+ g2d.setColor(stripColor.darker());
+ g2d.drawRect((int)(x - stripSize / 2), (int)(y + spacing - stripSize / 2), stripSize, (int)(spacing * (spacesToDraw - 1)
+ + stripSize));
+
+ y += spacing * spacesToDraw;
+ }
+
+ // draw holes
+ y = firstPoint.getY();
+
+ while (y < finalSecondPoint.getY() - spacing - holeSize) {
+ y += spacing;
+ g2d.setColor(Constants.CANVAS_COLOR);
+ g2d.fillOval((int)(x - holeSize / 2), (int)(y - holeSize / 2), holeSize, holeSize);
+ g2d.setColor(stripColor.darker());
+ g2d.drawOval((int)(x - holeSize / 2), (int)(y - holeSize / 2), holeSize, holeSize);
+ }
+ }
+ }
+ g2d.setComposite(oldComposite);
+
+ super.drawCoordinates(g2d, spacing, project);
+ }
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ g2d.setColor(PHENOLIC_COLOR);
+ g2d.fillRect(0, 0, width, height);
+
+ final int horizontalSpacing = width / 5;
+ final int horizontalIndent = horizontalSpacing / 2;
+
+ final int verticalSpacing = height / 5;
+ final int verticalIndent = verticalSpacing / 2;
+
+ for (int row = 0; row < 5; row++) {
+ g2d.setColor(COPPER_COLOR);
+ g2d.fillRect(0, row * verticalSpacing + 2, horizontalIndent / 2 + horizontalSpacing, verticalSpacing - 1);
+
+ g2d.setColor(COPPER_COLOR);
+ g2d.fillRect(horizontalSpacing + 2, row * verticalSpacing + 2, horizontalSpacing * 3 - 1, verticalSpacing - 1);
+
+ g2d.fillRect(horizontalSpacing * 4 + 2, row * verticalSpacing + 2, horizontalIndent / 2 + horizontalSpacing,
+ verticalSpacing - 1);
+ }
+
+ // draw dots
+ for (int row = 0; row < 5; row++) {
+ int y = (verticalSpacing * row) + verticalIndent;
+ for (int col = 0; col < 5; col++) {
+ int x = (horizontalSpacing * col) + horizontalIndent;
+ g2d.setColor(Constants.CANVAS_COLOR);
+ g2d.fillOval(x, y, 2, 2);
+ g2d.setColor(COPPER_COLOR.darker());
+ g2d.drawOval(x, y, 2, 2);
+ }
+ }
+ }
+
+ @EditableProperty(name = "Holes Per Strip")
+ public int getStripSpan() {
+ return stripSpan;
+ }
+
+ public void setStripSpan(int stripSpan) {
+ if (stripSpan < 1) {
+ this.stripSpan = 1;
+ } else {
+ this.stripSpan = stripSpan;
+ }
+ }
+
+ @Override
+ public String getControlPointNodeName(int index) {
+ return null;
+ }
+
+ @Override
+ public int getLayerId() {
+ return 1;
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/boards/VeroBoard.java b/diylc/diylc-library/src/main/java/org/diylc/components/boards/VeroBoard.java
index a2dece1f8..23cb85d72 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/boards/VeroBoard.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/boards/VeroBoard.java
@@ -1,155 +1,152 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.boards;
-
-import java.awt.AlphaComposite;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-import java.awt.Shape;
-import java.awt.geom.Point2D;
-
-import org.diylc.common.OrientationHV;
-import org.diylc.components.transform.VeroBoardTransformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.ILayeredComponent;
-import org.diylc.core.Project;
-import org.diylc.core.annotations.BomPolicy;
-import org.diylc.core.annotations.ComponentDescriptor;
-import org.diylc.core.annotations.KeywordPolicy;
-import org.diylc.utils.Constants;
-
-@ComponentDescriptor(name = "Vero Board", category = "Boards", author = "Branislav Stojkovic",
- zOrder = IDIYComponent.BOARD, instanceNamePrefix = "Board",
- description = "Perforated FR4 board with copper strips connecting all holes in a row",
- bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME,
- transformer = VeroBoardTransformer.class, enableCache = true)
-public class VeroBoard extends AbstractVeroBoard implements ILayeredComponent {
-
- private static final long serialVersionUID = 1L;
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- Point2D finalSecondPoint = getFinalSecondPoint();
-
- Shape clip = g2d.getClip();
- if (checkPointsClipped(clip) && !clip.contains(firstPoint.getX(), finalSecondPoint.getY())
- && !clip.contains(finalSecondPoint.getX(), firstPoint.getY())) {
- return;
- }
- super.draw(g2d, componentState, outlineMode, project, drawingObserver);
- if (componentState != ComponentState.DRAGGING) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- double x = firstPoint.getX();
- double y = firstPoint.getY();
- int stripSize = getClosestOdd((int) STRIP_SIZE.convertToPixels());
- int holeSize = getClosestOdd((int) HOLE_SIZE.convertToPixels());
- int spacing = (int) this.spacing.convertToPixels();
-
- if (orientation == OrientationHV.HORIZONTAL) {
- while (y < finalSecondPoint.getY() - spacing - stripSize / 2) {
- x = firstPoint.getX();
- y += spacing;
- g2d.setColor(stripColor);
- drawingObserver.startTrackingContinuityArea(true);
- g2d.fillRect((int)(x + spacing / 2), (int)(y - stripSize / 2), (int)(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);
- while (x < finalSecondPoint.getX() - spacing - holeSize) {
- x += spacing;
- g2d.setColor(Constants.CANVAS_COLOR);
- g2d.fillOval((int)(x - holeSize / 2), (int)(y - holeSize / 2), holeSize, holeSize);
- g2d.setColor(stripColor.darker());
- g2d.drawOval((int)(x - holeSize / 2), (int)(y - holeSize / 2), holeSize, holeSize);
- }
- }
- } else {
- while (x < finalSecondPoint.getX() - spacing) {
- x += spacing;
- 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));
- drawingObserver.stopTrackingContinuityArea();
- g2d.setColor(stripColor.darker());
- g2d.drawRect((int)(x - stripSize / 2), (int)(y + spacing / 2), stripSize, (int)(finalSecondPoint.getY() - spacing - y));
- while (y < finalSecondPoint.getY() - spacing - holeSize) {
- y += spacing;
- g2d.setColor(Constants.CANVAS_COLOR);
- g2d.fillOval((int)(x - holeSize / 2), (int)(y - holeSize / 2), holeSize, holeSize);
- g2d.setColor(stripColor.darker());
- g2d.drawOval((int)(x - holeSize / 2), (int)(y - holeSize / 2), holeSize, holeSize);
- }
- }
- }
- g2d.setComposite(oldComposite);
- super.drawCoordinates(g2d, spacing, project);
- }
- }
-
- @Override
- public int getLayerId() {
- return 1;
- }
-
- @Override
- public String getControlPointNodeName(int index) {
- return null;
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int factor = 32 / width;
- g2d.setColor(PHENOLIC_COLOR);
- g2d.fillRect(0, 2 / factor, width - 1, height - 4 / factor);
- g2d.setColor(BORDER_COLOR);
- g2d.drawRect(0, 2 / factor, width - 1, height - 4 / factor);
- g2d.setColor(COPPER_COLOR);
- g2d.fillRect(1 / factor, width / 4, width - 2 / factor, width / 2);
- g2d.setColor(COPPER_COLOR.darker());
- g2d.drawRect(1 / factor, width / 4, width - 2 / factor, width / 2);
-
- g2d.setColor(COPPER_COLOR);
- g2d.fillRect(1 / factor, 2 / factor, width - 2 / factor, 3 / factor);
- g2d.fillRect(1 / factor, height - 5 / factor, width - 2 / factor, 3 / factor);
- g2d.setColor(COPPER_COLOR.darker());
- g2d.drawRect(1 / factor, 2 / factor, width - 2 / factor, 3 / factor);
- g2d.drawRect(1 / factor, height - 5 / factor, width - 2 / factor, 3 / factor);
-
- g2d.setColor(Constants.CANVAS_COLOR);
- g2d.fillOval(width / 3 - 2 / factor, width / 2 - 2 / factor, getClosestOdd(5.0 / factor),
- getClosestOdd(5.0 / factor));
- g2d.fillOval(2 * width / 3 - 2 / factor, width / 2 - 2 / factor, getClosestOdd(5.0 / factor),
- getClosestOdd(5.0 / factor));
- g2d.setColor(COPPER_COLOR.darker());
- g2d.drawOval(width / 3 - 2 / factor, width / 2 - 2 / factor, getClosestOdd(5.0 / factor),
- getClosestOdd(5.0 / factor));
- g2d.drawOval(2 * width / 3 - 2 / factor, width / 2 - 2 / factor, getClosestOdd(5.0 / factor),
- getClosestOdd(5.0 / factor));
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.boards;
+
+import java.awt.AlphaComposite;
+import java.awt.Composite;
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.geom.Point2D;
+
+import org.diylc.common.OrientationHV;
+import org.diylc.components.transform.VeroBoardTransformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.ILayeredComponent;
+import org.diylc.core.Project;
+import org.diylc.core.annotations.BomPolicy;
+import org.diylc.core.annotations.ComponentDescriptor;
+import org.diylc.core.annotations.KeywordPolicy;
+import org.diylc.utils.Constants;
+
+@ComponentDescriptor(name = "Vero Board", category = "Boards", author = "Branislav Stojkovic",
+ zOrder = IDIYComponent.BOARD, instanceNamePrefix = "Board",
+ description = "Perforated FR4 board with copper strips connecting all holes in a row",
+ bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME,
+ transformer = VeroBoardTransformer.class, enableCache = true)
+public class VeroBoard extends AbstractVeroBoard implements ILayeredComponent {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ Point2D finalSecondPoint = getFinalSecondPoint();
+
+ Shape clip = g2d.getClip();
+ if (checkPointsClipped(clip) && !clip.contains(firstPoint.getX(), finalSecondPoint.getY())
+ && !clip.contains(finalSecondPoint.getX(), firstPoint.getY())) {
+ return;
+ }
+ super.draw(g2d, componentState, outlineMode, project, drawingObserver);
+ if (componentState != ComponentState.DRAGGING) {
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ double x = firstPoint.getX();
+ double y = firstPoint.getY();
+ int stripSize = getClosestOdd((int) STRIP_SIZE.convertToPixels());
+ int holeSize = getClosestOdd((int) HOLE_SIZE.convertToPixels());
+ int spacing = (int) this.spacing.convertToPixels();
+
+ if (orientation == OrientationHV.HORIZONTAL) {
+ while (y < finalSecondPoint.getY() - spacing - stripSize / 2) {
+ x = firstPoint.getX();
+ y += spacing;
+ g2d.setColor(stripColor);
+ drawingObserver.startTrackingContinuityArea(true);
+ g2d.fillRect((int)(x + spacing / 2), (int)(y - stripSize / 2), (int)(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);
+ while (x < finalSecondPoint.getX() - spacing - holeSize) {
+ x += spacing;
+ g2d.setColor(Constants.CANVAS_COLOR);
+ g2d.fillOval((int)(x - holeSize / 2), (int)(y - holeSize / 2), holeSize, holeSize);
+ g2d.setColor(stripColor.darker());
+ g2d.drawOval((int)(x - holeSize / 2), (int)(y - holeSize / 2), holeSize, holeSize);
+ }
+ }
+ } else {
+ while (x < finalSecondPoint.getX() - spacing) {
+ x += spacing;
+ 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));
+ drawingObserver.stopTrackingContinuityArea();
+ g2d.setColor(stripColor.darker());
+ g2d.drawRect((int)(x - stripSize / 2), (int)(y + spacing / 2), stripSize, (int)(finalSecondPoint.getY() - spacing - y));
+ while (y < finalSecondPoint.getY() - spacing - holeSize) {
+ y += spacing;
+ g2d.setColor(Constants.CANVAS_COLOR);
+ g2d.fillOval((int)(x - holeSize / 2), (int)(y - holeSize / 2), holeSize, holeSize);
+ g2d.setColor(stripColor.darker());
+ g2d.drawOval((int)(x - holeSize / 2), (int)(y - holeSize / 2), holeSize, holeSize);
+ }
+ }
+ }
+ g2d.setComposite(oldComposite);
+ super.drawCoordinates(g2d, spacing, project);
+ }
+ }
+
+ @Override
+ public int getLayerId() {
+ return 1;
+ }
+
+ @Override
+ public String getControlPointNodeName(int index) {
+ return null;
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int factor = 32 / width;
+ g2d.setColor(PHENOLIC_COLOR);
+ g2d.fillRect(0, 2 / factor, width - 1, height - 4 / factor);
+ g2d.setColor(BORDER_COLOR);
+ g2d.drawRect(0, 2 / factor, width - 1, height - 4 / factor);
+ g2d.setColor(COPPER_COLOR);
+ g2d.fillRect(1 / factor, width / 4, width - 2 / factor, width / 2);
+ g2d.setColor(COPPER_COLOR.darker());
+ g2d.drawRect(1 / factor, width / 4, width - 2 / factor, width / 2);
+
+ g2d.setColor(COPPER_COLOR);
+ g2d.fillRect(1 / factor, 2 / factor, width - 2 / factor, 3 / factor);
+ g2d.fillRect(1 / factor, height - 5 / factor, width - 2 / factor, 3 / factor);
+ g2d.setColor(COPPER_COLOR.darker());
+ g2d.drawRect(1 / factor, 2 / factor, width - 2 / factor, 3 / factor);
+ g2d.drawRect(1 / factor, height - 5 / factor, width - 2 / factor, 3 / factor);
+
+ g2d.setColor(Constants.CANVAS_COLOR);
+ g2d.fillOval(width / 3 - 2 / factor, width / 2 - 2 / factor, getClosestOdd(5.0 / factor),
+ getClosestOdd(5.0 / factor));
+ g2d.fillOval(2 * width / 3 - 2 / factor, width / 2 - 2 / factor, getClosestOdd(5.0 / factor),
+ getClosestOdd(5.0 / factor));
+ g2d.setColor(COPPER_COLOR.darker());
+ g2d.drawOval(width / 3 - 2 / factor, width / 2 - 2 / factor, getClosestOdd(5.0 / factor),
+ getClosestOdd(5.0 / factor));
+ g2d.drawOval(2 * width / 3 - 2 / factor, width / 2 - 2 / factor, getClosestOdd(5.0 / factor),
+ getClosestOdd(5.0 / factor));
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/chassis/ChassisPanel.java b/diylc/diylc-library/src/main/java/org/diylc/components/chassis/ChassisPanel.java
index dc2f9f0ce..06457d0e2 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/chassis/ChassisPanel.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/chassis/ChassisPanel.java
@@ -1,111 +1,108 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.chassis;
-
-import java.awt.AlphaComposite;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-
-import org.diylc.common.ObjectCache;
-import org.diylc.components.shapes.AbstractShape;
-import org.diylc.components.transform.SimpleComponentTransformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-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;
-
-@ComponentDescriptor(name = "Chassis Panel", author = "Branislav Stojkovic", category = "Electro-Mechanical",
- instanceNamePrefix = "CP", description = "One side of a chassis, with or withouth rounded edges",
- zOrder = IDIYComponent.CHASSIS, bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, autoEdit = false,
- transformer = SimpleComponentTransformer.class)
-public class ChassisPanel extends AbstractShape {
-
- private static final long serialVersionUID = 1L;
-
- protected Size edgeRadius = new Size(0d, SizeUnit.mm);
-
- public ChassisPanel() {
- this.color = LIGHT_METAL_COLOR;
- this.borderColor = LIGHT_METAL_COLOR.darker();
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke((int) borderThickness.convertToPixels()));
- int radius = (int) edgeRadius.convertToPixels();
- if (componentState != ComponentState.DRAGGING) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(color);
- if (radius == 0) {
- g2d.fillRect((int) firstPoint.getX(), (int) firstPoint.getY(),
- (int) (secondPoint.getX() - firstPoint.getX()),
- (int) (secondPoint.getY() - firstPoint.getY()));
- } else {
- g2d.fillRoundRect((int) firstPoint.getX(), (int) firstPoint.getY(),
- (int) (secondPoint.getX() - firstPoint.getX()),
- (int) (secondPoint.getY() - firstPoint.getY()), radius, radius);
- }
- g2d.setComposite(oldComposite);
- drawingObserver.stopTracking();
- }
- // Do not track any changes that follow because the whole rect has been
- // tracked so far.
- g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : borderColor);
- if (radius == 0) {
- g2d.drawRect((int) (firstPoint.getX()), (int) (firstPoint.getY()),
- (int) (secondPoint.getX() - firstPoint.getX()),
- (int) (secondPoint.getY() - firstPoint.getY()));
- } else {
- g2d.drawRoundRect((int) (firstPoint.getX()), (int) (firstPoint.getY()),
- (int) (secondPoint.getX() - firstPoint.getX()),
- (int) (secondPoint.getY() - firstPoint.getY()), radius, radius);
- }
- }
-
- @EditableProperty(name = "Radius")
- public Size getEdgeRadius() {
- return edgeRadius;
- }
-
- public void setEdgeRadius(Size edgeRadius) {
- this.edgeRadius = edgeRadius;
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int factor = 32 / width;
- g2d.setColor(LIGHT_METAL_COLOR);
- g2d.fillRect(2 / factor, 4 / factor, width - 4 / factor, height - 8 / factor);
- g2d.setColor(LIGHT_METAL_COLOR.darker());
- g2d.drawRect(2 / factor, 4 / factor, width - 4 / factor, height - 8 / factor);
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.chassis;
+
+import java.awt.AlphaComposite;
+import java.awt.Composite;
+import java.awt.Graphics2D;
+
+import org.diylc.common.ObjectCache;
+import org.diylc.components.shapes.AbstractShape;
+import org.diylc.components.transform.SimpleComponentTransformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+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;
+
+@ComponentDescriptor(name = "Chassis Panel", author = "Branislav Stojkovic", category = "Electro-Mechanical",
+ instanceNamePrefix = "CP", description = "One side of a chassis, with or withouth rounded edges",
+ zOrder = IDIYComponent.CHASSIS, bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, autoEdit = false,
+ transformer = SimpleComponentTransformer.class)
+public class ChassisPanel extends AbstractShape {
+
+ private static final long serialVersionUID = 1L;
+
+ protected Size edgeRadius = new Size(0d, SizeUnit.mm);
+
+ public ChassisPanel() {
+ this.color = LIGHT_METAL_COLOR;
+ this.borderColor = LIGHT_METAL_COLOR.darker();
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke((int) borderThickness.convertToPixels()));
+ int radius = (int) edgeRadius.convertToPixels();
+ if (componentState != ComponentState.DRAGGING) {
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.setColor(color);
+ if (radius == 0) {
+ g2d.fillRect((int) firstPoint.getX(), (int) firstPoint.getY(),
+ (int) (secondPoint.getX() - firstPoint.getX()),
+ (int) (secondPoint.getY() - firstPoint.getY()));
+ } else {
+ g2d.fillRoundRect((int) firstPoint.getX(), (int) firstPoint.getY(),
+ (int) (secondPoint.getX() - firstPoint.getX()),
+ (int) (secondPoint.getY() - firstPoint.getY()), radius, radius);
+ }
+ g2d.setComposite(oldComposite);
+ drawingObserver.stopTracking();
+ }
+ // Do not track any changes that follow because the whole rect has been
+ // tracked so far.
+ g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : borderColor);
+ if (radius == 0) {
+ g2d.drawRect((int) (firstPoint.getX()), (int) (firstPoint.getY()),
+ (int) (secondPoint.getX() - firstPoint.getX()),
+ (int) (secondPoint.getY() - firstPoint.getY()));
+ } else {
+ g2d.drawRoundRect((int) (firstPoint.getX()), (int) (firstPoint.getY()),
+ (int) (secondPoint.getX() - firstPoint.getX()),
+ (int) (secondPoint.getY() - firstPoint.getY()), radius, radius);
+ }
+ }
+
+ @EditableProperty(name = "Radius")
+ public Size getEdgeRadius() {
+ return edgeRadius;
+ }
+
+ public void setEdgeRadius(Size edgeRadius) {
+ this.edgeRadius = edgeRadius;
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int factor = 32 / width;
+ g2d.setColor(LIGHT_METAL_COLOR);
+ g2d.fillRect(2 / factor, 4 / factor, width - 4 / factor, height - 8 / factor);
+ g2d.setColor(LIGHT_METAL_COLOR.darker());
+ g2d.drawRect(2 / factor, 4 / factor, width - 4 / factor, height - 8 / factor);
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/chassis/EllipticalCutout.java b/diylc/diylc-library/src/main/java/org/diylc/components/chassis/EllipticalCutout.java
index 9fa17e49d..5727c3aa4 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/chassis/EllipticalCutout.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/chassis/EllipticalCutout.java
@@ -1,75 +1,72 @@
-/*
- *
- * 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
- * .
- */
-package org.diylc.components.chassis;
-
-import java.awt.AlphaComposite;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-
-import org.diylc.common.ObjectCache;
-import org.diylc.components.shapes.AbstractShape;
-import org.diylc.components.transform.SimpleComponentTransformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.annotations.BomPolicy;
-import org.diylc.core.annotations.ComponentDescriptor;
-
-@ComponentDescriptor(name = "Elliptical Cutout", author = "Branislav Stojkovic", category = "Electro-Mechanical",
- instanceNamePrefix = "ELC", description = "Elliptical chassis cutout", zOrder = IDIYComponent.CHASSIS + 0.1,
- bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false, transformer = SimpleComponentTransformer.class)
-public class EllipticalCutout extends AbstractShape {
-
- private static final long serialVersionUID = 1L;
-
- public EllipticalCutout() {
- this.borderColor = LIGHT_METAL_COLOR.darker();
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke((int) borderThickness.convertToPixels()));
-
- if (componentState != ComponentState.DRAGGING) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(color);
- g2d.fillOval((int)firstPoint.getX(), (int)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
- // tracked so far.
- 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()));
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int factor = 32 / width;
- g2d.setColor(COLOR);
- g2d.fillOval(2 / factor, 2 / factor, width - 4 / factor, height - 4 / factor);
- g2d.setColor(LIGHT_METAL_COLOR.darker());
- g2d.drawOval(2 / factor, 2 / factor, width - 4 / factor, height - 4 / factor);
- }
-}
+/*
+ *
+ * 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
+ * .
+ */
+package org.diylc.components.chassis;
+
+import java.awt.AlphaComposite;
+import java.awt.Composite;
+import java.awt.Graphics2D;
+
+import org.diylc.common.ObjectCache;
+import org.diylc.components.shapes.AbstractShape;
+import org.diylc.components.transform.SimpleComponentTransformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.annotations.BomPolicy;
+import org.diylc.core.annotations.ComponentDescriptor;
+
+@ComponentDescriptor(name = "Elliptical Cutout", author = "Branislav Stojkovic", category = "Electro-Mechanical",
+ instanceNamePrefix = "ELC", description = "Elliptical chassis cutout", zOrder = IDIYComponent.CHASSIS + 0.1,
+ bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false, transformer = SimpleComponentTransformer.class)
+public class EllipticalCutout extends AbstractShape {
+
+ private static final long serialVersionUID = 1L;
+
+ public EllipticalCutout() {
+ this.borderColor = LIGHT_METAL_COLOR.darker();
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke((int) borderThickness.convertToPixels()));
+
+ 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.setComposite(oldComposite);
+ }
+ // Do not track any changes that follow because the whole oval has been
+ // tracked so far.
+ 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()));
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int factor = 32 / width;
+ g2d.setColor(COLOR);
+ g2d.fillOval(2 / factor, 2 / factor, width - 4 / factor, height - 4 / factor);
+ g2d.setColor(LIGHT_METAL_COLOR.darker());
+ g2d.drawOval(2 / factor, 2 / factor, width - 4 / factor, height - 4 / factor);
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/chassis/PolygonalCutout.java b/diylc/diylc-library/src/main/java/org/diylc/components/chassis/PolygonalCutout.java
index 8b74917bf..313c23bf6 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/chassis/PolygonalCutout.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/chassis/PolygonalCutout.java
@@ -1,126 +1,123 @@
-/*
- *
- * 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
- * .
- */
-package org.diylc.components.chassis;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-import java.awt.geom.Point2D;
-import java.util.Arrays;
-
-import org.diylc.common.ObjectCache;
-import org.diylc.components.shapes.AbstractShape;
-import org.diylc.components.transform.SimpleComponentTransformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.annotations.BomPolicy;
-import org.diylc.core.annotations.ComponentDescriptor;
-import org.diylc.core.annotations.EditableProperty;
-
-@ComponentDescriptor(name = "Polygonal Cutout", author = "Branislav Stojkovic", category = "Electro-Mechanical",
- instanceNamePrefix = "POLYC", description = "Polygonal chassis cutout", zOrder = IDIYComponent.CHASSIS + 0.1,
- bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false, transformer = SimpleComponentTransformer.class)
-public class PolygonalCutout extends AbstractShape {
-
- private static final long serialVersionUID = 1L;
-
- protected PointCount pointCount = PointCount._4;
-
- public PolygonalCutout() {
- super();
- this.borderColor = LIGHT_METAL_COLOR.darker();
- this.controlPoints =
- new Point2D[] {new Point2D.Double(0, 0),
- new Point2D.Double(0, (int) DEFAULT_HEIGHT.convertToPixels()),
- new Point2D.Double((int) DEFAULT_WIDTH.convertToPixels(), (int) DEFAULT_HEIGHT.convertToPixels()),
- new Point2D.Double((int) DEFAULT_WIDTH.convertToPixels(), 0)};
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke((int) borderThickness.convertToPixels()));
- g2d.setColor(color);
- int[] xPoints = new int[controlPoints.length];
- int[] yPoints = new int[controlPoints.length];
- for (int i = 0; i < controlPoints.length; i++) {
- xPoints[i] = (int)controlPoints[i].getX();
- yPoints[i] = (int)controlPoints[i].getY();
- }
-
- Composite oldComposite = g2d.getComposite();
- if (this.alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(3, 1.0F * this.alpha / MAX_ALPHA));
- }
- g2d.fillPolygon(xPoints, yPoints, controlPoints.length);
- g2d.setComposite(oldComposite);
-
- // Do not track any changes that follow because the whole board has been
- // tracked so far.
- drawingObserver.stopTracking();
- Color lineColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : borderColor;
- g2d.setColor(lineColor);
- g2d.drawPolygon(xPoints, yPoints, controlPoints.length);
- }
-
- @EditableProperty(name = "Edges")
- public PointCount getPointCount() {
- return pointCount;
- }
-
- public void setPointCount(PointCount pointCount) {
- if (this.pointCount == pointCount)
- return;
- int oldPointCount = Integer.parseInt(this.pointCount.toString());
- int newPointCount = Integer.parseInt(pointCount.toString());
- this.controlPoints = Arrays.copyOf(this.controlPoints, newPointCount);
- if (oldPointCount < newPointCount) {
- this.controlPoints[newPointCount - 1] = this.controlPoints[oldPointCount - 1];
- for (int i = oldPointCount - 1; i < newPointCount - 1; i++) {
- this.controlPoints[i] =
- new Point2D.Double((this.controlPoints[i - 1].getX() + this.controlPoints[newPointCount - 1].getX()) / 2,
- (this.controlPoints[i - 1].getY() + this.controlPoints[newPointCount - 1].getY()) / 2);
- }
- }
- this.pointCount = pointCount;
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int factor = 32 / width;
- g2d.setColor(COLOR);
- int[] x = {2 / factor, width - 2 / factor, width - 4 / factor, 3 / factor};
- int[] y = {4 / factor, 2 / factor, height - 5 / factor, height - 2 / factor};
- g2d.fillPolygon(x, y, 4);
- g2d.setColor(LIGHT_METAL_COLOR.darker());
- g2d.drawPolygon(x, y, 4);
- }
-
- public enum PointCount {
- _3, _4, _5, _6, _7, _8;
-
- public String toString() {
- return name().substring(1);
- };
- }
-}
+/*
+ *
+ * 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
+ * .
+ */
+package org.diylc.components.chassis;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Graphics2D;
+import java.awt.geom.Point2D;
+import java.util.Arrays;
+
+import org.diylc.common.ObjectCache;
+import org.diylc.components.shapes.AbstractShape;
+import org.diylc.components.transform.SimpleComponentTransformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.annotations.BomPolicy;
+import org.diylc.core.annotations.ComponentDescriptor;
+import org.diylc.core.annotations.EditableProperty;
+
+@ComponentDescriptor(name = "Polygonal Cutout", author = "Branislav Stojkovic", category = "Electro-Mechanical",
+ instanceNamePrefix = "POLYC", description = "Polygonal chassis cutout", zOrder = IDIYComponent.CHASSIS + 0.1,
+ bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false, transformer = SimpleComponentTransformer.class)
+public class PolygonalCutout extends AbstractShape {
+
+ private static final long serialVersionUID = 1L;
+
+ protected PointCount pointCount = PointCount._4;
+
+ public PolygonalCutout() {
+ super();
+ this.borderColor = LIGHT_METAL_COLOR.darker();
+ this.controlPoints =
+ new Point2D[] {new Point2D.Double(0, 0),
+ new Point2D.Double(0, (int) DEFAULT_HEIGHT.convertToPixels()),
+ new Point2D.Double((int) DEFAULT_WIDTH.convertToPixels(), (int) DEFAULT_HEIGHT.convertToPixels()),
+ new Point2D.Double((int) DEFAULT_WIDTH.convertToPixels(), 0)};
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke((int) borderThickness.convertToPixels()));
+ g2d.setColor(color);
+ int[] xPoints = new int[controlPoints.length];
+ int[] yPoints = new int[controlPoints.length];
+ for (int i = 0; i < controlPoints.length; i++) {
+ xPoints[i] = (int)controlPoints[i].getX();
+ yPoints[i] = (int)controlPoints[i].getY();
+ }
+
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.fillPolygon(xPoints, yPoints, controlPoints.length);
+ g2d.setComposite(oldComposite);
+
+ // Do not track any changes that follow because the whole board has been
+ // tracked so far.
+ drawingObserver.stopTracking();
+ Color lineColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : borderColor;
+ g2d.setColor(lineColor);
+ g2d.drawPolygon(xPoints, yPoints, controlPoints.length);
+ }
+
+ @EditableProperty(name = "Edges")
+ public PointCount getPointCount() {
+ return pointCount;
+ }
+
+ public void setPointCount(PointCount pointCount) {
+ if (this.pointCount == pointCount)
+ return;
+ int oldPointCount = Integer.parseInt(this.pointCount.toString());
+ int newPointCount = Integer.parseInt(pointCount.toString());
+ this.controlPoints = Arrays.copyOf(this.controlPoints, newPointCount);
+ if (oldPointCount < newPointCount) {
+ this.controlPoints[newPointCount - 1] = this.controlPoints[oldPointCount - 1];
+ for (int i = oldPointCount - 1; i < newPointCount - 1; i++) {
+ this.controlPoints[i] =
+ new Point2D.Double((this.controlPoints[i - 1].getX() + this.controlPoints[newPointCount - 1].getX()) / 2,
+ (this.controlPoints[i - 1].getY() + this.controlPoints[newPointCount - 1].getY()) / 2);
+ }
+ }
+ this.pointCount = pointCount;
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int factor = 32 / width;
+ g2d.setColor(COLOR);
+ int[] x = {2 / factor, width - 2 / factor, width - 4 / factor, 3 / factor};
+ int[] y = {4 / factor, 2 / factor, height - 5 / factor, height - 2 / factor};
+ g2d.fillPolygon(x, y, 4);
+ g2d.setColor(LIGHT_METAL_COLOR.darker());
+ g2d.drawPolygon(x, y, 4);
+ }
+
+ public enum PointCount {
+ _3, _4, _5, _6, _7, _8;
+
+ public String toString() {
+ return name().substring(1);
+ };
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/chassis/RectangularCutout.java b/diylc/diylc-library/src/main/java/org/diylc/components/chassis/RectangularCutout.java
index a57f8902c..7a8bd35bf 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/chassis/RectangularCutout.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/chassis/RectangularCutout.java
@@ -1,92 +1,89 @@
-/*
- *
- * 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
- * .
- */
-package org.diylc.components.chassis;
-
-import java.awt.AlphaComposite;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-
-import org.diylc.common.ObjectCache;
-import org.diylc.components.shapes.AbstractShape;
-import org.diylc.components.transform.SimpleComponentTransformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-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;
-
-@ComponentDescriptor(name = "Rectangular Cutout", author = "Branislav Stojkovic", category = "Electro-Mechanical",
- instanceNamePrefix = "RECTC", description = "Rectangular chassis cutout, with or without rounded edges",
- zOrder = IDIYComponent.CHASSIS + 0.1, bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false,
- transformer = SimpleComponentTransformer.class)
-public class RectangularCutout extends AbstractShape {
-
- private static final long serialVersionUID = 1L;
-
- protected Size edgeRadius = new Size(0d, SizeUnit.mm);
-
- public RectangularCutout() {
- this.borderColor = LIGHT_METAL_COLOR.darker();
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke((int) borderThickness.convertToPixels()));
- int radius = (int) edgeRadius.convertToPixels();
- if (componentState != ComponentState.DRAGGING) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(color);
- g2d.fillRoundRect((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(secondPoint.getX() - firstPoint.getX()), (int)(secondPoint.getY() - firstPoint.getY()), radius,
- radius);
- g2d.setComposite(oldComposite);
- }
- // Do not track any changes that follow because the whole rect has been
- // tracked so far.
- 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,
- radius);
- }
-
- @EditableProperty(name = "Radius")
- public Size getEdgeRadius() {
- return edgeRadius;
- }
-
- public void setEdgeRadius(Size edgeRadius) {
- this.edgeRadius = edgeRadius;
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int factor = 32 / width;
- g2d.setColor(COLOR);
- g2d.fillRect(2 / factor, 4 / factor, width - 4 / factor, height - 8 / factor);
- g2d.setColor(LIGHT_METAL_COLOR.darker());
- g2d.drawRect(2 / factor, 4 / factor, width - 4 / factor, height - 8 / factor);
- }
-}
+/*
+ *
+ * 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
+ * .
+ */
+package org.diylc.components.chassis;
+
+import java.awt.AlphaComposite;
+import java.awt.Composite;
+import java.awt.Graphics2D;
+
+import org.diylc.common.ObjectCache;
+import org.diylc.components.shapes.AbstractShape;
+import org.diylc.components.transform.SimpleComponentTransformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+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;
+
+@ComponentDescriptor(name = "Rectangular Cutout", author = "Branislav Stojkovic", category = "Electro-Mechanical",
+ instanceNamePrefix = "RECTC", description = "Rectangular chassis cutout, with or without rounded edges",
+ zOrder = IDIYComponent.CHASSIS + 0.1, bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false,
+ transformer = SimpleComponentTransformer.class)
+public class RectangularCutout extends AbstractShape {
+
+ private static final long serialVersionUID = 1L;
+
+ protected Size edgeRadius = new Size(0d, SizeUnit.mm);
+
+ public RectangularCutout() {
+ this.borderColor = LIGHT_METAL_COLOR.darker();
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke((int) borderThickness.convertToPixels()));
+ int radius = (int) edgeRadius.convertToPixels();
+ 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,
+ radius);
+ g2d.setComposite(oldComposite);
+ }
+ // Do not track any changes that follow because the whole rect has been
+ // tracked so far.
+ 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,
+ radius);
+ }
+
+ @EditableProperty(name = "Radius")
+ public Size getEdgeRadius() {
+ return edgeRadius;
+ }
+
+ public void setEdgeRadius(Size edgeRadius) {
+ this.edgeRadius = edgeRadius;
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int factor = 32 / width;
+ g2d.setColor(COLOR);
+ g2d.fillRect(2 / factor, 4 / factor, width - 4 / factor, height - 8 / factor);
+ g2d.setColor(LIGHT_METAL_COLOR.darker());
+ g2d.drawRect(2 / factor, 4 / factor, width - 4 / factor, height - 8 / factor);
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/CurvedTrace.java b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/CurvedTrace.java
index 59471bd47..e8521f83c 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/CurvedTrace.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/CurvedTrace.java
@@ -27,6 +27,7 @@ import com.bancika.gerberwriter.GerberFunctions;
import org.diylc.common.LineStyle;
import org.diylc.common.ObjectCache;
import org.diylc.common.PCBLayer;
+import org.diylc.common.Percentage;
import org.diylc.components.AbstractCurvedComponent;
import org.diylc.components.AbstractLeadedComponent;
import org.diylc.components.LineEndingStyle;
@@ -126,7 +127,7 @@ public class CurvedTrace extends AbstractCurvedComponent implements ILayer
public void setValue(Void value) {}
@Override
- public void setAlpha(Byte alpha) {
+ public void setAlpha(Percentage alpha) {
super.setAlpha(alpha);
}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/CutLine.java b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/CutLine.java
index 915ea6764..8c6622516 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/CutLine.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/CutLine.java
@@ -1,165 +1,162 @@
-/*
- *
- * 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
- * .
- */
-package org.diylc.components.connectivity;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-import java.awt.geom.Point2D;
-
-import org.diylc.common.ObjectCache;
-import org.diylc.common.OrientationHV;
-import org.diylc.components.AbstractTransparentComponent;
-import org.diylc.components.transform.SimpleComponentTransformer;
-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;
-
-@ComponentDescriptor(name = "Cut Line", category = "Connectivity", author = "Branislav Stojkovic",
- description = "Cut line", instanceNamePrefix = "CL", zOrder = IDIYComponent.COMPONENT,
- bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false, transformer = SimpleComponentTransformer.class)
-public class CutLine extends AbstractTransparentComponent {
-
- private static final long serialVersionUID = 1L;
-
- public static Size WIDTH = new Size(0.125d, SizeUnit.in);
- public static Size LENGTH = new Size(3.125d, SizeUnit.in);
- public static Color COLOR = Color.black;
-
- private Size width = WIDTH;
- private Size length = LENGTH;
- private Color color = COLOR;
- private Point2D.Double point = new Point2D.Double(0, 0);
- private OrientationHV orientation = OrientationHV.VERTICAL;
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- int w = getClosestOdd((int) getWidth().convertToPixels());
- int l = getClosestOdd((int) getLength().convertToPixels());
- g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : color);
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(w));
-
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
-
- if (getOrientation() == OrientationHV.HORIZONTAL)
- g2d.drawLine((int)point.getX(), (int)point.getY(), (int)point.getX() + l, (int)point.getY());
- else
- g2d.drawLine((int)point.getX(), (int)point.getY(), (int)point.getX(), (int)point.getY() + l);
-
- g2d.setComposite(oldComposite);
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(2));
- g2d.setColor(COLOR);
- g2d.drawLine(width / 2, height - 2, width / 2, 1);
- }
-
- @EditableProperty
- public Size getWidth() {
- return width;
- }
-
- public void setWidth(Size width) {
- this.width = width;
- }
-
- @EditableProperty
- public Size getLength() {
- return length;
- }
-
- public void setLength(Size length) {
- this.length = length;
- }
-
- @EditableProperty
- public OrientationHV getOrientation() {
- return orientation;
- }
-
- public void setOrientation(OrientationHV orientation) {
- this.orientation = orientation;
- }
-
- @Override
- public String getName() {
- return super.getName();
- }
-
- @Override
- public int getControlPointCount() {
- return 1;
- }
-
- @Override
- public boolean isControlPointSticky(int index) {
- return false;
- }
-
- @Override
- public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
- return VisibilityPolicy.NEVER;
- }
-
- @Override
- public Point2D getControlPoint(int index) {
- return point;
- }
-
- @Override
- public void setControlPoint(Point2D point, int index) {
- this.point.setLocation(point);
- }
-
- @EditableProperty(name = "Color")
- public Color getColor() {
- return color;
- }
-
- public void setColor(Color color) {
- this.color = color;
- }
-
- @Override
- public Void getValue() {
- return null;
- }
-
- @Override
- public void setValue(Void value) {}
-
- @Override
- public String getControlPointNodeName(int index) {
- return null;
- }
-}
+/*
+ *
+ * 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
+ * .
+ */
+package org.diylc.components.connectivity;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Graphics2D;
+import java.awt.geom.Point2D;
+
+import org.diylc.common.ObjectCache;
+import org.diylc.common.OrientationHV;
+import org.diylc.components.AbstractTransparentComponent;
+import org.diylc.components.transform.SimpleComponentTransformer;
+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;
+
+@ComponentDescriptor(name = "Cut Line", category = "Connectivity", author = "Branislav Stojkovic",
+ description = "Cut line", instanceNamePrefix = "CL", zOrder = IDIYComponent.COMPONENT,
+ bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false, transformer = SimpleComponentTransformer.class)
+public class CutLine extends AbstractTransparentComponent {
+
+ private static final long serialVersionUID = 1L;
+
+ public static Size WIDTH = new Size(0.125d, SizeUnit.in);
+ public static Size LENGTH = new Size(3.125d, SizeUnit.in);
+ public static Color COLOR = Color.black;
+
+ private Size width = WIDTH;
+ private Size length = LENGTH;
+ private Color color = COLOR;
+ private Point2D.Double point = new Point2D.Double(0, 0);
+ private OrientationHV orientation = OrientationHV.VERTICAL;
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ int w = getClosestOdd((int) getWidth().convertToPixels());
+ int l = getClosestOdd((int) getLength().convertToPixels());
+ g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : color);
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(w));
+
+ Composite oldComposite = applyAlpha(g2d, componentState);
+
+ if (getOrientation() == OrientationHV.HORIZONTAL)
+ g2d.drawLine((int)point.getX(), (int)point.getY(), (int)point.getX() + l, (int)point.getY());
+ else
+ g2d.drawLine((int)point.getX(), (int)point.getY(), (int)point.getX(), (int)point.getY() + l);
+
+ g2d.setComposite(oldComposite);
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(2));
+ g2d.setColor(COLOR);
+ g2d.drawLine(width / 2, height - 2, width / 2, 1);
+ }
+
+ @EditableProperty
+ public Size getWidth() {
+ return width;
+ }
+
+ public void setWidth(Size width) {
+ this.width = width;
+ }
+
+ @EditableProperty
+ public Size getLength() {
+ return length;
+ }
+
+ public void setLength(Size length) {
+ this.length = length;
+ }
+
+ @EditableProperty
+ public OrientationHV getOrientation() {
+ return orientation;
+ }
+
+ public void setOrientation(OrientationHV orientation) {
+ this.orientation = orientation;
+ }
+
+ @Override
+ public String getName() {
+ return super.getName();
+ }
+
+ @Override
+ public int getControlPointCount() {
+ return 1;
+ }
+
+ @Override
+ public boolean isControlPointSticky(int index) {
+ return false;
+ }
+
+ @Override
+ public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
+ return VisibilityPolicy.NEVER;
+ }
+
+ @Override
+ public Point2D getControlPoint(int index) {
+ return point;
+ }
+
+ @Override
+ public void setControlPoint(Point2D point, int index) {
+ this.point.setLocation(point);
+ }
+
+ @EditableProperty(name = "Color")
+ public Color getColor() {
+ return color;
+ }
+
+ public void setColor(Color color) {
+ this.color = color;
+ }
+
+ @Override
+ public Void getValue() {
+ return null;
+ }
+
+ @Override
+ public void setValue(Void value) {}
+
+ @Override
+ public String getControlPointNodeName(int index) {
+ return null;
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Eyelet.java b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Eyelet.java
index e7fdd111b..253f0bccb 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Eyelet.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Eyelet.java
@@ -1,189 +1,186 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.connectivity;
-
-import java.awt.*;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-
-import org.diylc.common.ObjectCache;
-import org.diylc.components.AbstractComponent;
-import org.diylc.components.AbstractTransparentComponent;
-import org.diylc.components.transform.SimpleComponentTransformer;
-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.annotations.PositiveMeasureValidator;
-import org.diylc.core.annotations.PositiveNonZeroMeasureValidator;
-import org.diylc.core.measures.Size;
-import org.diylc.core.measures.SizeUnit;
-import org.diylc.utils.Constants;
-
-@ComponentDescriptor(name = "Eyelet", category = "Connectivity", author = "Branislav Stojkovic",
- description = "Eyelet or turret terminal", instanceNamePrefix = "Eyelet",
- zOrder = IDIYComponent.TRACE + 0.1, bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, autoEdit = false,
- keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, transformer = SimpleComponentTransformer.class,
- enableCache = true)
-public class Eyelet extends AbstractTransparentComponent {
-
- private static final long serialVersionUID = 1L;
-
- public static Size SIZE = new Size(0.2d, SizeUnit.in);
- public static Size HOLE_SIZE = new Size(0.1d, SizeUnit.in);
- public static Color COLOR = Color.decode("#C3E4ED");
-
- private Size size = SIZE;
- private Size holeSize = HOLE_SIZE;
- private Color color = COLOR;
- private Point2D.Double point = new Point2D.Double(0, 0);
- private String value = "";
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- if (checkPointsClipped(g2d.getClip())) {
- return;
- }
- int diameter = getClosestOdd((int) size.convertToPixels());
- int holeDiameter = getClosestOdd((int) holeSize.convertToPixels());
-
- Composite oldComposite = g2d.getComposite();
- if (getAlpha() < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * getAlpha() / MAX_ALPHA));
- }
-
- 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);
- 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.setColor(Constants.CANVAS_COLOR);
- g2d.fillOval((int)(point.getX() - holeDiameter / 2), (int)(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.setComposite(oldComposite);
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int diameter = getClosestOdd(width / 2);
- int holeDiameter = 5;
- g2d.setColor(COLOR);
- g2d.fillOval((width - diameter) / 2, (height - diameter) / 2, diameter, diameter);
- g2d.setColor(COLOR.darker());
- g2d.drawOval((width - diameter) / 2, (height - diameter) / 2, diameter, diameter);
- g2d.setColor(Constants.CANVAS_COLOR);
- g2d.fillOval((width - holeDiameter) / 2, (height - holeDiameter) / 2, holeDiameter, holeDiameter);
- g2d.setColor(COLOR.darker());
- g2d.drawOval((width - holeDiameter) / 2, (height - holeDiameter) / 2, holeDiameter, holeDiameter);
- }
-
- @EditableProperty(validatorClass = PositiveNonZeroMeasureValidator.class)
- public Size getSize() {
- return size;
- }
-
- public void setSize(Size size) {
- this.size = size;
- }
-
- @EditableProperty(name = "Hole Size", validatorClass = PositiveMeasureValidator.class)
- public Size getHoleSize() {
- return holeSize;
- }
-
- public void setHoleSize(Size holeSize) {
- this.holeSize = holeSize;
- }
-
- @Override
- public String getName() {
- return super.getName();
- }
-
- @Override
- public int getControlPointCount() {
- return 1;
- }
-
- @Override
- public boolean isControlPointSticky(int index) {
- return true;
- }
-
- @Override
- public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
- return VisibilityPolicy.NEVER;
- }
-
- @Override
- public Point2D getControlPoint(int index) {
- return point;
- }
-
- @Override
- public void setControlPoint(Point2D point, int index) {
- this.point.setLocation(point);
- }
-
- @EditableProperty(name = "Color")
- public Color getColor() {
- return color;
- }
-
- public void setColor(Color color) {
- this.color = color;
- }
-
- @Override
- @EditableProperty
- public String getValue() {
- return value;
- }
-
- @Override
- public void setValue(String value) {
- this.value = value;
- }
-
- @Override
- public String getControlPointNodeName(int index) {
- return null;
- }
-
- @Override
- public Rectangle2D getCachingBounds() {
- double size = getSize().convertToPixels();
- return new Rectangle2D.Double(point.getX() - size, point.getY() - size, size * 2, size * 2);
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.connectivity;
+
+import java.awt.*;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+import org.diylc.common.ObjectCache;
+import org.diylc.components.AbstractComponent;
+import org.diylc.components.AbstractTransparentComponent;
+import org.diylc.components.transform.SimpleComponentTransformer;
+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.annotations.PositiveMeasureValidator;
+import org.diylc.core.annotations.PositiveNonZeroMeasureValidator;
+import org.diylc.core.measures.Size;
+import org.diylc.core.measures.SizeUnit;
+import org.diylc.utils.Constants;
+
+@ComponentDescriptor(name = "Eyelet", category = "Connectivity", author = "Branislav Stojkovic",
+ description = "Eyelet or turret terminal", instanceNamePrefix = "Eyelet",
+ zOrder = IDIYComponent.TRACE + 0.1, bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, autoEdit = false,
+ keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, transformer = SimpleComponentTransformer.class,
+ enableCache = true)
+public class Eyelet extends AbstractTransparentComponent {
+
+ private static final long serialVersionUID = 1L;
+
+ public static Size SIZE = new Size(0.2d, SizeUnit.in);
+ public static Size HOLE_SIZE = new Size(0.1d, SizeUnit.in);
+ public static Color COLOR = Color.decode("#C3E4ED");
+
+ private Size size = SIZE;
+ private Size holeSize = HOLE_SIZE;
+ private Color color = COLOR;
+ private Point2D.Double point = new Point2D.Double(0, 0);
+ private String value = "";
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ if (checkPointsClipped(g2d.getClip())) {
+ return;
+ }
+ int diameter = getClosestOdd((int) size.convertToPixels());
+ int holeDiameter = getClosestOdd((int) holeSize.convertToPixels());
+
+ Composite oldComposite = applyAlpha(g2d, componentState);
+
+ 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);
+ 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.setColor(Constants.CANVAS_COLOR);
+ g2d.fillOval((int)(point.getX() - holeDiameter / 2), (int)(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.setComposite(oldComposite);
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int diameter = getClosestOdd(width / 2);
+ int holeDiameter = 5;
+ g2d.setColor(COLOR);
+ g2d.fillOval((width - diameter) / 2, (height - diameter) / 2, diameter, diameter);
+ g2d.setColor(COLOR.darker());
+ g2d.drawOval((width - diameter) / 2, (height - diameter) / 2, diameter, diameter);
+ g2d.setColor(Constants.CANVAS_COLOR);
+ g2d.fillOval((width - holeDiameter) / 2, (height - holeDiameter) / 2, holeDiameter, holeDiameter);
+ g2d.setColor(COLOR.darker());
+ g2d.drawOval((width - holeDiameter) / 2, (height - holeDiameter) / 2, holeDiameter, holeDiameter);
+ }
+
+ @EditableProperty(validatorClass = PositiveNonZeroMeasureValidator.class)
+ public Size getSize() {
+ return size;
+ }
+
+ public void setSize(Size size) {
+ this.size = size;
+ }
+
+ @EditableProperty(name = "Hole Size", validatorClass = PositiveMeasureValidator.class)
+ public Size getHoleSize() {
+ return holeSize;
+ }
+
+ public void setHoleSize(Size holeSize) {
+ this.holeSize = holeSize;
+ }
+
+ @Override
+ public String getName() {
+ return super.getName();
+ }
+
+ @Override
+ public int getControlPointCount() {
+ return 1;
+ }
+
+ @Override
+ public boolean isControlPointSticky(int index) {
+ return true;
+ }
+
+ @Override
+ public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
+ return VisibilityPolicy.NEVER;
+ }
+
+ @Override
+ public Point2D getControlPoint(int index) {
+ return point;
+ }
+
+ @Override
+ public void setControlPoint(Point2D point, int index) {
+ this.point.setLocation(point);
+ }
+
+ @EditableProperty(name = "Color")
+ public Color getColor() {
+ return color;
+ }
+
+ public void setColor(Color color) {
+ this.color = color;
+ }
+
+ @Override
+ @EditableProperty
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String getControlPointNodeName(int index) {
+ return null;
+ }
+
+ @Override
+ public Rectangle2D getCachingBounds() {
+ double size = getSize().convertToPixels();
+ return new Rectangle2D.Double(point.getX() - size, point.getY() - size, size * 2, size * 2);
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/GroundFill.java b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/GroundFill.java
index 49fdb1d31..b0f6eb24d 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/GroundFill.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/GroundFill.java
@@ -1,223 +1,220 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.connectivity;
-
-import java.awt.*;
-import java.awt.geom.Point2D;
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.Set;
-
-import com.bancika.gerberwriter.GerberFunctions;
-
-import org.diylc.common.ObjectCache;
-import org.diylc.common.PCBLayer;
-import org.diylc.components.AbstractComponent;
-import org.diylc.components.AbstractTransparentComponent;
-import org.diylc.components.transform.SimpleComponentTransformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.ILayeredComponent;
-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.gerber.GerberLayer;
-import org.diylc.core.gerber.GerberRenderMode;
-import org.diylc.core.gerber.IGerberComponentSimple;
-import org.diylc.core.measures.Size;
-import org.diylc.core.measures.SizeUnit;
-
-@ComponentDescriptor(name = "Ground Fill", author = "Branislav Stojkovic", category = "Connectivity",
- instanceNamePrefix = "GF", description = "Polygonal ground fill area", zOrder = IDIYComponent.TRACE,
- bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false, transformer = SimpleComponentTransformer.class)
-public class GroundFill extends AbstractTransparentComponent
- implements ILayeredComponent, IGerberComponentSimple {
-
- private static final long serialVersionUID = 1L;
-
- public static Color COLOR = Color.black;
- public static Size DEFAULT_WIDTH = new Size(1.5d, SizeUnit.in);
- public static Size DEFAULT_HEIGHT = new Size(1.2d, SizeUnit.in);
-
- protected Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0), new Point2D.Double(0, (int) DEFAULT_HEIGHT.convertToPixels()),
- new Point2D.Double((int) DEFAULT_WIDTH.convertToPixels(), (int) DEFAULT_HEIGHT.convertToPixels()),
- new Point2D.Double((int) DEFAULT_WIDTH.convertToPixels(), 0)};
-
- protected Color color = COLOR;
- protected PointCount pointCount = PointCount._4;
- private PCBLayer layer = PCBLayer._1;
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode,
- Project project, IDrawingObserver drawingObserver) {
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
- Color fillColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : color;
- g2d.setColor(fillColor);
- int[] xPoints = new int[controlPoints.length];
- int[] yPoints = new int[controlPoints.length];
- for (int i = 0; i < controlPoints.length; i++) {
- xPoints[i] = (int)controlPoints[i].getX();
- yPoints[i] = (int)controlPoints[i].getY();
- }
- drawingObserver.startTrackingContinuityArea(true);
- Composite oldComposite = g2d.getComposite();
- if (getAlpha() < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * getAlpha() / MAX_ALPHA));
- }
- g2d.fillPolygon(xPoints, yPoints, controlPoints.length);
- g2d.setComposite(oldComposite);
- drawingObserver.stopTrackingContinuityArea();
- // Do not track any changes that follow because the whole board has been
- // tracked so far.
- drawingObserver.stopTracking();
- }
-
- @EditableProperty(name = "Color")
- public Color getColor() {
- return color;
- }
-
- public void setColor(Color color) {
- this.color = color;
- }
-
- @Override
- public int getControlPointCount() {
- return controlPoints.length;
- }
-
- @Override
- public Point2D getControlPoint(int index) {
- return controlPoints[index];
- }
-
- @Override
- public boolean isControlPointSticky(int index) {
- return false;
- }
-
- @Override
- public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
- return VisibilityPolicy.WHEN_SELECTED;
- }
-
- @Override
- public void setControlPoint(Point2D point, int index) {
- controlPoints[index].setLocation(point);
- }
-
- @EditableProperty(name = "Edges")
- public PointCount getPointCount() {
- return pointCount;
- }
-
- public void setPointCount(PointCount pointCount) {
- if (this.pointCount == pointCount)
- return;
- int oldPointCount = Integer.parseInt(this.pointCount.toString());
- int newPointCount = Integer.parseInt(pointCount.toString());
- this.controlPoints = Arrays.copyOf(this.controlPoints, newPointCount);
- if (oldPointCount < newPointCount) {
- this.controlPoints[newPointCount - 1] = this.controlPoints[oldPointCount - 1];
- for (int i = oldPointCount - 1; i < newPointCount - 1; i++) {
- this.controlPoints[i] =
- new Point2D.Double((this.controlPoints[i - 1].getX() + this.controlPoints[newPointCount - 1].getX()) / 2,
- (this.controlPoints[i - 1].getY() + this.controlPoints[newPointCount - 1].getY()) / 2);
- }
- }
- this.pointCount = pointCount;
- }
-
- @EditableProperty
- public PCBLayer getLayer() {
- if (layer == null) {
- layer = PCBLayer._1;
- }
- return layer;
- }
-
- public void setLayer(PCBLayer layer) {
- this.layer = layer;
- }
-
- @Override
- public int getLayerId() {
- return getLayer().getId();
- }
-
- @Deprecated
- @Override
- public Void getValue() {
- return null;
- }
-
- @Deprecated
- @Override
- public void setValue(Void value) {}
-
- @Override
- public String getControlPointNodeName(int index) {
- return null;
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int factor = 32 / width;
- g2d.setColor(COLOR);
- int[] x = {2 / factor, width - 2 / factor, width - 4 / factor, 3 / factor};
- int[] y = {4 / factor, 2 / factor, height - 5 / factor, height - 2 / factor};
- g2d.fillPolygon(x, y, 4);
- }
-
- public enum PointCount {
- _3, _4, _5, _6, _7, _8;
-
- public String toString() {
- return name().substring(1);
- };
- }
-
- @Override
- public Set getGerberRenderModes() {
- return EnumSet.of(GerberRenderMode.Normal);
- }
-
- @Override
- public GerberLayer getGerberLayer() {
- return getLayer().toGerberCopperLayer();
- }
-
- @Override
- public String getGerberFunction() {
- return GerberFunctions.CONDUCTOR;
- }
-
- @Override
- public boolean isGerberNegative() {
- return false;
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.connectivity;
+
+import java.awt.*;
+import java.awt.geom.Point2D;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.Set;
+
+import com.bancika.gerberwriter.GerberFunctions;
+
+import org.diylc.common.ObjectCache;
+import org.diylc.common.PCBLayer;
+import org.diylc.components.AbstractComponent;
+import org.diylc.components.AbstractTransparentComponent;
+import org.diylc.components.transform.SimpleComponentTransformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.ILayeredComponent;
+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.gerber.GerberLayer;
+import org.diylc.core.gerber.GerberRenderMode;
+import org.diylc.core.gerber.IGerberComponentSimple;
+import org.diylc.core.measures.Size;
+import org.diylc.core.measures.SizeUnit;
+
+@ComponentDescriptor(name = "Ground Fill", author = "Branislav Stojkovic", category = "Connectivity",
+ instanceNamePrefix = "GF", description = "Polygonal ground fill area", zOrder = IDIYComponent.TRACE,
+ bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false, transformer = SimpleComponentTransformer.class)
+public class GroundFill extends AbstractTransparentComponent
+ implements ILayeredComponent, IGerberComponentSimple {
+
+ private static final long serialVersionUID = 1L;
+
+ public static Color COLOR = Color.black;
+ public static Size DEFAULT_WIDTH = new Size(1.5d, SizeUnit.in);
+ public static Size DEFAULT_HEIGHT = new Size(1.2d, SizeUnit.in);
+
+ protected Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0), new Point2D.Double(0, (int) DEFAULT_HEIGHT.convertToPixels()),
+ new Point2D.Double((int) DEFAULT_WIDTH.convertToPixels(), (int) DEFAULT_HEIGHT.convertToPixels()),
+ new Point2D.Double((int) DEFAULT_WIDTH.convertToPixels(), 0)};
+
+ protected Color color = COLOR;
+ protected PointCount pointCount = PointCount._4;
+ private PCBLayer layer = PCBLayer._1;
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode,
+ Project project, IDrawingObserver drawingObserver) {
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+ Color fillColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : color;
+ g2d.setColor(fillColor);
+ int[] xPoints = new int[controlPoints.length];
+ int[] yPoints = new int[controlPoints.length];
+ for (int i = 0; i < controlPoints.length; i++) {
+ xPoints[i] = (int)controlPoints[i].getX();
+ yPoints[i] = (int)controlPoints[i].getY();
+ }
+ drawingObserver.startTrackingContinuityArea(true);
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.fillPolygon(xPoints, yPoints, controlPoints.length);
+ g2d.setComposite(oldComposite);
+ drawingObserver.stopTrackingContinuityArea();
+ // Do not track any changes that follow because the whole board has been
+ // tracked so far.
+ drawingObserver.stopTracking();
+ }
+
+ @EditableProperty(name = "Color")
+ public Color getColor() {
+ return color;
+ }
+
+ public void setColor(Color color) {
+ this.color = color;
+ }
+
+ @Override
+ public int getControlPointCount() {
+ return controlPoints.length;
+ }
+
+ @Override
+ public Point2D getControlPoint(int index) {
+ return controlPoints[index];
+ }
+
+ @Override
+ public boolean isControlPointSticky(int index) {
+ return false;
+ }
+
+ @Override
+ public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
+ return VisibilityPolicy.WHEN_SELECTED;
+ }
+
+ @Override
+ public void setControlPoint(Point2D point, int index) {
+ controlPoints[index].setLocation(point);
+ }
+
+ @EditableProperty(name = "Edges")
+ public PointCount getPointCount() {
+ return pointCount;
+ }
+
+ public void setPointCount(PointCount pointCount) {
+ if (this.pointCount == pointCount)
+ return;
+ int oldPointCount = Integer.parseInt(this.pointCount.toString());
+ int newPointCount = Integer.parseInt(pointCount.toString());
+ this.controlPoints = Arrays.copyOf(this.controlPoints, newPointCount);
+ if (oldPointCount < newPointCount) {
+ this.controlPoints[newPointCount - 1] = this.controlPoints[oldPointCount - 1];
+ for (int i = oldPointCount - 1; i < newPointCount - 1; i++) {
+ this.controlPoints[i] =
+ new Point2D.Double((this.controlPoints[i - 1].getX() + this.controlPoints[newPointCount - 1].getX()) / 2,
+ (this.controlPoints[i - 1].getY() + this.controlPoints[newPointCount - 1].getY()) / 2);
+ }
+ }
+ this.pointCount = pointCount;
+ }
+
+ @EditableProperty
+ public PCBLayer getLayer() {
+ if (layer == null) {
+ layer = PCBLayer._1;
+ }
+ return layer;
+ }
+
+ public void setLayer(PCBLayer layer) {
+ this.layer = layer;
+ }
+
+ @Override
+ public int getLayerId() {
+ return getLayer().getId();
+ }
+
+ @Deprecated
+ @Override
+ public Void getValue() {
+ return null;
+ }
+
+ @Deprecated
+ @Override
+ public void setValue(Void value) {}
+
+ @Override
+ public String getControlPointNodeName(int index) {
+ return null;
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int factor = 32 / width;
+ g2d.setColor(COLOR);
+ int[] x = {2 / factor, width - 2 / factor, width - 4 / factor, 3 / factor};
+ int[] y = {4 / factor, 2 / factor, height - 5 / factor, height - 2 / factor};
+ g2d.fillPolygon(x, y, 4);
+ }
+
+ public enum PointCount {
+ _3, _4, _5, _6, _7, _8;
+
+ public String toString() {
+ return name().substring(1);
+ };
+ }
+
+ @Override
+ public Set getGerberRenderModes() {
+ return EnumSet.of(GerberRenderMode.Normal);
+ }
+
+ @Override
+ public GerberLayer getGerberLayer() {
+ return getLayer().toGerberCopperLayer();
+ }
+
+ @Override
+ public String getGerberFunction() {
+ return GerberFunctions.CONDUCTOR;
+ }
+
+ @Override
+ public boolean isGerberNegative() {
+ return false;
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/MultimeterProbe.java b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/MultimeterProbe.java
index db68a6b0d..0d4dfd2b1 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/MultimeterProbe.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/MultimeterProbe.java
@@ -32,6 +32,7 @@ import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.common.IPlugInPort;
import org.diylc.common.ObjectCache;
import org.diylc.common.Orientation45;
+import org.diylc.common.Percentage;
import org.diylc.components.AbstractTransparentComponent;
import org.diylc.components.transform.SimpleComponentTransformer;
import org.diylc.core.*;
@@ -67,7 +68,7 @@ public class MultimeterProbe extends AbstractTransparentComponent {
private transient Shape[] body = null;
public MultimeterProbe() {
- this.alpha = (byte) (MAX_ALPHA / 2);
+ this.alphaPercent = new Percentage(50);
}
@Override
@@ -85,11 +86,7 @@ public class MultimeterProbe extends AbstractTransparentComponent {
(int) (sensitivity * 2), (int) (sensitivity * 2));
drawingObserver.stopTrackingContinuityArea();
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(
- AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : PROBE_COLOR);
g2d.fill(shapes[0]);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : handleColor);
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/PCBTerminalBlock.java b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/PCBTerminalBlock.java
index 06301310a..34d19888c 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/PCBTerminalBlock.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/PCBTerminalBlock.java
@@ -206,11 +206,7 @@ public class PCBTerminalBlock extends AbstractTransparentComponent {
Shape[] body = getBody();
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : BASE_COLOR);
g2d.fill(body[0]);
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/SolderPad.java b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/SolderPad.java
index 93fdae945..42cdf6a9e 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/SolderPad.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/SolderPad.java
@@ -91,10 +91,7 @@ public class SolderPad extends AbstractTransparentComponent
gerberDrawingObserver.startGerberOutput(gerberCopperLayer, GerberFunctions.CONNECTOR_PAD, false);
gerberDrawingObserver.startGerberOutput(org.diylc.core.gerber.GerberLayer.SolderMaskBot, "Material", false);
}
- Composite oldComposite = g2d.getComposite();
- if (getAlpha() < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * getAlpha() / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
if (type == Type.ROUND) {
g2d.fill(new Ellipse2D.Double(point.getX() - diameter / 2, point.getY() - diameter / 2,
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/TraceCut.java b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/TraceCut.java
index 53aa737d0..a020216b1 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/TraceCut.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/TraceCut.java
@@ -1,268 +1,265 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.connectivity;
-
-import java.awt.*;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-
-import org.diylc.common.ObjectCache;
-import org.diylc.common.OrientationHV;
-import org.diylc.components.AbstractComponent;
-import org.diylc.components.AbstractTransparentComponent;
-import org.diylc.components.boards.AbstractBoard;
-import org.diylc.components.boards.VeroBoard;
-import org.diylc.components.transform.SimpleComponentTransformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.ILayeredComponent;
-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.Constants;
-
-@ComponentDescriptor(name = "Trace Cut", category = "Connectivity", author = "Branislav Stojkovic",
- description = "Designates the place where a trace on the vero board needs to be cut", instanceNamePrefix = "Cut",
- zOrder = IDIYComponent.BOARD + 1, bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false,
- transformer = SimpleComponentTransformer.class, enableCache = true)
-public class TraceCut extends AbstractTransparentComponent implements ILayeredComponent {
-
- private static final long serialVersionUID = 1L;
-
- public static Size SIZE = new Size(0.08d, SizeUnit.in);
- public static Size CUT_WIDTH = new Size(0.5d, SizeUnit.mm);
- public static Color FILL_COLOR = Color.white;
- public static Color BORDER_COLOR = Color.red;
- public static Color SELECTION_COLOR = Color.red;
- public static Size HOLE_SIZE = new Size(0.7d, SizeUnit.mm);
-
- private Size size = SIZE;
- @SuppressWarnings("unused")
- @Deprecated
- private Color fillColor = FILL_COLOR;
- @Deprecated
- private Color borderColor = BORDER_COLOR;
- private Color boardColor = AbstractBoard.PHENOLIC_COLOR;
- private Boolean cutBetweenHoles = false;
- private OrientationHV orientation = OrientationHV.VERTICAL;
- private Size holeSpacing = VeroBoard.SPACING;
-
- protected Point2D.Double point = new Point2D.Double(0, 0);
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- if (checkPointsClipped(g2d.getClip())) {
- return;
- }
- Composite oldComposite = g2d.getComposite();
- if (getAlpha() < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * getAlpha() / MAX_ALPHA));
- }
- g2d.setStroke(ObjectCache.getInstance().fetchZoomableStroke(1f));
- int size = getClosestOdd((int) this.size.convertToPixels());
- int cutWidth = getClosestOdd((int) CUT_WIDTH.convertToPixels());
- if (getCutBetweenHoles()) {
- int holeSpacing = getClosestOdd(getHoleSpacing().convertToPixels());
- g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : 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);
- else
- g2d.fillRect((int)(point.getX() - size / 2 - 1), (int)(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);
- 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.setColor(getBoardColor().darker());
- g2d.drawOval((int)(point.getX() - holeSize / 2), (int)(point.getY() - holeSize / 2), holeSize, holeSize);
- }
- g2d.setComposite(oldComposite);
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int factor = 32 / width;
- g2d.setColor(AbstractBoard.PHENOLIC_COLOR);
- g2d.fillRect(0, 2 / factor, width - 1, height - 4 / factor);
- g2d.setColor(AbstractBoard.BORDER_COLOR);
- g2d.drawRect(0, 2 / factor, width - 1, height - 4 / factor);
- g2d.setColor(COPPER_COLOR);
- g2d.fillRect(1 / factor, width / 3, width - 2 / factor, getClosestOdd(width / 3) + 1);
- g2d.setColor(COPPER_COLOR.darker());
- g2d.drawRect(1 / factor, width / 3, width - 2 / factor, getClosestOdd(width / 3) + 1);
-
- g2d.setColor(AbstractBoard.PHENOLIC_COLOR);
- g2d.fillRoundRect(width / 3, width / 3, getClosestOdd(width / 3) + 2, getClosestOdd(width / 3) + 2, width / 3,
- width / 3);
-
- g2d.setColor(COPPER_COLOR);
- g2d.fillRect(1 / factor, 2 / factor, width - 2 / factor, 4 / factor);
- g2d.fillRect(1 / factor, height - 6 / factor, width - 2 / factor, 4 / factor);
- g2d.setColor(COPPER_COLOR.darker());
- g2d.drawRect(1 / factor, 2 / factor, width - 2 / factor, 4 / factor);
- g2d.drawRect(1 / factor, height - 6 / factor, width - 2 / factor, 4 / factor);
-
- g2d.setColor(Constants.CANVAS_COLOR);
- g2d.fillOval(width / 6 - 1, width / 2 - 1, getClosestOdd(3.0 / factor), getClosestOdd(3.0 / factor));
- g2d.fillOval(width / 2 - 1, width / 2 - 1, getClosestOdd(3.0 / factor), getClosestOdd(3.0 / factor));
- g2d.fillOval(5 * width / 6 - 1, width / 2 - 1, getClosestOdd(3.0 / factor), getClosestOdd(3.0 / factor));
- g2d.setColor(COPPER_COLOR.darker());
- g2d.drawOval(width / 6 - 1, width / 2 - 1, getClosestOdd(3.0 / factor), getClosestOdd(3.0 / factor));
- g2d.drawOval(width / 2 - 1, width / 2 - 1, getClosestOdd(3.0 / factor), getClosestOdd(3.0 / factor));
- g2d.drawOval(5 * width / 6 - 1, width / 2 - 1, getClosestOdd(3.0 / factor), getClosestOdd(3.0 / factor));
- }
-
- @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);
- }
-
- @Override
- public Void getValue() {
- return null;
- }
-
- @Override
- public void setValue(Void value) {}
-
- @EditableProperty
- public Size getSize() {
- return size;
- }
-
- public void setSize(Size size) {
- this.size = size;
- }
-
- @Deprecated
- public Color getBorderColor() {
- return borderColor;
- }
-
- @Deprecated
- public void setBorderColor(Color borderColor) {
- this.borderColor = borderColor;
- }
-
- @EditableProperty(name = "Cut Between Holes")
- public boolean getCutBetweenHoles() {
- if (cutBetweenHoles == null) {
- cutBetweenHoles = false;
- }
- return cutBetweenHoles;
- }
-
- public void setCutBetweenHoles(boolean cutBetweenHoles) {
- this.cutBetweenHoles = cutBetweenHoles;
- }
-
- @EditableProperty(name = "Board")
- public Color getBoardColor() {
- if (boardColor == null) {
- boardColor = AbstractBoard.PHENOLIC_COLOR;
- }
- return boardColor;
- }
-
- public void setBoardColor(Color boardColor) {
- this.boardColor = boardColor;
- }
-
- @EditableProperty(name = "Hole Spacing")
- public Size getHoleSpacing() {
- if (holeSpacing == null) {
- holeSpacing = VeroBoard.SPACING;
- }
- return holeSpacing;
- }
-
- public void setHoleSpacing(Size holeSpacing) {
- this.holeSpacing = holeSpacing;
- }
-
- @EditableProperty(name = "Cut Orientation")
- public OrientationHV getOrientation() {
- if (orientation == null)
- orientation = OrientationHV.VERTICAL;
- return orientation;
- }
-
- public void setOrientation(OrientationHV orientation) {
- this.orientation = orientation;
- }
-
- @Deprecated
- @Override
- public String getName() {
- return super.getName();
- }
-
- @Override
- public String getControlPointNodeName(int index) {
- return null;
- }
-
- @Override
- public Rectangle2D getCachingBounds() {
- double size = getSize().convertToPixels();
- return new Rectangle2D.Double(point.getX() - size, point.getY() - size, size * 2, size * 2);
- }
-
- @Override
- public int getLayerId() {
- return 1;
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.connectivity;
+
+import java.awt.*;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+import org.diylc.common.ObjectCache;
+import org.diylc.common.OrientationHV;
+import org.diylc.components.AbstractComponent;
+import org.diylc.components.AbstractTransparentComponent;
+import org.diylc.components.boards.AbstractBoard;
+import org.diylc.components.boards.VeroBoard;
+import org.diylc.components.transform.SimpleComponentTransformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.ILayeredComponent;
+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.Constants;
+
+@ComponentDescriptor(name = "Trace Cut", category = "Connectivity", author = "Branislav Stojkovic",
+ description = "Designates the place where a trace on the vero board needs to be cut", instanceNamePrefix = "Cut",
+ zOrder = IDIYComponent.BOARD + 1, bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false,
+ transformer = SimpleComponentTransformer.class, enableCache = true)
+public class TraceCut extends AbstractTransparentComponent implements ILayeredComponent {
+
+ private static final long serialVersionUID = 1L;
+
+ public static Size SIZE = new Size(0.08d, SizeUnit.in);
+ public static Size CUT_WIDTH = new Size(0.5d, SizeUnit.mm);
+ public static Color FILL_COLOR = Color.white;
+ public static Color BORDER_COLOR = Color.red;
+ public static Color SELECTION_COLOR = Color.red;
+ public static Size HOLE_SIZE = new Size(0.7d, SizeUnit.mm);
+
+ private Size size = SIZE;
+ @SuppressWarnings("unused")
+ @Deprecated
+ private Color fillColor = FILL_COLOR;
+ @Deprecated
+ private Color borderColor = BORDER_COLOR;
+ private Color boardColor = AbstractBoard.PHENOLIC_COLOR;
+ private Boolean cutBetweenHoles = false;
+ private OrientationHV orientation = OrientationHV.VERTICAL;
+ private Size holeSpacing = VeroBoard.SPACING;
+
+ protected Point2D.Double point = new Point2D.Double(0, 0);
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ if (checkPointsClipped(g2d.getClip())) {
+ return;
+ }
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.setStroke(ObjectCache.getInstance().fetchZoomableStroke(1f));
+ int size = getClosestOdd((int) this.size.convertToPixels());
+ int cutWidth = getClosestOdd((int) CUT_WIDTH.convertToPixels());
+ if (getCutBetweenHoles()) {
+ int holeSpacing = getClosestOdd(getHoleSpacing().convertToPixels());
+ g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : 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);
+ else
+ g2d.fillRect((int)(point.getX() - size / 2 - 1), (int)(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);
+ 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.setColor(getBoardColor().darker());
+ g2d.drawOval((int)(point.getX() - holeSize / 2), (int)(point.getY() - holeSize / 2), holeSize, holeSize);
+ }
+ g2d.setComposite(oldComposite);
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int factor = 32 / width;
+ g2d.setColor(AbstractBoard.PHENOLIC_COLOR);
+ g2d.fillRect(0, 2 / factor, width - 1, height - 4 / factor);
+ g2d.setColor(AbstractBoard.BORDER_COLOR);
+ g2d.drawRect(0, 2 / factor, width - 1, height - 4 / factor);
+ g2d.setColor(COPPER_COLOR);
+ g2d.fillRect(1 / factor, width / 3, width - 2 / factor, getClosestOdd(width / 3) + 1);
+ g2d.setColor(COPPER_COLOR.darker());
+ g2d.drawRect(1 / factor, width / 3, width - 2 / factor, getClosestOdd(width / 3) + 1);
+
+ g2d.setColor(AbstractBoard.PHENOLIC_COLOR);
+ g2d.fillRoundRect(width / 3, width / 3, getClosestOdd(width / 3) + 2, getClosestOdd(width / 3) + 2, width / 3,
+ width / 3);
+
+ g2d.setColor(COPPER_COLOR);
+ g2d.fillRect(1 / factor, 2 / factor, width - 2 / factor, 4 / factor);
+ g2d.fillRect(1 / factor, height - 6 / factor, width - 2 / factor, 4 / factor);
+ g2d.setColor(COPPER_COLOR.darker());
+ g2d.drawRect(1 / factor, 2 / factor, width - 2 / factor, 4 / factor);
+ g2d.drawRect(1 / factor, height - 6 / factor, width - 2 / factor, 4 / factor);
+
+ g2d.setColor(Constants.CANVAS_COLOR);
+ g2d.fillOval(width / 6 - 1, width / 2 - 1, getClosestOdd(3.0 / factor), getClosestOdd(3.0 / factor));
+ g2d.fillOval(width / 2 - 1, width / 2 - 1, getClosestOdd(3.0 / factor), getClosestOdd(3.0 / factor));
+ g2d.fillOval(5 * width / 6 - 1, width / 2 - 1, getClosestOdd(3.0 / factor), getClosestOdd(3.0 / factor));
+ g2d.setColor(COPPER_COLOR.darker());
+ g2d.drawOval(width / 6 - 1, width / 2 - 1, getClosestOdd(3.0 / factor), getClosestOdd(3.0 / factor));
+ g2d.drawOval(width / 2 - 1, width / 2 - 1, getClosestOdd(3.0 / factor), getClosestOdd(3.0 / factor));
+ g2d.drawOval(5 * width / 6 - 1, width / 2 - 1, getClosestOdd(3.0 / factor), getClosestOdd(3.0 / factor));
+ }
+
+ @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);
+ }
+
+ @Override
+ public Void getValue() {
+ return null;
+ }
+
+ @Override
+ public void setValue(Void value) {}
+
+ @EditableProperty
+ public Size getSize() {
+ return size;
+ }
+
+ public void setSize(Size size) {
+ this.size = size;
+ }
+
+ @Deprecated
+ public Color getBorderColor() {
+ return borderColor;
+ }
+
+ @Deprecated
+ public void setBorderColor(Color borderColor) {
+ this.borderColor = borderColor;
+ }
+
+ @EditableProperty(name = "Cut Between Holes")
+ public boolean getCutBetweenHoles() {
+ if (cutBetweenHoles == null) {
+ cutBetweenHoles = false;
+ }
+ return cutBetweenHoles;
+ }
+
+ public void setCutBetweenHoles(boolean cutBetweenHoles) {
+ this.cutBetweenHoles = cutBetweenHoles;
+ }
+
+ @EditableProperty(name = "Board")
+ public Color getBoardColor() {
+ if (boardColor == null) {
+ boardColor = AbstractBoard.PHENOLIC_COLOR;
+ }
+ return boardColor;
+ }
+
+ public void setBoardColor(Color boardColor) {
+ this.boardColor = boardColor;
+ }
+
+ @EditableProperty(name = "Hole Spacing")
+ public Size getHoleSpacing() {
+ if (holeSpacing == null) {
+ holeSpacing = VeroBoard.SPACING;
+ }
+ return holeSpacing;
+ }
+
+ public void setHoleSpacing(Size holeSpacing) {
+ this.holeSpacing = holeSpacing;
+ }
+
+ @EditableProperty(name = "Cut Orientation")
+ public OrientationHV getOrientation() {
+ if (orientation == null)
+ orientation = OrientationHV.VERTICAL;
+ return orientation;
+ }
+
+ public void setOrientation(OrientationHV orientation) {
+ this.orientation = orientation;
+ }
+
+ @Deprecated
+ @Override
+ public String getName() {
+ return super.getName();
+ }
+
+ @Override
+ public String getControlPointNodeName(int index) {
+ return null;
+ }
+
+ @Override
+ public Rectangle2D getCachingBounds() {
+ double size = getSize().convertToPixels();
+ return new Rectangle2D.Double(point.getX() - size, point.getY() - size, size * 2, size * 2);
+ }
+
+ @Override
+ public int getLayerId() {
+ return 1;
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Turret.java b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Turret.java
index a1849bbca..7ec2ea440 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Turret.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Turret.java
@@ -1,184 +1,181 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.connectivity;
-
-import java.awt.*;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-
-import org.diylc.common.ObjectCache;
-import org.diylc.components.AbstractComponent;
-import org.diylc.components.AbstractTransparentComponent;
-import org.diylc.components.transform.SimpleComponentTransformer;
-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;
-import org.diylc.utils.Constants;
-
-@ComponentDescriptor(name = "Turret Lug", category = "Connectivity", author = "Branislav Stojkovic",
- description = "Turret terminal lug", instanceNamePrefix = "Turret",
- zOrder = IDIYComponent.TRACE + 0.1, bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, autoEdit = false,
- keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, transformer = SimpleComponentTransformer.class,
- enableCache = true)
-public class Turret extends AbstractTransparentComponent {
-
- private static final long serialVersionUID = 1L;
-
- public static Size SIZE = new Size(0.16d, SizeUnit.in);
- public static Size HOLE_SIZE = new Size(0.0625d, SizeUnit.in);
- public static Color COLOR = Color.decode("#E0C04C");
-
- private Size size = SIZE;
- private Size holeSize = HOLE_SIZE;
- private Color color = COLOR;
- private Point2D.Double point = new Point2D.Double(0, 0);
- private String value = "";
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- if (checkPointsClipped(g2d.getClip())) {
- return;
- }
- Composite oldComposite = g2d.getComposite();
- if (getAlpha() < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * getAlpha() / MAX_ALPHA));
- }
- int diameter = getClosestOdd((int) size.convertToPixels());
- int holeDiameter = getClosestOdd((int) holeSize.convertToPixels());
- 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);
- 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.setColor(Constants.CANVAS_COLOR);
- g2d.fillOval((int)(point.getX() - holeDiameter / 2), (int)(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.setComposite(oldComposite);
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int diameter = getClosestOdd(width / 2);
- int holeDiameter = 5;
- g2d.setColor(COLOR);
- g2d.fillOval((width - diameter) / 2, (height - diameter) / 2, diameter, diameter);
- g2d.setColor(COLOR.darker());
- g2d.drawOval((width - diameter) / 2, (height - diameter) / 2, diameter, diameter);
- g2d.setColor(Constants.CANVAS_COLOR);
- g2d.fillOval((width - holeDiameter) / 2, (height - holeDiameter) / 2, holeDiameter, holeDiameter);
- g2d.setColor(COLOR.darker());
- g2d.drawOval((width - holeDiameter) / 2, (height - holeDiameter) / 2, holeDiameter, holeDiameter);
- }
-
- @EditableProperty
- public Size getSize() {
- return size;
- }
-
- public void setSize(Size size) {
- this.size = size;
- }
-
- @EditableProperty(name = "Hole Size")
- public Size getHoleSize() {
- return holeSize;
- }
-
- public void setHoleSize(Size holeSize) {
- this.holeSize = holeSize;
- }
-
- @Override
- public String getName() {
- return super.getName();
- }
-
- @Override
- public int getControlPointCount() {
- return 1;
- }
-
- @Override
- public boolean isControlPointSticky(int index) {
- return true;
- }
-
- @Override
- public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
- return VisibilityPolicy.NEVER;
- }
-
- @Override
- public Point2D getControlPoint(int index) {
- return point;
- }
-
- @Override
- public void setControlPoint(Point2D point, int index) {
- this.point.setLocation(point);
- }
-
- @EditableProperty(name = "Color")
- public Color getColor() {
- return color;
- }
-
- public void setColor(Color color) {
- this.color = color;
- }
-
- @Override
- @EditableProperty
- public String getValue() {
- return value;
- }
-
- @Override
- public void setValue(String value) {
- this.value = value;
- }
-
- @Override
- public String getControlPointNodeName(int index) {
- return null;
- }
-
- @Override
- public Rectangle2D getCachingBounds() {
- double size = getSize().convertToPixels();
- return new Rectangle2D.Double(point.getX() - size, point.getY() - size, size * 2, size * 2);
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.connectivity;
+
+import java.awt.*;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+import org.diylc.common.ObjectCache;
+import org.diylc.components.AbstractComponent;
+import org.diylc.components.AbstractTransparentComponent;
+import org.diylc.components.transform.SimpleComponentTransformer;
+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;
+import org.diylc.utils.Constants;
+
+@ComponentDescriptor(name = "Turret Lug", category = "Connectivity", author = "Branislav Stojkovic",
+ description = "Turret terminal lug", instanceNamePrefix = "Turret",
+ zOrder = IDIYComponent.TRACE + 0.1, bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, autoEdit = false,
+ keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, transformer = SimpleComponentTransformer.class,
+ enableCache = true)
+public class Turret extends AbstractTransparentComponent {
+
+ private static final long serialVersionUID = 1L;
+
+ public static Size SIZE = new Size(0.16d, SizeUnit.in);
+ public static Size HOLE_SIZE = new Size(0.0625d, SizeUnit.in);
+ public static Color COLOR = Color.decode("#E0C04C");
+
+ private Size size = SIZE;
+ private Size holeSize = HOLE_SIZE;
+ private Color color = COLOR;
+ private Point2D.Double point = new Point2D.Double(0, 0);
+ private String value = "";
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ if (checkPointsClipped(g2d.getClip())) {
+ return;
+ }
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ int diameter = getClosestOdd((int) size.convertToPixels());
+ int holeDiameter = getClosestOdd((int) holeSize.convertToPixels());
+ 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);
+ 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.setColor(Constants.CANVAS_COLOR);
+ g2d.fillOval((int)(point.getX() - holeDiameter / 2), (int)(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.setComposite(oldComposite);
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int diameter = getClosestOdd(width / 2);
+ int holeDiameter = 5;
+ g2d.setColor(COLOR);
+ g2d.fillOval((width - diameter) / 2, (height - diameter) / 2, diameter, diameter);
+ g2d.setColor(COLOR.darker());
+ g2d.drawOval((width - diameter) / 2, (height - diameter) / 2, diameter, diameter);
+ g2d.setColor(Constants.CANVAS_COLOR);
+ g2d.fillOval((width - holeDiameter) / 2, (height - holeDiameter) / 2, holeDiameter, holeDiameter);
+ g2d.setColor(COLOR.darker());
+ g2d.drawOval((width - holeDiameter) / 2, (height - holeDiameter) / 2, holeDiameter, holeDiameter);
+ }
+
+ @EditableProperty
+ public Size getSize() {
+ return size;
+ }
+
+ public void setSize(Size size) {
+ this.size = size;
+ }
+
+ @EditableProperty(name = "Hole Size")
+ public Size getHoleSize() {
+ return holeSize;
+ }
+
+ public void setHoleSize(Size holeSize) {
+ this.holeSize = holeSize;
+ }
+
+ @Override
+ public String getName() {
+ return super.getName();
+ }
+
+ @Override
+ public int getControlPointCount() {
+ return 1;
+ }
+
+ @Override
+ public boolean isControlPointSticky(int index) {
+ return true;
+ }
+
+ @Override
+ public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
+ return VisibilityPolicy.NEVER;
+ }
+
+ @Override
+ public Point2D getControlPoint(int index) {
+ return point;
+ }
+
+ @Override
+ public void setControlPoint(Point2D point, int index) {
+ this.point.setLocation(point);
+ }
+
+ @EditableProperty(name = "Color")
+ public Color getColor() {
+ return color;
+ }
+
+ public void setColor(Color color) {
+ this.color = color;
+ }
+
+ @Override
+ @EditableProperty
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String getControlPointNodeName(int index) {
+ return null;
+ }
+
+ @Override
+ public Rectangle2D getCachingBounds() {
+ double size = getSize().convertToPixels();
+ return new Rectangle2D.Double(point.getX() - size, point.getY() - size, size * 2, size * 2);
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/BatterySnap9V.java b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/BatterySnap9V.java
index b31f8f79d..a256a76c0 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/BatterySnap9V.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/BatterySnap9V.java
@@ -1,275 +1,272 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.electromechanical;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-import java.awt.Polygon;
-import java.awt.Shape;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Area;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.Orientation;
-import org.diylc.components.AbstractTransparentComponent;
-import org.diylc.components.transform.BatterySnapTransformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-import org.diylc.core.VisibilityPolicy;
-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.Constants;
-
-@ComponentDescriptor(name = "9V Battery Snap", category = "Electro-Mechanical", author = "Branislav Stojkovic",
- description = "", zOrder = IDIYComponent.COMPONENT, instanceNamePrefix = "BTR",
- transformer = BatterySnapTransformer.class)
-public class BatterySnap9V extends AbstractTransparentComponent {
-
- private static final long serialVersionUID = 1L;
-
- private static Color BODY_COLOR = Color.darkGray;
- private static Size WIDTH = new Size(0.5d, SizeUnit.in);
- private static Size LENGTH = new Size(0.75d, SizeUnit.in);
- private static Size TERMINAL_DIAMETER = new Size(0.3d, SizeUnit.in);
- private static Size TERMINAL_SPACING = new Size(0.5d, SizeUnit.in);
- private static Size TERMINAL_BORDER = new Size(0.7d, SizeUnit.mm);
-
- private String value = "";
- private Point2D controlPoint = new Point2D.Double(0, 0);
- transient Shape[] body;
- private Orientation orientation = Orientation.DEFAULT;
- private Color color = BODY_COLOR;
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- Shape[] body = getBody();
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
- if (componentState != ComponentState.DRAGGING) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : color);
- g2d.fill(body[0]);
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : METAL_COLOR);
- g2d.fill(body[1]);
- g2d.fill(body[2]);
- g2d.setComposite(oldComposite);
- }
-
- Color finalBorderColor;
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : color.brighter();
- }
-
- drawingObserver.stopTracking();
-
- g2d.setColor(finalBorderColor);
- g2d.draw(body[0]);
- g2d.setColor(METAL_COLOR.darker());
- g2d.draw(body[1]);
- g2d.setColor(METAL_COLOR.darker());
- g2d.draw(body[2]);
- }
-
- @SuppressWarnings("incomplete-switch")
- public Shape[] getBody() {
- if (body == null) {
- body = new Shape[3];
-
- double x = controlPoint.getX();
- double y = controlPoint.getY();
- int width = (int) WIDTH.convertToPixels();
- int length = (int) LENGTH.convertToPixels();
- int totalLength = length + width / 2;
- int terminalDiameter = (int) TERMINAL_DIAMETER.convertToPixels();
- int terminalSpacing = (int) TERMINAL_SPACING.convertToPixels();
- int terminalBorder = (int) TERMINAL_BORDER.convertToPixels();
-
- Area mainArea = new Area(new Rectangle2D.Double(x, y - width / 2, length, width));
- mainArea.add(new Area(new Ellipse2D.Double(x + length - width / 2, y - width / 2, width, width)));
-
- body[0] = mainArea;
-
- Area terminalArea =
- new Area(new Ellipse2D.Double(x + (totalLength - terminalSpacing) / 2 - terminalDiameter / 2, y
- - terminalDiameter / 2, terminalDiameter, terminalDiameter));
-
- double centerX = x + (totalLength + terminalSpacing) / 2;
- int[] terminalX = new int[6];
- int[] terminalY = new int[6];
-
- for (int i = 0; i < 6; i++) {
- terminalX[i] = (int) (centerX + Math.cos(Math.PI / 3 * i) * terminalDiameter / 2);
- terminalY[i] = (int) (y + Math.sin(Math.PI / 3 * i) * terminalDiameter / 2);
- }
- terminalArea.add(new Area(new Polygon(terminalX, terminalY, 6)));
-
- body[1] = terminalArea;
-
- terminalArea =
- new Area(new Ellipse2D.Double(
- x + (totalLength - terminalSpacing) / 2 - terminalDiameter / 2 + terminalBorder, y - terminalDiameter / 2
- + terminalBorder, terminalDiameter - 2 * terminalBorder, terminalDiameter - 2 * terminalBorder));
-
- for (int i = 0; i < 6; i++) {
- terminalX[i] = (int) (centerX + Math.cos(Math.PI / 3 * i) * (terminalDiameter / 2 + terminalBorder));
- terminalY[i] = (int) (y + Math.sin(Math.PI / 3 * i) * (terminalDiameter / 2 + terminalBorder));
- }
- terminalArea.add(new Area(new Polygon(terminalX, terminalY, 6)));
-
- body[2] = terminalArea;
-
- // Rotate if needed
- if (orientation != Orientation.DEFAULT) {
- double theta = 0;
- switch (orientation) {
- case _90:
- theta = Math.PI / 2;
- break;
- case _180:
- theta = Math.PI;
- break;
- case _270:
- theta = Math.PI * 3 / 2;
- break;
- }
- AffineTransform rotation = AffineTransform.getRotateInstance(theta, x, y);
- for (Shape shape : body) {
- Area area = (Area) shape;
- area.transform(rotation);
- }
- }
- }
- return body;
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- g2d.setColor(BODY_COLOR);
- g2d.fillOval(width / 4, width / 32, width / 2, width / 2);
- g2d.setColor(BODY_COLOR.darker());
- g2d.drawOval(width / 4, width / 32, width / 2, width / 2);
- g2d.setColor(BODY_COLOR);
- g2d.fillRect(width / 4, width / 32 + width / 4, width / 2, width * 3 / 4 - 2 * width / 32);
- g2d.setColor(BODY_COLOR.darker());
- g2d.drawRect(width / 4, width / 32 + width / 4, width / 2, width * 3 / 4 - 2 * width / 32);
- g2d.setColor(METAL_COLOR);
- g2d.fillOval(width / 4 + 3 * width / 32, width / 32 + 3 * width / 32, width / 2 - 6 * width / 32, width / 2 - 6
- * width / 32);
-
- int centerX = width / 2;
- int centerY = height * 7 / 9;
- int terminalDiameter = width / 2 - 4 * width / 32;
- int[] terminalX = new int[6];
- int[] terminalY = new int[6];
-
- for (int i = 0; i < 6; i++) {
- terminalX[i] = (int) (centerX + Math.cos(Math.PI / 3 * i) * terminalDiameter / 2);
- terminalY[i] = (int) (centerY + Math.sin(Math.PI / 3 * i) * terminalDiameter / 2);
- }
- g2d.fillPolygon(terminalX, terminalY, 6);
- g2d.setColor(METAL_COLOR.darker());
- g2d.drawOval(width / 4 + 3 * width / 32, width / 32 + 3 * width / 32, width / 2 - 6 * width / 32, width / 2 - 6
- * width / 32);
- g2d.drawPolygon(terminalX, terminalY, 6);
- }
-
- @Override
- public int getControlPointCount() {
- return 1;
- }
-
- @Override
- public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
- return VisibilityPolicy.WHEN_SELECTED;
- }
-
- @Override
- public boolean isControlPointSticky(int index) {
- return true;
- }
-
- @Override
- public Point2D getControlPoint(int index) {
- return controlPoint;
- }
-
- @Override
- public void setControlPoint(Point2D point, int index) {
- this.controlPoint.setLocation(point);
- // Invalidate the body
- body = null;
- }
-
- @Override
- public String getValue() {
- return value;
- }
-
- @Override
- public void setValue(String value) {
- this.value = value;
- }
-
- @EditableProperty
- public Orientation getOrientation() {
- return orientation;
- }
-
- public void setOrientation(Orientation orientation) {
- this.orientation = orientation;
- // Invalidate the body
- body = null;
- }
-
- @EditableProperty
- public Color getColor() {
- return color;
- }
-
- public void setColor(Color color) {
- this.color = color;
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.electromechanical;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Graphics2D;
+import java.awt.Polygon;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Area;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.common.IPlugInPort;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.Orientation;
+import org.diylc.components.AbstractTransparentComponent;
+import org.diylc.components.transform.BatterySnapTransformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+import org.diylc.core.VisibilityPolicy;
+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.Constants;
+
+@ComponentDescriptor(name = "9V Battery Snap", category = "Electro-Mechanical", author = "Branislav Stojkovic",
+ description = "", zOrder = IDIYComponent.COMPONENT, instanceNamePrefix = "BTR",
+ transformer = BatterySnapTransformer.class)
+public class BatterySnap9V extends AbstractTransparentComponent {
+
+ private static final long serialVersionUID = 1L;
+
+ private static Color BODY_COLOR = Color.darkGray;
+ private static Size WIDTH = new Size(0.5d, SizeUnit.in);
+ private static Size LENGTH = new Size(0.75d, SizeUnit.in);
+ private static Size TERMINAL_DIAMETER = new Size(0.3d, SizeUnit.in);
+ private static Size TERMINAL_SPACING = new Size(0.5d, SizeUnit.in);
+ private static Size TERMINAL_BORDER = new Size(0.7d, SizeUnit.mm);
+
+ private String value = "";
+ private Point2D controlPoint = new Point2D.Double(0, 0);
+ transient Shape[] body;
+ private Orientation orientation = Orientation.DEFAULT;
+ private Color color = BODY_COLOR;
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ Shape[] body = getBody();
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+ if (componentState != ComponentState.DRAGGING) {
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : color);
+ g2d.fill(body[0]);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : METAL_COLOR);
+ g2d.fill(body[1]);
+ g2d.fill(body[2]);
+ g2d.setComposite(oldComposite);
+ }
+
+ Color finalBorderColor;
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : color.brighter();
+ }
+
+ drawingObserver.stopTracking();
+
+ g2d.setColor(finalBorderColor);
+ g2d.draw(body[0]);
+ g2d.setColor(METAL_COLOR.darker());
+ g2d.draw(body[1]);
+ g2d.setColor(METAL_COLOR.darker());
+ g2d.draw(body[2]);
+ }
+
+ @SuppressWarnings("incomplete-switch")
+ public Shape[] getBody() {
+ if (body == null) {
+ body = new Shape[3];
+
+ double x = controlPoint.getX();
+ double y = controlPoint.getY();
+ int width = (int) WIDTH.convertToPixels();
+ int length = (int) LENGTH.convertToPixels();
+ int totalLength = length + width / 2;
+ int terminalDiameter = (int) TERMINAL_DIAMETER.convertToPixels();
+ int terminalSpacing = (int) TERMINAL_SPACING.convertToPixels();
+ int terminalBorder = (int) TERMINAL_BORDER.convertToPixels();
+
+ Area mainArea = new Area(new Rectangle2D.Double(x, y - width / 2, length, width));
+ mainArea.add(new Area(new Ellipse2D.Double(x + length - width / 2, y - width / 2, width, width)));
+
+ body[0] = mainArea;
+
+ Area terminalArea =
+ new Area(new Ellipse2D.Double(x + (totalLength - terminalSpacing) / 2 - terminalDiameter / 2, y
+ - terminalDiameter / 2, terminalDiameter, terminalDiameter));
+
+ double centerX = x + (totalLength + terminalSpacing) / 2;
+ int[] terminalX = new int[6];
+ int[] terminalY = new int[6];
+
+ for (int i = 0; i < 6; i++) {
+ terminalX[i] = (int) (centerX + Math.cos(Math.PI / 3 * i) * terminalDiameter / 2);
+ terminalY[i] = (int) (y + Math.sin(Math.PI / 3 * i) * terminalDiameter / 2);
+ }
+ terminalArea.add(new Area(new Polygon(terminalX, terminalY, 6)));
+
+ body[1] = terminalArea;
+
+ terminalArea =
+ new Area(new Ellipse2D.Double(
+ x + (totalLength - terminalSpacing) / 2 - terminalDiameter / 2 + terminalBorder, y - terminalDiameter / 2
+ + terminalBorder, terminalDiameter - 2 * terminalBorder, terminalDiameter - 2 * terminalBorder));
+
+ for (int i = 0; i < 6; i++) {
+ terminalX[i] = (int) (centerX + Math.cos(Math.PI / 3 * i) * (terminalDiameter / 2 + terminalBorder));
+ terminalY[i] = (int) (y + Math.sin(Math.PI / 3 * i) * (terminalDiameter / 2 + terminalBorder));
+ }
+ terminalArea.add(new Area(new Polygon(terminalX, terminalY, 6)));
+
+ body[2] = terminalArea;
+
+ // Rotate if needed
+ if (orientation != Orientation.DEFAULT) {
+ double theta = 0;
+ switch (orientation) {
+ case _90:
+ theta = Math.PI / 2;
+ break;
+ case _180:
+ theta = Math.PI;
+ break;
+ case _270:
+ theta = Math.PI * 3 / 2;
+ break;
+ }
+ AffineTransform rotation = AffineTransform.getRotateInstance(theta, x, y);
+ for (Shape shape : body) {
+ Area area = (Area) shape;
+ area.transform(rotation);
+ }
+ }
+ }
+ return body;
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ g2d.setColor(BODY_COLOR);
+ g2d.fillOval(width / 4, width / 32, width / 2, width / 2);
+ g2d.setColor(BODY_COLOR.darker());
+ g2d.drawOval(width / 4, width / 32, width / 2, width / 2);
+ g2d.setColor(BODY_COLOR);
+ g2d.fillRect(width / 4, width / 32 + width / 4, width / 2, width * 3 / 4 - 2 * width / 32);
+ g2d.setColor(BODY_COLOR.darker());
+ g2d.drawRect(width / 4, width / 32 + width / 4, width / 2, width * 3 / 4 - 2 * width / 32);
+ g2d.setColor(METAL_COLOR);
+ g2d.fillOval(width / 4 + 3 * width / 32, width / 32 + 3 * width / 32, width / 2 - 6 * width / 32, width / 2 - 6
+ * width / 32);
+
+ int centerX = width / 2;
+ int centerY = height * 7 / 9;
+ int terminalDiameter = width / 2 - 4 * width / 32;
+ int[] terminalX = new int[6];
+ int[] terminalY = new int[6];
+
+ for (int i = 0; i < 6; i++) {
+ terminalX[i] = (int) (centerX + Math.cos(Math.PI / 3 * i) * terminalDiameter / 2);
+ terminalY[i] = (int) (centerY + Math.sin(Math.PI / 3 * i) * terminalDiameter / 2);
+ }
+ g2d.fillPolygon(terminalX, terminalY, 6);
+ g2d.setColor(METAL_COLOR.darker());
+ g2d.drawOval(width / 4 + 3 * width / 32, width / 32 + 3 * width / 32, width / 2 - 6 * width / 32, width / 2 - 6
+ * width / 32);
+ g2d.drawPolygon(terminalX, terminalY, 6);
+ }
+
+ @Override
+ public int getControlPointCount() {
+ return 1;
+ }
+
+ @Override
+ public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
+ return VisibilityPolicy.WHEN_SELECTED;
+ }
+
+ @Override
+ public boolean isControlPointSticky(int index) {
+ return true;
+ }
+
+ @Override
+ public Point2D getControlPoint(int index) {
+ return controlPoint;
+ }
+
+ @Override
+ public void setControlPoint(Point2D point, int index) {
+ this.controlPoint.setLocation(point);
+ // Invalidate the body
+ body = null;
+ }
+
+ @Override
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ @EditableProperty
+ public Orientation getOrientation() {
+ return orientation;
+ }
+
+ public void setOrientation(Orientation orientation) {
+ this.orientation = orientation;
+ // Invalidate the body
+ body = null;
+ }
+
+ @EditableProperty
+ public Color getColor() {
+ return color;
+ }
+
+ public void setColor(Color color) {
+ this.color = color;
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/CliffJack1_4.java b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/CliffJack1_4.java
index 76ded26f6..c08defcba 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/CliffJack1_4.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/CliffJack1_4.java
@@ -1,358 +1,355 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.electromechanical;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-import java.awt.RenderingHints;
-import java.awt.Shape;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Area;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.geom.RoundRectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.awt.StringUtils;
-import org.diylc.common.HorizontalAlignment;
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.Orientation;
-import org.diylc.common.VerticalAlignment;
-import org.diylc.components.AbstractMultiPartComponent;
-import org.diylc.components.transform.CliffJackTransformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-import org.diylc.core.VisibilityPolicy;
-import org.diylc.core.annotations.ComponentDescriptor;
-import org.diylc.core.annotations.EditableProperty;
-import org.diylc.core.gerber.IGerberComponentSimple;
-import org.diylc.core.measures.Size;
-import org.diylc.core.measures.SizeUnit;
-import org.diylc.utils.Constants;
-
-@ComponentDescriptor(name = "Cliff 1/4\" Jack", category = "Electro-Mechanical", author = "Branislav Stojkovic",
- description = "Cliff-style closed panel mount 1/4\" phono jack",
- zOrder = IDIYComponent.COMPONENT, instanceNamePrefix = "J", transformer = CliffJackTransformer.class,
- enableCache = true)
-public class CliffJack1_4 extends AbstractMultiPartComponent implements IGerberComponentSimple {
-
- private static final long serialVersionUID = 1L;
-
- private static Size SPACING = new Size(0.3d, SizeUnit.in);
- private static Size PIN_WIDTH = new Size(0.1d, SizeUnit.in);
- private static Size PIN_THICKNESS = new Size(0.02d, SizeUnit.in);
- private static Color BODY_COLOR = Color.decode("#666666");
- private static Color NUT_COLOR = Color.decode("#999999");
- private static Color BORDER_COLOR = Color.black;
- private static Color LABEL_COLOR = Color.white;
- private static Size BODY_WIDTH = new Size(3 / 4d, SizeUnit.in);
- private static Size BODY_LENGTH = new Size(0.9d, SizeUnit.in);
- private static Size TAIL_LENGTH = new Size(0.1d, SizeUnit.in);
-
- private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0)};
- private JackType type = JackType.MONO;
- private Orientation orientation = Orientation.DEFAULT;
- transient private Area[] body;
- @SuppressWarnings("unused")
- @Deprecated
- private transient String value = "";
-
- public CliffJack1_4() {
- super();
- updateControlPoints();
- }
-
- private void updateControlPoints() {
- // invalidate body shape
- body = null;
- double x = controlPoints[0].getX();
- double y = controlPoints[0].getY();
- int spacing = (int) SPACING.convertToPixels();
- controlPoints = new Point2D[type == JackType.STEREO ? 6 : 4];
-
- controlPoints[0] = new Point2D.Double(x, y);
- controlPoints[1] = new Point2D.Double(x, y + 2 * spacing);
- controlPoints[2] = new Point2D.Double(x + 2 * spacing, y);
- controlPoints[3] = new Point2D.Double(x + 2 * spacing, y + 2 * spacing);
- if (type == JackType.STEREO) {
- controlPoints[4] = new Point2D.Double(x + spacing, y);
- controlPoints[5] = new Point2D.Double(x + spacing, y + 2 * spacing);
- }
-
- // Apply rotation if necessary
- double angle = getAngle();
- if (angle != 0) {
- AffineTransform rotation = AffineTransform.getRotateInstance(angle, x, y);
- for (int i = 1; i < controlPoints.length; i++) {
- rotation.transform(controlPoints[i], controlPoints[i]);
- }
- }
- }
-
- private double getAngle() {
- // Apply rotation if necessary
- double angle;
- switch (orientation) {
- case _90:
- angle = Math.PI / 2;
- break;
- case _180:
- angle = Math.PI;
- break;
- case _270:
- angle = Math.PI * 3 / 2;
- break;
- default:
- angle = 0;
- }
-
- return angle;
- }
-
- public Area[] getBody() {
- if (body == null) {
- body = new Area[5];
-
- // Create body.
- int bodyLength = (int) BODY_LENGTH.convertToPixels();
- int bodyWidth = (int) BODY_WIDTH.convertToPixels();
- double centerX = (controlPoints[0].getX() + controlPoints[3].getX()) / 2;
- double centerY = (controlPoints[0].getY() + controlPoints[3].getY()) / 2;
- body[0] = new Area(new Rectangle2D.Double(centerX - bodyLength / 2, centerY - bodyWidth / 2, bodyLength, bodyWidth));
-
- int tailLength = (int) TAIL_LENGTH.convertToPixels();
- body[1] = new Area(new RoundRectangle2D.Double(centerX - bodyLength / 2 - tailLength, centerY - bodyWidth / 4, tailLength * 2,
- bodyWidth / 2, tailLength, tailLength));
- Area tailArea = new Area(body[1]);
- tailArea.subtract(new Area(body[0]));
- body[1] = tailArea;
-
- body[2] = new Area(new Rectangle2D.Double(centerX + bodyLength / 2, centerY - bodyWidth / 4, tailLength, bodyWidth / 2));
-
- body[3] = new Area(new Rectangle2D.Double(centerX + bodyLength / 2 + tailLength, centerY - bodyWidth / 4, tailLength, bodyWidth / 2));
- tailArea = new Area(body[3]);
- int radius = bodyLength / 2 + tailLength * 2;
- tailArea.intersect(new Area(new Ellipse2D.Double(centerX - radius, centerY - radius, radius * 2, radius * 2)));
- body[3] = tailArea;
-
- // Apply rotation if necessary
- double angle = getAngle();
- if (angle != 0) {
- AffineTransform rotation = AffineTransform.getRotateInstance(angle, centerX, centerY);
- for (int i = 0; i < body.length; i++) {
- if (body[i] != null) {
- Area area = new Area(body[i]);
- area.transform(rotation);
- body[i] = area;
- }
- }
- }
-
- // Create pins.
- Area pins = new Area();
-
- int pinWidth = (int) PIN_WIDTH.convertToPixels();
- int pinThickness = (int) PIN_THICKNESS.convertToPixels();
- for (int i = 0; i < getControlPointCount(); i++) {
- Point2D point = getControlPoint(i);
- Rectangle2D pin;
- if (orientation == Orientation.DEFAULT || orientation == Orientation._180) {
- pin = new Rectangle2D.Double(point.getX() - pinWidth / 2, point.getY() - pinThickness / 2, pinWidth, pinThickness);
- } else {
- pin = new Rectangle2D.Double(point.getX() - pinThickness / 2, point.getY() - pinWidth / 2, pinThickness, pinWidth);
- }
- pins.add(new Area(pin));
- }
-
- body[4] = pins;
- }
- return body;
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- Shape[] body = getBody();
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
-// if (componentState != ComponentState.DRAGGING) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : BODY_COLOR);
- for (int i = 0; i < body.length - 1; i++) {
- // Nut is brighter colored.
- if (i == body.length - 2)
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : NUT_COLOR);
- g2d.fill(body[i]);
- }
- g2d.setComposite(oldComposite);
-// }
-
- Color finalBorderColor;
- Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- if (outlineMode) {
- finalBorderColor = theme.getOutlineColor();
- } else {
- finalBorderColor = BORDER_COLOR;
- }
-
- drawingObserver.stopTracking();
-
- g2d.setColor(finalBorderColor);
- for (int i = 0; i < body.length - 1; i++) {
- g2d.draw(body[i]);
- }
-
- // Pins are the last piece.
- Shape pins = body[body.length - 1];
- if (!outlineMode) {
- g2d.setColor(METAL_COLOR);
- g2d.fill(pins);
- }
- g2d.setColor(outlineMode ? theme.getOutlineColor() : METAL_COLOR.darker());
- g2d.draw(pins);
-
- Color finalLabelColor;
- if (outlineMode) {
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : theme.getOutlineColor();
- } else {
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : LABEL_COLOR;
- }
- g2d.setColor(finalLabelColor);
- g2d.setFont(project.getFont());
-
- // Override font size
- if (getFontSizeOverride() != null)
- g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride()));
-
- double centerX = (controlPoints[0].getX() + controlPoints[3].getX()) / 2;
- double centerY = (controlPoints[0].getY() + controlPoints[3].getY()) / 2;
- StringUtils.drawCenteredText(g2d, name, centerX, centerY, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
-
- drawSelectionOutline(g2d, componentState, outlineMode, project, drawingObserver);
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int bodyWidth = getClosestOdd(width * 3 / 5);
- int tailWidth = getClosestOdd(width * 3 / 9);
-
- g2d.setColor(BODY_COLOR);
- g2d.fillRoundRect((width - tailWidth) / 2, height / 2, tailWidth, height / 2 - 2 * 32 / height, 4 * 32 / width,
- 4 * 32 / width);
- g2d.setColor(BORDER_COLOR);
- g2d.drawRoundRect((width - tailWidth) / 2, height / 2, tailWidth, height / 2 - 2 * 32 / height, 4 * 32 / width,
- 4 * 32 / width);
-
- g2d.setColor(NUT_COLOR);
- g2d.fillRoundRect((width - tailWidth) / 2, 2 * 32 / height, tailWidth, height / 2, 4 * 32 / width, 4 * 32 / width);
- g2d.setColor(BORDER_COLOR);
- g2d.drawRoundRect((width - tailWidth) / 2, 2 * 32 / height, tailWidth, height / 2, 4 * 32 / width, 4 * 32 / width);
-
- g2d.setColor(BODY_COLOR);
- g2d.fillRect((width - bodyWidth) / 2, height / 7 + 1, bodyWidth, height * 5 / 7);
- g2d.setColor(BORDER_COLOR);
- g2d.drawRect((width - bodyWidth) / 2, height / 7 + 1, bodyWidth, height * 5 / 7);
-
- g2d.setColor(METAL_COLOR);
- int pinX1 = getClosestOdd((width - bodyWidth * 3 / 4) / 2);
- int pinX2 = getClosestOdd((width + bodyWidth * 3 / 4) / 2) - 1;
- g2d.drawLine(pinX1, width * 2 / 8, pinX1, width * 3 / 8);
- g2d.drawLine(pinX1, width * 5 / 8, pinX1, width * 6 / 8);
- g2d.drawLine(pinX2, width * 2 / 8, pinX2, width * 3 / 8);
- g2d.drawLine(pinX2, width * 5 / 8, pinX2, width * 6 / 8);
-
- g2d.setColor(LABEL_COLOR);
- g2d.setFont(LABEL_FONT.deriveFont(width / 3.5f));
-
- RenderingHints rh = new RenderingHints(
- RenderingHints.KEY_TEXT_ANTIALIASING,
- RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
- g2d.setRenderingHints(rh);
-
- StringUtils.drawCenteredText(g2d, "6.3", width / 2 - 1, height / 2, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
- }
-
- @Override
- public int getControlPointCount() {
- return controlPoints.length;
- }
-
- @Override
- public Point2D getControlPoint(int index) {
- return controlPoints[index];
- }
-
- @Override
- public void setControlPoint(Point2D point, int index) {
- controlPoints[index].setLocation(point);
- body = null;
- }
-
- @Override
- public boolean isControlPointSticky(int index) {
- return true;
- }
-
- @Override
- public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
- return VisibilityPolicy.NEVER;
- }
-
- @EditableProperty(name = "Type")
- public JackType getValue() {
- return type;
- }
-
- public void setValue(JackType type) {
- this.type = type;
- updateControlPoints();
- }
-
- @EditableProperty
- public Orientation getOrientation() {
- return orientation;
- }
-
- public void setOrientation(Orientation orientation) {
- this.orientation = orientation;
- updateControlPoints();
- }
-
- @Override
- public boolean canPointMoveFreely(int pointIndex) {
- return false;
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.electromechanical;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Area;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.awt.StringUtils;
+import org.diylc.common.HorizontalAlignment;
+import org.diylc.common.IPlugInPort;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.Orientation;
+import org.diylc.common.VerticalAlignment;
+import org.diylc.components.AbstractMultiPartComponent;
+import org.diylc.components.transform.CliffJackTransformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+import org.diylc.core.VisibilityPolicy;
+import org.diylc.core.annotations.ComponentDescriptor;
+import org.diylc.core.annotations.EditableProperty;
+import org.diylc.core.gerber.IGerberComponentSimple;
+import org.diylc.core.measures.Size;
+import org.diylc.core.measures.SizeUnit;
+import org.diylc.utils.Constants;
+
+@ComponentDescriptor(name = "Cliff 1/4\" Jack", category = "Electro-Mechanical", author = "Branislav Stojkovic",
+ description = "Cliff-style closed panel mount 1/4\" phono jack",
+ zOrder = IDIYComponent.COMPONENT, instanceNamePrefix = "J", transformer = CliffJackTransformer.class,
+ enableCache = true)
+public class CliffJack1_4 extends AbstractMultiPartComponent implements IGerberComponentSimple {
+
+ private static final long serialVersionUID = 1L;
+
+ private static Size SPACING = new Size(0.3d, SizeUnit.in);
+ private static Size PIN_WIDTH = new Size(0.1d, SizeUnit.in);
+ private static Size PIN_THICKNESS = new Size(0.02d, SizeUnit.in);
+ private static Color BODY_COLOR = Color.decode("#666666");
+ private static Color NUT_COLOR = Color.decode("#999999");
+ private static Color BORDER_COLOR = Color.black;
+ private static Color LABEL_COLOR = Color.white;
+ private static Size BODY_WIDTH = new Size(3 / 4d, SizeUnit.in);
+ private static Size BODY_LENGTH = new Size(0.9d, SizeUnit.in);
+ private static Size TAIL_LENGTH = new Size(0.1d, SizeUnit.in);
+
+ private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0)};
+ private JackType type = JackType.MONO;
+ private Orientation orientation = Orientation.DEFAULT;
+ transient private Area[] body;
+ @SuppressWarnings("unused")
+ @Deprecated
+ private transient String value = "";
+
+ public CliffJack1_4() {
+ super();
+ updateControlPoints();
+ }
+
+ private void updateControlPoints() {
+ // invalidate body shape
+ body = null;
+ double x = controlPoints[0].getX();
+ double y = controlPoints[0].getY();
+ int spacing = (int) SPACING.convertToPixels();
+ controlPoints = new Point2D[type == JackType.STEREO ? 6 : 4];
+
+ controlPoints[0] = new Point2D.Double(x, y);
+ controlPoints[1] = new Point2D.Double(x, y + 2 * spacing);
+ controlPoints[2] = new Point2D.Double(x + 2 * spacing, y);
+ controlPoints[3] = new Point2D.Double(x + 2 * spacing, y + 2 * spacing);
+ if (type == JackType.STEREO) {
+ controlPoints[4] = new Point2D.Double(x + spacing, y);
+ controlPoints[5] = new Point2D.Double(x + spacing, y + 2 * spacing);
+ }
+
+ // Apply rotation if necessary
+ double angle = getAngle();
+ if (angle != 0) {
+ AffineTransform rotation = AffineTransform.getRotateInstance(angle, x, y);
+ for (int i = 1; i < controlPoints.length; i++) {
+ rotation.transform(controlPoints[i], controlPoints[i]);
+ }
+ }
+ }
+
+ private double getAngle() {
+ // Apply rotation if necessary
+ double angle;
+ switch (orientation) {
+ case _90:
+ angle = Math.PI / 2;
+ break;
+ case _180:
+ angle = Math.PI;
+ break;
+ case _270:
+ angle = Math.PI * 3 / 2;
+ break;
+ default:
+ angle = 0;
+ }
+
+ return angle;
+ }
+
+ public Area[] getBody() {
+ if (body == null) {
+ body = new Area[5];
+
+ // Create body.
+ int bodyLength = (int) BODY_LENGTH.convertToPixels();
+ int bodyWidth = (int) BODY_WIDTH.convertToPixels();
+ double centerX = (controlPoints[0].getX() + controlPoints[3].getX()) / 2;
+ double centerY = (controlPoints[0].getY() + controlPoints[3].getY()) / 2;
+ body[0] = new Area(new Rectangle2D.Double(centerX - bodyLength / 2, centerY - bodyWidth / 2, bodyLength, bodyWidth));
+
+ int tailLength = (int) TAIL_LENGTH.convertToPixels();
+ body[1] = new Area(new RoundRectangle2D.Double(centerX - bodyLength / 2 - tailLength, centerY - bodyWidth / 4, tailLength * 2,
+ bodyWidth / 2, tailLength, tailLength));
+ Area tailArea = new Area(body[1]);
+ tailArea.subtract(new Area(body[0]));
+ body[1] = tailArea;
+
+ body[2] = new Area(new Rectangle2D.Double(centerX + bodyLength / 2, centerY - bodyWidth / 4, tailLength, bodyWidth / 2));
+
+ body[3] = new Area(new Rectangle2D.Double(centerX + bodyLength / 2 + tailLength, centerY - bodyWidth / 4, tailLength, bodyWidth / 2));
+ tailArea = new Area(body[3]);
+ int radius = bodyLength / 2 + tailLength * 2;
+ tailArea.intersect(new Area(new Ellipse2D.Double(centerX - radius, centerY - radius, radius * 2, radius * 2)));
+ body[3] = tailArea;
+
+ // Apply rotation if necessary
+ double angle = getAngle();
+ if (angle != 0) {
+ AffineTransform rotation = AffineTransform.getRotateInstance(angle, centerX, centerY);
+ for (int i = 0; i < body.length; i++) {
+ if (body[i] != null) {
+ Area area = new Area(body[i]);
+ area.transform(rotation);
+ body[i] = area;
+ }
+ }
+ }
+
+ // Create pins.
+ Area pins = new Area();
+
+ int pinWidth = (int) PIN_WIDTH.convertToPixels();
+ int pinThickness = (int) PIN_THICKNESS.convertToPixels();
+ for (int i = 0; i < getControlPointCount(); i++) {
+ Point2D point = getControlPoint(i);
+ Rectangle2D pin;
+ if (orientation == Orientation.DEFAULT || orientation == Orientation._180) {
+ pin = new Rectangle2D.Double(point.getX() - pinWidth / 2, point.getY() - pinThickness / 2, pinWidth, pinThickness);
+ } else {
+ pin = new Rectangle2D.Double(point.getX() - pinThickness / 2, point.getY() - pinWidth / 2, pinThickness, pinWidth);
+ }
+ pins.add(new Area(pin));
+ }
+
+ body[4] = pins;
+ }
+ return body;
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ Shape[] body = getBody();
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+// if (componentState != ComponentState.DRAGGING) {
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : BODY_COLOR);
+ for (int i = 0; i < body.length - 1; i++) {
+ // Nut is brighter colored.
+ if (i == body.length - 2)
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : NUT_COLOR);
+ g2d.fill(body[i]);
+ }
+ g2d.setComposite(oldComposite);
+// }
+
+ Color finalBorderColor;
+ Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ if (outlineMode) {
+ finalBorderColor = theme.getOutlineColor();
+ } else {
+ finalBorderColor = BORDER_COLOR;
+ }
+
+ drawingObserver.stopTracking();
+
+ g2d.setColor(finalBorderColor);
+ for (int i = 0; i < body.length - 1; i++) {
+ g2d.draw(body[i]);
+ }
+
+ // Pins are the last piece.
+ Shape pins = body[body.length - 1];
+ if (!outlineMode) {
+ g2d.setColor(METAL_COLOR);
+ g2d.fill(pins);
+ }
+ g2d.setColor(outlineMode ? theme.getOutlineColor() : METAL_COLOR.darker());
+ g2d.draw(pins);
+
+ Color finalLabelColor;
+ if (outlineMode) {
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : theme.getOutlineColor();
+ } else {
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : LABEL_COLOR;
+ }
+ g2d.setColor(finalLabelColor);
+ g2d.setFont(project.getFont());
+
+ // Override font size
+ if (getFontSizeOverride() != null)
+ g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride()));
+
+ double centerX = (controlPoints[0].getX() + controlPoints[3].getX()) / 2;
+ double centerY = (controlPoints[0].getY() + controlPoints[3].getY()) / 2;
+ StringUtils.drawCenteredText(g2d, name, centerX, centerY, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
+
+ drawSelectionOutline(g2d, componentState, outlineMode, project, drawingObserver);
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int bodyWidth = getClosestOdd(width * 3 / 5);
+ int tailWidth = getClosestOdd(width * 3 / 9);
+
+ g2d.setColor(BODY_COLOR);
+ g2d.fillRoundRect((width - tailWidth) / 2, height / 2, tailWidth, height / 2 - 2 * 32 / height, 4 * 32 / width,
+ 4 * 32 / width);
+ g2d.setColor(BORDER_COLOR);
+ g2d.drawRoundRect((width - tailWidth) / 2, height / 2, tailWidth, height / 2 - 2 * 32 / height, 4 * 32 / width,
+ 4 * 32 / width);
+
+ g2d.setColor(NUT_COLOR);
+ g2d.fillRoundRect((width - tailWidth) / 2, 2 * 32 / height, tailWidth, height / 2, 4 * 32 / width, 4 * 32 / width);
+ g2d.setColor(BORDER_COLOR);
+ g2d.drawRoundRect((width - tailWidth) / 2, 2 * 32 / height, tailWidth, height / 2, 4 * 32 / width, 4 * 32 / width);
+
+ g2d.setColor(BODY_COLOR);
+ g2d.fillRect((width - bodyWidth) / 2, height / 7 + 1, bodyWidth, height * 5 / 7);
+ g2d.setColor(BORDER_COLOR);
+ g2d.drawRect((width - bodyWidth) / 2, height / 7 + 1, bodyWidth, height * 5 / 7);
+
+ g2d.setColor(METAL_COLOR);
+ int pinX1 = getClosestOdd((width - bodyWidth * 3 / 4) / 2);
+ int pinX2 = getClosestOdd((width + bodyWidth * 3 / 4) / 2) - 1;
+ g2d.drawLine(pinX1, width * 2 / 8, pinX1, width * 3 / 8);
+ g2d.drawLine(pinX1, width * 5 / 8, pinX1, width * 6 / 8);
+ g2d.drawLine(pinX2, width * 2 / 8, pinX2, width * 3 / 8);
+ g2d.drawLine(pinX2, width * 5 / 8, pinX2, width * 6 / 8);
+
+ g2d.setColor(LABEL_COLOR);
+ g2d.setFont(LABEL_FONT.deriveFont(width / 3.5f));
+
+ RenderingHints rh = new RenderingHints(
+ RenderingHints.KEY_TEXT_ANTIALIASING,
+ RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
+ g2d.setRenderingHints(rh);
+
+ StringUtils.drawCenteredText(g2d, "6.3", width / 2 - 1, height / 2, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
+ }
+
+ @Override
+ public int getControlPointCount() {
+ return controlPoints.length;
+ }
+
+ @Override
+ public Point2D getControlPoint(int index) {
+ return controlPoints[index];
+ }
+
+ @Override
+ public void setControlPoint(Point2D point, int index) {
+ controlPoints[index].setLocation(point);
+ body = null;
+ }
+
+ @Override
+ public boolean isControlPointSticky(int index) {
+ return true;
+ }
+
+ @Override
+ public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
+ return VisibilityPolicy.NEVER;
+ }
+
+ @EditableProperty(name = "Type")
+ public JackType getValue() {
+ return type;
+ }
+
+ public void setValue(JackType type) {
+ this.type = type;
+ updateControlPoints();
+ }
+
+ @EditableProperty
+ public Orientation getOrientation() {
+ return orientation;
+ }
+
+ public void setOrientation(Orientation orientation) {
+ this.orientation = orientation;
+ updateControlPoints();
+ }
+
+ @Override
+ public boolean canPointMoveFreely(int pointIndex) {
+ return false;
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/CliffJack1_8.java b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/CliffJack1_8.java
index 5939b15c7..3c204c7d4 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/CliffJack1_8.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/CliffJack1_8.java
@@ -216,10 +216,7 @@ public class CliffJack1_8 extends AbstractMultiPartComponent implement
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
// if (componentState != ComponentState.DRAGGING) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : BODY_COLOR);
for (int i = 0; i < 2; i++) {
g2d.fill(body[i]);
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/ClosedJack1_4.java b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/ClosedJack1_4.java
index 1dd2c9dc0..1a61147a8 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/ClosedJack1_4.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/ClosedJack1_4.java
@@ -1,384 +1,381 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.electromechanical;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-import java.awt.Rectangle;
-import java.awt.RenderingHints;
-import java.awt.Shape;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Area;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.GeneralPath;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.awt.StringUtils;
-import org.diylc.common.HorizontalAlignment;
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.Orientation;
-import org.diylc.common.VerticalAlignment;
-import org.diylc.components.AbstractMultiPartComponent;
-import org.diylc.components.transform.ClosedJackTransformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-import org.diylc.core.VisibilityPolicy;
-import org.diylc.core.annotations.ComponentDescriptor;
-import org.diylc.core.annotations.EditableProperty;
-import org.diylc.core.gerber.IGerberComponentSimple;
-import org.diylc.core.measures.Size;
-import org.diylc.core.measures.SizeUnit;
-import org.diylc.utils.Constants;
-
-@ComponentDescriptor(name = "Closed 1/4\" Jack", category = "Electro-Mechanical", author = "Branislav Stojkovic",
- description = "Enclosed panel mount 1/4\" phono jack", zOrder = IDIYComponent.COMPONENT,
- instanceNamePrefix = "J", transformer = ClosedJackTransformer.class, enableCache = true)
-public class ClosedJack1_4 extends AbstractMultiPartComponent implements IGerberComponentSimple {
-
- private static final long serialVersionUID = 1L;
-
- private static Size SPACING = new Size(0.1d, SizeUnit.in);
- private static Size LUG_WIDTH = new Size(0.1d, SizeUnit.in);
- private static Size LUG_LENGTH = new Size(0.12d, SizeUnit.in);
- private static Size LUG_HOLE_SIZE = new Size(1d, SizeUnit.mm);
- private static Color BODY_COLOR = Color.decode("#666666");
- private static Color SHAFT_COLOR = Color.decode("#AAAAAA");
- private static Size SHAFT_LENGTH = new Size(0.25d, SizeUnit.in);
- private static Size SHAFT_WIDTH = new Size(3d / 8, SizeUnit.in);
- private static Color BORDER_COLOR = Color.black;
- private static Color LABEL_COLOR = Color.white;
- private static Size BODY_WIDTH = new Size(0.65d, SizeUnit.in);
- private static Size BODY_LENGTH = new Size(0.8d, SizeUnit.in);
-
- private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0)};
- private JackType type = JackType.MONO;
- private Orientation orientation = Orientation.DEFAULT;
- transient private Shape[] body;
- @SuppressWarnings("unused")
- @Deprecated
- private transient String value = "";
-
- public ClosedJack1_4() {
- super();
- updateControlPoints();
- }
-
- private void updateControlPoints() {
- // invalidate body shape
- body = null;
- double x = controlPoints[0].getX();
- double y = controlPoints[0].getY();
- int spacing = (int) SPACING.convertToPixels();
- int bodyLength = (int) BODY_LENGTH.convertToPixels();
- controlPoints = new Point2D[type == JackType.STEREO ? 3 : 2];
-
- controlPoints[0] = new Point2D.Double(x, y);
- controlPoints[1] = new Point2D.Double(x + bodyLength, y);
- if (type == JackType.STEREO) {
- controlPoints[2] = new Point2D.Double(x, y + 2 * spacing);
- }
-
- // Apply rotation if necessary
- double angle = getAngle();
- if (angle != 0) {
- AffineTransform rotation = AffineTransform.getRotateInstance(angle, x, y);
- for (int i = 1; i < controlPoints.length; i++) {
- rotation.transform(controlPoints[i], controlPoints[i]);
- }
- }
- }
-
- private double getAngle() {
- // Apply rotation if necessary
- double angle;
- switch (orientation) {
- case _90:
- angle = Math.PI / 2;
- break;
- case _180:
- angle = Math.PI;
- break;
- case _270:
- angle = Math.PI * 3 / 2;
- break;
- default:
- angle = 0;
- }
-
- return angle;
- }
-
- public Shape[] getBody() {
- if (body == null) {
- body = new Shape[5];
-
- // Create body.
- double x = controlPoints[0].getX();
- double y = controlPoints[0].getY();
- int lugWidth = (int) LUG_WIDTH.convertToPixels();
- int lugLength = (int) LUG_LENGTH.convertToPixels();
- int lugHoleSize = (int) LUG_HOLE_SIZE.convertToPixels();
- int bodyLength = (int) BODY_LENGTH.convertToPixels();
- int bodyWidth = (int) BODY_WIDTH.convertToPixels();
- body[0] = new Area(new Rectangle2D.Double(x + lugLength, y - bodyWidth / 2, bodyLength, bodyWidth));
-
- int shaftLength = (int) SHAFT_LENGTH.convertToPixels();
- int shaftWidth = (int) SHAFT_WIDTH.convertToPixels();
- Area shaft = new Area(new Rectangle2D.Double(x + lugLength + bodyLength, y - shaftWidth / 2, shaftLength, shaftWidth));
- body[1] = shaft;
-
- double angle = getAngle();
- AffineTransform rotation = null;
- if (angle != 0) {
- rotation = AffineTransform.getRotateInstance(angle, x, y);
- }
-
- GeneralPath path = new GeneralPath();
- int step = 4;
- for (double i = x + lugLength + bodyLength + step; i <= x + lugLength + bodyLength + shaftLength; i += step) {
- Point2D p = new Point2D.Double(i, y - shaftWidth / 2 + 1);
- if (rotation != null) {
- rotation.transform(p, p);
- }
- path.moveTo(p.getX(), p.getY());
- p = new Point2D.Double(i - step, y + shaftWidth / 2 - 1);
- if (rotation != null) {
- rotation.transform(p, p);
- }
- path.lineTo(p.getX(), p.getY());
- }
-// Area pathArea = new Area(path);
-// pathArea.intersect(shaft);
- body[2] = path;
-
- // Create lugs.
- Area lugs = new Area();
-
- int spacing = (int) SPACING.convertToPixels();
- Point2D[] untransformedControlPoints = new Point2D[type == JackType.STEREO ? 3 : 2];
-
- untransformedControlPoints[0] = new Point2D.Double(x, y);
- untransformedControlPoints[1] = new Point2D.Double(x + bodyLength, y);
- if (type == JackType.STEREO) {
- untransformedControlPoints[2] = new Point2D.Double(x, y + 2 * spacing);
- }
-
- for (int i = 0; i < untransformedControlPoints.length; i++) {
- Point2D point = untransformedControlPoints[i];
- Area lug = new Area(new Ellipse2D.Double(point.getX() - lugWidth / 2, point.getY() - lugWidth / 2, lugWidth, lugWidth));
- lug.add(new Area(new Rectangle2D.Double(point.getX(), point.getY() - lugWidth / 2, lugLength, lugWidth)));
- lug.subtract(new Area(new Ellipse2D.Double(point.getX() - lugHoleSize / 2, point.getY() - lugHoleSize / 2, lugHoleSize,
- lugHoleSize)));
- lugs.add(lug);
- }
-
- body[3] = lugs;
-
- // Rotate everything that's of Area type, e.g. everything but lines.
- if (rotation != null) {
- for (Shape shape : body) {
- if (shape instanceof Area) {
- Area area = (Area) shape;
- area.transform(rotation);
- }
- }
- }
- }
- return body;
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- Shape[] body = getBody();
-
- // Rectangle bounds = body.getBounds();
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
-// if (componentState != ComponentState.DRAGGING) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : BODY_COLOR);
- g2d.fill(body[0]);
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : SHAFT_COLOR);
- g2d.fill(body[1]);
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : METAL_COLOR);
- g2d.fill(body[3]);
- g2d.setComposite(oldComposite);
-// }
-
- drawingObserver.stopTracking();
-
- Color finalBorderColor;
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalBorderColor = theme.getOutlineColor();
- } else {
- finalBorderColor = BORDER_COLOR;
- }
-
- g2d.setColor(finalBorderColor);
- g2d.draw(body[0]);
- g2d.draw(body[1]);
- if (!outlineMode) {
- g2d.setColor(SHAFT_COLOR.darker());
-// g2d.fill(body[2]);
- g2d.draw(body[2]);
- }
-
- // Pins are the last piece.
- g2d.setColor(outlineMode ? finalBorderColor : METAL_COLOR.darker());
- g2d.draw(body[3]);
-
- Color finalLabelColor;
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : theme.getOutlineColor();
- } else {
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : LABEL_COLOR;
- }
- g2d.setColor(finalLabelColor);
- g2d.setFont(project.getFont());
-
- // Override font size
- if (getFontSizeOverride() != null)
- g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride()));
-
- Rectangle bounds = body[0].getBounds();
- double centerX = bounds.getX() + bounds.width / 2;
- double centerY = bounds.getY() + bounds.height / 2;
- StringUtils.drawCenteredText(g2d, name, centerX, centerY, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
-
- drawSelectionOutline(g2d, componentState, outlineMode, project, drawingObserver);
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int bodyWidth = getClosestOdd(width * 3 / 5);
- int tailWidth = getClosestOdd(width * 3 / 10);
-
- g2d.setColor(SHAFT_COLOR);
- g2d.fillRect((width - tailWidth) / 2, 1, tailWidth, height / 2);
- g2d.setColor(BORDER_COLOR);
- g2d.drawRect((width - tailWidth) / 2, 1, tailWidth, height / 2);
-
- g2d.setColor(BODY_COLOR);
- g2d.fillRect((width - bodyWidth) / 2, height / 7 + 1, bodyWidth, height * 5 / 7);
- g2d.setColor(BORDER_COLOR);
- g2d.drawRect((width - bodyWidth) / 2, height / 7 + 1, bodyWidth, height * 5 / 7);
-
- g2d.setColor(METAL_COLOR);
-
- g2d.fillRect(width * 7 / 16, height * 6 / 7 + 1, width / 8, height / 7 - 1);
- g2d.fillRect(width * 7 / 16, height / 7 + 2, width / 8, height / 7 - 1);
-
- g2d.setColor(LABEL_COLOR);
- g2d.setFont(LABEL_FONT.deriveFont(width / 3.5f));
-
- RenderingHints rh = new RenderingHints(
- RenderingHints.KEY_TEXT_ANTIALIASING,
- RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
- g2d.setRenderingHints(rh);
-
- StringUtils.drawCenteredText(g2d, "6.3", width / 2 - 1, height / 2, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
- }
-
- @Override
- public int getControlPointCount() {
- return controlPoints.length;
- }
-
- @Override
- public Point2D getControlPoint(int index) {
- return controlPoints[index];
- }
-
- @Override
- public void setControlPoint(Point2D point, int index) {
- controlPoints[index].setLocation(point);
- body = null;
- }
-
- @Override
- public boolean isControlPointSticky(int index) {
- return true;
- }
-
- @Override
- public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
- return VisibilityPolicy.NEVER;
- }
-
- @EditableProperty(name = "Type")
- public JackType getValue() {
- return type;
- }
-
- public void setValue(JackType type) {
- this.type = type;
- updateControlPoints();
- }
-
- @EditableProperty
- public Orientation getOrientation() {
- return orientation;
- }
-
- public void setOrientation(Orientation orientation) {
- this.orientation = orientation;
- updateControlPoints();
- }
-
- @Override
- public String getControlPointNodeName(int index) {
- switch (index) {
- case 0:
- return "Tip";
- case 1:
- return "Sleeve";
- case 2:
- return "Ring";
- }
- return null;
- }
-
- @Override
- public boolean canPointMoveFreely(int pointIndex) {
- return false;
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.electromechanical;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Area;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.awt.StringUtils;
+import org.diylc.common.HorizontalAlignment;
+import org.diylc.common.IPlugInPort;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.Orientation;
+import org.diylc.common.VerticalAlignment;
+import org.diylc.components.AbstractMultiPartComponent;
+import org.diylc.components.transform.ClosedJackTransformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+import org.diylc.core.VisibilityPolicy;
+import org.diylc.core.annotations.ComponentDescriptor;
+import org.diylc.core.annotations.EditableProperty;
+import org.diylc.core.gerber.IGerberComponentSimple;
+import org.diylc.core.measures.Size;
+import org.diylc.core.measures.SizeUnit;
+import org.diylc.utils.Constants;
+
+@ComponentDescriptor(name = "Closed 1/4\" Jack", category = "Electro-Mechanical", author = "Branislav Stojkovic",
+ description = "Enclosed panel mount 1/4\" phono jack", zOrder = IDIYComponent.COMPONENT,
+ instanceNamePrefix = "J", transformer = ClosedJackTransformer.class, enableCache = true)
+public class ClosedJack1_4 extends AbstractMultiPartComponent implements IGerberComponentSimple {
+
+ private static final long serialVersionUID = 1L;
+
+ private static Size SPACING = new Size(0.1d, SizeUnit.in);
+ private static Size LUG_WIDTH = new Size(0.1d, SizeUnit.in);
+ private static Size LUG_LENGTH = new Size(0.12d, SizeUnit.in);
+ private static Size LUG_HOLE_SIZE = new Size(1d, SizeUnit.mm);
+ private static Color BODY_COLOR = Color.decode("#666666");
+ private static Color SHAFT_COLOR = Color.decode("#AAAAAA");
+ private static Size SHAFT_LENGTH = new Size(0.25d, SizeUnit.in);
+ private static Size SHAFT_WIDTH = new Size(3d / 8, SizeUnit.in);
+ private static Color BORDER_COLOR = Color.black;
+ private static Color LABEL_COLOR = Color.white;
+ private static Size BODY_WIDTH = new Size(0.65d, SizeUnit.in);
+ private static Size BODY_LENGTH = new Size(0.8d, SizeUnit.in);
+
+ private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0)};
+ private JackType type = JackType.MONO;
+ private Orientation orientation = Orientation.DEFAULT;
+ transient private Shape[] body;
+ @SuppressWarnings("unused")
+ @Deprecated
+ private transient String value = "";
+
+ public ClosedJack1_4() {
+ super();
+ updateControlPoints();
+ }
+
+ private void updateControlPoints() {
+ // invalidate body shape
+ body = null;
+ double x = controlPoints[0].getX();
+ double y = controlPoints[0].getY();
+ int spacing = (int) SPACING.convertToPixels();
+ int bodyLength = (int) BODY_LENGTH.convertToPixels();
+ controlPoints = new Point2D[type == JackType.STEREO ? 3 : 2];
+
+ controlPoints[0] = new Point2D.Double(x, y);
+ controlPoints[1] = new Point2D.Double(x + bodyLength, y);
+ if (type == JackType.STEREO) {
+ controlPoints[2] = new Point2D.Double(x, y + 2 * spacing);
+ }
+
+ // Apply rotation if necessary
+ double angle = getAngle();
+ if (angle != 0) {
+ AffineTransform rotation = AffineTransform.getRotateInstance(angle, x, y);
+ for (int i = 1; i < controlPoints.length; i++) {
+ rotation.transform(controlPoints[i], controlPoints[i]);
+ }
+ }
+ }
+
+ private double getAngle() {
+ // Apply rotation if necessary
+ double angle;
+ switch (orientation) {
+ case _90:
+ angle = Math.PI / 2;
+ break;
+ case _180:
+ angle = Math.PI;
+ break;
+ case _270:
+ angle = Math.PI * 3 / 2;
+ break;
+ default:
+ angle = 0;
+ }
+
+ return angle;
+ }
+
+ public Shape[] getBody() {
+ if (body == null) {
+ body = new Shape[5];
+
+ // Create body.
+ double x = controlPoints[0].getX();
+ double y = controlPoints[0].getY();
+ int lugWidth = (int) LUG_WIDTH.convertToPixels();
+ int lugLength = (int) LUG_LENGTH.convertToPixels();
+ int lugHoleSize = (int) LUG_HOLE_SIZE.convertToPixels();
+ int bodyLength = (int) BODY_LENGTH.convertToPixels();
+ int bodyWidth = (int) BODY_WIDTH.convertToPixels();
+ body[0] = new Area(new Rectangle2D.Double(x + lugLength, y - bodyWidth / 2, bodyLength, bodyWidth));
+
+ int shaftLength = (int) SHAFT_LENGTH.convertToPixels();
+ int shaftWidth = (int) SHAFT_WIDTH.convertToPixels();
+ Area shaft = new Area(new Rectangle2D.Double(x + lugLength + bodyLength, y - shaftWidth / 2, shaftLength, shaftWidth));
+ body[1] = shaft;
+
+ double angle = getAngle();
+ AffineTransform rotation = null;
+ if (angle != 0) {
+ rotation = AffineTransform.getRotateInstance(angle, x, y);
+ }
+
+ GeneralPath path = new GeneralPath();
+ int step = 4;
+ for (double i = x + lugLength + bodyLength + step; i <= x + lugLength + bodyLength + shaftLength; i += step) {
+ Point2D p = new Point2D.Double(i, y - shaftWidth / 2 + 1);
+ if (rotation != null) {
+ rotation.transform(p, p);
+ }
+ path.moveTo(p.getX(), p.getY());
+ p = new Point2D.Double(i - step, y + shaftWidth / 2 - 1);
+ if (rotation != null) {
+ rotation.transform(p, p);
+ }
+ path.lineTo(p.getX(), p.getY());
+ }
+// Area pathArea = new Area(path);
+// pathArea.intersect(shaft);
+ body[2] = path;
+
+ // Create lugs.
+ Area lugs = new Area();
+
+ int spacing = (int) SPACING.convertToPixels();
+ Point2D[] untransformedControlPoints = new Point2D[type == JackType.STEREO ? 3 : 2];
+
+ untransformedControlPoints[0] = new Point2D.Double(x, y);
+ untransformedControlPoints[1] = new Point2D.Double(x + bodyLength, y);
+ if (type == JackType.STEREO) {
+ untransformedControlPoints[2] = new Point2D.Double(x, y + 2 * spacing);
+ }
+
+ for (int i = 0; i < untransformedControlPoints.length; i++) {
+ Point2D point = untransformedControlPoints[i];
+ Area lug = new Area(new Ellipse2D.Double(point.getX() - lugWidth / 2, point.getY() - lugWidth / 2, lugWidth, lugWidth));
+ lug.add(new Area(new Rectangle2D.Double(point.getX(), point.getY() - lugWidth / 2, lugLength, lugWidth)));
+ lug.subtract(new Area(new Ellipse2D.Double(point.getX() - lugHoleSize / 2, point.getY() - lugHoleSize / 2, lugHoleSize,
+ lugHoleSize)));
+ lugs.add(lug);
+ }
+
+ body[3] = lugs;
+
+ // Rotate everything that's of Area type, e.g. everything but lines.
+ if (rotation != null) {
+ for (Shape shape : body) {
+ if (shape instanceof Area) {
+ Area area = (Area) shape;
+ area.transform(rotation);
+ }
+ }
+ }
+ }
+ return body;
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ Shape[] body = getBody();
+
+ // Rectangle bounds = body.getBounds();
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+// if (componentState != ComponentState.DRAGGING) {
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : BODY_COLOR);
+ g2d.fill(body[0]);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : SHAFT_COLOR);
+ g2d.fill(body[1]);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : METAL_COLOR);
+ g2d.fill(body[3]);
+ g2d.setComposite(oldComposite);
+// }
+
+ drawingObserver.stopTracking();
+
+ Color finalBorderColor;
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalBorderColor = theme.getOutlineColor();
+ } else {
+ finalBorderColor = BORDER_COLOR;
+ }
+
+ g2d.setColor(finalBorderColor);
+ g2d.draw(body[0]);
+ g2d.draw(body[1]);
+ if (!outlineMode) {
+ g2d.setColor(SHAFT_COLOR.darker());
+// g2d.fill(body[2]);
+ g2d.draw(body[2]);
+ }
+
+ // Pins are the last piece.
+ g2d.setColor(outlineMode ? finalBorderColor : METAL_COLOR.darker());
+ g2d.draw(body[3]);
+
+ Color finalLabelColor;
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : theme.getOutlineColor();
+ } else {
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : LABEL_COLOR;
+ }
+ g2d.setColor(finalLabelColor);
+ g2d.setFont(project.getFont());
+
+ // Override font size
+ if (getFontSizeOverride() != null)
+ g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride()));
+
+ Rectangle bounds = body[0].getBounds();
+ double centerX = bounds.getX() + bounds.width / 2;
+ double centerY = bounds.getY() + bounds.height / 2;
+ StringUtils.drawCenteredText(g2d, name, centerX, centerY, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
+
+ drawSelectionOutline(g2d, componentState, outlineMode, project, drawingObserver);
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int bodyWidth = getClosestOdd(width * 3 / 5);
+ int tailWidth = getClosestOdd(width * 3 / 10);
+
+ g2d.setColor(SHAFT_COLOR);
+ g2d.fillRect((width - tailWidth) / 2, 1, tailWidth, height / 2);
+ g2d.setColor(BORDER_COLOR);
+ g2d.drawRect((width - tailWidth) / 2, 1, tailWidth, height / 2);
+
+ g2d.setColor(BODY_COLOR);
+ g2d.fillRect((width - bodyWidth) / 2, height / 7 + 1, bodyWidth, height * 5 / 7);
+ g2d.setColor(BORDER_COLOR);
+ g2d.drawRect((width - bodyWidth) / 2, height / 7 + 1, bodyWidth, height * 5 / 7);
+
+ g2d.setColor(METAL_COLOR);
+
+ g2d.fillRect(width * 7 / 16, height * 6 / 7 + 1, width / 8, height / 7 - 1);
+ g2d.fillRect(width * 7 / 16, height / 7 + 2, width / 8, height / 7 - 1);
+
+ g2d.setColor(LABEL_COLOR);
+ g2d.setFont(LABEL_FONT.deriveFont(width / 3.5f));
+
+ RenderingHints rh = new RenderingHints(
+ RenderingHints.KEY_TEXT_ANTIALIASING,
+ RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
+ g2d.setRenderingHints(rh);
+
+ StringUtils.drawCenteredText(g2d, "6.3", width / 2 - 1, height / 2, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
+ }
+
+ @Override
+ public int getControlPointCount() {
+ return controlPoints.length;
+ }
+
+ @Override
+ public Point2D getControlPoint(int index) {
+ return controlPoints[index];
+ }
+
+ @Override
+ public void setControlPoint(Point2D point, int index) {
+ controlPoints[index].setLocation(point);
+ body = null;
+ }
+
+ @Override
+ public boolean isControlPointSticky(int index) {
+ return true;
+ }
+
+ @Override
+ public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
+ return VisibilityPolicy.NEVER;
+ }
+
+ @EditableProperty(name = "Type")
+ public JackType getValue() {
+ return type;
+ }
+
+ public void setValue(JackType type) {
+ this.type = type;
+ updateControlPoints();
+ }
+
+ @EditableProperty
+ public Orientation getOrientation() {
+ return orientation;
+ }
+
+ public void setOrientation(Orientation orientation) {
+ this.orientation = orientation;
+ updateControlPoints();
+ }
+
+ @Override
+ public String getControlPointNodeName(int index) {
+ switch (index) {
+ case 0:
+ return "Tip";
+ case 1:
+ return "Sleeve";
+ case 2:
+ return "Ring";
+ }
+ return null;
+ }
+
+ @Override
+ public boolean canPointMoveFreely(int pointIndex) {
+ return false;
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/DIPSwitch.java b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/DIPSwitch.java
index 342be275f..b7feef337 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/DIPSwitch.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/DIPSwitch.java
@@ -31,10 +31,7 @@ import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import org.diylc.appframework.miscutils.ConfigurationManager;
-import org.diylc.common.Display;
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.Orientation;
+import org.diylc.common.*;
import org.diylc.components.AbstractTransparentComponent;
import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent;
@@ -97,7 +94,7 @@ public class DIPSwitch extends AbstractTransparentComponent implements I
public DIPSwitch() {
super();
updateControlPoints();
- alpha = (byte) 100;
+ this.alphaPercent = new Percentage(100);
}
@EditableProperty
@@ -348,10 +345,7 @@ public class DIPSwitch extends AbstractTransparentComponent implements I
pinWidth, pinHeight);
}
}
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getBodyColor());
g2d.fill(mainArea);
g2d.setComposite(oldComposite);
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/DrillHole.java b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/DrillHole.java
index b39a79bbd..4e494e708 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/DrillHole.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/DrillHole.java
@@ -79,10 +79,7 @@ public class DrillHole extends AbstractTransparentComponent
gerberDrawingObserver.startGerberOutput(drillLayer, GerberFunctions.COMPONENT_DRILL, false);
}
- Composite oldComposite = g2d.getComposite();
- if (getAlpha() < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * getAlpha() / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
// Draw white circle (hole)
g2d.setColor(Color.white);
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/FuseHolderPanel.java b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/FuseHolderPanel.java
index e115957ad..87c697a73 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/FuseHolderPanel.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/FuseHolderPanel.java
@@ -174,10 +174,7 @@ public class FuseHolderPanel extends AbstractMultiPartComponent {
Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
// Draw body if available.
if (body != null) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getBodyColor());
for (Area a : body)
if (a != null) {
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/IECSocket.java b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/IECSocket.java
index e87ea5014..52f018ea0 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/IECSocket.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/IECSocket.java
@@ -197,10 +197,7 @@ public class IECSocket extends AbstractMultiPartComponent {
Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
// Draw body if available.
if (body != null) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getBodyColor());
for (Area a : body)
if (a != null) {
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/MiniRelay.java b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/MiniRelay.java
index 7a3e6bef4..61ccb7ec1 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/MiniRelay.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/MiniRelay.java
@@ -1,477 +1,474 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.electromechanical;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.FontMetrics;
-import java.awt.Graphics2D;
-import java.awt.Rectangle;
-import java.awt.geom.Area;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.geom.RoundRectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.common.Display;
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.Orientation;
-import org.diylc.components.AbstractLabeledComponent;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-import org.diylc.core.VisibilityPolicy;
-import org.diylc.core.annotations.ComponentDescriptor;
-import org.diylc.core.annotations.EditableProperty;
-import org.diylc.core.gerber.IGerberComponentSimple;
-import org.diylc.core.measures.Size;
-import org.diylc.core.measures.SizeUnit;
-import org.diylc.core.measures.Voltage;
-import org.diylc.core.measures.VoltageUnit;
-import org.diylc.utils.Constants;
-
-@ComponentDescriptor(name = "Mini Relay", author = "Branislav Stojkovic", category = "Electro-Mechanical",
- instanceNamePrefix = "RY", description = "Miniature PCB mount relay, like Omron G5V-1 or G5V-2",
- zOrder = IDIYComponent.COMPONENT, enableCache = true)
-public class MiniRelay extends AbstractLabeledComponent implements IGerberComponentSimple {
-
- private static final long serialVersionUID = 1L;
-
- public static Color BODY_COLOR = Color.gray;
- public static Color BORDER_COLOR = Color.gray.darker();
- public static Color PIN_COLOR = Color.decode("#00B2EE");
- public static Color PIN_BORDER_COLOR = PIN_COLOR.darker();
- public static Color INDENT_COLOR = Color.gray.darker();
- public static Color LABEL_COLOR = Color.white;
- public static int EDGE_RADIUS = 6;
- public static Size PIN_SIZE = new Size(0.03d, SizeUnit.in);
- public static Size INDENT_SIZE = new Size(0.07d, SizeUnit.in);
- public static Size BODY_MARGIN = new Size(0.05d, SizeUnit.in);
-
- public static Size MINI_PIN_SPACING = new Size(0.2d, SizeUnit.in);
- public static Size MINI_ROW_SPACING = new Size(0.3d, SizeUnit.in);
- public static Size MINI_WIDTH = new Size(20.1d, SizeUnit.mm);
- public static Size MINI_HEIGHT = new Size(9.9d, SizeUnit.mm);
- public static Size MINI_GAP = new Size(0.1d, SizeUnit.in);
-
- public static Size ULTRA_PIN_SPACING = new Size(0.1d, SizeUnit.in);
- public static Size ULTRA_ROW_SPACING = new Size(0.2d, SizeUnit.in);
- public static Size ULTRA_WIDTH = new Size(12.2d, SizeUnit.mm);
- public static Size ULTRA_HEIGHT = new Size(7.2d, SizeUnit.mm);
- public static Size ULTRA_GAP = new Size(0.1d, SizeUnit.in);
-
- private String value = "";
- private Orientation orientation = Orientation.DEFAULT;
-
- private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0)};
- protected Display display = Display.NAME;
- private RelayType type = RelayType.DPDT;
- private RelaySize size = RelaySize.Miniature;
- private Voltage voltage = new Voltage(12d, VoltageUnit.V);
- transient private Area[] body;
-
- public MiniRelay() {
- super();
- updateControlPoints();
- }
-
- @EditableProperty
- public String getValue() {
- return value;
- }
-
- public void setValue(String value) {
- this.value = value;
- }
-
- @EditableProperty
- public Orientation getOrientation() {
- return orientation;
- }
-
- public void setOrientation(Orientation orientation) {
- this.orientation = orientation;
- updateControlPoints();
- // Reset body shape.
- body = null;
- }
-
- @EditableProperty
- public Display getDisplay() {
- if (display == null) {
- display = Display.VALUE;
- }
- return display;
- }
-
- public void setDisplay(Display display) {
- this.display = display;
- }
-
- @Override
- public int getControlPointCount() {
- return controlPoints.length;
- }
-
- @Override
- public Point2D getControlPoint(int index) {
- return controlPoints[index];
- }
-
- @Override
- public boolean isControlPointSticky(int index) {
- return true;
- }
-
- @Override
- public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
- return VisibilityPolicy.NEVER;
- }
-
- @Override
- public void setControlPoint(Point2D point, int index) {
- controlPoints[index].setLocation(point);
- body = null;
- }
-
- private void updateControlPoints() {
- Point2D firstPoint = controlPoints[0];
- int pinCount = 0;
- switch (type) {
- case DPDT:
- pinCount = 8;
- break;
- case SPDT:
- pinCount = 6;
- break;
- default:
- throw new RuntimeException("Unexpected type: " + type);
- }
- controlPoints = new Point2D[pinCount];
- controlPoints[0] = firstPoint;
- int pinSpacing =
- size == RelaySize.Miniature ? (int) MINI_PIN_SPACING.convertToPixels() : (int) ULTRA_PIN_SPACING
- .convertToPixels();
- int rowSpacing =
- size == RelaySize.Miniature ? (int) MINI_ROW_SPACING.convertToPixels() : (int) ULTRA_ROW_SPACING
- .convertToPixels();
- // Update control points.
- int dx1;
- int dy1;
- int dx2;
- int dy2;
- int delta = 0;
- for (int i = 0; i < pinCount / 2; i++) {
- if (i == 1) {
- delta = size == RelaySize.Miniature ? (int) MINI_GAP.convertToPixels() : (int) ULTRA_GAP.convertToPixels();
- if (type == RelayType.SPDT) {
- delta += pinSpacing;
- }
- }
- switch (orientation) {
- case DEFAULT:
- dx1 = 0;
- dy1 = i * pinSpacing + delta;
- dx2 = rowSpacing;
- dy2 = i * pinSpacing + delta;
- break;
- case _90:
- dx1 = -(i * pinSpacing + delta);
- dy1 = 0;
- dx2 = -(i * pinSpacing + delta);
- dy2 = rowSpacing;
- break;
- case _180:
- dx1 = 0;
- dy1 = -(i * pinSpacing + delta);
- dx2 = -rowSpacing;
- dy2 = -(i * pinSpacing + delta);
- break;
- case _270:
- dx1 = i * pinSpacing + delta;
- dy1 = 0;
- dx2 = i * pinSpacing + delta;
- dy2 = -rowSpacing;
- break;
- default:
- throw new RuntimeException("Unexpected orientation: " + orientation);
- }
- controlPoints[i] = new Point2D.Double(firstPoint.getX() + dx1, firstPoint.getY() + dy1);
- controlPoints[i + pinCount / 2] = new Point2D.Double(firstPoint.getX() + dx2, firstPoint.getY() + dy2);
- }
- }
-
- public Area[] getBody() {
- if (body == null) {
- body = new Area[2];
- double x = controlPoints[0].getX();
- double y = controlPoints[0].getY();
- double centerX = (controlPoints[0].getX() + controlPoints[controlPoints.length - 1].getX()) / 2;
- double centerY = (controlPoints[0].getY() + controlPoints[controlPoints.length - 1].getY()) / 2;
- int bodyMargin = getClosestOdd(BODY_MARGIN.convertToPixels());
- int width = 0;
- int height = 0;
- int rowSpacing =
- size == RelaySize.Miniature ? (int) MINI_ROW_SPACING.convertToPixels() : (int) ULTRA_ROW_SPACING
- .convertToPixels();
- Area indentation = null;
- int indentationSize = getClosestOdd(INDENT_SIZE.convertToPixels());
- switch (orientation) {
- case DEFAULT:
- width = (int) (size == RelaySize.Miniature ? MINI_HEIGHT.convertToPixels() : ULTRA_HEIGHT.convertToPixels());
- height = (int) (size == RelaySize.Miniature ? MINI_WIDTH.convertToPixels() : ULTRA_WIDTH.convertToPixels());
- x -= bodyMargin;
- y -= bodyMargin;
- indentation =
- new Area(new Rectangle2D.Double(centerX - indentationSize / 2, y - indentationSize / 2, indentationSize,
- indentationSize));
- break;
- case _90:
- width = (int) (size == RelaySize.Miniature ? MINI_WIDTH.convertToPixels() : ULTRA_WIDTH.convertToPixels());
- height = (int) (size == RelaySize.Miniature ? MINI_HEIGHT.convertToPixels() : ULTRA_HEIGHT.convertToPixels());
- x -= -bodyMargin + width;
- y -= bodyMargin;
- indentation =
- new Area(new Rectangle2D.Double(x + width - indentationSize / 2, centerY - indentationSize / 2,
- indentationSize, indentationSize));
- break;
- case _180:
- width = (int) (size == RelaySize.Miniature ? MINI_HEIGHT.convertToPixels() : ULTRA_HEIGHT.convertToPixels());
- height = (int) (size == RelaySize.Miniature ? MINI_WIDTH.convertToPixels() : ULTRA_WIDTH.convertToPixels());
- x -= rowSpacing + bodyMargin;
- y -= -bodyMargin + height;
- indentation =
- new Area(new Rectangle2D.Double(centerX - indentationSize / 2, y + height - indentationSize / 2,
- indentationSize, indentationSize));
- break;
- case _270:
- width = (int) (size == RelaySize.Miniature ? MINI_WIDTH.convertToPixels() : ULTRA_WIDTH.convertToPixels());
- height = (int) (size == RelaySize.Miniature ? MINI_HEIGHT.convertToPixels() : ULTRA_HEIGHT.convertToPixels());
- x -= bodyMargin;
- y -= bodyMargin + rowSpacing;
- indentation =
- new Area(new Rectangle2D.Double(x - indentationSize / 2, centerY - indentationSize / 2, indentationSize,
- indentationSize));
- break;
- default:
- throw new RuntimeException("Unexpected orientation: " + orientation);
- }
- body[0] =
- new Area(new RoundRectangle2D.Double(centerX - width / 2, centerY - height / 2, width, height, EDGE_RADIUS,
- EDGE_RADIUS));
- body[1] = indentation;
- if (indentation != null) {
- indentation.intersect(body[0]);
- }
- }
- return body;
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- if (checkPointsClipped(g2d.getClip())) {
- return;
- }
- Area mainArea = getBody()[0];
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : BODY_COLOR);
- g2d.fill(mainArea);
- g2d.setComposite(oldComposite);
-
- drawingObserver.stopTracking();
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
-
- Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- int pinSize = (int) PIN_SIZE.convertToPixels() / 2 * 2;
- 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.setColor(outlineMode ? theme.getOutlineColor() : PIN_BORDER_COLOR);
- g2d.drawOval((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize);
- }
-
- Color finalBorderColor;
- if (outlineMode) {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : BORDER_COLOR;
- }
- g2d.setColor(finalBorderColor);
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
- if (outlineMode) {
- Area area = new Area(mainArea);
- area.subtract(getBody()[1]);
- g2d.draw(area);
- } else {
- g2d.draw(mainArea);
- if (getBody()[1] != null) {
- g2d.setColor(INDENT_COLOR);
- g2d.fill(getBody()[1]);
- }
- }
- // Draw label.
- g2d.setFont(project.getFont());
-
- // Override font size
- if (getFontSizeOverride() != null)
- g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride()));
-
- Color finalLabelColor;
- if (outlineMode) {
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : theme.getOutlineColor();
- } else {
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : LABEL_COLOR;
- }
- g2d.setColor(finalLabelColor);
- FontMetrics fontMetrics = g2d.getFontMetrics(g2d.getFont());
- String label = "";
- label = display == Display.VALUE ? getValue() : getName();
- if (display == Display.NONE) {
- label = "";
- }
- if (display == Display.BOTH) {
- label = getName() + " " + (getValue() == null ? "" : getValue().toString());
- }
- Rectangle2D rect = fontMetrics.getStringBounds(label, g2d);
- int textHeight = (int) (rect.getHeight());
- int textWidth = (int) (rect.getWidth());
- // Center text horizontally and vertically
- Rectangle bounds = mainArea.getBounds();
- double x = bounds.getX() + (bounds.width - textWidth) / 2;
- double y = bounds.getY() + (bounds.height - textHeight) / 2 + fontMetrics.getAscent();
- g2d.drawString(label, (int)x, (int)y);
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int radius = 6 * width / 32;
- g2d.setColor(BODY_COLOR);
- g2d.fillRoundRect(width / 6, 1, 4 * width / 6, height - 4, radius, radius);
- g2d.setColor(BORDER_COLOR);
- g2d.drawRoundRect(width / 6, 1, 4 * width / 6, height - 4, radius, radius);
- int pinSize = 2 * width / 32;
- g2d.setColor(PIN_COLOR);
- for (int i = 0; i < 4; i++) {
- if (i == 1)
- continue;
- g2d.fillOval(width / 4, (height / 5) * (i + 1) - 1, pinSize, pinSize);
- g2d.fillOval(3 * width / 4 - pinSize, (height / 5) * (i + 1) - 1, pinSize, pinSize);
- }
- }
-
- @Override
- public String getValueForDisplay() {
- return getValue() + " " + getType() + " " + getVoltage();
- }
-
- @EditableProperty
- public RelayType getType() {
- return type;
- }
-
- public void setType(RelayType type) {
- this.type = type;
- updateControlPoints();
- // Invalidate body
- this.body = null;
- }
-
- @EditableProperty
- public Voltage getVoltage() {
- return voltage;
- }
-
- public void setVoltage(Voltage voltage) {
- this.voltage = voltage;
- }
-
- @EditableProperty
- public RelaySize getSize() {
- return size;
- }
-
- public void setSize(RelaySize size) {
- this.size = size;
- updateControlPoints();
- // Invalidate body
- this.body = null;
- }
-
- @Override
- public boolean canPointMoveFreely(int pointIndex) {
- return false;
- }
-
- @Override
- public Rectangle2D getCachingBounds() {
- double minX = Integer.MAX_VALUE;
- double maxX = Integer.MIN_VALUE;
- double minY = Integer.MAX_VALUE;
- double maxY = Integer.MIN_VALUE;
- double margin = 50;
- for (int i = 0; i < getControlPointCount(); i++) {
- Point2D p = getControlPoint(i);
- if (p.getX() < minX)
- minX = p.getX();
- if (p.getX() > maxX)
- maxX = p.getX();
- if (p.getY() < minY)
- minY = p.getY();
- if (p.getY() > maxY)
- maxY = p.getY();
- }
-
- return new Rectangle2D.Double(minX - margin, minY - margin, maxX - minX + 2 * margin, maxY - minY + 2 * margin);
- }
-
- public static enum RelayType {
- SPDT, DPDT;
- }
-
- public static enum RelaySize {
-
- Miniature, Ultra_miniature;
-
- public String toString() {
- return name().replace('_', '-');
- };
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.electromechanical;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.geom.Area;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.common.Display;
+import org.diylc.common.IPlugInPort;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.Orientation;
+import org.diylc.components.AbstractLabeledComponent;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+import org.diylc.core.VisibilityPolicy;
+import org.diylc.core.annotations.ComponentDescriptor;
+import org.diylc.core.annotations.EditableProperty;
+import org.diylc.core.gerber.IGerberComponentSimple;
+import org.diylc.core.measures.Size;
+import org.diylc.core.measures.SizeUnit;
+import org.diylc.core.measures.Voltage;
+import org.diylc.core.measures.VoltageUnit;
+import org.diylc.utils.Constants;
+
+@ComponentDescriptor(name = "Mini Relay", author = "Branislav Stojkovic", category = "Electro-Mechanical",
+ instanceNamePrefix = "RY", description = "Miniature PCB mount relay, like Omron G5V-1 or G5V-2",
+ zOrder = IDIYComponent.COMPONENT, enableCache = true)
+public class MiniRelay extends AbstractLabeledComponent implements IGerberComponentSimple {
+
+ private static final long serialVersionUID = 1L;
+
+ public static Color BODY_COLOR = Color.gray;
+ public static Color BORDER_COLOR = Color.gray.darker();
+ public static Color PIN_COLOR = Color.decode("#00B2EE");
+ public static Color PIN_BORDER_COLOR = PIN_COLOR.darker();
+ public static Color INDENT_COLOR = Color.gray.darker();
+ public static Color LABEL_COLOR = Color.white;
+ public static int EDGE_RADIUS = 6;
+ public static Size PIN_SIZE = new Size(0.03d, SizeUnit.in);
+ public static Size INDENT_SIZE = new Size(0.07d, SizeUnit.in);
+ public static Size BODY_MARGIN = new Size(0.05d, SizeUnit.in);
+
+ public static Size MINI_PIN_SPACING = new Size(0.2d, SizeUnit.in);
+ public static Size MINI_ROW_SPACING = new Size(0.3d, SizeUnit.in);
+ public static Size MINI_WIDTH = new Size(20.1d, SizeUnit.mm);
+ public static Size MINI_HEIGHT = new Size(9.9d, SizeUnit.mm);
+ public static Size MINI_GAP = new Size(0.1d, SizeUnit.in);
+
+ public static Size ULTRA_PIN_SPACING = new Size(0.1d, SizeUnit.in);
+ public static Size ULTRA_ROW_SPACING = new Size(0.2d, SizeUnit.in);
+ public static Size ULTRA_WIDTH = new Size(12.2d, SizeUnit.mm);
+ public static Size ULTRA_HEIGHT = new Size(7.2d, SizeUnit.mm);
+ public static Size ULTRA_GAP = new Size(0.1d, SizeUnit.in);
+
+ private String value = "";
+ private Orientation orientation = Orientation.DEFAULT;
+
+ private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0)};
+ protected Display display = Display.NAME;
+ private RelayType type = RelayType.DPDT;
+ private RelaySize size = RelaySize.Miniature;
+ private Voltage voltage = new Voltage(12d, VoltageUnit.V);
+ transient private Area[] body;
+
+ public MiniRelay() {
+ super();
+ updateControlPoints();
+ }
+
+ @EditableProperty
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ @EditableProperty
+ public Orientation getOrientation() {
+ return orientation;
+ }
+
+ public void setOrientation(Orientation orientation) {
+ this.orientation = orientation;
+ updateControlPoints();
+ // Reset body shape.
+ body = null;
+ }
+
+ @EditableProperty
+ public Display getDisplay() {
+ if (display == null) {
+ display = Display.VALUE;
+ }
+ return display;
+ }
+
+ public void setDisplay(Display display) {
+ this.display = display;
+ }
+
+ @Override
+ public int getControlPointCount() {
+ return controlPoints.length;
+ }
+
+ @Override
+ public Point2D getControlPoint(int index) {
+ return controlPoints[index];
+ }
+
+ @Override
+ public boolean isControlPointSticky(int index) {
+ return true;
+ }
+
+ @Override
+ public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
+ return VisibilityPolicy.NEVER;
+ }
+
+ @Override
+ public void setControlPoint(Point2D point, int index) {
+ controlPoints[index].setLocation(point);
+ body = null;
+ }
+
+ private void updateControlPoints() {
+ Point2D firstPoint = controlPoints[0];
+ int pinCount = 0;
+ switch (type) {
+ case DPDT:
+ pinCount = 8;
+ break;
+ case SPDT:
+ pinCount = 6;
+ break;
+ default:
+ throw new RuntimeException("Unexpected type: " + type);
+ }
+ controlPoints = new Point2D[pinCount];
+ controlPoints[0] = firstPoint;
+ int pinSpacing =
+ size == RelaySize.Miniature ? (int) MINI_PIN_SPACING.convertToPixels() : (int) ULTRA_PIN_SPACING
+ .convertToPixels();
+ int rowSpacing =
+ size == RelaySize.Miniature ? (int) MINI_ROW_SPACING.convertToPixels() : (int) ULTRA_ROW_SPACING
+ .convertToPixels();
+ // Update control points.
+ int dx1;
+ int dy1;
+ int dx2;
+ int dy2;
+ int delta = 0;
+ for (int i = 0; i < pinCount / 2; i++) {
+ if (i == 1) {
+ delta = size == RelaySize.Miniature ? (int) MINI_GAP.convertToPixels() : (int) ULTRA_GAP.convertToPixels();
+ if (type == RelayType.SPDT) {
+ delta += pinSpacing;
+ }
+ }
+ switch (orientation) {
+ case DEFAULT:
+ dx1 = 0;
+ dy1 = i * pinSpacing + delta;
+ dx2 = rowSpacing;
+ dy2 = i * pinSpacing + delta;
+ break;
+ case _90:
+ dx1 = -(i * pinSpacing + delta);
+ dy1 = 0;
+ dx2 = -(i * pinSpacing + delta);
+ dy2 = rowSpacing;
+ break;
+ case _180:
+ dx1 = 0;
+ dy1 = -(i * pinSpacing + delta);
+ dx2 = -rowSpacing;
+ dy2 = -(i * pinSpacing + delta);
+ break;
+ case _270:
+ dx1 = i * pinSpacing + delta;
+ dy1 = 0;
+ dx2 = i * pinSpacing + delta;
+ dy2 = -rowSpacing;
+ break;
+ default:
+ throw new RuntimeException("Unexpected orientation: " + orientation);
+ }
+ controlPoints[i] = new Point2D.Double(firstPoint.getX() + dx1, firstPoint.getY() + dy1);
+ controlPoints[i + pinCount / 2] = new Point2D.Double(firstPoint.getX() + dx2, firstPoint.getY() + dy2);
+ }
+ }
+
+ public Area[] getBody() {
+ if (body == null) {
+ body = new Area[2];
+ double x = controlPoints[0].getX();
+ double y = controlPoints[0].getY();
+ double centerX = (controlPoints[0].getX() + controlPoints[controlPoints.length - 1].getX()) / 2;
+ double centerY = (controlPoints[0].getY() + controlPoints[controlPoints.length - 1].getY()) / 2;
+ int bodyMargin = getClosestOdd(BODY_MARGIN.convertToPixels());
+ int width = 0;
+ int height = 0;
+ int rowSpacing =
+ size == RelaySize.Miniature ? (int) MINI_ROW_SPACING.convertToPixels() : (int) ULTRA_ROW_SPACING
+ .convertToPixels();
+ Area indentation = null;
+ int indentationSize = getClosestOdd(INDENT_SIZE.convertToPixels());
+ switch (orientation) {
+ case DEFAULT:
+ width = (int) (size == RelaySize.Miniature ? MINI_HEIGHT.convertToPixels() : ULTRA_HEIGHT.convertToPixels());
+ height = (int) (size == RelaySize.Miniature ? MINI_WIDTH.convertToPixels() : ULTRA_WIDTH.convertToPixels());
+ x -= bodyMargin;
+ y -= bodyMargin;
+ indentation =
+ new Area(new Rectangle2D.Double(centerX - indentationSize / 2, y - indentationSize / 2, indentationSize,
+ indentationSize));
+ break;
+ case _90:
+ width = (int) (size == RelaySize.Miniature ? MINI_WIDTH.convertToPixels() : ULTRA_WIDTH.convertToPixels());
+ height = (int) (size == RelaySize.Miniature ? MINI_HEIGHT.convertToPixels() : ULTRA_HEIGHT.convertToPixels());
+ x -= -bodyMargin + width;
+ y -= bodyMargin;
+ indentation =
+ new Area(new Rectangle2D.Double(x + width - indentationSize / 2, centerY - indentationSize / 2,
+ indentationSize, indentationSize));
+ break;
+ case _180:
+ width = (int) (size == RelaySize.Miniature ? MINI_HEIGHT.convertToPixels() : ULTRA_HEIGHT.convertToPixels());
+ height = (int) (size == RelaySize.Miniature ? MINI_WIDTH.convertToPixels() : ULTRA_WIDTH.convertToPixels());
+ x -= rowSpacing + bodyMargin;
+ y -= -bodyMargin + height;
+ indentation =
+ new Area(new Rectangle2D.Double(centerX - indentationSize / 2, y + height - indentationSize / 2,
+ indentationSize, indentationSize));
+ break;
+ case _270:
+ width = (int) (size == RelaySize.Miniature ? MINI_WIDTH.convertToPixels() : ULTRA_WIDTH.convertToPixels());
+ height = (int) (size == RelaySize.Miniature ? MINI_HEIGHT.convertToPixels() : ULTRA_HEIGHT.convertToPixels());
+ x -= bodyMargin;
+ y -= bodyMargin + rowSpacing;
+ indentation =
+ new Area(new Rectangle2D.Double(x - indentationSize / 2, centerY - indentationSize / 2, indentationSize,
+ indentationSize));
+ break;
+ default:
+ throw new RuntimeException("Unexpected orientation: " + orientation);
+ }
+ body[0] =
+ new Area(new RoundRectangle2D.Double(centerX - width / 2, centerY - height / 2, width, height, EDGE_RADIUS,
+ EDGE_RADIUS));
+ body[1] = indentation;
+ if (indentation != null) {
+ indentation.intersect(body[0]);
+ }
+ }
+ return body;
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ if (checkPointsClipped(g2d.getClip())) {
+ return;
+ }
+ Area mainArea = getBody()[0];
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : BODY_COLOR);
+ g2d.fill(mainArea);
+ g2d.setComposite(oldComposite);
+
+ drawingObserver.stopTracking();
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+
+ Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ int pinSize = (int) PIN_SIZE.convertToPixels() / 2 * 2;
+ 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.setColor(outlineMode ? theme.getOutlineColor() : PIN_BORDER_COLOR);
+ g2d.drawOval((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize);
+ }
+
+ Color finalBorderColor;
+ if (outlineMode) {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : BORDER_COLOR;
+ }
+ g2d.setColor(finalBorderColor);
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+ if (outlineMode) {
+ Area area = new Area(mainArea);
+ area.subtract(getBody()[1]);
+ g2d.draw(area);
+ } else {
+ g2d.draw(mainArea);
+ if (getBody()[1] != null) {
+ g2d.setColor(INDENT_COLOR);
+ g2d.fill(getBody()[1]);
+ }
+ }
+ // Draw label.
+ g2d.setFont(project.getFont());
+
+ // Override font size
+ if (getFontSizeOverride() != null)
+ g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride()));
+
+ Color finalLabelColor;
+ if (outlineMode) {
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : theme.getOutlineColor();
+ } else {
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : LABEL_COLOR;
+ }
+ g2d.setColor(finalLabelColor);
+ FontMetrics fontMetrics = g2d.getFontMetrics(g2d.getFont());
+ String label = "";
+ label = display == Display.VALUE ? getValue() : getName();
+ if (display == Display.NONE) {
+ label = "";
+ }
+ if (display == Display.BOTH) {
+ label = getName() + " " + (getValue() == null ? "" : getValue().toString());
+ }
+ Rectangle2D rect = fontMetrics.getStringBounds(label, g2d);
+ int textHeight = (int) (rect.getHeight());
+ int textWidth = (int) (rect.getWidth());
+ // Center text horizontally and vertically
+ Rectangle bounds = mainArea.getBounds();
+ double x = bounds.getX() + (bounds.width - textWidth) / 2;
+ double y = bounds.getY() + (bounds.height - textHeight) / 2 + fontMetrics.getAscent();
+ g2d.drawString(label, (int)x, (int)y);
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int radius = 6 * width / 32;
+ g2d.setColor(BODY_COLOR);
+ g2d.fillRoundRect(width / 6, 1, 4 * width / 6, height - 4, radius, radius);
+ g2d.setColor(BORDER_COLOR);
+ g2d.drawRoundRect(width / 6, 1, 4 * width / 6, height - 4, radius, radius);
+ int pinSize = 2 * width / 32;
+ g2d.setColor(PIN_COLOR);
+ for (int i = 0; i < 4; i++) {
+ if (i == 1)
+ continue;
+ g2d.fillOval(width / 4, (height / 5) * (i + 1) - 1, pinSize, pinSize);
+ g2d.fillOval(3 * width / 4 - pinSize, (height / 5) * (i + 1) - 1, pinSize, pinSize);
+ }
+ }
+
+ @Override
+ public String getValueForDisplay() {
+ return getValue() + " " + getType() + " " + getVoltage();
+ }
+
+ @EditableProperty
+ public RelayType getType() {
+ return type;
+ }
+
+ public void setType(RelayType type) {
+ this.type = type;
+ updateControlPoints();
+ // Invalidate body
+ this.body = null;
+ }
+
+ @EditableProperty
+ public Voltage getVoltage() {
+ return voltage;
+ }
+
+ public void setVoltage(Voltage voltage) {
+ this.voltage = voltage;
+ }
+
+ @EditableProperty
+ public RelaySize getSize() {
+ return size;
+ }
+
+ public void setSize(RelaySize size) {
+ this.size = size;
+ updateControlPoints();
+ // Invalidate body
+ this.body = null;
+ }
+
+ @Override
+ public boolean canPointMoveFreely(int pointIndex) {
+ return false;
+ }
+
+ @Override
+ public Rectangle2D getCachingBounds() {
+ double minX = Integer.MAX_VALUE;
+ double maxX = Integer.MIN_VALUE;
+ double minY = Integer.MAX_VALUE;
+ double maxY = Integer.MIN_VALUE;
+ double margin = 50;
+ for (int i = 0; i < getControlPointCount(); i++) {
+ Point2D p = getControlPoint(i);
+ if (p.getX() < minX)
+ minX = p.getX();
+ if (p.getX() > maxX)
+ maxX = p.getX();
+ if (p.getY() < minY)
+ minY = p.getY();
+ if (p.getY() > maxY)
+ maxY = p.getY();
+ }
+
+ return new Rectangle2D.Double(minX - margin, minY - margin, maxX - minX + 2 * margin, maxY - minY + 2 * margin);
+ }
+
+ public static enum RelayType {
+ SPDT, DPDT;
+ }
+
+ public static enum RelaySize {
+
+ Miniature, Ultra_miniature;
+
+ public String toString() {
+ return name().replace('_', '-');
+ };
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/MiniToggleSwitch.java b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/MiniToggleSwitch.java
index b88db6d1d..48e0e2ea3 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/MiniToggleSwitch.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/MiniToggleSwitch.java
@@ -1,620 +1,617 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.electromechanical;
-
-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.Area;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.geom.RoundRectangle2D;
-
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.awt.StringUtils;
-import org.diylc.common.*;
-import org.diylc.components.AbstractTransparentComponent;
-import org.diylc.components.guitar.ToggleSwitchPositionPropertyValueSource;
-import org.diylc.components.transform.MiniToggleSwitchTransformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.ILayeredComponent;
-import org.diylc.core.ISwitch;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-import org.diylc.core.VisibilityPolicy;
-import org.diylc.core.annotations.ComponentDescriptor;
-import org.diylc.core.annotations.DynamicEditableProperty;
-import org.diylc.core.annotations.EditableProperty;
-import org.diylc.core.annotations.PositiveNonZeroMeasureValidator;
-import org.diylc.core.gerber.IGerberComponentSimple;
-import org.diylc.core.measures.Size;
-import org.diylc.core.measures.SizeUnit;
-import org.diylc.utils.Constants;
-import org.diylc.utils.SwitchUtils;
-
-@ComponentDescriptor(name = "Mini Toggle Switch", category = "Electro-Mechanical", author = "Branislav Stojkovic",
- description = "Panel mounted mini toggle switch", zOrder = IDIYComponent.COMPONENT,
- instanceNamePrefix = "SW", enableCache = true, transformer = MiniToggleSwitchTransformer.class)
-public class MiniToggleSwitch extends AbstractTransparentComponent implements ISwitch, ILayeredComponent, IGerberComponentSimple {
-
- private static final long serialVersionUID = 1L;
-
- private static Size SPACING = new Size(0.2d, SizeUnit.in);
- private static Size MARGIN = new Size(0.08d, SizeUnit.in);
- private static Size CIRCLE_SIZE = new Size(0.09d, SizeUnit.in);
- private static Size LUG_WIDTH = new Size(0.060d, SizeUnit.in);
- private static Size LUG_THICKNESS = new Size(0.02d, SizeUnit.in);
- private static Size MARKER_OFFSET = new Size(0.07d, SizeUnit.in);
-
- private static Color BODY_COLOR = Color.decode("#3299CC");
- private static Color BORDER_COLOR = BODY_COLOR.darker();
- private static Color CIRCLE_COLOR = Color.decode("#287ba4");
- private static Color TERMINAL_COLOR = LIGHT_METAL_COLOR;
- private static Color MARKER_COLOR = LIGHT_METAL_COLOR;
-
-
- protected Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0)};
- transient protected Shape body;
- protected ToggleSwitchType switchType = ToggleSwitchType.DPDT;
- private OrientationHV orientation = OrientationHV.VERTICAL;
- private Size spacing = SPACING;
-
- private Color bodyColor = BODY_COLOR;
- private Color borderColor = BORDER_COLOR;
- private Color terminalPadColor = CIRCLE_COLOR;
- private Color terminalColor = TERMINAL_COLOR;
-
- private Integer selectedPosition;
- private Boolean showMarkers;
-
- @Deprecated
- protected String name;
-
- public MiniToggleSwitch() {
- super();
- updateControlPoints();
- }
-
- private void updateControlPoints() {
- Point2D firstPoint = controlPoints[0];
- int spacing = (int) getSpacing().convertToPixels();
- switch (switchType) {
- case SPST:
- controlPoints = new Point2D[] {firstPoint, new Point2D.Double(firstPoint.getX(), firstPoint.getY() + spacing)};
- break;
- case SPDT:
- case SPDT_off:
- controlPoints =
- new Point2D[] {firstPoint, new Point2D.Double(firstPoint.getX(), firstPoint.getY() + spacing),
- new Point2D.Double(firstPoint.getX(), firstPoint.getY() + 2 * spacing)};
- break;
- case DPDT:
- case DPDT_off:
- case DPDT_ononon_1:
- case DPDT_ononon_2:
- controlPoints =
- new Point2D[] {firstPoint, new Point2D.Double(firstPoint.getX(), firstPoint.getY() + spacing),
- new Point2D.Double(firstPoint.getX(), firstPoint.getY() + 2 * spacing),
- new Point2D.Double(firstPoint.getX() + spacing, firstPoint.getY()),
- new Point2D.Double(firstPoint.getX() + spacing, firstPoint.getY() + spacing),
- new Point2D.Double(firstPoint.getX() + spacing, firstPoint.getY() + 2 * spacing)};
- break;
- case _3PDT:
- case _3PDT_off:
- controlPoints =
- new Point2D[] {firstPoint, new Point2D.Double(firstPoint.getX(), firstPoint.getY() + spacing),
- new Point2D.Double(firstPoint.getX(), firstPoint.getY() + 2 * spacing),
- new Point2D.Double(firstPoint.getX() + spacing, firstPoint.getY()),
- new Point2D.Double(firstPoint.getX() + spacing, firstPoint.getY() + spacing),
- new Point2D.Double(firstPoint.getX() + spacing, firstPoint.getY() + 2 * spacing),
- new Point2D.Double(firstPoint.getX() + 2 * spacing, firstPoint.getY()),
- new Point2D.Double(firstPoint.getX() + 2 * spacing, firstPoint.getY() + spacing),
- new Point2D.Double(firstPoint.getX() + 2 * spacing, firstPoint.getY() + 2 * spacing)};
- break;
- case _4PDT:
- case _4PDT_off:
- case _4PDT_ononon_1:
- case _4PDT_ononon_2:
- controlPoints =
- new Point2D[] {firstPoint, new Point2D.Double(firstPoint.getX(), firstPoint.getY() + spacing),
- new Point2D.Double(firstPoint.getX(), firstPoint.getY() + 2 * spacing),
- new Point2D.Double(firstPoint.getX() + spacing, firstPoint.getY()),
- new Point2D.Double(firstPoint.getX() + spacing, firstPoint.getY() + spacing),
- new Point2D.Double(firstPoint.getX() + spacing, firstPoint.getY() + 2 * spacing),
- new Point2D.Double(firstPoint.getX() + 2 * spacing, firstPoint.getY()),
- new Point2D.Double(firstPoint.getX() + 2 * spacing, firstPoint.getY() + spacing),
- new Point2D.Double(firstPoint.getX() + 2 * spacing, firstPoint.getY() + 2 * spacing),
- new Point2D.Double(firstPoint.getX() + 3 * spacing, firstPoint.getY()),
- new Point2D.Double(firstPoint.getX() + 3 * spacing, firstPoint.getY() + spacing),
- new Point2D.Double(firstPoint.getX() + 3 * spacing, firstPoint.getY() + 2 * spacing)};
- break;
- case _5PDT:
- case _5PDT_off:
- controlPoints =
- new Point2D[] {firstPoint, new Point2D.Double(firstPoint.getX(), firstPoint.getY() + spacing),
- new Point2D.Double(firstPoint.getX(), firstPoint.getY() + 2 * spacing),
- new Point2D.Double(firstPoint.getX() + spacing, firstPoint.getY()),
- new Point2D.Double(firstPoint.getX() + spacing, firstPoint.getY() + spacing),
- new Point2D.Double(firstPoint.getX() + spacing, firstPoint.getY() + 2 * spacing),
- new Point2D.Double(firstPoint.getX() + 2 * spacing, firstPoint.getY()),
- new Point2D.Double(firstPoint.getX() + 2 * spacing, firstPoint.getY() + spacing),
- new Point2D.Double(firstPoint.getX() + 2 * spacing, firstPoint.getY() + 2 * spacing),
- new Point2D.Double(firstPoint.getX() + 3 * spacing, firstPoint.getY()),
- new Point2D.Double(firstPoint.getX() + 3 * spacing, firstPoint.getY() + spacing),
- new Point2D.Double(firstPoint.getX() + 3 * spacing, firstPoint.getY() + 2 * spacing),
- new Point2D.Double(firstPoint.getX() + 4 * spacing, firstPoint.getY()),
- new Point2D.Double(firstPoint.getX() + 4 * spacing, firstPoint.getY() + spacing),
- new Point2D.Double(firstPoint.getX() + 4 * spacing, firstPoint.getY() + 2 * spacing)};
- break;
- }
- AffineTransform xform = AffineTransform.getRotateInstance(-Math.PI / 2, firstPoint.getX(), firstPoint.getY());
- if (getOrientation() == OrientationHV.HORIZONTAL) {
- for (int i = 1; i < controlPoints.length; i++) {
- xform.transform(controlPoints[i], controlPoints[i]);
- }
- }
- }
-
- @Override
- public Point2D getControlPoint(int index) {
- return controlPoints[index];
- }
-
- @Override
- public boolean isControlPointSticky(int index) {
- return true;
- }
-
- @Override
- public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
- return VisibilityPolicy.NEVER;
- }
-
- @Override
- public int getControlPointCount() {
- return controlPoints.length;
- }
-
- @Override
- public void setControlPoint(Point2D point, int index) {
- controlPoints[index].setLocation(point);
- // Reset body shape.
- body = null;
- }
-
- @EditableProperty(defaultable = false)
- @Override
- public String getName() {
- if (super.name == null || super.name.trim().isEmpty()) {
- super.name = name;
- name = null;
- }
- return super.name;
- }
-
- @Override
- public void setName(String name) {
- super.name = name;
- this.name = null;
- }
-
- @EditableProperty(name = "Type")
- @Override
- public ToggleSwitchType getValue() {
- return switchType;
- }
-
- @Override
- public void setValue(ToggleSwitchType value) {
- this.switchType = value;
- updateControlPoints();
- // Reset body shape.
- body = null;
- }
-
- @EditableProperty
- public OrientationHV getOrientation() {
- if (orientation == null) {
- orientation = OrientationHV.VERTICAL;
- }
- return orientation;
- }
-
- public void setOrientation(OrientationHV orientation) {
- this.orientation = orientation;
- updateControlPoints();
- // Reset body shape.
- body = null;
- }
-
- @EditableProperty(validatorClass = PositiveNonZeroMeasureValidator.class)
- public Size getSpacing() {
- if (spacing == null) {
- spacing = SPACING;
- }
- return spacing;
- }
-
- public void setSpacing(Size spacing) {
- this.spacing = spacing;
- updateControlPoints();
- // Reset body shape.
- body = null;
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- if (checkPointsClipped(g2d.getClip())) {
- return;
- }
- Shape body = getBody();
- Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- // Draw body if available.
- if (body != null) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getBodyColor());
- g2d.fill(body);
- g2d.setComposite(oldComposite);
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
- Color finalBorderColor;
- if (outlineMode) {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : getBorderColor();
- }
- g2d.setColor(finalBorderColor);
- g2d.draw(body);
- }
- // Do not track these changes because the whole switch has been tracked
- // so far.
- drawingObserver.stopTracking();
- // Draw lugs.
- int circleDiameter = getClosestOdd((int) CIRCLE_SIZE.convertToPixels());
-
- int lugWidth;
- int lugHeight;
-
- if (getOrientation() == OrientationHV.HORIZONTAL) {
- lugHeight = getClosestOdd((int) LUG_WIDTH.convertToPixels());
- lugWidth = getClosestOdd((int) LUG_THICKNESS.convertToPixels());
- } else {
- lugWidth = getClosestOdd((int) LUG_WIDTH.convertToPixels());
- lugHeight = getClosestOdd((int) LUG_THICKNESS.convertToPixels());
- }
-
- for (int i = 0; i < controlPoints.length; i++) {
- Point2D p = controlPoints[i];
- if (outlineMode) {
-// g2d.setColor(Constants.TRANSPARENT_COLOR);
-// drawingObserver.startTrackingContinuityArea(true);
-// g2d.fillRect((int)(p.getX() - lugWidth / 2), (int)(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);
- } else {
- g2d.setColor(getTerminalPadColor().darker());
-
- g2d.drawOval((int)(p.getX() - circleDiameter / 2d), (int)(p.getY() - circleDiameter / 2d), circleDiameter, circleDiameter);
-
- g2d.setColor(getTerminalPadColor());
- g2d.fillOval((int)(p.getX() - circleDiameter / 2d), (int)(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);
-// drawingObserver.stopTrackingContinuityArea();
- }
- }
-
- if (getShowMarkers()) {
- String[] markers =
- SwitchUtils.getSwitchingMarkers(this, getControlPointCount(), false);
-
- g2d.setColor(MARKER_COLOR);
-
- double offset = MARKER_OFFSET.convertToPixels();
- for (int i = 0; i < getControlPointCount(); i++) {
- if (markers[i] == null)
- continue;
-
- Point2D p = getControlPoint(i);
- Point2D labelPoint = new Point2D.Double(offset, 0);
-
- AffineTransform tx = null;
- if (getOrientation() == OrientationHV.HORIZONTAL) {
- tx = AffineTransform.getRotateInstance(-Math.PI / 2, 0, 0);
- }
- if (tx != null) {
- tx.transform(labelPoint, labelPoint);
- }
- StringUtils.drawCenteredText(g2d, markers[i], p.getX() + labelPoint.getX(), p.getY() + labelPoint.getY(),
- HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
- }
- }
- }
-
- public Shape getBody() {
- if (body == null) {
- Point2D firstPoint = controlPoints[0];
- int margin = (int) MARGIN.convertToPixels();
- int spacing = (int) getSpacing().convertToPixels();
- switch (switchType) {
- case SPST:
- body =
- new RoundRectangle2D.Double(firstPoint.getX() - margin, firstPoint.getY() - margin, 2 * margin, 2 * margin
- + spacing, margin, margin);
- break;
- case SPDT:
- case SPDT_off:
- body =
- new RoundRectangle2D.Double(firstPoint.getX() - margin, firstPoint.getY() - margin, 2 * margin, 2 * margin + 2
- * spacing, margin, margin);
- break;
- case DPDT:
- case DPDT_off:
- case DPDT_ononon_1:
- case DPDT_ononon_2:
- body =
- new RoundRectangle2D.Double(firstPoint.getX() - margin, firstPoint.getY() - margin, 2 * margin + spacing, 2
- * margin + 2 * spacing, margin, margin);
- break;
- case _3PDT:
- case _3PDT_off:
- body =
- new RoundRectangle2D.Double(firstPoint.getX() - margin, firstPoint.getY() - margin, 2 * margin + 2 * spacing, 2
- * margin + 2 * spacing, margin, margin);
- break;
- case _4PDT:
- case _4PDT_off:
- case _4PDT_ononon_1:
- case _4PDT_ononon_2:
- body =
- new RoundRectangle2D.Double(firstPoint.getX() - margin, firstPoint.getY() - margin, 2 * margin + 3 * spacing, 2
- * margin + 2 * spacing, margin, margin);
- break;
- case _5PDT:
- case _5PDT_off:
- body =
- new RoundRectangle2D.Double(firstPoint.getX() - margin, firstPoint.getY() - margin, 2 * margin + 4 * spacing, 2
- * margin + 2 * spacing, margin, margin);
- break;
- }
- if (getOrientation() == OrientationHV.HORIZONTAL) {
- AffineTransform xform = AffineTransform.getRotateInstance(-Math.PI / 2, firstPoint.getX(), firstPoint.getY());
- body = new Area(body);
- ((Area) body).transform(xform);
- }
- }
- return body;
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int circleSize = 5 * width / 32;
- g2d.setColor(BODY_COLOR);
- g2d.fillRoundRect(width / 4, 1, width / 2, height - 2, circleSize, circleSize);
- g2d.setColor(BORDER_COLOR);
- g2d.drawRoundRect(width / 4, 1, width / 2, height - 2, circleSize, circleSize);
- for (int i = 1; i <= 3; i++) {
- g2d.setColor(LIGHT_METAL_COLOR);
- g2d.fillOval(width / 2 - circleSize / 2, i * height / 4 - 3, circleSize, circleSize);
- g2d.setColor(METAL_COLOR);
- g2d.drawLine(width / 2 - circleSize / 2 + 1, i * height / 4 - 1, width / 2 + circleSize / 2 - 1, i * height / 4
- - 1);
- }
- }
-
- @EditableProperty(name = "Body")
- public Color getBodyColor() {
- if (bodyColor == null)
- bodyColor = BODY_COLOR;
- return bodyColor;
- }
-
- public void setBodyColor(Color bodyColor) {
- this.bodyColor = bodyColor;
- }
-
- @EditableProperty(name = "Border")
- public Color getBorderColor() {
- if (borderColor == null)
- borderColor = BORDER_COLOR;
- return borderColor;
- }
-
- public void setBorderColor(Color borderColor) {
- this.borderColor = borderColor;
- }
-
- @EditableProperty(name = "Pad")
- public Color getTerminalPadColor() {
- if (terminalPadColor == null) {
- terminalPadColor = CIRCLE_COLOR;
- }
- return terminalPadColor;
- }
-
- public void setTerminalPadColor(Color terminalPadColor) {
- this.terminalPadColor = terminalPadColor;
- }
-
- @EditableProperty(name = "Terminal")
- public Color getTerminalColor() {
- if (terminalColor == null) {
- terminalColor = TERMINAL_COLOR;
- }
- return terminalColor;
- }
-
- public void setTerminalColor(Color terminalColor) {
- this.terminalColor = terminalColor;
- }
-
- // switch stuff
-//
-// @Override
-// public String getControlPointNodeName(int index) {
-// // we don't want the switch to produce any nodes, it just makes connections
-// return null;
-// }
-
- @Override
- public boolean canPointMoveFreely(int pointIndex) {
- return false;
- }
-
- @Override
- public int getPositionCount() {
- return switchType.getPositionCount();
- }
-
- @Override
- public String getPositionName(int position) {
- int pos = position;
- if (switchType.name().endsWith("_off")) {
- int midPosition = (getPositionCount() - 1) / 2;
- if (position == midPosition) {
- return "OFF";
- } else if (position > midPosition) {
- --pos;
- }
- }
- return "ON" + Integer.toString(pos + 1);
- }
-
- @DynamicEditableProperty(source = ToggleSwitchPositionPropertyValueSource.class)
- @EditableProperty(name = "Selected Position")
- @Override
- public Integer getSelectedPosition() {
- return selectedPosition;
- }
-
- public void setSelectedPosition(Integer selectedPosition) {
- this.selectedPosition = selectedPosition;
- }
-
- @EditableProperty(name = "Markers")
- public Boolean getShowMarkers() {
- if (showMarkers == null) {
- showMarkers = false;
- }
- return showMarkers;
- }
-
- public void setShowMarkers(Boolean showMarkers) {
- this.showMarkers = showMarkers;
- }
-
- @Override
- public boolean arePointsConnected(int index1, int index2, int position) {
- if (index1 >= index2)
- return false;
-
- switch (switchType) {
- case SPST:
- return position == 0;
- case SPDT:
- case DPDT:
- case _3PDT:
- case _4PDT:
- case _5PDT:
- return (index2 - index1) < 3 && index1 % 3 == position && index2 % 3 == position + 1;
- case SPDT_off:
- case DPDT_off:
- case _3PDT_off:
- case _4PDT_off:
- case _5PDT_off:
- if (position == 1)
- return false;
- if (position == 2)
- position = 1;
- return (index2 - index1) < 3 && index1 % 3 == position && index2 % 3 == position + 1;
- case DPDT_ononon_1:
- switch (position) {
- case 0:
- return (index1 == 0 && index2 == 1) || (index1 == 3 && index2 == 4);
- case 1:
- return (index1 == 0 && index2 == 1) || (index1 == 4 && index2 == 5);
- case 2:
- return (index1 == 1 && index2 == 2) || (index1 == 4 && index2 == 5);
- default: return false;
- }
- case DPDT_ononon_2:
- switch (position) {
- case 0:
- return (index1 == 0 && index2 == 1) || (index1 == 3 && index2 == 4);
- case 1:
- return (index1 == 1 && index2 == 2) || (index1 == 3 && index2 == 4);
- case 2:
- return (index1 == 1 && index2 == 2) || (index1 == 4 && index2 == 5);
- default: return false;
- }
- case _4PDT_ononon_1:
- switch (position) {
- case 0:
- return (index1 == 0 && index2 == 1) || (index1 == 3 && index2 == 4) || (index1 == 6 && index2 == 7) || (index1 == 9 && index2 == 10);
- case 1:
- return (index1 == 0 && index2 == 1) || (index1 == 4 && index2 == 5) || (index1 == 6 && index2 == 7) || (index1 == 10 && index2 == 11);
- case 2:
- return (index1 == 1 && index2 == 2) || (index1 == 4 && index2 == 5) || (index1 == 7 && index2 == 8) || (index1 == 10 && index2 == 11);
- default: return false;
- }
- case _4PDT_ononon_2:
- switch (position) {
- case 0:
- return (index1 == 0 && index2 == 1) || (index1 == 3 && index2 == 4) || (index1 == 6 && index2 == 7) || (index1 == 9 && index2 == 10);
- case 1:
- return (index1 == 1 && index2 == 2) || (index1 == 3 && index2 == 4) || (index1 == 7 && index2 == 8) || (index1 == 9 && index2 == 10);
- case 2:
- return (index1 == 1 && index2 == 2) || (index1 == 4 && index2 == 5) || (index1 == 7 && index2 == 8) || (index1 == 10 && index2 == 11);
- default: return false;
- }
- }
- return false;
- }
-
- @Override
- public Rectangle2D getCachingBounds() {
- int margin = 20;
- Rectangle2D bounds = getBody().getBounds2D();
- return new Rectangle2D.Double(bounds.getX() - margin, bounds.getY() - margin, bounds.getWidth() + 2 * margin, bounds.getHeight() + 2 * margin);
- }
-
- @Override
- public int getLayerId() {
- return hashCode();
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.electromechanical;
+
+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.Area;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
+
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.awt.StringUtils;
+import org.diylc.common.*;
+import org.diylc.components.AbstractTransparentComponent;
+import org.diylc.components.guitar.ToggleSwitchPositionPropertyValueSource;
+import org.diylc.components.transform.MiniToggleSwitchTransformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.ILayeredComponent;
+import org.diylc.core.ISwitch;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+import org.diylc.core.VisibilityPolicy;
+import org.diylc.core.annotations.ComponentDescriptor;
+import org.diylc.core.annotations.DynamicEditableProperty;
+import org.diylc.core.annotations.EditableProperty;
+import org.diylc.core.annotations.PositiveNonZeroMeasureValidator;
+import org.diylc.core.gerber.IGerberComponentSimple;
+import org.diylc.core.measures.Size;
+import org.diylc.core.measures.SizeUnit;
+import org.diylc.utils.Constants;
+import org.diylc.utils.SwitchUtils;
+
+@ComponentDescriptor(name = "Mini Toggle Switch", category = "Electro-Mechanical", author = "Branislav Stojkovic",
+ description = "Panel mounted mini toggle switch", zOrder = IDIYComponent.COMPONENT,
+ instanceNamePrefix = "SW", enableCache = true, transformer = MiniToggleSwitchTransformer.class)
+public class MiniToggleSwitch extends AbstractTransparentComponent implements ISwitch, ILayeredComponent, IGerberComponentSimple {
+
+ private static final long serialVersionUID = 1L;
+
+ private static Size SPACING = new Size(0.2d, SizeUnit.in);
+ private static Size MARGIN = new Size(0.08d, SizeUnit.in);
+ private static Size CIRCLE_SIZE = new Size(0.09d, SizeUnit.in);
+ private static Size LUG_WIDTH = new Size(0.060d, SizeUnit.in);
+ private static Size LUG_THICKNESS = new Size(0.02d, SizeUnit.in);
+ private static Size MARKER_OFFSET = new Size(0.07d, SizeUnit.in);
+
+ private static Color BODY_COLOR = Color.decode("#3299CC");
+ private static Color BORDER_COLOR = BODY_COLOR.darker();
+ private static Color CIRCLE_COLOR = Color.decode("#287ba4");
+ private static Color TERMINAL_COLOR = LIGHT_METAL_COLOR;
+ private static Color MARKER_COLOR = LIGHT_METAL_COLOR;
+
+
+ protected Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0)};
+ transient protected Shape body;
+ protected ToggleSwitchType switchType = ToggleSwitchType.DPDT;
+ private OrientationHV orientation = OrientationHV.VERTICAL;
+ private Size spacing = SPACING;
+
+ private Color bodyColor = BODY_COLOR;
+ private Color borderColor = BORDER_COLOR;
+ private Color terminalPadColor = CIRCLE_COLOR;
+ private Color terminalColor = TERMINAL_COLOR;
+
+ private Integer selectedPosition;
+ private Boolean showMarkers;
+
+ @Deprecated
+ protected String name;
+
+ public MiniToggleSwitch() {
+ super();
+ updateControlPoints();
+ }
+
+ private void updateControlPoints() {
+ Point2D firstPoint = controlPoints[0];
+ int spacing = (int) getSpacing().convertToPixels();
+ switch (switchType) {
+ case SPST:
+ controlPoints = new Point2D[] {firstPoint, new Point2D.Double(firstPoint.getX(), firstPoint.getY() + spacing)};
+ break;
+ case SPDT:
+ case SPDT_off:
+ controlPoints =
+ new Point2D[] {firstPoint, new Point2D.Double(firstPoint.getX(), firstPoint.getY() + spacing),
+ new Point2D.Double(firstPoint.getX(), firstPoint.getY() + 2 * spacing)};
+ break;
+ case DPDT:
+ case DPDT_off:
+ case DPDT_ononon_1:
+ case DPDT_ononon_2:
+ controlPoints =
+ new Point2D[] {firstPoint, new Point2D.Double(firstPoint.getX(), firstPoint.getY() + spacing),
+ new Point2D.Double(firstPoint.getX(), firstPoint.getY() + 2 * spacing),
+ new Point2D.Double(firstPoint.getX() + spacing, firstPoint.getY()),
+ new Point2D.Double(firstPoint.getX() + spacing, firstPoint.getY() + spacing),
+ new Point2D.Double(firstPoint.getX() + spacing, firstPoint.getY() + 2 * spacing)};
+ break;
+ case _3PDT:
+ case _3PDT_off:
+ controlPoints =
+ new Point2D[] {firstPoint, new Point2D.Double(firstPoint.getX(), firstPoint.getY() + spacing),
+ new Point2D.Double(firstPoint.getX(), firstPoint.getY() + 2 * spacing),
+ new Point2D.Double(firstPoint.getX() + spacing, firstPoint.getY()),
+ new Point2D.Double(firstPoint.getX() + spacing, firstPoint.getY() + spacing),
+ new Point2D.Double(firstPoint.getX() + spacing, firstPoint.getY() + 2 * spacing),
+ new Point2D.Double(firstPoint.getX() + 2 * spacing, firstPoint.getY()),
+ new Point2D.Double(firstPoint.getX() + 2 * spacing, firstPoint.getY() + spacing),
+ new Point2D.Double(firstPoint.getX() + 2 * spacing, firstPoint.getY() + 2 * spacing)};
+ break;
+ case _4PDT:
+ case _4PDT_off:
+ case _4PDT_ononon_1:
+ case _4PDT_ononon_2:
+ controlPoints =
+ new Point2D[] {firstPoint, new Point2D.Double(firstPoint.getX(), firstPoint.getY() + spacing),
+ new Point2D.Double(firstPoint.getX(), firstPoint.getY() + 2 * spacing),
+ new Point2D.Double(firstPoint.getX() + spacing, firstPoint.getY()),
+ new Point2D.Double(firstPoint.getX() + spacing, firstPoint.getY() + spacing),
+ new Point2D.Double(firstPoint.getX() + spacing, firstPoint.getY() + 2 * spacing),
+ new Point2D.Double(firstPoint.getX() + 2 * spacing, firstPoint.getY()),
+ new Point2D.Double(firstPoint.getX() + 2 * spacing, firstPoint.getY() + spacing),
+ new Point2D.Double(firstPoint.getX() + 2 * spacing, firstPoint.getY() + 2 * spacing),
+ new Point2D.Double(firstPoint.getX() + 3 * spacing, firstPoint.getY()),
+ new Point2D.Double(firstPoint.getX() + 3 * spacing, firstPoint.getY() + spacing),
+ new Point2D.Double(firstPoint.getX() + 3 * spacing, firstPoint.getY() + 2 * spacing)};
+ break;
+ case _5PDT:
+ case _5PDT_off:
+ controlPoints =
+ new Point2D[] {firstPoint, new Point2D.Double(firstPoint.getX(), firstPoint.getY() + spacing),
+ new Point2D.Double(firstPoint.getX(), firstPoint.getY() + 2 * spacing),
+ new Point2D.Double(firstPoint.getX() + spacing, firstPoint.getY()),
+ new Point2D.Double(firstPoint.getX() + spacing, firstPoint.getY() + spacing),
+ new Point2D.Double(firstPoint.getX() + spacing, firstPoint.getY() + 2 * spacing),
+ new Point2D.Double(firstPoint.getX() + 2 * spacing, firstPoint.getY()),
+ new Point2D.Double(firstPoint.getX() + 2 * spacing, firstPoint.getY() + spacing),
+ new Point2D.Double(firstPoint.getX() + 2 * spacing, firstPoint.getY() + 2 * spacing),
+ new Point2D.Double(firstPoint.getX() + 3 * spacing, firstPoint.getY()),
+ new Point2D.Double(firstPoint.getX() + 3 * spacing, firstPoint.getY() + spacing),
+ new Point2D.Double(firstPoint.getX() + 3 * spacing, firstPoint.getY() + 2 * spacing),
+ new Point2D.Double(firstPoint.getX() + 4 * spacing, firstPoint.getY()),
+ new Point2D.Double(firstPoint.getX() + 4 * spacing, firstPoint.getY() + spacing),
+ new Point2D.Double(firstPoint.getX() + 4 * spacing, firstPoint.getY() + 2 * spacing)};
+ break;
+ }
+ AffineTransform xform = AffineTransform.getRotateInstance(-Math.PI / 2, firstPoint.getX(), firstPoint.getY());
+ if (getOrientation() == OrientationHV.HORIZONTAL) {
+ for (int i = 1; i < controlPoints.length; i++) {
+ xform.transform(controlPoints[i], controlPoints[i]);
+ }
+ }
+ }
+
+ @Override
+ public Point2D getControlPoint(int index) {
+ return controlPoints[index];
+ }
+
+ @Override
+ public boolean isControlPointSticky(int index) {
+ return true;
+ }
+
+ @Override
+ public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
+ return VisibilityPolicy.NEVER;
+ }
+
+ @Override
+ public int getControlPointCount() {
+ return controlPoints.length;
+ }
+
+ @Override
+ public void setControlPoint(Point2D point, int index) {
+ controlPoints[index].setLocation(point);
+ // Reset body shape.
+ body = null;
+ }
+
+ @EditableProperty(defaultable = false)
+ @Override
+ public String getName() {
+ if (super.name == null || super.name.trim().isEmpty()) {
+ super.name = name;
+ name = null;
+ }
+ return super.name;
+ }
+
+ @Override
+ public void setName(String name) {
+ super.name = name;
+ this.name = null;
+ }
+
+ @EditableProperty(name = "Type")
+ @Override
+ public ToggleSwitchType getValue() {
+ return switchType;
+ }
+
+ @Override
+ public void setValue(ToggleSwitchType value) {
+ this.switchType = value;
+ updateControlPoints();
+ // Reset body shape.
+ body = null;
+ }
+
+ @EditableProperty
+ public OrientationHV getOrientation() {
+ if (orientation == null) {
+ orientation = OrientationHV.VERTICAL;
+ }
+ return orientation;
+ }
+
+ public void setOrientation(OrientationHV orientation) {
+ this.orientation = orientation;
+ updateControlPoints();
+ // Reset body shape.
+ body = null;
+ }
+
+ @EditableProperty(validatorClass = PositiveNonZeroMeasureValidator.class)
+ public Size getSpacing() {
+ if (spacing == null) {
+ spacing = SPACING;
+ }
+ return spacing;
+ }
+
+ public void setSpacing(Size spacing) {
+ this.spacing = spacing;
+ updateControlPoints();
+ // Reset body shape.
+ body = null;
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ if (checkPointsClipped(g2d.getClip())) {
+ return;
+ }
+ Shape body = getBody();
+ Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ // Draw body if available.
+ if (body != null) {
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getBodyColor());
+ g2d.fill(body);
+ g2d.setComposite(oldComposite);
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+ Color finalBorderColor;
+ if (outlineMode) {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : getBorderColor();
+ }
+ g2d.setColor(finalBorderColor);
+ g2d.draw(body);
+ }
+ // Do not track these changes because the whole switch has been tracked
+ // so far.
+ drawingObserver.stopTracking();
+ // Draw lugs.
+ int circleDiameter = getClosestOdd((int) CIRCLE_SIZE.convertToPixels());
+
+ int lugWidth;
+ int lugHeight;
+
+ if (getOrientation() == OrientationHV.HORIZONTAL) {
+ lugHeight = getClosestOdd((int) LUG_WIDTH.convertToPixels());
+ lugWidth = getClosestOdd((int) LUG_THICKNESS.convertToPixels());
+ } else {
+ lugWidth = getClosestOdd((int) LUG_WIDTH.convertToPixels());
+ lugHeight = getClosestOdd((int) LUG_THICKNESS.convertToPixels());
+ }
+
+ for (int i = 0; i < controlPoints.length; i++) {
+ Point2D p = controlPoints[i];
+ if (outlineMode) {
+// g2d.setColor(Constants.TRANSPARENT_COLOR);
+// drawingObserver.startTrackingContinuityArea(true);
+// g2d.fillRect((int)(p.getX() - lugWidth / 2), (int)(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);
+ } else {
+ g2d.setColor(getTerminalPadColor().darker());
+
+ g2d.drawOval((int)(p.getX() - circleDiameter / 2d), (int)(p.getY() - circleDiameter / 2d), circleDiameter, circleDiameter);
+
+ g2d.setColor(getTerminalPadColor());
+ g2d.fillOval((int)(p.getX() - circleDiameter / 2d), (int)(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);
+// drawingObserver.stopTrackingContinuityArea();
+ }
+ }
+
+ if (getShowMarkers()) {
+ String[] markers =
+ SwitchUtils.getSwitchingMarkers(this, getControlPointCount(), false);
+
+ g2d.setColor(MARKER_COLOR);
+
+ double offset = MARKER_OFFSET.convertToPixels();
+ for (int i = 0; i < getControlPointCount(); i++) {
+ if (markers[i] == null)
+ continue;
+
+ Point2D p = getControlPoint(i);
+ Point2D labelPoint = new Point2D.Double(offset, 0);
+
+ AffineTransform tx = null;
+ if (getOrientation() == OrientationHV.HORIZONTAL) {
+ tx = AffineTransform.getRotateInstance(-Math.PI / 2, 0, 0);
+ }
+ if (tx != null) {
+ tx.transform(labelPoint, labelPoint);
+ }
+ StringUtils.drawCenteredText(g2d, markers[i], p.getX() + labelPoint.getX(), p.getY() + labelPoint.getY(),
+ HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
+ }
+ }
+ }
+
+ public Shape getBody() {
+ if (body == null) {
+ Point2D firstPoint = controlPoints[0];
+ int margin = (int) MARGIN.convertToPixels();
+ int spacing = (int) getSpacing().convertToPixels();
+ switch (switchType) {
+ case SPST:
+ body =
+ new RoundRectangle2D.Double(firstPoint.getX() - margin, firstPoint.getY() - margin, 2 * margin, 2 * margin
+ + spacing, margin, margin);
+ break;
+ case SPDT:
+ case SPDT_off:
+ body =
+ new RoundRectangle2D.Double(firstPoint.getX() - margin, firstPoint.getY() - margin, 2 * margin, 2 * margin + 2
+ * spacing, margin, margin);
+ break;
+ case DPDT:
+ case DPDT_off:
+ case DPDT_ononon_1:
+ case DPDT_ononon_2:
+ body =
+ new RoundRectangle2D.Double(firstPoint.getX() - margin, firstPoint.getY() - margin, 2 * margin + spacing, 2
+ * margin + 2 * spacing, margin, margin);
+ break;
+ case _3PDT:
+ case _3PDT_off:
+ body =
+ new RoundRectangle2D.Double(firstPoint.getX() - margin, firstPoint.getY() - margin, 2 * margin + 2 * spacing, 2
+ * margin + 2 * spacing, margin, margin);
+ break;
+ case _4PDT:
+ case _4PDT_off:
+ case _4PDT_ononon_1:
+ case _4PDT_ononon_2:
+ body =
+ new RoundRectangle2D.Double(firstPoint.getX() - margin, firstPoint.getY() - margin, 2 * margin + 3 * spacing, 2
+ * margin + 2 * spacing, margin, margin);
+ break;
+ case _5PDT:
+ case _5PDT_off:
+ body =
+ new RoundRectangle2D.Double(firstPoint.getX() - margin, firstPoint.getY() - margin, 2 * margin + 4 * spacing, 2
+ * margin + 2 * spacing, margin, margin);
+ break;
+ }
+ if (getOrientation() == OrientationHV.HORIZONTAL) {
+ AffineTransform xform = AffineTransform.getRotateInstance(-Math.PI / 2, firstPoint.getX(), firstPoint.getY());
+ body = new Area(body);
+ ((Area) body).transform(xform);
+ }
+ }
+ return body;
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int circleSize = 5 * width / 32;
+ g2d.setColor(BODY_COLOR);
+ g2d.fillRoundRect(width / 4, 1, width / 2, height - 2, circleSize, circleSize);
+ g2d.setColor(BORDER_COLOR);
+ g2d.drawRoundRect(width / 4, 1, width / 2, height - 2, circleSize, circleSize);
+ for (int i = 1; i <= 3; i++) {
+ g2d.setColor(LIGHT_METAL_COLOR);
+ g2d.fillOval(width / 2 - circleSize / 2, i * height / 4 - 3, circleSize, circleSize);
+ g2d.setColor(METAL_COLOR);
+ g2d.drawLine(width / 2 - circleSize / 2 + 1, i * height / 4 - 1, width / 2 + circleSize / 2 - 1, i * height / 4
+ - 1);
+ }
+ }
+
+ @EditableProperty(name = "Body")
+ public Color getBodyColor() {
+ if (bodyColor == null)
+ bodyColor = BODY_COLOR;
+ return bodyColor;
+ }
+
+ public void setBodyColor(Color bodyColor) {
+ this.bodyColor = bodyColor;
+ }
+
+ @EditableProperty(name = "Border")
+ public Color getBorderColor() {
+ if (borderColor == null)
+ borderColor = BORDER_COLOR;
+ return borderColor;
+ }
+
+ public void setBorderColor(Color borderColor) {
+ this.borderColor = borderColor;
+ }
+
+ @EditableProperty(name = "Pad")
+ public Color getTerminalPadColor() {
+ if (terminalPadColor == null) {
+ terminalPadColor = CIRCLE_COLOR;
+ }
+ return terminalPadColor;
+ }
+
+ public void setTerminalPadColor(Color terminalPadColor) {
+ this.terminalPadColor = terminalPadColor;
+ }
+
+ @EditableProperty(name = "Terminal")
+ public Color getTerminalColor() {
+ if (terminalColor == null) {
+ terminalColor = TERMINAL_COLOR;
+ }
+ return terminalColor;
+ }
+
+ public void setTerminalColor(Color terminalColor) {
+ this.terminalColor = terminalColor;
+ }
+
+ // switch stuff
+//
+// @Override
+// public String getControlPointNodeName(int index) {
+// // we don't want the switch to produce any nodes, it just makes connections
+// return null;
+// }
+
+ @Override
+ public boolean canPointMoveFreely(int pointIndex) {
+ return false;
+ }
+
+ @Override
+ public int getPositionCount() {
+ return switchType.getPositionCount();
+ }
+
+ @Override
+ public String getPositionName(int position) {
+ int pos = position;
+ if (switchType.name().endsWith("_off")) {
+ int midPosition = (getPositionCount() - 1) / 2;
+ if (position == midPosition) {
+ return "OFF";
+ } else if (position > midPosition) {
+ --pos;
+ }
+ }
+ return "ON" + Integer.toString(pos + 1);
+ }
+
+ @DynamicEditableProperty(source = ToggleSwitchPositionPropertyValueSource.class)
+ @EditableProperty(name = "Selected Position")
+ @Override
+ public Integer getSelectedPosition() {
+ return selectedPosition;
+ }
+
+ public void setSelectedPosition(Integer selectedPosition) {
+ this.selectedPosition = selectedPosition;
+ }
+
+ @EditableProperty(name = "Markers")
+ public Boolean getShowMarkers() {
+ if (showMarkers == null) {
+ showMarkers = false;
+ }
+ return showMarkers;
+ }
+
+ public void setShowMarkers(Boolean showMarkers) {
+ this.showMarkers = showMarkers;
+ }
+
+ @Override
+ public boolean arePointsConnected(int index1, int index2, int position) {
+ if (index1 >= index2)
+ return false;
+
+ switch (switchType) {
+ case SPST:
+ return position == 0;
+ case SPDT:
+ case DPDT:
+ case _3PDT:
+ case _4PDT:
+ case _5PDT:
+ return (index2 - index1) < 3 && index1 % 3 == position && index2 % 3 == position + 1;
+ case SPDT_off:
+ case DPDT_off:
+ case _3PDT_off:
+ case _4PDT_off:
+ case _5PDT_off:
+ if (position == 1)
+ return false;
+ if (position == 2)
+ position = 1;
+ return (index2 - index1) < 3 && index1 % 3 == position && index2 % 3 == position + 1;
+ case DPDT_ononon_1:
+ switch (position) {
+ case 0:
+ return (index1 == 0 && index2 == 1) || (index1 == 3 && index2 == 4);
+ case 1:
+ return (index1 == 0 && index2 == 1) || (index1 == 4 && index2 == 5);
+ case 2:
+ return (index1 == 1 && index2 == 2) || (index1 == 4 && index2 == 5);
+ default: return false;
+ }
+ case DPDT_ononon_2:
+ switch (position) {
+ case 0:
+ return (index1 == 0 && index2 == 1) || (index1 == 3 && index2 == 4);
+ case 1:
+ return (index1 == 1 && index2 == 2) || (index1 == 3 && index2 == 4);
+ case 2:
+ return (index1 == 1 && index2 == 2) || (index1 == 4 && index2 == 5);
+ default: return false;
+ }
+ case _4PDT_ononon_1:
+ switch (position) {
+ case 0:
+ return (index1 == 0 && index2 == 1) || (index1 == 3 && index2 == 4) || (index1 == 6 && index2 == 7) || (index1 == 9 && index2 == 10);
+ case 1:
+ return (index1 == 0 && index2 == 1) || (index1 == 4 && index2 == 5) || (index1 == 6 && index2 == 7) || (index1 == 10 && index2 == 11);
+ case 2:
+ return (index1 == 1 && index2 == 2) || (index1 == 4 && index2 == 5) || (index1 == 7 && index2 == 8) || (index1 == 10 && index2 == 11);
+ default: return false;
+ }
+ case _4PDT_ononon_2:
+ switch (position) {
+ case 0:
+ return (index1 == 0 && index2 == 1) || (index1 == 3 && index2 == 4) || (index1 == 6 && index2 == 7) || (index1 == 9 && index2 == 10);
+ case 1:
+ return (index1 == 1 && index2 == 2) || (index1 == 3 && index2 == 4) || (index1 == 7 && index2 == 8) || (index1 == 9 && index2 == 10);
+ case 2:
+ return (index1 == 1 && index2 == 2) || (index1 == 4 && index2 == 5) || (index1 == 7 && index2 == 8) || (index1 == 10 && index2 == 11);
+ default: return false;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Rectangle2D getCachingBounds() {
+ int margin = 20;
+ Rectangle2D bounds = getBody().getBounds2D();
+ return new Rectangle2D.Double(bounds.getX() - margin, bounds.getY() - margin, bounds.getWidth() + 2 * margin, bounds.getHeight() + 2 * margin);
+ }
+
+ @Override
+ public int getLayerId() {
+ return hashCode();
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/NeutrikJack1_4.java b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/NeutrikJack1_4.java
index 9dac807ef..0eb895e21 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/NeutrikJack1_4.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/NeutrikJack1_4.java
@@ -1,375 +1,372 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.electromechanical;
-
-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.Area;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.geom.RoundRectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.awt.StringUtils;
-import org.diylc.common.HorizontalAlignment;
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.Orientation;
-import org.diylc.common.VerticalAlignment;
-import org.diylc.components.AbstractMultiPartComponent;
-import org.diylc.components.transform.NeutrikJack1_4Transformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-import org.diylc.core.VisibilityPolicy;
-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.Constants;
-
-@ComponentDescriptor(name = "Neutrik 1/4\" Jack", category = "Electro-Mechanical", author = "Branislav Stojkovic",
- description = "1/4\" mono/stereo phono jack based on Neutrik NMJx series, PCB or Panel-mount",
- zOrder = IDIYComponent.COMPONENT, instanceNamePrefix = "J", transformer = NeutrikJack1_4Transformer.class,
- enableCache = true)
-public class NeutrikJack1_4 extends AbstractMultiPartComponent {
-
- private static final long serialVersionUID = 1L;
-
- private static Size X_SPACING = new Size(0.25d, SizeUnit.in);
- private static Size Y_SPACING = new Size(16.23d, SizeUnit.mm);
- private static Size PIN_WIDTH = new Size(0.1d, SizeUnit.in);
- private static Size PIN_THICKNESS = new Size(0.02d, SizeUnit.in);
- private static Size PIN_DIAMETER = new Size(1.4d, SizeUnit.mm);
- private static Size PIN_OFFSET_MONO = new Size(-6.27d, SizeUnit.mm);
- private static Size PIN_OFFSET_STEREO = new Size(-7.72d, SizeUnit.mm);
- private static Color BODY_COLOR = Color.decode("#666666");
- private static Color NUT_COLOR = Color.decode("#999999");
- private static Color BORDER_COLOR = Color.black;
- private static Color LABEL_COLOR = Color.white;
- private static Size BODY_WIDTH = new Size(18.2, SizeUnit.mm);
- private static Size BODY_LENGTH = new Size(20.6d, SizeUnit.mm);
- private static Size TAIL_LENGTH = new Size(0.1d, SizeUnit.in);
-
- private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0)};
- private JackType type = JackType.MONO;
- private Mount mount = Mount.Panel;
- private Orientation orientation = Orientation.DEFAULT;
- transient private Area[] body;
- @SuppressWarnings("unused")
- @Deprecated
- private transient String value = "";
-
-
- public NeutrikJack1_4() {
- super();
- updateControlPoints();
- }
-
- private void updateControlPoints() {
- // invalidate body shape
- body = null;
- double x = controlPoints[0].getX();
- double y = controlPoints[0].getY();
- int xSpacing = (int) X_SPACING.convertToPixels();
- int ySpacing = (int) Y_SPACING.convertToPixels();
- controlPoints = new Point2D[type == JackType.STEREO ? 6 : 4];
-
- controlPoints[0] = new Point2D.Double(x, y);
- controlPoints[1] = new Point2D.Double(x, y + ySpacing);
- controlPoints[2] = new Point2D.Double(x + 2 * xSpacing, y);
- controlPoints[3] = new Point2D.Double(x + 2 * xSpacing, y + ySpacing);
- if (type == JackType.STEREO) {
- controlPoints[4] = new Point2D.Double(x + xSpacing, y);
- controlPoints[5] = new Point2D.Double(x + xSpacing, y + ySpacing);
- }
-
- // Apply rotation if necessary
- double angle = getAngle();
- if (angle != 0) {
- AffineTransform rotation = AffineTransform.getRotateInstance(angle, x, y);
- for (int i = 1; i < controlPoints.length; i++) {
- rotation.transform(controlPoints[i], controlPoints[i]);
- }
- }
- }
-
- private double getAngle() {
- // Apply rotation if necessary
- double angle;
- switch (orientation) {
- case _90:
- angle = Math.PI / 2;
- break;
- case _180:
- angle = Math.PI;
- break;
- case _270:
- angle = Math.PI * 3 / 2;
- break;
- default:
- angle = 0;
- }
-
- return angle;
- }
-
- public Area[] getBody() {
- if (body == null) {
- body = new Area[5];
-
- // Create body.
- int bodyLength = (int) BODY_LENGTH.convertToPixels();
- int bodyWidth = (int) BODY_WIDTH.convertToPixels();
- int offset = (int)(type == JackType.MONO ? PIN_OFFSET_MONO : PIN_OFFSET_STEREO).convertToPixels();
- int xSpacing = (int) X_SPACING.convertToPixels();
- int ySpacing = (int) Y_SPACING.convertToPixels();
- double centerX = controlPoints[0].getX() + 2 * xSpacing + offset;
- double centerY = controlPoints[0].getY() + ySpacing / 2;
- body[0] = new Area(new Rectangle2D.Double(centerX - bodyLength / 2, centerY - bodyWidth / 2, bodyLength, bodyWidth));
-
- int tailLength = (int) TAIL_LENGTH.convertToPixels();
- body[1] = new Area(new RoundRectangle2D.Double(centerX - bodyLength / 2 - tailLength, centerY - bodyWidth / 4, tailLength * 2,
- bodyWidth / 2, tailLength, tailLength));
- Area tailArea = new Area(body[1]);
- tailArea.subtract(new Area(body[0]));
- body[1] = tailArea;
-
- body[2] = new Area(new Rectangle2D.Double(centerX + bodyLength / 2, centerY - bodyWidth / 4, tailLength, bodyWidth / 2));
-
- body[3] = new Area(new Rectangle2D.Double(centerX + bodyLength / 2 + tailLength, centerY - bodyWidth / 4, tailLength, bodyWidth / 2));
- tailArea = new Area(body[3]);
- int radius = bodyLength / 2 + tailLength * 2;
- tailArea.intersect(new Area(new Ellipse2D.Double(centerX - radius, centerY - radius, radius * 2, radius * 2)));
- body[3] = tailArea;
-
- // Apply rotation if necessary
- double angle = getAngle();
- if (angle != 0) {
- AffineTransform rotation = AffineTransform.getRotateInstance(angle, controlPoints[0].getX(), controlPoints[0].getY());
- for (int i = 0; i < body.length; i++) {
- if (body[i] != null) {
- Area area = new Area(body[i]);
- area.transform(rotation);
- body[i] = area;
- }
- }
- }
-
- // Create pins.
- Area pins = new Area();
-
- int pinWidth = (int) PIN_WIDTH.convertToPixels();
- int pinThickness = (int) PIN_THICKNESS.convertToPixels();
- int pinDiameter = (int) PIN_DIAMETER.convertToPixels();
- for (int i = 0; i < getControlPointCount(); i++) {
- Point2D point = getControlPoint(i);
- Shape pin;
- if (mount == Mount.PCB) {
- pin = new Ellipse2D.Double(point.getX() - pinDiameter / 2, point.getY() - pinDiameter / 2, pinDiameter, pinDiameter);
- } else {
- if (orientation == Orientation.DEFAULT || orientation == Orientation._180) {
- pin = new Rectangle2D.Double(point.getX() - pinWidth / 2, point.getY() - pinThickness / 2, pinWidth, pinThickness);
- } else {
- pin = new Rectangle2D.Double(point.getX() - pinThickness / 2, point.getY() - pinWidth / 2, pinThickness, pinWidth);
- }
- }
- pins.add(new Area(pin));
- }
-
- body[4] = pins;
- }
- return body;
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- Shape[] body = getBody();
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
-// if (componentState != ComponentState.DRAGGING) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : BODY_COLOR);
- for (int i = 0; i < body.length - 1; i++) {
- // Nut is brighter colored.
- if (i == body.length - 2)
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : NUT_COLOR);
- g2d.fill(body[i]);
- }
- g2d.setComposite(oldComposite);
-// }
-
- Color finalBorderColor;
- Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- if (outlineMode) {
- finalBorderColor = theme.getOutlineColor();
- } else {
- finalBorderColor = BORDER_COLOR;
- }
-
- drawingObserver.stopTracking();
-
- g2d.setColor(finalBorderColor);
- for (int i = 0; i < body.length - 1; i++) {
- g2d.draw(body[i]);
- }
-
- // Pins are the last piece.
- Shape pins = body[body.length - 1];
- if (!outlineMode) {
- g2d.setColor(METAL_COLOR);
- g2d.fill(pins);
- }
- g2d.setColor(outlineMode ? theme.getOutlineColor() : METAL_COLOR.darker());
- g2d.draw(pins);
-
- Color finalLabelColor;
- if (outlineMode) {
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : theme.getOutlineColor();
- } else {
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : LABEL_COLOR;
- }
- g2d.setColor(finalLabelColor);
- g2d.setFont(project.getFont());
-
- // Override font size
- if (getFontSizeOverride() != null)
- g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride()));
-
- double centerX = (controlPoints[0].getX() + controlPoints[3].getX()) / 2;
- double centerY = (controlPoints[0].getY() + controlPoints[3].getY()) / 2;
- StringUtils.drawCenteredText(g2d, name, centerX, centerY, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
-
- drawSelectionOutline(g2d, componentState, outlineMode, project, drawingObserver);
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int bodyWidth = getClosestOdd(width * 3 / 5);
- int tailWidth = getClosestOdd(width * 3 / 9);
-
- g2d.setColor(BODY_COLOR);
- g2d.fillRoundRect((width - tailWidth) / 2, height / 2, tailWidth, height / 2 - 2 * 32 / height, 4 * 32 / width,
- 4 * 32 / width);
- g2d.setColor(BORDER_COLOR);
- g2d.drawRoundRect((width - tailWidth) / 2, height / 2, tailWidth, height / 2 - 2 * 32 / height, 4 * 32 / width,
- 4 * 32 / width);
-
- g2d.setColor(NUT_COLOR);
- g2d.fillRoundRect((width - tailWidth) / 2, 2 * 32 / height, tailWidth, height / 2, 4 * 32 / width, 4 * 32 / width);
- g2d.setColor(BORDER_COLOR);
- g2d.drawRoundRect((width - tailWidth) / 2, 2 * 32 / height, tailWidth, height / 2, 4 * 32 / width, 4 * 32 / width);
-
- g2d.setColor(BODY_COLOR);
- g2d.fillRect((width - bodyWidth) / 2, height / 7 + 1, bodyWidth, height * 5 / 7);
- g2d.setColor(BORDER_COLOR);
- g2d.drawRect((width - bodyWidth) / 2, height / 7 + 1, bodyWidth, height * 5 / 7);
-
- g2d.setColor(METAL_COLOR);
- int pinX1 = getClosestOdd((width - bodyWidth * 3 / 4) / 2);
- int pinX2 = getClosestOdd((width + bodyWidth * 3 / 4) / 2) - 1;
- g2d.drawLine(pinX1, width * 2 / 8, pinX1, width * 3 / 8);
- g2d.drawLine(pinX1, width * 5 / 8, pinX1, width * 6 / 8);
- g2d.drawLine(pinX2, width * 2 / 8, pinX2, width * 3 / 8);
- g2d.drawLine(pinX2, width * 5 / 8, pinX2, width * 6 / 8);
- }
-
- @Override
- public int getControlPointCount() {
- return controlPoints.length;
- }
-
- @Override
- public Point2D getControlPoint(int index) {
- return controlPoints[index];
- }
-
- @Override
- public void setControlPoint(Point2D point, int index) {
- controlPoints[index].setLocation(point);
- body = null;
- }
-
- @Override
- public boolean isControlPointSticky(int index) {
- return true;
- }
-
- @Override
- public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
- return VisibilityPolicy.NEVER;
- }
-
- @EditableProperty(name = "Type")
- public JackType getValue() {
- return type;
- }
-
- public void setValue(JackType type) {
- this.type = type;
- updateControlPoints();
- }
-
- @EditableProperty
- public Orientation getOrientation() {
- return orientation;
- }
-
- public void setOrientation(Orientation orientation) {
- this.orientation = orientation;
- updateControlPoints();
- }
-
- @EditableProperty
- public Mount getMount() {
- return mount;
- }
-
- public void setMount(Mount mount) {
- this.mount = mount;
- body = null;
- }
-
- @Override
- public boolean canPointMoveFreely(int pointIndex) {
- return false;
- }
-
- enum Mount {
- PCB, Panel
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.electromechanical;
+
+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.Area;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.awt.StringUtils;
+import org.diylc.common.HorizontalAlignment;
+import org.diylc.common.IPlugInPort;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.Orientation;
+import org.diylc.common.VerticalAlignment;
+import org.diylc.components.AbstractMultiPartComponent;
+import org.diylc.components.transform.NeutrikJack1_4Transformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+import org.diylc.core.VisibilityPolicy;
+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.Constants;
+
+@ComponentDescriptor(name = "Neutrik 1/4\" Jack", category = "Electro-Mechanical", author = "Branislav Stojkovic",
+ description = "1/4\" mono/stereo phono jack based on Neutrik NMJx series, PCB or Panel-mount",
+ zOrder = IDIYComponent.COMPONENT, instanceNamePrefix = "J", transformer = NeutrikJack1_4Transformer.class,
+ enableCache = true)
+public class NeutrikJack1_4 extends AbstractMultiPartComponent {
+
+ private static final long serialVersionUID = 1L;
+
+ private static Size X_SPACING = new Size(0.25d, SizeUnit.in);
+ private static Size Y_SPACING = new Size(16.23d, SizeUnit.mm);
+ private static Size PIN_WIDTH = new Size(0.1d, SizeUnit.in);
+ private static Size PIN_THICKNESS = new Size(0.02d, SizeUnit.in);
+ private static Size PIN_DIAMETER = new Size(1.4d, SizeUnit.mm);
+ private static Size PIN_OFFSET_MONO = new Size(-6.27d, SizeUnit.mm);
+ private static Size PIN_OFFSET_STEREO = new Size(-7.72d, SizeUnit.mm);
+ private static Color BODY_COLOR = Color.decode("#666666");
+ private static Color NUT_COLOR = Color.decode("#999999");
+ private static Color BORDER_COLOR = Color.black;
+ private static Color LABEL_COLOR = Color.white;
+ private static Size BODY_WIDTH = new Size(18.2, SizeUnit.mm);
+ private static Size BODY_LENGTH = new Size(20.6d, SizeUnit.mm);
+ private static Size TAIL_LENGTH = new Size(0.1d, SizeUnit.in);
+
+ private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0)};
+ private JackType type = JackType.MONO;
+ private Mount mount = Mount.Panel;
+ private Orientation orientation = Orientation.DEFAULT;
+ transient private Area[] body;
+ @SuppressWarnings("unused")
+ @Deprecated
+ private transient String value = "";
+
+
+ public NeutrikJack1_4() {
+ super();
+ updateControlPoints();
+ }
+
+ private void updateControlPoints() {
+ // invalidate body shape
+ body = null;
+ double x = controlPoints[0].getX();
+ double y = controlPoints[0].getY();
+ int xSpacing = (int) X_SPACING.convertToPixels();
+ int ySpacing = (int) Y_SPACING.convertToPixels();
+ controlPoints = new Point2D[type == JackType.STEREO ? 6 : 4];
+
+ controlPoints[0] = new Point2D.Double(x, y);
+ controlPoints[1] = new Point2D.Double(x, y + ySpacing);
+ controlPoints[2] = new Point2D.Double(x + 2 * xSpacing, y);
+ controlPoints[3] = new Point2D.Double(x + 2 * xSpacing, y + ySpacing);
+ if (type == JackType.STEREO) {
+ controlPoints[4] = new Point2D.Double(x + xSpacing, y);
+ controlPoints[5] = new Point2D.Double(x + xSpacing, y + ySpacing);
+ }
+
+ // Apply rotation if necessary
+ double angle = getAngle();
+ if (angle != 0) {
+ AffineTransform rotation = AffineTransform.getRotateInstance(angle, x, y);
+ for (int i = 1; i < controlPoints.length; i++) {
+ rotation.transform(controlPoints[i], controlPoints[i]);
+ }
+ }
+ }
+
+ private double getAngle() {
+ // Apply rotation if necessary
+ double angle;
+ switch (orientation) {
+ case _90:
+ angle = Math.PI / 2;
+ break;
+ case _180:
+ angle = Math.PI;
+ break;
+ case _270:
+ angle = Math.PI * 3 / 2;
+ break;
+ default:
+ angle = 0;
+ }
+
+ return angle;
+ }
+
+ public Area[] getBody() {
+ if (body == null) {
+ body = new Area[5];
+
+ // Create body.
+ int bodyLength = (int) BODY_LENGTH.convertToPixels();
+ int bodyWidth = (int) BODY_WIDTH.convertToPixels();
+ int offset = (int)(type == JackType.MONO ? PIN_OFFSET_MONO : PIN_OFFSET_STEREO).convertToPixels();
+ int xSpacing = (int) X_SPACING.convertToPixels();
+ int ySpacing = (int) Y_SPACING.convertToPixels();
+ double centerX = controlPoints[0].getX() + 2 * xSpacing + offset;
+ double centerY = controlPoints[0].getY() + ySpacing / 2;
+ body[0] = new Area(new Rectangle2D.Double(centerX - bodyLength / 2, centerY - bodyWidth / 2, bodyLength, bodyWidth));
+
+ int tailLength = (int) TAIL_LENGTH.convertToPixels();
+ body[1] = new Area(new RoundRectangle2D.Double(centerX - bodyLength / 2 - tailLength, centerY - bodyWidth / 4, tailLength * 2,
+ bodyWidth / 2, tailLength, tailLength));
+ Area tailArea = new Area(body[1]);
+ tailArea.subtract(new Area(body[0]));
+ body[1] = tailArea;
+
+ body[2] = new Area(new Rectangle2D.Double(centerX + bodyLength / 2, centerY - bodyWidth / 4, tailLength, bodyWidth / 2));
+
+ body[3] = new Area(new Rectangle2D.Double(centerX + bodyLength / 2 + tailLength, centerY - bodyWidth / 4, tailLength, bodyWidth / 2));
+ tailArea = new Area(body[3]);
+ int radius = bodyLength / 2 + tailLength * 2;
+ tailArea.intersect(new Area(new Ellipse2D.Double(centerX - radius, centerY - radius, radius * 2, radius * 2)));
+ body[3] = tailArea;
+
+ // Apply rotation if necessary
+ double angle = getAngle();
+ if (angle != 0) {
+ AffineTransform rotation = AffineTransform.getRotateInstance(angle, controlPoints[0].getX(), controlPoints[0].getY());
+ for (int i = 0; i < body.length; i++) {
+ if (body[i] != null) {
+ Area area = new Area(body[i]);
+ area.transform(rotation);
+ body[i] = area;
+ }
+ }
+ }
+
+ // Create pins.
+ Area pins = new Area();
+
+ int pinWidth = (int) PIN_WIDTH.convertToPixels();
+ int pinThickness = (int) PIN_THICKNESS.convertToPixels();
+ int pinDiameter = (int) PIN_DIAMETER.convertToPixels();
+ for (int i = 0; i < getControlPointCount(); i++) {
+ Point2D point = getControlPoint(i);
+ Shape pin;
+ if (mount == Mount.PCB) {
+ pin = new Ellipse2D.Double(point.getX() - pinDiameter / 2, point.getY() - pinDiameter / 2, pinDiameter, pinDiameter);
+ } else {
+ if (orientation == Orientation.DEFAULT || orientation == Orientation._180) {
+ pin = new Rectangle2D.Double(point.getX() - pinWidth / 2, point.getY() - pinThickness / 2, pinWidth, pinThickness);
+ } else {
+ pin = new Rectangle2D.Double(point.getX() - pinThickness / 2, point.getY() - pinWidth / 2, pinThickness, pinWidth);
+ }
+ }
+ pins.add(new Area(pin));
+ }
+
+ body[4] = pins;
+ }
+ return body;
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ Shape[] body = getBody();
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+// if (componentState != ComponentState.DRAGGING) {
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : BODY_COLOR);
+ for (int i = 0; i < body.length - 1; i++) {
+ // Nut is brighter colored.
+ if (i == body.length - 2)
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : NUT_COLOR);
+ g2d.fill(body[i]);
+ }
+ g2d.setComposite(oldComposite);
+// }
+
+ Color finalBorderColor;
+ Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ if (outlineMode) {
+ finalBorderColor = theme.getOutlineColor();
+ } else {
+ finalBorderColor = BORDER_COLOR;
+ }
+
+ drawingObserver.stopTracking();
+
+ g2d.setColor(finalBorderColor);
+ for (int i = 0; i < body.length - 1; i++) {
+ g2d.draw(body[i]);
+ }
+
+ // Pins are the last piece.
+ Shape pins = body[body.length - 1];
+ if (!outlineMode) {
+ g2d.setColor(METAL_COLOR);
+ g2d.fill(pins);
+ }
+ g2d.setColor(outlineMode ? theme.getOutlineColor() : METAL_COLOR.darker());
+ g2d.draw(pins);
+
+ Color finalLabelColor;
+ if (outlineMode) {
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : theme.getOutlineColor();
+ } else {
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : LABEL_COLOR;
+ }
+ g2d.setColor(finalLabelColor);
+ g2d.setFont(project.getFont());
+
+ // Override font size
+ if (getFontSizeOverride() != null)
+ g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride()));
+
+ double centerX = (controlPoints[0].getX() + controlPoints[3].getX()) / 2;
+ double centerY = (controlPoints[0].getY() + controlPoints[3].getY()) / 2;
+ StringUtils.drawCenteredText(g2d, name, centerX, centerY, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
+
+ drawSelectionOutline(g2d, componentState, outlineMode, project, drawingObserver);
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int bodyWidth = getClosestOdd(width * 3 / 5);
+ int tailWidth = getClosestOdd(width * 3 / 9);
+
+ g2d.setColor(BODY_COLOR);
+ g2d.fillRoundRect((width - tailWidth) / 2, height / 2, tailWidth, height / 2 - 2 * 32 / height, 4 * 32 / width,
+ 4 * 32 / width);
+ g2d.setColor(BORDER_COLOR);
+ g2d.drawRoundRect((width - tailWidth) / 2, height / 2, tailWidth, height / 2 - 2 * 32 / height, 4 * 32 / width,
+ 4 * 32 / width);
+
+ g2d.setColor(NUT_COLOR);
+ g2d.fillRoundRect((width - tailWidth) / 2, 2 * 32 / height, tailWidth, height / 2, 4 * 32 / width, 4 * 32 / width);
+ g2d.setColor(BORDER_COLOR);
+ g2d.drawRoundRect((width - tailWidth) / 2, 2 * 32 / height, tailWidth, height / 2, 4 * 32 / width, 4 * 32 / width);
+
+ g2d.setColor(BODY_COLOR);
+ g2d.fillRect((width - bodyWidth) / 2, height / 7 + 1, bodyWidth, height * 5 / 7);
+ g2d.setColor(BORDER_COLOR);
+ g2d.drawRect((width - bodyWidth) / 2, height / 7 + 1, bodyWidth, height * 5 / 7);
+
+ g2d.setColor(METAL_COLOR);
+ int pinX1 = getClosestOdd((width - bodyWidth * 3 / 4) / 2);
+ int pinX2 = getClosestOdd((width + bodyWidth * 3 / 4) / 2) - 1;
+ g2d.drawLine(pinX1, width * 2 / 8, pinX1, width * 3 / 8);
+ g2d.drawLine(pinX1, width * 5 / 8, pinX1, width * 6 / 8);
+ g2d.drawLine(pinX2, width * 2 / 8, pinX2, width * 3 / 8);
+ g2d.drawLine(pinX2, width * 5 / 8, pinX2, width * 6 / 8);
+ }
+
+ @Override
+ public int getControlPointCount() {
+ return controlPoints.length;
+ }
+
+ @Override
+ public Point2D getControlPoint(int index) {
+ return controlPoints[index];
+ }
+
+ @Override
+ public void setControlPoint(Point2D point, int index) {
+ controlPoints[index].setLocation(point);
+ body = null;
+ }
+
+ @Override
+ public boolean isControlPointSticky(int index) {
+ return true;
+ }
+
+ @Override
+ public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
+ return VisibilityPolicy.NEVER;
+ }
+
+ @EditableProperty(name = "Type")
+ public JackType getValue() {
+ return type;
+ }
+
+ public void setValue(JackType type) {
+ this.type = type;
+ updateControlPoints();
+ }
+
+ @EditableProperty
+ public Orientation getOrientation() {
+ return orientation;
+ }
+
+ public void setOrientation(Orientation orientation) {
+ this.orientation = orientation;
+ updateControlPoints();
+ }
+
+ @EditableProperty
+ public Mount getMount() {
+ return mount;
+ }
+
+ public void setMount(Mount mount) {
+ this.mount = mount;
+ body = null;
+ }
+
+ @Override
+ public boolean canPointMoveFreely(int pointIndex) {
+ return false;
+ }
+
+ enum Mount {
+ PCB, Panel
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/OpenJack1_4.java b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/OpenJack1_4.java
index 6a57d056e..9440045b3 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/OpenJack1_4.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/OpenJack1_4.java
@@ -1,464 +1,458 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.electromechanical;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-import java.awt.RenderingHints;
-import java.awt.Shape;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Area;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.Point2D;
-import java.awt.geom.RoundRectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.awt.StringUtils;
-import org.diylc.common.HorizontalAlignment;
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.Orientation;
-import org.diylc.common.VerticalAlignment;
-import org.diylc.components.AbstractMultiPartComponent;
-import org.diylc.components.electromechanical.OpenJack1_4.OpenJackType;
-import org.diylc.components.transform.OpenJackTransformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-import org.diylc.core.VisibilityPolicy;
-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.Constants;
-
-@ComponentDescriptor(name = "Open 1/4\" Jack", category = "Electro-Mechanical", author = "Branislav Stojkovic",
- description = "Switchcraft-style open panel mount 1/4\" phono jack, stereo and mono",
- zOrder = IDIYComponent.COMPONENT, instanceNamePrefix = "J", transformer = OpenJackTransformer.class, enableCache = true)
-public class OpenJack1_4 extends AbstractMultiPartComponent {
-
- private static final float FONT_SCALE = 0.8f;
- private static final double RING_THETA = Math.PI * 0.795;
- private static final double SLEEVE_THETA = Math.PI * 0.29444444444;
- private static final double SLEEVE_SWITCHED_THETA = Math.PI * 4 / 3;
- private static final double SWITCH_THETA = Math.PI * 5 / 3;
-
- private static final long serialVersionUID = 1L;
-
- private static Color BASE_COLOR = Color.lightGray;
- private static Color WAFER_COLOR = PHENOLIC_DARK_COLOR;
-
- private static Size OUTER_DIAMETER = new Size(0.75d, SizeUnit.in);
- private static Size INNER_DIAMETER = new Size(0.25d, SizeUnit.in);
- private static Size RING_DIAMETER = new Size(0.33d, SizeUnit.in);
- private static Size SPRING_LENGTH = new Size(0.563d, SizeUnit.in);
- private static Size SPRING_WIDTH = new Size(0.12d, SizeUnit.in);
- private static Size HOLE_DIAMETER = new Size(0.05d, SizeUnit.in);
- private static Size HOLE_TO_EDGE = new Size(0.063d, SizeUnit.in);
-
- @SuppressWarnings("unused")
- @Deprecated
- private transient String value = "";
- private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0), new Point2D.Double(0, 0), new Point2D.Double(0, 0)};
- transient Area[] body;
- @Deprecated
- private Orientation orientation = Orientation.DEFAULT;
- private Integer angle = 0;
- private OpenJackType type = OpenJackType.MONO;
- private boolean showLabels = true;
-
- public OpenJack1_4() {
- super();
- updateControlPoints();
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- Shape[] body = getBody();
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
-// if (componentState != ComponentState.DRAGGING) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : WAFER_COLOR);
- g2d.fill(body[0]);
-
- g2d.setComposite(oldComposite);
-// }
-
- Color finalBorderColor;
-
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalBorderColor = theme.getOutlineColor();
- } else {
- finalBorderColor = WAFER_COLOR.darker();
- }
-
- g2d.setColor(finalBorderColor);
- g2d.draw(body[0]);
-
-// if (componentState != ComponentState.DRAGGING) {
- oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
-
- g2d.setColor(Constants.TRANSPARENT_COLOR);
- drawingObserver.startTrackingContinuityArea(true);
- g2d.fill(body[4]);
- g2d.fill(body[5]);
- if (body[6] != null)
- g2d.fill(body[6]);
- drawingObserver.stopTrackingContinuityArea();
-
- if (!outlineMode) {
- g2d.setColor(BASE_COLOR);
-
- g2d.fill(body[1]);
- g2d.fill(body[2]);
- if (body[3] != null)
- g2d.fill(body[3]);
- }
-
- g2d.setComposite(oldComposite);
-// }
-
- drawingObserver.stopTracking();
-
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalBorderColor = theme.getOutlineColor();
- } else {
- finalBorderColor = BASE_COLOR.darker();
- }
-
- g2d.setColor(finalBorderColor);
- g2d.draw(body[1]);
- g2d.draw(body[2]);
- if (body[3] != null)
- g2d.draw(body[3]);
-
- // draw labels
- if (showLabels) {
- g2d.setColor(BASE_COLOR.darker());
- g2d.setFont(project.getFont().deriveFont(project.getFont().getSize2D() * FONT_SCALE));
- 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));
- 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);
- Point2D sleeveLabel = new Point2D.Double(0, 0);
- ringTransform.transform(tipLabel, ringOrSwitchLabel);
- sleeveTransform.transform(tipLabel, sleeveLabel);
-
- if (getTheta() != 0) {
- AffineTransform rotation = AffineTransform.getRotateInstance(getTheta(), controlPoints[0].getX(), controlPoints[0].getY());
- rotation.transform(tipLabel, tipLabel);
- rotation.transform(ringOrSwitchLabel, ringOrSwitchLabel);
- rotation.transform(sleeveLabel, sleeveLabel);
- }
- StringUtils.drawCenteredText(g2d, "T", tipLabel.getX(), tipLabel.getY(), HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
- StringUtils.drawCenteredText(g2d, "S", sleeveLabel.getX(), sleeveLabel.getY(), HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
- if (getValue() == OpenJackType.STEREO)
- StringUtils.drawCenteredText(g2d, "R", ringOrSwitchLabel.getX(), ringOrSwitchLabel.getY(), HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
- if (getValue() == OpenJackType.SWITCHED)
- StringUtils.drawCenteredText(g2d, "Sw", ringOrSwitchLabel.getX(), ringOrSwitchLabel.getY(), HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
- }
-
- drawSelectionOutline(g2d, componentState, outlineMode, project, drawingObserver);
- }
-
- public Area[] getBody() {
- if (body == null) {
- body = new Area[7];
-
- double x = controlPoints[0].getX();
- double y = controlPoints[0].getY();
- int outerDiameter = getClosestOdd(OUTER_DIAMETER.convertToPixels());
- int innerDiameter = getClosestOdd(INNER_DIAMETER.convertToPixels());
- int ringDiameter = getClosestOdd(RING_DIAMETER.convertToPixels());
- int springLength = (int) SPRING_LENGTH.convertToPixels();
- int springWidth = (int) SPRING_WIDTH.convertToPixels();
- int holeDiameter = getClosestOdd(HOLE_DIAMETER.convertToPixels());
- int holeToEdge = (int) HOLE_TO_EDGE.convertToPixels();
-
- double centerY = y + springLength - holeToEdge;
-
- Area wafer =
- new Area(new Ellipse2D.Double(x - outerDiameter / 2, centerY - outerDiameter / 2, outerDiameter,
- outerDiameter));
- wafer.subtract(new Area(new Ellipse2D.Double(x - ringDiameter / 2, centerY - ringDiameter / 2, ringDiameter,
- ringDiameter)));
-
- body[0] = wafer;
-
- Area tip =
- new Area(new RoundRectangle2D.Double(x - springWidth / 2, y - holeToEdge, springWidth, springLength
- - ringDiameter / 2, springWidth, springWidth));
- tip.subtract(new Area(
- new Ellipse2D.Double(x - holeDiameter / 2, y - holeDiameter / 2, holeDiameter, holeDiameter)));
- tip.subtract(wafer);
-
- body[1] = tip;
-
- // no-hole tip for continuity
- tip =
- new Area(new RoundRectangle2D.Double(x - springWidth / 2, y - holeToEdge, springWidth, springLength
- - ringDiameter / 2, springWidth, springWidth));
- tip.subtract(wafer);
- body[4] = tip;
-
- Area sleeve =
- new Area(new RoundRectangle2D.Double(x - springWidth / 2, y - holeToEdge, springWidth, springLength,
- springWidth, springWidth));
- sleeve.subtract(new Area(new Ellipse2D.Double(x - holeDiameter / 2, y - holeDiameter / 2, holeDiameter,
- holeDiameter)));
- sleeve.transform(AffineTransform.getRotateInstance(getValue() == OpenJackType.SWITCHED ? SLEEVE_SWITCHED_THETA : SLEEVE_THETA, x, centerY));
- sleeve.add(new Area(new Ellipse2D.Double(x - ringDiameter / 2, centerY - ringDiameter / 2, ringDiameter,
- ringDiameter)));
- sleeve.subtract(new Area(new Ellipse2D.Double(x - innerDiameter / 2, centerY - innerDiameter / 2, innerDiameter,
- innerDiameter)));
-
- body[2] = sleeve;
-
- // no-hole sleeve for continuity
- sleeve =
- new Area(new RoundRectangle2D.Double(x - springWidth / 2, y - holeToEdge, springWidth, springLength,
- springWidth, springWidth));
- sleeve.transform(AffineTransform.getRotateInstance(getValue() == OpenJackType.SWITCHED ? SLEEVE_SWITCHED_THETA : SLEEVE_THETA, x, centerY));
- sleeve.add(new Area(new Ellipse2D.Double(x - ringDiameter / 2, centerY - ringDiameter / 2, ringDiameter,
- ringDiameter)));
- sleeve.subtract(new Area(new Ellipse2D.Double(x - innerDiameter / 2, centerY - innerDiameter / 2, innerDiameter,
- innerDiameter)));
- body[5] = sleeve;
-
- if (getValue() != OpenJackType.MONO) {
- Area ringOrSwitch =
- new Area(new RoundRectangle2D.Double(x - springWidth / 2, y - holeToEdge, springWidth, springLength,
- springWidth, springWidth));
- ringOrSwitch.subtract(new Area(new Ellipse2D.Double(x - holeDiameter / 2, y - holeDiameter / 2, holeDiameter,
- holeDiameter)));
- ringOrSwitch.transform(AffineTransform.getRotateInstance(getValue() == OpenJackType.SWITCHED ? SWITCH_THETA : RING_THETA, x, centerY));
- ringOrSwitch.subtract(new Area(new Ellipse2D.Double(x - outerDiameter / 2, centerY - outerDiameter / 2, outerDiameter,
- outerDiameter)));
-
- body[3] = ringOrSwitch;
-
- ringOrSwitch =
- new Area(new RoundRectangle2D.Double(x - springWidth / 2, y - holeToEdge, springWidth, springLength,
- springWidth, springWidth));
- ringOrSwitch.transform(AffineTransform.getRotateInstance(getValue() == OpenJackType.SWITCHED ? SWITCH_THETA : RING_THETA, x, centerY));
- ringOrSwitch.subtract(new Area(new Ellipse2D.Double(x - outerDiameter / 2, centerY - outerDiameter / 2, outerDiameter,
- outerDiameter)));
-
- body[6] = ringOrSwitch;
- }
-
- // Rotate if needed
- if (getTheta() != 0) {
- AffineTransform rotation = AffineTransform.getRotateInstance(getTheta(), x, y);
- // Skip the last one because it's already rotated
- for (int i = 0; i < body.length; i++) {
- Shape shape = body[i];
- Area area = (Area) shape;
- if (area != null) {
- area.transform(rotation);
- }
- }
- }
- }
-
- return body;
- }
-
- private void updateControlPoints() {
- double x = controlPoints[0].getX();
- double y = controlPoints[0].getY();
-
- int springLength = (int) SPRING_LENGTH.convertToPixels();
- int holeToEdge = (int) HOLE_TO_EDGE.convertToPixels();
-
- double centerY = y + springLength - holeToEdge;
-
- AffineTransform.getRotateInstance(getValue() == OpenJackType.SWITCHED ? SLEEVE_SWITCHED_THETA : SLEEVE_THETA, x, centerY).transform(controlPoints[0], controlPoints[1]);
- AffineTransform.getRotateInstance(getValue() == OpenJackType.SWITCHED ? SWITCH_THETA : RING_THETA, x, centerY).transform(controlPoints[0], controlPoints[2]);
-
- // Rotate if needed
- if (getTheta() != 0) {
- AffineTransform rotation = AffineTransform.getRotateInstance(getTheta(), x, y);
- for (Point2D point : controlPoints) {
- rotation.transform(point, point);
- }
- }
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int waferDiameter = 15 * width / 32;
- int sleeveDiameter = 9 * width / 32;
-
- AffineTransform tx = g2d.getTransform();
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(6f * width / 32));
- g2d.setColor(BASE_COLOR);
- g2d.drawLine(width / 2, 4 * width / 32, width / 2, width / 4);
-
- g2d.rotate(RING_THETA, width / 2, height / 2);
-
- g2d.drawLine(width / 2, 4 * width / 32, width / 2, width / 4);
-
- g2d.setColor(WAFER_COLOR);
- g2d.draw(new Ellipse2D.Double(width / 2 - waferDiameter / 2, height / 2 - waferDiameter / 2, waferDiameter,
- waferDiameter));
-
- g2d.setColor(BASE_COLOR);
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(2f * width / 32));
- g2d.draw(new Ellipse2D.Double(width / 2 - sleeveDiameter / 2, height / 2 - sleeveDiameter / 2, sleeveDiameter,
- sleeveDiameter));
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(6f * width / 32));
- g2d.rotate(-Math.PI / 2, width / 2, height / 2);
-
- g2d.drawLine(width / 2, 4 * width / 32, width / 2, width / 3);
-
- g2d.setTransform(tx);
- g2d.setColor(LABEL_COLOR);
- g2d.setFont(LABEL_FONT.deriveFont(width / 3.5f));
-
- RenderingHints rh = new RenderingHints(
- RenderingHints.KEY_TEXT_ANTIALIASING,
- RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
- g2d.setRenderingHints(rh);
-
- StringUtils.drawCenteredText(g2d, "6.3", width / 2 - 1, height / 2, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
- }
-
- @Override
- public int getControlPointCount() {
- return controlPoints.length;
- }
-
- @Override
- public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
- return VisibilityPolicy.NEVER;
- }
-
- @Override
- public boolean isControlPointSticky(int index) {
- return index < 2 || (getValue() == OpenJackType.STEREO || getValue() == OpenJackType.SWITCHED);
- }
-
- @Override
- public Point2D getControlPoint(int index) {
- return controlPoints[index];
- }
-
- @Override
- public void setControlPoint(Point2D point, int index) {
- this.controlPoints[index].setLocation(point);
- // Invalidate the body
- body = null;
- }
-
- @EditableProperty
- public Integer getAngle() {
- if (angle == null || (orientation != null && orientation != Orientation.DEFAULT)) {
- if (orientation != null && orientation != Orientation.DEFAULT)
- angle = Integer.parseInt(orientation.name().replace("_", ""));
- else
- angle = 0;
- }
- return angle;
- }
-
- public void setAngle(Integer angle) {
- this.angle = angle;
- updateControlPoints();
- // Invalidate the body
- body = null;
- }
-
- protected double getTheta() {
- return Math.toRadians(getAngle());
- }
-
- @EditableProperty(name = "Type")
- public OpenJackType getValue() {
- return type;
- }
-
- public void setValue(OpenJackType type) {
- this.type = type;
- updateControlPoints();
- // Invalidate the body
- body = null;
- }
-
- @EditableProperty(name = "Labels")
- public boolean getShowLabels() {
- return showLabels;
- }
-
- public void setShowLabels(boolean showLabels) {
- this.showLabels = showLabels;
- }
-
- @Override
- public String getControlPointNodeName(int index) {
- if (index == 0)
- return "Tip";
- if (index == 1)
- return "Sleeve";
- if (index == 2 && getValue() == OpenJackType.STEREO)
- return "Ring";
- if (index == 2 && getValue() == OpenJackType.SWITCHED)
- return "Shunt";
- return null;
- }
-
- @Override
- public boolean canPointMoveFreely(int pointIndex) {
- return false;
- }
-
- public static enum OpenJackType {
-
- MONO, STEREO, SWITCHED;
-
- @Override
- public String toString() {
- return name().substring(0, 1) + name().substring(1).toLowerCase();
- }
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.electromechanical;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Area;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.RoundRectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.awt.StringUtils;
+import org.diylc.common.HorizontalAlignment;
+import org.diylc.common.IPlugInPort;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.Orientation;
+import org.diylc.common.VerticalAlignment;
+import org.diylc.components.AbstractMultiPartComponent;
+import org.diylc.components.electromechanical.OpenJack1_4.OpenJackType;
+import org.diylc.components.transform.OpenJackTransformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+import org.diylc.core.VisibilityPolicy;
+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.Constants;
+
+@ComponentDescriptor(name = "Open 1/4\" Jack", category = "Electro-Mechanical", author = "Branislav Stojkovic",
+ description = "Switchcraft-style open panel mount 1/4\" phono jack, stereo and mono",
+ zOrder = IDIYComponent.COMPONENT, instanceNamePrefix = "J", transformer = OpenJackTransformer.class, enableCache = true)
+public class OpenJack1_4 extends AbstractMultiPartComponent {
+
+ private static final float FONT_SCALE = 0.8f;
+ private static final double RING_THETA = Math.PI * 0.795;
+ private static final double SLEEVE_THETA = Math.PI * 0.29444444444;
+ private static final double SLEEVE_SWITCHED_THETA = Math.PI * 4 / 3;
+ private static final double SWITCH_THETA = Math.PI * 5 / 3;
+
+ private static final long serialVersionUID = 1L;
+
+ private static Color BASE_COLOR = Color.lightGray;
+ private static Color WAFER_COLOR = PHENOLIC_DARK_COLOR;
+
+ private static Size OUTER_DIAMETER = new Size(0.75d, SizeUnit.in);
+ private static Size INNER_DIAMETER = new Size(0.25d, SizeUnit.in);
+ private static Size RING_DIAMETER = new Size(0.33d, SizeUnit.in);
+ private static Size SPRING_LENGTH = new Size(0.563d, SizeUnit.in);
+ private static Size SPRING_WIDTH = new Size(0.12d, SizeUnit.in);
+ private static Size HOLE_DIAMETER = new Size(0.05d, SizeUnit.in);
+ private static Size HOLE_TO_EDGE = new Size(0.063d, SizeUnit.in);
+
+ @SuppressWarnings("unused")
+ @Deprecated
+ private transient String value = "";
+ private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0), new Point2D.Double(0, 0), new Point2D.Double(0, 0)};
+ transient Area[] body;
+ @Deprecated
+ private Orientation orientation = Orientation.DEFAULT;
+ private Integer angle = 0;
+ private OpenJackType type = OpenJackType.MONO;
+ private boolean showLabels = true;
+
+ public OpenJack1_4() {
+ super();
+ updateControlPoints();
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ Shape[] body = getBody();
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+// if (componentState != ComponentState.DRAGGING) {
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : WAFER_COLOR);
+ g2d.fill(body[0]);
+
+ g2d.setComposite(oldComposite);
+// }
+
+ Color finalBorderColor;
+
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalBorderColor = theme.getOutlineColor();
+ } else {
+ finalBorderColor = WAFER_COLOR.darker();
+ }
+
+ g2d.setColor(finalBorderColor);
+ g2d.draw(body[0]);
+
+// if (componentState != ComponentState.DRAGGING) {
+ oldComposite = applyAlpha(g2d, componentState);
+
+ g2d.setColor(Constants.TRANSPARENT_COLOR);
+ drawingObserver.startTrackingContinuityArea(true);
+ g2d.fill(body[4]);
+ g2d.fill(body[5]);
+ if (body[6] != null)
+ g2d.fill(body[6]);
+ drawingObserver.stopTrackingContinuityArea();
+
+ if (!outlineMode) {
+ g2d.setColor(BASE_COLOR);
+
+ g2d.fill(body[1]);
+ g2d.fill(body[2]);
+ if (body[3] != null)
+ g2d.fill(body[3]);
+ }
+
+ g2d.setComposite(oldComposite);
+// }
+
+ drawingObserver.stopTracking();
+
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalBorderColor = theme.getOutlineColor();
+ } else {
+ finalBorderColor = BASE_COLOR.darker();
+ }
+
+ g2d.setColor(finalBorderColor);
+ g2d.draw(body[1]);
+ g2d.draw(body[2]);
+ if (body[3] != null)
+ g2d.draw(body[3]);
+
+ // draw labels
+ if (showLabels) {
+ g2d.setColor(BASE_COLOR.darker());
+ g2d.setFont(project.getFont().deriveFont(project.getFont().getSize2D() * FONT_SCALE));
+ 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));
+ 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);
+ Point2D sleeveLabel = new Point2D.Double(0, 0);
+ ringTransform.transform(tipLabel, ringOrSwitchLabel);
+ sleeveTransform.transform(tipLabel, sleeveLabel);
+
+ if (getTheta() != 0) {
+ AffineTransform rotation = AffineTransform.getRotateInstance(getTheta(), controlPoints[0].getX(), controlPoints[0].getY());
+ rotation.transform(tipLabel, tipLabel);
+ rotation.transform(ringOrSwitchLabel, ringOrSwitchLabel);
+ rotation.transform(sleeveLabel, sleeveLabel);
+ }
+ StringUtils.drawCenteredText(g2d, "T", tipLabel.getX(), tipLabel.getY(), HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
+ StringUtils.drawCenteredText(g2d, "S", sleeveLabel.getX(), sleeveLabel.getY(), HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
+ if (getValue() == OpenJackType.STEREO)
+ StringUtils.drawCenteredText(g2d, "R", ringOrSwitchLabel.getX(), ringOrSwitchLabel.getY(), HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
+ if (getValue() == OpenJackType.SWITCHED)
+ StringUtils.drawCenteredText(g2d, "Sw", ringOrSwitchLabel.getX(), ringOrSwitchLabel.getY(), HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
+ }
+
+ drawSelectionOutline(g2d, componentState, outlineMode, project, drawingObserver);
+ }
+
+ public Area[] getBody() {
+ if (body == null) {
+ body = new Area[7];
+
+ double x = controlPoints[0].getX();
+ double y = controlPoints[0].getY();
+ int outerDiameter = getClosestOdd(OUTER_DIAMETER.convertToPixels());
+ int innerDiameter = getClosestOdd(INNER_DIAMETER.convertToPixels());
+ int ringDiameter = getClosestOdd(RING_DIAMETER.convertToPixels());
+ int springLength = (int) SPRING_LENGTH.convertToPixels();
+ int springWidth = (int) SPRING_WIDTH.convertToPixels();
+ int holeDiameter = getClosestOdd(HOLE_DIAMETER.convertToPixels());
+ int holeToEdge = (int) HOLE_TO_EDGE.convertToPixels();
+
+ double centerY = y + springLength - holeToEdge;
+
+ Area wafer =
+ new Area(new Ellipse2D.Double(x - outerDiameter / 2, centerY - outerDiameter / 2, outerDiameter,
+ outerDiameter));
+ wafer.subtract(new Area(new Ellipse2D.Double(x - ringDiameter / 2, centerY - ringDiameter / 2, ringDiameter,
+ ringDiameter)));
+
+ body[0] = wafer;
+
+ Area tip =
+ new Area(new RoundRectangle2D.Double(x - springWidth / 2, y - holeToEdge, springWidth, springLength
+ - ringDiameter / 2, springWidth, springWidth));
+ tip.subtract(new Area(
+ new Ellipse2D.Double(x - holeDiameter / 2, y - holeDiameter / 2, holeDiameter, holeDiameter)));
+ tip.subtract(wafer);
+
+ body[1] = tip;
+
+ // no-hole tip for continuity
+ tip =
+ new Area(new RoundRectangle2D.Double(x - springWidth / 2, y - holeToEdge, springWidth, springLength
+ - ringDiameter / 2, springWidth, springWidth));
+ tip.subtract(wafer);
+ body[4] = tip;
+
+ Area sleeve =
+ new Area(new RoundRectangle2D.Double(x - springWidth / 2, y - holeToEdge, springWidth, springLength,
+ springWidth, springWidth));
+ sleeve.subtract(new Area(new Ellipse2D.Double(x - holeDiameter / 2, y - holeDiameter / 2, holeDiameter,
+ holeDiameter)));
+ sleeve.transform(AffineTransform.getRotateInstance(getValue() == OpenJackType.SWITCHED ? SLEEVE_SWITCHED_THETA : SLEEVE_THETA, x, centerY));
+ sleeve.add(new Area(new Ellipse2D.Double(x - ringDiameter / 2, centerY - ringDiameter / 2, ringDiameter,
+ ringDiameter)));
+ sleeve.subtract(new Area(new Ellipse2D.Double(x - innerDiameter / 2, centerY - innerDiameter / 2, innerDiameter,
+ innerDiameter)));
+
+ body[2] = sleeve;
+
+ // no-hole sleeve for continuity
+ sleeve =
+ new Area(new RoundRectangle2D.Double(x - springWidth / 2, y - holeToEdge, springWidth, springLength,
+ springWidth, springWidth));
+ sleeve.transform(AffineTransform.getRotateInstance(getValue() == OpenJackType.SWITCHED ? SLEEVE_SWITCHED_THETA : SLEEVE_THETA, x, centerY));
+ sleeve.add(new Area(new Ellipse2D.Double(x - ringDiameter / 2, centerY - ringDiameter / 2, ringDiameter,
+ ringDiameter)));
+ sleeve.subtract(new Area(new Ellipse2D.Double(x - innerDiameter / 2, centerY - innerDiameter / 2, innerDiameter,
+ innerDiameter)));
+ body[5] = sleeve;
+
+ if (getValue() != OpenJackType.MONO) {
+ Area ringOrSwitch =
+ new Area(new RoundRectangle2D.Double(x - springWidth / 2, y - holeToEdge, springWidth, springLength,
+ springWidth, springWidth));
+ ringOrSwitch.subtract(new Area(new Ellipse2D.Double(x - holeDiameter / 2, y - holeDiameter / 2, holeDiameter,
+ holeDiameter)));
+ ringOrSwitch.transform(AffineTransform.getRotateInstance(getValue() == OpenJackType.SWITCHED ? SWITCH_THETA : RING_THETA, x, centerY));
+ ringOrSwitch.subtract(new Area(new Ellipse2D.Double(x - outerDiameter / 2, centerY - outerDiameter / 2, outerDiameter,
+ outerDiameter)));
+
+ body[3] = ringOrSwitch;
+
+ ringOrSwitch =
+ new Area(new RoundRectangle2D.Double(x - springWidth / 2, y - holeToEdge, springWidth, springLength,
+ springWidth, springWidth));
+ ringOrSwitch.transform(AffineTransform.getRotateInstance(getValue() == OpenJackType.SWITCHED ? SWITCH_THETA : RING_THETA, x, centerY));
+ ringOrSwitch.subtract(new Area(new Ellipse2D.Double(x - outerDiameter / 2, centerY - outerDiameter / 2, outerDiameter,
+ outerDiameter)));
+
+ body[6] = ringOrSwitch;
+ }
+
+ // Rotate if needed
+ if (getTheta() != 0) {
+ AffineTransform rotation = AffineTransform.getRotateInstance(getTheta(), x, y);
+ // Skip the last one because it's already rotated
+ for (int i = 0; i < body.length; i++) {
+ Shape shape = body[i];
+ Area area = (Area) shape;
+ if (area != null) {
+ area.transform(rotation);
+ }
+ }
+ }
+ }
+
+ return body;
+ }
+
+ private void updateControlPoints() {
+ double x = controlPoints[0].getX();
+ double y = controlPoints[0].getY();
+
+ int springLength = (int) SPRING_LENGTH.convertToPixels();
+ int holeToEdge = (int) HOLE_TO_EDGE.convertToPixels();
+
+ double centerY = y + springLength - holeToEdge;
+
+ AffineTransform.getRotateInstance(getValue() == OpenJackType.SWITCHED ? SLEEVE_SWITCHED_THETA : SLEEVE_THETA, x, centerY).transform(controlPoints[0], controlPoints[1]);
+ AffineTransform.getRotateInstance(getValue() == OpenJackType.SWITCHED ? SWITCH_THETA : RING_THETA, x, centerY).transform(controlPoints[0], controlPoints[2]);
+
+ // Rotate if needed
+ if (getTheta() != 0) {
+ AffineTransform rotation = AffineTransform.getRotateInstance(getTheta(), x, y);
+ for (Point2D point : controlPoints) {
+ rotation.transform(point, point);
+ }
+ }
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int waferDiameter = 15 * width / 32;
+ int sleeveDiameter = 9 * width / 32;
+
+ AffineTransform tx = g2d.getTransform();
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(6f * width / 32));
+ g2d.setColor(BASE_COLOR);
+ g2d.drawLine(width / 2, 4 * width / 32, width / 2, width / 4);
+
+ g2d.rotate(RING_THETA, width / 2, height / 2);
+
+ g2d.drawLine(width / 2, 4 * width / 32, width / 2, width / 4);
+
+ g2d.setColor(WAFER_COLOR);
+ g2d.draw(new Ellipse2D.Double(width / 2 - waferDiameter / 2, height / 2 - waferDiameter / 2, waferDiameter,
+ waferDiameter));
+
+ g2d.setColor(BASE_COLOR);
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(2f * width / 32));
+ g2d.draw(new Ellipse2D.Double(width / 2 - sleeveDiameter / 2, height / 2 - sleeveDiameter / 2, sleeveDiameter,
+ sleeveDiameter));
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(6f * width / 32));
+ g2d.rotate(-Math.PI / 2, width / 2, height / 2);
+
+ g2d.drawLine(width / 2, 4 * width / 32, width / 2, width / 3);
+
+ g2d.setTransform(tx);
+ g2d.setColor(LABEL_COLOR);
+ g2d.setFont(LABEL_FONT.deriveFont(width / 3.5f));
+
+ RenderingHints rh = new RenderingHints(
+ RenderingHints.KEY_TEXT_ANTIALIASING,
+ RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
+ g2d.setRenderingHints(rh);
+
+ StringUtils.drawCenteredText(g2d, "6.3", width / 2 - 1, height / 2, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
+ }
+
+ @Override
+ public int getControlPointCount() {
+ return controlPoints.length;
+ }
+
+ @Override
+ public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
+ return VisibilityPolicy.NEVER;
+ }
+
+ @Override
+ public boolean isControlPointSticky(int index) {
+ return index < 2 || (getValue() == OpenJackType.STEREO || getValue() == OpenJackType.SWITCHED);
+ }
+
+ @Override
+ public Point2D getControlPoint(int index) {
+ return controlPoints[index];
+ }
+
+ @Override
+ public void setControlPoint(Point2D point, int index) {
+ this.controlPoints[index].setLocation(point);
+ // Invalidate the body
+ body = null;
+ }
+
+ @EditableProperty
+ public Integer getAngle() {
+ if (angle == null || (orientation != null && orientation != Orientation.DEFAULT)) {
+ if (orientation != null && orientation != Orientation.DEFAULT)
+ angle = Integer.parseInt(orientation.name().replace("_", ""));
+ else
+ angle = 0;
+ }
+ return angle;
+ }
+
+ public void setAngle(Integer angle) {
+ this.angle = angle;
+ updateControlPoints();
+ // Invalidate the body
+ body = null;
+ }
+
+ protected double getTheta() {
+ return Math.toRadians(getAngle());
+ }
+
+ @EditableProperty(name = "Type")
+ public OpenJackType getValue() {
+ return type;
+ }
+
+ public void setValue(OpenJackType type) {
+ this.type = type;
+ updateControlPoints();
+ // Invalidate the body
+ body = null;
+ }
+
+ @EditableProperty(name = "Labels")
+ public boolean getShowLabels() {
+ return showLabels;
+ }
+
+ public void setShowLabels(boolean showLabels) {
+ this.showLabels = showLabels;
+ }
+
+ @Override
+ public String getControlPointNodeName(int index) {
+ if (index == 0)
+ return "Tip";
+ if (index == 1)
+ return "Sleeve";
+ if (index == 2 && getValue() == OpenJackType.STEREO)
+ return "Ring";
+ if (index == 2 && getValue() == OpenJackType.SWITCHED)
+ return "Shunt";
+ return null;
+ }
+
+ @Override
+ public boolean canPointMoveFreely(int pointIndex) {
+ return false;
+ }
+
+ public static enum OpenJackType {
+
+ MONO, STEREO, SWITCHED;
+
+ @Override
+ public String toString() {
+ return name().substring(0, 1) + name().substring(1).toLowerCase();
+ }
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/OpenJack1_8.java b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/OpenJack1_8.java
index 34b47f317..ec05aa0c3 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/OpenJack1_8.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/OpenJack1_8.java
@@ -102,10 +102,7 @@ public class OpenJack1_8 extends AbstractMultiPartComponent {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
// if (componentState != ComponentState.DRAGGING) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : WAFER_COLOR);
g2d.fill(body[0]);
@@ -126,10 +123,7 @@ public class OpenJack1_8 extends AbstractMultiPartComponent {
g2d.draw(body[0]);
// if (componentState != ComponentState.DRAGGING) {
- oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : BASE_COLOR);
drawingObserver.startTrackingContinuityArea(true);
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/PilotLampHolder.java b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/PilotLampHolder.java
index a0f15e032..5bc55f0e2 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/PilotLampHolder.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/PilotLampHolder.java
@@ -94,10 +94,7 @@ public class PilotLampHolder extends AbstractMultiPartComponent {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
// if (componentState != ComponentState.DRAGGING) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : WAFER_COLOR);
g2d.fill(body[0]);
@@ -118,10 +115,7 @@ public class PilotLampHolder extends AbstractMultiPartComponent {
g2d.draw(body[0]);
// if (componentState != ComponentState.DRAGGING) {
- oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : BASE_COLOR);
drawingObserver.startTrackingContinuityArea(true);
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/PinHeader.java b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/PinHeader.java
index 958bd203d..5240b69bc 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/PinHeader.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/PinHeader.java
@@ -222,10 +222,7 @@ public class PinHeader extends AbstractTransparentComponent {
Area[] body = getBody();
Area mainArea = body[0];
Area shroudArea = body[1];
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor);
g2d.fill(mainArea);
if (shroudArea != null) {
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/PlasticDCJack.java b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/PlasticDCJack.java
index 03178237b..8d6a0cb21 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/PlasticDCJack.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/PlasticDCJack.java
@@ -1,285 +1,282 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.electromechanical;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-import java.awt.Shape;
-import java.awt.geom.Area;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.awt.StringUtils;
-import org.diylc.common.HorizontalAlignment;
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.VerticalAlignment;
-import org.diylc.components.AbstractMultiPartComponent;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-import org.diylc.core.VisibilityPolicy;
-import org.diylc.core.annotations.ComponentDescriptor;
-import org.diylc.core.annotations.EditableProperty;
-import org.diylc.core.gerber.IGerberComponentSimple;
-import org.diylc.core.measures.Size;
-import org.diylc.core.measures.SizeUnit;
-import org.diylc.utils.Constants;
-
-@ComponentDescriptor(name = "Plastic DC Jack", category = "Electro-Mechanical", author = "Branislav Stojkovic",
- description = "Panel mount plastic DC jack", zOrder = IDIYComponent.COMPONENT,
- instanceNamePrefix = "J", autoEdit = false, enableCache = true)
-public class PlasticDCJack extends AbstractMultiPartComponent implements IGerberComponentSimple {
-
- private static final long serialVersionUID = 1L;
-
- private static Size LUG_WIDTH = new Size(0.08d, SizeUnit.in);
- private static Size LUG_THICKNESS = new Size(0.02d, SizeUnit.in);
- private static Size SPACING = new Size(0.1d, SizeUnit.in);
- private static Size DIAMETER = new Size(0.5d, SizeUnit.in);
- private static Color BODY_COLOR = Color.decode("#666666");
- private static Color BORDER_COLOR = Color.black;
- private static Color MARKING_COLOR = Color.lightGray;
-
- private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0), new Point2D.Double(0, 0), new Point2D.Double(0, 0)};
- private String value = "";
- private DCPolarity polarity = DCPolarity.CENTER_NEGATIVE;
- transient private Area[] body;
-
- public PlasticDCJack() {
- updateControlPoints();
- }
-
- private void updateControlPoints() {
- // invalidate body shape
- body = null;
-
- double x = controlPoints[0].getX();
- double y = controlPoints[0].getY();
-
- int spacing = (int) SPACING.convertToPixels();
- controlPoints[1] = new Point2D.Double(x + spacing, y + spacing);
- controlPoints[2] = new Point2D.Double(x - spacing, y + spacing * 2);
- }
-
- @Override
- public Area[] getBody() {
- if (body == null) {
- body = new Area[4];
-
- double x = controlPoints[0].getX();
- double y = controlPoints[0].getY();
- int spacing = (int) SPACING.convertToPixels();
- int diameter = getClosestOdd(DIAMETER.convertToPixels());
- body[0] = new Area(new Ellipse2D.Double(x - diameter / 2, y + spacing - diameter / 2, diameter, diameter));
-
- int rectWidth = (int) (diameter / Math.sqrt(2)) - 2;
- body[1] = new Area(new Rectangle2D.Double(x - rectWidth / 2, y + spacing - rectWidth / 2, rectWidth, rectWidth));
-
- int lugWidth = getClosestOdd(LUG_WIDTH.convertToPixels());
- int lugThickness = getClosestOdd(LUG_THICKNESS.convertToPixels());
-
- Point2D groundPoint = controlPoints[controlPoints.length - 1];
- Area groundLug =
- new Area(new Ellipse2D.Double(groundPoint.getX() + spacing - lugWidth / 2, groundPoint.getY() - lugWidth / 2, lugWidth,
- lugWidth));
- groundLug.add(new Area(new Rectangle2D.Double(groundPoint.getX(), groundPoint.getY() - lugWidth / 2, spacing, lugWidth)));
- groundLug.subtract(new Area(new Ellipse2D.Double(groundPoint.getX() + spacing - lugWidth / 6, groundPoint.getY() - lugWidth
- / 6, lugWidth / 3, lugWidth / 3)));
- body[2] = groundLug;
-
- Area lugArea = new Area();
- for (int i = 0; i < controlPoints.length; i++) {
- Point2D point = controlPoints[i];
- if (i == getControlPointCount() - 1) {
- lugArea.add(new Area(
- new Rectangle2D.Double(point.getX() - lugThickness / 2, point.getY() - lugWidth / 2, lugThickness, lugWidth)));
- } else {
- lugArea.add(new Area(
- new Rectangle2D.Double(point.getX() - lugWidth / 2, point.getY() - lugThickness / 2, lugWidth, lugThickness)));
- }
- }
- body[3] = lugArea;
- }
- return body;
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- Shape[] body = getBody();
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
-// if (componentState != ComponentState.DRAGGING) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : BODY_COLOR);
- g2d.fill(body[0]);
- drawingObserver.stopTracking();
- if (!outlineMode) {
- g2d.setColor(PHENOLIC_DARK_COLOR);
- g2d.fill(body[1]);
- }
- g2d.setComposite(oldComposite);
-// }
-
- Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- Color finalBorderColor;
- if (outlineMode) {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : BORDER_COLOR;
- }
-
- g2d.setColor(finalBorderColor);
- g2d.draw(body[0]);
- if (!outlineMode) {
- g2d.setColor(PHENOLIC_DARK_COLOR.darker());
- g2d.draw(body[1]);
-
- g2d.setColor(METAL_COLOR);
- g2d.fill(body[2]);
- g2d.setColor(METAL_COLOR.darker());
- g2d.draw(body[2]);
-
- g2d.setColor(METAL_COLOR);
- g2d.fill(body[3]);
- }
-
- g2d.setColor(outlineMode ? theme.getOutlineColor() : METAL_COLOR.darker());
- g2d.draw(body[3]);
-
- if (!outlineMode && getPolarity() != DCPolarity.NONE) {
- int spacing = (int) SPACING.convertToPixels();
- g2d.setColor(MARKING_COLOR);
- g2d.setFont(project.getFont().deriveFont(12f));
- StringUtils.drawCenteredText(g2d, getPolarity() == DCPolarity.CENTER_NEGATIVE ? "+" : "-", controlPoints[0].getX(),
- controlPoints[0].getY() - spacing * 7 / 16, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
- StringUtils.drawCenteredText(g2d, getPolarity() == DCPolarity.CENTER_NEGATIVE ? "_" : "+", controlPoints[2].getX(),
- controlPoints[2].getY() - spacing * 3 / 4, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
- }
-
- drawSelectionOutline(g2d, componentState, outlineMode, project, drawingObserver);
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int margin = 2 * 32 / width;
- int diameter = getClosestOdd(width - margin);
- g2d.setColor(BODY_COLOR);
- g2d.fillOval((width - diameter) / 2, (height - diameter) / 2, diameter, diameter);
- g2d.setColor(BORDER_COLOR);
- g2d.drawOval((width - diameter) / 2, (height - diameter) / 2, diameter, diameter);
- int rectWidth = getClosestOdd(((width - 2 * margin) / Math.sqrt(2)) - margin / 2);
- g2d.setColor(PHENOLIC_DARK_COLOR);
- g2d.fillRect((width - rectWidth) / 2, (height - rectWidth) / 2, rectWidth, rectWidth);
- g2d.setColor(PHENOLIC_DARK_COLOR.darker());
- g2d.drawRect((width - rectWidth) / 2, (height - rectWidth) / 2, rectWidth, rectWidth);
- int lugWidth = 4 * 32 / width;
- g2d.setColor(METAL_COLOR);
- g2d.drawLine((width - lugWidth) / 2, height / 3, (width + lugWidth) / 2, height / 3);
- g2d.drawLine(width * 2 / 3, (height - lugWidth) / 2, width * 2 / 3, (height + lugWidth) / 2);
- g2d.fillOval((width - lugWidth) / 2, height * 2 / 3 - lugWidth / 2, lugWidth, lugWidth);
- g2d.fillRect(width / 2 - lugWidth * 3 / 2, height * 2 / 3 - lugWidth / 2, lugWidth * 3 / 2, lugWidth);
- g2d.setColor(PHENOLIC_DARK_COLOR);
- g2d.fillOval((width - margin) / 2, height * 2 / 3 - margin / 2, margin, margin);
- }
-
- @Override
- public int getControlPointCount() {
- return controlPoints.length;
- }
-
- @Override
- public Point2D getControlPoint(int index) {
- return controlPoints[index];
- }
-
- @Override
- public void setControlPoint(Point2D point, int index) {
- controlPoints[index].setLocation(point);
- this.body = null;
- }
-
- @Override
- public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
- return VisibilityPolicy.NEVER;
- }
-
- @Override
- public boolean isControlPointSticky(int index) {
- return true;
- }
-
- @EditableProperty
- @Override
- public String getValue() {
- return value;
- }
-
- @Override
- public void setValue(String value) {
- this.value = value;
- }
-
- @EditableProperty
- public DCPolarity getPolarity() {
- if (polarity == null) {
- polarity = DCPolarity.CENTER_NEGATIVE;
- }
- return polarity;
- }
-
- public void setPolarity(DCPolarity polarity) {
- this.polarity = polarity;
- }
-
- @Override
- public boolean canPointMoveFreely(int pointIndex) {
- return false;
- }
-
- @Override
- public Rectangle2D getCachingBounds() {
- int margin = 20;
- Rectangle2D bounds = getBody()[0].getBounds2D();
- return new Rectangle2D.Double(bounds.getX() - margin, bounds.getY() - margin, bounds.getWidth() + 2 * margin, bounds.getHeight() + 2 * margin);
- }
-
- @Deprecated
- @Override
- public Integer getFontSizeOverride() {
- return super.getFontSizeOverride();
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.electromechanical;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.geom.Area;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.awt.StringUtils;
+import org.diylc.common.HorizontalAlignment;
+import org.diylc.common.IPlugInPort;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.VerticalAlignment;
+import org.diylc.components.AbstractMultiPartComponent;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+import org.diylc.core.VisibilityPolicy;
+import org.diylc.core.annotations.ComponentDescriptor;
+import org.diylc.core.annotations.EditableProperty;
+import org.diylc.core.gerber.IGerberComponentSimple;
+import org.diylc.core.measures.Size;
+import org.diylc.core.measures.SizeUnit;
+import org.diylc.utils.Constants;
+
+@ComponentDescriptor(name = "Plastic DC Jack", category = "Electro-Mechanical", author = "Branislav Stojkovic",
+ description = "Panel mount plastic DC jack", zOrder = IDIYComponent.COMPONENT,
+ instanceNamePrefix = "J", autoEdit = false, enableCache = true)
+public class PlasticDCJack extends AbstractMultiPartComponent implements IGerberComponentSimple {
+
+ private static final long serialVersionUID = 1L;
+
+ private static Size LUG_WIDTH = new Size(0.08d, SizeUnit.in);
+ private static Size LUG_THICKNESS = new Size(0.02d, SizeUnit.in);
+ private static Size SPACING = new Size(0.1d, SizeUnit.in);
+ private static Size DIAMETER = new Size(0.5d, SizeUnit.in);
+ private static Color BODY_COLOR = Color.decode("#666666");
+ private static Color BORDER_COLOR = Color.black;
+ private static Color MARKING_COLOR = Color.lightGray;
+
+ private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0), new Point2D.Double(0, 0), new Point2D.Double(0, 0)};
+ private String value = "";
+ private DCPolarity polarity = DCPolarity.CENTER_NEGATIVE;
+ transient private Area[] body;
+
+ public PlasticDCJack() {
+ updateControlPoints();
+ }
+
+ private void updateControlPoints() {
+ // invalidate body shape
+ body = null;
+
+ double x = controlPoints[0].getX();
+ double y = controlPoints[0].getY();
+
+ int spacing = (int) SPACING.convertToPixels();
+ controlPoints[1] = new Point2D.Double(x + spacing, y + spacing);
+ controlPoints[2] = new Point2D.Double(x - spacing, y + spacing * 2);
+ }
+
+ @Override
+ public Area[] getBody() {
+ if (body == null) {
+ body = new Area[4];
+
+ double x = controlPoints[0].getX();
+ double y = controlPoints[0].getY();
+ int spacing = (int) SPACING.convertToPixels();
+ int diameter = getClosestOdd(DIAMETER.convertToPixels());
+ body[0] = new Area(new Ellipse2D.Double(x - diameter / 2, y + spacing - diameter / 2, diameter, diameter));
+
+ int rectWidth = (int) (diameter / Math.sqrt(2)) - 2;
+ body[1] = new Area(new Rectangle2D.Double(x - rectWidth / 2, y + spacing - rectWidth / 2, rectWidth, rectWidth));
+
+ int lugWidth = getClosestOdd(LUG_WIDTH.convertToPixels());
+ int lugThickness = getClosestOdd(LUG_THICKNESS.convertToPixels());
+
+ Point2D groundPoint = controlPoints[controlPoints.length - 1];
+ Area groundLug =
+ new Area(new Ellipse2D.Double(groundPoint.getX() + spacing - lugWidth / 2, groundPoint.getY() - lugWidth / 2, lugWidth,
+ lugWidth));
+ groundLug.add(new Area(new Rectangle2D.Double(groundPoint.getX(), groundPoint.getY() - lugWidth / 2, spacing, lugWidth)));
+ groundLug.subtract(new Area(new Ellipse2D.Double(groundPoint.getX() + spacing - lugWidth / 6, groundPoint.getY() - lugWidth
+ / 6, lugWidth / 3, lugWidth / 3)));
+ body[2] = groundLug;
+
+ Area lugArea = new Area();
+ for (int i = 0; i < controlPoints.length; i++) {
+ Point2D point = controlPoints[i];
+ if (i == getControlPointCount() - 1) {
+ lugArea.add(new Area(
+ new Rectangle2D.Double(point.getX() - lugThickness / 2, point.getY() - lugWidth / 2, lugThickness, lugWidth)));
+ } else {
+ lugArea.add(new Area(
+ new Rectangle2D.Double(point.getX() - lugWidth / 2, point.getY() - lugThickness / 2, lugWidth, lugThickness)));
+ }
+ }
+ body[3] = lugArea;
+ }
+ return body;
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ Shape[] body = getBody();
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+// if (componentState != ComponentState.DRAGGING) {
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : BODY_COLOR);
+ g2d.fill(body[0]);
+ drawingObserver.stopTracking();
+ if (!outlineMode) {
+ g2d.setColor(PHENOLIC_DARK_COLOR);
+ g2d.fill(body[1]);
+ }
+ g2d.setComposite(oldComposite);
+// }
+
+ Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ Color finalBorderColor;
+ if (outlineMode) {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : BORDER_COLOR;
+ }
+
+ g2d.setColor(finalBorderColor);
+ g2d.draw(body[0]);
+ if (!outlineMode) {
+ g2d.setColor(PHENOLIC_DARK_COLOR.darker());
+ g2d.draw(body[1]);
+
+ g2d.setColor(METAL_COLOR);
+ g2d.fill(body[2]);
+ g2d.setColor(METAL_COLOR.darker());
+ g2d.draw(body[2]);
+
+ g2d.setColor(METAL_COLOR);
+ g2d.fill(body[3]);
+ }
+
+ g2d.setColor(outlineMode ? theme.getOutlineColor() : METAL_COLOR.darker());
+ g2d.draw(body[3]);
+
+ if (!outlineMode && getPolarity() != DCPolarity.NONE) {
+ int spacing = (int) SPACING.convertToPixels();
+ g2d.setColor(MARKING_COLOR);
+ g2d.setFont(project.getFont().deriveFont(12f));
+ StringUtils.drawCenteredText(g2d, getPolarity() == DCPolarity.CENTER_NEGATIVE ? "+" : "-", controlPoints[0].getX(),
+ controlPoints[0].getY() - spacing * 7 / 16, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
+ StringUtils.drawCenteredText(g2d, getPolarity() == DCPolarity.CENTER_NEGATIVE ? "_" : "+", controlPoints[2].getX(),
+ controlPoints[2].getY() - spacing * 3 / 4, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
+ }
+
+ drawSelectionOutline(g2d, componentState, outlineMode, project, drawingObserver);
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int margin = 2 * 32 / width;
+ int diameter = getClosestOdd(width - margin);
+ g2d.setColor(BODY_COLOR);
+ g2d.fillOval((width - diameter) / 2, (height - diameter) / 2, diameter, diameter);
+ g2d.setColor(BORDER_COLOR);
+ g2d.drawOval((width - diameter) / 2, (height - diameter) / 2, diameter, diameter);
+ int rectWidth = getClosestOdd(((width - 2 * margin) / Math.sqrt(2)) - margin / 2);
+ g2d.setColor(PHENOLIC_DARK_COLOR);
+ g2d.fillRect((width - rectWidth) / 2, (height - rectWidth) / 2, rectWidth, rectWidth);
+ g2d.setColor(PHENOLIC_DARK_COLOR.darker());
+ g2d.drawRect((width - rectWidth) / 2, (height - rectWidth) / 2, rectWidth, rectWidth);
+ int lugWidth = 4 * 32 / width;
+ g2d.setColor(METAL_COLOR);
+ g2d.drawLine((width - lugWidth) / 2, height / 3, (width + lugWidth) / 2, height / 3);
+ g2d.drawLine(width * 2 / 3, (height - lugWidth) / 2, width * 2 / 3, (height + lugWidth) / 2);
+ g2d.fillOval((width - lugWidth) / 2, height * 2 / 3 - lugWidth / 2, lugWidth, lugWidth);
+ g2d.fillRect(width / 2 - lugWidth * 3 / 2, height * 2 / 3 - lugWidth / 2, lugWidth * 3 / 2, lugWidth);
+ g2d.setColor(PHENOLIC_DARK_COLOR);
+ g2d.fillOval((width - margin) / 2, height * 2 / 3 - margin / 2, margin, margin);
+ }
+
+ @Override
+ public int getControlPointCount() {
+ return controlPoints.length;
+ }
+
+ @Override
+ public Point2D getControlPoint(int index) {
+ return controlPoints[index];
+ }
+
+ @Override
+ public void setControlPoint(Point2D point, int index) {
+ controlPoints[index].setLocation(point);
+ this.body = null;
+ }
+
+ @Override
+ public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
+ return VisibilityPolicy.NEVER;
+ }
+
+ @Override
+ public boolean isControlPointSticky(int index) {
+ return true;
+ }
+
+ @EditableProperty
+ @Override
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ @EditableProperty
+ public DCPolarity getPolarity() {
+ if (polarity == null) {
+ polarity = DCPolarity.CENTER_NEGATIVE;
+ }
+ return polarity;
+ }
+
+ public void setPolarity(DCPolarity polarity) {
+ this.polarity = polarity;
+ }
+
+ @Override
+ public boolean canPointMoveFreely(int pointIndex) {
+ return false;
+ }
+
+ @Override
+ public Rectangle2D getCachingBounds() {
+ int margin = 20;
+ Rectangle2D bounds = getBody()[0].getBounds2D();
+ return new Rectangle2D.Double(bounds.getX() - margin, bounds.getY() - margin, bounds.getWidth() + 2 * margin, bounds.getHeight() + 2 * margin);
+ }
+
+ @Deprecated
+ @Override
+ public Integer getFontSizeOverride() {
+ return super.getFontSizeOverride();
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/RCAJack.java b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/RCAJack.java
index 28f86a253..b3d08bc2d 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/RCAJack.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/RCAJack.java
@@ -1,345 +1,339 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.electromechanical;
-
-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.Area;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.Path2D;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.awt.TwoCircleTangent;
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.Orientation;
-import org.diylc.components.AbstractMultiPartComponent;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-import org.diylc.core.VisibilityPolicy;
-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.Constants;
-
-@ComponentDescriptor(name = "RCA Jack", category = "Electro-Mechanical", author = "Branislav Stojkovic",
- description = "Panel mount RCA phono jack socket", zOrder = IDIYComponent.COMPONENT, instanceNamePrefix = "J",
- enableCache = true)
-public class RCAJack extends AbstractMultiPartComponent {
-
- private static final long serialVersionUID = 1L;
-
- private static Color BASE_COLOR = Color.lightGray;
- private static Color WAFER_COLOR = Color.black;
-
- private static Size BODY_DIAMETER = new Size(0.52d, SizeUnit.in);
- private static Size WAFER_DIAMETER = new Size(0.2d, SizeUnit.in);
- private static Size HEX_DIAMETER = new Size(0.44d, SizeUnit.in);
- private static Size SPRING_LENGTH = new Size(0.563d, SizeUnit.in);
- private static Size SPRING_WIDTH = new Size(0.12d, SizeUnit.in);
- private static Size HOLE_DIAMETER = new Size(0.05d, SizeUnit.in);
- private static Size HOLE_TO_EDGE = new Size(0.063d, SizeUnit.in);
-
- private String value = "";
- private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0), new Point2D.Double(0, 0) };
- transient Area[] body;
- private Orientation orientation = Orientation.DEFAULT;
-
- public RCAJack() {
- super();
- updateControlPoints();
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- Shape[] body = getBody();
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
-// if (componentState != ComponentState.DRAGGING) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : WAFER_COLOR);
- g2d.fill(body[0]);
-
- drawingObserver.stopTracking();
-
- g2d.setComposite(oldComposite);
-// }
-
- Color finalBorderColor;
-
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalBorderColor = theme.getOutlineColor();
- } else {
- finalBorderColor = WAFER_COLOR.darker();
- }
-
- g2d.setColor(finalBorderColor);
- g2d.draw(body[0]);
-
- oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : BASE_COLOR);
-
- drawingObserver.startTrackingContinuityArea(true);
- drawingObserver.startTracking();
- g2d.fill(body[1]);
- g2d.fill(body[2]);
- drawingObserver.stopTracking();
- drawingObserver.stopTrackingContinuityArea();
-
- if (body[3] != null)
- g2d.fill(body[3]);
-
- g2d.setComposite(oldComposite);
-
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalBorderColor = theme.getOutlineColor();
- } else {
- finalBorderColor = BASE_COLOR.darker();
- }
-
- g2d.setColor(finalBorderColor);
- g2d.draw(body[1]);
- g2d.draw(body[2]);
- if (body[3] != null)
- g2d.draw(body[3]);
-
- drawSelectionOutline(g2d, componentState, outlineMode, project, drawingObserver);
- }
-
- public Area[] getBody() {
- if (body == null) {
- body = new Area[4];
-
- double x0 = controlPoints[0].getX();
- double y0 = controlPoints[0].getY();
- double x1 = controlPoints[1].getX();
- double y1 = controlPoints[1].getY();
- int bodyDiameter = getClosestOdd(BODY_DIAMETER.convertToPixels());
- int waferDiameter = getClosestOdd(WAFER_DIAMETER.convertToPixels());
- int springWidth = (int) SPRING_WIDTH.convertToPixels();
- int holeDiameter = getClosestOdd(HOLE_DIAMETER.convertToPixels());
- double hexDiameter = HEX_DIAMETER.convertToPixels();
-
- Area wafer =
- new Area(new Ellipse2D.Double(x0 - waferDiameter / 2, y0 - waferDiameter / 2, waferDiameter,
- waferDiameter));
- wafer.subtract(new Area(new Ellipse2D.Double(x0 - holeDiameter / 2, y0 - holeDiameter / 2, holeDiameter,
- holeDiameter)));
-
- body[0] = wafer;
-
- Area tip = new TwoCircleTangent(controlPoints[0], controlPoints[1], bodyDiameter / 2, springWidth / 2);
- tip.subtract(new Area(
- new Ellipse2D.Double(x1 - holeDiameter / 2, y1 - holeDiameter / 2, holeDiameter, holeDiameter)));
- tip.subtract(new Area(new Ellipse2D.Double(x0 - waferDiameter / 2, y0 - waferDiameter / 2, waferDiameter,
- waferDiameter)));
-
- body[1] = tip;
-
- Area sleeve =
- new Area(new Ellipse2D.Double(x0 - springWidth / 2, y0 - springWidth / 2,
- springWidth, springWidth));
- sleeve.subtract(new Area(new Ellipse2D.Double(x0 - holeDiameter / 2, y0 - holeDiameter / 2, holeDiameter,
- holeDiameter)));
-
- body[2] = sleeve;
-
- Path2D hex = new Path2D.Double();
- for (int i = 0; i < 6; i++) {
- double x = x0 + Math.cos(Math.PI / 3 * i) * hexDiameter / 2;
- double y = y0 + Math.sin(Math.PI / 3 * i) * hexDiameter / 2;
- if (i == 0)
- hex.moveTo(x, y);
- else
- hex.lineTo(x, y);
- }
- hex.closePath();
- Area hexArea = new Area(hex);
- hexArea.subtract(new Area(new Ellipse2D.Double(x0 - waferDiameter / 2, y0 - waferDiameter / 2, waferDiameter,
- waferDiameter)));
- body[3] = hexArea;
- }
-
- return body;
- }
-
- @SuppressWarnings("incomplete-switch")
- private void updateControlPoints() {
- double x = controlPoints[0].getX();
- double y = controlPoints[0].getY();
-
- int springLength = (int) SPRING_LENGTH.convertToPixels();
- int holeToEdge = (int) HOLE_TO_EDGE.convertToPixels();
-
- double centerY = y + springLength - holeToEdge;
-
- controlPoints[1].setLocation(x, centerY);
-
- // Rotate if needed
- if (orientation != Orientation.DEFAULT) {
- double theta = 0;
- switch (orientation) {
- case _90:
- theta = Math.PI / 2;
- break;
- case _180:
- theta = Math.PI;
- break;
- case _270:
- theta = Math.PI * 3 / 2;
- break;
- }
-
- AffineTransform rotation = AffineTransform.getRotateInstance(theta, x, y);
- rotation.transform(controlPoints[1], controlPoints[1]);
- }
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- double x0 = width * 0.35;
- double y0 = height * 0.65;
- double x1 = width * 0.75;
- double y1 = height * 0.25;
- TwoCircleTangent main = new TwoCircleTangent(new Point2D.Double(width * 0.35, height * 0.65), new Point2D.Double(x1, y1), width * 0.3, width * 0.1);
- main.subtract(new Area(new Ellipse2D.Double(x0 - 1, y0 - 1, 3, 3)));
- main.subtract(new Area(new Ellipse2D.Double(x1 - 1, y1 - 1, 2, 2)));
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f));
- g2d.setColor(BASE_COLOR);
- g2d.fill(main);
- g2d.setColor(BASE_COLOR.darker());
- g2d.draw(main);
-
- double hexDiameter = width * 0.48;
-
- Path2D hex = new Path2D.Double();
- for (int i = 0; i < 6; i++) {
- double x = x0 + Math.cos(Math.PI / 3 * i) * hexDiameter / 2;
- double y = y0 + Math.sin(Math.PI / 3 * i) * hexDiameter / 2;
- if (i == 0)
- hex.moveTo(x, y);
- else
- hex.lineTo(x, y);
- }
- hex.closePath();
- g2d.draw(hex);
-
- double waferDiameter = width * 0.22;
-// g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(2f));
- g2d.setColor(WAFER_COLOR);
- g2d.draw(new Ellipse2D.Double(x0 - waferDiameter / 2, y0 - waferDiameter / 2, waferDiameter, waferDiameter));
- }
-
- @Override
- public int getControlPointCount() {
- return controlPoints.length;
- }
-
- @Override
- public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
- return VisibilityPolicy.NEVER;
- }
-
- @Override
- public boolean isControlPointSticky(int index) {
- return true;
- }
-
- @Override
- public Point2D getControlPoint(int index) {
- return controlPoints[index];
- }
-
- @Override
- public void setControlPoint(Point2D point, int index) {
- this.controlPoints[index].setLocation(point);
- // Invalidate the body
- body = null;
- }
-
- @Override
- public String getValue() {
- return value;
- }
-
- @Override
- public void setValue(String value) {
- this.value = value;
- }
-
- @EditableProperty
- public Orientation getOrientation() {
- return orientation;
- }
-
- public void setOrientation(Orientation orientation) {
- this.orientation = orientation;
- updateControlPoints();
- // Invalidate the body
- body = null;
- }
-
- @Override
- public String getControlPointNodeName(int index) {
- return getName() + (index == 0 ? "Tip" : "Sleeve");
- }
-
- @Override
- public boolean canPointMoveFreely(int pointIndex) {
- return false;
- }
-
- @Override
- public Rectangle2D getCachingBounds() {
- int margin = 20;
- Rectangle2D bounds = getBody()[1].getBounds2D();
- return new Rectangle2D.Double(bounds.getX() - margin, bounds.getY() - margin, bounds.getWidth() + 2 * margin, bounds.getHeight() + 2 * margin);
- }
-
- @Deprecated
- @Override
- public Integer getFontSizeOverride() {
- return super.getFontSizeOverride();
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.electromechanical;
+
+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.Area;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Path2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.awt.TwoCircleTangent;
+import org.diylc.common.IPlugInPort;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.Orientation;
+import org.diylc.components.AbstractMultiPartComponent;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+import org.diylc.core.VisibilityPolicy;
+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.Constants;
+
+@ComponentDescriptor(name = "RCA Jack", category = "Electro-Mechanical", author = "Branislav Stojkovic",
+ description = "Panel mount RCA phono jack socket", zOrder = IDIYComponent.COMPONENT, instanceNamePrefix = "J",
+ enableCache = true)
+public class RCAJack extends AbstractMultiPartComponent {
+
+ private static final long serialVersionUID = 1L;
+
+ private static Color BASE_COLOR = Color.lightGray;
+ private static Color WAFER_COLOR = Color.black;
+
+ private static Size BODY_DIAMETER = new Size(0.52d, SizeUnit.in);
+ private static Size WAFER_DIAMETER = new Size(0.2d, SizeUnit.in);
+ private static Size HEX_DIAMETER = new Size(0.44d, SizeUnit.in);
+ private static Size SPRING_LENGTH = new Size(0.563d, SizeUnit.in);
+ private static Size SPRING_WIDTH = new Size(0.12d, SizeUnit.in);
+ private static Size HOLE_DIAMETER = new Size(0.05d, SizeUnit.in);
+ private static Size HOLE_TO_EDGE = new Size(0.063d, SizeUnit.in);
+
+ private String value = "";
+ private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0), new Point2D.Double(0, 0) };
+ transient Area[] body;
+ private Orientation orientation = Orientation.DEFAULT;
+
+ public RCAJack() {
+ super();
+ updateControlPoints();
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ Shape[] body = getBody();
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+// if (componentState != ComponentState.DRAGGING) {
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : WAFER_COLOR);
+ g2d.fill(body[0]);
+
+ drawingObserver.stopTracking();
+
+ g2d.setComposite(oldComposite);
+// }
+
+ Color finalBorderColor;
+
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalBorderColor = theme.getOutlineColor();
+ } else {
+ finalBorderColor = WAFER_COLOR.darker();
+ }
+
+ g2d.setColor(finalBorderColor);
+ g2d.draw(body[0]);
+
+ oldComposite = applyAlpha(g2d, componentState);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : BASE_COLOR);
+
+ drawingObserver.startTrackingContinuityArea(true);
+ drawingObserver.startTracking();
+ g2d.fill(body[1]);
+ g2d.fill(body[2]);
+ drawingObserver.stopTracking();
+ drawingObserver.stopTrackingContinuityArea();
+
+ if (body[3] != null)
+ g2d.fill(body[3]);
+
+ g2d.setComposite(oldComposite);
+
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalBorderColor = theme.getOutlineColor();
+ } else {
+ finalBorderColor = BASE_COLOR.darker();
+ }
+
+ g2d.setColor(finalBorderColor);
+ g2d.draw(body[1]);
+ g2d.draw(body[2]);
+ if (body[3] != null)
+ g2d.draw(body[3]);
+
+ drawSelectionOutline(g2d, componentState, outlineMode, project, drawingObserver);
+ }
+
+ public Area[] getBody() {
+ if (body == null) {
+ body = new Area[4];
+
+ double x0 = controlPoints[0].getX();
+ double y0 = controlPoints[0].getY();
+ double x1 = controlPoints[1].getX();
+ double y1 = controlPoints[1].getY();
+ int bodyDiameter = getClosestOdd(BODY_DIAMETER.convertToPixels());
+ int waferDiameter = getClosestOdd(WAFER_DIAMETER.convertToPixels());
+ int springWidth = (int) SPRING_WIDTH.convertToPixels();
+ int holeDiameter = getClosestOdd(HOLE_DIAMETER.convertToPixels());
+ double hexDiameter = HEX_DIAMETER.convertToPixels();
+
+ Area wafer =
+ new Area(new Ellipse2D.Double(x0 - waferDiameter / 2, y0 - waferDiameter / 2, waferDiameter,
+ waferDiameter));
+ wafer.subtract(new Area(new Ellipse2D.Double(x0 - holeDiameter / 2, y0 - holeDiameter / 2, holeDiameter,
+ holeDiameter)));
+
+ body[0] = wafer;
+
+ Area tip = new TwoCircleTangent(controlPoints[0], controlPoints[1], bodyDiameter / 2, springWidth / 2);
+ tip.subtract(new Area(
+ new Ellipse2D.Double(x1 - holeDiameter / 2, y1 - holeDiameter / 2, holeDiameter, holeDiameter)));
+ tip.subtract(new Area(new Ellipse2D.Double(x0 - waferDiameter / 2, y0 - waferDiameter / 2, waferDiameter,
+ waferDiameter)));
+
+ body[1] = tip;
+
+ Area sleeve =
+ new Area(new Ellipse2D.Double(x0 - springWidth / 2, y0 - springWidth / 2,
+ springWidth, springWidth));
+ sleeve.subtract(new Area(new Ellipse2D.Double(x0 - holeDiameter / 2, y0 - holeDiameter / 2, holeDiameter,
+ holeDiameter)));
+
+ body[2] = sleeve;
+
+ Path2D hex = new Path2D.Double();
+ for (int i = 0; i < 6; i++) {
+ double x = x0 + Math.cos(Math.PI / 3 * i) * hexDiameter / 2;
+ double y = y0 + Math.sin(Math.PI / 3 * i) * hexDiameter / 2;
+ if (i == 0)
+ hex.moveTo(x, y);
+ else
+ hex.lineTo(x, y);
+ }
+ hex.closePath();
+ Area hexArea = new Area(hex);
+ hexArea.subtract(new Area(new Ellipse2D.Double(x0 - waferDiameter / 2, y0 - waferDiameter / 2, waferDiameter,
+ waferDiameter)));
+ body[3] = hexArea;
+ }
+
+ return body;
+ }
+
+ @SuppressWarnings("incomplete-switch")
+ private void updateControlPoints() {
+ double x = controlPoints[0].getX();
+ double y = controlPoints[0].getY();
+
+ int springLength = (int) SPRING_LENGTH.convertToPixels();
+ int holeToEdge = (int) HOLE_TO_EDGE.convertToPixels();
+
+ double centerY = y + springLength - holeToEdge;
+
+ controlPoints[1].setLocation(x, centerY);
+
+ // Rotate if needed
+ if (orientation != Orientation.DEFAULT) {
+ double theta = 0;
+ switch (orientation) {
+ case _90:
+ theta = Math.PI / 2;
+ break;
+ case _180:
+ theta = Math.PI;
+ break;
+ case _270:
+ theta = Math.PI * 3 / 2;
+ break;
+ }
+
+ AffineTransform rotation = AffineTransform.getRotateInstance(theta, x, y);
+ rotation.transform(controlPoints[1], controlPoints[1]);
+ }
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ double x0 = width * 0.35;
+ double y0 = height * 0.65;
+ double x1 = width * 0.75;
+ double y1 = height * 0.25;
+ TwoCircleTangent main = new TwoCircleTangent(new Point2D.Double(width * 0.35, height * 0.65), new Point2D.Double(x1, y1), width * 0.3, width * 0.1);
+ main.subtract(new Area(new Ellipse2D.Double(x0 - 1, y0 - 1, 3, 3)));
+ main.subtract(new Area(new Ellipse2D.Double(x1 - 1, y1 - 1, 2, 2)));
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f));
+ g2d.setColor(BASE_COLOR);
+ g2d.fill(main);
+ g2d.setColor(BASE_COLOR.darker());
+ g2d.draw(main);
+
+ double hexDiameter = width * 0.48;
+
+ Path2D hex = new Path2D.Double();
+ for (int i = 0; i < 6; i++) {
+ double x = x0 + Math.cos(Math.PI / 3 * i) * hexDiameter / 2;
+ double y = y0 + Math.sin(Math.PI / 3 * i) * hexDiameter / 2;
+ if (i == 0)
+ hex.moveTo(x, y);
+ else
+ hex.lineTo(x, y);
+ }
+ hex.closePath();
+ g2d.draw(hex);
+
+ double waferDiameter = width * 0.22;
+// g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(2f));
+ g2d.setColor(WAFER_COLOR);
+ g2d.draw(new Ellipse2D.Double(x0 - waferDiameter / 2, y0 - waferDiameter / 2, waferDiameter, waferDiameter));
+ }
+
+ @Override
+ public int getControlPointCount() {
+ return controlPoints.length;
+ }
+
+ @Override
+ public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
+ return VisibilityPolicy.NEVER;
+ }
+
+ @Override
+ public boolean isControlPointSticky(int index) {
+ return true;
+ }
+
+ @Override
+ public Point2D getControlPoint(int index) {
+ return controlPoints[index];
+ }
+
+ @Override
+ public void setControlPoint(Point2D point, int index) {
+ this.controlPoints[index].setLocation(point);
+ // Invalidate the body
+ body = null;
+ }
+
+ @Override
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ @EditableProperty
+ public Orientation getOrientation() {
+ return orientation;
+ }
+
+ public void setOrientation(Orientation orientation) {
+ this.orientation = orientation;
+ updateControlPoints();
+ // Invalidate the body
+ body = null;
+ }
+
+ @Override
+ public String getControlPointNodeName(int index) {
+ return getName() + (index == 0 ? "Tip" : "Sleeve");
+ }
+
+ @Override
+ public boolean canPointMoveFreely(int pointIndex) {
+ return false;
+ }
+
+ @Override
+ public Rectangle2D getCachingBounds() {
+ int margin = 20;
+ Rectangle2D bounds = getBody()[1].getBounds2D();
+ return new Rectangle2D.Double(bounds.getX() - margin, bounds.getY() - margin, bounds.getWidth() + 2 * margin, bounds.getHeight() + 2 * margin);
+ }
+
+ @Deprecated
+ @Override
+ public Integer getFontSizeOverride() {
+ return super.getFontSizeOverride();
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/RotarySelectorSwitch.java b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/RotarySelectorSwitch.java
index b9b75b2e8..1a7481af3 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/RotarySelectorSwitch.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/RotarySelectorSwitch.java
@@ -94,10 +94,7 @@ public class RotarySelectorSwitch extends AbstractMultiPartComponent imp
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
// if (componentState != ComponentState.DRAGGING) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : BODY_COLOR);
g2d.fill(body[0]);
@@ -117,10 +114,7 @@ public class RotarySelectorSwitch extends AbstractMultiPartComponent imp
g2d.setColor(finalBorderColor);
g2d.draw(body[0]);
- oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : TERMINAL_COLOR);
drawingObserver.startTrackingContinuityArea(true);
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/RotarySwitchOpen.java b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/RotarySwitchOpen.java
index 3c4ebc05d..a2f2719bd 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/RotarySwitchOpen.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/RotarySwitchOpen.java
@@ -349,10 +349,8 @@ public class RotarySwitchOpen extends AbstractAngledComponent i
Constants.DEFAULT_THEME);
// Draw body if available.
if (body != null) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(
- AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
if (getShowBracket()) {
g2d.setColor(getBracketColor());
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/TactileMicroSwitch.java b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/TactileMicroSwitch.java
index 1f73d5876..024e92630 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/TactileMicroSwitch.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/TactileMicroSwitch.java
@@ -242,10 +242,7 @@ public class TactileMicroSwitch extends AbstractLabeledComponent impleme
g2d.draw(rect);
}
}
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getBodyColor());
drawingObserver.startTracking();
g2d.fill(mainArea);
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/Freeway3x3_03.java b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/Freeway3x3_03.java
index 65682c528..4625767f5 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/Freeway3x3_03.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/Freeway3x3_03.java
@@ -146,10 +146,7 @@ public class Freeway3x3_03 extends AbstractTransparentComponent implements
List labels = getLabels();
Shape caseShape = getCase();
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
AffineTransform oldTx = new AffineTransform(g2d.getTransform());
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/Freeway3x3_05.java b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/Freeway3x3_05.java
index cf0806694..2f2c83eef 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/Freeway3x3_05.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/Freeway3x3_05.java
@@ -121,10 +121,7 @@ public class Freeway3x3_05 extends AbstractTransparentComponent implements
g2d.rotate(theta, x, y);
}
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
double offsetX = getXOffsetsPx()[0];
double offsetY = getYOffsetsPx()[0];
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/HumbuckerPickup.java b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/HumbuckerPickup.java
index 0549941da..32032eff9 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/HumbuckerPickup.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/HumbuckerPickup.java
@@ -98,10 +98,7 @@ public class HumbuckerPickup extends AbstractGuitarPickup {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : color);
if (getType() != HumbuckerType.Filtertron) {
drawingObserver.startTracking();
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/JazzBassPickup.java b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/JazzBassPickup.java
index b1e8db1df..d0e4298a1 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/JazzBassPickup.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/JazzBassPickup.java
@@ -1,286 +1,283 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.guitar;
-
-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.Area;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.Point2D;
-import java.awt.geom.RoundRectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.Orientation;
-import org.diylc.common.OrientationHV;
-import org.diylc.components.transform.GuitarPickupTransformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-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;
-import org.diylc.utils.Constants;
-
-@ComponentDescriptor(name = "Jazz Bass Pickup", category = "Guitar", author = "Branislav Stojkovic",
- description = "Single coil pickup for Jazz Bass and similar guitars",
- zOrder = IDIYComponent.COMPONENT, instanceNamePrefix = "PKP",
- keywordPolicy = KeywordPolicy.SHOW_TAG, keywordTag = "Guitar Wiring Diagram", enableCache = true,
- transformer = GuitarPickupTransformer.class)
-public class JazzBassPickup extends AbstractSingleOrHumbuckerPickup {
-
- private static final long serialVersionUID = 1L;
-
- private static Color BODY_COLOR = Color.decode("#333333");
-
- private static Size WIDTH = new Size(0.73, SizeUnit.in);
- private static Size LENGTH = new Size(4.1, SizeUnit.in);
- private static Size EDGE_RADIUS = new Size(0.08d, SizeUnit.in);
- private static Size LIP_RADIUS = new Size(0.45d, SizeUnit.in);
- private static Size LIP_SPACING = new Size(1.92d, SizeUnit.in);
- private static Size LIP_HOLE_SIZE = new Size(0.1d, SizeUnit.in);
- private static Size LIP_HOLE_SPACING = new Size(0.1d, SizeUnit.in);
-
- private static Size POINT_MARGIN = new Size(1.5d, SizeUnit.mm);
- private static Size POLE_SIZE = new Size(4d, SizeUnit.mm);
- private static Size POLE_SPACING = new Size(0.85d, SizeUnit.in);
- private static Size POLE_SPACING_MINOR = new Size(0.28d, SizeUnit.in);
-
- private Color color = BODY_COLOR;
- private Color poleColor = METAL_COLOR;
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
-
- Shape[] body = getBody();
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
-
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : color);
- g2d.fill(body[0]);
- g2d.fill(body[1]);
- drawingObserver.stopTracking();
- g2d.setComposite(oldComposite);
-
- markContactPoints(g2d, drawingObserver);
-
- Color finalBorderColor;
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : color.darker();
- }
-
- g2d.setColor(finalBorderColor);
- g2d.draw(body[0]);
- g2d.draw(body[1]);
-
- if (!outlineMode) {
- g2d.setColor(getPoleColor());
- g2d.fill(body[3]);
- g2d.setColor(darkerOrLighter(getPoleColor()));
- g2d.draw(body[3]);
- }
-
-// Color finalLabelColor;
-// if (outlineMode) {
-// Theme theme =
-// (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
-// finalLabelColor =
-// componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
-// : theme.getOutlineColor();
-// } else {
-// finalLabelColor =
-// componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
-// : LABEL_COLOR;
-// }
-// g2d.setColor(finalLabelColor);
-// g2d.setFont(project.getFont());
-// Rectangle bounds = body[0].getBounds();
-// drawCenteredText(g2d, value, bounds.x + bounds.width / 2, bounds.y + bounds.height / 2, HorizontalAlignment.CENTER,
-// VerticalAlignment.CENTER);
- drawMainLabel(g2d, project, outlineMode, componentState);
-
- drawTerminalLabels(g2d, finalBorderColor, project);
- }
-
- @SuppressWarnings("incomplete-switch")
- @Override
- public Shape[] getBody() {
- if (body == null) {
- body = new Shape[4];
-
- Point2D[] points = getControlPoints();
- double x = points[0].getX();
- double y = points[0].getY();
- int width = (int) WIDTH.convertToPixels();
- int length = (int) LENGTH.convertToPixels();
- int edgeRadius = (int) EDGE_RADIUS.convertToPixels();
- int pointMargin = (int) POINT_MARGIN.convertToPixels();
- int lipRadius = (int) LIP_RADIUS.convertToPixels();
- int lipSpacing = (int) LIP_SPACING.convertToPixels();
- int lipHoleSize = getClosestOdd(LIP_HOLE_SIZE.convertToPixels());
- int lipHoleSpacing = getClosestOdd(LIP_HOLE_SPACING.convertToPixels());
-
- body[0] =
- new Area(new RoundRectangle2D.Double(x - length, y - pointMargin, length, width, edgeRadius,
- edgeRadius));
-
- Area lip = new Area(new Ellipse2D.Double(-lipRadius / 2, -lipRadius / 2, lipRadius, lipRadius));
- lip.subtract(new Area(new Ellipse2D.Double(-lipHoleSize / 2, -lipHoleSpacing - lipHoleSize / 2, lipHoleSize, lipHoleSize)));
- lip.transform(AffineTransform.getTranslateInstance(x - length / 2 - lipSpacing / 2, y - pointMargin));
-
- body[1] = new Area(lip);
- lip.transform(AffineTransform.getTranslateInstance(lipSpacing, 0));
- ((Area)body[1]).add(lip);
- lip = new Area(body[1]);
- double y1 = lip.getBounds2D().getY();
- lip.transform(AffineTransform.getScaleInstance(1, -1));
- lip.transform(AffineTransform.getTranslateInstance(0, 2 * y1 + width + lipRadius));
- ((Area)body[1]).add(lip);
-
- ((Area)body[1]).subtract((Area)body[0]);
-
- int poleSize = (int) POLE_SIZE.convertToPixels();
- int poleSpacing = (int) POLE_SPACING.convertToPixels();
- int poleSpacingMinor = (int) POLE_SPACING_MINOR.convertToPixels();
- int poleMargin = (length - poleSpacing * 3) / 2;
- Area poleArea = new Area();
- for (int i = 0; i < 4; i++) {
- Ellipse2D pole =
- new Ellipse2D.Double(x - length + poleMargin + i * poleSpacing - poleSize / 2 - poleSpacingMinor / 2, y
- - pointMargin - poleSize / 2 + width / 2, poleSize, poleSize);
- poleArea.add(new Area(pole));
- pole =
- new Ellipse2D.Double(x - length + poleMargin + i * poleSpacing - poleSize / 2 + poleSpacingMinor / 2, y
- - pointMargin - poleSize / 2 + width / 2, poleSize, poleSize);
- poleArea.add(new Area(pole));
- }
- body[3] = poleArea;
-
- // Rotate if needed
- if (orientation != Orientation.DEFAULT) {
- double theta = 0;
- switch (orientation) {
- case _90:
- theta = Math.PI / 2;
- break;
- case _180:
- theta = Math.PI;
- break;
- case _270:
- theta = Math.PI * 3 / 2;
- break;
- }
- AffineTransform rotation = AffineTransform.getRotateInstance(theta, x, y);
- for (Shape shape : body) {
- Area area = (Area) shape;
- if (shape != null)
- area.transform(rotation);
- }
- }
- }
- return body;
- }
-
- @Override
- protected int getMainLabelYOffset() {
- return (int) (WIDTH.convertToPixels() / 2 - 20);
- }
-
- @Override
- protected OrientationHV getControlPointDirection() {
- return OrientationHV.VERTICAL;
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- g2d.rotate(Math.PI / 4, width / 2, height / 2);
-
- int bodyWidth = (int) (5f * width / 32);
- int bodyLength = (int) (30f * width / 32);
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f));
- g2d.setColor(BODY_COLOR);
- g2d.fillRoundRect((width - bodyWidth) / 2, (height - bodyLength) / 2, bodyWidth, bodyLength, 3, 3);
-
- int lipSpacing = (int) (14f * width / 32);
- int lipSize = (int) (3f * width / 32);
-
- g2d.fillRoundRect((width - bodyWidth) / 2 - lipSize, (height - lipSpacing - lipSize) / 2 , bodyWidth + 2 * lipSize, lipSize, lipSize, lipSize);
- g2d.fillRoundRect((width - bodyWidth) / 2 - lipSize, (height + lipSpacing - lipSize) / 2 , bodyWidth + 2 * lipSize, lipSize, lipSize, lipSize);
-
- g2d.setColor(BODY_COLOR.darker());
- g2d.drawRoundRect((width - bodyWidth) / 2, (height - bodyLength) / 2, bodyWidth, bodyLength, 3, 3);
-
- // g2d.setColor(Color.gray);
- // g2d.drawLine(width / 2, 4 * width / 32, width / 2, 4 * width / 32);
- // g2d.drawLine(width / 2, height - 4 * width / 32, width / 2, height - 4 * width / 32);
-
- g2d.setColor(METAL_COLOR);
- int poleSize = 2;
- int poleSpacing = (int) (15d * width / 32);
- for (int i = 0; i < 4; i++) {
- g2d.fillOval((width - poleSize) / 2, (height - poleSpacing) / 2 + (i * poleSpacing / 3), poleSize, poleSize);
- }
- }
-
- @EditableProperty
- public Color getColor() {
- return color;
- }
-
- public void setColor(Color color) {
- this.color = color;
- }
-
- @EditableProperty(name = "Pole Color")
- public Color getPoleColor() {
- if (poleColor == null)
- poleColor = METAL_COLOR;
- return poleColor;
- }
-
- public void setPoleColor(Color poleColor) {
- this.poleColor = poleColor;
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.guitar;
+
+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.Area;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.RoundRectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.common.IPlugInPort;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.Orientation;
+import org.diylc.common.OrientationHV;
+import org.diylc.components.transform.GuitarPickupTransformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+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;
+import org.diylc.utils.Constants;
+
+@ComponentDescriptor(name = "Jazz Bass Pickup", category = "Guitar", author = "Branislav Stojkovic",
+ description = "Single coil pickup for Jazz Bass and similar guitars",
+ zOrder = IDIYComponent.COMPONENT, instanceNamePrefix = "PKP",
+ keywordPolicy = KeywordPolicy.SHOW_TAG, keywordTag = "Guitar Wiring Diagram", enableCache = true,
+ transformer = GuitarPickupTransformer.class)
+public class JazzBassPickup extends AbstractSingleOrHumbuckerPickup {
+
+ private static final long serialVersionUID = 1L;
+
+ private static Color BODY_COLOR = Color.decode("#333333");
+
+ private static Size WIDTH = new Size(0.73, SizeUnit.in);
+ private static Size LENGTH = new Size(4.1, SizeUnit.in);
+ private static Size EDGE_RADIUS = new Size(0.08d, SizeUnit.in);
+ private static Size LIP_RADIUS = new Size(0.45d, SizeUnit.in);
+ private static Size LIP_SPACING = new Size(1.92d, SizeUnit.in);
+ private static Size LIP_HOLE_SIZE = new Size(0.1d, SizeUnit.in);
+ private static Size LIP_HOLE_SPACING = new Size(0.1d, SizeUnit.in);
+
+ private static Size POINT_MARGIN = new Size(1.5d, SizeUnit.mm);
+ private static Size POLE_SIZE = new Size(4d, SizeUnit.mm);
+ private static Size POLE_SPACING = new Size(0.85d, SizeUnit.in);
+ private static Size POLE_SPACING_MINOR = new Size(0.28d, SizeUnit.in);
+
+ private Color color = BODY_COLOR;
+ private Color poleColor = METAL_COLOR;
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+
+ Shape[] body = getBody();
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : color);
+ g2d.fill(body[0]);
+ g2d.fill(body[1]);
+ drawingObserver.stopTracking();
+ g2d.setComposite(oldComposite);
+
+ markContactPoints(g2d, drawingObserver);
+
+ Color finalBorderColor;
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : color.darker();
+ }
+
+ g2d.setColor(finalBorderColor);
+ g2d.draw(body[0]);
+ g2d.draw(body[1]);
+
+ if (!outlineMode) {
+ g2d.setColor(getPoleColor());
+ g2d.fill(body[3]);
+ g2d.setColor(darkerOrLighter(getPoleColor()));
+ g2d.draw(body[3]);
+ }
+
+// Color finalLabelColor;
+// if (outlineMode) {
+// Theme theme =
+// (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+// finalLabelColor =
+// componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+// : theme.getOutlineColor();
+// } else {
+// finalLabelColor =
+// componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+// : LABEL_COLOR;
+// }
+// g2d.setColor(finalLabelColor);
+// g2d.setFont(project.getFont());
+// Rectangle bounds = body[0].getBounds();
+// drawCenteredText(g2d, value, bounds.x + bounds.width / 2, bounds.y + bounds.height / 2, HorizontalAlignment.CENTER,
+// VerticalAlignment.CENTER);
+ drawMainLabel(g2d, project, outlineMode, componentState);
+
+ drawTerminalLabels(g2d, finalBorderColor, project);
+ }
+
+ @SuppressWarnings("incomplete-switch")
+ @Override
+ public Shape[] getBody() {
+ if (body == null) {
+ body = new Shape[4];
+
+ Point2D[] points = getControlPoints();
+ double x = points[0].getX();
+ double y = points[0].getY();
+ int width = (int) WIDTH.convertToPixels();
+ int length = (int) LENGTH.convertToPixels();
+ int edgeRadius = (int) EDGE_RADIUS.convertToPixels();
+ int pointMargin = (int) POINT_MARGIN.convertToPixels();
+ int lipRadius = (int) LIP_RADIUS.convertToPixels();
+ int lipSpacing = (int) LIP_SPACING.convertToPixels();
+ int lipHoleSize = getClosestOdd(LIP_HOLE_SIZE.convertToPixels());
+ int lipHoleSpacing = getClosestOdd(LIP_HOLE_SPACING.convertToPixels());
+
+ body[0] =
+ new Area(new RoundRectangle2D.Double(x - length, y - pointMargin, length, width, edgeRadius,
+ edgeRadius));
+
+ Area lip = new Area(new Ellipse2D.Double(-lipRadius / 2, -lipRadius / 2, lipRadius, lipRadius));
+ lip.subtract(new Area(new Ellipse2D.Double(-lipHoleSize / 2, -lipHoleSpacing - lipHoleSize / 2, lipHoleSize, lipHoleSize)));
+ lip.transform(AffineTransform.getTranslateInstance(x - length / 2 - lipSpacing / 2, y - pointMargin));
+
+ body[1] = new Area(lip);
+ lip.transform(AffineTransform.getTranslateInstance(lipSpacing, 0));
+ ((Area)body[1]).add(lip);
+ lip = new Area(body[1]);
+ double y1 = lip.getBounds2D().getY();
+ lip.transform(AffineTransform.getScaleInstance(1, -1));
+ lip.transform(AffineTransform.getTranslateInstance(0, 2 * y1 + width + lipRadius));
+ ((Area)body[1]).add(lip);
+
+ ((Area)body[1]).subtract((Area)body[0]);
+
+ int poleSize = (int) POLE_SIZE.convertToPixels();
+ int poleSpacing = (int) POLE_SPACING.convertToPixels();
+ int poleSpacingMinor = (int) POLE_SPACING_MINOR.convertToPixels();
+ int poleMargin = (length - poleSpacing * 3) / 2;
+ Area poleArea = new Area();
+ for (int i = 0; i < 4; i++) {
+ Ellipse2D pole =
+ new Ellipse2D.Double(x - length + poleMargin + i * poleSpacing - poleSize / 2 - poleSpacingMinor / 2, y
+ - pointMargin - poleSize / 2 + width / 2, poleSize, poleSize);
+ poleArea.add(new Area(pole));
+ pole =
+ new Ellipse2D.Double(x - length + poleMargin + i * poleSpacing - poleSize / 2 + poleSpacingMinor / 2, y
+ - pointMargin - poleSize / 2 + width / 2, poleSize, poleSize);
+ poleArea.add(new Area(pole));
+ }
+ body[3] = poleArea;
+
+ // Rotate if needed
+ if (orientation != Orientation.DEFAULT) {
+ double theta = 0;
+ switch (orientation) {
+ case _90:
+ theta = Math.PI / 2;
+ break;
+ case _180:
+ theta = Math.PI;
+ break;
+ case _270:
+ theta = Math.PI * 3 / 2;
+ break;
+ }
+ AffineTransform rotation = AffineTransform.getRotateInstance(theta, x, y);
+ for (Shape shape : body) {
+ Area area = (Area) shape;
+ if (shape != null)
+ area.transform(rotation);
+ }
+ }
+ }
+ return body;
+ }
+
+ @Override
+ protected int getMainLabelYOffset() {
+ return (int) (WIDTH.convertToPixels() / 2 - 20);
+ }
+
+ @Override
+ protected OrientationHV getControlPointDirection() {
+ return OrientationHV.VERTICAL;
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ g2d.rotate(Math.PI / 4, width / 2, height / 2);
+
+ int bodyWidth = (int) (5f * width / 32);
+ int bodyLength = (int) (30f * width / 32);
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f));
+ g2d.setColor(BODY_COLOR);
+ g2d.fillRoundRect((width - bodyWidth) / 2, (height - bodyLength) / 2, bodyWidth, bodyLength, 3, 3);
+
+ int lipSpacing = (int) (14f * width / 32);
+ int lipSize = (int) (3f * width / 32);
+
+ g2d.fillRoundRect((width - bodyWidth) / 2 - lipSize, (height - lipSpacing - lipSize) / 2 , bodyWidth + 2 * lipSize, lipSize, lipSize, lipSize);
+ g2d.fillRoundRect((width - bodyWidth) / 2 - lipSize, (height + lipSpacing - lipSize) / 2 , bodyWidth + 2 * lipSize, lipSize, lipSize, lipSize);
+
+ g2d.setColor(BODY_COLOR.darker());
+ g2d.drawRoundRect((width - bodyWidth) / 2, (height - bodyLength) / 2, bodyWidth, bodyLength, 3, 3);
+
+ // g2d.setColor(Color.gray);
+ // g2d.drawLine(width / 2, 4 * width / 32, width / 2, 4 * width / 32);
+ // g2d.drawLine(width / 2, height - 4 * width / 32, width / 2, height - 4 * width / 32);
+
+ g2d.setColor(METAL_COLOR);
+ int poleSize = 2;
+ int poleSpacing = (int) (15d * width / 32);
+ for (int i = 0; i < 4; i++) {
+ g2d.fillOval((width - poleSize) / 2, (height - poleSpacing) / 2 + (i * poleSpacing / 3), poleSize, poleSize);
+ }
+ }
+
+ @EditableProperty
+ public Color getColor() {
+ return color;
+ }
+
+ public void setColor(Color color) {
+ this.color = color;
+ }
+
+ @EditableProperty(name = "Pole Color")
+ public Color getPoleColor() {
+ if (poleColor == null)
+ poleColor = METAL_COLOR;
+ return poleColor;
+ }
+
+ public void setPoleColor(Color poleColor) {
+ this.poleColor = poleColor;
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/LPSwitch.java b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/LPSwitch.java
index 0c0f3a203..e2ae2e5bd 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/LPSwitch.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/LPSwitch.java
@@ -1,442 +1,439 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.guitar;
-
-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.Area;
-import java.awt.geom.GeneralPath;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.Orientation;
-import org.diylc.components.AbstractTransparentComponent;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.ISwitch;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-import org.diylc.core.VisibilityPolicy;
-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.Constants;
-
-@ComponentDescriptor(name = "LP Toggle Switch", category = "Guitar", author = "Branislav Stojkovic",
- description = "Les Paul style 3 position toggle switch", zOrder = IDIYComponent.COMPONENT,
- instanceNamePrefix = "SW")
-public class LPSwitch extends AbstractTransparentComponent implements ISwitch {
-
- private static final long serialVersionUID = 1L;
-
- private static Color BASE_COLOR = Color.lightGray;
- private static Color WAFER_COLOR = PHENOLIC_DARK_COLOR;
-
- private static Size LENGTH = new Size(1.3d, SizeUnit.in);
- private static Size BASE_LENGTH = new Size(18d, SizeUnit.mm);
- private static Size WAFER_THICKNESS = new Size(0.05d, SizeUnit.in);
- private static Size TERMINAL_SPACING_CONNECTED = new Size(0.2d, SizeUnit.in);
- private static Size TERMINAL_SPACING_DISCONNECTED = new Size(0.1d, SizeUnit.in);
-
- private String value = "";
- private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0), new Point2D.Double(0, 0), new Point2D.Double(0, 0), new Point2D.Double(0, 0)};
- transient Shape[] body;
- private Orientation orientation = Orientation.DEFAULT;
- private MiddleTerminalConfiguration middleTerminalConfiguration;
-
- public LPSwitch() {
- super();
- middleTerminalConfiguration = MiddleTerminalConfiguration.Connected;
- updateControlPoints();
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- Shape[] body = getBody();
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
- if (componentState != ComponentState.DRAGGING) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : WAFER_COLOR);
- g2d.fill(body[1]);
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : BASE_COLOR);
- g2d.fill(body[0]);
- g2d.setComposite(oldComposite);
- }
-
- drawingObserver.stopTracking();
-
- Color finalBorderColor;
-
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : WAFER_COLOR.darker();
- }
-
- g2d.setColor(finalBorderColor);
- g2d.draw(body[0]);
-
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : BASE_COLOR.darker();
- }
-
- g2d.setColor(finalBorderColor);
- g2d.draw(body[1]);
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(3));
- g2d.setColor(METAL_COLOR);
- drawingObserver.startTracking();
- g2d.draw(body[2]);
- drawingObserver.stopTracking();
- }
-
- @SuppressWarnings("incomplete-switch")
- public Shape[] getBody() {
- if (body == null) {
- body = new Shape[3];
-
- double x = controlPoints[0].getX();
- double y = controlPoints[0].getY();
- int baseLength = (int) BASE_LENGTH.convertToPixels();
- int length = (int) LENGTH.convertToPixels();
- int waferThickness = getClosestOdd(WAFER_THICKNESS.convertToPixels());
-
- Rectangle2D ground =
- new Rectangle2D.Double(x - waferThickness / 2, y, waferThickness - 1, baseLength + (length - baseLength) / 2);
- body[0] = new Area(ground);
-
- double bodyY = y + (length - baseLength) / 2;
-
- Area waferArea = new Area();//new Area(new Rectangle2D.Double(x - waferThickness * 3 / 2, bodyY, waferThickness, baseLength));
- waferArea.add(new Area(new Rectangle2D.Double(x + waferThickness / 2, bodyY, waferThickness *3, baseLength)));
-
- waferArea.add(new Area(new Rectangle2D.Double(x - waferThickness * 5 / 2, bodyY, waferThickness, baseLength)));
- waferArea.add(new Area(new Rectangle2D.Double(x + waferThickness * 3 / 2, bodyY, waferThickness, baseLength)));
-
- waferArea.add(new Area(new Rectangle2D.Double(x - waferThickness * 7 / 2, bodyY, waferThickness * 3, baseLength)));
-// waferArea.add(new Area(new Rectangle2D.Double(x + waferThickness * 5 / 2, bodyY, waferThickness, baseLength)));
-
- body[1] = waferArea;
-
- double theta = 0;
- // Rotate if needed
- if (orientation != Orientation.DEFAULT) {
- switch (orientation) {
- case _90:
- theta = Math.PI / 2;
- break;
- case _180:
- theta = Math.PI;
- break;
- case _270:
- theta = Math.PI * 3 / 2;
- break;
- }
- }
-
-
- GeneralPath terminalPath = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
-
- if (getMiddleTerminalConfiguration() == MiddleTerminalConfiguration.Connected) {
- int terminalSpacing = (int) TERMINAL_SPACING_CONNECTED.convertToPixels();
- terminalPath.moveTo(x - waferThickness * 3 / 2, bodyY + 1);
- terminalPath.lineTo(x - waferThickness * 3 / 2, bodyY + baseLength);
- terminalPath.lineTo(x, y + length);
-
- terminalPath.moveTo(x + waferThickness * 3 / 2, bodyY + 1);
- terminalPath.lineTo(x + waferThickness * 3 / 2, bodyY + baseLength);
- terminalPath.lineTo(x, y + length);
-
- terminalPath.moveTo(x - waferThickness * 5 / 2, bodyY + 1);
- terminalPath.lineTo(x - waferThickness * 5 / 2, bodyY + baseLength);
- terminalPath.lineTo(x - terminalSpacing, y + length);
-
- terminalPath.moveTo(x + waferThickness * 5 / 2, bodyY + 1);
- terminalPath.lineTo(x + waferThickness * 5 / 2, bodyY + baseLength);
- terminalPath.lineTo(x + terminalSpacing, y + length);
- } else {
- int terminalSpacing = (int) TERMINAL_SPACING_DISCONNECTED.convertToPixels();
- terminalPath.moveTo(x - waferThickness * 3 / 2, bodyY + 1);
- terminalPath.lineTo(x - waferThickness * 3 / 2, bodyY + baseLength);
- terminalPath.lineTo(x- terminalSpacing, y + length);
-
- terminalPath.moveTo(x + waferThickness * 3 / 2, bodyY + 1);
- terminalPath.lineTo(x + waferThickness * 3 / 2, bodyY + baseLength);
- terminalPath.lineTo(x + terminalSpacing, y + length);
-
- terminalPath.moveTo(x - waferThickness * 5 / 2, bodyY + 1);
- terminalPath.lineTo(x - waferThickness * 5 / 2, bodyY + baseLength);
- terminalPath.lineTo(x - terminalSpacing * 2, y + length);
-
- terminalPath.moveTo(x + waferThickness * 5 / 2, bodyY + 1);
- terminalPath.lineTo(x + waferThickness * 5 / 2, bodyY + baseLength);
- terminalPath.lineTo(x + terminalSpacing * 2, y + length);
- }
- body[2] = terminalPath;
-
- // Rotate if needed
- if (theta != 0) {
- AffineTransform rotation = AffineTransform.getRotateInstance(theta, x, y);
- // Skip the last one because it's already rotated
- for (int i = 0; i < body.length; i++) {
- Shape shape = body[i];
- if (shape instanceof Area) {
- Area area = (Area) shape;
- area.transform(rotation);
- } else if (shape instanceof GeneralPath) {
- GeneralPath path = (GeneralPath) shape;
- path.transform(rotation);
- }
- }
- }
- }
- return body;
- }
-
- @SuppressWarnings("incomplete-switch")
- private void updateControlPoints() {
-
- Point2D[] newControlPoints = null;
- if (getMiddleTerminalConfiguration() == MiddleTerminalConfiguration.Connected && controlPoints.length == 5) {
- newControlPoints = new Point2D[4];
- } else if (getMiddleTerminalConfiguration() == MiddleTerminalConfiguration.Disconnected && controlPoints.length == 4) {
- newControlPoints = new Point2D[5];
- newControlPoints[4] = new Point2D.Double();
- }
- if (newControlPoints != null) {
- for (int i = 0; i < newControlPoints.length && i < controlPoints.length; i++) {
- newControlPoints[i] = controlPoints[i];
- }
- controlPoints = newControlPoints;
- }
-
- double x = controlPoints[0].getX();
- double y = controlPoints[0].getY();
- int length = (int) LENGTH.convertToPixels();
-
- if (getMiddleTerminalConfiguration() == MiddleTerminalConfiguration.Connected) {
- int terminalSpacing = (int) TERMINAL_SPACING_CONNECTED.convertToPixels();
- controlPoints[1].setLocation(x - terminalSpacing, y + length);
- controlPoints[2].setLocation(x, y + length);
- controlPoints[3].setLocation(x + terminalSpacing, y + length);
- } else {
- int terminalSpacing = (int) TERMINAL_SPACING_DISCONNECTED.convertToPixels();
- controlPoints[1].setLocation(x - terminalSpacing * 2, y + length);
- controlPoints[2].setLocation(x - terminalSpacing, y + length);
- controlPoints[3].setLocation(x + terminalSpacing, y + length);
- controlPoints[4].setLocation(x + terminalSpacing * 2, y + length);
- }
-
- // Rotate if needed
- if (orientation != Orientation.DEFAULT) {
- double theta = 0;
- switch (orientation) {
- case _90:
- theta = Math.PI / 2;
- break;
- case _180:
- theta = Math.PI;
- break;
- case _270:
- theta = Math.PI * 3 / 2;
- break;
- }
- AffineTransform rotation = AffineTransform.getRotateInstance(theta, x, y);
- for (Point2D point : controlPoints) {
- rotation.transform(point, point);
- }
- }
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- g2d.rotate(Math.PI / 4, width / 2, height / 2);
- int baseLength = 20 * width / 32;
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(3f));
- g2d.setColor(BASE_COLOR);
- g2d.drawLine(width / 2, 0, width / 2, baseLength + (width - baseLength) / 2);
- g2d.setColor(WAFER_COLOR);
- g2d.fillRect(8 * width / 32, (width - baseLength) / 2, 16 * width / 32, baseLength);
- g2d.setColor(METAL_COLOR);
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f));
- g2d.drawLine(width / 2 - 2, (width - baseLength) / 2, width / 2 - 2, baseLength + (width - baseLength) / 2);
- g2d.drawLine(width / 2 + 2, (width - baseLength) / 2, width / 2 + 2, baseLength + (width - baseLength) / 2);
- g2d.drawLine(width / 2 - 5, (width - baseLength) / 2, width / 2 - 5, baseLength + (width - baseLength) / 2);
- g2d.drawLine(width / 2 + 5, (width - baseLength) / 2, width / 2 + 5, baseLength + (width - baseLength) / 2);
- int dx = 2 * width / 32;
- int dy = 4 * width / 32;
- g2d.drawLine(width / 2 - 2, baseLength + (width - baseLength) / 2, width / 2 - 2 + dx, baseLength
- + (width - baseLength) / 2 + dy);
- g2d.drawLine(width / 2 + 2, baseLength + (width - baseLength) / 2, width / 2 + 2 - dx, baseLength
- + (width - baseLength) / 2 + dy);
-
- g2d.drawLine(width / 2 - 5, baseLength + (width - baseLength) / 2, width / 2 - 5 - dx, baseLength
- + (width - baseLength) / 2 + dy);
- g2d.drawLine(width / 2 + 5, baseLength + (width - baseLength) / 2, width / 2 + 5 + dx, baseLength
- + (width - baseLength) / 2 + dy);
- }
-
- @Override
- public int getControlPointCount() {
- return controlPoints.length;
- }
-
- @Override
- public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
- return VisibilityPolicy.ALWAYS;
- }
-
- @Override
- public boolean isControlPointSticky(int index) {
- return true;
- }
-
- @Override
- public Point2D getControlPoint(int index) {
- return controlPoints[index];
- }
-
- @Override
- public void setControlPoint(Point2D point, int index) {
- this.controlPoints[index].setLocation(point);
- // Invalidate the body
- body = null;
- }
-
- @Override
- public boolean canPointMoveFreely(int pointIndex) {
- return false;
- }
-
- @Override
- public String getValue() {
- return value;
- }
-
- @Override
- public void setValue(String value) {
- this.value = value;
- }
-
- @EditableProperty
- public Orientation getOrientation() {
- return orientation;
- }
-
- public void setOrientation(Orientation orientation) {
- this.orientation = orientation;
- updateControlPoints();
- // Invalidate the body
- body = null;
- }
-
- @EditableProperty(name = "Middle Terminals")
- public MiddleTerminalConfiguration getMiddleTerminalConfiguration() {
- if (middleTerminalConfiguration == null) {
- middleTerminalConfiguration = MiddleTerminalConfiguration.Connected;
- }
- return middleTerminalConfiguration;
- }
-
- public void setMiddleTerminalConfiguration(
- MiddleTerminalConfiguration middleTerminalConfiguration) {
- this.middleTerminalConfiguration = middleTerminalConfiguration;
- updateControlPoints();
- // Invalidate the body
- body = null;
- }
-
- // @Override
-// public String getControlPointNodeName(int index) {
-// // we don't want the switch to produce any nodes, it just makes connections
-// return null;
-// }
-//
- // switch stuff
-
- @Override
- public int getPositionCount() {
- return 3;
- }
-
- @Override
- public String getPositionName(int position) {
- return switch (position) {
- case 0 -> "Treble";
- case 1 -> "Middle";
- case 2 -> "Rhythm";
- default -> null;
- };
- }
-
- @Override
- public boolean arePointsConnected(int index1, int index2, int position) {
- if (getMiddleTerminalConfiguration() == MiddleTerminalConfiguration.Connected) {
- return switch (position) {
- case 0 -> index1 == 1 && index2 == 2;
- case 1 -> index1 > 0 && index2 > 0 && index1 < index2;
- case 2 -> index1 == 2 && index2 == 3;
- default -> false;
- };
- } else {
- return switch (position) {
- case 0 -> index1 == 1 && index2 == 2;
- case 1 -> (index1 == 1 && index2 == 2) || (index1 == 3 && index2 == 4);
- case 2 -> index1 == 3 && index2 == 4;
- default -> false;
- };
- }
- }
-
- public enum MiddleTerminalConfiguration {
- Connected, Disconnected
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.guitar;
+
+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.Area;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.common.IPlugInPort;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.Orientation;
+import org.diylc.components.AbstractTransparentComponent;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.ISwitch;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+import org.diylc.core.VisibilityPolicy;
+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.Constants;
+
+@ComponentDescriptor(name = "LP Toggle Switch", category = "Guitar", author = "Branislav Stojkovic",
+ description = "Les Paul style 3 position toggle switch", zOrder = IDIYComponent.COMPONENT,
+ instanceNamePrefix = "SW")
+public class LPSwitch extends AbstractTransparentComponent implements ISwitch {
+
+ private static final long serialVersionUID = 1L;
+
+ private static Color BASE_COLOR = Color.lightGray;
+ private static Color WAFER_COLOR = PHENOLIC_DARK_COLOR;
+
+ private static Size LENGTH = new Size(1.3d, SizeUnit.in);
+ private static Size BASE_LENGTH = new Size(18d, SizeUnit.mm);
+ private static Size WAFER_THICKNESS = new Size(0.05d, SizeUnit.in);
+ private static Size TERMINAL_SPACING_CONNECTED = new Size(0.2d, SizeUnit.in);
+ private static Size TERMINAL_SPACING_DISCONNECTED = new Size(0.1d, SizeUnit.in);
+
+ private String value = "";
+ private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0), new Point2D.Double(0, 0), new Point2D.Double(0, 0), new Point2D.Double(0, 0)};
+ transient Shape[] body;
+ private Orientation orientation = Orientation.DEFAULT;
+ private MiddleTerminalConfiguration middleTerminalConfiguration;
+
+ public LPSwitch() {
+ super();
+ middleTerminalConfiguration = MiddleTerminalConfiguration.Connected;
+ updateControlPoints();
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ Shape[] body = getBody();
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+ if (componentState != ComponentState.DRAGGING) {
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : WAFER_COLOR);
+ g2d.fill(body[1]);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : BASE_COLOR);
+ g2d.fill(body[0]);
+ g2d.setComposite(oldComposite);
+ }
+
+ drawingObserver.stopTracking();
+
+ Color finalBorderColor;
+
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : WAFER_COLOR.darker();
+ }
+
+ g2d.setColor(finalBorderColor);
+ g2d.draw(body[0]);
+
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : BASE_COLOR.darker();
+ }
+
+ g2d.setColor(finalBorderColor);
+ g2d.draw(body[1]);
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(3));
+ g2d.setColor(METAL_COLOR);
+ drawingObserver.startTracking();
+ g2d.draw(body[2]);
+ drawingObserver.stopTracking();
+ }
+
+ @SuppressWarnings("incomplete-switch")
+ public Shape[] getBody() {
+ if (body == null) {
+ body = new Shape[3];
+
+ double x = controlPoints[0].getX();
+ double y = controlPoints[0].getY();
+ int baseLength = (int) BASE_LENGTH.convertToPixels();
+ int length = (int) LENGTH.convertToPixels();
+ int waferThickness = getClosestOdd(WAFER_THICKNESS.convertToPixels());
+
+ Rectangle2D ground =
+ new Rectangle2D.Double(x - waferThickness / 2, y, waferThickness - 1, baseLength + (length - baseLength) / 2);
+ body[0] = new Area(ground);
+
+ double bodyY = y + (length - baseLength) / 2;
+
+ Area waferArea = new Area();//new Area(new Rectangle2D.Double(x - waferThickness * 3 / 2, bodyY, waferThickness, baseLength));
+ waferArea.add(new Area(new Rectangle2D.Double(x + waferThickness / 2, bodyY, waferThickness *3, baseLength)));
+
+ waferArea.add(new Area(new Rectangle2D.Double(x - waferThickness * 5 / 2, bodyY, waferThickness, baseLength)));
+ waferArea.add(new Area(new Rectangle2D.Double(x + waferThickness * 3 / 2, bodyY, waferThickness, baseLength)));
+
+ waferArea.add(new Area(new Rectangle2D.Double(x - waferThickness * 7 / 2, bodyY, waferThickness * 3, baseLength)));
+// waferArea.add(new Area(new Rectangle2D.Double(x + waferThickness * 5 / 2, bodyY, waferThickness, baseLength)));
+
+ body[1] = waferArea;
+
+ double theta = 0;
+ // Rotate if needed
+ if (orientation != Orientation.DEFAULT) {
+ switch (orientation) {
+ case _90:
+ theta = Math.PI / 2;
+ break;
+ case _180:
+ theta = Math.PI;
+ break;
+ case _270:
+ theta = Math.PI * 3 / 2;
+ break;
+ }
+ }
+
+
+ GeneralPath terminalPath = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
+
+ if (getMiddleTerminalConfiguration() == MiddleTerminalConfiguration.Connected) {
+ int terminalSpacing = (int) TERMINAL_SPACING_CONNECTED.convertToPixels();
+ terminalPath.moveTo(x - waferThickness * 3 / 2, bodyY + 1);
+ terminalPath.lineTo(x - waferThickness * 3 / 2, bodyY + baseLength);
+ terminalPath.lineTo(x, y + length);
+
+ terminalPath.moveTo(x + waferThickness * 3 / 2, bodyY + 1);
+ terminalPath.lineTo(x + waferThickness * 3 / 2, bodyY + baseLength);
+ terminalPath.lineTo(x, y + length);
+
+ terminalPath.moveTo(x - waferThickness * 5 / 2, bodyY + 1);
+ terminalPath.lineTo(x - waferThickness * 5 / 2, bodyY + baseLength);
+ terminalPath.lineTo(x - terminalSpacing, y + length);
+
+ terminalPath.moveTo(x + waferThickness * 5 / 2, bodyY + 1);
+ terminalPath.lineTo(x + waferThickness * 5 / 2, bodyY + baseLength);
+ terminalPath.lineTo(x + terminalSpacing, y + length);
+ } else {
+ int terminalSpacing = (int) TERMINAL_SPACING_DISCONNECTED.convertToPixels();
+ terminalPath.moveTo(x - waferThickness * 3 / 2, bodyY + 1);
+ terminalPath.lineTo(x - waferThickness * 3 / 2, bodyY + baseLength);
+ terminalPath.lineTo(x- terminalSpacing, y + length);
+
+ terminalPath.moveTo(x + waferThickness * 3 / 2, bodyY + 1);
+ terminalPath.lineTo(x + waferThickness * 3 / 2, bodyY + baseLength);
+ terminalPath.lineTo(x + terminalSpacing, y + length);
+
+ terminalPath.moveTo(x - waferThickness * 5 / 2, bodyY + 1);
+ terminalPath.lineTo(x - waferThickness * 5 / 2, bodyY + baseLength);
+ terminalPath.lineTo(x - terminalSpacing * 2, y + length);
+
+ terminalPath.moveTo(x + waferThickness * 5 / 2, bodyY + 1);
+ terminalPath.lineTo(x + waferThickness * 5 / 2, bodyY + baseLength);
+ terminalPath.lineTo(x + terminalSpacing * 2, y + length);
+ }
+ body[2] = terminalPath;
+
+ // Rotate if needed
+ if (theta != 0) {
+ AffineTransform rotation = AffineTransform.getRotateInstance(theta, x, y);
+ // Skip the last one because it's already rotated
+ for (int i = 0; i < body.length; i++) {
+ Shape shape = body[i];
+ if (shape instanceof Area) {
+ Area area = (Area) shape;
+ area.transform(rotation);
+ } else if (shape instanceof GeneralPath) {
+ GeneralPath path = (GeneralPath) shape;
+ path.transform(rotation);
+ }
+ }
+ }
+ }
+ return body;
+ }
+
+ @SuppressWarnings("incomplete-switch")
+ private void updateControlPoints() {
+
+ Point2D[] newControlPoints = null;
+ if (getMiddleTerminalConfiguration() == MiddleTerminalConfiguration.Connected && controlPoints.length == 5) {
+ newControlPoints = new Point2D[4];
+ } else if (getMiddleTerminalConfiguration() == MiddleTerminalConfiguration.Disconnected && controlPoints.length == 4) {
+ newControlPoints = new Point2D[5];
+ newControlPoints[4] = new Point2D.Double();
+ }
+ if (newControlPoints != null) {
+ for (int i = 0; i < newControlPoints.length && i < controlPoints.length; i++) {
+ newControlPoints[i] = controlPoints[i];
+ }
+ controlPoints = newControlPoints;
+ }
+
+ double x = controlPoints[0].getX();
+ double y = controlPoints[0].getY();
+ int length = (int) LENGTH.convertToPixels();
+
+ if (getMiddleTerminalConfiguration() == MiddleTerminalConfiguration.Connected) {
+ int terminalSpacing = (int) TERMINAL_SPACING_CONNECTED.convertToPixels();
+ controlPoints[1].setLocation(x - terminalSpacing, y + length);
+ controlPoints[2].setLocation(x, y + length);
+ controlPoints[3].setLocation(x + terminalSpacing, y + length);
+ } else {
+ int terminalSpacing = (int) TERMINAL_SPACING_DISCONNECTED.convertToPixels();
+ controlPoints[1].setLocation(x - terminalSpacing * 2, y + length);
+ controlPoints[2].setLocation(x - terminalSpacing, y + length);
+ controlPoints[3].setLocation(x + terminalSpacing, y + length);
+ controlPoints[4].setLocation(x + terminalSpacing * 2, y + length);
+ }
+
+ // Rotate if needed
+ if (orientation != Orientation.DEFAULT) {
+ double theta = 0;
+ switch (orientation) {
+ case _90:
+ theta = Math.PI / 2;
+ break;
+ case _180:
+ theta = Math.PI;
+ break;
+ case _270:
+ theta = Math.PI * 3 / 2;
+ break;
+ }
+ AffineTransform rotation = AffineTransform.getRotateInstance(theta, x, y);
+ for (Point2D point : controlPoints) {
+ rotation.transform(point, point);
+ }
+ }
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ g2d.rotate(Math.PI / 4, width / 2, height / 2);
+ int baseLength = 20 * width / 32;
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(3f));
+ g2d.setColor(BASE_COLOR);
+ g2d.drawLine(width / 2, 0, width / 2, baseLength + (width - baseLength) / 2);
+ g2d.setColor(WAFER_COLOR);
+ g2d.fillRect(8 * width / 32, (width - baseLength) / 2, 16 * width / 32, baseLength);
+ g2d.setColor(METAL_COLOR);
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f));
+ g2d.drawLine(width / 2 - 2, (width - baseLength) / 2, width / 2 - 2, baseLength + (width - baseLength) / 2);
+ g2d.drawLine(width / 2 + 2, (width - baseLength) / 2, width / 2 + 2, baseLength + (width - baseLength) / 2);
+ g2d.drawLine(width / 2 - 5, (width - baseLength) / 2, width / 2 - 5, baseLength + (width - baseLength) / 2);
+ g2d.drawLine(width / 2 + 5, (width - baseLength) / 2, width / 2 + 5, baseLength + (width - baseLength) / 2);
+ int dx = 2 * width / 32;
+ int dy = 4 * width / 32;
+ g2d.drawLine(width / 2 - 2, baseLength + (width - baseLength) / 2, width / 2 - 2 + dx, baseLength
+ + (width - baseLength) / 2 + dy);
+ g2d.drawLine(width / 2 + 2, baseLength + (width - baseLength) / 2, width / 2 + 2 - dx, baseLength
+ + (width - baseLength) / 2 + dy);
+
+ g2d.drawLine(width / 2 - 5, baseLength + (width - baseLength) / 2, width / 2 - 5 - dx, baseLength
+ + (width - baseLength) / 2 + dy);
+ g2d.drawLine(width / 2 + 5, baseLength + (width - baseLength) / 2, width / 2 + 5 + dx, baseLength
+ + (width - baseLength) / 2 + dy);
+ }
+
+ @Override
+ public int getControlPointCount() {
+ return controlPoints.length;
+ }
+
+ @Override
+ public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
+ return VisibilityPolicy.ALWAYS;
+ }
+
+ @Override
+ public boolean isControlPointSticky(int index) {
+ return true;
+ }
+
+ @Override
+ public Point2D getControlPoint(int index) {
+ return controlPoints[index];
+ }
+
+ @Override
+ public void setControlPoint(Point2D point, int index) {
+ this.controlPoints[index].setLocation(point);
+ // Invalidate the body
+ body = null;
+ }
+
+ @Override
+ public boolean canPointMoveFreely(int pointIndex) {
+ return false;
+ }
+
+ @Override
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ @EditableProperty
+ public Orientation getOrientation() {
+ return orientation;
+ }
+
+ public void setOrientation(Orientation orientation) {
+ this.orientation = orientation;
+ updateControlPoints();
+ // Invalidate the body
+ body = null;
+ }
+
+ @EditableProperty(name = "Middle Terminals")
+ public MiddleTerminalConfiguration getMiddleTerminalConfiguration() {
+ if (middleTerminalConfiguration == null) {
+ middleTerminalConfiguration = MiddleTerminalConfiguration.Connected;
+ }
+ return middleTerminalConfiguration;
+ }
+
+ public void setMiddleTerminalConfiguration(
+ MiddleTerminalConfiguration middleTerminalConfiguration) {
+ this.middleTerminalConfiguration = middleTerminalConfiguration;
+ updateControlPoints();
+ // Invalidate the body
+ body = null;
+ }
+
+ // @Override
+// public String getControlPointNodeName(int index) {
+// // we don't want the switch to produce any nodes, it just makes connections
+// return null;
+// }
+//
+ // switch stuff
+
+ @Override
+ public int getPositionCount() {
+ return 3;
+ }
+
+ @Override
+ public String getPositionName(int position) {
+ return switch (position) {
+ case 0 -> "Treble";
+ case 1 -> "Middle";
+ case 2 -> "Rhythm";
+ default -> null;
+ };
+ }
+
+ @Override
+ public boolean arePointsConnected(int index1, int index2, int position) {
+ if (getMiddleTerminalConfiguration() == MiddleTerminalConfiguration.Connected) {
+ return switch (position) {
+ case 0 -> index1 == 1 && index2 == 2;
+ case 1 -> index1 > 0 && index2 > 0 && index1 < index2;
+ case 2 -> index1 == 2 && index2 == 3;
+ default -> false;
+ };
+ } else {
+ return switch (position) {
+ case 0 -> index1 == 1 && index2 == 2;
+ case 1 -> (index1 == 1 && index2 == 2) || (index1 == 3 && index2 == 4);
+ case 2 -> index1 == 3 && index2 == 4;
+ default -> false;
+ };
+ }
+ }
+
+ public enum MiddleTerminalConfiguration {
+ Connected, Disconnected
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/LeverSwitch.java b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/LeverSwitch.java
index cf9fb958b..d1d59df68 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/LeverSwitch.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/LeverSwitch.java
@@ -100,10 +100,7 @@ public class LeverSwitch extends AbstractAngledComponent.
-
-*/
-package org.diylc.components.guitar;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-import java.awt.Polygon;
-import java.awt.Rectangle;
-import java.awt.Shape;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Area;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.Point2D;
-import java.awt.geom.RoundRectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.Orientation;
-import org.diylc.common.OrientationHV;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-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;
-import org.diylc.utils.Constants;
-
-@ComponentDescriptor(name = "P-90 Single Coil Pickup", category = "Guitar", author = "Branislav Stojkovic",
- description = "Single coil P-90 guitar pickup, both \"dog ear\" and \"soap bar\"",
- zOrder = IDIYComponent.COMPONENT, instanceNamePrefix = "PKP",
- keywordPolicy = KeywordPolicy.SHOW_TAG, keywordTag = "Guitar Wiring Diagram", enableCache = true)
-public class P90Pickup extends AbstractSingleOrHumbuckerPickup {
-
- private static final long serialVersionUID = 1L;
-
- private static Color BODY_COLOR = Color.decode("#D8C989");;
-// private static Color POINT_COLOR = Color.darkGray;
-
- // dog ear
- private static Size DOG_EAR_WIDTH = new Size(41d, SizeUnit.mm);
- private static Size DOG_EAR_LENGTH = new Size(86.9d, SizeUnit.mm);
- private static Size TOTAL_LENGTH = new Size(118.7d, SizeUnit.mm);
- private static Size DOG_EAR_EDGE_RADIUS = new Size(4d, SizeUnit.mm);
-
- // soap bar
- private static Size SOAP_BAR_WIDTH = new Size(35.3d, SizeUnit.mm);
- private static Size SOAP_BAR_LENGTH = new Size(85.6d, SizeUnit.mm);
- private static Size SOAP_BAR_EDGE_RADIUS = new Size(8d, SizeUnit.mm);
-
- private static Size LIP_RADIUS = new Size(10d, SizeUnit.mm);
- private static Size POINT_MARGIN = new Size(3.5d, SizeUnit.mm);
- private static Size LIP_HOLE_SIZE = new Size(2.5d, SizeUnit.mm);
- private static Size LIP_HOLE_SPACING = new Size(97d, SizeUnit.mm);
- private static Size POLE_SIZE = new Size(4d, SizeUnit.mm);
- private static Size POLE_SPACING = new Size(11.68d, SizeUnit.mm);
-
- private Color color = BODY_COLOR;
- private P90Type type = P90Type.DOG_EAR;
- private Color poleColor = METAL_COLOR;
-
- @Override
- protected OrientationHV getControlPointDirection() {
- return OrientationHV.VERTICAL;
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- Shape[] body = getBody();
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
-
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : color);
- g2d.fill(body[0]);
- if (body[1] != null)
- g2d.fill(body[1]);
-// g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : POINT_COLOR);
-// g2d.fill(body[2]);
- drawingObserver.stopTracking();
- g2d.setComposite(oldComposite);
-
- Color finalBorderColor;
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : color.darker();
- }
-
- g2d.setColor(finalBorderColor);
- g2d.draw(body[0]);
- if (body[1] != null)
- g2d.draw(body[1]);
-
- markContactPoints(g2d, drawingObserver);
-
- if (!outlineMode) {
- g2d.setColor(getPoleColor());
- g2d.fill(body[3]);
- g2d.setColor(darkerOrLighter(getPoleColor()));
- g2d.draw(body[3]);
- }
-
-// Color finalLabelColor;
-// if (outlineMode) {
-// Theme theme =
-// (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
-// finalLabelColor =
-// componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
-// : theme.getOutlineColor();
-// } else {
-// finalLabelColor =
-// componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
-// : LABEL_COLOR;
-// }
-// g2d.setColor(finalLabelColor);
-// g2d.setFont(project.getFont());
-// Rectangle bounds = body[0].getBounds();
-// drawCenteredText(g2d, value, bounds.x + bounds.width / 2, bounds.y + bounds.height / 2, HorizontalAlignment.CENTER,
-// VerticalAlignment.CENTER);
- drawMainLabel(g2d, project, outlineMode, componentState);
-
- drawTerminalLabels(g2d, finalBorderColor, project);
- // terminal labels
-// Point[] points = getControlPoints();
-// g2d.setColor(finalBorderColor);
-//
-// g2d.setFont(project.getFont().deriveFont(TERMINAL_FONT_SIZE * 1f));
-// int dx = 0;
-// int dy = 0;
-// switch (orientation) {
-// case DEFAULT:
-// dx = (int) (TERMINAL_FONT_SIZE * 0.8);
-// dy = 0;
-// break;
-// case _90:
-// dx = 0;
-// dy = (int) (TERMINAL_FONT_SIZE * 0.8);
-// break;
-// case _180:
-// dx = -(int) (TERMINAL_FONT_SIZE * 0.8);
-// dy = 0;
-// break;
-// case _270:
-// dx = 0;
-// dy = -(int) (TERMINAL_FONT_SIZE * 0.8);
-// break;
-// }
-//
-// if (getPolarity() == Polarity.North || getPolarity() == Polarity.South) {
-// drawCenteredText(g2d, getPolarity().name().substring(0, 1), (points[1].x + points[2].x) / 2 + dx, (points[1].y + points[2].y) / 2 + dy, HorizontalAlignment.CENTER,
-// VerticalAlignment.CENTER);
-// } else {
-// drawCenteredText(g2d, "N", (points[0].x + points[1].x) / 2 + dx, (points[0].y + points[1].y) / 2 + dy, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
-// drawCenteredText(g2d, "S", (points[2].x + points[3].x) / 2 + dx, (points[2].y + points[3].y) / 2 + dy, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
-// }
- }
-
- @SuppressWarnings("incomplete-switch")
- @Override
- public Shape[] getBody() {
- if (body == null) {
- body = new Shape[4];
-
- Point2D[] points = getControlPoints();
- double x = points[0].getX();
- double y = points[0].getY();
- int width = (int) getType().getWidth().convertToPixels();
- int length = (int) getType().getLength().convertToPixels();
- int edgeRadius = (int) getType().getEdgeRadius().convertToPixels();
- int pointMargin = (int) POINT_MARGIN.convertToPixels();
- int totalLength = (int) TOTAL_LENGTH.convertToPixels();
- int lipRadius = (int) LIP_RADIUS.convertToPixels();
- int lipHoleSize = getClosestOdd(LIP_HOLE_SIZE.convertToPixels());
- int lipHoleSpacing = getClosestOdd(LIP_HOLE_SPACING.convertToPixels());
-
- body[0] =
- new Area(new RoundRectangle2D.Double(x /*+ pointMargin*/ - length, y - pointMargin, length, width, edgeRadius,
- edgeRadius));
-
- if (getType() == P90Type.DOG_EAR) {
- double rectWidth = (totalLength - length) / Math.sqrt(2);
- RoundRectangle2D roundRect =
- new RoundRectangle2D.Double(-rectWidth / 2, -rectWidth / 2, rectWidth, rectWidth, lipRadius, lipRadius);
- Area leftEar = new Area(roundRect);
- leftEar.transform(AffineTransform.getRotateInstance(Math.PI / 4));
- leftEar.transform(AffineTransform.getScaleInstance(1.1, 1.45));
- leftEar.transform(AffineTransform.getTranslateInstance(x /*+ pointMargin*/ - length, y - pointMargin + width / 2));
- leftEar.subtract((Area) body[0]);
- Area rightEar = new Area(roundRect);
- rightEar.transform(AffineTransform.getRotateInstance(Math.PI / 4));
- rightEar.transform(AffineTransform.getScaleInstance(1.1, 1.45));
- rightEar.transform(AffineTransform.getTranslateInstance(x /*+ pointMargin*/, y - pointMargin + width / 2));
- rightEar.subtract((Area) body[0]);
- Area lipArea = leftEar;
- lipArea.add(rightEar);
- lipArea.subtract(new Area(new Ellipse2D.Double(x /*+ pointMargin*/ - length / 2 - lipHoleSpacing / 2 - lipHoleSize
- / 2, y - pointMargin + width / 2 - lipHoleSize / 2, lipHoleSize, lipHoleSize)));
- lipArea.subtract(new Area(new Ellipse2D.Double(x /*+ pointMargin*/ - length / 2 + lipHoleSpacing / 2 - lipHoleSize
- / 2, y - pointMargin + width / 2 - lipHoleSize / 2, lipHoleSize, lipHoleSize)));
-
- body[1] = lipArea;
- }
-
- int poleSize = (int) POLE_SIZE.convertToPixels();
- int poleSpacing = (int) POLE_SPACING.convertToPixels();
- int poleMargin = (length - poleSpacing * 5) / 2;
- Area poleArea = new Area();
- for (int i = 0; i < 6; i++) {
- Ellipse2D pole =
- new Ellipse2D.Double(x /*+ pointMargin*/ - length + poleMargin + i * poleSpacing - poleSize / 2, y
- - pointMargin - poleSize / 2 + width / 2, poleSize, poleSize);
- poleArea.add(new Area(pole));
- }
- body[3] = poleArea;
-
- // Rotate if needed
- if (orientation != Orientation.DEFAULT) {
- double theta = 0;
- switch (orientation) {
- case _90:
- theta = Math.PI / 2;
- break;
- case _180:
- theta = Math.PI;
- break;
- case _270:
- theta = Math.PI * 3 / 2;
- break;
- }
- AffineTransform rotation = AffineTransform.getRotateInstance(theta, x, y);
- for (Shape shape : body) {
- Area area = (Area) shape;
- if (shape != null)
- area.transform(rotation);
- }
- }
- }
- return body;
- }
-
- @Override
- protected int getMainLabelYOffset() {
- return (int) (getType().getWidth().convertToPixels() / 2 - 20);
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- g2d.rotate(Math.PI / 4, width / 2, height / 2);
-
- int baseWidth = 13 * width / 32;
- int baseLength = 27 * width / 32;
- int radius = 6 * width / 32;
-
- g2d.setColor(BODY_COLOR);
- Polygon base =
- new Polygon(new int[] {width / 2, (width + baseWidth) / 2, (width + baseWidth) / 2, width / 2,
- (width - baseWidth) / 2, (width - baseWidth) / 2}, new int[] {-2, (height - baseLength) / 2,
- (height + baseLength) / 2, height + 1, (height + baseLength) / 2, (height - baseLength) / 2}, 6);
- Area baseArea = new Area(base);
- baseArea.intersect(new Area(new Rectangle(0, -1, width, height + 1)));
- g2d.fill(baseArea);
- g2d.setColor(BODY_COLOR.darker());
- g2d.draw(baseArea);
-
- g2d.setColor(BODY_COLOR);
- g2d.fillRoundRect((width - baseWidth) / 2, (height - baseLength) / 2, baseWidth, baseLength, radius, radius);
- g2d.setColor(BODY_COLOR.darker());
- g2d.drawRoundRect((width - baseWidth) / 2, (height - baseLength) / 2, baseWidth, baseLength, radius, radius);
-
- g2d.setColor(METAL_COLOR);
- int poleSize = 2;
- int poleSpacing = 17 * width / 32;
- for (int i = 0; i < 6; i++) {
- g2d.fillOval((width - poleSize) / 2, (height - poleSpacing) / 2 + (i * poleSpacing / 5), poleSize, poleSize);
- }
- }
-
- @EditableProperty(name = "Type")
- public P90Type getType() {
- return type;
- }
-
- public void setType(P90Type type) {
- this.type = type;
- // Invalidate the body
- body = null;
- }
-
- @EditableProperty
- public Color getColor() {
- return color;
- }
-
- public void setColor(Color color) {
- this.color = color;
- }
-
- @EditableProperty(name = "Pole Color")
- public Color getPoleColor() {
- if (poleColor == null)
- poleColor = METAL_COLOR;
- return poleColor;
- }
-
- public void setPoleColor(Color poleColor) {
- this.poleColor = poleColor;
- }
-
- public enum P90Type {
- DOG_EAR("Dog Ear", DOG_EAR_LENGTH, DOG_EAR_WIDTH, DOG_EAR_EDGE_RADIUS), SOAP_BAR("Soap Bar", SOAP_BAR_LENGTH,
- SOAP_BAR_WIDTH, SOAP_BAR_EDGE_RADIUS);
-
- private String label;
- private Size length;
- private Size width;
- private Size edgeRadius;
-
- private P90Type(String label, Size length, Size width, Size edgeRadius) {
- this.label = label;
- this.length = length;
- this.width = width;
- this.edgeRadius = edgeRadius;
- }
-
- public Size getLength() {
- return length;
- }
-
- public Size getWidth() {
- return width;
- }
-
- public Size getEdgeRadius() {
- return edgeRadius;
- }
-
- @Override
- public String toString() {
- return label;
- }
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.guitar;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Graphics2D;
+import java.awt.Polygon;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Area;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.RoundRectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.common.IPlugInPort;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.Orientation;
+import org.diylc.common.OrientationHV;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+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;
+import org.diylc.utils.Constants;
+
+@ComponentDescriptor(name = "P-90 Single Coil Pickup", category = "Guitar", author = "Branislav Stojkovic",
+ description = "Single coil P-90 guitar pickup, both \"dog ear\" and \"soap bar\"",
+ zOrder = IDIYComponent.COMPONENT, instanceNamePrefix = "PKP",
+ keywordPolicy = KeywordPolicy.SHOW_TAG, keywordTag = "Guitar Wiring Diagram", enableCache = true)
+public class P90Pickup extends AbstractSingleOrHumbuckerPickup {
+
+ private static final long serialVersionUID = 1L;
+
+ private static Color BODY_COLOR = Color.decode("#D8C989");;
+// private static Color POINT_COLOR = Color.darkGray;
+
+ // dog ear
+ private static Size DOG_EAR_WIDTH = new Size(41d, SizeUnit.mm);
+ private static Size DOG_EAR_LENGTH = new Size(86.9d, SizeUnit.mm);
+ private static Size TOTAL_LENGTH = new Size(118.7d, SizeUnit.mm);
+ private static Size DOG_EAR_EDGE_RADIUS = new Size(4d, SizeUnit.mm);
+
+ // soap bar
+ private static Size SOAP_BAR_WIDTH = new Size(35.3d, SizeUnit.mm);
+ private static Size SOAP_BAR_LENGTH = new Size(85.6d, SizeUnit.mm);
+ private static Size SOAP_BAR_EDGE_RADIUS = new Size(8d, SizeUnit.mm);
+
+ private static Size LIP_RADIUS = new Size(10d, SizeUnit.mm);
+ private static Size POINT_MARGIN = new Size(3.5d, SizeUnit.mm);
+ private static Size LIP_HOLE_SIZE = new Size(2.5d, SizeUnit.mm);
+ private static Size LIP_HOLE_SPACING = new Size(97d, SizeUnit.mm);
+ private static Size POLE_SIZE = new Size(4d, SizeUnit.mm);
+ private static Size POLE_SPACING = new Size(11.68d, SizeUnit.mm);
+
+ private Color color = BODY_COLOR;
+ private P90Type type = P90Type.DOG_EAR;
+ private Color poleColor = METAL_COLOR;
+
+ @Override
+ protected OrientationHV getControlPointDirection() {
+ return OrientationHV.VERTICAL;
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ Shape[] body = getBody();
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : color);
+ g2d.fill(body[0]);
+ if (body[1] != null)
+ g2d.fill(body[1]);
+// g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : POINT_COLOR);
+// g2d.fill(body[2]);
+ drawingObserver.stopTracking();
+ g2d.setComposite(oldComposite);
+
+ Color finalBorderColor;
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : color.darker();
+ }
+
+ g2d.setColor(finalBorderColor);
+ g2d.draw(body[0]);
+ if (body[1] != null)
+ g2d.draw(body[1]);
+
+ markContactPoints(g2d, drawingObserver);
+
+ if (!outlineMode) {
+ g2d.setColor(getPoleColor());
+ g2d.fill(body[3]);
+ g2d.setColor(darkerOrLighter(getPoleColor()));
+ g2d.draw(body[3]);
+ }
+
+// Color finalLabelColor;
+// if (outlineMode) {
+// Theme theme =
+// (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+// finalLabelColor =
+// componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+// : theme.getOutlineColor();
+// } else {
+// finalLabelColor =
+// componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+// : LABEL_COLOR;
+// }
+// g2d.setColor(finalLabelColor);
+// g2d.setFont(project.getFont());
+// Rectangle bounds = body[0].getBounds();
+// drawCenteredText(g2d, value, bounds.x + bounds.width / 2, bounds.y + bounds.height / 2, HorizontalAlignment.CENTER,
+// VerticalAlignment.CENTER);
+ drawMainLabel(g2d, project, outlineMode, componentState);
+
+ drawTerminalLabels(g2d, finalBorderColor, project);
+ // terminal labels
+// Point[] points = getControlPoints();
+// g2d.setColor(finalBorderColor);
+//
+// g2d.setFont(project.getFont().deriveFont(TERMINAL_FONT_SIZE * 1f));
+// int dx = 0;
+// int dy = 0;
+// switch (orientation) {
+// case DEFAULT:
+// dx = (int) (TERMINAL_FONT_SIZE * 0.8);
+// dy = 0;
+// break;
+// case _90:
+// dx = 0;
+// dy = (int) (TERMINAL_FONT_SIZE * 0.8);
+// break;
+// case _180:
+// dx = -(int) (TERMINAL_FONT_SIZE * 0.8);
+// dy = 0;
+// break;
+// case _270:
+// dx = 0;
+// dy = -(int) (TERMINAL_FONT_SIZE * 0.8);
+// break;
+// }
+//
+// if (getPolarity() == Polarity.North || getPolarity() == Polarity.South) {
+// drawCenteredText(g2d, getPolarity().name().substring(0, 1), (points[1].x + points[2].x) / 2 + dx, (points[1].y + points[2].y) / 2 + dy, HorizontalAlignment.CENTER,
+// VerticalAlignment.CENTER);
+// } else {
+// drawCenteredText(g2d, "N", (points[0].x + points[1].x) / 2 + dx, (points[0].y + points[1].y) / 2 + dy, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
+// drawCenteredText(g2d, "S", (points[2].x + points[3].x) / 2 + dx, (points[2].y + points[3].y) / 2 + dy, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
+// }
+ }
+
+ @SuppressWarnings("incomplete-switch")
+ @Override
+ public Shape[] getBody() {
+ if (body == null) {
+ body = new Shape[4];
+
+ Point2D[] points = getControlPoints();
+ double x = points[0].getX();
+ double y = points[0].getY();
+ int width = (int) getType().getWidth().convertToPixels();
+ int length = (int) getType().getLength().convertToPixels();
+ int edgeRadius = (int) getType().getEdgeRadius().convertToPixels();
+ int pointMargin = (int) POINT_MARGIN.convertToPixels();
+ int totalLength = (int) TOTAL_LENGTH.convertToPixels();
+ int lipRadius = (int) LIP_RADIUS.convertToPixels();
+ int lipHoleSize = getClosestOdd(LIP_HOLE_SIZE.convertToPixels());
+ int lipHoleSpacing = getClosestOdd(LIP_HOLE_SPACING.convertToPixels());
+
+ body[0] =
+ new Area(new RoundRectangle2D.Double(x /*+ pointMargin*/ - length, y - pointMargin, length, width, edgeRadius,
+ edgeRadius));
+
+ if (getType() == P90Type.DOG_EAR) {
+ double rectWidth = (totalLength - length) / Math.sqrt(2);
+ RoundRectangle2D roundRect =
+ new RoundRectangle2D.Double(-rectWidth / 2, -rectWidth / 2, rectWidth, rectWidth, lipRadius, lipRadius);
+ Area leftEar = new Area(roundRect);
+ leftEar.transform(AffineTransform.getRotateInstance(Math.PI / 4));
+ leftEar.transform(AffineTransform.getScaleInstance(1.1, 1.45));
+ leftEar.transform(AffineTransform.getTranslateInstance(x /*+ pointMargin*/ - length, y - pointMargin + width / 2));
+ leftEar.subtract((Area) body[0]);
+ Area rightEar = new Area(roundRect);
+ rightEar.transform(AffineTransform.getRotateInstance(Math.PI / 4));
+ rightEar.transform(AffineTransform.getScaleInstance(1.1, 1.45));
+ rightEar.transform(AffineTransform.getTranslateInstance(x /*+ pointMargin*/, y - pointMargin + width / 2));
+ rightEar.subtract((Area) body[0]);
+ Area lipArea = leftEar;
+ lipArea.add(rightEar);
+ lipArea.subtract(new Area(new Ellipse2D.Double(x /*+ pointMargin*/ - length / 2 - lipHoleSpacing / 2 - lipHoleSize
+ / 2, y - pointMargin + width / 2 - lipHoleSize / 2, lipHoleSize, lipHoleSize)));
+ lipArea.subtract(new Area(new Ellipse2D.Double(x /*+ pointMargin*/ - length / 2 + lipHoleSpacing / 2 - lipHoleSize
+ / 2, y - pointMargin + width / 2 - lipHoleSize / 2, lipHoleSize, lipHoleSize)));
+
+ body[1] = lipArea;
+ }
+
+ int poleSize = (int) POLE_SIZE.convertToPixels();
+ int poleSpacing = (int) POLE_SPACING.convertToPixels();
+ int poleMargin = (length - poleSpacing * 5) / 2;
+ Area poleArea = new Area();
+ for (int i = 0; i < 6; i++) {
+ Ellipse2D pole =
+ new Ellipse2D.Double(x /*+ pointMargin*/ - length + poleMargin + i * poleSpacing - poleSize / 2, y
+ - pointMargin - poleSize / 2 + width / 2, poleSize, poleSize);
+ poleArea.add(new Area(pole));
+ }
+ body[3] = poleArea;
+
+ // Rotate if needed
+ if (orientation != Orientation.DEFAULT) {
+ double theta = 0;
+ switch (orientation) {
+ case _90:
+ theta = Math.PI / 2;
+ break;
+ case _180:
+ theta = Math.PI;
+ break;
+ case _270:
+ theta = Math.PI * 3 / 2;
+ break;
+ }
+ AffineTransform rotation = AffineTransform.getRotateInstance(theta, x, y);
+ for (Shape shape : body) {
+ Area area = (Area) shape;
+ if (shape != null)
+ area.transform(rotation);
+ }
+ }
+ }
+ return body;
+ }
+
+ @Override
+ protected int getMainLabelYOffset() {
+ return (int) (getType().getWidth().convertToPixels() / 2 - 20);
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ g2d.rotate(Math.PI / 4, width / 2, height / 2);
+
+ int baseWidth = 13 * width / 32;
+ int baseLength = 27 * width / 32;
+ int radius = 6 * width / 32;
+
+ g2d.setColor(BODY_COLOR);
+ Polygon base =
+ new Polygon(new int[] {width / 2, (width + baseWidth) / 2, (width + baseWidth) / 2, width / 2,
+ (width - baseWidth) / 2, (width - baseWidth) / 2}, new int[] {-2, (height - baseLength) / 2,
+ (height + baseLength) / 2, height + 1, (height + baseLength) / 2, (height - baseLength) / 2}, 6);
+ Area baseArea = new Area(base);
+ baseArea.intersect(new Area(new Rectangle(0, -1, width, height + 1)));
+ g2d.fill(baseArea);
+ g2d.setColor(BODY_COLOR.darker());
+ g2d.draw(baseArea);
+
+ g2d.setColor(BODY_COLOR);
+ g2d.fillRoundRect((width - baseWidth) / 2, (height - baseLength) / 2, baseWidth, baseLength, radius, radius);
+ g2d.setColor(BODY_COLOR.darker());
+ g2d.drawRoundRect((width - baseWidth) / 2, (height - baseLength) / 2, baseWidth, baseLength, radius, radius);
+
+ g2d.setColor(METAL_COLOR);
+ int poleSize = 2;
+ int poleSpacing = 17 * width / 32;
+ for (int i = 0; i < 6; i++) {
+ g2d.fillOval((width - poleSize) / 2, (height - poleSpacing) / 2 + (i * poleSpacing / 5), poleSize, poleSize);
+ }
+ }
+
+ @EditableProperty(name = "Type")
+ public P90Type getType() {
+ return type;
+ }
+
+ public void setType(P90Type type) {
+ this.type = type;
+ // Invalidate the body
+ body = null;
+ }
+
+ @EditableProperty
+ public Color getColor() {
+ return color;
+ }
+
+ public void setColor(Color color) {
+ this.color = color;
+ }
+
+ @EditableProperty(name = "Pole Color")
+ public Color getPoleColor() {
+ if (poleColor == null)
+ poleColor = METAL_COLOR;
+ return poleColor;
+ }
+
+ public void setPoleColor(Color poleColor) {
+ this.poleColor = poleColor;
+ }
+
+ public enum P90Type {
+ DOG_EAR("Dog Ear", DOG_EAR_LENGTH, DOG_EAR_WIDTH, DOG_EAR_EDGE_RADIUS), SOAP_BAR("Soap Bar", SOAP_BAR_LENGTH,
+ SOAP_BAR_WIDTH, SOAP_BAR_EDGE_RADIUS);
+
+ private String label;
+ private Size length;
+ private Size width;
+ private Size edgeRadius;
+
+ private P90Type(String label, Size length, Size width, Size edgeRadius) {
+ this.label = label;
+ this.length = length;
+ this.width = width;
+ this.edgeRadius = edgeRadius;
+ }
+
+ public Size getLength() {
+ return length;
+ }
+
+ public Size getWidth() {
+ return width;
+ }
+
+ public Size getEdgeRadius() {
+ return edgeRadius;
+ }
+
+ @Override
+ public String toString() {
+ return label;
+ }
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/PBassPickup.java b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/PBassPickup.java
index 3c4bad366..92f384559 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/PBassPickup.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/PBassPickup.java
@@ -1,273 +1,270 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.guitar;
-
-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.Area;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.Point2D;
-import java.awt.geom.RoundRectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.Orientation;
-import org.diylc.common.OrientationHV;
-import org.diylc.components.transform.GuitarPickupTransformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-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;
-import org.diylc.utils.Constants;
-
-@ComponentDescriptor(name = "P- Bass Pickup", category = "Guitar", author = "Branislav Stojkovic",
- description = "Split-coil pickup for P-Bass and similar guitars",
- zOrder = IDIYComponent.COMPONENT, instanceNamePrefix = "PKP",
- keywordPolicy = KeywordPolicy.SHOW_TAG, keywordTag = "Guitar Wiring Diagram", enableCache = true,
- transformer = GuitarPickupTransformer.class)
-public class PBassPickup extends AbstractSingleOrHumbuckerPickup {
-
- private static final long serialVersionUID = 1L;
-
- private static Color BODY_COLOR = Color.decode("#333333");;
-
- private static Size WIDTH = new Size(1.1, SizeUnit.in);
- private static Size LENGTH = new Size(2.2, SizeUnit.in);
- private static Size EDGE_RADIUS = new Size(0.08d, SizeUnit.in);
- private static Size LIP_RADIUS = new Size(0.45d, SizeUnit.in);
- private static Size LIP_HOLE_SIZE = new Size(0.1d, SizeUnit.in);
- private static Size LIP_HOLE_SPACING = new Size(0.1d, SizeUnit.in);
-
- private static Size POINT_MARGIN = new Size(1.5d, SizeUnit.mm);
- private static Size POLE_SIZE = new Size(4d, SizeUnit.mm);
- private static Size POLE_SPACING = new Size(0.38d, SizeUnit.in);
-
- private Color color = BODY_COLOR;
- private Color poleColor = METAL_COLOR;
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- Shape[] body = getBody();
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
-
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : color);
- g2d.fill(body[0]);
- g2d.fill(body[1]);
- drawingObserver.stopTracking();
- g2d.setComposite(oldComposite);
-
- markContactPoints(g2d, drawingObserver);
-
- Color finalBorderColor;
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : color.darker();
- }
-
- g2d.setColor(finalBorderColor);
- g2d.draw(body[0]);
- g2d.draw(body[1]);
-
- if (!outlineMode) {
- g2d.setColor(getPoleColor());
- g2d.fill(body[3]);
- g2d.setColor(darkerOrLighter(getPoleColor()));
- g2d.draw(body[3]);
- }
-
-// Color finalLabelColor;
-// if (outlineMode) {
-// Theme theme =
-// (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
-// finalLabelColor =
-// componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
-// : theme.getOutlineColor();
-// } else {
-// finalLabelColor =
-// componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
-// : LABEL_COLOR;
-// }
-// g2d.setColor(finalLabelColor);
-// g2d.setFont(project.getFont());
-// Rectangle bounds = body[0].getBounds();
-// drawCenteredText(g2d, value, bounds.x + bounds.width / 2, bounds.y + bounds.height / 2, HorizontalAlignment.CENTER,
-// VerticalAlignment.CENTER);
- drawMainLabel(g2d, project, outlineMode, componentState);
-
- drawTerminalLabels(g2d, finalBorderColor, project);
- }
-
- @SuppressWarnings("incomplete-switch")
- @Override
- public Shape[] getBody() {
- if (body == null) {
- body = new Shape[4];
-
- Point2D[] points = getControlPoints();
- double x = points[0].getX();
- double y = points[0].getY();
- int width = (int) WIDTH.convertToPixels();
- int length = (int) LENGTH.convertToPixels();
- int edgeRadius = (int) EDGE_RADIUS.convertToPixels();
- int pointMargin = (int) POINT_MARGIN.convertToPixels();
- int lipRadius = (int) LIP_RADIUS.convertToPixels();
- int lipHoleSize = getClosestOdd(LIP_HOLE_SIZE.convertToPixels());
- int lipHoleSpacing = getClosestOdd(LIP_HOLE_SPACING.convertToPixels());
-
- body[0] =
- new Area(new RoundRectangle2D.Double(x - length, y - pointMargin, length, width, edgeRadius,
- edgeRadius));
-
- Area lip = new Area(new Ellipse2D.Double(-lipRadius / 2, -lipRadius / 2, lipRadius, lipRadius));
- lip.subtract(new Area(new Ellipse2D.Double(-lipHoleSize / 2 + lipHoleSpacing, -lipHoleSize / 2, lipHoleSize, lipHoleSize)));
- lip.transform(AffineTransform.getTranslateInstance(x, y - pointMargin + width / 2));
- Area lip2 = new Area(new Ellipse2D.Double(-lipRadius / 2, -lipRadius / 2, lipRadius, lipRadius));
- lip2 = new Area(new Ellipse2D.Double(-lipRadius / 2, -lipRadius / 2, lipRadius, lipRadius));
- lip2.subtract(new Area(new Ellipse2D.Double(-lipHoleSize / 2 - lipHoleSpacing, -lipHoleSize / 2, lipHoleSize, lipHoleSize)));
- lip2.transform(AffineTransform.getTranslateInstance(x - length, y - pointMargin + width / 2));
- lip.add(lip2);
-
- body[1] = new Area(lip);
-
- ((Area)body[1]).subtract((Area)body[0]);
-
- int poleSize = (int) POLE_SIZE.convertToPixels();
- int poleSpacing = (int) POLE_SPACING.convertToPixels();
- int poleMargin = (length - poleSpacing * 3) / 2;
- Area poleArea = new Area();
- for (int i = 0; i < 4; i++) {
- Ellipse2D pole =
- new Ellipse2D.Double(x - length + poleMargin + i * poleSpacing - poleSize / 2, y
- - pointMargin - poleSize / 2 + width / 2, poleSize, poleSize);
- poleArea.add(new Area(pole));
- }
- body[3] = poleArea;
-
- // Rotate if needed
- if (orientation != Orientation.DEFAULT) {
- double theta = 0;
- switch (orientation) {
- case _90:
- theta = Math.PI / 2;
- break;
- case _180:
- theta = Math.PI;
- break;
- case _270:
- theta = Math.PI * 3 / 2;
- break;
- }
- AffineTransform rotation = AffineTransform.getRotateInstance(theta, x, y);
- for (Shape shape : body) {
- Area area = (Area) shape;
- if (shape != null)
- area.transform(rotation);
- }
- }
- }
- return body;
- }
-
- @Override
- protected int getMainLabelYOffset() {
- return (int) (WIDTH.convertToPixels() / 2 - 20);
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- g2d.rotate(Math.PI / 4, width / 2, height / 2);
-
- int bodyWidth = (int) (13f * width / 32);
- int bodyLength = (int) (30f * width / 32);
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f));
- g2d.setColor(BODY_COLOR);
- g2d.fillRoundRect((width - bodyWidth) / 2, (height - bodyLength) / 2, bodyWidth, bodyLength, 3, 3);
-
- int lipSize = (int) (5f * width / 32);
-
- g2d.fillRoundRect((width - lipSize) / 2, (height - bodyLength) / 2 - lipSize + 1, lipSize, bodyLength + 2 * lipSize - 2, lipSize, lipSize);
-
- g2d.setColor(BODY_COLOR.darker());
- g2d.drawRoundRect((width - bodyWidth) / 2, (height - bodyLength) / 2, bodyWidth, bodyLength, 3, 3);
-
- // g2d.setColor(Color.gray);
- // g2d.drawLine(width / 2, 4 * width / 32, width / 2, 4 * width / 32);
- // g2d.drawLine(width / 2, height - 4 * width / 32, width / 2, height - 4 * width / 32);
-
- g2d.setColor(METAL_COLOR);
- int poleSize = 2;
- int poleSpacing = (int) (15d * width / 32);
- for (int i = 0; i < 4; i++) {
- g2d.fillOval((width - poleSize) / 2, (height - poleSpacing) / 2 + (i * poleSpacing / 3), poleSize, poleSize);
- }
- }
-
- @Override
- protected OrientationHV getControlPointDirection() {
- return OrientationHV.VERTICAL;
- }
-
- @EditableProperty
- public Color getColor() {
- return color;
- }
-
- public void setColor(Color color) {
- this.color = color;
- }
-
- @EditableProperty(name = "Pole Color")
- public Color getPoleColor() {
- if (poleColor == null)
- poleColor = METAL_COLOR;
- return poleColor;
- }
-
- public void setPoleColor(Color poleColor) {
- this.poleColor = poleColor;
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.guitar;
+
+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.Area;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.RoundRectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.common.IPlugInPort;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.Orientation;
+import org.diylc.common.OrientationHV;
+import org.diylc.components.transform.GuitarPickupTransformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+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;
+import org.diylc.utils.Constants;
+
+@ComponentDescriptor(name = "P- Bass Pickup", category = "Guitar", author = "Branislav Stojkovic",
+ description = "Split-coil pickup for P-Bass and similar guitars",
+ zOrder = IDIYComponent.COMPONENT, instanceNamePrefix = "PKP",
+ keywordPolicy = KeywordPolicy.SHOW_TAG, keywordTag = "Guitar Wiring Diagram", enableCache = true,
+ transformer = GuitarPickupTransformer.class)
+public class PBassPickup extends AbstractSingleOrHumbuckerPickup {
+
+ private static final long serialVersionUID = 1L;
+
+ private static Color BODY_COLOR = Color.decode("#333333");;
+
+ private static Size WIDTH = new Size(1.1, SizeUnit.in);
+ private static Size LENGTH = new Size(2.2, SizeUnit.in);
+ private static Size EDGE_RADIUS = new Size(0.08d, SizeUnit.in);
+ private static Size LIP_RADIUS = new Size(0.45d, SizeUnit.in);
+ private static Size LIP_HOLE_SIZE = new Size(0.1d, SizeUnit.in);
+ private static Size LIP_HOLE_SPACING = new Size(0.1d, SizeUnit.in);
+
+ private static Size POINT_MARGIN = new Size(1.5d, SizeUnit.mm);
+ private static Size POLE_SIZE = new Size(4d, SizeUnit.mm);
+ private static Size POLE_SPACING = new Size(0.38d, SizeUnit.in);
+
+ private Color color = BODY_COLOR;
+ private Color poleColor = METAL_COLOR;
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ Shape[] body = getBody();
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : color);
+ g2d.fill(body[0]);
+ g2d.fill(body[1]);
+ drawingObserver.stopTracking();
+ g2d.setComposite(oldComposite);
+
+ markContactPoints(g2d, drawingObserver);
+
+ Color finalBorderColor;
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : color.darker();
+ }
+
+ g2d.setColor(finalBorderColor);
+ g2d.draw(body[0]);
+ g2d.draw(body[1]);
+
+ if (!outlineMode) {
+ g2d.setColor(getPoleColor());
+ g2d.fill(body[3]);
+ g2d.setColor(darkerOrLighter(getPoleColor()));
+ g2d.draw(body[3]);
+ }
+
+// Color finalLabelColor;
+// if (outlineMode) {
+// Theme theme =
+// (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+// finalLabelColor =
+// componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+// : theme.getOutlineColor();
+// } else {
+// finalLabelColor =
+// componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+// : LABEL_COLOR;
+// }
+// g2d.setColor(finalLabelColor);
+// g2d.setFont(project.getFont());
+// Rectangle bounds = body[0].getBounds();
+// drawCenteredText(g2d, value, bounds.x + bounds.width / 2, bounds.y + bounds.height / 2, HorizontalAlignment.CENTER,
+// VerticalAlignment.CENTER);
+ drawMainLabel(g2d, project, outlineMode, componentState);
+
+ drawTerminalLabels(g2d, finalBorderColor, project);
+ }
+
+ @SuppressWarnings("incomplete-switch")
+ @Override
+ public Shape[] getBody() {
+ if (body == null) {
+ body = new Shape[4];
+
+ Point2D[] points = getControlPoints();
+ double x = points[0].getX();
+ double y = points[0].getY();
+ int width = (int) WIDTH.convertToPixels();
+ int length = (int) LENGTH.convertToPixels();
+ int edgeRadius = (int) EDGE_RADIUS.convertToPixels();
+ int pointMargin = (int) POINT_MARGIN.convertToPixels();
+ int lipRadius = (int) LIP_RADIUS.convertToPixels();
+ int lipHoleSize = getClosestOdd(LIP_HOLE_SIZE.convertToPixels());
+ int lipHoleSpacing = getClosestOdd(LIP_HOLE_SPACING.convertToPixels());
+
+ body[0] =
+ new Area(new RoundRectangle2D.Double(x - length, y - pointMargin, length, width, edgeRadius,
+ edgeRadius));
+
+ Area lip = new Area(new Ellipse2D.Double(-lipRadius / 2, -lipRadius / 2, lipRadius, lipRadius));
+ lip.subtract(new Area(new Ellipse2D.Double(-lipHoleSize / 2 + lipHoleSpacing, -lipHoleSize / 2, lipHoleSize, lipHoleSize)));
+ lip.transform(AffineTransform.getTranslateInstance(x, y - pointMargin + width / 2));
+ Area lip2 = new Area(new Ellipse2D.Double(-lipRadius / 2, -lipRadius / 2, lipRadius, lipRadius));
+ lip2 = new Area(new Ellipse2D.Double(-lipRadius / 2, -lipRadius / 2, lipRadius, lipRadius));
+ lip2.subtract(new Area(new Ellipse2D.Double(-lipHoleSize / 2 - lipHoleSpacing, -lipHoleSize / 2, lipHoleSize, lipHoleSize)));
+ lip2.transform(AffineTransform.getTranslateInstance(x - length, y - pointMargin + width / 2));
+ lip.add(lip2);
+
+ body[1] = new Area(lip);
+
+ ((Area)body[1]).subtract((Area)body[0]);
+
+ int poleSize = (int) POLE_SIZE.convertToPixels();
+ int poleSpacing = (int) POLE_SPACING.convertToPixels();
+ int poleMargin = (length - poleSpacing * 3) / 2;
+ Area poleArea = new Area();
+ for (int i = 0; i < 4; i++) {
+ Ellipse2D pole =
+ new Ellipse2D.Double(x - length + poleMargin + i * poleSpacing - poleSize / 2, y
+ - pointMargin - poleSize / 2 + width / 2, poleSize, poleSize);
+ poleArea.add(new Area(pole));
+ }
+ body[3] = poleArea;
+
+ // Rotate if needed
+ if (orientation != Orientation.DEFAULT) {
+ double theta = 0;
+ switch (orientation) {
+ case _90:
+ theta = Math.PI / 2;
+ break;
+ case _180:
+ theta = Math.PI;
+ break;
+ case _270:
+ theta = Math.PI * 3 / 2;
+ break;
+ }
+ AffineTransform rotation = AffineTransform.getRotateInstance(theta, x, y);
+ for (Shape shape : body) {
+ Area area = (Area) shape;
+ if (shape != null)
+ area.transform(rotation);
+ }
+ }
+ }
+ return body;
+ }
+
+ @Override
+ protected int getMainLabelYOffset() {
+ return (int) (WIDTH.convertToPixels() / 2 - 20);
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ g2d.rotate(Math.PI / 4, width / 2, height / 2);
+
+ int bodyWidth = (int) (13f * width / 32);
+ int bodyLength = (int) (30f * width / 32);
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f));
+ g2d.setColor(BODY_COLOR);
+ g2d.fillRoundRect((width - bodyWidth) / 2, (height - bodyLength) / 2, bodyWidth, bodyLength, 3, 3);
+
+ int lipSize = (int) (5f * width / 32);
+
+ g2d.fillRoundRect((width - lipSize) / 2, (height - bodyLength) / 2 - lipSize + 1, lipSize, bodyLength + 2 * lipSize - 2, lipSize, lipSize);
+
+ g2d.setColor(BODY_COLOR.darker());
+ g2d.drawRoundRect((width - bodyWidth) / 2, (height - bodyLength) / 2, bodyWidth, bodyLength, 3, 3);
+
+ // g2d.setColor(Color.gray);
+ // g2d.drawLine(width / 2, 4 * width / 32, width / 2, 4 * width / 32);
+ // g2d.drawLine(width / 2, height - 4 * width / 32, width / 2, height - 4 * width / 32);
+
+ g2d.setColor(METAL_COLOR);
+ int poleSize = 2;
+ int poleSpacing = (int) (15d * width / 32);
+ for (int i = 0; i < 4; i++) {
+ g2d.fillOval((width - poleSize) / 2, (height - poleSpacing) / 2 + (i * poleSpacing / 3), poleSize, poleSize);
+ }
+ }
+
+ @Override
+ protected OrientationHV getControlPointDirection() {
+ return OrientationHV.VERTICAL;
+ }
+
+ @EditableProperty
+ public Color getColor() {
+ return color;
+ }
+
+ public void setColor(Color color) {
+ this.color = color;
+ }
+
+ @EditableProperty(name = "Pole Color")
+ public Color getPoleColor() {
+ if (poleColor == null)
+ poleColor = METAL_COLOR;
+ return poleColor;
+ }
+
+ public void setPoleColor(Color poleColor) {
+ this.poleColor = poleColor;
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/S1Switch.java b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/S1Switch.java
index 519d9f1c4..275e51221 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/S1Switch.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/S1Switch.java
@@ -156,10 +156,7 @@ public class S1Switch extends AbstractTransparentComponent implements ISwi
Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
// Draw body if available.
if (body != null) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : BODY_COLOR);
g2d.fill(body);
drawingObserver.stopTracking();
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/SchallerMegaSwitch.java b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/SchallerMegaSwitch.java
index 9c3e6fb25..b38942dce 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/SchallerMegaSwitch.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/SchallerMegaSwitch.java
@@ -103,11 +103,7 @@ public class SchallerMegaSwitch extends AbstractAngledComponent implemen
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
if (componentState != ComponentState.DRAGGING) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(
- AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : BASE_COLOR);
g2d.fill(body[0]);
drawingObserver.stopTracking();
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/SingleCoilPickup.java b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/SingleCoilPickup.java
index bce655d34..d29fefd2a 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/SingleCoilPickup.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/SingleCoilPickup.java
@@ -1,460 +1,457 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.guitar;
-
-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.Area;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.geom.RoundRectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.Orientation;
-import org.diylc.common.OrientationHV;
-import org.diylc.components.RoundedPath;
-import org.diylc.components.transform.GuitarPickupTransformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-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;
-import org.diylc.utils.Constants;
-
-@ComponentDescriptor(name = "Single Coil Pickup", category = "Guitar", author = "Branislav Stojkovic",
- description = "Single coil guitar pickup, both Strat and Tele style",
- zOrder = IDIYComponent.COMPONENT, instanceNamePrefix = "PKP",
- keywordPolicy = KeywordPolicy.SHOW_TAG, keywordTag = "Guitar Wiring Diagram", enableCache = true,
- transformer = GuitarPickupTransformer.class)
-public class SingleCoilPickup extends AbstractSingleOrHumbuckerPickup {
-
- private static final long serialVersionUID = 1L;
-
- private static Color BODY_COLOR = Color.white;
- private static Color BASE_COLOR = Color.gray;
- public static Color LUG_COLOR = Color.decode("#E0C04C");
-// private static Color POINT_COLOR = Color.lightGray;
- private static Size WIDTH = new Size(15.5d, SizeUnit.mm);
- private static Size LENGTH = new Size(83d, SizeUnit.mm);
- private static Size BASE_RADIUS = new Size(0.15d, SizeUnit.in);
- private static Size LUG_DIAMETER = new Size(0.06d, SizeUnit.in);
-
- // strat-specific
- private static Size STRAT_LIP_WIDTH = new Size(5d, SizeUnit.mm);
- private static Size STRAT_LIP_LENGTH = new Size(20d, SizeUnit.mm);
- private static Size STRAT_INNER_LENGTH = new Size(70d, SizeUnit.mm);
-
- // tele-specific
- private static Size TELE_BASE_WIDTH = new Size(1.5d, SizeUnit.in);
- private static Size TELE_LIP_LENGTH = new Size(1.735d, SizeUnit.in);
- private static Size TELE_LENGTH = new Size(2.87d, SizeUnit.in);
- private static Size TELE_HOLE_SPACING = new Size(1.135d, SizeUnit.in);
-
- private static Size HOLE_SIZE = new Size(2d, SizeUnit.mm);
- private static Size HOLE_MARGIN = new Size(4d, SizeUnit.mm);
- private static Size POLE_SIZE = new Size(4d, SizeUnit.mm);
- private static Size POLE_SPACING = new Size(11.68d, SizeUnit.mm);
-
- private static Size RAIL_WIDTH = new Size(1.5d, SizeUnit.mm);
- private static Size RAIL_LENGTH = new Size(60d, SizeUnit.mm);
- private static Size COIL_SPACING = new Size(7.5d, SizeUnit.mm);
-
- private Color color = BODY_COLOR;
- private Color poleColor = METAL_COLOR;
- private Color baseColor = BASE_COLOR;
- private SingleCoilType type = SingleCoilType.Stratocaster;
- private PolePieceType polePieceType = PolePieceType.Rods;
- private Color lugColor = LUG_COLOR;
-
- @Override
- protected OrientationHV getControlPointDirection() {
- return OrientationHV.HORIZONTAL;
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- Shape[] body = getBody();
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
-
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
-
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
-
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getBaseColor());
- g2d.fill(body[4]);
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getColor());
- if (body[3] == null)
- g2d.fill(body[0]);
- else
- g2d.fill(body[3]);
-
- drawingObserver.stopTracking();
-
- markContactPoints(g2d, drawingObserver);
-
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getLugColor());
- g2d.fill(body[1]);
- g2d.setColor(outlineMode ? theme.getOutlineColor() : darkerOrLighter(LUG_COLOR));
- g2d.draw(body[1]);
-
- // g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : color);
- // g2d.fill(body[3]);
- g2d.setComposite(oldComposite);
-
- Color finalBorderColor;
- if (outlineMode) {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : darkerOrLighter(getBaseColor());
- }
-
- g2d.setColor(finalBorderColor);
- g2d.draw(body[4]);
-
- if (outlineMode) {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : darkerOrLighter(color);
- }
-
- g2d.setColor(finalBorderColor);
- g2d.draw(body[0]);
- if (body[3] != null)
- g2d.draw(body[3]);
-
- if (!outlineMode) {
- g2d.setColor(getPoleColor());
- g2d.fill(body[2]);
- g2d.setColor(darkerOrLighter(getPoleColor()));
- g2d.draw(body[2]);
- }
-
- drawMainLabel(g2d, project, outlineMode, componentState);
-
- drawTerminalLabels(g2d, finalBorderColor, project);
- }
-
- @Override
- protected int getMainLabelYOffset() {
- if (getPolePieceType() == PolePieceType.RailHumbucker || getPolePieceType() == PolePieceType.RodHumbucker || getPolePieceType() == PolePieceType.None)
- return 0;
- return (int) (WIDTH.convertToPixels() / 2 - 20);
- }
-
- @SuppressWarnings("incomplete-switch")
- @Override
- public Shape[] getBody() {
- if (body == null) {
- body = new Shape[5];
-
- Point2D[] points = getControlPoints();
- double x = (points[0].getX() + points[3].getX()) / 2;
- double y = (points[0].getY() + points[3].getY()) / 2;;
- int width = (int) WIDTH.convertToPixels();
- int length = (int) LENGTH.convertToPixels();
- int stratInnerLength = (int) STRAT_INNER_LENGTH.convertToPixels();
- int teleLength = (int) TELE_LENGTH.convertToPixels();
- int teleBaseWidth = (int) TELE_BASE_WIDTH.convertToPixels();
- int teleLipLength = getClosestOdd(TELE_LIP_LENGTH.convertToPixels());
- int teleHoleSpacing = (int) TELE_HOLE_SPACING.convertToPixels();
- int coilLength = getType() == SingleCoilType.Stratocaster ? stratInnerLength : teleLength;
- int lipWidth = (int) STRAT_LIP_WIDTH.convertToPixels();
- int lipLength = (int) STRAT_LIP_LENGTH.convertToPixels();
- int lugDiameter = getClosestOdd(LUG_DIAMETER.convertToPixels());
- int holeSize = getClosestOdd(HOLE_SIZE.convertToPixels());
- int holeMargin = getClosestOdd(HOLE_MARGIN.convertToPixels());
- int baseRadius = (int) BASE_RADIUS.convertToPixels();
- int coilOffset = 0;
-
- if (getType() == SingleCoilType.Stratocaster) {
- coilOffset = lipWidth / 2;
-
- Area mainArea =
- new Area(new RoundRectangle2D.Double(x - length / 2, y - lipWidth / 2 - width, length, width, width, width));
- // Cutout holes
- mainArea.subtract(new Area(new Ellipse2D.Double(x - length / 2 + holeMargin - holeSize / 2, y - lipWidth / 2
- - width / 2 - holeSize / 2, holeSize, holeSize)));
- mainArea.subtract(new Area(new Ellipse2D.Double(x + length / 2 - holeMargin - holeSize / 2, y - lipWidth / 2
- - width / 2 - holeSize / 2, holeSize, holeSize)));
-
- body[3] = mainArea;
- RoundedPath basePath = new RoundedPath(baseRadius);
- basePath.moveTo(x, y + lipWidth / 2);
- basePath.lineTo(x + lipLength / 2, y + lipWidth / 2);
- basePath.lineTo(x + length / 2, y - lipWidth);
- basePath.lineTo(x - length / 2, y - lipWidth);
- basePath.lineTo(x - lipLength / 2, y + lipWidth / 2);
- basePath.lineTo(x, y + lipWidth / 2);
-
- Area base = new Area(basePath.getPath());
- base.subtract(mainArea);
-
- body[4] = base;
- } else if (getType() == SingleCoilType.Telecaster) {
- coilOffset = (teleBaseWidth - width) / 4;
-
- RoundedPath basePath = new RoundedPath(baseRadius);
- basePath.moveTo(x, y + coilOffset);
- basePath.lineTo(x + teleLipLength / 2, y + coilOffset);
- basePath.lineTo(x + coilLength * 0.53, y - coilOffset - width / 2);
- basePath.lineTo(x + coilLength / 2 - width * 0.45, y - coilOffset - width);
- basePath.lineTo(x, y - 3 * coilOffset - width);
- basePath.lineTo(x - coilLength / 2 + width * 0.45, y - coilOffset - width);
- basePath.lineTo(x - coilLength * 0.53, y - coilOffset - width / 2);
- basePath.lineTo(x - teleLipLength / 2, y + coilOffset);
- basePath.lineTo(x, y + coilOffset);
-
- Area base = new Area(basePath.getPath());
- base.intersect(new Area(new Rectangle2D.Double(x - coilLength * 0.48, y - teleBaseWidth, coilLength * 0.96,
- teleBaseWidth * 2)));
-
- // Cutout holes
- base.subtract(new Area(new Ellipse2D.Double(x - teleLipLength / 2 - holeSize / 2, y, holeSize, holeSize)));
- base.subtract(new Area(new Ellipse2D.Double(x + teleLipLength / 2 - holeSize / 2, y, holeSize, holeSize)));
- base.subtract(new Area(new Ellipse2D.Double(x - holeSize / 2, y - teleHoleSpacing, holeSize, holeSize)));
-
- body[4] = base;
- }
-
- Area poleArea = new Area();
- if (getPolePieceType() == PolePieceType.Rods) {
- int poleSize = (int) POLE_SIZE.convertToPixels();
- int poleSpacing = (int) POLE_SPACING.convertToPixels();
- int poleMargin = (length - poleSpacing * 5) / 2;
- for (int i = 0; i < 6; i++) {
- Ellipse2D pole =
- new Ellipse2D.Double(x - length / 2 + poleMargin + i * poleSpacing - poleSize / 2, y - coilOffset - width
- / 2 - poleSize / 2, poleSize, poleSize);
- poleArea.add(new Area(pole));
- }
- } else if (getPolePieceType() == PolePieceType.RodHumbucker) {
- int poleSize = (int) POLE_SIZE.convertToPixels() / 2;
- int poleSpacing = (int) POLE_SPACING.convertToPixels();
- int poleMargin = (length - poleSpacing * 5) / 2;
- int coilSpacing = (int) COIL_SPACING.convertToPixels();
- for (int i = 0; i < 6; i++) {
- poleArea.add(new Area(new Ellipse2D.Double(x - length / 2 + poleMargin + i * poleSpacing - poleSize / 2, y
- - coilOffset - width / 2 - poleSize / 2 - coilSpacing / 2, poleSize, poleSize)));
- poleArea.add(new Area(new Ellipse2D.Double(x - length / 2 + poleMargin + i * poleSpacing - poleSize / 2, y
- - coilOffset - width / 2 - poleSize / 2 + coilSpacing / 2, poleSize, poleSize)));
- }
- } else if (getPolePieceType() == PolePieceType.RailHumbucker) {
- int railWidth = (int) RAIL_WIDTH.convertToPixels();
- int railSpacing = (int) COIL_SPACING.convertToPixels();
- int railLength = (int) RAIL_LENGTH.convertToPixels();
- poleArea.add(new Area(new Rectangle2D.Double(x - railLength / 2, y - coilOffset - width / 2 - railSpacing / 2
- - railWidth / 2, railLength, railWidth)));
- poleArea.add(new Area(new Rectangle2D.Double(x - railLength / 2, y - coilOffset - width / 2 + railSpacing / 2
- - railWidth / 2, railLength, railWidth)));
- } else if (getPolePieceType() == PolePieceType.Rail) {
- int railWidth = 2 * (int) RAIL_WIDTH.convertToPixels();
- int railLength = (int) RAIL_LENGTH.convertToPixels();
- poleArea.add(new Area(new RoundRectangle2D.Double(x - railLength / 2, y - coilOffset - width / 2 - railWidth
- / 2, railLength, railWidth, railWidth / 2, railWidth / 2)));
- }
-
- body[0] =
- new Area(new RoundRectangle2D.Double(x - coilLength / 2, y - coilOffset - width, coilLength, width, width,
- width));
-
- body[2] = poleArea;
-
- if (body[3] == null) {
- ((Area)body[4]).subtract((Area) body[0]);
- }
-
- // Rotate if needed
- if (orientation != Orientation.DEFAULT) {
- double theta = 0;
- switch (orientation) {
- case _90:
- theta = Math.PI / 2;
- break;
- case _180:
- theta = Math.PI;
- break;
- case _270:
- theta = Math.PI * 3 / 2;
- break;
- }
- AffineTransform rotation = AffineTransform.getRotateInstance(theta, x, y);
- for (Shape shape : body) {
- Area area = (Area) shape;
- if (area != null)
- area.transform(rotation);
- }
- }
-
- body[1] = new Area();
- double lugHole = getClosestOdd(lugDiameter * 0.4);
- for (int i = getPolarity() == Polarity.Humbucking ? 0 : 1; i < (getPolarity() == Polarity.Humbucking ? 4 : 3); i++) {
- Point2D p = points[i];
- ((Area)body[1]).add(new Area(new Ellipse2D.Double(p.getX() - lugDiameter / 2, p.getY() - lugDiameter / 2, lugDiameter, lugDiameter)));
- ((Area)body[1]).subtract(new Area(new Ellipse2D.Double(p.getX() - lugHole / 2, p.getY() - lugHole / 2, lugHole, lugHole)));
- }
- }
- return body;
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- g2d.rotate(Math.PI / 4, width / 2, height / 2);
-
- int bodyWidth = 8 * width / 32;
- int bodyLength = 30 * width / 32;
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f));
- g2d.setColor(BASE_COLOR);
- g2d.fillPolygon(new int[] {width * 9 / 16, width * 9 / 16, width * 11 / 16, width * 11 / 16}, new int[] {
- (height - bodyLength) / 2, (height + bodyLength) / 2, height * 5 / 8, height * 3 / 8}, 4);
- g2d.setColor(BODY_COLOR);
- g2d.fillRoundRect((width - bodyWidth) / 2, (height - bodyLength) / 2, bodyWidth, bodyLength, bodyWidth, bodyWidth);
-
- g2d.setColor(Color.gray);
- g2d.drawRoundRect((width - bodyWidth) / 2, (height - bodyLength) / 2, bodyWidth, bodyLength, bodyWidth, bodyWidth);
-
- // g2d.setColor(Color.gray);
- // g2d.drawLine(width / 2, 4 * width / 32, width / 2, 4 * width / 32);
- // g2d.drawLine(width / 2, height - 4 * width / 32, width / 2, height - 4 * width / 32);
-
- g2d.setColor(METAL_COLOR);
- int poleSize = 2;
- int poleSpacing = 17 * width / 32;
- for (int i = 0; i < 6; i++) {
- g2d.fillOval((width - poleSize) / 2, (height - poleSpacing) / 2 + (i * poleSpacing / 5), poleSize, poleSize);
- }
- }
-
- @EditableProperty
- public SingleCoilType getType() {
- if (type == null)
- type = SingleCoilType.Stratocaster;
- return type;
- }
-
- public void setType(SingleCoilType type) {
- this.type = type;
- // Invalidate the body
- body = null;
- }
-
- @EditableProperty(name = "Pole Pieces")
- public PolePieceType getPolePieceType() {
- if (polePieceType == null)
- polePieceType = PolePieceType.Rods;
- return polePieceType;
- }
-
- public void setPolePieceType(PolePieceType polePieceType) {
- this.polePieceType = polePieceType;
- // Invalidate the body
- body = null;
- }
-
- @EditableProperty
- public Color getColor() {
- return color;
- }
-
- public void setColor(Color color) {
- this.color = color;
- }
-
- @EditableProperty(name = "Base")
- public Color getBaseColor() {
- if (baseColor == null)
- baseColor = BASE_COLOR;
- return baseColor;
- }
-
- public void setBaseColor(Color baseColor) {
- this.baseColor = baseColor;
- }
-
- @EditableProperty(name = "Pole Color")
- public Color getPoleColor() {
- if (poleColor == null)
- poleColor = METAL_COLOR;
- return poleColor;
- }
-
- public void setPoleColor(Color poleColor) {
- this.poleColor = poleColor;
- }
-
- @EditableProperty(name = "Lugs")
- public Color getLugColor() {
- if (lugColor == null) {
- lugColor = LUG_COLOR;
- }
- return lugColor;
- }
-
- public void setLugColor(Color lugColor) {
- this.lugColor = lugColor;
- }
-
- public enum SingleCoilType {
- Stratocaster, Telecaster;
- }
-
- public enum PolePieceType {
- Rods("Single Rods"), Rail("Single Rail"), RodHumbucker("Double Rods"), RailHumbucker("Double Rails"), None("None");
-
- private String label;
-
- private PolePieceType(String label) {
- this.label = label;
- }
-
- @Override
- public String toString() {
- return label;
- }
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.guitar;
+
+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.Area;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.common.IPlugInPort;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.Orientation;
+import org.diylc.common.OrientationHV;
+import org.diylc.components.RoundedPath;
+import org.diylc.components.transform.GuitarPickupTransformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+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;
+import org.diylc.utils.Constants;
+
+@ComponentDescriptor(name = "Single Coil Pickup", category = "Guitar", author = "Branislav Stojkovic",
+ description = "Single coil guitar pickup, both Strat and Tele style",
+ zOrder = IDIYComponent.COMPONENT, instanceNamePrefix = "PKP",
+ keywordPolicy = KeywordPolicy.SHOW_TAG, keywordTag = "Guitar Wiring Diagram", enableCache = true,
+ transformer = GuitarPickupTransformer.class)
+public class SingleCoilPickup extends AbstractSingleOrHumbuckerPickup {
+
+ private static final long serialVersionUID = 1L;
+
+ private static Color BODY_COLOR = Color.white;
+ private static Color BASE_COLOR = Color.gray;
+ public static Color LUG_COLOR = Color.decode("#E0C04C");
+// private static Color POINT_COLOR = Color.lightGray;
+ private static Size WIDTH = new Size(15.5d, SizeUnit.mm);
+ private static Size LENGTH = new Size(83d, SizeUnit.mm);
+ private static Size BASE_RADIUS = new Size(0.15d, SizeUnit.in);
+ private static Size LUG_DIAMETER = new Size(0.06d, SizeUnit.in);
+
+ // strat-specific
+ private static Size STRAT_LIP_WIDTH = new Size(5d, SizeUnit.mm);
+ private static Size STRAT_LIP_LENGTH = new Size(20d, SizeUnit.mm);
+ private static Size STRAT_INNER_LENGTH = new Size(70d, SizeUnit.mm);
+
+ // tele-specific
+ private static Size TELE_BASE_WIDTH = new Size(1.5d, SizeUnit.in);
+ private static Size TELE_LIP_LENGTH = new Size(1.735d, SizeUnit.in);
+ private static Size TELE_LENGTH = new Size(2.87d, SizeUnit.in);
+ private static Size TELE_HOLE_SPACING = new Size(1.135d, SizeUnit.in);
+
+ private static Size HOLE_SIZE = new Size(2d, SizeUnit.mm);
+ private static Size HOLE_MARGIN = new Size(4d, SizeUnit.mm);
+ private static Size POLE_SIZE = new Size(4d, SizeUnit.mm);
+ private static Size POLE_SPACING = new Size(11.68d, SizeUnit.mm);
+
+ private static Size RAIL_WIDTH = new Size(1.5d, SizeUnit.mm);
+ private static Size RAIL_LENGTH = new Size(60d, SizeUnit.mm);
+ private static Size COIL_SPACING = new Size(7.5d, SizeUnit.mm);
+
+ private Color color = BODY_COLOR;
+ private Color poleColor = METAL_COLOR;
+ private Color baseColor = BASE_COLOR;
+ private SingleCoilType type = SingleCoilType.Stratocaster;
+ private PolePieceType polePieceType = PolePieceType.Rods;
+ private Color lugColor = LUG_COLOR;
+
+ @Override
+ protected OrientationHV getControlPointDirection() {
+ return OrientationHV.HORIZONTAL;
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ Shape[] body = getBody();
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+
+ Composite oldComposite = applyAlpha(g2d, componentState);
+
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getBaseColor());
+ g2d.fill(body[4]);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getColor());
+ if (body[3] == null)
+ g2d.fill(body[0]);
+ else
+ g2d.fill(body[3]);
+
+ drawingObserver.stopTracking();
+
+ markContactPoints(g2d, drawingObserver);
+
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getLugColor());
+ g2d.fill(body[1]);
+ g2d.setColor(outlineMode ? theme.getOutlineColor() : darkerOrLighter(LUG_COLOR));
+ g2d.draw(body[1]);
+
+ // g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : color);
+ // g2d.fill(body[3]);
+ g2d.setComposite(oldComposite);
+
+ Color finalBorderColor;
+ if (outlineMode) {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : darkerOrLighter(getBaseColor());
+ }
+
+ g2d.setColor(finalBorderColor);
+ g2d.draw(body[4]);
+
+ if (outlineMode) {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : darkerOrLighter(color);
+ }
+
+ g2d.setColor(finalBorderColor);
+ g2d.draw(body[0]);
+ if (body[3] != null)
+ g2d.draw(body[3]);
+
+ if (!outlineMode) {
+ g2d.setColor(getPoleColor());
+ g2d.fill(body[2]);
+ g2d.setColor(darkerOrLighter(getPoleColor()));
+ g2d.draw(body[2]);
+ }
+
+ drawMainLabel(g2d, project, outlineMode, componentState);
+
+ drawTerminalLabels(g2d, finalBorderColor, project);
+ }
+
+ @Override
+ protected int getMainLabelYOffset() {
+ if (getPolePieceType() == PolePieceType.RailHumbucker || getPolePieceType() == PolePieceType.RodHumbucker || getPolePieceType() == PolePieceType.None)
+ return 0;
+ return (int) (WIDTH.convertToPixels() / 2 - 20);
+ }
+
+ @SuppressWarnings("incomplete-switch")
+ @Override
+ public Shape[] getBody() {
+ if (body == null) {
+ body = new Shape[5];
+
+ Point2D[] points = getControlPoints();
+ double x = (points[0].getX() + points[3].getX()) / 2;
+ double y = (points[0].getY() + points[3].getY()) / 2;;
+ int width = (int) WIDTH.convertToPixels();
+ int length = (int) LENGTH.convertToPixels();
+ int stratInnerLength = (int) STRAT_INNER_LENGTH.convertToPixels();
+ int teleLength = (int) TELE_LENGTH.convertToPixels();
+ int teleBaseWidth = (int) TELE_BASE_WIDTH.convertToPixels();
+ int teleLipLength = getClosestOdd(TELE_LIP_LENGTH.convertToPixels());
+ int teleHoleSpacing = (int) TELE_HOLE_SPACING.convertToPixels();
+ int coilLength = getType() == SingleCoilType.Stratocaster ? stratInnerLength : teleLength;
+ int lipWidth = (int) STRAT_LIP_WIDTH.convertToPixels();
+ int lipLength = (int) STRAT_LIP_LENGTH.convertToPixels();
+ int lugDiameter = getClosestOdd(LUG_DIAMETER.convertToPixels());
+ int holeSize = getClosestOdd(HOLE_SIZE.convertToPixels());
+ int holeMargin = getClosestOdd(HOLE_MARGIN.convertToPixels());
+ int baseRadius = (int) BASE_RADIUS.convertToPixels();
+ int coilOffset = 0;
+
+ if (getType() == SingleCoilType.Stratocaster) {
+ coilOffset = lipWidth / 2;
+
+ Area mainArea =
+ new Area(new RoundRectangle2D.Double(x - length / 2, y - lipWidth / 2 - width, length, width, width, width));
+ // Cutout holes
+ mainArea.subtract(new Area(new Ellipse2D.Double(x - length / 2 + holeMargin - holeSize / 2, y - lipWidth / 2
+ - width / 2 - holeSize / 2, holeSize, holeSize)));
+ mainArea.subtract(new Area(new Ellipse2D.Double(x + length / 2 - holeMargin - holeSize / 2, y - lipWidth / 2
+ - width / 2 - holeSize / 2, holeSize, holeSize)));
+
+ body[3] = mainArea;
+ RoundedPath basePath = new RoundedPath(baseRadius);
+ basePath.moveTo(x, y + lipWidth / 2);
+ basePath.lineTo(x + lipLength / 2, y + lipWidth / 2);
+ basePath.lineTo(x + length / 2, y - lipWidth);
+ basePath.lineTo(x - length / 2, y - lipWidth);
+ basePath.lineTo(x - lipLength / 2, y + lipWidth / 2);
+ basePath.lineTo(x, y + lipWidth / 2);
+
+ Area base = new Area(basePath.getPath());
+ base.subtract(mainArea);
+
+ body[4] = base;
+ } else if (getType() == SingleCoilType.Telecaster) {
+ coilOffset = (teleBaseWidth - width) / 4;
+
+ RoundedPath basePath = new RoundedPath(baseRadius);
+ basePath.moveTo(x, y + coilOffset);
+ basePath.lineTo(x + teleLipLength / 2, y + coilOffset);
+ basePath.lineTo(x + coilLength * 0.53, y - coilOffset - width / 2);
+ basePath.lineTo(x + coilLength / 2 - width * 0.45, y - coilOffset - width);
+ basePath.lineTo(x, y - 3 * coilOffset - width);
+ basePath.lineTo(x - coilLength / 2 + width * 0.45, y - coilOffset - width);
+ basePath.lineTo(x - coilLength * 0.53, y - coilOffset - width / 2);
+ basePath.lineTo(x - teleLipLength / 2, y + coilOffset);
+ basePath.lineTo(x, y + coilOffset);
+
+ Area base = new Area(basePath.getPath());
+ base.intersect(new Area(new Rectangle2D.Double(x - coilLength * 0.48, y - teleBaseWidth, coilLength * 0.96,
+ teleBaseWidth * 2)));
+
+ // Cutout holes
+ base.subtract(new Area(new Ellipse2D.Double(x - teleLipLength / 2 - holeSize / 2, y, holeSize, holeSize)));
+ base.subtract(new Area(new Ellipse2D.Double(x + teleLipLength / 2 - holeSize / 2, y, holeSize, holeSize)));
+ base.subtract(new Area(new Ellipse2D.Double(x - holeSize / 2, y - teleHoleSpacing, holeSize, holeSize)));
+
+ body[4] = base;
+ }
+
+ Area poleArea = new Area();
+ if (getPolePieceType() == PolePieceType.Rods) {
+ int poleSize = (int) POLE_SIZE.convertToPixels();
+ int poleSpacing = (int) POLE_SPACING.convertToPixels();
+ int poleMargin = (length - poleSpacing * 5) / 2;
+ for (int i = 0; i < 6; i++) {
+ Ellipse2D pole =
+ new Ellipse2D.Double(x - length / 2 + poleMargin + i * poleSpacing - poleSize / 2, y - coilOffset - width
+ / 2 - poleSize / 2, poleSize, poleSize);
+ poleArea.add(new Area(pole));
+ }
+ } else if (getPolePieceType() == PolePieceType.RodHumbucker) {
+ int poleSize = (int) POLE_SIZE.convertToPixels() / 2;
+ int poleSpacing = (int) POLE_SPACING.convertToPixels();
+ int poleMargin = (length - poleSpacing * 5) / 2;
+ int coilSpacing = (int) COIL_SPACING.convertToPixels();
+ for (int i = 0; i < 6; i++) {
+ poleArea.add(new Area(new Ellipse2D.Double(x - length / 2 + poleMargin + i * poleSpacing - poleSize / 2, y
+ - coilOffset - width / 2 - poleSize / 2 - coilSpacing / 2, poleSize, poleSize)));
+ poleArea.add(new Area(new Ellipse2D.Double(x - length / 2 + poleMargin + i * poleSpacing - poleSize / 2, y
+ - coilOffset - width / 2 - poleSize / 2 + coilSpacing / 2, poleSize, poleSize)));
+ }
+ } else if (getPolePieceType() == PolePieceType.RailHumbucker) {
+ int railWidth = (int) RAIL_WIDTH.convertToPixels();
+ int railSpacing = (int) COIL_SPACING.convertToPixels();
+ int railLength = (int) RAIL_LENGTH.convertToPixels();
+ poleArea.add(new Area(new Rectangle2D.Double(x - railLength / 2, y - coilOffset - width / 2 - railSpacing / 2
+ - railWidth / 2, railLength, railWidth)));
+ poleArea.add(new Area(new Rectangle2D.Double(x - railLength / 2, y - coilOffset - width / 2 + railSpacing / 2
+ - railWidth / 2, railLength, railWidth)));
+ } else if (getPolePieceType() == PolePieceType.Rail) {
+ int railWidth = 2 * (int) RAIL_WIDTH.convertToPixels();
+ int railLength = (int) RAIL_LENGTH.convertToPixels();
+ poleArea.add(new Area(new RoundRectangle2D.Double(x - railLength / 2, y - coilOffset - width / 2 - railWidth
+ / 2, railLength, railWidth, railWidth / 2, railWidth / 2)));
+ }
+
+ body[0] =
+ new Area(new RoundRectangle2D.Double(x - coilLength / 2, y - coilOffset - width, coilLength, width, width,
+ width));
+
+ body[2] = poleArea;
+
+ if (body[3] == null) {
+ ((Area)body[4]).subtract((Area) body[0]);
+ }
+
+ // Rotate if needed
+ if (orientation != Orientation.DEFAULT) {
+ double theta = 0;
+ switch (orientation) {
+ case _90:
+ theta = Math.PI / 2;
+ break;
+ case _180:
+ theta = Math.PI;
+ break;
+ case _270:
+ theta = Math.PI * 3 / 2;
+ break;
+ }
+ AffineTransform rotation = AffineTransform.getRotateInstance(theta, x, y);
+ for (Shape shape : body) {
+ Area area = (Area) shape;
+ if (area != null)
+ area.transform(rotation);
+ }
+ }
+
+ body[1] = new Area();
+ double lugHole = getClosestOdd(lugDiameter * 0.4);
+ for (int i = getPolarity() == Polarity.Humbucking ? 0 : 1; i < (getPolarity() == Polarity.Humbucking ? 4 : 3); i++) {
+ Point2D p = points[i];
+ ((Area)body[1]).add(new Area(new Ellipse2D.Double(p.getX() - lugDiameter / 2, p.getY() - lugDiameter / 2, lugDiameter, lugDiameter)));
+ ((Area)body[1]).subtract(new Area(new Ellipse2D.Double(p.getX() - lugHole / 2, p.getY() - lugHole / 2, lugHole, lugHole)));
+ }
+ }
+ return body;
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ g2d.rotate(Math.PI / 4, width / 2, height / 2);
+
+ int bodyWidth = 8 * width / 32;
+ int bodyLength = 30 * width / 32;
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f));
+ g2d.setColor(BASE_COLOR);
+ g2d.fillPolygon(new int[] {width * 9 / 16, width * 9 / 16, width * 11 / 16, width * 11 / 16}, new int[] {
+ (height - bodyLength) / 2, (height + bodyLength) / 2, height * 5 / 8, height * 3 / 8}, 4);
+ g2d.setColor(BODY_COLOR);
+ g2d.fillRoundRect((width - bodyWidth) / 2, (height - bodyLength) / 2, bodyWidth, bodyLength, bodyWidth, bodyWidth);
+
+ g2d.setColor(Color.gray);
+ g2d.drawRoundRect((width - bodyWidth) / 2, (height - bodyLength) / 2, bodyWidth, bodyLength, bodyWidth, bodyWidth);
+
+ // g2d.setColor(Color.gray);
+ // g2d.drawLine(width / 2, 4 * width / 32, width / 2, 4 * width / 32);
+ // g2d.drawLine(width / 2, height - 4 * width / 32, width / 2, height - 4 * width / 32);
+
+ g2d.setColor(METAL_COLOR);
+ int poleSize = 2;
+ int poleSpacing = 17 * width / 32;
+ for (int i = 0; i < 6; i++) {
+ g2d.fillOval((width - poleSize) / 2, (height - poleSpacing) / 2 + (i * poleSpacing / 5), poleSize, poleSize);
+ }
+ }
+
+ @EditableProperty
+ public SingleCoilType getType() {
+ if (type == null)
+ type = SingleCoilType.Stratocaster;
+ return type;
+ }
+
+ public void setType(SingleCoilType type) {
+ this.type = type;
+ // Invalidate the body
+ body = null;
+ }
+
+ @EditableProperty(name = "Pole Pieces")
+ public PolePieceType getPolePieceType() {
+ if (polePieceType == null)
+ polePieceType = PolePieceType.Rods;
+ return polePieceType;
+ }
+
+ public void setPolePieceType(PolePieceType polePieceType) {
+ this.polePieceType = polePieceType;
+ // Invalidate the body
+ body = null;
+ }
+
+ @EditableProperty
+ public Color getColor() {
+ return color;
+ }
+
+ public void setColor(Color color) {
+ this.color = color;
+ }
+
+ @EditableProperty(name = "Base")
+ public Color getBaseColor() {
+ if (baseColor == null)
+ baseColor = BASE_COLOR;
+ return baseColor;
+ }
+
+ public void setBaseColor(Color baseColor) {
+ this.baseColor = baseColor;
+ }
+
+ @EditableProperty(name = "Pole Color")
+ public Color getPoleColor() {
+ if (poleColor == null)
+ poleColor = METAL_COLOR;
+ return poleColor;
+ }
+
+ public void setPoleColor(Color poleColor) {
+ this.poleColor = poleColor;
+ }
+
+ @EditableProperty(name = "Lugs")
+ public Color getLugColor() {
+ if (lugColor == null) {
+ lugColor = LUG_COLOR;
+ }
+ return lugColor;
+ }
+
+ public void setLugColor(Color lugColor) {
+ this.lugColor = lugColor;
+ }
+
+ public enum SingleCoilType {
+ Stratocaster, Telecaster;
+ }
+
+ public enum PolePieceType {
+ Rods("Single Rods"), Rail("Single Rail"), RodHumbucker("Double Rods"), RailHumbucker("Double Rails"), None("None");
+
+ private String label;
+
+ private PolePieceType(String label) {
+ this.label = label;
+ }
+
+ @Override
+ public String toString() {
+ return label;
+ }
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/StingrayBassPickup.java b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/StingrayBassPickup.java
index 8b4442fe9..ed11263ef 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/StingrayBassPickup.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/StingrayBassPickup.java
@@ -82,11 +82,7 @@ import java.awt.geom.*;
Shape[] body = getBody();
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
- Composite oldComposite = g2d.getComposite();
-
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : color);
g2d.fill(body[0]);
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/misc/Image.java b/diylc/diylc-library/src/main/java/org/diylc/components/misc/Image.java
index 540432439..318f307c9 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/misc/Image.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/misc/Image.java
@@ -128,10 +128,7 @@ public class Image extends AbstractTransparentComponent {
.getIconHeight() * scaleY))) {
return;
}
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
double x;
double y;
@@ -242,7 +239,7 @@ public class Image extends AbstractTransparentComponent {
}
}
- @PercentEditor(_100PercentValue = 25)
+ @PercentEditor(minValue = 1, maxValue = 1000)
@EditableProperty(defaultable = false)
public byte getScale() {
if (scale != null) {
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/misc/Loadline.java b/diylc/diylc-library/src/main/java/org/diylc/components/misc/Loadline.java
index 60abcbd9f..0eb3196cc 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/misc/Loadline.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/misc/Loadline.java
@@ -72,11 +72,7 @@ public class Loadline extends AbstractBoard {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
if (componentState != ComponentState.DRAGGING) {
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(
- AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(boardColor);
g2d.fillRect((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(finalSecondPoint.getX() - firstPoint.getX()),
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/misc/SVGImage.java b/diylc/diylc-library/src/main/java/org/diylc/components/misc/SVGImage.java
index 394587a66..f8d9a8ed6 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/misc/SVGImage.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/misc/SVGImage.java
@@ -107,10 +107,7 @@ public class SVGImage extends AbstractTransparentComponent {
svgDiagram.getWidth() * scaleX, svgDiagram.getHeight() * scaleY))) {
return;
}
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
double x;
double y;
@@ -229,7 +226,7 @@ public class SVGImage extends AbstractTransparentComponent {
this.svgDiagram = null;
}
- @PercentEditor(_100PercentValue = 25)
+ @PercentEditor(minValue = 0, maxValue = 1000)
@EditableProperty(defaultable = false)
public byte getScale() {
if (scale != null) {
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/passive/AudioTransformer.java b/diylc/diylc-library/src/main/java/org/diylc/components/passive/AudioTransformer.java
index c1229b839..ac51c89cb 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/passive/AudioTransformer.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/passive/AudioTransformer.java
@@ -1,531 +1,528 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.passive;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.FontMetrics;
-import java.awt.Graphics2D;
-import java.awt.Rectangle;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Area;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.geom.RoundRectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.awt.StringUtils;
-import org.diylc.common.Display;
-import org.diylc.common.HorizontalAlignment;
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.Orientation;
-import org.diylc.common.VerticalAlignment;
-import org.diylc.components.AbstractMultiPartComponent;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-import org.diylc.core.VisibilityPolicy;
-import org.diylc.core.annotations.ComponentDescriptor;
-import org.diylc.core.annotations.EditableProperty;
-import org.diylc.core.annotations.KeywordPolicy;
-import org.diylc.core.annotations.PositiveNonZeroMeasureValidator;
-import org.diylc.core.gerber.IGerberComponentSimple;
-import org.diylc.core.measures.Size;
-import org.diylc.core.measures.SizeUnit;
-import org.diylc.utils.Constants;
-
-@ComponentDescriptor(name = "Mini Signal Transformer", author = "Branislav Stojkovic", category = "Passive",
- instanceNamePrefix = "TR", description = "Miniature PCB-mount signal transformer with EI core",
- zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_VALUE)
-public class AudioTransformer extends AbstractMultiPartComponent implements IGerberComponentSimple {
-
- private static final long serialVersionUID = 1L;
-
- public static Color CORE_COLOR = METAL_COLOR;
- public static Color CORE_BORDER_COLOR = CORE_COLOR.darker();
- public static Color COIL_COLOR = Color.decode("#DDDDDD");
- public static Color COIL_BORDER_COLOR = COIL_COLOR.darker();
- public static Color PIN_COLOR = Color.decode("#00B2EE");
- public static Color PIN_BORDER_COLOR = PIN_COLOR.darker();
- public static Color LABEL_COLOR = Color.white;
- public static int EDGE_RADIUS = 6;
- public static Size PIN_SIZE = new Size(0.03d, SizeUnit.in);
-
- private String value = "";
- private Orientation orientation = Orientation.DEFAULT;
- private Size leadSpacing = new Size(0.1d, SizeUnit.in);
- private Size windingSpacing = new Size(0.5d, SizeUnit.in);
- private Size coreThickness = new Size(0.15d, SizeUnit.in);
- private Size coreWidth = new Size(0.6, SizeUnit.in);
- private Size coilWidth = new Size(0.5, SizeUnit.in);
- private Size coilLength = new Size(0.6, SizeUnit.in);
- private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0)};
- protected Display display = Display.BOTH;
- private Color coreColor = CORE_COLOR;
- private Color coreBorderColor = CORE_BORDER_COLOR;
- private Color coilColor = COIL_COLOR;
- private Color coilBorderColor = COIL_BORDER_COLOR;
- private Color labelColor = LABEL_COLOR;
- private boolean primaryCT = true;
- private boolean secondaryCT = true;
-
- transient private Area[] body;
-
- public AudioTransformer() {
- super();
- updateControlPoints();
- alpha = 100;
- }
-
- @EditableProperty
- public String getValue() {
- return value;
- }
-
- public void setValue(String value) {
- this.value = value;
- }
-
- @EditableProperty
- public Orientation getOrientation() {
- return orientation;
- }
-
- public void setOrientation(Orientation orientation) {
- this.orientation = orientation;
- updateControlPoints();
- // Reset body shape.
- body = null;
- }
-
- @EditableProperty(name = "Lead Spacing", validatorClass = PositiveNonZeroMeasureValidator.class)
- public Size getLeadSpacing() {
- return leadSpacing;
- }
-
- public void setLeadSpacing(Size leadSpacing) {
- this.leadSpacing = leadSpacing;
- updateControlPoints();
- // Reset body shape;
- body = null;
- }
-
- @EditableProperty(name = "Winding Spacing", validatorClass = PositiveNonZeroMeasureValidator.class)
- public Size getWindingSpacing() {
- return windingSpacing;
- }
-
- public void setWindingSpacing(Size rowSpacing) {
- this.windingSpacing = rowSpacing;
- updateControlPoints();
- // Reset body shape;
- body = null;
- }
-
- @EditableProperty
- public Display getDisplay() {
- if (display == null) {
- display = Display.VALUE;
- }
- return display;
- }
-
- public void setDisplay(Display display) {
- this.display = display;
- }
-
- @Override
- public int getControlPointCount() {
- return controlPoints.length;
- }
-
- @Override
- public Point2D getControlPoint(int index) {
- return controlPoints[index];
- }
-
- @Override
- public boolean isControlPointSticky(int index) {
- return true;
- }
-
- @Override
- public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
- return VisibilityPolicy.NEVER;
- }
-
- @Override
- public void setControlPoint(Point2D point, int index) {
- controlPoints[index].setLocation(point);
- body = null;
- }
-
- private void updateControlPoints() {
- Point2D firstPoint = controlPoints[0];
- int pinCount = 4 + (primaryCT ? 1 : 0) + (secondaryCT ? 1 : 0);
- controlPoints = new Point2D[pinCount];
- controlPoints[0] = firstPoint;
- double leadSpacing = this.leadSpacing.convertToPixels();
- double windingSpacing = this.windingSpacing.convertToPixels();
-
- // Update control points.
- for (int i = 1; i < 2 + (primaryCT ? 1 : 0); i++)
- controlPoints[i] = new Point2D.Double(firstPoint.getX(), firstPoint.getY() + i * leadSpacing * (primaryCT ? 1 : 2));
- for (int i = 0; i < 2 + (secondaryCT ? 1 : 0); i++)
- controlPoints[2 + (primaryCT ? 1 : 0) + i] = new Point2D.Double(firstPoint.getX() + windingSpacing, firstPoint.getY() + i * leadSpacing * (secondaryCT ? 1 : 2));
-
- AffineTransform tx = getTx();
-
- if (tx != null) {
- for (int i = 1; i < controlPoints.length; i++) {
- tx.transform(controlPoints[i], controlPoints[i]);
- }
- }
- }
-
- @Override
- public Area[] getBody() {
- if (body == null) {
- 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);
- int coreWidth = getClosestOdd(this.coreWidth.convertToPixels());
- int coreThickness = getClosestOdd(this.coreThickness.convertToPixels());
- int coilWidth = getClosestOdd(this.coilWidth.convertToPixels());
- int coilLength = getClosestOdd(this.coilLength.convertToPixels());
-
- body[0] = new Area(new Rectangle2D.Double(centerX - coreThickness / 2, centerY - coreWidth / 2, coreThickness, coreWidth));
- body[1] = new Area(new RoundRectangle2D.Double(centerX - coilLength / 2, centerY - coilWidth / 2, coilLength, coilWidth, coilWidth / 3, coilWidth / 3));
- body[1].subtract(body[0]);
-
- AffineTransform tx = getTx();
- if (tx != null)
- for (Area b : body) {
- if (b != null)
- b.transform(tx);
- }
- }
- return body;
- }
-
- @SuppressWarnings("incomplete-switch")
- private AffineTransform getTx() {
- double x = controlPoints[0].getX();
- double y = controlPoints[0].getY();
- if (orientation == Orientation.DEFAULT)
- return null;
-
- double theta = 0;
- switch (orientation) {
- case _90:
- theta = Math.PI / 2;
- break;
- case _180:
- theta = Math.PI;
- break;
- case _270:
- theta = Math.PI * 3 / 2;
- break;
- }
- AffineTransform rotation = AffineTransform.getRotateInstance(theta, x, y);
-
- return rotation;
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- if (checkPointsClipped(g2d.getClip())) {
- return;
- }
- Area[] body = getBody();
- Area coreArea = body[0];
- Area coilArea = body[1];
-
- if (!outlineMode) {
- 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.setColor(PIN_BORDER_COLOR);
- g2d.drawOval((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize);
- }
- }
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
-
- // render coil
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getCoilColor());
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
- g2d.fill(coilArea);
- Color finalBorderColor;
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalBorderColor = theme.getOutlineColor();
- } else {
- finalBorderColor = getCoilBorderColor();
- }
- g2d.setColor(finalBorderColor);
- g2d.draw(coilArea);
-
- // render core
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getCoreColor());
- g2d.fill(coreArea);
- g2d.setComposite(oldComposite);
-
- if (!outlineMode)
- finalBorderColor = getCoreBorderColor();
-
- g2d.setColor(finalBorderColor);
- g2d.draw(coreArea);
-
- drawingObserver.stopTracking();
-
- g2d.setFont(project.getFont());
-
- // Override font size
- if (getFontSizeOverride() != null)
- g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride()));
-
- // Draw winding designations
- Point2D wPoint = new Point2D.Double((int) (controlPoints[0].getX() + project.getFontSize()), (int) (controlPoints[0].getY() + leadSpacing.convertToPixels()));
- AffineTransform tx = getTx();
- if (tx != null)
- tx.transform(wPoint, wPoint);
- StringUtils.drawCenteredText(g2d, "P", wPoint.getX(), wPoint.getY(), HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
- wPoint = new Point2D.Double((int) (controlPoints[0].getX() + windingSpacing.convertToPixels() - project.getFontSize()), (int) (controlPoints[0].getY() + leadSpacing.convertToPixels()));
- if (tx != null)
- tx.transform(wPoint, wPoint);
- StringUtils.drawCenteredText(g2d, "S", wPoint.getX(), wPoint.getY(), HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
-
- // Draw label.
- Color finalLabelColor;
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : theme.getOutlineColor();
- } else {
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : getLabelColor();
- }
- g2d.setColor(finalLabelColor);
- FontMetrics fontMetrics = g2d.getFontMetrics(g2d.getFont());
- String[] label = null;
-
- if (getDisplay() == Display.NAME) {
- label = new String[] {getName()};
- } else if (getDisplay() == Display.VALUE) {
- label = new String[] {getValue().toString()};
- } else if (getDisplay() == Display.BOTH) {
- String value = getValue().toString();
- label = value.isEmpty() ? new String[] {getName()} : new String[] {getName(), value};
- }
-
- if (label != null) {
- for (int i = 0; i < label.length; i++) {
- String l = label[i];
- Rectangle2D rect = fontMetrics.getStringBounds(l, g2d);
- int textHeight = (int) (rect.getHeight());
- int textWidth = (int) (rect.getWidth());
- // Center text horizontally and vertically
- Rectangle bounds = coreArea.getBounds();
- double x = bounds.getX() + (bounds.width - textWidth) / 2;
- double y = bounds.getY() + (bounds.height - textHeight) / 2 + fontMetrics.getAscent();
-
- AffineTransform oldTransform = g2d.getTransform();
-
- if (getOrientation() == Orientation.DEFAULT || getOrientation() == Orientation._180) {
- double centerX = bounds.getX() + bounds.width / 2;
- double centerY = bounds.getY() + bounds.height / 2;
- g2d.rotate(-Math.PI / 2, centerX, centerY);
- }
-
- if (label.length == 2) {
- if (i == 0)
- g2d.translate(0, -textHeight / 2);
- else if (i == 1)
- g2d.translate(0, textHeight / 2);
- }
-
- g2d.drawString(l, (int)x, (int)y);
-
- g2d.setTransform(oldTransform);
- }
- }
-
- drawSelectionOutline(g2d, componentState, outlineMode, project, drawingObserver);
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int radius = (int) (12f * width / 32);
- g2d.setColor(COIL_COLOR);
- g2d.fillRoundRect(1, (int) (height / 8f), width - 2, (int) (height * 6 / 8f), radius, radius);
- g2d.setColor(COIL_BORDER_COLOR);
- g2d.drawRoundRect(1, (int) (height / 8f), width - 2, (int) (height * 6 / 8f), radius, radius);
-
- g2d.setColor(CORE_COLOR);
- g2d.fillRect(width * 3 / 8, 1, width / 4, height - 2);
- g2d.setColor(CORE_BORDER_COLOR);
- g2d.drawRect(width * 3 / 8, 1, width / 4, height - 2);
-
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
-
- int pinSize = (int) (2f * width / 32);
- g2d.setColor(PIN_COLOR);
- for (int i = 0; i < 3; i++) {
- g2d.fillOval(width / 5 - pinSize + 1, (height / 6) * (i + 2), pinSize, pinSize);
- g2d.fillOval(4 * width / 5 + 1, (height / 6) * (i + 2), pinSize, pinSize);
- }
- }
-
- @EditableProperty(name = "Core")
- public Color getCoreColor() {
- if (coreColor == null) {
- coreColor = CORE_COLOR;
- }
- return coreColor;
- }
-
- public void setCoreColor(Color coreColor) {
- this.coreColor = coreColor;
- }
-
- @EditableProperty(name = "Core Border")
- public Color getCoreBorderColor() {
- if (coreBorderColor == null) {
- coreBorderColor = CORE_BORDER_COLOR;
- }
- return coreBorderColor;
- }
-
- public void setCoreBorderColor(Color coreBorderColor) {
- this.coreBorderColor = coreBorderColor;
- }
-
- @EditableProperty(name = "Label")
- public Color getLabelColor() {
- if (labelColor == null) {
- labelColor = LABEL_COLOR;
- }
- return labelColor;
- }
-
- public void setLabelColor(Color labelColor) {
- this.labelColor = labelColor;
- }
-
- @EditableProperty(name = "Core Thickness")
- public Size getCoreThickness() {
- return coreThickness;
- }
-
- public void setCoreThickness(Size coreThickness) {
- this.coreThickness = coreThickness;
- body = null;
- }
-
- @EditableProperty(name = "Core Width")
- public Size getCoreWidth() {
- return coreWidth;
- }
-
- public void setCoreWidth(Size coreWidth) {
- this.coreWidth = coreWidth;
- body = null;
- }
-
- @EditableProperty(name = "Coil Width")
- public Size getCoilWidth() {
- return coilWidth;
- }
-
- public void setCoilWidth(Size coilWidth) {
- this.coilWidth = coilWidth;
- body = null;
- }
-
- @EditableProperty(name = "Coil Length")
- public Size getCoilLength() {
- return coilLength;
- }
-
- public void setCoilLength(Size coilLength) {
- this.coilLength = coilLength;
- body = null;
- }
-
- @EditableProperty(name = "Coil")
- public Color getCoilColor() {
- return coilColor;
- }
-
- public void setCoilColor(Color coilColor) {
- this.coilColor = coilColor;
- }
-
- @EditableProperty(name = "Coil Border")
- public Color getCoilBorderColor() {
- return coilBorderColor;
- }
-
- public void setCoilBorderColor(Color coilBorderColor) {
- this.coilBorderColor = coilBorderColor;
- }
-
- @EditableProperty(name = "Primary CT")
- public boolean getPrimaryCT() {
- return primaryCT;
- }
-
- public void setPrimaryCT(boolean primaryCT) {
- this.primaryCT = primaryCT;
- updateControlPoints();
- }
-
- @EditableProperty(name = "Secondary CT")
- public boolean getSecondaryCT() {
- return secondaryCT;
- }
-
- public void setSecondaryCT(boolean secondaryCT) {
- this.secondaryCT = secondaryCT;
- updateControlPoints();
- }
-
- @Override
- public boolean canPointMoveFreely(int pointIndex) {
- return false;
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.passive;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Area;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.awt.StringUtils;
+import org.diylc.common.Display;
+import org.diylc.common.HorizontalAlignment;
+import org.diylc.common.IPlugInPort;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.Orientation;
+import org.diylc.common.VerticalAlignment;
+import org.diylc.components.AbstractMultiPartComponent;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+import org.diylc.core.VisibilityPolicy;
+import org.diylc.core.annotations.ComponentDescriptor;
+import org.diylc.core.annotations.EditableProperty;
+import org.diylc.core.annotations.KeywordPolicy;
+import org.diylc.core.annotations.PositiveNonZeroMeasureValidator;
+import org.diylc.core.gerber.IGerberComponentSimple;
+import org.diylc.core.measures.Size;
+import org.diylc.core.measures.SizeUnit;
+import org.diylc.utils.Constants;
+
+@ComponentDescriptor(name = "Mini Signal Transformer", author = "Branislav Stojkovic", category = "Passive",
+ instanceNamePrefix = "TR", description = "Miniature PCB-mount signal transformer with EI core",
+ zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_VALUE)
+public class AudioTransformer extends AbstractMultiPartComponent implements IGerberComponentSimple {
+
+ private static final long serialVersionUID = 1L;
+
+ public static Color CORE_COLOR = METAL_COLOR;
+ public static Color CORE_BORDER_COLOR = CORE_COLOR.darker();
+ public static Color COIL_COLOR = Color.decode("#DDDDDD");
+ public static Color COIL_BORDER_COLOR = COIL_COLOR.darker();
+ public static Color PIN_COLOR = Color.decode("#00B2EE");
+ public static Color PIN_BORDER_COLOR = PIN_COLOR.darker();
+ public static Color LABEL_COLOR = Color.white;
+ public static int EDGE_RADIUS = 6;
+ public static Size PIN_SIZE = new Size(0.03d, SizeUnit.in);
+
+ private String value = "";
+ private Orientation orientation = Orientation.DEFAULT;
+ private Size leadSpacing = new Size(0.1d, SizeUnit.in);
+ private Size windingSpacing = new Size(0.5d, SizeUnit.in);
+ private Size coreThickness = new Size(0.15d, SizeUnit.in);
+ private Size coreWidth = new Size(0.6, SizeUnit.in);
+ private Size coilWidth = new Size(0.5, SizeUnit.in);
+ private Size coilLength = new Size(0.6, SizeUnit.in);
+ private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0)};
+ protected Display display = Display.BOTH;
+ private Color coreColor = CORE_COLOR;
+ private Color coreBorderColor = CORE_BORDER_COLOR;
+ private Color coilColor = COIL_COLOR;
+ private Color coilBorderColor = COIL_BORDER_COLOR;
+ private Color labelColor = LABEL_COLOR;
+ private boolean primaryCT = true;
+ private boolean secondaryCT = true;
+
+ transient private Area[] body;
+
+ public AudioTransformer() {
+ super();
+ updateControlPoints();
+// alpha = 100;
+ }
+
+ @EditableProperty
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ @EditableProperty
+ public Orientation getOrientation() {
+ return orientation;
+ }
+
+ public void setOrientation(Orientation orientation) {
+ this.orientation = orientation;
+ updateControlPoints();
+ // Reset body shape.
+ body = null;
+ }
+
+ @EditableProperty(name = "Lead Spacing", validatorClass = PositiveNonZeroMeasureValidator.class)
+ public Size getLeadSpacing() {
+ return leadSpacing;
+ }
+
+ public void setLeadSpacing(Size leadSpacing) {
+ this.leadSpacing = leadSpacing;
+ updateControlPoints();
+ // Reset body shape;
+ body = null;
+ }
+
+ @EditableProperty(name = "Winding Spacing", validatorClass = PositiveNonZeroMeasureValidator.class)
+ public Size getWindingSpacing() {
+ return windingSpacing;
+ }
+
+ public void setWindingSpacing(Size rowSpacing) {
+ this.windingSpacing = rowSpacing;
+ updateControlPoints();
+ // Reset body shape;
+ body = null;
+ }
+
+ @EditableProperty
+ public Display getDisplay() {
+ if (display == null) {
+ display = Display.VALUE;
+ }
+ return display;
+ }
+
+ public void setDisplay(Display display) {
+ this.display = display;
+ }
+
+ @Override
+ public int getControlPointCount() {
+ return controlPoints.length;
+ }
+
+ @Override
+ public Point2D getControlPoint(int index) {
+ return controlPoints[index];
+ }
+
+ @Override
+ public boolean isControlPointSticky(int index) {
+ return true;
+ }
+
+ @Override
+ public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
+ return VisibilityPolicy.NEVER;
+ }
+
+ @Override
+ public void setControlPoint(Point2D point, int index) {
+ controlPoints[index].setLocation(point);
+ body = null;
+ }
+
+ private void updateControlPoints() {
+ Point2D firstPoint = controlPoints[0];
+ int pinCount = 4 + (primaryCT ? 1 : 0) + (secondaryCT ? 1 : 0);
+ controlPoints = new Point2D[pinCount];
+ controlPoints[0] = firstPoint;
+ double leadSpacing = this.leadSpacing.convertToPixels();
+ double windingSpacing = this.windingSpacing.convertToPixels();
+
+ // Update control points.
+ for (int i = 1; i < 2 + (primaryCT ? 1 : 0); i++)
+ controlPoints[i] = new Point2D.Double(firstPoint.getX(), firstPoint.getY() + i * leadSpacing * (primaryCT ? 1 : 2));
+ for (int i = 0; i < 2 + (secondaryCT ? 1 : 0); i++)
+ controlPoints[2 + (primaryCT ? 1 : 0) + i] = new Point2D.Double(firstPoint.getX() + windingSpacing, firstPoint.getY() + i * leadSpacing * (secondaryCT ? 1 : 2));
+
+ AffineTransform tx = getTx();
+
+ if (tx != null) {
+ for (int i = 1; i < controlPoints.length; i++) {
+ tx.transform(controlPoints[i], controlPoints[i]);
+ }
+ }
+ }
+
+ @Override
+ public Area[] getBody() {
+ if (body == null) {
+ 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);
+ int coreWidth = getClosestOdd(this.coreWidth.convertToPixels());
+ int coreThickness = getClosestOdd(this.coreThickness.convertToPixels());
+ int coilWidth = getClosestOdd(this.coilWidth.convertToPixels());
+ int coilLength = getClosestOdd(this.coilLength.convertToPixels());
+
+ body[0] = new Area(new Rectangle2D.Double(centerX - coreThickness / 2, centerY - coreWidth / 2, coreThickness, coreWidth));
+ body[1] = new Area(new RoundRectangle2D.Double(centerX - coilLength / 2, centerY - coilWidth / 2, coilLength, coilWidth, coilWidth / 3, coilWidth / 3));
+ body[1].subtract(body[0]);
+
+ AffineTransform tx = getTx();
+ if (tx != null)
+ for (Area b : body) {
+ if (b != null)
+ b.transform(tx);
+ }
+ }
+ return body;
+ }
+
+ @SuppressWarnings("incomplete-switch")
+ private AffineTransform getTx() {
+ double x = controlPoints[0].getX();
+ double y = controlPoints[0].getY();
+ if (orientation == Orientation.DEFAULT)
+ return null;
+
+ double theta = 0;
+ switch (orientation) {
+ case _90:
+ theta = Math.PI / 2;
+ break;
+ case _180:
+ theta = Math.PI;
+ break;
+ case _270:
+ theta = Math.PI * 3 / 2;
+ break;
+ }
+ AffineTransform rotation = AffineTransform.getRotateInstance(theta, x, y);
+
+ return rotation;
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ if (checkPointsClipped(g2d.getClip())) {
+ return;
+ }
+ Area[] body = getBody();
+ Area coreArea = body[0];
+ Area coilArea = body[1];
+
+ if (!outlineMode) {
+ 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.setColor(PIN_BORDER_COLOR);
+ g2d.drawOval((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize);
+ }
+ }
+ Composite oldComposite = applyAlpha(g2d, componentState);
+
+ // render coil
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getCoilColor());
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+ g2d.fill(coilArea);
+ Color finalBorderColor;
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalBorderColor = theme.getOutlineColor();
+ } else {
+ finalBorderColor = getCoilBorderColor();
+ }
+ g2d.setColor(finalBorderColor);
+ g2d.draw(coilArea);
+
+ // render core
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getCoreColor());
+ g2d.fill(coreArea);
+ g2d.setComposite(oldComposite);
+
+ if (!outlineMode)
+ finalBorderColor = getCoreBorderColor();
+
+ g2d.setColor(finalBorderColor);
+ g2d.draw(coreArea);
+
+ drawingObserver.stopTracking();
+
+ g2d.setFont(project.getFont());
+
+ // Override font size
+ if (getFontSizeOverride() != null)
+ g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride()));
+
+ // Draw winding designations
+ Point2D wPoint = new Point2D.Double((int) (controlPoints[0].getX() + project.getFontSize()), (int) (controlPoints[0].getY() + leadSpacing.convertToPixels()));
+ AffineTransform tx = getTx();
+ if (tx != null)
+ tx.transform(wPoint, wPoint);
+ StringUtils.drawCenteredText(g2d, "P", wPoint.getX(), wPoint.getY(), HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
+ wPoint = new Point2D.Double((int) (controlPoints[0].getX() + windingSpacing.convertToPixels() - project.getFontSize()), (int) (controlPoints[0].getY() + leadSpacing.convertToPixels()));
+ if (tx != null)
+ tx.transform(wPoint, wPoint);
+ StringUtils.drawCenteredText(g2d, "S", wPoint.getX(), wPoint.getY(), HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
+
+ // Draw label.
+ Color finalLabelColor;
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : theme.getOutlineColor();
+ } else {
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : getLabelColor();
+ }
+ g2d.setColor(finalLabelColor);
+ FontMetrics fontMetrics = g2d.getFontMetrics(g2d.getFont());
+ String[] label = null;
+
+ if (getDisplay() == Display.NAME) {
+ label = new String[] {getName()};
+ } else if (getDisplay() == Display.VALUE) {
+ label = new String[] {getValue().toString()};
+ } else if (getDisplay() == Display.BOTH) {
+ String value = getValue().toString();
+ label = value.isEmpty() ? new String[] {getName()} : new String[] {getName(), value};
+ }
+
+ if (label != null) {
+ for (int i = 0; i < label.length; i++) {
+ String l = label[i];
+ Rectangle2D rect = fontMetrics.getStringBounds(l, g2d);
+ int textHeight = (int) (rect.getHeight());
+ int textWidth = (int) (rect.getWidth());
+ // Center text horizontally and vertically
+ Rectangle bounds = coreArea.getBounds();
+ double x = bounds.getX() + (bounds.width - textWidth) / 2;
+ double y = bounds.getY() + (bounds.height - textHeight) / 2 + fontMetrics.getAscent();
+
+ AffineTransform oldTransform = g2d.getTransform();
+
+ if (getOrientation() == Orientation.DEFAULT || getOrientation() == Orientation._180) {
+ double centerX = bounds.getX() + bounds.width / 2;
+ double centerY = bounds.getY() + bounds.height / 2;
+ g2d.rotate(-Math.PI / 2, centerX, centerY);
+ }
+
+ if (label.length == 2) {
+ if (i == 0)
+ g2d.translate(0, -textHeight / 2);
+ else if (i == 1)
+ g2d.translate(0, textHeight / 2);
+ }
+
+ g2d.drawString(l, (int)x, (int)y);
+
+ g2d.setTransform(oldTransform);
+ }
+ }
+
+ drawSelectionOutline(g2d, componentState, outlineMode, project, drawingObserver);
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int radius = (int) (12f * width / 32);
+ g2d.setColor(COIL_COLOR);
+ g2d.fillRoundRect(1, (int) (height / 8f), width - 2, (int) (height * 6 / 8f), radius, radius);
+ g2d.setColor(COIL_BORDER_COLOR);
+ g2d.drawRoundRect(1, (int) (height / 8f), width - 2, (int) (height * 6 / 8f), radius, radius);
+
+ g2d.setColor(CORE_COLOR);
+ g2d.fillRect(width * 3 / 8, 1, width / 4, height - 2);
+ g2d.setColor(CORE_BORDER_COLOR);
+ g2d.drawRect(width * 3 / 8, 1, width / 4, height - 2);
+
+ g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
+
+ int pinSize = (int) (2f * width / 32);
+ g2d.setColor(PIN_COLOR);
+ for (int i = 0; i < 3; i++) {
+ g2d.fillOval(width / 5 - pinSize + 1, (height / 6) * (i + 2), pinSize, pinSize);
+ g2d.fillOval(4 * width / 5 + 1, (height / 6) * (i + 2), pinSize, pinSize);
+ }
+ }
+
+ @EditableProperty(name = "Core")
+ public Color getCoreColor() {
+ if (coreColor == null) {
+ coreColor = CORE_COLOR;
+ }
+ return coreColor;
+ }
+
+ public void setCoreColor(Color coreColor) {
+ this.coreColor = coreColor;
+ }
+
+ @EditableProperty(name = "Core Border")
+ public Color getCoreBorderColor() {
+ if (coreBorderColor == null) {
+ coreBorderColor = CORE_BORDER_COLOR;
+ }
+ return coreBorderColor;
+ }
+
+ public void setCoreBorderColor(Color coreBorderColor) {
+ this.coreBorderColor = coreBorderColor;
+ }
+
+ @EditableProperty(name = "Label")
+ public Color getLabelColor() {
+ if (labelColor == null) {
+ labelColor = LABEL_COLOR;
+ }
+ return labelColor;
+ }
+
+ public void setLabelColor(Color labelColor) {
+ this.labelColor = labelColor;
+ }
+
+ @EditableProperty(name = "Core Thickness")
+ public Size getCoreThickness() {
+ return coreThickness;
+ }
+
+ public void setCoreThickness(Size coreThickness) {
+ this.coreThickness = coreThickness;
+ body = null;
+ }
+
+ @EditableProperty(name = "Core Width")
+ public Size getCoreWidth() {
+ return coreWidth;
+ }
+
+ public void setCoreWidth(Size coreWidth) {
+ this.coreWidth = coreWidth;
+ body = null;
+ }
+
+ @EditableProperty(name = "Coil Width")
+ public Size getCoilWidth() {
+ return coilWidth;
+ }
+
+ public void setCoilWidth(Size coilWidth) {
+ this.coilWidth = coilWidth;
+ body = null;
+ }
+
+ @EditableProperty(name = "Coil Length")
+ public Size getCoilLength() {
+ return coilLength;
+ }
+
+ public void setCoilLength(Size coilLength) {
+ this.coilLength = coilLength;
+ body = null;
+ }
+
+ @EditableProperty(name = "Coil")
+ public Color getCoilColor() {
+ return coilColor;
+ }
+
+ public void setCoilColor(Color coilColor) {
+ this.coilColor = coilColor;
+ }
+
+ @EditableProperty(name = "Coil Border")
+ public Color getCoilBorderColor() {
+ return coilBorderColor;
+ }
+
+ public void setCoilBorderColor(Color coilBorderColor) {
+ this.coilBorderColor = coilBorderColor;
+ }
+
+ @EditableProperty(name = "Primary CT")
+ public boolean getPrimaryCT() {
+ return primaryCT;
+ }
+
+ public void setPrimaryCT(boolean primaryCT) {
+ this.primaryCT = primaryCT;
+ updateControlPoints();
+ }
+
+ @EditableProperty(name = "Secondary CT")
+ public boolean getSecondaryCT() {
+ return secondaryCT;
+ }
+
+ public void setSecondaryCT(boolean secondaryCT) {
+ this.secondaryCT = secondaryCT;
+ updateControlPoints();
+ }
+
+ @Override
+ public boolean canPointMoveFreely(int pointIndex) {
+ return false;
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/passive/BoxTrimmer.java b/diylc/diylc-library/src/main/java/org/diylc/components/passive/BoxTrimmer.java
index a3b4d042a..07f63252e 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/passive/BoxTrimmer.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/passive/BoxTrimmer.java
@@ -110,10 +110,7 @@ public class BoxTrimmer extends AbstractTransparentComponent {
}
// Draw body
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor);
g2d.fillRoundRect(bodyX, bodyY, bodyW, bodyH, bodyW / 10, bodyH / 10);
g2d.setComposite(oldComposite);
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/passive/MultiSectionCapacitor.java b/diylc/diylc-library/src/main/java/org/diylc/components/passive/MultiSectionCapacitor.java
index 5f93cddab..50203577b 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/passive/MultiSectionCapacitor.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/passive/MultiSectionCapacitor.java
@@ -351,10 +351,7 @@ public class MultiSectionCapacitor extends AbstractLabeledComponent.
-
-*/
-package org.diylc.components.passive;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.FontMetrics;
-import java.awt.Graphics2D;
-import java.awt.Polygon;
-import java.awt.Shape;
-import java.awt.geom.Area;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.geom.RoundRectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.awt.StringUtils;
-import org.diylc.common.HorizontalAlignment;
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.Orientation;
-import org.diylc.common.VerticalAlignment;
-import org.diylc.components.transform.PotentiometerTransformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.CreationMethod;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.ILayeredComponent;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-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.Constants;
-
-@ComponentDescriptor(name = "Potentiometer", author = "Branislav Stojkovic", category = "Passive",
- creationMethod = CreationMethod.SINGLE_CLICK, instanceNamePrefix = "VR",
- description = "Panel mount potentiometer with solder lugs", zOrder = IDIYComponent.COMPONENT,
- transformer = PotentiometerTransformer.class, enableCache = true)
-public class PotentiometerPanel extends AbstractPotentiometer implements ILayeredComponent {
-
- private static final long serialVersionUID = 1L;
-
- protected static Size BODY_DIAMETER = new Size(1d, SizeUnit.in);
- protected static Size SPACING = new Size(0.3d, SizeUnit.in);
- protected static Size LUG_DIAMETER = new Size(0.15d, SizeUnit.in);
- protected static Size PIN_SIZE = new Size(0.05d, SizeUnit.in);
- protected static Size NUT_SIZE = new Size(0.4d, SizeUnit.in);
- protected static Size SHAFT_SIZE = new Size(1 / 4d, SizeUnit.in);
- protected static Size MARKER_OFFSET = new Size(0.05d, SizeUnit.in);
- protected static Color BODY_COLOR = Color.lightGray;
- protected static Color WAFER_COLOR = Color.decode("#CD8500");
- protected static Color BORDER_COLOR = Color.gray;
- protected static Color NUT_COLOR = Color.decode("#CBD5DB");
- protected static Color MARKER_COLOR_DEFAULT = Color.gray;
-
-
- protected Size bodyDiameter = BODY_DIAMETER;
- protected Size spacing = SPACING;
- protected Size lugDiameter = LUG_DIAMETER;
- protected Color bodyColor = BODY_COLOR;
- protected Color borderColor = BORDER_COLOR;
- protected Color nutColor = NUT_COLOR;
- protected Color waferColor = WAFER_COLOR;
- protected Type type = Type.ThroughHole;
- @Deprecated
- protected boolean showShaft = false;
- protected View view;
- private Boolean showMarkers;
- private Color markerColor;
- // Array of 7 elements: 3 lug connectors, 1 pot body and 3 lugs
- transient protected Area[] body = null;
-
- public PotentiometerPanel() {
- controlPoints = new Point2D[] {new Point2D.Double(0, 0), new Point2D.Double(0, 0), new Point2D.Double(0, 0)};
- updateControlPoints();
- }
-
- protected void updateControlPoints() {
- int spacing = (int) this.spacing.convertToPixels();
- switch (orientation) {
- case DEFAULT:
- controlPoints[1].setLocation(controlPoints[0].getX() + spacing, controlPoints[0].getY());
- controlPoints[2].setLocation(controlPoints[0].getX() + 2 * spacing, controlPoints[0].getY());
- break;
- case _90:
- controlPoints[1].setLocation(controlPoints[0].getX(), controlPoints[0].getY() + spacing);
- controlPoints[2].setLocation(controlPoints[0].getX(), controlPoints[0].getY() + 2 * spacing);
- break;
- case _180:
- controlPoints[1].setLocation(controlPoints[0].getX() - spacing, controlPoints[0].getY());
- controlPoints[2].setLocation(controlPoints[0].getX() - 2 * spacing, controlPoints[0].getY());
- break;
- case _270:
- controlPoints[1].setLocation(controlPoints[0].getX(), controlPoints[0].getY() - spacing);
- controlPoints[2].setLocation(controlPoints[0].getX(), controlPoints[0].getY() - 2 * spacing);
- break;
- default:
- break;
- }
- }
-
- public Area[] getBody() {
- int spacing = (int) this.spacing.convertToPixels();
- int diameter = getClosestOdd(bodyDiameter.convertToPixels());
- if (body == null) {
- // mandatory: 0, 1, 2 pins, 3 body, 9 wafer
- // optional: 4, 5, 6 lugs, 7 nut, 8 shaft
- body = new Area[13];
-
- // Add lugs.
- int pinWidth = (int) PIN_SIZE.convertToPixels();
-
- double centerX = 0;
- double centerY = 0;
-
- double waferWidth = 2.5 * spacing;
- double waferHeight = spacing;
-
- switch (orientation) {
- case DEFAULT:
- centerX = controlPoints[0].getX() + spacing;
- centerY = controlPoints[0].getY() - spacing / 2 - diameter / 2;
-
- body[9] =
- new Area(new RoundRectangle2D.Double(centerX - waferWidth / 2, controlPoints[0].getY() - waferHeight - spacing
- / 2, waferWidth, waferHeight, spacing / 4, spacing / 4));
-
- for (int i = 0; i < 3; i++) {
- body[i] =
- new Area(new Rectangle2D.Double(controlPoints[i].getX() - pinWidth / 2, controlPoints[i].getY()
- - (spacing + diameter) / 2, pinWidth, (spacing + diameter) / 2));
- }
- break;
- case _90:
- centerX = controlPoints[0].getX() + spacing / 2 + diameter / 2;
- centerY = controlPoints[0].getY() + spacing;
-
- body[9] =
- new Area(new RoundRectangle2D.Double(controlPoints[0].getX() + spacing / 2, centerY - waferWidth / 2,
- waferHeight, waferWidth, spacing / 4, spacing / 4));
-
- for (int i = 0; i < 3; i++) {
- body[i] =
- new Area(new Rectangle2D.Double(controlPoints[i].getX(), controlPoints[i].getY() - pinWidth / 2,
- (spacing + diameter) / 2, pinWidth));
- }
- break;
- case _180:
- centerX = controlPoints[0].getX() - spacing;
- centerY = controlPoints[0].getY() + spacing / 2 + diameter / 2;
-
- body[9] =
- new Area(new RoundRectangle2D.Double(centerX - waferWidth / 2, controlPoints[0].getY() + spacing / 2,
- waferWidth, waferHeight, spacing / 4, spacing / 4));
-
- for (int i = 0; i < 3; i++) {
- body[i] =
- new Area(new Rectangle2D.Double(controlPoints[i].getX() - pinWidth / 2, controlPoints[i].getY(), pinWidth,
- (spacing + diameter) / 2));
- }
- break;
- case _270:
- centerX = controlPoints[0].getX() - spacing / 2 - diameter / 2;
- centerY = controlPoints[0].getY() - spacing;
-
- body[9] =
- new Area(new RoundRectangle2D.Double(controlPoints[0].getX() - waferHeight - spacing / 2, centerY - waferWidth
- / 2, waferHeight, waferWidth, spacing / 4, spacing / 4));
-
- for (int i = 0; i < 3; i++) {
- body[i] =
- new Area(new Rectangle2D.Double(controlPoints[i].getX() - (spacing + diameter) / 2, controlPoints[i].getY()
- - pinWidth / 2, (spacing + diameter) / 2, pinWidth));
- }
- break;
- default:
- break;
- }
-
- body[3] = new Area(new Ellipse2D.Double(centerX - diameter / 2, centerY - diameter / 2, diameter, diameter));
-
- body[9].subtract(body[3]);
-
- for (int i = 0; i < 3; i++) {
- body[i].subtract(body[3]);
- }
-
- if (getType() == Type.ThroughHole) {
- int lugDiameter = getClosestOdd(this.lugDiameter.convertToPixels());
- int holeDiameter = getClosestOdd(this.lugDiameter.convertToPixels() / 2);
-
- for (int i = 0; i < 3; i++) {
- Area area =
- new Area(new Ellipse2D.Double(controlPoints[i].getX() - lugDiameter / 2, controlPoints[i].getY() - lugDiameter / 2,
- lugDiameter, lugDiameter));
- body[4 + i] = area;
- body[10 + i] = new Area(area);
- }
-
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++) {
- body[i].subtract(body[4 + j]);
- }
- }
- // Make holes in the lugs.
- for (int i = 0; i < 3; i++) {
- body[4 + i].subtract(new Area(new Ellipse2D.Double(controlPoints[i].getX() - holeDiameter / 2, controlPoints[i].getY()
- - holeDiameter / 2, holeDiameter, holeDiameter)));
- }
- }
-
- if (getView() == View.ShaftUp) {
- int nutSize = (int) NUT_SIZE.convertToPixels();
- int shaftSize = (int) SHAFT_SIZE.convertToPixels();
- int[] xPoints = new int[6];
- int[] yPoints = new int[6];
- for (int i = 0; i < 6; i++) {
- double alpha = Math.toRadians(60 * i);
- xPoints[i] = (int) (centerX + Math.cos(alpha) * nutSize / 2);
- yPoints[i] = (int) (centerY + Math.sin(alpha) * nutSize / 2);
- }
- body[7] = new Area(new Polygon(xPoints, yPoints, 6));
- body[8] =
- new Area(new Ellipse2D.Double(centerX - shaftSize / 2, centerY - shaftSize / 2, shaftSize, shaftSize));
- }
- }
- return body;
- }
-
- @Override
- public void setControlPoint(Point2D point, int index) {
- super.setControlPoint(point, index);
- body = null;
- }
-
- @Override
- public void setOrientation(Orientation orientation) {
- super.setOrientation(orientation);
- updateControlPoints();
- body = null;
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
- Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- Area[] body = getBody();
- for (int i = 0; i < body.length; i++) {
- Area shape = body[i];
- // determine color
- if (shape != null) {
- switch (i) {
- case 7:
- g2d.setColor(getNutColor());
- break;
- case 9:
- g2d.setColor(getWaferColor());
- break;
- case 10:
- case 11:
- case 12:
- g2d.setColor(Constants.TRANSPARENT_COLOR);
- break;
- default:
- g2d.setColor(getBodyColor());
- }
-
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- if (!outlineMode) {
- if (i >= 10)
- drawingObserver.startTrackingContinuityArea(true);
- g2d.fill(shape);
- if (i >= 10)
- drawingObserver.stopTrackingContinuityArea();
- }
- g2d.setComposite(oldComposite);
- Color finalBorderColor;
- if (outlineMode) {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : getBorderColor();
- }
- g2d.setColor(finalBorderColor);
- g2d.draw(shape);
- }
- }
-
- drawingObserver.stopTracking();
-
- // Draw caption.
- g2d.setFont(project.getFont());
-
- // Override font size
- if (getFontSizeOverride() != null)
- g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride()));
-
- Color finalLabelColor;
- if (outlineMode) {
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : theme.getOutlineColor();
- } else {
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : LABEL_COLOR;
- }
- g2d.setColor(finalLabelColor);
- FontMetrics fontMetrics = g2d.getFontMetrics();
- Rectangle2D bodyRect = getBody()[3].getBounds2D();
- Rectangle2D rect = fontMetrics.getStringBounds(getName(), g2d);
-
- int textHeight = (int) rect.getHeight();
- int textWidth = (int) rect.getWidth();
- int panelHeight = (int) bodyRect.getHeight();
- int panelWidth = (int) bodyRect.getWidth();
-
- int x = (panelWidth - textWidth) / 2;
- int y = panelHeight / 2 - textHeight + fontMetrics.getAscent();
-
- g2d.drawString(getName(), (int) (bodyRect.getX() + x), (int) (bodyRect.getY() + y));
-
- // Draw value.
- rect = fontMetrics.getStringBounds(getValueForDisplay(), g2d);
-
- textHeight = (int) rect.getHeight();
- textWidth = (int) rect.getWidth();
-
- x = (panelWidth - textWidth) / 2;
- y = panelHeight / 2 + fontMetrics.getAscent();
-
- g2d.drawString(getValueForDisplay(), (int) (bodyRect.getX() + x), (int) (bodyRect.getY() + y));
-
- // Draw markers if enabled.
- if (getShowMarkers()) {
- g2d.setColor(outlineMode ? theme.getOutlineColor() : getMarkerColor());
-
- // Get circle center and radius
- Rectangle2D circleBounds = body[3].getBounds2D();
- double centerX = circleBounds.getCenterX();
- double centerY = circleBounds.getCenterY();
- double radius = getBodyDiameter().convertToPixels() / 2;
-
- // Fixed distance from circle edge (inside the circle)
- double markerOffset = MARKER_OFFSET.convertToPixels() + 2;
- double markerDistance = radius - markerOffset;
-
- // Draw markers "1", "2", "3" along radial line from center to each lug, close to circle edge
- // Reverse numbering when view is ShaftDown
- boolean reverseOrder = getView() == View.ShaftDown;
-
- for (int i = 0; i < 3; i++) {
- Point2D lugPoint = controlPoints[i];
-
- // Calculate direction from center to lug
- double dx = lugPoint.getX() - centerX;
- double dy = lugPoint.getY() - centerY;
- double distance = Math.sqrt(dx * dx + dy * dy);
-
- if (distance > 0) {
- // Normalize direction vector
- double unitX = dx / distance;
- double unitY = dy / distance;
-
- // Position marker at fixed distance from circle edge along radial line
- double markerX = centerX + unitX * markerDistance;
- double markerY = centerY + unitY * markerDistance;
-
- // Determine marker number based on view
- int markerNumber = reverseOrder ? (3 - i) : (i + 1);
-
- StringUtils.drawCenteredText(g2d, Integer.toString(markerNumber), markerX, markerY,
- HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
- }
- }
- }
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int margin = 4 * width / 32;
- int waferMargin = 5 * width / 32;
- int spacing = width / 3 - 1;
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1 * width / 32));
- g2d.setColor(WAFER_COLOR);
- g2d.fillRect(waferMargin, height / 2, width - 2 * waferMargin, height / 3);
- g2d.setColor(BORDER_COLOR);
- g2d.drawRoundRect(waferMargin, height / 2, width - 2 * waferMargin, height / 3, 2 * width / 32, 2 * width / 32);
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(2 * width / 32));
- g2d.drawLine(width / 2 - spacing, height / 2, width / 2 - spacing, height - margin);
- g2d.drawLine(width / 2 + spacing, height / 2, width / 2 + spacing, height - margin);
- g2d.drawLine(width / 2, height / 2, width / 2, height - margin);
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(4 * width / 32));
- g2d.drawLine(width / 2 - spacing, height - margin, width / 2 - spacing, height - margin);
- g2d.drawLine(width / 2 + spacing, height - margin, width / 2 + spacing, height - margin);
- g2d.drawLine(width / 2, height - margin, width / 2, height - margin);
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
- g2d.setColor(BODY_COLOR);
- g2d.fillOval(margin, margin / 2, width - 2 * margin, height - 2 * margin);
- g2d.setColor(BORDER_COLOR);
- g2d.drawOval(margin, margin / 2, width - 2 * margin, height - 2 * margin);
- }
-
- @EditableProperty
- public Size getSpacing() {
- return spacing;
- }
-
- public void setSpacing(Size spacing) {
- this.spacing = spacing;
- updateControlPoints();
- body = null;
- }
-
- @EditableProperty
- public Type getType() {
- if (type == null)
- type = Type.ThroughHole;
- return type;
- }
-
- public void setType(Type type) {
- this.type = type;
- body = null;
- }
-
- @EditableProperty(name = "Nut")
- public Color getNutColor() {
- if (nutColor == null)
- nutColor = NUT_COLOR;
- return nutColor;
- }
-
- public void setNutColor(Color nutColor) {
- this.nutColor = nutColor;
- }
-
- @EditableProperty(name = "Diameter")
- public Size getBodyDiameter() {
- return bodyDiameter;
- }
-
- public void setBodyDiameter(Size bodyDiameter) {
- this.bodyDiameter = bodyDiameter;
- body = null;
- }
-
- @EditableProperty(name = "Lug Size")
- public Size getLugDiameter() {
- return lugDiameter;
- }
-
- public void setLugDiameter(Size lugDiameter) {
- this.lugDiameter = lugDiameter;
- body = null;
- }
-
- @EditableProperty(name = "Body")
- public Color getBodyColor() {
- return bodyColor;
- }
-
- public void setBodyColor(Color bodyColor) {
- this.bodyColor = bodyColor;
- }
-
- @EditableProperty(name = "Border")
- public Color getBorderColor() {
- return borderColor;
- }
-
- public void setBorderColor(Color borderColor) {
- this.borderColor = borderColor;
- }
-
- @EditableProperty(name = "View")
- public View getView() {
- if (view == null)
- view = showShaft ? View.ShaftUp : View.ShaftDown;
- return view;
- }
-
- public void setView(View view) {
- this.view = view;
- body = null;
- }
-
- @EditableProperty(name = "Wafer")
- public Color getWaferColor() {
- if (waferColor == null)
- waferColor = WAFER_COLOR;
- return waferColor;
- }
-
- public void setWaferColor(Color waferColor) {
- this.waferColor = waferColor;
- }
-
- @EditableProperty(name = "Markers")
- public Boolean getShowMarkers() {
- if (showMarkers == null) {
- showMarkers = false;
- }
- return showMarkers;
- }
-
- public void setShowMarkers(Boolean showMarkers) {
- this.showMarkers = showMarkers;
- }
-
- @EditableProperty(name = "Marker Color")
- public Color getMarkerColor() {
- if (markerColor == null) {
- markerColor = MARKER_COLOR_DEFAULT;
- }
- return markerColor;
- }
-
- public void setMarkerColor(Color markerColor) {
- this.markerColor = markerColor;
- }
-
- @Override
- public String getInternalLinkName(int index1, int index2) {
- if (index1 > index2)
- return getInternalLinkName(index2, index1);
-
- if (index2 - index1 == 1)
- return (index1 + 1) + "-" + (index2 + 1);
-
- return null;
- }
-
- @Override
- public Rectangle2D getCachingBounds() {
- Shape[] body = getBody();
- int margin = 20;
- double minX = 0;
- double minY = 0;
- double maxX = 0;
- double maxY = 0;
- for (Shape a : body) {
- if (a != null) {
- Rectangle2D bounds2d = a.getBounds2D();
- if (bounds2d.getMinX() < minX)
- minX = bounds2d.getMinX();
- if (bounds2d.getMinY() < minY)
- minY = bounds2d.getMinY();
- if (bounds2d.getMaxX() > maxX)
- maxX = bounds2d.getMaxX();
- if (bounds2d.getMaxY() > maxY)
- maxY = bounds2d.getMaxY();
- }
- }
- return new Rectangle2D.Double(minX - margin, minY - margin, maxX - minX + 2 * margin, maxY - minY + 2 * margin);
- }
-
- @Override
- public boolean canPointMoveFreely(int pointIndex) {
- return false;
- }
-
- @Override
- public int getLayerId() {
- return hashCode();
- }
-
- public enum Type {
- ThroughHole("Through Hole"), PCB("PCB");
-
- private String value;
-
- private Type(String value) {
- this.value = value;
- }
-
- @Override
- public String toString() {
- return value;
- }
- }
-
- public enum View {
- ShaftDown("Shaft Down"), ShaftUp("Shaft Up");//, TerminalsDown, TerminalsUp;
-
- private String value;
-
- private View(String value) {
- this.value = value;
- }
-
- @Override
- public String toString() {
- return 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 .
+
+*/
+package org.diylc.components.passive;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.Polygon;
+import java.awt.Shape;
+import java.awt.geom.Area;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.awt.StringUtils;
+import org.diylc.common.HorizontalAlignment;
+import org.diylc.common.IPlugInPort;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.Orientation;
+import org.diylc.common.VerticalAlignment;
+import org.diylc.components.transform.PotentiometerTransformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.CreationMethod;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.ILayeredComponent;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+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.Constants;
+
+@ComponentDescriptor(name = "Potentiometer", author = "Branislav Stojkovic", category = "Passive",
+ creationMethod = CreationMethod.SINGLE_CLICK, instanceNamePrefix = "VR",
+ description = "Panel mount potentiometer with solder lugs", zOrder = IDIYComponent.COMPONENT,
+ transformer = PotentiometerTransformer.class, enableCache = true)
+public class PotentiometerPanel extends AbstractPotentiometer implements ILayeredComponent {
+
+ private static final long serialVersionUID = 1L;
+
+ protected static Size BODY_DIAMETER = new Size(1d, SizeUnit.in);
+ protected static Size SPACING = new Size(0.3d, SizeUnit.in);
+ protected static Size LUG_DIAMETER = new Size(0.15d, SizeUnit.in);
+ protected static Size PIN_SIZE = new Size(0.05d, SizeUnit.in);
+ protected static Size NUT_SIZE = new Size(0.4d, SizeUnit.in);
+ protected static Size SHAFT_SIZE = new Size(1 / 4d, SizeUnit.in);
+ protected static Size MARKER_OFFSET = new Size(0.05d, SizeUnit.in);
+ protected static Color BODY_COLOR = Color.lightGray;
+ protected static Color WAFER_COLOR = Color.decode("#CD8500");
+ protected static Color BORDER_COLOR = Color.gray;
+ protected static Color NUT_COLOR = Color.decode("#CBD5DB");
+ protected static Color MARKER_COLOR_DEFAULT = Color.gray;
+
+
+ protected Size bodyDiameter = BODY_DIAMETER;
+ protected Size spacing = SPACING;
+ protected Size lugDiameter = LUG_DIAMETER;
+ protected Color bodyColor = BODY_COLOR;
+ protected Color borderColor = BORDER_COLOR;
+ protected Color nutColor = NUT_COLOR;
+ protected Color waferColor = WAFER_COLOR;
+ protected Type type = Type.ThroughHole;
+ @Deprecated
+ protected boolean showShaft = false;
+ protected View view;
+ private Boolean showMarkers;
+ private Color markerColor;
+ // Array of 7 elements: 3 lug connectors, 1 pot body and 3 lugs
+ transient protected Area[] body = null;
+
+ public PotentiometerPanel() {
+ controlPoints = new Point2D[] {new Point2D.Double(0, 0), new Point2D.Double(0, 0), new Point2D.Double(0, 0)};
+ updateControlPoints();
+ }
+
+ protected void updateControlPoints() {
+ int spacing = (int) this.spacing.convertToPixels();
+ switch (orientation) {
+ case DEFAULT:
+ controlPoints[1].setLocation(controlPoints[0].getX() + spacing, controlPoints[0].getY());
+ controlPoints[2].setLocation(controlPoints[0].getX() + 2 * spacing, controlPoints[0].getY());
+ break;
+ case _90:
+ controlPoints[1].setLocation(controlPoints[0].getX(), controlPoints[0].getY() + spacing);
+ controlPoints[2].setLocation(controlPoints[0].getX(), controlPoints[0].getY() + 2 * spacing);
+ break;
+ case _180:
+ controlPoints[1].setLocation(controlPoints[0].getX() - spacing, controlPoints[0].getY());
+ controlPoints[2].setLocation(controlPoints[0].getX() - 2 * spacing, controlPoints[0].getY());
+ break;
+ case _270:
+ controlPoints[1].setLocation(controlPoints[0].getX(), controlPoints[0].getY() - spacing);
+ controlPoints[2].setLocation(controlPoints[0].getX(), controlPoints[0].getY() - 2 * spacing);
+ break;
+ default:
+ break;
+ }
+ }
+
+ public Area[] getBody() {
+ int spacing = (int) this.spacing.convertToPixels();
+ int diameter = getClosestOdd(bodyDiameter.convertToPixels());
+ if (body == null) {
+ // mandatory: 0, 1, 2 pins, 3 body, 9 wafer
+ // optional: 4, 5, 6 lugs, 7 nut, 8 shaft
+ body = new Area[13];
+
+ // Add lugs.
+ int pinWidth = (int) PIN_SIZE.convertToPixels();
+
+ double centerX = 0;
+ double centerY = 0;
+
+ double waferWidth = 2.5 * spacing;
+ double waferHeight = spacing;
+
+ switch (orientation) {
+ case DEFAULT:
+ centerX = controlPoints[0].getX() + spacing;
+ centerY = controlPoints[0].getY() - spacing / 2 - diameter / 2;
+
+ body[9] =
+ new Area(new RoundRectangle2D.Double(centerX - waferWidth / 2, controlPoints[0].getY() - waferHeight - spacing
+ / 2, waferWidth, waferHeight, spacing / 4, spacing / 4));
+
+ for (int i = 0; i < 3; i++) {
+ body[i] =
+ new Area(new Rectangle2D.Double(controlPoints[i].getX() - pinWidth / 2, controlPoints[i].getY()
+ - (spacing + diameter) / 2, pinWidth, (spacing + diameter) / 2));
+ }
+ break;
+ case _90:
+ centerX = controlPoints[0].getX() + spacing / 2 + diameter / 2;
+ centerY = controlPoints[0].getY() + spacing;
+
+ body[9] =
+ new Area(new RoundRectangle2D.Double(controlPoints[0].getX() + spacing / 2, centerY - waferWidth / 2,
+ waferHeight, waferWidth, spacing / 4, spacing / 4));
+
+ for (int i = 0; i < 3; i++) {
+ body[i] =
+ new Area(new Rectangle2D.Double(controlPoints[i].getX(), controlPoints[i].getY() - pinWidth / 2,
+ (spacing + diameter) / 2, pinWidth));
+ }
+ break;
+ case _180:
+ centerX = controlPoints[0].getX() - spacing;
+ centerY = controlPoints[0].getY() + spacing / 2 + diameter / 2;
+
+ body[9] =
+ new Area(new RoundRectangle2D.Double(centerX - waferWidth / 2, controlPoints[0].getY() + spacing / 2,
+ waferWidth, waferHeight, spacing / 4, spacing / 4));
+
+ for (int i = 0; i < 3; i++) {
+ body[i] =
+ new Area(new Rectangle2D.Double(controlPoints[i].getX() - pinWidth / 2, controlPoints[i].getY(), pinWidth,
+ (spacing + diameter) / 2));
+ }
+ break;
+ case _270:
+ centerX = controlPoints[0].getX() - spacing / 2 - diameter / 2;
+ centerY = controlPoints[0].getY() - spacing;
+
+ body[9] =
+ new Area(new RoundRectangle2D.Double(controlPoints[0].getX() - waferHeight - spacing / 2, centerY - waferWidth
+ / 2, waferHeight, waferWidth, spacing / 4, spacing / 4));
+
+ for (int i = 0; i < 3; i++) {
+ body[i] =
+ new Area(new Rectangle2D.Double(controlPoints[i].getX() - (spacing + diameter) / 2, controlPoints[i].getY()
+ - pinWidth / 2, (spacing + diameter) / 2, pinWidth));
+ }
+ break;
+ default:
+ break;
+ }
+
+ body[3] = new Area(new Ellipse2D.Double(centerX - diameter / 2, centerY - diameter / 2, diameter, diameter));
+
+ body[9].subtract(body[3]);
+
+ for (int i = 0; i < 3; i++) {
+ body[i].subtract(body[3]);
+ }
+
+ if (getType() == Type.ThroughHole) {
+ int lugDiameter = getClosestOdd(this.lugDiameter.convertToPixels());
+ int holeDiameter = getClosestOdd(this.lugDiameter.convertToPixels() / 2);
+
+ for (int i = 0; i < 3; i++) {
+ Area area =
+ new Area(new Ellipse2D.Double(controlPoints[i].getX() - lugDiameter / 2, controlPoints[i].getY() - lugDiameter / 2,
+ lugDiameter, lugDiameter));
+ body[4 + i] = area;
+ body[10 + i] = new Area(area);
+ }
+
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ body[i].subtract(body[4 + j]);
+ }
+ }
+ // Make holes in the lugs.
+ for (int i = 0; i < 3; i++) {
+ body[4 + i].subtract(new Area(new Ellipse2D.Double(controlPoints[i].getX() - holeDiameter / 2, controlPoints[i].getY()
+ - holeDiameter / 2, holeDiameter, holeDiameter)));
+ }
+ }
+
+ if (getView() == View.ShaftUp) {
+ int nutSize = (int) NUT_SIZE.convertToPixels();
+ int shaftSize = (int) SHAFT_SIZE.convertToPixels();
+ int[] xPoints = new int[6];
+ int[] yPoints = new int[6];
+ for (int i = 0; i < 6; i++) {
+ double alpha = Math.toRadians(60 * i);
+ xPoints[i] = (int) (centerX + Math.cos(alpha) * nutSize / 2);
+ yPoints[i] = (int) (centerY + Math.sin(alpha) * nutSize / 2);
+ }
+ body[7] = new Area(new Polygon(xPoints, yPoints, 6));
+ body[8] =
+ new Area(new Ellipse2D.Double(centerX - shaftSize / 2, centerY - shaftSize / 2, shaftSize, shaftSize));
+ }
+ }
+ return body;
+ }
+
+ @Override
+ public void setControlPoint(Point2D point, int index) {
+ super.setControlPoint(point, index);
+ body = null;
+ }
+
+ @Override
+ public void setOrientation(Orientation orientation) {
+ super.setOrientation(orientation);
+ updateControlPoints();
+ body = null;
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+ Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ Area[] body = getBody();
+ for (int i = 0; i < body.length; i++) {
+ Area shape = body[i];
+ // determine color
+ if (shape != null) {
+ switch (i) {
+ case 7:
+ g2d.setColor(getNutColor());
+ break;
+ case 9:
+ g2d.setColor(getWaferColor());
+ break;
+ case 10:
+ case 11:
+ case 12:
+ g2d.setColor(Constants.TRANSPARENT_COLOR);
+ break;
+ default:
+ g2d.setColor(getBodyColor());
+ }
+
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ if (!outlineMode) {
+ if (i >= 10)
+ drawingObserver.startTrackingContinuityArea(true);
+ g2d.fill(shape);
+ if (i >= 10)
+ drawingObserver.stopTrackingContinuityArea();
+ }
+ g2d.setComposite(oldComposite);
+ Color finalBorderColor;
+ if (outlineMode) {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : getBorderColor();
+ }
+ g2d.setColor(finalBorderColor);
+ g2d.draw(shape);
+ }
+ }
+
+ drawingObserver.stopTracking();
+
+ // Draw caption.
+ g2d.setFont(project.getFont());
+
+ // Override font size
+ if (getFontSizeOverride() != null)
+ g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride()));
+
+ Color finalLabelColor;
+ if (outlineMode) {
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : theme.getOutlineColor();
+ } else {
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : LABEL_COLOR;
+ }
+ g2d.setColor(finalLabelColor);
+ FontMetrics fontMetrics = g2d.getFontMetrics();
+ Rectangle2D bodyRect = getBody()[3].getBounds2D();
+ Rectangle2D rect = fontMetrics.getStringBounds(getName(), g2d);
+
+ int textHeight = (int) rect.getHeight();
+ int textWidth = (int) rect.getWidth();
+ int panelHeight = (int) bodyRect.getHeight();
+ int panelWidth = (int) bodyRect.getWidth();
+
+ int x = (panelWidth - textWidth) / 2;
+ int y = panelHeight / 2 - textHeight + fontMetrics.getAscent();
+
+ g2d.drawString(getName(), (int) (bodyRect.getX() + x), (int) (bodyRect.getY() + y));
+
+ // Draw value.
+ rect = fontMetrics.getStringBounds(getValueForDisplay(), g2d);
+
+ textHeight = (int) rect.getHeight();
+ textWidth = (int) rect.getWidth();
+
+ x = (panelWidth - textWidth) / 2;
+ y = panelHeight / 2 + fontMetrics.getAscent();
+
+ g2d.drawString(getValueForDisplay(), (int) (bodyRect.getX() + x), (int) (bodyRect.getY() + y));
+
+ // Draw markers if enabled.
+ if (getShowMarkers()) {
+ g2d.setColor(outlineMode ? theme.getOutlineColor() : getMarkerColor());
+
+ // Get circle center and radius
+ Rectangle2D circleBounds = body[3].getBounds2D();
+ double centerX = circleBounds.getCenterX();
+ double centerY = circleBounds.getCenterY();
+ double radius = getBodyDiameter().convertToPixels() / 2;
+
+ // Fixed distance from circle edge (inside the circle)
+ double markerOffset = MARKER_OFFSET.convertToPixels() + 2;
+ double markerDistance = radius - markerOffset;
+
+ // Draw markers "1", "2", "3" along radial line from center to each lug, close to circle edge
+ // Reverse numbering when view is ShaftDown
+ boolean reverseOrder = getView() == View.ShaftDown;
+
+ for (int i = 0; i < 3; i++) {
+ Point2D lugPoint = controlPoints[i];
+
+ // Calculate direction from center to lug
+ double dx = lugPoint.getX() - centerX;
+ double dy = lugPoint.getY() - centerY;
+ double distance = Math.sqrt(dx * dx + dy * dy);
+
+ if (distance > 0) {
+ // Normalize direction vector
+ double unitX = dx / distance;
+ double unitY = dy / distance;
+
+ // Position marker at fixed distance from circle edge along radial line
+ double markerX = centerX + unitX * markerDistance;
+ double markerY = centerY + unitY * markerDistance;
+
+ // Determine marker number based on view
+ int markerNumber = reverseOrder ? (3 - i) : (i + 1);
+
+ StringUtils.drawCenteredText(g2d, Integer.toString(markerNumber), markerX, markerY,
+ HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int margin = 4 * width / 32;
+ int waferMargin = 5 * width / 32;
+ int spacing = width / 3 - 1;
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1 * width / 32));
+ g2d.setColor(WAFER_COLOR);
+ g2d.fillRect(waferMargin, height / 2, width - 2 * waferMargin, height / 3);
+ g2d.setColor(BORDER_COLOR);
+ g2d.drawRoundRect(waferMargin, height / 2, width - 2 * waferMargin, height / 3, 2 * width / 32, 2 * width / 32);
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(2 * width / 32));
+ g2d.drawLine(width / 2 - spacing, height / 2, width / 2 - spacing, height - margin);
+ g2d.drawLine(width / 2 + spacing, height / 2, width / 2 + spacing, height - margin);
+ g2d.drawLine(width / 2, height / 2, width / 2, height - margin);
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(4 * width / 32));
+ g2d.drawLine(width / 2 - spacing, height - margin, width / 2 - spacing, height - margin);
+ g2d.drawLine(width / 2 + spacing, height - margin, width / 2 + spacing, height - margin);
+ g2d.drawLine(width / 2, height - margin, width / 2, height - margin);
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+ g2d.setColor(BODY_COLOR);
+ g2d.fillOval(margin, margin / 2, width - 2 * margin, height - 2 * margin);
+ g2d.setColor(BORDER_COLOR);
+ g2d.drawOval(margin, margin / 2, width - 2 * margin, height - 2 * margin);
+ }
+
+ @EditableProperty
+ public Size getSpacing() {
+ return spacing;
+ }
+
+ public void setSpacing(Size spacing) {
+ this.spacing = spacing;
+ updateControlPoints();
+ body = null;
+ }
+
+ @EditableProperty
+ public Type getType() {
+ if (type == null)
+ type = Type.ThroughHole;
+ return type;
+ }
+
+ public void setType(Type type) {
+ this.type = type;
+ body = null;
+ }
+
+ @EditableProperty(name = "Nut")
+ public Color getNutColor() {
+ if (nutColor == null)
+ nutColor = NUT_COLOR;
+ return nutColor;
+ }
+
+ public void setNutColor(Color nutColor) {
+ this.nutColor = nutColor;
+ }
+
+ @EditableProperty(name = "Diameter")
+ public Size getBodyDiameter() {
+ return bodyDiameter;
+ }
+
+ public void setBodyDiameter(Size bodyDiameter) {
+ this.bodyDiameter = bodyDiameter;
+ body = null;
+ }
+
+ @EditableProperty(name = "Lug Size")
+ public Size getLugDiameter() {
+ return lugDiameter;
+ }
+
+ public void setLugDiameter(Size lugDiameter) {
+ this.lugDiameter = lugDiameter;
+ body = null;
+ }
+
+ @EditableProperty(name = "Body")
+ public Color getBodyColor() {
+ return bodyColor;
+ }
+
+ public void setBodyColor(Color bodyColor) {
+ this.bodyColor = bodyColor;
+ }
+
+ @EditableProperty(name = "Border")
+ public Color getBorderColor() {
+ return borderColor;
+ }
+
+ public void setBorderColor(Color borderColor) {
+ this.borderColor = borderColor;
+ }
+
+ @EditableProperty(name = "View")
+ public View getView() {
+ if (view == null)
+ view = showShaft ? View.ShaftUp : View.ShaftDown;
+ return view;
+ }
+
+ public void setView(View view) {
+ this.view = view;
+ body = null;
+ }
+
+ @EditableProperty(name = "Wafer")
+ public Color getWaferColor() {
+ if (waferColor == null)
+ waferColor = WAFER_COLOR;
+ return waferColor;
+ }
+
+ public void setWaferColor(Color waferColor) {
+ this.waferColor = waferColor;
+ }
+
+ @EditableProperty(name = "Markers")
+ public Boolean getShowMarkers() {
+ if (showMarkers == null) {
+ showMarkers = false;
+ }
+ return showMarkers;
+ }
+
+ public void setShowMarkers(Boolean showMarkers) {
+ this.showMarkers = showMarkers;
+ }
+
+ @EditableProperty(name = "Marker Color")
+ public Color getMarkerColor() {
+ if (markerColor == null) {
+ markerColor = MARKER_COLOR_DEFAULT;
+ }
+ return markerColor;
+ }
+
+ public void setMarkerColor(Color markerColor) {
+ this.markerColor = markerColor;
+ }
+
+ @Override
+ public String getInternalLinkName(int index1, int index2) {
+ if (index1 > index2)
+ return getInternalLinkName(index2, index1);
+
+ if (index2 - index1 == 1)
+ return (index1 + 1) + "-" + (index2 + 1);
+
+ return null;
+ }
+
+ @Override
+ public Rectangle2D getCachingBounds() {
+ Shape[] body = getBody();
+ int margin = 20;
+ double minX = 0;
+ double minY = 0;
+ double maxX = 0;
+ double maxY = 0;
+ for (Shape a : body) {
+ if (a != null) {
+ Rectangle2D bounds2d = a.getBounds2D();
+ if (bounds2d.getMinX() < minX)
+ minX = bounds2d.getMinX();
+ if (bounds2d.getMinY() < minY)
+ minY = bounds2d.getMinY();
+ if (bounds2d.getMaxX() > maxX)
+ maxX = bounds2d.getMaxX();
+ if (bounds2d.getMaxY() > maxY)
+ maxY = bounds2d.getMaxY();
+ }
+ }
+ return new Rectangle2D.Double(minX - margin, minY - margin, maxX - minX + 2 * margin, maxY - minY + 2 * margin);
+ }
+
+ @Override
+ public boolean canPointMoveFreely(int pointIndex) {
+ return false;
+ }
+
+ @Override
+ public int getLayerId() {
+ return hashCode();
+ }
+
+ public enum Type {
+ ThroughHole("Through Hole"), PCB("PCB");
+
+ private String value;
+
+ private Type(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+ }
+
+ public enum View {
+ ShaftDown("Shaft Down"), ShaftUp("Shaft Up");//, TerminalsDown, TerminalsUp;
+
+ private String value;
+
+ private View(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/passive/TrimmerPotentiometer.java b/diylc/diylc-library/src/main/java/org/diylc/components/passive/TrimmerPotentiometer.java
index bf62f8b62..903b1db1d 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/passive/TrimmerPotentiometer.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/passive/TrimmerPotentiometer.java
@@ -376,10 +376,7 @@ public class TrimmerPotentiometer extends AbstractPotentiometer {
Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
if (mainShape != null) {
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor);
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
g2d.fill(mainShape);
drawingObserver.stopTracking();
if (!outlineMode && shaftShape != null) {
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/BridgeRectifier.java b/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/BridgeRectifier.java
index cf2d7630a..e4c8296b1 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/BridgeRectifier.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/BridgeRectifier.java
@@ -34,12 +34,7 @@ import java.awt.geom.RoundRectangle2D;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.awt.StringUtils;
-import org.diylc.common.Display;
-import org.diylc.common.HorizontalAlignment;
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.Orientation;
-import org.diylc.common.VerticalAlignment;
+import org.diylc.common.*;
import org.diylc.components.AbstractLabeledComponent;
import org.diylc.components.RoundedPolygon;
import org.diylc.components.AbstractLeadedComponent.LabelOriantation;
@@ -117,7 +112,7 @@ public class BridgeRectifier extends AbstractLabeledComponent implements
public BridgeRectifier() {
super();
updateControlPoints();
- alpha = 100;
+ this.alphaPercent = new Percentage(100);
}
@EditableProperty
@@ -380,10 +375,7 @@ public class BridgeRectifier extends AbstractLabeledComponent implements
}
}
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getBodyColor());
g2d.fill(mainArea);
g2d.setComposite(oldComposite);
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/DIL_IC.java b/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/DIL_IC.java
index 09e2cfb58..c40425214 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/DIL_IC.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/DIL_IC.java
@@ -322,10 +322,7 @@ public class DIL_IC extends AbstractLabeledComponent implements IGerberC
g2d.draw(rect);
}
}
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getBodyColor());
drawingObserver.startTracking();
g2d.fill(mainArea);
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/ICSymbol.java b/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/ICSymbol.java
index 4958b70b1..c10e570a2 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/ICSymbol.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/ICSymbol.java
@@ -1,298 +1,295 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.semiconductors;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-import java.awt.Polygon;
-import java.awt.Shape;
-import java.awt.geom.Area;
-import java.awt.geom.GeneralPath;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.awt.StringUtils;
-import org.diylc.common.Display;
-import org.diylc.common.HorizontalAlignment;
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.VerticalAlignment;
-import org.diylc.components.AbstractTransparentComponent;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-import org.diylc.core.VisibilityPolicy;
-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;
-import org.diylc.utils.Constants;
-
-@ComponentDescriptor(name = "IC", author = "Branislav Stojkovic", category = "Schematic Symbols",
- instanceNamePrefix = "IC", description = "IC symbol with 3 or 5 contacts",
- zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_TAG_AND_VALUE, keywordTag = "Schematic")
-public class ICSymbol extends AbstractTransparentComponent {
-
- private static final long serialVersionUID = 1L;
-
- public static Size PIN_SPACING = new Size(0.1d, SizeUnit.in);
- public static Color BODY_COLOR = Color.white;
- public static Color BORDER_COLOR = Color.black;
-
- protected ICPointCount icPointCount = ICPointCount._5;
- protected String value = "";
- protected Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0), new Point2D.Double(0, 0), new Point2D.Double(0, 0), new Point2D.Double(0, 0),
- new Point2D.Double(0, 0)};
- protected Color bodyColor = BODY_COLOR;
- protected Color borderColor = BORDER_COLOR;
- protected Display display = Display.NAME;
- transient private Shape[] body;
- private Boolean flip;
-
- public ICSymbol() {
- super();
- updateControlPoints();
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- if (checkPointsClipped(g2d.getClip())) {
- return;
- }
- int pinSpacing = (int) PIN_SPACING.convertToPixels();
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
-
- Shape[] body = getBody();
-
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor);
- g2d.fill(body[0]);
- g2d.setComposite(oldComposite);
- Color finalBorderColor;
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalBorderColor = theme.getOutlineColor();
- } else {
- finalBorderColor = borderColor;
- }
- g2d.setColor(finalBorderColor);
- // Draw contacts
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
- g2d.draw(body[1]);
- // Draw triangle
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(2));
- g2d.draw(body[0]);
- // Draw label
- g2d.setFont(project.getFont());
- Color finalLabelColor;
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : theme.getOutlineColor();
- } else {
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : LABEL_COLOR;
- }
- g2d.setColor(finalLabelColor);
- double x = (controlPoints[0].getX() + controlPoints[2].getX()) / 2;
- String label = "";
- label = display == Display.VALUE ? getValue() : getName();
- if (display == Display.NONE) {
- label = "";
- }
- if (display == Display.BOTH) {
- label = getName() + " " + (getValue() == null ? "" : getValue().toString());
- }
- StringUtils.drawCenteredText(g2d, label, x, controlPoints[0].getY() + pinSpacing, HorizontalAlignment.CENTER,
- VerticalAlignment.CENTER);
- // Draw +/- markers
- StringUtils.drawCenteredText(g2d, getFlip() ? "+" : "-", controlPoints[0].getX() + pinSpacing, controlPoints[0].getY(), HorizontalAlignment.CENTER,
- VerticalAlignment.CENTER);
- StringUtils.drawCenteredText(g2d, getFlip() ? "-" : "+", controlPoints[1].getX() + pinSpacing, controlPoints[1].getY(), HorizontalAlignment.CENTER,
- VerticalAlignment.CENTER);
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int margin = 3 * width / 32;
- Area area =
- new Area(new Polygon(new int[] {margin, margin, width - margin},
- new int[] {margin, height - margin, height / 2}, 3));
- // area.subtract(new Area(new Rectangle2D.Double(0, 0, 2 * margin,
- // height)));
- area.intersect(new Area(new Rectangle2D.Double(2 * margin, 0, width, height)));
- g2d.setColor(BODY_COLOR);
- g2d.fill(area);
- g2d.setColor(BORDER_COLOR);
- g2d.setFont(LABEL_FONT.deriveFont(8f));
- StringUtils.drawCenteredText(g2d, "-", 3 * margin, height / 3, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
- StringUtils.drawCenteredText(g2d, "+", 3 * margin + 1, height * 2 / 3, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
- // g2d.setStroke(new BasicStroke(1f, BasicStroke.CAP_ROUND,
- // BasicStroke.JOIN_ROUND));
- g2d.draw(area);
- }
-
- @Override
- public Point2D getControlPoint(int index) {
- return controlPoints[index];
- }
-
- @Override
- public int getControlPointCount() {
- return icPointCount.getValue();
- }
-
- private void updateControlPoints() {
- int pinSpacing = (int) PIN_SPACING.convertToPixels();
- // Update control points.
- double x = controlPoints[0].getX();
- double y = controlPoints[0].getY();
-
- controlPoints[1].setLocation(x, y + pinSpacing * 2);
- controlPoints[2].setLocation(x + pinSpacing * 6, y + pinSpacing);
- controlPoints[3].setLocation(x + pinSpacing * 3, y - pinSpacing);
- controlPoints[4].setLocation(x + pinSpacing * 3, y + pinSpacing * 3);
- }
-
- public Shape[] getBody() {
- if (body == null) {
- body = new Shape[2];
- int pinSpacing = (int) PIN_SPACING.convertToPixels();
- int x = (int) controlPoints[0].getX();
- int y = (int) controlPoints[0].getY();
- Shape triangle =
- new Polygon(new int[] {x + pinSpacing / 2, x + pinSpacing * 11 / 2, x + pinSpacing / 2}, new int[] {
- y - pinSpacing * 3 / 2, y + pinSpacing, y + pinSpacing * 7 / 2}, 3);
- body[0] = triangle;
-
- GeneralPath polyline = new GeneralPath();
- polyline.moveTo(controlPoints[0].getX(), controlPoints[0].getY());
- polyline.lineTo(controlPoints[0].getX() + pinSpacing / 2, controlPoints[0].getY());
- polyline.moveTo(controlPoints[1].getX(), controlPoints[1].getY());
- polyline.lineTo(controlPoints[1].getX() + pinSpacing / 2, controlPoints[1].getY());
- polyline.moveTo(controlPoints[2].getX(), controlPoints[2].getY());
- polyline.lineTo(controlPoints[2].getX() - pinSpacing / 2, controlPoints[2].getY());
- if (icPointCount == ICPointCount._5) {
- polyline.moveTo(controlPoints[3].getX(), controlPoints[3].getY());
- polyline.lineTo(controlPoints[3].getX(), controlPoints[3].getY() + pinSpacing * 3 / 4);
- polyline.moveTo(controlPoints[4].getX(), controlPoints[4].getY());
- polyline.lineTo(controlPoints[4].getX(), controlPoints[4].getY() - pinSpacing * 3 / 4);
- }
- body[1] = polyline;
- }
- return body;
- }
-
- @Override
- public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
- return VisibilityPolicy.WHEN_SELECTED;
- }
-
- @EditableProperty
- @Override
- public String getValue() {
- return this.value;
- }
-
- @Override
- public void setValue(String value) {
- this.value = value;
- }
-
- @Override
- public boolean isControlPointSticky(int index) {
- return true;
- }
-
- @Override
- public void setControlPoint(Point2D point, int index) {
- controlPoints[index].setLocation(point);
- body = null;
- }
-
- @EditableProperty(name = "Contacts")
- public ICPointCount getIcPointCount() {
- return icPointCount;
- }
-
- public void setIcPointCount(ICPointCount icPointCount) {
- this.icPointCount = icPointCount;
- updateControlPoints();
- body = null;
- }
-
- @EditableProperty(name = "Body")
- public Color getBodyColor() {
- return bodyColor;
- }
-
- public void setBodyColor(Color bodyColor) {
- this.bodyColor = bodyColor;
- }
-
- @EditableProperty(name = "Border")
- public Color getBorderColor() {
- return borderColor;
- }
-
- public void setBorderColor(Color borderColor) {
- this.borderColor = borderColor;
- }
-
- @EditableProperty
- public Boolean getFlip() {
- if (flip == null)
- flip = false;
- return flip;
- }
-
- public void setFlip(Boolean flip) {
- this.flip = flip;
- }
-
- @EditableProperty
- public Display getDisplay() {
- return display;
- }
-
- public void setDisplay(Display display) {
- this.display = display;
- }
-
- @Override
- public boolean canPointMoveFreely(int pointIndex) {
- return false;
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.semiconductors;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Graphics2D;
+import java.awt.Polygon;
+import java.awt.Shape;
+import java.awt.geom.Area;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.awt.StringUtils;
+import org.diylc.common.Display;
+import org.diylc.common.HorizontalAlignment;
+import org.diylc.common.IPlugInPort;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.VerticalAlignment;
+import org.diylc.components.AbstractTransparentComponent;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+import org.diylc.core.VisibilityPolicy;
+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;
+import org.diylc.utils.Constants;
+
+@ComponentDescriptor(name = "IC", author = "Branislav Stojkovic", category = "Schematic Symbols",
+ instanceNamePrefix = "IC", description = "IC symbol with 3 or 5 contacts",
+ zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_TAG_AND_VALUE, keywordTag = "Schematic")
+public class ICSymbol extends AbstractTransparentComponent {
+
+ private static final long serialVersionUID = 1L;
+
+ public static Size PIN_SPACING = new Size(0.1d, SizeUnit.in);
+ public static Color BODY_COLOR = Color.white;
+ public static Color BORDER_COLOR = Color.black;
+
+ protected ICPointCount icPointCount = ICPointCount._5;
+ protected String value = "";
+ protected Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0), new Point2D.Double(0, 0), new Point2D.Double(0, 0), new Point2D.Double(0, 0),
+ new Point2D.Double(0, 0)};
+ protected Color bodyColor = BODY_COLOR;
+ protected Color borderColor = BORDER_COLOR;
+ protected Display display = Display.NAME;
+ transient private Shape[] body;
+ private Boolean flip;
+
+ public ICSymbol() {
+ super();
+ updateControlPoints();
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ if (checkPointsClipped(g2d.getClip())) {
+ return;
+ }
+ int pinSpacing = (int) PIN_SPACING.convertToPixels();
+ Composite oldComposite = applyAlpha(g2d, componentState);
+
+ Shape[] body = getBody();
+
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor);
+ g2d.fill(body[0]);
+ g2d.setComposite(oldComposite);
+ Color finalBorderColor;
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalBorderColor = theme.getOutlineColor();
+ } else {
+ finalBorderColor = borderColor;
+ }
+ g2d.setColor(finalBorderColor);
+ // Draw contacts
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+ g2d.draw(body[1]);
+ // Draw triangle
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(2));
+ g2d.draw(body[0]);
+ // Draw label
+ g2d.setFont(project.getFont());
+ Color finalLabelColor;
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : theme.getOutlineColor();
+ } else {
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : LABEL_COLOR;
+ }
+ g2d.setColor(finalLabelColor);
+ double x = (controlPoints[0].getX() + controlPoints[2].getX()) / 2;
+ String label = "";
+ label = display == Display.VALUE ? getValue() : getName();
+ if (display == Display.NONE) {
+ label = "";
+ }
+ if (display == Display.BOTH) {
+ label = getName() + " " + (getValue() == null ? "" : getValue().toString());
+ }
+ StringUtils.drawCenteredText(g2d, label, x, controlPoints[0].getY() + pinSpacing, HorizontalAlignment.CENTER,
+ VerticalAlignment.CENTER);
+ // Draw +/- markers
+ StringUtils.drawCenteredText(g2d, getFlip() ? "+" : "-", controlPoints[0].getX() + pinSpacing, controlPoints[0].getY(), HorizontalAlignment.CENTER,
+ VerticalAlignment.CENTER);
+ StringUtils.drawCenteredText(g2d, getFlip() ? "-" : "+", controlPoints[1].getX() + pinSpacing, controlPoints[1].getY(), HorizontalAlignment.CENTER,
+ VerticalAlignment.CENTER);
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int margin = 3 * width / 32;
+ Area area =
+ new Area(new Polygon(new int[] {margin, margin, width - margin},
+ new int[] {margin, height - margin, height / 2}, 3));
+ // area.subtract(new Area(new Rectangle2D.Double(0, 0, 2 * margin,
+ // height)));
+ area.intersect(new Area(new Rectangle2D.Double(2 * margin, 0, width, height)));
+ g2d.setColor(BODY_COLOR);
+ g2d.fill(area);
+ g2d.setColor(BORDER_COLOR);
+ g2d.setFont(LABEL_FONT.deriveFont(8f));
+ StringUtils.drawCenteredText(g2d, "-", 3 * margin, height / 3, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
+ StringUtils.drawCenteredText(g2d, "+", 3 * margin + 1, height * 2 / 3, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
+ // g2d.setStroke(new BasicStroke(1f, BasicStroke.CAP_ROUND,
+ // BasicStroke.JOIN_ROUND));
+ g2d.draw(area);
+ }
+
+ @Override
+ public Point2D getControlPoint(int index) {
+ return controlPoints[index];
+ }
+
+ @Override
+ public int getControlPointCount() {
+ return icPointCount.getValue();
+ }
+
+ private void updateControlPoints() {
+ int pinSpacing = (int) PIN_SPACING.convertToPixels();
+ // Update control points.
+ double x = controlPoints[0].getX();
+ double y = controlPoints[0].getY();
+
+ controlPoints[1].setLocation(x, y + pinSpacing * 2);
+ controlPoints[2].setLocation(x + pinSpacing * 6, y + pinSpacing);
+ controlPoints[3].setLocation(x + pinSpacing * 3, y - pinSpacing);
+ controlPoints[4].setLocation(x + pinSpacing * 3, y + pinSpacing * 3);
+ }
+
+ public Shape[] getBody() {
+ if (body == null) {
+ body = new Shape[2];
+ int pinSpacing = (int) PIN_SPACING.convertToPixels();
+ int x = (int) controlPoints[0].getX();
+ int y = (int) controlPoints[0].getY();
+ Shape triangle =
+ new Polygon(new int[] {x + pinSpacing / 2, x + pinSpacing * 11 / 2, x + pinSpacing / 2}, new int[] {
+ y - pinSpacing * 3 / 2, y + pinSpacing, y + pinSpacing * 7 / 2}, 3);
+ body[0] = triangle;
+
+ GeneralPath polyline = new GeneralPath();
+ polyline.moveTo(controlPoints[0].getX(), controlPoints[0].getY());
+ polyline.lineTo(controlPoints[0].getX() + pinSpacing / 2, controlPoints[0].getY());
+ polyline.moveTo(controlPoints[1].getX(), controlPoints[1].getY());
+ polyline.lineTo(controlPoints[1].getX() + pinSpacing / 2, controlPoints[1].getY());
+ polyline.moveTo(controlPoints[2].getX(), controlPoints[2].getY());
+ polyline.lineTo(controlPoints[2].getX() - pinSpacing / 2, controlPoints[2].getY());
+ if (icPointCount == ICPointCount._5) {
+ polyline.moveTo(controlPoints[3].getX(), controlPoints[3].getY());
+ polyline.lineTo(controlPoints[3].getX(), controlPoints[3].getY() + pinSpacing * 3 / 4);
+ polyline.moveTo(controlPoints[4].getX(), controlPoints[4].getY());
+ polyline.lineTo(controlPoints[4].getX(), controlPoints[4].getY() - pinSpacing * 3 / 4);
+ }
+ body[1] = polyline;
+ }
+ return body;
+ }
+
+ @Override
+ public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
+ return VisibilityPolicy.WHEN_SELECTED;
+ }
+
+ @EditableProperty
+ @Override
+ public String getValue() {
+ return this.value;
+ }
+
+ @Override
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public boolean isControlPointSticky(int index) {
+ return true;
+ }
+
+ @Override
+ public void setControlPoint(Point2D point, int index) {
+ controlPoints[index].setLocation(point);
+ body = null;
+ }
+
+ @EditableProperty(name = "Contacts")
+ public ICPointCount getIcPointCount() {
+ return icPointCount;
+ }
+
+ public void setIcPointCount(ICPointCount icPointCount) {
+ this.icPointCount = icPointCount;
+ updateControlPoints();
+ body = null;
+ }
+
+ @EditableProperty(name = "Body")
+ public Color getBodyColor() {
+ return bodyColor;
+ }
+
+ public void setBodyColor(Color bodyColor) {
+ this.bodyColor = bodyColor;
+ }
+
+ @EditableProperty(name = "Border")
+ public Color getBorderColor() {
+ return borderColor;
+ }
+
+ public void setBorderColor(Color borderColor) {
+ this.borderColor = borderColor;
+ }
+
+ @EditableProperty
+ public Boolean getFlip() {
+ if (flip == null)
+ flip = false;
+ return flip;
+ }
+
+ public void setFlip(Boolean flip) {
+ this.flip = flip;
+ }
+
+ @EditableProperty
+ public Display getDisplay() {
+ return display;
+ }
+
+ public void setDisplay(Display display) {
+ this.display = display;
+ }
+
+ @Override
+ public boolean canPointMoveFreely(int pointIndex) {
+ return false;
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/LogicGateSymbol.java b/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/LogicGateSymbol.java
index 7fe767d55..0d00c9913 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/LogicGateSymbol.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/LogicGateSymbol.java
@@ -82,10 +82,7 @@ public class LogicGateSymbol extends AbstractTransparentComponent {
return;
}
int pinSpacing = (int) PIN_SPACING.convertToPixels();
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
Shape[] body = getBody();
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/MultiwattIC.java b/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/MultiwattIC.java
index 1da245569..3f574d092 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/MultiwattIC.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/MultiwattIC.java
@@ -32,10 +32,7 @@ import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import org.diylc.appframework.miscutils.ConfigurationManager;
-import org.diylc.common.Display;
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.Orientation;
+import org.diylc.common.*;
import org.diylc.components.AbstractTransparentComponent;
import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent;
@@ -92,7 +89,7 @@ public class MultiwattIC extends AbstractTransparentComponent implements
public MultiwattIC() {
super();
updateControlPoints();
- alpha = 100;
+ this.alphaPercent = new Percentage(100);
}
@EditableProperty
@@ -421,10 +418,7 @@ public class MultiwattIC extends AbstractTransparentComponent implements
}
drawingObserver.startTracking();
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getBodyColor());
g2d.fill(mainArea);
drawingObserver.stopTracking();
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/SIL_IC.java b/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/SIL_IC.java
index 7e727344e..bc3be000d 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/SIL_IC.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/SIL_IC.java
@@ -1,472 +1,466 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.semiconductors;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.FontMetrics;
-import java.awt.Graphics2D;
-import java.awt.Rectangle;
-import java.awt.geom.Area;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.geom.RoundRectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.common.Display;
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.Orientation;
-import org.diylc.components.AbstractTransparentComponent;
-import org.diylc.components.transform.SIL_ICTransformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-import org.diylc.core.VisibilityPolicy;
-import org.diylc.core.annotations.ComponentDescriptor;
-import org.diylc.core.annotations.EditableProperty;
-import org.diylc.core.annotations.KeywordPolicy;
-import org.diylc.core.annotations.PositiveNonZeroMeasureValidator;
-import org.diylc.core.gerber.IGerberComponentSimple;
-import org.diylc.core.measures.Size;
-import org.diylc.core.measures.SizeUnit;
-import org.diylc.utils.Constants;
-
-@ComponentDescriptor(name = "SIP IC", author = "Branislav Stojkovic", category = "Semiconductors",
- instanceNamePrefix = "IC", description = "Single-in-line package IC",
- zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_VALUE, transformer = SIL_ICTransformer.class,
- enableCache = true)
-public class SIL_IC extends AbstractTransparentComponent implements IGerberComponentSimple {
-
- private static final long serialVersionUID = 1L;
-
- public static Color BODY_COLOR = Color.gray;
- public static Color BORDER_COLOR = Color.gray.darker();
- public static Color PIN_COLOR = Color.decode("#00B2EE");
- public static Color PIN_BORDER_COLOR = PIN_COLOR.darker();
- public static Color INDENT_COLOR = Color.gray.darker();
- public static Color LABEL_COLOR = Color.white;
- public static int EDGE_RADIUS = 6;
- public static Size PIN_SIZE = new Size(0.8d, SizeUnit.mm);
- public static Size INDENT_SIZE = new Size(0.07d, SizeUnit.in);
- public static Size THICKNESS = new Size(0.13d, SizeUnit.in);
-
- private String value = "";
- private Orientation orientation = Orientation.DEFAULT;
- private PinCount pinCount = PinCount._8;
- private Size pinSpacing = new Size(0.1d, SizeUnit.in);
- private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0)};
- protected Display display = Display.NAME;
- private Color bodyColor = BODY_COLOR;
- private Color borderColor = BORDER_COLOR;
- private Color labelColor = LABEL_COLOR;
- private Color indentColor = INDENT_COLOR;
- // new Point(0, pinSpacing.convertToPixels()),
- // new Point(0, 2 * pinSpacing.convertToPixels()),
- // new Point(0, 3 * pinSpacing.convertToPixels()),
- // new Point(3 * pinSpacing.convertToPixels(), 0),
- // new Point(3 * pinSpacing.convertToPixels(),
- // pinSpacing.convertToPixels()),
- // new Point(3 * pinSpacing.convertToPixels(), 2 *
- // pinSpacing.convertToPixels()),
- // new Point(3 * pinSpacing.convertToPixels(), 3 *
- // pinSpacing.convertToPixels()) };
- transient private Area[] body;
-
- public SIL_IC() {
- super();
- updateControlPoints();
- alpha = 100;
- }
-
- @EditableProperty
- public String getValue() {
- return value;
- }
-
- public void setValue(String value) {
- this.value = value;
- }
-
- @EditableProperty
- public Orientation getOrientation() {
- return orientation;
- }
-
- public void setOrientation(Orientation orientation) {
- this.orientation = orientation;
- updateControlPoints();
- // Reset body shape.
- body = null;
- }
-
- @EditableProperty(name = "Pins")
- public PinCount getPinCount() {
- return pinCount;
- }
-
- public void setPinCount(PinCount pinCount) {
- this.pinCount = pinCount;
- updateControlPoints();
- // Reset body shape;
- body = null;
- }
-
- @EditableProperty(name = "Pin Spacing", validatorClass = PositiveNonZeroMeasureValidator.class)
- public Size getPinSpacing() {
- return pinSpacing;
- }
-
- public void setPinSpacing(Size pinSpacing) {
- this.pinSpacing = pinSpacing;
- updateControlPoints();
- // Reset body shape;
- body = null;
- }
-
- @Override
- public boolean canPointMoveFreely(int pointIndex) {
- return false;
- }
-
- @EditableProperty
- public Display getDisplay() {
- if (display == null) {
- display = Display.VALUE;
- }
- return display;
- }
-
- public void setDisplay(Display display) {
- this.display = display;
- }
-
- @Override
- public int getControlPointCount() {
- return controlPoints.length;
- }
-
- @Override
- public Point2D getControlPoint(int index) {
- return controlPoints[index];
- }
-
- @Override
- public boolean isControlPointSticky(int index) {
- return true;
- }
-
- @Override
- public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
- return VisibilityPolicy.NEVER;
- }
-
- @Override
- public void setControlPoint(Point2D point, int index) {
- controlPoints[index].setLocation(point);
- body = null;
- }
-
- private void updateControlPoints() {
- Point2D firstPoint = controlPoints[0];
- controlPoints = new Point2D.Double[pinCount.getValue()];
- controlPoints[0] = firstPoint;
- double pinSpacing = this.pinSpacing.convertToPixels();
- // Update control points.
- double dx1;
- double dy1;
- for (int i = 0; i < pinCount.getValue(); i++) {
- switch (orientation) {
- case DEFAULT:
- dx1 = 0;
- dy1 = i * pinSpacing;
- break;
- case _90:
- dx1 = -i * pinSpacing;
- dy1 = 0;
- break;
- case _180:
- dx1 = 0;
- dy1 = -i * pinSpacing;
- break;
- case _270:
- dx1 = i * pinSpacing;
- dy1 = 0;
- break;
- default:
- throw new RuntimeException("Unexpected orientation: " + orientation);
- }
- controlPoints[i] = new Point2D.Double((int) (firstPoint.getX() + dx1), (int) (firstPoint.getY() + dy1));
- }
- }
-
- public Area[] getBody() {
- if (body == null) {
- body = new Area[2];
- double x = controlPoints[0].getX();
- double y = controlPoints[0].getY();
- int thickness = getClosestOdd(THICKNESS.convertToPixels());
- double width;
- double height;
- double pinSpacing = (int) this.pinSpacing.convertToPixels();
- Area indentation = null;
- int indentationSize = getClosestOdd(INDENT_SIZE.convertToPixels());
- switch (orientation) {
- case DEFAULT:
- width = thickness;
- height = pinCount.getValue() * pinSpacing;
- x -= thickness / 2;
- y -= pinSpacing / 2;
- indentation =
- new Area(new Ellipse2D.Double(x + width / 2 - indentationSize / 2, y - indentationSize / 2,
- indentationSize, indentationSize));
- break;
- case _90:
- width = pinCount.getValue() * pinSpacing;
- height = thickness;
- x -= (pinSpacing / 2) + width - pinSpacing;
- y -= thickness / 2;
- indentation =
- new Area(new Ellipse2D.Double(x + width - indentationSize / 2, y + height / 2 - indentationSize / 2,
- indentationSize, indentationSize));
- break;
- case _180:
- width = thickness;
- height = pinCount.getValue() * pinSpacing;
- x -= thickness / 2;
- y -= (pinSpacing / 2) + height - pinSpacing;
- indentation =
- new Area(new Ellipse2D.Double(x + width / 2 - indentationSize / 2, y + height - indentationSize / 2,
- indentationSize, indentationSize));
- break;
- case _270:
- width = pinCount.getValue() * pinSpacing;
- height = thickness;
- x -= pinSpacing / 2;
- y -= thickness / 2;
- indentation =
- new Area(new Ellipse2D.Double(x - indentationSize / 2, y + height / 2 - indentationSize / 2,
- indentationSize, indentationSize));
- break;
- default:
- throw new RuntimeException("Unexpected orientation: " + orientation);
- }
- body[0] = new Area(new RoundRectangle2D.Double(x, y, width, height, EDGE_RADIUS, EDGE_RADIUS));
- body[1] = indentation;
- if (indentation != null) {
- indentation.intersect(body[0]);
- }
- }
- return body;
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- if (checkPointsClipped(g2d.getClip())) {
- return;
- }
- Area mainArea = getBody()[0];
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f));
- if (!outlineMode) {
- 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.setColor(PIN_BORDER_COLOR);
- g2d.drawOval((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize);
- }
- }
-
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getBodyColor());
- g2d.fill(mainArea);
- drawingObserver.stopTracking();
- g2d.setComposite(oldComposite);
-
- Color finalBorderColor;
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : getBorderColor();
- }
- g2d.setColor(finalBorderColor);
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
- if (outlineMode) {
- Area area = new Area(mainArea);
- area.subtract(getBody()[1]);
- g2d.draw(area);
- } else {
- g2d.draw(mainArea);
- if (getBody()[1] != null) {
- g2d.setColor(getIndentColor());
- g2d.fill(getBody()[1]);
- }
- }
- // Draw label.
- g2d.setFont(project.getFont());
- Color finalLabelColor;
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : theme.getOutlineColor();
- } else {
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : getLabelColor();
- }
- g2d.setColor(finalLabelColor);
- FontMetrics fontMetrics = g2d.getFontMetrics(g2d.getFont());
- String label = "";
- label = (getDisplay() == Display.NAME) ? getName() : getValue();
- if (getDisplay() == Display.NONE) {
- label = "";
- }
- if (getDisplay() == Display.BOTH) {
- label = getName() + " " + (getValue() == null ? "" : getValue().toString());
- }
- Rectangle2D rect = fontMetrics.getStringBounds(label, g2d);
- int textHeight = (int) (rect.getHeight());
- int textWidth = (int) (rect.getWidth());
- // Center text horizontally and vertically
- Rectangle bounds = mainArea.getBounds();
- int x = (int) (bounds.getX() + (bounds.width - textWidth) / 2);
- int y = (int) (bounds.getY() + (bounds.height - textHeight) / 2 + fontMetrics.getAscent());
- g2d.drawString(label, x, y);
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int radius = 6 * width / 32;
- int thickness = getClosestOdd(width / 3);
- g2d.rotate(Math.PI / 4, width / 2, height / 2);
- g2d.setColor(BODY_COLOR);
- g2d.fillRoundRect((width - thickness) / 2, 0, thickness, height, radius, radius);
- g2d.setColor(BORDER_COLOR);
- g2d.drawRoundRect((width - thickness) / 2, 0, thickness, height, radius, radius);
- int pinSize = 2 * width / 32;
- g2d.setColor(PIN_COLOR);
- for (int i = 0; i < 4; i++) {
- g2d.fillOval(width / 2 - pinSize / 2, (height / 5) * (i + 1), pinSize, pinSize);
- }
- }
-
- @EditableProperty(name = "Body")
- public Color getBodyColor() {
- if (bodyColor == null) {
- bodyColor = BODY_COLOR;
- }
- return bodyColor;
- }
-
- public void setBodyColor(Color bodyColor) {
- this.bodyColor = bodyColor;
- }
-
- @EditableProperty(name = "Border")
- public Color getBorderColor() {
- if (borderColor == null) {
- borderColor = BORDER_COLOR;
- }
- return borderColor;
- }
-
- public void setBorderColor(Color borderColor) {
- this.borderColor = borderColor;
- }
-
- @EditableProperty(name = "Label")
- public Color getLabelColor() {
- if (labelColor == null) {
- labelColor = LABEL_COLOR;
- }
- return labelColor;
- }
-
- public void setLabelColor(Color labelColor) {
- this.labelColor = labelColor;
- }
-
- @EditableProperty(name = "Indent")
- public Color getIndentColor() {
- if (indentColor == null) {
- indentColor = INDENT_COLOR;
- }
- return indentColor;
- }
-
- public void setIndentColor(Color indentColor) {
- this.indentColor = indentColor;
- }
-
- @Override
- public Rectangle2D getCachingBounds() {
- double minX = Integer.MAX_VALUE;
- double maxX = Integer.MIN_VALUE;
- double minY = Integer.MAX_VALUE;
- double maxY = Integer.MIN_VALUE;
- int margin = 50;
- for (int i = 0; i < getControlPointCount(); i++) {
- Point2D p = getControlPoint(i);
- if (p.getX() < minX)
- minX = p.getX();
- if (p.getX() > maxX)
- maxX = p.getX();
- if (p.getY() < minY)
- minY = p.getY();
- if (p.getY() > maxY)
- maxY = p.getY();
- }
-
- return new Rectangle2D.Double(minX - margin, minY - margin, maxX - minX + 2 * margin, maxY - minY + 2 * margin);
- }
-
- public static enum PinCount {
-
- _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20;
-
- @Override
- public String toString() {
- return name().replace("_", "");
- }
-
- public int getValue() {
- return Integer.parseInt(toString());
- }
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.semiconductors;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.geom.Area;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.common.*;
+import org.diylc.components.AbstractTransparentComponent;
+import org.diylc.components.transform.SIL_ICTransformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+import org.diylc.core.VisibilityPolicy;
+import org.diylc.core.annotations.ComponentDescriptor;
+import org.diylc.core.annotations.EditableProperty;
+import org.diylc.core.annotations.KeywordPolicy;
+import org.diylc.core.annotations.PositiveNonZeroMeasureValidator;
+import org.diylc.core.gerber.IGerberComponentSimple;
+import org.diylc.core.measures.Size;
+import org.diylc.core.measures.SizeUnit;
+import org.diylc.utils.Constants;
+
+@ComponentDescriptor(name = "SIP IC", author = "Branislav Stojkovic", category = "Semiconductors",
+ instanceNamePrefix = "IC", description = "Single-in-line package IC",
+ zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_VALUE, transformer = SIL_ICTransformer.class,
+ enableCache = true)
+public class SIL_IC extends AbstractTransparentComponent implements IGerberComponentSimple {
+
+ private static final long serialVersionUID = 1L;
+
+ public static Color BODY_COLOR = Color.gray;
+ public static Color BORDER_COLOR = Color.gray.darker();
+ public static Color PIN_COLOR = Color.decode("#00B2EE");
+ public static Color PIN_BORDER_COLOR = PIN_COLOR.darker();
+ public static Color INDENT_COLOR = Color.gray.darker();
+ public static Color LABEL_COLOR = Color.white;
+ public static int EDGE_RADIUS = 6;
+ public static Size PIN_SIZE = new Size(0.8d, SizeUnit.mm);
+ public static Size INDENT_SIZE = new Size(0.07d, SizeUnit.in);
+ public static Size THICKNESS = new Size(0.13d, SizeUnit.in);
+
+ private String value = "";
+ private Orientation orientation = Orientation.DEFAULT;
+ private PinCount pinCount = PinCount._8;
+ private Size pinSpacing = new Size(0.1d, SizeUnit.in);
+ private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0)};
+ protected Display display = Display.NAME;
+ private Color bodyColor = BODY_COLOR;
+ private Color borderColor = BORDER_COLOR;
+ private Color labelColor = LABEL_COLOR;
+ private Color indentColor = INDENT_COLOR;
+ // new Point(0, pinSpacing.convertToPixels()),
+ // new Point(0, 2 * pinSpacing.convertToPixels()),
+ // new Point(0, 3 * pinSpacing.convertToPixels()),
+ // new Point(3 * pinSpacing.convertToPixels(), 0),
+ // new Point(3 * pinSpacing.convertToPixels(),
+ // pinSpacing.convertToPixels()),
+ // new Point(3 * pinSpacing.convertToPixels(), 2 *
+ // pinSpacing.convertToPixels()),
+ // new Point(3 * pinSpacing.convertToPixels(), 3 *
+ // pinSpacing.convertToPixels()) };
+ transient private Area[] body;
+
+ public SIL_IC() {
+ super();
+ updateControlPoints();
+ this.alphaPercent = new Percentage(100);
+ }
+
+ @EditableProperty
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ @EditableProperty
+ public Orientation getOrientation() {
+ return orientation;
+ }
+
+ public void setOrientation(Orientation orientation) {
+ this.orientation = orientation;
+ updateControlPoints();
+ // Reset body shape.
+ body = null;
+ }
+
+ @EditableProperty(name = "Pins")
+ public PinCount getPinCount() {
+ return pinCount;
+ }
+
+ public void setPinCount(PinCount pinCount) {
+ this.pinCount = pinCount;
+ updateControlPoints();
+ // Reset body shape;
+ body = null;
+ }
+
+ @EditableProperty(name = "Pin Spacing", validatorClass = PositiveNonZeroMeasureValidator.class)
+ public Size getPinSpacing() {
+ return pinSpacing;
+ }
+
+ public void setPinSpacing(Size pinSpacing) {
+ this.pinSpacing = pinSpacing;
+ updateControlPoints();
+ // Reset body shape;
+ body = null;
+ }
+
+ @Override
+ public boolean canPointMoveFreely(int pointIndex) {
+ return false;
+ }
+
+ @EditableProperty
+ public Display getDisplay() {
+ if (display == null) {
+ display = Display.VALUE;
+ }
+ return display;
+ }
+
+ public void setDisplay(Display display) {
+ this.display = display;
+ }
+
+ @Override
+ public int getControlPointCount() {
+ return controlPoints.length;
+ }
+
+ @Override
+ public Point2D getControlPoint(int index) {
+ return controlPoints[index];
+ }
+
+ @Override
+ public boolean isControlPointSticky(int index) {
+ return true;
+ }
+
+ @Override
+ public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
+ return VisibilityPolicy.NEVER;
+ }
+
+ @Override
+ public void setControlPoint(Point2D point, int index) {
+ controlPoints[index].setLocation(point);
+ body = null;
+ }
+
+ private void updateControlPoints() {
+ Point2D firstPoint = controlPoints[0];
+ controlPoints = new Point2D.Double[pinCount.getValue()];
+ controlPoints[0] = firstPoint;
+ double pinSpacing = this.pinSpacing.convertToPixels();
+ // Update control points.
+ double dx1;
+ double dy1;
+ for (int i = 0; i < pinCount.getValue(); i++) {
+ switch (orientation) {
+ case DEFAULT:
+ dx1 = 0;
+ dy1 = i * pinSpacing;
+ break;
+ case _90:
+ dx1 = -i * pinSpacing;
+ dy1 = 0;
+ break;
+ case _180:
+ dx1 = 0;
+ dy1 = -i * pinSpacing;
+ break;
+ case _270:
+ dx1 = i * pinSpacing;
+ dy1 = 0;
+ break;
+ default:
+ throw new RuntimeException("Unexpected orientation: " + orientation);
+ }
+ controlPoints[i] = new Point2D.Double((int) (firstPoint.getX() + dx1), (int) (firstPoint.getY() + dy1));
+ }
+ }
+
+ public Area[] getBody() {
+ if (body == null) {
+ body = new Area[2];
+ double x = controlPoints[0].getX();
+ double y = controlPoints[0].getY();
+ int thickness = getClosestOdd(THICKNESS.convertToPixels());
+ double width;
+ double height;
+ double pinSpacing = (int) this.pinSpacing.convertToPixels();
+ Area indentation = null;
+ int indentationSize = getClosestOdd(INDENT_SIZE.convertToPixels());
+ switch (orientation) {
+ case DEFAULT:
+ width = thickness;
+ height = pinCount.getValue() * pinSpacing;
+ x -= thickness / 2;
+ y -= pinSpacing / 2;
+ indentation =
+ new Area(new Ellipse2D.Double(x + width / 2 - indentationSize / 2, y - indentationSize / 2,
+ indentationSize, indentationSize));
+ break;
+ case _90:
+ width = pinCount.getValue() * pinSpacing;
+ height = thickness;
+ x -= (pinSpacing / 2) + width - pinSpacing;
+ y -= thickness / 2;
+ indentation =
+ new Area(new Ellipse2D.Double(x + width - indentationSize / 2, y + height / 2 - indentationSize / 2,
+ indentationSize, indentationSize));
+ break;
+ case _180:
+ width = thickness;
+ height = pinCount.getValue() * pinSpacing;
+ x -= thickness / 2;
+ y -= (pinSpacing / 2) + height - pinSpacing;
+ indentation =
+ new Area(new Ellipse2D.Double(x + width / 2 - indentationSize / 2, y + height - indentationSize / 2,
+ indentationSize, indentationSize));
+ break;
+ case _270:
+ width = pinCount.getValue() * pinSpacing;
+ height = thickness;
+ x -= pinSpacing / 2;
+ y -= thickness / 2;
+ indentation =
+ new Area(new Ellipse2D.Double(x - indentationSize / 2, y + height / 2 - indentationSize / 2,
+ indentationSize, indentationSize));
+ break;
+ default:
+ throw new RuntimeException("Unexpected orientation: " + orientation);
+ }
+ body[0] = new Area(new RoundRectangle2D.Double(x, y, width, height, EDGE_RADIUS, EDGE_RADIUS));
+ body[1] = indentation;
+ if (indentation != null) {
+ indentation.intersect(body[0]);
+ }
+ }
+ return body;
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ if (checkPointsClipped(g2d.getClip())) {
+ return;
+ }
+ Area mainArea = getBody()[0];
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f));
+ if (!outlineMode) {
+ 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.setColor(PIN_BORDER_COLOR);
+ g2d.drawOval((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize);
+ }
+ }
+
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getBodyColor());
+ g2d.fill(mainArea);
+ drawingObserver.stopTracking();
+ g2d.setComposite(oldComposite);
+
+ Color finalBorderColor;
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : getBorderColor();
+ }
+ g2d.setColor(finalBorderColor);
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+ if (outlineMode) {
+ Area area = new Area(mainArea);
+ area.subtract(getBody()[1]);
+ g2d.draw(area);
+ } else {
+ g2d.draw(mainArea);
+ if (getBody()[1] != null) {
+ g2d.setColor(getIndentColor());
+ g2d.fill(getBody()[1]);
+ }
+ }
+ // Draw label.
+ g2d.setFont(project.getFont());
+ Color finalLabelColor;
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : theme.getOutlineColor();
+ } else {
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : getLabelColor();
+ }
+ g2d.setColor(finalLabelColor);
+ FontMetrics fontMetrics = g2d.getFontMetrics(g2d.getFont());
+ String label = "";
+ label = (getDisplay() == Display.NAME) ? getName() : getValue();
+ if (getDisplay() == Display.NONE) {
+ label = "";
+ }
+ if (getDisplay() == Display.BOTH) {
+ label = getName() + " " + (getValue() == null ? "" : getValue().toString());
+ }
+ Rectangle2D rect = fontMetrics.getStringBounds(label, g2d);
+ int textHeight = (int) (rect.getHeight());
+ int textWidth = (int) (rect.getWidth());
+ // Center text horizontally and vertically
+ Rectangle bounds = mainArea.getBounds();
+ int x = (int) (bounds.getX() + (bounds.width - textWidth) / 2);
+ int y = (int) (bounds.getY() + (bounds.height - textHeight) / 2 + fontMetrics.getAscent());
+ g2d.drawString(label, x, y);
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int radius = 6 * width / 32;
+ int thickness = getClosestOdd(width / 3);
+ g2d.rotate(Math.PI / 4, width / 2, height / 2);
+ g2d.setColor(BODY_COLOR);
+ g2d.fillRoundRect((width - thickness) / 2, 0, thickness, height, radius, radius);
+ g2d.setColor(BORDER_COLOR);
+ g2d.drawRoundRect((width - thickness) / 2, 0, thickness, height, radius, radius);
+ int pinSize = 2 * width / 32;
+ g2d.setColor(PIN_COLOR);
+ for (int i = 0; i < 4; i++) {
+ g2d.fillOval(width / 2 - pinSize / 2, (height / 5) * (i + 1), pinSize, pinSize);
+ }
+ }
+
+ @EditableProperty(name = "Body")
+ public Color getBodyColor() {
+ if (bodyColor == null) {
+ bodyColor = BODY_COLOR;
+ }
+ return bodyColor;
+ }
+
+ public void setBodyColor(Color bodyColor) {
+ this.bodyColor = bodyColor;
+ }
+
+ @EditableProperty(name = "Border")
+ public Color getBorderColor() {
+ if (borderColor == null) {
+ borderColor = BORDER_COLOR;
+ }
+ return borderColor;
+ }
+
+ public void setBorderColor(Color borderColor) {
+ this.borderColor = borderColor;
+ }
+
+ @EditableProperty(name = "Label")
+ public Color getLabelColor() {
+ if (labelColor == null) {
+ labelColor = LABEL_COLOR;
+ }
+ return labelColor;
+ }
+
+ public void setLabelColor(Color labelColor) {
+ this.labelColor = labelColor;
+ }
+
+ @EditableProperty(name = "Indent")
+ public Color getIndentColor() {
+ if (indentColor == null) {
+ indentColor = INDENT_COLOR;
+ }
+ return indentColor;
+ }
+
+ public void setIndentColor(Color indentColor) {
+ this.indentColor = indentColor;
+ }
+
+ @Override
+ public Rectangle2D getCachingBounds() {
+ double minX = Integer.MAX_VALUE;
+ double maxX = Integer.MIN_VALUE;
+ double minY = Integer.MAX_VALUE;
+ double maxY = Integer.MIN_VALUE;
+ int margin = 50;
+ for (int i = 0; i < getControlPointCount(); i++) {
+ Point2D p = getControlPoint(i);
+ if (p.getX() < minX)
+ minX = p.getX();
+ if (p.getX() > maxX)
+ maxX = p.getX();
+ if (p.getY() < minY)
+ minY = p.getY();
+ if (p.getY() > maxY)
+ maxY = p.getY();
+ }
+
+ return new Rectangle2D.Double(minX - margin, minY - margin, maxX - minX + 2 * margin, maxY - minY + 2 * margin);
+ }
+
+ public static enum PinCount {
+
+ _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20;
+
+ @Override
+ public String toString() {
+ return name().replace("_", "");
+ }
+
+ public int getValue() {
+ return Integer.parseInt(toString());
+ }
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/TransistorTO1.java b/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/TransistorTO1.java
index 4a1b01900..4d9631ea5 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/TransistorTO1.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/TransistorTO1.java
@@ -1,280 +1,278 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.semiconductors;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.FontMetrics;
-import java.awt.Graphics2D;
-import java.awt.Rectangle;
-import java.awt.Shape;
-import java.awt.geom.Area;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.geom.RoundRectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.components.transform.TO1Transformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-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;
-import org.diylc.utils.Constants;
-
-@ComponentDescriptor(name = "Transistor (TO-1)", author = "Branislav Stojkovic", category = "Semiconductors",
- instanceNamePrefix = "Q", description = "Transistor with small metal body",
- zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_VALUE, transformer = TO1Transformer.class,
- enableCache = true)
-public class TransistorTO1 extends AbstractTransistorPackage {
-
- private static final long serialVersionUID = 1L;
-
- public static Color BODY_COLOR = Color.lightGray;
- public static Color BORDER_COLOR = BODY_COLOR.darker();
- public static Color PIN_COLOR = Color.decode("#00B2EE");
- public static Color PIN_BORDER_COLOR = PIN_COLOR.darker();
- public static Color LABEL_COLOR = Color.black;
- public static Size PIN_SIZE = new Size(0.03d, SizeUnit.in);
- public static Size PIN_SPACING = new Size(0.05d, SizeUnit.in);
- public static Size BODY_DIAMETER = new Size(0.24d, SizeUnit.in);
- public static Size BODY_LENGTH = new Size(0.4d, SizeUnit.in);
- public static Size EDGE_RADIUS = new Size(2d, SizeUnit.mm);
-
- private Size pinSpacing = PIN_SPACING;
-
- public TransistorTO1() {
- super();
- updateControlPoints();
- alpha = (byte) 100;
- bodyColor = BODY_COLOR;
- borderColor = BORDER_COLOR;
- }
-
- @Override
- protected void updateControlPoints() {
- int pinSpacing = (int) getPinSpacing().convertToPixels();
- // Update control points.
- double x = controlPoints[0].getX();
- double y = controlPoints[0].getY();
- switch (orientation) {
- case DEFAULT:
- controlPoints[1].setLocation(x - (folded ? 0 : pinSpacing), y + pinSpacing);
- controlPoints[2].setLocation(x, y + 2 * pinSpacing);
- break;
- case _90:
- controlPoints[1].setLocation(x - pinSpacing, y - (folded ? 0 : pinSpacing));
- controlPoints[2].setLocation(x - 2 * pinSpacing, y);
- break;
- case _180:
- controlPoints[1].setLocation(x + (folded ? 0 : pinSpacing), y - pinSpacing);
- controlPoints[2].setLocation(x, y - 2 * pinSpacing);
- break;
- case _270:
- controlPoints[1].setLocation(x + pinSpacing, y + (folded ? 0 : pinSpacing));
- controlPoints[2].setLocation(x + 2 * pinSpacing, y);
- break;
- default:
- throw new RuntimeException("Unexpected orientation: " + orientation);
- }
- }
-
- public Area[] getBody() {
- if (body == null) {
- double x = (controlPoints[0].getX() + controlPoints[1].getX() + controlPoints[2].getX()) / 3;
- double y = (controlPoints[0].getY() + controlPoints[1].getY() + controlPoints[2].getY()) / 3;
- int bodyDiameter = getClosestOdd(BODY_DIAMETER.convertToPixels());
- int bodyLength = getClosestOdd(BODY_LENGTH.convertToPixels());
- int edgeRadius = (int) EDGE_RADIUS.convertToPixels();
-
- Area newBody = null;
-
- if (folded) {
- switch (orientation) {
- case DEFAULT:
- newBody =
- new Area(new RoundRectangle2D.Double(x, y - bodyDiameter / 2, bodyLength, bodyDiameter, edgeRadius,
- edgeRadius));
- newBody.add(new Area(new Rectangle2D.Double(x, y - bodyDiameter / 2, bodyLength / 2, bodyDiameter)));
- break;
- case _90:
- newBody =
- new Area(new RoundRectangle2D.Double(x - bodyDiameter / 2, y, bodyDiameter, bodyLength, edgeRadius,
- edgeRadius));
- newBody.add(new Area(new Rectangle2D.Double(x - bodyDiameter / 2, y, bodyDiameter, bodyLength / 2)));
- break;
- case _180:
- newBody =
- new Area(new RoundRectangle2D.Double(x - bodyLength, y - bodyDiameter / 2, bodyLength, bodyDiameter,
- edgeRadius, edgeRadius));
- newBody.add(new Area(new Rectangle2D.Double(x - bodyLength / 2, y - bodyDiameter / 2, bodyLength / 2,
- bodyDiameter)));
-
- break;
- case _270:
- newBody =
- new Area(new RoundRectangle2D.Double(x - bodyDiameter / 2, y - bodyLength, bodyDiameter, bodyLength,
- edgeRadius, edgeRadius));
- newBody.add(new Area(new Rectangle2D.Double(x - bodyDiameter / 2, y - bodyLength / 2, bodyDiameter,
- bodyLength / 2)));
- break;
- default:
- throw new RuntimeException("Unexpected orientation: " + orientation);
- }
- } else {
- newBody = new Area(new Ellipse2D.Double(x - bodyDiameter / 2, y - bodyDiameter / 2, bodyDiameter, bodyDiameter));
- }
-
- body = new Area[] { newBody };
- }
- return body;
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
-
- drawingObserver.stopTracking();
- if (checkPointsClipped(g2d.getClip())) {
- return;
- }
- int pinSize = (int) PIN_SIZE.convertToPixels() / 2 * 2;
- Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f));
- for (Point2D point : controlPoints) {
- Shape shape = new Ellipse2D.Double(point.getX() - pinSize / 2, point.getY() - pinSize / 2, pinSize, pinSize);
- if (!outlineMode) {
- g2d.setColor(PIN_COLOR);
- g2d.fill(shape);
- }
- g2d.setColor(outlineMode ? theme.getOutlineColor() : PIN_BORDER_COLOR);
- g2d.draw(shape);
- }
-
- Area mainArea = getBody()[0];
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor);
- drawingObserver.startTracking();
- g2d.fill(mainArea);
- drawingObserver.stopTracking();
- g2d.setComposite(oldComposite);
- Color finalBorderColor;
-
- if (outlineMode) {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : borderColor;
- }
- g2d.setColor(finalBorderColor);
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
- g2d.draw(mainArea);
-
- // Draw label.
- g2d.setFont(project.getFont());
-
- // Override font size
- if (getFontSizeOverride() != null)
- g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride()));
-
- Color finalLabelColor;
- if (outlineMode) {
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : theme.getOutlineColor();
- } else {
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : getLabelColor();
- }
- g2d.setColor(finalLabelColor);
- if (getDisplay() == TransistorDisplay.PINOUT) {
- drawPinout(g2d);
- } else {
- String label = "";
- label = (getDisplay() == TransistorDisplay.NAME) ? getName() : getValue();
- if (getDisplay() == TransistorDisplay.NONE) {
- label = "";
- }
- if (getDisplay() == TransistorDisplay.BOTH) {
- label = getName() + " " + (getValue() == null ? "" : getValue().toString());
- }
- FontMetrics fontMetrics = g2d.getFontMetrics(g2d.getFont());
- Rectangle2D rect = fontMetrics.getStringBounds(label, g2d);
- int textHeight = (int) (rect.getHeight());
- int textWidth = (int) (rect.getWidth());
- // Center text horizontally and vertically
- Rectangle bounds = mainArea.getBounds();
- int x = (int) (bounds.getX() + (bounds.width - textWidth) / 2);
- int y = (int) (bounds.getY() + (bounds.height - textHeight) / 2 + fontMetrics.getAscent());
- g2d.drawString(label, x, y);
- }
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int margin = (int) (2f * width / 32);
- Area area = new Area(new Ellipse2D.Double(margin / 2, margin, width - 2 * margin, width - 2 * margin));
- g2d.setColor(BODY_COLOR);
- g2d.fill(area);
- g2d.setColor(BORDER_COLOR);
- g2d.draw(area);
- g2d.setColor(PIN_COLOR);
- int pinSize = 2 * width / 32;
- for (int i = 0; i < 3; i++) {
- g2d.fillOval((i == 1 ? width * 3 / 8 : width / 2) - pinSize / 2, (height / 4) * (i + 1), pinSize, pinSize);
- }
- }
-
- @EditableProperty(name = "Pin spacing")
- public Size getPinSpacing() {
- return pinSpacing;
- }
-
- public void setPinSpacing(Size pinSpacing) {
- this.pinSpacing = pinSpacing;
- updateControlPoints();
- // Reset body shape;
- body = null;
- }
-
- @Override
- protected boolean flipPinoutLabel() {
- return true;
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.semiconductors;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.geom.Area;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.common.IPlugInPort;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.Percentage;
+import org.diylc.components.transform.TO1Transformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+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;
+import org.diylc.utils.Constants;
+
+@ComponentDescriptor(name = "Transistor (TO-1)", author = "Branislav Stojkovic", category = "Semiconductors",
+ instanceNamePrefix = "Q", description = "Transistor with small metal body",
+ zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_VALUE, transformer = TO1Transformer.class,
+ enableCache = true)
+public class TransistorTO1 extends AbstractTransistorPackage {
+
+ private static final long serialVersionUID = 1L;
+
+ public static Color BODY_COLOR = Color.lightGray;
+ public static Color BORDER_COLOR = BODY_COLOR.darker();
+ public static Color PIN_COLOR = Color.decode("#00B2EE");
+ public static Color PIN_BORDER_COLOR = PIN_COLOR.darker();
+ public static Color LABEL_COLOR = Color.black;
+ public static Size PIN_SIZE = new Size(0.03d, SizeUnit.in);
+ public static Size PIN_SPACING = new Size(0.05d, SizeUnit.in);
+ public static Size BODY_DIAMETER = new Size(0.24d, SizeUnit.in);
+ public static Size BODY_LENGTH = new Size(0.4d, SizeUnit.in);
+ public static Size EDGE_RADIUS = new Size(2d, SizeUnit.mm);
+
+ private Size pinSpacing = PIN_SPACING;
+
+ public TransistorTO1() {
+ super();
+ updateControlPoints();
+ this.alphaPercent = new Percentage(100);
+ bodyColor = BODY_COLOR;
+ borderColor = BORDER_COLOR;
+ }
+
+ @Override
+ protected void updateControlPoints() {
+ int pinSpacing = (int) getPinSpacing().convertToPixels();
+ // Update control points.
+ double x = controlPoints[0].getX();
+ double y = controlPoints[0].getY();
+ switch (orientation) {
+ case DEFAULT:
+ controlPoints[1].setLocation(x - (folded ? 0 : pinSpacing), y + pinSpacing);
+ controlPoints[2].setLocation(x, y + 2 * pinSpacing);
+ break;
+ case _90:
+ controlPoints[1].setLocation(x - pinSpacing, y - (folded ? 0 : pinSpacing));
+ controlPoints[2].setLocation(x - 2 * pinSpacing, y);
+ break;
+ case _180:
+ controlPoints[1].setLocation(x + (folded ? 0 : pinSpacing), y - pinSpacing);
+ controlPoints[2].setLocation(x, y - 2 * pinSpacing);
+ break;
+ case _270:
+ controlPoints[1].setLocation(x + pinSpacing, y + (folded ? 0 : pinSpacing));
+ controlPoints[2].setLocation(x + 2 * pinSpacing, y);
+ break;
+ default:
+ throw new RuntimeException("Unexpected orientation: " + orientation);
+ }
+ }
+
+ public Area[] getBody() {
+ if (body == null) {
+ double x = (controlPoints[0].getX() + controlPoints[1].getX() + controlPoints[2].getX()) / 3;
+ double y = (controlPoints[0].getY() + controlPoints[1].getY() + controlPoints[2].getY()) / 3;
+ int bodyDiameter = getClosestOdd(BODY_DIAMETER.convertToPixels());
+ int bodyLength = getClosestOdd(BODY_LENGTH.convertToPixels());
+ int edgeRadius = (int) EDGE_RADIUS.convertToPixels();
+
+ Area newBody = null;
+
+ if (folded) {
+ switch (orientation) {
+ case DEFAULT:
+ newBody =
+ new Area(new RoundRectangle2D.Double(x, y - bodyDiameter / 2, bodyLength, bodyDiameter, edgeRadius,
+ edgeRadius));
+ newBody.add(new Area(new Rectangle2D.Double(x, y - bodyDiameter / 2, bodyLength / 2, bodyDiameter)));
+ break;
+ case _90:
+ newBody =
+ new Area(new RoundRectangle2D.Double(x - bodyDiameter / 2, y, bodyDiameter, bodyLength, edgeRadius,
+ edgeRadius));
+ newBody.add(new Area(new Rectangle2D.Double(x - bodyDiameter / 2, y, bodyDiameter, bodyLength / 2)));
+ break;
+ case _180:
+ newBody =
+ new Area(new RoundRectangle2D.Double(x - bodyLength, y - bodyDiameter / 2, bodyLength, bodyDiameter,
+ edgeRadius, edgeRadius));
+ newBody.add(new Area(new Rectangle2D.Double(x - bodyLength / 2, y - bodyDiameter / 2, bodyLength / 2,
+ bodyDiameter)));
+
+ break;
+ case _270:
+ newBody =
+ new Area(new RoundRectangle2D.Double(x - bodyDiameter / 2, y - bodyLength, bodyDiameter, bodyLength,
+ edgeRadius, edgeRadius));
+ newBody.add(new Area(new Rectangle2D.Double(x - bodyDiameter / 2, y - bodyLength / 2, bodyDiameter,
+ bodyLength / 2)));
+ break;
+ default:
+ throw new RuntimeException("Unexpected orientation: " + orientation);
+ }
+ } else {
+ newBody = new Area(new Ellipse2D.Double(x - bodyDiameter / 2, y - bodyDiameter / 2, bodyDiameter, bodyDiameter));
+ }
+
+ body = new Area[] { newBody };
+ }
+ return body;
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+
+ drawingObserver.stopTracking();
+ if (checkPointsClipped(g2d.getClip())) {
+ return;
+ }
+ int pinSize = (int) PIN_SIZE.convertToPixels() / 2 * 2;
+ Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f));
+ for (Point2D point : controlPoints) {
+ Shape shape = new Ellipse2D.Double(point.getX() - pinSize / 2, point.getY() - pinSize / 2, pinSize, pinSize);
+ if (!outlineMode) {
+ g2d.setColor(PIN_COLOR);
+ g2d.fill(shape);
+ }
+ g2d.setColor(outlineMode ? theme.getOutlineColor() : PIN_BORDER_COLOR);
+ g2d.draw(shape);
+ }
+
+ Area mainArea = getBody()[0];
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor);
+ drawingObserver.startTracking();
+ g2d.fill(mainArea);
+ drawingObserver.stopTracking();
+ g2d.setComposite(oldComposite);
+ Color finalBorderColor;
+
+ if (outlineMode) {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : borderColor;
+ }
+ g2d.setColor(finalBorderColor);
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+ g2d.draw(mainArea);
+
+ // Draw label.
+ g2d.setFont(project.getFont());
+
+ // Override font size
+ if (getFontSizeOverride() != null)
+ g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride()));
+
+ Color finalLabelColor;
+ if (outlineMode) {
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : theme.getOutlineColor();
+ } else {
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : getLabelColor();
+ }
+ g2d.setColor(finalLabelColor);
+ if (getDisplay() == TransistorDisplay.PINOUT) {
+ drawPinout(g2d);
+ } else {
+ String label = "";
+ label = (getDisplay() == TransistorDisplay.NAME) ? getName() : getValue();
+ if (getDisplay() == TransistorDisplay.NONE) {
+ label = "";
+ }
+ if (getDisplay() == TransistorDisplay.BOTH) {
+ label = getName() + " " + (getValue() == null ? "" : getValue().toString());
+ }
+ FontMetrics fontMetrics = g2d.getFontMetrics(g2d.getFont());
+ Rectangle2D rect = fontMetrics.getStringBounds(label, g2d);
+ int textHeight = (int) (rect.getHeight());
+ int textWidth = (int) (rect.getWidth());
+ // Center text horizontally and vertically
+ Rectangle bounds = mainArea.getBounds();
+ int x = (int) (bounds.getX() + (bounds.width - textWidth) / 2);
+ int y = (int) (bounds.getY() + (bounds.height - textHeight) / 2 + fontMetrics.getAscent());
+ g2d.drawString(label, x, y);
+ }
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int margin = (int) (2f * width / 32);
+ Area area = new Area(new Ellipse2D.Double(margin / 2, margin, width - 2 * margin, width - 2 * margin));
+ g2d.setColor(BODY_COLOR);
+ g2d.fill(area);
+ g2d.setColor(BORDER_COLOR);
+ g2d.draw(area);
+ g2d.setColor(PIN_COLOR);
+ int pinSize = 2 * width / 32;
+ for (int i = 0; i < 3; i++) {
+ g2d.fillOval((i == 1 ? width * 3 / 8 : width / 2) - pinSize / 2, (height / 4) * (i + 1), pinSize, pinSize);
+ }
+ }
+
+ @EditableProperty(name = "Pin spacing")
+ public Size getPinSpacing() {
+ return pinSpacing;
+ }
+
+ public void setPinSpacing(Size pinSpacing) {
+ this.pinSpacing = pinSpacing;
+ updateControlPoints();
+ // Reset body shape;
+ body = null;
+ }
+
+ @Override
+ protected boolean flipPinoutLabel() {
+ return true;
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/TransistorTO126.java b/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/TransistorTO126.java
index 506441cd2..1a4e275b9 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/TransistorTO126.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/TransistorTO126.java
@@ -1,378 +1,376 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.semiconductors;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.FontMetrics;
-import java.awt.Graphics2D;
-import java.awt.Rectangle;
-import java.awt.Shape;
-import java.awt.geom.Area;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.Line2D;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.components.transform.TO220Transformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-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;
-import org.diylc.utils.Constants;
-
-@ComponentDescriptor(name = "Transistor (TO-126)", author = "Branislav Stojkovic", category = "Semiconductors",
- instanceNamePrefix = "Q", description = "Transistors with a hole for heat sink mounting",
- zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_VALUE, transformer = TO220Transformer.class,
- enableCache = true)
-public class TransistorTO126 extends AbstractTransistorPackage {
-
- private static final long serialVersionUID = 1L;
-
- public static Color BODY_COLOR = Color.gray;
- public static Color BORDER_COLOR = Color.gray.darker();
- public static Color PIN_COLOR = Color.decode("#00B2EE");
- public static Color PIN_BORDER_COLOR = PIN_COLOR.darker();
- public static Color LABEL_COLOR = Color.white;
- public static Size PIN_SIZE = new Size(0.8d, SizeUnit.mm);
- public static Size PIN_SPACING = new Size(0.1d, SizeUnit.in);
- public static Size BODY_WIDTH = new Size(8d, SizeUnit.mm);
- public static Size BODY_THICKNESS = new Size(3.25d, SizeUnit.mm);
- public static Size BODY_HEIGHT = new Size(11d, SizeUnit.mm);
- public static Size HOLE_DIAMETER = new Size(3.2d, SizeUnit.mm);
- public static Size HOLE_OFFSET = new Size(8.1d, SizeUnit.mm);
- public static Size LEAD_LENGTH = new Size(3.5d, SizeUnit.mm);
- public static Size LEAD_THICKNESS = new Size(0.8d, SizeUnit.mm);
-
- private Size leadLength = LEAD_LENGTH;
-
- public TransistorTO126() {
- super();
- updateControlPoints();
- alpha = (byte) 100;
- bodyColor = BODY_COLOR;
- borderColor = BORDER_COLOR;
- }
-
- @Override
- protected void updateControlPoints() {
- int pinSpacing = (int) PIN_SPACING.convertToPixels();
- // Update control points.
- double x = controlPoints[0].getX();
- double y = controlPoints[0].getY();
- switch (orientation) {
- case DEFAULT:
- controlPoints[1].setLocation(x, y + pinSpacing);
- controlPoints[2].setLocation(x, y + 2 * pinSpacing);
- break;
- case _90:
- controlPoints[1].setLocation(x - pinSpacing, y);
- controlPoints[2].setLocation(x - 2 * pinSpacing, y);
- break;
- case _180:
- controlPoints[1].setLocation(x, y - pinSpacing);
- controlPoints[2].setLocation(x, y - 2 * pinSpacing);
- break;
- case _270:
- controlPoints[1].setLocation(x + pinSpacing, y);
- controlPoints[2].setLocation(x + 2 * pinSpacing, y);
- break;
- default:
- throw new RuntimeException("Unexpected orientation: " + orientation);
- }
- }
-
- public Area[] getBody() {
- if (body == null) {
- body = new Area[2];
- double x = controlPoints[0].getX();
- double y = controlPoints[0].getY();
- int pinSpacing = (int) PIN_SPACING.convertToPixels();
- int bodyWidth = getClosestOdd(BODY_WIDTH.convertToPixels());
- int bodyThickness = getClosestOdd(BODY_THICKNESS.convertToPixels());
- int bodyHeight = getClosestOdd(BODY_HEIGHT.convertToPixels());
-
- int tabHoleDiameter = (int) HOLE_DIAMETER.convertToPixels();
- int holeOffset = (int) HOLE_OFFSET.convertToPixels();
- double leadLength = getLeadLength().convertToPixels();
-
- switch (orientation) {
- case DEFAULT:
- if (folded) {
- body[0] = new Area(new Rectangle2D.Double(x + leadLength, y + pinSpacing - bodyWidth / 2, bodyHeight, bodyWidth));
- ((Area) body[0]).subtract(new Area(new Ellipse2D.Double(x + leadLength + holeOffset
- - tabHoleDiameter / 2, y + pinSpacing - tabHoleDiameter / 2, tabHoleDiameter, tabHoleDiameter)));
- } else {
- body[0] = new Area(
- new Rectangle2D.Double(x - bodyThickness / 2, y + pinSpacing - bodyWidth / 2, bodyThickness, bodyWidth));
- }
- break;
- case _90:
- if (folded) {
- body[0] = new Area(new Rectangle2D.Double(x - pinSpacing - bodyWidth / 2, y + leadLength, bodyWidth, bodyHeight));
- ((Area) body[0]).subtract(new Area(new Ellipse2D.Double(x - pinSpacing - tabHoleDiameter / 2, y
- + leadLength + holeOffset - tabHoleDiameter / 2, tabHoleDiameter, tabHoleDiameter)));
- } else {
- body[0] = new Area(
- new Rectangle2D.Double(x - pinSpacing - bodyWidth / 2, y - bodyThickness / 2, bodyWidth, bodyThickness));
- }
- break;
- case _180:
- if (folded) {
- body[0] = new Area(
- new Rectangle2D.Double(x - leadLength - bodyHeight, y - pinSpacing - bodyWidth / 2, bodyHeight,
- bodyWidth));
- ((Area) body[0]).subtract(new Area(new Ellipse2D.Double(x - leadLength - holeOffset
- - tabHoleDiameter / 2, y - pinSpacing - tabHoleDiameter / 2, tabHoleDiameter, tabHoleDiameter)));
- } else {
- body[0] = new Area(
- new Rectangle2D.Double(x - bodyThickness / 2, y - pinSpacing - bodyWidth / 2, bodyThickness, bodyWidth));
- }
- break;
- case _270:
- if (folded) {
- body[0] = new Area(
- new Rectangle2D.Double(x + pinSpacing - bodyWidth / 2, y - leadLength - bodyHeight, bodyWidth,
- bodyHeight));
- ((Area) body[0]).subtract(new Area(new Ellipse2D.Double(x + pinSpacing - tabHoleDiameter / 2, y
- - leadLength - holeOffset - tabHoleDiameter / 2, tabHoleDiameter, tabHoleDiameter)));
- } else {
- body[0] = new Area(
- new Rectangle2D.Double(x + pinSpacing - bodyWidth / 2, y - bodyThickness / 2, bodyWidth, bodyThickness));
- }
- break;
- default:
- throw new RuntimeException("Unexpected orientation: " + orientation);
- }
- }
- return body;
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- if (checkPointsClipped(g2d.getClip())) {
- return;
- }
- drawingObserver.stopTracking();
- int pinSize = (int) PIN_SIZE.convertToPixels() / 2 * 2;
-
- Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
-
- // Draw pins.
-
- if (folded) {
- if (getLeadLength().getValue() > 0) {
- int leadThickness = getClosestOdd(LEAD_THICKNESS.convertToPixels());
- int leadLength = (int) getLeadLength().convertToPixels();
- Color finalPinColor;
- Color finalPinBorderColor;
- if (outlineMode) {
- finalPinColor = new Color(0, 0, 0, 0);
- finalPinBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalPinColor = METAL_COLOR;
- finalPinBorderColor = METAL_COLOR.darker();
- }
- Line2D line;
- for (Point2D point : controlPoints) {
- switch (orientation) {
- case DEFAULT:
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
- g2d.setColor(finalPinBorderColor);
- line = new Line2D.Double(point.getX(), point.getY(), point.getX() + leadLength - leadThickness / 2, point.getY());
- drawingObserver.startTracking();
- g2d.draw(line);
- drawingObserver.stopTracking();
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2));
- g2d.setColor(finalPinColor);
- g2d.draw(line);
- break;
- case _90:
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
- g2d.setColor(finalPinBorderColor);
- line = new Line2D.Double(point.getX(), point.getY(), point.getX(), point.getY() + leadLength - leadThickness / 2);
- drawingObserver.startTracking();
- g2d.draw(line);
- drawingObserver.stopTracking();
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2));
- g2d.setColor(finalPinColor);
- g2d.draw(line);
- break;
- case _180:
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
- g2d.setColor(finalPinBorderColor);
- line = new Line2D.Double(point.getX(), point.getY(), point.getX() - leadLength - leadThickness / 2, point.getY());
- drawingObserver.startTracking();
- g2d.draw(line);
- drawingObserver.stopTracking();
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2));
- g2d.setColor(finalPinColor);
- g2d.draw(line);
- break;
- case _270:
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
- g2d.setColor(finalPinBorderColor);
- line = new Line2D.Double(point.getX(), point.getY(), point.getX(), point.getY() - leadLength);
- drawingObserver.startTracking();
- g2d.draw(line);
- drawingObserver.stopTracking();
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2));
- g2d.setColor(finalPinColor);
- g2d.draw(line);
- break;
- }
- }
- }
- } else {
- if (!outlineMode) {
- for (Point2D point : controlPoints) {
-
- g2d.setColor(PIN_COLOR);
- Shape pin = new Ellipse2D.Double(point.getX() - pinSize / 2, point.getY() - pinSize / 2, pinSize, pinSize);
- g2d.fill(pin);
- g2d.setColor(outlineMode ? theme.getOutlineColor() : PIN_BORDER_COLOR);
- g2d.draw(pin);
- }
- }
- }
-
-
- Shape mainArea = getBody()[0];
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor);
- drawingObserver.startTracking();
- g2d.fill(mainArea);
- drawingObserver.stopTracking();
-
- g2d.setComposite(oldComposite);
- if (!outlineMode) {
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
- }
-
- Color finalBorderColor;
-
- if (outlineMode) {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : borderColor;
- }
- g2d.setColor(finalBorderColor);
- g2d.draw(mainArea);
-
- g2d.setComposite(oldComposite);
-
- // Draw label.
- g2d.setFont(project.getFont());
-
- // Override font size
- if (getFontSizeOverride() != null)
- g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride()));
-
- Color finalLabelColor;
- if (outlineMode) {
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : theme.getOutlineColor();
- } else {
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : getLabelColor();
- }
- g2d.setColor(finalLabelColor);
- if (getDisplay() == TransistorDisplay.PINOUT) {
- drawPinout(g2d);
- } else {
- String label = "";
- label = (getDisplay() == TransistorDisplay.NAME) ? getName() : getValue();
- if (getDisplay() == TransistorDisplay.NONE) {
- label = "";
- }
- if (getDisplay() == TransistorDisplay.BOTH) {
- label = getName() + " " + (getValue() == null ? "" : getValue().toString());
- }
- FontMetrics fontMetrics = g2d.getFontMetrics(g2d.getFont());
- Rectangle2D rect = fontMetrics.getStringBounds(label, g2d);
- int textHeight = (int) (rect.getHeight());
- int textWidth = (int) (rect.getWidth());
- // Center text horizontally and vertically
- Rectangle bounds = mainArea.getBounds();
- int x = (int) (bounds.getX() + (bounds.width - textWidth) / 2);
- int y = (int) (bounds.getY() + (bounds.height - textHeight) / 2 + fontMetrics.getAscent());
- g2d.drawString(label, x, y);
- }
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int margin = 2 * width / 32;
- int bodyWidth = width * 5 / 10;
- int bodyHeight = width * 7 / 10;
- int holeSize = 6 * width / 32;
- Area a = new Area(new Rectangle2D.Double((width - bodyWidth) / 2, margin, bodyWidth, bodyHeight));
- a.subtract(new Area(new Ellipse2D.Double(width / 2 - holeSize / 2, margin + bodyHeight / 3 - holeSize / 2, holeSize,
- holeSize)));
- g2d.setColor(BODY_COLOR);
- g2d.fill(a);
- g2d.setColor(BORDER_COLOR);
- g2d.draw(a);
-
- g2d.setColor(METAL_COLOR);
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(2));
- g2d.drawLine(width / 2, margin + bodyHeight, width / 2, height - margin);
- g2d.drawLine(width / 2 - bodyWidth / 3, margin + bodyHeight + 1, width / 2 - bodyWidth / 3, height - margin);
- g2d.drawLine(width / 2 + bodyWidth / 3, margin + bodyHeight + 1, width / 2 + bodyWidth / 3, height - margin);
- }
-
- @EditableProperty(name = "Lead Length")
- public Size getLeadLength() {
- if (leadLength == null) {
- leadLength = LEAD_LENGTH;
- }
- return leadLength;
- }
-
- public void setLeadLength(Size leadLength) {
- this.leadLength = leadLength;
- // Invalidate the body
- this.body = null;
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.semiconductors;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.geom.Area;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Line2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.common.IPlugInPort;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.Percentage;
+import org.diylc.components.transform.TO220Transformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+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;
+import org.diylc.utils.Constants;
+
+@ComponentDescriptor(name = "Transistor (TO-126)", author = "Branislav Stojkovic", category = "Semiconductors",
+ instanceNamePrefix = "Q", description = "Transistors with a hole for heat sink mounting",
+ zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_VALUE, transformer = TO220Transformer.class,
+ enableCache = true)
+public class TransistorTO126 extends AbstractTransistorPackage {
+
+ private static final long serialVersionUID = 1L;
+
+ public static Color BODY_COLOR = Color.gray;
+ public static Color BORDER_COLOR = Color.gray.darker();
+ public static Color PIN_COLOR = Color.decode("#00B2EE");
+ public static Color PIN_BORDER_COLOR = PIN_COLOR.darker();
+ public static Color LABEL_COLOR = Color.white;
+ public static Size PIN_SIZE = new Size(0.8d, SizeUnit.mm);
+ public static Size PIN_SPACING = new Size(0.1d, SizeUnit.in);
+ public static Size BODY_WIDTH = new Size(8d, SizeUnit.mm);
+ public static Size BODY_THICKNESS = new Size(3.25d, SizeUnit.mm);
+ public static Size BODY_HEIGHT = new Size(11d, SizeUnit.mm);
+ public static Size HOLE_DIAMETER = new Size(3.2d, SizeUnit.mm);
+ public static Size HOLE_OFFSET = new Size(8.1d, SizeUnit.mm);
+ public static Size LEAD_LENGTH = new Size(3.5d, SizeUnit.mm);
+ public static Size LEAD_THICKNESS = new Size(0.8d, SizeUnit.mm);
+
+ private Size leadLength = LEAD_LENGTH;
+
+ public TransistorTO126() {
+ super();
+ updateControlPoints();
+ this.alphaPercent = new Percentage(100);
+ bodyColor = BODY_COLOR;
+ borderColor = BORDER_COLOR;
+ }
+
+ @Override
+ protected void updateControlPoints() {
+ int pinSpacing = (int) PIN_SPACING.convertToPixels();
+ // Update control points.
+ double x = controlPoints[0].getX();
+ double y = controlPoints[0].getY();
+ switch (orientation) {
+ case DEFAULT:
+ controlPoints[1].setLocation(x, y + pinSpacing);
+ controlPoints[2].setLocation(x, y + 2 * pinSpacing);
+ break;
+ case _90:
+ controlPoints[1].setLocation(x - pinSpacing, y);
+ controlPoints[2].setLocation(x - 2 * pinSpacing, y);
+ break;
+ case _180:
+ controlPoints[1].setLocation(x, y - pinSpacing);
+ controlPoints[2].setLocation(x, y - 2 * pinSpacing);
+ break;
+ case _270:
+ controlPoints[1].setLocation(x + pinSpacing, y);
+ controlPoints[2].setLocation(x + 2 * pinSpacing, y);
+ break;
+ default:
+ throw new RuntimeException("Unexpected orientation: " + orientation);
+ }
+ }
+
+ public Area[] getBody() {
+ if (body == null) {
+ body = new Area[2];
+ double x = controlPoints[0].getX();
+ double y = controlPoints[0].getY();
+ int pinSpacing = (int) PIN_SPACING.convertToPixels();
+ int bodyWidth = getClosestOdd(BODY_WIDTH.convertToPixels());
+ int bodyThickness = getClosestOdd(BODY_THICKNESS.convertToPixels());
+ int bodyHeight = getClosestOdd(BODY_HEIGHT.convertToPixels());
+
+ int tabHoleDiameter = (int) HOLE_DIAMETER.convertToPixels();
+ int holeOffset = (int) HOLE_OFFSET.convertToPixels();
+ double leadLength = getLeadLength().convertToPixels();
+
+ switch (orientation) {
+ case DEFAULT:
+ if (folded) {
+ body[0] = new Area(new Rectangle2D.Double(x + leadLength, y + pinSpacing - bodyWidth / 2, bodyHeight, bodyWidth));
+ ((Area) body[0]).subtract(new Area(new Ellipse2D.Double(x + leadLength + holeOffset
+ - tabHoleDiameter / 2, y + pinSpacing - tabHoleDiameter / 2, tabHoleDiameter, tabHoleDiameter)));
+ } else {
+ body[0] = new Area(
+ new Rectangle2D.Double(x - bodyThickness / 2, y + pinSpacing - bodyWidth / 2, bodyThickness, bodyWidth));
+ }
+ break;
+ case _90:
+ if (folded) {
+ body[0] = new Area(new Rectangle2D.Double(x - pinSpacing - bodyWidth / 2, y + leadLength, bodyWidth, bodyHeight));
+ ((Area) body[0]).subtract(new Area(new Ellipse2D.Double(x - pinSpacing - tabHoleDiameter / 2, y
+ + leadLength + holeOffset - tabHoleDiameter / 2, tabHoleDiameter, tabHoleDiameter)));
+ } else {
+ body[0] = new Area(
+ new Rectangle2D.Double(x - pinSpacing - bodyWidth / 2, y - bodyThickness / 2, bodyWidth, bodyThickness));
+ }
+ break;
+ case _180:
+ if (folded) {
+ body[0] = new Area(
+ new Rectangle2D.Double(x - leadLength - bodyHeight, y - pinSpacing - bodyWidth / 2, bodyHeight,
+ bodyWidth));
+ ((Area) body[0]).subtract(new Area(new Ellipse2D.Double(x - leadLength - holeOffset
+ - tabHoleDiameter / 2, y - pinSpacing - tabHoleDiameter / 2, tabHoleDiameter, tabHoleDiameter)));
+ } else {
+ body[0] = new Area(
+ new Rectangle2D.Double(x - bodyThickness / 2, y - pinSpacing - bodyWidth / 2, bodyThickness, bodyWidth));
+ }
+ break;
+ case _270:
+ if (folded) {
+ body[0] = new Area(
+ new Rectangle2D.Double(x + pinSpacing - bodyWidth / 2, y - leadLength - bodyHeight, bodyWidth,
+ bodyHeight));
+ ((Area) body[0]).subtract(new Area(new Ellipse2D.Double(x + pinSpacing - tabHoleDiameter / 2, y
+ - leadLength - holeOffset - tabHoleDiameter / 2, tabHoleDiameter, tabHoleDiameter)));
+ } else {
+ body[0] = new Area(
+ new Rectangle2D.Double(x + pinSpacing - bodyWidth / 2, y - bodyThickness / 2, bodyWidth, bodyThickness));
+ }
+ break;
+ default:
+ throw new RuntimeException("Unexpected orientation: " + orientation);
+ }
+ }
+ return body;
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ if (checkPointsClipped(g2d.getClip())) {
+ return;
+ }
+ drawingObserver.stopTracking();
+ int pinSize = (int) PIN_SIZE.convertToPixels() / 2 * 2;
+
+ Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+
+ // Draw pins.
+
+ if (folded) {
+ if (getLeadLength().getValue() > 0) {
+ int leadThickness = getClosestOdd(LEAD_THICKNESS.convertToPixels());
+ int leadLength = (int) getLeadLength().convertToPixels();
+ Color finalPinColor;
+ Color finalPinBorderColor;
+ if (outlineMode) {
+ finalPinColor = new Color(0, 0, 0, 0);
+ finalPinBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalPinColor = METAL_COLOR;
+ finalPinBorderColor = METAL_COLOR.darker();
+ }
+ Line2D line;
+ for (Point2D point : controlPoints) {
+ switch (orientation) {
+ case DEFAULT:
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
+ g2d.setColor(finalPinBorderColor);
+ line = new Line2D.Double(point.getX(), point.getY(), point.getX() + leadLength - leadThickness / 2, point.getY());
+ drawingObserver.startTracking();
+ g2d.draw(line);
+ drawingObserver.stopTracking();
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2));
+ g2d.setColor(finalPinColor);
+ g2d.draw(line);
+ break;
+ case _90:
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
+ g2d.setColor(finalPinBorderColor);
+ line = new Line2D.Double(point.getX(), point.getY(), point.getX(), point.getY() + leadLength - leadThickness / 2);
+ drawingObserver.startTracking();
+ g2d.draw(line);
+ drawingObserver.stopTracking();
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2));
+ g2d.setColor(finalPinColor);
+ g2d.draw(line);
+ break;
+ case _180:
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
+ g2d.setColor(finalPinBorderColor);
+ line = new Line2D.Double(point.getX(), point.getY(), point.getX() - leadLength - leadThickness / 2, point.getY());
+ drawingObserver.startTracking();
+ g2d.draw(line);
+ drawingObserver.stopTracking();
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2));
+ g2d.setColor(finalPinColor);
+ g2d.draw(line);
+ break;
+ case _270:
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
+ g2d.setColor(finalPinBorderColor);
+ line = new Line2D.Double(point.getX(), point.getY(), point.getX(), point.getY() - leadLength);
+ drawingObserver.startTracking();
+ g2d.draw(line);
+ drawingObserver.stopTracking();
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2));
+ g2d.setColor(finalPinColor);
+ g2d.draw(line);
+ break;
+ }
+ }
+ }
+ } else {
+ if (!outlineMode) {
+ for (Point2D point : controlPoints) {
+
+ g2d.setColor(PIN_COLOR);
+ Shape pin = new Ellipse2D.Double(point.getX() - pinSize / 2, point.getY() - pinSize / 2, pinSize, pinSize);
+ g2d.fill(pin);
+ g2d.setColor(outlineMode ? theme.getOutlineColor() : PIN_BORDER_COLOR);
+ g2d.draw(pin);
+ }
+ }
+ }
+
+
+ Shape mainArea = getBody()[0];
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor);
+ drawingObserver.startTracking();
+ g2d.fill(mainArea);
+ drawingObserver.stopTracking();
+
+ g2d.setComposite(oldComposite);
+ if (!outlineMode) {
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+ }
+
+ Color finalBorderColor;
+
+ if (outlineMode) {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : borderColor;
+ }
+ g2d.setColor(finalBorderColor);
+ g2d.draw(mainArea);
+
+ g2d.setComposite(oldComposite);
+
+ // Draw label.
+ g2d.setFont(project.getFont());
+
+ // Override font size
+ if (getFontSizeOverride() != null)
+ g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride()));
+
+ Color finalLabelColor;
+ if (outlineMode) {
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : theme.getOutlineColor();
+ } else {
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : getLabelColor();
+ }
+ g2d.setColor(finalLabelColor);
+ if (getDisplay() == TransistorDisplay.PINOUT) {
+ drawPinout(g2d);
+ } else {
+ String label = "";
+ label = (getDisplay() == TransistorDisplay.NAME) ? getName() : getValue();
+ if (getDisplay() == TransistorDisplay.NONE) {
+ label = "";
+ }
+ if (getDisplay() == TransistorDisplay.BOTH) {
+ label = getName() + " " + (getValue() == null ? "" : getValue().toString());
+ }
+ FontMetrics fontMetrics = g2d.getFontMetrics(g2d.getFont());
+ Rectangle2D rect = fontMetrics.getStringBounds(label, g2d);
+ int textHeight = (int) (rect.getHeight());
+ int textWidth = (int) (rect.getWidth());
+ // Center text horizontally and vertically
+ Rectangle bounds = mainArea.getBounds();
+ int x = (int) (bounds.getX() + (bounds.width - textWidth) / 2);
+ int y = (int) (bounds.getY() + (bounds.height - textHeight) / 2 + fontMetrics.getAscent());
+ g2d.drawString(label, x, y);
+ }
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int margin = 2 * width / 32;
+ int bodyWidth = width * 5 / 10;
+ int bodyHeight = width * 7 / 10;
+ int holeSize = 6 * width / 32;
+ Area a = new Area(new Rectangle2D.Double((width - bodyWidth) / 2, margin, bodyWidth, bodyHeight));
+ a.subtract(new Area(new Ellipse2D.Double(width / 2 - holeSize / 2, margin + bodyHeight / 3 - holeSize / 2, holeSize,
+ holeSize)));
+ g2d.setColor(BODY_COLOR);
+ g2d.fill(a);
+ g2d.setColor(BORDER_COLOR);
+ g2d.draw(a);
+
+ g2d.setColor(METAL_COLOR);
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(2));
+ g2d.drawLine(width / 2, margin + bodyHeight, width / 2, height - margin);
+ g2d.drawLine(width / 2 - bodyWidth / 3, margin + bodyHeight + 1, width / 2 - bodyWidth / 3, height - margin);
+ g2d.drawLine(width / 2 + bodyWidth / 3, margin + bodyHeight + 1, width / 2 + bodyWidth / 3, height - margin);
+ }
+
+ @EditableProperty(name = "Lead Length")
+ public Size getLeadLength() {
+ if (leadLength == null) {
+ leadLength = LEAD_LENGTH;
+ }
+ return leadLength;
+ }
+
+ public void setLeadLength(Size leadLength) {
+ this.leadLength = leadLength;
+ // Invalidate the body
+ this.body = null;
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/TransistorTO220.java b/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/TransistorTO220.java
index 4313dc216..a6f9345c8 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/TransistorTO220.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/TransistorTO220.java
@@ -1,441 +1,439 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.semiconductors;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.FontMetrics;
-import java.awt.Graphics2D;
-import java.awt.Rectangle;
-import java.awt.Shape;
-import java.awt.geom.Area;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.Line2D;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.components.transform.TO220Transformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-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;
-import org.diylc.utils.Constants;
-
-@ComponentDescriptor(name = "Transistor (TO-220)", author = "Branislav Stojkovic", category = "Semiconductors",
- instanceNamePrefix = "Q", description = "Transistors with metal tab for heat sink mounting",
- zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_VALUE, transformer = TO220Transformer.class,
- enableCache = true)
-public class TransistorTO220 extends AbstractTransistorPackage {
-
- private static final long serialVersionUID = 1L;
-
- public static Color BODY_COLOR = Color.gray;
- public static Color BORDER_COLOR = Color.gray.darker();
- public static Color PIN_COLOR = Color.decode("#00B2EE");
- public static Color PIN_BORDER_COLOR = PIN_COLOR.darker();
- public static Color TAB_COLOR = Color.lightGray;
- public static Color TAB_BORDER_COLOR = TAB_COLOR.darker();
- public static Color LABEL_COLOR = Color.white;
- public static Size PIN_SIZE = new Size(0.03d, SizeUnit.in);
- public static Size PIN_SPACING = new Size(0.1d, SizeUnit.in);
- public static Size BODY_WIDTH = new Size(0.4d, SizeUnit.in);
- public static Size BODY_THICKNESS = new Size(4.5d, SizeUnit.mm);
- public static Size BODY_HEIGHT = new Size(9d, SizeUnit.mm);
- public static Size TAB_THICKNESS = new Size(1d, SizeUnit.mm);
- public static Size TAB_HEIGHT = new Size(6.2d, SizeUnit.mm);
- public static Size TAB_HOLE_DIAMETER = new Size(3.6d, SizeUnit.mm);
- public static Size LEAD_LENGTH = new Size(3.5d, SizeUnit.mm);
- public static Size LEAD_THICKNESS = new Size(0.8d, SizeUnit.mm);
-
- private Color tabColor = TAB_COLOR;
- private Color tabBorderColor = TAB_BORDER_COLOR;
- private Size leadLength = LEAD_LENGTH;
-
- public TransistorTO220() {
- super();
- updateControlPoints();
- alpha = (byte) 100;
- bodyColor = BODY_COLOR;
- borderColor = BORDER_COLOR;
- }
-
- @Override
- protected void updateControlPoints() {
- int pinSpacing = (int) PIN_SPACING.convertToPixels();
- // Update control points.
- double x = controlPoints[0].getX();
- double y = controlPoints[0].getY();
- switch (orientation) {
- case DEFAULT:
- controlPoints[1].setLocation(x, y + pinSpacing);
- controlPoints[2].setLocation(x, y + 2 * pinSpacing);
- break;
- case _90:
- controlPoints[1].setLocation(x - pinSpacing, y);
- controlPoints[2].setLocation(x - 2 * pinSpacing, y);
- break;
- case _180:
- controlPoints[1].setLocation(x, y - pinSpacing);
- controlPoints[2].setLocation(x, y - 2 * pinSpacing);
- break;
- case _270:
- controlPoints[1].setLocation(x + pinSpacing, y);
- controlPoints[2].setLocation(x + 2 * pinSpacing, y);
- break;
- default:
- throw new RuntimeException("Unexpected orientation: " + orientation);
- }
- }
-
- public Area[] getBody() {
- if (body == null) {
- body = new Area[2];
- double x = controlPoints[0].getX();
- double y = controlPoints[0].getY();
- int pinSpacing = (int) PIN_SPACING.convertToPixels();
- int bodyWidth = getClosestOdd(BODY_WIDTH.convertToPixels());
- int bodyThickness = getClosestOdd(BODY_THICKNESS.convertToPixels());
- int bodyHeight = getClosestOdd(BODY_HEIGHT.convertToPixels());
- int tabThickness = (int) TAB_THICKNESS.convertToPixels();
- int tabHeight = (int) TAB_HEIGHT.convertToPixels();
- int tabHoleDiameter = (int) TAB_HOLE_DIAMETER.convertToPixels();
- double leadLength = getLeadLength().convertToPixels();
-
- switch (orientation) {
- case DEFAULT:
- if (folded) {
- body[0] = new Area(new Rectangle2D.Double(x + leadLength, y + pinSpacing - bodyWidth / 2, bodyHeight, bodyWidth));
- body[1] =
- new Area(new Rectangle2D.Double(x + leadLength + bodyHeight, y + pinSpacing - bodyWidth / 2, tabHeight,
- bodyWidth));
- ((Area) body[1]).subtract(new Area(new Ellipse2D.Double(x + leadLength + bodyHeight + tabHeight / 2
- - tabHoleDiameter / 2, y + pinSpacing - tabHoleDiameter / 2, tabHoleDiameter, tabHoleDiameter)));
- } else {
- body[0] = new Area(
- new Rectangle2D.Double(x - bodyThickness / 2, y + pinSpacing - bodyWidth / 2, bodyThickness, bodyWidth));
- body[1] = new Area(
- new Rectangle2D.Double(x + bodyThickness / 2 - tabThickness, y + pinSpacing - bodyWidth / 2,
- tabThickness, bodyWidth));
- }
- break;
- case _90:
- if (folded) {
- body[0] = new Area(new Rectangle2D.Double(x - pinSpacing - bodyWidth / 2, y + leadLength, bodyWidth, bodyHeight));
- body[1] =
- new Area(new Rectangle2D.Double(x - pinSpacing - bodyWidth / 2, y + leadLength + bodyHeight, bodyWidth,
- tabHeight));
- ((Area) body[1]).subtract(new Area(new Ellipse2D.Double(x - pinSpacing - tabHoleDiameter / 2, y
- + leadLength + bodyHeight + tabHeight / 2 - tabHoleDiameter / 2, tabHoleDiameter, tabHoleDiameter)));
- } else {
- body[0] = new Area(
- new Rectangle2D.Double(x - pinSpacing - bodyWidth / 2, y - bodyThickness / 2, bodyWidth, bodyThickness));
- body[1] = new Area(
- new Rectangle2D.Double(x - pinSpacing - bodyWidth / 2, y + bodyThickness / 2 - tabThickness, bodyWidth,
- tabThickness));
- }
- break;
- case _180:
- if (folded) {
- body[0] = new Area(
- new Rectangle2D.Double(x - leadLength - bodyHeight, y - pinSpacing - bodyWidth / 2, bodyHeight,
- bodyWidth));
- body[1] =
- new Area(new Rectangle2D.Double(x - leadLength - bodyHeight - tabHeight,
- y - pinSpacing - bodyWidth / 2, tabHeight, bodyWidth));
- ((Area) body[1]).subtract(new Area(new Ellipse2D.Double(x - leadLength - bodyHeight - tabHeight / 2
- - tabHoleDiameter / 2, y - pinSpacing - tabHoleDiameter / 2, tabHoleDiameter, tabHoleDiameter)));
- } else {
- body[0] = new Area(
- new Rectangle2D.Double(x - bodyThickness / 2, y - pinSpacing - bodyWidth / 2, bodyThickness, bodyWidth));
- body[1] = new Area(
- new Rectangle2D.Double(x - bodyThickness / 2, y - pinSpacing - bodyWidth / 2, tabThickness, bodyWidth));
- }
- break;
- case _270:
- if (folded) {
- body[0] = new Area(
- new Rectangle2D.Double(x + pinSpacing - bodyWidth / 2, y - leadLength - bodyHeight, bodyWidth,
- bodyHeight));
- body[1] =
- new Area(new Rectangle2D.Double(x + pinSpacing - bodyWidth / 2,
- y - leadLength - bodyHeight - tabHeight, bodyWidth, tabHeight));
- ((Area) body[1]).subtract(new Area(new Ellipse2D.Double(x + pinSpacing - tabHoleDiameter / 2, y
- - leadLength - bodyHeight - tabHeight / 2 - tabHoleDiameter / 2, tabHoleDiameter, tabHoleDiameter)));
- } else {
- body[0] = new Area(
- new Rectangle2D.Double(x + pinSpacing - bodyWidth / 2, y - bodyThickness / 2, bodyWidth, bodyThickness));
- body[1] = new Area(
- new Rectangle2D.Double(x + pinSpacing - bodyWidth / 2, y - bodyThickness / 2, bodyWidth, tabThickness));
- }
- break;
- default:
- throw new RuntimeException("Unexpected orientation: " + orientation);
- }
- }
- return body;
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- if (checkPointsClipped(g2d.getClip())) {
- return;
- }
- drawingObserver.stopTracking();
- int pinSize = (int) PIN_SIZE.convertToPixels() / 2 * 2;
-
- Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
-
- // Draw pins.
-
- if (folded) {
- if (getLeadLength().getValue() > 0) {
- int leadThickness = getClosestOdd(LEAD_THICKNESS.convertToPixels());
- int leadLength = (int) getLeadLength().convertToPixels();
- Color finalPinColor;
- Color finalPinBorderColor;
- if (outlineMode) {
- finalPinColor = new Color(0, 0, 0, 0);
- finalPinBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalPinColor = METAL_COLOR;
- finalPinBorderColor = METAL_COLOR.darker();
- }
- Line2D line;
- for (Point2D point : controlPoints) {
- switch (orientation) {
- case DEFAULT:
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
- g2d.setColor(finalPinBorderColor);
- line = new Line2D.Double(point.getX(), point.getY(), point.getX() + leadLength - leadThickness / 2, point.getY());
- drawingObserver.startTracking();
- g2d.draw(line);
- drawingObserver.stopTracking();
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2));
- g2d.setColor(finalPinColor);
- g2d.draw(line);
- break;
- case _90:
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
- g2d.setColor(finalPinBorderColor);
- line = new Line2D.Double(point.getX(), point.getY(), point.getX(), point.getY() + leadLength - leadThickness / 2);
- drawingObserver.startTracking();
- g2d.draw(line);
- drawingObserver.stopTracking();
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2));
- g2d.setColor(finalPinColor);
- g2d.draw(line);
- break;
- case _180:
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
- g2d.setColor(finalPinBorderColor);
- line = new Line2D.Double(point.getX(), point.getY(), point.getX() - leadLength - leadThickness / 2, point.getY());
- drawingObserver.startTracking();
- g2d.draw(line);
- drawingObserver.stopTracking();
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2));
- g2d.setColor(finalPinColor);
- g2d.draw(line);
- break;
- case _270:
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
- g2d.setColor(finalPinBorderColor);
- line = new Line2D.Double(point.getX(), point.getY(), point.getX(), point.getY() - leadLength);
- drawingObserver.startTracking();
- g2d.draw(line);
- drawingObserver.stopTracking();
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2));
- g2d.setColor(finalPinColor);
- g2d.draw(line);
- break;
- }
- }
- }
- } else {
- if (!outlineMode) {
- for (Point2D point : controlPoints) {
-
- g2d.setColor(PIN_COLOR);
- Shape pin = new Ellipse2D.Double(point.getX() - pinSize / 2, point.getY() - pinSize / 2, pinSize, pinSize);
- g2d.fill(pin);
- g2d.setColor(outlineMode ? theme.getOutlineColor() : PIN_BORDER_COLOR);
- g2d.draw(pin);
- }
- }
- }
-
-
- Shape mainArea = getBody()[0];
- Shape tabArea = getBody()[1];
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor);
- drawingObserver.startTracking();
- g2d.fill(mainArea);
- drawingObserver.stopTracking();
- Color finalTabColor;
- if (outlineMode) {
- finalTabColor = theme.getOutlineColor();
- } else {
- finalTabColor = tabColor;
- }
- g2d.setColor(finalTabColor);
- g2d.fill(tabArea);
- g2d.setComposite(oldComposite);
- if (!outlineMode) {
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
- g2d.setColor(tabBorderColor);
- g2d.draw(tabArea);
- }
- Color finalBorderColor;
-
- if (outlineMode) {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : borderColor;
- }
- g2d.setColor(finalBorderColor);
- g2d.draw(mainArea);
- if (folded) {
- g2d.draw(tabArea);
- }
-
- // Draw label.
- g2d.setFont(project.getFont());
-
- // Override font size
- if (getFontSizeOverride() != null)
- g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride()));
-
- Color finalLabelColor;
- if (outlineMode) {
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : theme.getOutlineColor();
- } else {
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : getLabelColor();
- }
- g2d.setColor(finalLabelColor);
- if (getDisplay() == TransistorDisplay.PINOUT) {
- drawPinout(g2d);
- } else {
- String label = "";
- label = (getDisplay() == TransistorDisplay.NAME) ? getName() : getValue();
- if (getDisplay() == TransistorDisplay.NONE) {
- label = "";
- }
- if (getDisplay() == TransistorDisplay.BOTH) {
- label = getName() + " " + (getValue() == null ? "" : getValue().toString());
- }
- FontMetrics fontMetrics = g2d.getFontMetrics(g2d.getFont());
- Rectangle2D rect = fontMetrics.getStringBounds(label, g2d);
- int textHeight = (int) (rect.getHeight());
- int textWidth = (int) (rect.getWidth());
- // Center text horizontally and vertically
- Rectangle bounds = mainArea.getBounds();
- int x = (int) (bounds.getX() + (bounds.width - textWidth) / 2);
- int y = (int) (bounds.getY() + (bounds.height - textHeight) / 2 + fontMetrics.getAscent());
- g2d.drawString(label, x, y);
- }
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int margin = 2 * width / 32;
- int bodySize = width * 5 / 10;
- int tabSize = bodySize * 6 / 10;
- int holeSize = 5 * width / 32;
- Area a = new Area(new Rectangle2D.Double((width - bodySize) / 2, margin, bodySize, tabSize));
- a.subtract(new Area(new Ellipse2D.Double(width / 2 - holeSize / 2, margin + tabSize / 2 - holeSize / 2, holeSize,
- holeSize)));
- g2d.setColor(TAB_COLOR);
- g2d.fill(a);
- g2d.setColor(BORDER_COLOR);
- g2d.draw(a);
- g2d.setColor(BODY_COLOR);
- g2d.fillRect((width - bodySize) / 2, margin + tabSize, bodySize, bodySize);
- g2d.setColor(BORDER_COLOR);
- g2d.drawRect((width - bodySize) / 2, margin + tabSize, bodySize, bodySize);
- g2d.setColor(METAL_COLOR);
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(2));
- g2d.drawLine(width / 2, margin + tabSize + bodySize + 1, width / 2, height - margin);
- g2d.drawLine(width / 2 - bodySize / 3, margin + tabSize + bodySize + 1, width / 2 - bodySize / 3, height - margin);
- g2d.drawLine(width / 2 + bodySize / 3, margin + tabSize + bodySize + 1, width / 2 + bodySize / 3, height - margin);
- }
-
- @EditableProperty(name = "Tab")
- public Color getTabColor() {
- return tabColor;
- }
-
- public void setTabColor(Color tabColor) {
- this.tabColor = tabColor;
- }
-
- @EditableProperty(name = "Lead Length")
- public Size getLeadLength() {
- if (leadLength == null) {
- leadLength = LEAD_LENGTH;
- }
- return leadLength;
- }
-
- public void setLeadLength(Size leadLength) {
- this.leadLength = leadLength;
- // Invalidate the body
- this.body = null;
- }
-
- @EditableProperty(name = "Tab Border")
- public Color getTabBorderColor() {
- return tabBorderColor;
- }
-
- public void setTabBorderColor(Color tabBorderColor) {
- this.tabBorderColor = tabBorderColor;
- }
-
- @Override
- protected boolean flipPinoutLabel() {
- return true;
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.semiconductors;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.geom.Area;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Line2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.common.IPlugInPort;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.Percentage;
+import org.diylc.components.transform.TO220Transformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+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;
+import org.diylc.utils.Constants;
+
+@ComponentDescriptor(name = "Transistor (TO-220)", author = "Branislav Stojkovic", category = "Semiconductors",
+ instanceNamePrefix = "Q", description = "Transistors with metal tab for heat sink mounting",
+ zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_VALUE, transformer = TO220Transformer.class,
+ enableCache = true)
+public class TransistorTO220 extends AbstractTransistorPackage {
+
+ private static final long serialVersionUID = 1L;
+
+ public static Color BODY_COLOR = Color.gray;
+ public static Color BORDER_COLOR = Color.gray.darker();
+ public static Color PIN_COLOR = Color.decode("#00B2EE");
+ public static Color PIN_BORDER_COLOR = PIN_COLOR.darker();
+ public static Color TAB_COLOR = Color.lightGray;
+ public static Color TAB_BORDER_COLOR = TAB_COLOR.darker();
+ public static Color LABEL_COLOR = Color.white;
+ public static Size PIN_SIZE = new Size(0.03d, SizeUnit.in);
+ public static Size PIN_SPACING = new Size(0.1d, SizeUnit.in);
+ public static Size BODY_WIDTH = new Size(0.4d, SizeUnit.in);
+ public static Size BODY_THICKNESS = new Size(4.5d, SizeUnit.mm);
+ public static Size BODY_HEIGHT = new Size(9d, SizeUnit.mm);
+ public static Size TAB_THICKNESS = new Size(1d, SizeUnit.mm);
+ public static Size TAB_HEIGHT = new Size(6.2d, SizeUnit.mm);
+ public static Size TAB_HOLE_DIAMETER = new Size(3.6d, SizeUnit.mm);
+ public static Size LEAD_LENGTH = new Size(3.5d, SizeUnit.mm);
+ public static Size LEAD_THICKNESS = new Size(0.8d, SizeUnit.mm);
+
+ private Color tabColor = TAB_COLOR;
+ private Color tabBorderColor = TAB_BORDER_COLOR;
+ private Size leadLength = LEAD_LENGTH;
+
+ public TransistorTO220() {
+ super();
+ updateControlPoints();
+ this.alphaPercent = new Percentage(100);
+ bodyColor = BODY_COLOR;
+ borderColor = BORDER_COLOR;
+ }
+
+ @Override
+ protected void updateControlPoints() {
+ int pinSpacing = (int) PIN_SPACING.convertToPixels();
+ // Update control points.
+ double x = controlPoints[0].getX();
+ double y = controlPoints[0].getY();
+ switch (orientation) {
+ case DEFAULT:
+ controlPoints[1].setLocation(x, y + pinSpacing);
+ controlPoints[2].setLocation(x, y + 2 * pinSpacing);
+ break;
+ case _90:
+ controlPoints[1].setLocation(x - pinSpacing, y);
+ controlPoints[2].setLocation(x - 2 * pinSpacing, y);
+ break;
+ case _180:
+ controlPoints[1].setLocation(x, y - pinSpacing);
+ controlPoints[2].setLocation(x, y - 2 * pinSpacing);
+ break;
+ case _270:
+ controlPoints[1].setLocation(x + pinSpacing, y);
+ controlPoints[2].setLocation(x + 2 * pinSpacing, y);
+ break;
+ default:
+ throw new RuntimeException("Unexpected orientation: " + orientation);
+ }
+ }
+
+ public Area[] getBody() {
+ if (body == null) {
+ body = new Area[2];
+ double x = controlPoints[0].getX();
+ double y = controlPoints[0].getY();
+ int pinSpacing = (int) PIN_SPACING.convertToPixels();
+ int bodyWidth = getClosestOdd(BODY_WIDTH.convertToPixels());
+ int bodyThickness = getClosestOdd(BODY_THICKNESS.convertToPixels());
+ int bodyHeight = getClosestOdd(BODY_HEIGHT.convertToPixels());
+ int tabThickness = (int) TAB_THICKNESS.convertToPixels();
+ int tabHeight = (int) TAB_HEIGHT.convertToPixels();
+ int tabHoleDiameter = (int) TAB_HOLE_DIAMETER.convertToPixels();
+ double leadLength = getLeadLength().convertToPixels();
+
+ switch (orientation) {
+ case DEFAULT:
+ if (folded) {
+ body[0] = new Area(new Rectangle2D.Double(x + leadLength, y + pinSpacing - bodyWidth / 2, bodyHeight, bodyWidth));
+ body[1] =
+ new Area(new Rectangle2D.Double(x + leadLength + bodyHeight, y + pinSpacing - bodyWidth / 2, tabHeight,
+ bodyWidth));
+ ((Area) body[1]).subtract(new Area(new Ellipse2D.Double(x + leadLength + bodyHeight + tabHeight / 2
+ - tabHoleDiameter / 2, y + pinSpacing - tabHoleDiameter / 2, tabHoleDiameter, tabHoleDiameter)));
+ } else {
+ body[0] = new Area(
+ new Rectangle2D.Double(x - bodyThickness / 2, y + pinSpacing - bodyWidth / 2, bodyThickness, bodyWidth));
+ body[1] = new Area(
+ new Rectangle2D.Double(x + bodyThickness / 2 - tabThickness, y + pinSpacing - bodyWidth / 2,
+ tabThickness, bodyWidth));
+ }
+ break;
+ case _90:
+ if (folded) {
+ body[0] = new Area(new Rectangle2D.Double(x - pinSpacing - bodyWidth / 2, y + leadLength, bodyWidth, bodyHeight));
+ body[1] =
+ new Area(new Rectangle2D.Double(x - pinSpacing - bodyWidth / 2, y + leadLength + bodyHeight, bodyWidth,
+ tabHeight));
+ ((Area) body[1]).subtract(new Area(new Ellipse2D.Double(x - pinSpacing - tabHoleDiameter / 2, y
+ + leadLength + bodyHeight + tabHeight / 2 - tabHoleDiameter / 2, tabHoleDiameter, tabHoleDiameter)));
+ } else {
+ body[0] = new Area(
+ new Rectangle2D.Double(x - pinSpacing - bodyWidth / 2, y - bodyThickness / 2, bodyWidth, bodyThickness));
+ body[1] = new Area(
+ new Rectangle2D.Double(x - pinSpacing - bodyWidth / 2, y + bodyThickness / 2 - tabThickness, bodyWidth,
+ tabThickness));
+ }
+ break;
+ case _180:
+ if (folded) {
+ body[0] = new Area(
+ new Rectangle2D.Double(x - leadLength - bodyHeight, y - pinSpacing - bodyWidth / 2, bodyHeight,
+ bodyWidth));
+ body[1] =
+ new Area(new Rectangle2D.Double(x - leadLength - bodyHeight - tabHeight,
+ y - pinSpacing - bodyWidth / 2, tabHeight, bodyWidth));
+ ((Area) body[1]).subtract(new Area(new Ellipse2D.Double(x - leadLength - bodyHeight - tabHeight / 2
+ - tabHoleDiameter / 2, y - pinSpacing - tabHoleDiameter / 2, tabHoleDiameter, tabHoleDiameter)));
+ } else {
+ body[0] = new Area(
+ new Rectangle2D.Double(x - bodyThickness / 2, y - pinSpacing - bodyWidth / 2, bodyThickness, bodyWidth));
+ body[1] = new Area(
+ new Rectangle2D.Double(x - bodyThickness / 2, y - pinSpacing - bodyWidth / 2, tabThickness, bodyWidth));
+ }
+ break;
+ case _270:
+ if (folded) {
+ body[0] = new Area(
+ new Rectangle2D.Double(x + pinSpacing - bodyWidth / 2, y - leadLength - bodyHeight, bodyWidth,
+ bodyHeight));
+ body[1] =
+ new Area(new Rectangle2D.Double(x + pinSpacing - bodyWidth / 2,
+ y - leadLength - bodyHeight - tabHeight, bodyWidth, tabHeight));
+ ((Area) body[1]).subtract(new Area(new Ellipse2D.Double(x + pinSpacing - tabHoleDiameter / 2, y
+ - leadLength - bodyHeight - tabHeight / 2 - tabHoleDiameter / 2, tabHoleDiameter, tabHoleDiameter)));
+ } else {
+ body[0] = new Area(
+ new Rectangle2D.Double(x + pinSpacing - bodyWidth / 2, y - bodyThickness / 2, bodyWidth, bodyThickness));
+ body[1] = new Area(
+ new Rectangle2D.Double(x + pinSpacing - bodyWidth / 2, y - bodyThickness / 2, bodyWidth, tabThickness));
+ }
+ break;
+ default:
+ throw new RuntimeException("Unexpected orientation: " + orientation);
+ }
+ }
+ return body;
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ if (checkPointsClipped(g2d.getClip())) {
+ return;
+ }
+ drawingObserver.stopTracking();
+ int pinSize = (int) PIN_SIZE.convertToPixels() / 2 * 2;
+
+ Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+
+ // Draw pins.
+
+ if (folded) {
+ if (getLeadLength().getValue() > 0) {
+ int leadThickness = getClosestOdd(LEAD_THICKNESS.convertToPixels());
+ int leadLength = (int) getLeadLength().convertToPixels();
+ Color finalPinColor;
+ Color finalPinBorderColor;
+ if (outlineMode) {
+ finalPinColor = new Color(0, 0, 0, 0);
+ finalPinBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalPinColor = METAL_COLOR;
+ finalPinBorderColor = METAL_COLOR.darker();
+ }
+ Line2D line;
+ for (Point2D point : controlPoints) {
+ switch (orientation) {
+ case DEFAULT:
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
+ g2d.setColor(finalPinBorderColor);
+ line = new Line2D.Double(point.getX(), point.getY(), point.getX() + leadLength - leadThickness / 2, point.getY());
+ drawingObserver.startTracking();
+ g2d.draw(line);
+ drawingObserver.stopTracking();
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2));
+ g2d.setColor(finalPinColor);
+ g2d.draw(line);
+ break;
+ case _90:
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
+ g2d.setColor(finalPinBorderColor);
+ line = new Line2D.Double(point.getX(), point.getY(), point.getX(), point.getY() + leadLength - leadThickness / 2);
+ drawingObserver.startTracking();
+ g2d.draw(line);
+ drawingObserver.stopTracking();
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2));
+ g2d.setColor(finalPinColor);
+ g2d.draw(line);
+ break;
+ case _180:
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
+ g2d.setColor(finalPinBorderColor);
+ line = new Line2D.Double(point.getX(), point.getY(), point.getX() - leadLength - leadThickness / 2, point.getY());
+ drawingObserver.startTracking();
+ g2d.draw(line);
+ drawingObserver.stopTracking();
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2));
+ g2d.setColor(finalPinColor);
+ g2d.draw(line);
+ break;
+ case _270:
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
+ g2d.setColor(finalPinBorderColor);
+ line = new Line2D.Double(point.getX(), point.getY(), point.getX(), point.getY() - leadLength);
+ drawingObserver.startTracking();
+ g2d.draw(line);
+ drawingObserver.stopTracking();
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2));
+ g2d.setColor(finalPinColor);
+ g2d.draw(line);
+ break;
+ }
+ }
+ }
+ } else {
+ if (!outlineMode) {
+ for (Point2D point : controlPoints) {
+
+ g2d.setColor(PIN_COLOR);
+ Shape pin = new Ellipse2D.Double(point.getX() - pinSize / 2, point.getY() - pinSize / 2, pinSize, pinSize);
+ g2d.fill(pin);
+ g2d.setColor(outlineMode ? theme.getOutlineColor() : PIN_BORDER_COLOR);
+ g2d.draw(pin);
+ }
+ }
+ }
+
+
+ Shape mainArea = getBody()[0];
+ Shape tabArea = getBody()[1];
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor);
+ drawingObserver.startTracking();
+ g2d.fill(mainArea);
+ drawingObserver.stopTracking();
+ Color finalTabColor;
+ if (outlineMode) {
+ finalTabColor = theme.getOutlineColor();
+ } else {
+ finalTabColor = tabColor;
+ }
+ g2d.setColor(finalTabColor);
+ g2d.fill(tabArea);
+ g2d.setComposite(oldComposite);
+ if (!outlineMode) {
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+ g2d.setColor(tabBorderColor);
+ g2d.draw(tabArea);
+ }
+ Color finalBorderColor;
+
+ if (outlineMode) {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : borderColor;
+ }
+ g2d.setColor(finalBorderColor);
+ g2d.draw(mainArea);
+ if (folded) {
+ g2d.draw(tabArea);
+ }
+
+ // Draw label.
+ g2d.setFont(project.getFont());
+
+ // Override font size
+ if (getFontSizeOverride() != null)
+ g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride()));
+
+ Color finalLabelColor;
+ if (outlineMode) {
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : theme.getOutlineColor();
+ } else {
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : getLabelColor();
+ }
+ g2d.setColor(finalLabelColor);
+ if (getDisplay() == TransistorDisplay.PINOUT) {
+ drawPinout(g2d);
+ } else {
+ String label = "";
+ label = (getDisplay() == TransistorDisplay.NAME) ? getName() : getValue();
+ if (getDisplay() == TransistorDisplay.NONE) {
+ label = "";
+ }
+ if (getDisplay() == TransistorDisplay.BOTH) {
+ label = getName() + " " + (getValue() == null ? "" : getValue().toString());
+ }
+ FontMetrics fontMetrics = g2d.getFontMetrics(g2d.getFont());
+ Rectangle2D rect = fontMetrics.getStringBounds(label, g2d);
+ int textHeight = (int) (rect.getHeight());
+ int textWidth = (int) (rect.getWidth());
+ // Center text horizontally and vertically
+ Rectangle bounds = mainArea.getBounds();
+ int x = (int) (bounds.getX() + (bounds.width - textWidth) / 2);
+ int y = (int) (bounds.getY() + (bounds.height - textHeight) / 2 + fontMetrics.getAscent());
+ g2d.drawString(label, x, y);
+ }
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int margin = 2 * width / 32;
+ int bodySize = width * 5 / 10;
+ int tabSize = bodySize * 6 / 10;
+ int holeSize = 5 * width / 32;
+ Area a = new Area(new Rectangle2D.Double((width - bodySize) / 2, margin, bodySize, tabSize));
+ a.subtract(new Area(new Ellipse2D.Double(width / 2 - holeSize / 2, margin + tabSize / 2 - holeSize / 2, holeSize,
+ holeSize)));
+ g2d.setColor(TAB_COLOR);
+ g2d.fill(a);
+ g2d.setColor(BORDER_COLOR);
+ g2d.draw(a);
+ g2d.setColor(BODY_COLOR);
+ g2d.fillRect((width - bodySize) / 2, margin + tabSize, bodySize, bodySize);
+ g2d.setColor(BORDER_COLOR);
+ g2d.drawRect((width - bodySize) / 2, margin + tabSize, bodySize, bodySize);
+ g2d.setColor(METAL_COLOR);
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(2));
+ g2d.drawLine(width / 2, margin + tabSize + bodySize + 1, width / 2, height - margin);
+ g2d.drawLine(width / 2 - bodySize / 3, margin + tabSize + bodySize + 1, width / 2 - bodySize / 3, height - margin);
+ g2d.drawLine(width / 2 + bodySize / 3, margin + tabSize + bodySize + 1, width / 2 + bodySize / 3, height - margin);
+ }
+
+ @EditableProperty(name = "Tab")
+ public Color getTabColor() {
+ return tabColor;
+ }
+
+ public void setTabColor(Color tabColor) {
+ this.tabColor = tabColor;
+ }
+
+ @EditableProperty(name = "Lead Length")
+ public Size getLeadLength() {
+ if (leadLength == null) {
+ leadLength = LEAD_LENGTH;
+ }
+ return leadLength;
+ }
+
+ public void setLeadLength(Size leadLength) {
+ this.leadLength = leadLength;
+ // Invalidate the body
+ this.body = null;
+ }
+
+ @EditableProperty(name = "Tab Border")
+ public Color getTabBorderColor() {
+ return tabBorderColor;
+ }
+
+ public void setTabBorderColor(Color tabBorderColor) {
+ this.tabBorderColor = tabBorderColor;
+ }
+
+ @Override
+ protected boolean flipPinoutLabel() {
+ return true;
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/TransistorTO3.java b/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/TransistorTO3.java
index e6be5fd09..357ab3b4c 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/TransistorTO3.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/TransistorTO3.java
@@ -1,395 +1,389 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.semiconductors;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.FontMetrics;
-import java.awt.Graphics2D;
-import java.awt.Rectangle;
-import java.awt.RenderingHints;
-import java.awt.Shape;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Area;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.awt.TwoCircleTangent;
-import org.diylc.common.Display;
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.Orientation;
-import org.diylc.components.AbstractLabeledComponent;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-import org.diylc.core.VisibilityPolicy;
-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;
-import org.diylc.utils.Constants;
-
-@ComponentDescriptor(name = "Transistor (TO-3)", author = "Branislav Stojkovic", category = "Semiconductors",
- instanceNamePrefix = "Q", description = "Transistor with large metal body",
- zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_VALUE, enableCache = true)
-public class TransistorTO3 extends AbstractLabeledComponent {
-
- private static final long serialVersionUID = 1L;
-
- public static Color BODY_COLOR = Color.lightGray;
- public static Color BORDER_COLOR = BODY_COLOR.darker();
- public static Color PIN_COLOR = Color.decode("#00B2EE");
- public static Color PIN_BORDER_COLOR = PIN_COLOR.darker();
- public static Color LABEL_COLOR = Color.black;
-
- public static Size LARGE_DIAMETER = new Size(26.2d, SizeUnit.mm);
- public static Size INNER_DIAMETER = new Size(21.3d, SizeUnit.mm);
- public static Size SMALL_DIAMETER = new Size(8d, SizeUnit.mm);
- public static Size HOLE_DISTANCE = new Size(30.1d, SizeUnit.mm);
- public static Size HOLE_SIZE = new Size(4.1d, SizeUnit.mm);
- public static Size PIN_SPACING = new Size(10.9d, SizeUnit.mm);
- public static Size PIN_OFFSET = new Size(1.85d, SizeUnit.mm);
- public static Size PIN_DIAMETER = new Size(1d, SizeUnit.mm);
-
- private String value = "";
- private Orientation orientation = Orientation.DEFAULT;
- private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0), new Point2D.Double(0, 0)};
- transient private Area[] body;
- private Color bodyColor = BODY_COLOR;
- private Color borderColor = BORDER_COLOR;
- private Color labelColor = LABEL_COLOR;
- protected Display display = Display.NAME;
-
- public TransistorTO3() {
- super();
- updateControlPoints();
- alpha = (byte) 100;
- }
-
- @EditableProperty
- public String getValue() {
- return value;
- }
-
- public void setValue(String value) {
- this.value = value;
- }
-
- @EditableProperty
- public Orientation getOrientation() {
- return orientation;
- }
-
- public void setOrientation(Orientation orientation) {
- this.orientation = orientation;
- updateControlPoints();
- // Reset body shape;
- body = null;
- }
-
- @Override
- public int getControlPointCount() {
- return controlPoints.length;
- }
-
- @Override
- public Point2D getControlPoint(int index) {
- return controlPoints[index];
- }
-
- @Override
- public boolean isControlPointSticky(int index) {
- return true;
- }
-
- @Override
- public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
- return VisibilityPolicy.NEVER;
- }
-
- @Override
- public void setControlPoint(Point2D point, int index) {
- controlPoints[index].setLocation(point);
- body = null;
- }
-
- private void updateControlPoints() {
- int pinSpacing = (int) PIN_SPACING.convertToPixels();
- // Update control points.
- double x = controlPoints[0].getX();
- double y = controlPoints[0].getY();
- switch (orientation) {
- case DEFAULT:
- controlPoints[1].setLocation(x, y + pinSpacing);
- break;
- case _90:
- controlPoints[1].setLocation(x - pinSpacing, y);
- break;
- case _180:
- controlPoints[1].setLocation(x, y - pinSpacing);
- break;
- case _270:
- controlPoints[1].setLocation(x + pinSpacing, y);
- break;
- default:
- throw new RuntimeException("Unexpected orientation: " + orientation);
- }
- }
-
- public Area[] getBody() {
- if (body == null) {
- body = new Area[2];
- int pinOffset = (int) PIN_OFFSET.convertToPixels();
- double x = (controlPoints[0].getX() + controlPoints[1].getX()) / 2;
- double y = (controlPoints[0].getY() + controlPoints[1].getY()) / 2;
-
- switch (orientation) {
- case DEFAULT:
- x += pinOffset;
- break;
- case _90:
- y += pinOffset;
- break;
- case _180:
- x -= pinOffset;
- break;
- case _270:
- y -= pinOffset;
- break;
- default:
- throw new RuntimeException("Unexpected orientation: " + orientation);
- }
-
- int largeDiameter = getClosestOdd(LARGE_DIAMETER.convertToPixels());
- int innerDiameter = getClosestOdd(INNER_DIAMETER.convertToPixels());
- int smallDiameter = getClosestOdd(SMALL_DIAMETER.convertToPixels());
- int holeDistance = getClosestOdd(HOLE_DISTANCE.convertToPixels());
- int holeSize = getClosestOdd(HOLE_SIZE.convertToPixels());
-
- TwoCircleTangent left = new TwoCircleTangent(new Point2D.Double(x, y), new Point2D.Double(x - holeDistance / 2, y), largeDiameter / 2, smallDiameter / 2);
- TwoCircleTangent right = new TwoCircleTangent(new Point2D.Double(x, y), new Point2D.Double(x + holeDistance / 2, y), largeDiameter / 2, smallDiameter / 2);
-
- body[0] = left;
- body[0].add(right);
-
- body[0].subtract(new Area(new Ellipse2D.Double(x - holeDistance / 2 - holeSize / 2, y - holeSize / 2, holeSize,
- holeSize)));
- body[0].subtract(new Area(new Ellipse2D.Double(x + holeDistance / 2 - holeSize / 2, y - holeSize / 2, holeSize,
- holeSize)));
-
- switch (orientation) {
- case DEFAULT:
- break;
- case _90:
- body[0].transform(AffineTransform.getRotateInstance(Math.PI / 2, x, y));
- break;
- case _180:
- body[0].transform(AffineTransform.getRotateInstance(Math.PI, x, y));
- break;
- case _270:
- body[0].transform(AffineTransform.getRotateInstance(Math.PI * 3 / 2, x, y));
- break;
- default:
- throw new RuntimeException("Unexpected orientation: " + orientation);
- }
-
- body[1] =
- new Area(new Ellipse2D.Double(x - innerDiameter / 2, y - innerDiameter / 2, innerDiameter, innerDiameter));
- }
- return body;
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- if (checkPointsClipped(g2d.getClip())) {
- return;
- }
- drawingObserver.stopTracking();
- int pinSize = (int) PIN_DIAMETER.convertToPixels() / 2 * 2;
- Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f));
-
- 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.setColor(outlineMode ? theme.getOutlineColor() : PIN_BORDER_COLOR);
- g2d.drawOval((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize);
- }
-
- Area mainArea = getBody()[0];
- Area innerArea = getBody()[1];
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor);
- drawingObserver.startTracking();
- g2d.fill(mainArea);
- drawingObserver.stopTracking();
- g2d.setComposite(oldComposite);
- Color finalBorderColor;
-
- if (outlineMode) {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : borderColor;
- }
- g2d.setColor(finalBorderColor);
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
- g2d.draw(mainArea);
- g2d.draw(innerArea);
-
- // Draw label.
- g2d.setFont(project.getFont());
-
- // Override font size
- if (getFontSizeOverride() != null)
- g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride()));
-
- Color finalLabelColor;
- if (outlineMode) {
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : theme.getOutlineColor();
- } else {
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : getLabelColor();
- }
- g2d.setColor(finalLabelColor);
- String label = "";
- label = (getDisplay() == Display.NAME) ? getName() : getValue();
- if (getDisplay() == Display.NONE) {
- label = "";
- }
- if (getDisplay() == Display.BOTH) {
- label = getName() + " " + (getValue() == null ? "" : getValue().toString());
- }
- FontMetrics fontMetrics = g2d.getFontMetrics(g2d.getFont());
- Rectangle2D rect = fontMetrics.getStringBounds(label, g2d);
- int textHeight = (int) (rect.getHeight());
- int textWidth = (int) (rect.getWidth());
- // Center text horizontally and vertically
- Rectangle bounds = mainArea.getBounds();
- int x = (int) (bounds.getX() + (bounds.width - textWidth) / 2);
- int y = (int) (bounds.getY() + (bounds.height - textHeight) / 2 + fontMetrics.getAscent());
- g2d.drawString(label, x, y);
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
- int largeR = getClosestOdd(width * 3d / 8);
- int smallR = getClosestOdd(width / 6d);
- int innerD = getClosestOdd(width / 2d);
- int hole = 4 * width / 32;
-
- Area area = new TwoCircleTangent(new Point2D.Double(width * 0.5, height * 0.5), new Point2D.Double(width / 2, height / 8d), largeR, smallR);
- area.add((Area)new TwoCircleTangent(new Point2D.Double(width * 0.5, height * 0.5), new Point2D.Double(width / 2, height * 7 / 8d), largeR, smallR));
-
- area.subtract(new Area(new Ellipse2D.Double((width - hole) / 2, height / 8 - hole / 2, hole, hole)));
- area.subtract(new Area(new Ellipse2D.Double((width - hole) / 2, height * 7 / 8 - hole / 2, hole, hole)));
- area.transform(AffineTransform.getRotateInstance(Math.PI / 4, width / 2, height / 2));
- g2d.setColor(BODY_COLOR);
- g2d.fill(area);
- g2d.setColor(BORDER_COLOR);
- g2d.draw(area);
- g2d.drawOval((width - innerD) / 2, (height - innerD) / 2, innerD, innerD);
- }
-
- @EditableProperty(name = "Body")
- public Color getBodyColor() {
- return bodyColor;
- }
-
- public void setBodyColor(Color bodyColor) {
- this.bodyColor = bodyColor;
- }
-
- @EditableProperty(name = "Border")
- public Color getBorderColor() {
- return borderColor;
- }
-
- public void setBorderColor(Color borderColor) {
- this.borderColor = borderColor;
- }
-
- @EditableProperty(name = "Label")
- public Color getLabelColor() {
- return labelColor;
- }
-
- public void setLabelColor(Color labelColor) {
- this.labelColor = labelColor;
- }
-
- @EditableProperty
- public Display getDisplay() {
- if (display == null) {
- display = Display.NAME;
- }
- return display;
- }
-
- public void setDisplay(Display display) {
- this.display = display;
- }
-
- @Override
- public Rectangle2D getCachingBounds() {
- Shape[] body = getBody();
- int margin = 20;
- double minX = 0;
- double minY = 0;
- double maxX = 0;
- double maxY = 0;
- for (Shape a : body) {
- if (a != null) {
- Rectangle2D bounds2d = a.getBounds2D();
- if (bounds2d.getMinX() < minX)
- minX = bounds2d.getMinX();
- if (bounds2d.getMinY() < minY)
- minY = bounds2d.getMinY();
- if (bounds2d.getMaxX() > maxX)
- maxX = bounds2d.getMaxX();
- if (bounds2d.getMaxY() > maxY)
- maxY = bounds2d.getMaxY();
- }
- }
- return new Rectangle2D.Double(minX - margin, minY - margin, maxX - minX + 2 * margin, maxY - minY + 2 * margin);
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.semiconductors;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Area;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.awt.TwoCircleTangent;
+import org.diylc.common.*;
+import org.diylc.components.AbstractLabeledComponent;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+import org.diylc.core.VisibilityPolicy;
+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;
+import org.diylc.utils.Constants;
+
+@ComponentDescriptor(name = "Transistor (TO-3)", author = "Branislav Stojkovic", category = "Semiconductors",
+ instanceNamePrefix = "Q", description = "Transistor with large metal body",
+ zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_VALUE, enableCache = true)
+public class TransistorTO3 extends AbstractLabeledComponent {
+
+ private static final long serialVersionUID = 1L;
+
+ public static Color BODY_COLOR = Color.lightGray;
+ public static Color BORDER_COLOR = BODY_COLOR.darker();
+ public static Color PIN_COLOR = Color.decode("#00B2EE");
+ public static Color PIN_BORDER_COLOR = PIN_COLOR.darker();
+ public static Color LABEL_COLOR = Color.black;
+
+ public static Size LARGE_DIAMETER = new Size(26.2d, SizeUnit.mm);
+ public static Size INNER_DIAMETER = new Size(21.3d, SizeUnit.mm);
+ public static Size SMALL_DIAMETER = new Size(8d, SizeUnit.mm);
+ public static Size HOLE_DISTANCE = new Size(30.1d, SizeUnit.mm);
+ public static Size HOLE_SIZE = new Size(4.1d, SizeUnit.mm);
+ public static Size PIN_SPACING = new Size(10.9d, SizeUnit.mm);
+ public static Size PIN_OFFSET = new Size(1.85d, SizeUnit.mm);
+ public static Size PIN_DIAMETER = new Size(1d, SizeUnit.mm);
+
+ private String value = "";
+ private Orientation orientation = Orientation.DEFAULT;
+ private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0), new Point2D.Double(0, 0)};
+ transient private Area[] body;
+ private Color bodyColor = BODY_COLOR;
+ private Color borderColor = BORDER_COLOR;
+ private Color labelColor = LABEL_COLOR;
+ protected Display display = Display.NAME;
+
+ public TransistorTO3() {
+ super();
+ updateControlPoints();
+ this.alphaPercent = new Percentage(100);
+ }
+
+ @EditableProperty
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ @EditableProperty
+ public Orientation getOrientation() {
+ return orientation;
+ }
+
+ public void setOrientation(Orientation orientation) {
+ this.orientation = orientation;
+ updateControlPoints();
+ // Reset body shape;
+ body = null;
+ }
+
+ @Override
+ public int getControlPointCount() {
+ return controlPoints.length;
+ }
+
+ @Override
+ public Point2D getControlPoint(int index) {
+ return controlPoints[index];
+ }
+
+ @Override
+ public boolean isControlPointSticky(int index) {
+ return true;
+ }
+
+ @Override
+ public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
+ return VisibilityPolicy.NEVER;
+ }
+
+ @Override
+ public void setControlPoint(Point2D point, int index) {
+ controlPoints[index].setLocation(point);
+ body = null;
+ }
+
+ private void updateControlPoints() {
+ int pinSpacing = (int) PIN_SPACING.convertToPixels();
+ // Update control points.
+ double x = controlPoints[0].getX();
+ double y = controlPoints[0].getY();
+ switch (orientation) {
+ case DEFAULT:
+ controlPoints[1].setLocation(x, y + pinSpacing);
+ break;
+ case _90:
+ controlPoints[1].setLocation(x - pinSpacing, y);
+ break;
+ case _180:
+ controlPoints[1].setLocation(x, y - pinSpacing);
+ break;
+ case _270:
+ controlPoints[1].setLocation(x + pinSpacing, y);
+ break;
+ default:
+ throw new RuntimeException("Unexpected orientation: " + orientation);
+ }
+ }
+
+ public Area[] getBody() {
+ if (body == null) {
+ body = new Area[2];
+ int pinOffset = (int) PIN_OFFSET.convertToPixels();
+ double x = (controlPoints[0].getX() + controlPoints[1].getX()) / 2;
+ double y = (controlPoints[0].getY() + controlPoints[1].getY()) / 2;
+
+ switch (orientation) {
+ case DEFAULT:
+ x += pinOffset;
+ break;
+ case _90:
+ y += pinOffset;
+ break;
+ case _180:
+ x -= pinOffset;
+ break;
+ case _270:
+ y -= pinOffset;
+ break;
+ default:
+ throw new RuntimeException("Unexpected orientation: " + orientation);
+ }
+
+ int largeDiameter = getClosestOdd(LARGE_DIAMETER.convertToPixels());
+ int innerDiameter = getClosestOdd(INNER_DIAMETER.convertToPixels());
+ int smallDiameter = getClosestOdd(SMALL_DIAMETER.convertToPixels());
+ int holeDistance = getClosestOdd(HOLE_DISTANCE.convertToPixels());
+ int holeSize = getClosestOdd(HOLE_SIZE.convertToPixels());
+
+ TwoCircleTangent left = new TwoCircleTangent(new Point2D.Double(x, y), new Point2D.Double(x - holeDistance / 2, y), largeDiameter / 2, smallDiameter / 2);
+ TwoCircleTangent right = new TwoCircleTangent(new Point2D.Double(x, y), new Point2D.Double(x + holeDistance / 2, y), largeDiameter / 2, smallDiameter / 2);
+
+ body[0] = left;
+ body[0].add(right);
+
+ body[0].subtract(new Area(new Ellipse2D.Double(x - holeDistance / 2 - holeSize / 2, y - holeSize / 2, holeSize,
+ holeSize)));
+ body[0].subtract(new Area(new Ellipse2D.Double(x + holeDistance / 2 - holeSize / 2, y - holeSize / 2, holeSize,
+ holeSize)));
+
+ switch (orientation) {
+ case DEFAULT:
+ break;
+ case _90:
+ body[0].transform(AffineTransform.getRotateInstance(Math.PI / 2, x, y));
+ break;
+ case _180:
+ body[0].transform(AffineTransform.getRotateInstance(Math.PI, x, y));
+ break;
+ case _270:
+ body[0].transform(AffineTransform.getRotateInstance(Math.PI * 3 / 2, x, y));
+ break;
+ default:
+ throw new RuntimeException("Unexpected orientation: " + orientation);
+ }
+
+ body[1] =
+ new Area(new Ellipse2D.Double(x - innerDiameter / 2, y - innerDiameter / 2, innerDiameter, innerDiameter));
+ }
+ return body;
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ if (checkPointsClipped(g2d.getClip())) {
+ return;
+ }
+ drawingObserver.stopTracking();
+ int pinSize = (int) PIN_DIAMETER.convertToPixels() / 2 * 2;
+ Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f));
+
+ 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.setColor(outlineMode ? theme.getOutlineColor() : PIN_BORDER_COLOR);
+ g2d.drawOval((int)(point.getX() - pinSize / 2), (int)(point.getY() - pinSize / 2), pinSize, pinSize);
+ }
+
+ Area mainArea = getBody()[0];
+ Area innerArea = getBody()[1];
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor);
+ drawingObserver.startTracking();
+ g2d.fill(mainArea);
+ drawingObserver.stopTracking();
+ g2d.setComposite(oldComposite);
+ Color finalBorderColor;
+
+ if (outlineMode) {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : borderColor;
+ }
+ g2d.setColor(finalBorderColor);
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+ g2d.draw(mainArea);
+ g2d.draw(innerArea);
+
+ // Draw label.
+ g2d.setFont(project.getFont());
+
+ // Override font size
+ if (getFontSizeOverride() != null)
+ g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride()));
+
+ Color finalLabelColor;
+ if (outlineMode) {
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : theme.getOutlineColor();
+ } else {
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : getLabelColor();
+ }
+ g2d.setColor(finalLabelColor);
+ String label = "";
+ label = (getDisplay() == Display.NAME) ? getName() : getValue();
+ if (getDisplay() == Display.NONE) {
+ label = "";
+ }
+ if (getDisplay() == Display.BOTH) {
+ label = getName() + " " + (getValue() == null ? "" : getValue().toString());
+ }
+ FontMetrics fontMetrics = g2d.getFontMetrics(g2d.getFont());
+ Rectangle2D rect = fontMetrics.getStringBounds(label, g2d);
+ int textHeight = (int) (rect.getHeight());
+ int textWidth = (int) (rect.getWidth());
+ // Center text horizontally and vertically
+ Rectangle bounds = mainArea.getBounds();
+ int x = (int) (bounds.getX() + (bounds.width - textWidth) / 2);
+ int y = (int) (bounds.getY() + (bounds.height - textHeight) / 2 + fontMetrics.getAscent());
+ g2d.drawString(label, x, y);
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
+ int largeR = getClosestOdd(width * 3d / 8);
+ int smallR = getClosestOdd(width / 6d);
+ int innerD = getClosestOdd(width / 2d);
+ int hole = 4 * width / 32;
+
+ Area area = new TwoCircleTangent(new Point2D.Double(width * 0.5, height * 0.5), new Point2D.Double(width / 2, height / 8d), largeR, smallR);
+ area.add((Area)new TwoCircleTangent(new Point2D.Double(width * 0.5, height * 0.5), new Point2D.Double(width / 2, height * 7 / 8d), largeR, smallR));
+
+ area.subtract(new Area(new Ellipse2D.Double((width - hole) / 2, height / 8 - hole / 2, hole, hole)));
+ area.subtract(new Area(new Ellipse2D.Double((width - hole) / 2, height * 7 / 8 - hole / 2, hole, hole)));
+ area.transform(AffineTransform.getRotateInstance(Math.PI / 4, width / 2, height / 2));
+ g2d.setColor(BODY_COLOR);
+ g2d.fill(area);
+ g2d.setColor(BORDER_COLOR);
+ g2d.draw(area);
+ g2d.drawOval((width - innerD) / 2, (height - innerD) / 2, innerD, innerD);
+ }
+
+ @EditableProperty(name = "Body")
+ public Color getBodyColor() {
+ return bodyColor;
+ }
+
+ public void setBodyColor(Color bodyColor) {
+ this.bodyColor = bodyColor;
+ }
+
+ @EditableProperty(name = "Border")
+ public Color getBorderColor() {
+ return borderColor;
+ }
+
+ public void setBorderColor(Color borderColor) {
+ this.borderColor = borderColor;
+ }
+
+ @EditableProperty(name = "Label")
+ public Color getLabelColor() {
+ return labelColor;
+ }
+
+ public void setLabelColor(Color labelColor) {
+ this.labelColor = labelColor;
+ }
+
+ @EditableProperty
+ public Display getDisplay() {
+ if (display == null) {
+ display = Display.NAME;
+ }
+ return display;
+ }
+
+ public void setDisplay(Display display) {
+ this.display = display;
+ }
+
+ @Override
+ public Rectangle2D getCachingBounds() {
+ Shape[] body = getBody();
+ int margin = 20;
+ double minX = 0;
+ double minY = 0;
+ double maxX = 0;
+ double maxY = 0;
+ for (Shape a : body) {
+ if (a != null) {
+ Rectangle2D bounds2d = a.getBounds2D();
+ if (bounds2d.getMinX() < minX)
+ minX = bounds2d.getMinX();
+ if (bounds2d.getMinY() < minY)
+ minY = bounds2d.getMinY();
+ if (bounds2d.getMaxX() > maxX)
+ maxX = bounds2d.getMaxX();
+ if (bounds2d.getMaxY() > maxY)
+ maxY = bounds2d.getMaxY();
+ }
+ }
+ return new Rectangle2D.Double(minX - margin, minY - margin, maxX - minX + 2 * margin, maxY - minY + 2 * margin);
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/TransistorTO92.java b/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/TransistorTO92.java
index 0454f139f..c126a6b63 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/TransistorTO92.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/TransistorTO92.java
@@ -1,291 +1,289 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.semiconductors;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.FontMetrics;
-import java.awt.Graphics2D;
-import java.awt.Rectangle;
-import java.awt.RenderingHints;
-import java.awt.Shape;
-import java.awt.geom.Area;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.components.transform.TO92Transformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-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;
-import org.diylc.utils.Constants;
-
-@ComponentDescriptor(name = "Transistor (TO-92)", author = "Branislav Stojkovic", category = "Semiconductors",
- instanceNamePrefix = "Q", description = "Transistor with small plastic or epoxy body",
- zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_VALUE, transformer = TO92Transformer.class,
- enableCache = true)
-public class TransistorTO92 extends AbstractTransistorPackage {
-
- private static final long serialVersionUID = 1L;
-
- public static Color BODY_COLOR = Color.gray;
- public static Color BORDER_COLOR = Color.gray.darker();
- public static Color PIN_COLOR = Color.decode("#00B2EE");
- public static Color PIN_BORDER_COLOR = PIN_COLOR.darker();
- public static Color LABEL_COLOR = Color.white;
- public static Size PIN_SIZE = new Size(0.03d, SizeUnit.in);
- public static Size PIN_SPACING = new Size(0.05d, SizeUnit.in);
- public static Size BODY_DIAMETER = new Size(0.2d, SizeUnit.in);
-
- private Size pinSpacing = PIN_SPACING;
-
- public TransistorTO92() {
- super();
- updateControlPoints();
- alpha = (byte) 100;
- bodyColor = BODY_COLOR;
- borderColor = BORDER_COLOR;
- }
-
- @EditableProperty(name = "Pin spacing")
- public Size getPinSpacing() {
- if (pinSpacing == null) {
- pinSpacing = new Size(0.1, SizeUnit.in);
- }
- return pinSpacing;
- }
-
- public void setPinSpacing(Size pinSpacing) {
- this.pinSpacing = pinSpacing;
- updateControlPoints();
- // Reset body shape;
- body = null;
- }
-
- @Override
- protected void updateControlPoints() {
- int pinSpacing = (int) getPinSpacing().convertToPixels();
- // Update control points.
- double x = controlPoints[0].getX();
- double y = controlPoints[0].getY();
- switch (orientation) {
- case DEFAULT:
- controlPoints[1].setLocation(x, y + pinSpacing);
- controlPoints[2].setLocation(x, y + 2 * pinSpacing);
- break;
- case _90:
- controlPoints[1].setLocation(x - pinSpacing, y);
- controlPoints[2].setLocation(x - 2 * pinSpacing, y);
- break;
- case _180:
- controlPoints[1].setLocation(x, y - pinSpacing);
- controlPoints[2].setLocation(x, y - 2 * pinSpacing);
- break;
- case _270:
- controlPoints[1].setLocation(x + pinSpacing, y);
- controlPoints[2].setLocation(x + 2 * pinSpacing, y);
- break;
- default:
- throw new RuntimeException("Unexpected orientation: " + orientation);
- }
- }
-
- public Area[] getBody() {
- if (body == null) {
- double x = (controlPoints[0].getX() + controlPoints[1].getX() + controlPoints[2].getX()) / 3;
- double y = (controlPoints[0].getY() + controlPoints[1].getY() + controlPoints[2].getY()) / 3;
- int bodyDiameter = getClosestOdd(BODY_DIAMETER.convertToPixels());
-
- Area newBody = null;
-
- if (folded) {
- switch (orientation) {
- case DEFAULT:
- newBody = new Area(new Rectangle2D.Double(x, y - bodyDiameter / 2, bodyDiameter, bodyDiameter));
- break;
- case _90:
- newBody = new Area(new Rectangle2D.Double(x - bodyDiameter / 2, y, bodyDiameter, bodyDiameter));
- break;
- case _180:
- newBody = new Area(new Rectangle2D.Double(x - bodyDiameter, y - bodyDiameter / 2, bodyDiameter, bodyDiameter));
- break;
- case _270:
- newBody = new Area(new Rectangle2D.Double(x - bodyDiameter / 2, y - bodyDiameter, bodyDiameter, bodyDiameter));
- break;
- default:
- throw new RuntimeException("Unexpected orientation: " + orientation);
- }
- } else {
- switch (orientation) {
- case DEFAULT:
- newBody =
- new Area(new Ellipse2D.Double(x - bodyDiameter / 2, y - bodyDiameter / 2, bodyDiameter, bodyDiameter));
- newBody.subtract(new Area(new Rectangle2D.Double(x - bodyDiameter, y - bodyDiameter / 2, 3 * bodyDiameter / 4,
- bodyDiameter)));
- break;
- case _90:
- newBody =
- new Area(new Ellipse2D.Double(x - bodyDiameter / 2, y - bodyDiameter / 2, bodyDiameter, bodyDiameter));
- newBody.subtract(new Area(new Rectangle2D.Double(x - bodyDiameter / 2, y - bodyDiameter, bodyDiameter,
- 3 * bodyDiameter / 4)));
- break;
- case _180:
- newBody =
- new Area(new Ellipse2D.Double(x - bodyDiameter / 2, y - bodyDiameter / 2, bodyDiameter, bodyDiameter));
- newBody.subtract(new Area(new Rectangle2D.Double(x + bodyDiameter / 4, y - bodyDiameter / 2,
- 3 * bodyDiameter / 4, bodyDiameter)));
- break;
- case _270:
- newBody =
- new Area(new Ellipse2D.Double(x - bodyDiameter / 2, y - bodyDiameter / 2, bodyDiameter, bodyDiameter));
- newBody.subtract(new Area(new Rectangle2D.Double(x - bodyDiameter / 2, y + bodyDiameter / 4, bodyDiameter,
- 3 * bodyDiameter / 4)));
- break;
- default:
- throw new RuntimeException("Unexpected orientation: " + orientation);
- }
- }
-
- body = new Area[] { newBody };
- }
- return body;
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- if (checkPointsClipped(g2d.getClip())) {
- return;
- }
- drawingObserver.stopTracking();
- int pinSize = (int) PIN_SIZE.convertToPixels() / 2 * 2;
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f));
-
- if (!outlineMode) {
- for (Point2D point : controlPoints) {
- Shape pin = new Ellipse2D.Double(point.getX() - pinSize / 2, point.getY() - pinSize / 2, pinSize, pinSize);
- g2d.setColor(PIN_COLOR);
- g2d.fill(pin);
- g2d.setColor(PIN_BORDER_COLOR);
- g2d.draw(pin);
- }
- }
-
- Area mainArea = getBody()[0];
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor);
- drawingObserver.startTracking();
- g2d.fill(mainArea);
- drawingObserver.stopTracking();
- g2d.setComposite(oldComposite);
- Color finalBorderColor;
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : borderColor;
- }
- g2d.setColor(finalBorderColor);
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
- g2d.draw(mainArea);
-
- // Draw label.
- g2d.setFont(project.getFont());
-
- // Override font size
- if (getFontSizeOverride() != null)
- g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride()));
-
- Color finalLabelColor;
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : theme.getOutlineColor();
- } else {
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : getLabelColor();
- }
- g2d.setColor(finalLabelColor);
- if (getDisplay() == TransistorDisplay.PINOUT) {
- drawPinout(g2d);
- } else {
- String label = "";
- label = (getDisplay() == TransistorDisplay.NAME) ? getName() : getValue();
- if (display == TransistorDisplay.NONE) {
- label = "";
- }
- if (display == TransistorDisplay.BOTH) {
- label = getName() + " " + getValue();
- }
- FontMetrics fontMetrics = g2d.getFontMetrics(g2d.getFont());
- Rectangle2D rect = fontMetrics.getStringBounds(label, g2d);
- int textHeight = (int) (rect.getHeight());
- int textWidth = (int) (rect.getWidth());
- // Center text horizontally and vertically
- Rectangle bounds = mainArea.getBounds();
- int x = (int) (bounds.getX() + (bounds.width - textWidth) / 2);
- int y = (int) (bounds.getY() + (bounds.height - textHeight) / 2 + fontMetrics.getAscent());
- g2d.drawString(label, x, y);
- }
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
- int margin = 3 * width / 32;
- Area area = new Area(new Ellipse2D.Double(margin / 2, margin, width - 2 * margin, width - 2 * margin));
- // area.subtract(new Area(new Rectangle2D.Double(0, 0, 2 * margin,
- // height)));
- area.intersect(new Area(new Rectangle2D.Double(2 * margin, 0, width, height)));
- g2d.setColor(BODY_COLOR);
- g2d.fill(area);
- g2d.setColor(BORDER_COLOR);
- g2d.draw(area);
- g2d.setColor(PIN_COLOR);
- int pinSize = 2 * width / 32;
- for (int i = 0; i < 3; i++) {
- g2d.fillOval(width / 2 - pinSize / 2, (height / 4) * (i + 1), pinSize, pinSize);
- }
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.semiconductors;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.geom.Area;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.common.IPlugInPort;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.Percentage;
+import org.diylc.components.transform.TO92Transformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+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;
+import org.diylc.utils.Constants;
+
+@ComponentDescriptor(name = "Transistor (TO-92)", author = "Branislav Stojkovic", category = "Semiconductors",
+ instanceNamePrefix = "Q", description = "Transistor with small plastic or epoxy body",
+ zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_VALUE, transformer = TO92Transformer.class,
+ enableCache = true)
+public class TransistorTO92 extends AbstractTransistorPackage {
+
+ private static final long serialVersionUID = 1L;
+
+ public static Color BODY_COLOR = Color.gray;
+ public static Color BORDER_COLOR = Color.gray.darker();
+ public static Color PIN_COLOR = Color.decode("#00B2EE");
+ public static Color PIN_BORDER_COLOR = PIN_COLOR.darker();
+ public static Color LABEL_COLOR = Color.white;
+ public static Size PIN_SIZE = new Size(0.03d, SizeUnit.in);
+ public static Size PIN_SPACING = new Size(0.05d, SizeUnit.in);
+ public static Size BODY_DIAMETER = new Size(0.2d, SizeUnit.in);
+
+ private Size pinSpacing = PIN_SPACING;
+
+ public TransistorTO92() {
+ super();
+ updateControlPoints();
+ this.alphaPercent = new Percentage(100);
+ bodyColor = BODY_COLOR;
+ borderColor = BORDER_COLOR;
+ }
+
+ @EditableProperty(name = "Pin spacing")
+ public Size getPinSpacing() {
+ if (pinSpacing == null) {
+ pinSpacing = new Size(0.1, SizeUnit.in);
+ }
+ return pinSpacing;
+ }
+
+ public void setPinSpacing(Size pinSpacing) {
+ this.pinSpacing = pinSpacing;
+ updateControlPoints();
+ // Reset body shape;
+ body = null;
+ }
+
+ @Override
+ protected void updateControlPoints() {
+ int pinSpacing = (int) getPinSpacing().convertToPixels();
+ // Update control points.
+ double x = controlPoints[0].getX();
+ double y = controlPoints[0].getY();
+ switch (orientation) {
+ case DEFAULT:
+ controlPoints[1].setLocation(x, y + pinSpacing);
+ controlPoints[2].setLocation(x, y + 2 * pinSpacing);
+ break;
+ case _90:
+ controlPoints[1].setLocation(x - pinSpacing, y);
+ controlPoints[2].setLocation(x - 2 * pinSpacing, y);
+ break;
+ case _180:
+ controlPoints[1].setLocation(x, y - pinSpacing);
+ controlPoints[2].setLocation(x, y - 2 * pinSpacing);
+ break;
+ case _270:
+ controlPoints[1].setLocation(x + pinSpacing, y);
+ controlPoints[2].setLocation(x + 2 * pinSpacing, y);
+ break;
+ default:
+ throw new RuntimeException("Unexpected orientation: " + orientation);
+ }
+ }
+
+ public Area[] getBody() {
+ if (body == null) {
+ double x = (controlPoints[0].getX() + controlPoints[1].getX() + controlPoints[2].getX()) / 3;
+ double y = (controlPoints[0].getY() + controlPoints[1].getY() + controlPoints[2].getY()) / 3;
+ int bodyDiameter = getClosestOdd(BODY_DIAMETER.convertToPixels());
+
+ Area newBody = null;
+
+ if (folded) {
+ switch (orientation) {
+ case DEFAULT:
+ newBody = new Area(new Rectangle2D.Double(x, y - bodyDiameter / 2, bodyDiameter, bodyDiameter));
+ break;
+ case _90:
+ newBody = new Area(new Rectangle2D.Double(x - bodyDiameter / 2, y, bodyDiameter, bodyDiameter));
+ break;
+ case _180:
+ newBody = new Area(new Rectangle2D.Double(x - bodyDiameter, y - bodyDiameter / 2, bodyDiameter, bodyDiameter));
+ break;
+ case _270:
+ newBody = new Area(new Rectangle2D.Double(x - bodyDiameter / 2, y - bodyDiameter, bodyDiameter, bodyDiameter));
+ break;
+ default:
+ throw new RuntimeException("Unexpected orientation: " + orientation);
+ }
+ } else {
+ switch (orientation) {
+ case DEFAULT:
+ newBody =
+ new Area(new Ellipse2D.Double(x - bodyDiameter / 2, y - bodyDiameter / 2, bodyDiameter, bodyDiameter));
+ newBody.subtract(new Area(new Rectangle2D.Double(x - bodyDiameter, y - bodyDiameter / 2, 3 * bodyDiameter / 4,
+ bodyDiameter)));
+ break;
+ case _90:
+ newBody =
+ new Area(new Ellipse2D.Double(x - bodyDiameter / 2, y - bodyDiameter / 2, bodyDiameter, bodyDiameter));
+ newBody.subtract(new Area(new Rectangle2D.Double(x - bodyDiameter / 2, y - bodyDiameter, bodyDiameter,
+ 3 * bodyDiameter / 4)));
+ break;
+ case _180:
+ newBody =
+ new Area(new Ellipse2D.Double(x - bodyDiameter / 2, y - bodyDiameter / 2, bodyDiameter, bodyDiameter));
+ newBody.subtract(new Area(new Rectangle2D.Double(x + bodyDiameter / 4, y - bodyDiameter / 2,
+ 3 * bodyDiameter / 4, bodyDiameter)));
+ break;
+ case _270:
+ newBody =
+ new Area(new Ellipse2D.Double(x - bodyDiameter / 2, y - bodyDiameter / 2, bodyDiameter, bodyDiameter));
+ newBody.subtract(new Area(new Rectangle2D.Double(x - bodyDiameter / 2, y + bodyDiameter / 4, bodyDiameter,
+ 3 * bodyDiameter / 4)));
+ break;
+ default:
+ throw new RuntimeException("Unexpected orientation: " + orientation);
+ }
+ }
+
+ body = new Area[] { newBody };
+ }
+ return body;
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ if (checkPointsClipped(g2d.getClip())) {
+ return;
+ }
+ drawingObserver.stopTracking();
+ int pinSize = (int) PIN_SIZE.convertToPixels() / 2 * 2;
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f));
+
+ if (!outlineMode) {
+ for (Point2D point : controlPoints) {
+ Shape pin = new Ellipse2D.Double(point.getX() - pinSize / 2, point.getY() - pinSize / 2, pinSize, pinSize);
+ g2d.setColor(PIN_COLOR);
+ g2d.fill(pin);
+ g2d.setColor(PIN_BORDER_COLOR);
+ g2d.draw(pin);
+ }
+ }
+
+ Area mainArea = getBody()[0];
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor);
+ drawingObserver.startTracking();
+ g2d.fill(mainArea);
+ drawingObserver.stopTracking();
+ g2d.setComposite(oldComposite);
+ Color finalBorderColor;
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : borderColor;
+ }
+ g2d.setColor(finalBorderColor);
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+ g2d.draw(mainArea);
+
+ // Draw label.
+ g2d.setFont(project.getFont());
+
+ // Override font size
+ if (getFontSizeOverride() != null)
+ g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride()));
+
+ Color finalLabelColor;
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : theme.getOutlineColor();
+ } else {
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : getLabelColor();
+ }
+ g2d.setColor(finalLabelColor);
+ if (getDisplay() == TransistorDisplay.PINOUT) {
+ drawPinout(g2d);
+ } else {
+ String label = "";
+ label = (getDisplay() == TransistorDisplay.NAME) ? getName() : getValue();
+ if (display == TransistorDisplay.NONE) {
+ label = "";
+ }
+ if (display == TransistorDisplay.BOTH) {
+ label = getName() + " " + getValue();
+ }
+ FontMetrics fontMetrics = g2d.getFontMetrics(g2d.getFont());
+ Rectangle2D rect = fontMetrics.getStringBounds(label, g2d);
+ int textHeight = (int) (rect.getHeight());
+ int textWidth = (int) (rect.getWidth());
+ // Center text horizontally and vertically
+ Rectangle bounds = mainArea.getBounds();
+ int x = (int) (bounds.getX() + (bounds.width - textWidth) / 2);
+ int y = (int) (bounds.getY() + (bounds.height - textHeight) / 2 + fontMetrics.getAscent());
+ g2d.drawString(label, x, y);
+ }
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
+ int margin = 3 * width / 32;
+ Area area = new Area(new Ellipse2D.Double(margin / 2, margin, width - 2 * margin, width - 2 * margin));
+ // area.subtract(new Area(new Rectangle2D.Double(0, 0, 2 * margin,
+ // height)));
+ area.intersect(new Area(new Rectangle2D.Double(2 * margin, 0, width, height)));
+ g2d.setColor(BODY_COLOR);
+ g2d.fill(area);
+ g2d.setColor(BORDER_COLOR);
+ g2d.draw(area);
+ g2d.setColor(PIN_COLOR);
+ int pinSize = 2 * width / 32;
+ for (int i = 0; i < 3; i++) {
+ g2d.fillOval(width / 2 - pinSize / 2, (height / 4) * (i + 1), pinSize, pinSize);
+ }
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/shapes/Ellipse.java b/diylc/diylc-library/src/main/java/org/diylc/components/shapes/Ellipse.java
index 0c992eef5..2a2bdf968 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/shapes/Ellipse.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/shapes/Ellipse.java
@@ -1,76 +1,71 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.shapes;
-
-import java.awt.AlphaComposite;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-
-import org.diylc.common.ObjectCache;
-import org.diylc.components.transform.SimpleComponentTransformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.annotations.BomPolicy;
-import org.diylc.core.annotations.ComponentDescriptor;
-
-@ComponentDescriptor(name = "Ellipse", author = "Branislav Stojkovic", category = "Shapes", instanceNamePrefix = "ELL",
- description = "Elliptical area", zOrder = IDIYComponent.COMPONENT, flexibleZOrder = true,
- bomPolicy = BomPolicy.NEVER_SHOW, transformer = SimpleComponentTransformer.class)
-public class Ellipse extends AbstractShapeWithDimensions {
-
- private static final long serialVersionUID = 1L;
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke((int) borderThickness.convertToPixels()));
-
- float alpha = this.alpha;
- if (componentState == ComponentState.DRAGGING)
- alpha = 0;
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(color);
- g2d.fillOval((int)firstPoint.getX(), (int)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
- // tracked so far.
- 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()));
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int factor = 32 / width;
- g2d.setColor(COLOR);
- g2d.fillOval(2 / factor, 2 / factor, width - 4 / factor, height - 4 / factor);
- g2d.setColor(BORDER_COLOR);
- g2d.drawOval(2 / factor, 2 / factor, width - 4 / factor, height - 4 / factor);
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.shapes;
+
+import java.awt.AlphaComposite;
+import java.awt.Composite;
+import java.awt.Graphics2D;
+
+import org.diylc.common.ObjectCache;
+import org.diylc.common.Percentage;
+import org.diylc.components.transform.SimpleComponentTransformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.annotations.BomPolicy;
+import org.diylc.core.annotations.ComponentDescriptor;
+
+@ComponentDescriptor(name = "Ellipse", author = "Branislav Stojkovic", category = "Shapes", instanceNamePrefix = "ELL",
+ description = "Elliptical area", zOrder = IDIYComponent.COMPONENT, flexibleZOrder = true,
+ bomPolicy = BomPolicy.NEVER_SHOW, transformer = SimpleComponentTransformer.class)
+public class Ellipse extends AbstractShapeWithDimensions {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke((int) borderThickness.convertToPixels()));
+
+ 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.setComposite(oldComposite);
+
+ // Do not track any changes that follow because the whole oval has been
+ // tracked so far.
+ 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()));
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int factor = 32 / width;
+ g2d.setColor(COLOR);
+ g2d.fillOval(2 / factor, 2 / factor, width - 4 / factor, height - 4 / factor);
+ g2d.setColor(BORDER_COLOR);
+ g2d.drawOval(2 / factor, 2 / factor, width - 4 / factor, height - 4 / factor);
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/shapes/Polygon.java b/diylc/diylc-library/src/main/java/org/diylc/components/shapes/Polygon.java
index f770b46d0..75175ca41 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/shapes/Polygon.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/shapes/Polygon.java
@@ -1,129 +1,126 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.shapes;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-import java.awt.geom.Point2D;
-import java.util.Arrays;
-
-import org.diylc.common.ObjectCache;
-import org.diylc.components.transform.SimpleComponentTransformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.annotations.BomPolicy;
-import org.diylc.core.annotations.ComponentDescriptor;
-import org.diylc.core.annotations.EditableProperty;
-
-@ComponentDescriptor(name = "Polygon", author = "Branislav Stojkovic", category = "Shapes",
- instanceNamePrefix = "POLY", description = "Polygonal area", zOrder = IDIYComponent.COMPONENT,
- flexibleZOrder = true, bomPolicy = BomPolicy.NEVER_SHOW,
- transformer = SimpleComponentTransformer.class)
-public class Polygon extends AbstractShape {
-
- private static final long serialVersionUID = 1L;
-
- protected PointCount pointCount = PointCount._4;
-
- public Polygon() {
- super();
- this.controlPoints =
- new Point2D[] {new Point2D.Double(0, 0),
- new Point2D.Double(0, (int) DEFAULT_HEIGHT.convertToPixels()),
- new Point2D.Double((int) DEFAULT_WIDTH.convertToPixels(), (int) DEFAULT_HEIGHT.convertToPixels()),
- new Point2D.Double((int) DEFAULT_WIDTH.convertToPixels(), 0)};
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke((int) borderThickness.convertToPixels()));
- g2d.setColor(color);
- int[] xPoints = new int[controlPoints.length];
- int[] yPoints = new int[controlPoints.length];
- for (int i = 0; i < controlPoints.length; i++) {
- xPoints[i] = (int)controlPoints[i].getX();
- yPoints[i] = (int)controlPoints[i].getY();
- }
-
- Composite oldComposite = g2d.getComposite();
- if (this.alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(3, 1.0F * this.alpha / MAX_ALPHA));
- }
- g2d.fillPolygon(xPoints, yPoints, controlPoints.length);
- g2d.setComposite(oldComposite);
-
- // Do not track any changes that follow because the whole board has been
- // tracked so far.
- drawingObserver.stopTracking();
- Color lineColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : borderColor;
- g2d.setColor(lineColor);
- g2d.drawPolygon(xPoints, yPoints, controlPoints.length);
- }
-
- @EditableProperty(name = "Edges")
- public PointCount getPointCount() {
- return pointCount;
- }
-
- public void setPointCount(PointCount pointCount) {
- if (this.pointCount == pointCount)
- return;
- int oldPointCount = Integer.parseInt(this.pointCount.toString());
- int newPointCount = Integer.parseInt(pointCount.toString());
- this.controlPoints = Arrays.copyOf(this.controlPoints, newPointCount);
- if (oldPointCount < newPointCount) {
- this.controlPoints[newPointCount - 1] = this.controlPoints[oldPointCount - 1];
- for (int i = oldPointCount - 1; i < newPointCount - 1; i++) {
- this.controlPoints[i] =
- new Point2D.Double((this.controlPoints[i - 1].getX() + this.controlPoints[newPointCount - 1].getX()) / 2,
- (this.controlPoints[i - 1].getY() + this.controlPoints[newPointCount - 1].getY()) / 2);
- }
- }
- this.pointCount = pointCount;
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int factor = 32 / width;
- g2d.setColor(COLOR);
- int[] x = {2 / factor, width - 2 / factor, width - 4 / factor, 3 / factor};
- int[] y = {4 / factor, 2 / factor, height - 5 / factor, height - 2 / factor};
- g2d.fillPolygon(x, y, 4);
- g2d.setColor(BORDER_COLOR);
- g2d.drawPolygon(x, y, 4);
- }
-
- public enum PointCount {
- _3, _4, _5, _6, _7, _8;
-
- public String toString() {
- return name().substring(1);
- };
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.shapes;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Graphics2D;
+import java.awt.geom.Point2D;
+import java.util.Arrays;
+
+import org.diylc.common.ObjectCache;
+import org.diylc.components.transform.SimpleComponentTransformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.annotations.BomPolicy;
+import org.diylc.core.annotations.ComponentDescriptor;
+import org.diylc.core.annotations.EditableProperty;
+
+@ComponentDescriptor(name = "Polygon", author = "Branislav Stojkovic", category = "Shapes",
+ instanceNamePrefix = "POLY", description = "Polygonal area", zOrder = IDIYComponent.COMPONENT,
+ flexibleZOrder = true, bomPolicy = BomPolicy.NEVER_SHOW,
+ transformer = SimpleComponentTransformer.class)
+public class Polygon extends AbstractShape {
+
+ private static final long serialVersionUID = 1L;
+
+ protected PointCount pointCount = PointCount._4;
+
+ public Polygon() {
+ super();
+ this.controlPoints =
+ new Point2D[] {new Point2D.Double(0, 0),
+ new Point2D.Double(0, (int) DEFAULT_HEIGHT.convertToPixels()),
+ new Point2D.Double((int) DEFAULT_WIDTH.convertToPixels(), (int) DEFAULT_HEIGHT.convertToPixels()),
+ new Point2D.Double((int) DEFAULT_WIDTH.convertToPixels(), 0)};
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke((int) borderThickness.convertToPixels()));
+ g2d.setColor(color);
+ int[] xPoints = new int[controlPoints.length];
+ int[] yPoints = new int[controlPoints.length];
+ for (int i = 0; i < controlPoints.length; i++) {
+ xPoints[i] = (int)controlPoints[i].getX();
+ yPoints[i] = (int)controlPoints[i].getY();
+ }
+
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.fillPolygon(xPoints, yPoints, controlPoints.length);
+ g2d.setComposite(oldComposite);
+
+ // Do not track any changes that follow because the whole board has been
+ // tracked so far.
+ drawingObserver.stopTracking();
+ Color lineColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : borderColor;
+ g2d.setColor(lineColor);
+ g2d.drawPolygon(xPoints, yPoints, controlPoints.length);
+ }
+
+ @EditableProperty(name = "Edges")
+ public PointCount getPointCount() {
+ return pointCount;
+ }
+
+ public void setPointCount(PointCount pointCount) {
+ if (this.pointCount == pointCount)
+ return;
+ int oldPointCount = Integer.parseInt(this.pointCount.toString());
+ int newPointCount = Integer.parseInt(pointCount.toString());
+ this.controlPoints = Arrays.copyOf(this.controlPoints, newPointCount);
+ if (oldPointCount < newPointCount) {
+ this.controlPoints[newPointCount - 1] = this.controlPoints[oldPointCount - 1];
+ for (int i = oldPointCount - 1; i < newPointCount - 1; i++) {
+ this.controlPoints[i] =
+ new Point2D.Double((this.controlPoints[i - 1].getX() + this.controlPoints[newPointCount - 1].getX()) / 2,
+ (this.controlPoints[i - 1].getY() + this.controlPoints[newPointCount - 1].getY()) / 2);
+ }
+ }
+ this.pointCount = pointCount;
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int factor = 32 / width;
+ g2d.setColor(COLOR);
+ int[] x = {2 / factor, width - 2 / factor, width - 4 / factor, 3 / factor};
+ int[] y = {4 / factor, 2 / factor, height - 5 / factor, height - 2 / factor};
+ g2d.fillPolygon(x, y, 4);
+ g2d.setColor(BORDER_COLOR);
+ g2d.drawPolygon(x, y, 4);
+ }
+
+ public enum PointCount {
+ _3, _4, _5, _6, _7, _8;
+
+ public String toString() {
+ return name().substring(1);
+ };
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/shapes/Rectangle.java b/diylc/diylc-library/src/main/java/org/diylc/components/shapes/Rectangle.java
index 1a5cc7e38..ace2cff16 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/shapes/Rectangle.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/shapes/Rectangle.java
@@ -1,95 +1,88 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.shapes;
-
-import java.awt.AlphaComposite;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-
-import org.diylc.common.ObjectCache;
-import org.diylc.components.transform.SimpleComponentTransformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-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;
-
-@ComponentDescriptor(name = "Rectangle", author = "Branislav Stojkovic", category = "Shapes",
- instanceNamePrefix = "RECT", description = "Rectangular area, with or without rounded edges",
- zOrder = IDIYComponent.COMPONENT, flexibleZOrder = true, bomPolicy = BomPolicy.NEVER_SHOW,
- transformer = SimpleComponentTransformer.class)
-public class Rectangle extends AbstractShapeWithDimensions {
-
- private static final long serialVersionUID = 1L;
-
- protected Size edgeRadius = new Size(0d, SizeUnit.mm);
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke((int) borderThickness.convertToPixels()));
- int radius = (int) edgeRadius.convertToPixels();
-
- float alpha = this.alpha;
- if (componentState == ComponentState.DRAGGING)
- alpha = 0;
-
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(color);
- g2d.fillRoundRect((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(secondPoint.getX() - firstPoint.getX()), (int)(secondPoint.getY() - firstPoint.getY()), radius,
- radius);
- g2d.setComposite(oldComposite);
-
- // Do not track any changes that follow because the whole rect has been
- // tracked so far.
- 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,
- radius);
- }
-
- @EditableProperty(name = "Radius")
- public Size getEdgeRadius() {
- return edgeRadius;
- }
-
- public void setEdgeRadius(Size edgeRadius) {
- this.edgeRadius = edgeRadius;
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int factor = 32 / width;
- g2d.setColor(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);
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.shapes;
+
+import java.awt.AlphaComposite;
+import java.awt.Composite;
+import java.awt.Graphics2D;
+
+import org.diylc.common.ObjectCache;
+import org.diylc.components.transform.SimpleComponentTransformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+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;
+
+@ComponentDescriptor(name = "Rectangle", author = "Branislav Stojkovic", category = "Shapes",
+ instanceNamePrefix = "RECT", description = "Rectangular area, with or without rounded edges",
+ zOrder = IDIYComponent.COMPONENT, flexibleZOrder = true, bomPolicy = BomPolicy.NEVER_SHOW,
+ transformer = SimpleComponentTransformer.class)
+public class Rectangle extends AbstractShapeWithDimensions {
+
+ private static final long serialVersionUID = 1L;
+
+ protected Size edgeRadius = new Size(0d, SizeUnit.mm);
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke((int) borderThickness.convertToPixels()));
+ int radius = (int) edgeRadius.convertToPixels();
+
+ 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,
+ radius);
+ g2d.setComposite(oldComposite);
+
+ // Do not track any changes that follow because the whole rect has been
+ // tracked so far.
+ 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,
+ radius);
+ }
+
+ @EditableProperty(name = "Radius")
+ public Size getEdgeRadius() {
+ return edgeRadius;
+ }
+
+ public void setEdgeRadius(Size edgeRadius) {
+ this.edgeRadius = edgeRadius;
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int factor = 32 / width;
+ g2d.setColor(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);
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/shapes/TapeMeasure.java b/diylc/diylc-library/src/main/java/org/diylc/components/shapes/TapeMeasure.java
index 2a85cc230..67b93b5c7 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/shapes/TapeMeasure.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/shapes/TapeMeasure.java
@@ -38,6 +38,7 @@ import java.text.DecimalFormat;
import org.diylc.common.Display;
import org.diylc.common.LineStyle;
import org.diylc.common.ObjectCache;
+import org.diylc.common.Percentage;
import org.diylc.components.AbstractLeadedComponent;
import org.diylc.components.transform.SimpleComponentTransformer;
import org.diylc.core.ComponentState;
@@ -276,7 +277,7 @@ public class TapeMeasure extends AbstractLeadedComponent {
}
@Override
- public Byte getAlpha() {
+ public Percentage getAlpha() {
return super.getAlpha();
}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/smd/PassiveSMDComponent.java b/diylc/diylc-library/src/main/java/org/diylc/components/smd/PassiveSMDComponent.java
index 229700280..86d4bd542 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/smd/PassiveSMDComponent.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/smd/PassiveSMDComponent.java
@@ -1,452 +1,447 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.smd;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.FontMetrics;
-import java.awt.Graphics2D;
-import java.awt.Rectangle;
-import java.awt.geom.Area;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.geom.RoundRectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.common.Display;
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.Orientation;
-import org.diylc.components.AbstractLabeledComponent;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-import org.diylc.core.VisibilityPolicy;
-import org.diylc.core.annotations.EditableProperty;
-import org.diylc.core.gerber.IGerberComponentSimple;
-import org.diylc.core.measures.Size;
-import org.diylc.core.measures.SizeUnit;
-import org.diylc.utils.Constants;
-
-public abstract class PassiveSMDComponent extends AbstractLabeledComponent implements IGerberComponentSimple {
-
- private static final long serialVersionUID = 1L;
-
- public static Color PIN_COLOR = METAL_COLOR;
- public static Color PIN_BORDER_COLOR = PIN_COLOR.darker();
- public static Color LABEL_COLOR = Color.white;
- public static int EDGE_RADIUS = 4;
- public static Size PIN_SIZE = new Size(0.8d, SizeUnit.mm);
-
- protected T value;
- private Orientation orientation = Orientation.DEFAULT;
-
- private SMDSize size = SMDSize._1206;
- private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0), new Point2D.Double(0, 0)};
- protected Display display = Display.NAME;
- protected Color bodyColor;
- protected Color borderColor;
- private Color labelColor = LABEL_COLOR;
- transient private Area[] body;
-
- public PassiveSMDComponent() {
- super();
- updateControlPoints();
- }
-
- @EditableProperty
- public Orientation getOrientation() {
- return orientation;
- }
-
- public void setOrientation(Orientation orientation) {
- this.orientation = orientation;
- updateControlPoints();
- // Reset body shape.
- body = null;
- }
-
- @EditableProperty
- public Display getDisplay() {
- if (display == null) {
- display = Display.VALUE;
- }
- return display;
- }
-
- public void setDisplay(Display display) {
- this.display = display;
- }
-
- @EditableProperty
- public SMDSize getSize() {
- return size;
- }
-
- public void setSize(SMDSize size) {
- this.size = size;
- updateControlPoints();
- // Reset body shape.
- body = null;
- }
-
- @Override
- public int getControlPointCount() {
- return controlPoints.length;
- }
-
- @Override
- public Point2D getControlPoint(int index) {
- return controlPoints[index];
- }
-
- @Override
- public boolean isControlPointSticky(int index) {
- return true;
- }
-
- @Override
- public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
- return VisibilityPolicy.NEVER;
- }
-
- @Override
- public void setControlPoint(Point2D point, int index) {
- controlPoints[index].setLocation(point);
- body = null;
- }
-
- private void updateControlPoints() {
- Point2D firstPoint = controlPoints[0];
- controlPoints[0] = firstPoint;
- double pinSize = PIN_SIZE.convertToPixels();
- double smdLength = getSize().getLength().convertToPixels();
- double pinSpacing = smdLength - pinSize;
-
- // Update control points.
- double dx1;
- double dy1;
- switch (orientation) {
- case DEFAULT:
- dx1 = 0;
- dy1 = pinSpacing;
- break;
- case _90:
- dx1 = -pinSpacing;
- dy1 = 0;
- break;
- case _180:
- dx1 = 0;
- dy1 = -pinSpacing;
- break;
- case _270:
- dx1 = pinSpacing;
- dy1 = 0;
- break;
- default:
- throw new RuntimeException("Unexpected orientation: " + orientation);
- }
- controlPoints[1] = new Point2D.Double(firstPoint.getX() + dx1, firstPoint.getY() + dy1);
- }
-
- public Area[] getBody() {
- if (body == null) {
- body = new Area[2];
- double x = controlPoints[0].getX();
- double y = controlPoints[0].getY();
- double smdWidth = getSize().getWidth().convertToPixels();
- double smdLength = getSize().getLength().convertToPixels();
- double pinSize = PIN_SIZE.convertToPixels();
- double width;
- double height;
-
- // create main body
- switch (orientation) {
- case DEFAULT:
- width = smdWidth;
- height = smdLength;
- x = controlPoints[0].getX() - smdWidth / 2;
- y = controlPoints[0].getY() - pinSize / 2;
- break;
- case _90:
- width = smdLength;
- height = smdWidth;
- x = controlPoints[1].getX() - pinSize / 2;
- y = controlPoints[1].getY() - smdWidth / 2;
- break;
- case _180:
- width = smdWidth;
- height = smdLength;
- x = controlPoints[1].getX() - smdWidth / 2;
- y = controlPoints[1].getY() - pinSize / 2;
- break;
- case _270:
- width = smdLength;
- height = smdWidth;
- x = controlPoints[0].getX() - pinSize / 2;
- y = controlPoints[0].getY() - smdWidth / 2;
- break;
- default:
- throw new RuntimeException("Unexpected orientation: " + orientation);
- }
- Area mainArea = new Area(new RoundRectangle2D.Double(x, y, width, height, EDGE_RADIUS, EDGE_RADIUS));
-
- // create contact area
- Area contactArea = new Area();
- if (width > height) {
- contactArea.add(new Area(new Rectangle2D.Double(x, y, pinSize, height)));
- contactArea.add(new Area(new Rectangle2D.Double(x + width - pinSize, y, pinSize, height)));
- } else {
- contactArea.add(new Area(new Rectangle2D.Double(x, y, width, pinSize)));
- contactArea.add(new Area(new Rectangle2D.Double(x, y + height - pinSize, width, pinSize)));
- }
- contactArea.intersect(mainArea);
-
- mainArea.subtract(contactArea);
- body[0] = mainArea;
- body[1] = contactArea;
-
- }
- return body;
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- if (checkPointsClipped(g2d.getClip())) {
- return;
- }
-
- // draw main area
- Area mainArea = getBody()[0];
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getBodyColor());
- g2d.fill(mainArea);
- g2d.setComposite(oldComposite);
-
- Color finalBorderColor;
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : getBorderColor();
- }
- g2d.setColor(finalBorderColor);
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
- g2d.draw(mainArea);
-
-
- // draw contact area
- Area contactArea = getBody()[1];
- if (!outlineMode) {
- g2d.setColor(PIN_COLOR);
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- g2d.fill(contactArea);
- g2d.setComposite(oldComposite);
- }
-
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : PIN_BORDER_COLOR;
- }
- g2d.setColor(finalBorderColor);
- g2d.draw(contactArea);
-
- // Draw label.
- g2d.setFont(project.getFont());
-
- // Override font size
- if (getFontSizeOverride() != null)
- g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride()));
-
- Color finalLabelColor;
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : theme.getOutlineColor();
- } else {
- finalLabelColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
- : getLabelColor();
- }
- g2d.setColor(finalLabelColor);
- FontMetrics fontMetrics = g2d.getFontMetrics(g2d.getFont());
- String label = "";
- label = (getDisplay() == Display.NAME) ? getName() : getValue().toString();
- if (getDisplay() == Display.NONE) {
- label = "";
- }
- if (getDisplay() == Display.BOTH) {
- label = getName() + " " + (getValue() == null ? "" : getValue().toString());
- }
-
- Rectangle textTarget = mainArea.getBounds();
- int length = textTarget.height > textTarget.width ? textTarget.height : textTarget.width;
-
- Rectangle2D rect = fontMetrics.getStringBounds(label, g2d);
- int textHeight = (int) (rect.getHeight());
- int textWidth = (int) (rect.getWidth());
-
- do {
- g2d.setFont(g2d.getFont().deriveFont(g2d.getFont().getSize2D() - 1));
- fontMetrics = g2d.getFontMetrics(g2d.getFont());
- rect = fontMetrics.getStringBounds(label, g2d);
- textHeight = (int) (rect.getHeight());
- textWidth = (int) (rect.getWidth());
- } while (textWidth > length && g2d.getFont().getSize2D() > 2);
-
- double centerX = textTarget.getX() + textTarget.getWidth() / 2;
- double centerY = textTarget.getY() + textTarget.getHeight() / 2;
- g2d.translate(centerX, centerY);
-
- switch (orientation) {
- case DEFAULT:
- g2d.rotate(Math.PI / 2);
- break;
- case _90:
- g2d.rotate(Math.PI);
- break;
- case _180:
- g2d.rotate(Math.PI * 3 / 2);
- break;
- case _270:
- break;
- default:
- throw new RuntimeException("Unexpected orientation: " + orientation);
- }
-
- // Center text horizontally and vertically
- int x = -textWidth / 2;
- int y = -textHeight / 2 + fontMetrics.getAscent() - 1;
- g2d.drawString(label, x, y);
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- int radius = 4 * width / 32;
- int contactSize = 4 * width / 32;
- int thickness = getClosestOdd(width / 2);
- g2d.rotate(Math.PI / 4, width / 2, height / 2);
- RoundRectangle2D rect =
- new RoundRectangle2D.Double((width - thickness) / 2, 4 * width / 32, thickness, height - 8 * width / 32,
- radius, radius);
- g2d.setColor(getBodyColor());
- g2d.fill(rect);
- g2d.setColor(getBorderColor());
- g2d.draw(rect);
- Area contactArea = new Area();
- contactArea.add(new Area(new Rectangle2D.Double((width - thickness) / 2, 4 * width / 32, thickness, contactSize)));
- contactArea.add(new Area(new Rectangle2D.Double((width - thickness) / 2, height - 8 * width / 32, thickness,
- contactSize)));
- contactArea.intersect(new Area(rect));
- g2d.setColor(PIN_COLOR);
- g2d.fill(contactArea);
- }
-
- @EditableProperty(name = "Body")
- public Color getBodyColor() {
- return bodyColor;
- }
-
- public void setBodyColor(Color bodyColor) {
- this.bodyColor = bodyColor;
- }
-
- @EditableProperty(name = "Border")
- public Color getBorderColor() {
- return borderColor;
- }
-
- public void setBorderColor(Color borderColor) {
- this.borderColor = borderColor;
- }
-
- @EditableProperty(name = "Label")
- public Color getLabelColor() {
- if (labelColor == null) {
- labelColor = LABEL_COLOR;
- }
- return labelColor;
- }
-
- public void setLabelColor(Color labelColor) {
- this.labelColor = labelColor;
- }
-
- @Override
- public boolean canPointMoveFreely(int pointIndex) {
- return false;
- }
-
- public static enum SMDSize {
-
- _0805(new Size(0.05d, SizeUnit.in), new Size(0.08d, SizeUnit.in)), _1206(new Size(1.6d, SizeUnit.mm), new Size(3.2d,
- SizeUnit.mm)), _1210(new Size(2.5d, SizeUnit.mm), new Size(3.2d, SizeUnit.mm)), _1806(new Size(1.6d,
- SizeUnit.mm), new Size(4.5d, SizeUnit.mm)), _1812(new Size(3.2d, SizeUnit.mm), new Size(4.5d, SizeUnit.mm));
-
- private Size width;
- private Size length;
-
- private SMDSize(Size width, Size length) {
- this.width = width;
- this.length = length;
- }
-
- public Size getWidth() {
- return width;
- }
-
- public Size getLength() {
- return length;
- }
-
- @Override
- public String toString() {
- return name().replace("_", "");
- }
-
- public int getValue() {
- return Integer.parseInt(toString());
- }
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.smd;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.geom.Area;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.common.Display;
+import org.diylc.common.IPlugInPort;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.Orientation;
+import org.diylc.components.AbstractLabeledComponent;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+import org.diylc.core.VisibilityPolicy;
+import org.diylc.core.annotations.EditableProperty;
+import org.diylc.core.gerber.IGerberComponentSimple;
+import org.diylc.core.measures.Size;
+import org.diylc.core.measures.SizeUnit;
+import org.diylc.utils.Constants;
+
+public abstract class PassiveSMDComponent extends AbstractLabeledComponent implements IGerberComponentSimple {
+
+ private static final long serialVersionUID = 1L;
+
+ public static Color PIN_COLOR = METAL_COLOR;
+ public static Color PIN_BORDER_COLOR = PIN_COLOR.darker();
+ public static Color LABEL_COLOR = Color.white;
+ public static int EDGE_RADIUS = 4;
+ public static Size PIN_SIZE = new Size(0.8d, SizeUnit.mm);
+
+ protected T value;
+ private Orientation orientation = Orientation.DEFAULT;
+
+ private SMDSize size = SMDSize._1206;
+ private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0), new Point2D.Double(0, 0)};
+ protected Display display = Display.NAME;
+ protected Color bodyColor;
+ protected Color borderColor;
+ private Color labelColor = LABEL_COLOR;
+ transient private Area[] body;
+
+ public PassiveSMDComponent() {
+ super();
+ updateControlPoints();
+ }
+
+ @EditableProperty
+ public Orientation getOrientation() {
+ return orientation;
+ }
+
+ public void setOrientation(Orientation orientation) {
+ this.orientation = orientation;
+ updateControlPoints();
+ // Reset body shape.
+ body = null;
+ }
+
+ @EditableProperty
+ public Display getDisplay() {
+ if (display == null) {
+ display = Display.VALUE;
+ }
+ return display;
+ }
+
+ public void setDisplay(Display display) {
+ this.display = display;
+ }
+
+ @EditableProperty
+ public SMDSize getSize() {
+ return size;
+ }
+
+ public void setSize(SMDSize size) {
+ this.size = size;
+ updateControlPoints();
+ // Reset body shape.
+ body = null;
+ }
+
+ @Override
+ public int getControlPointCount() {
+ return controlPoints.length;
+ }
+
+ @Override
+ public Point2D getControlPoint(int index) {
+ return controlPoints[index];
+ }
+
+ @Override
+ public boolean isControlPointSticky(int index) {
+ return true;
+ }
+
+ @Override
+ public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
+ return VisibilityPolicy.NEVER;
+ }
+
+ @Override
+ public void setControlPoint(Point2D point, int index) {
+ controlPoints[index].setLocation(point);
+ body = null;
+ }
+
+ private void updateControlPoints() {
+ Point2D firstPoint = controlPoints[0];
+ controlPoints[0] = firstPoint;
+ double pinSize = PIN_SIZE.convertToPixels();
+ double smdLength = getSize().getLength().convertToPixels();
+ double pinSpacing = smdLength - pinSize;
+
+ // Update control points.
+ double dx1;
+ double dy1;
+ switch (orientation) {
+ case DEFAULT:
+ dx1 = 0;
+ dy1 = pinSpacing;
+ break;
+ case _90:
+ dx1 = -pinSpacing;
+ dy1 = 0;
+ break;
+ case _180:
+ dx1 = 0;
+ dy1 = -pinSpacing;
+ break;
+ case _270:
+ dx1 = pinSpacing;
+ dy1 = 0;
+ break;
+ default:
+ throw new RuntimeException("Unexpected orientation: " + orientation);
+ }
+ controlPoints[1] = new Point2D.Double(firstPoint.getX() + dx1, firstPoint.getY() + dy1);
+ }
+
+ public Area[] getBody() {
+ if (body == null) {
+ body = new Area[2];
+ double x = controlPoints[0].getX();
+ double y = controlPoints[0].getY();
+ double smdWidth = getSize().getWidth().convertToPixels();
+ double smdLength = getSize().getLength().convertToPixels();
+ double pinSize = PIN_SIZE.convertToPixels();
+ double width;
+ double height;
+
+ // create main body
+ switch (orientation) {
+ case DEFAULT:
+ width = smdWidth;
+ height = smdLength;
+ x = controlPoints[0].getX() - smdWidth / 2;
+ y = controlPoints[0].getY() - pinSize / 2;
+ break;
+ case _90:
+ width = smdLength;
+ height = smdWidth;
+ x = controlPoints[1].getX() - pinSize / 2;
+ y = controlPoints[1].getY() - smdWidth / 2;
+ break;
+ case _180:
+ width = smdWidth;
+ height = smdLength;
+ x = controlPoints[1].getX() - smdWidth / 2;
+ y = controlPoints[1].getY() - pinSize / 2;
+ break;
+ case _270:
+ width = smdLength;
+ height = smdWidth;
+ x = controlPoints[0].getX() - pinSize / 2;
+ y = controlPoints[0].getY() - smdWidth / 2;
+ break;
+ default:
+ throw new RuntimeException("Unexpected orientation: " + orientation);
+ }
+ Area mainArea = new Area(new RoundRectangle2D.Double(x, y, width, height, EDGE_RADIUS, EDGE_RADIUS));
+
+ // create contact area
+ Area contactArea = new Area();
+ if (width > height) {
+ contactArea.add(new Area(new Rectangle2D.Double(x, y, pinSize, height)));
+ contactArea.add(new Area(new Rectangle2D.Double(x + width - pinSize, y, pinSize, height)));
+ } else {
+ contactArea.add(new Area(new Rectangle2D.Double(x, y, width, pinSize)));
+ contactArea.add(new Area(new Rectangle2D.Double(x, y + height - pinSize, width, pinSize)));
+ }
+ contactArea.intersect(mainArea);
+
+ mainArea.subtract(contactArea);
+ body[0] = mainArea;
+ body[1] = contactArea;
+
+ }
+ return body;
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+ if (checkPointsClipped(g2d.getClip())) {
+ return;
+ }
+
+ // draw main area
+ Area mainArea = getBody()[0];
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getBodyColor());
+ g2d.fill(mainArea);
+ g2d.setComposite(oldComposite);
+
+ Color finalBorderColor;
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : getBorderColor();
+ }
+ g2d.setColor(finalBorderColor);
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+ g2d.draw(mainArea);
+
+
+ // draw contact area
+ Area contactArea = getBody()[1];
+ if (!outlineMode) {
+ g2d.setColor(PIN_COLOR);
+ applyAlpha(g2d, componentState);
+ g2d.fill(contactArea);
+ g2d.setComposite(oldComposite);
+ }
+
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : PIN_BORDER_COLOR;
+ }
+ g2d.setColor(finalBorderColor);
+ g2d.draw(contactArea);
+
+ // Draw label.
+ g2d.setFont(project.getFont());
+
+ // Override font size
+ if (getFontSizeOverride() != null)
+ g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride()));
+
+ Color finalLabelColor;
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : theme.getOutlineColor();
+ } else {
+ finalLabelColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
+ : getLabelColor();
+ }
+ g2d.setColor(finalLabelColor);
+ FontMetrics fontMetrics = g2d.getFontMetrics(g2d.getFont());
+ String label = "";
+ label = (getDisplay() == Display.NAME) ? getName() : getValue().toString();
+ if (getDisplay() == Display.NONE) {
+ label = "";
+ }
+ if (getDisplay() == Display.BOTH) {
+ label = getName() + " " + (getValue() == null ? "" : getValue().toString());
+ }
+
+ Rectangle textTarget = mainArea.getBounds();
+ int length = textTarget.height > textTarget.width ? textTarget.height : textTarget.width;
+
+ Rectangle2D rect = fontMetrics.getStringBounds(label, g2d);
+ int textHeight = (int) (rect.getHeight());
+ int textWidth = (int) (rect.getWidth());
+
+ do {
+ g2d.setFont(g2d.getFont().deriveFont(g2d.getFont().getSize2D() - 1));
+ fontMetrics = g2d.getFontMetrics(g2d.getFont());
+ rect = fontMetrics.getStringBounds(label, g2d);
+ textHeight = (int) (rect.getHeight());
+ textWidth = (int) (rect.getWidth());
+ } while (textWidth > length && g2d.getFont().getSize2D() > 2);
+
+ double centerX = textTarget.getX() + textTarget.getWidth() / 2;
+ double centerY = textTarget.getY() + textTarget.getHeight() / 2;
+ g2d.translate(centerX, centerY);
+
+ switch (orientation) {
+ case DEFAULT:
+ g2d.rotate(Math.PI / 2);
+ break;
+ case _90:
+ g2d.rotate(Math.PI);
+ break;
+ case _180:
+ g2d.rotate(Math.PI * 3 / 2);
+ break;
+ case _270:
+ break;
+ default:
+ throw new RuntimeException("Unexpected orientation: " + orientation);
+ }
+
+ // Center text horizontally and vertically
+ int x = -textWidth / 2;
+ int y = -textHeight / 2 + fontMetrics.getAscent() - 1;
+ g2d.drawString(label, x, y);
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ int radius = 4 * width / 32;
+ int contactSize = 4 * width / 32;
+ int thickness = getClosestOdd(width / 2);
+ g2d.rotate(Math.PI / 4, width / 2, height / 2);
+ RoundRectangle2D rect =
+ new RoundRectangle2D.Double((width - thickness) / 2, 4 * width / 32, thickness, height - 8 * width / 32,
+ radius, radius);
+ g2d.setColor(getBodyColor());
+ g2d.fill(rect);
+ g2d.setColor(getBorderColor());
+ g2d.draw(rect);
+ Area contactArea = new Area();
+ contactArea.add(new Area(new Rectangle2D.Double((width - thickness) / 2, 4 * width / 32, thickness, contactSize)));
+ contactArea.add(new Area(new Rectangle2D.Double((width - thickness) / 2, height - 8 * width / 32, thickness,
+ contactSize)));
+ contactArea.intersect(new Area(rect));
+ g2d.setColor(PIN_COLOR);
+ g2d.fill(contactArea);
+ }
+
+ @EditableProperty(name = "Body")
+ public Color getBodyColor() {
+ return bodyColor;
+ }
+
+ public void setBodyColor(Color bodyColor) {
+ this.bodyColor = bodyColor;
+ }
+
+ @EditableProperty(name = "Border")
+ public Color getBorderColor() {
+ return borderColor;
+ }
+
+ public void setBorderColor(Color borderColor) {
+ this.borderColor = borderColor;
+ }
+
+ @EditableProperty(name = "Label")
+ public Color getLabelColor() {
+ if (labelColor == null) {
+ labelColor = LABEL_COLOR;
+ }
+ return labelColor;
+ }
+
+ public void setLabelColor(Color labelColor) {
+ this.labelColor = labelColor;
+ }
+
+ @Override
+ public boolean canPointMoveFreely(int pointIndex) {
+ return false;
+ }
+
+ public static enum SMDSize {
+
+ _0805(new Size(0.05d, SizeUnit.in), new Size(0.08d, SizeUnit.in)), _1206(new Size(1.6d, SizeUnit.mm), new Size(3.2d,
+ SizeUnit.mm)), _1210(new Size(2.5d, SizeUnit.mm), new Size(3.2d, SizeUnit.mm)), _1806(new Size(1.6d,
+ SizeUnit.mm), new Size(4.5d, SizeUnit.mm)), _1812(new Size(3.2d, SizeUnit.mm), new Size(4.5d, SizeUnit.mm));
+
+ private Size width;
+ private Size length;
+
+ private SMDSize(Size width, Size length) {
+ this.width = width;
+ this.length = length;
+ }
+
+ public Size getWidth() {
+ return width;
+ }
+
+ public Size getLength() {
+ return length;
+ }
+
+ @Override
+ public String toString() {
+ return name().replace("_", "");
+ }
+
+ public int getValue() {
+ return Integer.parseInt(toString());
+ }
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/smd/SOT23Package.java b/diylc/diylc-library/src/main/java/org/diylc/components/smd/SOT23Package.java
index a114e51b4..55f1990d2 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/smd/SOT23Package.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/smd/SOT23Package.java
@@ -266,8 +266,8 @@ package org.diylc.components.smd;
// // draw main area
// Area mainArea = getBody()[0];
// Composite oldComposite = g2d.getComposite();
-// if (alpha < MAX_ALPHA) {
-// g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
+// if (getAlpha().getValue() < MAX_ALPHA) {
+// g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, getAlpha().getValue() / 100f));
// }
// g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getBodyColor());
// g2d.fill(mainArea);
@@ -294,8 +294,8 @@ package org.diylc.components.smd;
// Area contactArea = getBody()[1];
// if (!outlineMode) {
// g2d.setColor(PIN_COLOR);
-// if (alpha < MAX_ALPHA) {
-// g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
+// if (getAlpha().getValue() < MAX_ALPHA) {
+// g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, getAlpha().getValue() / 100f));
// }
// g2d.fill(contactArea);
// g2d.setComposite(oldComposite);
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/tube/Jumbo4PinTubeSocket.java b/diylc/diylc-library/src/main/java/org/diylc/components/tube/Jumbo4PinTubeSocket.java
index 880b1054f..0cceeba0f 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/tube/Jumbo4PinTubeSocket.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/tube/Jumbo4PinTubeSocket.java
@@ -206,10 +206,7 @@ public class Jumbo4PinTubeSocket extends AbstractAngledComponent {
Shape baseShape = body[0];
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
if (componentState != ComponentState.DRAGGING) {
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getColor());
g2d.fill(baseShape);
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/tube/SubminiTube.java b/diylc/diylc-library/src/main/java/org/diylc/components/tube/SubminiTube.java
index 4c6f77acb..82659260b 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/tube/SubminiTube.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/tube/SubminiTube.java
@@ -306,10 +306,7 @@ public class SubminiTube extends AbstractLabeledComponent {
}
int pinSize = (int) LEAD_THICKNESS.convertToPixels() / 2 * 2;
Shape mainArea = getBody()[0];
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
+ Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor);
g2d.fill(mainArea);
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/tube/TubeSocket.java b/diylc/diylc-library/src/main/java/org/diylc/components/tube/TubeSocket.java
index e3e00da45..c8edb4b13 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/tube/TubeSocket.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/tube/TubeSocket.java
@@ -1,462 +1,459 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.components.tube;
-
-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.Area;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import org.diylc.appframework.miscutils.ConfigurationManager;
-
-import org.diylc.awt.StringUtils;
-import org.diylc.common.HorizontalAlignment;
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.common.VerticalAlignment;
-import org.diylc.components.AbstractAngledComponent;
-import org.diylc.components.transform.AngledComponentTransformer;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.IDrawingObserver;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-import org.diylc.core.VisibilityPolicy;
-import org.diylc.core.annotations.ComponentDescriptor;
-import org.diylc.core.annotations.EditableProperty;
-import org.diylc.core.annotations.KeywordPolicy;
-import org.diylc.core.gerber.IGerberComponentSimple;
-import org.diylc.core.measures.Size;
-import org.diylc.core.measures.SizeUnit;
-import org.diylc.utils.Constants;
-
-@ComponentDescriptor(name = "Tube Socket", author = "Branislav Stojkovic", category = "Tubes",
- instanceNamePrefix = "V", description = "Various types of tube/valve sockets",
- zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_VALUE, enableCache = true,
- transformer = AngledComponentTransformer.class)
-public class TubeSocket extends AbstractAngledComponent implements IGerberComponentSimple {
-
- private static final Size B9A_PIN_SPACING_CHASSIS = new Size(12.5d, SizeUnit.mm);
- private static final Size B9A_PIN_SPACING_PCB = new Size(21d, SizeUnit.mm);
- private static final Size OCTAL_PIN_SPACING = new Size(17.5d, SizeUnit.mm);
- private static final Size B7G_PIN_SPACING = new Size(12d, SizeUnit.mm);
- private static final Size B7G_CUTOUT_DIAMETER = new Size(4d, SizeUnit.mm);
- private static final Size B9A_CUTOUT_DIAMETER = new Size(5.5d, SizeUnit.mm);
- private static final Size B12C_HOLE_SIZE = new Size(10d, SizeUnit.mm);
- private static final Size B12C_CUTOUT_DIAMETER = new Size(5.5d, SizeUnit.mm);
- private static final Size B12C_PIN_SPACING_PCB = new Size(25d, SizeUnit.mm);
- private static final Size B12C_PIN_SPACING_CHASSIS = new Size(22d, SizeUnit.mm);
-
- private static final Size OCTAL_DIAMETER = new Size(25d, SizeUnit.mm);
- private static final Size B9A_DIAMETER = new Size(3 / 4d, SizeUnit.in);
- private static final Size B7G_DIAMETER = new Size(17d, SizeUnit.mm);
- private static final Size B12C_DIAMETER = new Size(30d, SizeUnit.mm);
-
- private static final long serialVersionUID = 1L;
-
- private static Color BODY_COLOR = Color.decode("#F7F7EF");
- private static Color LABEL_COLOR = BODY_COLOR.darker();
- public static Color PIN_COLOR = METAL_COLOR;
- public static Color PIN_BORDER_COLOR = PIN_COLOR.darker();
- public static Size PIN_DIAMETER = new Size(1d, SizeUnit.mm);
- private static Size PIN_WIDTH = new Size(0.08d, SizeUnit.in);
- private static Size PIN_THICKNESS = new Size(0.02d, SizeUnit.in);
- public static Size HOLE_SIZE = new Size(5d, SizeUnit.mm);
- public static Size OCTAL_TICK_SIZE = new Size(2d, SizeUnit.mm);
-
- private Base base = Base.B9A;
- private String type = "";
- private Color color = BODY_COLOR;
- private String electrodeLabels = null;
- private Mount mount = Mount.CHASSIS;
- private Color labelColor = LABEL_COLOR;
-
- private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0)};
-
- public TubeSocket() {
- super();
- updateControlPoints();
- }
-
- @EditableProperty
- public Base getBase() {
- return base;
- }
-
- public void setBase(Base base) {
- this.base = base;
- updateControlPoints();
- // Reset body shape
- body = null;
- }
-
- @EditableProperty
- public Color getColor() {
- if (color == null) {
- color = BODY_COLOR;
- }
- return color;
- }
-
- public void setColor(Color color) {
- this.color = color;
- }
-
- // @EditableProperty
- // public Mount getMount() {
- // return mount;
- // }
- //
- // public void setMount(Mount mount) {
- // this.mount = mount;
- // }
-
- @Override
- protected void updateControlPoints() {
- Point2D firstPoint = controlPoints[0];
- int pinCount;
- int pinSpacing;
- boolean hasEmptySpace;
- switch (base) {
- case B7G:
- pinCount = 7;
- pinSpacing = getClosestOdd(B7G_PIN_SPACING.convertToPixels());
- hasEmptySpace = true;
- break;
- case OCTAL:
- pinCount = 8;
- pinSpacing = getClosestOdd(OCTAL_PIN_SPACING.convertToPixels());
- hasEmptySpace = false;
- break;
- case B9A:
- pinCount = 9;
- pinSpacing = getClosestOdd(getMount() == Mount.PCB ? B9A_PIN_SPACING_PCB.convertToPixels() : B9A_PIN_SPACING_CHASSIS.convertToPixels());
- hasEmptySpace = true;
- break;
- case B12C:
- pinCount = 12;
- pinSpacing = getClosestOdd(getMount() == Mount.PCB ? B12C_PIN_SPACING_PCB.convertToPixels() : B12C_PIN_SPACING_CHASSIS.convertToPixels());
- hasEmptySpace = true;
- break;
- default:
- throw new RuntimeException("Unexpected base: " + base);
- }
- double angleIncrement = Math.PI * 2 / (hasEmptySpace ? (pinCount + 1) : pinCount);
- double initialAngleOffset = hasEmptySpace ? angleIncrement : (angleIncrement / 2);
-
- controlPoints = new Point2D[pinCount + 1];
- double theta = initialAngleOffset + getAngle().getValueRad();
- controlPoints[0] = firstPoint;
- for (int i = 0; i < pinCount; i++) {
- controlPoints[i + 1] =
- new Point2D.Double(firstPoint.getX() + Math.cos(theta) * pinSpacing / 2,
- firstPoint.getY() + Math.sin(theta) * pinSpacing / 2);
- theta += angleIncrement;
- }
- }
-
- public Shape[] getBody() {
- if (body == null) {
- int bodyDiameter;
- switch (base) {
- case B7G:
- bodyDiameter = getClosestOdd(B7G_DIAMETER.convertToPixels());
- break;
- case B9A:
- bodyDiameter = getClosestOdd(B9A_DIAMETER.convertToPixels());
- break;
- case OCTAL:
- bodyDiameter = getClosestOdd(OCTAL_DIAMETER.convertToPixels());
- break;
- case B12C:
- bodyDiameter = getClosestOdd(B12C_DIAMETER.convertToPixels());
- break;
- default:
- throw new RuntimeException("Unexpected base: " + base);
- }
-
- Ellipse2D baseShape =
- new Ellipse2D.Double(controlPoints[0].getX() - bodyDiameter / 2, controlPoints[0].getY() - bodyDiameter / 2,
- bodyDiameter, bodyDiameter);
- Area bodyArea = new Area(baseShape);
- int holeSize = getClosestOdd(base == Base.B12C ? B12C_HOLE_SIZE.convertToPixels() : HOLE_SIZE.convertToPixels());
- bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - holeSize / 2, controlPoints[0].getY() - holeSize
- / 2, holeSize, holeSize)));
-
- if (base == Base.OCTAL) {
- int tickSize = getClosestOdd(OCTAL_TICK_SIZE.convertToPixels());
- double theta = getAngle().getValueRad();
- int centerX = (int) (controlPoints[0].getX() + Math.cos(theta) * holeSize / 2);
- int centerY = (int) (controlPoints[0].getY() + Math.sin(theta) * holeSize / 2);
- bodyArea.subtract(new Area(new Ellipse2D.Double(centerX - tickSize / 2, centerY - tickSize / 2, tickSize,
- tickSize)));
- } else if (base == Base.B9A && getMount() == Mount.CHASSIS) {
- double cutoutDiameter = getClosestOdd(B9A_CUTOUT_DIAMETER.convertToPixels());
- bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - cutoutDiameter / 2, controlPoints[0].getY() - bodyDiameter / 2 - cutoutDiameter * 3 / 4, cutoutDiameter, cutoutDiameter)));
- bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - cutoutDiameter / 2, controlPoints[0].getY() + bodyDiameter / 2 - cutoutDiameter / 4, cutoutDiameter, cutoutDiameter)));
- } else if (base == Base.B7G && getMount() == Mount.CHASSIS) {
- double cutoutDiameter = getClosestOdd(B7G_CUTOUT_DIAMETER.convertToPixels());
- bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - cutoutDiameter / 2, controlPoints[0].getY() - bodyDiameter / 2 - cutoutDiameter * 3 / 4, cutoutDiameter, cutoutDiameter)));
- bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - cutoutDiameter / 2, controlPoints[0].getY() + bodyDiameter / 2 - cutoutDiameter / 4, cutoutDiameter, cutoutDiameter)));
- } else if (base == Base.B12C && getMount() == Mount.CHASSIS) {
- double cutoutDiameter = getClosestOdd(B12C_CUTOUT_DIAMETER.convertToPixels());
- bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - cutoutDiameter / 2, controlPoints[0].getY() - bodyDiameter / 2 - cutoutDiameter * 3 / 4, cutoutDiameter, cutoutDiameter)));
- bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - cutoutDiameter / 2, controlPoints[0].getY() + bodyDiameter / 2 - cutoutDiameter / 4, cutoutDiameter, cutoutDiameter)));
- }
-
- body = new Shape[] { bodyArea };
- }
- return body;
- }
-
- @Override
- public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
-
- g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
-
- // Draw body
- Shape[] body = getBody();
- Composite oldComposite = g2d.getComposite();
- if (alpha < MAX_ALPHA) {
- g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
- }
- if (componentState != ComponentState.DRAGGING) {
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getColor());
- g2d.fill(body[0]);
- }
- g2d.setComposite(oldComposite);
- Color finalBorderColor;
- if (outlineMode) {
- Theme theme =
- (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : theme.getOutlineColor();
- } else {
- finalBorderColor =
- componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : getColor().darker();
- }
- g2d.setColor(finalBorderColor);
- g2d.draw(body[0]);
-
- drawingObserver.stopTracking();
-
- // Draw pins
-
- for (int i = 1; i < controlPoints.length; i++) {
- Shape pinShape;
- if (getMount() == Mount.PCB) {
- int pinSize = getClosestOdd(PIN_DIAMETER.convertToPixels());
- pinShape = new Ellipse2D.Double(controlPoints[i].getX() - pinSize / 2,
- controlPoints[i].getY() - pinSize / 2, pinSize, pinSize);
- } else {
- int pinWidth = getClosestOdd(PIN_WIDTH.convertToPixels());
- int pinThickness = getClosestOdd(PIN_THICKNESS.convertToPixels());
- pinShape = new Rectangle2D.Double(controlPoints[i].getX() - pinWidth / 2,
- controlPoints[i].getY() - pinThickness / 2, pinWidth, pinThickness);
- double theta = Math.atan2(controlPoints[i].getY() - controlPoints[0].getY(),
- controlPoints[i].getX() - controlPoints[0].getX()) + Math.PI / 2;
- Area rotatedPin = new Area(pinShape);
- rotatedPin.transform(AffineTransform.getRotateInstance(theta, controlPoints[i].getX(),
- controlPoints[i].getY()));
- pinShape = rotatedPin;
- }
- g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : PIN_COLOR);
- if (getMount() == Mount.CHASSIS)
- drawingObserver.startTrackingContinuityArea(true);
- g2d.fill(pinShape);
- drawingObserver.stopTrackingContinuityArea();
- if (!outlineMode) {
- g2d.setColor(PIN_BORDER_COLOR);
- g2d.draw(pinShape);
- }
- }
-
- // draw electrode labels
- if (getElectrodeLabels() != null) {
- g2d.setColor(getLabelColor());
- g2d.setFont(project.getFont().deriveFont((float) (project.getFont().getSize2D() * 0.8)));
- String[] labels = getElectrodeLabels().split(",");
- double electrodeLabelOffset = project.getFont().getSize2D() * (getBase() == Base.B9A && getMount() == Mount.PCB ? 1.5 : 1);
- for (int i = 0; i < labels.length; i++) {
- if (i < controlPoints.length - 1) {
- String label = labels[i];
- double theta = Math.atan2(controlPoints[i + 1].getY() - controlPoints[0].getY(), controlPoints[i + 1].getX() - controlPoints[0].getX());
- double x = controlPoints[i + 1].getX() - Math.cos(theta) * electrodeLabelOffset;
- double y = controlPoints[i + 1].getY() - Math.sin(theta) * electrodeLabelOffset;
- StringUtils.drawCenteredText(g2d, label, (int)x, (int)y, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
- }
- }
- }
- }
-
- @Override
- public void drawIcon(Graphics2D g2d, int width, int height) {
- Area area = new Area(new Ellipse2D.Double(1, 1, width - 2, width - 2));
- int center = width / 2;
- area.subtract(new Area(new Ellipse2D.Double(center - 2, center - 2, 5, 5)));
- g2d.setColor(BODY_COLOR);
- g2d.fill(area);
- g2d.setColor(BODY_COLOR.darker());
- g2d.draw(area);
-
- int radius = width / 2 - 6;
- for (int i = 0; i < 8; i++) {
- int x = (int) (center + Math.cos(i * Math.PI / 4) * radius);
- int y = (int) (center + Math.sin(i * Math.PI / 4) * radius);
- g2d.setColor(PIN_COLOR);
- g2d.fillOval(x - 1, y - 1, 3, 3);
- g2d.setColor(PIN_BORDER_COLOR);
- g2d.drawOval(x - 1, y - 1, 3, 3);
- }
- }
-
- @Override
- public Point2D getControlPoint(int index) {
- return controlPoints[index];
- }
-
- @Override
- public int getControlPointCount() {
- return controlPoints.length;
- }
-
- @Override
- public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
- return VisibilityPolicy.NEVER;
- }
-
- @Override
- @EditableProperty(name = "Designation")
- public String getValue() {
- return type;
- }
-
- @Override
- public void setValue(String value) {
- this.type = value;
- }
-
- @Override
- public boolean isControlPointSticky(int index) {
- return index > 0;
- }
-
- @Override
- public void setControlPoint(Point2D point, int index) {
- controlPoints[index].setLocation(point);
-
- body = null;
- }
-
- @Override
- public boolean canPointMoveFreely(int pointIndex) {
- return false;
- }
-
- @EditableProperty(name = "Electrode Labels")
- public String getElectrodeLabels() {
- if (electrodeLabels == null)
- electrodeLabels = "1,2,3,4,5,6,7,8,9,10,11,12";
- return electrodeLabels;
- }
-
- public void setElectrodeLabels(String electrodeLabels) {
- this.electrodeLabels = electrodeLabels;
- }
-
- @EditableProperty(name = "Label")
- public Color getLabelColor() {
- if (labelColor == null)
- labelColor = LABEL_COLOR;
- return labelColor;
- }
-
- public void setLabelColor(Color labelColor) {
- this.labelColor = labelColor;
- }
-
- @EditableProperty(name = "Mount")
- public Mount getMount() {
- if (mount == null)
- mount = Mount.CHASSIS;
- return mount;
- }
-
- public void setMount(Mount mount) {
- this.mount = mount;
-
- updateControlPoints();
- // Reset body shape
- body = null;
- }
-
- @Override
- public String getControlPointNodeName(int index) {
- String[] labels = getElectrodeLabels().split(",");
- return index > 0 && index <= labels.length ? labels[index - 1] : null;
- }
-
- @Override
- public Rectangle2D getCachingBounds() {
- Rectangle2D rect = getBody()[0].getBounds2D();
- int margin = 40; // to catch the pins that are outside the body, if needed
- return new Rectangle2D.Double(rect.getX() - margin, rect.getY() - margin, rect.getWidth() + 2 * margin, rect.getHeight() + 2 * margin);
- }
-
- public static enum Base {
- B9A("Noval B9A"), OCTAL("Octal"), B7G("Small-button B7G"), B12C("Duodecar B12C");
-
- String name;
-
- private Base(String name) {
- this.name = name;
- }
-
- @Override
- public String toString() {
- return name;
- }
- }
-
- public static enum Mount {
- CHASSIS("Chassis"), PCB("PCB");
-
- String name;
-
- private Mount(String name) {
- this.name = name;
- }
-
- @Override
- public String toString() {
- return name;
- }
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.components.tube;
+
+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.Area;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import org.diylc.appframework.miscutils.ConfigurationManager;
+
+import org.diylc.awt.StringUtils;
+import org.diylc.common.HorizontalAlignment;
+import org.diylc.common.IPlugInPort;
+import org.diylc.common.ObjectCache;
+import org.diylc.common.VerticalAlignment;
+import org.diylc.components.AbstractAngledComponent;
+import org.diylc.components.transform.AngledComponentTransformer;
+import org.diylc.core.ComponentState;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.IDrawingObserver;
+import org.diylc.core.Project;
+import org.diylc.core.Theme;
+import org.diylc.core.VisibilityPolicy;
+import org.diylc.core.annotations.ComponentDescriptor;
+import org.diylc.core.annotations.EditableProperty;
+import org.diylc.core.annotations.KeywordPolicy;
+import org.diylc.core.gerber.IGerberComponentSimple;
+import org.diylc.core.measures.Size;
+import org.diylc.core.measures.SizeUnit;
+import org.diylc.utils.Constants;
+
+@ComponentDescriptor(name = "Tube Socket", author = "Branislav Stojkovic", category = "Tubes",
+ instanceNamePrefix = "V", description = "Various types of tube/valve sockets",
+ zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_VALUE, enableCache = true,
+ transformer = AngledComponentTransformer.class)
+public class TubeSocket extends AbstractAngledComponent implements IGerberComponentSimple {
+
+ private static final Size B9A_PIN_SPACING_CHASSIS = new Size(12.5d, SizeUnit.mm);
+ private static final Size B9A_PIN_SPACING_PCB = new Size(21d, SizeUnit.mm);
+ private static final Size OCTAL_PIN_SPACING = new Size(17.5d, SizeUnit.mm);
+ private static final Size B7G_PIN_SPACING = new Size(12d, SizeUnit.mm);
+ private static final Size B7G_CUTOUT_DIAMETER = new Size(4d, SizeUnit.mm);
+ private static final Size B9A_CUTOUT_DIAMETER = new Size(5.5d, SizeUnit.mm);
+ private static final Size B12C_HOLE_SIZE = new Size(10d, SizeUnit.mm);
+ private static final Size B12C_CUTOUT_DIAMETER = new Size(5.5d, SizeUnit.mm);
+ private static final Size B12C_PIN_SPACING_PCB = new Size(25d, SizeUnit.mm);
+ private static final Size B12C_PIN_SPACING_CHASSIS = new Size(22d, SizeUnit.mm);
+
+ private static final Size OCTAL_DIAMETER = new Size(25d, SizeUnit.mm);
+ private static final Size B9A_DIAMETER = new Size(3 / 4d, SizeUnit.in);
+ private static final Size B7G_DIAMETER = new Size(17d, SizeUnit.mm);
+ private static final Size B12C_DIAMETER = new Size(30d, SizeUnit.mm);
+
+ private static final long serialVersionUID = 1L;
+
+ private static Color BODY_COLOR = Color.decode("#F7F7EF");
+ private static Color LABEL_COLOR = BODY_COLOR.darker();
+ public static Color PIN_COLOR = METAL_COLOR;
+ public static Color PIN_BORDER_COLOR = PIN_COLOR.darker();
+ public static Size PIN_DIAMETER = new Size(1d, SizeUnit.mm);
+ private static Size PIN_WIDTH = new Size(0.08d, SizeUnit.in);
+ private static Size PIN_THICKNESS = new Size(0.02d, SizeUnit.in);
+ public static Size HOLE_SIZE = new Size(5d, SizeUnit.mm);
+ public static Size OCTAL_TICK_SIZE = new Size(2d, SizeUnit.mm);
+
+ private Base base = Base.B9A;
+ private String type = "";
+ private Color color = BODY_COLOR;
+ private String electrodeLabels = null;
+ private Mount mount = Mount.CHASSIS;
+ private Color labelColor = LABEL_COLOR;
+
+ private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0)};
+
+ public TubeSocket() {
+ super();
+ updateControlPoints();
+ }
+
+ @EditableProperty
+ public Base getBase() {
+ return base;
+ }
+
+ public void setBase(Base base) {
+ this.base = base;
+ updateControlPoints();
+ // Reset body shape
+ body = null;
+ }
+
+ @EditableProperty
+ public Color getColor() {
+ if (color == null) {
+ color = BODY_COLOR;
+ }
+ return color;
+ }
+
+ public void setColor(Color color) {
+ this.color = color;
+ }
+
+ // @EditableProperty
+ // public Mount getMount() {
+ // return mount;
+ // }
+ //
+ // public void setMount(Mount mount) {
+ // this.mount = mount;
+ // }
+
+ @Override
+ protected void updateControlPoints() {
+ Point2D firstPoint = controlPoints[0];
+ int pinCount;
+ int pinSpacing;
+ boolean hasEmptySpace;
+ switch (base) {
+ case B7G:
+ pinCount = 7;
+ pinSpacing = getClosestOdd(B7G_PIN_SPACING.convertToPixels());
+ hasEmptySpace = true;
+ break;
+ case OCTAL:
+ pinCount = 8;
+ pinSpacing = getClosestOdd(OCTAL_PIN_SPACING.convertToPixels());
+ hasEmptySpace = false;
+ break;
+ case B9A:
+ pinCount = 9;
+ pinSpacing = getClosestOdd(getMount() == Mount.PCB ? B9A_PIN_SPACING_PCB.convertToPixels() : B9A_PIN_SPACING_CHASSIS.convertToPixels());
+ hasEmptySpace = true;
+ break;
+ case B12C:
+ pinCount = 12;
+ pinSpacing = getClosestOdd(getMount() == Mount.PCB ? B12C_PIN_SPACING_PCB.convertToPixels() : B12C_PIN_SPACING_CHASSIS.convertToPixels());
+ hasEmptySpace = true;
+ break;
+ default:
+ throw new RuntimeException("Unexpected base: " + base);
+ }
+ double angleIncrement = Math.PI * 2 / (hasEmptySpace ? (pinCount + 1) : pinCount);
+ double initialAngleOffset = hasEmptySpace ? angleIncrement : (angleIncrement / 2);
+
+ controlPoints = new Point2D[pinCount + 1];
+ double theta = initialAngleOffset + getAngle().getValueRad();
+ controlPoints[0] = firstPoint;
+ for (int i = 0; i < pinCount; i++) {
+ controlPoints[i + 1] =
+ new Point2D.Double(firstPoint.getX() + Math.cos(theta) * pinSpacing / 2,
+ firstPoint.getY() + Math.sin(theta) * pinSpacing / 2);
+ theta += angleIncrement;
+ }
+ }
+
+ public Shape[] getBody() {
+ if (body == null) {
+ int bodyDiameter;
+ switch (base) {
+ case B7G:
+ bodyDiameter = getClosestOdd(B7G_DIAMETER.convertToPixels());
+ break;
+ case B9A:
+ bodyDiameter = getClosestOdd(B9A_DIAMETER.convertToPixels());
+ break;
+ case OCTAL:
+ bodyDiameter = getClosestOdd(OCTAL_DIAMETER.convertToPixels());
+ break;
+ case B12C:
+ bodyDiameter = getClosestOdd(B12C_DIAMETER.convertToPixels());
+ break;
+ default:
+ throw new RuntimeException("Unexpected base: " + base);
+ }
+
+ Ellipse2D baseShape =
+ new Ellipse2D.Double(controlPoints[0].getX() - bodyDiameter / 2, controlPoints[0].getY() - bodyDiameter / 2,
+ bodyDiameter, bodyDiameter);
+ Area bodyArea = new Area(baseShape);
+ int holeSize = getClosestOdd(base == Base.B12C ? B12C_HOLE_SIZE.convertToPixels() : HOLE_SIZE.convertToPixels());
+ bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - holeSize / 2, controlPoints[0].getY() - holeSize
+ / 2, holeSize, holeSize)));
+
+ if (base == Base.OCTAL) {
+ int tickSize = getClosestOdd(OCTAL_TICK_SIZE.convertToPixels());
+ double theta = getAngle().getValueRad();
+ int centerX = (int) (controlPoints[0].getX() + Math.cos(theta) * holeSize / 2);
+ int centerY = (int) (controlPoints[0].getY() + Math.sin(theta) * holeSize / 2);
+ bodyArea.subtract(new Area(new Ellipse2D.Double(centerX - tickSize / 2, centerY - tickSize / 2, tickSize,
+ tickSize)));
+ } else if (base == Base.B9A && getMount() == Mount.CHASSIS) {
+ double cutoutDiameter = getClosestOdd(B9A_CUTOUT_DIAMETER.convertToPixels());
+ bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - cutoutDiameter / 2, controlPoints[0].getY() - bodyDiameter / 2 - cutoutDiameter * 3 / 4, cutoutDiameter, cutoutDiameter)));
+ bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - cutoutDiameter / 2, controlPoints[0].getY() + bodyDiameter / 2 - cutoutDiameter / 4, cutoutDiameter, cutoutDiameter)));
+ } else if (base == Base.B7G && getMount() == Mount.CHASSIS) {
+ double cutoutDiameter = getClosestOdd(B7G_CUTOUT_DIAMETER.convertToPixels());
+ bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - cutoutDiameter / 2, controlPoints[0].getY() - bodyDiameter / 2 - cutoutDiameter * 3 / 4, cutoutDiameter, cutoutDiameter)));
+ bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - cutoutDiameter / 2, controlPoints[0].getY() + bodyDiameter / 2 - cutoutDiameter / 4, cutoutDiameter, cutoutDiameter)));
+ } else if (base == Base.B12C && getMount() == Mount.CHASSIS) {
+ double cutoutDiameter = getClosestOdd(B12C_CUTOUT_DIAMETER.convertToPixels());
+ bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - cutoutDiameter / 2, controlPoints[0].getY() - bodyDiameter / 2 - cutoutDiameter * 3 / 4, cutoutDiameter, cutoutDiameter)));
+ bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - cutoutDiameter / 2, controlPoints[0].getY() + bodyDiameter / 2 - cutoutDiameter / 4, cutoutDiameter, cutoutDiameter)));
+ }
+
+ body = new Shape[] { bodyArea };
+ }
+ return body;
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
+ IDrawingObserver drawingObserver) {
+
+ g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
+
+ // Draw body
+ Shape[] body = getBody();
+ Composite oldComposite = applyAlpha(g2d, componentState);
+ if (componentState != ComponentState.DRAGGING) {
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getColor());
+ g2d.fill(body[0]);
+ }
+ g2d.setComposite(oldComposite);
+ Color finalBorderColor;
+ if (outlineMode) {
+ Theme theme =
+ (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : theme.getOutlineColor();
+ } else {
+ finalBorderColor =
+ componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
+ : getColor().darker();
+ }
+ g2d.setColor(finalBorderColor);
+ g2d.draw(body[0]);
+
+ drawingObserver.stopTracking();
+
+ // Draw pins
+
+ for (int i = 1; i < controlPoints.length; i++) {
+ Shape pinShape;
+ if (getMount() == Mount.PCB) {
+ int pinSize = getClosestOdd(PIN_DIAMETER.convertToPixels());
+ pinShape = new Ellipse2D.Double(controlPoints[i].getX() - pinSize / 2,
+ controlPoints[i].getY() - pinSize / 2, pinSize, pinSize);
+ } else {
+ int pinWidth = getClosestOdd(PIN_WIDTH.convertToPixels());
+ int pinThickness = getClosestOdd(PIN_THICKNESS.convertToPixels());
+ pinShape = new Rectangle2D.Double(controlPoints[i].getX() - pinWidth / 2,
+ controlPoints[i].getY() - pinThickness / 2, pinWidth, pinThickness);
+ double theta = Math.atan2(controlPoints[i].getY() - controlPoints[0].getY(),
+ controlPoints[i].getX() - controlPoints[0].getX()) + Math.PI / 2;
+ Area rotatedPin = new Area(pinShape);
+ rotatedPin.transform(AffineTransform.getRotateInstance(theta, controlPoints[i].getX(),
+ controlPoints[i].getY()));
+ pinShape = rotatedPin;
+ }
+ g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : PIN_COLOR);
+ if (getMount() == Mount.CHASSIS)
+ drawingObserver.startTrackingContinuityArea(true);
+ g2d.fill(pinShape);
+ drawingObserver.stopTrackingContinuityArea();
+ if (!outlineMode) {
+ g2d.setColor(PIN_BORDER_COLOR);
+ g2d.draw(pinShape);
+ }
+ }
+
+ // draw electrode labels
+ if (getElectrodeLabels() != null) {
+ g2d.setColor(getLabelColor());
+ g2d.setFont(project.getFont().deriveFont((float) (project.getFont().getSize2D() * 0.8)));
+ String[] labels = getElectrodeLabels().split(",");
+ double electrodeLabelOffset = project.getFont().getSize2D() * (getBase() == Base.B9A && getMount() == Mount.PCB ? 1.5 : 1);
+ for (int i = 0; i < labels.length; i++) {
+ if (i < controlPoints.length - 1) {
+ String label = labels[i];
+ double theta = Math.atan2(controlPoints[i + 1].getY() - controlPoints[0].getY(), controlPoints[i + 1].getX() - controlPoints[0].getX());
+ double x = controlPoints[i + 1].getX() - Math.cos(theta) * electrodeLabelOffset;
+ double y = controlPoints[i + 1].getY() - Math.sin(theta) * electrodeLabelOffset;
+ StringUtils.drawCenteredText(g2d, label, (int)x, (int)y, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, int width, int height) {
+ Area area = new Area(new Ellipse2D.Double(1, 1, width - 2, width - 2));
+ int center = width / 2;
+ area.subtract(new Area(new Ellipse2D.Double(center - 2, center - 2, 5, 5)));
+ g2d.setColor(BODY_COLOR);
+ g2d.fill(area);
+ g2d.setColor(BODY_COLOR.darker());
+ g2d.draw(area);
+
+ int radius = width / 2 - 6;
+ for (int i = 0; i < 8; i++) {
+ int x = (int) (center + Math.cos(i * Math.PI / 4) * radius);
+ int y = (int) (center + Math.sin(i * Math.PI / 4) * radius);
+ g2d.setColor(PIN_COLOR);
+ g2d.fillOval(x - 1, y - 1, 3, 3);
+ g2d.setColor(PIN_BORDER_COLOR);
+ g2d.drawOval(x - 1, y - 1, 3, 3);
+ }
+ }
+
+ @Override
+ public Point2D getControlPoint(int index) {
+ return controlPoints[index];
+ }
+
+ @Override
+ public int getControlPointCount() {
+ return controlPoints.length;
+ }
+
+ @Override
+ public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
+ return VisibilityPolicy.NEVER;
+ }
+
+ @Override
+ @EditableProperty(name = "Designation")
+ public String getValue() {
+ return type;
+ }
+
+ @Override
+ public void setValue(String value) {
+ this.type = value;
+ }
+
+ @Override
+ public boolean isControlPointSticky(int index) {
+ return index > 0;
+ }
+
+ @Override
+ public void setControlPoint(Point2D point, int index) {
+ controlPoints[index].setLocation(point);
+
+ body = null;
+ }
+
+ @Override
+ public boolean canPointMoveFreely(int pointIndex) {
+ return false;
+ }
+
+ @EditableProperty(name = "Electrode Labels")
+ public String getElectrodeLabels() {
+ if (electrodeLabels == null)
+ electrodeLabels = "1,2,3,4,5,6,7,8,9,10,11,12";
+ return electrodeLabels;
+ }
+
+ public void setElectrodeLabels(String electrodeLabels) {
+ this.electrodeLabels = electrodeLabels;
+ }
+
+ @EditableProperty(name = "Label")
+ public Color getLabelColor() {
+ if (labelColor == null)
+ labelColor = LABEL_COLOR;
+ return labelColor;
+ }
+
+ public void setLabelColor(Color labelColor) {
+ this.labelColor = labelColor;
+ }
+
+ @EditableProperty(name = "Mount")
+ public Mount getMount() {
+ if (mount == null)
+ mount = Mount.CHASSIS;
+ return mount;
+ }
+
+ public void setMount(Mount mount) {
+ this.mount = mount;
+
+ updateControlPoints();
+ // Reset body shape
+ body = null;
+ }
+
+ @Override
+ public String getControlPointNodeName(int index) {
+ String[] labels = getElectrodeLabels().split(",");
+ return index > 0 && index <= labels.length ? labels[index - 1] : null;
+ }
+
+ @Override
+ public Rectangle2D getCachingBounds() {
+ Rectangle2D rect = getBody()[0].getBounds2D();
+ int margin = 40; // to catch the pins that are outside the body, if needed
+ return new Rectangle2D.Double(rect.getX() - margin, rect.getY() - margin, rect.getWidth() + 2 * margin, rect.getHeight() + 2 * margin);
+ }
+
+ public static enum Base {
+ B9A("Noval B9A"), OCTAL("Octal"), B7G("Small-button B7G"), B12C("Duodecar B12C");
+
+ String name;
+
+ private Base(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+ }
+
+ public static enum Mount {
+ CHASSIS("Chassis"), PCB("PCB");
+
+ String name;
+
+ private Mount(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/serialization/V1FileParser.java b/diylc/diylc-library/src/main/java/org/diylc/serialization/V1FileParser.java
index 2e16f7dc4..f8fc0bfec 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/serialization/V1FileParser.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/serialization/V1FileParser.java
@@ -31,15 +31,11 @@ import java.util.List;
import java.util.Map;
import java.util.Random;
import org.apache.log4j.Logger;
+import org.diylc.common.*;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
-import org.diylc.common.Display;
-import org.diylc.common.HorizontalAlignment;
-import org.diylc.common.Orientation;
-import org.diylc.common.OrientationHV;
-import org.diylc.common.VerticalAlignment;
import org.diylc.components.AbstractLeadedComponent;
import org.diylc.components.AbstractTransparentComponent;
import org.diylc.components.boards.AbstractBoard;
@@ -673,7 +669,7 @@ public class V1FileParser implements IOldFileParser {
((AbstractLeadedComponent>) component).setDisplay(Display.NAME);
}
if (component instanceof AbstractTransparentComponent>) {
- ((AbstractTransparentComponent>) component).setAlpha((byte) 100);
+ ((AbstractTransparentComponent>) component).setAlpha(new Percentage(100));
}
project.getComponents().add(component);
}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/serialization/V2FileParser.java b/diylc/diylc-library/src/main/java/org/diylc/serialization/V2FileParser.java
index 3d9cc20d6..d9c94801d 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/serialization/V2FileParser.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/serialization/V2FileParser.java
@@ -27,6 +27,7 @@ import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.diylc.appframework.miscutils.ConfigurationManager;
+import org.diylc.common.Percentage;
import org.nfunk.jep.JEP;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@@ -83,10 +84,8 @@ import org.diylc.core.measures.ResistanceUnit;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
import org.diylc.presenter.Presenter;
-import org.diylc.serialization.IOldFileParser;
import org.diylc.utils.Constants;
-
public class V2FileParser implements IOldFileParser {
private static final Logger LOG = Logger.getLogger(V2FileParser.class);
@@ -142,9 +141,9 @@ public class V2FileParser implements IOldFileParser {
if (node.getNodeType() == Node.ELEMENT_NODE) {
if (node.getNodeName().equalsIgnoreCase("component")) {
LOG.debug(node.getAttributes().getNamedItem("name").getNodeValue());
- NodeList unuci = node.getChildNodes();
- Node properties = unuci.item(1);
- Node points = unuci.item(3);
+ NodeList grandchildNodes = node.getChildNodes();
+ Node properties = grandchildNodes.item(1);
+ Node points = grandchildNodes.item(3);
NodeList propertyList = properties.getChildNodes();
NodeList pointList = points.getChildNodes();
@@ -174,7 +173,6 @@ public class V2FileParser implements IOldFileParser {
// // gives Name Part# Thickness Color Group
if (propertyList.item(j).getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("color")) {
String color = propertyList.item(j).getAttributes().getNamedItem("value").getNodeValue();
- System.out.println(color);
String hex_r = color.substring(0, 2);
int value_r = Integer.parseInt(hex_r, 16);
String hex_g = color.substring(2, 4);
@@ -234,7 +232,7 @@ public class V2FileParser implements IOldFileParser {
} else if (propertyList.item(j).getAttributes().getNamedItem("name").getNodeValue()
.equalsIgnoreCase("Value")) {
String pr8 = propertyList.item(j).getAttributes().getNamedItem("value").getNodeValue();
- if (pr8 != "") {
+ if (!pr8.isEmpty()) {
value_s = pr8;
String pr9 = pr8.replaceAll("[^0-9.]", "");
String pr10 = pr8.replaceAll("[^a-zA-Z]", "");
@@ -287,7 +285,7 @@ public class V2FileParser implements IOldFileParser {
if (cl != null) {
board.setBoardColor(cl);
}
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
board.setName(com_name);
} else {
board.setName("Main board");
@@ -298,7 +296,7 @@ public class V2FileParser implements IOldFileParser {
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Perfboard")) {
PerfBoard board = new PerfBoard();
board.setBoardColor(Color.white);
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
board.setName(com_name);
} else {
board.setName("Main board");
@@ -309,7 +307,7 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(board);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Copper Trace")) {
CopperTrace trace = new CopperTrace();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
trace.setName(com_name);
} else {
trace.setName("t");
@@ -324,7 +322,7 @@ public class V2FileParser implements IOldFileParser {
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Copper Trace Curved")) {
CurvedTrace trace = new CurvedTrace();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
trace.setName(com_name);
} else {
trace.setName("t");
@@ -340,7 +338,7 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(trace);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Eyelet")) {
Eyelet eyelet = new Eyelet();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
eyelet.setName(com_name);
} else {
eyelet.setName("eyelet");
@@ -350,7 +348,7 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(eyelet);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Solder pad")) {
SolderPad pad = new SolderPad();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
pad.setName(com_name);
} else
pad.setName("pad");
@@ -363,7 +361,7 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(pad);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Stripboard")) {
VeroBoard board = new VeroBoard();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
board.setName(com_name);
} else {
board.setName("Main board");
@@ -374,7 +372,7 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(board);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Trace Cut")) {
TraceCut cut = new TraceCut();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
cut.setName(com_name);
} else
cut.setName("cut");
@@ -383,7 +381,7 @@ public class V2FileParser implements IOldFileParser {
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Switch")) {
MiniToggleSwitch sw = new MiniToggleSwitch();
sw.setValue(ToggleSwitchType.DPDT);
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
sw.setName(com_name);
} else
sw.setName("sw");
@@ -416,7 +414,7 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(sw);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Wire")) {
HookupWire hw = new HookupWire();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
hw.setName(com_name);
} else
hw.setName("hookup_wire");
@@ -472,11 +470,11 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(hw);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Electrolytic (Axial)")) {
AxialElectrolyticCapacitor capacitor = new AxialElectrolyticCapacitor();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
capacitor.setName(com_name);
} else
capacitor.setName("A_E_C");
- capacitor.setAlpha((byte) transparency);
+ capacitor.setAlpha(new Percentage(transparency));
if (value != -9999) {
capacitor.setValue(new Capacitance(value, cp));
}
@@ -492,10 +490,10 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(capacitor);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Capacitor (Axial)")) {
AxialFilmCapacitor capacitor = new AxialFilmCapacitor();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
capacitor.setName(com_name);
}
- capacitor.setAlpha((byte) transparency);
+ capacitor.setAlpha(new Percentage(transparency));
if (value != -9999) {
capacitor.setValue(new Capacitance(value, cp));
} else
@@ -512,11 +510,11 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(capacitor);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Capacitor (Ceramic)")) {
RadialCeramicDiskCapacitor capacitor = new RadialCeramicDiskCapacitor();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
capacitor.setName(com_name);
} else
capacitor.setName("Radial_Ceramic_Capacitor");
- capacitor.setAlpha((byte) transparency);
+ capacitor.setAlpha(new Percentage(transparency));
if (value != -9999) {
capacitor.setValue(new Capacitance(value, cp));
}
@@ -532,11 +530,11 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(capacitor);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Capacitor (Radial)")) {
RadialFilmCapacitor capacitor = new RadialFilmCapacitor();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
capacitor.setName(com_name);
} else
capacitor.setName("Radial_Film_Capacitor");
- capacitor.setAlpha((byte) transparency);
+ capacitor.setAlpha(new Percentage(transparency));
if (value != -9999) {
capacitor.setValue(new Capacitance(value, cp));
}
@@ -552,28 +550,28 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(capacitor);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Electrolytic (Radial)")) {
RadialElectrolytic capacitor = new RadialElectrolytic();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
capacitor.setName(com_name);
} else
capacitor.setName("Radial_Electrolytic_Capacitor");
if (value != -9999) {
capacitor.setValue(new Capacitance(value, cp));
}
- capacitor.setAlpha((byte) transparency);
+ capacitor.setAlpha(new Percentage(transparency));
capacitor.setLength(diameterPro);
capacitor.setControlPoint(tacke.get(0), 0);
capacitor.setControlPoint(tacke.get(1), 1);
project.getComponents().add(capacitor);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Potentiometer Lug")) {
PotentiometerPanel panel = new PotentiometerPanel();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
panel.setName(com_name);
} else
panel.setName("potentiometer_panel");
if (value != -9999) {
panel.setValue(new Resistance(value, ru));
}
- panel.setAlpha((byte) transparency);
+ panel.setAlpha(new Percentage(transparency));
if (angle > 45 && angle <= 135)
panel.setOrientation(Orientation._90);
else if (angle > 135 && angle <= 225)
@@ -592,14 +590,14 @@ public class V2FileParser implements IOldFileParser {
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Resistor")
|| node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Resistor Standing")) {
Resistor resistor = new Resistor();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
resistor.setName(com_name);
} else
resistor.setName("resistor");
if (value != -9999) {
resistor.setValue(new Resistance(value, ru));
}
- resistor.setAlpha((byte) transparency);
+ resistor.setAlpha(new Percentage(transparency));
resistor.setWidth(diameterPro);
if (lengthPro.getValue() != 0) {
resistor.setLength(lengthPro);
@@ -609,7 +607,7 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(resistor);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Capacitor Symbol")) {
CapacitorSymbol cap = new CapacitorSymbol();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
cap.setName(com_name);
} else
cap.setName("cap_simbol");
@@ -625,7 +623,7 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(cap);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Diode Symbol")) {
DiodeSymbol dio = new DiodeSymbol();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
dio.setName(com_name);
} else
dio.setName("dp");
@@ -639,7 +637,7 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(dio);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Ground Symbol")) {
GroundSymbol gs = new GroundSymbol();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
gs.setName(com_name);
} else
gs.setName("gs");
@@ -648,11 +646,11 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(gs);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("LED Symbol")) {
LEDSymbol ls = new LEDSymbol();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
ls.setName(com_name);
} else
ls.setName("ls");
- if (value_s != "") {
+ if (!value_s.isEmpty()) {
ls.setValue(value_s);
}
ls.setBodyColor(cl);
@@ -662,12 +660,12 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(ls);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Pentode")) {
PentodeSymbol ps = new PentodeSymbol();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
ps.setName(com_name);
} else
ps.setName("ps");
ps.setColor(cl);
- if (value_s != "")
+ if (!value_s.isEmpty())
ps.setValue(value_s);
Point point;
@@ -678,7 +676,7 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(ps);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Electrolytic Symbol")) {
CapacitorSymbol cs = new CapacitorSymbol();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
cs.setName(com_name);
} else
cs.setName("cs");
@@ -694,13 +692,13 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(cs);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Opamp Symbol")) {
ICSymbol ic = new ICSymbol();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
ic.setName(com_name);
} else
ic.setName("ics");
- if (value_s != "")
+ if (!value_s.isEmpty())
ic.setValue(value_s);
- ic.setAlpha((byte) transparency);
+ ic.setAlpha(new Percentage(transparency));
Point point;
int x = (int) (tacke.get(0).getX() - 70);
int y = (int) tacke.get(0).getY() - 20;
@@ -710,12 +708,12 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(ic);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Potentiometer Symbol")) {
PotentiometerSymbol ps = new PotentiometerSymbol();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
ps.setName(com_name);
} else
ps.setName("ps");
ps.setOrientation(Orientation._270);
- if (value_s != "")
+ if (!value_s.isEmpty())
ps.setValue(value_s);
ps.setColor(cl);
Point point;
@@ -730,7 +728,7 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(ps);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Resistor Symbol")) {
ResistorSymbol rs = new ResistorSymbol();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
rs.setName(com_name);
} else
rs.setName("rs");
@@ -746,11 +744,11 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(rs);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Triode")) {
TriodeSymbol ts = new TriodeSymbol();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
ts.setName(com_name);
} else
ts.setName("ts");
- if (value_s != "") {
+ if (!value_s.isEmpty()) {
ts.setValue(value_s);
}
ts.setColor(cl);
@@ -762,14 +760,14 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(ts);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Diode")) {
DiodePlastic dp = new DiodePlastic();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
dp.setName(com_name);
} else
dp.setName("dp");
- if (value_s != "") {
+ if (!value_s.isEmpty()) {
dp.setValue(value_s);
}
- dp.setAlpha((byte) transparency);
+ dp.setAlpha(new Percentage(transparency));
if (display.equals("Name"))
dp.setDisplay(Display.NAME);
else
@@ -781,7 +779,7 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(dp);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("IC DIL")) {
DIL_IC dil = new DIL_IC();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
dil.setName(com_name);
} else
dil.setName("dil");
@@ -795,8 +793,6 @@ public class V2FileParser implements IOldFileParser {
dil.setPinCount(PinCount._10);
else if (pins == 12)
dil.setPinCount(PinCount._12);
- else if (pins == 12)
- dil.setPinCount(PinCount._12);
else if (pins == 14)
dil.setPinCount(PinCount._14);
else if (pins == 16)
@@ -835,8 +831,8 @@ public class V2FileParser implements IOldFileParser {
dil.setPinCount(PinCount._48);
else if (pins == 50)
dil.setPinCount(PinCount._50);
- dil.setAlpha((byte) transparency);
- if (value_s != "")
+ dil.setAlpha(new Percentage(transparency));
+ if (!value_s.isEmpty())
dil.setValue(value_s);
dil.setRowSpacing(spacingPro);
dil.setControlPoint(tacke.get(0), 0);
@@ -844,12 +840,12 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(dil);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Transistor")) {
TransistorTO92 trans = new TransistorTO92();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
trans.setName(com_name);
} else
trans.setName("tr");
- trans.setAlpha((byte) transparency);
- if (value_s != "") {
+ trans.setAlpha(new Percentage(transparency));
+ if (!value_s.isEmpty()) {
trans.setValue(value_s);
}
trans.setPinSpacing(new Size(0.1, SizeUnit.in));
@@ -898,7 +894,7 @@ public class V2FileParser implements IOldFileParser {
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Ellipse")) {
Ellipse el = new Ellipse();
el.setName("elipse");
- el.setAlpha((byte) transparency);
+ el.setAlpha(new Percentage(transparency));
el.setColor(cl);
el.setControlPoint(tacke.get(0), 0);
el.setControlPoint(tacke.get(1), 1);
@@ -915,19 +911,19 @@ public class V2FileParser implements IOldFileParser {
Rectangle rec = new Rectangle();
rec.setName("rec");
rec.setColor(cl);
- rec.setAlpha((byte) transparency);
+ rec.setAlpha(new Percentage(transparency));
rec.setEdgeRadius(radiusPro);
rec.setControlPoint(tacke.get(0), 0);
rec.setControlPoint(tacke.get(1), 1);
project.getComponents().add(rec);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Noval Tube Socket")) {
TubeSocket ts = new TubeSocket();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
ts.setName(com_name);
} else
ts.setName("ts");
- ts.setAlpha((byte) transparency);
- if (value_s != "")
+ ts.setAlpha(new Percentage(transparency));
+ if (!value_s.isEmpty())
ts.setValue(value_s);
ts.setAngle(Angle.of((int) angle));
ts.setControlPoint(tacke.get(0), 0);
@@ -935,12 +931,12 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(ts);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("BJT Transistor")) {
BJTSymbol bjt = new BJTSymbol();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
bjt.setName(com_name);
} else
bjt.setName("bjt");
bjt.setColor(cl);
- if (value_s != "")
+ if (!value_s.isEmpty())
bjt.setValue(value_s);
if (angle <= 45 || angle > 315)
bjt.setOrientation(Orientation.DEFAULT);
@@ -958,12 +954,12 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(bjt);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Octal Tube Socket")) {
TubeSocket ts = new TubeSocket();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
ts.setName(com_name);
} else
ts.setName("ts");
- ts.setAlpha((byte) transparency);
- if (value_s != "")
+ ts.setAlpha(new Percentage(transparency));
+ if (!value_s.isEmpty())
ts.setValue(value_s);
ts.setAngle(Angle.of((int) angle));
ts.setControlPoint(tacke.get(0), 0);
@@ -971,12 +967,12 @@ public class V2FileParser implements IOldFileParser {
project.getComponents().add(ts);
} else if (node.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("7-pin Tube Socket")) {
TubeSocket ts = new TubeSocket();
- if (com_name != "") {
+ if (!com_name.isEmpty()) {
ts.setName(com_name);
} else
ts.setName("ts");
- ts.setAlpha((byte) transparency);
- if (value_s != "")
+ ts.setAlpha(new Percentage(transparency));
+ if (!value_s.isEmpty())
ts.setValue(value_s);
ts.setAngle(Angle.of((int)angle));
diff --git a/diylc/diylc-swing/src/main/java/org/diylc/swing/gui/editor/FieldEditorFactory.java b/diylc/diylc-swing/src/main/java/org/diylc/swing/gui/editor/FieldEditorFactory.java
index 3ef102417..7bd3cf5d0 100644
--- a/diylc/diylc-swing/src/main/java/org/diylc/swing/gui/editor/FieldEditorFactory.java
+++ b/diylc/diylc-swing/src/main/java/org/diylc/swing/gui/editor/FieldEditorFactory.java
@@ -26,6 +26,7 @@ import java.awt.Component;
import java.awt.Font;
import javax.swing.JLabel;
import org.apache.log4j.Logger;
+import org.diylc.common.Percentage;
import org.diylc.components.misc.LoadlineEntity;
import org.diylc.common.PropertyWrapper;
@@ -99,8 +100,8 @@ public class FieldEditorFactory {
DynamicValueEditor editor = new DynamicValueEditor(property);
return editor;
}
- if (Byte.class.isAssignableFrom(property.getType()) || byte.class.isAssignableFrom(property.getType())) {
- ByteEditor editor = new ByteEditor(property);
+ if (Percentage.class.isAssignableFrom(property.getType())) {
+ PercentageEditor editor = new PercentageEditor(property);
return editor;
}
if (Boolean.class.isAssignableFrom(property.getType()) || boolean.class.isAssignableFrom(property.getType())) {
diff --git a/diylc/diylc-swing/src/main/java/org/diylc/swing/gui/editor/ByteEditor.java b/diylc/diylc-swing/src/main/java/org/diylc/swing/gui/editor/PercentageEditor.java
similarity index 65%
rename from diylc/diylc-swing/src/main/java/org/diylc/swing/gui/editor/ByteEditor.java
rename to diylc/diylc-swing/src/main/java/org/diylc/swing/gui/editor/PercentageEditor.java
index 44008a191..361f04062 100644
--- a/diylc/diylc-swing/src/main/java/org/diylc/swing/gui/editor/ByteEditor.java
+++ b/diylc/diylc-swing/src/main/java/org/diylc/swing/gui/editor/PercentageEditor.java
@@ -1,117 +1,120 @@
-/*
-
- 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 .
-
-*/
-package org.diylc.swing.gui.editor;
-
-import java.awt.Color;
-import java.awt.FlowLayout;
-import java.awt.event.KeyAdapter;
-import java.awt.event.KeyEvent;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JSlider;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-
-import org.diylc.swingframework.DoubleTextField;
-
-import org.diylc.common.PropertyWrapper;
-import org.diylc.core.annotations.PercentEditor;
-import org.diylc.utils.Constants;
-
-public class ByteEditor extends JPanel {
-
- private static final long serialVersionUID = 1L;
-
- private Color oldBg = getBackground();
-
- private static final byte default100Percent = 127;
-
- private byte _100PercentValue;
-
- public ByteEditor(final PropertyWrapper property) {
- super();
-
- setLayout(new FlowLayout());
-
- try {
- PercentEditor percentEditor = property.getGetter().getAnnotation(PercentEditor.class);
- if (percentEditor == null)
- _100PercentValue = default100Percent;
- else
- _100PercentValue = percentEditor._100PercentValue();
- } catch (Exception e) {
- _100PercentValue = default100Percent;
- }
-
- final JSlider slider = new JSlider();
- final DoubleTextField valueField = new DoubleTextField();
-
- if (property.isReadOnly()) {
- slider.setEnabled(false);
- valueField.setEnabled(false);
- }
-
- final double percentFactor = (double) default100Percent / _100PercentValue;
-
- slider.setMinimum(0);
- slider.setMaximum(default100Percent * 100);
-
- slider.addChangeListener(new ChangeListener() {
-
- @Override
- public void stateChanged(ChangeEvent e) {
- property.setChanged(true);
- setBackground(oldBg);
- slider.setBackground(oldBg);
- property.setValue(Integer.valueOf(slider.getValue() / 100).byteValue());
- valueField.setText(Integer.toString((int) Math.round(percentFactor * (double) slider.getValue()
- / default100Percent)));
- }
- });
- slider.setValue((Byte) property.getValue() * 100);
-
- valueField
- .setText(Integer.toString((int) Math.round(percentFactor * (double) slider.getValue() / default100Percent)));
- valueField.setColumns(3);
- valueField.addKeyListener(new KeyAdapter() {
-
- @Override
- public void keyReleased(KeyEvent e) {
- try {
- int newPosition = (int) (Double.parseDouble(valueField.getText()) * default100Percent / percentFactor);
- System.out.println("keyReleased, pos: " + newPosition);
- slider.setValue(newPosition);
- } catch (Exception ex) {
- }
- }
- });
-
- if (!property.isUnique()) {
- setBackground(Constants.MULTI_VALUE_COLOR);
- slider.setBackground(Constants.MULTI_VALUE_COLOR);
- }
-
- add(slider);
- add(valueField);
- add(new JLabel("%"));
- }
-}
+/*
+
+ 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 .
+
+*/
+package org.diylc.swing.gui.editor;
+
+import java.awt.Color;
+import java.awt.FlowLayout;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSlider;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import org.diylc.swingframework.DoubleTextField;
+
+import org.diylc.common.Percentage;
+import org.diylc.common.PropertyWrapper;
+import org.diylc.core.annotations.PercentEditor;
+import org.diylc.utils.Constants;
+
+public class PercentageEditor extends JPanel {
+
+ private static final long serialVersionUID = 1L;
+
+ private Color oldBg = getBackground();
+
+ private int minValue = 0;
+ private int maxValue = 100;
+
+ public PercentageEditor(final PropertyWrapper property) {
+ super();
+
+ setLayout(new FlowLayout());
+
+ try {
+ PercentEditor percentEditor = property.getGetter().getAnnotation(PercentEditor.class);
+ if (percentEditor != null) {
+ minValue = percentEditor.minValue();
+ maxValue = percentEditor.maxValue();
+ }
+ } catch (Exception e) {
+ }
+
+ final JSlider slider = new JSlider();
+ final DoubleTextField valueField = new DoubleTextField();
+
+ if (property.isReadOnly()) {
+ slider.setEnabled(false);
+ valueField.setEnabled(false);
+ }
+
+ slider.setMinimum(minValue);
+ slider.setMaximum(maxValue);
+
+ slider.addChangeListener(new ChangeListener() {
+
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ property.setChanged(true);
+ setBackground(oldBg);
+ slider.setBackground(oldBg);
+
+ property.setValue(new Percentage(slider.getValue()));
+ valueField.setText(Integer.toString(slider.getValue()));
+ }
+ });
+
+ Object val = property.getValue();
+ if (val != null) {
+ slider.setValue(((Percentage) val).getValue());
+ } else {
+ slider.setValue(minValue);
+ }
+
+ valueField.setText(Integer.toString(slider.getValue()));
+ valueField.setColumns(3);
+ valueField.addKeyListener(new KeyAdapter() {
+
+ @Override
+ public void keyReleased(KeyEvent e) {
+ try {
+ int newPosition = (int) Double.parseDouble(valueField.getText());
+ if (newPosition >= minValue && newPosition <= maxValue) {
+ slider.setValue(newPosition);
+ }
+ } catch (Exception ex) {
+ }
+ }
+ });
+
+ if (!property.isUnique()) {
+ setBackground(Constants.MULTI_VALUE_COLOR);
+ slider.setBackground(Constants.MULTI_VALUE_COLOR);
+ }
+
+ add(slider);
+ add(valueField);
+ add(new JLabel("%"));
+ }
+}
diff --git a/diylc/diylc-swing/src/main/java/org/diylc/swing/loadline/LoadlineEditorFrame.java b/diylc/diylc-swing/src/main/java/org/diylc/swing/loadline/LoadlineEditorFrame.java
index d3c956fcf..f1c8bab5d 100644
--- a/diylc/diylc-swing/src/main/java/org/diylc/swing/loadline/LoadlineEditorFrame.java
+++ b/diylc/diylc-swing/src/main/java/org/diylc/swing/loadline/LoadlineEditorFrame.java
@@ -35,6 +35,7 @@ import org.apache.poi.util.IOUtils;
import org.diylc.appframework.miscutils.IConfigurationManager;
import org.diylc.appframework.miscutils.InMemoryConfigurationManager;
import org.diylc.appframework.miscutils.Utils;
+import org.diylc.common.*;
import org.diylc.components.connectivity.Dot;
import org.diylc.components.connectivity.Line;
import org.diylc.components.misc.Image;
@@ -47,12 +48,6 @@ import org.diylc.swingframework.DoubleTextField;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
-import org.diylc.common.EventType;
-import org.diylc.common.HorizontalAlignment;
-import org.diylc.common.IPlugIn;
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.PropertyWrapper;
-import org.diylc.common.VerticalAlignment;
import org.diylc.components.AbstractCurvedComponent.PointCount;
import org.diylc.core.IDIYComponent;
import org.diylc.core.IView;
@@ -687,7 +682,7 @@ public class LoadlineEditorFrame extends JFrame implements IView {
image.setControlPoint(new Point((int) spacing, (int) spacing), 0);
image.setControlPoint(new Point((int) (canvasDimensions.width - spacing),
(int) (canvasDimensions.height - spacing)), 1);
- image.setAlpha((byte) 50); // make it transparent
+ image.setAlpha(new Percentage(50)); // make it transparent
fis.close();
// add to the bottom
project.getComponents().add(0, image);