KQuickImageEditor

SelectionTool.qml
1/* SPDX-FileCopyrightText: 2021 Noah Davis <noahadvs@gmail.com>
2 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
3 */
4
5import QtQuick 2.15
6import QtQml 2.15
7
8Item {
9 id: root
10 // make this readonly so it can be accessed without risking external modification
11 readonly property SelectionHandle pressedHandle: _private.pressedHandle
12 readonly property alias selectionArea: selectionArea
13 property alias selectionX: selectionArea.x
14 property alias selectionY: selectionArea.y
15 property alias selectionWidth: selectionArea.width
16 property alias selectionHeight: selectionArea.height
17
18 QtObject {
19 id: _private
20 property SelectionHandle pressedHandle: null
21 }
22
23 MouseArea {
24 id: selectionArea
25 x: 0
26 y: 0
27 z: 1
28 width: parent.width
29 height: parent.height
30 LayoutMirroring.enabled: false
31 anchors.left: if (_private.pressedHandle) {
32 if (_private.pressedHandle.backwardDiagonal) {
33 handleTopLeft.horizontalCenter
34 } else if (_private.pressedHandle.forwardDiagonal) {
35 handleBottomLeft.horizontalCenter
36 } else if (_private.pressedHandle.horizontalOnly) {
37 handleLeft.horizontalCenter
38 }
39 }
40 anchors.right: if (_private.pressedHandle) {
41 if (_private.pressedHandle.backwardDiagonal) {
42 handleBottomRight.horizontalCenter
43 } else if (_private.pressedHandle.forwardDiagonal) {
44 handleTopRight.horizontalCenter
45 } else if (_private.pressedHandle.horizontalOnly) {
46 handleRight.horizontalCenter
47 }
48 }
49 anchors.top: if (_private.pressedHandle) {
50 if (_private.pressedHandle.backwardDiagonal) {
51 handleTopLeft.verticalCenter
52 } else if (_private.pressedHandle.forwardDiagonal) {
53 handleTopRight.verticalCenter
54 } else if (_private.pressedHandle.verticalOnly) {
55 handleTop.verticalCenter
56 }
57 }
58 anchors.bottom: if (_private.pressedHandle) {
59 if (_private.pressedHandle.backwardDiagonal) {
60 handleBottomRight.verticalCenter
61 } else if (_private.pressedHandle.forwardDiagonal) {
62 handleBottomLeft.verticalCenter
63 } else if (_private.pressedHandle.verticalOnly) {
64 handleBottom.verticalCenter
65 }
66 }
67 enabled: drag.target
68 cursorShape: if (_private.pressedHandle || (pressed && enabled)) {
69 Qt.ClosedHandCursor
70 } else if (enabled) {
71 Qt.OpenHandCursor
72 } else {
73 Qt.ArrowCursor
74 }
75 drag {
76 axis: Drag.XAndYAxis
77 target: (selectionArea.width === root.width && selectionArea.height === root.height) || _private.pressedHandle ? null : selectionArea
78 minimumX: 0
79 maximumX: root.width - selectionArea.width
80 minimumY: 0
81 maximumY: root.height - selectionArea.height
82 threshold: 0
83 }
84 }
85
86 SelectionHandle {
87 id: handleTopLeft
88 target: selectionArea
89 position: SelectionHandle.TopLeft
90 lockX: _private.pressedHandle && _private.pressedHandle.backwardDiagonal
91 lockY: lockX
92 drag.maximumX: handleBottomRight.x - implicitWidth / 2
93 drag.maximumY: handleBottomRight.y - implicitHeight / 2
94 Binding {
95 target: _private; property: "pressedHandle"
96 value: handleTopLeft; when: handleTopLeft.pressed
97 restoreMode: Binding.RestoreBindingOrValue
98 }
99 }
100 SelectionHandle {
101 id: handleTop
102 visible: selectionArea.width >= implicitWidth
103 target: selectionArea
104 position: SelectionHandle.Top
105 lockY: _private.pressedHandle && _private.pressedHandle.verticalOnly
106 drag.maximumY: handleBottom.y - implicitHeight / 2
107 Binding {
108 target: _private; property: "pressedHandle"
109 value: handleTop; when: handleTop.pressed
110 restoreMode: Binding.RestoreBindingOrValue
111 }
112 }
113 SelectionHandle {
114 id: handleTopRight
115 target: selectionArea
116 position: SelectionHandle.TopRight
117 lockX: _private.pressedHandle && _private.pressedHandle.forwardDiagonal
118 lockY: lockX
119 drag.minimumX: handleBottomLeft.x + implicitWidth / 2
120 drag.maximumY: handleBottomLeft.y - implicitHeight / 2
121 Binding {
122 target: _private; property: "pressedHandle"
123 value: handleTopRight; when: handleTopRight.pressed
124 restoreMode: Binding.RestoreBindingOrValue
125 }
126 }
127 SelectionHandle {
128 id: handleLeft
129 visible: selectionArea.height >= implicitHeight
130 target: selectionArea
131 position: SelectionHandle.Left
132 lockX: _private.pressedHandle && _private.pressedHandle.horizontalOnly
133 drag.maximumX: handleRight.x - implicitWidth / 2
134 Binding {
135 target: _private; property: "pressedHandle"
136 value: handleLeft; when: handleLeft.pressed
137 restoreMode: Binding.RestoreBindingOrValue
138 }
139 }
140 SelectionHandle {
141 id: handleRight
142 visible: selectionArea.height >= implicitHeight
143 target: selectionArea
144 position: SelectionHandle.Right
145 lockX: _private.pressedHandle && _private.pressedHandle.horizontalOnly
146 drag.minimumX: handleLeft.x + implicitWidth / 2
147 Binding {
148 target: _private; property: "pressedHandle"
149 value: handleRight; when: handleRight.pressed
150 restoreMode: Binding.RestoreBindingOrValue
151 }
152 }
153 SelectionHandle {
154 id: handleBottomLeft
155 target: selectionArea
156 position: SelectionHandle.BottomLeft
157 lockX: _private.pressedHandle && _private.pressedHandle.forwardDiagonal
158 lockY: lockX
159 drag.maximumX: handleTopRight.x - implicitWidth / 2
160 drag.minimumY: handleTopRight.y + implicitHeight / 2
161 Binding {
162 target: _private; property: "pressedHandle"
163 value: handleBottomLeft; when: handleBottomLeft.pressed
164 restoreMode: Binding.RestoreBindingOrValue
165 }
166 }
167 SelectionHandle {
168 id: handleBottom
169 visible: selectionArea.width >= implicitWidth
170 target: selectionArea
171 position: SelectionHandle.Bottom
172 lockY: _private.pressedHandle && _private.pressedHandle.verticalOnly
173 drag.minimumY: handleTop.y + implicitHeight / 2
174 Binding {
175 target: _private; property: "pressedHandle"
176 value: handleBottom; when: handleBottom.pressed
177 restoreMode: Binding.RestoreBindingOrValue
178 }
179 }
180 SelectionHandle {
181 id: handleBottomRight
182 target: selectionArea
183 position: SelectionHandle.BottomRight
184 lockX: _private.pressedHandle && _private.pressedHandle.backwardDiagonal
185 lockY: lockX
186 drag.minimumX: handleTopLeft.x + implicitWidth / 2
187 drag.minimumY: handleTopLeft.y + implicitHeight / 2
188 Binding {
189 target: _private; property: "pressedHandle"
190 value: handleBottomRight; when: handleBottomRight.pressed
191 restoreMode: Binding.RestoreBindingOrValue
192 }
193 }
194 // TODO: maybe scale proportions instead of just limiting size
195 onWidthChanged: if (selectionArea.x + selectionArea.width > root.width) {
196 selectionArea.width = Math.max(root.width - selectionArea.x, handleTopLeft.implicitWidth/2)
197 if (selectionArea.x > root.width) {
198 selectionArea.x = Math.max(root.width - selectionArea.width, 0)
199 }
200 }
201 onHeightChanged: if (selectionArea.y + selectionArea.height > root.height) {
202 selectionArea.height = Math.max(root.height - selectionArea.y, handleTopLeft.implicitHeight/2)
203 if (selectionArea.y > root.height) {
204 selectionArea.y = Math.max(root.height - selectionArea.height, 0)
205 }
206 }
207}
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:19:40 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.