Lomiri
Loading...
Searching...
No Matches
ScreensAndWorkspaces.qml
1/*
2 * Copyright (C) 2017 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 */
16
17import QtQuick 2.12
18import Lomiri.Components 1.3
19import Lomiri.Components.Popups 1.3
20import WindowManager 1.0
21import QtMir.Application 0.1
22import ".."
23import "../.."
24
25Item {
26 id: root
27
28 property string background
29
30 property var screensProxy: Screens.createProxy();
31
32 property QtObject activeWorkspace: null
33
34 property string mode : "staged"
35
36 signal closeSpread();
37
38 DeviceConfiguration {
39 id: deviceConfiguration
40 }
41
42 Row {
43 id: row
44 anchors.bottom: parent.bottom
45 anchors.horizontalCenter: parent.horizontalCenter
46 Behavior on anchors.horizontalCenterOffset { NumberAnimation { duration: LomiriAnimation.SlowDuration } }
47 spacing: units.gu(1)
48
49 property var selectedIndex: undefined
50
51 Repeater {
52 model: screensProxy
53
54 delegate: Item {
55 height: root.height - units.gu(6)
56 width: workspaces.width
57 visible: (deviceConfiguration.category == "phone" && index !== 0) || deviceConfiguration.category != "phone"
58
59 Item {
60 id: header
61 anchors { left: parent.left; top: parent.top; right: parent.right }
62 height: units.gu(7)
63 z: 1
64
65 property bool isCurrent: {
66 // another screen is selected.
67 if (row.selectedIndex != undefined && row.selectedIndex != index) return false;
68
69 // this screen is active.
70 if (WMScreen.active && WMScreen.isSameAs(model.screen) && WMScreen.currentWorkspace.isSameAs(activeWorkspace)) return true;
71 if (model.screen.workspaces.indexOf(activeWorkspace) >= 0) return true;
72
73 // not active.
74 return false;
75 }
76
77 property bool isSelected: screenMA.containsMouse
78 onIsSelectedChanged: {
79 if (isSelected) {
80 row.selectedIndex = Qt.binding(function() { return index; });
81 } else if (row.selectedIndex === index) {
82 row.selectedIndex = undefined;
83 }
84 }
85
86 LomiriShape {
87 anchors.fill: parent
88 backgroundColor: "white"
89 opacity: header.isCurrent || header.isSelected ? 1.0 : 0.5
90 }
91
92 DropArea {
93 anchors.fill: parent
94 keys: ["workspace"]
95
96 onEntered: {
97 workspaces.workspaceModel.insert(workspaces.workspaceModel.count, {text: drag.source.text})
98 drag.source.inDropArea = true;
99 }
100
101 onExited: {
102 workspaces.workspaceModel.remove(workspaces.workspaceModel.count - 1, 1)
103 drag.source.inDropArea = false;
104 }
105
106 onDropped: {
107 drag.source.inDropArea = false;
108 }
109 }
110
111 Column {
112 anchors.fill: parent
113 anchors.margins: units.gu(1)
114
115 Label {
116 text: model.screen.name
117 color: header.isCurrent || header.isSelected ? "black" : "white"
118 }
119
120 Label {
121 text: model.screen.outputTypeName
122 color: header.isCurrent || header.isSelected ? "black" : "white"
123 fontSize: "x-small"
124 }
125
126 Label {
127 text: screen.availableModes[screen.currentModeIndex].size.width + "x" + screen.availableModes[screen.currentModeIndex].size.height
128 color: header.isCurrent || header.isSelected ? "black" : "white"
129 fontSize: "x-small"
130 }
131 }
132
133 Icon {
134 anchors {
135 top: parent.top
136 right: parent.right
137 margins: units.gu(1)
138 }
139 width: units.gu(3)
140 height: width
141 source: "image://theme/select"
142 color: header.isCurrent || header.isSelected ? "black" : "white"
143 visible: model.screen.active
144 }
145
146 MouseArea {
147 id: screenMA
148 hoverEnabled: true
149 anchors.fill: parent
150
151 onClicked: {
152 var obj = screensMenuComponent.createObject(header)
153 obj.open(mouseX, mouseY)
154 }
155 }
156
157 Component {
158 id: screensMenuComponent
159 LomiriShape {
160 id: screensMenu
161 width: units.gu(20)
162 height: contentColumn.childrenRect.height
163 backgroundColor: "white"
164
165 function open(mouseX, mouseY) {
166 x = Math.max(0, Math.min(mouseX - width / 2, parent.width - width))
167 y = mouseY + units.gu(1)
168 }
169
170 InverseMouseArea {
171 anchors.fill: parent
172 onClicked: {
173 screensMenu.destroy()
174 }
175 }
176
177 Column {
178 id: contentColumn
179 width: parent.width
180 ListItem {
181 height: layout.height
182 highlightColor: "transparent"
183 ListItemLayout {
184 id: layout
185 title.text: qsTr("Add workspace")
186 title.color: "black"
187 }
188 onClicked: {
189 screen.workspaces.addWorkspace();
190 Screens.sync(root.screensProxy);
191 screensMenu.destroy();
192 }
193 }
194 }
195 }
196 }
197 }
198
199 Workspaces {
200 id: workspaces
201 height: parent.height - header.height - units.gu(2)
202 width: {
203 var width = 0;
204 if (screensProxy.count == 1) {
205 width = Math.min(implicitWidth, root.width - units.gu(8));
206 } else {
207 width = Math.min(implicitWidth, model.screen.active ? root.width - units.gu(48) : units.gu(40))
208 }
209 return Math.max(workspaces.minimumWidth, width);
210 }
211
212 Behavior on width { LomiriNumberAnimation {} }
213 anchors.bottom: parent.bottom
214 anchors.bottomMargin: units.gu(1)
215 anchors.horizontalCenter: parent.horizontalCenter
216 screen: model.screen
217 background: root.background
218
219 workspaceModel: model.screen.workspaces
220 activeWorkspace: root.activeWorkspace
221 readOnly: false
222
223 onCommitScreenSetup: Screens.sync(root.screensProxy)
224 onCloseSpread: root.closeSpread();
225
226 onClicked: {
227 root.activeWorkspace = workspace;
228 }
229 }
230 }
231 }
232 }
233
234 Rectangle {
235 anchors { left: parent.left; top: parent.top; bottom: parent.bottom; topMargin: units.gu(6); bottomMargin: units.gu(1) }
236 width: units.gu(5)
237 color: "#33000000"
238 visible: (row.width - root.width + units.gu(10)) / 2 - row.anchors.horizontalCenterOffset > units.gu(5)
239 MouseArea {
240 id: leftScrollArea
241 anchors.fill: parent
242 hoverEnabled: true
243 onPressed: mouse.accepted = false;
244 }
245 DropArea {
246 id: leftFakeDropArea
247 anchors.fill: parent
248 keys: ["application", "workspace"]
249 }
250 }
251 Rectangle {
252 anchors { right: parent.right; top: parent.top; bottom: parent.bottom; topMargin: units.gu(6); bottomMargin: units.gu(1) }
253 width: units.gu(5)
254 color: "#33000000"
255 visible: (row.width - root.width + units.gu(10)) / 2 + row.anchors.horizontalCenterOffset > units.gu(5)
256 MouseArea {
257 id: rightScrollArea
258 anchors.fill: parent
259 hoverEnabled: true
260 onPressed: mouse.accepted = false;
261 }
262 DropArea {
263 id: rightFakeDropArea
264 anchors.fill: parent
265 keys: ["application", "workspace"]
266 }
267 }
268 Timer {
269 repeat: true
270 running: leftScrollArea.containsMouse || rightScrollArea.containsMouse || leftFakeDropArea.containsDrag || rightFakeDropArea.containsDrag
271 interval: LomiriAnimation.SlowDuration
272 triggeredOnStart: true
273 onTriggered: {
274 var newOffset = row.anchors.horizontalCenterOffset;
275 var maxOffset = Math.max((row.width - root.width + units.gu(10)) / 2, 0);
276 if (leftScrollArea.containsMouse || leftFakeDropArea.containsDrag) {
277 newOffset += units.gu(20)
278 } else {
279 newOffset -= units.gu(20)
280 }
281 newOffset = Math.max(-maxOffset, Math.min(maxOffset, newOffset));
282 row.anchors.horizontalCenterOffset = newOffset;
283 }
284 }
285}