diff options
author | Martin Jones <martin.jones@nokia.com> | 2009-10-27 06:30:51 (GMT) |
---|---|---|
committer | Martin Jones <martin.jones@nokia.com> | 2009-10-27 06:30:51 (GMT) |
commit | 7a5fdc99bb3d7fde52428a5fbc4ae1f25de12b5c (patch) | |
tree | bbab318f1d04903680fdf8ed93194a150e889d4f /src/declarative/fx | |
parent | a8fb485e1f2a7c2d6de913a2f0b3809b95c47e36 (diff) | |
download | Qt-7a5fdc99bb3d7fde52428a5fbc4ae1f25de12b5c.zip Qt-7a5fdc99bb3d7fde52428a5fbc4ae1f25de12b5c.tar.gz Qt-7a5fdc99bb3d7fde52428a5fbc4ae1f25de12b5c.tar.bz2 |
Try to be a bit more clever with snapping.
Diffstat (limited to 'src/declarative/fx')
-rw-r--r-- | src/declarative/fx/qfxflickable.cpp | 26 | ||||
-rw-r--r-- | src/declarative/fx/qfxflickable.h | 4 | ||||
-rw-r--r-- | src/declarative/fx/qfxflickable_p.h | 5 | ||||
-rw-r--r-- | src/declarative/fx/qfxlistview.cpp | 69 |
4 files changed, 97 insertions, 7 deletions
diff --git a/src/declarative/fx/qfxflickable.cpp b/src/declarative/fx/qfxflickable.cpp index cbfe9f6..92e79dd 100644 --- a/src/declarative/fx/qfxflickable.cpp +++ b/src/declarative/fx/qfxflickable.cpp @@ -157,7 +157,7 @@ QFxFlickablePrivate::QFxFlickablePrivate() : viewport(new QFxItem), _moveX(viewport, &QFxItem::setX), _moveY(viewport, &QFxItem::setY) , vWidth(-1), vHeight(-1), overShoot(true), flicked(false), moving(false), stealMouse(false) , pressed(false), atXEnd(false), atXBeginning(true), atYEnd(false), atYBeginning(true) - , interactive(true), maxVelocity(5000), reportedVelocitySmoothing(100) + , interactive(true), deceleration(500), maxVelocity(5000), reportedVelocitySmoothing(100) , delayedPressEvent(0), delayedPressTarget(0), pressDelay(0) , horizontalVelocity(this), verticalVelocity(this), vTime(0), visibleArea(0) { @@ -202,7 +202,7 @@ void QFxFlickablePrivate::flickX(qreal velocity) v = maxVelocity; } timeline.reset(_moveX); - timeline.accel(_moveX, v, 500, maxDistance); + timeline.accel(_moveX, v, deceleration, maxDistance); timeline.execute(fixupXEvent); if (!flicked) { flicked = true; @@ -238,7 +238,7 @@ void QFxFlickablePrivate::flickY(qreal velocity) v = maxVelocity; } timeline.reset(_moveY); - timeline.accel(_moveY, v, 500, maxDistance); + timeline.accel(_moveY, v, deceleration, maxDistance); timeline.execute(fixupYEvent); if (!flicked) { flicked = true; @@ -1131,7 +1131,7 @@ bool QFxFlickable::sceneEventFilter(QGraphicsItem *i, QEvent *e) } /*! - \qmlproperty int Flickable::maximumFlickVelocity + \qmlproperty real Flickable::maximumFlickVelocity This property holds the maximum velocity that the user can flick the view in pixels/second. The default is 5000 pixels/s @@ -1150,6 +1150,24 @@ void QFxFlickable::setMaximumFlickVelocity(qreal v) d->maxVelocity = v; } +/*! + \qmlproperty real Flickable::maximumFlickVelocity + This property holds the rate at which a flick will decelerate. + + The default is 500. +*/ +qreal QFxFlickable::flickDeceleration() const +{ + Q_D(const QFxFlickable); + return d->deceleration; +} + +void QFxFlickable::setFlickDeceleration(qreal deceleration) +{ + Q_D(QFxFlickable); + d->deceleration = deceleration; +} + bool QFxFlickable::isFlicking() const { Q_D(const QFxFlickable); diff --git a/src/declarative/fx/qfxflickable.h b/src/declarative/fx/qfxflickable.h index aaf4e0f..4c80e8f 100644 --- a/src/declarative/fx/qfxflickable.h +++ b/src/declarative/fx/qfxflickable.h @@ -67,6 +67,7 @@ class Q_DECLARATIVE_EXPORT QFxFlickable : public QFxItem Q_PROPERTY(bool overShoot READ overShoot WRITE setOverShoot) Q_PROPERTY(qreal maximumFlickVelocity READ maximumFlickVelocity WRITE setMaximumFlickVelocity) + Q_PROPERTY(qreal flickDeceleration READ flickDeceleration WRITE setFlickDeceleration) Q_PROPERTY(bool moving READ isMoving NOTIFY movingChanged) Q_PROPERTY(bool flicking READ isFlicking NOTIFY flickingChanged) @@ -118,6 +119,9 @@ public: qreal maximumFlickVelocity() const; void setMaximumFlickVelocity(qreal); + qreal flickDeceleration() const; + void setFlickDeceleration(qreal); + bool isInteractive() const; void setInteractive(bool); diff --git a/src/declarative/fx/qfxflickable_p.h b/src/declarative/fx/qfxflickable_p.h index 7224f21..07d66b8 100644 --- a/src/declarative/fx/qfxflickable_p.h +++ b/src/declarative/fx/qfxflickable_p.h @@ -70,8 +70,8 @@ class QFxFlickablePrivate : public QFxItemPrivate public: QFxFlickablePrivate(); void init(); - void flickX(qreal velocity); - void flickY(qreal velocity); + virtual void flickX(qreal velocity); + virtual void flickY(qreal velocity); virtual void fixupX(); virtual void fixupY(); void updateBeginningEnd(); @@ -106,6 +106,7 @@ public: QTime pressTime; QmlTimeLineEvent fixupXEvent; QmlTimeLineEvent fixupYEvent; + qreal deceleration; qreal maxVelocity; QTime velocityTime; QPointF lastFlickablePosition; diff --git a/src/declarative/fx/qfxlistview.cpp b/src/declarative/fx/qfxlistview.cpp index 28d2bb2..ca3132f 100644 --- a/src/declarative/fx/qfxlistview.cpp +++ b/src/declarative/fx/qfxlistview.cpp @@ -287,6 +287,11 @@ public: return index; } + //XXX Rough. Only works for fixed size items. + qreal snapPosAt(qreal pos) { + return qRound((pos - startPosition()) / averageSize) * averageSize + startPosition(); + } + int lastVisibleIndex() const { int lastIndex = -1; for (int i = visibleItems.count()-1; i >= 0; --i) { @@ -365,6 +370,8 @@ public: void fixupPosition(); virtual void fixupY(); virtual void fixupX(); + virtual void flickX(qreal velocity); + virtual void flickY(qreal velocity); QFxVisualModel *model; QVariant modelVariant; @@ -750,7 +757,6 @@ void QFxListViewPrivate::updateCurrent(int modelIndex) updateHighlight(); return; } - FxListItem *oldCurrentItem = currentItem; currentIndex = modelIndex; currentItem = createItem(modelIndex); @@ -822,6 +828,67 @@ void QFxListViewPrivate::fixupX() } } +void QFxListViewPrivate::flickX(qreal velocity) +{ + Q_Q(QFxListView); + + if (!haveHighlightRange || highlightRange != QFxListView::StrictlyEnforceRange) + QFxFlickablePrivate::flickX(velocity); + + qreal maxDistance = -1; + // -ve velocity means list is moving up + if (velocity > 0) { + if (_moveX.value() < q->minXExtent()) + maxDistance = qAbs(q->minXExtent() -_moveX.value() + (overShoot?30:0)); + flickTargetX = q->minXExtent(); + } else { + if (_moveX.value() > q->maxXExtent()) + maxDistance = qAbs(q->maxXExtent() - _moveX.value()) + (overShoot?30:0); + flickTargetX = q->maxXExtent(); + } + if (maxDistance > 0) { + qreal v = velocity; + if (maxVelocity != -1 && maxVelocity < qAbs(v)) { + if (v < 0) + v = -maxVelocity; + else + v = maxVelocity; + } + qreal accel = deceleration; + qreal maxAccel = (v * v) / (2.0f * maxDistance); + if (maxAccel < accel) { + // If we are not flicking to the end then attempt to stop exactly on an item boundary + qreal dist = (v * v) / accel / 2.0; + if (v > 0) + dist = -dist; + dist = -_moveX.value() - snapPosAt(-_moveX.value() + dist + highlightRangeStart); + if (v < 0 && dist >= 0 || v > 0 && dist <= 0) { + timeline.reset(_moveX); + fixupX(); + return; + } + accel = (v * v) / (2.0f * qAbs(dist)); + } + timeline.reset(_moveX); + timeline.accel(_moveX, v, accel, maxDistance); + timeline.execute(fixupXEvent); + if (!flicked) { + flicked = true; + emit q->flickingChanged(); + emit q->flickStarted(); + } + } else { + timeline.reset(_moveX); + fixupX(); + } +} + +void QFxListViewPrivate::flickY(qreal velocity) +{ + if (!haveHighlightRange || highlightRange != QFxListView::StrictlyEnforceRange) + QFxFlickablePrivate::flickY(velocity); +} + //---------------------------------------------------------------------------- /*! |