Item icons were drawn bare in the panels and dialogs while only the game world composed them onto the item's visuals.toml square, so the same item read differently on a belt than in a panel. Move the composition into ItemIconCache, which now holds the visuals and offers it in two forms: paintItem() for the world's fractional geometry and getSquarePixmap() for widgets. WorldRenderer::drawWorldItem collapses onto the former, and the recipe-selection dialog, the selection panel's item chips and the recipe summary onto the latter. The inset fraction that shapes the composition now has one definition instead of two. An item with no icon file now shows its square alone rather than falling back to text, so callers gate on the composed pixmap being null -- the case of an item with neither square nor icon -- instead of on hasIcon(). The inline building_block icon beside a number keeps using the bare getPixmap() and takes no square. The chip and summary squares are drawn a few pixels larger than the icons were, so the artwork keeps its size once the square insets it. Reloading the visuals on a restart drops the composed pixmaps, which carry the colors they were painted with (REQ-CFG-RELOAD). REQ-UI-ITEM-ICON, REQ-UI-RECIPE-ICON, REQ-UI-SINGLE-SELECTION, REQ-UI-RECIPE-SUMMARY, REQ-UI-HQ-PANEL Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ne3mejABZoLWKLh8fgpM3x
84 lines
2.6 KiB
C++
84 lines
2.6 KiB
C++
#include "ItemChipRow.h"
|
|
|
|
#include <QGridLayout>
|
|
|
|
#include "ItemChip.h"
|
|
#include "ItemIconCache.h"
|
|
|
|
namespace
|
|
{
|
|
|
|
// Size the item's colored square is drawn at inside a chip, in device-independent
|
|
// pixels. Larger than the artwork it carries, which the square insets (REQ-UI-ITEM-ICON).
|
|
const int kChipIconSizePx = 22;
|
|
|
|
// Chips per row. Two fit the panel's capped width side by side; a third would force the
|
|
// counts to shrink.
|
|
const int kChipsPerRow = 2;
|
|
|
|
} // namespace
|
|
|
|
|
|
ItemChipRow::ItemChipRow(ItemIconCache* itemIcons, QWidget* parent)
|
|
: QWidget(parent)
|
|
, m_itemIcons(itemIcons)
|
|
{
|
|
m_layout = new QGridLayout(this);
|
|
m_layout->setContentsMargins(0, 0, 0, 0);
|
|
m_layout->setSpacing(4);
|
|
}
|
|
|
|
void ItemChipRow::setEntries(const std::vector<Entry>& entries)
|
|
{
|
|
std::vector<std::string> itemIds;
|
|
itemIds.reserve(entries.size());
|
|
for (const Entry& entry : entries)
|
|
{
|
|
itemIds.push_back(entry.itemId);
|
|
}
|
|
|
|
// Only the set of items changing is a structural change; the counts change every
|
|
// tick and must not cost a widget rebuild.
|
|
if (itemIds != m_itemIds)
|
|
{
|
|
m_itemIds = std::move(itemIds);
|
|
rebuildChips(entries);
|
|
}
|
|
|
|
for (std::size_t index = 0; index < entries.size(); ++index)
|
|
{
|
|
m_chips[index]->setCount(entries[index].countText);
|
|
m_chips[index]->setSubLine(entries[index].subLine);
|
|
}
|
|
setVisible(!entries.empty());
|
|
}
|
|
|
|
void ItemChipRow::rebuildChips(const std::vector<Entry>& entries)
|
|
{
|
|
for (ItemChip* chip : m_chips)
|
|
{
|
|
m_layout->removeWidget(chip);
|
|
chip->deleteLater();
|
|
}
|
|
m_chips.clear();
|
|
|
|
for (std::size_t index = 0; index < entries.size(); ++index)
|
|
{
|
|
const std::string& itemId = entries[index].itemId;
|
|
// The item's icon on its colored square (REQ-UI-ITEM-ICON). A missing icon file
|
|
// is not an error: the chip then carries the square alone, and only an item with
|
|
// no square either leaves the chip laid out around its count alone.
|
|
const QPixmap icon = m_itemIcons->getSquarePixmap(itemId, kChipIconSizePx);
|
|
|
|
ItemChip* chip = new ItemChip(icon, this);
|
|
m_layout->addWidget(chip, static_cast<int>(index) / kChipsPerRow,
|
|
static_cast<int>(index) % kChipsPerRow);
|
|
// Shown right away, because the panel measures itself as soon as this returns. A
|
|
// widget created under an already-visible parent starts hidden, and a layout
|
|
// treats a hidden item as empty, so an unshown chip would add nothing to the
|
|
// size hint and the panel would be fitted to a buffer section that looks empty.
|
|
chip->show();
|
|
m_chips.push_back(chip);
|
|
}
|
|
}
|