# src/shell/panel — the docked bank-panel shell + the shared LICE draw kit ## Scope The REAPER-facing shell for the docked bank panel: the eight `bank_panel` split TUs (`panel_window` / `panel_layout` / `panel_render` / `panel_input` / `panel_drag` / `panel_thumbnails` / `panel_audition` / `panel_bank_ops`, sharing state via `panel_state.h`), plus `draw_kit`, the shared LICE draw shell also consumed by the VST3 editor (`shell/instrument/`). Pure layout/hit-test/palette modules the panel draws through (`theme`, `component_geometry`, `bank_grid`, `tab_strip`, `mode_switch`, `action_bar`, `footer_bar`, `overflow_menu`, `prune_button`, `mode_enable`, `insert_fx_enable`, `tooltip`, `card_drag`, `card_meta`) live in `core/ui` / `core/model` and are documented there — this directory consumes them but does not own them. The promptless bank-mutation verbs (`bankOpCreate`/`Rename`/`Delete`/… + `persistBankOp`) that `panel_bank_ops` skins live in `shell/bank_ops`, a sibling directory, not here. ## Invariants - **Draw through the kit, by palette ROLE, not hardcoded hue.** The shared LICE-based drawing kit is the one source of drawing for the whole system — a button, row, slider, or waveform looks identical in the bank panel, the embed strip, and the VST editor because it is the same kit function, drawn against palette roles (`bg/base`, `bg/panel`, `bg/cell`, `accent/primary`, `accent/secondary`, `accent/tertiary`, `accent/hot`, `text/primary`, `text/dim`, `line/hairline`, `warn`) rather than a literal color. The kit palette stays abstract (role→color, one constants block), so a whole visual direction is a single-file change (Phase L, DS-1/DS-2). - **Dock-panel layout is a thorough redesign, not a light re-skin (DS-3).** The panel lays out the full button/affordance inventory intuitively and uncluttered, then applies the kit — but this does **not** restructure the panel bones: the vertical-split / grid / tab structure is sound and stays as-is; a redesign designs the layout of the button inventory *around* it, not through it. - **What Phase L does not change (Precision / invariant implications):** - The pure/shell split holds — all layout/hit-test stays in pure CTest-covered geometry modules; the kit's *draw* half is shell, its *geometry* half is pure, even where a WDL piece is reused. No hit-test math moves into untestable code. - RT discipline is untouched — the kit is draw-thread only; nothing here touches `process` or any off-thread reload handoff (a VST3-instrument concern). - Read-only-over-bank is untouched — this is look-and-feel; no data-ownership change. - The capture/placement load-bearing principle is untouched — Phase L draws; it does not capture, place, or mutate the bank. - VST3 class UID / component-state contract is unchanged. - Windows-only (D5) — font/GDI/HFONT choices assume Windows; no cross-platform font-fallback concern. ## Modules - `bank_panel` (`shell/panel/`: `panel_window` / `panel_layout` / `panel_render` / `panel_input` / `panel_drag` / `panel_thumbnails` / `panel_audition` / `panel_bank_ops`, sharing state via `panel_state.h` — Q-W2 split of the former god-module into eight TUs) — docked LICE-drawn grid with three-zone layout: top toolbar (Capture → Placement, frequent acts only, via `action_bar`, short labels; Maintenance and the rarer Placement/Capture variants sit in the More (⋯) overflow menu via `overflow_menu`), bottom toolbar (four opposite-mode tag buttons + Show Both), and footer (`[Arrange|Design]` toggle, Tail button, Prune via `footer_bar`). Grid renders in sparse slot order with gap cells, drop dispatch, metadata overlay, and selection via `accent/tertiary` purple border. Draws through the L1 kit by palette role; OS drag-out via `drag_out` + `drag_out_win`. `panel_window` owns the SWELL dialog lifecycle + dialog proc + drop-target opt-in; `panel_layout` the toolbar/footer/menu rects + vertical-split geometry (the one geometry source both paint and hit-test read); `panel_render` the WM_PAINT draw; `panel_input` click/wheel/keyboard routing + the new-content auto-tag timer; `panel_drag` the hover + card-drag state machine + drop dispatch; `panel_thumbnails` the PCM→envelope thumbnail cache + the bank-change fingerprint pass; `panel_audition` the preview-playback engine; `panel_bank_ops` the menu/prompt UX skin over the promptless `shell/bank_ops` verbs. `draw_kit` (shared with the VST3 editor) stays a separate TU. - `panel_window` — SWELL dialog lifecycle + dialog proc + drop-target opt-in. The drop splits by extension: a `.rsbank` is a whole bank and routes to the package-import action (one NEW bank each), everything else keeps the audio-ingest route. - `panel_layout` — toolbar/footer/menu rects + vertical-split geometry (the one geometry source both paint and hit-test read). - `panel_render` — the WM_PAINT draw. - `panel_input` — click/wheel/keyboard routing + the new-content auto-tag timer. - `panel_drag` — the hover + card-drag state machine + drop dispatch. - `panel_thumbnails` — the PCM→envelope thumbnail cache + the bank-change fingerprint pass. - `panel_audition` — the preview-playback engine. - `panel_bank_ops` — the menu/prompt UX skin over the promptless `shell/bank_ops` verbs. - `draw_kit` — shared LICE draw shell: `fillSurface`, `drawButton`/`drawSlider`/`drawListRow`/`drawWaveform`, cached-font `text()`, full interaction-state model, double-buffer preserved. Consumes `theme` + `component_geometry`. Its antialiasing contract — which surfaces alias, which cannot, and the LICE primitive each answers with — is the disposition table in `docs/product/visual-design-language.md` §8, which governs `drawWaveform` as much as this doc does. `drawWaveform`'s per-column vertical arithmetic is NOT here: it is the pure, unit-tested `component_geometry::waveformBand`/`waveformColumnSpan` pair, because this TU is DAW-verified and not unit-tested. ## Gotchas - **No external UI framework.** iPlug2 / JUCE / VSTGUI are rejected (DS-1). LICE + reused WDL pieces are the toolkit; reject any path that pulls in a new framework. - **No hit-test geometry in untestable shell code.** Even when reusing a WDL piece (e.g. a `vwnd` control for a long scroll list), layout/hit-test math stays in pure CTest-covered modules — do not import a WDL control's retained-mode object model wholesale, since its controls own their hit-test internally and that would move geometry into untestable shell code. - Verify every LICE/WDL/SWELL API name/signature against `vendor/WDL` before use.