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

@@ -57,12 +57,13 @@ int getAvailableBottomPx(const QRect& band, const std::vector<QRect>& occupiedRe
}
PanelSide chooseSide(const QRect& band, const QRect& anchorRect, int widthPx,
int marginPx)
int selectionGapPx)
{
// What each side offers: the gap between the anchor and that edge of the band, less
// the margin the panel keeps from the anchor.
const int roomRightPx = band.right() - anchorRect.right() - marginPx;
const int roomLeftPx = anchorRect.left() - band.left() - marginPx;
// What each side offers: the room between the anchor and that edge of the band, less
// the gap the panel keeps from the anchor. The band's own inset from the view has
// already taken the edge margin off.
const int roomRightPx = band.right() - anchorRect.right() - selectionGapPx;
const int roomLeftPx = anchorRect.left() - band.left() - selectionGapPx;
if (roomRightPx >= widthPx)
{
@@ -79,20 +80,20 @@ PanelSide chooseSide(const QRect& band, const QRect& anchorRect, int widthPx,
QRect placeBesideAnchor(const QRect& band, const QRect& anchorRect, PanelSide side,
QSize wantedSize, const std::vector<QRect>& occupiedRects,
int marginPx)
int selectionGapPx, int marginPx)
{
const int widthPx = std::min(wantedSize.width(), band.width());
// Against the anchor on the chosen side, growing away from it: the edge facing the
// A gap from the anchor on the chosen side, growing away from it: the edge facing the
// selection is the one that stays put as the panel's content resizes. A panel that
// does not fit there is pushed back inside the view rather than hanging off it, which
// is what puts it over the selection when neither side had room.
const int wantedLeftPx = (side == PanelSide::Right)
? anchorRect.right() + marginPx + 1
: anchorRect.left() - marginPx - widthPx;
? anchorRect.right() + selectionGapPx + 1
: anchorRect.left() - selectionGapPx - widthPx;
// Top-aligned with the anchor, then lifted by however much of it hangs below what is
// free.
// Top-aligned with the anchor -- the gap separates the two horizontally and plays no
// part here -- then lifted by however much of the panel hangs below what is free.
return fitInBand(band, wantedLeftPx, anchorRect.top(), wantedSize, occupiedRects,
marginPx);
}