diff --git a/diylc/diylc-core/src/main/resources/update.xml b/diylc/diylc-core/src/main/resources/update.xml index 410c65df..f09b0b14 100644 --- a/diylc/diylc-core/src/main/resources/update.xml +++ b/diylc/diylc-core/src/main/resources/update.xml @@ -593,6 +593,10 @@ NEW_FEATURE Holding 'Shift' when starting to drag components or control points keeps the whole drag strictly horizontal or vertical, in the direction of the initial gesture. Holding 'Shift' while drawing a new wire or two-point component does the same + + NEW_FEATURE + Added Rectangular shape to LED component in addition to Round; added ability to set LED lead spacing + IMPROVEMENT 'S1 Switch' can now be rotated to match the orientation of the potentiometer it is mounted on, so the switching matrix stays correct relative to the pot lugs diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/LED.java b/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/LED.java index ca3da9e9..a4cc0b02 100644 --- a/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/LED.java +++ b/diylc/diylc-library/src/main/java/org/diylc/components/semiconductors/LED.java @@ -23,6 +23,7 @@ package org.diylc.components.semiconductors; import java.awt.Color; import java.awt.Graphics2D; +import java.awt.Rectangle; import java.awt.Shape; import java.awt.geom.Area; import java.awt.geom.Ellipse2D; @@ -35,6 +36,7 @@ import org.diylc.core.CreationMethod; import org.diylc.core.IDIYComponent; import org.diylc.core.annotations.ComponentDescriptor; 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; @@ -47,10 +49,14 @@ public class LED extends AbstractLeadedComponent implements IGerberCompo private static final long serialVersionUID = 1L; public static Size DEFAULT_SIZE = new Size(5d, SizeUnit.mm); + public static Size DEFAULT_WIDTH = new Size(2d, SizeUnit.mm); + public static Size PIN_SPACING = new Size(2.54d, SizeUnit.mm); public static Color BODY_COLOR = Color.decode("#5DFC0A"); public static Color BORDER_COLOR = BODY_COLOR.darker(); private String value = ""; + private BodyShape shape = BodyShape.ROUND; + private Size pinSpacing = PIN_SPACING; public LED() { super(); @@ -67,6 +73,35 @@ public class LED extends AbstractLeadedComponent implements IGerberCompo this.value = value; } + @EditableProperty + public BodyShape getShape() { + if (shape == null) { + shape = BodyShape.ROUND; + } + return shape; + } + + public void setShape(BodyShape shape) { + this.shape = shape; + } + + @Override + protected int calculatePinSpacing(Rectangle shapeRect) { + return (int) getPinSpacing().convertToPixels(); + } + + @EditableProperty(name = "Lead Spacing") + public Size getPinSpacing() { + if (pinSpacing == null) { + pinSpacing = PIN_SPACING; + } + return pinSpacing; + } + + public void setPinSpacing(Size pinSpacing) { + this.pinSpacing = pinSpacing; + } + @Override public String getControlPointNodeName(int index) { switch (index) { @@ -97,7 +132,7 @@ public class LED extends AbstractLeadedComponent implements IGerberCompo @Override protected Size getDefaultWidth() { - return DEFAULT_SIZE; + return DEFAULT_WIDTH; } @Override @@ -107,6 +142,10 @@ public class LED extends AbstractLeadedComponent implements IGerberCompo @Override protected Shape getBodyShape() { + if (getShape() == BodyShape.RECTANGLE) { + return new Rectangle2D.Double(0, 0, getClosestOdd(getLength().convertToPixels()), + getClosestOdd(getWidth().convertToPixels())); + } int size = getClosestOdd((int) (getLength().convertToPixels() * 1.2)); Area area = new Area(new Ellipse2D.Double(0, 0, size, size)); area.intersect(new Area(new Rectangle2D.Double(0, 0, getLength().convertToPixels() * 1.15, size))); @@ -115,7 +154,7 @@ public class LED extends AbstractLeadedComponent implements IGerberCompo @Override protected void decorateComponentBody(Graphics2D g2d, boolean outlineMode) { - if (!outlineMode) { + if (!outlineMode && getShape() == BodyShape.ROUND) { int size = getClosestOdd((int) (getLength().convertToPixels() * 1.2)); int innerSize = getClosestOdd(getLength().convertToPixels()); int x = (size - innerSize) / 2; @@ -125,14 +164,47 @@ public class LED extends AbstractLeadedComponent implements IGerberCompo } } + // the border always follows the body color; the inherited borderColor field stays only so + // that older files and older builds keep reading it + @Override + public Color getBorderColor() { + Color bodyColor = getBodyColor(); + return bodyColor == null ? null : bodyColor.darker(); + } + + @Deprecated + @Override + public void setBorderColor(Color borderColor) { + super.setBorderColor(borderColor); + } + @EditableProperty(name = "Size") @Override public Size getLength() { return super.getLength(); } + // only rectangular LEDs use the width; a round body is sized by its diameter alone + @EditableProperty(name = "Width", validatorClass = PositiveNonZeroMeasureValidator.class, + sortOrder = 102) @Override public Size getWidth() { return super.getWidth(); } + + public enum BodyShape { + + ROUND("Round"), RECTANGLE("Rectangle"); + + private String label; + + private BodyShape(String label) { + this.label = label; + } + + @Override + public String toString() { + return label; + } + } }