2 * Copyright (C) 2014-2016 Canonical, Ltd.
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.
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.
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/>.
18import Ubuntu.Components 1.3
20import Unity.Application 0.1 // for Mir.cursorName
21import "../Components/PanelState"
27 anchors.margins: -borderThickness
29 hoverEnabled: target && !target.maximized // don't grab the resize under the panel
31 property var windowStateStorage: WindowStateStorage
32 readonly property alias dragging: d.dragging
33 readonly property alias normalWidth: priv.normalWidth
34 readonly property alias normalHeight: priv.normalHeight
36 // The target item managed by this. Must be a parent or a sibling
37 // The area will anchor to it and manage resize events
38 property Item target: null
39 property string windowId: ""
40 property int borderThickness: 0
41 property int minWidth: 0
42 property int minHeight: 0
43 property int defaultWidth: units.gu(60)
44 property int defaultHeight: units.gu(50)
45 property int screenWidth: 0
46 property int screenHeight: 0
47 property int leftMargin: 0
53 property int normalX: 0
54 property int normalY: 0
55 property int normalWidth: 0
56 property int normalHeight: 0
58 function updateNormalGeometry() {
59 if (root.target.state == "normal" || root.target.state == "restored") {
60 normalX = root.target.requestedX
61 normalY = root.target.requestedY
62 normalWidth = root.target.width
63 normalHeight = root.target.height
70 onXChanged: priv.updateNormalGeometry();
71 onYChanged: priv.updateNormalGeometry();
72 onWidthChanged: priv.updateNormalGeometry();
73 onHeightChanged: priv.updateNormalGeometry();
76 function loadWindowState() {
77 var windowGeometry = windowStateStorage.getGeometry(root.windowId,
78 Qt.rect(target.windowedX, target.windowedY, defaultWidth, defaultHeight));
81 target.windowedWidth = Qt.binding(function() { return Math.min(Math.max(windowGeometry.width, d.minimumWidth), screenWidth - root.leftMargin); });
82 target.windowedHeight = Qt.binding(function() { return Math.min(Math.max(windowGeometry.height, d.minimumHeight),
83 root.screenHeight - (target.fullscreen ? 0 : PanelState.panelHeight)); });
84 target.windowedX = Qt.binding(function() { return Math.max(Math.min(windowGeometry.x, root.screenWidth - root.leftMargin - target.windowedWidth),
85 (target.fullscreen ? 0 : root.leftMargin)); });
86 target.windowedY = Qt.binding(function() { return Math.max(Math.min(windowGeometry.y, root.screenHeight - target.windowedHeight), PanelState.panelHeight); });
88 var windowState = windowStateStorage.getState(root.windowId, WindowStateStorage.WindowStateNormal)
89 target.restore(false /* animated */, windowState);
91 priv.updateNormalGeometry();
93 // initialize the x/y to restore to
94 target.restoredX = priv.normalX;
95 target.restoredY = priv.normalY;
98 function saveWindowState() {
99 var state = target.windowState;
100 if (state === WindowStateStorage.WindowStateRestored) {
101 state = WindowStateStorage.WindowStateNormal;
103 windowStateStorage.saveState(root.windowId, state & ~WindowStateStorage.WindowStateMinimized); // clear the minimized bit when saving
104 windowStateStorage.saveGeometry(root.windowId, Qt.rect(priv.normalX, priv.normalY, priv.normalWidth, priv.normalHeight));
110 readonly property int maxSafeInt: 2147483647
111 readonly property int maxSizeIncrement: units.gu(40)
113 readonly property int minimumWidth: root.target ? Math.max(root.minWidth, root.target.minimumWidth) : root.minWidth
114 onMinimumWidthChanged: {
115 if (target.windowedWidth < minimumWidth) {
116 target.windowedWidth = minimumWidth;
119 readonly property int minimumHeight: root.target ? Math.max(root.minHeight, root.target.minimumHeight) : root.minHeight
120 onMinimumHeightChanged: {
121 if (target.windowedHeight < minimumHeight) {
122 target.windowedHeight = minimumHeight;
125 readonly property int maximumWidth: root.target && root.target.maximumWidth >= minimumWidth && root.target.maximumWidth > 0
126 ? root.target.maximumWidth : maxSafeInt
127 onMaximumWidthChanged: {
128 if (target.windowedWidth > maximumWidth) {
129 target.windowedWidth = maximumWidth;
132 readonly property int maximumHeight: root.target && root.target.maximumHeight >= minimumHeight && root.target.maximumHeight > 0
133 ? root.target.maximumHeight : maxSafeInt
134 onMaximumHeightChanged: {
135 if (target.windowedHeight > maximumHeight) {
136 target.windowedHeight = maximumHeight;
139 readonly property int widthIncrement: {
143 if (root.target.widthIncrement > 0) {
144 if (root.target.widthIncrement < maxSizeIncrement) {
145 return root.target.widthIncrement;
147 return maxSizeIncrement;
153 readonly property int heightIncrement: {
157 if (root.target.heightIncrement > 0) {
158 if (root.target.heightIncrement < maxSizeIncrement) {
159 return root.target.heightIncrement;
161 return maxSizeIncrement;
168 property bool leftBorder: false
169 property bool rightBorder: false
170 property bool topBorder: false
171 property bool bottomBorder: false
173 // true - A change in surface size will cause the left border of the window to move accordingly.
174 // The window's right border will stay in the same position.
175 // false - a change in surface size will cause the right border of the window to move accordingly.
176 // The window's left border will stay in the same position.
177 property bool moveLeftBorder: false
179 // true - A change in surface size will cause the top border of the window to move accordingly.
180 // The window's bottom border will stay in the same position.
181 // false - a change in surface size will cause the bottom border of the window to move accordingly.
182 // The window's top border will stay in the same position.
183 property bool moveTopBorder: false
185 property bool dragging: false
186 property real startMousePosX
187 property real startMousePosY
190 property real startWidth
191 property real startHeight
192 property real currentWidth
193 property real currentHeight
195 readonly property string cursorName: {
196 if (root.containsMouse || root.pressed) {
197 if (leftBorder && !topBorder && !bottomBorder) {
199 } else if (rightBorder && !topBorder && !bottomBorder) {
201 } else if (topBorder && !leftBorder && !rightBorder) {
203 } else if (bottomBorder && !leftBorder && !rightBorder) {
204 return "bottom_side";
205 } else if (leftBorder && topBorder) {
206 return "top_left_corner";
207 } else if (leftBorder && bottomBorder) {
208 return "bottom_left_corner";
209 } else if (rightBorder && topBorder) {
210 return "top_right_corner";
211 } else if (rightBorder && bottomBorder) {
212 return "bottom_right_corner";
220 onCursorNameChanged: {
221 Mir.cursorName = cursorName;
224 function updateBorders() {
225 leftBorder = mouseX <= borderThickness;
226 rightBorder = mouseX >= width - borderThickness;
227 topBorder = mouseY <= borderThickness;
228 bottomBorder = mouseY >= height - borderThickness;
233 id: resetBordersToMoveTimer
236 d.moveLeftBorder = false;
237 d.moveTopBorder = false;
244 resetBordersToMoveTimer.stop();
245 d.moveLeftBorder = d.leftBorder;
246 d.moveTopBorder = d.topBorder;
248 var pos = mapToItem(root.target.parent, mouseX, mouseY);
249 d.startMousePosX = pos.x;
250 d.startMousePosY = pos.y;
251 d.startX = target.windowedX;
252 d.startY = target.windowedY;
253 d.startWidth = target.width;
254 d.startHeight = target.height;
255 d.currentWidth = target.width;
256 d.currentHeight = target.height;
259 resetBordersToMoveTimer.start();
282 var pos = mapToItem(target.parent, mouse.x, mouse.y);
284 var deltaX = Math.floor((pos.x - d.startMousePosX) / d.widthIncrement) * d.widthIncrement;
285 var deltaY = Math.floor((pos.y - d.startMousePosY) / d.heightIncrement) * d.heightIncrement;
288 var newTargetX = d.startX + deltaX;
289 var rightBorderX = target.windowedX + target.width;
290 if (rightBorderX > newTargetX + d.minimumWidth) {
291 if (rightBorderX < newTargetX + d.maximumWidth) {
292 target.windowedWidth = rightBorderX - newTargetX;
294 target.windowedWidth = d.maximumWidth;
297 target.windowedWidth = d.minimumWidth;
300 } else if (d.rightBorder) {
301 var newWidth = d.startWidth + deltaX;
302 if (newWidth > d.minimumWidth) {
303 if (newWidth < d.maximumWidth) {
304 target.windowedWidth = newWidth;
306 target.windowedWidth = d.maximumWidth;
309 target.windowedWidth = d.minimumWidth;
314 var newTargetY = Math.max(d.startY + deltaY, PanelState.panelHeight); // disallow resizing up past Panel
315 var bottomBorderY = target.windowedY + target.height;
316 if (bottomBorderY > newTargetY + d.minimumHeight) {
317 if (bottomBorderY < newTargetY + d.maximumHeight) {
318 target.windowedHeight = bottomBorderY - newTargetY;
320 target.windowedHeight = d.maximumHeight;
323 target.windowedHeight = d.minimumHeight;
326 } else if (d.bottomBorder) {
327 var newHeight = d.startHeight + deltaY;
328 if (newHeight > d.minimumHeight) {
329 if (newHeight < d.maximumHeight) {
330 target.windowedHeight = newHeight;
332 target.windowedHeight = d.maximumHeight;
335 target.windowedHeight = d.minimumHeight;
343 if (d.moveLeftBorder) {
344 target.windowedX += d.currentWidth - target.width;
346 d.currentWidth = target.width;
349 if (d.moveTopBorder) {
350 target.windowedY += d.currentHeight - target.height;
352 d.currentHeight = target.height;
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list