Skip to content

feat(chart): own captions for comparisons and a per-kind default reset - #408

Merged
guyverino merged 1 commit into
mainfrom
feat/compare-chart-defaults
Sep 3, 2026
Merged

feat(chart): own captions for comparisons and a per-kind default reset#408
guyverino merged 1 commit into
mainfrom
feat/compare-chart-defaults

Conversation

@guyverino

Copy link
Copy Markdown
Collaborator

What & why

A comparison tab was wearing the main chart's captions. It draws the same coin several times over, each pane a third of the usual width, so the live default's per-market blocks — the minute's volumes, the cursor-measuring block, the session counters, funding — were printed once per pane, in the space where the pane's own identity belongs. A comparison now ships a caption set of its own, the way the trade-detail window already does: the instrument, the Y-scale badge, what is open on this venue, the venue roster, and the spread against the anchor.

The set is transcribed from a comparison tab in daily use rather than assembled, exactly as ChartLabelsCfg::default() was transcribed from a main chart. Its two font multipliers are stated as steps from LABEL_SIZE_MULT_DEFAULT (badge a step up, roster a step down) so they keep following that number if it ever moves.

The second half is the way back. Once a default is stored for a kind it shadows the shipped one forever, and the first "make default" press on ANY kind freezes every other kind at what it was showing — so a profile that ever used the feature could not reach a shipped set again. The apply row therefore gains Reset beside Make default: it empties the ticked kinds' stored default, so a kind that ships a set of its own gets it back and the rest follow Main again. It clears those kinds' tab overrides through the same path the store press uses, so the result is visible without a restart.

Notable decisions

  • Resetting Main takes the shipped value instead of emptying, because Main's default IS the base field. It goes through the setter, whose separation pass holds the other kinds where they are — which costs a stored copy for a kind that held none. That is the deliberate half of the trade: moving those kinds instead would redress tabs the reader never ticked. The walk visits Main first for the same reason, and ChartTabKind::RESET_ORDER states that order in moon-core, where a test pins it.
  • ApplyMode::ResetDefault carries its slots rather than reading them out of the press's values: a reset lands on what the terminal ships, so a value it carried could only be noise — and a ChartLabelsCfg is over six kilobytes, copied on every render of the row.
  • Neither button carries a tooltip. This fork defers a tooltip at priority 2 against a popover's 30 000, so a hint inside a popup paints under it and is never seen (docs-internal/FORK_BUGS.md). The sentence above the row is the only explanation these buttons can have, and it now says what both of them do.
  • The row wraps at two levels. A popover is a fixed width and neither MoonButton nor MoonCheckbox shrinks, so four ticks beside two buttons had a hard minimum that was past the popup's edge in Spanish.

Known limitations

  • A profile that already stored a comparison default keeps it — there is no migration, by choice. Pressing Reset with "Comparisons" ticked is what adopts the new set; after that the slot stays empty, because the separation pass now skips a kind that ships its own captions.
  • Conversely, a profile whose comparison slot is EMPTY adopts the new set on upgrade, which does drop captions its comparison tabs are currently showing. Deliberate — that is the point of the change — but it is the one place this PR does not follow CONTRIBUTING's "an upgrade never silently drops what the user already reads".
  • Only the CAPTIONS have a per-kind shipped set; candles and graphics ship none, so resetting a non-Main kind there returns it to following Main. The hint says so.
  • Four unrelated controls in these same popups are still explained only by an invisible tooltip (the apply button, the row-edit glyph, the labels popup's own Reset, the orientation toggle). Not touched here — separate change.

How to verify

cargo build -p moon-ui-gpui --bin moonterminal --target x86_64-pc-windows-msvc --all-targets
cargo clippy -p moon-core -p moon-ui-gpui --target x86_64-pc-windows-msvc --all-targets -- -D warnings
cargo test -p moon-core -p moon-ui-gpui -p moon-chart --target x86_64-pc-windows-msvc
  • Build: green, no warnings from this diff.
  • Tests: green — moon-core 1538, moon-ui-gpui 1403, theme_contract 264, moon-chart 87, 0 failed. Five are new: the comparison set and its sanitize fixpoint, the shipped-graphics normalizer fixpoint, the per-kind reset (one kind at a time, and Main without dragging its neighbours), and the reset walk order.
  • Clippy: this repo carries pre-existing debt (403 locations across the tree). Every location was cross-checked against this diff's hunks — 0 fall on a line this change touches.
  • FireTest: not run (the developer runs it), and the visual check of the popups is theirs as well.

In the app: open the labels popup on a comparison tab, press the apply button, tick "Comparisons", press Reset — the panes adopt the shipped comparison set without a restart, and the stored default is gone from layout.toml.

A comparison tab draws the same coin several times over, each pane a third of
the usual width, and it followed the main chart's captions: the volume block,
the cursor-measuring block, the session counters and funding were printed once
per pane, in the space where the pane's own identity should be. So a comparison
now ships a caption set of its own, the way the trade-detail window already
does — the instrument, the Y-scale badge, what is open on this venue, the venue
roster and the spread against the anchor. Transcribed from a comparison tab in
daily use rather than assembled: two font multipliers come with it, stated as
steps from LABEL_SIZE_MULT_DEFAULT so they still follow that number if it moves.

The second half is the way back. Once a default has been stored for a kind, that
value shadows the shipped one forever, and the first press of "make default" on
ANY kind freezes every other kind at what it was showing — so a profile that
ever used the feature could not reach a shipped set again. The ⧉ row therefore
gains a "Reset" beside "Make default", which empties the ticked kinds' stored
default: a kind that ships a set of its own gets it back, the rest follow Main
again. It clears those kinds' tab overrides through the same path the store
press uses, so the change is visible without a restart.

Resetting Main is the one case that cannot empty anything — Main's default IS
the base field — so it takes the shipped value through the setter, whose
separation pass holds the other kinds where they are. That costs a stored copy
for a kind that held none, and it is the deliberate half of the trade: moving
those kinds instead would redress tabs the reader never ticked. The walk visits
Main first for that reason, and ChartTabKind::RESET_ORDER states the order in
moon-core where a test can pin it.

The row also wraps now, at both levels. A popover is a fixed width and neither a
button nor a checkbox shrinks, so four ticks beside two buttons had a hard
minimum wider than the popup in Spanish. Neither button carries a tooltip: this
fork paints a tooltip under the popover that owns it, so the sentence above the
row is the only explanation either button can have, and it says what both do.
@guyverino
guyverino merged commit 966b3f4 into main Sep 3, 2026
6 checks passed
@guyverino
guyverino deleted the feat/compare-chart-defaults branch September 3, 2026 21:03
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