7cd0771e45
Top-bar rare-capture variants move to a right-anchored More popup; short faces gain hover-delay full-name tooltips (prefix stripped); bottom bar becomes four opposite-mode Item/Track tag buttons + Show Both (Toggle/Activates dropped); wider cluster gaps. New pure overflow_menu/mode_enable/tooltip modules, CTest-covered. Same actions, same contract.
145 lines
6.4 KiB
C++
145 lines
6.4 KiB
C++
// Standalone tests for reasampler::overflow_menu — no REAPER, no test framework. Same fast
|
|
// loop as the sibling pure tests (prune_button / mode_switch): assert the top-toolbar More
|
|
// ("⋯") button placement, the action-bar reserve, and hit-testing directly.
|
|
//
|
|
// Covers (L5 refinement 1 pure module): right-anchored layout in a wide band; the reserve the
|
|
// action_bar must leave (width + 2*rightInset); vertical inset; thin-band height clamp;
|
|
// SUPPRESSION (empty rect) when the band is too narrow to clear the left inset or is degenerate;
|
|
// a degenerate band reserves nothing; hit-test in/out/edge (half-open bounds); an empty button
|
|
// claims no point; draw and hit-test agree over the whole rect.
|
|
|
|
#include "../src/overflow_menu.h"
|
|
|
|
#include <cstdio>
|
|
|
|
using namespace reasampler;
|
|
|
|
static int g_fail = 0;
|
|
#define CHECK(cond) do { if(!(cond)) { \
|
|
std::printf("FAIL line %d: %s\n", __LINE__, #cond); ++g_fail; } } while(0)
|
|
|
|
// --- Layout: wide band, right-anchored ---------------------------------------
|
|
|
|
// Band 400 wide at origin (0, 0), height 40. Default spec: buttonWidth 28, rightInset 6,
|
|
// verticalInset 3, minLeftInset 40. Right edge = 0+400-6 = 394, left = 394-28 = 366
|
|
// (>= 0+40, placed). Top = 0+3 = 3, height = 40-6 = 34.
|
|
static void testWideBandRightAnchored() {
|
|
MenuBarRect bar{0, 0, 400, 40};
|
|
const MenuButtonRect b = computeMenuButton(bar, MenuButtonSpec{});
|
|
CHECK(!b.empty());
|
|
CHECK((b == MenuButtonRect{366, 3, 28, 34}));
|
|
CHECK(b.x + b.width == bar.x + bar.width - 6); // right edge at rightInset
|
|
CHECK(b.x >= bar.x + 40); // clears the left inset
|
|
}
|
|
|
|
// Origin offset honoured (button anchors to THIS band's right).
|
|
static void testOffsetBandAnchors() {
|
|
MenuBarRect bar{10, 5, 400, 40};
|
|
const MenuButtonRect b = computeMenuButton(bar, MenuButtonSpec{});
|
|
CHECK(!b.empty());
|
|
CHECK(b.x + b.width == bar.x + bar.width - 6); // = 10+400-6 = 404
|
|
CHECK(b.y == 8); // 5 + 3
|
|
}
|
|
|
|
// --- Reserve -----------------------------------------------------------------
|
|
|
|
// The reserve = buttonWidth + 2*rightInset so the frequent buttons get a right gap AND a left
|
|
// breathing gap before the menu button. Default: 28 + 2*6 = 40.
|
|
static void testReserve() {
|
|
MenuBarRect bar{0, 0, 400, 40};
|
|
CHECK(menuButtonReserve(bar, MenuButtonSpec{}) == 40);
|
|
}
|
|
|
|
// A degenerate band reserves nothing (no button to reserve for).
|
|
static void testDegenerateBandReservesNothing() {
|
|
CHECK(menuButtonReserve(MenuBarRect{0, 0, 0, 40}, MenuButtonSpec{}) == 0);
|
|
CHECK(menuButtonReserve(MenuBarRect{0, 0, 400, 0}, MenuButtonSpec{}) == 0);
|
|
MenuButtonSpec zero{}; zero.buttonWidth = 0;
|
|
CHECK(menuButtonReserve(MenuBarRect{0, 0, 400, 40}, zero) == 0);
|
|
}
|
|
|
|
// --- Suppression: too narrow / degenerate ------------------------------------
|
|
|
|
// The button is suppressed when its left edge would fall past minLeftInset. left = x + width -
|
|
// rightInset - buttonWidth. Need left < x + minLeftInset ->
|
|
// width < rightInset + buttonWidth + minLeftInset = 6 + 28 + 40 = 74. Width 73 suppresses; 74
|
|
// places (boundary).
|
|
static void testNarrowBandSuppressed() {
|
|
CHECK(computeMenuButton(MenuBarRect{0, 0, 73, 40}, MenuButtonSpec{}).empty());
|
|
CHECK(!computeMenuButton(MenuBarRect{0, 0, 74, 40}, MenuButtonSpec{}).empty());
|
|
}
|
|
|
|
static void testDegenerateBandSuppressed() {
|
|
CHECK(computeMenuButton(MenuBarRect{0, 0, 0, 40}, MenuButtonSpec{}).empty());
|
|
CHECK(computeMenuButton(MenuBarRect{0, 0, 400, 0}, MenuButtonSpec{}).empty());
|
|
MenuButtonSpec zero{}; zero.buttonWidth = 0;
|
|
CHECK(computeMenuButton(MenuBarRect{0, 0, 400, 40}, zero).empty());
|
|
}
|
|
|
|
// A thin band (height <= 2*verticalInset) still places a button, clamped to the band's height.
|
|
static void testThinBandClampsHeight() {
|
|
MenuBarRect bar{0, 0, 400, 4}; // 4 <= 2*3, so height would be negative -> clamp
|
|
const MenuButtonRect b = computeMenuButton(bar, MenuButtonSpec{});
|
|
CHECK(!b.empty());
|
|
CHECK(b.y == bar.y);
|
|
CHECK(b.height == bar.height);
|
|
}
|
|
|
|
// --- Hit-test ----------------------------------------------------------------
|
|
|
|
static void testHitTestInside() {
|
|
MenuBarRect bar{0, 0, 400, 40};
|
|
const MenuButtonRect b = computeMenuButton(bar, MenuButtonSpec{}); // {366,3,28,34}
|
|
CHECK(hitTestMenuButton(b.x, b.y, b)); // top-left inclusive
|
|
CHECK(hitTestMenuButton(b.x + b.width - 1, b.y + b.height - 1, b)); // bottom-right inclusive
|
|
CHECK(hitTestMenuButton(b.x + b.width / 2, b.y + b.height / 2, b)); // centre
|
|
}
|
|
|
|
static void testHitTestEdgesExcluded() {
|
|
MenuBarRect bar{0, 0, 400, 40};
|
|
const MenuButtonRect b = computeMenuButton(bar, MenuButtonSpec{});
|
|
CHECK(!hitTestMenuButton(b.x - 1, b.y, b)); // just left
|
|
CHECK(!hitTestMenuButton(b.x + b.width, b.y, b)); // right edge excluded
|
|
CHECK(!hitTestMenuButton(b.x, b.y - 1, b)); // just above
|
|
CHECK(!hitTestMenuButton(b.x, b.y + b.height, b)); // bottom edge excluded
|
|
}
|
|
|
|
// An empty/suppressed button claims no point — a click where it would be falls through.
|
|
static void testEmptyButtonClaimsNothing() {
|
|
MenuButtonRect empty{};
|
|
CHECK(!hitTestMenuButton(0, 0, empty));
|
|
const MenuButtonRect suppressed = computeMenuButton(MenuBarRect{0, 0, 50, 40}, MenuButtonSpec{});
|
|
CHECK(suppressed.empty());
|
|
CHECK(!hitTestMenuButton(30, 20, suppressed));
|
|
}
|
|
|
|
// Draw/hit-test agreement over the whole rect + the four immediate outside neighbours.
|
|
static void testHitTestMatchesLayout() {
|
|
MenuBarRect bar{3, 7, 377, 38}; // awkward origin/size
|
|
const MenuButtonRect b = computeMenuButton(bar, MenuButtonSpec{});
|
|
CHECK(!b.empty());
|
|
for (int py = b.y; py < b.y + b.height; ++py)
|
|
for (int px = b.x; px < b.x + b.width; ++px)
|
|
CHECK(hitTestMenuButton(px, py, b));
|
|
CHECK(!hitTestMenuButton(b.x - 1, b.y, b));
|
|
CHECK(!hitTestMenuButton(b.x + b.width, b.y, b));
|
|
}
|
|
|
|
int main() {
|
|
testWideBandRightAnchored();
|
|
testOffsetBandAnchors();
|
|
testReserve();
|
|
testDegenerateBandReservesNothing();
|
|
testNarrowBandSuppressed();
|
|
testDegenerateBandSuppressed();
|
|
testThinBandClampsHeight();
|
|
testHitTestInside();
|
|
testHitTestEdgesExcluded();
|
|
testEmptyButtonClaimsNothing();
|
|
testHitTestMatchesLayout();
|
|
|
|
if (g_fail == 0) std::printf("overflow_menu: all tests passed\n");
|
|
else std::printf("overflow_menu: %d CHECK(s) FAILED\n", g_fail);
|
|
return g_fail == 0 ? 0 : 1;
|
|
}
|