Fix stale post-widen deck-reflow figures (90/144/1190px) across docs and tests, and split test_deck_groups.cpp's width-budget fixtures into a new file.

This commit is contained in:
2026-08-02 12:13:37 -04:00
parent b956fe0d5a
commit 4b0b03d8d5
9 changed files with 475 additions and 429 deletions
+1 -1
View File
@@ -326,7 +326,7 @@ anything for a trigger shape.
### `ui/`
- `editor_geometry` (`core/instrument/ui`) — the shared geometry VOCABULARY every instrument UI module speaks: the `core::ui::Rect` alias, `contains()`, and `OverlayArea` (a one-field `Rect` wrapper, no implicit conversion from `Rect`). Header-only (an INTERFACE CMake target), so it carries no layout of its own.
- `sample_bands` — **THE band-stack allocator**, and the only module that owns the Sample face's vertical inventory — including `kEditorMinWidth`/`kEditorMinHeight`, the editor's client-area floor, which IS its default size (the shell's `checkSizeConstraint` and opening `ViewRect` both read it; the face grows, never shrinks below what the stack is laid out for), and `kEditorCeilingWidth`, the floor's sibling window fact (the hard cap the floor may not exceed) — moved here from `knob_deck.h` since it is a window fact, not a deck one; the derivation identity against the deck's width budget stays in `test_deck_groups.cpp`, the one place that already includes both headers. Three bands top-to-bottom (CHROME toolbar+control row / WAVEFORM elastic, floored at two stacked lanes / DECKS bottom-anchored at the knob deck's own wrapped height), plus the waveform band's lane split (`waveformLanes` takes a resolved `LaneSplit`, not a raw bool — only `waveformSurface` folds the source-channel-count decision in). A shared READ-ONLY surface for every band owner — a band's interior module lays out inside the rect it is handed and never re-allocates the stack.
- `sample_bands` — **THE band-stack allocator**, and the only module that owns the Sample face's vertical inventory — including `kEditorMinWidth`/`kEditorMinHeight`, the editor's client-area floor, which IS its default size (the shell's `checkSizeConstraint` and opening `ViewRect` both read it; the face grows, never shrinks below what the stack is laid out for), and `kEditorCeilingWidth`, the floor's sibling window fact (the hard cap the floor may not exceed) — moved here from `knob_deck.h` since it is a window fact, not a deck one; the derivation identity against the deck's width budget stays in `test_deck_groups_measured.cpp`, the one place that already includes both headers. Three bands top-to-bottom (CHROME toolbar+control row / WAVEFORM elastic, floored at two stacked lanes / DECKS bottom-anchored at the knob deck's own height), plus the waveform band's lane split (`waveformLanes` takes a resolved `LaneSplit`, not a raw bool — only `waveformSurface` folds the source-channel-count decision in). A shared READ-ONLY surface for every band owner — a band's interior module lays out inside the rect it is handed and never re-allocates the stack.
- `sample_chrome` — the CHROME band's interior: the toolbar row (title + the whole right-anchored control run — bake Hold cell, bake, preview, velocity knob cell, loop enable, channel toggle, Browse) over the strip row, which the piano strip owns outright. The title takes what the run leaves; the strip takes its whole row, inset only by the shared band pad so it lines up with the waveform band beneath. Every run member's width is RESERVED unconditionally, the Hold cell included — the only conditionally-drawn one, and the leftmost, so what its reservation buys is a title slot that does not re-measure when a loop is dialled in or out (`sample_chrome.h` records the cost). Also `previewGlyph`, the preview button's play triangle — three vertices for one filled-triangle draw, so the button's label needs no font metric and no image asset.
- `bake_hold` — the Hold knob's value domain and nothing else: the knob's normalized [0,1] mapped onto the note-length ladder and back, ordered by LENGTH rather than by the ladder's presentation order. Split from `sample_chrome` on the same axis `deck_values` was split from `knob_deck` — that says where the cell is, this says what its position means.
- `keyboard_strip` — piano-keyboard strip: true white/black key geometry (whites tiled at one width, blacks overlaid at one width and height, straddling their boundary), hit-test resolving black-over-white by zone, root-marker rect, the absolute-position drag resolver, and MIDI note naming under the C4 convention. **Same-class keys are one integer width by construction; the residue of an indivisible band width (`w % 75`, up to 74 px) lands in symmetric end margins, never in a key** — uniform widths and gap-free edge-to-edge tiling cannot both hold, and uniformity wins.
+7 -4
View File
@@ -75,10 +75,13 @@ reasampler_test(master_meter LINK master_meter waveform_view)
reasampler_pure_library(deck_groups
SOURCES deck_groups.cpp
LINK PUBLIC knob_deck velocity_curve peaks curve_law PRIVATE master_meter)
# sample_bands and master_meter are linked directly for the test: the deck-fits-the-floor-window
# assertion needs the band allocator, and the MASTER-reserve identity needs the column width the
# PRIVATE edge above does not re-export.
reasampler_test(deck_groups LINK deck_groups sample_bands master_meter)
# WHICH descriptors the deck carries, and how they resolve to a layout — no window-floor budget
# assertion here, so this target needs neither sample_bands nor master_meter.
reasampler_test(deck_groups LINK deck_groups)
# The width-BUDGET half, split out on the same seam PRIVATE master_meter already draws above:
# the deck-fits-the-floor-window assertion needs the band allocator, and the MASTER-reserve
# identity needs the column width the PRIVATE edge on deck_groups does not re-export.
reasampler_test(deck_groups_measured LINK deck_groups sample_bands master_meter)
# The commit-tier + overlay-selection state machine, split out of deck_groups_tests on the seam
# those fixtures already had: deckParamCommit/liveCommitFor and the overlay predicates are pure
# control-id/enum logic that touches no layout, so this target needs no sample_bands/master_meter.
+2 -2
View File
@@ -15,7 +15,7 @@ double clamp(double v, double lo, double hi) { return v < lo ? lo : (v > hi ? hi
// Segment width of the three Staged|Spline toggles. Sized so each env group's caption row stays
// no wider than its knob row; the binding group is PITCH ENV, which reaches its four-cell knob
// row at 47 (AMP, the next tightest, at 55). Well inside the ceiling — raising it would widen
// the CONTOUR row, which has 144px of slack, not the SOUND row.
// the CONTOUR row, which has 152px of slack, not the SOUND row.
constexpr int kEnvModeSegW = 23;
} // namespace
@@ -133,7 +133,7 @@ std::vector<DeckGroupDesc> sampleDeckGroups(PlayMode playMode) {
{
// The lower slot is reserved and draws NOTHING: blank reads as breathing room where a
// dashed placeholder would read as unfinished. It is one cell, not two — a second
// would spend 60 of the layout's whole 90px budget on a control nobody has named.
// would spend 60 of the layout's whole 82px budget on a control nobody has named.
DeckGroupDesc master;
master.id = kGroupMaster;
master.captionWidth = 46;
+1 -1
View File
@@ -55,7 +55,7 @@ struct SampleBands {
};
// Divide a (w x h) client area into the three bands. `deckHeight` is the knob deck's own
// wrapped height (from knob_deck) — the only interior measurement the allocator needs, so
// height (from knob_deck) — the only interior measurement the allocator needs, so
// the deck band is exactly as tall as its content. Pure.
SampleBands computeSampleBands(int w, int h, int deckHeight);