diff --git a/components/flatbutton.cpp b/components/flatbutton.cpp index 0724c76..1fad80d 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); @@ -66,6 +68,13 @@ FlatButton::~FlatButton() { } +void FlatButton::setRippleStyle(RippleStyle style) +{ + Q_D(FlatButton); + + d->rippleStyle = style; +} + void FlatButton::setRole(Material::Role role) { Q_D(FlatButton); @@ -113,10 +122,13 @@ void FlatButton::paintEvent(QPaintEvent *event) Q_D(FlatButton); const qreal bgOpacity = d->delegate->backgroundOpacity(); + const qreal haloOpacity = d->delegate->focusHaloOpacity(); + const int hs = (width()/2)*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,13 +138,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); + style.drawControl(QStyle::CE_PushButtonLabel, option); #ifdef DEBUG_LAYOUT QPainter debug(this); @@ -148,9 +170,15 @@ void FlatButton::mousePressEvent(QMouseEvent *event) { Q_D(FlatButton); + if (FlatButton::NoRipple == d->rippleStyle) { + return; + } + QColor color = palette().color(QPalette::Active, QPalette::ButtonText); - Ripple *ripple = new Ripple(event->pos()); + Ripple *ripple = new Ripple(FlatButton::CenteredRipple == d->rippleStyle + ? rect().center() : event->pos()); + ripple->setRadiusEndValue(100); ripple->setOpacityStartValue(0.4); ripple->setColor(color); diff --git a/components/flatbutton.h b/components/flatbutton.h index 0de44eb..253cb63 100644 --- a/components/flatbutton.h +++ b/components/flatbutton.h @@ -12,12 +12,20 @@ class FlatButton : public QPushButton Q_OBJECT public: + enum RippleStyle { + CenteredRipple, + PositionedRipple, + NoRipple + }; + explicit FlatButton(QWidget *parent = 0); explicit FlatButton(const QString &text, QWidget *parent = 0); ~FlatButton(); virtual void setRole(Material::Role role); + void setRippleStyle(RippleStyle style); + protected: FlatButton(FlatButtonPrivate &d, QWidget *parent = 0); diff --git a/components/flatbutton_internal.cpp b/components/flatbutton_internal.cpp index c9a9ed4..cdac694 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,57 +11,48 @@ FlatButtonDelegate::FlatButtonDelegate(FlatButton *parent) : QStateMachine(parent), button(parent), _normalState(new QState(this)), - _focusedState(new QState(this)), - _pressedState(new QState(this)) + _normalFocusedState(new QState(this)), + _hoveredState(new QState(this)), + _hoveredFocusedState(new QState(this)), + _pressedState(new QState(this)), + _focusHaloSize(0.8) { 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(_focusedState); + 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(0.8); + grow->setEndValue(0.9); + grow->setEasingCurve(QEasingCurve::InOutSine); + grow->setDuration(840); - // + shrink->setTargetObject(this); + shrink->setPropertyName("focusHaloSize"); + shrink->setStartValue(0.9); + shrink->setEndValue(0.8); + shrink->setEasingCurve(QEasingCurve::InOutSine); + shrink->setDuration(840); - transition = new QEventTransition(button, QEvent::Leave); - transition->setTargetState(_normalState); - - animation = new QPropertyAnimation(this, "backgroundOpacity"); - animation->setDuration(140); - transition->addAnimation(animation); - _focusedState->addTransition(transition); - - // - - transition = new QEventTransition(button, QEvent::MouseButtonPress); - transition->setTargetState(_pressedState); - - animation = new QPropertyAnimation(this, "backgroundOpacity"); - animation->setDuration(140); - transition->addAnimation(animation); - _focusedState->addTransition(transition); - - // - - transition = new QEventTransition(button, QEvent::MouseButtonRelease); - transition->setTargetState(_focusedState); - - 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(); } @@ -91,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(qreal size) +{ + _focusHaloSize = size; + button->update(); +} + +qreal FlatButtonDelegate::focusHaloSize() const +{ + return _focusHaloSize; +} + void FlatButtonDelegate::assignProperties() { QColor textColor = button->palette().color(QPalette::Active, @@ -98,10 +112,45 @@ void FlatButtonDelegate::assignProperties() _normalState->assignProperty(this, "backgroundOpacity", 0); _normalState->assignProperty(this, "backgroundColor", textColor); + _normalState->assignProperty(this, "focusHaloOpacity", 0); - _focusedState->assignProperty(this, "backgroundOpacity", 0.15); - _focusedState->assignProperty(this, "backgroundColor", textColor); + _normalFocusedState->assignProperty(this, "backgroundOpacity", 0); + _normalFocusedState->assignProperty(this, "backgroundColor", textColor); + _normalFocusedState->assignProperty(this, "focusHaloOpacity", 0.15); + + _hoveredState->assignProperty(this, "backgroundOpacity", 0.15); + _hoveredState->assignProperty(this, "backgroundColor", textColor); + _hoveredState->assignProperty(this, "focusHaloOpacity", 0); + + _hoveredFocusedState->assignProperty(this, "backgroundOpacity", 0.15); + _hoveredFocusedState->assignProperty(this, "backgroundColor", textColor); + _normalFocusedState->assignProperty(this, "focusHaloOpacity", 0.15); _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 ec74478..51b54db 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(qreal focusHaloSize WRITE setFocusHaloSize READ focusHaloSize) public: FlatButtonDelegate(FlatButton *parent); @@ -23,18 +26,29 @@ public: void setBackgroundColor(const QColor &color); QColor backgroundColor() const; + void setFocusHaloOpacity(qreal opacity); + qreal focusHaloOpacity() const; + + void setFocusHaloSize(qreal size); + qreal 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 _focusedState; + QState *const _normalFocusedState; + QState *const _hoveredState; + QState *const _hoveredFocusedState; QState *const _pressedState; qreal _backgroundOpacity; + qreal _focusHaloOpacity; + qreal _focusHaloSize; QColor _backgroundColor; - }; #endif // FLATBUTTON_INTERNAL_H diff --git a/components/flatbutton_p.h b/components/flatbutton_p.h index ccc7750..30c8b91 100644 --- a/components/flatbutton_p.h +++ b/components/flatbutton_p.h @@ -17,7 +17,8 @@ class FlatButtonPrivate public: FlatButtonPrivate(FlatButton *q) : q_ptr(q), - role(Material::Default) + role(Material::Default), + rippleStyle(FlatButton::PositionedRipple) {} void init(); @@ -27,6 +28,7 @@ public: RippleOverlay *ripple; FlatButtonDelegate *delegate; Material::Role role; + FlatButton::RippleStyle rippleStyle; }; #endif // FLATBUTTON_P_H diff --git a/components/raisedbutton.cpp b/components/raisedbutton.cpp index 79f49a5..45c1da1 100644 --- a/components/raisedbutton.cpp +++ b/components/raisedbutton.cpp @@ -129,17 +129,28 @@ void RaisedButton::paintEvent(QPaintEvent *event) Q_D(RaisedButton); QPainter painter(this); - painter.setRenderHint(QPainter::Antialiasing); + painter.save(); + QBrush brush; brush.setStyle(Qt::SolidPattern); brush.setColor(palette().color(QPalette::Active, QPalette::Background)); painter.setBrush(brush); painter.setPen(Qt::NoPen); - painter.drawRoundedRect(rect(), 3, 3); + const int hs = (width()/2)*d->delegate->focusHaloSize(); + const qreal haloOpacity = d->delegate->focusHaloOpacity(); + + brush.setColor(palette().color(QPalette::Active, QPalette::ButtonText)); + painter.setBrush(brush); + painter.setOpacity(haloOpacity); + painter.setPen(Qt::NoPen); + painter.drawEllipse(rect().center(), hs, hs); + + painter.restore(); + QStylePainter style(this); QStyleOptionButton 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;