Make schematic wires non-interactive by locking the WIRING layer

The schematic wrapper project now locks IDIYComponent.WIRING, so users
cannot select, drag or detach SchematicWire endpoints from symbols;
symbols stay on the COMPONENT layer and remain fully movable. SchematicWire
now forces an opaque composite while drawing so the locked-layer alpha
dimming does not fade the wires.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWD3QJxbr7RuEHxyFEYeEY
This commit is contained in:
Bane Stojkovic
2026-09-03 10:44:14 +02:00
parent 0ebd7e012a
commit fb3f1a82aa
3 changed files with 16 additions and 1 deletions
@@ -21,7 +21,9 @@
*/
package org.diylc.components.schematic;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Graphics2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
@@ -81,6 +83,11 @@ public class SchematicWire extends AbstractComponent<Void> implements IContinuit
List<Point2D> points = getRoutePoints();
if (points.size() < 2)
return;
// The schematic renders wires on a locked layer (so they cannot be selected or detached), but
// locked components are painted at reduced alpha. A wire must stay solid, so force an opaque
// composite for its own drawing and restore it afterwards.
Composite oldComposite = g2d.getComposite();
g2d.setComposite(AlphaComposite.SrcOver);
g2d.setColor(
componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: color);
@@ -91,6 +98,7 @@ public class SchematicWire extends AbstractComponent<Void> implements IContinuit
path.lineTo(points.get(i).getX(), points.get(i).getY());
}
g2d.draw(path);
g2d.setComposite(oldComposite);
}
@Override
@@ -43,6 +43,7 @@ import org.diylc.common.BadPositionException;
import org.diylc.common.EventType;
import org.diylc.common.IPlugIn;
import org.diylc.common.IPlugInPort;
import org.diylc.core.IDIYComponent;
import org.diylc.core.Project;
import org.diylc.core.SchematicView;
import org.diylc.presenter.ContinuityArea;
@@ -182,6 +183,10 @@ public class SchematicTabPlugin implements IPlugIn {
wrapper.setGridSpacing(view.getGridSpacing());
wrapper.setFont(layoutProject.getFont());
wrapper.getComponents().addAll(view.getComponents());
// Wires are auto-routed and must never be touched by the user: lock the whole WIRING layer so
// they cannot be selected, dragged or detached from symbols. Symbols live on the COMPONENT
// layer and stay fully movable.
wrapper.getLockedLayers().add(IDIYComponent.WIRING);
return wrapper;
}
+3 -1
View File
@@ -441,13 +441,15 @@ The schematic uses the **existing `DrawingManager` + `Presenter`** rendering pip
**diylc-swing**
- `SchematicTabPlugin` adds the Excel-style tab strip (**Layout | Schematic**) below the canvas. It owns a **second `Presenter` + `CanvasPlugin`**, so the schematic renders through the exact same `RulerScrollPane` — rulers, scroll bars, wheel/gesture zoom — as the layout canvas, with no extra controls. Selecting **Schematic** runs `SchematicSynchronizer` automatically and loads the resulting wrapper `Project` into the schematic presenter; selecting **Layout** swaps the visible scroll pane back. `CanvasPlugin.getCanvasScrollComponent()` exposes each scroll pane so the plugin can show/hide it.
- The wrapper project **locks the `WIRING` layer**, so `SchematicWire`s cannot be selected, dragged or detached from symbols; symbols (on the `COMPONENT` layer) stay movable. `SchematicWire.draw()` forces an opaque composite so the lock-alpha dimming does not fade the wires.
- `SchematicMenuPlugin` / `SchematicViewFrame` / `SchematicPanel` — a detached-window viewer (*Analyze → Schematic View…*) that renders the `SchematicView` through a private `DrawingManager` and adds PNG export. Independent of the tab.
Unit tests: `ManhattanRouterTest`, `GenericBoxSchematicFactoryTest` (library); `SchematicViewIntegrationTest` (swing — end-to-end build/sync/render).
### Not yet done (follow-ups)
- The schematic canvas is not **restricted** yet: selecting and nudging symbols is possible, but there is no explicit block on add / delete / paste / value-edit, and no shared undo integration with the layout history.
- Wires are fully inert (locked layer), but the schematic canvas is otherwise not **restricted**: there is no explicit block on add / delete / paste / value-edit of symbols, and no shared undo integration with the layout history.
- Symbols moved on the schematic do not drag their wires along; wires only re-route on the next switch to the Schematic tab (targeted re-routing on mouse release is a follow-up).
- Shared undo/redo integration with the layout history.
- Multi-section 1:N factories (`TubeSocket` → triode/pentode/duo-diode, `DIL_IC` → dual op-amps, switches).
- Smarter placement (true connection-density clustering) and crossing-aware routing.