diff --git a/docs/requirements.md b/docs/requirements.md index f6196d2..fc845b4 100644 --- a/docs/requirements.md +++ b/docs/requirements.md @@ -259,7 +259,7 @@ Modules in `modules.toml` define a `surface_mask` — a list of strings that des ### Module UI -- REQ-MOD-UI-PREVIEW: When a schematic is selected in a shipyard's selected building panel, a small non-interactive **ship layout preview** widget is shown below the schematic selection button (REQ-UI-SELECT-BUTTON). The preview renders the ship's layout grid at a reduced scale: buildable cells without a module are shown as white, non-buildable cells are shown as black, and cells occupied by a module are shown in that module's `fill_color` with the module's `glyph` character. Below the preview, a "Configure" button is shown. +- REQ-MOD-UI-PREVIEW: For a selected shipyard (operational building or construction site), the selected building panel always shows a small non-interactive **ship layout preview** widget below the schematic selection button (REQ-UI-SELECT-BUTTON) and a "Configure" button below the preview. Both are **disabled while no schematic is selected**, and enabled once one is; the preview then shows an empty placeholder in place of a layout grid. When a schematic is selected, the preview renders the ship's layout grid at a reduced scale: buildable cells without a module are shown as white, non-buildable cells are shown as black, and cells occupied by a module are shown in that module's `fill_color` with the module's `glyph` character. For non-shipyard buildings, neither the preview nor the "Configure" button is shown. - REQ-MOD-UI-DIALOG: Clicking the "Configure" button opens the **layout configuration dialog** as a modal. While the dialog is open, the game is paused (speed set to 0×). On close, the game speed is restored to what it was before the dialog was opened. The dialog contains: diff --git a/src/ui/SelectedBuildingPanel.cpp b/src/ui/SelectedBuildingPanel.cpp index d070440..926b8f8 100644 --- a/src/ui/SelectedBuildingPanel.cpp +++ b/src/ui/SelectedBuildingPanel.cpp @@ -566,11 +566,21 @@ void SelectedBuildingPanel::updateShipyardLayoutWidgets( const std::string& recipeId, const std::optional& shipLayout) { - const ShipDef* shipDef = (type == BuildingType::Shipyard) - ? findShipDef(recipeId) - : nullptr; + // The preview and Configure button are shipyard-only controls; hide them + // entirely for other building types. + if (type != BuildingType::Shipyard) + { + m_layoutPreview->hide(); + m_configureLayoutBtn->hide(); + return; + } - if (shipDef && !shipDef->layout.empty()) + const ShipDef* shipDef = findShipDef(recipeId); + const bool hasSchematic = shipDef && !shipDef->layout.empty(); + + // Always show the preview and Configure button for a shipyard; they are only + // enabled once a schematic is selected (REQ-MOD-UI-PREVIEW). + if (hasSchematic) { ShipLayoutConfig layout; if (shipLayout.has_value()) @@ -579,14 +589,16 @@ void SelectedBuildingPanel::updateShipyardLayoutWidgets( } m_layoutPreview->setShipAndLayout( shipDef->layout, layout, &m_config->modules.modules); - m_layoutPreview->show(); - m_configureLayoutBtn->show(); } else { - m_layoutPreview->hide(); - m_configureLayoutBtn->hide(); + m_layoutPreview->showPlaceholder(); } + + m_layoutPreview->setEnabled(hasSchematic); + m_configureLayoutBtn->setEnabled(hasSchematic); + m_layoutPreview->show(); + m_configureLayoutBtn->show(); } const RecipeDef* SelectedBuildingPanel::findRecipe(const Building* b) const diff --git a/src/ui/ShipLayoutPreview.cpp b/src/ui/ShipLayoutPreview.cpp index 1474da0..0754157 100644 --- a/src/ui/ShipLayoutPreview.cpp +++ b/src/ui/ShipLayoutPreview.cpp @@ -8,6 +8,10 @@ namespace const int kCellSize = 8; +// Size of the empty placeholder box shown when no schematic is selected. +const int kPlaceholderWidth = 64; +const int kPlaceholderHeight = 40; + const ModuleDef* findModuleDef(const std::vector& modules, const std::string& id) { @@ -90,14 +94,28 @@ void ShipLayoutPreview::clear() m_modules = nullptr; m_rows = 0; m_cols = 0; + m_placeholder = false; setFixedSize(0, 0); update(); } +void ShipLayoutPreview::showPlaceholder() +{ + m_grid.clear(); + m_placedModules.clear(); + m_modules = nullptr; + m_rows = 0; + m_cols = 0; + m_placeholder = true; + setFixedSize(kPlaceholderWidth, kPlaceholderHeight); + update(); +} + void ShipLayoutPreview::setShipAndLayout(const std::vector& shipLayout, const ShipLayoutConfig& layout, const std::vector* modules) { + m_placeholder = false; m_modules = modules; m_placedModules = layout.placedModules; m_rows = static_cast(shipLayout.size()); @@ -156,6 +174,18 @@ void ShipLayoutPreview::setShipAndLayout(const std::vector& shipLay void ShipLayoutPreview::paintEvent(QPaintEvent* /*event*/) { + if (m_placeholder) + { + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing, false); + const QRect box = rect().adjusted(0, 0, -1, -1); + painter.fillRect(box, QColor(40, 40, 40)); + painter.setPen(QColor(128, 128, 128)); + painter.drawRect(box); + painter.drawText(box, Qt::AlignCenter, tr("No schematic")); + return; + } + if (m_rows == 0 || m_cols == 0) { return; diff --git a/src/ui/ShipLayoutPreview.h b/src/ui/ShipLayoutPreview.h index 7e768fa..558fc31 100644 --- a/src/ui/ShipLayoutPreview.h +++ b/src/ui/ShipLayoutPreview.h @@ -20,6 +20,10 @@ public: const std::vector* modules); void clear(); + // Shows an empty placeholder box (no ship layout) so the preview stays + // visible while no schematic is selected (REQ-MOD-UI-PREVIEW). + void showPlaceholder(); + protected: void paintEvent(QPaintEvent* event) override; @@ -35,4 +39,5 @@ private: const std::vector* m_modules; int m_rows; int m_cols; + bool m_placeholder = false; };