on ef246e1 help sign in
unity8/Launcher/LauncherPanel.qml
186 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 "../Components/ListItems"
22Item {
23 id: root
25 rotation: inverted ? 180 : 0
27 property var model
28 property bool inverted: true
29 property bool dragging: false
30 property bool moving: launcherListView.moving || launcherListView.flicking
31 property int dragPosition: 0
32 property int highlightIndex: -1
34 signal applicationSelected(string desktopFile)
35 signal dashItemSelected(int index)
37 onDragPositionChanged: {
38 var effectiveDragPosition = root.inverted ? launcherListView.height - dragPosition : dragPosition - mainColumn.anchors.margins
40 var hiddenContentHeight = launcherListView.contentHeight - launcherListView.height
41 // Shortening scrollable height because the first/last item needs to be fully expanded before reaching the top/bottom
42 var scrollableHeight = launcherListView.height - (launcherListView.itemSize + launcherColumn.spacing) *2
43 // As we shortened the scrollableHeight, lets move everything down by the itemSize
44 var shortenedEffectiveDragPosition = effectiveDragPosition - launcherListView.itemSize - launcherColumn.spacing
45 var newContentY = shortenedEffectiveDragPosition * hiddenContentHeight / scrollableHeight
47 // limit top/bottom to prevent overshooting
48 launcherListView.contentY = Math.min(hiddenContentHeight, Math.max(0, newContentY));
50 // Now calculate the current index:
51 // > the current mouse position + the hidden/scolled content on top is the mouse position in the averall view
52 // > adjust that removing all the margins
53 // > divide by itemSize to get index
54 highlightIndex = (effectiveDragPosition + launcherListView.contentY - mainColumn.anchors.margins*3 - launcherColumn.spacing/2) / (launcherListView.itemSize + launcherColumn.spacing)
55 }
57 BorderImage {
58 id: background
59 source: "graphics/launcher_bg.sci"
60 anchors.fill: parent
61 }
63 Column {
64 id: mainColumn
65 anchors {
66 fill: parent
67 topMargin: units.gu(0.5)
68 bottomMargin: units.gu(1)
69 leftMargin: units.gu(0.5)
70 rightMargin: units.gu(0.5)
71 }
72 spacing: units.gu(0.5)
74 MouseArea {
75 id: dashItem
76 width: parent.width
77 height: units.gu(6.5)
78 onClicked: root.dashItemSelected(0)
79 z: 1
80 Image {
81 objectName: "dashItem"
82 width: units.gu(5.5)
83 height: width
84 anchors.centerIn: parent
85 source: "graphics/home.png"
86 }
87 }
88 ThinDivider {
89 anchors {
90 left: parent.left
91 right: parent.right
92 margins: -mainColumn.anchors.leftMargin
93 }
94 rotation: root.rotation
95 }
97 Item {
98 anchors.left: parent.left
99 anchors.right: parent.right
100 height: parent.height - dashItem.height - parent.spacing*2
101 ListView {
102 id: launcherListView
103 objectName: "launcherListView"
104 anchors.fill: parent
105 anchors.topMargin: -itemSize
106 anchors.bottomMargin: -itemSize
107 topMargin: itemSize
108 bottomMargin: itemSize
109 height: parent.height - dashItem.height - parent.spacing*2
110 model: root.model
111 cacheBuffer: itemSize * 3
112 snapMode: ListView.SnapToItem
113 highlightRangeMode: ListView.ApplyRange
114 preferredHighlightBegin: (height - itemSize) / 2
115 preferredHighlightEnd: (height + itemSize) / 2
117 // The height of the area where icons start getting folded
118 property int foldingAreaHeight: itemSize * 0.75
119 property int itemSize: width
120 property int clickFlickSpeed: units.gu(60)
122 delegate: LauncherDelegate {
123 id: launcherDelegate
124 objectName: "launcherDelegate" + index
125 width: launcherListView.itemSize
126 height: launcherListView.itemSize
127 iconName: model.icon
128 inverted: root.inverted
129 highlighted: root.dragging && index === root.highlightIndex
130 z: -Math.abs(offset)
131 state: "docked"
132 maxAngle: 60
134 onClicked: {
135 // First/last item do the scrolling at more than 12 degrees
136 if (index == 0 || index == launcherListView.count -1) {
137 if (angle > 12) {
138 launcherListView.flick(0, -launcherListView.clickFlickSpeed);
139 } else if (angle < -12) {
140 launcherListView.flick(0, launcherListView.clickFlickSpeed);
141 } else {
142 root.applicationSelected(launcherModel.get(index).desktopFile);
143 }
144 return;
145 }
147 // the rest launches apps up to an angle of 30 degrees
148 if (angle > 30) {
149 launcherListView.flick(0, -launcherListView.clickFlickSpeed);
150 } else if (angle < -30) {
151 launcherListView.flick(0, launcherListView.clickFlickSpeed);
152 } else {
153 root.applicationSelected(launcherModel.get(index).desktopFile);
154 }
155 }
156 }
158 MouseArea {
159 id: topFoldingArea
160 anchors {
161 left: parent.left
162 right: parent.right
163 top: parent.top
164 topMargin: launcherListView.topMargin
165 }
166 height: launcherListView.itemSize / 2
167 enabled: launcherListView.contentY > -launcherListView.topMargin
168 onClicked: launcherListView.flick(0, launcherListView.clickFlickSpeed)
169 }
171 MouseArea {
172 id: bottomFoldingArea
173 anchors {
174 left: parent.left
175 right: parent.right
176 bottom: parent.bottom
177 bottomMargin: launcherListView.bottomMargin
178 }
179 height: launcherListView.itemSize / 2
180 enabled: launcherListView.contentHeight - launcherListView.height - launcherListView.contentY > -launcherListView.bottomMargin
181 onClicked: launcherListView.flick(0, -launcherListView.clickFlickSpeed)
182 }
183 }
184 }
185 }