put the controls panel in the corner and let it step around the build bar

It was confined to the band above the build button bar's strip, borrowing the
selection panel's rule. That rule exists because the selection panel is
full-height on the right, where the bar's strip is genuinely in the way. This
panel is short and in the corner, and the bar is centered and sized to its
buttons, so the corner is normally free -- reserving the whole strip pushed the
panel up for a collision that was not happening.

It now sits in the bottom-left corner and shares the view's bottom edge with
the bar, rising only when the panel's rectangle would actually intersect the
bar's, in which case it clears the bar's top by the usual margin and caps its
height at what is left. So it moves for a wide bar and a wide panel, and drops
back into the corner as soon as they no longer meet.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YHcUerKAZKWNvSKJxYKbnG
This commit is contained in:
2026-08-07 20:07:22 +02:00
parent 3c4688bdb6
commit a5c51f08f8
4 changed files with 45 additions and 26 deletions

View File

@@ -139,9 +139,10 @@ ControlsPanel::ControlsPanel(const GameWorldView* view, QWidget* parent)
refresh();
}
void ControlsPanel::anchorTo(const QRect& bandRect)
void ControlsPanel::anchorTo(const QRect& worldRect, const QRect& buildBarRect)
{
m_bandRect = bandRect;
m_worldRect = worldRect;
m_buildBarRect = buildBarRect;
refit();
}
@@ -258,7 +259,7 @@ QString ControlsPanel::getHeadingText(const ControlContext& context) const
void ControlsPanel::refit()
{
if (m_bandRect.isNull()) { return; }
if (m_worldRect.isNull()) { return; }
// Rows are torn down and rebuilt wholesale, and a widget added to a layout is only
// shown once that layout runs -- without this the new rows count for nothing and
@@ -277,13 +278,26 @@ void ControlsPanel::refit()
layout()->invalidate();
const QSize needed = layout()->totalSizeHint();
const QRect band = m_bandRect.adjusted(kMarginPx, kMarginPx, -kMarginPx, -kMarginPx);
const QRect band = m_worldRect.adjusted(kMarginPx, kMarginPx, -kMarginPx, -kMarginPx);
if (band.width() <= 0 || band.height() <= 0) { return; }
// The bottom-left corner of the view, growing upward as rows are added
// (REQ-UI-CONTROLS-PANEL).
const int widthPx = qMin(needed.width(), band.width());
const int heightPx = qMin(needed.height(), band.height());
int heightPx = qMin(needed.height(), band.height());
int topPx = band.bottom() - heightPx + 1;
// Left edge of the band, sitting on its bottom edge, so the panel grows upward as
// rows are added (REQ-UI-CONTROLS-PANEL).
setGeometry(band.left(), band.bottom() - heightPx + 1, widthPx, heightPx);
// The build button bar is centered and sized to its buttons, so it usually leaves
// this corner free and the panel can share the bottom edge with it. Only when the
// two would actually overlap does the panel rise, clearing the bar's top by the
// same margin it keeps from the view's edges (REQ-UI-BUILD-BAR).
const QRect wanted(band.left(), topPx, widthPx, heightPx);
if (!m_buildBarRect.isNull() && wanted.intersects(m_buildBarRect))
{
const int availablePx = m_buildBarRect.top() - kMarginPx - band.top();
heightPx = qMin(heightPx, qMax(0, availablePx));
topPx = m_buildBarRect.top() - kMarginPx - heightPx;
}
setGeometry(band.left(), topPx, widthPx, heightPx);
}