1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include "private/qdeclarativeflipable_p.h"
44 #include "private/qdeclarativeitem_p.h"
45 #include "private/qdeclarativeguard_p.h"
47 #include <qdeclarativeinfo.h>
49 #include <QtGui/qgraphicstransform.h>
53 class QDeclarativeFlipablePrivate : public QDeclarativeItemPrivate
55 Q_DECLARE_PUBLIC(QDeclarativeFlipable)
57 QDeclarativeFlipablePrivate() : current(QDeclarativeFlipable::Front), front(0), back(0) {}
59 void updateSceneTransformFromParent();
60 void setBackTransform();
62 QDeclarativeFlipable::Side current;
63 QDeclarativeGuard<QGraphicsObject> front;
64 QDeclarativeGuard<QGraphicsObject> back;
66 bool wantBackXFlipped;
67 bool wantBackYFlipped;
71 \qmlclass Flipable QDeclarativeFlipable
73 \ingroup qml-basic-interaction-elements
74 \brief The Flipable item provides a surface that can be flipped.
77 Flipable is an item that can be visibly "flipped" between its front and
78 back sides, like a card. It is used together with \l Rotation, \l State
79 and \l Transition elements to produce a flipping effect.
81 The \l front and \l back properties are used to hold the items that are
82 shown respectively on the front and back sides of the flipable item.
84 \section1 Example Usage
86 The following example shows a Flipable item that flips whenever it is
87 clicked, rotating about the y-axis.
89 This flipable item has a \c flipped boolean property that is toggled
90 whenever the MouseArea within the flipable is clicked. When
91 \c flipped is true, the item changes to the "back" state; in this
92 state, the \c angle of the \l Rotation item is changed to 180
93 degrees to produce the flipping effect. When \c flipped is false, the
94 item reverts to the default state, in which the \c angle value is 0.
96 \snippet doc/src/snippets/declarative/flipable/flipable.qml 0
100 The \l Transition creates the animation that changes the angle over
101 four seconds. When the item changes between its "back" and
102 default states, the NumberAnimation animates the angle between
103 its old and new values.
105 See \l {QML States} for details on state changes and the default
106 state, and \l {QML Animation and Transitions} for more information on how
107 animations work within transitions.
109 \sa {declarative/ui-components/flipable}{Flipable example}
112 QDeclarativeFlipable::QDeclarativeFlipable(QDeclarativeItem *parent)
113 : QDeclarativeItem(*(new QDeclarativeFlipablePrivate), parent)
117 QDeclarativeFlipable::~QDeclarativeFlipable()
122 \qmlproperty Item Flipable::front
123 \qmlproperty Item Flipable::back
125 The front and back sides of the flipable.
128 QGraphicsObject *QDeclarativeFlipable::front()
130 Q_D(const QDeclarativeFlipable);
134 void QDeclarativeFlipable::setFront(QGraphicsObject *front)
136 Q_D(QDeclarativeFlipable);
138 qmlInfo(this) << tr("front is a write-once property");
142 d->front->setParentItem(this);
143 if (Back == d->current)
144 d->front->setOpacity(0.);
148 QGraphicsObject *QDeclarativeFlipable::back()
150 Q_D(const QDeclarativeFlipable);
154 void QDeclarativeFlipable::setBack(QGraphicsObject *back)
156 Q_D(QDeclarativeFlipable);
158 qmlInfo(this) << tr("back is a write-once property");
162 d->back->setParentItem(this);
163 if (Front == d->current)
164 d->back->setOpacity(0.);
165 connect(back, SIGNAL(widthChanged()),
166 this, SLOT(retransformBack()));
167 connect(back, SIGNAL(heightChanged()),
168 this, SLOT(retransformBack()));
172 void QDeclarativeFlipable::retransformBack()
174 Q_D(QDeclarativeFlipable);
175 if (d->current == QDeclarativeFlipable::Back && d->back)
176 d->setBackTransform();
180 \qmlproperty enumeration Flipable::side
182 The side of the Flipable currently visible. Possible values are \c
183 Flipable.Front and \c Flipable.Back.
185 QDeclarativeFlipable::Side QDeclarativeFlipable::side() const
187 Q_D(const QDeclarativeFlipable);
188 if (d->dirtySceneTransform)
189 const_cast<QDeclarativeFlipablePrivate *>(d)->ensureSceneTransform();
194 // determination on the currently visible side of the flipable
195 // has to be done on the complete scene transform to give
197 void QDeclarativeFlipablePrivate::updateSceneTransformFromParent()
199 Q_Q(QDeclarativeFlipable);
201 QDeclarativeItemPrivate::updateSceneTransformFromParent();
206 QPointF scenep1 = sceneTransform.map(p1);
207 QPointF scenep2 = sceneTransform.map(p2);
208 QPointF scenep3 = sceneTransform.map(p3);
209 p1 = q->mapToParent(p1);
210 p2 = q->mapToParent(p2);
211 p3 = q->mapToParent(p3);
213 qreal cross = (scenep1.x() - scenep2.x()) * (scenep3.y() - scenep2.y()) -
214 (scenep1.y() - scenep2.y()) * (scenep3.x() - scenep2.x());
216 wantBackYFlipped = p1.x() >= p2.x();
217 wantBackXFlipped = p2.y() >= p3.y();
219 QDeclarativeFlipable::Side newSide;
221 newSide = QDeclarativeFlipable::Back;
223 newSide = QDeclarativeFlipable::Front;
226 if (newSide != current) {
228 if (current == QDeclarativeFlipable::Back && back)
231 front->setOpacity((current==QDeclarativeFlipable::Front)?1.:0.);
233 back->setOpacity((current==QDeclarativeFlipable::Back)?1.:0.);
234 emit q->sideChanged();
238 /* Depends on the width/height of the back item, and so needs reevaulating
241 void QDeclarativeFlipablePrivate::setBackTransform()
244 QGraphicsItemPrivate *dBack = QGraphicsItemPrivate::get(back);
245 mat.translate(dBack->width()/2,dBack->height()/2);
246 if (dBack->width() && wantBackYFlipped)
247 mat.rotate(180, Qt::YAxis);
248 if (dBack->height() && wantBackXFlipped)
249 mat.rotate(180, Qt::XAxis);
250 mat.translate(-dBack->width()/2,-dBack->height()/2);
251 back->setTransform(mat);