2 * Copyright (C) 2013-2016 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/>.
17import "Gradient.js" as Gradient
19import Lomiri.Components 1.3
26 property int animDuration: 10
28 property int currentWeekDay
32 objectName: "infographicPrivate"
33 property bool useDotAnimation: true
34 property int circleModifier: useDotAnimation ? 1 : 2
35 property bool animating: dotHideAnimTimer.running
36 || dotShowAnimTimer.running
37 || circleChangeAnimTimer.running
42 property color main: "white"
43 property color start: "white"
44 property color end: "white"
49 ignoreUnknownSignals: model === undefined
51 onDataAboutToAppear: startHideAnimation() // hide "no data" label
52 onDataAppeared: startShowAnimation()
54 onDataAboutToChange: startHideAnimation()
55 onDataChanged: startShowAnimation()
57 onDataAboutToDisappear: startHideAnimation()
58 onDataDisappeared: startShowAnimation() // show "no data" label
62 frequency: LiveTimer.Hour
63 onTrigger: handleTimerTrigger()
66 function handleTimerTrigger(){
67 var today = new Date().getDay()
68 if(infographic.currentWeekDay !== today){
69 infographic.currentWeekDay = today
74 function reloadUserData(){
75 d.useDotAnimation = false
76 infographic.model.nextDataSource()
79 function startShowAnimation() {
80 dotHideAnimTimer.stop()
81 notification.hideAnim.stop()
83 if (d.useDotAnimation) {
84 dotShowAnimTimer.startFromBeginning()
86 notification.showAnim.start()
89 function startHideAnimation() {
90 dotShowAnimTimer.stop()
91 circleChangeAnimTimer.stop()
92 notification.showAnim.stop()
94 if (d.useDotAnimation) {
95 dotHideAnimTimer.startFromBeginning()
97 circleChangeAnimTimer.startFromBeginning()
99 notification.hideAnim.start()
102 visible: model.username !== ""
104 Component.onCompleted: {
105 currentWeekDay = new Date().getDay()
111 objectName: "dataCircle"
113 property real divisor: 1.5
115 width: Math.min(parent.height, parent.width) / divisor
118 anchors.centerIn: parent
121 id: circleChangeAnimTimer
123 property int pastCircleCounter
124 property int presentCircleCounter
126 interval: notification.duration
130 if (pastCircleCounter < pastCircles.count) {
131 var nextCircle = pastCircles.itemAt(pastCircleCounter++)
132 if (nextCircle !== null) nextCircle.pastCircleChangeAnim.start()
134 if (pastCircleCounter > pastCircles.count / 2) {
135 var nextCircle = presentCircles.itemAt(presentCircleCounter++)
136 if (nextCircle !== null) nextCircle.presentCircleChangeAnim.start()
138 if (presentCircleCounter > infographic.model.currentDay && pastCircleCounter >= pastCircles.count) {
143 function startFromBeginning() {
144 circleChangeAnimTimer.pastCircleCounter = 0
145 circleChangeAnimTimer.presentCircleCounter = 0
152 objectName: "pastCircles"
153 model: infographic.model.secondMonth
155 delegate: ObjectPositioner {
156 property alias pastCircleChangeAnim: pastCircleChangeAnim
159 count: pastCircles.count
160 radius: dataCircle.width / 2
161 halfSize: pastCircle.width / 2
166 objectName: "pastCircle" + index
168 property real divisor: 1.8
169 property real circleOpacity: 0.1
171 width: dataCircle.width / divisor
172 height: dataCircle.height / divisor
175 visible: modelData !== undefined
177 centerCircle: dataCircle
179 SequentialAnimation {
180 id: pastCircleChangeAnim
187 to: pastCircle.circleOpacity
188 easing.type: Easing.OutCurve
189 duration: circleChangeAnimTimer.interval * d.circleModifier
193 property: "circleScale"
195 easing.type: Easing.OutCurve
196 duration: circleChangeAnimTimer.interval * d.circleModifier
201 to: Gradient.threeColorByIndex(index, count, whiteTheme)
202 easing.type: Easing.OutCurve
203 duration: circleChangeAnimTimer.interval * d.circleModifier
213 objectName: "presentCircles"
214 model: infographic.model.firstMonth
216 delegate: ObjectPositioner {
217 property alias presentCircleChangeAnim: presentCircleChangeAnim
220 count: presentCircles.count
221 radius: dataCircle.width / 2
222 halfSize: presentCircle.width / 2
227 objectName: "presentCircle" + index
229 property real divisor: 1.8
230 property real circleOpacity: 0.3
232 width: dataCircle.width / divisor
233 height: dataCircle.height / divisor
236 visible: modelData !== undefined
238 centerCircle: dataCircle
240 SequentialAnimation {
241 id: presentCircleChangeAnim
247 target: presentCircle
249 to: presentCircle.circleOpacity
250 easing.type: Easing.OutCurve
251 duration: circleChangeAnimTimer.interval * d.circleModifier
254 target: presentCircle
255 property: "circleScale"
257 easing.type: Easing.OutCurve
258 duration: circleChangeAnimTimer.interval * d.circleModifier
261 target: presentCircle
263 to: Gradient.threeColorByIndex(index, infographic.model.currentDay, whiteTheme)
264 easing.type: Easing.OutCurve
265 duration: circleChangeAnimTimer.interval * d.circleModifier
276 property int dotCounter: 0
278 interval: animDuration * 0.5; running: false; repeat: true
280 if (dotCounter < dots.count) {
281 var nextDot = dots.itemAt(dotCounter);
283 nextDot.unlockAnimation.start();
284 if (++dotCounter == Math.round(dots.count / 2)) {
285 circleChangeAnimTimer.startFromBeginning();
293 function startFromBeginning() {
294 if (!dotShowAnimTimer.running)
304 property int dotCounter
306 interval: animDuration * 0.5
310 if (dotCounter >= 0) {
311 var nextDot = dots.itemAt(dotCounter--)
312 nextDot.changeAnimation.start()
316 if (dotCounter == 0) {
317 infographic.model.readyForDataChange()
321 function startFromBeginning() {
322 if (!dotHideAnimTimer.running)
323 dotCounter = dots.count - 1
333 model: infographic.model.firstMonth
335 delegate: ObjectPositioner {
336 property alias unlockAnimation: dotUnlockAnim
337 property alias changeAnimation: dotChangeAnim
339 property int currentDay: infographic.model.currentDay
343 radius: dataCircle.width / 2
344 halfSize: dot.width / 2
345 posOffset: radius / dot.width / 3
350 objectName: "dot" + index
352 property real baseOpacity: 1
354 width: units.dp(5) * parent.radius / 200
355 height: units.dp(5) * parent.radius / 200
358 state: index < currentDay ? "filled" : index == currentDay ? "pointer" : "unfilled"
366 duration: dotShowAnimTimer.interval
375 duration: dotHideAnimTimer.interval
385 property alias hideAnim: decreaseOpacity
386 property alias showAnim: increaseOpacity
388 property real baseOpacity: 1
389 property real duration: dotShowAnimTimer.interval * 5
391 height: 0.7 * dataCircle.width
392 width: notification.height
393 anchors.centerIn: parent
395 text: infographic.model.label
397 wrapMode: Text.WordWrap
398 horizontalAlignment: Text.AlignHCenter
399 verticalAlignment: Text.AlignVCenter
408 to: notification.baseOpacity
409 duration: notification.duration * dots.count
417 from: notification.baseOpacity
419 duration: notification.duration * dots.count
420 onStopped: if (!d.useDotAnimation) infographic.model.readyForDataChange()
426 anchors.fill: dataCircle
427 enabled: notification.text != ""