give the selection cards their own parts instead of label blobs

This commit is contained in:
2026-08-07 18:43:23 +02:00
parent 2289277e12
commit 075e44d295
54 changed files with 1505 additions and 533 deletions

View File

@@ -1,24 +1,17 @@
#include "BufferSection.h"
#include <QLabel>
#include <vector>
#include <QVBoxLayout>
#include "Building.h"
#include "DisplayName.h"
#include "ItemChipRow.h"
#include "SectionBox.h"
namespace
{
// One "<item>: <count>[/<per cycle>]" entry.
QString formatEntry(const std::string& itemId, int count, int perCycle)
{
QString text = QString::fromStdString(itemId) + ": " + QString::number(count);
if (perCycle > 0)
{
text += "/" + QString::number(perCycle);
}
return text + " ";
}
int findPerCycle(const std::map<std::string, int>& perCycle, const std::string& itemId)
{
const std::map<std::string, int>::const_iterator it = perCycle.find(itemId);
@@ -28,33 +21,42 @@ int findPerCycle(const std::map<std::string, int>& perCycle, const std::string&
} // namespace
BufferSection::BufferSection(QWidget* parent)
BufferSection::BufferSection(const SelectionContext& context, QWidget* parent)
: QWidget(parent)
{
QVBoxLayout* layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0);
layout->setSpacing(6);
m_label = new QLabel(this);
m_label->setWordWrap(true);
layout->addWidget(m_label);
m_inputSection = new SectionBox(tr("Input buffers"), this);
m_inputChips = new ItemChipRow(context.itemIcons, m_inputSection);
m_inputSection->getContentLayout()->addWidget(m_inputChips);
m_outputSection = new SectionBox(tr("Output buffer"), this);
m_outputChips = new ItemChipRow(context.itemIcons, m_outputSection);
m_outputSection->getContentLayout()->addWidget(m_outputChips);
layout->addWidget(m_inputSection);
layout->addWidget(m_outputSection);
}
void BufferSection::setBuffers(const Building& building,
const std::map<std::string, int>& perCycleInputs,
const std::map<std::string, int>& perCycleOutputs)
{
QString text;
if (!building.inputBuffer.counts.empty())
std::vector<ItemChipRow::Entry> inputs;
for (const std::pair<const ItemType, int>& entry : building.inputBuffer.counts)
{
text += tr("Input: ");
for (const std::pair<const ItemType, int>& entry : building.inputBuffer.counts)
ItemChipRow::Entry chip;
chip.itemId = entry.first.id;
chip.countText = QString::number(entry.second);
const int perCycle = findPerCycle(perCycleInputs, entry.first.id);
if (perCycle > 0)
{
text += formatEntry(entry.first.id, entry.second,
findPerCycle(perCycleInputs, entry.first.id));
chip.subLine = tr("/ %1 per cycle").arg(perCycle);
}
text += "\n";
inputs.push_back(chip);
}
// Output-side items are the buffered ones plus those still emerging onto the output
@@ -72,24 +74,30 @@ void BufferSection::setBuffers(const Building& building,
outputCounts[slot.item.type.id]++;
}
}
// A configured building lists every item its cycle produces, so an output the player
// is waiting for shows as 0 rather than being absent.
// A configured building lists everything its cycle produces, so an output the player
// is waiting for reads as 0 rather than being absent.
for (const std::pair<const std::string, int>& entry : perCycleOutputs)
{
outputCounts.emplace(entry.first, 0);
}
if (!outputCounts.empty())
std::vector<ItemChipRow::Entry> outputs;
for (const std::pair<const std::string, int>& entry : outputCounts)
{
text += tr("Output: ");
for (const std::pair<const std::string, int>& entry : outputCounts)
{
text += formatEntry(entry.first, entry.second,
findPerCycle(perCycleOutputs, entry.first));
}
ItemChipRow::Entry chip;
chip.itemId = entry.first;
// Counted against the buffer's capacity, which is what production stops at
// (REQ-MAT-OUTPUT-BUFFER).
chip.countText = building.outputBuffer.capacity > 0
? tr("%1 / %2").arg(entry.second).arg(building.outputBuffer.capacity)
: QString::number(entry.second);
chip.subLine = QString::fromStdString(toDisplayName(entry.first));
outputs.push_back(chip);
}
m_label->setText(text.trimmed());
setVisible(!text.trimmed().isEmpty());
m_inputChips->setEntries(inputs);
m_outputChips->setEntries(outputs);
m_inputSection->setVisible(!inputs.empty());
m_outputSection->setVisible(!outputs.empty());
setVisible(!inputs.empty() || !outputs.empty());
}