open selection panel modals on the panel

This commit is contained in:
2026-08-11 21:21:12 +02:00
parent d1da4b2937
commit 3274df91d4
3 changed files with 58 additions and 2 deletions

View File

@@ -7,6 +7,7 @@
#include <QApplication>
#include <QCloseEvent>
#include <QDialog>
#include <QDir>
#include <QFile>
#include <QInputDialog>
@@ -317,6 +318,9 @@ void MainWindow::openShipLayoutDialog(BuildingId shipyardId,
std::move(unlockedModuleIds),
m_gameWorldView->isDebugDrawEnabled(),
this);
// Opened from the panel's "Configure" button (REQ-MOD-UI-PREVIEW) or straight after
// a schematic change (REQ-MOD-UI-AUTO-DIALOG), so it opens on the panel either way.
placeOnSelectionPanel(dialog);
if (dialog.exec() == QDialog::Accepted && dialog.getResult().has_value())
{
std::shared_ptr<SetShipLayoutCommand> command =
@@ -328,6 +332,45 @@ void MainWindow::openShipLayoutDialog(BuildingId shipyardId,
}
}
void MainWindow::placeOnSelectionPanel(QDialog& dialog) const
{
// The panel is up whenever one of these modals opens -- they are opened from its own
// controls, and it is shown whenever anything is selected (REQ-UI-EMPTY-SELECTION).
// Were it not, there would be no rectangle to center on and Qt's own centering on
// this window stands.
if (!m_selectionPanel->isVisible()) { return; }
// The dialog has never been shown, so it is still at its default size until its
// layout has run; centering it before that would use the wrong extent.
dialog.adjustSize();
const QSize dialogSize = dialog.size();
// The panel's live geometry, so a panel the player has dragged
// (REQ-UI-SELECTION-PANEL-DRAG) carries the modal with it.
const QRect panelRect(m_selectionPanel->mapToGlobal(QPoint(0, 0)),
m_selectionPanel->size());
const QRect windowRect(mapToGlobal(QPoint(0, 0)), size());
QPoint topLeft(panelRect.center().x() - dialogSize.width() / 2,
panelRect.center().y() - dialogSize.height() / 2);
// Pushed back inside the window, never resized to fit (REQ-UI-PANEL-MODAL). The far
// edge is clamped first and the near edge second, which is what aligns a dialog too
// large for the window with the window's top-left corner rather than pushing it off
// the opposite edge.
topLeft.setX(qMax(windowRect.left(),
qMin(topLeft.x(), windowRect.right() - dialogSize.width() + 1)));
topLeft.setY(qMax(windowRect.top(),
qMin(topLeft.y(), windowRect.bottom() - dialogSize.height() + 1)));
// Positions the dialog's frame, whose size is not known until it is first shown, so
// the result sits low by the title bar height against a true center -- measuring it
// would mean showing the dialog at the wrong place first. The move also marks the
// dialog as positioned, which is what stops QDialog from centering it on this window
// when it is shown.
dialog.move(topLeft);
}
void MainWindow::handleEvent(std::shared_ptr<const LayoutDialogRequestedEvent> event)
{
// A construction site has no Building yet; fall back to its site record so
@@ -385,6 +428,7 @@ void MainWindow::handleEvent(std::shared_ptr<const RecipeSelectionRequestedEvent
bool autoOpenLayout = false;
std::string chosenSchematic;
RecipeSelectionDialog dialog(options, title, m_itemIcons.get(), this);
placeOnSelectionPanel(dialog);
if (dialog.exec() == QDialog::Accepted && dialog.getChosenId().has_value())
{
std::shared_ptr<SetRecipeCommand> command = std::make_shared<SetRecipeCommand>();