// footer_bar — pure implementation. See footer_bar.h. #include "core/ui/footer_bar.h" namespace reasampler::ui { namespace { // True iff a box [x, x+width) fits entirely left of `rightBound`. 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; // 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; } bool modeSegmentEnabled(bool isActiveSegment, bool transportRunning, bool routable) { return isActiveSegment || (!transportRunning && routable); } } // namespace reasampler::ui