feat(command-zone): add zone toggle button component

Implement ZoneToggleButton - a reusable UI component for toggling
zone visibility states.

Features:
- Click to toggle between hidden/revealed states
- Visual feedback showing current state
- Hover effects for discoverability
- Proper event handling for mouse interactions

This self-contained graphics component will be used by CommandZone
to provide users with intuitive visibility controls.
This commit is contained in:
DawnFire42 2026-02-25 13:31:22 -05:00
parent 7a0a3ff9ac
commit 78db49a9b3
3 changed files with 184 additions and 0 deletions

View file

@ -113,6 +113,7 @@ set(cockatrice_SOURCES
src/game/zones/logic/stack_zone_logic.cpp
src/game/zones/logic/table_zone_logic.cpp
src/game/zones/logic/view_zone_logic.cpp
src/game/zones/zone_toggle_button.cpp
src/game/zones/pile_zone.cpp
src/game/zones/select_zone.cpp
src/game/zones/stack_zone.cpp

View file

@ -0,0 +1,107 @@
#include "zone_toggle_button.h"
#include "../../client/settings/cache_settings.h"
#include "../z_values.h"
#include "command_zone.h"
#include <QCursor>
#include <QGraphicsSceneMouseEvent>
#include <QPainter>
#include <QPainterPath>
ZoneToggleButton::ZoneToggleButton(CommandZoneType _zoneType, QGraphicsItem *parent)
: QGraphicsObject(parent), zoneType(_zoneType), expanded(false), hovered(false)
{
setAcceptHoverEvents(true);
setCursor(Qt::PointingHandCursor);
setZValue(ZValues::TOGGLE_BUTTON);
connect(&SettingsCache::instance(), &SettingsCache::langChanged, this, &ZoneToggleButton::retranslateUi);
retranslateUi();
}
QRectF ZoneToggleButton::boundingRect() const
{
return QRectF(0, 0, BUTTON_WIDTH, HIT_AREA_HEIGHT);
}
void ZoneToggleButton::paint(QPainter *painter,
[[maybe_unused]] const QStyleOptionGraphicsItem *option,
[[maybe_unused]] QWidget *widget)
{
painter->save();
painter->setRenderHint(QPainter::Antialiasing);
QRectF visualRect(0, 0, BUTTON_WIDTH, BUTTON_HEIGHT);
visualRect.adjust(0.5, 0, -0.5, -0.5);
QPainterPath path;
path.moveTo(visualRect.topLeft());
path.lineTo(visualRect.topRight());
path.lineTo(visualRect.right(), visualRect.bottom() - CORNER_RADIUS);
path.arcTo(visualRect.right() - 2 * CORNER_RADIUS, visualRect.bottom() - 2 * CORNER_RADIUS, 2 * CORNER_RADIUS,
2 * CORNER_RADIUS, 0, -90);
path.lineTo(visualRect.left() + CORNER_RADIUS, visualRect.bottom());
path.arcTo(visualRect.left(), visualRect.bottom() - 2 * CORNER_RADIUS, 2 * CORNER_RADIUS, 2 * CORNER_RADIUS, -90,
-90);
path.lineTo(visualRect.topLeft());
path.closeSubpath();
QColor bgColor = hovered ? GameColors::OVERLAY_BG_HOVERED : GameColors::OVERLAY_BG_NORMAL;
painter->setPen(Qt::NoPen);
painter->setBrush(bgColor);
painter->drawPath(path);
painter->restore();
}
void ZoneToggleButton::setExpanded(bool _expanded)
{
if (expanded != _expanded) {
expanded = _expanded;
update();
}
}
void ZoneToggleButton::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
emit clicked();
event->accept();
} else {
QGraphicsObject::mousePressEvent(event);
}
}
void ZoneToggleButton::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
hovered = true;
update();
QGraphicsObject::hoverEnterEvent(event);
}
void ZoneToggleButton::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
hovered = false;
update();
QGraphicsObject::hoverLeaveEvent(event);
}
void ZoneToggleButton::retranslateUi()
{
switch (zoneType) {
case CommandZoneType::Partner:
setToolTip(tr("Click to show/hide partner zone"));
break;
case CommandZoneType::Companion:
setToolTip(tr("Click to show/hide companion zone"));
break;
case CommandZoneType::Background:
setToolTip(tr("Click to show/hide background zone"));
break;
default:
setToolTip(tr("Click to show/hide zone"));
break;
}
}

View file

@ -0,0 +1,76 @@
/**
* @file zone_toggle_button.h
* @ingroup GameGraphicsZones
* @brief Toggle button for showing/hiding collapsible command zones.
*/
#ifndef COCKATRICE_ZONE_TOGGLE_BUTTON_H
#define COCKATRICE_ZONE_TOGGLE_BUTTON_H
#include <QGraphicsObject>
enum class CommandZoneType;
/**
* @class ZoneToggleButton
* @brief Button to toggle collapsible command zone visibility.
*
* Rendered as a thin horizontal bar at the seam between zones.
* Emits clicked() when activated. Supports mouse and keyboard (Enter/Space).
*
* Visual states: semi-transparent dark (normal), lighter (hovered).
*
* @see CommandZone
*/
class ZoneToggleButton : public QGraphicsObject
{
Q_OBJECT
public:
/**
* @brief Constructs the toggle button.
* @param zoneType The type of zone this button toggles (used for tooltip)
* @param parent Parent graphics item (the CommandZone)
*/
explicit ZoneToggleButton(CommandZoneType zoneType, QGraphicsItem *parent = nullptr);
~ZoneToggleButton() override = default;
[[nodiscard]] QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
/**
* @brief Updates the button's expanded state (called by parent CommandZone).
* @param expanded True if zone is expanded
*/
void setExpanded(bool expanded);
/**
* @brief Returns whether the zone is expanded.
* @return True if expanded, false if collapsed
*/
[[nodiscard]] bool isExpanded() const
{
return expanded;
}
signals:
void clicked();
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
private slots:
void retranslateUi();
private:
static constexpr qreal BUTTON_WIDTH = 30;
static constexpr qreal BUTTON_HEIGHT = 5;
static constexpr qreal HIT_AREA_HEIGHT = 15;
static constexpr qreal CORNER_RADIUS = 1.5;
CommandZoneType zoneType;
bool expanded;
bool hovered;
};
#endif // COCKATRICE_ZONE_TOGGLE_BUTTON_H