float the selection panel over the game world instead of a side column
This commit is contained in:
151
src/ui/SelectionPanel.h
Normal file
151
src/ui/SelectionPanel.h
Normal file
@@ -0,0 +1,151 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <QPoint>
|
||||
#include <QRect>
|
||||
#include <QWidget>
|
||||
|
||||
#include "BeltSystem.h"
|
||||
#include "Building.h"
|
||||
#include "BuildingId.h"
|
||||
#include "EntitySelectionChangedEvent.h"
|
||||
#include "EventHandler.h"
|
||||
#include "GameConfig.h"
|
||||
#include "PlayerCommandsAppliedEvent.h"
|
||||
#include "RecipesConfig.h"
|
||||
#include "DebrisSelectionChangedEvent.h"
|
||||
#include "SelectionChangedEvent.h"
|
||||
#include "ShipLayout.h"
|
||||
#include "ShipsConfig.h"
|
||||
#include "Tick.h"
|
||||
#include "TickAdvancedEvent.h"
|
||||
|
||||
class Simulation;
|
||||
class FieldSelectionPanel;
|
||||
class ShipLayoutPreview;
|
||||
class QLabel;
|
||||
class QListWidget;
|
||||
class QPushButton;
|
||||
class QScrollArea;
|
||||
class QVBoxLayout;
|
||||
|
||||
// Shows the current selection. The building category (buildings and construction sites)
|
||||
// is rendered by this panel itself; the field category (ships, defence stations, debris)
|
||||
// is rendered by the embedded FieldSelectionPanel.
|
||||
//
|
||||
// The two categories are mutually exclusive (REQ-UI-SELECTION-CATEGORIES) and this panel
|
||||
// is the sole arbiter of which one owns the content: it listens to all three selection
|
||||
// events, forwards the field ones to the child panel, and drops the losing category's
|
||||
// content. Neither panel touches the other's widgets.
|
||||
//
|
||||
// The panel floats over the game world view rather than occupying a column of its own
|
||||
// (REQ-UI-SELECTION-PANEL): it sizes itself to its content, anchors to the right edge of
|
||||
// the band its owner hands it, and hides itself entirely while nothing is selected
|
||||
// (REQ-UI-EMPTY-SELECTION).
|
||||
class SelectionPanel : public QWidget,
|
||||
public CombinedEventHandler<TickAdvancedEvent,
|
||||
PlayerCommandsAppliedEvent,
|
||||
EntitySelectionChangedEvent,
|
||||
SelectionChangedEvent,
|
||||
DebrisSelectionChangedEvent>
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SelectionPanel(Simulation* sim, const GameConfig* config,
|
||||
QWidget* parent = nullptr);
|
||||
~SelectionPanel() override;
|
||||
|
||||
// Confines the panel to the given band of the game world view: it right-aligns
|
||||
// within it and centers vertically in it. The band is the world view less the strip
|
||||
// the build button bar occupies, so the two never overlap and the bar never has to
|
||||
// move (REQ-UI-SELECTION-PANEL, REQ-UI-BUILD-BAR).
|
||||
void anchorTo(const QRect& bandRect);
|
||||
|
||||
private:
|
||||
void handleEvent(std::shared_ptr<const TickAdvancedEvent> event) override;
|
||||
void handleEvent(std::shared_ptr<const PlayerCommandsAppliedEvent> event) override;
|
||||
void handleEvent(std::shared_ptr<const EntitySelectionChangedEvent> event) override;
|
||||
void handleEvent(std::shared_ptr<const SelectionChangedEvent> event) override;
|
||||
void handleEvent(std::shared_ptr<const DebrisSelectionChangedEvent> event) override;
|
||||
|
||||
private slots:
|
||||
void onSelectRecipeClicked();
|
||||
void onClearBelt();
|
||||
void onSplitterFilterChanged();
|
||||
|
||||
private:
|
||||
// Why the selection display is being refreshed. A periodic tick only needs a
|
||||
// lightweight content update (e.g. a construction site's progress label),
|
||||
// whereas an applied player command may have changed the configuration and
|
||||
// needs a full structural rebuild.
|
||||
enum class RefreshReason
|
||||
{
|
||||
PeriodicTick,
|
||||
CommandApplied
|
||||
};
|
||||
|
||||
void onSelectionChanged(const std::vector<BuildingId>& ids);
|
||||
// Gives the panel to the field category once it has anything selected.
|
||||
void yieldToFieldSelection();
|
||||
// Shows the panel while either category has a selection and hides it otherwise
|
||||
// (REQ-UI-EMPTY-SELECTION), re-fitting it to its current content while it is shown.
|
||||
// Every path that changes the content ends here, because the content is what sizes
|
||||
// the panel.
|
||||
void updateVisibility();
|
||||
// Re-fits the panel to its content within the anchored band.
|
||||
void refit();
|
||||
void refreshSelectionDisplay(RefreshReason reason);
|
||||
void rebuild();
|
||||
void hideAllWidgets();
|
||||
void buildEmpty();
|
||||
void buildSingle(BuildingId id);
|
||||
void buildMulti(const std::vector<BuildingId>& ids);
|
||||
void refreshBuffers(const Building* b);
|
||||
void refreshSiteProgress(const ConstructionSite* s);
|
||||
void updateShipyardLayoutWidgets(BuildingType type,
|
||||
const std::string& recipeId,
|
||||
const std::optional<ShipLayoutConfig>& shipLayout);
|
||||
void buildSplitterFilters(const std::optional<BeltSystem::SplitterInfo>& info);
|
||||
const RecipeDef* findRecipe(const Building* b) const;
|
||||
const ShipDef* findShipDef(const std::string& id) const;
|
||||
std::vector<std::string> getAllItemIds() const;
|
||||
|
||||
Simulation* m_sim;
|
||||
const GameConfig* m_config;
|
||||
std::vector<BuildingId> m_selectedBuildingIds;
|
||||
|
||||
// The band the panel confines itself to, in the coordinates of its parent; null
|
||||
// until the owner has anchored it for the first time.
|
||||
QRect m_bandRect;
|
||||
|
||||
// Scrolls the content once it outgrows the band (REQ-UI-SELECTION-PANEL). All the
|
||||
// content widgets below are children of m_content, not of the panel itself.
|
||||
QScrollArea* m_scrollArea;
|
||||
QWidget* m_content;
|
||||
|
||||
QVBoxLayout* m_layout;
|
||||
QLabel* m_titleLabel;
|
||||
QPushButton* m_recipeSelectButton;
|
||||
QPushButton* m_clearBeltBtn;
|
||||
QLabel* m_filterALabel;
|
||||
QListWidget* m_filterAList;
|
||||
QLabel* m_filterBLabel;
|
||||
QListWidget* m_filterBList;
|
||||
QLabel* m_buffersLabel;
|
||||
|
||||
ShipLayoutPreview* m_layoutPreview;
|
||||
QPushButton* m_configureLayoutBtn;
|
||||
|
||||
std::optional<BuildingId> m_singleBuildingId;
|
||||
bool m_singleIsSite = false; // selected single entity is a construction site
|
||||
QPoint m_splitterTile;
|
||||
std::string m_currentRecipeId;
|
||||
|
||||
// Renders the field selection (actors + debris) below the building content
|
||||
// (REQ-UI-FIELD-MULTI-SELECTION). Hides itself while nothing field-side is selected.
|
||||
FieldSelectionPanel* m_fieldSelectionPanel;
|
||||
};
|
||||
Reference in New Issue
Block a user