diff options
author | Michael Brasser <michael.brasser@nokia.com> | 2009-06-26 02:28:34 (GMT) |
---|---|---|
committer | Michael Brasser <michael.brasser@nokia.com> | 2009-06-26 02:28:34 (GMT) |
commit | afa4e61b10187102d3ea49d1c11bae1ef919d94d (patch) | |
tree | 7890eb2f3194de2b9a2ca7ed6fd0227f7b92fa36 /src/declarative/util | |
parent | ffc9e62cbf7e24cd04a1202de1b3e618f9e12642 (diff) | |
parent | 5b52c348243e6459cc7faa4ee76a23c7fadcd299 (diff) | |
download | Qt-afa4e61b10187102d3ea49d1c11bae1ef919d94d.zip Qt-afa4e61b10187102d3ea49d1c11bae1ef919d94d.tar.gz Qt-afa4e61b10187102d3ea49d1c11bae1ef919d94d.tar.bz2 |
Merge branch 'kinetic-declarativeui' of git@scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
Diffstat (limited to 'src/declarative/util')
-rw-r--r-- | src/declarative/util/qmlfollow.cpp | 8 | ||||
-rw-r--r-- | src/declarative/util/qmlstate.cpp | 102 | ||||
-rw-r--r-- | src/declarative/util/qmlstate.h | 23 | ||||
-rw-r--r-- | src/declarative/util/qmlstate_p.h | 29 |
4 files changed, 96 insertions, 66 deletions
diff --git a/src/declarative/util/qmlfollow.cpp b/src/declarative/util/qmlfollow.cpp index 95e7792..d3b3617 100644 --- a/src/declarative/util/qmlfollow.cpp +++ b/src/declarative/util/qmlfollow.cpp @@ -93,11 +93,11 @@ void QmlFollowPrivate::tick(int time) if (!elapsed) return; if (mode == Spring) { - if (elapsed < 10) // capped at 100fps. + if (elapsed < 16) // capped at 62fps. return; // Real men solve the spring DEs using RK4. // We'll do something much simpler which gives a result that looks fine. - int count = (elapsed+5) / 10; + int count = (elapsed+8) / 16; for (int i = 0; i < count; ++i) { qreal diff = sourceValue - currentValue; velocity = velocity + spring * diff - damping * velocity; @@ -110,14 +110,14 @@ void QmlFollowPrivate::tick(int time) else if (velocity < -maxVelocity) velocity = -maxVelocity; } - currentValue += velocity * 10.0 / 1000.0; + currentValue += velocity * 16.0 / 1000.0; } if (qAbs(velocity) < epsilon && qAbs(sourceValue - currentValue) < epsilon) { velocity = 0.0; currentValue = sourceValue; clock.stop(); } - lastTime = time - (elapsed - count * 10); + lastTime = time - (elapsed - count * 16); } else { qreal moveBy = elapsed * velocityms; qreal diff = sourceValue - currentValue; diff --git a/src/declarative/util/qmlstate.cpp b/src/declarative/util/qmlstate.cpp index abe8301..0574224 100644 --- a/src/declarative/util/qmlstate.cpp +++ b/src/declarative/util/qmlstate.cpp @@ -234,19 +234,6 @@ QmlState &QmlState::operator<<(QmlStateOperation *op) return *this; } -#if 0 -static void dump(const QmlStateOperation::ActionList &list) -{ - if (!QString(getenv("STATE_DEBUG")).isEmpty()) - return; - - for (int ii = 0; ii < list.count(); ++ii) { - const Action &action = list.at(ii); - qWarning() << action.property.object << action.property.name << action.toValue; - } -} -#endif - void QmlStatePrivate::applyBindings() { foreach(const Action &action, bindingsList) { @@ -282,12 +269,16 @@ void QmlStatePrivate::complete() emit q->completed(); } -QmlStateOperation::ActionList QmlStatePrivate::generateActionList(QmlStateGroup *group) const +// Generate a list of actions for this state. This includes coelescing state +// actions that this state "extends" +QmlStateOperation::ActionList +QmlStatePrivate::generateActionList(QmlStateGroup *group) const { QmlStateOperation::ActionList applyList; if (inState) return applyList; + // Prevent "extends" recursion inState = true; if (!extends.isEmpty()) { @@ -336,12 +327,19 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever d->reverting.clear(); d->bindingsList.clear(); - if (revert) - d->revertList = static_cast<QmlStatePrivate*>(revert->d_ptr)->revertList; - QmlStateOperation::RevertActionList additionalReverts; + if (revert) { + QmlStatePrivate *revertPrivate = + static_cast<QmlStatePrivate*>(revert->d_ptr); + d->revertList = revertPrivate->revertList; + revertPrivate->revertList.clear(); + } + // List of actions caused by this state QmlStateOperation::ActionList applyList = d->generateActionList(group); + // List of actions that need to be reverted to roll back (just) this state + QmlStatePrivate::SimpleActionList additionalReverts; + // First add the reverse of all the applyList actions for (int ii = 0; ii < applyList.count(); ++ii) { const Action &action = applyList.at(ii); if (action.event || !action.restore) @@ -353,10 +351,15 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever found = true; } if (!found) { - RevertAction r(action); + // Only need to revert the applyList action if the previous + // state doesn't have a higher priority revert already + SimpleAction r(action); additionalReverts << r; } } + + // Any reverts from a previous state that aren't carried forth + // into this state need to be translated into apply actions for (int ii = 0; ii < d->revertList.count(); ++ii) { bool found = false; for (int jj = 0; !found && jj < applyList.count(); ++jj) { @@ -376,26 +379,41 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever a.bv = d->revertList.at(ii).bv; } applyList << a; + // Store these special reverts in the reverting list d->reverting << d->revertList.at(ii).property; } } + // All the local reverts now become part of the ongoing revertList d->revertList << additionalReverts; - //apply all changes, and work out any ending positions for bindings - //then rewind all changes and proceed as normal - //### 4 foreach loops! - //////////////////////////////////////////////////////////////////// - foreach(const Action &action, applyList) { - if (stateChangeDebug()) - qWarning() << " Action:" << action.property.object() << action.property.name() << action.toValue; + // Output for debugging + if (stateChangeDebug()) { + foreach(const Action &action, applyList) { + qWarning() << " Action:" << action.property.object() + << action.property.name() << action.toValue; + } + } + // Determine which actions are binding changes. + foreach(const Action &action, applyList) { if (action.bv && !action.toBinding.isEmpty()) { d->bindingsList << action; action.bv->clearExpression(); } } + // Animated transitions need both the start and the end value for + // each property change. In the presence of bindings, the end values + // are non-trivial to calculate. As a "best effort" attempt, we first + // apply all the property and binding changes, then read all the actual + // final values, then roll back the changes and proceed as normal. + // + // This doesn't catch everything, and it might be a little fragile in + // some cases - but whatcha going to do? + if (!d->bindingsList.isEmpty()) { + + // Apply all the property and binding changes foreach(const Action &action, applyList) { if (action.bv && !action.toBinding.isEmpty()) { action.bv->setExpression(action.toBinding); @@ -404,6 +422,7 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever } } + // Read all the end values for binding changes for (int ii = 0; ii < applyList.size(); ++ii) { Action *action = &applyList[ii]; if (action->event) @@ -415,6 +434,7 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever } } + // Revert back to the original values foreach(const Action &action, applyList) { if (action.event) continue; @@ -424,36 +444,44 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever action.property.write(action.fromValue); } } - //////////////////////////////////////////////////////////////////// - QmlStateOperation::ActionList modList = applyList; - QList<QmlMetaProperty> touched; + d->completeList.clear(); + if (trans) { + QList<QmlMetaProperty> touched; d->transition = trans; - trans->prepare(modList, touched, this); - for (int ii = 0; ii < modList.count(); ++ii) { - const Action &action = modList.at(ii); + trans->prepare(applyList, touched, this); + + // Modify the action list to remove actions handled in the transition + for (int ii = 0; ii < applyList.count(); ++ii) { + const Action &action = applyList.at(ii); if (action.event) { + if (action.actionDone) { - modList.removeAt(ii); + applyList.removeAt(ii); --ii; } + } else { - if (action.toValue != action.fromValue) { - d->completeList << RevertAction(action, false); - } if (touched.contains(action.property)) { - modList.removeAt(ii); + if (action.toValue != action.fromValue) + d->completeList << SimpleAction(action, + SimpleAction::EndState); + + applyList.removeAt(ii); --ii; } + } } } - foreach(const Action &action, modList) { + // Any actions remaining have not been handled by the transition and should + // be applied immediately + foreach(const Action &action, applyList) { if (action.event) action.event->execute(); else diff --git a/src/declarative/util/qmlstate.h b/src/declarative/util/qmlstate.h index 0b8d82a..59ef812 100644 --- a/src/declarative/util/qmlstate.h +++ b/src/declarative/util/qmlstate.h @@ -79,28 +79,6 @@ public: virtual void execute(); }; -class RevertAction -{ -public: - RevertAction(const Action &a, bool from = true) : bv(0) - { - property = a.property; - if (from) { - value = a.fromValue; - binding = a.fromBinding; - } else { - value = a.toValue; - binding = a.toBinding; - } - bv = a.bv; - } - - QmlMetaProperty property; - QVariant value; - QString binding; - QmlBindableValue *bv; -}; - class QmlStateGroup; class Q_DECLARATIVE_EXPORT QmlStateOperation : public QObject { @@ -109,7 +87,6 @@ public: QmlStateOperation(QObject *parent = 0) : QObject(parent) {} typedef QList<Action> ActionList; - typedef QList<RevertAction> RevertActionList; virtual ActionList actions(); diff --git a/src/declarative/util/qmlstate_p.h b/src/declarative/util/qmlstate_p.h index da8fdcd..7fcbcd7 100644 --- a/src/declarative/util/qmlstate_p.h +++ b/src/declarative/util/qmlstate_p.h @@ -48,6 +48,29 @@ QT_BEGIN_NAMESPACE +class SimpleAction +{ +public: + enum State { StartState, EndState }; + SimpleAction(const Action &a, State state = StartState) : bv(0) + { + property = a.property; + if (state == StartState) { + value = a.fromValue; + binding = a.fromBinding; + } else { + value = a.toValue; + binding = a.toBinding; + } + bv = a.bv; + } + + QmlMetaProperty property; + QVariant value; + QString binding; + QmlBindableValue *bv; +}; + class QmlStatePrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QmlState) @@ -56,13 +79,15 @@ public: QmlStatePrivate() : when(0), transition(0), inState(false), group(0) {} + typedef QList<SimpleAction> SimpleActionList; + QString name; QmlBindableValue *when; QmlConcreteList<QmlStateOperation *> operations; QmlTransition *transition; - QmlStateOperation::RevertActionList revertList; + SimpleActionList revertList; QList<QmlMetaProperty> reverting; - QmlStateOperation::RevertActionList completeList; + SimpleActionList completeList; QmlStateOperation::ActionList bindingsList; QString extends; mutable bool inState; |