@@ -0,0 +1,340 @@
2+ * Copyright 2014 Canonical Ltd.
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
16+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
21+import Ubuntu.Components 0.1
22+import Unity.Application 0.1
27+ property bool active: false
29+ property real progress: 0
30+ property real animatedProgress: 0
31+ property bool selected: false
32+ property bool otherSelected: false
34+ property real startDistance: units.gu(5)
35+ property real endDistance: units.gu(.5)
37+ property real startScale: 1.1
38+ property real endScale: 0.7
39+ property real dragStartScale: startScale + .2
41+ property real startAngle: 15
42+ property real endAngle: 5
44+ property bool isInSideStage: false
47+ print("selected changed:", selected)
49+ print("snappsshotting", index)
52+ priv.isSelected = selected;
55+ onOtherSelectedChanged: {
59+ priv.otherSelected = otherSelected;
66+ if (spreadView.phase == 1) {
67+ var phase2Progress = spreadView.positionMarker4 - (root.zIndex * spreadView.tileDistance / spreadView.width);
68+ priv.phase2StartTranslate = priv.easingAnimation(0, 1, 0, -spreadView.width + (root.zIndex * root.endDistance), phase2Progress);
69+ print("calculating end value for", root.zIndex, priv.phase2StartTranslate, "startprogress:", phase2Progress)
71+ priv.phase2StartScale = priv.easingAnimation(0, 1, root.startScale, root.endScale, phase2Progress)
72+ priv.phase2StartAngle = priv.easingAnimation(0, 1, root.startAngle, root.endAngle, phase2Progress)
74+ if (spreadView.phase == 2) {
75+ print("phase 2 entered: progress for index", root.zIndex, "is", root.progress)
83+ property bool nextInStack: spreadView.nextInStack == index;
84+ property real animatedEndDistance: linearAnimation(0, 2, root.endDistance, 0, root.progress)
86+ property real phase2StartTranslate
87+ property real phase2StartScale
88+ property real phase2StartAngle
90+ property bool isSelected: false
91+ property bool otherSelected: false
92+ property real selectedProgress
93+ property real selectedXTranslate
94+ property real selectedAngle
95+ property real selectedScale
96+ property real selectedOpacity
98+ function snapshot() {
99+ selectedProgress = root.progress;
100+ selectedXTranslate = xTranslate;
101+ selectedAngle = angle;
102+ selectedScale = priv.scale;
103+ selectedOpacity = priv.opacityTransform;
104+ print("snapshotting at phase", spreadView.phase, negativeProgress);
105+ print("snapshotted", root.zIndex, "prog:", selectedProgress, "translate:", selectedXTranslate, "angle", selectedAngle, "scale", selectedScale)
106+// selectedTopMarginProgress = topMarginProgress;
109+ // This calculates how much negative progress there can be if unwinding the spread completely
110+ // the progress for each tile starts at 0 when it crosses the right edge, so the later a tile comes in,
111+ // the bigger its negativeProgress can be.
112+ property real negativeProgress: {
113+ if (index == spreadView.nextInStack && spreadView.phase < 2) {
116+ return -root.zIndex * spreadView.tileDistance / spreadView.width;
119+ function linearAnimation(startProgress, endProgress, startValue, endValue, progress) {
120+ // progress : progressDiff = value : valueDiff => value = progress * valueDiff / progressDiff
121+ return (progress - startProgress) * (endValue - startValue) / (endProgress - startProgress) + startValue;
124+ function easingAnimation(startProgress, endProgress, startValue, endValue, progress) {
125+ helperEasingCurve.progress = progress - startProgress;
126+ helperEasingCurve.period = endProgress - startProgress;
127+ return helperEasingCurve.value * (endValue - startValue) + startValue;
130+ property real xTranslate: {
131+ var newTranslate = 0;
133+ if (otherSelected) {
134+ return priv.selectedXTranslate
138+ print("progress:", root.progress, negativeProgress)
139+ if (model.stage == ApplicationInfoInterface.MainStage) {
140+ return linearAnimation(selectedProgress, negativeProgress, selectedXTranslate, -spreadView.width, root.progress)
142+ return linearAnimation(selectedProgress, negativeProgress, selectedXTranslate, -spreadView.sideStageWidth, root.progress)
147+ newTranslate -= root.width
149+ if (nextInStack && spreadView.phase == 0) {
150+ if (model.stage == ApplicationInfoInterface.MainStage) {
151+ if (spreadView.sideStageVisible && root.progress > 0) {
152+ // Move it so it appears from behind the side stage immediately
153+ newTranslate += -spreadView.sideStageWidth;
157+ if (model.stage == ApplicationInfoInterface.SideStage && !spreadView.sideStageVisible) {
158+ // This is when we only drag the side stage in, without rotation or snapping
159+ newTranslate = linearAnimation(0, spreadView.positionMarker2, 0, -spreadView.sideStageWidth, root.progress)
161+ newTranslate += linearAnimation(0, spreadView.positionMarker2, 0, -spreadView.sideStageWidth * spreadView.snapPosition, root.animatedProgress)
165+ if (spreadView.phase == 1) {
167+ if (model.stage == ApplicationInfoInterface.MainStage) {
168+ var startValue = -spreadView.sideStageWidth * spreadView.snapPosition + (spreadView.sideStageVisible ? -spreadView.sideStageWidth : 0)
169+// var endValue = -spreadView.width + spreadView.width * root.zIndex / 6;
170+ newTranslate += linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, startValue, priv.phase2StartTranslate, root.animatedProgress);
172+ var endValue = -spreadView.width + spreadView.width * root.zIndex / 6;
173+ if (!spreadView.sideStageVisible) {
174+ newTranslate += linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, -spreadView.sideStageWidth, priv.phase2StartTranslate, root.progress);
176+ newTranslate += linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, -spreadView.sideStageWidth * spreadView.snapPosition, priv.phase2StartTranslate, root.animatedProgress);
179+ } else if (root.active) {
180+ var startProgress = spreadView.positionMarker2 - (zIndex * spreadView.positionMarker2 / 2)
181+ var endProgress = spreadView.positionMarker4 - (zIndex * spreadView.tileDistance / spreadView.width)
182+ newTranslate = linearAnimation(startProgress, endProgress, -root.width, priv.phase2StartTranslate, root.progress);
184+ var startProgress = spreadView.positionMarker2 - (zIndex * spreadView.positionMarker2 / 2)
185+ var endProgress = spreadView.positionMarker4 - (zIndex * spreadView.tileDistance / spreadView.width)
186+ newTranslate = linearAnimation(startProgress, endProgress, 0, priv.phase2StartTranslate, root.progress);
187+ if (root.zIndex == 2) print("********** progress:", root.progress, "startProgress:", startProgress, "newTranslate", newTranslate)
191+ if (spreadView.phase == 2) {
192+ newTranslate = -easingCurve.value * (spreadView.width - root.zIndex * animatedEndDistance)
193+ if (root.zIndex == 2) print("index", zIndex, "translate", newTranslate, "progress:", root.progress)
196+ return newTranslate;
199+ property real scale: {
200+ if (otherSelected) {
201+ return selectedScale;
205+ return linearAnimation(selectedProgress, negativeProgress, selectedScale, 1, root.progress)
208+ if (spreadView.phase == 0) {
210+ if (model.stage == ApplicationInfoInterface.SideStage && !spreadView.sideStageVisible) {
213+ var targetScale = root.dragStartScale - ((root.dragStartScale - 1) * spreadView.snapPosition);
214+ return linearAnimation(0, spreadView.positionMarker2, root.dragStartScale, targetScale, root.animatedProgress);
216+ } else if (active) {
219+ return linearAnimation(0, spreadView.positionMarker2, root.startScale, root.endScale, root.progress)
223+ if (spreadView.phase == 1) {
226+ if (model.stage !== ApplicationInfoInterface.SideStage || spreadView.sideStageVisible) {
227+ startScale = root.dragStartScale - ((root.dragStartScale - 1) * spreadView.snapPosition);
229+ return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, startScale, priv.phase2StartScale, root.animatedProgress)
231+ var startProgress = spreadView.positionMarker2 - (zIndex * spreadView.positionMarker2 / 2)
232+ var endProgress = spreadView.positionMarker4 - (zIndex * spreadView.tileDistance / spreadView.width)
233+ return linearAnimation(startProgress, endProgress, 1, priv.phase2StartScale, root.animatedProgress)
236+ if (spreadView.phase == 2) {
237+ return root.startScale - easingCurve.value * (root.startScale - root.endScale)
243+ property real angle: {
244+ if (otherSelected) {
245+ return selectedAngle;
248+ return linearAnimation(selectedProgress, negativeProgress, selectedAngle, 0, root.progress)
251+ if (spreadView.phase == 0) {
253+ if (model.stage == ApplicationInfoInterface.SideStage && !spreadView.sideStageVisible) {
256+// print("return angle for index", root.zIndex, linearAnimation(0, spreadView.positionMarker2, root.startAngle, root.startAngle * (1-spreadView.snapPosition), root.animatedProgress))
257+ return linearAnimation(0, spreadView.positionMarker2, root.startAngle, root.startAngle * (1-spreadView.snapPosition), root.animatedProgress)
261+ if (spreadView.phase == 1) {
263+ if (model.stage == ApplicationInfoInterface.SideStage && !spreadView.sideStageVisible) {
264+ return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, 0, priv.phase2StartAngle, root.animatedProgress)
266+ return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, root.startAngle * (1-spreadView.snapPosition), priv.phase2StartAngle, root.animatedProgress)
269+ var startProgress = spreadView.positionMarker2 - (zIndex * spreadView.positionMarker2 / 2)
270+ var endProgress = spreadView.positionMarker4 - (zIndex * spreadView.tileDistance / spreadView.width)
271+ return linearAnimation(startProgress, endProgress, 0, priv.phase2StartAngle, root.progress)
273+ if (spreadView.phase == 2) {
274+ return root.startAngle - easingCurve.value * (root.startAngle - root.endAngle);
280+ property real opacityTransform: {
281+ if (otherSelected) {
282+// if (active && root.progress == 0) {
283+// fadeBackInAnimation.start()
285+ return linearAnimation(selectedProgress, negativeProgress, selectedOpacity, 0, root.progress)
291+// onXTranslateChanged: print("xtrnslate changed", xTranslate)
296+ name: "sideStageDragging"; when: spreadView.sideStageDragging && root.isInSideStage
297+ PropertyChanges { target: priv; xTranslate: -spreadView.sideStageWidth + spreadView.sideStageWidth * spreadView.sideStageDragProgress }
300+ onStateChanged: print("jfdksjflkdsajfklsdjlfsdaklfjdsalkfjsad", state)
304+ origin { x: 0; y: spreadView.height / 2 }
305+ axis { x: 0; y: 1; z: 0 }
309+ origin { x: 0; y: spreadView.height / 2 }
317+ opacity: priv.opacityTransform
319+ UbuntuNumberAnimation {
320+ id: fadeBackInAnimation
323+ duration: UbuntuAnimation.SlowDuration
330+ type: EasingCurve.OutSine
332+ progress: root.progress
336+ id: helperEasingCurve
337+ type: easingCurve.type
338+ period: easingCurve.period