explain an item wherever the UI names one

Every display naming an item now shows that item's production tooltip, not
only the selection panel's chips: the header block stock, the total cost of
a building multi-selection, the remaining scrap of a debris selection, the
icons of every recipe summary, and a blueprint card's cost.

ItemTooltip moves out of the selection panel and takes an
ItemTooltipContext of its own -- an item is named all over the UI, and the
panel's context carries visuals and a debug flag no tooltip reads. A
recipe line wraps each icon with its amount so the pair can be pointed at
as one statement, and attaches tooltips only where asked: a module button
and the item tooltip itself draw the same line and stay silent.

Hover only wherever the display sits on something the player clicks, whose
click is not free to explain. Note that a recipe line on an option button
can no longer be transparent to the mouse -- Qt never looks inside a
transparent widget for the cursor -- so it relies on press propagation to
keep picking the option.

The header block stock loses world.building_blocks_tooltip, showing what
every other block icon shows instead. The Expand button keeps no tooltip:
its cost is painted into its face with nowhere to hang one, and the button
is due to be removed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ne3mejABZoLWKLh8fgpM3x
This commit is contained in:
2026-08-18 21:41:34 +02:00
parent dcc801f017
commit 44ec3c51f1
34 changed files with 336 additions and 157 deletions

View File

@@ -418,17 +418,17 @@ private:
// ShipLayoutDialog implementation
// ---------------------------------------------------------------------------
ShipLayoutDialog::ShipLayoutDialog(const GameConfig* config,
const std::string& shipId,
ShipLayoutDialog::ShipLayoutDialog(const std::string& shipId,
const ShipLayoutConfig& currentLayout,
std::vector<ShipLayoutBlueprint>& allBlueprints,
std::set<std::string> unlockedModuleIds,
bool debugDraw,
ItemIconCache* itemIcons,
const ItemTooltipContext& context,
QWidget* parent)
: ModalDialog(parent)
, m_config(config)
, m_itemIcons(itemIcons)
, m_context(context)
, m_config(context.config)
, m_itemIcons(context.itemIcons)
, m_shipId(shipId)
, m_unlockedModuleIds(std::move(unlockedModuleIds))
, m_rows(0)
@@ -441,7 +441,7 @@ ShipLayoutDialog::ShipLayoutDialog(const GameConfig* config,
, m_debugDraw(debugDraw)
{
// Find the ship's layout grid.
const ShipDef* shipDef = config->ships.findShipDef(shipId);
const ShipDef* shipDef = m_config->ships.findShipDef(shipId);
if (shipDef)
{
m_shipLayout = shipDef->layout;
@@ -495,12 +495,15 @@ ShipLayoutDialog::ShipLayoutDialog(const GameConfig* config,
// neither of which costs anything -- and the balancing tool is deliberately built
// without the item icons this line draws with.
QVBoxLayout* leftLayout = new QVBoxLayout();
m_statsPanel = new ShipStatsPanel(config, this);
m_statsPanel = new ShipStatsPanel(m_config, this);
m_statsPanel->setDebugDrawEnabled(m_debugDraw);
leftLayout->addWidget(m_statsPanel);
m_buildCostSection = new SectionBox(tr("Build cost"), this);
m_buildCostLine = new RecipeLineRow(m_itemIcons, nullptr, m_buildCostSection);
// A section of the dialog rather than a control, so its materials explain themselves
// on hover or click, as they do in the panel (REQ-UI-ITEM-VALUE-TOOLTIP).
m_buildCostLine->setItemTooltips(m_context, TooltipTrigger::Trigger::HoverAndClick);
m_buildCostSection->getContentLayout()->addWidget(m_buildCostLine);
leftLayout->addWidget(m_buildCostSection);
leftLayout->addStretch(1);
@@ -517,9 +520,9 @@ ShipLayoutDialog::ShipLayoutDialog(const GameConfig* config,
int row = 0;
const int kCols = 2;
for (int i = 0; i < static_cast<int>(config->modules.modules.size()); ++i)
for (int i = 0; i < static_cast<int>(m_config->modules.modules.size()); ++i)
{
const ModuleDef& def = config->modules.modules[i];
const ModuleDef& def = m_config->modules.modules[i];
if (m_unlockedModuleIds.count(def.id) == 0)
{
m_moduleButtons.push_back(nullptr);
@@ -553,7 +556,10 @@ ShipLayoutDialog::ShipLayoutDialog(const GameConfig* config,
// The config tooltip stays: it says what the module does, which the cost line
// does not (REQ-MOD-UI-MODULE-TOOLTIP). Hover only: the click selects the module
// (REQ-UI-TOOLTIP-TRIGGER).
// (REQ-UI-TOOLTIP-TRIGGER). The materials on the face stay silent whether or not
// this module fills its description in -- the button is a described control, and
// one module's config gap must not make it read differently from the one beside
// it (REQ-UI-ITEM-VALUE-TOOLTIP).
if (def.tooltip)
{
TooltipTrigger::attachText(*btn, QString::fromStdString(*def.tooltip),