2 * Copyright (C) 2015 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/>.
18 import Ubuntu.Components 1.3
23 anchors { left: parent.left; top: parent.top; margins: units.gu(1) }
25 // Information about the transformed item
26 property int itemIndex: 0
27 property real itemHeight: units.gu(10)
29 // Information about the environment
30 property int totalItems: 0
31 property Item flickable: null
32 property int sceneHeight: units.gu(20)
35 property real spreadHeight: sceneHeight * 0.4
36 property int spreadBottomOffset: sceneHeight * 0.18
37 property int foldingAreaWidth: flickableWidth * 0.2
38 property int maxVisibleItems: 7
39 property int margins: flickableWidth * 0.05
40 property real stackScale: 0.1
41 property int leftEndFoldedAngle: 70
42 property int rightEndFoldedAngle: 65
43 property int unfoldedAngle: 30
44 property int stackWidth: flickableWidth * 0.01
48 readonly property int flickableWidth: flickable ? flickable.width : 0
49 readonly property int flickableContentWidth: flickable ? flickable.contentWidth: 0
50 readonly property real flickableProgress: flickable ? flickable.contentX / (flickable.contentWidth - flickableWidth) : 0
52 readonly property int contentWidth: flickableWidth - root.margins * 2
54 readonly property int distance: (flickableContentWidth - (margins * 2) - (foldingAreaWidth * 2)) / (totalItems - 2)
55 readonly property int startPos: margins + foldingAreaWidth + (itemIndex - 1) * distance
56 readonly property int linearX: startPos - flickableProgress * (flickableContentWidth - flickableWidth)
58 readonly property int leftFoldingAreaX: margins + foldingAreaWidth
59 readonly property int rightFoldingAreaX: flickableWidth - foldingAreaWidth - margins
61 readonly property real leftFoldingAreaProgress: linearAnimation(leftFoldingAreaX, margins, 0, 1, linearX)
62 readonly property real rightFoldingAreaProgress: linearAnimation(rightFoldingAreaX, flickableWidth - margins, 0, 1, linearX)
64 readonly property real limitedLeftProgress: Math.min(2, leftFoldingAreaProgress)
65 readonly property real limitedRightProgress: Math.min(2, rightFoldingAreaProgress)
67 readonly property real middleSectionProgress: (linearX - margins - foldingAreaWidth) / (flickableWidth - (margins + foldingAreaWidth) * 2)
70 readonly property int animatedX: {
71 if (leftFoldingAreaProgress > 4) { // Stop it at the edge
74 if (leftFoldingAreaProgress > 2) { // move it slowly through the stack
75 return linearAnimation(2, 4, margins + stackWidth, margins, leftFoldingAreaProgress)
77 if (leftFoldingAreaProgress > 1 && itemIndex == 0) {
78 // The leftmost runs faster... make it stop before the stack and wait for others
79 return margins + stackWidth;
82 if (leftFoldingAreaProgress > 0) { // slow it down in a curve
83 if (itemIndex == 0) { // except if it's the leftmost. that one goes straigt
84 return linearAnimation(0, 1, leftFoldingAreaX, margins + stackWidth, leftFoldingAreaProgress)
86 return linearAnimation(0, 1, leftFoldingAreaX, margins + stackWidth, leftEasing.value)
88 // same for the right side stack... mostly... don't need to treat the rightmost special...
89 if (rightFoldingAreaProgress > 4) {
90 return flickableWidth - margins
92 if (rightFoldingAreaProgress > 2) {
93 return linearAnimation(2, 4, flickableWidth - margins - stackWidth, flickableWidth - margins, rightFoldingAreaProgress)
96 if (rightFoldingAreaProgress > 0) {
97 return linearAnimation(0, 1, rightFoldingAreaX, flickableWidth - margins - stackWidth, rightEasing.value);
103 readonly property int animatedY: sceneHeight - itemHeight - spreadBottomOffset
105 readonly property real animatedAngle: {
106 if (limitedLeftProgress > 0) {
107 // Leftmost is special...
109 if (limitedLeftProgress < 1) {
110 return unfoldedAngle;
112 return linearAnimation(1, 2, unfoldedAngle, leftEndFoldedAngle, limitedLeftProgress)
115 return linearAnimation(0, 2, unfoldedAngle, leftEndFoldedAngle, limitedLeftProgress)
116 } else if (limitedRightProgress > 0) {
117 return linearAnimation(0, 1, unfoldedAngle, rightEndFoldedAngle, rightEasing.value)
123 readonly property real scale: limitedLeftProgress > 0 ?
124 linearAnimation(0, 1, 1, 1 + stackScale, leftEasing.value)
125 : limitedRightProgress > 0 ?
126 linearAnimation(0, 1, 1, 1 + stackScale, rightEasing.value)
127 : 0.95 + Math.abs(middleSectionProgress - 0.5) * 0.1
129 readonly property real closeIconOffset: (scale - 1) * (-root.spreadHeight / 2)
131 readonly property real tileInfoOpacity: leftFoldingAreaProgress > 0 ?
132 linearAnimation(1, 1.5, 1, 0, leftFoldingAreaProgress)
133 : rightFoldingAreaProgress > 0 ?
134 linearAnimation(1, 1.5, 1, 0, rightFoldingAreaProgress)
137 readonly property bool itemVisible: itemIndex == totalItems - 1 ? true : leftFoldingAreaProgress < 5 && rightFoldingAreaProgress < 5
138 readonly property real shadowOpacity: itemIndex == totalItems -1 ?
140 : leftFoldingAreaProgress > 3 ?
141 linearAnimation(3, 3.5, 1, 0, leftFoldingAreaProgress)
142 : rightFoldingAreaProgress > 3 ?
143 linearAnimation(3, 3.5, 1, 0, rightFoldingAreaProgress)
148 function linearAnimation(startProgress, endProgress, startValue, endValue, progress) {
149 // progress : progressDiff = value : valueDiff => value = progress * valueDiff / progressDiff
150 return (progress - startProgress) * (endValue - startValue) / (endProgress - startProgress) + startValue;
155 type: EasingCurve.OutSine
156 progress: limitedLeftProgress / 2 // OutSine starts with twice the speed. slow it down.
161 type: EasingCurve.OutSine
162 progress: limitedRightProgress / 2 // OutSine starts with twice the speed. slow it down.