diff options
author | Martin Jones <martin.jones@nokia.com> | 2010-02-26 06:21:39 (GMT) |
---|---|---|
committer | Martin Jones <martin.jones@nokia.com> | 2010-02-26 06:21:39 (GMT) |
commit | dfda902012adee3869a1619ba96d9c0b1bf339f2 (patch) | |
tree | a2dff43133984ec39a55196aea031ee750562b21 /src/declarative/graphicsitems | |
parent | 91b4b6ce6684503b117817fc72b30812ab0e7722 (diff) | |
download | Qt-dfda902012adee3869a1619ba96d9c0b1bf339f2.zip Qt-dfda902012adee3869a1619ba96d9c0b1bf339f2.tar.gz Qt-dfda902012adee3869a1619ba96d9c0b1bf339f2.tar.bz2 |
Make Flickable overshoot behavior nicer.
Diffstat (limited to 'src/declarative/graphicsitems')
3 files changed, 58 insertions, 27 deletions
diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index 333ad60..3f4a9ce 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -128,7 +128,7 @@ QDeclarativeFlickablePrivate::QDeclarativeFlickablePrivate() , vWidth(-1), vHeight(-1), overShoot(true), flicked(false), moving(false), stealMouse(false) , pressed(false), atXEnd(false), atXBeginning(true), atYEnd(false), atYBeginning(true) , interactive(true), deceleration(500), maxVelocity(2000), reportedVelocitySmoothing(100) - , delayedPressEvent(0), delayedPressTarget(0), pressDelay(0), fixupDuration(200) + , delayedPressEvent(0), delayedPressTarget(0), pressDelay(0), fixupDuration(600) , horizontalVelocity(this), verticalVelocity(this), vTime(0), visibleArea(0) , flickDirection(QDeclarativeFlickable::AutoFlickDirection) { @@ -148,6 +148,23 @@ void QDeclarativeFlickablePrivate::init() QObject::connect(q, SIGNAL(widthChanged()), q, SLOT(widthChange())); } +/* + Returns the amount to overshoot by given a velocity. + Will be roughly in range 0 - size/4 +*/ +qreal QDeclarativeFlickablePrivate::overShootDistance(qreal velocity, qreal size) +{ + Q_Q(QDeclarativeFlickable); + if (maxVelocity <= 0) + return 0.0; + + velocity = qAbs(velocity); + if (velocity > maxVelocity) + velocity = maxVelocity; + qreal dist = size / 4 * velocity / maxVelocity; + return dist; +} + void QDeclarativeFlickablePrivate::flickX(qreal velocity) { Q_Q(QDeclarativeFlickable); @@ -156,12 +173,12 @@ void QDeclarativeFlickablePrivate::flickX(qreal velocity) if (velocity > 0) { const qreal minX = q->minXExtent(); if (_moveX.value() < minX) - maxDistance = qAbs(minX -_moveX.value() + (overShoot?30:0)); + maxDistance = qAbs(minX -_moveX.value() + (overShoot?overShootDistance(velocity,q->width()):0)); flickTargetX = minX; } else { const qreal maxX = q->maxXExtent(); if (_moveX.value() > maxX) - maxDistance = qAbs(maxX - _moveX.value()) + (overShoot?30:0); + maxDistance = qAbs(maxX - _moveX.value()) + (overShoot?overShootDistance(velocity,q->width()):0); flickTargetX = maxX; } if (maxDistance > 0) { @@ -194,12 +211,12 @@ void QDeclarativeFlickablePrivate::flickY(qreal velocity) if (velocity > 0) { const qreal minY = q->minYExtent(); if (_moveY.value() < minY) - maxDistance = qAbs(minY -_moveY.value() + (overShoot?30:0)); + maxDistance = qAbs(minY -_moveY.value() + (overShoot?overShootDistance(velocity,q->height()):0)); flickTargetY = minY; } else { const qreal maxY = q->maxYExtent(); if (_moveY.value() > maxY) - maxDistance = qAbs(maxY - _moveY.value()) + (overShoot?30:0); + maxDistance = qAbs(maxY - _moveY.value()) + (overShoot?overShootDistance(velocity,q->height()):0); flickTargetY = maxY; } if (maxDistance > 0) { @@ -233,18 +250,24 @@ void QDeclarativeFlickablePrivate::fixupX() if (_moveX.value() > q->minXExtent() || (q->maxXExtent() > q->minXExtent())) { timeline.reset(_moveX); if (_moveX.value() != q->minXExtent()) { - if (fixupDuration) - timeline.move(_moveX, q->minXExtent(), QEasingCurve(QEasingCurve::InOutQuad), fixupDuration); - else - _moveY.setValue(q->minYExtent()); + if (fixupDuration) { + qreal dist = q->minXExtent() - _moveX; + timeline.move(_moveX, q->minXExtent() - dist/2, QEasingCurve(QEasingCurve::InQuad), fixupDuration/4); + timeline.move(_moveX, q->minXExtent(), QEasingCurve(QEasingCurve::OutQuint), 3*fixupDuration/4); + } else { + _moveX.setValue(q->minXExtent()); + } } //emit flickingChanged(); } else if (_moveX.value() < q->maxXExtent()) { timeline.reset(_moveX); - if (fixupDuration) - timeline.move(_moveX, q->maxXExtent(), QEasingCurve(QEasingCurve::InOutQuad), fixupDuration); - else - _moveY.setValue(q->maxYExtent()); + if (fixupDuration) { + qreal dist = q->maxXExtent() - _moveX; + timeline.move(_moveX, q->maxXExtent() - dist/2, QEasingCurve(QEasingCurve::InQuad), fixupDuration/4); + timeline.move(_moveX, q->maxXExtent(), QEasingCurve(QEasingCurve::OutQuint), 3*fixupDuration/4); + } else { + _moveX.setValue(q->maxXExtent()); + } //emit flickingChanged(); } else { flicked = false; @@ -272,18 +295,24 @@ void QDeclarativeFlickablePrivate::fixupY() if (_moveY.value() > q->minYExtent() || (q->maxYExtent() > q->minYExtent())) { timeline.reset(_moveY); if (_moveY.value() != q->minYExtent()) { - if (fixupDuration) - timeline.move(_moveY, q->minYExtent(), QEasingCurve(QEasingCurve::InOutQuad), fixupDuration); - else + if (fixupDuration) { + qreal dist = q->minYExtent() - _moveY; + timeline.move(_moveY, q->minYExtent() - dist/2, QEasingCurve(QEasingCurve::InQuad), fixupDuration/4); + timeline.move(_moveY, q->minYExtent(), QEasingCurve(QEasingCurve::OutQuint), 3*fixupDuration/4); + } else { _moveY.setValue(q->minYExtent()); + } } //emit flickingChanged(); } else if (_moveY.value() < q->maxYExtent()) { timeline.reset(_moveY); - if (fixupDuration) - timeline.move(_moveY, q->maxYExtent(), QEasingCurve(QEasingCurve::InOutQuad), fixupDuration); - else + if (fixupDuration) { + qreal dist = q->maxYExtent() - _moveY; + timeline.move(_moveY, q->maxYExtent() - dist/2, QEasingCurve(QEasingCurve::InQuad), fixupDuration/4); + timeline.move(_moveY, q->maxYExtent(), QEasingCurve(QEasingCurve::OutQuint), 3*fixupDuration/4); + } else { _moveY.setValue(q->maxYExtent()); + } //emit flickingChanged(); } else { flicked = false; diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h index dc3a8a2..1ff4f92 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h @@ -85,6 +85,8 @@ public: void setRoundedViewportX(qreal x); void setRoundedViewportY(qreal y); + qreal overShootDistance(qreal velocity, qreal size); + public: QDeclarativeItem *viewport; QDeclarativeTimeLineValueProxy<QDeclarativeFlickablePrivate> _moveX; diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp index 6421018..c496c97 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview.cpp +++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp @@ -1073,7 +1073,7 @@ void QDeclarativeListViewPrivate::fixupY() qreal pos = currentItem->position() - highlightRangeStart; timeline.reset(_moveY); if (fixupDuration) - timeline.move(_moveY, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration); + timeline.move(_moveY, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2); else _moveY.setValue(-pos); vTime = timeline.time(); @@ -1085,7 +1085,7 @@ void QDeclarativeListViewPrivate::fixupY() if (dist > 0) { timeline.reset(_moveY); if (fixupDuration) - timeline.move(_moveY, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration); + timeline.move(_moveY, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2); else _moveY.setValue(-pos); vTime = timeline.time(); @@ -1155,7 +1155,7 @@ void QDeclarativeListViewPrivate::flickX(qreal velocity) if (FxListItem *item = firstVisibleItem()) maxDistance = qAbs(item->position() + _moveX.value()); } else if (_moveX.value() < minX) { - maxDistance = qAbs(minX -_moveX.value() + (overShoot?30:0)); + maxDistance = qAbs(minX -_moveX.value() + (overShoot?overShootDistance(velocity, q->width()):0)); } if (snapMode != QDeclarativeListView::SnapToItem && highlightRange != QDeclarativeListView::StrictlyEnforceRange) flickTargetX = minX; @@ -1164,7 +1164,7 @@ void QDeclarativeListViewPrivate::flickX(qreal velocity) if (FxListItem *item = nextVisibleItem()) maxDistance = qAbs(item->position() + _moveX.value()); } else if (_moveX.value() > maxX) { - maxDistance = qAbs(maxX - _moveX.value()) + (overShoot?30:0); + maxDistance = qAbs(maxX - _moveX.value()) + (overShoot?overShootDistance(velocity, q->width()):0); } if (snapMode != QDeclarativeListView::SnapToItem && highlightRange != QDeclarativeListView::StrictlyEnforceRange) flickTargetX = maxX; @@ -1196,7 +1196,7 @@ void QDeclarativeListViewPrivate::flickX(qreal velocity) overshootDist = 0.0; } else { flickTargetX = velocity > 0 ? minX : maxX; - overshootDist = overShoot ? 30 : 0; + overshootDist = overShoot ? overShootDistance(v, q->width()) : 0; } timeline.reset(_moveX); timeline.accel(_moveX, v, accel, maxDistance + overshootDist); @@ -1253,7 +1253,7 @@ void QDeclarativeListViewPrivate::flickY(qreal velocity) if (FxListItem *item = firstVisibleItem()) maxDistance = qAbs(item->position() + _moveY.value()); } else if (_moveY.value() < minY) { - maxDistance = qAbs(minY -_moveY.value() + (overShoot?30:0)); + maxDistance = qAbs(minY -_moveY.value() + (overShoot?overShootDistance(velocity, q->height()):0)); } if (snapMode != QDeclarativeListView::SnapToItem && highlightRange != QDeclarativeListView::StrictlyEnforceRange) flickTargetY = minY; @@ -1262,7 +1262,7 @@ void QDeclarativeListViewPrivate::flickY(qreal velocity) if (FxListItem *item = nextVisibleItem()) maxDistance = qAbs(item->position() + _moveY.value()); } else if (_moveY.value() > maxY) { - maxDistance = qAbs(maxY - _moveY.value()) + (overShoot?30:0); + maxDistance = qAbs(maxY - _moveY.value()) + (overShoot?overShootDistance(velocity, q->height()):0); } if (snapMode != QDeclarativeListView::SnapToItem && highlightRange != QDeclarativeListView::StrictlyEnforceRange) flickTargetY = maxY; @@ -1294,7 +1294,7 @@ void QDeclarativeListViewPrivate::flickY(qreal velocity) overshootDist = 0.0; } else { flickTargetY = velocity > 0 ? minY : maxY; - overshootDist = overShoot ? 30 : 0; + overshootDist = overShoot ? overShootDistance(v, q->height()) : 0; } timeline.reset(_moveY); timeline.accel(_moveY, v, accel, maxDistance + overshootDist); |