From e0d5221957bf0d7857f924f1f2ae63d490de0a0a Mon Sep 17 00:00:00 2001 From: Casper van Donderen Date: Wed, 22 Jun 2011 13:54:56 +0200 Subject: Move all other demos in qtbase to examples. Change-Id: Iab0e7364d1f6b348d0e3033ea9304139f5bd6d0d Reviewed-on: http://codereview.qt.nokia.com/617 Reviewed-by: Qt Sanity Bot Reviewed-by: David Boddie --- examples/embedded/flickable/flickable.cpp | 284 ++++++++++++++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 examples/embedded/flickable/flickable.cpp (limited to 'examples/embedded/flickable/flickable.cpp') diff --git a/examples/embedded/flickable/flickable.cpp b/examples/embedded/flickable/flickable.cpp new file mode 100644 index 0000000000..edcc1a7396 --- /dev/null +++ b/examples/embedded/flickable/flickable.cpp @@ -0,0 +1,284 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "flickable.h" + +#include +#include + +class FlickableTicker: QObject +{ +public: + FlickableTicker(Flickable *scroller) { + m_scroller = scroller; + } + + void start(int interval) { + if (!m_timer.isActive()) + m_timer.start(interval, this); + } + + void stop() { + m_timer.stop(); + } + +protected: + void timerEvent(QTimerEvent *event) { + Q_UNUSED(event); + m_scroller->tick(); + } + +private: + Flickable *m_scroller; + QBasicTimer m_timer; +}; + +class FlickablePrivate +{ +public: + typedef enum { + Steady, + Pressed, + ManualScroll, + AutoScroll, + Stop + } State; + + State state; + int threshold; + QPoint pressPos; + QPoint offset; + QPoint delta; + QPoint speed; + FlickableTicker *ticker; + QTime timeStamp; + QWidget *target; + QList ignoreList; +}; + +Flickable::Flickable() +{ + d = new FlickablePrivate; + d->state = FlickablePrivate::Steady; + d->threshold = 10; + d->ticker = new FlickableTicker(this); + d->timeStamp = QTime::currentTime(); + d->target = 0; +} + +Flickable::~Flickable() +{ + delete d; +} + +void Flickable::setThreshold(int th) +{ + if (th >= 0) + d->threshold = th; +} + +int Flickable::threshold() const +{ + return d->threshold; +} + +void Flickable::setAcceptMouseClick(QWidget *target) +{ + d->target = target; +} + +static QPoint deaccelerate(const QPoint &speed, int a = 1, int max = 64) +{ + int x = qBound(-max, speed.x(), max); + int y = qBound(-max, speed.y(), max); + x = (x == 0) ? x : (x > 0) ? qMax(0, x - a) : qMin(0, x + a); + y = (y == 0) ? y : (y > 0) ? qMax(0, y - a) : qMin(0, y + a); + return QPoint(x, y); +} + +void Flickable::handleMousePress(QMouseEvent *event) +{ + event->ignore(); + + if (event->button() != Qt::LeftButton) + return; + + if (d->ignoreList.removeAll(event)) + return; + + switch (d->state) { + + case FlickablePrivate::Steady: + event->accept(); + d->state = FlickablePrivate::Pressed; + d->pressPos = event->pos(); + break; + + case FlickablePrivate::AutoScroll: + event->accept(); + d->state = FlickablePrivate::Stop; + d->speed = QPoint(0, 0); + d->pressPos = event->pos(); + d->offset = scrollOffset(); + d->ticker->stop(); + break; + + default: + break; + } +} + +void Flickable::handleMouseRelease(QMouseEvent *event) +{ + event->ignore(); + + if (event->button() != Qt::LeftButton) + return; + + if (d->ignoreList.removeAll(event)) + return; + + QPoint delta; + + switch (d->state) { + + case FlickablePrivate::Pressed: + event->accept(); + d->state = FlickablePrivate::Steady; + if (d->target) { + QMouseEvent *event1 = new QMouseEvent(QEvent::MouseButtonPress, + d->pressPos, Qt::LeftButton, + Qt::LeftButton, Qt::NoModifier); + QMouseEvent *event2 = new QMouseEvent(*event); + d->ignoreList << event1; + d->ignoreList << event2; + QApplication::postEvent(d->target, event1); + QApplication::postEvent(d->target, event2); + } + break; + + case FlickablePrivate::ManualScroll: + event->accept(); + delta = event->pos() - d->pressPos; + if (d->timeStamp.elapsed() > 100) { + d->timeStamp = QTime::currentTime(); + d->speed = delta - d->delta; + d->delta = delta; + } + d->offset = scrollOffset(); + d->pressPos = event->pos(); + if (d->speed == QPoint(0, 0)) { + d->state = FlickablePrivate::Steady; + } else { + d->speed /= 4; + d->state = FlickablePrivate::AutoScroll; + d->ticker->start(20); + } + break; + + case FlickablePrivate::Stop: + event->accept(); + d->state = FlickablePrivate::Steady; + d->offset = scrollOffset(); + break; + + default: + break; + } +} + +void Flickable::handleMouseMove(QMouseEvent *event) +{ + event->ignore(); + + if (!(event->buttons() & Qt::LeftButton)) + return; + + if (d->ignoreList.removeAll(event)) + return; + + QPoint delta; + + switch (d->state) { + + case FlickablePrivate::Pressed: + case FlickablePrivate::Stop: + delta = event->pos() - d->pressPos; + if (delta.x() > d->threshold || delta.x() < -d->threshold || + delta.y() > d->threshold || delta.y() < -d->threshold) { + d->timeStamp = QTime::currentTime(); + d->state = FlickablePrivate::ManualScroll; + d->delta = QPoint(0, 0); + d->pressPos = event->pos(); + event->accept(); + } + break; + + case FlickablePrivate::ManualScroll: + event->accept(); + delta = event->pos() - d->pressPos; + setScrollOffset(d->offset - delta); + if (d->timeStamp.elapsed() > 100) { + d->timeStamp = QTime::currentTime(); + d->speed = delta - d->delta; + d->delta = delta; + } + break; + + default: + break; + } +} + +void Flickable::tick() +{ + if (d->state == FlickablePrivate:: AutoScroll) { + d->speed = deaccelerate(d->speed); + setScrollOffset(d->offset - d->speed); + d->offset = scrollOffset(); + if (d->speed == QPoint(0, 0)) { + d->state = FlickablePrivate::Steady; + d->ticker->stop(); + } + } else { + d->ticker->stop(); + } +} -- cgit v1.2.3