add toggle animations

This commit is contained in:
laserpants 2016-05-29 16:42:13 +03:00
parent e97d88b5a9
commit 00662865f5
7 changed files with 128 additions and 4 deletions

View File

@ -2,11 +2,15 @@
#include <QPainter>
#include <QState>
#include <QEventTransition>
#include <QPropertyAnimation>
#include <QDebug>
#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)

View File

@ -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<TogglePrivate> d_ptr;

View File

@ -1,5 +1,6 @@
#include <QPainter>
#include <QEvent>
#include <QGraphicsDropShadowEffect>
#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<qreal>(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);
}

View File

@ -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

View File

@ -4,6 +4,8 @@
#include <QStateMachine>
#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;
};

View File

@ -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);

View File

@ -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<Ripple *>::const_iterator i;