From e13133fd2b4ff1e0cfffbf8f153435f767430956 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Mon, 16 Aug 2021 21:21:19 +0100 Subject: [PATCH] Add align actions to editor --- .../editor-client/src/js/keymap.json | 8 +- .../editor-client/src/js/ui/view-tools.js | 109 ++++++++++++++++++ 2 files changed, 116 insertions(+), 1 deletion(-) diff --git a/packages/node_modules/@node-red/editor-client/src/js/keymap.json b/packages/node_modules/@node-red/editor-client/src/js/keymap.json index c323b3e64..b9459e681 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/keymap.json +++ b/packages/node_modules/@node-red/editor-client/src/js/keymap.json @@ -77,6 +77,12 @@ "right": "core:go-to-nearest-node-on-right", "left": "core:go-to-nearest-node-on-left", "up": "core:go-to-nearest-node-above", - "down": "core:go-to-nearest-node-below" + "down": "core:go-to-nearest-node-below", + "alt-a l": "core:align-nodes-to-left", + "alt-a r": "core:align-nodes-to-right", + "alt-a t": "core:align-nodes-to-top", + "alt-a b": "core:align-nodes-to-bottom", + "alt-a m": "core:align-nodes-to-middle", + "alt-a c": "core:align-nodes-to-center" } } diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js b/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js index 6c3889832..001155519 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js @@ -427,8 +427,107 @@ RED.view.tools = (function() { } } } + } + function alignSelectionToEdge(direction) { + var selection = RED.view.selection(); + if (selection.nodes && selection.nodes.length > 1) { + var changedNodes = []; + var bounds = { + minX: Number.MAX_SAFE_INTEGER, + minY: Number.MAX_SAFE_INTEGER, + maxX: Number.MIN_SAFE_INTEGER, + maxY: Number.MIN_SAFE_INTEGER + } + selection.nodes.forEach(function(n) { + if (n.type === "group") { + bounds.minX = Math.min(bounds.minX, n.x); + bounds.minY = Math.min(bounds.minY, n.y); + bounds.maxX = Math.max(bounds.maxX, n.x + n.w); + bounds.maxY = Math.max(bounds.maxY, n.y + n.h); + } else { + bounds.minX = Math.min(bounds.minX, n.x - n.w/2); + bounds.minY = Math.min(bounds.minY, n.y - n.h/2); + bounds.maxX = Math.max(bounds.maxX, n.x + n.w/2); + bounds.maxY = Math.max(bounds.maxY, n.y + n.h/2); + } + }); + + bounds.midX = bounds.minX + (bounds.maxX - bounds.minX)/2; + bounds.midY = bounds.minY + (bounds.maxY - bounds.minY)/2; + + selection.nodes.forEach(function(n) { + var targetX; + var targetY; + var isGroup = n.type==="group"; + switch(direction) { + case 'top': + targetX = n.x; + targetY = bounds.minY + (isGroup?0:(n.h/2)); + break; + case 'bottom': + targetX = n.x; + targetY = bounds.maxY - (isGroup?n.h:(n.h/2)); + break; + case 'left': + targetX = bounds.minX + (isGroup?0:(n.w/2)); + targetY = n.y; + break; + case 'right': + targetX = bounds.maxX - (isGroup?n.w:(n.w/2)); + targetY = n.y; + break; + case 'middle': + targetX = n.x; + targetY = bounds.midY - (isGroup?n.h/2:0) + break; + case 'center': + targetX = bounds.midX - (isGroup?n.w/2:0) + targetY = n.y; + break; + } + + if (n.x !== targetX || n.y !== targetY) { + if (!isGroup) { + changedNodes.push({ + n:n, + ox: n.x, + oy: n.y, + moved: n.moved + }); + n.x = targetX; + n.y = targetY; + n.dirty = true; + n.moved = true; + } else { + var groupNodes = RED.group.getNodes(n, true); + var deltaX = n.x - targetX; + var deltaY = n.y - targetY; + 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 (changedNodes.length > 0) { + RED.history.push({t:"move",nodes:changedNodes,dirty:RED.nodes.dirty()}); + RED.nodes.dirty(true); + RED.view.redraw(true); + } + } } @@ -474,6 +573,16 @@ RED.view.tools = (function() { RED.actions.add("core:go-to-nearest-node-on-right", function() { gotoNearestNode('right')}) RED.actions.add("core:go-to-nearest-node-above", function() { gotoNearestNode('up') }) RED.actions.add("core:go-to-nearest-node-below", function() { gotoNearestNode('down') }) + + RED.actions.add("core:align-nodes-to-left", function() { alignSelectionToEdge('left') }) + RED.actions.add("core:align-nodes-to-right", function() { alignSelectionToEdge('right') }) + RED.actions.add("core:align-nodes-to-top", function() { alignSelectionToEdge('top') }) + RED.actions.add("core:align-nodes-to-bottom", function() { alignSelectionToEdge('bottom') }) + RED.actions.add("core:align-nodes-to-middle", function() { alignSelectionToEdge('middle') }) + RED.actions.add("core:align-nodes-to-center", function() { alignSelectionToEdge('center') }) + + + // RED.actions.add("core:add-node", function() { addNode() }) }, /**