155 lines
3.0 KiB
QML
155 lines
3.0 KiB
QML
|
import QtQuick
|
||
|
|
||
|
Item {
|
||
|
id: root
|
||
|
property var parentBlock
|
||
|
property var childBlocks: [] // nested blocks inside this block
|
||
|
property var currentStack: [ root ] // the block stack that root is in
|
||
|
property var workspace // workspace
|
||
|
|
||
|
property bool draggable: false
|
||
|
property alias dragging: drag.active
|
||
|
property real startX // only available when dragging
|
||
|
property real startY
|
||
|
|
||
|
// TMP
|
||
|
property int idx
|
||
|
function toString() { return "Block #" + idx.toString(); }
|
||
|
// TMP
|
||
|
|
||
|
Rectangle {
|
||
|
id: rect
|
||
|
anchors.fill: parent
|
||
|
color: drag.active ? "grey" : "snow"
|
||
|
border.width: 1
|
||
|
radius: 0
|
||
|
}
|
||
|
|
||
|
Text {
|
||
|
text: idx
|
||
|
}
|
||
|
|
||
|
DragHandler {
|
||
|
id: drag
|
||
|
enabled: root.draggable
|
||
|
grabPermissions: PointHandler.TakeOverForbidden
|
||
|
xAxis.enabled: true
|
||
|
yAxis.enabled: true
|
||
|
}
|
||
|
|
||
|
onDraggingChanged: {
|
||
|
if (!dragging) {
|
||
|
finishDrag();
|
||
|
} else {
|
||
|
startDrag();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
onXChanged: {
|
||
|
if (dragging) {
|
||
|
updateChildrenPos();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
onYChanged: {
|
||
|
if (dragging) {
|
||
|
updateChildrenPos();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function getStackParent() {
|
||
|
const idx = currentStack.indexOf(root);
|
||
|
if (idx <= 0) {
|
||
|
return null;
|
||
|
}
|
||
|
return currentStack[idx - 1];
|
||
|
}
|
||
|
|
||
|
function getStackChildren() {
|
||
|
const idx = currentStack.indexOf(root);
|
||
|
if (idx >= currentStack.length - 1) {
|
||
|
return [];
|
||
|
}
|
||
|
return currentStack.slice(idx + 1);
|
||
|
}
|
||
|
|
||
|
function startDrag() {
|
||
|
startX = x;
|
||
|
startY = y;
|
||
|
let children = getStackChildren();
|
||
|
children.push(...childBlocks);
|
||
|
children.forEach(b => {
|
||
|
b.startX = b.x;
|
||
|
b.startY = b.y;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function updateChildrenPos() {
|
||
|
const dx = root.x - root.startX;
|
||
|
const dy = root.y - root.startY;
|
||
|
let children = getStackChildren();
|
||
|
children.push(...childBlocks);
|
||
|
children.forEach(b => {
|
||
|
b.x = b.startX + dx;
|
||
|
b.y = b.startY + dy;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function finishDrag() {
|
||
|
if (currentStack[0] !== root) {
|
||
|
tearFrom(getStackParent());
|
||
|
}
|
||
|
|
||
|
if (parentBlock) {
|
||
|
tearFrom(parentBlock);
|
||
|
}
|
||
|
|
||
|
if (workspace) {
|
||
|
workspace.arrangeBlock(root);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function pasteTo(dest, asParent) {
|
||
|
x = dest.x;
|
||
|
y = dest.y + dest.height;
|
||
|
updateChildrenPos();
|
||
|
|
||
|
if (!asParent) {
|
||
|
const stk = currentStack;
|
||
|
dest.currentStack.push(...stk);
|
||
|
|
||
|
const p = dest.parentBlock;
|
||
|
let c = getStackChildren();
|
||
|
c.push(root);
|
||
|
c.forEach(cc => {
|
||
|
cc.parentBlock = p;
|
||
|
cc.currentStack = dest.currentStack;
|
||
|
});
|
||
|
} else {
|
||
|
// TODO
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function tearFrom(dest) {
|
||
|
const fromParent = dest === root.parentBlock;
|
||
|
if (!fromParent) {
|
||
|
const idx = currentStack.indexOf(root);
|
||
|
const newStack = currentStack.slice(idx);
|
||
|
let c = getStackChildren();
|
||
|
|
||
|
currentStack.splice(idx);
|
||
|
|
||
|
c.push(root);
|
||
|
c.forEach(cc => {
|
||
|
cc.parentBlock = null;
|
||
|
cc.currentStack = newStack;
|
||
|
});
|
||
|
} else {
|
||
|
// TODO
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Component.onCompleted: {
|
||
|
}
|
||
|
}
|