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:
102
src/ui/ItemTooltip.cpp
Normal file
102
src/ui/ItemTooltip.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
#include "ItemTooltip.h"
|
||||
|
||||
#include <QFont>
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "DisplayName.h"
|
||||
#include "GameConfig.h"
|
||||
#include "ItemProducers.h"
|
||||
#include "RecipeLineRow.h"
|
||||
#include "RecipesConfig.h"
|
||||
#include "Simulation.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
std::vector<RecipeLineRow::Amount> toAmounts(
|
||||
const std::vector<RecipeIngredient>& ingredients)
|
||||
{
|
||||
std::vector<RecipeLineRow::Amount> amounts;
|
||||
amounts.reserve(ingredients.size());
|
||||
for (const RecipeIngredient& ingredient : ingredients)
|
||||
{
|
||||
amounts.push_back(RecipeLineRow::Amount{ ingredient.item, ingredient.amount });
|
||||
}
|
||||
return amounts;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void ItemTooltip::attachTo(QWidget& target, const ItemTooltipContext& context,
|
||||
const std::string& itemId, TooltipTrigger::Trigger trigger)
|
||||
{
|
||||
ItemTooltip* tooltip = new ItemTooltip(context, itemId, &target);
|
||||
TooltipTrigger::attach(target, *tooltip, trigger);
|
||||
}
|
||||
|
||||
ItemTooltip::ItemTooltip(const ItemTooltipContext& context, const std::string& itemId,
|
||||
QWidget* parent)
|
||||
: Tooltip(parent)
|
||||
, m_context(context)
|
||||
, m_itemId(itemId)
|
||||
{
|
||||
}
|
||||
|
||||
void ItemTooltip::refreshContent()
|
||||
{
|
||||
clearContent();
|
||||
QVBoxLayout* layout = getContentLayout();
|
||||
|
||||
// The heading names the item. For an input chip this is the only place it is named
|
||||
// at all, since such a chip carries a count and no name (REQ-UI-SINGLE-SELECTION).
|
||||
QLabel* heading =
|
||||
new QLabel(QString::fromStdString(toDisplayName(m_itemId)), this);
|
||||
QFont headingFont = heading->font();
|
||||
headingFont.setBold(true);
|
||||
heading->setFont(headingFont);
|
||||
layout->addWidget(heading);
|
||||
heading->show();
|
||||
|
||||
const ItemProduction production =
|
||||
findItemProduction(m_itemId, *m_context.sim, *m_context.config);
|
||||
|
||||
// Scrap is salvaged from debris rather than crafted (REQ-RES-DEBRIS-DROP), so it
|
||||
// says where it comes from in place of the caption and lists nothing.
|
||||
QLabel* caption = new QLabel(production.origin == ItemOrigin::Salvaged
|
||||
? tr("Salvaged from debris")
|
||||
: tr("Produced by"), this);
|
||||
layout->addWidget(caption);
|
||||
caption->show();
|
||||
|
||||
if (production.origin == ItemOrigin::Undiscovered)
|
||||
{
|
||||
// Made somehow, but by nothing the player has unlocked -- named without being
|
||||
// shown a path they cannot take yet (REQ-UI-ITEM-TOOLTIP).
|
||||
QLabel* undiscovered = new QLabel(tr("Undiscovered"), this);
|
||||
layout->addWidget(undiscovered);
|
||||
undiscovered->show();
|
||||
return;
|
||||
}
|
||||
|
||||
for (const RecipeDef* recipe : production.recipes)
|
||||
{
|
||||
RecipeLineRow::Spec spec;
|
||||
spec.building = recipe->building;
|
||||
spec.name = QString::fromStdString(toDisplayName(recipe->id));
|
||||
spec.inputs = toAmounts(recipe->inputs);
|
||||
spec.outputGroups = RecipeLineRow::toOutputGroups(*recipe);
|
||||
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). The items it
|
||||
// names carry no tooltip of their own: this is already one
|
||||
// (REQ-UI-ITEM-VALUE-TOOLTIP).
|
||||
RecipeLineRow* line =
|
||||
new RecipeLineRow(m_context.itemIcons, m_context.buildingIcons, this);
|
||||
line->setCardChrome(true);
|
||||
layout->addWidget(line);
|
||||
line->setLine(spec);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user