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/>.
17
import "Gradient.js" as Gradient
19
import Ubuntu.Components 1.3
26
property int animDuration: 10
30
objectName: "infographicPrivate"
31
property bool useDotAnimation: true
32
property int circleModifier: useDotAnimation ? 1 : 2
33
property bool animating: dotHideAnimTimer.running
34
|| dotShowAnimTimer.running
35
|| circleChangeAnimTimer.running
40
property color main: "white"
41
property color start: "white"
42
property color end: "white"
47
ignoreUnknownSignals: model === undefined
49
onDataAboutToAppear: startHideAnimation() // hide "no data" label
50
onDataAppeared: startShowAnimation()
52
onDataAboutToChange: startHideAnimation()
53
onDataChanged: startShowAnimation()
55
onDataAboutToDisappear: startHideAnimation()
56
onDataDisappeared: startShowAnimation() // show "no data" label
59
function startShowAnimation() {
60
dotHideAnimTimer.stop()
61
notification.hideAnim.stop()
63
if (d.useDotAnimation) {
64
dotShowAnimTimer.startFromBeginning()
66
notification.showAnim.start()
69
function startHideAnimation() {
70
dotShowAnimTimer.stop()
71
circleChangeAnimTimer.stop()
72
notification.showAnim.stop()
74
if (d.useDotAnimation) {
75
dotHideAnimTimer.startFromBeginning()
77
circleChangeAnimTimer.startFromBeginning()
79
notification.hideAnim.start()
82
visible: model.username !== ""
84
Component.onCompleted: startShowAnimation()
88
objectName: "dataCircle"
90
property real divisor: 1.5
92
width: Math.min(parent.height, parent.width) / divisor
95
anchors.centerIn: parent
98
id: circleChangeAnimTimer
100
property int pastCircleCounter
101
property int presentCircleCounter
103
interval: notification.duration
107
if (pastCircleCounter < pastCircles.count) {
108
var nextCircle = pastCircles.itemAt(pastCircleCounter++)
109
if (nextCircle !== null) nextCircle.pastCircleChangeAnim.start()
111
if (pastCircleCounter > pastCircles.count / 2) {
112
var nextCircle = presentCircles.itemAt(presentCircleCounter++)
113
if (nextCircle !== null) nextCircle.presentCircleChangeAnim.start()
115
if (presentCircleCounter > infographic.model.currentDay && pastCircleCounter >= pastCircles.count) {
120
function startFromBeginning() {
121
circleChangeAnimTimer.pastCircleCounter = 0
122
circleChangeAnimTimer.presentCircleCounter = 0
129
objectName: "pastCircles"
130
model: infographic.model.secondMonth
132
delegate: ObjectPositioner {
133
property alias pastCircleChangeAnim: pastCircleChangeAnim
136
count: pastCircles.count
137
radius: dataCircle.width / 2
138
halfSize: pastCircle.width / 2
143
objectName: "pastCircle" + index
145
property real divisor: 1.8
146
property real circleOpacity: 0.1
148
width: dataCircle.width / divisor
149
height: dataCircle.height / divisor
152
visible: modelData !== undefined
154
centerCircle: dataCircle
156
SequentialAnimation {
157
id: pastCircleChangeAnim
164
to: pastCircle.circleOpacity
165
easing.type: Easing.OutCurve
166
duration: circleChangeAnimTimer.interval * d.circleModifier
170
property: "circleScale"
172
easing.type: Easing.OutCurve
173
duration: circleChangeAnimTimer.interval * d.circleModifier
178
to: Gradient.threeColorByIndex(index, count, whiteTheme)
179
easing.type: Easing.OutCurve
180
duration: circleChangeAnimTimer.interval * d.circleModifier
190
objectName: "presentCircles"
191
model: infographic.model.firstMonth
193
delegate: ObjectPositioner {
194
property alias presentCircleChangeAnim: presentCircleChangeAnim
197
count: presentCircles.count
198
radius: dataCircle.width / 2
199
halfSize: presentCircle.width / 2
204
objectName: "presentCircle" + index
206
property real divisor: 1.8
207
property real circleOpacity: 0.3
209
width: dataCircle.width / divisor
210
height: dataCircle.height / divisor
213
visible: modelData !== undefined
215
centerCircle: dataCircle
217
SequentialAnimation {
218
id: presentCircleChangeAnim
224
target: presentCircle
226
to: presentCircle.circleOpacity
227
easing.type: Easing.OutCurve
228
duration: circleChangeAnimTimer.interval * d.circleModifier
231
target: presentCircle
232
property: "circleScale"
234
easing.type: Easing.OutCurve
235
duration: circleChangeAnimTimer.interval * d.circleModifier
238
target: presentCircle
240
to: Gradient.threeColorByIndex(index, infographic.model.currentDay, whiteTheme)
241
easing.type: Easing.OutCurve
242
duration: circleChangeAnimTimer.interval * d.circleModifier
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);
260
nextDot.unlockAnimation.start();
261
if (++dotCounter == Math.round(dots.count / 2)) {
262
circleChangeAnimTimer.startFromBeginning();
270
function startFromBeginning() {
271
if (!dotShowAnimTimer.running)
281
property int dotCounter
283
interval: animDuration * 0.5
287
if (dotCounter >= 0) {
288
var nextDot = dots.itemAt(dotCounter--)
289
nextDot.changeAnimation.start()
293
if (dotCounter == 0) {
294
infographic.model.readyForDataChange()
298
function startFromBeginning() {
299
if (!dotHideAnimTimer.running)
300
dotCounter = dots.count - 1
310
model: infographic.model.firstMonth
312
delegate: ObjectPositioner {
313
property alias unlockAnimation: dotUnlockAnim
314
property alias changeAnimation: dotChangeAnim
316
property int currentDay: infographic.model.currentDay
320
radius: dataCircle.width / 2
321
halfSize: dot.width / 2
322
posOffset: radius / dot.width / 3
327
objectName: "dot" + index
329
property real baseOpacity: 1
331
width: units.dp(5) * parent.radius / 200
332
height: units.dp(5) * parent.radius / 200
335
state: index < currentDay ? "filled" : index == currentDay ? "pointer" : "unfilled"
343
duration: dotShowAnimTimer.interval
352
duration: dotHideAnimTimer.interval
362
property alias hideAnim: decreaseOpacity
363
property alias showAnim: increaseOpacity
365
property real baseOpacity: 1
366
property real duration: dotShowAnimTimer.interval * 5
368
height: 0.7 * dataCircle.width
369
width: notification.height
370
anchors.centerIn: parent
372
text: infographic.model.label
374
wrapMode: Text.WordWrap
375
horizontalAlignment: Text.AlignHCenter
376
verticalAlignment: Text.AlignVCenter
385
to: notification.baseOpacity
386
duration: notification.duration * dots.count
394
from: notification.baseOpacity
396
duration: notification.duration * dots.count
397
onStopped: if (!d.useDotAnimation) infographic.model.readyForDataChange()
403
anchors.fill: dataCircle
404
enabled: notification.text != ""
408
d.useDotAnimation = false
409
infographic.model.nextDataSource()