summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Engels <ralf.engels@nokia.com>2010-04-09 17:30:31 +0200
committerRalf Engels <ralf.engels@nokia.com>2010-04-09 17:30:31 +0200
commit88e018356973866017db25cbc16700fd3da59a99 (patch)
tree62e9b27177848f215bd492fc126537c5c6844c28
parentf557f9a5099a07dfa599e394c779558a7e1fb167 (diff)
Fiddling around with the kinetic scroller
-rw-r--r--main.cpp4
-rw-r--r--qkineticscroller.cpp59
-rw-r--r--qkineticscroller.h2
3 files changed, 52 insertions, 13 deletions
diff --git a/main.cpp b/main.cpp
index f7febd6..128d69b 100644
--- a/main.cpp
+++ b/main.cpp
@@ -14,5 +14,7 @@ int main(int argc, char **argv)
s->setWidget(lw);
lw->show();
+ s->scrollTo(QPointF(80,800));
+
return a.exec();
-} \ No newline at end of file
+}
diff --git a/qkineticscroller.cpp b/qkineticscroller.cpp
index 04b0b83..2197ec8 100644
--- a/qkineticscroller.cpp
+++ b/qkineticscroller.cpp
@@ -190,7 +190,7 @@ void QKineticScroller::resetScrollMetrics()
metrics.insert(FramesPerSecond, qreal(20));
#else
metrics.insert(DragVelocitySmoothingFactor, qreal(0.02));
- metrics.insert(ExponentialDecelerationBase, qreal(0));
+ metrics.insert(ExponentialDecelerationBase, qreal(1));
metrics.insert(LinearDecelerationFactor, qreal(0.38));
metrics.insert(OvershootSpringConstant, qreal(15.0));
metrics.insert(OvershootDragResistanceFactor, qreal(0.5));
@@ -712,12 +712,10 @@ void QKineticScrollerPrivate::timerEventWhileScrolling(qint64 time_ms)
if (overshootDistance.x() && ((overshootDistance.x() > 0) != (newOvershootDistance.x() > 0))) {
overshootDistance.setX(0);
velocity.setX(0);
- scrollToX = false;
}
if (overshootDistance.y() && ((overshootDistance.y() > 0) != (newOvershootDistance.y() > 0))) {
overshootDistance.setY(0);
velocity.setY(0);
- scrollToY = false;
}
}
@@ -739,11 +737,14 @@ void QKineticScrollerPrivate::timerEventWhileScrolling(qint64 time_ms)
velocity.setX(qBound(-overshootMaximumVelocity, velocity.x(), overshootMaximumVelocity));
} else if (scrollToX) {
- if (qAbs(velocity.x()) >= qreal(3.0 / 1000 /* 3mm/s */))
+ if (qAbs(velocity.x()) * exponentialDecelerationPerFrame > linearDecelerationPerFrame + qreal(30.0 / 1000) )/* 30 px/s */
velocity.setX(decelerate(velocity.x(), exponentialDecelerationPerFrame, linearDecelerationPerFrame));
+ else
+ velocity.setX((velocity.x()<0 ? -1.0 : 1.0) * qreal(30.0 / 1000));
// - target reached?
qreal dist = scrollToPosition.x() - q->contentPosition().x();
+qDebug() << "scroll to x" << scrollToPosition.x() << "v:"<< velocity.x() << " dist " << dist;
if ((velocity.x() > 0.0 && dist <= 0.0) || (velocity.x() < 0.0 && dist >= 0.0)) {
velocity.setX(0.0);
scrollToX = false;
@@ -759,11 +760,14 @@ void QKineticScrollerPrivate::timerEventWhileScrolling(qint64 time_ms)
velocity.setY(qBound(-overshootMaximumVelocity, velocity.y(), overshootMaximumVelocity));
} else if (scrollToY) {
- if (qAbs(velocity.y()) >= qreal(3.0 / 1000 /* 3mm/s */))
+ if (qAbs(velocity.y()) * exponentialDecelerationPerFrame > linearDecelerationPerFrame + qreal(30.0 / 1000) )/* 30 px/s */
velocity.setY(decelerate(velocity.y(), exponentialDecelerationPerFrame, linearDecelerationPerFrame));
+ else
+ velocity.setY((velocity.y()<0 ? -1.0 : 1.0) * qreal(30.0 / 1000));
// - target reached?
qreal dist = scrollToPosition.y() - q->contentPosition().y();
+qDebug() << "scroll to y" << scrollToPosition.y() << "v:"<< velocity.y() << " dist " << dist;
if ((velocity.y() > 0.0 && dist <= 0.0) || (velocity.y() < 0.0 && dist >= 0.0)) {
velocity.setY(0.0);
scrollToY = false;
@@ -821,6 +825,8 @@ void QKineticScrollerPrivate::setState(QKineticScroller::State newstate)
killTimer(timerId);
timerId = 0;
}
+ scrollToX = false;
+ scrollToY = false;
velocity = QPointF(0, 0);
break;
@@ -837,11 +843,11 @@ void QKineticScrollerPrivate::setState(QKineticScroller::State newstate)
break;
case QKineticScroller::StateScrolling:
- if (state == QKineticScroller::StatePressed) {
+ // if (state == QKineticScroller::StatePressed) {
if (!timerId) {
timerId = startTimer(1000 / framesPerSecond);
}
- }
+ // }
scrollTimer.start();
break;
}
@@ -867,20 +873,45 @@ void QKineticScroller::scrollTo(const QPointF &pos, int scrollTime)
{
Q_D(QKineticScroller);
- if ((pos == contentPosition()) || (d->state != QKineticScroller::StateInactive)) {
+ qreal time = qreal(scrollTime) / 1000;
+
+ if ((pos == contentPosition()) ||
+ (d->state == QKineticScroller::StatePressed) ||
+ (d->state == QKineticScroller::StateDragging)) {
return;
}
- // v(t) = vstart * exponentialDecelerationBase ^ t + linearDecelerationFactor * t
+ // 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;
+
+ qKSDebug() << "QAbstractKineticScroller::scrollTo v, dis(" << vMin << ", " << distMin;
+
+ QPointF v = QPointF((pos.x()-contentPosition().x()) / distMin * vMin,
+ (pos.y()-contentPosition().y()) / distMin * vMin);
+
+ qKSDebug() << "QAbstractKineticScroller::scrollTo(" << pos << ", " << v;
+
+ // v(t) = vstart * exponentialDecelerationBase ^ t - linearDecelerationFactor * t
// pos(t) = integrate(v(t) * dt)
- // pos(t) = vstart * eDB ^ t / ln(eDB) + lDF / 2 * t ^ 2
+ // pos(t) = vstart * eDB ^ t / ln(eDB) - lDF / (2 * t ^ 2)
//
// pos(scrollTime) = pos - contentsPos()
// vstart = (lDF / 2 * scrollTime ^ 2 - (pos - contentPos())) * ln(eDB) / eDB ^ scrollTime
+/*
- QPointF v = QPointF(1, 1) * d->linearDecelerationFactor / 2 * scrollTime * scrollTime - (pos - contentPosition()) *
+ QPointF v = QPointF(-1, -1) * d->linearDecelerationFactor / (qreal(2) * qreal(scrollTime) * qreal(scrollTime)) - (pos - contentPosition()) *
qLn(d->exponentialDecelerationBase) / qPow(d->exponentialDecelerationBase, scrollTime);
+ qKSDebug() << "QAbstractKineticScroller::scrollTo(" << pos << ", " << v;
+ qKSDebug() << "QAbstr " << d->linearDecelerationFactor <<" 1: "<< (qreal(2) * qreal(scrollTime) * qreal(scrollTime)) << " 2: " << (pos - contentPosition()) << " 3: " <<
+ qLn(d->exponentialDecelerationBase) << "4: " << qPow(d->exponentialDecelerationBase, scrollTime);
+
+ v = QPointF(0.01, 0.01);
+*/
// start the scrolling
d->scrollToPosition = pos;
d->scrollToX = true;
@@ -941,6 +972,12 @@ void QKineticScrollerPrivate::setContentPositionHelper(const QPointF &pos)
clampedPos.setX(qBound(qreal(0), pos.x(), maxPos.x()));
clampedPos.setY(qBound(qreal(0), pos.y(), maxPos.y()));
+ // -- stop scroll to if hitting boundary
+ if (clampedPos.x() != pos.x())
+ scrollToX = false;
+ if (clampedPos.y() != pos.y())
+ scrollToY = false;
+
bool alwaysOvershoot = (overshootPolicy == QKineticScroller::OvershootAlwaysOn);
qreal overshootX = (maxPos.x() || alwaysOvershoot) ? pos.x() - clampedPos.x() : 0;
qreal overshootY = (maxPos.y() || alwaysOvershoot) ? pos.y() - clampedPos.y() : 0;
diff --git a/qkineticscroller.h b/qkineticscroller.h
index 3b31b88..a574891 100644
--- a/qkineticscroller.h
+++ b/qkineticscroller.h
@@ -88,7 +88,7 @@ public:
{
DragVelocitySmoothingFactor, // qreal [0..1/s] (complex calculation involving time) v = v_new* DASF + v_old * (1-DASF)
- LinearDecelerationFactor, // qreal [0..1]
+ LinearDecelerationFactor, // qreal [m/s^2]
ExponentialDecelerationBase, // qreal [0..1]
OvershootSpringConstant, // qreal [0..1]
OvershootDragResistanceFactor, // qreal [0..1]