source: trunk/src/declarative/graphicsitems/qdeclarativeflipable.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 8.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtDeclarative module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
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.
23**
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.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "private/qdeclarativeflipable_p.h"
43
44#include "private/qdeclarativeitem_p.h"
45#include "private/qdeclarativeguard_p.h"
46
47#include <qdeclarativeinfo.h>
48
49#include <QtGui/qgraphicstransform.h>
50
51QT_BEGIN_NAMESPACE
52
53class QDeclarativeFlipablePrivate : public QDeclarativeItemPrivate
54{
55 Q_DECLARE_PUBLIC(QDeclarativeFlipable)
56public:
57 QDeclarativeFlipablePrivate() : current(QDeclarativeFlipable::Front), front(0), back(0) {}
58
59 void updateSceneTransformFromParent();
60 void setBackTransform();
61
62 QDeclarativeFlipable::Side current;
63 QDeclarativeGuard<QGraphicsObject> front;
64 QDeclarativeGuard<QGraphicsObject> back;
65
66 bool wantBackXFlipped;
67 bool wantBackYFlipped;
68};
69
70/*!
71 \qmlclass Flipable QDeclarativeFlipable
72 \since 4.7
73 \ingroup qml-basic-interaction-elements
74 \brief The Flipable item provides a surface that can be flipped.
75 \inherits Item
76
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.
80
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.
83
84 \section1 Example Usage
85
86 The following example shows a Flipable item that flips whenever it is
87 clicked, rotating about the y-axis.
88
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.
95
96 \snippet doc/src/snippets/declarative/flipable/flipable.qml 0
97
98 \image flipable.gif
99
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.
104
105 See \l {QML States} for details on state changes and the default
106 state, and \l {QML Animation} for more information on how animations
107 work within transitions.
108
109 \sa {declarative/ui-components/flipable}{Flipable example}
110*/
111
112QDeclarativeFlipable::QDeclarativeFlipable(QDeclarativeItem *parent)
113: QDeclarativeItem(*(new QDeclarativeFlipablePrivate), parent)
114{
115}
116
117QDeclarativeFlipable::~QDeclarativeFlipable()
118{
119}
120
121/*!
122 \qmlproperty Item Flipable::front
123 \qmlproperty Item Flipable::back
124
125 The front and back sides of the flipable.
126*/
127
128QGraphicsObject *QDeclarativeFlipable::front()
129{
130 Q_D(const QDeclarativeFlipable);
131 return d->front;
132}
133
134void QDeclarativeFlipable::setFront(QGraphicsObject *front)
135{
136 Q_D(QDeclarativeFlipable);
137 if (d->front) {
138 qmlInfo(this) << tr("front is a write-once property");
139 return;
140 }
141 d->front = front;
142 d->front->setParentItem(this);
143 if (Back == d->current)
144 d->front->setOpacity(0.);
145}
146
147QGraphicsObject *QDeclarativeFlipable::back()
148{
149 Q_D(const QDeclarativeFlipable);
150 return d->back;
151}
152
153void QDeclarativeFlipable::setBack(QGraphicsObject *back)
154{
155 Q_D(QDeclarativeFlipable);
156 if (d->back) {
157 qmlInfo(this) << tr("back is a write-once property");
158 return;
159 }
160 d->back = back;
161 d->back->setParentItem(this);
162 if (Front == d->current)
163 d->back->setOpacity(0.);
164 connect(back, SIGNAL(widthChanged()),
165 this, SLOT(retransformBack()));
166 connect(back, SIGNAL(heightChanged()),
167 this, SLOT(retransformBack()));
168}
169
170void QDeclarativeFlipable::retransformBack()
171{
172 Q_D(QDeclarativeFlipable);
173 if (d->current == QDeclarativeFlipable::Back && d->back)
174 d->setBackTransform();
175}
176
177/*!
178 \qmlproperty enumeration Flipable::side
179
180 The side of the Flippable currently visible. Possible values are \c
181 Flippable.Front and \c Flippable.Back.
182*/
183QDeclarativeFlipable::Side QDeclarativeFlipable::side() const
184{
185 Q_D(const QDeclarativeFlipable);
186 if (d->dirtySceneTransform)
187 const_cast<QDeclarativeFlipablePrivate *>(d)->ensureSceneTransform();
188
189 return d->current;
190}
191
192// determination on the currently visible side of the flipable
193// has to be done on the complete scene transform to give
194// correct results.
195void QDeclarativeFlipablePrivate::updateSceneTransformFromParent()
196{
197 Q_Q(QDeclarativeFlipable);
198
199 QDeclarativeItemPrivate::updateSceneTransformFromParent();
200 QPointF p1(0, 0);
201 QPointF p2(1, 0);
202 QPointF p3(1, 1);
203
204 QPointF scenep1 = sceneTransform.map(p1);
205 QPointF scenep2 = sceneTransform.map(p2);
206 QPointF scenep3 = sceneTransform.map(p3);
207 p1 = q->mapToParent(p1);
208 p2 = q->mapToParent(p2);
209 p3 = q->mapToParent(p3);
210
211 qreal cross = (scenep1.x() - scenep2.x()) * (scenep3.y() - scenep2.y()) -
212 (scenep1.y() - scenep2.y()) * (scenep3.x() - scenep2.x());
213
214 wantBackYFlipped = p1.x() >= p2.x();
215 wantBackXFlipped = p2.y() >= p3.y();
216
217 QDeclarativeFlipable::Side newSide;
218 if (cross > 0) {
219 newSide = QDeclarativeFlipable::Back;
220 } else {
221 newSide = QDeclarativeFlipable::Front;
222 }
223
224 if (newSide != current) {
225 current = newSide;
226 if (current == QDeclarativeFlipable::Back && back)
227 setBackTransform();
228 if (front)
229 front->setOpacity((current==QDeclarativeFlipable::Front)?1.:0.);
230 if (back)
231 back->setOpacity((current==QDeclarativeFlipable::Back)?1.:0.);
232 emit q->sideChanged();
233 }
234}
235
236/* Depends on the width/height of the back item, and so needs reevaulating
237 if those change.
238*/
239void QDeclarativeFlipablePrivate::setBackTransform()
240{
241 QTransform mat;
242 QGraphicsItemPrivate *dBack = QGraphicsItemPrivate::get(back);
243 mat.translate(dBack->width()/2,dBack->height()/2);
244 if (dBack->width() && wantBackYFlipped)
245 mat.rotate(180, Qt::YAxis);
246 if (dBack->height() && wantBackXFlipped)
247 mat.rotate(180, Qt::XAxis);
248 mat.translate(-dBack->width()/2,-dBack->height()/2);
249 back->setTransform(mat);
250}
251
252QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.