on 60de064 help sign in
unity8/Greeter/Infographics.qml
455 lines 15 kB history raw
1/*
2 * Copyright (C) 2013 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
17import "../Components"
18import "Gradient.js" as Gradient
19import QtQuick 2.0
20import Ubuntu.Components 0.1
22Item {
23 id: infographic
25 property var model
27 property int animDuration: 10
29 Connections {
30 target: model
32 onDataAppeared: startShowAnimation()
34 onDataAboutToChange: startHideAnimation()
36 onDataChanged: startShowAnimation()
38 onDataAboutToDisappear: startHideAnimation()
39 }
41 function startShowAnimation() {
42 dotShowAnimTimer.startFromBeginning()
43 notification.showAnim.start()
44 }
46 function startHideAnimation() {
47 dotHideAnimTimer.startFromBeginning()
48 notification.hideAnim.start()
49 }
51 visible: model.label !== ""
53 Component.onCompleted: startShowAnimation()
55 Item {
56 id: dataCircle
57 objectName: "dataCircle"
59 property real divisor: 1.5
61 width: Math.min(parent.height, parent.width) / divisor
62 height: width
64 anchors.centerIn: parent
66 Timer {
67 id: circleGrowAnimTimer
69 property int pastCircleCounter
70 property int presentCircleCounter
72 interval: animDuration
73 running: false
74 repeat: true
75 onTriggered: {
76 if (pastCircleCounter < pastCircles.count) {
77 var nextCircle = pastCircles.itemAt(pastCircleCounter++)
78 if (nextCircle !== null) nextCircle.pastCircleGrowAnim.start()
79 }
80 if (pastCircleCounter > pastCircles.count / 2) {
81 var nextCircle = presentCircles.itemAt(presentCircleCounter++)
82 if (nextCircle !== null) nextCircle.presentCircleGrowAnim.start()
83 }
84 if (presentCircleCounter > infographic.model.currentDay) {
85 stop()
86 }
87 }
89 function startFromBeginning() {
90 circleGrowAnimTimer.pastCircleCounter = 0
91 circleGrowAnimTimer.presentCircleCounter = 0
92 start()
93 }
94 }
96 Timer {
97 id: circleShrinkAnimTimer
99 property int pastCircleCounter
100 property int presentCircleCounter
102 interval: animDuration
103 running: false
104 repeat: true
105 onTriggered: {
106 if (pastCircleCounter >= 0) {
107 var nextCircle = pastCircles.itemAt(pastCircleCounter--)
108 if (nextCircle !== null) nextCircle.pastCircleShrinkAnim.start()
109 }
110 if (pastCircleCounter < pastCircles.count / 2) {
111 var nextCircle = presentCircles.itemAt(presentCircleCounter--)
112 if (nextCircle !== null) nextCircle.presentCircleShrinkAnim.start()
113 }
114 if (presentCircleCounter < 0) {
115 stop()
116 infographic.model.readyForDataChange()
117 }
118 }
120 function startFromBeginning() {
121 pastCircleCounter = pastCircles.count - 1
122 presentCircleCounter = model.currentDay
123 start()
124 }
125 }
127 Repeater {
128 id: pastCircles
129 objectName: "pastCircles"
130 model: infographic.model.secondMonth
132 delegate: ObjectPositioner {
133 property alias pastCircleGrowAnim: pastCircleGrowAnim
134 property alias pastCircleShrinkAnim: pastCircleShrinkAnim
136 index: model.index
137 count: pastCircles.count
138 radius: parent.width / 2
139 halfSize: pastCircle.width / 2
140 posOffset: 0.0
142 Circle {
143 id: pastCircle
144 objectName: "pastCircle" + index
146 property real divisor: 1.8
147 property real circleOpacity: 0.1
149 width: dataCircle.width / divisor
150 height: dataCircle.height / divisor
151 opacity: 0.0
152 scale: 0.0
153 visible: modelData !== undefined
154 color: Gradient.threeColorByIndex(index, count, infographic.model.secondColor)
156 SequentialAnimation {
157 id: pastCircleGrowAnim
159 loops: 1
160 ParallelAnimation {
161 PropertyAnimation {
162 target: pastCircle
163 property: "opacity"
164 from: 0.0
165 to: pastCircle.circleOpacity
166 easing.type: Easing.OutCurve
167 duration: circleGrowAnimTimer.interval * 4
168 }
169 PropertyAnimation {
170 target: pastCircle
171 property: "scale"
172 from: 0.0
173 to: modelData
174 easing.type: Easing.OutCurve
175 duration: circleGrowAnimTimer.interval * 4
176 }
177 }
178 }
180 SequentialAnimation {
181 id: pastCircleShrinkAnim
183 loops: 1
184 ParallelAnimation {
185 PropertyAnimation {
186 target: pastCircle
187 property: "opacity"
188 from: pastCircle.circleOpacity
189 to: 0.0
190 easing.type: Easing.OutCurve
191 duration: circleShrinkAnimTimer.interval * 4
192 }
193 PropertyAnimation {
194 target: pastCircle
195 property: "scale"
196 from: modelData
197 to: 0.0
198 easing.type: Easing.OutCurve
199 duration: circleShrinkAnimTimer.interval * 4
200 }
201 }
202 }
203 }
204 }
205 }
207 Repeater {
208 id: presentCircles
209 objectName: "presentCircles"
210 model: infographic.model.firstMonth
212 delegate: ObjectPositioner {
213 property alias presentCircleGrowAnim: presentCircleGrowAnim
214 property alias presentCircleShrinkAnim: presentCircleShrinkAnim
216 index: model.index
217 count: presentCircles.count
218 radius: parent.width / 2
219 halfSize: presentCircle.width / 2
220 posOffset: 0.0
222 Circle {
223 id: presentCircle
224 objectName: "presentCircle" + index
226 property real divisor: 1.8
227 property real circleOpacity: 0.3
229 width: dataCircle.width / divisor
230 height: dataCircle.height / divisor
231 opacity: 0.0
232 scale: 0.0
233 visible: modelData !== undefined
234 color: Gradient.threeColorByIndex(index, infographic.model.currentDay, infographic.model.firstColor)
236 SequentialAnimation {
237 id: presentCircleGrowAnim
239 loops: 1
241 ParallelAnimation {
242 PropertyAnimation {
243 target: presentCircle
244 property: "opacity"
245 to: presentCircle.circleOpacity
246 easing.type: Easing.OutCurve
247 duration: circleGrowAnimTimer.interval * 4
248 }
249 PropertyAnimation {
250 target: presentCircle
251 property: "scale"
252 to: modelData
253 easing.type: Easing.OutCurve
254 duration: circleGrowAnimTimer.interval * 4
255 }
256 }
257 }
259 SequentialAnimation {
260 id: presentCircleShrinkAnim
262 loops: 1
263 ParallelAnimation {
264 PropertyAnimation {
265 target: presentCircle
266 property: "opacity"
267 to: 0.0
268 easing.type: Easing.OutCurve
269 duration: circleShrinkAnimTimer.interval * 4
270 }
271 PropertyAnimation {
272 target: presentCircle
273 property: "scale"
274 to: 0.0
275 easing.type: Easing.OutCurve
276 duration: circleShrinkAnimTimer.interval * 4
277 }
278 }
279 }
280 }
281 }
282 }
284 Image {
285 id: backgroundCircle
286 objectName: "backgroundCircle"
288 anchors.fill: parent
289 opacity: 0.9
291 source: "graphics/infographic_circle.png"
292 }
294 Timer {
295 id: dotShowAnimTimer
297 property int dotCounter: 0
299 interval: animDuration * 0.5; running: false; repeat: true
300 onTriggered: {
301 if (dotCounter < dots.count) {
302 var nextDot = dots.itemAt(dotCounter++)
303 nextDot.unlockAnimation.start()
304 } else {
305 stop()
306 }
307 if (dotCounter == Math.round(dots.count / 2)) {
308 circleGrowAnimTimer.startFromBeginning()
309 }
310 }
312 function startFromBeginning() {
313 if (!dotShowAnimTimer.running)
314 dotCounter = 0
316 start()
317 }
318 }
320 Timer {
321 id: dotHideAnimTimer
323 property int dotCounter
325 interval: animDuration * 0.5
326 running: false
327 repeat: true
328 onTriggered: {
329 if (dotCounter >= 0) {
330 var nextDot = dots.itemAt(dotCounter--)
331 nextDot.changeAnimation.start()
332 } else {
333 stop()
334 }
335 if (dotCounter == Math.round(dots.count / 2)) {
336 circleShrinkAnimTimer.startFromBeginning()
337 }
338 }
340 function startFromBeginning() {
341 if (!dotHideAnimTimer.running)
342 dotCounter = dots.count - 1
344 start()
345 }
346 }
348 Repeater {
349 id: dots
350 objectName: "dots"
352 model: infographic.model.firstMonth
354 delegate: ObjectPositioner {
355 property alias unlockAnimation: dotUnlockAnim
356 property alias changeAnimation: dotChangeAnim
358 property int currentDay: infographic.model.currentDay
360 index: model.index
361 count: dots.count
362 radius: backgroundCircle.width / 2
363 halfSize: dot.width / 2
364 posOffset: radius / dot.width / 3
365 state: dot.state
367 Dot {
368 id: dot
369 objectName: "dot" + index
371 property real baseOpacity: 0.4
373 width: units.dp(5) * parent.radius / 200
374 height: units.dp(5) * parent.radius / 200
375 opacity: 0.0
376 smooth: true
377 state: index < currentDay ? "filled" : index == currentDay ? "pointer" : "unfilled"
379 PropertyAnimation {
380 id: dotUnlockAnim
382 target: dot
383 property: "opacity"
384 to: dot.baseOpacity
385 duration: dotShowAnimTimer.interval
386 }
388 PropertyAnimation {
389 id: dotChangeAnim
391 target: dot
392 property: "opacity"
393 to: 0.0
394 duration: dotHideAnimTimer.interval
395 }
396 }
397 }
398 }
400 Text {
401 id: notification
402 objectName: "label"
404 property alias hideAnim: decreaseOpacity
405 property alias showAnim: increaseOpacity
407 property real baseOpacity: 0.6
409 height: 0.7 * backgroundCircle.width
410 width: notification.height
411 anchors.centerIn: parent
413 text: infographic.model.label
414 font.pixelSize: notification.height / 12
416 wrapMode: Text.WordWrap
417 horizontalAlignment: Text.AlignHCenter
418 verticalAlignment: Text.AlignVCenter
419 color: "white"
420 font.weight: Font.Light
422 PropertyAnimation {
423 id: increaseOpacity
425 target: notification
426 property: "opacity"
427 from: 0.0
428 to: notification.baseOpacity
429 duration: dotShowAnimTimer.interval * dots.count * 5
430 }
432 PropertyAnimation {
433 id: decreaseOpacity
435 target: notification
436 property: "opacity"
437 from: notification.baseOpacity
438 to: 0.0
439 duration: dotShowAnimTimer.interval * dots.count * 5
440 }
441 }
442 }
444 MouseArea {
445 anchors.fill: dataCircle
447 onDoubleClicked: {
448 if (!dotHideAnimTimer.running &&
449 !dotShowAnimTimer.running &&
450 !circleShrinkAnimTimer.running &&
451 !circleGrowAnimTimer.running)
452 infographic.model.nextDataSource()
453 }
454 }