diff -r dde80bf4a8c7 -r 8bf920201dea ganeswidgets/src/hgspring.cpp --- a/ganeswidgets/src/hgspring.cpp Tue Jul 06 15:29:26 2010 +0300 +++ b/ganeswidgets/src/hgspring.cpp Wed Aug 18 10:52:49 2010 +0300 @@ -21,7 +21,7 @@ const int KTimeDelta(10); const qreal KTimeDeltaF(0.01f); -//const qreal KVelocitySnap(0.05f); +const qreal KVelocitySnap(0.06f); const qreal KPositionSnap(0.01f); const int KTimerInterval(10); @@ -29,11 +29,13 @@ mStartPos(QPointF(0,0)), mPos(QPointF(0,0)), mEndPos(QPointF(0,0)), +mEndPosOverListBoundary(QPointF(0,0)), mVelocity(QPointF(0,0)), mK(30.1), mDamping(10.1), mAccumulator(0.0), -mDoNotUpdate(false) +mDoNotUpdate(false), +mEndPosOverListEdge(false) { mTimer = new QTimer(this); @@ -56,8 +58,24 @@ mDamping = damping; } +qreal HgSpring::k() const +{ + return mK; +} + +qreal HgSpring::damping() const +{ + return mDamping; +} + +// TODO: Remove this function and use only the animateToPosAfterPanning version? void HgSpring::animateToPos(const QPointF& pos) -{ +{ + if (mPos == pos) { + // No need to animate, we are already in correct position. + return; + } + mStartPos = mPos; mEndPos = pos; @@ -70,6 +88,39 @@ } } +void HgSpring::animateToPosAfterPanning(const QPointF& pos, qreal worldWidth) +{ + mWorldWidth = worldWidth; + mStartPos = mPos; + + qreal xPos = pos.x(); + if( xPos < 0.0 ) + { + mEndPosOverListEdge = true; + mEndPosOverListBoundary = pos; + mEndPos = QPointF(0, 0); + } + else if( xPos > worldWidth ) + { + mEndPosOverListEdge = true; + mEndPosOverListBoundary = pos; + mEndPos = QPointF(worldWidth, 0); + } + else + { + mEndPosOverListEdge = false; + mEndPos = pos; + } + + emit started(); + + if (!mTimer->isActive()) + { + mTimer->start(KTimerInterval); + mPrevTime.start(); + } +} + void HgSpring::gotoPos(const QPointF& pos) { if (mTimer->isActive()) @@ -122,12 +173,36 @@ bool stopped = false; while (mAccumulator >= KTimeDelta) { - QPointF delta = mEndPos - mPos; + QPointF delta; + if(mEndPosOverListEdge) + { + delta = mEndPosOverListBoundary - mPos; + + if( mPos.x() < KPositionSnap || mPos.x() > mWorldWidth ) + { + // When list's position goes past the world boundary + // we reset our mEndPosOverListEdge boolean flag + // -> the passed boundary will be used as end point, + // and the K value of this spring will be modified. + mEndPosOverListEdge = false; //reset + mEndPosOverListBoundary = QPointF(0,0); //reset + mWorldWidth = 0.0; //reset + mK = 60.0; + } + + } + else + { + delta = mEndPos - mPos; + } + QPointF force = delta * mK - mVelocity * mDamping; mVelocity += force * KTimeDeltaF; mPos += mVelocity * KTimeDeltaF; + if ( (qAbs(mPos.x() - mEndPos.x()) < KPositionSnap && - qAbs(mPos.y() - mEndPos.y()) < KPositionSnap) ) + qAbs(mPos.y() - mEndPos.y()) < KPositionSnap) + && qAbs(mVelocity.x()) < KVelocitySnap ) { mPos = mEndPos; mAccumulator = 0; @@ -139,7 +214,7 @@ mAccumulator -= KTimeDelta; } - + if (!mDoNotUpdate) emit updated();