Files
reasampler/src/core/instrument/ui/sample_bands.h
T

79 lines
4.2 KiB
C++

#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.
//
// The width is a LITERAL here on purpose, though it is derived from knob_deck's width budget:
// this allocator is deliberately independent of the deck (it takes deckHeight as a parameter
// for exactly that reason), so the derivation is asserted in test_deck_groups.cpp — the one
// place that already includes both headers — rather than coded as an include edge.
inline constexpr int kEditorMinWidth = 1190;
inline constexpr int kEditorMinHeight = 680;
// The hard ceiling the floor above may not exceed; the window itself still grows freely above
// it. A window fact, sibling of kEditorMinWidth/kEditorMinHeight, not a deck one — moved here
// from knob_deck.h for that reason. The gap to the floor (today: 90px) is the deck's whole
// width budget, spent once; the identity is asserted in test_deck_groups.cpp, the one place
// that already includes both this header and knob_deck.h.
inline constexpr int kEditorCeilingWidth = 1280;
// 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 = 64;
// 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