on xenial help sign in
initial import of the TabletStage
dbadcb7Michael Zanetti
qml/Shell.qml+1−1
@@ -228,7 +228,7 @@ FocusScope {
228 id: applicationsDisplayLoader
228 id: applicationsDisplayLoader
229 anchors.fill: parent
229 anchors.fill: parent
230
230
231− source: shell.sideStageEnabled ? "Stages/StageWithSideStage.qml" : "Stages/PhoneStage.qml"
231+ source: shell.sideStageEnabled ? "Stages/TabletStage.qml" : "Stages/PhoneStage.qml"
232
232
233 Binding {
233 Binding {
234 target: applicationsDisplayLoader.item
234 target: applicationsDisplayLoader.item
qml/Stages/TabletStage.qmlnew file+443
@@ -0,0 +1,443 @@
1+/*
2+ * Copyright (C) 2014 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 QtQuick 2.0
18+import Ubuntu.Components 0.1
19+import Ubuntu.Gestures 0.1
20+import Unity.Application 0.1
21+import Utils 0.1
22+import "../Components"
23+
24+Item {
25+ id: root
26+ objectName: "stages"
27+ anchors.fill: parent
28+
29+ // Controls to be set from outside
30+ property bool shown: false
31+ property bool moving: false
32+ property int dragAreaWidth
33+
34+ // State information propagated to the outside
35+ readonly property bool painting: true
36+ property bool fullscreen: true
37+ property bool overlayMode: false
38+
39+ readonly property int overlayWidth: priv.overlayOverride ? 0 : priv.sideStageWidth
40+
41+ property var surfaces
42+ property real maximizedAppTopMargin
43+
44+ QtObject {
45+ id: priv
46+
47+ property string focusedAppId: ApplicationManager.focusedApplicationId
48+ property string oldFocusedAppId: ""
49+
50+ property string mainStageAppId
51+ property string sideStageAppId
52+
53+ // For convenience, keep properties of the first two apps in the model
54+ property string appId0
55+ property string appId1
56+
57+ onFocusedAppIdChanged: {
58+ print("focused appid changed", priv.focusedAppId)
59+ var focusedApp = ApplicationManager.findApplication(focusedAppId);
60+ if (focusedApp.stage == ApplicationInfoInterface.SideStage) {
61+ priv.sideStageAppId = focusedAppId;
62+ } else {
63+ priv.mainStageAppId = focusedAppId;
64+ }
65+
66+ appId0 = ApplicationManager.get(0).appId;
67+ appId1 = ApplicationManager.get(1).appId;
68+ }
69+
70+ function indexOf(appId) {
71+ for (var i = 0; i < ApplicationManager.count; i++) {
72+ if (ApplicationManager.get(i).appId == appId) {
73+ return i;
74+ }
75+ }
76+ return -1;
77+ }
78+ }
79+
80+ Connections {
81+ target: ApplicationManager
82+ onFocusRequested: {
83+ if (spreadView.visible) {
84+ spreadView.snapTo(priv.indexOf(appId));
85+ } else {
86+ priv.switchToApp(appId);
87+ ApplicationManager.focusApplication(appId)
88+ }
89+ }
90+ }
91+
92+ Flickable {
93+ id: spreadView
94+ anchors.fill: parent
95+ contentWidth: spreadRow.width
96+ interactive: phase == 2
97+
98+ property int tileDistance: units.gu(20)
99+ property int sideStageWidth: units.gu(40)
100+ property bool sideStageVisible: priv.sideStageAppId
101+
102+ property int phase
103+
104+ property int phase0Width: sideStageWidth
105+ property int phase1Width: sideStageWidth
106+
107+ property real positionMarker1: 0.2
108+ property real positionMarker2: sideStageWidth / spreadView.width
109+ property real positionMarker3: 0.6
110+ property real positionMarker4: 0.8
111+
112+ property int startSnapPosition: phase0Width * 0.5
113+ property int endSnapPosition: phase0Width * 0.75
114+ property real snapPosition: 0.75
115+
116+ property int selectedIndex: -1
117+ onSelectedIndexChanged: print("selected index changed", selectedIndex)
118+
119+ property bool sideStageDragging: sideStageDragHandle.dragging
120+ property real sideStageDragProgress: sideStageDragHandle.progress
121+
122+ onSideStageDragProgressChanged: {
123+ if (sideStageDragProgress == 1) {
124+ ApplicationManager.focusApplication(priv.mainStageAppId)
125+ priv.sideStageAppId = ""
126+ }
127+ }
128+
129+ property int nextInStack: {
130+ switch (state) {
131+ case "main":
132+ if (ApplicationManager.count > 1) {
133+ return 1;
134+ }
135+ return -1;
136+ case "mainAndOverlay":
137+ if (ApplicationManager.count <= 2) {
138+ return -1;
139+ }
140+ print("nextinstack calculation! appId0", priv.appId0, "appid1", priv.appId1, "MS", priv.mainStageAppId, "SS", priv.sideStageAppId)
141+ if (priv.appId0 == priv.mainStageAppId || priv.appId0 == priv.sideStageAppId) {
142+ if (priv.appId1 == priv.mainStageAppId || priv.appId1 == priv.sideStageAppId) {
143+ return 2;
144+ }
145+ return 1;
146+ }
147+ return 0;
148+ }
149+ print("unhandled nextInStack case!!!!!");
150+ return -1;
151+ }
152+ onNextInStackChanged: print("next in stack is", nextInStack)
153+
154+ states: [
155+ State {
156+ name: "invalid" // temporary until Dash is an app and we always have a main stage app
157+ },
158+ State {
159+ name: "main"
160+ },
161+ State {
162+ name: "overlay"
163+ },
164+ State {
165+ name: "mainAndOverlay"
166+ },
167+ State {
168+ name: "mainAndSplit"
169+ }
170+ ]
171+ state: {
172+ if (priv.mainStageAppId && !priv.sideStageAppId) {
173+ return "main";
174+ }
175+ if (!priv.mainStageAppId && priv.sideStageAppId) {
176+ return "overlay";
177+ }
178+ if (priv.mainStageAppId && priv.sideStageAppId) {
179+ return "mainAndOverlay";
180+ }
181+ return "invalid";
182+ }
183+
184+ onContentXChanged: {
185+ if (spreadView.phase == 0 && spreadView.contentX > spreadView.width * spreadView.positionMarker2) {
186+ spreadView.phase = 1;
187+ } else if (spreadView.phase == 1 && spreadView.contentX > spreadView.width * spreadView.positionMarker4) {
188+ spreadView.phase = 2;
189+ } else if (spreadView.phase == 1 && spreadView.contentX < spreadView.width * spreadView.positionMarker2) {
190+ spreadView.phase = 0;
191+ }
192+ }
193+
194+ function snap() {
195+ if (contentX < phase0Width) {
196+ snapAnimation.targetContentX = 0;
197+ snapAnimation.start();
198+ } else if (contentX < phase1Width) {
199+ snapTo(1)
200+ } else if (contentX < phase1Width + units.gu(5)) {
201+ snapTo(1)
202+ } else {
203+ // Add 1 pixel to make sure we definitely hit positionMarker4 even with rounding errors of the animation.
204+ snapAnimation.targetContentX = spreadView.width * spreadView.positionMarker4 + 1;
205+ snapAnimation.start();
206+ }
207+ }
208+ function snapTo(index) {
209+ print("snapping to index", index)
210+ spreadView.selectedIndex = index;
211+// root.fullscreen = ApplicationManager.get(index).fullscreen;
212+ snapAnimation.targetContentX = 0;
213+ snapAnimation.start();
214+ }
215+
216+ SequentialAnimation {
217+ id: snapAnimation
218+ property int targetContentX: 0
219+
220+ UbuntuNumberAnimation {
221+ target: spreadView
222+ property: "contentX"
223+ to: snapAnimation.targetContentX
224+ duration: UbuntuAnimation.SlowDuration
225+// duration: UbuntuAnimation.FastDuration
226+ }
227+
228+ ScriptAction {
229+ script: {
230+ if (spreadView.selectedIndex >= 0) {
231+ var newIndex = spreadView.selectedIndex;
232+ spreadView.selectedIndex = -1
233+ ApplicationManager.focusApplication(ApplicationManager.get(newIndex).appId);
234+ spreadView.phase = 0;
235+ spreadView.contentX = 0;
236+ }
237+ }
238+ }
239+ }
240+
241+ Rectangle {
242+ id: spreadRow
243+ x: spreadView.contentX
244+ height: root.height
245+// width: root.width
246+ width: spreadView.width + Math.max(4, ApplicationManager.count) * spreadView.tileDistance
247+
248+ color: "black"
249+
250+ Repeater {
251+ id: spreadRepeater
252+ model: root.surfaces
253+
254+ delegate: Rectangle {
255+ height: spreadView.height
256+ width: spreadView.tileDistance
257+ color: "#44FF0000"
258+ x: spreadView.width // - units.gu(10) // just to see 'em
259+
260+ // We need to shuffle z ordering a bit in order to keep side stage apps above main stage apps.
261+ // We don't want to really reorder them in the model because that allows us to keep track
262+ // of the last focused order.
263+ z: {
264+ if (spreadTile.active && model.stage == ApplicationInfoInterface.MainStage) return 0;
265+ if (spreadTile.active && model.stage == ApplicationInfoInterface.SideStage) {
266+ if (spreadView.nextInStack >= 0 && ApplicationManager.get(spreadView.nextInStack).stage == ApplicationInfoInterface.MainStage) {
267+ return Math.max(index, 2);
268+ } else {
269+ return 1;
270+ }
271+ }
272+ if (index <= 2 && model.stage == ApplicationInfoInterface.MainStage && priv.sideStageAppId) {
273+ return priv.indexOf(priv.sideStageAppId) < index ? index - 1 : index;
274+ }
275+ if (index == spreadView.nextInStack && model.stage == ApplicationInfoInterface.SideStage) {
276+ if (priv.sideStageAppId) {
277+ return 2;
278+ }
279+ return 1;
280+ }
281+ return index;
282+ }
283+
284+ TransformedTabletSpreadDelegate {
285+ id: spreadTile
286+ height: spreadView.height
287+ width: model.stage == ApplicationInfoInterface.MainStage ? spreadView.width : spreadView.sideStageWidth
288+// opacity: .3
289+
290+ active: model.appId == priv.mainStageAppId || model.appId == priv.sideStageAppId
291+ zIndex: parent.z
292+ selected: spreadView.selectedIndex == index
293+ otherSelected: spreadView.selectedIndex >= 0 && !selected
294+ isInSideStage: priv.sideStageAppId == model.appId
295+ surface: model.surface
296+ interactive: !spreadView.interactive
297+ maximizedAppTopMargin: root.maximizedAppTopMargin
298+
299+ progress: {
300+ var tileProgress = (spreadView.contentX - zIndex * spreadView.tileDistance) / spreadView.width;
301+ // The Tile which is next in the stack needs to move directly from the beginning...
302+// print("tile0Progress is", tileProgress, "next", spreadView.nextInStack, zIndex, "PHASE:", spreadView.phase)
303+ if (index == spreadView.nextInStack && spreadView.phase < 2) {
304+// print("üüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüü")
305+ tileProgress += zIndex * spreadView.tileDistance / spreadView.width;
306+ }
307+ return tileProgress;
308+ }
309+
310+ animatedProgress: {
311+// print("PHASE:", spreadView.phase)
312+ if (spreadView.phase == 0 && (active || spreadView.nextInStack == index)) {
313+ if (progress < spreadView.positionMarker1) {
314+// print("progress is", progress, "index", zIndex, "appid", model.appId)
315+ return progress;
316+ } else if (progress < spreadView.positionMarker1 + snappingCurve.period){
317+// print("progress is", progress, "index", zIndex, "appid", model.appId)
318+ return spreadView.positionMarker1 + snappingCurve.value * 3;
319+ } else {
320+// print("progress is", progress, "index", zIndex, "appid", model.appId)
321+ return spreadView.positionMarker2;
322+ }
323+ }
324+// print("progress is", progress, "index", zIndex, "appid", model.appId)
325+ return progress;
326+ }
327+
328+ onClicked: {
329+ if (spreadView.phase == 2) {
330+ print("selected index", index, "appId", ApplicationManager.get(index))
331+ if (ApplicationManager.focusedApplicationId == ApplicationManager.get(index).appId) {
332+ spreadView.snapTo(index);
333+ } else {
334+ ApplicationManager.requestFocusApplication(ApplicationManager.get(index).appId);
335+ }
336+ }
337+ }
338+
339+ EasingCurve {
340+ id: snappingCurve
341+ type: EasingCurve.Linear
342+ period: (spreadView.positionMarker2 - spreadView.positionMarker1) / 3
343+ progress: spreadTile.progress - spreadView.positionMarker1
344+ }
345+
346+// Rectangle {
347+// anchors.fill: parent; color: "#FF00FF"
348+// border.width: units.gu(1)
349+// border.color: "black"
350+// Label {
351+// anchors { verticalCenter: parent.verticalCenter; left: parent.left; leftMargin: units.gu(2) }
352+// fontSize: "x-large"
353+// text: spreadTile.zIndex + "/" + model.index
354+// }
355+// }
356+ }
357+ }
358+ }
359+ }
360+ }
361+
362+ Rectangle {
363+ id: sideStageDragHandle
364+ color: "red"
365+ anchors { top: parent.top; bottom: parent.bottom; right: parent.right; rightMargin: spreadView.sideStageWidth }
366+ width: units.gu(2)
367+ visible: spreadView.phase <= 0 && spreadView.sideStageVisible
368+ property real progress: 0
369+ property bool dragging: false
370+
371+ onProgressChanged: print("prigress is", progress)
372+
373+ MouseArea {
374+ id: sideStageDragHandleMouseArea
375+ anchors.fill: parent
376+ property int startX
377+ onPressed: {
378+ startX = mouseX;
379+ sideStageDragHandle.progress = 0;
380+ sideStageDragHandle.dragging = true;
381+ print("sideStageDragHandle pressed")
382+ }
383+ onMouseXChanged: {
384+ sideStageDragHandle.progress = (-startX + mouseX) / spreadView.sideStageWidth
385+ print("foooo", -spreadView.sideStageWidth + spreadView.sideStageWidth * spreadView.sideStageDragProgress)
386+ }
387+ onReleased: {
388+ sideStageDragSnapAnimation.to = sideStageDragHandle.progress < 0.5 ? 0 : 1
389+ sideStageDragSnapAnimation.start();
390+ }
391+ }
392+ UbuntuNumberAnimation {
393+ id: sideStageDragSnapAnimation
394+ target: sideStageDragHandle
395+ property: "progress"
396+
397+ onRunningChanged: {
398+ if (!running) {
399+ sideStageDragHandle.dragging = false;
400+ }
401+ }
402+ }
403+ }
404+
405+ EdgeDragArea {
406+ id: spreadDragArea
407+ anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
408+ width: root.dragAreaWidth
409+
410+ Rectangle { anchors.fill: parent; color: "#4400FF00"}
411+
412+ property bool attachedToView: false
413+
414+ onTouchXChanged: {
415+ if (!dragging) {
416+ spreadView.phase = 0;
417+ spreadView.contentX = 0;
418+ }
419+
420+ if (attachedToView) {
421+ spreadView.contentX = -touchX + spreadDragArea.width
422+ if (spreadView.contentX > spreadView.phase0Width + spreadView.phase1Width / 2) {
423+ attachedToView = false;
424+ spreadView.snap();
425+ }
426+ }
427+ }
428+
429+ onDraggingChanged: {
430+ if (dragging) {
431+ attachedToView = true;
432+ } else {
433+ print("released on contentX", spreadView.contentX)
434+ if (spreadView.contentX /spreadView.width < spreadView.positionMarker1) {
435+ print("rleased in phase 1")
436+ spreadView.snap();
437+ } else if (spreadView.contentX / spreadView.width < spreadView.positionMarker3) {
438+ spreadView.snapTo(spreadView.nextInStack)
439+ }
440+ }
441+ }
442+ }
443+}
qml/Stages/TransformedTabletSpreadDelegate.qmlnew file+340
@@ -0,0 +1,340 @@
1+/*
2+ * Copyright 2014 Canonical Ltd.
3+ *
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.
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 Lesser General Public License for more details.
12+ *
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/>.
15+ *
16+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17+*/
18+
19+import QtQuick 2.0
20+import Utils 0.1
21+import Ubuntu.Components 0.1
22+import Unity.Application 0.1
23+
24+SpreadDelegate {
25+ id: root
26+
27+ property bool active: false
28+ property int zIndex
29+ property real progress: 0
30+ property real animatedProgress: 0
31+ property bool selected: false
32+ property bool otherSelected: false
33+
34+ property real startDistance: units.gu(5)
35+ property real endDistance: units.gu(.5)
36+
37+ property real startScale: 1.1
38+ property real endScale: 0.7
39+ property real dragStartScale: startScale + .2
40+
41+ property real startAngle: 15
42+ property real endAngle: 5
43+
44+ property bool isInSideStage: false
45+
46+ onSelectedChanged: {
47+ print("selected changed:", selected)
48+ if (selected) {
49+ print("snappsshotting", index)
50+ priv.snapshot();
51+ }
52+ priv.isSelected = selected;
53+ }
54+
55+ onOtherSelectedChanged: {
56+ if (otherSelected) {
57+ priv.snapshot();
58+ }
59+ priv.otherSelected = otherSelected;
60+ }
61+
62+ Connections {
63+ target: spreadView
64+
65+ onPhaseChanged: {
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)
70+
71+ priv.phase2StartScale = priv.easingAnimation(0, 1, root.startScale, root.endScale, phase2Progress)
72+ priv.phase2StartAngle = priv.easingAnimation(0, 1, root.startAngle, root.endAngle, phase2Progress)
73+ }
74+ if (spreadView.phase == 2) {
75+ print("phase 2 entered: progress for index", root.zIndex, "is", root.progress)
76+ }
77+ }
78+ }
79+
80+ QtObject {
81+ id: priv
82+
83+ property bool nextInStack: spreadView.nextInStack == index;
84+ property real animatedEndDistance: linearAnimation(0, 2, root.endDistance, 0, root.progress)
85+
86+ property real phase2StartTranslate
87+ property real phase2StartScale
88+ property real phase2StartAngle
89+
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
97+
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;
107+ }
108+
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) {
114+ return 0;
115+ }
116+ return -root.zIndex * spreadView.tileDistance / spreadView.width;
117+ }
118+
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;
122+ }
123+
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;
128+ }
129+
130+ property real xTranslate: {
131+ var newTranslate = 0;
132+
133+ if (otherSelected) {
134+ return priv.selectedXTranslate
135+ }
136+
137+ if (isSelected) {
138+ print("progress:", root.progress, negativeProgress)
139+ if (model.stage == ApplicationInfoInterface.MainStage) {
140+ return linearAnimation(selectedProgress, negativeProgress, selectedXTranslate, -spreadView.width, root.progress)
141+ } else {
142+ return linearAnimation(selectedProgress, negativeProgress, selectedXTranslate, -spreadView.sideStageWidth, root.progress)
143+ }
144+ }
145+
146+ if (active) {
147+ newTranslate -= root.width
148+ }
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;
154+ }
155+ }
156+
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)
160+ } else {
161+ newTranslate += linearAnimation(0, spreadView.positionMarker2, 0, -spreadView.sideStageWidth * spreadView.snapPosition, root.animatedProgress)
162+ }
163+ }
164+
165+ if (spreadView.phase == 1) {
166+ if (nextInStack) {
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);
171+ } else {
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);
175+ } else {
176+ newTranslate += linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, -spreadView.sideStageWidth * spreadView.snapPosition, priv.phase2StartTranslate, root.animatedProgress);
177+ }
178+ }
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);
183+ } else {
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)
188+ }
189+ }
190+
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)
194+ }
195+
196+ return newTranslate;
197+ }
198+
199+ property real scale: {
200+ if (otherSelected) {
201+ return selectedScale;
202+ }
203+
204+ if (isSelected) {
205+ return linearAnimation(selectedProgress, negativeProgress, selectedScale, 1, root.progress)
206+ }
207+
208+ if (spreadView.phase == 0) {
209+ if (nextInStack) {
210+ if (model.stage == ApplicationInfoInterface.SideStage && !spreadView.sideStageVisible) {
211+ return 1;
212+ } else {
213+ var targetScale = root.dragStartScale - ((root.dragStartScale - 1) * spreadView.snapPosition);
214+ return linearAnimation(0, spreadView.positionMarker2, root.dragStartScale, targetScale, root.animatedProgress);
215+ }
216+ } else if (active) {
217+ return 1;
218+ } else {
219+ return linearAnimation(0, spreadView.positionMarker2, root.startScale, root.endScale, root.progress)
220+ }
221+ }
222+
223+ if (spreadView.phase == 1) {
224+ if (nextInStack) {
225+ var startScale = 1;
226+ if (model.stage !== ApplicationInfoInterface.SideStage || spreadView.sideStageVisible) {
227+ startScale = root.dragStartScale - ((root.dragStartScale - 1) * spreadView.snapPosition);
228+ }
229+ return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, startScale, priv.phase2StartScale, root.animatedProgress)
230+ }
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)
234+ }
235+
236+ if (spreadView.phase == 2) {
237+ return root.startScale - easingCurve.value * (root.startScale - root.endScale)
238+ }
239+
240+ return 1;
241+ }
242+
243+ property real angle: {
244+ if (otherSelected) {
245+ return selectedAngle;
246+ }
247+ if (isSelected) {
248+ return linearAnimation(selectedProgress, negativeProgress, selectedAngle, 0, root.progress)
249+ }
250+
251+ if (spreadView.phase == 0) {
252+ if (nextInStack) {
253+ if (model.stage == ApplicationInfoInterface.SideStage && !spreadView.sideStageVisible) {
254+ return 0;
255+ } else {
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)
258+ }
259+ }
260+ }
261+ if (spreadView.phase == 1) {
262+ if (nextInStack) {
263+ if (model.stage == ApplicationInfoInterface.SideStage && !spreadView.sideStageVisible) {
264+ return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, 0, priv.phase2StartAngle, root.animatedProgress)
265+ } else {
266+ return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, root.startAngle * (1-spreadView.snapPosition), priv.phase2StartAngle, root.animatedProgress)
267+ }
268+ }
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)
272+ }
273+ if (spreadView.phase == 2) {
274+ return root.startAngle - easingCurve.value * (root.startAngle - root.endAngle);
275+ }
276+
277+ return 0;
278+ }
279+
280+ property real opacityTransform: {
281+ if (otherSelected) {
282+// if (active && root.progress == 0) {
283+// fadeBackInAnimation.start()
284+// }
285+ return linearAnimation(selectedProgress, negativeProgress, selectedOpacity, 0, root.progress)
286+ }
287+
288+ return 1;
289+ }
290+
291+// onXTranslateChanged: print("xtrnslate changed", xTranslate)
292+ }
293+
294+ states: [
295+ State {
296+ name: "sideStageDragging"; when: spreadView.sideStageDragging && root.isInSideStage
297+ PropertyChanges { target: priv; xTranslate: -spreadView.sideStageWidth + spreadView.sideStageWidth * spreadView.sideStageDragProgress }
298+ }
299+ ]
300+ onStateChanged: print("jfdksjflkdsajfklsdjlfsdaklfjdsalkfjsad", state)
301+
302+ transform: [
303+ Rotation {
304+ origin { x: 0; y: spreadView.height / 2 }
305+ axis { x: 0; y: 1; z: 0 }
306+ angle: priv.angle
307+ },
308+ Scale {
309+ origin { x: 0; y: spreadView.height / 2 }
310+ xScale: priv.scale
311+ yScale: xScale
312+ },
313+ Translate {
314+ x: priv.xTranslate
315+ }
316+ ]
317+ opacity: priv.opacityTransform
318+
319+ UbuntuNumberAnimation {
320+ id: fadeBackInAnimation
321+ target: root
322+ property: "opacity"
323+ duration: UbuntuAnimation.SlowDuration
324+ from: 0
325+ to: 1
326+ }
327+
328+ EasingCurve {
329+ id: easingCurve
330+ type: EasingCurve.OutSine
331+ period: 1
332+ progress: root.progress
333+ }
334+
335+ EasingCurve {
336+ id: helperEasingCurve
337+ type: easingCurve.type
338+ period: easingCurve.period
339+ }
340+}