on xenial help sign in
tweak launcher folding and visuals according to feedback from design:
a4557f4Michael Zanetti
Launcher/FoldingLauncherDelegate.qml+35−24
@@ -26,21 +26,21 @@ LauncherDelegate {
26 if (index == 0 || index == priv.listView.count-1) {
26 if (index == 0 || index == priv.listView.count-1) {
27 if (priv.distanceFromEdge < 0) {
27 if (priv.distanceFromEdge < 0) {
28 // proportion equation: distanceFromTopEdge : angle = totalUnfoldedHeight/2 : maxAngle
28 // proportion equation: distanceFromTopEdge : angle = totalUnfoldedHeight/2 : maxAngle
29− return Math.max(-maxAngle, priv.distanceFromEdge * maxAngle / (priv.listView.foldingAreaHeight)) * priv.orientationFlag
29+ return Math.max(-maxAngle, priv.distanceFromEdge * maxAngle / (priv.foldingAreaHeight)) * priv.orientationFlag
30 }
30 }
31 return 0; // Don't fold first/last item as long as inside the view
31 return 0; // Don't fold first/last item as long as inside the view
32 }
32 }
33
33
34− // Are we in the already completely outside the flickable? Fold for the last 5 degrees
34+ // We reached the folded area... fold the last 5 degrees
35− if (priv.distanceFromEdge < 0) {
35+ if (priv.overlapWithFoldedArea > 0) {
36− // proportion equation: -distanceFromTopEdge : angle = totalUnfoldedHeight : 5
36+ // proportion equation: overlap : x = height : 5
37− return Math.max(-maxAngle, (priv.distanceFromEdge * 5 / priv.listView.foldingAreaHeight) - (maxAngle-5)) * priv.orientationFlag
37+ return ((maxAngle - 5) + (priv.overlapWithFoldedArea * 5 / priv.foldingAreaHeight)) * -priv.orientationFlag
38 }
38 }
39
39
40 // We are overlapping with the folding area, fold the icon to maxAngle - 5 degrees
40 // We are overlapping with the folding area, fold the icon to maxAngle - 5 degrees
41 if (priv.overlapWithFoldingArea > 0) {
41 if (priv.overlapWithFoldingArea > 0) {
42 // proportion equation: overlap: totalHeight = angle : (maxAngle - 5)
42 // proportion equation: overlap: totalHeight = angle : (maxAngle - 5)
43− return -priv.overlapWithFoldingArea * (maxAngle -5) / priv.listView.foldingAreaHeight * priv.orientationFlag;
43+ return -priv.overlapWithFoldingArea * (maxAngle -5) / priv.foldingAreaHeight * priv.orientationFlag;
44 }
44 }
45 return 0;
45 return 0;
46 }
46 }
@@ -61,9 +61,9 @@ LauncherDelegate {
61 return (-priv.distanceFromEdge - (root.height - effectiveHeight)) * priv.orientationFlag;
61 return (-priv.distanceFromEdge - (root.height - effectiveHeight)) * priv.orientationFlag;
62 }
62 }
63
63
64− // We're touching the edge, move slower than the actual flicking speed.
64+ // We stopped folding, move slower than the actual flicking speed.
65− if (priv.distanceFromEdge < 0) {
65+ if (priv.overlapWithFoldedArea > 0) {
66− return (Math.abs(priv.distanceFromEdge) * priv.totalEffectiveHeight / priv.totalUnfoldedHeight) * priv.orientationFlag
66+ return (priv.overlapWithFoldedArea * priv.totalEffectiveHeight / (priv.totalUnfoldedHeight + priv.listView.foldingStopHeight)) * priv.orientationFlag;
67 }
67 }
68 return 0;
68 return 0;
69 }
69 }
@@ -72,22 +72,23 @@ LauncherDelegate {
72 // First/last items are special
72 // First/last items are special
73 if (index == 0 || index == priv.listView.count-1) {
73 if (index == 0 || index == priv.listView.count-1) {
74 if (priv.distanceFromEdge < 0) {
74 if (priv.distanceFromEdge < 0) {
75− // Fade from 1 to 0 in the distance of 3 * foldingAreaHeight (which is when the next item reaches the edge)
75+ // Fade from 1 to 0 while traversing a distance of 2*foldingAreaHeight
76+ // proportion equation: 0.5 : x = -2*foldingAreaHeight : distance
76− return 1.0 - (-priv.distanceFromEdge / (priv.listView.foldingAreaHeight * 3))
77+ return 1 + (priv.distanceFromEdge / (priv.foldingAreaHeight * 2))
77 }
78 }
78 return 1; // Don't make first/last item transparent as long as inside the view
79 return 1; // Don't make first/last item transparent as long as inside the view
79 }
80 }
80
81
81− // Are we already completely outside the flickable? Fade from 0.75 to 0 in 2 items height
82+ // Did we stop folding? Fade out to 0 in 2*foldingAreaHeight
82− if (priv.distanceFromEdge < 0) {
83+ if (priv.overlapWithFoldedArea > 0) {
83− // proportion equation: -distanceFromEdge : 1-opacity = totalUnfoldedHeight : 0.75
84+ // overlap : foldingAreaHeight = opacity : 0.75
84− return 0.75 - (-priv.distanceFromEdge * 0.75 / (priv.totalUnfoldedHeight*2))
85+ return 0.75 - (priv.overlapWithFoldedArea * 0.75 / (priv.foldingAreaHeight * 2));
85 }
86 }
86
87
87− // We are overlapping with the folding area, fade out to 0.75
88+ // We are overlapping with the folding area, fade out to 0.75 transparency
88 if (priv.overlapWithFoldingArea > 0) {
89 if (priv.overlapWithFoldingArea > 0) {
89 // proportion equation: overlap : totalHeight = 1-opacity : 0.25
90 // proportion equation: overlap : totalHeight = 1-opacity : 0.25
90− return 1 - (priv.overlapWithFoldingArea * 0.25 / priv.listView.foldingAreaHeight)
91+ return 1 - (priv.overlapWithFoldingArea * 0.25 / priv.foldingAreaHeight)
91 }
92 }
92 return 1;
93 return 1;
93 }
94 }
@@ -95,19 +96,27 @@ LauncherDelegate {
95 brightness: {
96 brightness: {
96 // First/last items are special
97 // First/last items are special
97 if (index == 0 || index == priv.listView.count-1) {
98 if (index == 0 || index == priv.listView.count-1) {
99+
100+ // Traversed one foldingAreaHeight. Stop at 0.3
101+ if (priv.distanceFromEdge < -priv.foldingAreaHeight) {
102+ return -0.3
103+ }
104+
105+ // We started moving, fade to 0.3
98 if (priv.distanceFromEdge < 0) {
106 if (priv.distanceFromEdge < 0) {
99− return -(-priv.distanceFromEdge / (priv.listView.foldingAreaHeight * 3))
107+ return -0.3 * (-priv.distanceFromEdge / (priv.foldingAreaHeight))
100 }
108 }
101 return 0;
109 return 0;
102 }
110 }
103− // Are we already completely outside the flickable? Fade from 0.7 to 0 in 2 items height
111+
104− if (priv.distanceFromEdge < 0) {
112+ // We stopped folding? Stop brightness change at 0.3
105− return -0.3 - (-priv.distanceFromEdge * 0.1 / (priv.totalUnfoldedHeight*2))
113+ if (priv.overlapWithFoldedArea > 0) {
114+ return -0.3;
106 }
115 }
107
116
108− // We are overlapping with the folding area, fade out to 0.7
117+ // We are overlapping with the folding area, fade out to 0.3
109 if (priv.overlapWithFoldingArea > 0) {
118 if (priv.overlapWithFoldingArea > 0) {
110− return - (priv.overlapWithFoldingArea * 0.3 / priv.listView.foldingAreaHeight)
119+ return - (priv.overlapWithFoldingArea * 0.3 / priv.listView.foldingStartHeight);
111 }
120 }
112 return 0;
121 return 0;
113 }
122 }
@@ -127,7 +136,9 @@ LauncherDelegate {
127 property real distanceFromEdge: Math.abs(distanceFromBottomEdge) < Math.abs(distanceFromTopEdge) ? distanceFromBottomEdge : distanceFromTopEdge
136 property real distanceFromEdge: Math.abs(distanceFromBottomEdge) < Math.abs(distanceFromTopEdge) ? distanceFromBottomEdge : distanceFromTopEdge
128 property real orientationFlag: Math.abs(distanceFromBottomEdge) < Math.abs(distanceFromTopEdge) ? -1 : 1
137 property real orientationFlag: Math.abs(distanceFromBottomEdge) < Math.abs(distanceFromTopEdge) ? -1 : 1
129
138
130− property real overlapWithFoldingArea: listView.foldingAreaHeight - distanceFromEdge
139+ property real overlapWithFoldingArea: listView.foldingStartHeight - distanceFromEdge
140+ property real overlapWithFoldedArea: listView.foldingStopHeight - distanceFromEdge
141+ property real foldingAreaHeight: listView.foldingStartHeight - listView.foldingStopHeight
131 }
142 }
132
143
133}
144}
Launcher/Launcher.qml+1−1
@@ -26,7 +26,7 @@ Item {
26
26
27 property bool available: true // can be used to disable all interactions
27 property bool available: true // can be used to disable all interactions
28
28
29− property int panelWidth: units.gu(8.5)
29+ property int panelWidth: units.gu(8)
30 property int dragAreaWidth: units.gu(1)
30 property int dragAreaWidth: units.gu(1)
31 property real progress: dragArea.dragging && dragArea.touchX > panel.width ? dragArea.touchX : 0
31 property real progress: dragArea.dragging && dragArea.touchX > panel.width ? dragArea.touchX : 0
32
32
Launcher/LauncherDelegate.qml+2−2
@@ -80,7 +80,7 @@ Item {
80 top: parent.top
80 top: parent.top
81 margins: -units.dp(1)
81 margins: -units.dp(1)
82 }
82 }
83− width: Math.min(units.gu(7.5), Math.max(units.gu(3), countLabel.implicitWidth + units.gu(2.5)))
83+ width: Math.min(root.itemWidth, Math.max(units.gu(3), countLabel.implicitWidth + units.gu(2.5)))
84 height: units.gu(3)
84 height: units.gu(3)
85 source: "graphics/notification.sci"
85 source: "graphics/notification.sci"
86 visible: root.count > 0
86 visible: root.count > 0
@@ -89,7 +89,7 @@ Item {
89 id: countLabel
89 id: countLabel
90 text: root.count
90 text: root.count
91 anchors.centerIn: parent
91 anchors.centerIn: parent
92− width: units.gu(6)
92+ width: root.itemWidth - units.gu(1)
93 horizontalAlignment: Text.AlignHCenter
93 horizontalAlignment: Text.AlignHCenter
94 elide: Text.ElideRight
94 elide: Text.ElideRight
95 color: "white"
95 color: "white"
Launcher/LauncherPanel.qml+13−13
@@ -62,7 +62,7 @@ Item {
62 z: 1
62 z: 1
63 Image {
63 Image {
64 objectName: "dashItem"
64 objectName: "dashItem"
65− width: units.gu(5.5)
65+ width: units.gu(5)
66 height: width
66 height: width
67 anchors.centerIn: parent
67 anchors.centerIn: parent
68 source: "graphics/home.png"
68 source: "graphics/home.png"
@@ -113,9 +113,11 @@ Item {
113 property int extensionSize: itemHeight * 3
113 property int extensionSize: itemHeight * 3
114
114
115 // The height of the area where icons start getting folded
115 // The height of the area where icons start getting folded
116− property int foldingAreaHeight: itemHeight * 0.75
116+ property int foldingStartHeight: units.gu(6.5)
117+ // The height of the area where the items reach the final folding angle
118+ property int foldingStopHeight: foldingStartHeight - itemHeight - spacing
117− property int itemWidth: width
119+ property int itemWidth: units.gu(7)
118− property int itemHeight: width * 7.5 / 8
120+ property int itemHeight: units.gu(6.5)
119 property int clickFlickSpeed: units.gu(60)
121 property int clickFlickSpeed: units.gu(60)
120 property int draggedIndex: dndArea.draggedIndex
122 property int draggedIndex: dndArea.draggedIndex
121 property real realContentY: contentY - originY + topMargin
123 property real realContentY: contentY - originY + topMargin
@@ -142,9 +144,8 @@ Item {
142 count: model.count
144 count: model.count
143 progress: model.progress
145 progress: model.progress
144 inverted: root.inverted
146 inverted: root.inverted
145− highlighted: dragging && index === root.highlightIndex
146 z: -Math.abs(offset)
147 z: -Math.abs(offset)
147− maxAngle: 60
148+ maxAngle: 55
148 property bool dragging: false
149 property bool dragging: false
149
150
150 ThinDivider {
151 ThinDivider {
@@ -235,7 +236,9 @@ Item {
235 NumberAnimation { target: dropIndicator; properties: "opacity"; duration: UbuntuAnimation.FastDuration }
236 NumberAnimation { target: dropIndicator; properties: "opacity"; duration: UbuntuAnimation.FastDuration }
236 NumberAnimation { properties: "itemOpacity"; duration: UbuntuAnimation.BriskDuration }
237 NumberAnimation { properties: "itemOpacity"; duration: UbuntuAnimation.BriskDuration }
237 SequentialAnimation {
238 SequentialAnimation {
239+ ScriptAction { script: if (index == launcherListView.count-1) launcherListView.flick(0, -launcherListView.clickFlickSpeed); }
238 UbuntuNumberAnimation { properties: "height" }
240 UbuntuNumberAnimation { properties: "height" }
241+ ScriptAction { script: if (index == launcherListView.count-1) launcherListView.flick(0, -launcherListView.clickFlickSpeed); }
239 PropertyAction { target: dndArea; property: "postDragging"; value: false }
242 PropertyAction { target: dndArea; property: "postDragging"; value: false }
240 PropertyAction { target: dndArea; property: "draggedIndex"; value: -1 }
243 PropertyAction { target: dndArea; property: "draggedIndex"; value: -1 }
241 }
244 }
@@ -265,9 +268,6 @@ Item {
265
268
266 onPressed: {
269 onPressed: {
267 selectedItem = launcherListView.itemAt(mouseX, mouseY + launcherListView.realContentY)
270 selectedItem = launcherListView.itemAt(mouseX, mouseY + launcherListView.realContentY)
268− if (selectedItem !== null) {
269− selectedItem.highlighted = true
270− }
271 }
271 }
272
272
273 onClicked: {
273 onClicked: {
@@ -302,7 +302,6 @@ Item {
302 }
302 }
303
303
304 onCanceled: {
304 onCanceled: {
305− selectedItem.highlighted = false
306 selectedItem = undefined;
305 selectedItem = undefined;
307 preDragging = false;
306 preDragging = false;
308 postDragging = false;
307 postDragging = false;
@@ -320,7 +319,6 @@ Item {
320 return;
319 return;
321 }
320 }
322
321
323− selectedItem.highlighted = false
324 selectedItem.dragging = false;
322 selectedItem.dragging = false;
325 selectedItem = undefined;
323 selectedItem = undefined;
326 preDragging = false;
324 preDragging = false;
@@ -332,6 +330,9 @@ Item {
332 if (droppedIndex >= launcherListView.count - 2 && postDragging) {
330 if (droppedIndex >= launcherListView.count - 2 && postDragging) {
333 launcherListView.flick(0, -launcherListView.clickFlickSpeed);
331 launcherListView.flick(0, -launcherListView.clickFlickSpeed);
334 }
332 }
333+ if (droppedIndex == 0 && postDragging) {
334+ launcherListView.flick(0, launcherListView.clickFlickSpeed);
335+ }
335 }
336 }
336
337
337 onPressAndHold: {
338 onPressAndHold: {
@@ -451,8 +452,7 @@ Item {
451 height: itemHeight
452 height: itemHeight
452 width: itemWidth
453 width: itemWidth
453 rotation: root.rotation
454 rotation: root.rotation
454− highlighted: true
455− itemOpacity: 0.8
455+ itemOpacity: 0.9
456
456
457 function flatten() {
457 function flatten() {
458 fakeDragItemAnimation.start();
458 fakeDragItemAnimation.start();
tests/qmltests/Launcher/tst_Launcher.qml+8−4
@@ -285,12 +285,16 @@ Item {
285
285
286 function test_dragndrop(data) {
286 function test_dragndrop(data) {
287 revealer.dragLauncherIntoView();
287 revealer.dragLauncherIntoView();
288− var draggedItem = findChild(launcher, "launcherDelegate5")
288+ var draggedItem = findChild(launcher, "launcherDelegate4")
289 var item0 = findChild(launcher, "launcherDelegate0")
289 var item0 = findChild(launcher, "launcherDelegate0")
290 var fakeDragItem = findChild(launcher, "fakeDragItem")
290 var fakeDragItem = findChild(launcher, "fakeDragItem")
291 var initialItemHeight = draggedItem.height
291 var initialItemHeight = draggedItem.height
292− var item5 = LauncherModel.get(5).appId
293 var item4 = LauncherModel.get(4).appId
292 var item4 = LauncherModel.get(4).appId
293+ var item3 = LauncherModel.get(3).appId
294+
295+ var listView = findChild(launcher, "launcherListView");
296+ listView.flick(0, units.gu(200));
297+ tryCompare(listView, "flicking", false);
294
298
295 // Initial state
299 // Initial state
296 compare(draggedItem.itemOpacity, 1, "Item's opacity is not 1 at beginning")
300 compare(draggedItem.itemOpacity, 1, "Item's opacity is not 1 at beginning")
@@ -333,8 +337,8 @@ Item {
333 }
337 }
334
338
335 waitForRendering(draggedItem)
339 waitForRendering(draggedItem)
336− compare(LauncherModel.get(5).appId, item4)
340+ compare(LauncherModel.get(4).appId, item3)
337− compare(LauncherModel.get(4).appId, item5)
341+ compare(LauncherModel.get(3).appId, item4)
338 }
342 }
339
343
340 // Releasing and checking if initial values are restored
344 // Releasing and checking if initial values are restored