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)) {
62 _private.updatingPendingRect = true;
64 if (_private.isSquareRatio()) {
67 const flagWidth = 0x4;
68 const flagHeight = 0x8;
69 const oldRect = _private.currentRect;
70 let wide = Math.max(oldRect.width, oldRect.height);
71 let newRect = oldRect;
74 if (newRect.x < 0 || newRect.y < 0) {
75 return Math.abs(Math.min(newRect.x, newRect.y));
76 } else if (newRect.x + newRect.width > root.width) {
77 return (newRect.x + newRect.width) - root.width;
78 } else if (newRect.y + newRect.height > root.height) {
79 return (newRect.y + newRect.height) - root.height;
85 function patchValues(flags, offset) {
86 if (flags & flagX) newRect.x += offset;
87 if (flags & flagY) newRect.y += offset;
88 if (flags & flagWidth) newRect.width -= offset;
89 if (flags & flagHeight) newRect.height -= offset;
92 switch (_private.pressedHandle) {
94 newRect = Qt.rect(oldRect.right - wide, oldRect.bottom - wide, wide, wide);
95 patchValues(flagX | flagY | flagWidth | flagHeight, offset());
98 newRect = Qt.rect(oldRect.left, oldRect.bottom - wide, wide, wide);
99 patchValues(flagY | flagWidth | flagHeight, offset());
101 case handleBottomRight:
102 newRect = Qt.rect(oldRect.left, oldRect.top, wide, wide);
103 patchValues(flagWidth | flagHeight, offset());
105 case handleBottomLeft:
106 newRect = Qt.rect(oldRect.right - wide, oldRect.top, wide, wide);
107 patchValues(flagX | flagWidth | flagHeight, offset());
111 if (_private.pendingRect !== newRect) {
112 _private.pendingRect = newRect;
115 _private.pendingRect = _private.currentRect;
118 _private.updatingPendingRect =
false;
129 height: parent.height
130 LayoutMirroring.enabled:
false
131 anchors.left:
if (_private.pressedHandle) {
132 if (_private.pressedHandle.backwardDiagonal) {
133 handleTopLeft.horizontalCenter
134 }
else if (_private.pressedHandle.forwardDiagonal) {
135 handleBottomLeft.horizontalCenter
136 }
else if (_private.pressedHandle.horizontalOnly) {
137 handleLeft.horizontalCenter
140 anchors.right:
if (_private.pressedHandle) {
141 if (_private.pressedHandle.backwardDiagonal) {
142 handleBottomRight.horizontalCenter
143 }
else if (_private.pressedHandle.forwardDiagonal) {
144 handleTopRight.horizontalCenter
145 }
else if (_private.pressedHandle.horizontalOnly) {
146 handleRight.horizontalCenter
149 anchors.top:
if (_private.pressedHandle) {
150 if (_private.pressedHandle.backwardDiagonal) {
151 handleTopLeft.verticalCenter
152 }
else if (_private.pressedHandle.forwardDiagonal) {
153 handleTopRight.verticalCenter
154 }
else if (_private.pressedHandle.verticalOnly) {
155 handleTop.verticalCenter
158 anchors.bottom:
if (_private.pressedHandle) {
159 if (_private.pressedHandle.backwardDiagonal) {
160 handleBottomRight.verticalCenter
161 }
else if (_private.pressedHandle.forwardDiagonal) {
162 handleBottomLeft.verticalCenter
163 }
else if (_private.pressedHandle.verticalOnly) {
164 handleBottom.verticalCenter
168 cursorShape:
if (_private.pressedHandle || (pressed && enabled)) {
170 }
else if (enabled) {
177 target: (selectionArea.width === root.width && selectionArea.height === root.height) || _private.pressedHandle ? null : selectionArea
179 maximumX: root.width - selectionArea.width
181 maximumY: root.height - selectionArea.height
185 onMouseXChanged: _private.updatePendingRect()
186 onMouseYChanged: _private.updatePendingRect()
187 onXChanged: _private.updatePendingRect()
188 onYChanged: _private.updatePendingRect()
189 onWidthChanged: _private.updatePendingRect()
190 onHeightChanged: _private.updatePendingRect()
195 target: selectionArea
196 position: SelectionHandle.TopLeft
197 lockX: _private.pressedHandle && _private.pressedHandle.backwardDiagonal
199 drag.maximumX: handleBottomRight.x - implicitWidth / 2
200 drag.maximumY: handleBottomRight.y - implicitHeight / 2
202 target: _private; property:
"pressedHandle"
203 value: handleTopLeft; when: !_private.applyingPendingRect && handleTopLeft.pressed
204 restoreMode: Binding.RestoreBindingOrValue
209 visible: !_private.isSquareRatio() && selectionArea.width >= implicitWidth
210 target: selectionArea
211 position: SelectionHandle.Top
212 lockY: _private.pressedHandle && _private.pressedHandle.verticalOnly
213 drag.maximumY: handleBottom.y - implicitHeight / 2
215 target: _private; property:
"pressedHandle"
216 value: handleTop; when: handleTop.pressed
217 restoreMode: Binding.RestoreBindingOrValue
222 target: selectionArea
223 position: SelectionHandle.TopRight
224 lockX: _private.pressedHandle && _private.pressedHandle.forwardDiagonal
226 drag.minimumX: handleBottomLeft.x + implicitWidth / 2
227 drag.maximumY: handleBottomLeft.y - implicitHeight / 2
229 target: _private; property:
"pressedHandle"
230 value: handleTopRight; when: !_private.applyingPendingRect && handleTopRight.pressed
231 restoreMode: Binding.RestoreBindingOrValue
236 visible: !_private.isSquareRatio() && selectionArea.height >= implicitHeight
237 target: selectionArea
238 position: SelectionHandle.Left
239 lockX: _private.pressedHandle && _private.pressedHandle.horizontalOnly
240 drag.maximumX: handleRight.x - implicitWidth / 2
242 target: _private; property:
"pressedHandle"
243 value: handleLeft; when: handleLeft.pressed
244 restoreMode: Binding.RestoreBindingOrValue
249 visible: !_private.isSquareRatio() && selectionArea.height >= implicitHeight
250 target: selectionArea
251 position: SelectionHandle.Right
252 lockX: _private.pressedHandle && _private.pressedHandle.horizontalOnly
253 drag.minimumX: handleLeft.x + implicitWidth / 2
255 target: _private; property:
"pressedHandle"
256 value: handleRight; when: handleRight.pressed
257 restoreMode: Binding.RestoreBindingOrValue
262 target: selectionArea
263 position: SelectionHandle.BottomLeft
264 lockX: _private.pressedHandle && _private.pressedHandle.forwardDiagonal
266 drag.maximumX: handleTopRight.x - implicitWidth / 2
267 drag.minimumY: handleTopRight.y + implicitHeight / 2
269 target: _private; property:
"pressedHandle"
270 value: handleBottomLeft; when: !_private.applyingPendingRect && handleBottomLeft.pressed
271 restoreMode: Binding.RestoreBindingOrValue
276 visible: !_private.isSquareRatio() && selectionArea.width >= implicitWidth
277 target: selectionArea
278 position: SelectionHandle.Bottom
279 lockY: _private.pressedHandle && _private.pressedHandle.verticalOnly
280 drag.minimumY: handleTop.y + implicitHeight / 2
282 target: _private; property:
"pressedHandle"
283 value: handleBottom; when: handleBottom.pressed
284 restoreMode: Binding.RestoreBindingOrValue
288 id: handleBottomRight
289 target: selectionArea
290 position: SelectionHandle.BottomRight
291 lockX: _private.pressedHandle && _private.pressedHandle.backwardDiagonal
293 drag.minimumX: handleTopLeft.x + implicitWidth / 2
294 drag.minimumY: handleTopLeft.y + implicitHeight / 2
296 target: _private; property:
"pressedHandle"
297 value: handleBottomRight; when: !_private.applyingPendingRect && handleBottomRight.pressed
298 restoreMode: Binding.RestoreBindingOrValue
302 onWidthChanged:
if (selectionArea.x + selectionArea.width > root.width) {
303 selectionArea.width = Math.max(root.width - selectionArea.x, handleTopLeft.implicitWidth/2)
304 if (selectionArea.x > root.width) {
305 selectionArea.x = Math.max(root.width - selectionArea.width, 0)
308 onHeightChanged:
if (selectionArea.y + selectionArea.height > root.height) {
309 selectionArea.height = Math.max(root.height - selectionArea.y, handleTopLeft.implicitHeight/2)
310 if (selectionArea.y > root.height) {
311 selectionArea.y = Math.max(root.height - selectionArea.height, 0)