Q-W1 pt2: core/shell/app relocation + sub-namespaces; one concrete ui::Rect (LTRB fork retired); slot_map split from bank_book; BankIndex→BankModel; 59/59 green
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
// footer_bar — pure implementation. See footer_bar.h. NO REAPER / SWELL / LICE / vendor.
|
||||
|
||||
#include "core/ui/footer_bar.h"
|
||||
|
||||
namespace reasampler::ui {
|
||||
|
||||
namespace {
|
||||
|
||||
// True iff a box [x, x+width) fits entirely left of `rightBound` (its right edge does not
|
||||
// cross the reserved right region). A non-positive width never "fits" (nothing to place).
|
||||
bool fitsLeftOf(int x, int width, int rightBound) {
|
||||
return width > 0 && x + width <= rightBound;
|
||||
}
|
||||
|
||||
bool pointIn(int px, int py, const FooterBarRect& r) {
|
||||
return !r.empty() && px >= r.x && px < r.x + r.width && py >= r.y && py < r.y + r.height;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
FooterBarLayout computeFooterBar(const FooterRect& footer, const FooterBarSpec& spec) {
|
||||
FooterBarLayout out;
|
||||
if (footer.width <= 0 || footer.height <= 0) return out;
|
||||
|
||||
const int top = footer.y + spec.verticalInset;
|
||||
const int boxH = footer.height - 2 * spec.verticalInset;
|
||||
if (boxH <= 0) return out;
|
||||
|
||||
// The right bound the LEFT group must stay clear of (prune + version region). Clamp so a
|
||||
// pathologically large rightReserve never yields a negative bound.
|
||||
int rightBound = footer.x + footer.width - spec.rightReserve;
|
||||
if (rightBound < footer.x) rightBound = footer.x;
|
||||
|
||||
int cursorX = footer.x + spec.leftPad;
|
||||
|
||||
// Toggle (most important — placed first, drops last).
|
||||
if (fitsLeftOf(cursorX, spec.toggleWidth, rightBound)) {
|
||||
out.toggle = FooterBarRect{cursorX, top, spec.toggleWidth, boxH};
|
||||
cursorX += spec.toggleWidth + spec.gap;
|
||||
} else {
|
||||
return out; // no room for even the toggle — nothing else can fit either
|
||||
}
|
||||
|
||||
// Count label (passive readout). Suppressed by countWidth <= 0 (no gap consumed then).
|
||||
if (spec.countWidth > 0) {
|
||||
if (fitsLeftOf(cursorX, spec.countWidth, rightBound)) {
|
||||
out.count = FooterBarRect{cursorX, top, spec.countWidth, boxH};
|
||||
cursorX += spec.countWidth + spec.gap;
|
||||
}
|
||||
// If the count does not fit, do NOT advance the cursor past it — the Tail button then
|
||||
// gets its chance at the same slot (a passive label yields to the interactive button).
|
||||
}
|
||||
|
||||
// Tail button.
|
||||
if (fitsLeftOf(cursorX, spec.tailWidth, rightBound))
|
||||
out.tail = FooterBarRect{cursorX, top, spec.tailWidth, boxH};
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
FooterHit hitTestFooterBar(int px, int py, const FooterBarLayout& layout) {
|
||||
// Toggle first (matches the shell's segment sub-hit precedence), then the Tail button. The
|
||||
// count label is a passive readout — never a hit target.
|
||||
if (pointIn(px, py, layout.toggle)) return FooterHit::Toggle;
|
||||
if (pointIn(px, py, layout.tail)) return FooterHit::Tail;
|
||||
return FooterHit::None;
|
||||
}
|
||||
|
||||
} // namespace reasampler::ui
|
||||
Reference in New Issue
Block a user