@@ -15,6 +15,7 @@
1515 */
1616
1717import QtQuick 2.4
18+import QtQml.StateMachine 1.0 as DSM
1819import Ubuntu.Components 1.3
1920import Unity.Launcher 0.1
2021import Ubuntu.Components.Popups 1.3
@@ -44,9 +45,6 @@ Rectangle {
4445 if (quickList.state === "open") {
4546 quickList.state = ""
4647 }
47− if (tooltip.state === "open") {
48− quickList.state = ""
49− }
5048 }
5149
5250 function highlightNext() {
@@ -175,12 +173,6 @@ Rectangle {
175173 property real realContentY: contentY - originY + topMargin
176174 property int realItemHeight: itemHeight + spacing
177175
178− onRealContentYChanged : {
179− if (tooltip.state === "open") {
180− tooltip.state = "";
181− }
182− }
183−
184176 // In case the start dragging transition is running, we need to delay the
185177 // move because the displaced transition would clash with it and cause items
186178 // to be moved to wrong places
@@ -235,6 +227,7 @@ Rectangle {
235227 // the right app when running autopilot tests for
236228 // multiple apps.
237229 readonly property string appId: model.appId
230+ name: model.name
238231 itemIndex: index
239232 itemHeight: launcherListView.itemHeight
240233 itemWidth: launcherListView.itemWidth
@@ -431,20 +424,12 @@ Rectangle {
431424
432425 function processPress(mouse) {
433426 selectedItem = launcherListView.itemAt(mouse.x, mouse.y + launcherListView.realContentY)
434−
435− if (tooltip.state === "open") {
436− tooltip.state = "";
437− }
438427 }
439428
440429 onClicked: {
441430 var index = Math.floor((mouseY + launcherListView.realContentY) / launcherListView.realItemHeight);
442431 var clickedItem = launcherListView.itemAt(mouseX, mouseY + launcherListView.realContentY)
443432
444− if (tooltip.state === "open") {
445− tooltip.state = "";
446− }
447−
448433 // Check if we actually clicked an item or only at the spacing in between
449434 if (clickedItem === null) {
450435 return;
@@ -544,10 +529,6 @@ Rectangle {
544529 startY = mouse.y
545530 }
546531
547− onExited: {
548− tooltip.state = "";
549− }
550−
551532 onPositionChanged: {
552533 processPositionChanged(mouse)
553534 }
@@ -602,17 +583,6 @@ Rectangle {
602583 draggedIndex = newIndex
603584 }
604585 }
605− } else {
606− var index = Math.floor((mouse.y + launcherListView.realContentY) / launcherListView.realItemHeight);
607− var clickedItem = launcherListView.itemAt(mouse.x, mouse.y + launcherListView.realContentY);
608−
609− // Check if we actually hovered an item or only the spacing in between
610− if (clickedItem === null || mouse.buttons) {
611− tooltip.state = "";
612− return;
613− }
614−
615− tooltip.open(index);
616586 }
617587 }
618588 }
@@ -866,13 +836,15 @@ Rectangle {
866836 id: tooltipShape
867837 objectName: "tooltipShape"
868838 anchors.fill: tooltip
869− opacity: tooltip.state === "open" && quickList.state != "open" ? 0.95 : 0
839+ opacity: tooltipShownState.active ? 0.95 : 0
870840 visible: opacity > 0
871841 rotation: root.rotation
872842 aspect: UbuntuShape.Flat
873843
874844 Behavior on opacity {
875− UbuntuNumberAnimation {}
845+ UbuntuNumberAnimation {
846+ duration: UbuntuAnimation.BriskDuration
847+ }
876848 }
877849
878850 source: ShaderEffectSource {
@@ -896,6 +868,7 @@ Rectangle {
896868
897869 Rectangle {
898870 id: tooltip
871+ objectName: "tooltip"
899872
900873 color: theme.palette.normal.background
901874 visible: tooltipShape.visible
@@ -912,19 +885,17 @@ Rectangle {
912885 margins: units.gu(1)
913886 }
914887
915− property string text
916− property var item
888+ property var hoveredItem: dndArea.containsMouse ? launcherListView.itemAt(dndArea.mouseX, dndArea.mouseY + launcherListView.realContentY) : null
917889
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
919891 property int offset: itemCenter + (height/2) + units.gu(1) > parent.height ? -itemCenter - (height/2) - units.gu(1) + parent.height :
920892 itemCenter - (height/2) < units.gu(1) ? (height/2) - itemCenter + units.gu(1) : 0
921893
922− function open(index) {
923− var itemPosition = index * launcherListView.itemHeight;
924− var height = launcherListView.height - launcherListView.topMargin - launcherListView.bottomMargin
925− item = launcherListView.itemAt(launcherListView.width / 2, itemPosition + launcherListView.itemHeight / 2);
926− tooltip.text = launcherListView.model.get(index).name;
927− tooltip.state = "open";
894+ onHoveredItemChanged : {
895+ if (hoveredItem != null && !root.moving) {
896+ itemCenter = root.mapFromItem(hoveredItem, 0, 0).y + (hoveredItem.height / 2) + hoveredItem.offset
897+ tooltipLabel.text = tooltip.hoveredItem.name
898+ }
928899 }
929900
930901 Label {
@@ -932,8 +903,72 @@ Rectangle {
932903 height: parent.height
933904 anchors.centerIn: parent
934905 verticalAlignment: Label.AlignVCenter
935− text: tooltip.text
936906 color: theme.palette.normal.backgroundText
937907 }
908+
909+ DSM.StateMachine {
910+ id: tooltipStateMachine
911+ initialState: tooltipHiddenState
912+ running: true
913+
914+ DSM.State {
915+ id: tooltipHiddenState
916+
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
922+ }
923+ }
924+
925+ DSM.State {
926+ id: tooltipShownState
927+
928+ DSM.SignalTransition {
929+ targetState: tooltipHiddenState
930+ signal: tooltip.hoveredItemChanged
931+ guard: tooltip.hoveredItem == null
932+ }
933+
934+ DSM.SignalTransition {
935+ targetState: tooltipHiddenState
936+ signal: dndArea.exited
937+ }
938+
939+ DSM.SignalTransition {
940+ targetState: tooltipDismissedState
941+ signal: dndArea.onPressed
942+ }
943+
944+ DSM.SignalTransition {
945+ targetState: tooltipDismissedState
946+ signal: quickList.stateChanged
947+ guard: quickList.state === "open"
948+ }
949+
950+ DSM.SignalTransition {
951+ targetState: tooltipDismissedState
952+ signal: root.movingChanged
953+ guard: root.moving
954+ }
955+ }
956+
957+ DSM.State {
958+ id: tooltipDismissedState
959+
960+ DSM.SignalTransition {
961+ targetState: tooltipHiddenState
962+ signal: dndArea.positionChanged
963+ guard: quickList.state != "open" && !dndArea.pressed && !dndArea.moving
964+ }
965+
966+ DSM.SignalTransition {
967+ targetState: tooltipHiddenState
968+ signal: dndArea.exited
969+ guard: quickList.state != "open"
970+ }
971+ }
972+ }
938973 }
939974}