18 import Ubuntu.Components 0.1
19 import Ubuntu.Components.ListItems 0.1 as ListItems
20 import Unity.Launcher 0.1
21 import Ubuntu.Components.Popups 0.1
22 import
"../Components/ListItems"
23 import "../Components/"
29 rotation: inverted ? 180 : 0
32 property bool inverted:
true
33 property bool dragging:
false
34 property bool moving: launcherListView.moving || launcherListView.flicking
35 property bool preventHiding: moving || dndArea.draggedIndex >= 0 || quickList.state ===
"open" || dndArea.pressed
36 property int highlightIndex: -1
38 signal applicationSelected(
string appId)
50 color: UbuntuColors.orange
54 objectName:
"dashItem"
57 anchors.centerIn: parent
58 source:
"graphics/home.png"
59 rotation: root.rotation
64 onClicked: root.showDashHome()
72 margins: -mainColumn.anchors.leftMargin
74 rotation: root.rotation
78 anchors.left: parent.left
79 anchors.right: parent.right
80 height: parent.height - dashItem.height - parent.spacing*2
88 objectName:
"launcherListView"
91 topMargin: -extensionSize + units.gu(0.5)
92 bottomMargin: -extensionSize + units.gu(1)
93 leftMargin: units.gu(0.5)
94 rightMargin: units.gu(0.5)
96 topMargin: extensionSize
97 bottomMargin: extensionSize
98 height: parent.height - dashItem.height - parent.spacing*2
100 cacheBuffer: itemHeight * 3
101 snapMode: interactive ? ListView.SnapToItem : ListView.NoSnap
102 highlightRangeMode: ListView.ApplyRange
103 preferredHighlightBegin: (height - itemHeight) / 2
104 preferredHighlightEnd: (height + itemHeight) / 2
110 property int extensionSize: 0
120 Component.onCompleted: {
121 extensionSize = itemHeight * 3
122 flick(0, clickFlickSpeed)
126 property int foldingStartHeight: units.gu(6.5)
128 property int foldingStopHeight: foldingStartHeight - itemHeight - spacing
129 property int itemWidth: units.gu(7)
130 property int itemHeight: units.gu(6.5)
131 property int clickFlickSpeed: units.gu(60)
132 property int draggedIndex: dndArea.draggedIndex
133 property real realContentY: contentY - originY + topMargin
134 property int realItemHeight: itemHeight + spacing
139 property bool draggingTransitionRunning:
false
140 property int scheduledMoveTo: -1
142 displaced: Transition {
143 NumberAnimation { properties:
"x,y"; duration: UbuntuAnimation.FastDuration; easing: UbuntuAnimation.StandardEasing }
146 delegate: FoldingLauncherDelegate {
148 objectName:
"launcherDelegate" + index
149 itemHeight: launcherListView.itemHeight
150 itemWidth: launcherListView.itemWidth
155 progress: model.progress
156 clipCorner: model.pinned
157 itemFocused: model.focused
158 inverted: root.inverted
161 property bool dragging:
false
165 objectName:
"dropIndicator"
166 anchors.centerIn: parent
167 width: parent.width + mainColumn.anchors.leftMargin + mainColumn.anchors.rightMargin
169 source:
"graphics/divider-line.png"
175 when: dndArea.selectedItem === launcherDelegate && fakeDragItem.visible && !dragging
177 target: launcherDelegate
185 target: launcherDelegate
190 target: dropIndicator
196 when: dndArea.draggedIndex >= 0 && (dndArea.preDragging || dndArea.dragging || dndArea.postDragging) && dndArea.draggedIndex != index
198 target: launcherDelegate
210 NumberAnimation { properties:
"itemOpacity"; duration: UbuntuAnimation.FastDuration }
215 NumberAnimation { properties:
"itemOpacity"; duration: UbuntuAnimation.FastDuration }
216 UbuntuNumberAnimation { properties:
"angle,offset" }
221 NumberAnimation { properties:
"itemOpacity"; duration: UbuntuAnimation.BriskDuration }
222 UbuntuNumberAnimation { properties:
"angle,offset" }
225 id: draggingTransition
228 SequentialAnimation {
229 PropertyAction { target: launcherListView;
property:
"draggingTransitionRunning"; value:
true }
231 UbuntuNumberAnimation { properties:
"height" }
232 NumberAnimation { target: dropIndicator; properties:
"opacity"; duration: UbuntuAnimation.FastDuration }
236 if (launcherListView.scheduledMoveTo > -1) {
237 launcherListView.model.move(dndArea.draggedIndex, launcherListView.scheduledMoveTo)
238 dndArea.draggedIndex = launcherListView.scheduledMoveTo
239 launcherListView.scheduledMoveTo = -1
243 PropertyAction { target: launcherListView;
property:
"draggingTransitionRunning"; value:
false }
249 NumberAnimation { target: dropIndicator; properties:
"opacity"; duration: UbuntuAnimation.SnapDuration }
250 NumberAnimation { properties:
"itemOpacity"; duration: UbuntuAnimation.BriskDuration }
251 SequentialAnimation {
252 ScriptAction { script:
if (index == launcherListView.count-1) launcherListView.flick(0, -launcherListView.clickFlickSpeed); }
253 UbuntuNumberAnimation { properties:
"height" }
254 ScriptAction { script:
if (index == launcherListView.count-1) launcherListView.flick(0, -launcherListView.clickFlickSpeed); }
255 PropertyAction { target: dndArea;
property:
"postDragging"; value:
false }
256 PropertyAction { target: dndArea;
property:
"draggedIndex"; value: -1 }
264 objectName:
"dndArea"
267 topMargin: launcherListView.topMargin
268 bottomMargin: launcherListView.bottomMargin
270 drag.minimumY: -launcherListView.topMargin
271 drag.maximumY: height + launcherListView.bottomMargin
273 property int draggedIndex: -1
274 property var selectedItem
275 property bool preDragging:
false
276 property bool dragging: selectedItem !== undefined && selectedItem !== null && selectedItem.dragging
277 property bool postDragging:
false
282 selectedItem = launcherListView.itemAt(mouseX, mouseY + launcherListView.realContentY)
286 var index = Math.floor((mouseY + launcherListView.realContentY) / launcherListView.realItemHeight);
287 var clickedItem = launcherListView.itemAt(mouseX, mouseY + launcherListView.realContentY)
290 if (clickedItem === null) {
295 if (index == 0 || index == launcherListView.count - 1) {
296 if (clickedItem.angle > 12) {
297 launcherListView.flick(0, -launcherListView.clickFlickSpeed);
298 }
else if (clickedItem.angle < -12) {
299 launcherListView.flick(0, launcherListView.clickFlickSpeed);
301 root.applicationSelected(LauncherModel.get(index).appId);
307 if (clickedItem.angle > 30) {
308 launcherListView.flick(0, -launcherListView.clickFlickSpeed);
309 }
else if (clickedItem.angle < -30) {
310 launcherListView.flick(0, launcherListView.clickFlickSpeed);
312 root.applicationSelected(LauncherModel.get(index).appId);
317 selectedItem = undefined;
319 postDragging =
false;
323 var droppedIndex = draggedIndex;
334 selectedItem.dragging =
false;
335 selectedItem = undefined;
338 drag.target = undefined
340 progressiveScrollingTimer.stop();
341 launcherListView.interactive =
true;
342 if (droppedIndex >= launcherListView.count - 2 && postDragging) {
343 launcherListView.flick(0, -launcherListView.clickFlickSpeed);
345 if (droppedIndex == 0 && postDragging) {
346 launcherListView.flick(0, launcherListView.clickFlickSpeed);
351 if (Math.abs(selectedItem.angle) > 30) {
355 draggedIndex = Math.floor((mouseY + launcherListView.realContentY) / launcherListView.realItemHeight);
358 quickList.item = selectedItem;
359 quickList.model = launcherListView.model.get(draggedIndex).quickList;
360 quickList.appId = launcherListView.model.get(draggedIndex).appId;
361 quickList.state =
"open";
363 launcherListView.interactive =
false
365 var yOffset = draggedIndex > 0 ? (mouseY + launcherListView.realContentY) % (draggedIndex * launcherListView.realItemHeight) : mouseY + launcherListView.realContentY
367 fakeDragItem.iconName = launcherListView.model.get(draggedIndex).icon
368 fakeDragItem.x = units.gu(0.5)
369 fakeDragItem.y = mouseY - yOffset + launcherListView.anchors.topMargin + launcherListView.topMargin
370 fakeDragItem.angle = selectedItem.angle * (root.inverted ? -1 : 1)
371 fakeDragItem.offset = selectedItem.offset * (root.inverted ? -1 : 1)
372 fakeDragItem.count = LauncherModel.get(draggedIndex).count
373 fakeDragItem.progress = LauncherModel.get(draggedIndex).progress
374 fakeDragItem.flatten()
375 drag.target = fakeDragItem
382 if (draggedIndex >= 0) {
383 if (!selectedItem.dragging) {
384 var distance = Math.max(Math.abs(mouseX - startX), Math.abs(mouseY - startY))
385 if (!preDragging && distance > units.gu(1.5)) {
387 quickList.state =
"";
389 if (distance > launcherListView.itemHeight) {
390 selectedItem.dragging =
true
394 if (!selectedItem.dragging) {
398 var itemCenterY = fakeDragItem.y + fakeDragItem.height / 2
401 itemCenterY += (launcherListView.itemHeight - selectedItem.height) / 2
403 if (mouseY > launcherListView.height - launcherListView.topMargin - launcherListView.bottomMargin - launcherListView.realItemHeight) {
404 progressiveScrollingTimer.downwards =
false
405 progressiveScrollingTimer.start()
406 }
else if (mouseY < launcherListView.realItemHeight) {
407 progressiveScrollingTimer.downwards =
true
408 progressiveScrollingTimer.start()
410 progressiveScrollingTimer.stop()
413 var newIndex = (itemCenterY + launcherListView.realContentY) / launcherListView.realItemHeight
415 if (newIndex > draggedIndex + 1) {
416 newIndex = draggedIndex + 1
417 }
else if (newIndex < draggedIndex) {
418 newIndex = draggedIndex -1
423 if (newIndex >= 0 && newIndex < launcherListView.count) {
424 if (launcherListView.draggingTransitionRunning) {
425 launcherListView.scheduledMoveTo = newIndex
427 launcherListView.model.move(draggedIndex, newIndex)
428 draggedIndex = newIndex
435 id: progressiveScrollingTimer
439 property bool downwards:
true
442 var minY = -launcherListView.topMargin
443 if (launcherListView.contentY > minY) {
444 launcherListView.contentY = Math.max(launcherListView.contentY - units.dp(2), minY)
447 var maxY = launcherListView.contentHeight - launcherListView.height + launcherListView.topMargin + launcherListView.originY
448 if (launcherListView.contentY < maxY) {
449 launcherListView.contentY = Math.min(launcherListView.contentY + units.dp(2), maxY)
459 objectName:
"fakeDragItem"
460 visible: dndArea.draggedIndex >= 0 && !dndArea.postDragging
461 itemWidth: launcherListView.itemWidth
462 itemHeight: launcherListView.itemHeight
465 rotation: root.rotation
467 clipCorner: dndArea.draggedIndex > -1 &&
468 LauncherModel.get(dndArea.draggedIndex).pinned &&
469 !dndArea.preDragging &&
473 fakeDragItemAnimation.start();
476 UbuntuNumberAnimation {
477 id: fakeDragItemAnimation
478 target: fakeDragItem;
479 properties:
"angle,offset";
488 objectName:
"quickListShape"
489 anchors.fill: quickList
490 opacity: quickList.state ===
"open" ? 0.8 : 0
492 rotation: root.rotation
494 Behavior on opacity {
495 UbuntuNumberAnimation {}
503 rightMargin: -units.dp(4)
504 verticalCenter: parent.verticalCenter
505 verticalCenterOffset: -quickList.offset
509 source:
"graphics/quicklist_tooltip.png"
515 enabled: quickList.state ==
"open"
525 objectName:
"quickList"
528 height: quickListColumn.height
529 visible: quickListShape.visible
531 left: root.inverted ? undefined : parent.right
532 right: root.inverted ? parent.left : undefined
535 y: itemCenter - (height / 2) + offset
536 rotation: root.rotation
539 property
string appId
543 property
int itemCenter: item ? root.mapFromItem(quickList.item).y + (item.height / 2) : units.gu(1)
544 property int offset: itemCenter + (height/2) + units.gu(1) > parent.height ? -itemCenter - (height/2) - units.gu(1) + parent.height :
545 itemCenter - (height/2) < units.gu(1) ? (height/2) - itemCenter + units.gu(1) : 0
550 height: childrenRect.height
554 model: quickList.model
557 objectName:
"quickListEntry" + index
558 text: (model.clickable ?
"" :
"<b>") + model.label + (model.clickable ?
"" :
"</b>")
559 highlightWhenPressed: model.clickable
564 __foregroundColor: Theme.palette.selected.backgroundText
567 if (!model.clickable) {
570 quickList.state =
"";
573 LauncherModel.quickListActionInvoked(quickList.appId, index);
574 quickList.model = undefined;