From 61d18dd5ff3310f3a3831814d86a5283d1c4910d Mon Sep 17 00:00:00 2001 From: Ralf Engels Date: Fri, 2 Jul 2010 18:40:54 +0200 Subject: New architecture --- scroller/qflickgesture.cpp | 256 ++++---- scroller/qflickgesture.h | 30 +- scroller/qkineticscroller.cpp | 1182 ---------------------------------- scroller/qkineticscroller.h | 160 ----- scroller/qkineticscroller_mac.mm | 69 -- scroller/qkineticscroller_maemo5.cpp | 55 -- scroller/qkineticscroller_p.h | 180 ------ scroller/scroller.pro | 8 +- testapp/main.cpp | 16 +- testapp/settingswidget.cpp | 28 +- testapp/settingswidget.h | 3 +- 11 files changed, 206 insertions(+), 1781 deletions(-) delete mode 100644 scroller/qkineticscroller.cpp delete mode 100644 scroller/qkineticscroller.h delete mode 100644 scroller/qkineticscroller_mac.mm delete mode 100644 scroller/qkineticscroller_maemo5.cpp delete mode 100644 scroller/qkineticscroller_p.h diff --git a/scroller/qflickgesture.cpp b/scroller/qflickgesture.cpp index 6fa9dde..375fb62 100644 --- a/scroller/qflickgesture.cpp +++ b/scroller/qflickgesture.cpp @@ -39,177 +39,199 @@ ** ****************************************************************************/ +#include +#include +#include + #include "qflickgesture.h" -#include "qgesture.h" -#include "qevent.h" -#include "qwidget.h" -#include "qabstractscrollarea.h" -#include "qdebug.h" +#include "qscroller.h" +#include "qscroller_p.h" + +#include "private/qgesturemanager_p.h" +#include "private/qgesture_p.h" + +#include +#include +#include +// #include +// #include + +#include + QT_BEGIN_NAMESPACE -class QFlickGesturePrivate +bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); + +#define KINETIC_SCROLLER_DEBUG + +#ifdef KINETIC_SCROLLER_DEBUG +# define qKSDebug qDebug +#else +# define qKSDebug while (false) qDebug +#endif + + +class QFlickGesturePrivate : public QGesturePrivate { + Q_DECLARE_PUBLIC(QFlickGesture) + public: - QFlickGesturePrivate() + + QScroller *scroller() { + if (!receiverScroller) + receiverScroller = QScroller::scroller(receiver); + return receiverScroller; } - QKineticScroller *scroller() - { - // qDebug() << "QKineticScroller::scroller"<parent(); - QKineticScroller *res = 0; + QPointer receiver; + QPointer receiverScroller; - if (!target) - return 0; + QFlickGesture *q_ptr; +}; - res = target->property("kineticScroller").value(); - if (res) - return res; - if (!target->parent()) - return 0; - res = target->parent()->property("kineticScroller").value(); - return res; - } +inline bool operator<=(const QPointF &p, qreal f) +{ + return (qAbs(p.x()) <= f) && (qAbs(p.y()) <= f); +} +inline bool operator<(const QPointF &p, qreal f) +{ + return (qAbs(p.x()) < f) && (qAbs(p.y()) < f); +} - QPointer target; +inline bool operator>=(const QPointF &p, qreal f) +{ + return (qAbs(p.x()) >= f) || (qAbs(p.y()) >= f); +} +inline bool operator>(const QPointF &p, qreal f) +{ + return (qAbs(p.x()) > f) || (qAbs(p.y()) > f); +} -#if QT_VERSION < 0x040700 - QTime timer; -#else - QElapsedTimer timer; -#endif +inline QPointF qAbs(const QPointF &p) +{ + return QPointF(qAbs(p.x()), qAbs(p.y())); +} - friend class QFlickGesture; -}; +inline int qSign(qreal r) +{ + return (r < 0) ? -1 : ((r > 0) ? 1 : 0); +} +/*! + \class QFlickGestureRecognizer + \since 4.8 + \brief The \c QFlickGestureRecognizer is used to detect \c QFlickGesture. + \ingroup gestures + + \sa {Gestures Programming}, QFlickGesture +*/ QFlickGestureRecognizer::QFlickGestureRecognizer() { } +/*! \reimp + */ QGesture *QFlickGestureRecognizer::create(QObject *target) { - qDebug() << "Recognizer::create for"<isWidgetType():false); if (target && target->isWidgetType()) { - QWidget *widget = static_cast(target); -#if defined(Q_OS_WIN) && !defined(QT_NO_NATIVE_GESTURES) - // for scroll areas on Windows we want to use native gestures instead - if (!qobject_cast(target->parent())) - widget->setAttribute(Qt::WA_AcceptTouchEvents); -#else + QWidget *widget = static_cast(target); widget->setAttribute(Qt::WA_AcceptTouchEvents); -#endif - return new QFlickGesture(widget); + + } else if (target) { + QGraphicsObject *go = qobject_cast(target); + if (go) { + go->setAcceptTouchEvents(true); + } } - return new QFlickGesture(0); + return new QFlickGesture(target); } +/*! The recognize function detects a touch event suitable to start the attached QScroller. + The QFlickGesture will be triggered when the scroller is not longer in the state + QScroller::StateInactive or QScrollerStatePressed. It will be finished or canceled + at the QEvent::TouchEnd. + Note that the QScroller might continue scrolling at this point. + */ QGestureRecognizer::Result QFlickGestureRecognizer::recognize(QGesture *state, QObject *, QEvent *event) { QFlickGesture *q = static_cast(state); - QFlickGesturePrivate *d = q->d; + QFlickGesturePrivate *d = q->d_ptr; - QKineticScroller *scroller = d->scroller(); - // qDebug() << "QFlickGestureRecognizer::recognize for"<scroller(); if (!scroller) - return QGestureRecognizer::Ignore; + return QGestureRecognizer::Ignore; // nothing to do without a scroller? + QScrollerPrivate *scrollerD = scroller->d_ptr; // eat mouse events if the scroller is active - if ((scroller->state() == QKineticScroller::StateDragging || - scroller->state() == QKineticScroller::StateScrolling) && + if ((scrollerD->state == QScroller::StateDragging || + scrollerD->state == QScroller::StateScrolling) && (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseMove || event->type() == QEvent::MouseButtonDblClick || event->type() == QEvent::MouseButtonRelease) ) return QGestureRecognizer::Ignore | QGestureRecognizer::ConsumeEventHint; - // qDebug()<<"recognize event: "<target<<"scroller:"<scroller(); - - QKineticScroller::State oldState = scroller->state(); - - // ignore all other events except touch - /* - QGestureRecognizer::Result resultVector[4] = { - QGestureRecognizer::Ignore, - QGestureRecognizer::MayBeGesture, - QGestureRecognizer::TriggerGesture, - QGestureRecognizer::TriggerGesture }; - */ - + // ignore everything except touch events if (event->type() != QEvent::TouchBegin && event->type() != QEvent::TouchEnd && event->type() != QEvent::TouchUpdate) return QGestureRecognizer::Ignore; - // return resultVector[(int)oldState]; const QTouchEvent *ev = static_cast(event); QTouchEvent::TouchPoint tp = ev->touchPoints().first(); - qint64 timestamp = d->timer.elapsed(); - - - QGestureRecognizer::Result result = QGestureRecognizer::Ignore; + // inform the scroller about the new event + qint64 timestamp = scrollerD->timer.elapsed(); // TODO: have your own timer switch (event->type()) { case QEvent::TouchBegin: - scroller->handleInput(QKineticScroller::InputPress, tp.pos(), timestamp); + scrollerD->handleInput(QScrollerPrivate::InputPress, tp.pos(), timestamp); break; - // return QGestureRecognizer::MayBeGesture; case QEvent::TouchEnd: - scroller->handleInput(QKineticScroller::InputRelease, tp.pos(), timestamp); + scrollerD->handleInput(QScrollerPrivate::InputRelease, tp.pos(), timestamp); break; - /* - if (oldState == QKineticScroller::StatePressed) - return QGestureRecognizer::CancelGesture; - else - return QGestureRecognizer::FinishGesture | QGestureRecognizer::ConsumeEventHint; - */ case QEvent::TouchUpdate: - scroller->handleInput(QKineticScroller::InputMove, tp.pos(), timestamp); + scrollerD->handleInput(QScrollerPrivate::InputMove, tp.pos(), timestamp); break; - /* - if (scroller->state() == QKineticScroller::StatePressed) - return QGestureRecognizer::MayBeGesture; + default: + break; + } + + // depending on the scroller state return the gesture state + QGestureRecognizer::Result result = QGestureRecognizer::Ignore; + bool scrollerActive = (scrollerD->state == QScroller::StateDragging || + scrollerD->state == QScroller::StateScrolling); + + switch (event->type()) { + case QEvent::TouchEnd: + if (scrollerActive) + return QGestureRecognizer::FinishGesture | QGestureRecognizer::ConsumeEventHint; else + return QGestureRecognizer::CancelGesture; + break; + + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + if (scrollerActive) return QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint; - */ + else + return QGestureRecognizer::MayBeGesture; + default: break; } - QKineticScroller::State newState = scroller->state(); - - // old state: inactive, pressed, dragging, scrolling - QGestureRecognizer::Result resultMatrix[4][4] = { - // new state inactive - {QGestureRecognizer::Ignore, - QGestureRecognizer::CancelGesture, - QGestureRecognizer::FinishGesture | QGestureRecognizer::ConsumeEventHint, - QGestureRecognizer::FinishGesture | QGestureRecognizer::ConsumeEventHint}, - // new state pressed - {QGestureRecognizer::MayBeGesture, - QGestureRecognizer::Ignore, - QGestureRecognizer::FinishGesture | QGestureRecognizer::ConsumeEventHint, - QGestureRecognizer::FinishGesture | QGestureRecognizer::ConsumeEventHint}, - // new state dragging - {QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint, - QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint, - QGestureRecognizer::Ignore | QGestureRecognizer::ConsumeEventHint, - QGestureRecognizer::Ignore | QGestureRecognizer::ConsumeEventHint}, - // new state scrolling - {QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint, - QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint, - QGestureRecognizer::Ignore | QGestureRecognizer::ConsumeEventHint, - QGestureRecognizer::Ignore | QGestureRecognizer::ConsumeEventHint} - }; - - return resultMatrix[(int)newState][(int)oldState]; + return QGestureRecognizer::Ignore; } +/*! \reimp + */ void QFlickGestureRecognizer::reset(QGesture *state) { // carefull here: the gesture is reset if we cancel or finishe the gesture. @@ -217,27 +239,35 @@ void QFlickGestureRecognizer::reset(QGesture *state) QGestureRecognizer::reset(state); } - - /*! \class QFlickGesture - \since 4.7 + \since 4.8 \brief The QFlickGesture class describes a flicking gesture made by the user. \ingroup gestures + The QFlickGesture is a smarter QPanGesture that uses QScroller and QScrollerProperties + to decide if it is triggered. - \sa {Gestures Programming}, QPinchGesture, QSwipeGesture + \sa {Gestures Programming}, QScroller, QScrollerProperties */ /*! \internal */ -QFlickGesture::QFlickGesture(QWidget *target, QObject *parent) +QFlickGesture::QFlickGesture(QObject *receiver, QObject *parent) : QGesture(parent) + , d_ptr(new QFlickGesturePrivate()) +{ + Q_D(QFlickGesture); + d->q_ptr = this; + d->gestureType = Qt::FlickGesture; + d->receiver = receiver; + + qDebug() << "QFlickGesture::FlickGesture for: " << receiver; +} + +QFlickGesture::~QFlickGesture() { - d = new QFlickGesturePrivate(); - d->target = target; - d->timer.start(); - qDebug() << "QFlickGesture::FlickGesture for: " << target; + delete d_ptr; } QT_END_NAMESPACE diff --git a/scroller/qflickgesture.h b/scroller/qflickgesture.h index b6571d0..5262bf0 100644 --- a/scroller/qflickgesture.h +++ b/scroller/qflickgesture.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef QFLICKGESTURE_P_H -#define QFLICKGESTURE_P_H +#ifndef QFLICKGESTURE_H +#define QFLICKGESTURE_H // // W A R N I N G @@ -56,8 +56,6 @@ #include "qgesturerecognizer.h" #include "private/qgesture_p.h" -#include "qkineticscroller.h" - QT_BEGIN_NAMESPACE class QFlickGestureRecognizer : public QGestureRecognizer @@ -77,14 +75,30 @@ class Q_GUI_EXPORT QFlickGesture : public QGesture Q_OBJECT public: - QFlickGesture(QWidget *widget, QObject *parent = 0); + enum State + { + StateInactive, + StatePressed, + StateDragging, + StateScrolling, + }; - friend class QFlickGestureRecognizer; +public: + QFlickGesture(QObject *receiver, QObject *parent = 0); + virtual ~QFlickGesture(); + + // void reset(); + +protected: + QFlickGesturePrivate* d_ptr; private: - QFlickGesturePrivate *d; + Q_DISABLE_COPY(QFlickGesture) + Q_DECLARE_PRIVATE(QFlickGesture) + + friend class QFlickGestureRecognizer; }; QT_END_NAMESPACE -#endif // QFLICKGESTURES_P_H +#endif // QFLICKGESTURES_H diff --git a/scroller/qkineticscroller.cpp b/scroller/qkineticscroller.cpp deleted file mode 100644 index e031ec1..0000000 --- a/scroller/qkineticscroller.cpp +++ /dev/null @@ -1,1182 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include -#include -#include -#include -#include -#include -#include - -#include - -QT_BEGIN_NAMESPACE - -bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); - -// #define KINETIC_SCROLLER_DEBUG - -#ifdef KINETIC_SCROLLER_DEBUG -# define qKSDebug qDebug -#else -# define qKSDebug while (false) qDebug -#endif - - -inline bool operator<=(const QPointF &p, qreal f) -{ - return (qAbs(p.x()) <= f) && (qAbs(p.y()) <= f); -} -inline bool operator<(const QPointF &p, qreal f) -{ - return (qAbs(p.x()) < f) && (qAbs(p.y()) < f); -} - -inline bool operator>=(const QPointF &p, qreal f) -{ - return (qAbs(p.x()) >= f) || (qAbs(p.y()) >= f); -} -inline bool operator>(const QPointF &p, qreal f) -{ - return (qAbs(p.x()) > f) || (qAbs(p.y()) > f); -} - -inline QPointF qAbs(const QPointF &p) -{ - return QPointF(qAbs(p.x()), qAbs(p.y())); -} - -inline int qSign(qreal r) -{ - return (r < 0) ? -1 : ((r > 0) ? 1 : 0); -} - - -/*! - \class QKineticScroller - \brief The QKineticScroller class enables kinetic scrolling for any scrolling widget or graphics item. - \ingroup qtmaemo5 - \since 4.6 - \preliminary - - With kinetic scrolling, the user can push the widget in a given - direction and it will continue to scroll in this direction until it is - stopped either by the user or by friction. Aspects of inertia, friction - and other physical concepts can be changed in order to fine-tune an - intuitive user experience. - - To enable kinetic scrolling for a widget or graphics item, you need to - derive from this class and implement at least all the pure-virtual - functions. - - Qt for Maemo 5 already comes with two implementations for - QScrollArea and QWebView, and those kinetic scrollers are - automatically instantiated and attached to these widgets on creation. - In the QScrollArea case, the kinetic scroller is initially - disabled. However, for QItemView and QScrollArea derived classes - it is enabled by default. You can obtain these automatically created - objects via a dynamic property: - - \code - // disable the kinetic scroller on scrollArea - QKineticScroller *scroller = scrollArea->property("kineticScroller") - .value(); - if (scroller) - scroller->setEnabled(false); - \endcode - - In addition there is also an example on how you would add kinetic - scrolling to a QGraphicsView based application in \c maemobrowser - examples in the \c maemo5 examples directory. - - The kinetic scroller installs an event filter on the widget to handle mouse - presses and moves on the widget \mdash presses and moves on a device's touch screen - are also handled by this mechanism. These events will be interpreted as scroll actions - depending on the current state() of the scroller. - - Even though this kinetic scroller has a huge number of settings, we - recommend that you leave them all at their default values. In case you - really want to change them you can try out the \c kineticscroller - example in the \c maemo5 examples directory. - - \sa QWidget -*/ - - -/*! - Constructs a new kinetic scroller. -*/ -QKineticScroller::QKineticScroller(QObject *receiver) - : d_ptr(new QKineticScrollerPrivate()) -{ - Q_D(QKineticScroller); - d->q_ptr = this; - d->init(); - d->receiver = receiver; -} - -/*! \internal -*/ -QKineticScroller::QKineticScroller(QObject *receiver, QKineticScrollerPrivate &dd) - : d_ptr(&dd) -{ - Q_D(QKineticScroller); - d->q_ptr = this; - d->init(); - d->receiver = receiver; -} - -/*! - Destroys the scroller. -*/ -QKineticScroller::~QKineticScroller() -{ -} - -/*! - \enum QKineticScroller::State - - This enum describes the possible states the kinetic scroller can be in. - - \value Inactive The scroller is inactive. It may also have been disabled. - \value Pressed The user has pressed the mouse button (or pressed the - the touch screen). - \value Dragging The user is dragging the mouse cursor (or other input - point) over the scroll area. - \value Scrolling Scrolling is occurring without direct user input. -*/ - -QKineticScrollerPrivate::QKineticScrollerPrivate() - : enabled(true) - , state(QKineticScroller::StateInactive) - , hOvershootPolicy(QKineticScroller::OvershootWhenScrollable) - , vOvershootPolicy(QKineticScroller::OvershootWhenScrollable) - , pressTimestamp(0) - , lastTimestamp(0) - , scrollToX(false) - , scrollToY(false) - , overshootX(false) - , overshootY(false) - , firstScroll(false) - , debugHook(0) - , debugHookUser(0) -{ } - -QKineticScrollerPrivate::~QKineticScrollerPrivate() -{ } - -void QKineticScrollerPrivate::init() -{ - Q_Q(QKineticScroller); - q->setDpiFromWidget(0); - q->resetScrollMetrics(); -} - -void QKineticScrollerPrivate::sendEvent(QObject *o, QEvent *e) -{ - qt_sendSpontaneousEvent(o, e); -} - -void QKineticScroller::registerDebugHook(void (*callback)(void *user, const QPointF &releaseVelocity, const QPointF &position, const QPointF &overshootPosition), void *user) -{ - Q_D(QKineticScroller); - d->debugHook = callback; - d->debugHookUser = user; -} - -void QKineticScroller::resetScrollMetrics() -{ - static QMap metrics; - -#ifdef Q_WS_MAEMO_5 - metrics.insert(DragVelocitySmoothingFactor, qreal(0.15)); - metrics.insert(ExponentialDecelerationBase, qreal(0.38)); // 0.85^20 - metrics.insert(LinearDecelerationFactor, qreal(0)); - metrics.insert(OvershootSpringConstant, qreal(80.56)); - metrics.insert(OvershootDragResistanceFactor, qreal(1)); - metrics.insert(OvershootMaximumDistance, QPointF(qreal(15.0 / 1000), qreal(15.0 / 1000))); - metrics.insert(DragStartDistance, qreal(2.5 / 1000)); - metrics.insert(DragStartDirectionErrorMargin, qreal(1.0 / 1000)); - metrics.insert(MaximumVelocity, qreal(6.84)); - metrics.insert(MinimumVelocity, qreal(0.0195)); - metrics.insert(MaximumNonAcceleratedVelocity, qreal(5.6)); - metrics.insert(MaximumClickThroughVelocity, qreal(0.0684)); - metrics.insert(AxisLockThreshold, qreal(0)); - metrics.insert(FastSwipeBaseVelocity, qreal(5.6 * 27)); - metrics.insert(FastSwipeMinimumVelocity, qreal(0.078)); - metrics.insert(FastSwipeMaximumTime, qreal(0.125)); - metrics.insert(FramesPerSecond, qreal(20)); -#else - metrics.insert(DragVelocitySmoothingFactor, qreal(0.02)); - metrics.insert(ExponentialDecelerationBase, qreal(1)); - metrics.insert(LinearDecelerationFactor, qreal(0.38)); - metrics.insert(OvershootSpringConstant, qreal(15.0)); - metrics.insert(OvershootDragResistanceFactor, qreal(0.5)); - metrics.insert(OvershootMaximumDistance, QPointF(0,0)); // QPointF(qreal(14.25 / 1000), qreal(14.25 / 1000))); - metrics.insert(DragStartDistance, qreal(2.5 / 1000)); - metrics.insert(DragStartDirectionErrorMargin, qreal(1.0 / 1000)); - metrics.insert(MaximumVelocity, qreal(6650.0 / 1000)); - metrics.insert(MinimumVelocity, qreal(30.0 / 1000)); - metrics.insert(MaximumNonAcceleratedVelocity, qreal(532.0 / 1000)); - metrics.insert(MaximumClickThroughVelocity, qreal(66.5 / 1000)); - metrics.insert(AxisLockThreshold, qreal(0)); - metrics.insert(FastSwipeBaseVelocity, qreal(51.3 / 1000)); - metrics.insert(FastSwipeMinimumVelocity, qreal(76.0 / 1000)); - metrics.insert(FastSwipeMaximumTime, qreal(0.125)); - metrics.insert(FramesPerSecond, qreal(60)); -#endif - - if (!metrics.isEmpty()) { - for (QMap::const_iterator it = metrics.constBegin(); it != metrics.constEnd(); ++it) - setScrollMetric(it.key(), it.value()); - if (metrics.count() != ScrollMetricCount) - qWarning("QKineticScroller::resetAllMetrics(): scroll metrics parameter set did not contain all metrics."); - } else { - qWarning("QKineticScroller::resetAllMetrics(): no platform default parameter set available."); - } -} - - -const char *QKineticScrollerPrivate::stateName(QKineticScroller::State state) -{ - switch (state) { - case QKineticScroller::StateInactive: return "inactive"; - case QKineticScroller::StatePressed: return "pressed"; - case QKineticScroller::StateDragging: return "dragging"; - case QKineticScroller::StateScrolling: return "scrolling"; - default: return "(invalid)"; - } -} - -const char *QKineticScrollerPrivate::inputName(QKineticScroller::Input input) -{ - switch (input) { - case QKineticScroller::InputPress: return "press"; - case QKineticScroller::InputMove: return "move"; - case QKineticScroller::InputRelease: return "release"; - default: return "(invalid)"; - } -} - - - - -void QKineticScrollerPrivate::timerEvent(QTimerEvent *e) -{ - if (e->timerId() != timerId) { - QObject::timerEvent(e); - return; - } - - struct timerevent { - QKineticScroller::State state; - typedef void (QKineticScrollerPrivate::*timerhandler_t)(); - timerhandler_t handler; - }; - - timerevent timerevents[] = { - { QKineticScroller::StateDragging, &QKineticScrollerPrivate::timerEventWhileDragging }, - { QKineticScroller::StateScrolling, &QKineticScrollerPrivate::timerEventWhileScrolling }, - }; - - for (int i = 0; i < int(sizeof(timerevents) / sizeof(*timerevents)); ++i) { - timerevent *te = timerevents + i; - - if (state == te->state) { - (this->*te->handler)(); - return; - } - } - - if (timerId) { - qWarning() << "Unhandled timer event, while in state " << stateName(state); - killTimer(timerId); - timerId = 0; - } - // otherwise this is a timer event that was already queued when the - // timer was killed, so just ignore it -} - -bool QKineticScroller::handleInput(Input input, const QPointF &position, qint64 timestamp) -{ - Q_D(QKineticScroller); - - qKSDebug() << "QKS::handleInput(" << input << ", " << position << ", " << timestamp << ")"; - struct statechange { - State state; - Input input; - typedef bool (QKineticScrollerPrivate::*inputhandler_t)(Input input, const QPointF &position, qint64 timestamp); - inputhandler_t handler; - }; - - statechange statechanges[] = { - { StateInactive, InputPress, &QKineticScrollerPrivate::pressWhileInactive }, - { StatePressed, InputMove, &QKineticScrollerPrivate::moveWhilePressed }, - { StatePressed, InputRelease, &QKineticScrollerPrivate::releaseWhilePressed }, - { StateDragging, InputMove, &QKineticScrollerPrivate::moveWhileDragging }, - { StateDragging, InputRelease, &QKineticScrollerPrivate::releaseWhileDragging }, - { StateScrolling, InputPress, &QKineticScrollerPrivate::pressWhileScrolling } - }; - - for (int i = 0; i < int(sizeof(statechanges) / sizeof(*statechanges)); ++i) { - statechange *sc = statechanges + i; - - if (d->state == sc->state && input == sc->input) - return (d->*sc->handler)(input, position - d->overshootPosition, timestamp); - } - - qWarning() << "Unhandled input: got input " << d->inputName(input) << " while in state " << d->stateName(d->state); - return false; -} - -bool QKineticScroller::isEnabled() const -{ - Q_D(const QKineticScroller); - return d->enabled; -} - -void QKineticScroller::setEnabled(bool b) -{ - Q_D(QKineticScroller); - d->enabled = b; -} - -QKineticScroller::State QKineticScroller::state() const -{ - Q_D(const QKineticScroller); - return d->state; -} - -/*! - Resets the internal state of the kinetic scroller. This function is not - needed for normal use. This function only needs to be called if the - kinetic scroller is being re-attached to a different widget. -*/ -void QKineticScroller::reset() -{ - Q_D(QKineticScroller); - - d->setState(StateInactive); -} - -QKineticScroller::OvershootPolicy QKineticScroller::horizontalOvershootPolicy() const -{ - Q_D(const QKineticScroller); - return d->hOvershootPolicy; -} - -void QKineticScroller::setHorizontalOvershootPolicy(QKineticScroller::OvershootPolicy policy) -{ - Q_D(QKineticScroller); - d->hOvershootPolicy = policy; -} - -QKineticScroller::OvershootPolicy QKineticScroller::verticalOvershootPolicy() const -{ - Q_D(const QKineticScroller); - return d->vOvershootPolicy; -} - -void QKineticScroller::setVerticalOvershootPolicy(QKineticScroller::OvershootPolicy policy) -{ - Q_D(QKineticScroller); - d->vOvershootPolicy = policy; -} - -QVariant QKineticScroller::scrollMetric(ScrollMetric metric) const -{ - Q_D(const QKineticScroller); - - switch (metric) { - case DragVelocitySmoothingFactor: return d->dragVelocitySmoothingFactor; - case LinearDecelerationFactor: return d->linearDecelerationFactor; - case ExponentialDecelerationBase: return d->exponentialDecelerationBase; - case OvershootSpringConstant: return d->overshootSpringConstantRoot * d->overshootSpringConstantRoot; - case OvershootDragResistanceFactor: return d->overshootDragResistanceFactor; - case OvershootMaximumDistance: return d->overshootMaximumDistance; - case DragStartDistance: return d->dragStartDistance; - case DragStartDirectionErrorMargin: return d->dragStartDirectionErrorMargin; - case MinimumVelocity: return d->minimumVelocity; - case MaximumVelocity: return d->maximumVelocity; - case MaximumNonAcceleratedVelocity: return d->maximumNonAcceleratedVelocity; - case MaximumClickThroughVelocity: return d->maximumClickThroughVelocity; - case AxisLockThreshold: return d->axisLockThreshold; - case FramesPerSecond: return d->framesPerSecond; - case FastSwipeMaximumTime: return d->fastSwipeMaximumTime; - case FastSwipeMinimumVelocity: return d->fastSwipeMinimumVelocity; - case FastSwipeBaseVelocity: return d->fastSwipeBaseVelocity; - case ScrollMetricCount: break; - } - return QVariant(); -} - - -void QKineticScroller::setScrollMetric(ScrollMetric metric, const QVariant &value) -{ - Q_D(QKineticScroller); - - switch (metric) { - case DragVelocitySmoothingFactor: d->dragVelocitySmoothingFactor = qBound(qreal(0), value.toReal(), qreal(1)); break; - case LinearDecelerationFactor: d->linearDecelerationFactor = qBound(qreal(0), value.toReal(), qreal(1)); break; - case ExponentialDecelerationBase: d->exponentialDecelerationBase = qBound(qreal(0), value.toReal(), qreal(1)); break; - case OvershootSpringConstant: d->overshootSpringConstantRoot = qSqrt(value.toReal()); break; - case OvershootDragResistanceFactor: d->overshootDragResistanceFactor = value.toReal(); break; - case OvershootMaximumDistance: d->overshootMaximumDistance = value.toPointF(); break; - case DragStartDistance: d->dragStartDistance = value.toReal(); break; - case DragStartDirectionErrorMargin: d->dragStartDirectionErrorMargin = value.toReal(); break; - case MinimumVelocity: d->minimumVelocity = value.toReal(); break; - case MaximumVelocity: d->maximumVelocity = value.toReal(); break; - case MaximumNonAcceleratedVelocity: d->maximumNonAcceleratedVelocity = value.toReal(); break; - case MaximumClickThroughVelocity: d->maximumClickThroughVelocity = value.toReal(); break; - case AxisLockThreshold: d->axisLockThreshold = qBound(qreal(0), value.toReal(), qreal(1)); break; - case FramesPerSecond: d->framesPerSecond = qBound(1, value.toInt(), 100); break; - case FastSwipeMaximumTime: d->fastSwipeMaximumTime = value.toReal(); break; - case FastSwipeMinimumVelocity: d->fastSwipeMinimumVelocity = value.toReal(); break; - case FastSwipeBaseVelocity: d->fastSwipeBaseVelocity = value.toReal(); break; - case ScrollMetricCount: break; - } -} - -qreal QKineticScroller::dpi() const -{ - Q_D(const QKineticScroller); - return d->pixelPerMeter / qreal(39.3700787); -} - - -void QKineticScroller::setDpi(qreal dpi) -{ - Q_D(QKineticScroller); - d->pixelPerMeter = dpi * qreal(39.3700787); -} - -void QKineticScroller::setDpiFromWidget(QWidget *widget) -{ - Q_D(QKineticScroller); - - QDesktopWidget *dw = QApplication::desktop(); - QPointF dpi = d->realDpi(widget ? dw->screenNumber(widget) : dw->primaryScreen()); - setDpi((dpi.x() + dpi.y()) / qreal(2)); -} - -#if !defined(Q_WS_MAEMO_5) && !defined(Q_WS_MAC) - -QPointF QKineticScrollerPrivate::realDpi(int screen) -{ - QWidget *w = QApplication::desktop()->screen(screen); - return QPointF(w->physicalDpiX(), w->physicalDpiY()); -} - -#endif - - -void QKineticScrollerPrivate::updateVelocity(const QPointF &deltaPixelRaw, qint64 deltaTime) -{ - qKSDebug() << "QKS::updateVelocity(" << deltaPixelRaw << " [delta pix], " << deltaTime << " [delta ms])"; - - QPointF deltaPixel = deltaPixelRaw; - - // faster than 2.5mm/ms seems bogus (that would be a screen height in ~20 ms) - if (((deltaPixelRaw / qreal(deltaTime)).manhattanLength() / pixelPerMeter * 1000) > qreal(2.5)) - deltaPixel = deltaPixelRaw * qreal(2.5) * pixelPerMeter / 1000 / (deltaPixelRaw / qreal(deltaTime)).manhattanLength(); - - qreal inversSmoothingFactor = ((qreal(1) - dragVelocitySmoothingFactor) * qreal(deltaTime) / qreal(1000)); - QPointF newv = -deltaPixel / qreal(deltaTime) * qreal(1000) / pixelPerMeter; - newv = newv * (qreal(1) - inversSmoothingFactor) + releaseVelocity * inversSmoothingFactor; - - // newv = newv * dragVelocitySmoothingFactor + velocity * (qreal(1) - dragVelocitySmoothingFactor); - - if (deltaPixel.x()) - releaseVelocity.setX(qBound(-maximumVelocity, newv.x(), maximumVelocity)); - if (deltaPixel.y()) - releaseVelocity.setY(qBound(-maximumVelocity, newv.y(), maximumVelocity)); - - qKSDebug() << " --> new velocity:" << releaseVelocity; -} - -qreal QKineticScrollerPrivate::decelerate(qreal v, qreal t) -{ - qreal result = v * qPow(exponentialDecelerationBase, t); - qreal linear = linearDecelerationFactor * t; - if (qAbs(result) > linear) - return result + (result < 0 ? linear : -linear); - else - return 0; -} - -/*! Calculates the current velocity during scrolling - */ -QPointF QKineticScrollerPrivate::calculateVelocity(qreal time) -{ - QPointF velocity; - - // -- x coordinate - if (overshootX) { - if (overshootSpringConstantRoot * (time-overshootStartTimeX) < M_PI) // prevent swinging around - velocity.setX(overshootVelocity.x() * qCos(overshootSpringConstantRoot * (time - overshootStartTimeX))); - else - velocity.setX(-overshootVelocity.x()); - - } else { - qreal newVelocity = decelerate(releaseVelocity.x(), time); - - if (scrollToX) { - if (qAbs(newVelocity) < qreal(30.0 / 1000) /* 30mm/s */) - newVelocity = qreal(30.0 / 1000) * qSign(releaseVelocity.x()); - - } else { - if (qAbs(newVelocity) < qreal(0.5) * qreal(framesPerSecond) / pixelPerMeter /* 0.5 [pix/frame] */) - newVelocity = 0; - } - - velocity.setX(newVelocity); - } - - // -- y coordinate - if (overshootY) { - if (overshootSpringConstantRoot * (time-overshootStartTimeY) < M_PI) // prevent swinging around - velocity.setY(overshootVelocity.y() * qCos(overshootSpringConstantRoot * (time - overshootStartTimeY))); - else - velocity.setY(-overshootVelocity.y()); - - } else { - qreal newVelocity = decelerate(releaseVelocity.y(), time); - - if (scrollToY) { - if (qAbs(newVelocity) < qreal(30.0 / 1000) /* 30mm/s */) - newVelocity = qreal(30.0 / 1000) * qSign(releaseVelocity.y()); - - } else { - if (qAbs(newVelocity) < qreal(0.5) * qreal(framesPerSecond) / pixelPerMeter /* 0.5 [pix/frame] */) - newVelocity = 0; - } - - velocity.setY(newVelocity); - } - - return velocity; -} - - -void QKineticScrollerPrivate::handleDrag(const QPointF &position, qint64 timestamp) -{ - QPointF deltaPixel = position - lastPosition; - qint64 deltaTime = timestamp - lastTimestamp; - - if (axisLockThreshold) { - int dx = qAbs(deltaPixel.x()); - int dy = qAbs(deltaPixel.y()); - if (dx || dy) { - bool vertical = (dy > dx); - qreal alpha = qreal(vertical ? dx : dy) / qreal(vertical ? dy : dx); - //qKSDebug() << "QKS::handleDrag() -- axis lock:" << alpha << " / " << axisLockThreshold << "- isvertical:" << vertical << "- dx:" << dx << "- dy:" << dy; - if (alpha <= axisLockThreshold) { - if (vertical) - deltaPixel.setX(0); - else - deltaPixel.setY(0); - } - } - } - - // calculate velocity (if the user would release the mouse NOW) - updateVelocity(deltaPixel, deltaTime); - - // restrict velocity, if content is not scrollable - QPointF maxPos = maximumContentPosition; - bool canScrollX = maxPos.x() || (hOvershootPolicy == QKineticScroller::OvershootAlwaysOn); - bool canScrollY = maxPos.y() || (vOvershootPolicy == QKineticScroller::OvershootAlwaysOn); - - if (!canScrollX) { - deltaPixel.setX(0); - releaseVelocity.setX(0); - } - if (!canScrollY) { - deltaPixel.setY(0); - releaseVelocity.setY(0); - } - -// if (firstDrag) { -// // Do not delay the first drag -// setContentPositionHelper(q->contentPosition() - overshootDistance - deltaPixel); -// dragDistance = QPointF(0, 0); -// } else { - dragDistance += deltaPixel; -// } - - if (canScrollX) - lastPosition.setX(position.x()); - if (canScrollY) - lastPosition.setY(position.y()); - lastTimestamp = timestamp; -} - - - -bool QKineticScrollerPrivate::pressWhileInactive(QKineticScroller::Input, const QPointF &position, qint64 timestamp) -{ - QScrollPrepareEvent spe(position); - sendEvent(receiver, &spe); - - qKSDebug() << "QScrollPrepareEvent returned with "< qreal(0)) || - (hOvershootPolicy == QKineticScroller::OvershootAlwaysOn) || - (vOvershootPolicy == QKineticScroller::OvershootAlwaysOn)) { - - lastPosition = pressPosition = position; - lastTimestamp = pressTimestamp = timestamp; - firstScroll = true; - setState(QKineticScroller::StatePressed); - } - } - return false; -} - -bool QKineticScrollerPrivate::releaseWhilePressed(QKineticScroller::Input, const QPointF &, qint64) -{ - if (overshootX || overshootY) - setState(QKineticScroller::StateScrolling); - else - setState(QKineticScroller::StateInactive); - return false; -} - -bool QKineticScrollerPrivate::moveWhilePressed(QKineticScroller::Input, const QPointF &position, qint64 timestamp) -{ - Q_Q(QKineticScroller); - - QPointF deltaPixel = position - pressPosition; - - bool moveStarted = ((deltaPixel.manhattanLength() / pixelPerMeter) > dragStartDistance); - - if (moveStarted) { - qreal deltaXtoY = qAbs(pressPosition.x() - position.x()) - qAbs(pressPosition.y() - position.y()); - deltaXtoY /= pixelPerMeter; - - QPointF maxPos = maximumContentPosition; - bool canScrollX = (maxPos.x() > 0); - bool canScrollY = (maxPos.y() > 0); - - if (hOvershootPolicy == QKineticScroller::OvershootAlwaysOn) - canScrollX = true; - if (vOvershootPolicy == QKineticScroller::OvershootAlwaysOn) - canScrollY = true; - - if (deltaXtoY < 0) { - if (!canScrollY && (!canScrollX || (-deltaXtoY >= dragStartDirectionErrorMargin))) - moveStarted = false; - } else { - if (!canScrollX && (!canScrollY || (deltaXtoY >= dragStartDirectionErrorMargin))) - moveStarted = false; - } - } - - if (moveStarted) { - setState(QKineticScroller::StateDragging); - - // subtract the dragStartDistance - deltaPixel = deltaPixel - deltaPixel * (dragStartDistance / deltaPixel.manhattanLength()); - - if (!deltaPixel.isNull()) { - // handleDrag updates lastPosition, lastTimestamp and velocity - handleDrag(pressPosition + deltaPixel, timestamp); - } - } - return moveStarted; -} - -bool QKineticScrollerPrivate::moveWhileDragging(QKineticScroller::Input, const QPointF &position, qint64 timestamp) -{ - // handleDrag updates lastPosition, lastTimestamp and velocity - handleDrag(position, timestamp); - return true; -} - -void QKineticScrollerPrivate::timerEventWhileDragging() -{ - if (!dragDistance.isNull()) { - qKSDebug() << "QKS::timerEventWhileDragging() -- dragDistance:" << dragDistance; - - setContentPositionHelper(-dragDistance); - dragDistance = QPointF(0, 0); - } -} - -bool QKineticScrollerPrivate::releaseWhileDragging(QKineticScroller::Input, const QPointF &, qint64 timestamp) -{ - // calculate the fastSwipe velocity - QPointF maxPos = maximumContentPosition; - QPointF fastSwipeVelocity = QPoint(0, 0); - QSizeF size = viewportSize; - if (size.width()) - fastSwipeVelocity.setX(qMin(maximumVelocity, maxPos.x() / size.width() * fastSwipeBaseVelocity)); - if (size.height()) - fastSwipeVelocity.setY(qMin(maximumVelocity, maxPos.y() / size.height() * fastSwipeBaseVelocity)); - - if (fastSwipeMaximumTime && - ((timestamp - pressTimestamp) < qint64(fastSwipeMaximumTime * 1000)) && - (oldVelocity > fastSwipeMinimumVelocity)) { - - // more than one fast swipe in a row: add fastSwipeVelocity - int signX = 0, signY = 0; - if (releaseVelocity.x()) - signX = (releaseVelocity.x() > 0) == (oldVelocity.x() > 0) ? 1 : -1; - if (releaseVelocity.y()) - signY = (releaseVelocity.y() > 0) == (oldVelocity.y() > 0) ? 1 : -1; - - releaseVelocity.setX(signX * (oldVelocity.x() + (oldVelocity.x() > 0 ? fastSwipeVelocity.x() : -fastSwipeVelocity.x()))); - releaseVelocity.setY(signY * (oldVelocity.y() + (oldVelocity.y() > 0 ? fastSwipeVelocity.y() : -fastSwipeVelocity.y()))); - - } else if (releaseVelocity >= minimumVelocity) { - - // if we have a fast swipe, accelerate it to the fastSwipe velocity - if ((qAbs(releaseVelocity.x()) > maximumNonAcceleratedVelocity) && - (fastSwipeVelocity.x() > maximumNonAcceleratedVelocity)) { - releaseVelocity.setX(releaseVelocity.x() > 0 ? fastSwipeVelocity.x() : -fastSwipeVelocity.x()); - } - if ((qAbs(releaseVelocity.y()) > maximumNonAcceleratedVelocity) && - (fastSwipeVelocity.y() > maximumNonAcceleratedVelocity)) { - releaseVelocity.setY(releaseVelocity.y() > 0 ? fastSwipeVelocity.y() : -fastSwipeVelocity.y()); - } - - } - - qKSDebug() << "QKS::releaseWhileDragging() -- velocity:" << releaseVelocity << "-- minimum velocity:" << minimumVelocity; - if (overshootX || overshootY) - setState(QKineticScroller::StateScrolling); - else if (releaseVelocity >= minimumVelocity) - setState(QKineticScroller::StateScrolling); - else - setState(QKineticScroller::StateInactive); - - return true; -} - -void QKineticScrollerPrivate::timerEventWhileScrolling() -{ - qreal deltaTime = qreal(scrollRelativeTimer.restart()) / 1000; - qreal time = qreal(scrollAbsoluteTimer.elapsed()) / 1000; - - // calculate the velocity for the passed interval deltatime. - // using the midpoint of the interval gives a better precision than using just time. - QPointF newVelocity = calculateVelocity(time - deltaTime / 2); - QPointF deltaPos = newVelocity * deltaTime * pixelPerMeter; - - // -- move (convert from [m/s] to [pix/frame] - if (!deltaPos.isNull()) - setContentPositionHelper(deltaPos); - - qKSDebug() << "QKS::timerEventWhileScrolling() -- DeltaPos:" << deltaPos << "- NewVel:" << newVelocity << "- Time:" << time; - - if (newVelocity.isNull() || - (releaseVelocity.isNull() && !scrollToX && !scrollToY && !overshootX && !overshootY)) - // if (newVelocity.isNull()) - setState(QKineticScroller::StateInactive); -} - -bool QKineticScrollerPrivate::pressWhileScrolling(QKineticScroller::Input, const QPointF &position, qint64 timestamp) -{ - lastPosition = pressPosition = position; - lastTimestamp = pressTimestamp = timestamp; - setState(QKineticScroller::StatePressed); - return true; -} - -void QKineticScrollerPrivate::setState(QKineticScroller::State newstate) -{ - Q_Q(QKineticScroller); - - if (state == newstate) - return; - - qKSDebug() << "QKS::setState(" << stateName(newstate) << ")"; - - switch (newstate) { - case QKineticScroller::StateInactive: - if (state == QKineticScroller::StateScrolling) { - if (timerId) { - killTimer(timerId); - timerId = 0; - } else { - qKSDebug() << " --> state change from " << stateName(state) << " to " << stateName(newstate) << ", but timer is not active."; - } - } - releaseVelocity = QPointF(0, 0); - break; - - case QKineticScroller::StatePressed: - if (timerId) { - killTimer(timerId); - timerId = 0; - } - scrollToX = false; - scrollToY = false; - oldVelocity = releaseVelocity; - // releaseVelocity = QPointF(0, 0); - break; - - case QKineticScroller::StateDragging: - - dragDistance = QPointF(0, 0); - if (state == QKineticScroller::StatePressed) { - if (!timerId) { - timerId = startTimer(1000 / framesPerSecond); - } else { - qKSDebug() << " --> state change from " << stateName(state) << " to " << stateName(newstate) << ", but timer is already active."; - } - } - - break; - - case QKineticScroller::StateScrolling: - if (!timerId) { - timerId = startTimer(1000 / framesPerSecond); - } - scrollRelativeTimer.start(); - scrollAbsoluteTimer.start(); - - if (state == QKineticScroller::StateDragging) { - // TODO: better calculate StartTime using the current releaseVelocity - overshootStartTimeX = overshootStartTimeY = qreal(scrollAbsoluteTimer.elapsed()) / 1000 - M_PI / (overshootSpringConstantRoot * 2); - overshootVelocity = overshootPosition / pixelPerMeter * overshootSpringConstantRoot; - } - - break; - } - - qSwap(state, newstate); - q->stateChanged(newstate); -} - -/*! - Starts scrolling the widget so that the point \a pos is visible inside - the viewport. - - If the specified point cannot be reached, the contents are scrolled to the - nearest valid position (in this case the scroller might or might not overshoot). - - The scrolling speed will be calculated so that the given position will - be reached after a platform-defined time span (1 second for Maemo 5). - The final speed at the end position is not guaranteed to be zero. - - \sa ensureVisible() -*/ -void QKineticScroller::scrollTo(const QPointF &pos, int scrollTime) -{ - Q_D(QKineticScroller); - - if (scrollTime <= 0) - scrollTime = 1; - - qKSDebug() << "QKS::scrollTo(" << pos << " [pix], " << scrollTime << " [ms])"; - - qreal time = qreal(scrollTime) / 1000; - - if ((pos == d->contentPosition) || - (d->state == QKineticScroller::StatePressed) || - (d->state == QKineticScroller::StateDragging)) { - return; - } - - // estimate the minimal start velocity - // if the start velocity is below that then the scrolling would stop before scrollTime. - //qreal vMin = d->linearDecelerationFactor * time / qPow(d->exponentialDecelerationBase, time); - - /* - // estimate of the distance passed within the vMin time during scrollTime - qreal distMin = qreal(scrollTime) * vMin / 2.0; - - QPointF v = QPointF((pos.x()-contentPosition().x()) / distMin * vMin, - (pos.y()-contentPosition().y()) / distMin * vMin); - - */ - - // v(t) = vstart * exponentialDecelerationBase ^ t - linearDecelerationFactor * t - // pos(t) = integrate(v(t) * dt) - // pos(t) = vstart * (eDB ^ t / ln(eDB) + C) - lDF / 2 * t ^ 2 - // - // pos(time) = pos - contentsPos() - // vstart = ((lDF / 2) * time ^ 2 + (pos - contentPos())) / (eDB ^ time / ln(eDB) + C) - // (for C = -1/ln(eDB) ) - - QPointF scrollDir(qSign(pos.x() - d->contentPosition.x()), - qSign(pos.y() - d->contentPosition.y())); - - QPointF v = (scrollDir * (d->linearDecelerationFactor / qreal(2)) * qreal(time) * qreal(time) + (pos - d->contentPosition) / d->pixelPerMeter); - if (d->exponentialDecelerationBase != qreal(1)) - v /= (qPow(d->exponentialDecelerationBase, time) - 1) / qLn(d->exponentialDecelerationBase); - else - v /= time; - - d->scrollToPosition = pos; - d->scrollToX = true; - d->scrollToY = true; - d->releaseVelocity = v; - d->scrollRelativeTimer.restart(); - d->scrollAbsoluteTimer.restart(); - d->setState(QKineticScroller::StateScrolling); -} - -/*! - Starts scrolling the widget so that the point \a pos is visible inside the - viewport with margins specified in pixels by \a xmargin and \a ymargin. - - If the specified point cannot be reached, the contents are scrolled to the - nearest valid position. The default value for both margins is 50 pixels. - - This function performs the actual scrolling by calling scrollTo(). -*/ -void QKineticScroller::ensureVisible(const QPointF &pos, int xmargin, int ymargin, int scrollTime) -{ - Q_D(QKineticScroller); - - QSizeF visible = d->viewportSize; - QPointF currentPos = d->contentPosition; - - qKSDebug() << "QKS::ensureVisible(" << pos << " [pix], " << xmargin << " [pix], " << ymargin << " [pix], " << scrollTime << "[ms])"; - qKSDebug() << " --> content position:" << d->contentPosition; - - QRectF posRect(pos.x() - xmargin, pos.y() - ymargin, 2 * xmargin, 2 * ymargin); - QRectF visibleRect(currentPos, visible); - - if (visibleRect.contains(posRect)) - return; - - QPointF newPos = currentPos; - if (posRect.top() < visibleRect.top()) - newPos.setY(posRect.top()); - else if (posRect.bottom() > visibleRect.bottom()) - newPos.setY(posRect.bottom() - visible.height()); - if (posRect.left() < visibleRect.left()) - newPos.setX(posRect.left()); - else if (posRect.right() > visibleRect.right()) - newPos.setY(posRect.right() - visible.width()); - - scrollTo(newPos, scrollTime); -} - - -/*! \internal - Helps when setting the content position. - It will try to move the content by the requested delta but stop in case - when we are coming back from an overshoot or a scrollTo. - It will also indicate a new overshooting condition by the overshootX and oversthootY flags. - - In this cases it will reset the velocity variables and other flags. - - Also keeps track of the current over-shooting value in overshootPosition. - - \deltaPos is the amout of pixels the current content position should be moved -*/ -void QKineticScrollerPrivate::setContentPositionHelper(const QPointF &deltaPos) -{ - if (state == QKineticScroller::StateDragging && overshootDragResistanceFactor) - overshootPosition /= overshootDragResistanceFactor; - - QPointF oldPos = contentPosition + overshootPosition; - QPointF newPos = oldPos + deltaPos; - QPointF maxPos = maximumContentPosition; - - QPointF oldScrollToDist = scrollToPosition - oldPos; - QPointF newScrollToDist = scrollToPosition - newPos; - - qKSDebug() << "QKS::setContentPositionHelper(" << deltaPos << " [pix])"; - qKSDebug() << " --> overshoot:" << overshootPosition << "- old pos:" << oldPos << "- new pos:" << newPos; - - QPointF oldClampedPos; - oldClampedPos.setX(qBound(qreal(0), oldPos.x(), maxPos.x())); - oldClampedPos.setY(qBound(qreal(0), oldPos.y(), maxPos.y())); - - QPointF newClampedPos; - newClampedPos.setX(qBound(qreal(0), newPos.x(), maxPos.x())); - newClampedPos.setY(qBound(qreal(0), newPos.y(), maxPos.y())); - - // --- handle overshooting and stop if the coordinate is going back inside the normal area - bool alwaysOvershootX = (hOvershootPolicy == QKineticScroller::OvershootAlwaysOn); - bool alwaysOvershootY = (vOvershootPolicy == QKineticScroller::OvershootAlwaysOn); - bool noOvershootX = (hOvershootPolicy == QKineticScroller::OvershootAlwaysOff) || - ((state == QKineticScroller::StateDragging) && !overshootDragResistanceFactor); - bool noOvershootY = (vOvershootPolicy == QKineticScroller::OvershootAlwaysOff) || - ((state == QKineticScroller::StateDragging) && !overshootDragResistanceFactor); - bool canOvershootX = !noOvershootX && (alwaysOvershootX || maxPos.x()); - bool canOvershootY = !noOvershootY && (alwaysOvershootY || maxPos.y()); - - qreal oldOvershootX = (canOvershootX) ? oldPos.x() - oldClampedPos.x() : 0; - qreal oldOvershootY = (canOvershootY) ? oldPos.y() - oldClampedPos.y() : 0; - - qreal newOvershootX = (canOvershootX) ? newPos.x() - newClampedPos.x() : 0; - qreal newOvershootY = (canOvershootY) ? newPos.y() - newClampedPos.y() : 0; - - if (state == QKineticScroller::StateDragging && overshootDragResistanceFactor) { - oldOvershootX *= overshootDragResistanceFactor; - oldOvershootY *= overshootDragResistanceFactor; - newOvershootX *= overshootDragResistanceFactor; - newOvershootY *= overshootDragResistanceFactor; - } - - // -- stop at the maximum overshoot distance (if set) - if (!overshootMaximumDistance.isNull()) { - newOvershootX = qBound(-overshootMaximumDistance.x() * pixelPerMeter, newOvershootX, overshootMaximumDistance.x() * pixelPerMeter); - - newOvershootY = qBound(-overshootMaximumDistance.y() * pixelPerMeter, newOvershootY, overshootMaximumDistance.y() * pixelPerMeter); - } - - // --- sanity check for scrollTo in case we can't even scroll that direction - if (!(maxPos.x() || alwaysOvershootX)) - scrollToX = false; - if (!(maxPos.y() || alwaysOvershootY)) - scrollToY = false; - - // --- handle crossing over borders (scrollTo and overshoot) - qKSDebug() << " --> old overshoot Y:" << oldOvershootY << "- new overshoot Y:" << newOvershootY; - // -- x axis - if (scrollToX && qSign(oldScrollToDist.x()) != qSign(newScrollToDist.x())) { - newClampedPos.setX(scrollToPosition.x()); - newOvershootX = 0; - releaseVelocity.setX(0); - scrollToX = false; - - } else if (oldOvershootX && (qSign(oldOvershootX) != qSign(newOvershootX))) { - newClampedPos.setX((oldOvershootX < 0) ? 0 : maxPos.x()); - newOvershootX = 0; - releaseVelocity.setX(0); - overshootVelocity.setX(0); - overshootX = false; - - } else if (!oldOvershootX && newOvershootX) { - overshootStartTimeX = qreal(scrollAbsoluteTimer.elapsed()) / 1000; - overshootVelocity.setX(calculateVelocity(overshootStartTimeX).x()); - - // restrict the overshoot to overshootMaximumDistance - qreal maxOvershootVelocity = overshootMaximumDistance.x() * overshootSpringConstantRoot; - if (overshootMaximumDistance.x() && qAbs(overshootVelocity.x()) > maxOvershootVelocity) - overshootVelocity.setX(maxOvershootVelocity * qSign(newOvershootX)); - - // -- prevent going into overshoot too far - if (state != QKineticScroller::StateDragging) - newOvershootX = qSign(newOvershootX) * qreal(0.0001); - - scrollToX = false; - overshootX = true; - } - - // -- y axis - if (scrollToY && qSign(oldScrollToDist.y()) != qSign(newScrollToDist.y())) { - newClampedPos.setY(scrollToPosition.y()); - newOvershootY = 0; - releaseVelocity.setY(0); - scrollToY = false; - - } else if (oldOvershootY && (qSign(oldOvershootY) != qSign(newOvershootY))) { - newClampedPos.setY((oldOvershootY < 0) ? 0 : maxPos.y()); - newOvershootY = 0; - releaseVelocity.setY(0); - overshootVelocity.setY(0); - overshootY = false; - - } else if (!oldOvershootY && newOvershootY) { - overshootStartTimeY = qreal(scrollAbsoluteTimer.elapsed()) / 1000; - overshootVelocity.setY(calculateVelocity(overshootStartTimeY).y()); - - // -- restrict the overshoot to overshootMaximumDistance - qreal maxOvershootVelocity = overshootMaximumDistance.y() * overshootSpringConstantRoot; - if (overshootMaximumDistance.y() && (qAbs(overshootVelocity.y()) > maxOvershootVelocity)) - overshootVelocity.setY(maxOvershootVelocity * qSign(newOvershootY)); - - // -- prevent going into overshoot too far - if (state != QKineticScroller::StateDragging) - newOvershootY = qSign(newOvershootY) * qreal(0.0001); - - scrollToY = false; - overshootY = true; - } - - overshootPosition.setX(newOvershootX); - overshootPosition.setY(newOvershootY); - - if( target ) { - QScrollEvent se(newClampedPos, overshootPosition, firstScroll); - sendEvent(target, &se); - firstScroll = false; - } - contentPosition = newClampedPos; - - if (debugHook) - debugHook(debugHookUser, calculateVelocity(qreal(scrollAbsoluteTimer.elapsed()) / 1000), newClampedPos, overshootPosition); - - qKSDebug() << " --> new position:" << newClampedPos << "- new overshoot:" << overshootPosition << - "- overshoot x/y?:" << overshootX << "/" << overshootY << "- scrollto x/y?:" << scrollToX << "/" << scrollToY; -} - - -/*! - \enum QKineticScroller::OvershootPolicy - - This enum describes the various modes of overshooting. - - \value OvershootWhenScrollable Overshooting is when the content is scrollable. This is the default. - - \value OvershootAlwaysOff Overshooting is never enabled (even when the content is scrollable). - - \value OvershootAlwaysOn Overshooting is always enabled (even when the content is not scrollable). -*/ - -/*! - This function get called whenever the state of the kinetic scroller changes. - The old state is supplied as \a oldState, while the new state is returned by - calling state(). - - The default implementation does nothing. - - \sa state() -*/ -void QKineticScroller::stateChanged(State oldState) -{ - Q_UNUSED(oldState); -} - -QT_END_NAMESPACE diff --git a/scroller/qkineticscroller.h b/scroller/qkineticscroller.h deleted file mode 100644 index 610eb2f..0000000 --- a/scroller/qkineticscroller.h +++ /dev/null @@ -1,160 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QKINETICSCROLLER_H -#define QKINETICSCROLLER_H - -#include -#include -#include -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -class QFlickGestureRecognizer; -class QKineticScrollerPrivate; - -class QKineticScroller -{ -public: - explicit QKineticScroller(QObject *receiver); - virtual ~QKineticScroller(); - - bool isEnabled() const; - void setEnabled(bool b); - - enum State - { - StateInactive, - StatePressed, - StateDragging, - StateScrolling, - }; - - State state() const; - void reset(); - - enum OvershootPolicy - { - OvershootWhenScrollable, - OvershootAlwaysOff, - OvershootAlwaysOn, - }; - - OvershootPolicy horizontalOvershootPolicy() const; - void setHorizontalOvershootPolicy(OvershootPolicy policy); - OvershootPolicy verticalOvershootPolicy() const; - void setVerticalOvershootPolicy(OvershootPolicy policy); - - enum ScrollMetric - { - DragVelocitySmoothingFactor, // qreal [0..1/s] (complex calculation involving time) v = v_new* DASF + v_old * (1-DASF) - - LinearDecelerationFactor, // qreal [m/s^2] - ExponentialDecelerationBase, // qreal - OvershootSpringConstant, // qreal [kg/s^2] - OvershootDragResistanceFactor, // qreal [0..1] - OvershootMaximumDistance, // QPointF([m], [m]) - - DragStartDistance, // qreal [m] - DragStartDirectionErrorMargin, // qreal [m] - - MinimumVelocity, // qreal [m/s] - MaximumVelocity, // qreal [m/s] - MaximumNonAcceleratedVelocity, // qreal [m/s] - - MaximumClickThroughVelocity, // qreal [m/s] - AxisLockThreshold, // qreal [0..1] atan(|min(dx,dy)|/|max(dx,dy)|) - - FramesPerSecond, // int [frames/s] - - FastSwipeMaximumTime, // qreal [s] - FastSwipeMinimumVelocity, // qreal [m/s] - FastSwipeBaseVelocity, // qreal [m/s] - - ScrollMetricCount - }; - - QVariant scrollMetric(ScrollMetric metric) const; - void setScrollMetric(ScrollMetric metric, const QVariant &value); - void resetScrollMetrics(); - - void scrollTo(const QPointF &pos, int scrollTime = 1000); - void ensureVisible(const QPointF &pos, int xmargin, int ymargin, int scrollTime = 1000); - - qreal dpi() const; - void setDpi(qreal dpi); - void setDpiFromWidget(QWidget *widget); - - void registerDebugHook(void (*callback)(void *user, const QPointF &releaseVelocity, const QPointF &position, const QPointF &overshootPosition), void *user); - -protected: - virtual void stateChanged(State oldState); - - enum Input { - InputPress, - InputMove, - InputRelease - }; - - bool handleInput(Input input, const QPointF &position, qint64 timestamp); - - QKineticScroller(QObject *receiver, QKineticScrollerPrivate &dd); - QScopedPointer d_ptr; - -private: - Q_DISABLE_COPY(QKineticScroller) - Q_DECLARE_PRIVATE(QKineticScroller) - - friend class QFlickGestureRecognizer; -}; - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(QKineticScroller *) - -QT_END_HEADER - -#endif // QKINETICSCROLLER_H diff --git a/scroller/qkineticscroller_mac.mm b/scroller/qkineticscroller_mac.mm deleted file mode 100644 index b358063..0000000 --- a/scroller/qkineticscroller_mac.mm +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#import - -#include "qkineticscroller_p.h" - -#ifdef Q_WS_MAC - -QPointF QKineticScrollerPrivate::realDpi(int screen) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSArray *nsscreens = [NSScreen screens]; - - if (screen < 0 || screen >= int([nsscreens count])) - screen = 0; - - NSScreen *nsscreen = [nsscreens objectAtIndex:screen]; - CGDirectDisplayID display = [[[nsscreen deviceDescription] objectForKey:@"NSScreenNumber"] intValue]; - - CGSize mmsize = CGDisplayScreenSize(display); - if (mmsize.width > 0 && mmsize.height > 0) { - return QPointF(CGDisplayPixelsWide(display) / mmsize.width, - CGDisplayPixelsHigh(display) / mmsize.height) * qreal(25.4); - } else { - return QPointF(); - } - [pool release]; -} - -#endif diff --git a/scroller/qkineticscroller_maemo5.cpp b/scroller/qkineticscroller_maemo5.cpp deleted file mode 100644 index 4c6c9cc..0000000 --- a/scroller/qkineticscroller_maemo5.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qkineticscroller_p.h" - -#ifdef Q_WS_MAEMO_5 - -QPointF QKineticScrollerPrivate::realDpi(int screen) -{ - // The DPI value is hardcoded to 96 on Maemo5: - // https://projects.maemo.org/bugzilla/show_bug.cgi?id=152525 - // This value (260) is only correct for the N900 though, but - // there's no way to get the real DPI at run time. - return QPointF(260, 260); -} - -#endif diff --git a/scroller/qkineticscroller_p.h b/scroller/qkineticscroller_p.h deleted file mode 100644 index 0f5e030..0000000 --- a/scroller/qkineticscroller_p.h +++ /dev/null @@ -1,180 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include -#include -#if QT_VERSION < 0x040700 -# include -#else -# include -#endif - -QT_BEGIN_NAMESPACE - -class QEvent; -class QTimerEvent; - -class QKineticScrollerPrivate : public QObject -{ - Q_OBJECT - Q_DECLARE_PUBLIC(QKineticScroller) - -public: - QKineticScrollerPrivate(); - virtual ~QKineticScrollerPrivate(); - void init(); - - void sendEvent(QObject *o, QEvent *e); - - void setState(QKineticScroller::State s); - - bool pressWhileInactive(QKineticScroller::Input input, const QPointF &position, qint64 timestamp); - bool moveWhilePressed(QKineticScroller::Input input, const QPointF &position, qint64 timestamp); - bool releaseWhilePressed(QKineticScroller::Input input, const QPointF &position, qint64 timestamp); - bool moveWhileDragging(QKineticScroller::Input input, const QPointF &position, qint64 timestamp); - bool releaseWhileDragging(QKineticScroller::Input input, const QPointF &position, qint64 timestamp); - bool pressWhileScrolling(QKineticScroller::Input input, const QPointF &position, qint64 timestamp); - - void timerEvent(QTimerEvent *); - void timerEventWhileDragging(); - void timerEventWhileScrolling(); - - void handleDrag(const QPointF &position, qint64 timestamp); - void updateVelocity(const QPointF &deltaPixel, qint64 deltaTime); - - qreal decelerate(qreal v, qreal t); - QPointF calculateVelocity(qreal time); - void setContentPositionHelper(const QPointF &deltaPos); - - QPointF realDpi(int screen); - - - static const char *stateName(QKineticScroller::State state); - static const char *inputName(QKineticScroller::Input input); - - // metrics - - qreal dragVelocitySmoothingFactor; - qreal linearDecelerationFactor; - qreal exponentialDecelerationBase; - qreal overshootSpringConstantRoot; - QPointF overshootMaximumDistance; - qreal overshootDragResistanceFactor; - qreal dragStartDistance; - qreal dragStartDirectionErrorMargin; - qreal maximumVelocity; - qreal minimumVelocity; - qreal maximumNonAcceleratedVelocity; - qreal maximumClickThroughVelocity; - qreal axisLockThreshold; - qreal fastSwipeBaseVelocity; - qreal fastSwipeMinimumVelocity; - qreal fastSwipeMaximumTime; - int framesPerSecond; - - // widget info - QPointer receiver; // the object this scroller was registered for - - QPointer target; - QSizeF viewportSize; - QPointF maximumContentPosition; - QPointF contentPosition; - - // state - - bool enabled; - QKineticScroller::State state; - QKineticScroller::OvershootPolicy hOvershootPolicy; - QKineticScroller::OvershootPolicy vOvershootPolicy; - QPointF oldVelocity; - - QPointF pressPosition; - QPointF lastPosition; - qint64 pressTimestamp; - qint64 lastTimestamp; - - QPointF dragDistance; // the distance we should move during the next drag timer event - - QPointF scrollToPosition; - bool scrollToX; - bool scrollToY; - - QPointF overshootPosition; // the number of pixels we are overshooting (before overshootDragResistanceFactor) - bool overshootX; - bool overshootY; - - qreal pixelPerMeter; - -#if QT_VERSION < 0x040700 - QTime scrollRelativeTimer; - QTime scrollAbsoluteTimer; -#else - QElapsedTimer scrollRelativeTimer; - QElapsedTimer scrollAbsoluteTimer; -#endif - QPointF releaseVelocity; // the starting velocity of the scrolling state - QPointF overshootVelocity; // the starting velocity when going into overshoot - qreal overshootStartTimeX; - qreal overshootStartTimeY; - int timerId; - - bool firstScroll; - - void (*debugHook)(void *user, const QPointF &releaseVelocity, const QPointF &position, const QPointF &overshootPosition); - void *debugHookUser; - - QKineticScroller *q_ptr; -}; - -QT_END_NAMESPACE diff --git a/scroller/scroller.pro b/scroller/scroller.pro index 28b794b..cc11f24 100644 --- a/scroller/scroller.pro +++ b/scroller/scroller.pro @@ -9,10 +9,10 @@ DEPENDPATH += . INCLUDEPATH += . # Input -HEADERS += qkineticscroller.h qkineticscroller_p.h qflickgesture.h -SOURCES += qkineticscroller.cpp qflickgesture.cpp +HEADERS += qscroller.h qscroller_p.h qscrollerproperties.h qscrollerproperties_p.h qflickgesture.h +SOURCES += qscroller.cpp qscrollerproperties.cpp qflickgesture.cpp -macx:SOURCES += qkineticscroller_mac.mm -maemo5:SOURCES += qkineticscroller_maemo5.cpp +#macx:SOURCES += qkineticscroller_mac.mm +#maemo5:SOURCES += qkineticscroller_maemo5.cpp macx:LIBS += -framework Cocoa diff --git a/testapp/main.cpp b/testapp/main.cpp index 3dd4e1e..9ec8a70 100644 --- a/testapp/main.cpp +++ b/testapp/main.cpp @@ -15,7 +15,7 @@ # include #endif -#include "qscrollareakineticscroller.h" +// #include "qscrollareakineticscroller.h" #include #include "qwebviewkineticscroller.h" @@ -88,11 +88,11 @@ private slots: return; switch (page) { case 0: - m_settings->setKineticScroller(m_list_scroller); + m_settings->setKineticScroller(m_list->viewport(), m_list_scroller); m_plot->setKineticScroller(m_list_scroller); break; case 1: - m_settings->setKineticScroller(m_web_scroller); + m_settings->setKineticScroller(m_web, m_web_scroller); m_plot->setKineticScroller(m_web_scroller); break; default: @@ -140,6 +140,16 @@ private: return newScroller; } else if (QWebView *web = qobject_cast(w)) { web->grabGesture(gestureType); + + QKineticScroller prop; + prop. + QFlickGestureRecognizer::setProperties(web, prop); + + prop = QFlickGestureRecognizer::properties(web); + + QFlicker f(web); + f.ensureVisible(10, 10); + QKineticScroller *newScroller = new QKineticScroller(web); w->setProperty("kineticScroller", QVariant::fromValue(static_cast(newScroller)) ); return newScroller; diff --git a/testapp/settingswidget.cpp b/testapp/settingswidget.cpp index 30f1d90..f61f297 100644 --- a/testapp/settingswidget.cpp +++ b/testapp/settingswidget.cpp @@ -51,8 +51,11 @@ #include #include +#include + #include "settingswidget.h" #include "qkineticscroller.h" +#include "qflickgesture.h" struct MetricItem { @@ -69,7 +72,8 @@ class MetricItemUpdater : public QObject Q_OBJECT public: MetricItemUpdater(MetricItem *item) - : m_item(item), m_scroller(0) + : m_item(item) + , m_scroller(0) { if (m_item->min.type() == QVariant::PointF) { m_slider = new QSlider(Qt::Horizontal); @@ -277,7 +281,10 @@ public: }; SettingsWidget::SettingsWidget(bool smallscreen) - : QScrollArea(), m_scroller(0), m_smallscreen(smallscreen) + : QScrollArea() + , m_widget(0) + , m_scroller(0) + , m_smallscreen(smallscreen) { setWindowTitle(QLatin1String("Settings")); QWidget *view = new QWidget(); @@ -368,8 +375,9 @@ SettingsWidget::SettingsWidget(bool smallscreen) setWidgetResizable(true); } -void SettingsWidget::setKineticScroller(QKineticScroller *scroller) +void SettingsWidget::setKineticScroller(QWidget *widget, QKineticScroller *scroller) { + m_widget = widget; m_scroller = scroller; //setEnabled(m_scroller); @@ -380,8 +388,8 @@ void SettingsWidget::setKineticScroller(QKineticScroller *scroller) if (!m_scroller) return; - m_onoff->setChecked(m_scroller->isEnabled()); - m_dpi->setValue(m_scroller->dpi()); + //TODO m_onoff->setChecked(m_scroller->isEnabled()); + //TODO m_dpi->setValue(m_scroller->dpi()); m_hospolicy->setCurrentIndex(m_hospolicy->findData(m_scroller->horizontalOvershootPolicy())); m_vospolicy->setCurrentIndex(m_vospolicy->findData(m_scroller->verticalOvershootPolicy())); @@ -399,14 +407,18 @@ void SettingsWidget::setKineticScroller(QKineticScroller *scroller) void SettingsWidget::enabledChanged(bool on) { + /* TODO if (m_scroller) m_scroller->setEnabled(on); + */ } void SettingsWidget::dpiChanged(int dpi) { + /* TODO if (m_scroller) m_scroller->setDpi(dpi); + */ } void SettingsWidget::overshootPolicyChanged(int index) @@ -427,7 +439,11 @@ void SettingsWidget::scrollTo() return; if (!m_scroller) return; - m_scroller->scrollTo(QPointF(m_scrollx->value(), m_scrolly->value()), m_scrolltime->value()); + +qDebug() << "SettingsWidget::scrollTo" << m_scrollx->value(); + + QFlickGesture *flick = QFlickGestureRecognizer::getFlickGesture(m_widget); + flick->scrollTo(QPointF(m_scrollx->value(), m_scrolly->value()), m_scrolltime->value()); } #include "settingswidget.moc" diff --git a/testapp/settingswidget.h b/testapp/settingswidget.h index ec7a180..c0605e4 100644 --- a/testapp/settingswidget.h +++ b/testapp/settingswidget.h @@ -59,7 +59,7 @@ class SettingsWidget : public QScrollArea public: SettingsWidget(bool smallscreen = false); - void setKineticScroller(QKineticScroller *scroller); + void setKineticScroller(QWidget *widget, QKineticScroller *scroller); private slots: void enabledChanged(bool on); @@ -70,6 +70,7 @@ private slots: private: void addToGrid(QGridLayout *grid, QWidget *label, int widgetCount, ...); + QWidget *m_widget; QKineticScroller *m_scroller; QCheckBox *m_onoff; QSpinBox *m_dpi, *m_scrollx, *m_scrolly, *m_scrolltime; -- cgit v1.2.3