pragma ComponentBehavior: Bound import QtQuick Item { id: root property color handleBorder: "#3584e4" property color handleFill: "white" property real hs: 12 property real minSize: 24 required property real selH required property real selW required property real selX required property real selY signal boundsChanged(x: real, y: real, w: real, h: real) signal dragFinished signal moveBy(dx: real, dy: real) height: selH width: selW x: selX y: selY DragHandler { id: moveHandler property real accumX: 0 property real accumY: 0 target: null onActiveChanged: { accumX = 0; accumY = 0; if (!active) root.dragFinished(); } onTranslationChanged: { const t = moveHandler.translation; root.moveBy(t.x - accumX, t.y - accumY); accumX = t.x; accumY = t.y; } } Handle { edge: "tl" x: -root.hs / 2 y: -root.hs / 2 } Handle { edge: "t" x: root.width / 2 - root.hs / 2 y: -root.hs / 2 } Handle { edge: "tr" x: root.width - root.hs / 2 y: -root.hs / 2 } Handle { edge: "r" x: root.width - root.hs / 2 y: root.height / 2 - root.hs / 2 } Handle { edge: "br" x: root.width - root.hs / 2 y: root.height - root.hs / 2 } Handle { edge: "b" x: root.width / 2 - root.hs / 2 y: root.height - root.hs / 2 } Handle { edge: "bl" x: -root.hs / 2 y: root.height - root.hs / 2 } Handle { edge: "l" x: -root.hs / 2 y: root.height / 2 - root.hs / 2 } component Handle: Rectangle { id: handle required property string edge border.color: root.handleBorder border.width: 2 color: root.handleFill height: root.hs radius: root.hs / 2 width: root.hs z: 10 HoverHandler { cursorShape: { switch (handle.edge) { case "tl": case "br": return Qt.SizeFDiagCursor; case "tr": case "bl": return Qt.SizeBDiagCursor; case "t": case "b": return Qt.SizeVerCursor; default: return Qt.SizeHorCursor; } } } DragHandler { id: dh property real startH property real startW property real startX property real startY grabPermissions: PointerHandler.CanTakeOverFromAnything | PointerHandler.TakeOverForbidden target: null onActiveChanged: { if (active) { startX = root.x; startY = root.y; startW = root.width; startH = root.height; } else { root.dragFinished(); } } onTranslationChanged: { const delta = dh.translation; const e = handle.edge; let nx = startX, ny = startY, nw = startW, nh = startH; if (e.includes("l")) { nx = startX + delta.x; nw = startW - delta.x; } if (e.includes("r")) { nw = startW + delta.x; } if (e.includes("t")) { ny = startY + delta.y; nh = startH - delta.y; } if (e.includes("b")) { nh = startH + delta.y; } if (nw < root.minSize) { if (e.includes("l")) nx = startX + startW - root.minSize; nw = root.minSize; } if (nh < root.minSize) { if (e.includes("t")) ny = startY + startH - root.minSize; nh = root.minSize; } root.boundsChanged(nx, ny, nw, nh); } } } }