#pragma once #include #include #include #include #include #include "BuildingId.h" #include "BuildingType.h" #include "SelectionContext.h" struct Building; class BarRow; class QLabel; class QVBoxLayout; class SectionBox; class StatusPill; // One card of the selection panel: the content shown for a particular kind of selection // (REQ-UI-SELECTION-CARD). Every content is this base plus the parts its constructor // puts into the two groups; which content is shown for which selection is decided in // SelectionContentFactory (REQ-UI-SELECTION-CONTENT). // // The card has three parts, top to bottom: // * the header -- identity symbol, name, and one optional right slot (a status // indicator, a ship's behavior, or an object count); // * the configuration group -- controls that change how the object is set up; // * the runtime group -- what the object is currently doing. // // A construction site keeps its configuration group and has its whole runtime group // replaced by the construction section (REQ-BLD-SITE-CONFIG). That rule lives here and // nowhere else: a subclass fills both groups unconditionally in its constructor and // never asks whether it is showing a site. class SelectionContent : public QWidget { Q_OBJECT public: ~SelectionContent() override; // Re-reads the live values behind the card. It never changes the card's structure: // a change that would (a site finishing, the selection changing) is a rebuild, and // SelectionPanel owns that decision. void refresh(); // The card's header (REQ-UI-SELECTION-CARD), which is also the handle the panel is // dragged by (REQ-UI-SELECTION-PANEL-DRAG). The panel hit-tests against it; the card // itself does nothing with the gesture. QWidget* getHeaderWidget() const { return m_header; } protected: // constructionSiteId is set only while the card shows a construction site, in which // case this base builds and drives the construction section in place of whatever the // subclass puts into the runtime group. SelectionContent(const SelectionContext& context, std::optional constructionSiteId, QWidget* parent); // Live values of the runtime group. Not called while the card shows a construction // site, which has neither buffers nor a production cycle (REQ-BLD-SITE-CONFIG). virtual void refreshRuntime() = 0; // Live values of the configuration group. Called for a site too, because a site is // configured exactly like the building it will become (REQ-BLD-SITE-CONFIG). virtual void refreshConfiguration() {} const SelectionContext& getContext() const { return m_context; } // The two group layouts a subclass adds its parts to, in its constructor. QVBoxLayout* getConfigurationLayout(); QVBoxLayout* getRuntimeLayout(); void setIdentity(const QPixmap& symbol, const QString& name); // Header symbol for a building type: its chip icon, or nothing when the icon file is // missing -- which is not an error (REQ-UI-BUILD-ICON, REQ-UI-SELECTION-CARD). void setBuildingIdentity(BuildingType type, const QString& name); // Fills the header's right slot. A null dot color leaves the dot off, for the slots // that are a plain caption (a construction site, a ship's behavior). void setSlot(const QColor& dotColor, const QString& caption); // "x", for an aggregated multi-selection (REQ-UI-SELECTION-AGGREGATE). void setCountSlot(int count); void clearSlot(); // Fills the right slot from the building's production status, mapped to the same // colors and states the world's status light uses (REQ-UI-SELECTION-STATUS). Leaves // the slot empty for a type that has no status light. void setProductionStatusSlot(const Building& building); private: void refreshConstruction(); SelectionContext m_context; // Set while this card shows a construction site rather than a finished object. std::optional m_siteId; QWidget* m_header; QLabel* m_symbolLabel; QLabel* m_nameLabel; StatusPill* m_statusPill; QWidget* m_configurationGroup; QWidget* m_runtimeGroup; // Replaces the runtime group while this card shows a construction site; both null // otherwise. SectionBox* m_constructionSection; BarRow* m_constructionBar; };