mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-13 02:32:09 +10:00
192 lines
10 KiB
Markdown
192 lines
10 KiB
Markdown
# DIY Layout Creator — agent guidelines
|
|
|
|
DIYLC is a Java 21 Swing desktop application for drawing circuit layouts, schematics and guitar
|
|
wiring diagrams. It is a mature codebase (~690 source files) with long-standing conventions and a
|
|
file format that must stay readable by every version. **Consistency with the surrounding code
|
|
outweighs personal preference or modern idiom in every case.**
|
|
|
|
## The one rule that matters most
|
|
|
|
Before writing anything, read two or three existing files that do the same kind of job — the
|
|
neighbouring component, the sibling plugin, the analyzer next to the one you are touching — and
|
|
match them. Match their naming, their structure, their comment density, their ordering of members,
|
|
their choice of helper classes. If your change looks different from its neighbours, it is wrong even
|
|
if it compiles and works.
|
|
|
|
## Modules
|
|
|
|
Maven reactor rooted at `diylc/pom.xml`, version `6.4.0`, three modules with a strict one-way
|
|
dependency chain:
|
|
|
|
| Module | Contains | Depends on |
|
|
| --- | --- | --- |
|
|
| `diylc-core` | Domain model, `Presenter`, rendering pipeline, messaging, serialization, netlist engine, annotations | — |
|
|
| `diylc-library` | Concrete component classes, transformers, datasheets, legacy file parsers, component-aware analyzers | `diylc-core` |
|
|
| `diylc-swing` | Swing shell, plugins, dialogs, editors, `DIYLCStarter` | `diylc-core`, `diylc-library` |
|
|
|
|
**`diylc-core` must never reference a concrete component type.** It knows components only through
|
|
`IDIYComponent` and the annotations. If core logic seems to need knowledge of a specific component,
|
|
that knowledge belongs in `diylc-library` (an analyzer, a transformer, a parser) or is exposed
|
|
through a new interface in core that the component implements — look at
|
|
`org.diylc.core.gerber.IGerberComponentSimple` for the established shape of that escape hatch.
|
|
|
|
Component and plugin classes are discovered at runtime by Reflections scanning the `org.diylc`
|
|
package (`ComponentProcessor`). There is no registry to update when adding a component.
|
|
|
|
## Build and verify
|
|
|
|
Run from `diylc/`. Before reporting a change as done:
|
|
|
|
```bash
|
|
mvn -q -pl diylc-core -am compile # after core changes
|
|
mvn -q -pl diylc-library -am test # after library changes (~20s)
|
|
mvn -q -pl diylc-swing -am compile # after swing changes
|
|
mvn -q test # whole reactor, when the change spans modules
|
|
```
|
|
|
|
Compile the module you touched plus everything downstream of it, and run the unit tests of any
|
|
module whose tests could plausibly cover the change. Do not report success without having actually
|
|
run these — quote the failure if something breaks rather than describing it.
|
|
|
|
Do not run `mvn package`, `build-all-profiles.sh`, or the regression suite unless asked; they are
|
|
slow and the deployment build needs Docker and signing certificates. The regression suite is
|
|
described in `.claude/skills/regression-test/SKILL.md` and is worth *offering* whenever a change
|
|
affects rendering, serialization or netlist output.
|
|
|
|
The app runs from the `.run/DIYLCStarter.run.xml` IntelliJ configuration, which carries the required
|
|
`--add-opens`/`--add-exports` JVM flags. Copy them if launching from a terminal.
|
|
|
|
## Code style
|
|
|
|
The formatter is `eclipse-java-google-style.xml` (Google Java Style):
|
|
|
|
- **Two-space indent**, four spaces for continuation lines. No tabs.
|
|
- **100-column** line limit.
|
|
- Source encoding is **ISO-8859-1** — do not introduce non-ASCII characters into `.java` files. Use
|
|
Unicode escapes or the resource bundles instead.
|
|
- Braces on the same line; single-statement `if` bodies without braces are common in this codebase
|
|
and acceptable when you are matching the surrounding style.
|
|
- Imports: `java.*` first, then third-party, then `org.diylc.*`, separated by blank lines. No
|
|
wildcard imports.
|
|
- Constants are `UPPER_SNAKE_CASE`. Note that component appearance constants are deliberately
|
|
`public static` and **not** `final` (`BODY_COLOR`, `DEFAULT_WIDTH`), so they can be overridden at
|
|
runtime; keep that convention when adding new ones.
|
|
- `private static final Logger LOG = Logger.getLogger(TheClass.class);` — log4j 1.2, declared first
|
|
among the static members.
|
|
|
|
### Comments
|
|
|
|
Write comments only where the code cannot speak for itself: a non-obvious electrical or geometric
|
|
reason, a workaround for a library bug, a compatibility constraint, a unit or coordinate-system
|
|
assumption. Never restate the code.
|
|
|
|
```java
|
|
// BAD — adds nothing
|
|
// set the body color
|
|
g2d.setColor(bodyColor);
|
|
|
|
// GOOD — explains something the reader cannot infer
|
|
// the outer foil marking is drawn on the lead that is closer to the first control point,
|
|
// which is the convention printed on most film capacitors
|
|
```
|
|
|
|
Javadoc on public interfaces and abstract base classes in `diylc-core` is expected and should carry
|
|
`@author`. Concrete component classes generally carry no Javadoc — do not add it just to fill space.
|
|
|
|
### License header
|
|
|
|
**Every new source file starts with the GPL header**, copied verbatim from `HEADER.txt` (or from any
|
|
existing class), immediately followed by the `package` declaration with no blank line between the
|
|
closing `*/` and `package`. This applies to Java files in all three modules, including tests.
|
|
|
|
## File-format backward compatibility
|
|
|
|
DIYLC projects are XStream-serialized object graphs. Users open decade-old `.diy` files with the
|
|
current build, so **the serialized shape of a component class is a public contract**.
|
|
|
|
- Never rename or delete a serialized field, and never change its type. To replace one, keep the old
|
|
field, add a new one, mark the old accessors `@Deprecated`, and migrate lazily inside the new
|
|
getter. The canonical examples are `AbstractTransparentComponent.getAlpha()` (legacy `Byte alpha`
|
|
→ `Percentage alphaPercent`) and `Resistor.getPowerNew()` / `AbstractFilmCapacitor.getVoltageNew()`.
|
|
- Fields added to an existing class deserialize as `null` in old files. Every read path must tolerate
|
|
that, typically by defaulting in the getter rather than the constructor.
|
|
- Never rename or move a component class that has shipped. If a component genuinely must change
|
|
identity, an alias has to be registered on the XStream side and the legacy parsers in
|
|
`V1FileParser` / `V2FileParser` reviewed.
|
|
- Prefer **a `Version` property on a single component class over a new class per revision** when a
|
|
board or part gains a new variant. One class with a version enum keeps old files loading and keeps
|
|
the toolbox uncluttered.
|
|
- Any change here calls for a regression-suite run.
|
|
|
|
## Components
|
|
|
|
See `.claude/skills/add-component/SKILL.md` for the full recipe. The rules that apply to *editing*
|
|
existing components too:
|
|
|
|
- Extend the most specific abstract base that fits (`AbstractLeadedComponent`,
|
|
`AbstractRadialComponent`, `AbstractBoard`, `AbstractTransparentComponent`, …) rather than
|
|
reimplementing shared behaviour.
|
|
- Every editable property needs a matching getter/setter pair with `@EditableProperty` on the
|
|
**getter**; the property name is derived from the getter unless `name` is given.
|
|
- Drawing code must fetch strokes from `ObjectCache.getInstance().fetchBasicStroke(...)` /
|
|
`fetchZoomableStroke(...)` / `fetchStroke(...)` rather than allocating `new BasicStroke(...)`.
|
|
`draw()` runs on every repaint; do not allocate what can be cached or reused.
|
|
- Conductive areas are reported to the `IDrawingObserver` via
|
|
`startTrackingContinuityArea(true)` / `stopTrackingContinuityArea()`. Getting this wrong silently
|
|
breaks continuity checks and the netlist, so mirror a neighbouring component exactly.
|
|
- Rotation and mirroring live in an `IComponentTransformer` referenced from `@ComponentDescriptor`,
|
|
never inside the component.
|
|
- `drawIcon()` draws into a small fixed box for the toolbox; it is hand-drawn, not scaled from
|
|
`draw()`.
|
|
|
|
## Plugins and Swing
|
|
|
|
- Everything in the UI is an `IPlugIn` installed from `MainFrame` via `presenter.installPlugin(...)`.
|
|
- Plugins talk to the domain only through `IPlugInPort`, and react to domain changes by returning a
|
|
narrow `EnumSet<EventType>` from `getSubscribedEventTypes()`. Subscribe to as little as possible —
|
|
`PROJECT_MODIFIED` fires constantly.
|
|
- UI is injected through `ISwingUI.injectMenuAction` / `injectGUIComponent` / `injectSubmenu`, not by
|
|
reaching into frames directly.
|
|
- Persisted settings go through `ConfigurationManager.getInstance().readString/writeValue` with a
|
|
`String` key constant.
|
|
- User-visible strings are wrapped in `LangUtil.translate(...)`.
|
|
- Long-running work belongs on a background executor, never on the EDT.
|
|
|
|
## Testing
|
|
|
|
JUnit 4 under `src/test/java` in each module. Add tests where the project already tests: switching
|
|
logic, netlist and analyzer behaviour, datasheet parsing, core utilities. Component rendering and
|
|
user interaction are covered by the regression suite instead, not by unit tests. Test classes are
|
|
named `*Test` or `*Tests` and carry the license header like any other file.
|
|
|
|
## Git
|
|
|
|
**Do not commit or push.** Make the change in the working tree and stop; the maintainer reviews and
|
|
commits. If a commit is explicitly requested, commit only what was asked for, never to a remote, and
|
|
never `git add -A` over unrelated dirty files.
|
|
|
|
## Out of scope unless explicitly asked
|
|
|
|
- `diylc-server-api/` — PHP backend that runs in an isolated environment on diy-fever.com and cannot
|
|
be tested locally.
|
|
- `deploy/`, `build-all-profiles.sh`, packaging and notarization.
|
|
- `lib/` — vendored jars for dependencies not on Maven Central.
|
|
- `diylc-regression-data/reports/` — historical evidence, append-only.
|
|
- Bumping the project version in the POMs.
|
|
|
|
## Task recipes
|
|
|
|
Detailed, step-by-step recipes live in `.claude/skills/` and are worth reading in full before
|
|
starting the corresponding kind of work:
|
|
|
|
| Skill | Covers |
|
|
| --- | --- |
|
|
| `add-component` | Creating or substantially changing a component in `diylc-library` |
|
|
| `add-plugin` | Adding UI: plugins, menu actions, panels, dialogs, background tasks |
|
|
| `regression-test` | Running the end-to-end regression suite and reading its report |
|
|
|
|
## Reference
|
|
|
|
Chapter 13 of *Mastering DIY Layout Creator* is the authoritative developer guide and covers the
|
|
architecture, extension points and regression suite in prose.
|