diff options
author | Ralf Engels <ralf.engels@nokia.com> | 2010-04-01 17:19:26 +0200 |
---|---|---|
committer | Ralf Engels <ralf.engels@nokia.com> | 2010-04-01 17:19:26 +0200 |
commit | f5cd7a76c3b73616afbd6d79bf5eff522ceb24c5 (patch) | |
tree | 1b52367497cf68b3acde85b1e8c6977e089c8f25 | |
parent | 8eac27d4c572d1f23ad067ed8fa398488e24733b (diff) |
Debugging
-rw-r--r-- | qkineticscroller.cpp | 81 | ||||
-rw-r--r-- | qkineticscroller.h | 2 | ||||
-rw-r--r-- | qscrollareakineticscroller.cpp | 27 |
3 files changed, 77 insertions, 33 deletions
diff --git a/qkineticscroller.cpp b/qkineticscroller.cpp index ec46f08..005abb8 100644 --- a/qkineticscroller.cpp +++ b/qkineticscroller.cpp @@ -169,10 +169,10 @@ void QKineticScroller::resetScrollMetrics() static QMap<ScrollMetric, QVariant> metrics; #ifdef Q_WS_MAEMO_5 - metrics.insert(DragVelocitySmoothingFactor, qreal(0.85)); + metrics.insert(DragVelocitySmoothingFactor, qreal(0.15)); metrics.insert(FrictionCoefficent, qreal(0.85)); metrics.insert(OvershootSpringConstant, qreal(0.1)); - metrics.insert(OvershootMaximumDistance, qreal(150)); + metrics.insert(OvershootMaximumDistance, QPointF(qreal(150), qreal(150))); metrics.insert(OvershootMaximumVelocity, qreal(2600)); metrics.insert(DragStartDistance, qreal(25)); metrics.insert(DragStartDirectionErrorMargin, qreal(10)); @@ -186,15 +186,16 @@ void QKineticScroller::resetScrollMetrics() metrics.insert(FastSwipeMaximumTime, qreal(0.125)); metrics.insert(FramesPerSecond, qreal(20)); #else - metrics.insert(DragVelocitySmoothingFactor, qreal(0.85)); - metrics.insert(FrictionCoefficent, qreal(0.95)); - metrics.insert(OvershootSpringConstant, qreal(0.1)); - metrics.insert(OvershootMaximumDistance, qreal(14.25 / 1000)); + metrics.insert(DragVelocitySmoothingFactor, qreal(0.02)); + metrics.insert(FrictionCoefficent, qreal(0.05)); + metrics.insert(OvershootSpringConstant, qreal(2.0)); + metrics.insert(OvershootMaximumDistance, QPointF(qreal(14.25 / 1000), qreal(14.25 / 1000))); metrics.insert(OvershootMaximumVelocity, qreal(247.0 / 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(19.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)); @@ -281,6 +282,8 @@ bool QKineticScroller::handleInput(Input input, const QPointF &position, qint64 { Q_D(QKineticScroller); + +qKSDebug() << __PRETTY_FUNCTION__ << input << "pos: " << position << "timestamp: " << timestamp; struct statechange { State state; Input input; @@ -441,13 +444,18 @@ void QKineticScrollerPrivate::updateVelocity(const QPointF &deltaPixelRaw, qint6 if (((deltaPixelRaw / qreal(deltaTime)).manhattanLength() / pixelPerMeter * 1000) > qreal(2.5)) deltaPixel = deltaPixelRaw * qreal(2.5) * pixelPerMeter / 1000 / (deltaPixelRaw / qreal(deltaTime)).manhattanLength(); - QPointF newv = -deltaPixel / qreal(deltaTime) * 1000 / pixelPerMeter; - newv = newv * dragVelocitySmoothingFactor + velocity * (qreal(1) - dragVelocitySmoothingFactor); + qreal inversSmoothingFactor = ((qreal(1) - dragVelocitySmoothingFactor) * qreal(deltaTime) / qreal(1000)); + QPointF newv = -deltaPixel / qreal(deltaTime) * qreal(1000) / pixelPerMeter; + newv = newv * (qreal(1) - inversSmoothingFactor) + velocity * inversSmoothingFactor; + + // newv = newv * dragVelocitySmoothingFactor + velocity * (qreal(1) - dragVelocitySmoothingFactor); if (deltaPixel.x()) velocity.setX(qBound(-maximumVelocity, newv.x(), maximumVelocity)); if (deltaPixel.y()) velocity.setY(qBound(-maximumVelocity, newv.y(), maximumVelocity)); + + qKSDebug() << "resulting new velocity:" << velocity; } @@ -549,7 +557,10 @@ bool QKineticScrollerPrivate::pressWhileInactive(QKineticScroller::Input, const bool QKineticScrollerPrivate::releaseWhilePressed(QKineticScroller::Input, const QPointF &, qint64) { - setState(QKineticScroller::StateInactive); + if (!overshootDistance.isNull()) + setState(QKineticScroller::StateScrolling); + else + setState(QKineticScroller::StateInactive); return false; } @@ -608,7 +619,7 @@ void QKineticScrollerPrivate::timerEventWhileDragging(qint64) Q_Q(QKineticScroller); if (!dragDistance.isNull()) { - setContentPositionHelper(q->contentPosition() - overshootDistance - dragDistance); + setContentPositionHelper(q->contentPosition() + overshootDistance - dragDistance); dragDistance = QPointF(0, 0); } } @@ -654,7 +665,11 @@ bool QKineticScrollerPrivate::releaseWhileDragging(QKineticScroller::Input, cons } - if (!overshootDistance.isNull() || velocity >= minimumVelocity) + qKSDebug() << "release While dragging, velocity: "<<velocity<<"minimum velocity"<<minimumVelocity; + if (!overshootDistance.isNull()) { + velocity = QPointF(0, 0); + setState(QKineticScroller::StateScrolling); + } else if (velocity >= minimumVelocity) setState(QKineticScroller::StateScrolling); else setState(QKineticScroller::StateInactive); @@ -671,6 +686,8 @@ void QKineticScrollerPrivate::timerEventWhileScrolling(qint64 time) // calculate the new overshoot distance (convert from [m/s] to [pixel/frame] QPointF newOvershootDistance = overshootDistance + velocity * qreal(time) / 1000 * pixelPerMeter; + qKSDebug() << "Overshooting, old: "<<overshootDistance<<"new:"<<newOvershootDistance; + // -- check if we going back. Then stop if (overshootDistance.x() && ((overshootDistance.x() > 0) != (newOvershootDistance.x() > 0))) { overshootDistance.setX(0); @@ -685,9 +702,11 @@ void QKineticScrollerPrivate::timerEventWhileScrolling(qint64 time) } // -- move (convert from [m/s] to [pix/frame] - setContentPositionHelper(q->contentPosition() - overshootDistance + velocity * qreal(time) / 1000 * pixelPerMeter); + setContentPositionHelper(q->contentPosition() + overshootDistance + velocity * qreal(time) / 1000 * pixelPerMeter); + // --- (de)accelerate overshooting axis using spring constant or friction + // actually we would need to calculate a root and not just divide qreal forcePerFrame = overshootSpringConstant * qreal(time) / 1000; qreal frictionPerFrame = (qreal(1) - ((qreal(1) - frictionCoefficent) * qreal(time) / 1000)); @@ -695,7 +714,7 @@ void QKineticScrollerPrivate::timerEventWhileScrolling(qint64 time) // -- x coordinate if (overshootDistance.x()) { - velocity.rx() += forcePerFrame * overshootDistance.x() / pixelPerMeter; + velocity.rx() -= forcePerFrame * overshootDistance.x() / pixelPerMeter; velocity.setX(qBound(-overshootMaximumVelocity, velocity.x(), overshootMaximumVelocity)); } else if (scrollToX) { @@ -715,7 +734,7 @@ void QKineticScrollerPrivate::timerEventWhileScrolling(qint64 time) // -- y coordinate if (overshootDistance.y()) { - velocity.ry() += forcePerFrame * overshootDistance.y() / pixelPerMeter; + velocity.ry() -= forcePerFrame * overshootDistance.y() / pixelPerMeter; velocity.setY(qBound(-overshootMaximumVelocity, velocity.y(), overshootMaximumVelocity)); } else if (scrollToY) { @@ -752,7 +771,7 @@ void QKineticScrollerPrivate::setState(QKineticScroller::State newstate) if (state == newstate) return; - qWarning() << "Switiching to state " << stateName(newstate); + qWarning() << "Switching to state " << stateName(newstate); switch (newstate) { case QKineticScroller::StateInactive: @@ -768,6 +787,10 @@ void QKineticScrollerPrivate::setState(QKineticScroller::State newstate) break; case QKineticScroller::StatePressed: + if (timerId) { + killTimer(timerId); + timerId = 0; + } velocity = QPointF(0, 0); break; @@ -784,6 +807,11 @@ void QKineticScrollerPrivate::setState(QKineticScroller::State newstate) break; case QKineticScroller::StateScrolling: + if (state == QKineticScroller::StatePressed) { + if (!timerId) { + timerId = startTimer(1000 / framesPerSecond); + } + } scrollTimer.start(); break; } @@ -886,18 +914,29 @@ void QKineticScrollerPrivate::setContentPositionHelper(const QPointF &pos) clampedPos.setY(qBound(qreal(0), pos.y(), maxPos.y())); bool alwaysOvershoot = (overshootPolicy == QKineticScroller::OvershootAlwaysOn); - qreal overshootX = (maxPos.x() || alwaysOvershoot) ? clampedPos.x() - pos.x() : 0; - qreal overshootY = (maxPos.y() || alwaysOvershoot) ? clampedPos.y() - pos.y() : 0; + qreal overshootX = (maxPos.x() || alwaysOvershoot) ? pos.x() - clampedPos.x() : 0; + qreal overshootY = (maxPos.y() || alwaysOvershoot) ? pos.y() - clampedPos.y() : 0; + // -- stop at the maximum overshoot distance (if set) if (!overshootMaximumDistance.isNull()) { - overshootDistance.setX(qBound(-overshootMaximumDistance.x(), overshootX, overshootMaximumDistance.x())); - overshootDistance.setY(qBound(-overshootMaximumDistance.y(), overshootY, overshootMaximumDistance.y())); + + qreal x = qBound(-overshootMaximumDistance.x() * pixelPerMeter, overshootX, overshootMaximumDistance.x() * pixelPerMeter); + if (x != overshootX) + velocity.setX(0); + overshootDistance.setX(x); + + qKSDebug() << "Overshoot y: "<<(overshootMaximumDistance.y() * pixelPerMeter)<<"distance: "<<overshootY; + qreal y = qBound(-overshootMaximumDistance.y() * pixelPerMeter, overshootY, overshootMaximumDistance.y() * pixelPerMeter); + if (y != overshootY) + velocity.setY(0); + overshootDistance.setY(y); + } else { overshootDistance = QPointF(overshootX, overshootY); } qKSDebug() << "setPosition raw: " << pos << ", clamped: " << clampedPos << ", overshoot: " << overshootDistance; - q->setContentPosition(clampedPos, overshootPolicy == QKineticScroller::OvershootAlwaysOff ? QPoint() : overshootDistance); + q->setContentPosition(clampedPos, overshootPolicy == QKineticScroller::OvershootAlwaysOff ? QPointF() : overshootDistance); } diff --git a/qkineticscroller.h b/qkineticscroller.h index 34fb175..8e9336c 100644 --- a/qkineticscroller.h +++ b/qkineticscroller.h @@ -86,7 +86,7 @@ public: enum ScrollMetric { - DragVelocitySmoothingFactor, // qreal [0..1] v = v_new* DASF + v_old * (1-DASF) + DragVelocitySmoothingFactor, // qreal [0..1/s] (complex calculation involving time) v = v_new* DASF + v_old * (1-DASF) FrictionCoefficent, // qreal [0..1] OvershootSpringConstant, // qreal [0..1] OvershootMaximumDistance, // QPointF([m], [m]) diff --git a/qscrollareakineticscroller.cpp b/qscrollareakineticscroller.cpp index 3b9c980..7b28dee 100644 --- a/qscrollareakineticscroller.cpp +++ b/qscrollareakineticscroller.cpp @@ -76,7 +76,7 @@ public: QAbstractScrollArea *area; QItemSelection oldSelection; // the selection before the first mouse down bool ignoreEvents; - QPointF lastOvershoot; + QPoint lastOvershoot; // don't change the type to QPointF or we might never shoot completely back. QPointer<QWidget> childWidget; // the widget where the mouse was pressed QElapsedTimer timer; @@ -136,11 +136,15 @@ void QScrollAreaKineticScroller::setWidget(QAbstractScrollArea *widget) { Q_D(QScrollAreaKineticScroller); - if (d->area) + if (d->area) { d->area->viewport()->removeEventFilter(this); - // todo: move back overshoot + d->area->viewport()->move(d->area->viewport()->pos() + d->lastOvershoot ); + } + reset(); d->area = widget; + d->lastOvershoot = QPoint(); + setParent(d->area); if (d->area) { d->area->viewport()->installEventFilter(this); @@ -149,7 +153,6 @@ void QScrollAreaKineticScroller::setWidget(QAbstractScrollArea *widget) view->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); } } - d->lastOvershoot = QPointF(); } bool QScrollAreaKineticScroller::eventFilter(QObject *o, QEvent *e) @@ -172,7 +175,7 @@ bool QScrollAreaKineticScroller::eventFilter(QObject *o, QEvent *e) // fall through QMouseEvent *me = static_cast<QMouseEvent *>(e); isMouseEvent = true; - res = handleInput(InputPress, me->posF(), timestamp); + res = handleInput(InputPress, me->posF() - d->lastOvershoot, timestamp); break; } case QEvent::MouseButtonDblClick: { @@ -180,21 +183,22 @@ bool QScrollAreaKineticScroller::eventFilter(QObject *o, QEvent *e) // fall through QMouseEvent *me = static_cast<QMouseEvent *>(e); isMouseEvent = true; - res = handleInput(InputPress, me->pos(), timestamp); + res = handleInput(InputPress, me->posF() - d->lastOvershoot, timestamp); break; } case QEvent::MouseMove: { QMouseEvent *me = static_cast<QMouseEvent *>(e); isMouseEvent = true; - res = handleInput(InputMove, me->posF(), timestamp); + res = handleInput(InputMove, me->posF() - d->lastOvershoot, timestamp); break; } case QEvent::MouseButtonRelease: { QMouseEvent *me = static_cast<QMouseEvent *>(e); isMouseEvent = true; - res = handleInput(InputRelease, me->pos(), timestamp); + res = handleInput(InputRelease, me->posF() - d->lastOvershoot, timestamp); break; } + case QEvent::ChildAdded: case QEvent::ChildRemoved: { QChildEvent *ce = static_cast<QChildEvent *>(e); @@ -256,6 +260,7 @@ bool QScrollAreaKineticScroller::canStartScrollingAt(const QPointF &pos) const if (childItem && (childItem->flags() & QGraphicsItem::ItemIsMovable)) return false; } + // don't start scrolling on a QSlider if (qobject_cast<QSlider *>(d->mouseTransparentChildAtGlobalPos(d->area->viewport(), d->area->viewport()->mapToGlobal(pos.toPoint())))) { return false; @@ -336,10 +341,10 @@ void QScrollAreaKineticScroller::setContentPosition(const QPointF &p, const QPoi if (QScrollBar *s = d->area->verticalScrollBar()) s->setValue(p.y()); - QPointF delta = overshootDelta - d->lastOvershoot; + QPoint delta = d->lastOvershoot - overshootDelta.toPoint(); if (!delta.isNull()) - d->area->viewport()->move(d->area->viewport()->pos() + delta.toPoint()); - d->lastOvershoot = overshootDelta; + d->area->viewport()->move(d->area->viewport()->pos() + delta); + d->lastOvershoot -= delta; } } |