54f37be0bb
New pure action_bar module (clusters, keybinding sub-labels, overflow, hit-test) supersedes the flat M11 strip; bank_panel chrome/buttons/tabs/grid now draw through the L1 kit by role with hover. Expose draw_kit::toLice in header to fix drawThumbnail forward-refs. CTest 27/27.
127 lines
7.4 KiB
C++
127 lines
7.4 KiB
C++
#pragma once
|
|
// draw_kit — the LICE-facing SHELL half of the shared drawing kit (Phase L, L1). This is
|
|
// the ONE source of drawing for the whole system: every surface (bank_panel now; the VST
|
|
// editor + embed strip at L3) fills, buttons, rows, sliders, waveforms, and — above all —
|
|
// draws TEXT through this kit, so a control looks identical everywhere because it is the
|
|
// same kit function. It replaces the flat LICE_FillRect blocks and raw-GDI DrawTextA with
|
|
// gradient/AA surfaces (the vwnd micro-gradient + inner highlight/shadow trick) and cached
|
|
// anti-aliased text (LICE_CachedFont), honoring the interaction-state model.
|
|
//
|
|
// PURE/SHELL SPLIT (CLAUDE.md §load-bearing): this file is SHELL — it touches LICE and
|
|
// SWELL (HFONT). All palette decisions come from the pure `theme` module (role -> KitColor);
|
|
// all layout/hit-test from the pure `component_geometry` / mode_switch / etc. modules. This
|
|
// file only turns those pure answers into LICE calls. It is DAW-verified, not unit-tested.
|
|
//
|
|
// FONT LIFECYCLE (owned here): the kit holds a small set of LICE_CachedFonts (title / label
|
|
// / value-mono / micro). kitFontsInit() creates them once (from HFONTs handed off with
|
|
// LICE_FONT_FLAG_OWNS_HFONT, so the cached font frees the HFONT itself — verified in
|
|
// lice_text.h §SetFromHFont doc: "OWNS means LICE_IFont will clean up hfont on font change
|
|
// or exit"). kitFontsShutdown() deletes the cached fonts. The consumer calls init on panel
|
|
// open and shutdown on close/teardown. text() no-ops safely before init (defensive), so a
|
|
// draw that races construction never crashes.
|
|
//
|
|
// DOUBLE-BUFFER DISCIPLINE (§3.5 "zero-jank"): every function here draws into the caller's
|
|
// offscreen LICE_IBitmap; the caller BitBlt's once. Nothing here draws direct-to-DC.
|
|
|
|
#include "component_geometry.h" // KitBox / SliderGeometry — the pure geometry the shell draws
|
|
#include "peaks.h" // Envelope — the waveform primitive's input
|
|
#include "theme.h" // Role / InteractionState / KitColor / TextClass
|
|
|
|
// LICE types at the boundary (this is the shell half). LICE_IBitmap is forward-declared
|
|
// to keep the header light. LICE_pixel is a typedef (unsigned int) — not forward-declarable
|
|
// — so the full lice.h is included only for the toLice() declaration; on Windows lice.h
|
|
// pulls in <windows.h>, which is fine since draw_kit.h is shell-only and never included by
|
|
// a pure module.
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#endif
|
|
#include "lice/lice.h"
|
|
class LICE_IBitmap;
|
|
|
|
namespace reasampler {
|
|
|
|
// The kit's four cached fonts (§3.1 type scale). Consumers pass a Font to text() to pick
|
|
// the size/weight; the kit maps it to the matching LICE_CachedFont.
|
|
enum class Font {
|
|
Title, // ~15px semibold — region titles, headings
|
|
Label, // ~12px regular — labels, body
|
|
ValueMono, // ~12px tabular/mono — numbers (dB/ms/notes) that must not jitter
|
|
Micro, // ~10px dim — units, counts, keybinding sub-labels
|
|
};
|
|
|
|
// Horizontal text alignment for text(). Vertical is always centered in the rect (the kit's
|
|
// single-line convention); a caller wanting multi-line composes rows itself.
|
|
enum class Align { Left, Center, Right };
|
|
|
|
// --- KitColor → LICE_pixel conversion ----------------------------------------
|
|
|
|
// The one place a pure KitColor becomes a LICE_pixel. Declared here so any shell
|
|
// translation unit that already includes draw_kit.h can use it without duplicating
|
|
// the LICE_RGBA packing. Defined in draw_kit.cpp.
|
|
LICE_pixel toLice(const KitColor& c);
|
|
|
|
// --- Font lifecycle (owned by the kit) ---------------------------------------
|
|
|
|
// Creates the four cached fonts once. Idempotent: a second call before shutdown is a no-op
|
|
// (the kit already holds live fonts). Safe to call on every panel open. Uses the platform
|
|
// UI sans (Segoe UI) for title/label/micro and a tabular mono (Consolas) for value-mono;
|
|
// the exact HFONT is created here, so a face change is a one-line edit. NO-OP-SAFE: if font
|
|
// creation fails, text() degrades to drawing nothing rather than crashing.
|
|
void kitFontsInit();
|
|
|
|
// Deletes the cached fonts (which free their owned HFONTs — LICE_FONT_FLAG_OWNS_HFONT).
|
|
// Idempotent. The consumer calls this on panel close / extension shutdown.
|
|
void kitFontsShutdown();
|
|
|
|
// --- Text (the single biggest "temple os -> modern" lever) -------------------
|
|
|
|
// Draws a single line of AA cached-font text in `color` inside `box`, horizontally aligned
|
|
// per `align` and vertically centered, clipped with an end-ellipsis. This REPLACES the
|
|
// GDI SetTextColor + DrawText path. No-op (safe) before kitFontsInit() or on a null bitmap.
|
|
void text(LICE_IBitmap* bmp, const KitBox& box, const char* str,
|
|
Font font, const KitColor& color, Align align);
|
|
|
|
// Convenience overload: text in a palette ROLE's color (the common case — the shell almost
|
|
// always wants text/primary or text/dim, not a raw color).
|
|
void text(LICE_IBitmap* bmp, const KitBox& box, const char* str,
|
|
Font font, Role role, Align align);
|
|
|
|
// --- Surfaces + components ----------------------------------------------------
|
|
|
|
// The kit's foundational fill: a micro-gradient (a few percent lighter at the top, via
|
|
// LICE_GradRect) plus a 1px inner top-highlight and bottom-shadow — the vwnd trick that
|
|
// kills the flat look (§2.2). Every button/row/cell fills through this so elevation reads
|
|
// without a border. `role` picks the surface color; `state` transforms it per the
|
|
// interaction model (hover lightens, pressed darkens, disabled desaturates, etc.).
|
|
void fillSurface(LICE_IBitmap* bmp, const KitBox& box, Role role, InteractionState state);
|
|
|
|
// A rounded, gradient-filled button with the inner highlight/shadow and a centered label,
|
|
// honoring the interaction state. `warn == true` swaps the surface to the warn role (for
|
|
// byte-deleting verbs like prune/delete) — the only place warn is drawn. A degenerate box
|
|
// is a no-op.
|
|
void drawButton(LICE_IBitmap* bmp, const KitButtonBox& button, const char* label,
|
|
InteractionState state, bool warn);
|
|
|
|
// A horizontal slider: the track groove, the accent-filled portion up to the handle, and
|
|
// the handle (a raised knob honoring state — hover/dragging brighten it). `geom` is the
|
|
// pure SliderGeometry the caller computed; the kit only draws it. Degenerate geom is a no-op.
|
|
void drawSlider(LICE_IBitmap* bmp, const SliderGeometry& geom, InteractionState state);
|
|
|
|
// A selectable list row: the row surface (rest/hover/active/focus via state), an optional
|
|
// leading thumbnail area reserved at `thumbWidth` px (0 for none — the caller draws the
|
|
// thumbnail into the returned-by-convention left inset), and a left-aligned label in the
|
|
// remaining width. Focus draws a 1px text/primary ring distinct from the accent selection
|
|
// fill. A degenerate row is a no-op.
|
|
void drawListRow(LICE_IBitmap* bmp, const ListRowBox& row, const char* label,
|
|
int thumbWidth, InteractionState state);
|
|
|
|
// A waveform envelope drawn as a min/max column plot over the bg/panel surface: a midline
|
|
// per channel and an accent vertical line per bin (the same shape the panel thumbnail
|
|
// draws, lifted into the kit so the panel and the L3 editor waveform share it). `box` is
|
|
// the draw region; `env` is the per-channel min/max envelope from peaks::computeEnvelope.
|
|
// An empty env draws just the midline. The caller fills the surface first (or passes a box
|
|
// already filled); this draws only the wave + midline.
|
|
void drawWaveform(LICE_IBitmap* bmp, const KitBox& box, const Envelope& env);
|
|
|
|
} // namespace reasampler
|