2 * Copyright (C) 2013 Canonical, Ltd.
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.
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.
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/>.
17 import "../Components"
18 import "Gradient.js" as Gradient
20 import Ubuntu.Components 0.1
27 property int animDuration: 10
31 objectName: "infographicPrivate"
32 property bool useDotAnimation: true
33 property int circleModifier: useDotAnimation ? 1 : 2
34 property bool animating: dotHideAnimTimer.running
35 || dotShowAnimTimer.running
36 || circleChangeAnimTimer.running
42 onDataAboutToAppear: startHideAnimation() // hide "no data" label
43 onDataAppeared: startShowAnimation()
45 onDataAboutToChange: startHideAnimation()
46 onDataChanged: startShowAnimation()
48 onDataAboutToDisappear: startHideAnimation()
49 onDataDisappeared: startShowAnimation() // show "no data" label
52 function startShowAnimation() {
53 dotHideAnimTimer.stop()
54 notification.hideAnim.stop()
56 if (d.useDotAnimation) {
57 dotShowAnimTimer.startFromBeginning()
59 notification.showAnim.start()
62 function startHideAnimation() {
63 dotShowAnimTimer.stop()
64 circleChangeAnimTimer.stop()
65 notification.showAnim.stop()
67 if (d.useDotAnimation) {
68 dotHideAnimTimer.startFromBeginning()
70 circleChangeAnimTimer.startFromBeginning()
72 notification.hideAnim.start()
75 visible: model.label !== ""
77 Component.onCompleted: startShowAnimation()
81 objectName: "dataCircle"
83 property real divisor: 1.5
85 width: Math.min(parent.height, parent.width) / divisor
88 anchors.centerIn: parent
91 id: circleChangeAnimTimer
93 property int pastCircleCounter
94 property int presentCircleCounter
96 interval: notification.duration
100 if (pastCircleCounter < pastCircles.count) {
101 var nextCircle = pastCircles.itemAt(pastCircleCounter++)
102 if (nextCircle !== null) nextCircle.pastCircleChangeAnim.start()
104 if (pastCircleCounter > pastCircles.count / 2) {
105 var nextCircle = presentCircles.itemAt(presentCircleCounter++)
106 if (nextCircle !== null) nextCircle.presentCircleChangeAnim.start()
108 if (presentCircleCounter > infographic.model.currentDay && pastCircleCounter >= pastCircles.count) {
113 function startFromBeginning() {
114 circleChangeAnimTimer.pastCircleCounter = 0
115 circleChangeAnimTimer.presentCircleCounter = 0
122 objectName: "pastCircles"
123 model: infographic.model.secondMonth
125 delegate: ObjectPositioner {
126 property alias pastCircleChangeAnim: pastCircleChangeAnim
129 count: pastCircles.count
130 radius: parent.width / 2
131 halfSize: pastCircle.width / 2
136 objectName: "pastCircle" + index
138 property real divisor: 1.8
139 property real circleOpacity: 0.1
141 width: dataCircle.width / divisor
142 height: dataCircle.height / divisor
145 visible: modelData !== undefined
148 SequentialAnimation {
149 id: pastCircleChangeAnim
156 to: pastCircle.circleOpacity
157 easing.type: Easing.OutCurve
158 duration: circleChangeAnimTimer.interval * d.circleModifier
164 easing.type: Easing.OutCurve
165 duration: circleChangeAnimTimer.interval * d.circleModifier
170 to: Gradient.threeColorByIndex(index, count, infographic.model.secondColor)
171 easing.type: Easing.OutCurve
172 duration: circleChangeAnimTimer.interval * d.circleModifier
182 objectName: "presentCircles"
183 model: infographic.model.firstMonth
185 delegate: ObjectPositioner {
186 property alias presentCircleChangeAnim: presentCircleChangeAnim
189 count: presentCircles.count
190 radius: parent.width / 2
191 halfSize: presentCircle.width / 2
196 objectName: "presentCircle" + index
198 property real divisor: 1.8
199 property real circleOpacity: 0.3
201 width: dataCircle.width / divisor
202 height: dataCircle.height / divisor
205 visible: modelData !== undefined
208 SequentialAnimation {
209 id: presentCircleChangeAnim
215 target: presentCircle
217 to: presentCircle.circleOpacity
218 easing.type: Easing.OutCurve
219 duration: circleChangeAnimTimer.interval * d.circleModifier
222 target: presentCircle
225 easing.type: Easing.OutCurve
226 duration: circleChangeAnimTimer.interval * d.circleModifier
229 target: presentCircle
231 to: Gradient.threeColorByIndex(index, infographic.model.currentDay, infographic.model.firstColor)
232 easing.type: Easing.OutCurve
233 duration: circleChangeAnimTimer.interval * d.circleModifier
243 objectName: "backgroundCircle"
247 source: "graphics/infographic_circle_back.png"
253 property int dotCounter: 0
255 interval: animDuration * 0.5; running: false; repeat: true
257 if (dotCounter < dots.count) {
258 var nextDot = dots.itemAt(dotCounter++)
259 nextDot.unlockAnimation.start()
263 if (dotCounter == Math.round(dots.count / 2)) {
264 circleChangeAnimTimer.startFromBeginning()
268 function startFromBeginning() {
269 if (!dotShowAnimTimer.running)
279 property int dotCounter
281 interval: animDuration * 0.5
285 if (dotCounter >= 0) {
286 var nextDot = dots.itemAt(dotCounter--)
287 nextDot.changeAnimation.start()
291 if (dotCounter == 0) {
292 infographic.model.readyForDataChange()
296 function startFromBeginning() {
297 if (!dotHideAnimTimer.running)
298 dotCounter = dots.count - 1
308 model: infographic.model.firstMonth
310 delegate: ObjectPositioner {
311 property alias unlockAnimation: dotUnlockAnim
312 property alias changeAnimation: dotChangeAnim
314 property int currentDay: infographic.model.currentDay
318 radius: backgroundCircle.width / 2
319 halfSize: dot.width / 2
320 posOffset: radius / dot.width / 3
325 objectName: "dot" + index
327 property real baseOpacity: 0.4
329 width: units.dp(5) * parent.radius / 200
330 height: units.dp(5) * parent.radius / 200
333 state: index < currentDay ? "filled" : index == currentDay ? "pointer" : "unfilled"
341 duration: dotShowAnimTimer.interval
350 duration: dotHideAnimTimer.interval
360 property alias hideAnim: decreaseOpacity
361 property alias showAnim: increaseOpacity
363 property real baseOpacity: 0.6
364 property real duration: dotShowAnimTimer.interval * 5
366 height: 0.7 * backgroundCircle.width
367 width: notification.height
368 anchors.centerIn: parent
370 text: infographic.model.label
372 wrapMode: Text.WordWrap
373 horizontalAlignment: Text.AlignHCenter
374 verticalAlignment: Text.AlignVCenter
383 to: notification.baseOpacity
384 duration: notification.duration * dots.count
392 from: notification.baseOpacity
394 duration: notification.duration * dots.count
395 onStopped: if (!d.useDotAnimation) infographic.model.readyForDataChange()
401 anchors.fill: dataCircle
405 d.useDotAnimation = false
406 infographic.model.nextDataSource()
410 onClicked: mouse.accepted = false
411 onPressed: mouse.accepted = false