diff --git a/diylc/diylc-core/src/main/java/org/diylc/core/AbstractDynamicPropertyValueSource.java b/diylc/diylc-core/src/main/java/org/diylc/core/AbstractDynamicPropertyValueSource.java new file mode 100644 index 00000000..793181ad --- /dev/null +++ b/diylc/diylc-core/src/main/java/org/diylc/core/AbstractDynamicPropertyValueSource.java @@ -0,0 +1,34 @@ +package org.diylc.core; + +import org.diylc.common.PropertyWrapper; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public abstract class AbstractDynamicPropertyValueSource implements IDynamicPropertySource { + + protected List properties; + protected IDIYComponent component; + + @Override + public void setProperties(List properties) { + this.properties = properties; + } + + @Override + public void setComponent(IDIYComponent component) { + this.component = component; + } + + @Override + public String getDisplayValue(Object value) { + if (value == null) { + return "None"; + } + if (component instanceof ISwitch sw) { + return sw.getPositionName((Integer)value); + } + return "#" + (((Integer)value) + 1); + } +} diff --git a/diylc/diylc-core/src/main/java/org/diylc/utils/SwitchUtils.java b/diylc/diylc-core/src/main/java/org/diylc/utils/SwitchUtils.java index 754f683a..b1aca465 100644 --- a/diylc/diylc-core/src/main/java/org/diylc/utils/SwitchUtils.java +++ b/diylc/diylc-core/src/main/java/org/diylc/utils/SwitchUtils.java @@ -27,63 +27,68 @@ import java.util.*; public class SwitchUtils { - public static List> getConnectedTerminals(ISwitch switchComponent, int numPoints) { - List> connectedGroups = new ArrayList<>(); - - // Only process if we have a selected position and should render connections - if (switchComponent.getSelectedPosition() == null || !Boolean.TRUE.equals(switchComponent.getHighlightConnectedTerminals())) { - return connectedGroups; - } + public static List> getConnectedTerminals(ISwitch switchComponent, int numPoints) { - // First, collect all direct connections - List connections = new ArrayList<>(); - for (int i = 0; i < numPoints; i++) { - for (int j = i + 1; j < numPoints; j++) { - if (switchComponent.arePointsConnected(i, j, switchComponent.getSelectedPosition())) { - connections.add(new int[]{i, j}); - } - } - } - - // Create a map to track which points are in which group - Map> pointToGroup = new HashMap<>(); - - // Process each connection - for (int[] connection : connections) { - int p1 = connection[0]; - int p2 = connection[1]; - - Set group1 = pointToGroup.get(p1); - Set group2 = pointToGroup.get(p2); - - if (group1 == null && group2 == null) { - // Create new group - Set newGroup = new HashSet<>(); - newGroup.add(p1); - newGroup.add(p2); - pointToGroup.put(p1, newGroup); - pointToGroup.put(p2, newGroup); - } else if (group1 == null) { - // Add p1 to p2's group - group2.add(p1); - pointToGroup.put(p1, group2); - } else if (group2 == null) { - // Add p2 to p1's group - group1.add(p2); - pointToGroup.put(p2, group1); - } else if (group1 != group2) { - // Merge groups - group1.addAll(group2); - for (Integer p : group2) { - pointToGroup.put(p, group1); - } - } - } - - // Collect unique groups - Set> uniqueGroups = new HashSet<>(pointToGroup.values()); - connectedGroups.addAll(uniqueGroups); - - return connectedGroups; + if (!Boolean.TRUE.equals(switchComponent.getHighlightConnectedTerminals())) { + return List.of(); } + List> connectedGroups = new ArrayList<>(); + + // Only process if we have a selected position and should render connections + if (switchComponent.getSelectedPosition() == null || !Boolean.TRUE.equals( + switchComponent.getHighlightConnectedTerminals())) { + return connectedGroups; + } + + // First, collect all direct connections + List connections = new ArrayList<>(); + for (int i = 0; i < numPoints; i++) { + for (int j = i + 1; j < numPoints; j++) { + if (switchComponent.arePointsConnected(i, j, switchComponent.getSelectedPosition())) { + connections.add(new int[] {i, j}); + } + } + } + + // Create a map to track which points are in which group + Map> pointToGroup = new HashMap<>(); + + // Process each connection + for (int[] connection : connections) { + int p1 = connection[0]; + int p2 = connection[1]; + + Set group1 = pointToGroup.get(p1); + Set group2 = pointToGroup.get(p2); + + if (group1 == null && group2 == null) { + // Create new group + Set newGroup = new HashSet<>(); + newGroup.add(p1); + newGroup.add(p2); + pointToGroup.put(p1, newGroup); + pointToGroup.put(p2, newGroup); + } else if (group1 == null) { + // Add p1 to p2's group + group2.add(p1); + pointToGroup.put(p1, group2); + } else if (group2 == null) { + // Add p2 to p1's group + group1.add(p2); + pointToGroup.put(p2, group1); + } else if (group1 != group2) { + // Merge groups + group1.addAll(group2); + for (Integer p : group2) { + pointToGroup.put(p, group1); + } + } + } + + // Collect unique groups + Set> uniqueGroups = new HashSet<>(pointToGroup.values()); + connectedGroups.addAll(uniqueGroups); + + return connectedGroups; + } } diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/SlideSwitch.java b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/SlideSwitch.java index 70d53eb4..00cacf72 100644 --- a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/SlideSwitch.java +++ b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/SlideSwitch.java @@ -29,12 +29,17 @@ import java.awt.geom.Ellipse2D; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.geom.RoundRectangle2D; +import java.util.List; +import java.util.Set; +import java.util.stream.IntStream; + import org.diylc.appframework.miscutils.ConfigurationManager; import org.diylc.common.IPlugInPort; import org.diylc.common.ObjectCache; import org.diylc.common.OrientationHV; import org.diylc.components.AbstractTransparentComponent; +import org.diylc.components.guitar.Freeway3x4_03SwitchPositionPropertyValueSource; import org.diylc.components.transform.MiniToggleSwitchTransformer; import org.diylc.core.ComponentState; import org.diylc.core.IDIYComponent; @@ -44,6 +49,7 @@ 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; @@ -51,6 +57,8 @@ import org.diylc.core.measures.Size; import org.diylc.core.measures.SizeUnit; import org.diylc.utils.Constants; +import static org.diylc.utils.SwitchUtils.getConnectedTerminals; + @ComponentDescriptor(name = "Slide Switch", category = "Electro-Mechanical", author = "Branislav Stojkovic", description = "Panel mounted slide switch", zOrder = IDIYComponent.COMPONENT, instanceNamePrefix = "SW", autoEdit = false, @@ -85,6 +93,9 @@ public class SlideSwitch extends AbstractTransparentComponent i private Color bracketColor = BRACKET_COLOR; private Boolean showBracket = true; + private Integer selectedPosition; + private Boolean highlightConnectedTerminals; + public SlideSwitch() { super(); updateControlPoints(); @@ -273,39 +284,36 @@ public class SlideSwitch extends AbstractTransparentComponent i lugHeight = getClosestOdd((int) LUG_THICKNESS.convertToPixels()); } + List> connectedTerminals = getConnectedTerminals(this, controlPoints.length); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1)); - for (Point2D p : controlPoints) { + for (int i = 0; i < controlPoints.length; i++) { + Point2D p = controlPoints[i]; if (outlineMode) { g2d.setColor(theme.getOutlineColor()); g2d.drawRect((int) (p.getX() - lugWidth / 2), (int) (p.getY() - lugHeight / 2), lugWidth, lugHeight); } else { - g2d.setColor(TERMINAL_COLOR); + int finalI = i; + int groupIndex = IntStream.range(0, connectedTerminals.size()) + .filter(j -> connectedTerminals.get(j).contains(finalI)) + .findFirst().orElse(-1); + if (groupIndex < 0) { + g2d.setColor(TERMINAL_COLOR); + } else { + g2d.setColor(ISwitch.POLE_COLORS[groupIndex]); + } g2d.fillRect((int) (p.getX() - lugWidth / 2), (int) (p.getY() - lugHeight / 2), lugWidth, lugHeight); - g2d.setColor(TERMINAL_COLOR.darker()); + if (groupIndex < 0) { + g2d.setColor(TERMINAL_COLOR.darker()); + } else { + g2d.setColor(ISwitch.POLE_COLORS[groupIndex].darker()); + } g2d.drawRect((int) (p.getX() - lugWidth / 2), (int) (p.getY() - lugHeight / 2), lugWidth, lugHeight); } } - -// g2d.setFont(project.getFont()); -// g2d.setColor(getLabelColor()); -// -// double labelOffsetX = 0; -// double labelOffsetY = 0; -// if (getValue() == SlideSwitchType.SPDT) { -// int rowSpacing = (int) getRowSpacing().convertToPixels(); -// if (getOrientation() == OrientationHV.VERTICAL) { -// labelOffsetY = -rowSpacing / 2; -// } else { -// labelOffsetX = -rowSpacing / 2; -// } -// } -// -// Rectangle bounds = body[0].getBounds(); -// StringUtils.drawCenteredText(g2d, getName(), bounds.getCenterX() + labelOffsetX, -// bounds.getCenterY() + labelOffsetY, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); } public Shape[] getBody() { @@ -411,14 +419,7 @@ public class SlideSwitch extends AbstractTransparentComponent i @Override public int getPositionCount() { - switch (switchType) { - case SPDT: - case DPDT: - return 2; - case DP3T: - return 3; - } - return 2; + return switchType.getPositionCount(); } @Override @@ -428,12 +429,43 @@ public class SlideSwitch extends AbstractTransparentComponent i @Override public boolean arePointsConnected(int index1, int index2, int position) { + // Method assumes index1 < index2 switch (switchType) { case SPDT: - return (index1 == position) && (index2 - index1 == 1); + // For SPDT, index 1 is the common (center) terminal + // Position 1: connects terminals 0-1 + // Position 2: connects terminals 1-2 + if (position == 0) { + return index1 == 0 && index2 == 1; + } else if (position == 1) { + return index1 == 1 && index2 == 2; + } + return false; case DPDT: + // For DPDT, indices 1 and 4 are the common (center) terminals + // Position 1: connects terminals 0-1 and 3-4 + // Position 2: connects terminals 1-2 and 4-5 + if (position == 0) { + return (index1 == 0 && index2 == 1) || (index1 == 3 && index2 == 4); + } else if (position == 1) { + return (index1 == 1 && index2 == 2) || (index1 == 4 && index2 == 5); + } + return false; case DP3T: - return (index1 == position * 2 || index1 == position * 2 + 1) && (index2 - index1 == 2); + // For DP3T, following the schematic: + // Position 1: A1-A2 and B1-B2 (0-1 and 4-5) + // Position 2: A2-A3 and B2-B3 (1-2 and 5-6) + // Position 3: A3-A4 and B3-B4 (2-3 and 6-7) + if (position == 0) { // Position 1 + return (index1 == 0 && index2 == 1) || // A1-A2 + (index1 == 4 && index2 == 5); // B1-B2 + } else if (position == 1) { // Position 2 + return (index1 == 1 && index2 == 2) || // A2-A3 + (index1 == 5 && index2 == 6); // B2-B3 + } else if (position == 2) { // Position 3 + return (index1 == 2 && index2 == 3) || // A3-A4 + (index1 == 6 && index2 == 7); // B3-B4 + } } return false; } @@ -465,6 +497,30 @@ public class SlideSwitch extends AbstractTransparentComponent i this.bracketColor = bracketColor; } + @DynamicEditableProperty(source = SlideSwitchPositionPropertyValueSource.class) + @EditableProperty(name = "Selected Position") + @Override + public Integer getSelectedPosition() { + return selectedPosition; + } + + public void setSelectedPosition(Integer selectedPosition) { + this.selectedPosition = selectedPosition; + } + + @EditableProperty(name = "Highlight Connected") + @Override + public Boolean getHighlightConnectedTerminals() { + if (highlightConnectedTerminals == null) { + highlightConnectedTerminals = false; + } + return highlightConnectedTerminals; + } + + public void setHighlightConnectedTerminals(Boolean highlightConnectedTerminals) { + this.highlightConnectedTerminals = highlightConnectedTerminals; + } + @Override public Rectangle2D getCachingBounds() { int margin = 20; diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/SlideSwitchPositionPropertyValueSource.java b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/SlideSwitchPositionPropertyValueSource.java new file mode 100644 index 00000000..64c64cf9 --- /dev/null +++ b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/SlideSwitchPositionPropertyValueSource.java @@ -0,0 +1,41 @@ +package org.diylc.components.electromechanical; + +import org.diylc.common.PropertyWrapper; +import org.diylc.components.guitar.LeverSwitch; +import org.diylc.core.AbstractDynamicPropertyValueSource; +import org.diylc.core.IDIYComponent; +import org.diylc.core.IDynamicPropertySource; +import org.diylc.core.ISwitch; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public class SlideSwitchPositionPropertyValueSource extends AbstractDynamicPropertyValueSource { + + @Override + public List getAvailableValues() { + if (properties == null) { + return List.of(); + } + Optional optionalPropertyWrapper = this.properties.stream().filter(p -> { + try { + return p.getGetter().getName().equals("getValue"); + } catch (NoSuchMethodException e) { + return false; + } + }).findFirst(); + if (optionalPropertyWrapper.isEmpty()) { + return List.of(); + } + SlideSwitchType + switchType = (SlideSwitchType) optionalPropertyWrapper.get().getValue(); + int positionCount = switchType.getPositionCount(); + List res = new ArrayList<>(); + res.add(null); + for (int i = 0; i < positionCount; i++) { + res.add(i); + } + return res; + } +} diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/SlideSwitchType.java b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/SlideSwitchType.java index 61f93018..86e627dc 100644 --- a/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/SlideSwitchType.java +++ b/diylc/diylc-library/src/main/java/org/diylc/components/electromechanical/SlideSwitchType.java @@ -2,16 +2,15 @@ package org.diylc.components.electromechanical; public enum SlideSwitchType { - SPDT, DPDT, DP3T; + SPDT(2), DPDT(2), DP3T(3); - @Override - public String toString() { - String name = name(); - if (name.startsWith("_")) - name = name.substring(1); - name = name.replace("_", " "); - name = name.replace("mustang", ""); - name = name.replace("off", " (Center OFF)"); - return name; + private final int positionCount; + + SlideSwitchType(int positionCount) { + this.positionCount = positionCount; } -} \ No newline at end of file + + public int getPositionCount() { + return positionCount; + } +} 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 0fc7420f..253ae23d 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 @@ -129,8 +129,6 @@ public class Freeway3x3_03 extends AbstractTransparentComponent implements double[] xOffsets = getXOffsetsPx(); double[] yOffsets = getYOffsetsPx(); - - Rectangle2D rect = new Rectangle2D.Double(x - xOffsets[0], y - yOffsets[0], bounds2d.getWidth(), bounds2d.getHeight()); diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/Freeway3x4_03SwitchPositionPropertyValueSource.java b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/Freeway3x4_03SwitchPositionPropertyValueSource.java index 5efd2866..b939b819 100644 --- a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/Freeway3x4_03SwitchPositionPropertyValueSource.java +++ b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/Freeway3x4_03SwitchPositionPropertyValueSource.java @@ -1,6 +1,7 @@ package org.diylc.components.guitar; import org.diylc.common.PropertyWrapper; +import org.diylc.core.AbstractDynamicPropertyValueSource; import org.diylc.core.IDIYComponent; import org.diylc.core.IDynamicPropertySource; import org.diylc.core.ISwitch; @@ -9,20 +10,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; -public class Freeway3x4_03SwitchPositionPropertyValueSource implements IDynamicPropertySource { - - private List properties; - private IDIYComponent component; - - @Override - public void setProperties(List properties) { - this.properties = properties; - } - - @Override - public void setComponent(IDIYComponent component) { - this.component = component; - } +public class Freeway3x4_03SwitchPositionPropertyValueSource extends + AbstractDynamicPropertyValueSource { @Override public List getAvailableValues() { @@ -34,15 +23,4 @@ public class Freeway3x4_03SwitchPositionPropertyValueSource implements IDynamicP } return res; } - - @Override - public String getDisplayValue(Object value) { - if (value == null) { - return "None"; - } - if (component instanceof ISwitch sw) { - return sw.getPositionName((Integer)value); - } - return "#" + (((Integer)value) + 1); - } } diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/LeverSwitchPositionPropertyValueSource.java b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/LeverSwitchPositionPropertyValueSource.java index f507d02e..24232f20 100644 --- a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/LeverSwitchPositionPropertyValueSource.java +++ b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/LeverSwitchPositionPropertyValueSource.java @@ -1,26 +1,14 @@ package org.diylc.components.guitar; import org.diylc.common.PropertyWrapper; +import org.diylc.core.AbstractDynamicPropertyValueSource; import org.diylc.core.IDIYComponent; import org.diylc.core.IDynamicPropertySource; import org.diylc.core.ISwitch; import java.util.*; -public class LeverSwitchPositionPropertyValueSource implements IDynamicPropertySource { - - private List properties; - private IDIYComponent component; - - @Override - public void setProperties(List properties) { - this.properties = properties; - } - - @Override - public void setComponent(IDIYComponent component) { - this.component = component; - } +public class LeverSwitchPositionPropertyValueSource extends AbstractDynamicPropertyValueSource { @Override public List getAvailableValues() { @@ -47,15 +35,4 @@ public class LeverSwitchPositionPropertyValueSource implements IDynamicPropertyS } return res; } - - @Override - public String getDisplayValue(Object value) { - if (value == null) { - return "None"; - } - if (component instanceof ISwitch sw) { - return sw.getPositionName((Integer)value); - } - return "#" + (((Integer)value) + 1); - } } diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/SchallerMegaSwitchPositionPropertyValueSource.java b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/SchallerMegaSwitchPositionPropertyValueSource.java index b9b10375..11bd7235 100644 --- a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/SchallerMegaSwitchPositionPropertyValueSource.java +++ b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/SchallerMegaSwitchPositionPropertyValueSource.java @@ -1,6 +1,7 @@ package org.diylc.components.guitar; import org.diylc.common.PropertyWrapper; +import org.diylc.core.AbstractDynamicPropertyValueSource; import org.diylc.core.IDIYComponent; import org.diylc.core.IDynamicPropertySource; import org.diylc.core.ISwitch; @@ -9,20 +10,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; -public class SchallerMegaSwitchPositionPropertyValueSource implements IDynamicPropertySource { - - private List properties; - private IDIYComponent component; - - @Override - public void setProperties(List properties) { - this.properties = properties; - } - - @Override - public void setComponent(IDIYComponent component) { - this.component = component; - } +public class SchallerMegaSwitchPositionPropertyValueSource extends + AbstractDynamicPropertyValueSource { @Override public List getAvailableValues() { @@ -49,15 +38,4 @@ public class SchallerMegaSwitchPositionPropertyValueSource implements IDynamicPr } return res; } - - @Override - public String getDisplayValue(Object value) { - if (value == null) { - return "None"; - } - if (component instanceof ISwitch sw) { - return sw.getPositionName((Integer)value); - } - return "#" + (((Integer)value) + 1); - } } diff --git a/diylc/diylc-library/src/test/java/org/diylc/netlist/SlideSwitchTests.java b/diylc/diylc-library/src/test/java/org/diylc/netlist/SlideSwitchTests.java index e924096a..7ccf0eba 100644 --- a/diylc/diylc-library/src/test/java/org/diylc/netlist/SlideSwitchTests.java +++ b/diylc/diylc-library/src/test/java/org/diylc/netlist/SlideSwitchTests.java @@ -5,7 +5,7 @@ import org.junit.Test; import org.diylc.components.electromechanical.SlideSwitch; import org.diylc.components.electromechanical.SlideSwitchType; -public abstract class SlideSwitchTests extends AbstractSwitchTests { +public class SlideSwitchTests extends AbstractSwitchTests { @Test public void testSlideSwitchSPDT() { @@ -19,7 +19,10 @@ public abstract class SlideSwitchTests extends AbstractSwitchTests { public void testSlideSwitchDPDT() { SlideSwitch slideSwitch = new SlideSwitch(); slideSwitch.setValue(SlideSwitchType.DPDT); - String[] validCombinations = new String[] {"0,0,2", "0,1,3", "1,2,4", "1,3,5"}; + String[] validCombinations = new String[] { + "0,0,1", "0,3,4", // Position 1 connections + "1,1,2", "1,4,5" // Position 2 connections + }; testSwitch(slideSwitch, validCombinations); } @@ -27,7 +30,11 @@ public abstract class SlideSwitchTests extends AbstractSwitchTests { public void testSlideSwitchDP3T() { SlideSwitch slideSwitch = new SlideSwitch(); slideSwitch.setValue(SlideSwitchType.DP3T); - String[] validCombinations = new String[] {"0,0,2", "0,1,3", "1,2,4", "1,3,5", "2,4,6", "2,5,7"}; + String[] validCombinations = new String[] { + "0,0,1", "0,4,5", // Position 1 connections + "1,1,2", "1,5,6", // Position 2 connections + "2,2,3", "2,6,7" // Position 3 connections + }; testSwitch(slideSwitch, validCombinations); } }