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)