Commit 52b48fc
Light theme: one palette owns every colour, and the title bar chooses which one (#200)
The light theme itself is the small part. The work was taking colour away from
the 1100 places that decided it by hand and giving it to one file.
**`UiThemePalette` is the only place a colour is built.** 139 roles named for the
job they do — `ControlSurface`, `TextSecondary`, `CurveExcessPhase`,
`MarkerFirstArrival`, `PlotZoomBoxStroke` — each answered by BOTH themes. The
properties are `required`, so a role cannot be added to one theme and forgotten
in the other, and `UiPalette` is the static face of whichever palette is in
force. Call sites, `.Designer.cs` included, read `UiPalette.<Role>`; plot code
converts with the new `.ToOxy()`.
What that swept up: 604 `Color.FromArgb` literals and 346 `Color.White` in 22
designer files, 148 `SystemColors.ControlLight` label foregrounds, ~290 OxyPlot
colours across 19 files, the band-strip tints, the fader cap gradients, the
meter, the trash cursor. `UiPaletteCoverageTests` now fails the build on a colour
built out of numbers or framework names anywhere under `source/`; its allow list
names the six files that keep theirs and why (the user's own curve colours, PDF
sheets on paper, OxyPlot's defaults compared against). It has already earned its
keep: it caught the three literals the Auto Crossover dialog brought in when
main was merged, which no eye was going to find in a 140-file branch.
**Near-duplicates collapsed into roles rather than being carried over twice.**
Twelve greys of text became a ladder of six; two button fills (50,55,80 and
46,51,67) and the dialog button grey became one `ButtonBackground`; nine greens
became `Success`; four ambers became `Warning`. The plot surfaces went from the
four TODO.md complained about to two: `GraphSurface` (main, wizard, Virtual DSP)
and `GraphSurfaceMuted` (the previews). The satellite plots — Time Alignment,
`AngleCalibrationDialog`, `ImpulseWindowPreview`, `OverlayTargetSettingsDialog`,
`MeasurementHistoryWindow` — no longer carry their own chrome: they go through
`PlotModelStyle.CreatePreviewModel` and `AddAxis`/`StyleAxis`, which is now the
single home of what a plot looks like.
**The twelve overlay slots got designed colours.** They came from `new Random(3)`,
and that colour becomes a curve colour the moment the slot is captured into.
Seeded, so deterministic, but nobody chose it: five of the twelve sit under 3:1
against the DARK plot as shipped — slot 12 reads 1.23:1, slot 6 1.56:1 — and on
white the bright green slot 4 falls to 1.47:1. They are `OverlaySlotDefaults` in
the palette now, twelve per theme, the weakest 4.26:1. The dark slot colours
therefore change; a slot that already holds a capture keeps the colour in its
file.
**The theme is chosen at startup.** A designer reads the palette inside
`InitializeComponent`, so `Program.Main` calls `UiPalette.Use` before the first
control exists; the gear button in the title bar opens Settings, and switching
the theme offers a restart. `Application.Restart` cannot do that here — the shell
cancels its first close to await the audio aborts, so the replacement would meet
a `SingleInstanceGuard` the old process still owns — so the request is recorded
and carried out after `Application.Run` returns and the guard is released. The
choice lives in its own `appearance.json`, written through `AtomicFile` so a
failed write leaves the previous theme rather than an empty file, and a failed
write does not offer a restart into a theme that was not saved.
The gear is drawn rather than typed: at 13 px the U+2699 glyph falls back to the
colour emoji font and reads as a flower. Candidates were rendered side by side —
the glyph with and without the text-presentation selector, in Segoe UI Symbol and
in Segoe MDL2 Assets, against a drawn one — and only the drawn one is legible at
that size. It takes the button's own ink, so it follows the theme.
`DarkComboBox`, `DarkNumericUpDown` and `DarkScrollBars` became `Themed*` — the
scrollbars now ask the OS for the light or dark native theme to match, with the
app-mode value chosen per Windows build (ordinal 135 is `AllowDarkModeForApp` on
1809 and `SetPreferredAppMode` from 1903, where ForceLight is 3, not 1).
Held to the same floors as the dark theme where it is honest to say so:
`UiPaletteContrastTests` runs its whole table against both palettes, plus every
`Curve*`/`Marker*` role, all twelve Virtual DSP channel colours and all twelve
overlay slot defaults against the plot surface. The dark analysis curves predate
that floor — the weakest, violet HD3 on deep blue, reads 1.58:1 — so dark is held
where it stands, REFERENCE.md says so instead of claiming parity, and the gap is
written down in TODO.md rather than quietly retuned.
Deliberately untouched: colours the user chose (captured overlay slots, Virtual
DSP channels in a saved session, the EQ Wizard target) stay exactly as they are
in their files. What follows the theme is the colour a slot or target STARTS in.
Tuning sheet PDFs are printed on paper and have no theme.
Verified beyond the test suite with a scratchpad render harness: every
constructible panel, dialog and control drawn to a bitmap and hashed before and
after the sweep, so the dark theme is provably unchanged except where a merge was
intended — the diffs are the merged values and nothing else. The same harness
drew both themes of the shell, the panels, the settings dialog and the title bar
for the visual passes.
One test-harness fix rides along. `FirConstructorTests` failed once on CI and
never locally, and the state it reported — design and kernel replaced,
`RebuildPending` already false, the button still disabled — has exactly one
cause: the panel publishes that flag one statement before `ApplyRendering`
re-enables the button, which is invisible while both run on the UI thread. It
stops being invisible when the continuation resumes on the thread pool, and
WinForms only installs a `WindowsFormsSynchronizationContext` while the
process-wide `AutoInstall` is on — which a test running beside it can turn off.
`StaTest.Run` installs the context itself now.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>1 parent 3738743 commit 52b48fc
155 files changed
Lines changed: 3927 additions & 2478 deletions
File tree
- source
- LiveSpectrum
- Options
- Overlays
- Plotting
- Settings
- Shell
- Storage
- TimeAlignment
- Tools
- Eq
- FirConstructor
- Sheets
- SignalGenerator
- VirtualCrossover
- Ui
- Controls
- Dialogs
- tests/Resonalyze.App.Tests
- tools/Resonalyze.Screenshots
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
218 | 218 | | |
219 | 219 | | |
220 | 220 | | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
221 | 231 | | |
222 | 232 | | |
223 | 233 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
278 | 278 | | |
279 | 279 | | |
280 | 280 | | |
| 281 | + | |
| 282 | + | |
281 | 283 | | |
282 | 284 | | |
283 | 285 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
| 14 | + | |
14 | 15 | | |
15 | 16 | | |
16 | 17 | | |
| |||
60 | 61 | | |
61 | 62 | | |
62 | 63 | | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
63 | 94 | | |
64 | 95 | | |
65 | 96 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
433 | 433 | | |
434 | 434 | | |
435 | 435 | | |
436 | | - | |
437 | | - | |
438 | | - | |
439 | | - | |
440 | | - | |
441 | | - | |
442 | | - | |
443 | | - | |
444 | | - | |
445 | | - | |
446 | | - | |
447 | | - | |
448 | | - | |
449 | | - | |
450 | | - | |
451 | | - | |
452 | | - | |
453 | | - | |
454 | | - | |
455 | | - | |
456 | | - | |
457 | 436 | | |
458 | 437 | | |
459 | 438 | | |
| |||
466 | 445 | | |
467 | 446 | | |
468 | 447 | | |
469 | | - | |
470 | | - | |
471 | | - | |
472 | | - | |
473 | | - | |
474 | | - | |
475 | | - | |
476 | | - | |
477 | | - | |
478 | | - | |
479 | | - | |
480 | | - | |
481 | | - | |
482 | | - | |
483 | | - | |
484 | | - | |
485 | | - | |
486 | | - | |
487 | | - | |
488 | | - | |
489 | | - | |
490 | | - | |
491 | | - | |
492 | | - | |
493 | | - | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
494 | 461 | | |
495 | 462 | | |
496 | 463 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
720 | 720 | | |
721 | 721 | | |
722 | 722 | | |
723 | | - | |
| 723 | + | |
724 | 724 | | |
725 | 725 | | |
726 | 726 | | |
| |||
799 | 799 | | |
800 | 800 | | |
801 | 801 | | |
802 | | - | |
| 802 | + | |
803 | 803 | | |
804 | 804 | | |
805 | 805 | | |
| |||
815 | 815 | | |
816 | 816 | | |
817 | 817 | | |
818 | | - | |
819 | | - | |
| 818 | + | |
| 819 | + | |
820 | 820 | | |
821 | 821 | | |
822 | 822 | | |
| |||
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
0 commit comments