ganeswidgets/src/hgspring.cpp
changeset 13 8bf920201dea
parent 5 4fa04caf0f43
child 19 31a1a9e11046
equal deleted inserted replaced
9:dde80bf4a8c7 13:8bf920201dea
    19 #include <QTimer>
    19 #include <QTimer>
    20 #include "trace.h"
    20 #include "trace.h"
    21 
    21 
    22 const int KTimeDelta(10);
    22 const int KTimeDelta(10);
    23 const qreal KTimeDeltaF(0.01f);
    23 const qreal KTimeDeltaF(0.01f);
    24 //const qreal KVelocitySnap(0.05f);
    24 const qreal KVelocitySnap(0.06f);
    25 const qreal KPositionSnap(0.01f);
    25 const qreal KPositionSnap(0.01f);
    26 const int KTimerInterval(10);
    26 const int KTimerInterval(10);
    27 
    27 
    28 HgSpring::HgSpring() :
    28 HgSpring::HgSpring() :
    29 mStartPos(QPointF(0,0)),
    29 mStartPos(QPointF(0,0)),
    30 mPos(QPointF(0,0)),
    30 mPos(QPointF(0,0)),
    31 mEndPos(QPointF(0,0)),
    31 mEndPos(QPointF(0,0)),
       
    32 mEndPosOverListBoundary(QPointF(0,0)),
    32 mVelocity(QPointF(0,0)),
    33 mVelocity(QPointF(0,0)),
    33 mK(30.1),
    34 mK(30.1),
    34 mDamping(10.1),
    35 mDamping(10.1),
    35 mAccumulator(0.0),
    36 mAccumulator(0.0),
    36 mDoNotUpdate(false)
    37 mDoNotUpdate(false),
       
    38 mEndPosOverListEdge(false)
    37 {
    39 {
    38     mTimer = new QTimer(this);
    40     mTimer = new QTimer(this);
    39 
    41 
    40     QObject::connect( mTimer, SIGNAL( timeout() ), this, SLOT( update() ) );
    42     QObject::connect( mTimer, SIGNAL( timeout() ), this, SLOT( update() ) );
    41 
    43 
    54 void HgSpring::setDamping(qreal damping)
    56 void HgSpring::setDamping(qreal damping)
    55 {
    57 {
    56     mDamping = damping;
    58     mDamping = damping;
    57 }
    59 }
    58 
    60 
       
    61 qreal HgSpring::k() const
       
    62 {
       
    63     return mK;
       
    64 }
       
    65 
       
    66 qreal HgSpring::damping() const
       
    67 {
       
    68     return mDamping;
       
    69 }
       
    70 
       
    71 // TODO: Remove this function and use only the animateToPosAfterPanning version?
    59 void HgSpring::animateToPos(const QPointF& pos)
    72 void HgSpring::animateToPos(const QPointF& pos)
    60 {
    73 {    
       
    74     if (mPos == pos) {
       
    75         // No need to animate, we are already in correct position.
       
    76         return;
       
    77     }
       
    78             
    61     mStartPos = mPos;
    79     mStartPos = mPos;
    62     mEndPos = pos;
    80     mEndPos = pos;
       
    81 
       
    82     emit started();
       
    83 
       
    84     if (!mTimer->isActive())
       
    85     {
       
    86         mTimer->start(KTimerInterval);
       
    87         mPrevTime.start();
       
    88     }
       
    89 }
       
    90 
       
    91 void HgSpring::animateToPosAfterPanning(const QPointF& pos, qreal worldWidth)
       
    92 {    
       
    93     mWorldWidth = worldWidth;
       
    94     mStartPos = mPos;
       
    95     
       
    96     qreal xPos = pos.x();
       
    97     if( xPos < 0.0 )
       
    98     {
       
    99         mEndPosOverListEdge = true;
       
   100         mEndPosOverListBoundary = pos;
       
   101         mEndPos = QPointF(0, 0);
       
   102     }
       
   103     else if( xPos > worldWidth )
       
   104     {
       
   105         mEndPosOverListEdge = true;
       
   106         mEndPosOverListBoundary = pos;
       
   107         mEndPos = QPointF(worldWidth, 0);
       
   108     }
       
   109     else
       
   110     {
       
   111         mEndPosOverListEdge = false;
       
   112         mEndPos = pos;
       
   113     }
    63 
   114 
    64     emit started();
   115     emit started();
    65 
   116 
    66     if (!mTimer->isActive())
   117     if (!mTimer->isActive())
    67     {
   118     {
   120     mAccumulator += deltaTime;
   171     mAccumulator += deltaTime;
   121 
   172 
   122     bool stopped = false;
   173     bool stopped = false;
   123     while (mAccumulator >= KTimeDelta)
   174     while (mAccumulator >= KTimeDelta)
   124     {
   175     {
   125         QPointF delta = mEndPos - mPos;
   176         QPointF delta;
       
   177         if(mEndPosOverListEdge)
       
   178         {
       
   179             delta = mEndPosOverListBoundary - mPos;
       
   180             
       
   181             if( mPos.x() < KPositionSnap || mPos.x() > mWorldWidth )
       
   182             {
       
   183                 // When list's position goes past the world boundary
       
   184                 // we reset our mEndPosOverListEdge boolean flag
       
   185                 // -> the passed boundary will be used as end point,
       
   186                 // and the K value of this spring will be modified.
       
   187                 mEndPosOverListEdge = false; //reset
       
   188                 mEndPosOverListBoundary = QPointF(0,0); //reset
       
   189                 mWorldWidth = 0.0; //reset
       
   190                 mK = 60.0;
       
   191             }
       
   192             
       
   193         }
       
   194         else
       
   195         {
       
   196             delta = mEndPos - mPos;
       
   197         }
       
   198         
   126         QPointF force = delta * mK - mVelocity * mDamping;
   199         QPointF force = delta * mK - mVelocity * mDamping;
   127         mVelocity += force * KTimeDeltaF;
   200         mVelocity += force * KTimeDeltaF;
   128         mPos += mVelocity * KTimeDeltaF;
   201         mPos += mVelocity * KTimeDeltaF;
       
   202         
   129         if ( (qAbs(mPos.x() - mEndPos.x()) < KPositionSnap &&
   203         if ( (qAbs(mPos.x() - mEndPos.x()) < KPositionSnap &&
   130               qAbs(mPos.y() - mEndPos.y()) < KPositionSnap) )
   204                   qAbs(mPos.y() - mEndPos.y()) < KPositionSnap)
       
   205              && qAbs(mVelocity.x()) < KVelocitySnap )
   131         {
   206         {
   132             mPos = mEndPos;
   207             mPos = mEndPos;
   133             mAccumulator = 0;
   208             mAccumulator = 0;
   134             mVelocity = QPointF(0,0);
   209             mVelocity = QPointF(0,0);
   135             mTimer->stop();
   210             mTimer->stop();
   137             break;
   212             break;
   138         }
   213         }
   139 
   214 
   140         mAccumulator -= KTimeDelta;
   215         mAccumulator -= KTimeDelta;
   141     }
   216     }
   142 
   217     
   143     if (!mDoNotUpdate)
   218     if (!mDoNotUpdate)
   144         emit updated();
   219         emit updated();
   145     
   220     
   146     if (stopped)
   221     if (stopped)
   147         emit ended();
   222         emit ended();