mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-13 10:42:09 +10:00
Split trace layer
This commit is contained in:
@@ -5,7 +5,8 @@ that copper on one side of the board can be hidden, locked or selected without t
|
||||
Two-sided boards, the Underside Display editing and the Via made one trace layer too coarse: a user
|
||||
routing the bottom in the Underside Display wants to lock the top, and the other way round.
|
||||
|
||||
Status: planned, nothing built yet.
|
||||
Status: done. Core, library and swing tests pass; the regression suite has not been run, and no
|
||||
change is expected there (section 5).
|
||||
|
||||
## 1. Background
|
||||
|
||||
@@ -37,6 +38,8 @@ Status: planned, nothing built yet.
|
||||
| The Visible shortcuts are renumbered to follow the menu: Ctrl+1 Chassis, Ctrl+2 Board, Ctrl+3 Bottom Traces, Ctrl+4 Top Traces, Ctrl+5 Component, Ctrl+6 Wiring, Ctrl+7 Text | Shortcuts that follow the menu order are easier to learn than a new one added out of order. Only the shortcuts move; the saved layer ids do not, so files are unaffected. |
|
||||
| New ids: Bottom Traces `31`, Top Traces `32` (`TRACE * 10 + PCBLayer.getId()`) | They cannot collide with a z-order. Reusing `3` for one side would make an older DIYLC treat a file with only one side hidden as all traces hidden. |
|
||||
| `3` stays as the legacy id meaning both trace layers, and the saved sets keep the invariant "`3` is present exactly when `31` and `32` both are" | A file saved with both sides hidden or locked still hides or locks all traces in an older DIYLC, and an older DIYLC that unhides or unlocks Trace is understood by the new one (section 4). |
|
||||
| The ids and the set rules live in `org.diylc.core.LayerIds`; which layer a component is on lives in `org.diylc.presenter.ComponentLayers` | `Project` applies the rules on load and must not depend on the presenter package; layer membership needs the z-order from `ComponentProcessor`. |
|
||||
| Two set rules, not one: `migrateLoaded` after a load, `syncLegacy` after a change | "Both sides set, no `3`" means opposite things in the two cases: written by an older version that cleared Trace, or just set by the user. |
|
||||
| Copper with a side is on the layer of that side; the deprecated inner layers count as Bottom | `IPCBLayerComponent.getBoardSide()` already maps them that way. |
|
||||
| A Trace-band component that reports layer id `0` is on both trace layers: a PTH `SolderPad`, and `Via`, `Eyelet` and `Turret`, which implement `ILayeredComponent` to say so. A composite whose z-order falls in the Trace band is on both as well | Layer id `0` already means "every layer" to continuity, and the three go through the board. A composite may hold copper of both sides. Core names no concrete component. |
|
||||
| Every other Trace-band component is on the layer of `IBoardSideComponent.sideOf`, so a component without a side, such as `Jumper`, is on Top Traces | `sideOf` already treats a component without a side as top, the same rule the rendering uses. A jumper sits on top of the board: locking Bottom Traces to work on the top must leave it movable. |
|
||||
@@ -48,22 +51,23 @@ Status: planned, nothing built yet.
|
||||
|
||||
### diylc-core
|
||||
|
||||
- `org.diylc.presenter.ComponentLayers` (new, not in `Presenter`, which stays lean):
|
||||
- constants `BOTTOM_TRACES = 31`, `TOP_TRACES = 32`, and `LEGACY_TRACES = IDIYComponent.TRACE`;
|
||||
- `Set<Integer> getLayers(IDIYComponent<?>)`: the rounded z-order for everything outside the
|
||||
Trace band; inside it, both trace ids for layer id `0` and for a composite, otherwise the id
|
||||
of `IBoardSideComponent.sideOf`;
|
||||
- `isHidden(Project, component)` (all its layers hidden), `isLocked(Project, component)` (any of
|
||||
its layers locked) and `isOnLayer(component, layerId)` for Select All;
|
||||
- `normalize(Set<Integer>)`, which applies the invariant of section 4 and is used both after
|
||||
loading and after every change.
|
||||
- `org.diylc.core.LayerIds` (new): `LEGACY_TRACES = IDIYComponent.TRACE`, `BOTTOM_TRACES = 31`,
|
||||
`TOP_TRACES = 32`, `migrateLoaded(Set<Integer>)` for a set read from a file and
|
||||
`syncLegacy(Set<Integer>)` for a set just changed (section 4).
|
||||
- `org.diylc.presenter.ComponentLayers` (new, not in `Presenter`, which stays lean): the layer of a
|
||||
component is the rounded z-order outside the Trace band; inside it, both trace layers for layer
|
||||
id `0` and for a composite, otherwise the layer of `IBoardSideComponent.sideOf`. It answers
|
||||
`isHidden(hiddenLayers, component)` (all its layers hidden), `isLocked(lockedLayers, component)`
|
||||
(any of its layers locked) and `isOnLayer(component, layerId)` for Select All, without
|
||||
allocating, since drawing asks for every component on every repaint.
|
||||
- `Presenter.isComponentVisible`, `isComponentLayerLocked`, `selectAll(int)` and
|
||||
`GroupAndLockIndex.isLocked` call the helper. Internal types without a descriptor stay visible
|
||||
and unlocked, as today.
|
||||
- `Presenter.setLayerLocked` and `setLayerVisibility` call `normalize` on the changed set.
|
||||
- `Project.readResolve()` (new) normalizes `lockedLayers` and `hiddenLayers` whenever XStream
|
||||
loads a project, so the migration does not depend on which code path opened the file. XStream
|
||||
calls `readResolve` on any class that declares it.
|
||||
- `Presenter.setLayerLocked` and `setLayerVisibility` call `syncLegacy` on the changed set; given
|
||||
the legacy id `3`, they change both trace layers.
|
||||
- `Project.readResolve()` (new) runs `migrateLoaded` on `lockedLayers` and `hiddenLayers`
|
||||
whenever XStream loads a project, so the migration does not depend on which code path opened
|
||||
the file. XStream calls `readResolve` on any class that declares it.
|
||||
- `Via`, `Eyelet` and `Turret` (diylc-library) implement `ILayeredComponent` with `getLayerId()`
|
||||
returning `0`. Continuity does not change: a component that is not layered already counts as
|
||||
layer `0`.
|
||||
@@ -87,8 +91,8 @@ Status: planned, nothing built yet.
|
||||
Nothing about components changes, and no field is added, renamed or retyped. The only saved data
|
||||
involved are the two `Set<Integer>` fields of `Project`, whose type stays the same.
|
||||
|
||||
**Invariant.** In a saved set, `3` is present exactly when `31` and `32` both are. `normalize`
|
||||
enforces it:
|
||||
**Invariant.** In a saved set, `3` is present exactly when `31` and `32` both are. `migrateLoaded`
|
||||
applies the first three rows after a load, `syncLegacy` the last one after a change:
|
||||
|
||||
| Set as loaded or changed | Normalized | Why |
|
||||
| --- | --- | --- |
|
||||
@@ -117,22 +121,21 @@ clipboard carries components, not layer sets.
|
||||
|
||||
## 5. Verification
|
||||
|
||||
- `ComponentLayersTest`: a top and a bottom trace, an inner-layer trace (Bottom), PTH and NPTH
|
||||
pads, a `Via`, an `Eyelet`, a `Jumper` (Top Traces) and a Trace-band composite each land on the
|
||||
expected layers; a
|
||||
Component-band part keeps its z-order layer.
|
||||
- `ComponentLayersTest` (library): a top and a bottom trace, an inner-layer trace (Bottom), PTH and
|
||||
NPTH pads, a `Via`, an `Eyelet`, a `Jumper` (Top Traces) and a Trace-band composite each land on
|
||||
the expected layers; a Component-band part keeps its z-order layer.
|
||||
- Hidden and locked rules: a via is hidden only with both sides hidden and locked with either side
|
||||
locked; a jumper stays unlocked when only Bottom Traces is locked.
|
||||
- Continuity: the netlist of a project with vias, eyelets and turrets is unchanged.
|
||||
- `normalize`: each row of the table in section 4, and that a loaded project goes through it
|
||||
(`readResolve`), using an XML project with `<int>3</int>` in `hiddenLayers` and `lockedLayers`.
|
||||
- Presenter: Select All per trace layer; locking Bottom Traces and then moving a selected top trace
|
||||
to the bottom leaves it locked.
|
||||
- `LayerIdsTest` (core): each row of the table in section 4, and a project saved and loaded through
|
||||
XStream, so that `readResolve` runs.
|
||||
- `TraceLayerTests` (swing): Select All per trace layer; locking Bottom Traces locks the via but
|
||||
not the top trace or the jumper; both sides hidden keeps `3`; a top trace moved to the locked
|
||||
bottom through its Layer property is locked.
|
||||
- Regression suite: no image or netlist change expected, since no regression project hides or
|
||||
locks the Trace layer.
|
||||
|
||||
## 6. Next steps
|
||||
|
||||
1. Build the core helper with its tests, the `ILayeredComponent` declarations on `Via`, `Eyelet`
|
||||
and `Turret`, then the menu and the language keys.
|
||||
2. Changelog entry in the unreleased version, including the renumbered shortcuts.
|
||||
1. Check the menu, the shortcuts and the locking in the running app, and open a project saved with
|
||||
the old Trace layer hidden or locked.
|
||||
|
||||
Reference in New Issue
Block a user