116 lines
4.8 KiB
C++
116 lines
4.8 KiB
C++
#pragma once
|
|
|
|
#include <optional>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <QString>
|
|
#include <QWidget>
|
|
|
|
#include "BuildingType.h"
|
|
|
|
class BuildingIconCache;
|
|
class ItemIconCache;
|
|
class QHBoxLayout;
|
|
class QVBoxLayout;
|
|
|
|
// One recipe drawn: what it consumes, an arrow, what it produces, and how long a cycle
|
|
// takes (REQ-UI-RECIPE-SUMMARY), under a header naming the building that runs it and the
|
|
// recipe itself where the recipe has to identify itself. Every place the UI states what
|
|
// something makes draws this same line, so a recipe reads alike wherever it is shown:
|
|
//
|
|
// * beneath the selection button, for the recipe a building is running
|
|
// (REQ-UI-RECIPE-SUMMARY);
|
|
// * on a selection dialog's option buttons, under the option's name
|
|
// (REQ-UI-SELECT-OPTIONS);
|
|
// * in an item's production tooltip and in the unlock-choice dialog, there led by the
|
|
// icon of the building that runs the recipe and its name
|
|
// (REQ-UI-ITEM-TOOLTIP, REQ-DEF-SCHEMATIC-DROP);
|
|
// * on a module button and in the layout dialog's build cost, where there is a price
|
|
// and a time but nothing produced (REQ-MOD-UI-DIALOG, REQ-MOD-UI-STATS-PANEL).
|
|
class RecipeLineRow : public QWidget
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
// One item and how many of it the line states.
|
|
struct Amount
|
|
{
|
|
std::string itemId;
|
|
int amount = 0;
|
|
|
|
bool operator==(const Amount& other) const
|
|
{
|
|
return itemId == other.itemId && amount == other.amount;
|
|
}
|
|
};
|
|
|
|
// What the line says. Everything but the inputs is optional, which is what lets the
|
|
// one widget serve the summary, the option buttons, the tooltip lines and the cost
|
|
// lines.
|
|
struct Spec
|
|
{
|
|
// The chip of the building running the recipe, on the header line, where the
|
|
// recipe has to say which building that is -- an item may have several producers
|
|
// (REQ-UI-ITEM-TOOLTIP). Unset wherever the surrounding widget already
|
|
// establishes the building, and the header line is then left out entirely.
|
|
std::optional<BuildingType> building;
|
|
// The recipe's name, beside the building chip on the header line. Empty where the
|
|
// name is the caption of the widget around this one instead.
|
|
QString name;
|
|
std::vector<Amount> inputs;
|
|
// Empty for a line that produces no item of its own: a ship schematic, or a
|
|
// module's price. No arrow is drawn then.
|
|
std::vector<Amount> outputs;
|
|
std::optional<double> durationSeconds;
|
|
// True where the time is added to something else rather than being a cycle of
|
|
// its own, and so reads "+3.0 s" (REQ-MOD-UI-DIALOG).
|
|
bool durationIsAddition = false;
|
|
|
|
bool operator==(const Spec& other) const
|
|
{
|
|
return building == other.building && name == other.name
|
|
&& inputs == other.inputs && outputs == other.outputs
|
|
&& durationSeconds == other.durationSeconds
|
|
&& durationIsAddition == other.durationIsAddition;
|
|
}
|
|
|
|
bool isEmpty() const { return inputs.empty() && outputs.empty(); }
|
|
};
|
|
|
|
// Both caches may be null, which leaves the icons off: an item with no square and
|
|
// no icon falls back to its id, and a building with no chip to its name alone.
|
|
// Neither is owned.
|
|
RecipeLineRow(ItemIconCache* itemIcons, BuildingIconCache* buildingIcons,
|
|
QWidget* parent = nullptr);
|
|
|
|
// Hides the row when the spec has nothing to state, which is how a building with no
|
|
// recipe shows no summary at all (REQ-UI-RECIPE-SUMMARY).
|
|
void setLine(const Spec& spec);
|
|
|
|
// Boxes the line in a card of its own, for the two places that stack several of them
|
|
// (REQ-UI-ITEM-TOOLTIP, REQ-DEF-SCHEMATIC-DROP): a run of bare lines reads as one
|
|
// field of icons and numbers, and the box is what separates one recipe from the next.
|
|
// Off by default -- a line drawn inside a button or a panel section is already framed
|
|
// by what holds it.
|
|
void setCardChrome(bool enabled);
|
|
|
|
private:
|
|
void rebuild(const Spec& spec);
|
|
void addAmounts(const std::vector<Amount>& amounts);
|
|
|
|
ItemIconCache* m_itemIcons;
|
|
BuildingIconCache* m_buildingIcons;
|
|
QVBoxLayout* m_outerLayout;
|
|
// The two lines, each a row widget of its own so a rebuild only has to empty their
|
|
// layouts -- no nested layout to take apart. The header is hidden where the spec
|
|
// names neither a building nor a recipe.
|
|
QWidget* m_headerRow;
|
|
QHBoxLayout* m_headerLayout;
|
|
QWidget* m_amountsRow;
|
|
QHBoxLayout* m_amountsLayout;
|
|
// What the row currently shows, so a refresh at tick rate rebuilds it only when the
|
|
// recipe actually changed.
|
|
Spec m_spec;
|
|
};
|