Add support for using AnimatedTiles as a standalone widget.
[qt:qt-ios-plaszma.git] / examples / animation / animatedtiles / main.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
10 **
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
13 ** met:
14 **   * Redistributions of source code must retain the above copyright
15 **     notice, this list of conditions and the following disclaimer.
16 **   * Redistributions in binary form must reproduce the above copyright
17 **     notice, this list of conditions and the following disclaimer in
18 **     the documentation and/or other materials provided with the
19 **     distribution.
20 **   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
21 **     of its contributors may be used to endorse or promote products derived
22 **     from this software without specific prior written permission.
23 **
24 **
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40
41 #include <QtGui>
42 #include <QtCore/qstate.h>
43
44 // Enable this for standalone
45 #define USE_MAIN
46
47 //#define USE_OPENGL
48 #ifdef USE_OPENGL
49 #include <QtOpenGL>
50 #endif
51
52 class Pixmap : public QObject, public QGraphicsPixmapItem
53 {
54     Q_OBJECT
55     Q_PROPERTY(QPointF pos READ pos WRITE setPos)
56 public:
57     Pixmap(const QPixmap &pix)
58         : QObject(), QGraphicsPixmapItem(pix)
59     {
60         setCacheMode(DeviceCoordinateCache);
61     }
62 };
63
64 class Button : public QGraphicsWidget
65 {
66     Q_OBJECT
67 public:
68     Button(const QPixmap &pixmap, QGraphicsItem *parent = 0)
69         : QGraphicsWidget(parent), _pix(pixmap)
70     {
71         setAcceptHoverEvents(true);
72         setCacheMode(DeviceCoordinateCache);
73     }
74
75     QRectF boundingRect() const
76     {
77         return QRectF(-65, -65, 130, 130);
78     }
79
80     QPainterPath shape() const
81     {
82         QPainterPath path;
83         path.addEllipse(boundingRect());
84         return path;
85     }
86
87     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
88     {
89         bool down = option->state & QStyle::State_Sunken;
90         QRectF r = boundingRect();
91         QLinearGradient grad(r.topLeft(), r.bottomRight());
92         grad.setColorAt(down ? 1 : 0, option->state & QStyle::State_MouseOver ? Qt::white : Qt::lightGray);
93         grad.setColorAt(down ? 0 : 1, Qt::darkGray);
94         painter->setPen(Qt::darkGray);
95         painter->setBrush(grad);
96         painter->drawEllipse(r);
97         QLinearGradient grad2(r.topLeft(), r.bottomRight());
98         grad.setColorAt(down ? 1 : 0, Qt::darkGray);
99         grad.setColorAt(down ? 0 : 1, Qt::lightGray);
100         painter->setPen(Qt::NoPen);
101         painter->setBrush(grad);
102         if (down)
103             painter->translate(2, 2);
104         painter->drawEllipse(r.adjusted(5, 5, -5, -5));
105         painter->drawPixmap(-_pix.width()/2, -_pix.height()/2, _pix);
106     }
107
108 signals:
109     void pressed();
110
111 protected:
112     void mousePressEvent(QGraphicsSceneMouseEvent *)
113     {
114         emit pressed();
115         update();
116     }
117
118     void mouseReleaseEvent(QGraphicsSceneMouseEvent *)
119     {
120         update();
121     }
122
123 private:
124     QPixmap _pix;
125 };
126
127 class View : public QGraphicsView
128 {
129 public:
130     View(QGraphicsScene *scene) : QGraphicsView(scene) { }
131
132 protected:
133     void resizeEvent(QResizeEvent *event)
134     {
135         QGraphicsView::resizeEvent(event);
136         fitInView(sceneRect(), Qt::KeepAspectRatio);
137     }
138 };
139
140 #ifndef USE_MAIN
141 #include "animatedtilesview.h"
142
143 QAnimatedTilesView::QAnimatedTilesView()
144     : scene(-350, -350, 700, 700)
145 {
146     Q_INIT_RESOURCE(animatedtiles);
147
148     kineticPix = QPixmap(":/images/kinetic.png");
149     bgPix = QPixmap(":/images/Time-For-Lunch-2.jpg");
150
151 #else // USE_MAIN
152 int main(int argc, char **argv)
153 {
154     Q_INIT_RESOURCE(animatedtiles);
155
156     QApplication app(argc, argv);
157
158     QPixmap kineticPix(":/images/kinetic.png");
159     QPixmap bgPix(":/images/Time-For-Lunch-2.jpg");
160
161     QGraphicsScene scene(-350, -350, 700, 700);
162 #endif // USE_MAIN
163
164     QList<Pixmap *> items;
165     for (int i = 0; i < 64; ++i) {
166         Pixmap *item = new Pixmap(kineticPix);
167         item->setOffset(-kineticPix.width()/2, -kineticPix.height()/2);
168         item->setZValue(i);
169         items << item;
170         scene.addItem(item);
171     }
172
173     // Buttons
174     QGraphicsItem *buttonParent = new QGraphicsRectItem;
175     Button *ellipseButton = new Button(QPixmap(":/images/ellipse.png"), buttonParent);
176     Button *figure8Button = new Button(QPixmap(":/images/figure8.png"), buttonParent);
177     Button *randomButton = new Button(QPixmap(":/images/random.png"), buttonParent);
178     Button *tiledButton = new Button(QPixmap(":/images/tile.png"), buttonParent);
179     Button *centeredButton = new Button(QPixmap(":/images/centered.png"), buttonParent);
180
181     ellipseButton->setPos(-100, -100);
182     figure8Button->setPos(100, -100);
183     randomButton->setPos(0, 0);
184     tiledButton->setPos(-100, 100);
185     centeredButton->setPos(100, 100);
186
187     scene.addItem(buttonParent);
188     buttonParent->scale(0.75, 0.75);
189     buttonParent->setPos(200, 200);
190     buttonParent->setZValue(65);
191
192     // States
193     QState *rootState = new QState;
194     QState *ellipseState = new QState(rootState);
195     QState *figure8State = new QState(rootState);
196     QState *randomState = new QState(rootState);
197     QState *tiledState = new QState(rootState);
198     QState *centeredState = new QState(rootState);
199
200     // Values
201     for (int i = 0; i < items.count(); ++i) {
202         Pixmap *item = items.at(i);
203         // Ellipse
204         ellipseState->assignProperty(item, "pos",
205                                          QPointF(cos((i / 63.0) * 6.28) * 250,
206                                                  sin((i / 63.0) * 6.28) * 250));
207
208         // Figure 8
209         figure8State->assignProperty(item, "pos",
210                                          QPointF(sin((i / 63.0) * 6.28) * 250,
211                                                  sin(((i * 2)/63.0) * 6.28) * 250));
212
213         // Random
214         randomState->assignProperty(item, "pos",
215                                         QPointF(-250 + qrand() % 500,
216                                                 -250 + qrand() % 500));
217
218         // Tiled
219         tiledState->assignProperty(item, "pos",
220                                        QPointF(((i % 8) - 4) * kineticPix.width() + kineticPix.width() / 2,
221                                                ((i / 8) - 4) * kineticPix.height() + kineticPix.height() / 2));
222
223         // Centered
224         centeredState->assignProperty(item, "pos", QPointF());
225     }
226
227 #ifdef USE_MAIN
228     // Ui
229     View *view = new View(&scene);
230     view->setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Animated Tiles"));
231 #ifdef USE_OPENGL
232     // Use OpenGL
233     view->setViewport(new QGLWidget);
234     view->setViewportUpdateMode( QGraphicsView::FullViewportUpdate );
235 #else
236     view->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
237 #endif
238     view->setBackgroundBrush(bgPix);
239     view->setCacheMode(QGraphicsView::CacheBackground);
240     view->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
241 #ifdef Q_OS_SYMBIAN
242     view->showMaximized();
243 #elif defined( Q_OS_IOS ) || defined( Q_OS_PLASZMA )
244     view->showFullScreen();
245 #else
246     view->show();
247 #endif
248
249     QStateMachine states;
250 #endif // USE_MAIN
251
252     states.addState(rootState);
253     states.setInitialState(rootState);
254     rootState->setInitialState(centeredState);
255
256     QParallelAnimationGroup *group = new QParallelAnimationGroup;
257     for (int i = 0; i < items.count(); ++i) {
258         QPropertyAnimation *anim = new QPropertyAnimation(items[i], "pos");
259         anim->setDuration(750 + i * 25);
260         anim->setEasingCurve(QEasingCurve::InOutBack);
261         group->addAnimation(anim);
262     }
263     QAbstractTransition *trans = rootState->addTransition(ellipseButton, SIGNAL(pressed()), ellipseState);
264     trans->addAnimation(group);
265
266     trans = rootState->addTransition(figure8Button, SIGNAL(pressed()), figure8State);
267     trans->addAnimation(group);
268
269     trans = rootState->addTransition(randomButton, SIGNAL(pressed()), randomState);
270     trans->addAnimation(group);
271
272     trans = rootState->addTransition(tiledButton, SIGNAL(pressed()), tiledState);
273     trans->addAnimation(group);
274
275     trans = rootState->addTransition(centeredButton, SIGNAL(pressed()), centeredState);
276     trans->addAnimation(group);
277
278 #ifdef USE_MAIN
279     QTimer timer;
280     timer.start(125);
281 #endif // USE_MAIN
282     timer.setSingleShot(true);
283     trans = rootState->addTransition(&timer, SIGNAL(timeout()), ellipseState);
284     trans->addAnimation(group);
285
286 #ifdef USE_MAIN
287     states.start();
288
289 #ifdef QT_KEYPAD_NAVIGATION
290     QApplication::setNavigationMode(Qt::NavigationModeCursorAuto);
291 #endif
292     return app.exec();
293 #endif // USE_MAIN
294 }
295
296 #ifndef USE_MAIN
297 void QAnimatedTilesView::show()
298 {
299     // Ui
300     view = new View(&scene);
301     view->setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Animated Tiles"));
302 #ifdef USE_OPENGL
303     // Use OpenGL
304     view->setViewport(new QGLWidget);
305     view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
306 #else
307     view->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
308 #endif
309     view->setBackgroundBrush(bgPix);
310     view->setCacheMode(QGraphicsView::CacheBackground);
311     view->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
312     view->show();
313
314     timer.start(125);
315     states.start();
316 }
317 #endif // USE_MAIN
318
319 #include "main.moc"