Files
dota_factory/src/ui/ExpandButton.cpp
Malte Langkabel abe8c8f448 stand the expansion button on the ground it buys
The button leaves the header bar for the world, centered on the columns
the next purchase unlocks and panning with them until it leaves the view.
Those columns now take a lighter tint than the locked ground behind them,
so the boundary between the two says how far one purchase reaches.

Nothing in the code reported a scroll: the camera knew it had moved and
told only the hover. A ViewScrolledEvent says it now, which is what a
widget keeping a place in the world rather than on the screen needs. The
panels want none of it -- they are placed against the screen and stay put
as the world moves under them -- so the button is placed after their pass
and never joins the rectangles they step around.

Its face is two lines, "Expand" over the cost. That makes the cost a
display of its own, so it carries the building-block tooltip the way every
other item value does, on hover alone since the click buys the expansion.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ne3mejABZoLWKLh8fgpM3x
2026-08-18 22:55:06 +02:00

100 lines
3.4 KiB
C++

#include "ExpandButton.h"
#include <QLabel>
#include <QPalette>
#include <QPixmap>
#include <QVBoxLayout>
#include "Command.h"
#include "CommandRequestedEvent.h"
#include "EventManager.h"
#include "FloatingLayoutInvalidatedEvent.h"
#include "IconCaption.h"
#include "ItemIconCache.h"
#include "ItemTooltip.h"
#include "Simulation.h"
#include "TooltipTrigger.h"
ExpandButton::ExpandButton(const ItemTooltipContext& context, QWidget* parent)
: OptionButton(parent)
, m_context(context)
{
QVBoxLayout* face = new QVBoxLayout(this);
face->setContentsMargins(8, 4, 8, 4);
face->setSpacing(1);
// Names the action, not an item, so it says nothing of its own and stays out of the
// mouse's way -- a click anywhere on the face reaches the button beneath it.
QLabel* actionLabel = new QLabel(tr("Expand"), this);
actionLabel->setAlignment(Qt::AlignCenter);
actionLabel->setAttribute(Qt::WA_TransparentForMouseEvents, true);
face->addWidget(actionLabel);
// The cost line, deliberately not transparent to the mouse: it names an item and has
// to be hoverable to explain it. Hover only, the click being the button's
// (REQ-UI-ITEM-VALUE-TOOLTIP). A label ignores presses, so they still reach the
// button.
m_costLabel = new QLabel(this);
m_costLabel->setAlignment(Qt::AlignCenter);
face->addWidget(m_costLabel);
ItemTooltip::attachTo(*m_costLabel, m_context, kBlockItemId,
TooltipTrigger::Trigger::HoverOnly);
// Carries no payload: the simulation derives the cost and the column count from its
// own expansion counter (REQ-EXP-UNLOCK, REQ-GW-ASTEROID-EXPAND).
connect(this, &QPushButton::clicked, this, []() {
EventManager::getInstance()->sendEventImmediately(
std::make_shared<CommandRequestedEvent>(
std::make_shared<ExpandAsteroidCommand>()));
});
refresh();
registerForEvents();
}
ExpandButton::~ExpandButton()
{
unregisterForEvents();
}
void ExpandButton::handleEvent(std::shared_ptr<const ExpansionCostChangedEvent> /*event*/)
{
refresh();
}
void ExpandButton::handleEvent(std::shared_ptr<const BuildingBlocksChangedEvent> /*event*/)
{
refresh();
}
void ExpandButton::refresh()
{
const int blocks = m_context.sim->getBuildingBlocksStock();
const int expansionCost = m_context.sim->getCurrentExpansionCost();
setEnabled(blocks >= expansionCost);
// The cost reads as it does everywhere else: the number, then the block icon in place
// of a trailing `Blocks` word (REQ-UI-BLOCKS-ICON, REQ-UI-ITEM-ICON). With no icon
// file the word comes back, since nothing else on the line would name the item.
const QPixmap icon = m_context.itemIcons->getInlineIcon(kBlockItemId, font());
if (icon.isNull())
{
m_costLabel->setPixmap(QPixmap());
m_costLabel->setText(tr("%1 Blocks").arg(expansionCost));
}
else
{
m_costLabel->setText(QString());
m_costLabel->setPixmap(renderCaptionWithIcon(
QString::number(expansionCost), icon, font(),
palette().color(isEnabled() ? QPalette::Active : QPalette::Disabled,
QPalette::ButtonText)));
}
// A cost of a different width re-centers the button on its columns, which is the
// owner's to do (ui/FloatingPanel.h, MainWindow::placeExpandButton).
EventManager::getInstance()->sendEventImmediately(
std::make_shared<FloatingLayoutInvalidatedEvent>());
}