instrument: a deck group's reserved cell width goes to the cells present

A Trigger face dropping Sustain and Release now gets wider cells instead of
144 px of dead slots. Group widths, row packing and Gate are untouched.
This commit is contained in:
2026-07-31 22:43:13 -04:00
parent 1c774226d3
commit d8ffd860d1
8 changed files with 213 additions and 29 deletions
+1 -1
View File
@@ -307,7 +307,7 @@ anything for a trigger shape.
- `browser_scroll` — scroll + type-to-filter layered over `capture_browser`: vertical scroll offset, scrollbar thumb, thumb-drag mapping, and name-substring search.
- `param_slider` — parameter control-panel: vertical stack of TOGGLE (two-segment selector) and SLIDER (horizontal track) rows; maps normalized value to/from handle pixel.
- `embed_strip` — compact single-row control layout for embed mode in the track FX chain.
- `knob_deck` — pure knob-deck layout + hit-test (FB1): group-box / caption-row / compact-toggle / knob-cell geometry, deterministic whole-group wrap, `DeckLayout` / `DeckHit`. Mirror of `action_bar`/`param_slider`; no LICE or REAPER types. A group carries TWO caption-toggle slots, laid right-to-left: the second exists because a group whose knob row is wider than its caption row has caption slack a toggle can occupy for free, and the deck has six pixels of headroom on its first row at the editor's floor width — a `rowToggle` would widen the GROUP and wrap the deck to a fourth row, past what the minimum window holds.
- `knob_deck` — pure knob-deck layout + hit-test (FB1): group-box / caption-row / compact-toggle / knob-cell geometry, deterministic whole-group wrap, `DeckLayout` / `DeckHit`. Mirror of `action_bar`/`param_slider`; no LICE or REAPER types. A group carries TWO caption-toggle slots, laid right-to-left: the second exists because a group whose knob row is wider than its caption row has caption slack a toggle can occupy for free, and the deck has six pixels of headroom on its first row at the editor's floor width — a `rowToggle` would widen the GROUP and wrap the deck to a fourth row, past what the minimum window holds. **A group's cell run is a RESERVED WIDTH, not a fixed cell size**: a `-1` id reserves one cell's width without a cell, and the cells present divide the whole run between them at one uniform integer width (residue in symmetric end margins). That is what lets a mode flip drop controls from a face — Trigger's AMP and FILTER ENV lose their Sustain/Release stages — without either reflowing the deck or leaving dead slots in the box; a face with fewer controls simply gets roomier cells. Do not reintroduce fixed-width cells with blank slots.
- `deck_groups` — also home to `isLiveDeckParam` and `liveCommitFor`, the editor's whole commit-tier routing decision (see "Live parameter delivery" above), and to `OverlayEnv` + `nextOverlaySelection`/`overlayEnvEnabled`/`overlayEnvInert`, the whole overlay-selection state machine (exclusivity, the none resting state, and which selections a disabled or DRAWN group makes inert); WHICH groups the Sample face's deck carries, split from `knob_deck`'s HOW they lay out: the `DeckParam` control-id space (the editor's `ParamControl` is an alias of it), the `DeckGroupId` list, `sampleDeckGroups` in signal-flow order (**pitch → filter → amp**, then velocity/voice/master), and the deck's bipolar-knob law. Reads `PlayMode` for the AMP group's Gate/Trigger face, which is why this and not `knob_deck` is the module that touches the engine's value layer. Also home to `CurveTarget` + `curveTargetFor` — the VELOCITY group's three cells are popup openers, not dials, and that predicate is the ONE place they are named, so paint, hit-test routing and the popup's title all agree. MASTER is reserved for post-voice-mixer concerns, which is why the curves sit in their own group immediately left of VOICE rather than there.
- `spline_edit` — THE point-editing grammar, and the one place it is written down: left-click grabs a node and adds one in empty space, right-click deletes, control-click toggles hard/smooth. Both spline consumers — the velocity-curve popup and the spline EG overlay — route their mouse-down through `resolveSplineEdit`, so the two cannot drift into two grammars. The endpoint and point-count rules are NOT restated here: `deletePoint` and `addPoint` own them, and the caller applies the resolved action to the curve. Also home to `splineOverlayBox`, the contour's mapping box inside the waveform overlay — the FULL area, no inset, so the drawn contour stays 1:1 with the sample's time axis.
- `curve_popup` — pure curve-popup geometry + dismissal test (FB1): centered sheet over the Sample face — width/height clamps, title row, Close button rect, curve-box rect, outside-sheet dismissal test. Mirror of `overflow_menu`; no LICE or REAPER types.