f3be4d8cce
capture.h realtime seam split to capture_realtime_shell.h; GetProjExtState grow-loop rehomed to core/wire/ext_state_read; stale persist.cpp/bank_panel.cpp comment refs fixed; CLAUDE.md persist/bank_book/actions bullets updated. Command-id suffixes, display phrases, and undo labels byte-identical.
83 lines
5.3 KiB
C++
83 lines
5.3 KiB
C++
#pragma once
|
|
#include "core/ui/rect.h"
|
|
// prune_button — the REAPER-free layout math behind the bank_panel's Prune button
|
|
// (Phase R, Wave 3 — R3, fork R-E). A single labelled button drawn in the panel's
|
|
// tail-footer strip that fires the "Prune bank folder" command. The panel shell
|
|
// (shell/panel/) owns the SWELL window, LICE drawing, and the Main_OnCommand
|
|
// dispatch of the registered command id — all REAPER-bound, DAW-verified. What is
|
|
// NOT DAW-bound — WHERE the button sits in the footer and whether a click lands on
|
|
// it — lives here so it is unit-tested outside the DAW (CLAUDE.md §load-bearing
|
|
// split). Mirror of mode_switch / tab_strip.
|
|
//
|
|
// PURE MODULE: NO REAPER types, NO SWELL, NO vendor/ includes. Standard library
|
|
// only. Builds and unit-tests without REAPER.
|
|
//
|
|
// -- Placement contract --------------------------------------------------------
|
|
//
|
|
// The footer hosts (L4) a LEFT group — the [Arrange|Design] mode toggle, a per-mode
|
|
// count, and the Tail button (bank_panel footer_bar) — and a RIGHT-aligned version
|
|
// readout (bank_panel drawFooter). The prune button is a fixed-width button anchored
|
|
// to the RIGHT of the footer, inset from the right edge, sitting just LEFT of the
|
|
// version readout's inset region and set APART from the benign left group. It never
|
|
// overlaps the left group (footer_bar reserves rightReserve px at the right to match).
|
|
// When the footer is too narrow to fit the button without colliding with the left
|
|
// inset, the button is suppressed (empty rect) rather than drawn on top — the action
|
|
// is always reachable via its bindable command, so a hidden button is a graceful
|
|
// degradation, not a lost affordance.
|
|
|
|
namespace reasampler::ui {
|
|
|
|
// The footer strip the button is drawn into, top-left origin (SWELL/LICE
|
|
// convention). (x, y) is the top-left corner; width/height are the strip extents.
|
|
// bank_panel derives this from panelFooter() and passes it here.
|
|
using FooterRect = Rect; // Q-W1: the shared concrete ui::Rect (core/ui/rect.h), role-aliased
|
|
|
|
// A button's pixel rectangle within the footer, top-left origin. A zero-area rect
|
|
// (width <= 0 or height <= 0) means "no button" — the footer is too narrow to place
|
|
// it, or the footer itself is degenerate; the caller must not draw or hit-test it.
|
|
using ButtonRect = Rect; // Q-W1: the shared concrete ui::Rect (core/ui/rect.h), role-aliased
|
|
|
|
// Layout inputs for the prune button, in pixels. Defaults match the bank_panel footer
|
|
// metrics; the shell passes its own so draw and hit-test share one source of truth.
|
|
// * buttonWidth — the button's fixed width.
|
|
// * rightInset — gap from the footer's right edge to the button's right edge (the
|
|
// button sits left of this inset, clearing the right-aligned version
|
|
// readout). COUPLED TO drawFooter (panel_render.cpp): the version readout
|
|
// uses an 8 px right margin. The button's right edge lands at
|
|
// footer.right - 84, i.e. 76 px left of the readout's right margin —
|
|
// enough clearance for the ~10-char label. ALSO COUPLED to
|
|
// FooterBarSpec::rightReserve (footer_bar.h): the L4 footer-left group
|
|
// (mode toggle + count + Tail) reserves that many px at the right so it
|
|
// never runs under this button; rightReserve must exceed rightInset +
|
|
// buttonWidth. If the version readout's inset changes in drawFooter,
|
|
// update this value to maintain clearance.
|
|
// * verticalInset — top/bottom gap inside the footer (the button is shorter than the
|
|
// strip so it reads as a raised control, not a full-height fill).
|
|
// * minLeftInset — the button's left edge must stay at least this far from the footer
|
|
// left edge (reserving room for the L4 footer-left group). If the button
|
|
// would encroach past this, computePruneButton yields an empty rect
|
|
// (button suppressed — see header placement contract).
|
|
struct PruneButtonSpec {
|
|
int buttonWidth = 72;
|
|
int rightInset = 84; // COUPLED: version readout in drawFooter uses an 8 px right margin
|
|
int verticalInset = 4;
|
|
int minLeftInset = 120;
|
|
};
|
|
|
|
// Computes the prune button's rect within `footer` per `spec`. Right-anchored: the
|
|
// button's right edge is footer.x + footer.width - rightInset, its width is buttonWidth,
|
|
// and it is vertically centred by verticalInset. Returns an EMPTY rect (button
|
|
// suppressed) when: the footer is degenerate (width/height <= 0), OR the resulting left
|
|
// edge would fall closer to the footer left than minLeftInset (too narrow to place
|
|
// without colliding with the tail label). The action stays reachable via its command in
|
|
// that case — a suppressed button is graceful, not a lost feature.
|
|
ButtonRect computePruneButton(const FooterRect& footer, const PruneButtonSpec& spec);
|
|
|
|
// True iff the point (px, py) (SWELL/LICE top-left client coords) falls inside `button`.
|
|
// Half-open bounds [x, x+width) x [y, y+height) — matches computePruneButton so draw and
|
|
// hit-test agree on the same pixels. An empty button never claims a point (always false),
|
|
// so a suppressed button cannot be accidentally clicked.
|
|
bool hitTestPruneButton(int px, int py, const ButtonRect& button);
|
|
|
|
} // namespace reasampler::ui
|