#pragma once #include #include #include #include // Geometry for the widgets floating over the game world view (REQ-UI-WORLD-SIZE). Their // owner places them in one ordered pass, each into the space the earlier ones left free, // and these are the rules they place themselves by. Pure geometry -- no widget is // involved, which is what lets the rules be tested without a display. // The lowest bottom edge available to a widget occupying the horizontal span // [leftPx, rightPx] inside band: the band's own bottom, or marginPx above the topmost // occupied rectangle whose horizontal extent meets that span. A rectangle beside the // span is not in the way and does not shorten it (REQ-UI-SELECTION-PANEL, // REQ-UI-CONTROLS-PANEL). The result is inclusive, as QRect::bottom() is. int getAvailableBottomPx(const QRect& band, const std::vector& occupiedRects, int leftPx, int rightPx, int marginPx); // Which side of the selection the panel stands on (REQ-UI-SELECTION-PANEL). enum class PanelSide { Right, Left }; // The side a panel widthPx wide takes beside anchorRect: the right of it where it fits // within band, otherwise the left, and where it fits on neither, whichever side leaves // more room -- the one case in which the panel ends up over the selection // (REQ-UI-SELECTION-PANEL). Decided once when the selection starts and kept for as long // as it lasts, so a card that grows later never flips the panel across the object. PanelSide chooseSide(const QRect& band, const QRect& anchorRect, int widthPx, int marginPx); // Where a panel of wantedSize stands beside anchorRect on the given side: separated from // it by marginPx and growing away from it, its top edge on the anchor's top edge, pushed // inside band and above whatever occupies it. The returned height is short of // wantedSize's when there was not enough room, which is the caller's cue to scroll its // content (REQ-UI-SELECTION-PANEL). QRect placeBesideAnchor(const QRect& band, const QRect& anchorRect, PanelSide side, QSize wantedSize, const std::vector& occupiedRects, int marginPx); // Where a panel of wantedSize stands once the player has dragged it to desiredTopLeftPx: // at that point, by the same rules that place it beside a selection -- pushed inside band, // lifted above whatever occupies its column, and capped in height where that leaves too // little room (REQ-UI-SELECTION-PANEL-DRAG). The desired point is an input only: it is // never corrected and handed back, which is what lets the caller keep it exactly as // dropped and return to it once the room is there again. QRect placeAtDesiredTopLeft(const QRect& band, const QPoint& desiredTopLeftPx, QSize wantedSize, const std::vector& occupiedRects, int marginPx);