mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Add distribute-horizontally/vertically actions to editor
This commit is contained in:
parent
56121203bf
commit
d2cdc67ec7
@ -84,6 +84,8 @@
|
|||||||
"alt-a t": "core:align-selection-to-top",
|
"alt-a t": "core:align-selection-to-top",
|
||||||
"alt-a b": "core:align-selection-to-bottom",
|
"alt-a b": "core:align-selection-to-bottom",
|
||||||
"alt-a m": "core:align-selection-to-middle",
|
"alt-a m": "core:align-selection-to-middle",
|
||||||
"alt-a c": "core:align-selection-to-center"
|
"alt-a c": "core:align-selection-to-center",
|
||||||
|
"alt-a h": "core:distribute-selection-horizontally",
|
||||||
|
"alt-a v": "core:distribute-selection-vertically"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -531,6 +531,165 @@ RED.view.tools = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function distributeSelection(direction) {
|
||||||
|
var selection = RED.view.selection();
|
||||||
|
|
||||||
|
if (selection.nodes && selection.nodes.length > 2) {
|
||||||
|
var changedNodes = [];
|
||||||
|
var bounds = {
|
||||||
|
minX: Number.MAX_SAFE_INTEGER,
|
||||||
|
minY: Number.MAX_SAFE_INTEGER,
|
||||||
|
maxX: Number.MIN_SAFE_INTEGER,
|
||||||
|
maxY: Number.MIN_SAFE_INTEGER
|
||||||
|
}
|
||||||
|
var startAnchors = [];
|
||||||
|
var endAnchors = [];
|
||||||
|
|
||||||
|
selection.nodes.forEach(function(n) {
|
||||||
|
var nx,ny;
|
||||||
|
if (n.type === "group") {
|
||||||
|
nx = n.x + n.w/2;
|
||||||
|
ny = n.y + n.h/2;
|
||||||
|
} else {
|
||||||
|
nx = n.x;
|
||||||
|
ny = n.y;
|
||||||
|
}
|
||||||
|
if (direction === "h") {
|
||||||
|
if (nx < bounds.minX) {
|
||||||
|
startAnchors = [];
|
||||||
|
bounds.minX = nx;
|
||||||
|
}
|
||||||
|
if (nx === bounds.minX) {
|
||||||
|
startAnchors.push(n);
|
||||||
|
}
|
||||||
|
if (nx > bounds.maxX) {
|
||||||
|
endAnchors = [];
|
||||||
|
bounds.maxX = nx;
|
||||||
|
}
|
||||||
|
if (nx === bounds.maxX) {
|
||||||
|
endAnchors.push(n);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ny < bounds.minY) {
|
||||||
|
startAnchors = [];
|
||||||
|
bounds.minY = ny;
|
||||||
|
}
|
||||||
|
if (ny === bounds.minY) {
|
||||||
|
startAnchors.push(n);
|
||||||
|
}
|
||||||
|
if (ny > bounds.maxY) {
|
||||||
|
endAnchors = [];
|
||||||
|
bounds.maxY = ny;
|
||||||
|
}
|
||||||
|
if (ny === bounds.maxY) {
|
||||||
|
endAnchors.push(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var startAnchor = startAnchors[0];
|
||||||
|
var endAnchor = endAnchors[0];
|
||||||
|
|
||||||
|
var nodeSpace = 0;
|
||||||
|
var nodesToMove = selection.nodes.filter(function(n) {
|
||||||
|
if (n.id !== startAnchor.id && n.id !== endAnchor.id) {
|
||||||
|
nodeSpace += direction === 'h'?n.w:n.h;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}).sort(function(A,B) {
|
||||||
|
if (direction === 'h') {
|
||||||
|
return A.x - B.x
|
||||||
|
} else {
|
||||||
|
return A.y - B.y
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var saX = startAnchor.x + startAnchor.w/2;
|
||||||
|
var saY = startAnchor.y + startAnchor.h/2;
|
||||||
|
if (startAnchor.type === "group") {
|
||||||
|
saX = startAnchor.x + startAnchor.w;
|
||||||
|
saY = startAnchor.y + startAnchor.h;
|
||||||
|
}
|
||||||
|
var eaX = endAnchor.x;
|
||||||
|
var eaY = endAnchor.y;
|
||||||
|
if (endAnchor.type !== "group") {
|
||||||
|
eaX -= endAnchor.w/2;
|
||||||
|
eaY -= endAnchor.h/2;
|
||||||
|
}
|
||||||
|
var spaceToFill = direction === 'h'?(eaX - saX - nodeSpace): (eaY - saY - nodeSpace);
|
||||||
|
var spaceBetweenNodes = spaceToFill / (nodesToMove.length + 1);
|
||||||
|
|
||||||
|
var tx = saX;
|
||||||
|
var ty = saY;
|
||||||
|
while(nodesToMove.length > 0) {
|
||||||
|
if (direction === 'h') {
|
||||||
|
tx += spaceBetweenNodes;
|
||||||
|
} else {
|
||||||
|
ty += spaceBetweenNodes;
|
||||||
|
}
|
||||||
|
var nextNode = nodesToMove.shift();
|
||||||
|
var isGroup = nextNode.type==="group";
|
||||||
|
|
||||||
|
var nx = nextNode.x;
|
||||||
|
var ny = nextNode.y;
|
||||||
|
if (!isGroup) {
|
||||||
|
tx += nextNode.w/2;
|
||||||
|
ty += nextNode.h/2;
|
||||||
|
}
|
||||||
|
if ((direction === 'h' && nx !== tx) || (direction === 'v' && ny !== ty)) {
|
||||||
|
if (!isGroup) {
|
||||||
|
changedNodes.push({
|
||||||
|
n:nextNode,
|
||||||
|
ox: nextNode.x,
|
||||||
|
oy: nextNode.y,
|
||||||
|
moved: nextNode.moved
|
||||||
|
});
|
||||||
|
if (direction === 'h') {
|
||||||
|
nextNode.x = tx;
|
||||||
|
} else {
|
||||||
|
nextNode.y = ty;
|
||||||
|
}
|
||||||
|
nextNode.dirty = true;
|
||||||
|
nextNode.moved = true;
|
||||||
|
} else {
|
||||||
|
var groupNodes = RED.group.getNodes(nextNode, true);
|
||||||
|
var deltaX = direction === 'h'? nx - tx : 0;
|
||||||
|
var deltaY = direction === 'v'? ny - ty : 0;
|
||||||
|
groupNodes.forEach(function(gn) {
|
||||||
|
if (gn.type !== "group" ) {
|
||||||
|
changedNodes.push({
|
||||||
|
n:gn,
|
||||||
|
ox: gn.x,
|
||||||
|
oy: gn.y,
|
||||||
|
moved: gn.moved
|
||||||
|
});
|
||||||
|
gn.x = gn.x - deltaX;
|
||||||
|
gn.y = gn.y - deltaY;
|
||||||
|
gn.dirty = true;
|
||||||
|
gn.moved = true;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isGroup) {
|
||||||
|
tx += nextNode.w;
|
||||||
|
ty += nextNode.h;
|
||||||
|
} else {
|
||||||
|
tx += nextNode.w/2;
|
||||||
|
ty += nextNode.h/2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changedNodes.length > 0) {
|
||||||
|
RED.history.push({t:"move",nodes:changedNodes,dirty:RED.nodes.dirty()});
|
||||||
|
RED.nodes.dirty(true);
|
||||||
|
RED.view.redraw(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
init: function() {
|
init: function() {
|
||||||
RED.actions.add("core:show-selected-node-labels", function() { setSelectedNodeLabelState(true); })
|
RED.actions.add("core:show-selected-node-labels", function() { setSelectedNodeLabelState(true); })
|
||||||
@ -580,6 +739,8 @@ RED.view.tools = (function() {
|
|||||||
RED.actions.add("core:align-selection-to-middle", function() { alignSelectionToEdge('middle') })
|
RED.actions.add("core:align-selection-to-middle", function() { alignSelectionToEdge('middle') })
|
||||||
RED.actions.add("core:align-selection-to-center", function() { alignSelectionToEdge('center') })
|
RED.actions.add("core:align-selection-to-center", function() { alignSelectionToEdge('center') })
|
||||||
|
|
||||||
|
RED.actions.add("core:distribute-selection-horizontally", function() { distributeSelection('h') })
|
||||||
|
RED.actions.add("core:distribute-selection-vertically", function() { distributeSelection('v') })
|
||||||
|
|
||||||
|
|
||||||
// RED.actions.add("core:add-node", function() { addNode() })
|
// RED.actions.add("core:add-node", function() { addNode() })
|
||||||
|
Loading…
Reference in New Issue
Block a user