diff --git a/CLAUDE.md b/CLAUDE.md index 8ba15e2..9c6c67a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Repo identity and current state -The CMake project and binary are now named `reaper_reasampler`. This is **ReaSampler** — a per-project audio sample-bank capture tool. The MPE modules (`mpe_model`, `mpe_view`) have been removed. M0–M8 are complete (bank_model, peaks, capture offline+realtime, persist, bank_panel, insert, capture action family, RealtimeRecordBackend, tail T1+T2+T1-followons). Phase B multi-bank (B1–B5, B-cap), Phase D1/D2 Design View (D1–D5, D2-W1–W3-B), Phase V versioning/beta-channel (V1/V3, V4), M10 provenance + re-capture from source, Phase R Reclaim (R1–R3: prune-reconcile core, dry-run shell, guarded deletion + action + panel button), and M11 in full (batch capture, action-button strip + keybinding labels, conform-on-insert verified-extant, native OS drag-out) have all landed. M9 slots deferred indefinitely. The *discipline* — pure REAPER-free testable core split from REAPER-facing shells — is **preserved** throughout. +The CMake project and binary are now named `reaper_reasampler`. This is **ReaSampler** — a per-project audio sample-bank capture tool. The MPE modules (`mpe_model`, `mpe_view`) have been removed. M0–M8 are complete (bank_model, peaks, capture offline+realtime, persist, bank_panel, insert, capture action family, RealtimeRecordBackend, tail T1+T2+T1-followons). Phase B multi-bank (B1–B5, B-cap), Phase D1/D2 Design View (D1–D5, D2-W1–W3-B), Phase V versioning/beta-channel (V1/V3, V4), M10 provenance + re-capture from source, Phase R Reclaim (R1–R3: prune-reconcile core, dry-run shell, guarded deletion + action + panel button), M11 in full (batch capture, action-button strip + keybinding labels, conform-on-insert verified-extant, native OS drag-out), and Phase L wave 1 L1 (shared LICE drawing kit: `theme`/palette module, `component_geometry` geometry helpers, `draw_kit` shell, GDI DrawText retired in `bank_panel`) have all landed. M9 slots deferred indefinitely. The *discipline* — pure REAPER-free testable core split from REAPER-facing shells — is **preserved** throughout. CONTEXT.md is the authoritative spec and build roadmap. Read it first for any non-trivial task. Every REAPER API name cited there is correct-by-intent; verify argument order, types, and flag values against `vendor/reaper-sdk/sdk/reaper_plugin_functions.h` before use. @@ -42,6 +42,8 @@ Key targets (see CMakeLists.txt for the full list): | `batch_capture_tests` | executable | Pure unit tests for `batch_capture` — no REAPER, no DAW. | | `action_buttons_tests` | executable | Pure unit tests for `action_buttons` — no REAPER, no DAW. | | `drag_out_tests` | executable | Pure unit tests for `drag_out` — no REAPER, no DAW. | +| `theme_tests` | executable | Pure unit tests for `theme` — no REAPER, no DAW. | +| `component_geometry_tests` | executable | Pure unit tests for `component_geometry` — no REAPER, no DAW. | | `reaper_reasampler` | loadable module | The actual extension binary (`.dll` / `.dylib` / `.so`). | ### Beta channel build (Phase V, V4) @@ -83,6 +85,8 @@ There is no hot-reload. Copy the built binary into REAPER's `UserPlugins/` folde - `batch_capture` — M11 pure batch-capture planner: maps a list of source ranges to ordinal capture units, drives per-unit capture via a shared `captureAndIndexOne` helper, and aggregates mixed results. No REAPER types at the boundary. - `action_buttons` — M11 pure action-button strip layout/hit-test: divides a strip rect into N action buttons, min-width overflow-hiding, label formatting with "(unbound)" fallback, `ActionButtonRect` struct. Mirror of `mode_switch` / `bank_grid`. - `drag_out` — M11 pure OS drag-out module: gesture-boundary decision (internal drag becomes OS-bound when the pointer leaves the panel client rect), path-list assembly with dedupe and missing-file skip. No REAPER types at the boundary. +- `theme` — Phase L pure palette module (L1): role→color mapping via one constants block (Direction B Neon Console + Direction C spectral, DS-2); WCAG contrast-floor helpers; interaction-state color model; spectral ramp. No LICE or REAPER types. +- `component_geometry` — Phase L pure component geometry/hit-test helpers (L1): button/slider/list-row geometry + hover hit-test. No LICE or REAPER types. Mirror of `mode_switch`/`bank_grid`. **REAPER-facing shells:** - `capture` — `ICaptureBackend` interface; `OfflineRenderBackend` (deterministic default) and `RealtimeRecordBackend`. Input: `CaptureRequest`. Output: finished file + populated `Sample` handed to `bank_model`. @@ -93,6 +97,7 @@ There is no hot-reload. Copy the built binary into REAPER's `UserPlugins/` folde - `track_guid` — shared `MediaTrack*` → canonical GUID-string formatter; single source of truth for membership keys used by both the view shell and the actions layer. - `provenance_shell` — FX-chain identity queries via `TrackFX_*` / `TakeFX_*` APIs; collects source-item paths and parent-detection inputs to feed the pure `provenance` fingerprint builder. Stamps `Sample.provenance` on capture when every resolving source item maps by exact normalized path (case-folded on Windows) to exactly one bank sample; ambiguous/mixed cases record nothing conservatively. - `drag_out_win` — M11 OS drag-out shell: Windows OLE `DoDragDrop` / `CF_HDROP`, copy-only structurally (`DROPEFFECT_MOVE` not offered, no source-deletion path); macOS/Linux via `SWELL_InitiateDragDropOfFileList` (copy-semantics caveat documented — SWELL does not expose a drop-effect query). Driven by the `drag_out` pure module. +- `draw_kit` — Phase L shared LICE draw shell (L1): `fillSurface` (micro-gradient + inner highlight/shadow), `drawButton`/`drawSlider`/`drawListRow`/`drawWaveform`, cached-font `text()` over four `LICE_CachedFont`s (kit-owned lifecycle), full interaction-state model, double-buffer preserved. Consumes `theme` + `component_geometry`. First consumer: `bank_panel` (GDI `DrawText` path retired in L1). - `actions` — registers the capture/placement/slot action family, the Design View action family (toggle active mode, activate Arrange/Design, tag/untag selected tracks, show-both), the multi-bank action family (create/rename/reorder/delete bank, evacuate, activate, move/copy/remove selected samples), and the Phase R prune action (`BANK_PRUNE_FOLDER` — dry-run-first, confirm-with-manifest, then `pruneDeletePlan`-guarded deletion; **the ONLY file-deletion authority in the system**); routes each to the modules above via the `command_id`/`gaccel`/`hookcommand` contract. Every bank index verb wraps its mutation in a batched REAPER undo point (`Undo_BeginBlock2`/`EndBlock2`, `UNDO_STATE_MISCCFG`) so one bank operation is one Ctrl-Z. The prune action writes no ext state and opens no undo point (file deletion is not REAPER-undoable). ## REAPER extension contract (src/main.cpp) diff --git a/COMPLETED.md b/COMPLETED.md index a8b4b44..4758e3b 100644 --- a/COMPLETED.md +++ b/COMPLETED.md @@ -1240,3 +1240,36 @@ deletion on drop); internal move/copy drag unchanged. Both docs of record: `docs/product/removal-and-prune.md` §Fork R-C/R-D/R-E and CONTEXT.md §Prune (Settled forks). + +--- + +# Phase L — Look-and-feel (system-wide visual design language) + +> Separate phase namespace. Namespaced **`L` (Look-and-feel)**, orthogonal to and ungated +> by the M/D/B/R/V/S pillars. Authoritative spec: **CONTEXT.md §Phase L**. Product +> framing + settled decisions (DS-1/DS-2/DS-3): `docs/product/visual-design-language.md`. + +## L1 — shared LICE drawing kit (the foundation) +**Goal:** Stand up the shared LICE-based drawing kit that every Phase L surface (L2 dock +panel, L3 VST editor) consumes — palette/theme module, pure component geometry/hit-test +helpers, LICE draw shell, and retirement of the GDI `DrawText` path in `bank_panel`. +CONTEXT.md §Phase L (Kit architecture). DS-1 (LICE + WDL, no external frameworks) and +DS-2 (Direction B Neon Console + Direction C spectral) are the governing settled decisions. +**Verify:** CTest green (`theme_tests`, `component_geometry_tests`). Each text-on-surface +pair in the palette clears its WCAG floor (tested). `bank_panel` text routes through +cached-font `text()` — GDI `DrawText` path retired. Double-buffer discipline preserved. + +- [x] **`theme`/palette module** (`src/theme.{h,cpp}`): role→color mapping via one + constants block (Direction B Neon Console + Direction C spectral, DS-2); WCAG + contrast-floor helpers + tests; interaction-state color model; spectral ramp. Pure; + no LICE types. New CTest target `theme_tests`. +- [x] **`component_geometry` module** (`src/component_geometry.{h,cpp}`): button/slider/ + list-row geometry + hover hit-test. Pure; no LICE or REAPER types. New CTest target + `component_geometry_tests`. +- [x] **`draw_kit` shell** (`src/draw_kit.{h,cpp}`): LICE draw layer — `fillSurface` + (micro-gradient + inner highlight/shadow), `drawButton`/`drawSlider`/`drawListRow`/ + `drawWaveform`, cached-font `text()` over four `LICE_CachedFont`s (kit-owned lifecycle), + full interaction-state model, double-buffer preserved. +- [x] **GDI `DrawText` retirement in `bank_panel`**: all panel text now routes through the + kit's cached-font `text()`; raw GDI `DrawText` path retired (the single biggest + "temple os → modern" lever). diff --git a/PLAN.md b/PLAN.md index aedc900..cf749aa 100644 --- a/PLAN.md +++ b/PLAN.md @@ -284,6 +284,10 @@ build:** the `IReaperUIEmbedInterface` contract + embed message/lifecycle agains > directions: `docs/product/visual-design-language.md`. When a point lands, doc-keeper > moves it to `COMPLETED.md`. > +> **L1 (shared LICE drawing kit — the foundation) has landed** — `theme`/palette module, +> `component_geometry` geometry/hit-test helpers, `draw_kit` shell, and GDI `DrawText` +> retirement in `bank_panel`. See `COMPLETED.md`. **L2 and L3 remain.** +> > **This section is self-contained for a team without Phase S context.** Where a point > touches a Phase S surface (the VST editor, the embed strip, the keyboard strip), the > gate is stated explicitly so the team does not chase files that are not on dev yet. @@ -304,48 +308,6 @@ build:** the `IReaperUIEmbedInterface` contract + embed message/lifecycle agains > out the full button inventory (including M11's action-button additions) intuitively, > uncluttered, and useful — then applies the kit. Sequenced after M11 merges. -## L1 — shared LICE drawing kit (the foundation) -**Goal:** One shared **LICE-based design kit** — a role-based palette + a type scale + a -component-draw layer — that every surface (the bank panel now, the VST editor + embed -strip later) draws through, replacing flat `LICE_FillRect` blocks and raw-GDI `DrawTextA` -with a modern dark look: gradient surfaces (`LICE_GradRect`), anti-aliased rounded controls -(`LICE_RoundRect`/`LICE_Line`), cached anti-aliased text (`LICE_CachedFont`), and a full -interaction-state model (rest/hover/active/pressed/dragging/focus/disabled) the current -drawing lacks entirely. The B+spectral palette constants (DS-2) live in one constants block. -No new dependency — LICE is the toolkit; WDL/vwnd reuse is assessed at build time per DS-1 -("don't reinvent the wheel"). CONTEXT.md §Phase L (design-system spec). Product framing + -palette + directions + forks: `docs/product/visual-design-language.md`. **Verify LICE -gradient/AA/font surfaces and the `LICE_CachedFont`↔`HFONT` lifecycle against -`vendor/WDL/WDL/lice/lice.h` + `lice_text.h` before use.** -**Verify:** CTest green on the pure layer (the theme/palette contrast-floor tests + the -component geometry/hit-test helpers); in-DAW, the kit renders a modern dark button/row/ -surface with AA cached-font text and working hover/pressed states, drawn double-buffered -with no flicker. -**Depends on:** the existing `bank_panel` LICE surface (the first consumer). Nothing in -Phase S — L1 stands alone on the extension side. - -- [ ] Pure `theme`/palette layer: role→color mapping (`bg/base`, `bg/panel`, `bg/cell`, - `text/primary`, `text/dim`, `accent`, `accent/hot`, `warn`) selected via **one direction - constants block** carrying the settled **B (Neon Console) + C spectral** values (DS-2), - so the direction is a single-file change. Unit-test that each text-on-surface pair clears - its WCAG floor (AA 4.5:1 body / 3:1 large + state indicators) — the "punch to the floor, - not past it" rule made testable. No LICE/host types. -- [ ] Pure component **geometry/hit-test** helpers where not already owned: button rect, - slider track/handle geometry, list-row rect + hover hit-test (mirror of - `mode_switch`/`bank_grid`/`editor_geometry` — no LICE, no host types, CTest-covered). -- [ ] Shell **draw kit** (LICE): `fillSurface` (micro-gradient + 1px inner highlight/shadow - — the vwnd trick that kills the flat look), `drawButton`/`drawSlider`/`drawListRow`/ - `drawWaveform`/segmented-switch/tab draw, and a shared `text()` over a cached - `LICE_CachedFont` set (title/label/value-mono/micro). Owns the cached-font lifecycle. - Honors the interaction state model (rest/hover/active/pressed/dragging/focus/disabled). - Double-buffered draw preserved (draw to `LICE_SysBitmap`, single `BitBlt`) — the - "zero-jank" half of "speed is the selling point." **DS-1: assess WDL/vwnd reuse here at - build time** — reuse a vwnd piece (e.g. its scroll listbox) where genuinely cheaper than - LICE, else draw on LICE; keep hit-test geometry in the pure layer either way. -- [ ] Retire the raw GDI `DrawText` path in `bank_panel` in favor of the kit's cached-font - `text()` — the single biggest "temple os → modern" lever. (The VST-editor/embed-strip GDI - retirement is L3, gated on Phase S — see below.) - ## L2 — dock-panel layout redesign (extension-side; DS-3: thorough, not a re-skin) **Goal:** Redesign the docked `bank_panel` **layout** to house the *full* button/affordance inventory — including the buttons **M11 adds** — intuitively, uncluttered, and useful, then