1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qquickflipable_p.h"
43 #include "qquickitem_p.h"
45 #include <private/qqmlguard_p.h>
47 #include <QtQml/qqmlinfo.h>
51 // XXX todo - i think this needs work and a bit of a re-think
53 class QQuickLocalTransform : public QQuickTransform
57 QQuickLocalTransform(QObject *parent) : QQuickTransform(parent) {}
59 void setTransform(const QTransform &t) {
63 virtual void applyTo(QMatrix4x4 *matrix) const {
70 class QQuickFlipablePrivate : public QQuickItemPrivate
72 Q_DECLARE_PUBLIC(QQuickFlipable)
74 QQuickFlipablePrivate() : current(QQuickFlipable::Front), front(0), back(0), sideDirty(false) {}
76 virtual void transformChanged();
78 void setBackTransform();
80 QQuickFlipable::Side current;
81 QQmlGuard<QQuickLocalTransform> backTransform;
82 QQmlGuard<QQuickItem> front;
83 QQmlGuard<QQuickItem> back;
86 bool wantBackXFlipped;
87 bool wantBackYFlipped;
92 \instantiates QQuickFlipable
93 \inqmlmodule QtQuick 2
95 \ingroup qtquick-input
96 \ingroup qtquick-containers
97 \brief Provides a surface that can be flipped
99 Flipable is an item that can be visibly "flipped" between its front and
100 back sides, like a card. It may used together with \l Rotation, \l State
101 and \l Transition types to produce a flipping effect.
103 The \l front and \l back properties are used to hold the items that are
104 shown respectively on the front and back sides of the flipable item.
106 \section1 Example Usage
108 The following example shows a Flipable item that flips whenever it is
109 clicked, rotating about the y-axis.
111 This flipable item has a \c flipped boolean property that is toggled
112 whenever the MouseArea within the flipable is clicked. When
113 \c flipped is true, the item changes to the "back" state; in this
114 state, the \c angle of the \l Rotation item is changed to 180
115 degrees to produce the flipping effect. When \c flipped is false, the
116 item reverts to the default state, in which the \c angle value is 0.
118 \snippet qml/flipable/flipable.qml 0
122 The \l Transition creates the animation that changes the angle over
123 four seconds. When the item changes between its "back" and
124 default states, the NumberAnimation animates the angle between
125 its old and new values.
127 See \l {States} for details on state changes and the default
128 state, and \l {QML Animation and Transitions} for more information on how
129 animations work within transitions.
131 \sa {declarative/ui-components/flipable}{Flipable example}
133 QQuickFlipable::QQuickFlipable(QQuickItem *parent)
134 : QQuickItem(*(new QQuickFlipablePrivate), parent)
138 QQuickFlipable::~QQuickFlipable()
143 \qmlproperty Item QtQuick2::Flipable::front
144 \qmlproperty Item QtQuick2::Flipable::back
146 The front and back sides of the flipable.
149 QQuickItem *QQuickFlipable::front()
151 Q_D(const QQuickFlipable);
155 void QQuickFlipable::setFront(QQuickItem *front)
159 qmlInfo(this) << tr("front is a write-once property");
163 d->front->setParentItem(this);
164 if (Back == d->current)
165 d->front->setOpacity(0.);
169 QQuickItem *QQuickFlipable::back()
171 Q_D(const QQuickFlipable);
175 void QQuickFlipable::setBack(QQuickItem *back)
179 qmlInfo(this) << tr("back is a write-once property");
185 d->back->setParentItem(this);
187 d->backTransform = new QQuickLocalTransform(d->back);
188 d->backTransform->prependToItem(d->back);
190 if (Front == d->current)
191 d->back->setOpacity(0.);
192 connect(back, SIGNAL(widthChanged()),
193 this, SLOT(retransformBack()));
194 connect(back, SIGNAL(heightChanged()),
195 this, SLOT(retransformBack()));
199 void QQuickFlipable::retransformBack()
202 if (d->current == QQuickFlipable::Back && d->back)
203 d->setBackTransform();
207 \qmlproperty enumeration QtQuick2::Flipable::side
209 The side of the Flipable currently visible. Possible values are \c
210 Flipable.Front and \c Flipable.Back.
212 QQuickFlipable::Side QQuickFlipable::side() const
214 Q_D(const QQuickFlipable);
216 const_cast<QQuickFlipablePrivate *>(d)->updateSide();
220 void QQuickFlipablePrivate::transformChanged()
229 QQuickItemPrivate::transformChanged();
232 void QQuickFlipable::updatePolish()
238 // determination on the currently visible side of the flipable
239 // has to be done on the complete scene transform to give
241 void QQuickFlipablePrivate::updateSide()
250 QTransform sceneTransform;
251 itemToParentTransform(sceneTransform);
257 QPointF scenep1 = sceneTransform.map(p1);
258 QPointF scenep2 = sceneTransform.map(p2);
259 QPointF scenep3 = sceneTransform.map(p3);
261 p1 = q->mapToParent(p1);
262 p2 = q->mapToParent(p2);
263 p3 = q->mapToParent(p3);
266 qreal cross = (scenep1.x() - scenep2.x()) * (scenep3.y() - scenep2.y()) -
267 (scenep1.y() - scenep2.y()) * (scenep3.x() - scenep2.x());
269 wantBackYFlipped = scenep1.x() >= scenep2.x();
270 wantBackXFlipped = scenep2.y() >= scenep3.y();
272 QQuickFlipable::Side newSide;
274 newSide = QQuickFlipable::Back;
276 newSide = QQuickFlipable::Front;
279 if (newSide != current) {
281 if (current == QQuickFlipable::Back && back)
284 front->setOpacity((current==QQuickFlipable::Front)?1.:0.);
286 back->setOpacity((current==QQuickFlipable::Back)?1.:0.);
287 emit q->sideChanged();
291 /* Depends on the width/height of the back item, and so needs reevaulating
294 void QQuickFlipablePrivate::setBackTransform()
297 mat.translate(back->width()/2,back->height()/2);
298 if (back->width() && wantBackYFlipped)
299 mat.rotate(180, Qt::YAxis);
300 if (back->height() && wantBackXFlipped)
301 mat.rotate(180, Qt::XAxis);
302 mat.translate(-back->width()/2,-back->height()/2);
305 backTransform->setTransform(mat);
310 #include "qquickflipable.moc"