~unity-team/unity8/dash-only

« back to all changes in this revision

Viewing changes to qml/Greeter/Infographics.qml

  • Committer: Kevin Gunn
  • Date: 2016-10-24 19:51:33 UTC
  • Revision ID: kevin.gunn@canonical.com-20161024195133-61lwdzzdwsnue1mn
shave some more

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2013-2016 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
 
 */
16
 
 
17
 
import "Gradient.js" as Gradient
18
 
import QtQuick 2.4
19
 
import Ubuntu.Components 1.3
20
 
 
21
 
Item {
22
 
    id: infographic
23
 
 
24
 
    property var model
25
 
 
26
 
    property int animDuration: 10
27
 
 
28
 
    QtObject {
29
 
        id: d
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
36
 
    }
37
 
 
38
 
    QtObject {
39
 
        id: whiteTheme
40
 
        property color main: "white"
41
 
        property color start: "white"
42
 
        property color end: "white"
43
 
    }
44
 
 
45
 
    Connections {
46
 
        target: model
47
 
        ignoreUnknownSignals: model === undefined
48
 
 
49
 
        onDataAboutToAppear: startHideAnimation() // hide "no data" label
50
 
        onDataAppeared: startShowAnimation()
51
 
 
52
 
        onDataAboutToChange: startHideAnimation()
53
 
        onDataChanged: startShowAnimation()
54
 
 
55
 
        onDataAboutToDisappear: startHideAnimation()
56
 
        onDataDisappeared: startShowAnimation() // show "no data" label
57
 
    }
58
 
 
59
 
    function startShowAnimation() {
60
 
        dotHideAnimTimer.stop()
61
 
        notification.hideAnim.stop()
62
 
 
63
 
        if (d.useDotAnimation) {
64
 
            dotShowAnimTimer.startFromBeginning()
65
 
        }
66
 
        notification.showAnim.start()
67
 
    }
68
 
 
69
 
    function startHideAnimation() {
70
 
        dotShowAnimTimer.stop()
71
 
        circleChangeAnimTimer.stop()
72
 
        notification.showAnim.stop()
73
 
 
74
 
        if (d.useDotAnimation) {
75
 
            dotHideAnimTimer.startFromBeginning()
76
 
        } else {
77
 
            circleChangeAnimTimer.startFromBeginning()
78
 
        }
79
 
        notification.hideAnim.start()
80
 
    }
81
 
 
82
 
    visible: model.username !== ""
83
 
 
84
 
    Component.onCompleted: startShowAnimation()
85
 
 
86
 
    Item {
87
 
        id: dataCircle
88
 
        objectName: "dataCircle"
89
 
 
90
 
        property real divisor: 1.5
91
 
 
92
 
        width: Math.min(parent.height, parent.width) / divisor
93
 
        height: width
94
 
 
95
 
        anchors.centerIn: parent
96
 
 
97
 
        Timer {
98
 
            id: circleChangeAnimTimer
99
 
 
100
 
            property int pastCircleCounter
101
 
            property int presentCircleCounter
102
 
 
103
 
            interval: notification.duration
104
 
            running: false
105
 
            repeat: true
106
 
            onTriggered: {
107
 
                if (pastCircleCounter < pastCircles.count) {
108
 
                    var nextCircle = pastCircles.itemAt(pastCircleCounter++)
109
 
                    if (nextCircle !== null) nextCircle.pastCircleChangeAnim.start()
110
 
                }
111
 
                if (pastCircleCounter > pastCircles.count / 2) {
112
 
                    var nextCircle = presentCircles.itemAt(presentCircleCounter++)
113
 
                    if (nextCircle !== null) nextCircle.presentCircleChangeAnim.start()
114
 
                }
115
 
                if (presentCircleCounter > infographic.model.currentDay && pastCircleCounter >= pastCircles.count) {
116
 
                    stop()
117
 
                }
118
 
            }
119
 
 
120
 
            function startFromBeginning() {
121
 
                circleChangeAnimTimer.pastCircleCounter = 0
122
 
                circleChangeAnimTimer.presentCircleCounter = 0
123
 
                start()
124
 
            }
125
 
        }
126
 
 
127
 
        Repeater {
128
 
            id: pastCircles
129
 
            objectName: "pastCircles"
130
 
            model: infographic.model.secondMonth
131
 
 
132
 
            delegate: ObjectPositioner {
133
 
                property alias pastCircleChangeAnim: pastCircleChangeAnim
134
 
 
135
 
                index: model.index
136
 
                count: pastCircles.count
137
 
                radius: dataCircle.width / 2
138
 
                halfSize: pastCircle.width / 2
139
 
                posOffset: 0.0
140
 
 
141
 
                Circle {
142
 
                    id: pastCircle
143
 
                    objectName: "pastCircle" + index
144
 
 
145
 
                    property real divisor: 1.8
146
 
                    property real circleOpacity: 0.1
147
 
 
148
 
                    width: dataCircle.width / divisor
149
 
                    height: dataCircle.height / divisor
150
 
                    opacity: 0.0
151
 
                    circleScale: 0.0
152
 
                    visible: modelData !== undefined
153
 
                    color: "transparent"
154
 
                    centerCircle: dataCircle
155
 
 
156
 
                    SequentialAnimation {
157
 
                        id: pastCircleChangeAnim
158
 
 
159
 
                        loops: 1
160
 
                        ParallelAnimation {
161
 
                            PropertyAnimation {
162
 
                                target: pastCircle
163
 
                                property: "opacity"
164
 
                                to: pastCircle.circleOpacity
165
 
                                easing.type: Easing.OutCurve
166
 
                                duration: circleChangeAnimTimer.interval * d.circleModifier
167
 
                            }
168
 
                            PropertyAnimation {
169
 
                                target: pastCircle
170
 
                                property: "circleScale"
171
 
                                to: modelData
172
 
                                easing.type: Easing.OutCurve
173
 
                                duration: circleChangeAnimTimer.interval * d.circleModifier
174
 
                            }
175
 
                            ColorAnimation {
176
 
                                target: pastCircle
177
 
                                property: "color"
178
 
                                to: Gradient.threeColorByIndex(index, count, whiteTheme)
179
 
                                easing.type: Easing.OutCurve
180
 
                                duration: circleChangeAnimTimer.interval * d.circleModifier
181
 
                            }
182
 
                        }
183
 
                    }
184
 
                }
185
 
            }
186
 
        }
187
 
 
188
 
        Repeater {
189
 
            id: presentCircles
190
 
            objectName: "presentCircles"
191
 
            model: infographic.model.firstMonth
192
 
 
193
 
            delegate: ObjectPositioner {
194
 
                property alias presentCircleChangeAnim: presentCircleChangeAnim
195
 
 
196
 
                index: model.index
197
 
                count: presentCircles.count
198
 
                radius: dataCircle.width / 2
199
 
                halfSize: presentCircle.width / 2
200
 
                posOffset: 0.0
201
 
 
202
 
                Circle {
203
 
                    id: presentCircle
204
 
                    objectName: "presentCircle" + index
205
 
 
206
 
                    property real divisor: 1.8
207
 
                    property real circleOpacity: 0.3
208
 
 
209
 
                    width: dataCircle.width / divisor
210
 
                    height: dataCircle.height / divisor
211
 
                    opacity: 0.0
212
 
                    circleScale: 0.0
213
 
                    visible: modelData !== undefined
214
 
                    color: "transparent"
215
 
                    centerCircle: dataCircle
216
 
 
217
 
                    SequentialAnimation {
218
 
                        id: presentCircleChangeAnim
219
 
 
220
 
                        loops: 1
221
 
 
222
 
                        ParallelAnimation {
223
 
                            PropertyAnimation {
224
 
                                target: presentCircle
225
 
                                property: "opacity"
226
 
                                to: presentCircle.circleOpacity
227
 
                                easing.type: Easing.OutCurve
228
 
                                duration: circleChangeAnimTimer.interval * d.circleModifier
229
 
                            }
230
 
                            PropertyAnimation {
231
 
                                target: presentCircle
232
 
                                property: "circleScale"
233
 
                                to: modelData
234
 
                                easing.type: Easing.OutCurve
235
 
                                duration: circleChangeAnimTimer.interval * d.circleModifier
236
 
                            }
237
 
                            ColorAnimation {
238
 
                                target: presentCircle
239
 
                                property: "color"
240
 
                                to: Gradient.threeColorByIndex(index, infographic.model.currentDay, whiteTheme)
241
 
                                easing.type: Easing.OutCurve
242
 
                                duration: circleChangeAnimTimer.interval * d.circleModifier
243
 
                            }
244
 
                        }
245
 
                    }
246
 
                }
247
 
            }
248
 
        }
249
 
 
250
 
        Timer {
251
 
            id: dotShowAnimTimer
252
 
 
253
 
            property int dotCounter: 0
254
 
 
255
 
            interval: animDuration * 0.5; running: false; repeat: true
256
 
            onTriggered: {
257
 
                if (dotCounter < dots.count) {
258
 
                    var nextDot = dots.itemAt(dotCounter);
259
 
                    if (nextDot) {
260
 
                        nextDot.unlockAnimation.start();
261
 
                        if (++dotCounter == Math.round(dots.count / 2)) {
262
 
                            circleChangeAnimTimer.startFromBeginning();
263
 
                        }
264
 
                    }
265
 
                } else {
266
 
                    stop()
267
 
                }
268
 
            }
269
 
 
270
 
            function startFromBeginning() {
271
 
                if (!dotShowAnimTimer.running)
272
 
                    dotCounter = 0
273
 
 
274
 
                start()
275
 
            }
276
 
        }
277
 
 
278
 
        Timer {
279
 
            id: dotHideAnimTimer
280
 
 
281
 
            property int dotCounter
282
 
 
283
 
            interval: animDuration * 0.5
284
 
            running: false
285
 
            repeat: true
286
 
            onTriggered: {
287
 
                if (dotCounter >= 0) {
288
 
                    var nextDot = dots.itemAt(dotCounter--)
289
 
                    nextDot.changeAnimation.start()
290
 
                } else {
291
 
                    stop()
292
 
                }
293
 
                if (dotCounter == 0) {
294
 
                    infographic.model.readyForDataChange()
295
 
                }
296
 
            }
297
 
 
298
 
            function startFromBeginning() {
299
 
                if (!dotHideAnimTimer.running)
300
 
                    dotCounter = dots.count - 1
301
 
 
302
 
                start()
303
 
            }
304
 
        }
305
 
 
306
 
        Repeater {
307
 
            id: dots
308
 
            objectName: "dots"
309
 
 
310
 
            model: infographic.model.firstMonth
311
 
 
312
 
            delegate: ObjectPositioner {
313
 
                property alias unlockAnimation: dotUnlockAnim
314
 
                property alias changeAnimation: dotChangeAnim
315
 
 
316
 
                property int currentDay: infographic.model.currentDay
317
 
 
318
 
                index: model.index
319
 
                count: dots.count
320
 
                radius: dataCircle.width / 2
321
 
                halfSize: dot.width / 2
322
 
                posOffset: radius / dot.width / 3
323
 
                state: dot.state
324
 
 
325
 
                Dot {
326
 
                    id: dot
327
 
                    objectName: "dot" + index
328
 
 
329
 
                    property real baseOpacity: 1
330
 
 
331
 
                    width: units.dp(5) * parent.radius / 200
332
 
                    height: units.dp(5) * parent.radius / 200
333
 
                    opacity: 0.0
334
 
                    smooth: true
335
 
                    state: index < currentDay ? "filled" : index == currentDay ? "pointer" : "unfilled"
336
 
 
337
 
                    PropertyAnimation {
338
 
                        id: dotUnlockAnim
339
 
 
340
 
                        target: dot
341
 
                        property: "opacity"
342
 
                        to: dot.baseOpacity
343
 
                        duration: dotShowAnimTimer.interval
344
 
                    }
345
 
 
346
 
                    PropertyAnimation {
347
 
                        id: dotChangeAnim
348
 
 
349
 
                        target: dot
350
 
                        property: "opacity"
351
 
                        to: 0.0
352
 
                        duration: dotHideAnimTimer.interval
353
 
                    }
354
 
                }
355
 
            }
356
 
        }
357
 
 
358
 
        Label {
359
 
            id: notification
360
 
            objectName: "label"
361
 
 
362
 
            property alias hideAnim: decreaseOpacity
363
 
            property alias showAnim: increaseOpacity
364
 
 
365
 
            property real baseOpacity: 1
366
 
            property real duration: dotShowAnimTimer.interval * 5
367
 
 
368
 
            height: 0.7 * dataCircle.width
369
 
            width: notification.height
370
 
            anchors.centerIn: parent
371
 
 
372
 
            text: infographic.model.label
373
 
 
374
 
            wrapMode: Text.WordWrap
375
 
            horizontalAlignment: Text.AlignHCenter
376
 
            verticalAlignment: Text.AlignVCenter
377
 
            color: "white"
378
 
 
379
 
            PropertyAnimation {
380
 
                id: increaseOpacity
381
 
 
382
 
                target: notification
383
 
                property: "opacity"
384
 
                from: 0.0
385
 
                to: notification.baseOpacity
386
 
                duration: notification.duration * dots.count
387
 
            }
388
 
 
389
 
            PropertyAnimation {
390
 
                id: decreaseOpacity
391
 
 
392
 
                target: notification
393
 
                property: "opacity"
394
 
                from: notification.baseOpacity
395
 
                to: 0.0
396
 
                duration: notification.duration * dots.count
397
 
                onStopped: if (!d.useDotAnimation) infographic.model.readyForDataChange()
398
 
            }
399
 
        }
400
 
    }
401
 
 
402
 
    MouseArea {
403
 
        anchors.fill: dataCircle
404
 
        enabled: notification.text != ""
405
 
 
406
 
        onDoubleClicked: {
407
 
            if (!d.animating) {
408
 
                d.useDotAnimation = false
409
 
                infographic.model.nextDataSource()
410
 
            }
411
 
        }
412
 
    }
413
 
}