keep the selection panel half a tile off what it describes

The panel had one distance for the view edges, the widgets it steps around,
and the selection alike, so it stood eight pixels from a building and touched
it outright along the top. The gap from the selection is now its own value,
half a tile, and it is horizontal only -- the top edges stay level.

It is sampled where the tile size is known, in the same moment as the anchor
rectangle, and travels with it: a rectangle frozen in one moment has no
meaningful distance to a tile size measured in another. chooseSide now takes
the gap in place of the margin, the band having already taken the margin off.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ne3mejABZoLWKLh8fgpM3x
This commit is contained in:
2026-08-17 16:24:14 +02:00
parent abaccc45b5
commit 392a2b8d00
7 changed files with 115 additions and 61 deletions

View File

@@ -17,8 +17,11 @@
namespace
{
// Distance kept between the panel and the edges of the game world view, and between it
// and the widgets it steps around (REQ-UI-SELECTION-PANEL).
// The edge margin: the distance kept between the panel and the edges of the game world
// view, and between it and the widgets it steps around (REQ-UI-SELECTION-PANEL). The gap
// the panel keeps from the selection itself is the wider of the two and is not this: being
// half a tile, it is measured where the tile size is known and arrives with the anchor
// rectangle (SelectionAnchorChangedEvent).
const int kMarginPx = 8;
// Upper bound on the card width. The panel is content-sized, but several of the cards'
@@ -170,12 +173,14 @@ void SelectionPanel::handleEvent(std::shared_ptr<const SelectionChangedEvent> ev
void SelectionPanel::handleEvent(
std::shared_ptr<const SelectionAnchorChangedEvent> event)
{
// A new selection is starting. Both the anchor and the side are settled against it
// and then left alone for as long as it lasts (REQ-UI-SELECTION-PANEL); the side is
// only reset here, being resolved on the next placement once the card's width is
// known. The rect arrives in the world view's coordinates and is translated when the
// panel is placed, the two widgets being siblings in the same parent.
m_anchorRect = event->rectPx;
// A new selection is starting. The anchor, the gap kept from it, and the side are all
// settled against it and then left alone for as long as it lasts
// (REQ-UI-SELECTION-PANEL); the side is only reset here, being resolved on the next
// placement once the card's width is known. The rect arrives in the world view's
// coordinates and is translated when the panel is placed, the two widgets being
// siblings in the same parent.
m_anchorRect = event->rectPx;
m_selectionGapPx = event->selectionGapPx;
m_side.reset();
// A position the player dragged the panel to belongs to the selection it was set in.
// A new selection places the panel anew against its own anchor
@@ -354,7 +359,7 @@ void SelectionPanel::placeIn(const QRect& viewRect, const std::vector<QRect>& oc
wantedSize, occupiedRects, kMarginPx);
}
return placeBesideAnchor(band, anchorRect, *m_side, wantedSize, occupiedRects,
kMarginPx);
m_selectionGapPx, kMarginPx);
};
// Run twice. Parts of a card report an unstyled size until the style has actually
@@ -376,7 +381,7 @@ void SelectionPanel::placeIn(const QRect& viewRect, const std::vector<QRect>& oc
if (!m_side.has_value())
{
m_side = chooseSide(band, anchorRect, contentWidthPx + 2 * borderPx,
kMarginPx);
m_selectionGapPx);
}
// How much height there is depends on where the panel ends up standing: of the