@@ -15,6 +15,7 @@
17import QtQuick 2.4
17import QtQuick 2.4
18+import QtQml.StateMachine 1.0 as DSM
18import Ubuntu.Components 1.3
19import Ubuntu.Components 1.3
19import Unity.Launcher 0.1
20import Unity.Launcher 0.1
20import Ubuntu.Components.Popups 1.3
21import Ubuntu.Components.Popups 1.3
@@ -44,9 +45,6 @@ Rectangle {
44 if (quickList.state === "open") {
45 if (quickList.state === "open") {
45 quickList.state = ""
46 quickList.state = ""
47− if (tooltip.state === "open") {
52 function highlightNext() {
50 function highlightNext() {
@@ -175,12 +173,6 @@ Rectangle {
175 property real realContentY: contentY - originY + topMargin
173 property real realContentY: contentY - originY + topMargin
176 property int realItemHeight: itemHeight + spacing
174 property int realItemHeight: itemHeight + spacing
178− onRealContentYChanged : {
179− if (tooltip.state === "open") {
184 // In case the start dragging transition is running, we need to delay the
176 // In case the start dragging transition is running, we need to delay the
185 // move because the displaced transition would clash with it and cause items
177 // move because the displaced transition would clash with it and cause items
186 // to be moved to wrong places
178 // to be moved to wrong places
@@ -235,6 +227,7 @@ Rectangle {
235 // the right app when running autopilot tests for
227 // the right app when running autopilot tests for
236 // multiple apps.
228 // multiple apps.
237 readonly property string appId: model.appId
229 readonly property string appId: model.appId
238 itemIndex: index
231 itemIndex: index
239 itemHeight: launcherListView.itemHeight
232 itemHeight: launcherListView.itemHeight
240 itemWidth: launcherListView.itemWidth
233 itemWidth: launcherListView.itemWidth
@@ -431,20 +424,12 @@ Rectangle {
432 function processPress(mouse) {
425 function processPress(mouse) {
433 selectedItem = launcherListView.itemAt(mouse.x, mouse.y + launcherListView.realContentY)
426 selectedItem = launcherListView.itemAt(mouse.x, mouse.y + launcherListView.realContentY)
435− if (tooltip.state === "open") {
440 onClicked: {
429 onClicked: {
441 var index = Math.floor((mouseY + launcherListView.realContentY) / launcherListView.realItemHeight);
430 var index = Math.floor((mouseY + launcherListView.realContentY) / launcherListView.realItemHeight);
442 var clickedItem = launcherListView.itemAt(mouseX, mouseY + launcherListView.realContentY)
431 var clickedItem = launcherListView.itemAt(mouseX, mouseY + launcherListView.realContentY)
444− if (tooltip.state === "open") {
448 // Check if we actually clicked an item or only at the spacing in between
433 // Check if we actually clicked an item or only at the spacing in between
449 if (clickedItem === null) {
434 if (clickedItem === null) {
@@ -544,10 +529,6 @@ Rectangle {
544 startY = mouse.y
529 startY = mouse.y
551 onPositionChanged: {
532 onPositionChanged: {
552 processPositionChanged(mouse)
533 processPositionChanged(mouse)
@@ -602,17 +583,6 @@ Rectangle {
602 draggedIndex = newIndex
583 draggedIndex = newIndex
606− var index = Math.floor((mouse.y + launcherListView.realContentY) / launcherListView.realItemHeight);
607− var clickedItem = launcherListView.itemAt(mouse.x, mouse.y + launcherListView.realContentY);
609− // Check if we actually hovered an item or only the spacing in between
610− if (clickedItem === null || mouse.buttons) {
615− tooltip.open(index);
@@ -866,13 +836,15 @@ Rectangle {
866 id: tooltipShape
836 id: tooltipShape
867 objectName: "tooltipShape"
837 objectName: "tooltipShape"
868 anchors.fill: tooltip
838 anchors.fill: tooltip
869− opacity: tooltip.state === "open" && quickList.state != "open" ? 0.95 : 0
839+ opacity: tooltipShownState.active ? 0.95 : 0
870 visible: opacity > 0
840 visible: opacity > 0
871 rotation: root.rotation
841 rotation: root.rotation
872 aspect: UbuntuShape.Flat
842 aspect: UbuntuShape.Flat
874 Behavior on opacity {
844 Behavior on opacity {
875− UbuntuNumberAnimation {}
845+ UbuntuNumberAnimation {
846+ duration: UbuntuAnimation.BriskDuration
878 source: ShaderEffectSource {
850 source: ShaderEffectSource {
@@ -896,6 +868,7 @@ Rectangle {
897 Rectangle {
869 Rectangle {
898 id: tooltip
870 id: tooltip
871+ objectName: "tooltip"
900 color: theme.palette.normal.background
873 color: theme.palette.normal.background
901 visible: tooltipShape.visible
874 visible: tooltipShape.visible
@@ -912,19 +885,17 @@ Rectangle {
912 margins: units.gu(1)
885 margins: units.gu(1)
915− property string text
888+ property var hoveredItem: dndArea.containsMouse ? launcherListView.itemAt(dndArea.mouseX, dndArea.mouseY + launcherListView.realContentY) : null
918− property int itemCenter: item ? root.mapFromItem(tooltip.item, 0, 0).y + (item.height / 2) + tooltip.item.offset : units.gu(1)
890+ property int itemCenter
919 property int offset: itemCenter + (height/2) + units.gu(1) > parent.height ? -itemCenter - (height/2) - units.gu(1) + parent.height :
891 property int offset: itemCenter + (height/2) + units.gu(1) > parent.height ? -itemCenter - (height/2) - units.gu(1) + parent.height :
920 itemCenter - (height/2) < units.gu(1) ? (height/2) - itemCenter + units.gu(1) : 0
892 itemCenter - (height/2) < units.gu(1) ? (height/2) - itemCenter + units.gu(1) : 0
922− function open(index) {
894+ onHoveredItemChanged : {
923− var itemPosition = index * launcherListView.itemHeight;
895+ if (hoveredItem != null && !root.moving) {
924− var height = launcherListView.height - launcherListView.topMargin - launcherListView.bottomMargin
896+ itemCenter = root.mapFromItem(hoveredItem, 0, 0).y + (hoveredItem.height / 2) + hoveredItem.offset
925− item = launcherListView.itemAt(launcherListView.width / 2, itemPosition + launcherListView.itemHeight / 2);
897+ tooltipLabel.text = tooltip.hoveredItem.name
926− tooltip.text = launcherListView.model.get(index).name;
898+ }
927− tooltip.state = "open";
@@ -932,8 +903,72 @@ Rectangle {
932 height: parent.height
903 height: parent.height
933 anchors.centerIn: parent
904 anchors.centerIn: parent
934 verticalAlignment: Label.AlignVCenter
905 verticalAlignment: Label.AlignVCenter
936 color: theme.palette.normal.backgroundText
906 color: theme.palette.normal.backgroundText
910+ id: tooltipStateMachine
911+ initialState: tooltipHiddenState
915+ id: tooltipHiddenState
917+ DSM.SignalTransition {
918+ targetState: tooltipShownState
919+ signal: tooltip.hoveredItemChanged
920+ // !dndArea.pressed allows us to filter out touch input events
921+ guard: tooltip.hoveredItem != null && !dndArea.pressed && !root.moving
926+ id: tooltipShownState
928+ DSM.SignalTransition {
929+ targetState: tooltipHiddenState
930+ signal: tooltip.hoveredItemChanged
931+ guard: tooltip.hoveredItem == null
934+ DSM.SignalTransition {
935+ targetState: tooltipHiddenState
936+ signal: dndArea.exited
939+ DSM.SignalTransition {
940+ targetState: tooltipDismissedState
941+ signal: dndArea.onPressed
944+ DSM.SignalTransition {
945+ targetState: tooltipDismissedState
946+ signal: quickList.stateChanged
947+ guard: quickList.state === "open"
950+ DSM.SignalTransition {
951+ targetState: tooltipDismissedState
952+ signal: root.movingChanged
958+ id: tooltipDismissedState
960+ DSM.SignalTransition {
961+ targetState: tooltipHiddenState
962+ signal: dndArea.positionChanged
963+ guard: quickList.state != "open" && !dndArea.pressed && !dndArea.moving
966+ DSM.SignalTransition {
967+ targetState: tooltipHiddenState
968+ signal: dndArea.exited
969+ guard: quickList.state != "open"