Skip to content

fix(colours): v6 palettes without label sequences inherit the parent's labels - #79

Merged
willwade merged 1 commit into
mainfrom
fix/palette-label-colours
Sep 1, 2026
Merged

fix(colours): v6 palettes without label sequences inherit the parent's labels#79
willwade merged 1 commit into
mainfrom
fix/palette-label-colours

Conversation

@willwade

@willwade willwade commented Sep 1, 2026

Copy link
Copy Markdown

Summary

Fixes Dasher-Windows #47: "Yellow on Black colour theme — it's all black. The font is not yellow. There is no yellow anywhere."

Root cause

The v6 palette files (Data/colors/color.*.xml, RFC 0007) are authored with only defaultLabelColor and no per-group label sequences. Label resolution in GetNodeLabelColor/GetGroupLabelColor treats the empty sequences as "undefined" and falls through to the parent palette — whose group-specific label colours win before the child palette's own defaultLabel fallback can run. For "Yellow on Black" (parentName="Default"), the legacy Default palette supplies black labels → invisible on the dark background.

Fix

The v6 parser now defaults empty group label colours (groupLabelColor / nodeLabelColorSequence) to the palette's own defaultLabelColor — mirroring what ParseLegacy has always done when building its groups (ColorIO.cpp:105-128). Explicit per-group sequences still win; palettes that don't define defaultLabelColor keep the previous parent-inheritance behaviour.

Regression test

yellow_on_black_labels_carry_palette_default_label_colour (test_draw_commands.cpp): with "Yellow on Black" selected, every opcode-5 text command must be #FFFFFF00. Measured pre-fix: all #FF000000; post-fix: 21/21 yellow.

