1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qdeclarativebehavior_p.h"
44 #include "qdeclarativeanimation_p.h"
45 #include <qdeclarativecontext.h>
46 #include <qdeclarativeinfo.h>
47 #include <private/qdeclarativeproperty_p.h>
48 #include <private/qdeclarativeguard_p.h>
49 #include <private/qdeclarativeengine_p.h>
51 #include <private/qobject_p.h>
55 class QDeclarativeBehaviorPrivate : public QObjectPrivate
57 Q_DECLARE_PUBLIC(QDeclarativeBehavior)
59 QDeclarativeBehaviorPrivate() : animation(0), enabled(true), finalized(false)
60 , blockRunningChanged(false) {}
62 QDeclarativeProperty property;
64 QDeclarativeGuard<QDeclarativeAbstractAnimation> animation;
67 bool blockRunningChanged;
71 \qmlclass Behavior QDeclarativeBehavior
72 \inqmlmodule QtQuick 2
73 \ingroup qml-animation-transition
74 \brief The Behavior element allows you to specify a default animation for a property change.
76 A Behavior defines the default animation to be applied whenever a
77 particular property value changes.
79 For example, the following Behavior defines a NumberAnimation to be run
80 whenever the \l Rectangle's \c width value changes. When the MouseArea
81 is clicked, the \c width is changed, triggering the behavior's animation:
83 \snippet doc/src/snippets/declarative/behavior.qml 0
85 Note that a property cannot have more than one assigned Behavior. To provide
86 multiple animations within a Behavior, use ParallelAnimation or
89 If a \l{QML States}{state change} has a \l Transition that matches the same property as a
90 Behavior, the \l Transition animation overrides the Behavior for that
91 state change. For general advice on using Behaviors to animate state changes, see
92 \l{Using QML Behaviors with States}.
94 \sa {QML Animation and Transitions}, {declarative/animation/behaviors}{Behavior example}, QtDeclarative
98 QDeclarativeBehavior::QDeclarativeBehavior(QObject *parent)
99 : QObject(*(new QDeclarativeBehaviorPrivate), parent)
103 QDeclarativeBehavior::~QDeclarativeBehavior()
108 \qmlproperty Animation QtQuick2::Behavior::animation
111 This property holds the animation to run when the behavior is triggered.
114 QDeclarativeAbstractAnimation *QDeclarativeBehavior::animation()
116 Q_D(QDeclarativeBehavior);
120 void QDeclarativeBehavior::setAnimation(QDeclarativeAbstractAnimation *animation)
122 Q_D(QDeclarativeBehavior);
124 qmlInfo(this) << tr("Cannot change the animation assigned to a Behavior.");
128 d->animation = animation;
130 d->animation->setDefaultTarget(d->property);
131 d->animation->setDisableUserControl();
132 FAST_CONNECT(d->animation->qtAnimation(),
133 SIGNAL(stateChanged(QAbstractAnimation::State,QAbstractAnimation::State)),
135 SLOT(qtAnimationStateChanged(QAbstractAnimation::State,QAbstractAnimation::State)))
140 void QDeclarativeBehavior::qtAnimationStateChanged(QAbstractAnimation::State newState,QAbstractAnimation::State)
142 Q_D(QDeclarativeBehavior);
143 if (!d->blockRunningChanged)
144 d->animation->notifyRunningChanged(newState == QAbstractAnimation::Running);
149 \qmlproperty bool QtQuick2::Behavior::enabled
151 This property holds whether the behavior will be triggered when the tracked
152 property changes value.
154 By default a Behavior is enabled.
157 bool QDeclarativeBehavior::enabled() const
159 Q_D(const QDeclarativeBehavior);
163 void QDeclarativeBehavior::setEnabled(bool enabled)
165 Q_D(QDeclarativeBehavior);
166 if (d->enabled == enabled)
168 d->enabled = enabled;
169 emit enabledChanged();
172 void QDeclarativeBehavior::write(const QVariant &value)
174 Q_D(QDeclarativeBehavior);
175 bool bypass = !d->enabled || !d->finalized;
177 qmlExecuteDeferred(this);
178 if (!d->animation || bypass) {
179 QDeclarativePropertyPrivate::write(d->property, value, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding);
180 d->targetValue = value;
184 if (d->animation->isRunning() && value == d->targetValue)
187 const QVariant ¤tValue = d->property.read();
188 d->targetValue = value;
190 if (d->animation->qtAnimation()->duration() != -1
191 && d->animation->qtAnimation()->state() != QAbstractAnimation::Stopped) {
192 d->blockRunningChanged = true;
193 d->animation->qtAnimation()->stop();
196 QDeclarativeStateOperation::ActionList actions;
197 QDeclarativeAction action;
198 action.property = d->property;
199 action.fromValue = currentValue;
200 action.toValue = value;
203 QList<QDeclarativeProperty> after;
204 d->animation->transition(actions, after, QDeclarativeAbstractAnimation::Forward);
205 d->animation->qtAnimation()->start();
206 d->blockRunningChanged = false;
207 if (!after.contains(d->property))
208 QDeclarativePropertyPrivate::write(d->property, value, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding);
211 void QDeclarativeBehavior::setTarget(const QDeclarativeProperty &property)
213 Q_D(QDeclarativeBehavior);
214 d->property = property;
216 d->animation->setDefaultTarget(property);
218 QDeclarativeEnginePrivate *engPriv = QDeclarativeEnginePrivate::get(qmlEngine(this));
219 engPriv->registerFinalizeCallback(this, this->metaObject()->indexOfSlot("componentFinalized()"));
222 void QDeclarativeBehavior::componentFinalized()
224 Q_D(QDeclarativeBehavior);