#pragma once // sample_bands.h — THE band-stack allocator for the Sample face: the one module that owns // the editor's vertical inventory. Three bands, top to bottom — CHROME (toolbar + control // row), WAVEFORM (elastic, sized to hold two stacked channel lanes), DECKS (the knob-deck // row). Everything else in the editor fills a band it is handed; nothing else allocates // vertical space, so a band's owner can re-lay its interior without moving its neighbours. #include "core/instrument/ui/editor_geometry.h" // Rect namespace reasampler::instrument::ui { // Shared outer inset every band honours horizontally. inline constexpr int kPad = 8; // The editor's client-area floor, which IS its default size: the band stack is laid out for // exactly this, and there is no scroll, so anything smaller pushes the deck band off the // window bottom (computeSampleBands' waveform-floor-wins degrade). Growing is fine — the // waveform band is the elastic one. Both the enforced minimum and the opening rect read this. inline constexpr int kEditorMinWidth = 840; inline constexpr int kEditorMinHeight = 620; // Chrome band: the toolbar row (title + nav) stacked over the control row (piano strip, // preview, velocity knob, channel toggle). sample_chrome partitions it. inline constexpr int kTitleHeight = 26; inline constexpr int kChromeRowHeight = 52; // Waveform band floor: two stacked lanes plus the seam between them. The band never shrinks // below this — a window too short for it clips the bands beneath instead, so the waveform // stays a usable two-lane surface at every size. inline constexpr int kLaneMinHeight = 74; inline constexpr int kLaneGap = 2; inline constexpr int kWaveformMinHeight = 2 * kLaneMinHeight + kLaneGap; // Vertical seam between adjacent bands. inline constexpr int kBandGap = 4; // The vertical inventory. Bands never overlap and are returned top-to-bottom; a band may be // empty() on a degenerate window, in which case its owner draws and hit-tests nothing. struct SampleBands { Rect chrome; // full width: toolbar row + control row Rect waveform; // kPad-inset, elastic, >= kWaveformMinHeight Rect decks; // kPad-inset, bottom-anchored, height `deckHeight` }; // Divide a (w x h) client area into the three bands. `deckHeight` is the knob deck's own // wrapped height (from knob_deck) — the only interior measurement the allocator needs, so // the deck band is exactly as tall as its content. Pure. SampleBands computeSampleBands(int w, int h, int deckHeight); // The waveform band's two channel lanes: L above R, separated by kLaneGap. In mono only // `upper` is populated (it takes the whole band) and `lower` is empty — a mono capture has // no second lane to draw, and overlays that ride the waveform draw ONCE across the whole // band in either mode, never per lane. struct WaveformLanes { Rect upper; Rect lower; // empty() in mono }; // A RESOLVED lane-split decision, not "is the instrument in stereo mode" — a mono source // stays Single even in stereo mode (dual-mono, no second channel to draw). Only // waveformSurface (waveform_view) folds the source channel count in; a bare bool here would // let a caller pass isStereoMode straight through and skip that check. enum class LaneSplit { Single, Stereo }; WaveformLanes waveformLanes(const Rect& waveform, LaneSplit split); } // namespace reasampler::instrument::ui