diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/schematic/SchematicWire.java b/diylc/diylc-library/src/main/java/org/diylc/components/schematic/SchematicWire.java index 12bd9a6e..e77300ba 100644 --- a/diylc/diylc-library/src/main/java/org/diylc/components/schematic/SchematicWire.java +++ b/diylc/diylc-library/src/main/java/org/diylc/components/schematic/SchematicWire.java @@ -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 implements IContinuit List 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 implements IContinuit path.lineTo(points.get(i).getX(), points.get(i).getY()); } g2d.draw(path); + g2d.setComposite(oldComposite); } @Override diff --git a/diylc/diylc-swing/src/main/java/org/diylc/swing/plugins/schematic/SchematicTabPlugin.java b/diylc/diylc-swing/src/main/java/org/diylc/swing/plugins/schematic/SchematicTabPlugin.java index 92ad1ea5..d8770fbc 100644 --- a/diylc/diylc-swing/src/main/java/org/diylc/swing/plugins/schematic/SchematicTabPlugin.java +++ b/diylc/diylc-swing/src/main/java/org/diylc/swing/plugins/schematic/SchematicTabPlugin.java @@ -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; } diff --git a/diylc/docs/schematic_view_plan.md b/diylc/docs/schematic_view_plan.md index f03ff5dd..fb0eeb2d 100644 --- a/diylc/docs/schematic_view_plan.md +++ b/diylc/docs/schematic_view_plan.md @@ -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.