157 lines
6.8 KiB
C++
157 lines
6.8 KiB
C++
#include "catch.hpp"
|
|
|
|
#include <vector>
|
|
|
|
#include <QRect>
|
|
|
|
#include "FloatingPanelPlacement.h"
|
|
|
|
// The band every case below places into: 1000x600, so a bottom edge of 599.
|
|
static QRect makeBand()
|
|
{
|
|
return QRect(0, 0, 1000, 600);
|
|
}
|
|
|
|
static const int kMarginPx = 8;
|
|
|
|
TEST_CASE("With nothing in the way a widget may use the whole band", "[layout]")
|
|
{
|
|
// REQ-UI-SELECTION-PANEL: the band's own bottom is the limit when no other floating
|
|
// widget has been placed yet.
|
|
REQUIRE(getAvailableBottomPx(makeBand(), {}, 0, 999, kMarginPx) == 599);
|
|
}
|
|
|
|
TEST_CASE("A widget in the same column pushes the bottom above it", "[layout]")
|
|
{
|
|
// The build button bar sitting at the bottom center leaves the space above it, less
|
|
// the margin kept between the two (REQ-UI-BUILD-BAR).
|
|
const std::vector<QRect> occupied = { QRect(400, 520, 200, 72) };
|
|
REQUIRE(getAvailableBottomPx(makeBand(), occupied, 350, 650, kMarginPx) == 511);
|
|
}
|
|
|
|
TEST_CASE("A widget beside the column does not shorten it", "[layout]")
|
|
{
|
|
// The controls panel in the bottom-left corner is not in the way of a panel standing
|
|
// at the right edge, however tall it is (REQ-UI-CONTROLS-PANEL).
|
|
const std::vector<QRect> occupied = { QRect(0, 100, 200, 499) };
|
|
REQUIRE(getAvailableBottomPx(makeBand(), occupied, 700, 999, kMarginPx) == 599);
|
|
|
|
// Touching columns do count as meeting: the panel starts exactly where the widget
|
|
// ends, which is an overlap of one pixel.
|
|
REQUIRE(getAvailableBottomPx(makeBand(), occupied, 199, 999, kMarginPx) == 91);
|
|
}
|
|
|
|
TEST_CASE("The topmost widget in the column decides", "[layout]")
|
|
{
|
|
// Several widgets meet the column: the one that reaches highest is the binding one,
|
|
// whatever order they are given in.
|
|
const std::vector<QRect> occupied = { QRect(400, 520, 200, 72),
|
|
QRect(0, 300, 500, 299),
|
|
QRect(900, 560, 100, 40) };
|
|
REQUIRE(getAvailableBottomPx(makeBand(), occupied, 450, 550, kMarginPx) == 291);
|
|
}
|
|
|
|
TEST_CASE("An empty rectangle occupies nothing", "[layout]")
|
|
{
|
|
// A floating widget that is hidden contributes a null rect rather than being left
|
|
// out of the pass.
|
|
const std::vector<QRect> occupied = { QRect(), QRect(400, 520, 200, 0) };
|
|
REQUIRE(getAvailableBottomPx(makeBand(), occupied, 0, 999, kMarginPx) == 599);
|
|
}
|
|
|
|
TEST_CASE("A widget filling the column leaves nothing", "[layout]")
|
|
{
|
|
// The caller is expected to notice that the space left is not positive rather than
|
|
// being handed a floor of its own.
|
|
const std::vector<QRect> occupied = { QRect(0, 0, 1000, 600) };
|
|
REQUIRE(getAvailableBottomPx(makeBand(), occupied, 0, 999, kMarginPx) == -9);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Which side of the selection the panel takes
|
|
// ---------------------------------------------------------------------------
|
|
|
|
TEST_CASE("The panel stands to the right of the selection where it fits", "[layout]")
|
|
{
|
|
// REQ-UI-SELECTION-PANEL: right of the anchor is the first choice.
|
|
REQUIRE(chooseSide(makeBand(), QRect(100, 100, 60, 60), 300, kMarginPx)
|
|
== PanelSide::Right);
|
|
}
|
|
|
|
TEST_CASE("The panel goes left when the right cannot hold it", "[layout]")
|
|
{
|
|
// A selection near the right edge leaves 100 px there, not enough for a 300 px
|
|
// panel, and the left is wide open.
|
|
REQUIRE(chooseSide(makeBand(), QRect(880, 100, 20, 60), 300, kMarginPx)
|
|
== PanelSide::Left);
|
|
}
|
|
|
|
TEST_CASE("Fitting on neither side, the panel takes the roomier one", "[layout]")
|
|
{
|
|
// A bounding box spanning most of the view: 192 px free on the left, 92 on the
|
|
// right, and a 300 px panel fits in neither. It covers as little as it can.
|
|
REQUIRE(chooseSide(makeBand(), QRect(200, 100, 700, 200), 300, kMarginPx)
|
|
== PanelSide::Left);
|
|
REQUIRE(chooseSide(makeBand(), QRect(100, 100, 700, 200), 300, kMarginPx)
|
|
== PanelSide::Right);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Where it then stands
|
|
// ---------------------------------------------------------------------------
|
|
|
|
TEST_CASE("The panel sits beside the anchor with its top edges aligned", "[layout]")
|
|
{
|
|
// REQ-UI-SELECTION-PANEL: separated by the margin, growing away from the selection,
|
|
// top edge on the anchor's top edge.
|
|
const QRect placed = placeBesideAnchor(makeBand(), QRect(100, 120, 60, 60),
|
|
PanelSide::Right, QSize(300, 200), {},
|
|
kMarginPx);
|
|
REQUIRE(placed == QRect(168, 120, 300, 200));
|
|
|
|
const QRect placedLeft = placeBesideAnchor(makeBand(), QRect(500, 120, 60, 60),
|
|
PanelSide::Left, QSize(300, 200), {},
|
|
kMarginPx);
|
|
REQUIRE(placedLeft == QRect(192, 120, 300, 200));
|
|
}
|
|
|
|
TEST_CASE("A panel that would hang below the view is lifted", "[layout]")
|
|
{
|
|
// Top-aligning with a selection low in the view would put the panel's bottom past
|
|
// the band, so it rises until it fits rather than overrunning it.
|
|
const QRect placed = placeBesideAnchor(makeBand(), QRect(100, 500, 60, 60),
|
|
PanelSide::Right, QSize(300, 200), {},
|
|
kMarginPx);
|
|
REQUIRE(placed == QRect(168, 400, 300, 200));
|
|
}
|
|
|
|
TEST_CASE("A panel standing over another widget rises above it", "[layout]")
|
|
{
|
|
// The controls panel in the bottom-left is in the way of a panel placed to the left
|
|
// of a selection: it clears the top of it by the margin (REQ-UI-CONTROLS-PANEL).
|
|
const std::vector<QRect> occupied = { QRect(0, 300, 260, 300) };
|
|
const QRect placed = placeBesideAnchor(makeBand(), QRect(500, 250, 60, 60),
|
|
PanelSide::Left, QSize(300, 200), occupied,
|
|
kMarginPx);
|
|
REQUIRE(placed == QRect(192, 92, 300, 200));
|
|
}
|
|
|
|
TEST_CASE("A panel taller than the space left is capped", "[layout]")
|
|
{
|
|
// Capping is the caller's cue to scroll: it asked for 700 and got what there was.
|
|
const QRect placed = placeBesideAnchor(makeBand(), QRect(100, 100, 60, 60),
|
|
PanelSide::Right, QSize(300, 700), {},
|
|
kMarginPx);
|
|
REQUIRE(placed == QRect(168, 0, 300, 600));
|
|
}
|
|
|
|
TEST_CASE("A panel that fits on neither side is pushed inside the view", "[layout]")
|
|
{
|
|
// The one case where it covers part of the selection (REQ-UI-SELECTION-PANEL): it
|
|
// stands as far from the anchor as the band allows, not off the edge of it.
|
|
const QRect placed = placeBesideAnchor(makeBand(), QRect(100, 100, 700, 200),
|
|
PanelSide::Right, QSize(300, 200), {},
|
|
kMarginPx);
|
|
REQUIRE(placed == QRect(700, 100, 300, 200));
|
|
}
|