mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-13 10:42:09 +10:00
Controllers (#1080)
* initial * more components * fixes * Update TreePanel.java * fix boost converter * Improve wrapping of component names * Update ULN2003Driver.java * Update NRF24L01Transceiver.java * imp * updates * improvements * more components * arduino * uno * icon * cleanup * mega * mega * improveent * nano * esp boards * esp * esp32 * esp32 * Update ESP8266NodeMCU.java * d1 * Update WemosD1Mini.java * pi * consolidate esp32 * pi pico updates * pi zero * Update RaspberryPiZero.java * pi pico * cleanup * pi improvements * consolidate pins * antenna consolidation * improve solder pads * teensy * headers * teensy fix, test cleanup * s3 * Update ESP32DevKit.java * usb standardization * pico w * button standardization * arduino improvements * Update AbstractMakerBoard.java * Update RaspberryPiZero.java * Update RaspberryPi.java * pi 3 * pi 5 improvements * Update RaspberryPiZero.java * fix tests * esp pinout fix * Update ESP32DevKit.java * pin name improvements * Create tier-1-modern-boards.md * new versions * pinouts * nano improvements * sanitize node names * label improvements * minima fixes * arduino uno labels * nano labels * Update ArduinoNano.java * mega * mega * comment out future stuff * release prep * Update RaspberryPiPico.java * Refactor abstract class * labeling improvement * label offset fixes * Update Teensy.java * consolidate tests * micro variants * Update RaspberryPi.java * displays tweaks * display improvements * neopix * displays * improvements * led matrix * strip * led bar graph * jewel * tft * tft * Update maker-peripherals.md * nokia * led bar * labels * tft * cleanup * oled * cleanup * display enhancement * displays * neopixel * displays * displays * new tft * displays * icon * variants * 2-digit 0.56 inch 7 segment * Added ability to hide component categories in the component tree and toolbar from the Config menu * led bar * Update variants.xml * color selection for bar graph * Added 1.8" sd * tft fixes * Update WS2812BRing.java * neopixel improvements * netlist and node name improvements * oled tweak * cleanup * mockito fix --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -74,6 +74,17 @@
|
||||
<version>5.11.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- Subclass mock maker, selected in src/test/resources/mockito-extensions. Mockito 5
|
||||
defaults to the inline maker, which attaches a Java agent to the running JVM; that
|
||||
attachment fails outright on some CI JDKs and is deprecated since Java 21. Every type
|
||||
mocked in these tests is an interface, which the subclass maker handles without an
|
||||
agent. -->
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-subclass</artifactId>
|
||||
<version>5.11.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Local dependencies from lib folder -->
|
||||
<dependency>
|
||||
|
||||
@@ -117,5 +117,11 @@ public enum EventType {
|
||||
* Called when the mouse hovers over sticky control points (nodes) in tooltip mode.
|
||||
* Parameters: String text (semicolon-separated component and node names, or null), Point point.
|
||||
*/
|
||||
NODE_NAME_HOVER_TOOLTIP;
|
||||
NODE_NAME_HOVER_TOOLTIP,
|
||||
/**
|
||||
* Called when the set of enabled component categories changes. The first parameter is a
|
||||
* <code>Set<String></code> of disabled category names. All categories not included are
|
||||
* enabled.
|
||||
*/
|
||||
COMPONENT_CATEGORIES_CHANGED;
|
||||
}
|
||||
|
||||
@@ -83,6 +83,7 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP
|
||||
public static final String HARDWARE_ACCELERATION = "hardwareAcceleration";
|
||||
public static final String EXTRA_SPACE_KEY = "extraSpace";
|
||||
public static final String FAVORITES_KEY = "favorites";
|
||||
public static final String DISABLED_CATEGORIES_KEY = "disabledComponentCategories";
|
||||
public static final String RENUMBER_ON_PASTE_KEY = "renumberOnPaste";
|
||||
public static final String RULER_IN_SUBDIVISION_KEY = "rulerInSubdivision";
|
||||
public static final String CACHING_ENABLED_KEY = "cachingEnabled";
|
||||
@@ -213,6 +214,20 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP
|
||||
*/
|
||||
Map<String, List<ComponentType>> getComponentTypes();
|
||||
|
||||
/**
|
||||
* Returns the {@link ComponentType}s that should be offered to the user, i.e. the result of
|
||||
* {@link #getComponentTypes()} without the categories the user disabled. Intended for component
|
||||
* browsers; anything that needs to resolve an arbitrary component class must use
|
||||
* {@link #getComponentTypes()} instead.
|
||||
*/
|
||||
Map<String, List<ComponentType>> getVisibleComponentTypes();
|
||||
|
||||
boolean isCategoryEnabled(String category);
|
||||
|
||||
void setCategoryEnabled(String category, boolean enabled);
|
||||
|
||||
void resetCategoryVisibility();
|
||||
|
||||
/**
|
||||
* Draws project on the provided {@link Graphics2D}. If the provided filter is not null, it will
|
||||
* be used to filter the components that are shown.
|
||||
|
||||
@@ -411,6 +411,23 @@ public class NetlistBuilder {
|
||||
if (((IContinuity) c).arePointsConnected(i, j))
|
||||
connections.add(new Connection(c.getControlPoint(i), c.getControlPoint(j), z));
|
||||
}
|
||||
// Pins of one component that name the same rail are the same node: a board's eight ground
|
||||
// pins land on one plane, and grounding one of them must not leave the rest floating.
|
||||
// Switches are excluded because their connectivity depends on the position, which a name
|
||||
// cannot express -- a switch states it through ISwitch.arePointsConnected instead.
|
||||
if (!(c instanceof ISwitch)) {
|
||||
for (int i = 0; i < c.getControlPointCount() - 1; i++) {
|
||||
String rail = Node.railName(c.getControlPointNodeName(i));
|
||||
if (rail == null) {
|
||||
continue;
|
||||
}
|
||||
for (int j = i + 1; j < c.getControlPointCount(); j++) {
|
||||
if (rail.equals(Node.railName(c.getControlPointNodeName(j)))) {
|
||||
connections.add(new Connection(c.getControlPoint(i), c.getControlPoint(j), z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// handle switches
|
||||
if (ISwitch.class.isAssignableFrom(type.getInstanceClass())
|
||||
&& switchPositions.containsKey(c)) {
|
||||
|
||||
@@ -22,7 +22,10 @@
|
||||
package org.diylc.netlist;
|
||||
|
||||
import java.awt.geom.Point2D;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import org.diylc.core.ICommonNode;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
@@ -34,6 +37,10 @@ import org.diylc.core.IDIYComponent;
|
||||
*/
|
||||
public class Node implements Comparable<Node> {
|
||||
|
||||
/** Pin names that mark an absent connection, so repeats of them are not one net. */
|
||||
private static final Set<String> NON_NET_NAMES =
|
||||
new HashSet<String>(Arrays.asList("NC", "RSV"));
|
||||
|
||||
private IDIYComponent<?> component;
|
||||
private int pointIndex;
|
||||
|
||||
@@ -60,8 +67,9 @@ public class Node implements Comparable<Node> {
|
||||
* <code>MCU1.D11</code> rather than <code>MCU1.D11 (~, MOSI)</code>. The bare name identifies the
|
||||
* pin; everything in parentheses documents its alternate functions and only adds noise here.
|
||||
*
|
||||
* <p>A trailing disambiguator such as the <code>_1</code> in <code>GND_1</code> is deliberately
|
||||
* kept, because those mark genuinely different pins that a netlist has to tell apart.
|
||||
* <p>A trailing disambiguator such as the <code>_1</code> in <code>GND_1</code> is kept, so the
|
||||
* netlist can still say which pad a connection reached. Whether two such pins are the same
|
||||
* net is a separate question, answered by {@link #railName(String)}.
|
||||
*
|
||||
* @param nodeName raw name from {@link IDIYComponent#getControlPointNodeName(int)}
|
||||
* @return the sanitized name, or null if the raw name was null
|
||||
@@ -75,6 +83,28 @@ public class Node implements Comparable<Node> {
|
||||
// Never let sanitizing leave a pin nameless
|
||||
return sanitized.isEmpty() ? nodeName.trim() : sanitized;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rail a pin belongs to: its sanitized name with a trailing <code>_1</code>, <code>_2</code>
|
||||
* disambiguator removed, so <code>GND_1</code> and <code>GND_2</code> report the same rail.
|
||||
*
|
||||
* <p>Only a numeric suffix is dropped. An underscore does three unrelated jobs across the
|
||||
* pinouts in this library: it disambiguates a repeated rail, it namespaces a connector's signals
|
||||
* (<code>ETH_TX-</code>, <code>USB_D+</code>), and it qualifies a genuinely separate net
|
||||
* (<code>MISO_16U2</code>, <code>3V3_EN</code>). Cutting at the first underscore instead would
|
||||
* report an Ethernet header as one rail.
|
||||
*
|
||||
* @param nodeName raw name from {@link IDIYComponent#getControlPointNodeName(int)}
|
||||
* @return the rail name, or null if the pin has no name or names no net at all
|
||||
*/
|
||||
public static String railName(String nodeName) {
|
||||
String sanitized = sanitizeNodeName(nodeName);
|
||||
if (sanitized == null || sanitized.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
String rail = sanitized.replaceAll("_\\d+$", "");
|
||||
return NON_NET_NAMES.contains(rail) ? null : rail;
|
||||
}
|
||||
|
||||
public Point2D getPoint2D() {
|
||||
return component.getControlPoint(pointIndex);
|
||||
|
||||
@@ -202,6 +202,14 @@ public class Presenter implements IPlugInPort {
|
||||
messageDispatcher.dispatchMessage(EventType.NODE_NAME_HOVER_TOOLTIP, null, null);
|
||||
}
|
||||
});
|
||||
|
||||
configManager.addConfigListener(IPlugInPort.DISABLED_CATEGORIES_KEY, new IConfigListener() {
|
||||
@Override
|
||||
public void valueChanged(String key, Object value) {
|
||||
messageDispatcher.dispatchMessage(EventType.COMPONENT_CATEGORIES_CHANGED,
|
||||
getDisabledCategories());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void installPlugin(Supplier<IPlugIn> plugInSupplier) {
|
||||
@@ -408,12 +416,58 @@ public class Presenter implements IPlugInPort {
|
||||
return projectFileManager.isModified();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Set<String> getDisabledCategories() {
|
||||
List<String> list = (List<String>) configManager.readObject(
|
||||
IPlugInPort.DISABLED_CATEGORIES_KEY, new ArrayList<String>());
|
||||
if (list == null) {
|
||||
return new HashSet<String>();
|
||||
}
|
||||
return new HashSet<String>(list);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Map<String, List<ComponentType>> getComponentTypes() {
|
||||
return ComponentProcessor.getInstance().getComponentTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<ComponentType>> getVisibleComponentTypes() {
|
||||
Set<String> disabled = getDisabledCategories();
|
||||
Map<String, List<ComponentType>> all = getComponentTypes();
|
||||
Map<String, List<ComponentType>> visible = new HashMap<String, List<ComponentType>>();
|
||||
for (Map.Entry<String, List<ComponentType>> entry : all.entrySet()) {
|
||||
if (!disabled.contains(entry.getKey())) {
|
||||
visible.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
return visible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCategoryEnabled(String category) {
|
||||
return !getDisabledCategories().contains(category);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCategoryEnabled(String category, boolean enabled) {
|
||||
Set<String> disabled = getDisabledCategories();
|
||||
if (enabled) {
|
||||
disabled.remove(category);
|
||||
} else {
|
||||
disabled.add(category);
|
||||
}
|
||||
List<String> list = new ArrayList<String>(disabled);
|
||||
Collections.sort(list);
|
||||
configManager.writeValue(IPlugInPort.DISABLED_CATEGORIES_KEY, list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetCategoryVisibility() {
|
||||
configManager.writeValue(IPlugInPort.DISABLED_CATEGORIES_KEY, new ArrayList<String>());
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private boolean isComponentVisible(IDIYComponent<?> component) {
|
||||
ComponentType componentType =
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -496,5 +496,85 @@
|
||||
</changes>
|
||||
<url>https://github.com/bancika/diy-layout-creator/releases</url>
|
||||
</org.diylc.appframework.update.Version>
|
||||
<org.diylc.appframework.update.Version>
|
||||
<versionNumber>
|
||||
<major>6</major>
|
||||
<minor>7</minor>
|
||||
<build>0</build>
|
||||
</versionNumber>
|
||||
<releaseDate>2026-10-11 00:00:00.000 CET</releaseDate>
|
||||
<name></name>
|
||||
<changes>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>NEW_FEATURE</changeType>
|
||||
<description>7-Segment Display - 1-digit 0.56 inch, 2-digit 0.56 inch, 4-digit in 0.36 inch and 0.56 inch, and TM1637 driver module</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>NEW_FEATURE</changeType>
|
||||
<description>Character LCD - 16x2 and 20x4, with I2C backpack or 16-pin parallel interface</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>NEW_FEATURE</changeType>
|
||||
<description>LED Bar Graph - 4, 5, 6, 8, 10 and 12 segments</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>NEW_FEATURE</changeType>
|
||||
<description>LED Matrix (MAX7219) - single 8x8, compact 8x8, 4-in-1 32x8, 8-in-1 64x8</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>NEW_FEATURE</changeType>
|
||||
<description>NeoPixel Breakout (WS2812B) - single LED</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>NEW_FEATURE</changeType>
|
||||
<description>NeoPixel Jewel (WS2812B) - 7 LEDs</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>NEW_FEATURE</changeType>
|
||||
<description>NeoPixel Panel (WS2812B) - 8x8, 64 LEDs</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>NEW_FEATURE</changeType>
|
||||
<description>NeoPixel Ring (WS2812B) - 12, 16 and 24 LEDs</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>NEW_FEATURE</changeType>
|
||||
<description>NeoPixel Stick (WS2812B) - 8 LEDs</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>NEW_FEATURE</changeType>
|
||||
<description>NeoPixel Strip (WS2812B) - 30, 60 and 144 LEDs per meter, up to 144 LEDs</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>NEW_FEATURE</changeType>
|
||||
<description>Nokia 5110 LCD (PCD8544)</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>NEW_FEATURE</changeType>
|
||||
<description>OLED Display - 0.96 inch SSD1306, 0.91 inch SSD1306, 1.3 inch SH1106, in I2C, 7-pin SPI and 6-pin SPI</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>NEW_FEATURE</changeType>
|
||||
<description>TFT Display - 2.8 inch and 2.4 inch ILI9341, 1.8 inch and 0.96 inch ST7735, 1.54 inch ST7789, 1.28 inch round GC9A01</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>NEW_FEATURE</changeType>
|
||||
<description>Added ability to hide component categories in the component tree and toolbar from the Config menu</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>IMPROVEMENT</changeType>
|
||||
<description>Bill of Materials now lists the selected variant of microcontroller boards and displays, so different versions of the same board are no longer merged into a single row</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>BUG_FIX</changeType>
|
||||
<description>4-pin Jumbo Tube Socket - the two filament pins are now labeled F1 and F2 instead of both being labeled F, so they no longer read as the same node</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>IMPROVEMENT</changeType>
|
||||
<description>Netlists now treat the repeated supply pins of a microcontroller or display board as one node, so grounding a single GND pin no longer leaves the others floating</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
</changes>
|
||||
<url>https://github.com/bancika/diy-layout-creator/releases</url>
|
||||
</org.diylc.appframework.update.Version>
|
||||
</a>
|
||||
</java.util.Arrays_-ArrayList>
|
||||
|
||||
@@ -48,4 +48,41 @@ public class NodeNameTest {
|
||||
Assert.assertEquals("(only annotation)", Node.sanitizeNodeName("(only annotation)"));
|
||||
Assert.assertNull(Node.sanitizeNodeName(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void railNameDropsOnlyANumericDisambiguator() {
|
||||
Assert.assertEquals("GND", Node.railName("GND_1"));
|
||||
Assert.assertEquals("GND", Node.railName("GND_12"));
|
||||
Assert.assertEquals("GND", Node.railName("GND"));
|
||||
Assert.assertEquals("GND", Node.railName("GND (Pin 6)"));
|
||||
Assert.assertEquals("+5V", Node.railName("+5V_2"));
|
||||
// the annotation is stripped before the disambiguator, so an annotated rail still resolves
|
||||
Assert.assertEquals("3.3V", Node.railName("3.3V_2 (250mA)"));
|
||||
Assert.assertEquals("GND", Node.railName("GND_4 (Mid)"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void railNameKeepsNonNumericQualifiers() {
|
||||
// namespaced connector signals
|
||||
Assert.assertEquals("ETH_TX-", Node.railName("ETH_TX-"));
|
||||
Assert.assertEquals("USB_D+", Node.railName("USB_D+"));
|
||||
// qualifiers that name a separate net
|
||||
Assert.assertEquals("MISO_16U2", Node.railName("MISO_16U2"));
|
||||
Assert.assertEquals("3V3_EN", Node.railName("3V3_EN"));
|
||||
// a bare trailing digit is part of the name, not a disambiguator
|
||||
Assert.assertEquals("GP1", Node.railName("GP1"));
|
||||
Assert.assertEquals("GND1", Node.railName("GND1"));
|
||||
// digits that are not at the end are part of the name too: the 16U2 bridge's ground and 5V
|
||||
// are separate nets from the board's own, and USB_5V is a connector pin, not a 5V rail
|
||||
Assert.assertEquals("GND_16U2", Node.railName("GND_16U2"));
|
||||
Assert.assertEquals("5V_16U2", Node.railName("5V_16U2"));
|
||||
Assert.assertEquals("USB_5V", Node.railName("USB_5V"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void railNameRejectsPinsThatNameNoNet() {
|
||||
Assert.assertNull(Node.railName("NC_1"));
|
||||
Assert.assertNull(Node.railName("RSV_2"));
|
||||
Assert.assertNull(Node.railName(null));
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
member-accessor-reflection
|
||||
@@ -0,0 +1 @@
|
||||
mock-maker-subclass
|
||||
Reference in New Issue
Block a user