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
29 property bool __useDotAnimation: true
30 property int __circleModifier: __useDotAnimation ? 1 : 2
35 onDataAboutToAppear: startHideAnimation() // hide "no data" label
36 onDataAppeared: startShowAnimation()
38 onDataAboutToChange: startHideAnimation()
39 onDataChanged: startShowAnimation()
41 onDataAboutToDisappear: startHideAnimation()
42 onDataDisappeared: startShowAnimation() // show "no data" label
45 function startShowAnimation() {
46 dotHideAnimTimer.stop()
47 notification.hideAnim.stop()
49 if (__useDotAnimation) {
50 dotShowAnimTimer.startFromBeginning()
52 notification.showAnim.start()
55 function startHideAnimation() {
56 dotShowAnimTimer.stop()
57 circleChangeAnimTimer.stop()
58 notification.showAnim.stop()
60 if (__useDotAnimation) {
61 dotHideAnimTimer.startFromBeginning()
63 circleChangeAnimTimer.startFromBeginning()
65 notification.hideAnim.start()
68 visible: model.label !== ""
70 Component.onCompleted: startShowAnimation()
74 objectName: "dataCircle"
76 property real divisor: 1.5
78 width: Math.min(parent.height, parent.width) / divisor
81 anchors.centerIn: parent
84 id: circleChangeAnimTimer
86 property int pastCircleCounter
87 property int presentCircleCounter
89 interval: notification.duration
93 if (pastCircleCounter < pastCircles.count) {
94 var nextCircle = pastCircles.itemAt(pastCircleCounter++)
95 if (nextCircle !== null) nextCircle.pastCircleChangeAnim.start()
97 if (pastCircleCounter > pastCircles.count / 2) {
98 var nextCircle = presentCircles.itemAt(presentCircleCounter++)
99 if (nextCircle !== null) nextCircle.presentCircleChangeAnim.start()
101 if (presentCircleCounter > infographic.model.currentDay && pastCircleCounter >= pastCircles.count) {
106 function startFromBeginning() {
107 circleChangeAnimTimer.pastCircleCounter = 0
108 circleChangeAnimTimer.presentCircleCounter = 0
115 objectName: "pastCircles"
116 model: infographic.model.secondMonth
118 delegate: ObjectPositioner {
119 property alias pastCircleChangeAnim: pastCircleChangeAnim
122 count: pastCircles.count
123 radius: parent.width / 2
124 halfSize: pastCircle.width / 2
129 objectName: "pastCircle" + index
131 property real divisor: 1.8
132 property real circleOpacity: 0.1
134 width: dataCircle.width / divisor
135 height: dataCircle.height / divisor
138 visible: modelData !== undefined
141 SequentialAnimation {
142 id: pastCircleChangeAnim
149 to: pastCircle.circleOpacity
150 easing.type: Easing.OutCurve
151 duration: circleChangeAnimTimer.interval * __circleModifier
157 easing.type: Easing.OutCurve
158 duration: circleChangeAnimTimer.interval * __circleModifier
163 to: Gradient.threeColorByIndex(index, count, infographic.model.secondColor)
164 easing.type: Easing.OutCurve
165 duration: circleChangeAnimTimer.interval * __circleModifier
175 objectName: "presentCircles"
176 model: infographic.model.firstMonth
178 delegate: ObjectPositioner {
179 property alias presentCircleChangeAnim: presentCircleChangeAnim
182 count: presentCircles.count
183 radius: parent.width / 2
184 halfSize: presentCircle.width / 2
189 objectName: "presentCircle" + index
191 property real divisor: 1.8
192 property real circleOpacity: 0.3
194 width: dataCircle.width / divisor
195 height: dataCircle.height / divisor
198 visible: modelData !== undefined
201 SequentialAnimation {
202 id: presentCircleChangeAnim
208 target: presentCircle
210 to: presentCircle.circleOpacity
211 easing.type: Easing.OutCurve
212 duration: circleChangeAnimTimer.interval * __circleModifier
215 target: presentCircle
218 easing.type: Easing.OutCurve
219 duration: circleChangeAnimTimer.interval * __circleModifier
222 target: presentCircle
224 to: Gradient.threeColorByIndex(index, infographic.model.currentDay, infographic.model.firstColor)
225 easing.type: Easing.OutCurve
226 duration: circleChangeAnimTimer.interval * __circleModifier
236 objectName: "backgroundCircle"
240 source: "graphics/infographic_circle_back.png"
246 property int dotCounter: 0
248 interval: animDuration * 0.5; running: false; repeat: true
250 if (dotCounter < dots.count) {
251 var nextDot = dots.itemAt(dotCounter++)
252 nextDot.unlockAnimation.start()
256 if (dotCounter == Math.round(dots.count / 2)) {
257 circleChangeAnimTimer.startFromBeginning()
261 function startFromBeginning() {
262 if (!dotShowAnimTimer.running)
272 property int dotCounter
274 interval: animDuration * 0.5
278 if (dotCounter >= 0) {
279 var nextDot = dots.itemAt(dotCounter--)
280 nextDot.changeAnimation.start()
284 if (dotCounter == 0) {
285 infographic.model.readyForDataChange()
289 function startFromBeginning() {
290 if (!dotHideAnimTimer.running)
291 dotCounter = dots.count - 1
301 model: infographic.model.firstMonth
303 delegate: ObjectPositioner {
304 property alias unlockAnimation: dotUnlockAnim
305 property alias changeAnimation: dotChangeAnim
307 property int currentDay: infographic.model.currentDay
311 radius: backgroundCircle.width / 2
312 halfSize: dot.width / 2
313 posOffset: radius / dot.width / 3
318 objectName: "dot" + index
320 property real baseOpacity: 0.4
322 width: units.dp(5) * parent.radius / 200
323 height: units.dp(5) * parent.radius / 200
326 state: index < currentDay ? "filled" : index == currentDay ? "pointer" : "unfilled"
334 duration: dotShowAnimTimer.interval
343 duration: dotHideAnimTimer.interval
353 property alias hideAnim: decreaseOpacity
354 property alias showAnim: increaseOpacity
356 property real baseOpacity: 0.6
357 property real duration: dotShowAnimTimer.interval * 5
359 height: 0.7 * backgroundCircle.width
360 width: notification.height
361 anchors.centerIn: parent
363 text: infographic.model.label
365 wrapMode: Text.WordWrap
366 horizontalAlignment: Text.AlignHCenter
367 verticalAlignment: Text.AlignVCenter
376 to: notification.baseOpacity
377 duration: notification.duration * dots.count
385 from: notification.baseOpacity
387 duration: notification.duration * dots.count
388 onStopped: if (!__useDotAnimation) infographic.model.readyForDataChange()
394 anchors.fill: dataCircle
397 if (!dotHideAnimTimer.running &&
398 !dotShowAnimTimer.running &&
399 !circleChangeAnimTimer.running) {
400 __useDotAnimation = false
401 infographic.model.nextDataSource()
405 onClicked: mouse.accepted = false
406 onPressed: mouse.accepted = false