add border around recipes where several of them stack

This commit is contained in:
2026-08-12 08:30:10 +02:00
parent a3fddf63cc
commit bd8fe5157e
5 changed files with 49 additions and 9 deletions

View File

@@ -1,8 +1,10 @@
#include "RecipeLineRow.h"
#include <QFont>
#include <QHBoxLayout>
#include <QLabel>
#include <QLayoutItem>
#include <QMargins>
#include <QPixmap>
#include <QVBoxLayout>
@@ -51,26 +53,40 @@ RecipeLineRow::RecipeLineRow(ItemIconCache* itemIcons, BuildingIconCache* buildi
, m_itemIcons(itemIcons)
, m_buildingIcons(buildingIcons)
{
QVBoxLayout* outerLayout = new QVBoxLayout(this);
outerLayout->setContentsMargins(0, 0, 0, 0);
outerLayout->setSpacing(1);
m_outerLayout = new QVBoxLayout(this);
m_outerLayout->setContentsMargins(0, 0, 0, 0);
m_outerLayout->setSpacing(1);
m_headerRow = new QWidget(this);
m_headerLayout = new QHBoxLayout(m_headerRow);
m_headerLayout->setContentsMargins(0, 0, 0, 0);
m_headerLayout->setSpacing(4);
m_headerRow->hide();
outerLayout->addWidget(m_headerRow);
m_outerLayout->addWidget(m_headerRow);
m_amountsRow = new QWidget(this);
m_amountsLayout = new QHBoxLayout(m_amountsRow);
m_amountsLayout->setContentsMargins(0, 0, 0, 0);
m_amountsLayout->setSpacing(4);
outerLayout->addWidget(m_amountsRow);
m_outerLayout->addWidget(m_amountsRow);
hide();
}
void RecipeLineRow::setCardChrome(bool enabled)
{
// Palette colors like the item chip's chrome (REQ-UI-SELECTION-CARD), not
// visuals.toml, which is for world rendering. The selector names this class alone, so
// nothing inside the card inherits the border.
setAttribute(Qt::WA_StyledBackground, enabled);
setStyleSheet(enabled
? QStringLiteral("RecipeLineRow { border: 1px solid palette(mid); "
"border-radius: 4px; }")
: QString());
m_outerLayout->setContentsMargins(enabled ? QMargins(6, 4, 6, 4)
: QMargins(0, 0, 0, 0));
}
void RecipeLineRow::setLine(const Spec& spec)
{
if (spec.isEmpty())
@@ -112,7 +128,11 @@ void RecipeLineRow::rebuild(const Spec& spec)
}
if (!spec.name.isEmpty())
{
addAndShow(m_headerLayout, new QLabel(spec.name, m_headerRow));
QLabel* nameLabel = new QLabel(spec.name, m_headerRow);
QFont nameFont = nameLabel->font();
nameFont.setBold(true);
nameLabel->setFont(nameFont);
addAndShow(m_headerLayout, nameLabel);
}
const bool hasHeader = m_headerLayout->count() > 0;
if (hasHeader)
@@ -146,6 +166,13 @@ void RecipeLineRow::addAmounts(const std::vector<Amount>& amounts)
{
for (const Amount& entry : amounts)
{
// Between one item and the next, so a run of icons and numbers reads as a sum
// rather than as a list.
if (&entry != &amounts.front())
{
addAndShow(m_amountsLayout, new QLabel(QStringLiteral("+"), m_amountsRow));
}
// The item's icon on its colored square (REQ-UI-ITEM-ICON). A missing icon file
// is not an error: the square stands alone then, and only an item with no square
// either falls back to its id in text.

View File

@@ -12,6 +12,7 @@
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
@@ -87,12 +88,20 @@ public:
// 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.

View File

@@ -152,6 +152,7 @@ SchematicChoiceDialog::SchematicChoiceDialog(
RecipeLineRow* line =
new RecipeLineRow(itemIcons, buildingIcons, card);
line->setCardChrome(true);
cardLayout->addWidget(line);
line->setLine(spec);
}

View File

@@ -155,8 +155,11 @@ void ItemTooltip::rebuild()
spec.outputs = toAmounts(recipe->outputs);
spec.durationSeconds = recipe->durationSeconds;
// Boxed, because an item with several producers stacks several of these and a run
// of bare lines reads as one field of icons (REQ-UI-ITEM-TOOLTIP).
RecipeLineRow* line =
new RecipeLineRow(m_context.itemIcons, m_context.buildingIcons, this);
line->setCardChrome(true);
m_layout->addWidget(line);
line->setLine(spec);
}