From 078c3699cc5e65646bf4ab6ac5a8c54f53018cfd Mon Sep 17 00:00:00 2001 From: laserpants Date: Sat, 28 May 2016 10:52:03 +0300 Subject: [PATCH] add focus halo animation to buttons --- components/flatbutton.cpp | 35 ++++--- components/flatbutton_internal.cpp | 151 +++++++++++++++++------------ components/flatbutton_internal.h | 19 +++- components/raisedbutton.cpp | 13 +-- lib/rippleoverlay.cpp | 2 +- 5 files changed, 134 insertions(+), 86 deletions(-) diff --git a/components/flatbutton.cpp b/components/flatbutton.cpp index 36f059e..36f947e 100644 --- a/components/flatbutton.cpp +++ b/components/flatbutton.cpp @@ -34,7 +34,9 @@ void FlatButtonPrivate::init() q->setPalette(palette); } -void FlatButtonPrivate::setPaletteColor(QPalette::ColorGroup group, QPalette::ColorRole role, const QString &themeColor) +void FlatButtonPrivate::setPaletteColor(QPalette::ColorGroup group, + QPalette::ColorRole role, + const QString &themeColor) { Q_Q(FlatButton); @@ -113,10 +115,13 @@ void FlatButton::paintEvent(QPaintEvent *event) Q_D(FlatButton); const qreal bgOpacity = d->delegate->backgroundOpacity(); + const qreal haloOpacity = d->delegate->focusHaloOpacity(); + const int hs = d->delegate->focusHaloSize(); - if (isEnabled() && bgOpacity > 0) - { - QPainter painter(this); + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + + if (isEnabled() && bgOpacity > 0) { QBrush brush; brush.setStyle(Qt::SolidPattern); brush.setColor(d->delegate->backgroundColor()); @@ -126,20 +131,23 @@ void FlatButton::paintEvent(QPaintEvent *event) painter.drawRoundedRect(rect(), 3, 3); } - QStylePainter painter(this); + if (isEnabled() && haloOpacity > 0) { + QBrush brush; + brush.setStyle(Qt::SolidPattern); + brush.setColor(palette().color(QPalette::Active, QPalette::ButtonText)); + painter.setOpacity(haloOpacity); + painter.setBrush(brush); + painter.setPen(Qt::NoPen); + painter.drawEllipse(rect().center(), hs, hs); + } + + QStylePainter style(this); QStyleOptionButton option; initStyleOption(&option); option.features |= QStyleOptionButton::Flat; - painter.drawControl(QStyle::CE_PushButtonLabel, option); - - //if (hasFocus() && !underMouse()) { - // QPen pen; - // pen.setWidth(4); - // painter.setPen(pen); - // painter.drawRect(rect()); - //} + style.drawControl(QStyle::CE_PushButtonLabel, option); #ifdef DEBUG_LAYOUT QPainter debug(this); @@ -160,6 +168,7 @@ void FlatButton::mousePressEvent(QMouseEvent *event) Ripple *ripple = new Ripple(event->pos()); ripple->setRadiusEndValue(100); ripple->setOpacityStartValue(0.4); + ripple->setColor(color); d->ripple->addRipple(ripple); diff --git a/components/flatbutton_internal.cpp b/components/flatbutton_internal.cpp index 05365a3..90bb799 100644 --- a/components/flatbutton_internal.cpp +++ b/components/flatbutton_internal.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "flatbutton.h" #include "lib/style.h" @@ -10,78 +11,48 @@ FlatButtonDelegate::FlatButtonDelegate(FlatButton *parent) : QStateMachine(parent), button(parent), _normalState(new QState(this)), + _normalFocusedState(new QState(this)), _hoveredState(new QState(this)), - _focusedState2(new QState(this)), - _pressedState(new QState(this)) + _hoveredFocusedState(new QState(this)), + _pressedState(new QState(this)), + _focusHaloSize(85) { setInitialState(_normalState); assignProperties(); - QAbstractTransition *transition; - QPropertyAnimation *animation; + addTransition(QEvent::Enter, _normalFocusedState, _hoveredFocusedState); + addTransition(QEvent::FocusIn, _normalState, _normalFocusedState); + addTransition(QEvent::FocusOut, _normalFocusedState, _normalState); + addTransition(QEvent::Enter, _normalState, _hoveredState); + addTransition(QEvent::Leave, _hoveredFocusedState, _normalFocusedState); + addTransition(QEvent::Leave, _hoveredState, _normalState); + addTransition(QEvent::MouseButtonPress, _hoveredState, _pressedState); + addTransition(QEvent::MouseButtonRelease, _pressedState, _hoveredFocusedState); - // + QSequentialAnimationGroup *group = new QSequentialAnimationGroup(this); - transition = new QEventTransition(button, QEvent::Enter); - transition->setTargetState(_hoveredState); + QPropertyAnimation *grow = new QPropertyAnimation; + QPropertyAnimation *shrink = new QPropertyAnimation; - animation = new QPropertyAnimation(this, "backgroundOpacity"); - animation->setDuration(140); - transition->addAnimation(animation); - _normalState->addTransition(transition); + grow->setTargetObject(this); + grow->setPropertyName("focusHaloSize"); + grow->setStartValue(85); + grow->setEndValue(100); + grow->setEasingCurve(QEasingCurve::InOutSine); + grow->setDuration(840); - // + shrink->setTargetObject(this); + shrink->setPropertyName("focusHaloSize"); + shrink->setStartValue(100); + shrink->setEndValue(85); + shrink->setEasingCurve(QEasingCurve::InOutSine); + shrink->setDuration(840); - //transition = new QEventTransition(button, QEvent::FocusIn); - //transition->setTargetState(_focusedState2); - - ////animation = new QPropertyAnimation(this, "backgroundOpacity"); - ////animation->setDuration(140); - ////transition->addAnimation(animation); - //_normalState->addTransition(transition); - - // - - transition = new QEventTransition(button, QEvent::Leave); - transition->setTargetState(_normalState); - - animation = new QPropertyAnimation(this, "backgroundOpacity"); - animation->setDuration(140); - transition->addAnimation(animation); - _focusedState2->addTransition(transition); - - // - - transition = new QEventTransition(button, QEvent::Leave); - transition->setTargetState(_normalState); - - animation = new QPropertyAnimation(this, "backgroundOpacity"); - animation->setDuration(140); - transition->addAnimation(animation); - _hoveredState->addTransition(transition); - - // - - transition = new QEventTransition(button, QEvent::MouseButtonPress); - transition->setTargetState(_pressedState); - - animation = new QPropertyAnimation(this, "backgroundOpacity"); - animation->setDuration(140); - transition->addAnimation(animation); - _hoveredState->addTransition(transition); - - // - - transition = new QEventTransition(button, QEvent::MouseButtonRelease); - transition->setTargetState(_focusedState2); - - animation = new QPropertyAnimation(this, "backgroundOpacity"); - animation->setDuration(500); - transition->addAnimation(animation); - _pressedState->addTransition(transition); - - // + group->addAnimation(grow); + group->addAnimation(shrink); + group->setLoopCount(-1); + group->start(); start(); } @@ -112,6 +83,28 @@ QColor FlatButtonDelegate::backgroundColor() const return _backgroundColor; } +void FlatButtonDelegate::setFocusHaloOpacity(qreal opacity) +{ + _focusHaloOpacity = opacity; + button->update(); +} + +qreal FlatButtonDelegate::focusHaloOpacity() const +{ + return _focusHaloOpacity; +} + +void FlatButtonDelegate::setFocusHaloSize(int size) +{ + _focusHaloSize = size; + button->update(); +} + +int FlatButtonDelegate::focusHaloSize() const +{ + return _focusHaloSize; +} + void FlatButtonDelegate::assignProperties() { QColor textColor = button->palette().color(QPalette::Active, @@ -119,13 +112,45 @@ void FlatButtonDelegate::assignProperties() _normalState->assignProperty(this, "backgroundOpacity", 0); _normalState->assignProperty(this, "backgroundColor", textColor); + _normalState->assignProperty(this, "focusHaloOpacity", 0); + + _normalFocusedState->assignProperty(this, "backgroundOpacity", 0); + _normalFocusedState->assignProperty(this, "backgroundColor", textColor); + _normalFocusedState->assignProperty(this, "focusHaloOpacity", 0.12); _hoveredState->assignProperty(this, "backgroundOpacity", 0.15); _hoveredState->assignProperty(this, "backgroundColor", textColor); + _hoveredState->assignProperty(this, "focusHaloOpacity", 0); - _focusedState2->assignProperty(this, "backgroundOpacity", 0.15); - _focusedState2->assignProperty(this, "backgroundColor", textColor); + _hoveredFocusedState->assignProperty(this, "backgroundOpacity", 0.15); + _hoveredFocusedState->assignProperty(this, "backgroundColor", textColor); + _normalFocusedState->assignProperty(this, "focusHaloOpacity", 0.12); _pressedState->assignProperty(this, "backgroundOpacity", 0.15); _pressedState->assignProperty(this, "backgroundColor", textColor); + _pressedState->assignProperty(this, "focusHaloOpacity", 0); +} + +void FlatButtonDelegate::addTransition(QEvent::Type eventType, + QState *fromState, + QState *toState) +{ + QAbstractTransition *transition = new QEventTransition(button, eventType); + transition->setTargetState(toState); + + QPropertyAnimation *animation; + + animation = new QPropertyAnimation(this, "backgroundOpacity"); + animation->setDuration(200); + transition->addAnimation(animation); + + animation = new QPropertyAnimation(this, "backgroundColor"); + animation->setDuration(200); + transition->addAnimation(animation); + + animation = new QPropertyAnimation(this, "focusHaloOpacity"); + animation->setDuration(350); + transition->addAnimation(animation); + + fromState->addTransition(transition); } diff --git a/components/flatbutton_internal.h b/components/flatbutton_internal.h index 12cbdac..53dd70f 100644 --- a/components/flatbutton_internal.h +++ b/components/flatbutton_internal.h @@ -4,14 +4,17 @@ #include #include +class QPropertyAnimation; class FlatButton; class FlatButtonDelegate : public QStateMachine { Q_OBJECT - Q_PROPERTY(qreal backgroundOpacity WRITE setBackgroundOpacity READ backgroundOpacity) Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor) + Q_PROPERTY(qreal backgroundOpacity WRITE setBackgroundOpacity READ backgroundOpacity) + Q_PROPERTY(qreal focusHaloOpacity WRITE setFocusHaloOpacity READ focusHaloOpacity) + Q_PROPERTY(int focusHaloSize WRITE setFocusHaloSize READ focusHaloSize) public: FlatButtonDelegate(FlatButton *parent); @@ -23,19 +26,29 @@ public: void setBackgroundColor(const QColor &color); QColor backgroundColor() const; + void setFocusHaloOpacity(qreal opacity); + qreal focusHaloOpacity() const; + + void setFocusHaloSize(int size); + int focusHaloSize() const; + void assignProperties(); private: Q_DISABLE_COPY(FlatButtonDelegate) + void addTransition(QEvent::Type eventType, QState *fromState, QState *toState); + FlatButton *const button; QState *const _normalState; + QState *const _normalFocusedState; QState *const _hoveredState; - QState *const _focusedState2; + QState *const _hoveredFocusedState; QState *const _pressedState; qreal _backgroundOpacity; + qreal _focusHaloOpacity; + int _focusHaloSize; QColor _backgroundColor; - }; #endif // FLATBUTTON_INTERNAL_H diff --git a/components/raisedbutton.cpp b/components/raisedbutton.cpp index 79f49a5..4758142 100644 --- a/components/raisedbutton.cpp +++ b/components/raisedbutton.cpp @@ -129,7 +129,6 @@ void RaisedButton::paintEvent(QPaintEvent *event) Q_D(RaisedButton); QPainter painter(this); - painter.setRenderHint(QPainter::Antialiasing); QBrush brush; @@ -140,11 +139,13 @@ void RaisedButton::paintEvent(QPaintEvent *event) painter.drawRoundedRect(rect(), 3, 3); - QStylePainter style(this); + FlatButton::paintEvent(event); - QStyleOptionButton option; - initStyleOption(&option); - option.features |= QStyleOptionButton::Flat; + //QStylePainter style(this); - style.drawControl(QStyle::CE_PushButtonLabel, option); + //QStyleOptionButton option; + //initStyleOption(&option); + //option.features |= QStyleOptionButton::Flat; + + //style.drawControl(QStyle::CE_PushButtonLabel, option); } diff --git a/lib/rippleoverlay.cpp b/lib/rippleoverlay.cpp index 7212c43..67e6ce7 100644 --- a/lib/rippleoverlay.cpp +++ b/lib/rippleoverlay.cpp @@ -34,7 +34,7 @@ void RippleOverlay::paintEvent(QPaintEvent *event) Q_UNUSED(event) QPainter painter(this); - painter.setRenderHint(QPainter::Antialiasing); + //painter.setRenderHint(QPainter::Antialiasing); painter.setPen(Qt::NoPen); QList::const_iterator i;