Skip to content

Load the component libraries in the Avalonia palette - #6

Merged
ledogar merged 2 commits into
masterfrom
avalonia-component-library
Aug 8, 2026
Merged

ledogar merged 2 commits into
masterfrom
avalonia-component-library

Conversation

@ledogar

@ledogar ledogar commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Placing a 2N3904 in the macOS GUI meant dropping a generic BJT and typing IS, BF and BR by hand — the shipped part libraries were unreachable. Tubes were effectively unusable.

The palette was building its list from a hardcoded type array plus a reflection scan over CircuitComponent subclasses, so it showed component types, never parts. The WPF app has always read Circuit/Components/*.xml (Library.cs); the port never carried it over. GUI_PORT_PLAN.md:85 lists "component library insertion" as Phase 3 work, so this was known-incomplete rather than an oversight.

What this adds

ComponentLibrary reads the same XML the WPF app does — a Library element of Component elements, each handed to Circuit.Component.Deserialize. That's 87 parts across Diodes, Op-Amps, Transistors and Tubes.

Parts are listed after the generic types, so the built-ins stay where they were rather than being buried among 80-odd part numbers, and each is labelled with its category. Since the palette goes from ~25 entries to ~110, it also gains a filter box.

Two things worth review

Fresh instance per placement. Each LibraryPart keeps its source XElement rather than a deserialized prototype, and deserializes again for every placement. Components are mutable, so a shared prototype would let an edit to one placed part show up in the next one. There's a test for exactly that.

The libraries weren't reaching the build output. Circuit.csproj marked all four XML files as Content but set CopyToOutputDirectory on Tubes.xml alone — so even with this code, a host looking beside its executable would have found one library out of four. Fixed with a wildcard.

Verification

49/49 Avalonia tests (three new: all four categories load, a 2N3904 comes out with IS=1e-14, BF=300, BR=4, and placements are independent), 49/49 circuits against goldens. Confirmed in the running GUI by filtering 2N39 and getting 2N3904 and 2N3906.

🤖 Generated with Claude Code

tobleromed and others added 2 commits August 8, 2026 08:07
The Avalonia palette listed only component *types* - a generic BJT, Diode,
JFET - built from a hardcoded array plus a reflection scan. The part
libraries the project ships were unreachable, so placing a 2N3904 meant
dropping a bare BJT and typing IS, BF and BR by hand, and the tube models
were effectively unusable. The WPF app has always read these (its
Library.cs parses Circuit/Components/*.xml); the port never carried it
over. GUI_PORT_PLAN.md:85 lists component library insertion as Phase 3
work, so this was known-incomplete rather than an oversight.

ComponentLibrary reads the same XML the WPF app does: a Library element of
Component elements, each handed to Circuit.Component.Deserialize. Parts
are listed after the generic types so the built-ins stay where they were,
and are labelled with their category. Since this takes the palette from
~25 entries to ~110, it also adds a filter box.

Each LibraryPart keeps its source XElement rather than a deserialized
prototype, and deserializes afresh per placement: components are mutable,
so a shared instance would let an edit to one placed part appear in the
next one. There is a test for exactly that.

Also fixes the reason the libraries would not have been found even once
this code existed: Circuit.csproj marked all four XML files as Content but
set CopyToOutputDirectory on Tubes.xml alone, so a host looking beside its
executable saw one library out of four.

Tests: 49/49 Avalonia, 49/49 circuits against goldens. Verified in the GUI
by filtering for 2N39 and getting 2N3904 and 2N3906.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A flat list put the generic Diode at the same level as the sixteen specific
ones, with only a trailing "s" distinguishing "Diode" from "Diodes" - and
110 entries is too many to scan anyway.

The palette is now a tree of collapsible categories, matching what the WPF
app has always done (ComponentLibrary.xaml.cs builds Common, then Generic,
then the libraries). The tier names are taken from it too: "Generic" says
what "Component Types" only implied - the unconfigured component you fill
in yourself, as opposed to a pre-configured part. A Windows user now finds
the same layout.

  Common (10)      everyday parts, expanded by default
  Generic (22)     the reflection-discovered component classes
  Diodes (16), Op-Amps (12), Transistors (47), Tubes (12)

Both Diode entries earn their place: the generic one is what you need for a
part the libraries do not carry, or to hand-tune a model.

Headers carry counts. Filtering expands every category that matched, since
results hidden behind a collapsed header would defeat the search, and drops
categories that did not match entirely.

Verified in the running GUI: the tree renders as above, filtering "1N4"
leaves Diodes (6) expanded with the four 1N4xxx parts, and placing two
2N3904s and editing one leaves the other unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ledogar

ledogar commented Aug 8, 2026

Copy link
Copy Markdown
Owner Author

Follow-up after manual testing: the palette is now a tree of collapsible categories rather than a flat list.

The flat version put the generic Diode at the same level as the sixteen specific ones, distinguished only by a trailing "s" — and 110 entries is too many to scan regardless.

Common (10)      everyday parts, expanded by default
Generic (22)     the reflection-discovered component classes
Diodes (16)  Op-Amps (12)  Transistors (47)  Tubes (12)

This matches what the WPF app has always done — ComponentLibrary.xaml.cs:62,71 builds Common, then Generic, then the libraries — and the tier names are taken from it. "Generic" says what my first attempt ("Component Types") only implied: the unconfigured component you fill in yourself, as opposed to a pre-configured part. A Windows user now finds the same layout.

Both Diode entries earn their place: the generic one is what you need for a part the libraries don't carry, or to hand-tune a model.

Filtering expands every category that matched and drops the rest, so results can't hide behind a collapsed header.

Verified in the running GUI, not just by test: the tree renders as above; filtering 1N4 leaves Diodes (6) expanded with the 1N4xxx parts; and placing two 2N3904s and setting BF=999 on one leaves the other reading 300 — confirming the fresh-deserialize-per-placement behaviour through the real place-and-edit path, which the unit test only covers at the LibraryPart.Create() level.

@ledogar
ledogar merged commit b92ecfa into master Aug 8, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants