ganeswidgets/src/hgspring.cpp
changeset 11 42505cd701c6
parent 5 4fa04caf0f43
child 12 6c0ec0ccd2d4
equal deleted inserted replaced
7:5ebec3429918 11:42505cd701c6
    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 {    
    61     mStartPos = mPos;
    74     mStartPos = mPos;
    62     mEndPos = pos;
    75     mEndPos = pos;
       
    76 
       
    77     emit started();
       
    78 
       
    79     if (!mTimer->isActive())
       
    80     {
       
    81         mTimer->start(KTimerInterval);
       
    82         mPrevTime.start();
       
    83     }
       
    84 }
       
    85 
       
    86 void HgSpring::animateToPosAfterPanning(const QPointF& pos, qreal worldWidth)
       
    87 {    
       
    88     mWorldWidth = worldWidth;
       
    89     mStartPos = mPos;
       
    90     
       
    91     qreal xPos = pos.x();
       
    92     if( xPos < 0.0 )
       
    93     {
       
    94         mEndPosOverListEdge = true;
       
    95         mEndPosOverListBoundary = pos;
       
    96         mEndPos = QPointF(0, 0);
       
    97     }
       
    98     else if( xPos > worldWidth )
       
    99     {
       
   100         mEndPosOverListEdge = true;
       
   101         mEndPosOverListBoundary = pos;
       
   102         mEndPos = QPointF(worldWidth, 0);
       
   103     }
       
   104     else
       
   105     {
       
   106         mEndPosOverListEdge = false;
       
   107         mEndPos = pos;
       
   108     }
    63 
   109 
    64     emit started();
   110     emit started();
    65 
   111 
    66     if (!mTimer->isActive())
   112     if (!mTimer->isActive())
    67     {
   113     {
   120     mAccumulator += deltaTime;
   166     mAccumulator += deltaTime;
   121 
   167 
   122     bool stopped = false;
   168     bool stopped = false;
   123     while (mAccumulator >= KTimeDelta)
   169     while (mAccumulator >= KTimeDelta)
   124     {
   170     {
   125         QPointF delta = mEndPos - mPos;
   171         QPointF delta;
       
   172         if(mEndPosOverListEdge)
       
   173         {
       
   174             delta = mEndPosOverListBoundary - mPos;
       
   175             
       
   176             if( mPos.x() < KPositionSnap || mPos.x() > mWorldWidth )
       
   177             {
       
   178                 // When list's position goes past the world boundary
       
   179                 // we reset our mEndPosOverListEdge boolean flag
       
   180                 // -> the passed boundary will be used as end point,
       
   181                 // and the K value of this spring will be modified.
       
   182                 mEndPosOverListEdge = false; //reset
       
   183                 mEndPosOverListBoundary = QPointF(0,0); //reset
       
   184                 mWorldWidth = 0.0; //reset
       
   185                 mK = 60.0;
       
   186             }
       
   187             
       
   188         }
       
   189         else
       
   190         {
       
   191             delta = mEndPos - mPos;
       
   192         }
       
   193         
   126         QPointF force = delta * mK - mVelocity * mDamping;
   194         QPointF force = delta * mK - mVelocity * mDamping;
   127         mVelocity += force * KTimeDeltaF;
   195         mVelocity += force * KTimeDeltaF;
   128         mPos += mVelocity * KTimeDeltaF;
   196         mPos += mVelocity * KTimeDeltaF;
       
   197         
   129         if ( (qAbs(mPos.x() - mEndPos.x()) < KPositionSnap &&
   198         if ( (qAbs(mPos.x() - mEndPos.x()) < KPositionSnap &&
   130               qAbs(mPos.y() - mEndPos.y()) < KPositionSnap) )
   199                   qAbs(mPos.y() - mEndPos.y()) < KPositionSnap)
       
   200              && qAbs(mVelocity.x()) < KVelocitySnap )
   131         {
   201         {
   132             mPos = mEndPos;
   202             mPos = mEndPos;
   133             mAccumulator = 0;
   203             mAccumulator = 0;
   134             mVelocity = QPointF(0,0);
   204             mVelocity = QPointF(0,0);
   135             mTimer->stop();
   205             mTimer->stop();
   137             break;
   207             break;
   138         }
   208         }
   139 
   209 
   140         mAccumulator -= KTimeDelta;
   210         mAccumulator -= KTimeDelta;
   141     }
   211     }
   142 
   212     
   143     if (!mDoNotUpdate)
   213     if (!mDoNotUpdate)
   144         emit updated();
   214         emit updated();
   145     
   215     
   146     if (stopped)
   216     if (stopped)
   147         emit ended();
   217         emit ended();