on xenial help sign in
add drag and drop wor workspaces between screens
commit1c773229af1edf4b5a7c596729021e1b84760667 authorMichael Zanetti <michael.zanetti@canonical.com> dateThu 9 Feb 2017, 14:09 (10 years ago) parentbc9e93f
2 files changed+178−76
qml/Stage/Spread/ScreensAndWorkspaces.qml+44−3 qml/Stage/Spread/Workspaces.qml+134−73
qml/Stage/Spread/ScreensAndWorkspaces.qml+44−3
@@ -1,18 +1,19 @@
11import QtQuick 2.4
22import Ubuntu.Components 1.3
3+import Ubuntu.Components.Popups 1.3
34import Unity.Screens 0.1
45import Unity.Application 0.1
56import ".."
67
78Item {
89 id: root
10+
911 property string background
1012
1113 Row {
1214 anchors.bottom: parent.bottom
13− anchors.bottomMargin: units.gu(1)
14−// anchors.horizontalCenter: parent.horizontalCenter
15− anchors.left: parent.left
15+ anchors.horizontalCenter: parent.horizontalCenter
16+// anchors.left: parent.left
1617 spacing: units.gu(1)
1718
1819 Repeater {
@@ -21,12 +22,14 @@ Item {
2122 delegate: Item {
2223 height: root.height - units.gu(6)
2324 width: workspaces.width
25+ clip: true
2426
2527 UbuntuShape {
2628 id: header
2729 anchors { left: parent.left; top: parent.top; right: parent.right }
2830 height: units.gu(7)
2931 backgroundColor: "white"
32+ z: 1
3033
3134 Column {
3235 anchors.fill: parent
@@ -49,6 +52,29 @@ Item {
4952 fontSize: "x-small"
5053 }
5154 }
55+
56+ MouseArea {
57+ anchors.fill: parent
58+// acceptedButtons: Qt.RightButton
59+
60+
61+ onClicked: {
62+ print("should open popup")
63+ PopupUtils.open(contextMenu)
64+ }
65+ }
66+
67+ Component {
68+ id: contextMenu
69+ ActionSelectionPopover {
70+ actions: ActionList {
71+ Action {
72+ text: "Add workspace"
73+ onTriggered: workspaces.workspaceModel.append({text: "" + workspaces.workspaceModel.count})
74+ }
75+ }
76+ }
77+ }
5278 }
5379
5480
@@ -56,10 +82,25 @@ Item {
5682 id: workspaces
5783 height: parent.height - header.height - units.gu(2)
5884 width: Math.min(implicitWidth, units.gu(80), root.width)
85+ Behavior on width { UbuntuNumberAnimation {} }
5986 anchors.bottom: parent.bottom
87+ anchors.bottomMargin: units.gu(1)
6088 anchors.horizontalCenter: parent.horizontalCenter
6189 screen: model.screen
6290 background: root.background
91+
92+ workspaceModel: ListModel {
93+ onCountChanged: print("model count changed to", count)
94+ ListElement {text: "1"}
95+// ListElement {text: "2"}
96+// ListElement {text: "3"}
97+// ListElement {text: "4"}
98+// ListElement {text: "5"}
99+// ListElement {text: "6"}
100+// ListElement {text: "7"}
101+// ListElement {text: "8"}
102+// ListElement {text: "9"}
103+ }
63104 }
64105 }
65106 }
qml/Stage/Spread/Workspaces.qml+134−73
@@ -2,15 +2,46 @@ import QtQuick 2.4
22import Ubuntu.Components 1.3
33import "MathUtils.js" as MathUtils
44
5−Rectangle {
5+Item {
66 id: root
7− implicitWidth: listView.count * (height * 16/9)
8− color: "blue"
7+ implicitWidth: listView.count * (height * 16/9 + listView.spacing) - listView.spacing
8+// color: "blue"
99
10− property var screen: null
10+ property QtObject screen: null
11+ property alias workspaceModel: listView.model
1112 property var background // TODO: should be stored in the workspace data
1213
13−// Rectangle { anchors.fill: parent; color: "green" }
14+ DropArea {
15+ anchors.fill: root
16+
17+ keys: ['workspace']
18+
19+ onEntered: {
20+ var index = listView.getDropIndex(drag);
21+ listView.model.insert(index, {text: drag.source.text})
22+ listView.dropItemIndex = index;
23+ drag.source.inDropArea = true;
24+ }
25+
26+ onPositionChanged: {
27+ var index = listView.getDropIndex(drag);
28+ if (listView.dropItemIndex == index) return;
29+ listView.model.move(listView.dropItemIndex, index, 1);
30+ listView.dropItemIndex = index;
31+ }
32+
33+ onExited: {
34+ listView.model.remove(listView.dropItemIndex, 1);
35+ listView.dropItemIndex = -1;
36+ drag.source.inDropArea = false;
37+ }
38+
39+ onDropped: {
40+ listView.dropItemIndex = -1;
41+ drag.source.inDropArea = false;
42+ }
43+ }
44+
1445 ListView {
1546 id: listView
1647 anchors.fill: parent
@@ -18,19 +49,6 @@ Rectangle {
1849 anchors.rightMargin: -itemWidth
1950 interactive: false
2051
21− model: ListModel {
22− ListElement {text: "1"}
23− ListElement {text: "2"}
24− ListElement {text: "3"}
25− ListElement {text: "4"}
26− ListElement {text: "5"}
27− ListElement {text: "6"}
28− ListElement {text: "7"}
29− ListElement {text: "8"}
30− ListElement {text: "9"}
31− }
32−
33−
3452 orientation: ListView.Horizontal
3553 spacing: units.gu(1)
3654 leftMargin: itemWidth
@@ -39,14 +57,25 @@ Rectangle {
3957 property int itemWidth: height * 16 / 9
4058 property int foldingAreaWidth: units.gu(10)
4159 property real realContentX: contentX - originX + leftMargin
60+ property int dropItemIndex: -1
61+
62+ function getDropIndex(drag) {
63+ var coords = mapToItem(listView.contentItem, drag.x, drag.y)
64+ var index = Math.floor((drag.x + listView.realContentX) / (listView.itemWidth + listView.spacing));
65+ if (index < 0) index = 0;
66+ var upperLimit = dropItemIndex == -1 ? listView.count : listView.count - 1
67+ if (index > upperLimit) index = upperLimit;
68+ return index;
69+ }
4270
4371 displaced: Transition { UbuntuNumberAnimation { properties: "x" } }
4472
4573 delegate: Item {
4674 objectName: "delegate" + index
4775 height: parent.height
48− width: /*dndArea.draggedIndex == index ? units.gu(5) :*/ listView.itemWidth
76+ width: listView.itemWidth
4977 Behavior on width { UbuntuNumberAnimation {} }
78+ visible: listView.dropItemIndex !== index
5079
5180 property int itemX: -listView.realContentX + index * (listView.itemWidth + listView.spacing)
5281 property int distanceFromLeft: itemX //- listView.leftMargin
@@ -83,34 +112,33 @@ Rectangle {
83112 }
84113
85114 property int itemOffset: {
115+ var rotationOffset = (1 - Math.cos(itemAngle * Math.PI / 360)) * listView.itemWidth
86116 if (index == 0) {
87117 if (distanceFromLeft < 0) {
88− return -distanceFromLeft
118+ return -distanceFromLeft - rotationOffset
89119 }
90120 return 0
91121 }
92122 if (index == listView.count - 1) {
93123 if (distanceFromRight < 0) {
94− return distanceFromRight
124+ return distanceFromRight + rotationOffset
95125 }
96126 return 0
97127 }
98128
99129 if (itemX < -listView.foldingAreaWidth) {
100− return -itemX
130+ return -itemX - rotationOffset
101131 }
102132 if (distanceFromLeft < listView.foldingAreaWidth) {
103− var progress = distanceFromLeft / listView.foldingAreaWidth
104− return (listView.foldingAreaWidth - distanceFromLeft) / 2
133+ return (listView.foldingAreaWidth - distanceFromLeft) / 2 - rotationOffset
105134 }
106135
107136 if (distanceFromRight < -listView.foldingAreaWidth) {
108− return distanceFromRight
137+ return distanceFromRight + rotationOffset
109138 }
110139
111140 if (distanceFromRight < listView.foldingAreaWidth) {
112− var progress = distanceFromRight / listView.foldingAreaWidth;
113− return -(listView.foldingAreaWidth - distanceFromRight) / 2
141+ return -(listView.foldingAreaWidth - distanceFromRight) / 2 + rotationOffset
114142 }
115143
116144 return 0
@@ -123,38 +151,36 @@ Rectangle {
123151 Rotation {
124152 angle: itemAngle
125153 axis { x: 0; y: 1; z: 0 }
126− origin { x: /*itemAngle > 0 ? 0 : listView.itemWidth*/ listView.itemWidth / 2; y: height / 2 }
154+ origin { x: listView.itemWidth / 2; y: height / 2 }
127155 },
128156 Translate {
129157 x: itemOffset
130158 }
131−
132159 ]
133160
134161 WorkspacePreview {
135162 height: listView.height
136163 width: listView.itemWidth
137164 background: root.background
138− screenHeight: screen.physicalSize.height
139− }
165+ screenHeight: root.screen.physicalSize.height
140166
141− Label {
142− anchors.centerIn: parent
143− text: model.text
144− fontSize: "large"
145− color: "red"
167+ Label {
168+ anchors.centerIn: parent
169+ text: model.text
170+ color: "red"
171+ fontSize: "large"
172+ }
146173 }
147174 }
148175
149176 MouseArea {
150− id: dndArea
177+ id: mouseArea
151178 anchors.fill: parent
152179 hoverEnabled: true
153180 preventStealing: true
154181 anchors.leftMargin: listView.leftMargin
155182 anchors.rightMargin: listView.rightMargin
156183
157−
158184 property int draggedIndex: -1
159185
160186 onMouseXChanged: {
@@ -162,54 +188,89 @@ Rectangle {
162188// var progress = mouseX / width
163189// print("p:", progress)
164190 listView.contentX = listView.originX + (listView.contentWidth - listView.width + listView.leftMargin + listView.rightMargin) * progress - listView.leftMargin
191+ }
165192
193+ onReleased: {
194+ fakeDragItem.Drag.drop();
195+ drag.target = null;
196+ }
166197
167− if (draggedIndex == -1) {
168− return;
198+ property bool dragging: drag.active
199+ onDraggingChanged: {
200+ if (drag.active) {
201+ print("drai", draggedIndex)
202+ listView.model.remove(draggedIndex, 1)
169203 }
204+ }
170205
171−// var newIndex = (listView.realContentX) / listView.itemWidth
172− var coords = mapToItem(listView.contentItem, mouseX + listView.itemWidth, mouseY)
173− var newIndex = (coords.x + listView.leftMargin) / (listView.itemWidth + listView.spacing)
174− print("newIndex", newIndex)
175−// var newIndex = listView.indexAt(coords.x, coords.y)
176−// if (newIndex == -1) return;
177−
178− if (newIndex > draggedIndex + 1) {
179− newIndex = draggedIndex + 1
180− } else if (newIndex < draggedIndex) {
181− newIndex = draggedIndex - 1
182− } else {
183− return
184− }
206+ onPressed: {
207+ if (listView.model.count < 2) return;
185208
186− if (newIndex >= 0 && newIndex < listView.count) {
187− listView.model.move(draggedIndex, newIndex, 1)
188− draggedIndex = newIndex
189− }
190− }
209+ var coords = mapToItem(listView.contentItem, mouseX, mouseY)
210+ draggedIndex = listView.indexAt(coords.x, coords.y)
211+ var clickedItem = listView.itemAt(coords.x, coords.y)
191212
192− onReleased: {
193− draggedIndex = -1
194− }
213+ var itemCoords = clickedItem.mapToItem(listView, -listView.leftMargin, 0);
214+ fakeDragItem.x = itemCoords.x
215+ fakeDragItem.y = itemCoords.y
216+ fakeDragItem.text = listView.model.get(draggedIndex).text
195217
196− onPressAndHold: {
197−// var clickedItem = listView.itemAt(mouseX /*+ listView.realContentX*/, mouseY)
198−// var clickedIndex = listView.indexAt(mouseX /*- listView.realContentX*/, mouseY)
218+ var mouseCoordsInItem = mapToItem(clickedItem, mouseX, mouseY);
219+ fakeDragItem.Drag.hotSpot.x = mouseCoordsInItem.x
220+ fakeDragItem.Drag.hotSpot.y = mouseCoordsInItem.y
221+
222+ drag.target = fakeDragItem;
223+ }
199224
200− for (var i = 0; i < listView.count; i++) {
201− var x = -listView.leftMargin + i * listView.itemWidth - units.gu(1);
202− print("x:", x, "index:", listView.indexAt(x, listView.height / 2))
225+ WorkspacePreview {
226+ id: fakeDragItem
227+ height: listView.height
228+ width: listView.itemWidth
229+ background: root.background
230+ screenHeight: root.screen.physicalSize.height
231+ visible: Drag.active
232+
233+ Drag.active: mouseArea.drag.active
234+ Drag.keys: ['workspace']
235+
236+ property string text
237+ property bool inDropArea: false
238+ Label {
239+ anchors.centerIn: parent
240+ text: parent.text
241+ color: "red"
242+ fontSize: "large"
203243 }
204244
205− var coords = mapToItem(listView.contentItem, mouseX, mouseY)
206− var clickedIndex = listView.indexAt(coords.x, coords.y)
245+ Rectangle {
246+ anchors.fill: parent
247+ color: "#33000000"
248+ opacity: parent.inDropArea ? 0 : 1
249+ Behavior on opacity { UbuntuNumberAnimation { } }
250+ Rectangle {
251+ anchors.centerIn: parent
252+ width: units.gu(6)
253+ height: units.gu(6)
254+ radius: width / 2
255+ color: "#aa000000"
256+ }
207257
208− draggedIndex = clickedIndex
258+ Icon {
259+ height: units.gu(3)
260+ width: height
261+ anchors.centerIn: parent
262+ name: "edit-delete"
263+ color: "white"
264+ }
265+ }
209266
210− print("index:", mouseX, clickedIndex)
267+ states: [
268+ State {
269+ when: fakeDragItem.Drag.active
270+ ParentChange { target: fakeDragItem; parent: shell }
271+ }
272+ ]
211273 }
212−
213274 }
214275 }
215276}