From 78db49a9b3ee80eebfb23a0573d14aab7125f78e Mon Sep 17 00:00:00 2001 From: DawnFire42 Date: Wed, 25 Feb 2026 13:31:22 -0500 Subject: [PATCH] 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. --- cockatrice/CMakeLists.txt | 1 + .../src/game/zones/zone_toggle_button.cpp | 107 ++++++++++++++++++ .../src/game/zones/zone_toggle_button.h | 76 +++++++++++++ 3 files changed, 184 insertions(+) create mode 100644 cockatrice/src/game/zones/zone_toggle_button.cpp create mode 100644 cockatrice/src/game/zones/zone_toggle_button.h diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index f40c8561d..25705e2e2 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -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 diff --git a/cockatrice/src/game/zones/zone_toggle_button.cpp b/cockatrice/src/game/zones/zone_toggle_button.cpp new file mode 100644 index 000000000..bce4fd036 --- /dev/null +++ b/cockatrice/src/game/zones/zone_toggle_button.cpp @@ -0,0 +1,107 @@ +#include "zone_toggle_button.h" + +#include "../../client/settings/cache_settings.h" +#include "../z_values.h" +#include "command_zone.h" + +#include +#include +#include +#include + +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; + } +} diff --git a/cockatrice/src/game/zones/zone_toggle_button.h b/cockatrice/src/game/zones/zone_toggle_button.h new file mode 100644 index 000000000..6a2831e24 --- /dev/null +++ b/cockatrice/src/game/zones/zone_toggle_button.h @@ -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 + +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