on b9739cb help sign in
unity8/qml/Stage/Spread/Workspaces.qml
343 lines 13 kB history raw
1import QtQuick 2.4
2import Ubuntu.Components 1.3
3import WindowManager 1.0
4import "MathUtils.js" as MathUtils
5import "../../Components"
7Item {
8 id: root
9 implicitWidth: listView.contentWidth
11 property QtObject screen: null
12 property alias workspaceModel: listView.model
13 property var background // TODO: should be stored in the workspace data
15 signal commitScreenSetup();
17 DropArea {
18 anchors.fill: root
20 keys: ['workspace']
22 onEntered: {
23 var index = listView.getDropIndex(drag);
24 drag.source.workspace.assign(workspaceModel, index)
25 listView.dropItemIndex = index;
26 drag.source.inDropArea = true;
27 }
29 onPositionChanged: {
30 var index = listView.getDropIndex(drag);
31 if (listView.dropItemIndex == index) return;
32 listView.model.move(listView.dropItemIndex, index, 1);
33 listView.dropItemIndex = index;
34 }
36 onExited: {
37 drag.source.workspace.unassign()
38 listView.dropItemIndex = -1;
39 drag.source.inDropArea = false;
40 }
42 onDropped: {
43 drop.accept(Qt.MoveAction);
44 listView.dropItemIndex = -1;
45 drag.source.inDropArea = false;
46 }
47 }
48 DropArea {
49 anchors.fill: parent
50 keys: ["application"]
52 onPositionChanged: {
53 listView.progressiveScroll(drag.x)
54 listView.hoveredWorkspaceIndex = listView.getDropIndex(drag)
55 }
56 onExited: {
57 listView.hoveredWorkspaceIndex = -1
58 }
59 }
61 ListView {
62 id: listView
63 anchors.fill: parent
64 anchors.leftMargin: -itemWidth
65 anchors.rightMargin: -itemWidth
66 boundsBehavior: Flickable.StopAtBounds
68 orientation: ListView.Horizontal
69 spacing: units.gu(1)
70 leftMargin: itemWidth
71 rightMargin: itemWidth
73 property var screenSize: screen.availableModes[screen.currentModeIndex].size
74 property int itemWidth: height * screenSize.width / screenSize.height
75 property int foldingAreaWidth: units.gu(10)
76 property real realContentX: contentX - originX + leftMargin
77 property int dropItemIndex: -1
78 property int hoveredWorkspaceIndex: -1
80 function getDropIndex(drag) {
81 var coords = mapToItem(listView.contentItem, drag.x, drag.y)
82 var index = Math.floor((drag.x + listView.realContentX) / (listView.itemWidth + listView.spacing));
83 if (index < 0) index = 0;
84 var upperLimit = dropItemIndex == -1 ? listView.count : listView.count - 1
85 if (index > upperLimit) index = upperLimit;
86 return index;
87 }
89 function progressiveScroll(mouseX) {
90 var progress = Math.max(0, Math.min(1, (mouseX - listView.foldingAreaWidth) / (width - listView.leftMargin * 2 - listView.foldingAreaWidth * 2)))
91 listView.contentX = listView.originX + (listView.contentWidth - listView.width + listView.leftMargin + listView.rightMargin) * progress - listView.leftMargin
92 }
94 displaced: Transition { UbuntuNumberAnimation { properties: "x" } }
96 delegate: Item {
97 id: workspaceDelegate
98 objectName: "delegate" + index
99 height: parent.height
100 width: listView.itemWidth
101 Behavior on width { UbuntuNumberAnimation {} }
102 visible: listView.dropItemIndex !== index
104 property int itemX: -listView.realContentX + index * (listView.itemWidth + listView.spacing)
105 property int distanceFromLeft: itemX //- listView.leftMargin
106 property int distanceFromRight: listView.width - listView.leftMargin - listView.rightMargin - itemX - listView.itemWidth
108 property int maxAngle: 40
110 property int itemAngle: {
111 if (index == 0) {
112 if (distanceFromLeft < 0) {
113 var progress = (distanceFromLeft + listView.foldingAreaWidth) / listView.foldingAreaWidth
114 return MathUtils.linearAnimation(1, -1, 0, maxAngle, Math.max(-1, Math.min(1, progress)));
115 }
116 return 0
117 }
118 if (index == listView.count - 1) {
119 if (distanceFromRight < 0) {
120 var progress = (distanceFromRight + listView.foldingAreaWidth) / listView.foldingAreaWidth
121 return MathUtils.linearAnimation(1, -1, 0, -maxAngle, Math.max(-1, Math.min(1, progress)));
122 }
123 return 0
124 }
126 if (distanceFromLeft < listView.foldingAreaWidth) {
127 // itemX : 10gu = p : 100
128 var progress = distanceFromLeft / listView.foldingAreaWidth
129 return MathUtils.linearAnimation(1, -1, 0, maxAngle, Math.max(-1, Math.min(1, progress)));
130 }
131 if (distanceFromRight < listView.foldingAreaWidth) {
132 var progress = distanceFromRight / listView.foldingAreaWidth
133 return MathUtils.linearAnimation(1, -1, 0, -maxAngle, Math.max(-1, Math.min(1, progress)));
134 }
135 return 0
136 }
138 property int itemOffset: {
139 var rotationOffset = (1 - Math.cos(itemAngle * Math.PI / 360)) * listView.itemWidth
140 if (index == 0) {
141 if (distanceFromLeft < 0) {
142 return -distanceFromLeft - rotationOffset
143 }
144 return 0
145 }
146 if (index == listView.count - 1) {
147 if (distanceFromRight < 0) {
148 return distanceFromRight + rotationOffset
149 }
150 return 0
151 }
153 if (itemX < -listView.foldingAreaWidth) {
154 return -itemX - rotationOffset
155 }
156 if (distanceFromLeft < listView.foldingAreaWidth) {
157 return (listView.foldingAreaWidth - distanceFromLeft) / 2 - rotationOffset
158 }
160 if (distanceFromRight < -listView.foldingAreaWidth) {
161 return distanceFromRight + rotationOffset
162 }
164 if (distanceFromRight < listView.foldingAreaWidth) {
165 return -(listView.foldingAreaWidth - distanceFromRight) / 2 + rotationOffset
166 }
168 return 0
169 }
171// onItemXChanged: if (index == 1) print("x", itemX, listView.contentX)
173 z: itemOffset < 0 ? itemOffset : -itemOffset
174 transform: [
175 Rotation {
176 angle: itemAngle
177 axis { x: 0; y: 1; z: 0 }
178 origin { x: itemAngle < 0 ? listView.itemWidth : 0; y: height / 2 }
179 },
180 Translate {
181 x: itemOffset
182 }
183 ]
185 WorkspacePreview {
186 height: listView.height
187 width: listView.itemWidth
188 background: root.background
189 screenHeight: screen.availableModes[screen.currentModeIndex].size.height
190 containsDrag: listView.hoveredWorkspaceIndex == index
191 }
192 MouseArea {
193 anchors.fill: parent
194 onClicked: {
195 screenWindow.screen.currentWorkspace = model.workspace
196 }
197 }
199 MouseArea {
200 id: closeMouseArea
201 objectName: "closeMouseArea"
202 anchors { left: parent.left; top: parent.top; leftMargin: -height / 2; topMargin: -height / 2 }
203 hoverEnabled: true
204 height: units.gu(4)
205 width: height
207 onClicked: {
208 model.workspace.unassign();
209 root.commitScreenSetup();
210 }
211 Image {
212 id: closeImage
213 source: "../graphics/window-close.svg"
214 anchors.fill: closeMouseArea
215 anchors.margins: units.gu(1)
216 sourceSize.width: width
217 sourceSize.height: height
218 readonly property var mousePos: hoverMouseArea.mapToItem(workspaceDelegate, hoverMouseArea.mouseX, hoverMouseArea.mouseY)
219 readonly property bool shown: (hoverMouseArea.containsMouse || parent.containsMouse)
220 && mousePos.y < workspaceDelegate.width / 4
221 && mousePos.y > -units.gu(2)
222 && mousePos.x > -units.gu(2)
223 && mousePos.x < workspaceDelegate.height / 4
224 opacity: shown ? 1 : 0
225 visible: opacity > 0
226 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
228 }
229 }
230 }
232 MouseArea {
233 id: hoverMouseArea
234 anchors.fill: parent
235 hoverEnabled: true
236 propagateComposedEvents: true
237 anchors.leftMargin: listView.leftMargin
238 anchors.rightMargin: listView.rightMargin
240 property int draggedIndex: -1
242 property int startX: 0
243 property int startY: 0
245 onMouseXChanged: {
246 if (!pressed || dragging) {
247 listView.progressiveScroll(mouseX)
248 }
249 }
250 onMouseYChanged: {
251 if (Math.abs(mouseY - startY) > units.gu(3)) {
252 drag.axis = Drag.XAndYAxis;
253 }
254 }
256 onReleased: {
257 var result = fakeDragItem.Drag.drop();
258// if (result == Qt.IgnoreAction) {
259// WorkspaceManager.destroyWorkspace(fakeDragItem.workspace);
260// }
261 root.commitScreenSetup();
262 drag.target = null;
263 }
265 property bool dragging: drag.active
266 onDraggingChanged: {
267 if (drag.active) {
268 print("drai", draggedIndex)
269 var ws = listView.model.get(draggedIndex);
270 print("ws:", ws)
271 ws.unassign();
272// listView.model.remove(draggedIndex, 1)
273 }
274 }
276 onPressed: {
277 startX = mouseX;
278 startY = mouseY;
279 if (listView.model.count < 2) return;
281 var coords = mapToItem(listView.contentItem, mouseX, mouseY)
282 draggedIndex = listView.indexAt(coords.x, coords.y)
283 var clickedItem = listView.itemAt(coords.x, coords.y)
285 var itemCoords = clickedItem.mapToItem(listView, -listView.leftMargin, 0);
286 fakeDragItem.x = itemCoords.x
287 fakeDragItem.y = itemCoords.y
288 fakeDragItem.workspace = listView.model.get(draggedIndex)
290 var mouseCoordsInItem = mapToItem(clickedItem, mouseX, mouseY);
291 fakeDragItem.Drag.hotSpot.x = mouseCoordsInItem.x
292 fakeDragItem.Drag.hotSpot.y = mouseCoordsInItem.y
294 drag.axis = Drag.YAxis;
295 drag.target = fakeDragItem;
296 }
298 WorkspacePreview {
299 id: fakeDragItem
300 height: listView.height
301 width: listView.itemWidth
302 background: root.background
303 screenHeight: screen.availableModes[screen.currentModeIndex].size.height
304 visible: Drag.active
306 Drag.active: hoverMouseArea.drag.active
307 Drag.keys: ['workspace']
309 property var workspace
310 property bool inDropArea: false
312 Rectangle {
313 anchors.fill: parent
314 color: "#33000000"
315 opacity: parent.inDropArea ? 0 : 1
316 Behavior on opacity { UbuntuNumberAnimation { } }
317 Rectangle {
318 anchors.centerIn: parent
319 width: units.gu(6)
320 height: units.gu(6)
321 radius: width / 2
322 color: "#aa000000"
323 }
325 Icon {
326 height: units.gu(3)
327 width: height
328 anchors.centerIn: parent
329 name: "edit-delete"
330 color: "white"
331 }
332 }
334 states: [
335 State {
336 when: fakeDragItem.Drag.active
337 ParentChange { target: fakeDragItem; parent: shell }
338 }
339 ]
340 }
341 }
342 }