on e6bb3a2 help sign in
unity8/Launcher/LauncherPanel.qml
188 lines 7.7 kB history raw
1/*
2 * Copyright (C) 2013 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
17import QtQuick 2.0
18import Ubuntu.Components 0.1
19import Unity 0.1
20import Unity.Launcher 0.1
21import "../Components/ListItems"
23Item {
24 id: root
26 rotation: inverted ? 180 : 0
28 property var model
29 property bool inverted: true
30 property bool dragging: false
31 property bool moving: launcherListView.moving || launcherListView.flicking
32 property int dragPosition: 0
33 property int highlightIndex: -1
35 signal applicationSelected(string desktopFile)
36 signal dashItemSelected(int index)
38 onDragPositionChanged: {
39 var effectiveDragPosition = root.inverted ? launcherListView.height - dragPosition : dragPosition - mainColumn.anchors.margins
41 var hiddenContentHeight = launcherListView.contentHeight - launcherListView.height
42 // Shortening scrollable height because the first/last item needs to be fully expanded before reaching the top/bottom
43 var scrollableHeight = launcherListView.height - (launcherListView.itemSize + launcherColumn.spacing) *2
44 // As we shortened the scrollableHeight, lets move everything down by the itemSize
45 var shortenedEffectiveDragPosition = effectiveDragPosition - launcherListView.itemSize - launcherColumn.spacing
46 var newContentY = shortenedEffectiveDragPosition * hiddenContentHeight / scrollableHeight
48 // limit top/bottom to prevent overshooting
49 launcherListView.contentY = Math.min(hiddenContentHeight, Math.max(0, newContentY));
51 // Now calculate the current index:
52 // > the current mouse position + the hidden/scolled content on top is the mouse position in the averall view
53 // > adjust that removing all the margins
54 // > divide by itemSize to get index
55 highlightIndex = (effectiveDragPosition + launcherListView.contentY - mainColumn.anchors.margins*3 - launcherColumn.spacing/2) / (launcherListView.itemSize + launcherColumn.spacing)
56 }
58 BorderImage {
59 id: background
60 source: "graphics/launcher_bg.sci"
61 anchors.fill: parent
62 }
64 Column {
65 id: mainColumn
66 anchors {
67 fill: parent
68 topMargin: units.gu(0.5)
69 bottomMargin: units.gu(1)
70 leftMargin: units.gu(0.5)
71 rightMargin: units.gu(0.5)
72 }
73 spacing: units.gu(0.5)
75 MouseArea {
76 id: dashItem
77 width: parent.width
78 height: units.gu(6.5)
79 onClicked: root.dashItemSelected(0)
80 z: 1
81 Image {
82 objectName: "dashItem"
83 width: units.gu(5.5)
84 height: width
85 anchors.centerIn: parent
86 source: "graphics/home.png"
87 rotation: root.rotation
88 }
89 }
90 ThinDivider {
91 anchors {
92 left: parent.left
93 right: parent.right
94 margins: -mainColumn.anchors.leftMargin
95 }
96 rotation: root.rotation
97 }
99 Item {
100 anchors.left: parent.left
101 anchors.right: parent.right
102 height: parent.height - dashItem.height - parent.spacing*2
103 ListView {
104 id: launcherListView
105 objectName: "launcherListView"
106 anchors.fill: parent
107 anchors.topMargin: -itemSize
108 anchors.bottomMargin: -itemSize
109 topMargin: itemSize
110 bottomMargin: itemSize
111 height: parent.height - dashItem.height - parent.spacing*2
112 model: root.model
113 cacheBuffer: itemSize * 3
114 snapMode: ListView.SnapToItem
115 highlightRangeMode: ListView.ApplyRange
116 preferredHighlightBegin: (height - itemSize) / 2
117 preferredHighlightEnd: (height + itemSize) / 2
119 // The height of the area where icons start getting folded
120 property int foldingAreaHeight: itemSize * 0.75
121 property int itemSize: width
122 property int clickFlickSpeed: units.gu(60)
124 delegate: LauncherDelegate {
125 id: launcherDelegate
126 objectName: "launcherDelegate" + index
127 width: launcherListView.itemSize
128 height: launcherListView.itemSize
129 iconName: model.icon
130 inverted: root.inverted
131 highlighted: root.dragging && index === root.highlightIndex
132 z: -Math.abs(offset)
133 state: "docked"
134 maxAngle: 60
136 onClicked: {
137 // First/last item do the scrolling at more than 12 degrees
138 if (index == 0 || index == launcherListView.count -1) {
139 if (angle > 12) {
140 launcherListView.flick(0, -launcherListView.clickFlickSpeed);
141 } else if (angle < -12) {
142 launcherListView.flick(0, launcherListView.clickFlickSpeed);
143 } else {
144 root.applicationSelected(LauncherModel.get(index).desktopFile);
145 }
146 return;
147 }
149 // the rest launches apps up to an angle of 30 degrees
150 if (angle > 30) {
151 launcherListView.flick(0, -launcherListView.clickFlickSpeed);
152 } else if (angle < -30) {
153 launcherListView.flick(0, launcherListView.clickFlickSpeed);
154 } else {
155 root.applicationSelected(LauncherModel.get(index).desktopFile);
156 }
157 }
158 }
160 MouseArea {
161 id: topFoldingArea
162 anchors {
163 left: parent.left
164 right: parent.right
165 top: parent.top
166 topMargin: launcherListView.topMargin
167 }
168 height: launcherListView.itemSize / 2
169 enabled: launcherListView.contentY > -launcherListView.topMargin
170 onClicked: launcherListView.flick(0, launcherListView.clickFlickSpeed)
171 }
173 MouseArea {
174 id: bottomFoldingArea
175 anchors {
176 left: parent.left
177 right: parent.right
178 bottom: parent.bottom
179 bottomMargin: launcherListView.bottomMargin
180 }
181 height: launcherListView.itemSize / 2
182 enabled: launcherListView.contentHeight - launcherListView.height - launcherListView.contentY > -launcherListView.bottomMargin
183 onClicked: launcherListView.flick(0, -launcherListView.clickFlickSpeed)
184 }
185 }
186 }
187 }