11 readonly property SelectionHandle pressedHandle: _private.pressedHandle
12 readonly property alias selectionArea: selectionArea
13 property alias selectionX: _private.pendingRect.x
14 property alias selectionY: _private.pendingRect.y
15 property alias selectionWidth: _private.pendingRect.width
16 property alias selectionHeight: _private.pendingRect.height
17 property int aspectRatio: SelectionTool.AspectRatio.Free
27 readonly property rect currentRect: Qt.rect(selectionArea.x, selectionArea.y, selectionArea.width, selectionArea.height)
28 property SelectionHandle pressedHandle: null
29 property bool applyingPendingRect: false
30 property bool updatingPendingRect: false
31 property rect pendingRect: currentRect
33 onPressedHandleChanged: {
34 if (!pressedHandle && !_private.applyingPendingRect) {
35 Qt.callLater(_private.updateHandles);
39 function isSquareRatio(): bool {
40 return root.aspectRatio === SelectionTool.
AspectRatio.Square;
43 function updateHandles(): void {
44 if (_private.applyingPendingRect) {
48 _private.applyingPendingRect =
true;
49 selectionArea.x = _private.pendingRect.x;
50 selectionArea.y = _private.pendingRect.y;
51 selectionArea.width = _private.pendingRect.width;
52 selectionArea.height = _private.pendingRect.height;
53 _private.applyingPendingRect =
false;
56 function updatePendingRect(): void {
57 if (_private.applyingPendingRect || _private.updatingPendingRect) {
61 if ((selectionArea.pressed || _private.pressedHandle) && _private.isSquareRatio()) {
62 _private.updatingPendingRect = true;
66 const flagWidth = 0x4;
67 const flagHeight = 0x8;
68 const oldRect = _private.currentRect;
69 let wide = Math.max(oldRect.width, oldRect.height);
70 let newRect = oldRect;
73 if (newRect.x < 0 || newRect.y < 0) {
74 return Math.abs(Math.min(newRect.x, newRect.y));
75 } else if (newRect.x + newRect.width > root.width) {
76 return (newRect.x + newRect.width) - root.width;
77 } else if (newRect.y + newRect.height > root.height) {
78 return (newRect.y + newRect.height) - root.height;
84 function patchValues(flags, offset) {
85 if (flags & flagX) newRect.x += offset;
86 if (flags & flagY) newRect.y += offset;
87 if (flags & flagWidth) newRect.width -= offset;
88 if (flags & flagHeight) newRect.height -= offset;
91 switch (_private.pressedHandle) {
93 newRect = Qt.rect(oldRect.right - wide, oldRect.bottom - wide, wide, wide);
94 patchValues(flagX | flagY | flagWidth | flagHeight, offset());
97 newRect = Qt.rect(oldRect.left, oldRect.bottom - wide, wide, wide);
98 patchValues(flagY | flagWidth | flagHeight, offset());
100 case handleBottomRight:
101 newRect = Qt.rect(oldRect.left, oldRect.top, wide, wide);
102 patchValues(flagWidth | flagHeight, offset());
104 case handleBottomLeft:
105 newRect = Qt.rect(oldRect.right - wide, oldRect.top, wide, wide);
106 patchValues(flagX | flagWidth | flagHeight, offset());
110 if (_private.pendingRect !== newRect) {
111 _private.pendingRect = newRect;
114 _private.updatingPendingRect =
false;
125 height: parent.height
126 LayoutMirroring.enabled:
false
127 anchors.left:
if (_private.pressedHandle) {
128 if (_private.pressedHandle.backwardDiagonal) {
129 handleTopLeft.horizontalCenter
130 }
else if (_private.pressedHandle.forwardDiagonal) {
131 handleBottomLeft.horizontalCenter
132 }
else if (_private.pressedHandle.horizontalOnly) {
133 handleLeft.horizontalCenter
136 anchors.right:
if (_private.pressedHandle) {
137 if (_private.pressedHandle.backwardDiagonal) {
138 handleBottomRight.horizontalCenter
139 }
else if (_private.pressedHandle.forwardDiagonal) {
140 handleTopRight.horizontalCenter
141 }
else if (_private.pressedHandle.horizontalOnly) {
142 handleRight.horizontalCenter
145 anchors.top:
if (_private.pressedHandle) {
146 if (_private.pressedHandle.backwardDiagonal) {
147 handleTopLeft.verticalCenter
148 }
else if (_private.pressedHandle.forwardDiagonal) {
149 handleTopRight.verticalCenter
150 }
else if (_private.pressedHandle.verticalOnly) {
151 handleTop.verticalCenter
154 anchors.bottom:
if (_private.pressedHandle) {
155 if (_private.pressedHandle.backwardDiagonal) {
156 handleBottomRight.verticalCenter
157 }
else if (_private.pressedHandle.forwardDiagonal) {
158 handleBottomLeft.verticalCenter
159 }
else if (_private.pressedHandle.verticalOnly) {
160 handleBottom.verticalCenter
164 cursorShape:
if (_private.pressedHandle || (pressed && enabled)) {
166 }
else if (enabled) {
173 target: (selectionArea.width === root.width && selectionArea.height === root.height) || _private.pressedHandle ? null : selectionArea
175 maximumX: root.width - selectionArea.width
177 maximumY: root.height - selectionArea.height
181 onMouseXChanged: _private.updatePendingRect()
182 onMouseYChanged: _private.updatePendingRect()
183 onXChanged: _private.updatePendingRect()
184 onYChanged: _private.updatePendingRect()
185 onWidthChanged: _private.updatePendingRect()
186 onHeightChanged: _private.updatePendingRect()
191 target: selectionArea
192 position: SelectionHandle.TopLeft
193 lockX: _private.pressedHandle && _private.pressedHandle.backwardDiagonal
195 drag.maximumX: handleBottomRight.x - implicitWidth / 2
196 drag.maximumY: handleBottomRight.y - implicitHeight / 2
198 target: _private; property:
"pressedHandle"
199 value: handleTopLeft; when: !_private.applyingPendingRect && handleTopLeft.pressed
200 restoreMode: Binding.RestoreBindingOrValue
205 visible: !_private.isSquareRatio() && selectionArea.width >= implicitWidth
206 target: selectionArea
207 position: SelectionHandle.Top
208 lockY: _private.pressedHandle && _private.pressedHandle.verticalOnly
209 drag.maximumY: handleBottom.y - implicitHeight / 2
211 target: _private; property:
"pressedHandle"
212 value: handleTop; when: handleTop.pressed
213 restoreMode: Binding.RestoreBindingOrValue
218 target: selectionArea
219 position: SelectionHandle.TopRight
220 lockX: _private.pressedHandle && _private.pressedHandle.forwardDiagonal
222 drag.minimumX: handleBottomLeft.x + implicitWidth / 2
223 drag.maximumY: handleBottomLeft.y - implicitHeight / 2
225 target: _private; property:
"pressedHandle"
226 value: handleTopRight; when: !_private.applyingPendingRect && handleTopRight.pressed
227 restoreMode: Binding.RestoreBindingOrValue
232 visible: !_private.isSquareRatio() && selectionArea.height >= implicitHeight
233 target: selectionArea
234 position: SelectionHandle.Left
235 lockX: _private.pressedHandle && _private.pressedHandle.horizontalOnly
236 drag.maximumX: handleRight.x - implicitWidth / 2
238 target: _private; property:
"pressedHandle"
239 value: handleLeft; when: handleLeft.pressed
240 restoreMode: Binding.RestoreBindingOrValue
245 visible: !_private.isSquareRatio() && selectionArea.height >= implicitHeight
246 target: selectionArea
247 position: SelectionHandle.Right
248 lockX: _private.pressedHandle && _private.pressedHandle.horizontalOnly
249 drag.minimumX: handleLeft.x + implicitWidth / 2
251 target: _private; property:
"pressedHandle"
252 value: handleRight; when: handleRight.pressed
253 restoreMode: Binding.RestoreBindingOrValue
258 target: selectionArea
259 position: SelectionHandle.BottomLeft
260 lockX: _private.pressedHandle && _private.pressedHandle.forwardDiagonal
262 drag.maximumX: handleTopRight.x - implicitWidth / 2
263 drag.minimumY: handleTopRight.y + implicitHeight / 2
265 target: _private; property:
"pressedHandle"
266 value: handleBottomLeft; when: !_private.applyingPendingRect && handleBottomLeft.pressed
267 restoreMode: Binding.RestoreBindingOrValue
272 visible: !_private.isSquareRatio() && selectionArea.width >= implicitWidth
273 target: selectionArea
274 position: SelectionHandle.Bottom
275 lockY: _private.pressedHandle && _private.pressedHandle.verticalOnly
276 drag.minimumY: handleTop.y + implicitHeight / 2
278 target: _private; property:
"pressedHandle"
279 value: handleBottom; when: handleBottom.pressed
280 restoreMode: Binding.RestoreBindingOrValue
284 id: handleBottomRight
285 target: selectionArea
286 position: SelectionHandle.BottomRight
287 lockX: _private.pressedHandle && _private.pressedHandle.backwardDiagonal
289 drag.minimumX: handleTopLeft.x + implicitWidth / 2
290 drag.minimumY: handleTopLeft.y + implicitHeight / 2
292 target: _private; property:
"pressedHandle"
293 value: handleBottomRight; when:!_private.applyingPendingRect && handleBottomRight.pressed
294 restoreMode: Binding.RestoreBindingOrValue
298 onWidthChanged:
if (selectionArea.x + selectionArea.width > root.width) {
299 selectionArea.width = Math.max(root.width - selectionArea.x, handleTopLeft.implicitWidth/2)
300 if (selectionArea.x > root.width) {
301 selectionArea.x = Math.max(root.width - selectionArea.width, 0)
304 onHeightChanged:
if (selectionArea.y + selectionArea.height > root.height) {
305 selectionArea.height = Math.max(root.height - selectionArea.y, handleTopLeft.implicitHeight/2)
306 if (selectionArea.y > root.height) {
307 selectionArea.y = Math.max(root.height - selectionArea.height, 0)