Full suite: 40/40 test executables green (incl. the #63 uppercase-colour regression, which shares this code path).

Notes

Type of change

  • Bug fix

Definition of Done

  • 40/40 engine test suites green
  • Regression test added
  • clang-format clean
  • DCO signed

Greptile Summary

The PR updates v6 palette parsing so groups with no explicit label colors use their palette’s own defaultLabelColor, preventing parent group colors from overriding intended high-contrast labels.

  • Defaults wholly unspecified group and node label colors during parsing.
  • Preserves explicit label sequences and existing inheritance when no palette-local default exists.
  • Adds an end-to-end draw-command regression test for Yellow on Black.

Confidence Score: 5/5

The PR appears safe to merge with no actionable correctness, security, or quality issues identified.

The parser change is scoped to wholly unspecified label colors, preserves explicit definitions and no-default inheritance, and the regression test exercises the resulting frontend-visible draw commands.

Important Files Changed

Filename Overview
src/DasherCore/ColorIO.cpp Defaults wholly empty v6 group and node label definitions from the current palette while retaining explicit values and inheritance when no local default exists.
tests/test_draw_commands.cpp Adds public-API rendering coverage that verifies every emitted Yellow on Black text command uses the palette’s yellow label color.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[v6 palette group] --> B{Explicit label colors?}
  B -->|Yes| C[Use explicit group or node colors]
  B -->|No| D{Palette defines defaultLabelColor?}
  D -->|Yes| E[Materialize palette-local label default]
  D -->|No| F[Retain parent inheritance]
  C --> G[Render labels]
  E --> G
  F --> G
Loading

Reviews (1): Last reviewed commit: "fix(colours): v6 palettes without label ..." | Re-trigger Greptile

Context used:

…s labels

Issue #47 (Dasher-Windows): 'Yellow on Black' rendered with no yellow anywhere - labels invisible on the dark background. The v6 palette files author only defaultLabelColor; their groupColorInfo entries carry no label sequences, so GetNodeLabelColor fell through the empty sequences to the PARENT palette's group-specific label colours - the legacy Default palette supplies black - which won before the palette's own defaultLabel fallback could run.

Fix: the v6 parser defaults empty group label colours (groupLabelColor / nodeLabelColorSequence) to the palette's OWN defaultLabelColor, mirroring what ParseLegacy has always done when building its groups. Explicit per-group sequences still win; palettes without defaultLabelColor keep the old parent-inheritance.

Regression test: with 'Yellow on Black' selected, every opcode-5 text command must be #FFFFFF00. Verified 21/21 yellow post-fix (pre-fix: all #FF000000).

Signed-off-by: will wade <willwade@gmail.com>
@willwade
willwade merged commit 1753be2 into main Sep 1, 2026
15 checks passed
willwade added a commit to dasher-project/Dasher-Windows that referenced this pull request Sep 1, 2026
… startup crash handler (#48)

## Summary

Fixes #46 and #47, plus the PostHog-reported startup crash handler bug.
DasherCore bumped to v0.2.17 (+ the palette fix branch pending merge).

### #46 — Window size/position not remembered between runs
- New `WindowSettings` (`%APPDATA%\Dasher\window_settings.json`) with
**mode-scoped bounds**: normal and direct/keyboard modes save
separately, so quitting in direct mode never shrinks the next normal
launch
- Restored before first show (constructor,
`WindowStartupLocation.Manual`); saved on close and on runtime mode
switches
- **Off-screen guard**: a saved position that no longer intersects any
connected screen (unplugged monitor, DPI change) falls back to the AXAML
default instead of stranding the window behind a bezel — requires a
visible ~80px chunk, not just a pixel
- **Maximized**: normal-state bounds are tracked continuously, so
closing while maximized saves the *restore* bounds, not the maximized
frame; maximized state restores for normal mode only

### #47 — Yellow on Black theme renders all black
Root cause is **DasherCore-side**: v6 palette files author only
`defaultLabelColor`; their groups carry no label sequences, so label
resolution fell through to the **parent** palette's group-specific label
colours — the legacy Default palette supplies **black** — which won
before the palette's own yellow fallback. Fixed in DasherCore [PR
#79](dasher-project/DasherCore#79) (v6 parser
defaults empty group label colours to the palette's own `defaultLabel`,
mirroring `ParseLegacy`); submodule pinned to that branch pending merge,
re-pin to the tagged release after.

- Windows-side engine-driven regression test: with "Yellow on Black"
active, **every** opcode-5 text command must be `#FFFFFF00` (measured
pre-fix: all `#FF000000`)
- Benefits all frontends — same parser, same palette files

### Startup crash handler (PostHog: `SavedCrashException` ×2, 31 Aug)
The top-level handler wrote to a hardcoded dev path
(`C:\github\DasherProjects\crash.log`) — user machines don't have it, so
the handler crashed *itself* with `DirectoryNotFoundException` and
telemetry captured the secondary exception. Now writes the RFC 0009
envelope (`AnalyticsService.WriteCrashFile`, scrubbed + versioned) plus
a plain-text `startup-crash.log` fallback under `%APPDATA%\Dasher`, and
no longer blocks on `Console.ReadLine()`.

### DasherCore v0.2.17
ScanFiles skips bad entries; failed Realize latches engineError (#77);
direct-mode shadow-buffer invariant test (#78).

## Verification
- 40/40 DasherCore test suites green (incl. new label-colour regression)
- 77/77 Windows tests green
- Geometry restore/clamp logic verified by build + manual review (needs
an eyeball pass: resize/move → relaunch; unplug-monitor fallback can't
be tested locally)

## Type of change
- [x] Bug fix
- [x] New feature (window geometry)

## Definition of Done
- [x] Build + tests green
- [x] Regression tests added
- [x] Commits signed off (DCO)














<!-- greptile_comment -->

<h3>Greptile Summary</h3>

The PR adds mode-scoped window geometry persistence, corrects startup
crash recording, updates DasherCore for palette and engine fixes, and
adds a native-engine palette regression test.
- Restores and saves separate normal and keyboard-mode window bounds,
including maximized restore behavior and off-screen validation.
- Records fatal startup exceptions under the user’s application-data
directory without blocking or throwing from the handler.
- Updates DasherCore and verifies Yellow-on-Black text commands use
yellow labels.

<h3>Confidence Score: 5/5</h3>

The PR appears safe to merge.

No blocking failure remains.

<details><summary><h3>Important Files Changed</h3></summary>




| Filename | Overview |
|----------|----------|
| src/Dasher.Windows/Views/MainWindow.axaml.cs | Adds geometry
restoration, visibility validation, mode-scoped persistence, and tracker
handling; the previously reported geometry defects are addressed at
current HEAD. |
| src/Dasher.Windows/Controls/WindowSettings.cs | Introduces resilient
JSON persistence for separate normal and keyboard-mode bounds. |
| src/Dasher.Windows/Program.cs | Replaces the hardcoded and blocking
startup crash path with guarded application-data crash records. |
| tests/Dasher.Windows.Tests/PaletteLabelColorTests.cs | Adds a
native-engine regression test asserting Yellow-on-Black text commands
use the expected yellow color. |
| DasherCore | Advances the engine submodule for palette parsing and
related engine corrections. |

</details>


<details open><summary><h3>Flowchart</h3></summary>

```mermaid
%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Startup] --> B[Load pane and window settings]
    B --> C{Saved bounds usable?}
    C -->|Yes| D[Apply mode-scoped bounds]
    C -->|No| E[Keep AXAML defaults]
    D --> F[Track normal-state geometry]
    E --> F
    F --> G{Runtime pane switch?}
    G -->|Yes| H[Save outgoing mode bounds]
    H --> I[Apply entering mode layout and bounds]
    I --> F
    G -->|Close| J[Save active mode bounds]
```
</details>

<sub>Reviews (7): Last reviewed commit: ["fix(window): one coherent DPI
scale for
..."](01c08c6)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=58992149)</sub>

<details><summary><h4>Context used (4)</h4></summary>

- Knowledge Base — [Application lifecycle and
startup](https://app.greptile.com/dasher-project/-/custom-context/knowledge-base/dasher-project/dasher-windows/-/docs/application-lifecycle.md)
- Knowledge Base — [Desktop UI
composition](https://app.greptile.com/dasher-project/-/custom-context/knowledge-base/dasher-project/dasher-windows/-/docs/desktop-ui.md)
- Knowledge Base — [Settings panels and text
output](https://app.greptile.com/dasher-project/-/custom-context/knowledge-base/dasher-project/dasher-windows/-/docs/settings-and-output.md)
- Knowledge Base — [Automated
validation](https://app.greptile.com/dasher-project/-/custom-context/knowledge-base/dasher-project/dasher-windows/-/docs/automated-validation.md)
</details>


<!-- /greptile_comment -->

---------

Signed-off-by: will wade <willwade@gmail.com>
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.

1 participant