on xenial help sign in
drop quicklist as it doesn't do what we need yet
2837e9cMichael Zanetti
Launcher/LauncherPanel.qml+261−294
@@ -16,7 +16,6 @@
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19−import Ubuntu.Components.Popups 0.1
20import Ubuntu.Components.ListItems 0.1 as ListItems
19import Ubuntu.Components.ListItems 0.1 as ListItems
21import Unity 0.1
20import Unity 0.1
22import Unity.Launcher 0.1
21import Unity.Launcher 0.1
@@ -84,319 +83,312 @@ Item {
84 anchors.fill: parent
83 anchors.fill: parent
85 clip: true
84 clip: true
86
85
87− ListView {
86+ ListView {
88− id: launcherListView
87+ id: launcherListView
89− objectName: "launcherListView"
88+ objectName: "launcherListView"
90− anchors {
89+ anchors {
91− fill: parent
90+ fill: parent
92− topMargin: -extensionSize + units.gu(0.5)
91+ topMargin: -extensionSize + units.gu(0.5)
93− bottomMargin: -extensionSize + units.gu(1)
92+ bottomMargin: -extensionSize + units.gu(1)
94− }
93+ }
95− topMargin: extensionSize
94+ topMargin: extensionSize
96− bottomMargin: extensionSize
95+ bottomMargin: extensionSize
97− height: parent.height - dashItem.height - parent.spacing*2
96+ height: parent.height - dashItem.height - parent.spacing*2
98− model: root.model
97+ model: root.model
99− cacheBuffer: itemHeight * 3
98+ cacheBuffer: itemHeight * 3
100− snapMode: interactive ? ListView.SnapToItem : ListView.NoSnap
99+ snapMode: interactive ? ListView.SnapToItem : ListView.NoSnap
101− highlightRangeMode: ListView.ApplyRange
100+ highlightRangeMode: ListView.ApplyRange
102− preferredHighlightBegin: (height - itemHeight) / 2
101+ preferredHighlightBegin: (height - itemHeight) / 2
103− preferredHighlightEnd: (height + itemHeight) / 2
102+ preferredHighlightEnd: (height + itemHeight) / 2
104− layoutDirection: root.inverted ? Qt.RightToLeft : Qt.LeftToRight
103+ layoutDirection: root.inverted ? Qt.RightToLeft : Qt.LeftToRight
105− spacing: units.gu(0.5)
104+ spacing: units.gu(0.5)
106−
105+
107− // The size of the area the ListView is extended to make sure items are not
106+ // The size of the area the ListView is extended to make sure items are not
108− // destructed. Note that if the move() operation when dragging switches
107+ // destructed. Note that if the move() operation when dragging switches
109− // the item with one that doesn't have a delegate yet everything breaks badly.
108+ // the item with one that doesn't have a delegate yet everything breaks badly.
110− property int extensionSize: itemHeight * 3
109+ property int extensionSize: itemHeight * 3
111−
110+
112− // The height of the area where icons start getting folded
111+ // The height of the area where icons start getting folded
113− property int foldingAreaHeight: itemHeight * 0.75
112+ property int foldingAreaHeight: itemHeight * 0.75
114− property int itemWidth: width
113+ property int itemWidth: width
115− property int itemHeight: width * 7.5 / 8
114+ property int itemHeight: width * 7.5 / 8
116− property int clickFlickSpeed: units.gu(60)
115+ property int clickFlickSpeed: units.gu(60)
117− property int draggedIndex: dndArea.draggedIndex
116+ property int draggedIndex: dndArea.draggedIndex
118−
117+
119− displaced: Transition {
118+ displaced: Transition {
120− NumberAnimation { properties: "x,y"; duration: UbuntuAnimation.FastDuration; easing: UbuntuAnimation.StandardEasing }
119+ NumberAnimation { properties: "x,y"; duration: UbuntuAnimation.FastDuration; easing: UbuntuAnimation.StandardEasing }
121− }
122−
123− delegate: LauncherListDelegate {
124− id: launcherDelegate
125− objectName: "launcherDelegate" + index
126− itemHeight: launcherListView.itemHeight
127− itemWidth: launcherListView.itemWidth
128− width: itemWidth
129− height: itemHeight
130− iconName: model.icon
131− inverted: root.inverted
132− highlighted: dragging && index === root.highlightIndex
133− z: -Math.abs(offset)
134− maxAngle: 60
135− property bool dragging: false
136−
137− ThinDivider {
138− anchors.centerIn: parent
139− width: parent.width + mainColumn.anchors.leftMargin + mainColumn.anchors.rightMargin
140− opacity: parent.dragging ? 1 : 0
141− Behavior on opacity {
142− NumberAnimation { duration: UbuntuAnimation.FastDuration }
143− }
144 }
120 }
145
121
146− states: [
122+ delegate: LauncherListDelegate {
147− State {
123+ id: launcherDelegate
148− name: "selected"
124+ objectName: "launcherDelegate" + index
149− when: dndArea.selectedItem === launcherDelegate && fakeDragItem.visible && !dragging
125+ itemHeight: launcherListView.itemHeight
150− PropertyChanges {
126+ itemWidth: launcherListView.itemWidth
151− target: launcherDelegate
127+ width: itemWidth
152− itemOpacity: 0
128+ height: itemHeight
153− }
129+ iconName: model.icon
154− },
130+ inverted: root.inverted
155− State {
131+ highlighted: dragging && index === root.highlightIndex
156− name: "dragging"
132+ z: -Math.abs(offset)
157− when: dragging
133+ maxAngle: 60
158− PropertyChanges {
134+ property bool dragging: false
159− target: launcherDelegate
135+
160− offset: units.gu(0.5)
136+ ThinDivider {
161− height: units.gu(1)
137+ anchors.centerIn: parent
162− itemOpacity: 0
138+ width: parent.width + mainColumn.anchors.leftMargin + mainColumn.anchors.rightMargin
163− }
139+ opacity: parent.dragging ? 1 : 0
164− },
140+ Behavior on opacity {
165− State {
141+ NumberAnimation { duration: UbuntuAnimation.FastDuration }
166− name: "expanded"
167− when: dndArea.draggedIndex >= 0 && (dndArea.preDragging || dndArea.selectedItem.dragging) && !dragging
168− PropertyChanges {
169− target: launcherDelegate
170− angle: 0
171− offset: 0
172− itemOpacity: 0.6
173 }
142 }
174 }
143 }
175
144
176− ]
145+ states: [
177− onStateChanged: if (index == 5) print("state changed to", state)
146+ State {
178− transitions: [
147+ name: "selected"
179− Transition {
148+ when: dndArea.selectedItem === launcherDelegate && fakeDragItem.visible && !dragging
180− from: ""
149+ PropertyChanges {
181− to: "selected"
150+ target: launcherDelegate
182− NumberAnimation { properties: "itemOpacity"; duration: UbuntuAnimation.FastDuration }
151+ itemOpacity: 0
183− },
152+ }
184− Transition {
185− from: "*"
186− to: "expanded"
187− NumberAnimation { properties: "itemOpacity"; duration: UbuntuAnimation.FastDuration }
188− NumberAnimation { properties: "angle,offset"; duration: UbuntuAnimation.FastDuration; easing: UbuntuAnimation.StandardEasing }
189− },
153+ },
190− Transition {
154+ State {
191− from: "expanded"
155+ name: "dragging"
192− to: ""
156+ when: dragging
193− NumberAnimation { properties: "itemOpacity"; duration: UbuntuAnimation.BriskDuration }
157+ PropertyChanges {
194− NumberAnimation { properties: "angle,offset"; duration: UbuntuAnimation.BriskDuration; easing: UbuntuAnimation.StandardEasing }
158+ target: launcherDelegate
159+ offset: units.gu(0.5)
160+ height: units.gu(1)
161+ itemOpacity: 0
162+ }
195− },
163+ },
196− Transition {
164+ State {
197− from: "selected"
165+ name: "expanded"
198− to: "dragging"
166+ when: dndArea.draggedIndex >= 0 && (dndArea.preDragging || dndArea.selectedItem.dragging) && !dragging
199− NumberAnimation { properties: "height"; duration: UbuntuAnimation.FastDuration; easing: UbuntuAnimation.StandardEasing }
167+ PropertyChanges {
200− },
168+ target: launcherDelegate
201− Transition {
169+ angle: 0
202− from: "dragging"
170+ offset: 0
203− to: "*"
171+ itemOpacity: 0.6
204− NumberAnimation { properties: "itemOpacity"; duration: UbuntuAnimation.BriskDuration }
205− NumberAnimation { properties: "height"; duration: UbuntuAnimation.BriskDuration; easing: UbuntuAnimation.StandardEasing }
206− }
172+ }
207− ]
208− }
173+ }
209
174
210− MouseArea {
175+ ]
211− id: dndArea
176+ onStateChanged: if (index == 5) print("state changed to", state)
212− anchors.fill: parent
177+ transitions: [
213− anchors.topMargin: launcherListView.topMargin
178+ Transition {
214− anchors.bottomMargin: launcherListView.bottomMargin
179+ from: ""
215−
180+ to: "selected"
216− property int draggedIndex: -1
181+ NumberAnimation { properties: "itemOpacity"; duration: UbuntuAnimation.FastDuration }
217− property var selectedItem
182+ },
218− property bool preDragging: false
183+ Transition {
219− property int startX
184+ from: "*"
220− property int startY
185+ to: "expanded"
221− property var quickListPopover
186+ NumberAnimation { properties: "itemOpacity"; duration: UbuntuAnimation.FastDuration }
222−
187+ NumberAnimation { properties: "angle,offset"; duration: UbuntuAnimation.FastDuration; easing: UbuntuAnimation.StandardEasing }
223− onPressed: {
188+ },
224− var realContentY = launcherListView.contentY + launcherListView.topMargin
189+ Transition {
225− selectedItem = launcherListView.itemAt(mouseX, mouseY + realContentY)
190+ from: "expanded"
226− selectedItem.highlighted = true
191+ to: ""
192+ NumberAnimation { properties: "itemOpacity"; duration: UbuntuAnimation.BriskDuration }
193+ NumberAnimation { properties: "angle,offset"; duration: UbuntuAnimation.BriskDuration; easing: UbuntuAnimation.StandardEasing }
194+ },
195+ Transition {
196+ from: "selected"
197+ to: "dragging"
198+ NumberAnimation { properties: "height"; duration: UbuntuAnimation.FastDuration; easing: UbuntuAnimation.StandardEasing }
199+ },
200+ Transition {
201+ from: "dragging"
202+ to: "*"
203+ NumberAnimation { properties: "itemOpacity"; duration: UbuntuAnimation.BriskDuration }
204+ NumberAnimation { properties: "height"; duration: UbuntuAnimation.BriskDuration; easing: UbuntuAnimation.StandardEasing }
205+ }
206+ ]
227 }
207 }
228
208
229− onClicked: {
209+ MouseArea {
230− var realItemHeight = launcherListView.itemHeight + launcherListView.spacing
210+ id: dndArea
231− var realContentY = launcherListView.contentY + launcherListView.topMargin
211+ anchors.fill: parent
232− var index = Math.floor((mouseY + realContentY) / realItemHeight);
212+ anchors.topMargin: launcherListView.topMargin
233− var clickedItem = launcherListView.itemAt(mouseX, mouseY + realContentY)
213+ anchors.bottomMargin: launcherListView.bottomMargin
214+
215+ property int draggedIndex: -1
216+ property var selectedItem
217+ property bool preDragging: false
218+ property int startX
219+ property int startY
234
220
221+ onPressed: {
222+ var realContentY = launcherListView.contentY + launcherListView.topMargin
223+ selectedItem = launcherListView.itemAt(mouseX, mouseY + realContentY)
224+ selectedItem.highlighted = true
225+ }
226+
227+ onClicked: {
228+ var realItemHeight = launcherListView.itemHeight + launcherListView.spacing
229+ var realContentY = launcherListView.contentY + launcherListView.topMargin
230+ var index = Math.floor((mouseY + realContentY) / realItemHeight);
231+ var clickedItem = launcherListView.itemAt(mouseX, mouseY + realContentY)
232+
235− // First/last item do the scrolling at more than 12 degrees
233+ // First/last item do the scrolling at more than 12 degrees
236− if (index == 0 || index == launcherListView.count -1) {
234+ if (index == 0 || index == launcherListView.count -1) {
237− if (clickedItem.angle > 12) {
235+ if (clickedItem.angle > 12) {
236+ launcherListView.flick(0, -launcherListView.clickFlickSpeed);
237+ } else if (clickedItem.angle < -12) {
238+ launcherListView.flick(0, launcherListView.clickFlickSpeed);
239+ } else {
240+ root.applicationSelected(LauncherModel.get(index).desktopFile);
241+ }
242+ return;
243+ }
244+
245+ // the rest launches apps up to an angle of 30 degrees
246+ if (clickedItem.angle > 30) {
238 launcherListView.flick(0, -launcherListView.clickFlickSpeed);
247 launcherListView.flick(0, -launcherListView.clickFlickSpeed);
239− } else if (clickedItem.angle < -12) {
248+ } else if (clickedItem.angle < -30) {
240 launcherListView.flick(0, launcherListView.clickFlickSpeed);
249 launcherListView.flick(0, launcherListView.clickFlickSpeed);
241 } else {
250 } else {
242 root.applicationSelected(LauncherModel.get(index).desktopFile);
251 root.applicationSelected(LauncherModel.get(index).desktopFile);
243 }
252 }
244− return;
245 }
253 }
246
254
247− // the rest launches apps up to an angle of 30 degrees
255+ onCanceled: {
248− if (clickedItem.angle > 30) {
256+ selectedItem.highlighted = false
249− launcherListView.flick(0, -launcherListView.clickFlickSpeed);
257+ selectedItem = undefined;
250− } else if (clickedItem.angle < -30) {
258+ preDragging = false;
251− launcherListView.flick(0, launcherListView.clickFlickSpeed);
252− } else {
253− root.applicationSelected(LauncherModel.get(index).desktopFile);
254 }
259 }
255− }
256
260
257− onCanceled: {
261+ onReleased: {
262+ draggedIndex = -1;
258− selectedItem.highlighted = false
263+ selectedItem.highlighted = false
264+ selectedItem.dragging = false;
259− selectedItem = undefined;
265+ selectedItem = undefined;
260− preDragging = false;
266+ preDragging = false;
261− }
262
267
263− onReleased: {
264− draggedIndex = -1;
265− selectedItem.highlighted = false
266− selectedItem.dragging = false;
267− selectedItem = undefined;
268+ drag.target = undefined
268− preDragging = false;
269
269
270− drag.target = undefined
270+ progressiveScrollingTimer.stop();
271+ launcherListView.interactive = true;
271
272
272− progressiveScrollingTimer.stop();
273− launcherListView.interactive = true;
274−
275− }
273+ }
276−
277− onPressAndHold: {
278− var realItemHeight = launcherListView.itemHeight + launcherListView.spacing
279− var realContentY = launcherListView.contentY + launcherListView.topMargin
280− draggedIndex = Math.floor((mouseY + realContentY) / realItemHeight);
281−
282− launcherListView.interactive = false
283
274
284− var quickListModel = launcherListView.model.get(draggedIndex).quickList
275+ onPressAndHold: {
285− var quickListAppId = launcherListView.model.get(draggedIndex).appId
276+ var realItemHeight = launcherListView.itemHeight + launcherListView.spacing
286− quickListPopover = PopupUtils.open(popoverComponent, selectedItem,
277+ var realContentY = launcherListView.contentY + launcherListView.topMargin
287− {model: quickListModel, appId: quickListAppId})
278+ draggedIndex = Math.floor((mouseY + realContentY) / realItemHeight);
288
279
289− var yOffset = draggedIndex > 0 ? (mouseY + realContentY) % (draggedIndex * realItemHeight) : mouseY + realContentY
280+ launcherListView.interactive = false
290
281
291− fakeDragItem.iconName = launcherListView.model.get(draggedIndex).icon
282+ var yOffset = draggedIndex > 0 ? (mouseY + realContentY) % (draggedIndex * realItemHeight) : mouseY + realContentY
292− fakeDragItem.x = 0
293− fakeDragItem.y = mouseY - yOffset + launcherListView.anchors.topMargin + launcherListView.topMargin
294− drag.target = fakeDragItem
295
283
296− startX = mouseX
284+ fakeDragItem.iconName = launcherListView.model.get(draggedIndex).icon
297− startY = mouseY
285+ fakeDragItem.x = 0
298− }
286+ fakeDragItem.y = mouseY - yOffset + launcherListView.anchors.topMargin + launcherListView.topMargin
287+ drag.target = fakeDragItem
299
288
300− onPositionChanged: {
289+ startX = mouseX
301− if (draggedIndex >= 0) {
290+ startY = mouseY
291+ }
302
292
293+ onPositionChanged: {
294+ if (draggedIndex >= 0) {
295+
303− if (!selectedItem.dragging) {
296+ if (!selectedItem.dragging) {
304− var distance = Math.max(Math.abs(mouseX - startX), Math.abs(mouseY - startY))
297+ var distance = Math.max(Math.abs(mouseX - startX), Math.abs(mouseY - startY))
305− if (!preDragging && distance > units.gu(1.5)) {
298+ if (!preDragging && distance > units.gu(1.5)) {
306− PopupUtils.close(quickListPopover)
299+ preDragging = true;
307− preDragging = true;
300+ }
301+ if (distance > launcherListView.itemHeight) {
302+ selectedItem.dragging = true
303+ preDragging = false;
304+ }
308 }
305 }
309− if (distance > launcherListView.itemHeight) {
310− selectedItem.dragging = true
306+ if (!selectedItem.dragging) {
311− preDragging = false;
307+ return
312 }
308 }
313− }
314− if (!selectedItem.dragging) {
315− return
316− }
317
309
318− var realContentY = launcherListView.contentY + launcherListView.topMargin
310+ var realContentY = launcherListView.contentY + launcherListView.topMargin
319− var realItemHeight = launcherListView.itemHeight + launcherListView.spacing
311+ var realItemHeight = launcherListView.itemHeight + launcherListView.spacing
320− var itemCenterY = fakeDragItem.y + fakeDragItem.height / 2
312+ var itemCenterY = fakeDragItem.y + fakeDragItem.height / 2
321−
313+
322− // Move it down by the the missing size to compensate index calculation with only expanded items
314+ // Move it down by the the missing size to compensate index calculation with only expanded items
323− itemCenterY += selectedItem.height / 2
315+ itemCenterY += selectedItem.height / 2
324−
316+
325− if (mouseY > launcherListView.height - launcherListView.topMargin - launcherListView.bottomMargin - realItemHeight) {
317+ if (mouseY > launcherListView.height - launcherListView.topMargin - launcherListView.bottomMargin - realItemHeight) {
326− progressiveScrollingTimer.downwards = false
318+ progressiveScrollingTimer.downwards = false
327− progressiveScrollingTimer.start()
319+ progressiveScrollingTimer.start()
328− } else if (mouseY < realItemHeight) {
320+ } else if (mouseY < realItemHeight) {
329− progressiveScrollingTimer.downwards = true
321+ progressiveScrollingTimer.downwards = true
330− progressiveScrollingTimer.start()
322+ progressiveScrollingTimer.start()
331− } else {
323+ } else {
332− progressiveScrollingTimer.stop()
324+ progressiveScrollingTimer.stop()
333− }
325+ }
334
326
335− var newIndex = (itemCenterY + realContentY) / realItemHeight
327+ var newIndex = (itemCenterY + realContentY) / realItemHeight
336
328
337− if (newIndex > draggedIndex + 1) {
329+ if (newIndex > draggedIndex + 1) {
338− newIndex = draggedIndex + 1
330+ newIndex = draggedIndex + 1
339− } else if (newIndex < draggedIndex) {
331+ } else if (newIndex < draggedIndex) {
340− newIndex = draggedIndex -1
332+ newIndex = draggedIndex -1
341− } else {
333+ } else {
342− return
334+ return
343− }
335+ }
344
336
345− if (newIndex >= 0 && newIndex < launcherListView.count) {
337+ if (newIndex >= 0 && newIndex < launcherListView.count) {
346− launcherListView.model.move(draggedIndex, newIndex)
338+ launcherListView.model.move(draggedIndex, newIndex)
347− draggedIndex = newIndex
339+ draggedIndex = newIndex
340+ }
348 }
341 }
349 }
342 }
350 }
343 }
351− }
352− Timer {
344+ Timer {
353− id: progressiveScrollingTimer
345+ id: progressiveScrollingTimer
354− interval: 2
346+ interval: 2
355− repeat: true
347+ repeat: true
356− running: false
348+ running: false
357− property bool downwards: true
349+ property bool downwards: true
358− onTriggered: {
350+ onTriggered: {
359− if (downwards) {
351+ if (downwards) {
360− var minY = -launcherListView.topMargin
352+ var minY = -launcherListView.topMargin
361− if (launcherListView.contentY > minY) {
353+ if (launcherListView.contentY > minY) {
362− launcherListView.contentY = Math.max(launcherListView.contentY - units.dp(2), minY)
354+ launcherListView.contentY = Math.max(launcherListView.contentY - units.dp(2), minY)
363− }
355+ }
364− } else {
356+ } else {
365− var maxY = launcherListView.contentHeight - launcherListView.height + launcherListView.topMargin + dndArea.selectedItem.height*2
357+ var maxY = launcherListView.contentHeight - launcherListView.height + launcherListView.topMargin + dndArea.selectedItem.height*2
366− if (launcherListView.contentY < maxY) {
358+ if (launcherListView.contentY < maxY) {
367− launcherListView.contentY = Math.min(launcherListView.contentY + units.dp(2), maxY)
359+ launcherListView.contentY = Math.min(launcherListView.contentY + units.dp(2), maxY)
360+ }
368 }
361 }
369 }
362 }
370 }
363 }
371− }
372
364
373− MouseArea {
365+ MouseArea {
374− id: topFoldingArea
366+ id: topFoldingArea
375− anchors {
367+ anchors {
376− left: parent.left
368+ left: parent.left
377− right: parent.right
369+ right: parent.right
378− top: parent.top
370+ top: parent.top
371+ topMargin: launcherListView.topMargin
372+ }
373+ height: launcherListView.itemSize / 2
379− topMargin: launcherListView.topMargin
374+ enabled: launcherListView.contentY > -launcherListView.topMargin
375+ onClicked: launcherListView.flick(0, launcherListView.clickFlickSpeed)
380 }
376 }
381− height: launcherListView.itemSize / 2
382− enabled: launcherListView.contentY > -launcherListView.topMargin
383− onClicked: launcherListView.flick(0, launcherListView.clickFlickSpeed)
384− }
385
377
386− MouseArea {
378+ MouseArea {
387− id: bottomFoldingArea
379+ id: bottomFoldingArea
388− anchors {
380+ anchors {
389− left: parent.left
381+ left: parent.left
390− right: parent.right
382+ right: parent.right
391− bottom: parent.bottom
383+ bottom: parent.bottom
392− bottomMargin: launcherListView.bottomMargin
384+ bottomMargin: launcherListView.bottomMargin
385+ }
386+ height: launcherListView.itemHeight / 2
387+ enabled: launcherListView.contentHeight - launcherListView.height - launcherListView.contentY > -launcherListView.bottomMargin
388+ onClicked: launcherListView.flick(0, -launcherListView.clickFlickSpeed)
393 }
389 }
394− height: launcherListView.itemHeight / 2
395− enabled: launcherListView.contentHeight - launcherListView.height - launcherListView.contentY > -launcherListView.bottomMargin
396− onClicked: launcherListView.flick(0, -launcherListView.clickFlickSpeed)
397 }
390 }
398 }
391 }
399− }
400
392
401 LauncherDelegate {
393 LauncherDelegate {
402 id: fakeDragItem
394 id: fakeDragItem
@@ -412,29 +404,4 @@ Item {
412 }
404 }
413
405
414 }
406 }
415−
416− Component {
417− id: popoverComponent
418− Popover {
419− id: popover
420− width: units.gu(20)
421− property var model
422− property string appId
423−
424− Column {
425− width: parent.width
426− height: childrenRect.height
427− Repeater {
428− model: popover.model
429− ListItems.Standard {
430− text: model.label
431− onClicked: {
432− LauncherModel.quickListActionInvoked(appId, index)
433− PopupUtils.close(popover)
434− }
435− }
436− }
437− }
438− }
439− }
440}
407}