diff --git a/src/citron/configuration/style_animation_event_filter.cpp b/src/citron/configuration/style_animation_event_filter.cpp index eafb74641..d6b4ff98a 100644 --- a/src/citron/configuration/style_animation_event_filter.cpp +++ b/src/citron/configuration/style_animation_event_filter.cpp @@ -1,20 +1,75 @@ -// SPDX-FileCopyrightText: 2016 Citra Emulator Project // SPDX-FileCopyrightText: 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "citron/configuration/style_animation_event_filter.h" #include +#include #include -#include + +// A helper class that owns the property being animated. +class PaddingAnimator : public QObject { + Q_OBJECT + Q_PROPERTY(int padding READ GetPadding WRITE SetPadding) + +public: + explicit PaddingAnimator(QPushButton* button, int initial_padding) + : QObject(button), target_button(button), current_padding(initial_padding) {} + + void SetPadding(int padding) { + current_padding = padding; + target_button->setStyleSheet(QStringLiteral("padding-left: %1px;").arg(padding)); + } + + int GetPadding() const { return current_padding; } + +private: + QPushButton* target_button; + int current_padding; +}; StyleAnimationEventFilter::StyleAnimationEventFilter(QObject* parent) : QObject(parent) {} +StyleAnimationEventFilter::~StyleAnimationEventFilter() = default; -bool StyleAnimationEventFilter::eventFilter(QObject* obj, QEvent* event) { - if (event->type() == QEvent::Enter || event->type() == QEvent::Leave) { - if (auto* widget = qobject_cast(obj)) { - // Trigger style update for hover effects - widget->update(); - } +void StyleAnimationEventFilter::animatePadding(QPushButton* button, int end) { + if (animations.contains(button)) { + animations.value(button)->stop(); } - return QObject::eventFilter(obj, event); + + int start_padding = 10; // Assume a default start padding + // A better approach would be to parse the current stylesheet, but this is safer for now. + if (end == 10) { // If shrinking, start from the expanded state + start_padding = 14; + } + + auto* animator = new PaddingAnimator(button, start_padding); + auto* animation = new QPropertyAnimation(animator, "padding", this); + + animation->setDuration(150); + animation->setStartValue(start_padding); + animation->setEndValue(end); + animation->setEasingCurve(QEasingCurve::OutQuad); + + animations.insert(button, animation); + + connect(animation, &QPropertyAnimation::finished, this, [this, button](){ + animations.remove(button); + }); + + animation->start(QAbstractAnimation::DeleteWhenStopped); } + +bool StyleAnimationEventFilter::eventFilter(QObject* watched, QEvent* event) { + auto* button = qobject_cast(watched); + if (!button) { + return false; + } + + if (event->type() == QEvent::Enter) { + animatePadding(button, 14); // Grow + } else if (event->type() == QEvent::Leave) { + animatePadding(button, 10); // Shrink + } + return QObject::eventFilter(watched, event); +} + +#include "citron/configuration/style_animation_event_filter.moc" diff --git a/src/citron/configuration/style_animation_event_filter.h b/src/citron/configuration/style_animation_event_filter.h index 1502d96ff..86778b991 100644 --- a/src/citron/configuration/style_animation_event_filter.h +++ b/src/citron/configuration/style_animation_event_filter.h @@ -1,17 +1,26 @@ -// SPDX-FileCopyrightText: 2016 Citra Emulator Project // SPDX-FileCopyrightText: 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include +#include -class StyleAnimationEventFilter : public QObject { +class QPropertyAnimation; +class QPushButton; + +class StyleAnimationEventFilter final : public QObject { Q_OBJECT public: explicit StyleAnimationEventFilter(QObject* parent = nullptr); + ~StyleAnimationEventFilter() override; protected: - bool eventFilter(QObject* obj, QEvent* event) override; + bool eventFilter(QObject* watched, QEvent* event) override; + +private: + void animatePadding(QPushButton* button, int end); + + QHash animations; };