docs(multi-bank): settle fork 5 — LICE tabs + both move affordances (Phase B closed)

5a: named-banks tab strip is LICE-drawn (matching M5 grid + Design View
segmented switch), with overflow/scroll in scope from B4 start.
5b: move ships as both a bindable "move to bank" menu and drag-between-regions;
copy stays the deliberate secondary act. Drag mis-drop mitigated by drop-target
highlighting and recoverable by design (index-only, reversible).

Phase B now fully settled (all five forks resolved), ready to scope into
implementation waves; only the active-bank indicator placement polish remains.
This commit is contained in:
2026-07-23 13:13:04 -04:00
parent dcbe5d7bdc
commit 2c468bb40c
3 changed files with 113 additions and 42 deletions
+31 -17
View File
@@ -468,9 +468,16 @@ REAPER-facing:
layer adds to. layer adds to.
- `bank_panel` (extension) — the vertical split: pool grid on top, named-banks - `bank_panel` (extension) — the vertical split: pool grid on top, named-banks
tab-page region below; two full-height toggles; the active-bank indicator; the tab-page region below; two full-height toggles; the active-bank indicator; the
create / rename / delete / activate affordances; sample move/copy affordance create / rename / delete / activate affordances. The named-banks tab strip is
(drag between regions and/or a "send to bank" menu on selection). Reuses the **LICE-drawn** to match the M5 grid and the Design View segmented switch (not a
existing LICE grid render loop per bank region. SWELL-native tab control), with an **overflow/scroll affordance** so it scales past
the ~812-tab point. Sample move ships **both ways**: a "move to bank" menu on the
current selection (the bindable front-end for the B3 move action) and
drag-between-regions (the direct-manipulation accelerator); copy is the deliberate
secondary act, offered on the menu. Drag carries clear drop-target highlighting on
the destination region/tab, and a mis-drop is recoverable by design (move is
index-only and reversible — the user moves the sample back). Reuses the existing
LICE grid render loop per bank region.
- `actions` (entries) — create bank / rename bank / delete bank (confirm on - `actions` (entries) — create bank / rename bank / delete bank (confirm on
non-empty delete); evacuate bank → pool; activate bank (direct + cycle); move non-empty delete); evacuate bank → pool; activate bank (direct + cycle); move
selected samples → bank; copy selected samples → bank; pool/banks full-height selected samples → bank; copy selected samples → bank; pool/banks full-height
@@ -486,9 +493,13 @@ verify against the SDK header where they extend existing surfaces:
- **Persistence:** `SetProjExtState` / `GetProjExtState` under `"reasampler"`, new - **Persistence:** `SetProjExtState` / `GetProjExtState` under `"reasampler"`, new
key `banks` (shared blob machinery from M4 — no new API, new key only). key `banks` (shared blob machinery from M4 — no new API, new key only).
- **Panel UI:** the docked-window + LICE-grid surface from M5 (`bank_panel`), - **Panel UI:** the docked-window + LICE-grid surface from M5 (`bank_panel`),
extended to two grid regions + a tab strip + toggles. SWELL controls for the tab extended to two grid regions + a **LICE-drawn** tab strip (with overflow/scroll) +
strip / toggle affordances follow the M5 docking pattern; **verify SWELL control toggles. The tab strip, the toggle affordances, and the drag hit-testing are
usage against the M5 reference**, no new REAPER audio API involved. custom-drawn on the M5 LICE surface (not SWELL-native tabs); the "move to bank" menu
uses a SWELL popup-menu surface. **Verify LICE drawing and any SWELL menu/drag
hit-test usage against the M5 reference / SWELL headers**, and confirm the drag
hit-test does not collide with the M5 grid's multi-select drag. No new REAPER audio
API involved.
- **Actions:** the `command_id` / `gaccel` / `hookcommand` contract from `main.cpp` - **Actions:** the `command_id` / `gaccel` / `hookcommand` contract from `main.cpp`
(unchanged), new command-id strings under the sampler family prefix. (unchanged), new command-id strings under the sampler family prefix.
@@ -515,18 +526,21 @@ verify against the SDK header where they extend existing surfaces:
## Open questions to resolve during build ## Open questions to resolve during build
Forks 14 are settled (see product notes → *Settled forks*, and the settled-decision Forks 15 are all settled (see product notes → *Settled forks* and *Fork 5 — settled*,
prose above). Two panel-build items remain open. and the settled-decision prose above). One panel-polish detail remains open.
- **Fork 5 — tab rendering + move affordance (B4).** Two sub-questions: (5a) the - **Fork 5 — tab rendering + move affordance (B4). Settled (2026-07-23).** (5a) The
named-banks region as a SWELL-native tab control vs. LICE-drawn tabs matching the named-banks region is **LICE-drawn** to match the M5 grid and the Design View
grid aesthetic; (5b) the move gesture as drag-between-regions vs. a "send to bank" segmented switch — not a SWELL-native tab control — with an **overflow/scroll
menu vs. both. Full options analysis (pros/cons across visual consistency, keyboard affordance in scope from the start** so the strip scales past the ~812-tab
nav, HiDPI, cross-platform SWELL parity, scaling, discoverability, mis-drop risk, breakdown. (5b) Move ships as **both** a "move to bank" menu (the precise,
MIDI-bindability, implementation cost) and pending recommendations in product notes MIDI-bindable front-end for the B3 move action) **and** drag-between-regions (the
*Fork 5*. **Verify SWELL tab-control availability and cross-platform behavior direct-manipulation accelerator); copy stays the deliberate secondary act via the
parity against the SWELL headers / SWS reference** before committing to native tabs. menu. Drag mis-drop is mitigated by drop-target highlighting and is recoverable by
Decision pending Daniel. design (move is index-only and reversible). Folded into the `bank_panel` prose and
the API surface below. **Verify LICE tab drawing and any SWELL menu/drag hit-test
surface against the M5 reference / SWELL headers before use** (confirm no collision
with the M5 grid's multi-select drag). Analysis in product notes → *Fork 5*.
- **Active-bank indicator placement (B4 polish)** — per-region headers vs. a single - **Active-bank indicator placement (B4 polish)** — per-region headers vs. a single
header readout vs. lit-tab treatment. The "visually unmistakable" requirement is header readout vs. lit-tab treatment. The "visually unmistakable" requirement is
settled (fork 4); only the placement is open. Panel-polish detail. settled (fork 4); only the placement is open. Panel-polish detail.
+20 -14
View File
@@ -174,32 +174,38 @@ indicated; both full-height toggles collapse the split correctly; sample move/co
affordance works; non-empty delete confirms and offers evacuate; the Design View mode affordance works; non-empty delete confirms and offers evacuate; the Design View mode
switch in the header is unaffected. switch in the header is unaffected.
**Depends on:** B1, B2, B3. (Tab rendering + move-affordance mechanics — fork 5 — **Depends on:** B1, B2, B3. (Tab rendering + move-affordance mechanics — fork 5 —
pending Daniel's decision; see Phase B open questions and product notes → *Fork 5*.) settled 2026-07-23: LICE-drawn tabs + both move affordances; see Phase B open questions
and product notes → *Fork 5 — settled*.)
- [ ] Vertical split: pool grid region (top) + named-banks tab-page region (bottom). - [ ] Vertical split: pool grid region (top) + named-banks tab-page region (bottom).
- [ ] Named-banks tab strip: one tab per named bank; empty state when none. - [ ] Named-banks tab strip: **LICE-drawn** (matching the M5 grid + Design View
(SWELL-native vs. LICE-drawn — fork 5a, pending.) segmented switch, not SWELL-native — fork 5a); one tab per named bank; empty state
when none. **Verify LICE tab draw against the M5 reference before use.**
- [ ] Tab-strip overflow/scroll affordance — **in scope from the start** (fork 5a): a
naive fixed-width LICE strip breaks down at ~812 tabs, so ship scroll/chevron
overflow with the strip, do not defer it.
- [ ] Pool full-height / banks full-height toggle affordances wired to B3. - [ ] Pool full-height / banks full-height toggle affordances wired to B3.
- [ ] Active-bank indicator — **visually unmistakable** (settled constraint); - [ ] Active-bank indicator — **visually unmistakable** (settled constraint);
placement (per-region header / single readout / lit-tab) is the residual polish placement (per-region header / single readout / lit-tab) is the residual polish
detail. detail.
- [ ] Create / rename / delete / activate / evacuate affordances driving B3 actions. - [ ] Create / rename / delete / activate / evacuate affordances driving B3 actions.
- [ ] Delete confirms on a non-empty bank, naming the evacuate alternative. - [ ] Delete confirms on a non-empty bank, naming the evacuate alternative.
- [ ] Sample move/copy affordance (drag between regions and/or "send to bank" menu - [ ] Sample move affordance **both** (fork 5b): a "move to bank" menu on the current
fork 5b, pending). selection (bindable front-end for the B3 move action) **and** drag-between-regions.
Copy is the deliberate secondary act, offered on the menu.
- [ ] Drag mis-drop mitigation (fork 5b): clear drop-target highlighting on the
destination region/tab during a drag; a mis-drop is recoverable by design (move is
index-only and reversible). **Verify the drag hit-test doesn't collide with the M5
grid's multi-select drag.**
## Phase B open questions ## Phase B open questions
Forks 14 settled by Daniel (2026-07-23): persistence key = fold pool into `banks`, All five forks settled by Daniel (2026-07-23): persistence key = fold pool into `banks`,
retire legacy key (1a); delete drops members + add evacuate verb (2); move is the retire legacy key (1a); delete drops members + add evacuate verb (2); move is the
default gesture (3); active-bank/shown-tab distinct with an unmistakable indicator default gesture (3); active-bank/shown-tab distinct with an unmistakable indicator (4);
(4). Folded into CONTEXT.md §Multi-bank + the B1B4 points above. Remaining: LICE-drawn tabs + overflow, and both move affordances with drop-highlighting (5).
Folded into CONTEXT.md §Multi-bank + the B1B4 points above. Phase B is fully settled and
ready to scope into implementation waves. One polish detail remains:
- **Fork 5 — tab rendering + move affordance** — (5a) SWELL-native tab control vs.
LICE-drawn tabs matching the grid aesthetic; (5b) drag-between-regions vs.
"send to bank" menu vs. both. Options analysis + pending recommendations in product
notes → *Fork 5*. Verify SWELL tab-control availability + cross-platform parity
against the SWELL headers / SWS reference before choosing native tabs. Decision
pending Daniel. (touches B4)
- **Active-bank indicator placement** — per-region headers vs. single header readout - **Active-bank indicator placement** — per-region headers vs. single header readout
vs. lit-tab. "Unmistakable" is settled; only placement is open. Polish detail. vs. lit-tab. "Unmistakable" is settled; only placement is open. Polish detail.
(touches B4) (touches B4)
+62 -11
View File
@@ -6,9 +6,10 @@ detail in `CONTEXT.md` (§Multi-bank). This doc holds the *why* — the workflow
narrative, the pool-privilege reasoning, the movement semantics, and the narrative, the pool-privilege reasoning, the movement semantics, and the
design-direction recommendations — so those don't clutter the build docs. design-direction recommendations — so those don't clutter the build docs.
Status: framed by product-designer (2026-07-23). Forks 14 settled by Daniel Status: framed by product-designer (2026-07-23). All five forks settled by Daniel
(2026-07-23); fork 5 (tab rendering + move affordance) still open — options (2026-07-23) fork 5 (tab rendering + move affordance) is now closed; the record at
analysis at the bottom. Settled forks are folded into the prose below. the bottom carries the decision and rationale. Settled forks are folded into the prose
below. Only the active-bank indicator *placement* remains an open B4 polish detail.
--- ---
@@ -382,9 +383,9 @@ the M5 LICE grid render loop per region.
## Settled forks (Daniel, 2026-07-23) ## Settled forks (Daniel, 2026-07-23)
Four of the five open forks are now decided; their implications are folded into the All five forks are now decided; their implications are folded into the prose above.
prose above. Recorded here as a scan-line so the decisions don't have to be Recorded here as a scan-line so the decisions don't have to be reconstructed from the
reconstructed from the body text. body text.
1. **Persistence key — (a), retire `bank_index`.** The pool folds into the `banks` 1. **Persistence key — (a), retire `bank_index`.** The pool folds into the `banks`
blob as bank-zero; the legacy `bank_index` key is retired after a one-way, blob as bank-zero; the legacy `bank_index` key is retired after a one-way,
@@ -403,14 +404,60 @@ reconstructed from the body text.
indicator.** Browsing never retargets capture; the "visually unmistakable" indicator.** Browsing never retargets capture; the "visually unmistakable"
requirement is a settled constraint (placement remains a B4 detail). (See requirement is a settled constraint (placement remains a B4 detail). (See
*design-direction → active bank and shown tab stay distinct*.) *design-direction → active bank and shown tab stay distinct*.)
5. **Named-banks tabs are LICE-drawn; move ships as both menu and drag.** (5a) The
tab strip is LICE-drawn to match the M5 grid and the Design View segmented switch —
not a SWELL-native tab control — with an overflow/scroll affordance built in from
the start so the strip scales past the ~812-tab breakdown point. (5b) Move ships as
*both* a "move to bank" / "send to bank" menu on the current selection (the precise,
MIDI-bindable front-end for the B3 move action) *and* drag-between-regions (the
direct-manipulation accelerator); copy stays the deliberate secondary act via the
menu. Drag mis-drop is mitigated by clear drop-target highlighting and is recoverable
by design (move is index-only and reversible). (See *Fork 5 — settled* below.)
--- ---
## Fork 5 — options for discussion, decision pending ## Fork 5 — settled (Daniel, 2026-07-23)
The one fork Daniel wants to weigh before deciding. Two sub-questions, both B4 Two sub-questions, both B4 panel-build mechanics — neither phase-defining, both
panel-build mechanics, neither phase-defining but both shaping the panel's feel. shaping the panel's feel. The full options analysis that produced these calls is
Nothing below is decided; the recommendations at the end are *pending Daniel's call*. retained below the decision for the record; the *decision* is what governs B4.
**Decision.**
- **5a — LICE-drawn custom tabs**, matching the M5 grid aesthetic and the Design View
`[ Arrange | Design ]` segmented-switch precedent. **Overflow/scroll is in scope from
the start** (chevron or scroll affordance), not deferred — a naive fixed-width LICE
strip breaks down at ~812 tabs, so the panel must scale from B4 onward.
- **5b — both a "move to bank" menu and drag-between-regions.** The menu is the precise,
MIDI-bindable front-end for the B3 move action; drag is the direct-manipulation
accelerator. Copy remains available as the deliberate secondary act, offered on the
menu. **Drag mis-drop is a designed-for property, not an afterthought:** the
destination region/tab shows clear drop-target highlighting during a drag, and because
move is index-only and move-is-default, a mis-drop is *recoverable* (the user moves the
sample back) rather than destructive — state this as the safety net, not a hope.
**Rationale (brief).** 5a: visual consistency across one coherent custom-drawn surface
plus full cross-platform certainty (we own every pixel, no SWELL tab-parity risk) beats
buying keyboard-nav/overflow from an inconsistent native widget; the segmented switch is
a partial precedent to extend. Overflow is pulled forward because banks routinely running
past a handful is plausible and a backfill after the naive strip ships would be a visible
cliff. 5b: the menu carries the precise/bindable path (and is the natural front-end for
the already-bindable B3 action, consistent with how the M5 grid and Design View act on
the current selection); drag serves users who prefer direct manipulation — the pattern
every media manager (Finder, Lightroom, Ableton browser) ships. The mis-drop hazard that
argued against drag-only is defused by highlighting + reversibility, so drag is safe as
the accelerator.
**Verify before building.** LICE tab drawing and any SWELL surface used for the
menu/drag hit-testing must be verified against the M5 reference and the SWELL/SDK headers
before use — even having chosen LICE, confirm what a native fallback would offer, and
confirm the drag hit-test doesn't collide with the M5 grid's existing multi-select drag.
---
## Fork 5 — options analysis (retained for the record)
The analysis that produced the decision above. Kept so the reasoning behind the
LICE-tabs / both-affordances calls doesn't have to be reconstructed.
### 5a — Named-banks tab rendering: SWELL-native tabs vs. LICE-drawn custom tabs ### 5a — Named-banks tab rendering: SWELL-native tabs vs. LICE-drawn custom tabs
@@ -500,7 +547,11 @@ primary; drag as the direct-manipulation accelerator for users who prefer it.
- **Cons:** most implementation cost (build both, and make them agree); drag still - **Cons:** most implementation cost (build both, and make them agree); drag still
carries its mis-drop risk even as a secondary path. carries its mis-drop risk even as a secondary path.
### Recommendations (pending Daniel's decision) ### Recommendations that fed the decision (now settled above)
These were the product-designer recommendations Daniel weighed; the settled record at
the top of Fork 5 is authoritative where it differs (notably 5b, which Daniel took all
the way to "both" with overflow and drop-highlighting pulled forward).
- **5a — recommend LICE-drawn custom tabs (Option B).** Visual consistency with the - **5a — recommend LICE-drawn custom tabs (Option B).** Visual consistency with the
M5 grid and the Design View segmented switch is worth the hand-rolled keyboard-nav M5 grid and the Design View segmented switch is worth the hand-rolled keyboard-nav