1 /****************************************************************************
3 ** Copyright (C) 2009 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 demonstration applications 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 "itemcircleanimation.h"
43 #include "demoitemanimation.h"
45 #include "menumanager.h"
46 #include "mainwindow.h"
47 #include "menumanager.h"
49 static QGraphicsScene
*sscene
;
51 //////////////////// POST EFFECT STUFF ////////////////////////////////////////
53 class TickerPostEffect
56 virtual ~TickerPostEffect(){};
57 virtual void tick(float){};
58 virtual void transform(DemoItem
*, QPointF
&){};
61 class PostRotateXY
: public TickerPostEffect
64 float currRotX
, currRotY
;
65 float speedx
, speedy
, curvx
, curvy
;
67 PostRotateXY(float speedx
, float speedy
, float curvx
, float curvy
)
68 : currRotX(0), currRotY(0),
69 speedx(speedx
), speedy(speedy
),
70 curvx(curvx
), curvy(curvy
){};
72 void tick(float adjust
)
74 currRotX
+= speedx
* adjust
;
75 currRotY
+= speedy
* adjust
;
78 void transform(DemoItem
*item
, QPointF
&pos
)
80 DemoItem
*parent
= (DemoItem
*) item
->parentItem();
81 QPointF center
= parent
->boundingRect().center();
82 pos
.setX(center
.x() + (pos
.x() - center
.x()) * cos(currRotX
+ pos
.x() * curvx
));
83 pos
.setY(center
.y() + (pos
.y() - center
.y()) * cos(currRotY
+ pos
.y() * curvy
));
87 class PostRotateXYTwist
: public TickerPostEffect
90 float currRotX
, currRotY
;
91 float speedx
, speedy
, curvx
, curvy
;
93 PostRotateXYTwist(float speedx
, float speedy
, float curvx
, float curvy
)
94 : currRotX(0), currRotY(0),
95 speedx(speedx
), speedy(speedy
),
96 curvx(curvx
), curvy(curvy
){};
98 void tick(float adjust
)
100 currRotX
+= speedx
* adjust
;
101 currRotY
+= speedy
* adjust
;
104 void transform(DemoItem
*item
, QPointF
&pos
)
106 DemoItem
*parent
= (DemoItem
*) item
->parentItem();
107 QPointF center
= parent
->boundingRect().center();
108 pos
.setX(center
.x() + (pos
.x() - center
.x()) * cos(currRotX
+ pos
.y() * curvx
));
109 pos
.setY(center
.y() + (pos
.y() - center
.y()) * cos(currRotY
+ pos
.x() * curvy
));
113 //////////////////// TICKER EFFECT STUFF //////////////////////////////////////
117 TickerPostEffect
*postEffect
;
119 enum EffectStatus
{Normal
, Intro
, Outro
} status
;
121 float morphSpeed
, moveSpeed
;
122 float normalMorphSpeed
, normalMoveSpeed
;
123 bool useSheepDog
, morphBetweenModels
;
125 TickerEffect(LetterList
*letters
)
126 : postEffect(new TickerPostEffect()), status(Intro
), letters(letters
),
127 morphSpeed(Colors::tickerMorphSpeed
), moveSpeed(Colors::tickerMoveSpeed
),
128 normalMorphSpeed(Colors::tickerMorphSpeed
), normalMoveSpeed(Colors::tickerMoveSpeed
),
129 useSheepDog(true), morphBetweenModels(!Colors::noTickerMorph
){}
131 void setPostEffect(TickerPostEffect
*effect
)
137 virtual ~TickerEffect()
142 void slowDownAfterIntro(float adjust
)
144 if (morphBetweenModels
){
145 if (status
== Intro
){
146 float dec
= 0.1 * adjust
;
148 if (moveSpeed
< Colors::tickerMoveSpeed
){
149 moveSpeed
= normalMoveSpeed
;
150 morphSpeed
= normalMorphSpeed
;
157 void moveLetters(float adjust
)
159 float adaptedMoveSpeed
= this->moveSpeed
* adjust
;
160 float adaptedMorphSpeed
= this->morphSpeed
* adjust
;
161 postEffect
->tick(adjust
);
163 for (int i
=0; i
<letters
->size(); i
++){
164 LetterItem
*letter
= letters
->at(i
);
165 letter
->guideAdvance(this->morphBetweenModels
? adaptedMoveSpeed
: Colors::tickerMoveSpeed
);
166 letter
->guideMove(this->morphBetweenModels
? adaptedMorphSpeed
: -1);
168 QPointF pos
= letter
->getGuidedPos();
169 postEffect
->transform(letter
, pos
);
172 letter
->setPosUsingSheepDog(pos
, QRectF(0, 0, 800, 600));
178 virtual void tick(float adjust
)
180 slowDownAfterIntro(adjust
);
186 class EffectWhirlWind
: public TickerEffect
189 EffectWhirlWind(LetterList
*letters
) : TickerEffect(letters
)
192 for (int i
=0; i
<this->letters
->size(); i
++){
193 LetterItem
*letter
= this->letters
->at(i
);
194 letter
->setGuidedPos(QPointF(0, 100));
199 class EffectSnake
: public TickerEffect
202 EffectSnake(LetterList
*letters
) : TickerEffect(letters
)
205 for (int i
=0; i
<this->letters
->size(); i
++){
206 LetterItem
*letter
= this->letters
->at(i
);
207 letter
->setGuidedPos(QPointF(0, -250 - (i
* 5)));
212 class EffectScan
: public TickerEffect
215 EffectScan(LetterList
*letters
) : TickerEffect(letters
)
217 for (int i
=0; i
<this->letters
->size(); i
++){
218 LetterItem
*letter
= this->letters
->at(i
);
219 letter
->setGuidedPos(QPointF(100, -300));
224 class EffectRaindrops
: public TickerEffect
227 EffectRaindrops(LetterList
*letters
) : TickerEffect(letters
)
229 for (int i
=0; i
<this->letters
->size(); i
++){
230 LetterItem
*letter
= this->letters
->at(i
);
231 letter
->setGuidedPos(QPointF(-100 + rand() % 200, - 200.0f
- rand() % 1300));
236 class EffectLine
: public TickerEffect
239 EffectLine(LetterList
*letters
) : TickerEffect(letters
)
241 for (int i
=0; i
<this->letters
->size(); i
++){
242 LetterItem
*letter
= this->letters
->at(i
);
243 letter
->setGuidedPos(QPointF(100, 500.0f
+ i
* 20));
248 //////////////////// TICKER STUFF /////////////////////////////////////////////
250 ItemCircleAnimation::ItemCircleAnimation(QGraphicsScene
*scene
, QGraphicsItem
*parent
)
251 : DemoItem(scene
, parent
)
254 this->letterCount
= Colors::tickerLetterCount
;
256 this->showCount
= -1;
257 this->tickOnPaint
= false;
258 this->paused
= false;
259 this->doIntroTransitions
= true;
260 this->setAcceptsHoverEvents(true);
261 this->setCursor(Qt::OpenHandCursor
);
263 this->setupLetters();
265 this->effect
= 0;//new TickerEffect(this->letterList);
268 ItemCircleAnimation::~ItemCircleAnimation()
270 delete this->letterList
;
271 delete this->qtGuide1
;
272 delete this->qtGuide2
;
273 delete this->qtGuide3
;
277 void ItemCircleAnimation::createLetter(char c
)
279 LetterItem
*letter
= new LetterItem(c
, sscene
, this);
280 this->letterList
->append(letter
);
283 void ItemCircleAnimation::setupLetters()
285 this->letterList
= new LetterList();
287 QString s
= Colors::tickerText
;
288 int len
= s
.length();
290 for (; i
< this->letterCount
- len
; i
+= len
)
291 for (int l
=0; l
<len
; l
++)
292 createLetter(s
[l
].toLatin1());
294 // Fill inn with blanks:
295 for (; i
< this->letterCount
; ++i
)
299 void ItemCircleAnimation::setupGuides()
304 this->qtGuide1
= new GuideCircle(QRectF(x
, y
, 260, 260), -36, 342);
305 new GuideLine(QPointF(x
+ 240, y
+ 268), this->qtGuide1
);
306 new GuideLine(QPointF(x
+ 265, y
+ 246), this->qtGuide1
);
307 new GuideLine(QPointF(x
+ 158, y
+ 134), this->qtGuide1
);
308 new GuideLine(QPointF(x
+ 184, y
+ 109), this->qtGuide1
);
309 new GuideLine(QPointF(x
+ 160, y
+ 82), this->qtGuide1
);
310 new GuideLine(QPointF(x
+ 77, y
+ 163), this->qtGuide1
); // T-top
311 new GuideLine(QPointF(x
+ 100, y
+ 190), this->qtGuide1
);
312 new GuideLine(QPointF(x
+ 132, y
+ 159), this->qtGuide1
);
313 new GuideLine(QPointF(x
+ 188, y
+ 211), this->qtGuide1
);
314 new GuideCircle(QRectF(x
+ 30, y
+ 30, 200, 200), -30, 336, GuideCircle::CW
, this->qtGuide1
);
315 new GuideLine(QPointF(x
+ 238, y
+ 201), this->qtGuide1
);
318 this->qtGuide2
= new GuideCircle(QRectF(x
+ 30, y
+ 30, 200, 200), 135, 270, GuideCircle::CCW
);
319 new GuideLine(QPointF(x
+ 222, y
+ 38), this->qtGuide2
);
320 new GuideCircle(QRectF(x
, y
, 260, 260), 135, 270, GuideCircle::CW
, this->qtGuide2
);
321 new GuideLine(QPointF(x
+ 59, y
+ 59), this->qtGuide2
);
325 this->qtGuide3
= new GuideLine(QLineF(x
, y
, x
+ 30, y
));
326 new GuideLine(QPointF(x
+ 30, y
+ 170), this->qtGuide3
);
327 new GuideLine(QPointF(x
, y
+ 170), this->qtGuide3
);
328 new GuideLine(QPointF(x
, y
), this->qtGuide3
);
330 this->qtGuide1
->setFence(QRectF(0, 0, 800, 600));
331 this->qtGuide2
->setFence(QRectF(0, 0, 800, 600));
332 this->qtGuide3
->setFence(QRectF(0, 0, 800, 600));
335 void ItemCircleAnimation::useGuide(Guide
*guide
, int firstLetter
, int lastLetter
)
337 float padding
= guide
->lengthAll() / float(lastLetter
- firstLetter
);
338 for (int i
=firstLetter
; i
<lastLetter
; i
++){
339 LetterItem
*letter
= this->letterList
->at(i
);
340 letter
->useGuide(guide
, (i
- firstLetter
) * padding
);
344 void ItemCircleAnimation::useGuideQt()
346 if (this->currGuide
!= this->qtGuide1
){
347 this->useGuide(qtGuide1
, 0, this->letterCount
);
348 this->currGuide
= qtGuide1
;
352 void ItemCircleAnimation::useGuideTt()
354 if (this->currGuide
!= this->qtGuide2
){
355 int split
= int(this->letterCount
* 5.0 / 7.0);
356 this->useGuide(qtGuide2
, 0, split
);
357 this->useGuide(qtGuide3
, split
, this->letterCount
);
358 this->currGuide
= qtGuide2
;
362 QRectF
ItemCircleAnimation::boundingRect() const
364 return QRectF(0, 0, 300, 320);
367 void ItemCircleAnimation::prepare()
371 void ItemCircleAnimation::switchToNextEffect()
376 switch (this->showCount
){
378 this->effect
= new EffectSnake(this->letterList
);
381 this->effect
= new EffectLine(this->letterList
);
382 this->effect
->setPostEffect(new PostRotateXYTwist(0.01f
, 0.0f
, 0.003f
, 0.0f
));
385 this->effect
= new EffectRaindrops(this->letterList
);
386 this->effect
->setPostEffect(new PostRotateXYTwist(0.01f
, 0.005f
, 0.003f
, 0.003f
));
389 this->effect
= new EffectScan(this->letterList
);
390 this->effect
->normalMoveSpeed
= 0;
391 this->effect
->setPostEffect(new PostRotateXY(0.008f
, 0.0f
, 0.005f
, 0.0f
));
395 this->effect
= new EffectWhirlWind(this->letterList
);
399 void ItemCircleAnimation::animationStarted(int id
)
401 if (id
== DemoItemAnimation::ANIM_IN
){
402 if (this->doIntroTransitions
){
403 // Make all letters dissapear
404 for (int i
=0; i
<this->letterList
->size(); i
++){
405 LetterItem
*letter
= this->letterList
->at(i
);
406 letter
->setPos(1000, 0);
408 this->switchToNextEffect();
411 // The first time we run, we have a rather large
412 // delay to perform benchmark before the ticker shows.
413 // But now, since we are showing, use a more appropriate value:
414 this->currentAnimation
->startDelay
= 1500;
417 else if (this->effect
)
418 this->effect
->useSheepDog
= false;
420 this->tickTimer
= QTime::currentTime();
423 void ItemCircleAnimation::animationStopped(int)
428 void ItemCircleAnimation::swapModel(){
429 if (this->currGuide
== this->qtGuide2
)
435 void ItemCircleAnimation::hoverEnterEvent(QGraphicsSceneHoverEvent
*)
437 // Skip swap here to enhance ticker dragging
438 // this->swapModel();
441 void ItemCircleAnimation::hoverLeaveEvent(QGraphicsSceneHoverEvent
*)
446 void ItemCircleAnimation::setTickerScale(float s
)
449 qtGuide1
->setScale(this->scale
, this->scale
);
450 qtGuide2
->setScale(this->scale
, this->scale
);
451 qtGuide3
->setScale(this->scale
, this->scale
);
454 void ItemCircleAnimation::mousePressEvent(QGraphicsSceneMouseEvent
*event
)
456 this->mouseMoveLastPosition
= event
->scenePos();
457 if (event
->button() == Qt::LeftButton
)
458 this->setCursor(Qt::ClosedHandCursor
);
460 this->switchToNextEffect();
463 void ItemCircleAnimation::mouseReleaseEvent(QGraphicsSceneMouseEvent
*event
)
465 if (event
->button() == Qt::LeftButton
)
466 this->setCursor(Qt::OpenHandCursor
);
469 void ItemCircleAnimation::mouseMoveEvent(QGraphicsSceneMouseEvent
*event
)
471 QPointF newPosition
= event
->scenePos();
472 this->setPosUsingSheepDog(this->pos() + newPosition
- this->mouseMoveLastPosition
, QRectF(-260, -280, 1350, 1160));
473 this->mouseMoveLastPosition
= newPosition
;
476 void ItemCircleAnimation::wheelEvent(QGraphicsSceneWheelEvent
*event
)
478 this->effect
->moveSpeed
= this->effect
->moveSpeed
+ (event
->delta() > 0 ? -0.20 : 0.20);
479 if (this->effect
->moveSpeed
< 0)
480 this->effect
->moveSpeed
= 0;
483 void ItemCircleAnimation::pause(bool on
)
486 this->tickTimer
= QTime::currentTime();
489 void ItemCircleAnimation::tick()
491 if (this->paused
|| !this->effect
)
494 float t
= this->tickTimer
.msecsTo(QTime::currentTime());
495 this->tickTimer
= QTime::currentTime();
496 this->effect
->tick(t
/10.0f
);
499 void ItemCircleAnimation::paint(QPainter
*, const QStyleOptionGraphicsItem
*, QWidget
*)
501 if (this->tickOnPaint
)