S12: editor scale + S15/S16 control surfaces
Pure browser_scroll/note_entry/param_slider modules (+ CTest) for scroll, type-to-filter search, numeric note entry, and the AHDSR/Trigger/pitch-engine/ pitch-env control panel. Editor shell draws + routes through them; params edit the selected zone's ZonePlayParams via commitAndReload.
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
// browser_scroll.h — PURE scroll + type-to-filter geometry LAYERED over the S10
|
||||
// capture_browser. NO VST3, NO REAPER, NO SWELL/LICE types at the boundary. The mirror of
|
||||
// capture_browser / editor_geometry: the fiddly scroll-window + scrollbar-thumb + search-box
|
||||
// arithmetic lives here, unit-tested outside the DAW, while the editor shell draws the
|
||||
// clipped card window + the scrollbar + the search field and routes wheel/drag/keystrokes
|
||||
// into these functions.
|
||||
//
|
||||
// WHY IT EXISTS (S12). capture_browser (S10) lays out EVERY card top-down and the shell
|
||||
// clips at the browser bottom — a bank longer than the panel runs off with no way to reach
|
||||
// it (the S12 gap). This module adds the two things S12 layers over that stable geometry:
|
||||
// * SCROLL — a vertical pixel offset into the card grid, with the max-offset clamp, the
|
||||
// visible-row window, a scrollbar thumb rect, and the thumb-drag<->offset mapping so a
|
||||
// wheel tick or a thumb drag reaches every card; and
|
||||
// * SEARCH — a name-substring filter (case-insensitive) that narrows the drawn cards,
|
||||
// COMPOSING with capture_browser's bank filter (the shell applies the bank filter first,
|
||||
// then this search narrows within it) + the search-box rect the shell draws the field in.
|
||||
//
|
||||
// It holds NO card data and draws nothing — it knows only the browser layout (from
|
||||
// capture_browser), COUNTS, and the scroll OFFSET the shell owns as transient UI state. It
|
||||
// reuses capture_browser's BrowserLayout + the shared Rect (one geometry idiom).
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "capture_browser.h" // BrowserLayout, cardCellRect, kBrowserCardHeight, Rect
|
||||
|
||||
namespace reasampler::vst {
|
||||
|
||||
// The width (px) of the vertical scrollbar gutter at the right edge of the grid. The shell
|
||||
// draws the track + thumb here and hit-tests thumb grabs against scrollThumbRect. Exposed so
|
||||
// the shell and tests agree. When the content fits (no scroll needed) the scrollbar is
|
||||
// suppressed (scrollThumbRect returns empty) and the shell may reclaim the gutter.
|
||||
inline constexpr int kScrollbarWidth = 10;
|
||||
|
||||
// The height (px) of the type-to-filter search box the shell draws ABOVE the tab strip (a
|
||||
// thin band spanning the browser width). Exposed so the shell reserves the band and tests
|
||||
// agree. capture_browser's tab strip + grid sit BELOW this band (the shell offsets the
|
||||
// BrowserLayout it feeds to capture_browser by kSearchBoxHeight).
|
||||
inline constexpr int kSearchBoxHeight = 22;
|
||||
|
||||
// The total pixel HEIGHT the card grid needs to draw all `cardCount` cards at `layout`'s
|
||||
// column count: the number of ROWS (ceil(cardCount / columns)) times the fixed cell height.
|
||||
// Zero cards -> 0. Pure — the content extent the scroll offset ranges over.
|
||||
int scrollContentHeight(const BrowserLayout& layout, int cardCount);
|
||||
|
||||
// The maximum scroll offset (px): content height minus the visible grid height, floored at 0.
|
||||
// When the content fits within the grid this is 0 (nothing to scroll). Pure — the clamp
|
||||
// ceiling for every offset the shell tracks.
|
||||
int scrollMaxOffset(const BrowserLayout& layout, int cardCount);
|
||||
|
||||
// Clamp a proposed scroll offset into [0, scrollMaxOffset]. The shell clamps after every wheel
|
||||
// tick / thumb drag so an over-scroll pins to an edge rather than showing past the last card
|
||||
// or above the first. Pure.
|
||||
int clampScrollOffset(const BrowserLayout& layout, int cardCount, int proposedOffset);
|
||||
|
||||
// The half-open range of card INDICES [first, last) at least partially visible in the grid at
|
||||
// scroll `offset`. The shell draws only these cards (the S12 clip window) rather than every
|
||||
// card. `offset` is assumed pre-clamped (the shell clamps on input); a first past the last row
|
||||
// yields an empty range (first==last==cardCount). Pure.
|
||||
struct VisibleRange {
|
||||
int first = 0; // first card index drawn (inclusive)
|
||||
int last = 0; // one past the last card index drawn (exclusive)
|
||||
};
|
||||
VisibleRange visibleCardRange(const BrowserLayout& layout, int cardCount, int offset);
|
||||
|
||||
// The cell rect of card `index` SHIFTED UP by the scroll offset, ready to draw (the shell
|
||||
// still adds the browser sub-area origin). Equivalent to capture_browser::cardCellRect with
|
||||
// the offset subtracted from top/bottom. Pure — the one place the offset applies to a card.
|
||||
Rect scrolledCardCellRect(const BrowserLayout& layout, int index, int offset);
|
||||
|
||||
// The vertical scrollbar THUMB rect within the grid's right-edge gutter, sized proportional to
|
||||
// the visible fraction (grid height / content height) and positioned proportional to the
|
||||
// scroll offset. Returns an EMPTY rect when the content fits (no scroll needed) — the shell
|
||||
// suppresses the scrollbar then. A minimum thumb height keeps a tiny thumb grabbable on a very
|
||||
// long bank. Pure — the geometry the shell draws + hit-tests the thumb grab against.
|
||||
Rect scrollThumbRect(const BrowserLayout& layout, int cardCount, int offset);
|
||||
|
||||
// Map a thumb-drag to a scroll offset. Given the offset the thumb held at grab time
|
||||
// (`startOffset`) and the vertical pixel delta since grab (`dyPixels`), returns the new
|
||||
// (clamped) scroll offset: startOffset shifted by the delta scaled from thumb-track pixels to
|
||||
// content pixels (a 1px thumb move covers content/track px of content). A degenerate track /
|
||||
// fitting content pins to startOffset. Pure — the inverse of scrollThumbRect's position map.
|
||||
int thumbDragToOffset(const BrowserLayout& layout, int cardCount, int startOffset, int dyPixels);
|
||||
|
||||
// The search-box rect: a full-width band of height kSearchBoxHeight at the TOP of the browser
|
||||
// area (above where capture_browser's tab strip draws). `w` is the browser sub-area width;
|
||||
// the shell adds its origin. A zero/negative width yields an empty rect. Pure.
|
||||
Rect searchBoxRect(int w);
|
||||
|
||||
// True iff `name` contains `query` as a case-insensitive ASCII substring. An EMPTY query
|
||||
// matches everything (the no-filter identity). Matching is ASCII case-folded (the display
|
||||
// names are ASCII until the Phase L type kit lands, mirroring the editor's other ASCII-only
|
||||
// text). Pure — the single match predicate the shell's search narrow is built from.
|
||||
bool nameMatchesQuery(const std::string& name, const std::string& query);
|
||||
|
||||
// Narrow a list of display `names` to the INDICES whose name matches `query`, preserving
|
||||
// order. An EMPTY query returns every index [0, names.size()) (the composition base so "bank
|
||||
// filter, no search" == today's browser). Kept name-only (indices, not card structs) so this
|
||||
// module stays free of the sample_map/bank_book chain — the shell owns the SampleChoice list
|
||||
// and applies the bank filter FIRST, then feeds the surviving display names here (search
|
||||
// narrows within the bank). Pure.
|
||||
std::vector<int> filterNameIndices(const std::vector<std::string>& names,
|
||||
const std::string& query);
|
||||
|
||||
} // namespace reasampler::vst
|
||||
Reference in New Issue
Block a user