From 00662865f5d1d9461e65787c22a02eac99966e90 Mon Sep 17 00:00:00 2001 From: laserpants Date: Sun, 29 May 2016 16:42:13 +0300 Subject: [PATCH] add toggle animations --- components/toggle.cpp | 88 ++++++++++++++++++++++++++++++++++ components/toggle.h | 6 +++ components/toggle_internal.cpp | 23 ++++++++- components/toggle_internal.h | 8 +++- components/toggle_p.h | 3 ++ examples/toggleexamples.cpp | 2 + lib/rippleoverlay.cpp | 2 +- 7 files changed, 128 insertions(+), 4 deletions(-) diff --git a/components/toggle.cpp b/components/toggle.cpp index 81f8af2..89df96d 100644 --- a/components/toggle.cpp +++ b/components/toggle.cpp @@ -2,11 +2,15 @@ #include #include #include +#include +#include +#include "lib/rippleoverlay.h" #include "toggle_p.h" TogglePrivate::TogglePrivate(Toggle *q) : q_ptr(q), thumb(new Thumb(q)), + ripple(new RippleOverlay(q->parentWidget())), orientation(Qt::Horizontal) { } @@ -26,27 +30,64 @@ void TogglePrivate::init() machine.setInitialState(offState); QEventTransition *transition; + QPropertyAnimation *animation; + + // transition = new QEventTransition(q, QEvent::MouseButtonPress); transition->setTargetState(onState); offState->addTransition(transition); + animation = new QPropertyAnimation; + animation->setPropertyName("shift"); + animation->setTargetObject(thumb); + animation->setDuration(200); + transition->addAnimation(animation); + + // + transition = new QEventTransition(q, QEvent::MouseButtonDblClick); transition->setTargetState(onState); offState->addTransition(transition); + animation = new QPropertyAnimation; + animation->setPropertyName("shift"); + animation->setTargetObject(thumb); + animation->setDuration(200); + transition->addAnimation(animation); + + // + transition = new QEventTransition(q, QEvent::MouseButtonPress); transition->setTargetState(offState); onState->addTransition(transition); + animation = new QPropertyAnimation; + animation->setPropertyName("shift"); + animation->setTargetObject(thumb); + animation->setDuration(200); + transition->addAnimation(animation); + + // + transition = new QEventTransition(q, QEvent::MouseButtonDblClick); transition->setTargetState(offState); onState->addTransition(transition); + animation = new QPropertyAnimation; + animation->setPropertyName("shift"); + animation->setTargetObject(thumb); + animation->setDuration(200); + transition->addAnimation(animation); + + // + offState->assignProperty(thumb, "shift", 0); onState->assignProperty(thumb, "shift", 1); machine.start(); + + QObject::connect(thumb, SIGNAL(clicked()), q, SLOT(addRipple())); } Toggle::Toggle(QWidget *parent) @@ -85,6 +126,53 @@ void Toggle::setOrientation(Qt::Orientation orientation) d->orientation = orientation; } +void Toggle::updateOverlayGeometry() +{ + Q_D(Toggle); + + const qreal offset = d->thumb->offset(); + if (Qt::Horizontal == d->orientation) { + d->ripple->setGeometry(geometry().adjusted(-10+offset, -20, 10+offset, 20)); + } else { + d->ripple->setGeometry(geometry().adjusted(-10, -20+offset, 10, 20+offset)); + } +} + +void Toggle::addRipple() +{ + Q_D(Toggle); + + if (Qt::Horizontal == d->orientation) { + const int t = height()/2; + const int w = d->thumb->height()/2+10; + d->ripple->addRipple(QPoint(10+t, 20+t), w); + } else { + const int t = width()/2; + const int w = d->thumb->width()/2+10; + d->ripple->addRipple(QPoint(10+t, 20+t), w); + } +} + +bool Toggle::event(QEvent *event) +{ + Q_D(Toggle); + + const QEvent::Type type = event->type(); + + if (QEvent::EnabledChange == type) { + if (isEnabled()) { + d->machine.start(); + } else { + d->machine.stop(); + } + } else if (QEvent::ParentChange == type && parentWidget()) { + d->ripple->setParent(parentWidget()); + } else if (QEvent::Resize == type || QEvent::Move == type) { + d->ripple->setGeometry(geometry().adjusted(-10, -20, 10, 20)); + } + return QAbstractButton::event(event); +} + void Toggle::paintEvent(QPaintEvent *event) { Q_UNUSED(event) diff --git a/components/toggle.h b/components/toggle.h index c7276e3..08ec8f5 100644 --- a/components/toggle.h +++ b/components/toggle.h @@ -18,7 +18,13 @@ public: Qt::Orientation orientation() const; void setOrientation(Qt::Orientation orientation) Q_DECL_OVERRIDE; + void updateOverlayGeometry(); + +protected slots: + void addRipple(); + protected: + bool event(QEvent *event) Q_DECL_OVERRIDE; void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; const QScopedPointer d_ptr; diff --git a/components/toggle_internal.cpp b/components/toggle_internal.cpp index 937a083..2f17807 100644 --- a/components/toggle_internal.cpp +++ b/components/toggle_internal.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "toggle_internal.h" #include "toggle.h" @@ -10,6 +11,14 @@ Thumb::Thumb(Toggle *parent) _offset(0) { parent->installEventFilter(this); + + QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect; + + effect->setBlurRadius(6); + effect->setColor(QColor(0, 0, 0, 80)); + effect->setOffset(QPointF(0, 1)); + + setGraphicsEffect(effect); } Thumb::~Thumb() @@ -27,6 +36,7 @@ void Thumb::setShift(qreal shift) ? size() : size().transposed()); _offset = shift*static_cast(s.width()-s.height()); + _toggle->updateOverlayGeometry(); update(); } @@ -56,9 +66,18 @@ void Thumb::paintEvent(QPaintEvent *event) if (Qt::Horizontal == _toggle->orientation()) { const int s = height()-10; - painter.drawEllipse(5+_offset, 5, s, s); + painter.drawEllipse(QRectF(5+_offset, 5, s, s)); } else { const int s = width()-10; - painter.drawEllipse(5, 5+_offset, s, s); + painter.drawEllipse(QRectF(5, 5+_offset, s, s)); } } + +void Thumb::mouseReleaseEvent(QMouseEvent *event) +{ + if (_toggle->isEnabled()) { + _toggle->setChecked(!_toggle->isChecked()); + emit clicked(); + } + QWidget::mouseReleaseEvent(event); +} diff --git a/components/toggle_internal.h b/components/toggle_internal.h index 52cf540..fd3ebc4 100644 --- a/components/toggle_internal.h +++ b/components/toggle_internal.h @@ -18,16 +18,22 @@ public: void setShift(qreal shift); inline qreal shift() const { return _shift; } + inline qreal offset() const { return _offset; } + +signals: + void clicked(); + protected: bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE; void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; + void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; private: Q_DISABLE_COPY(Thumb) Toggle *const _toggle; qreal _shift; - int _offset; + qreal _offset; }; #endif // TOGGLE_INTERNAL_H diff --git a/components/toggle_p.h b/components/toggle_p.h index 66e4d1b..1767d2d 100644 --- a/components/toggle_p.h +++ b/components/toggle_p.h @@ -4,6 +4,8 @@ #include #include "toggle_internal.h" +class RippleOverlay; + class TogglePrivate { Q_DISABLE_COPY(TogglePrivate) @@ -16,6 +18,7 @@ public: Toggle *const q_ptr; Thumb *const thumb; + RippleOverlay *const ripple; QStateMachine machine; Qt::Orientation orientation; }; diff --git a/examples/toggleexamples.cpp b/examples/toggleexamples.cpp index e940083..06b0cad 100644 --- a/examples/toggleexamples.cpp +++ b/examples/toggleexamples.cpp @@ -27,6 +27,8 @@ ToggleExamples::ToggleExamples(QWidget *parent) Toggle *toggle = new Toggle; toggle->setOrientation(Qt::Vertical); + toggle->setDisabled(true); + ExampleView *view = new ExampleView; view->setWidget(toggle); diff --git a/lib/rippleoverlay.cpp b/lib/rippleoverlay.cpp index 67e6ce7..7212c43 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;