mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
commit
44ef9a13d6
@ -684,6 +684,13 @@ RED.history = (function() {
|
|||||||
peek: function() {
|
peek: function() {
|
||||||
return undoHistory[undoHistory.length-1];
|
return undoHistory[undoHistory.length-1];
|
||||||
},
|
},
|
||||||
|
replace: function(ev) {
|
||||||
|
if (undoHistory.length === 0) {
|
||||||
|
RED.history.push(ev);
|
||||||
|
} else {
|
||||||
|
undoHistory[undoHistory.length-1] = ev;
|
||||||
|
}
|
||||||
|
},
|
||||||
clear: function() {
|
clear: function() {
|
||||||
undoHistory = [];
|
undoHistory = [];
|
||||||
redoHistory = [];
|
redoHistory = [];
|
||||||
|
@ -38,7 +38,9 @@
|
|||||||
},
|
},
|
||||||
"red-ui-workspace": {
|
"red-ui-workspace": {
|
||||||
"backspace": "core:delete-selection",
|
"backspace": "core:delete-selection",
|
||||||
|
"ctrl-backspace": "core:delete-selection-and-reconnect",
|
||||||
"delete": "core:delete-selection",
|
"delete": "core:delete-selection",
|
||||||
|
"ctrl-delete": "core:delete-selection-and-reconnect",
|
||||||
"enter": "core:edit-selected-node",
|
"enter": "core:edit-selected-node",
|
||||||
"ctrl-enter": "core:go-to-selection",
|
"ctrl-enter": "core:go-to-selection",
|
||||||
"ctrl-c": "core:copy-selection-to-internal-clipboard",
|
"ctrl-c": "core:copy-selection-to-internal-clipboard",
|
||||||
|
@ -15,6 +15,9 @@
|
|||||||
**/
|
**/
|
||||||
RED.nodes = (function() {
|
RED.nodes = (function() {
|
||||||
|
|
||||||
|
var PORT_TYPE_INPUT = 1;
|
||||||
|
var PORT_TYPE_OUTPUT = 0;
|
||||||
|
|
||||||
var node_defs = {};
|
var node_defs = {};
|
||||||
var linkTabMap = {};
|
var linkTabMap = {};
|
||||||
|
|
||||||
@ -2458,6 +2461,144 @@ RED.nodes = (function() {
|
|||||||
return helpContent;
|
return helpContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getNodeIslands(nodes) {
|
||||||
|
var selectedNodes = new Set(nodes);
|
||||||
|
// Maps node => island index
|
||||||
|
var nodeToIslandIndex = new Map();
|
||||||
|
// Maps island index => [nodes in island]
|
||||||
|
var islandIndexToNodes = new Map();
|
||||||
|
var internalLinks = new Set();
|
||||||
|
nodes.forEach((node, index) => {
|
||||||
|
nodeToIslandIndex.set(node,index);
|
||||||
|
islandIndexToNodes.set(index, [node]);
|
||||||
|
var inboundLinks = RED.nodes.getNodeLinks(node, PORT_TYPE_INPUT);
|
||||||
|
var outboundLinks = RED.nodes.getNodeLinks(node, PORT_TYPE_OUTPUT);
|
||||||
|
inboundLinks.forEach(l => {
|
||||||
|
if (selectedNodes.has(l.source)) {
|
||||||
|
internalLinks.add(l)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
outboundLinks.forEach(l => {
|
||||||
|
if (selectedNodes.has(l.target)) {
|
||||||
|
internalLinks.add(l)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
internalLinks.forEach(l => {
|
||||||
|
let source = l.source;
|
||||||
|
let target = l.target;
|
||||||
|
if (nodeToIslandIndex.get(source) !== nodeToIslandIndex.get(target)) {
|
||||||
|
let sourceIsland = nodeToIslandIndex.get(source);
|
||||||
|
let islandToMove = nodeToIslandIndex.get(target);
|
||||||
|
let nodesToMove = islandIndexToNodes.get(islandToMove);
|
||||||
|
nodesToMove.forEach(n => {
|
||||||
|
nodeToIslandIndex.set(n,sourceIsland);
|
||||||
|
islandIndexToNodes.get(sourceIsland).push(n);
|
||||||
|
})
|
||||||
|
islandIndexToNodes.delete(islandToMove);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const result = [];
|
||||||
|
islandIndexToNodes.forEach((nodes,index) => {
|
||||||
|
result.push(nodes);
|
||||||
|
})
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function detachNodes(nodes) {
|
||||||
|
let allSelectedNodes = [];
|
||||||
|
nodes.forEach(node => {
|
||||||
|
if (node.type === 'group') {
|
||||||
|
let groupNodes = RED.group.getNodes(node,true,true);
|
||||||
|
allSelectedNodes = allSelectedNodes.concat(groupNodes);
|
||||||
|
} else {
|
||||||
|
allSelectedNodes.push(node);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (allSelectedNodes.length > 0 ) {
|
||||||
|
const nodeIslands = RED.nodes.getNodeIslands(allSelectedNodes);
|
||||||
|
let removedLinks = [];
|
||||||
|
let newLinks = [];
|
||||||
|
let createdLinkIds = new Set();
|
||||||
|
|
||||||
|
nodeIslands.forEach(nodes => {
|
||||||
|
let selectedNodes = new Set(nodes);
|
||||||
|
let allInboundLinks = [];
|
||||||
|
let allOutboundLinks = [];
|
||||||
|
// Identify links that enter or exit this island of nodes
|
||||||
|
nodes.forEach(node => {
|
||||||
|
var inboundLinks = RED.nodes.getNodeLinks(node, PORT_TYPE_INPUT);
|
||||||
|
var outboundLinks = RED.nodes.getNodeLinks(node, PORT_TYPE_OUTPUT);
|
||||||
|
inboundLinks.forEach(l => {
|
||||||
|
if (!selectedNodes.has(l.source)) {
|
||||||
|
allInboundLinks.push(l)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
outboundLinks.forEach(l => {
|
||||||
|
if (!selectedNodes.has(l.target)) {
|
||||||
|
allOutboundLinks.push(l)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Identify the links to restore
|
||||||
|
allInboundLinks.forEach(inLink => {
|
||||||
|
// For Each inbound link,
|
||||||
|
// - get source node.
|
||||||
|
// - trace through to all outbound links
|
||||||
|
let sourceNode = inLink.source;
|
||||||
|
let targetNodes = new Set();
|
||||||
|
let visited = new Set();
|
||||||
|
let stack = [inLink.target];
|
||||||
|
while (stack.length > 0) {
|
||||||
|
let node = stack.pop(stack);
|
||||||
|
visited.add(node)
|
||||||
|
let links = RED.nodes.getNodeLinks(node, PORT_TYPE_OUTPUT);
|
||||||
|
links.forEach(l => {
|
||||||
|
if (visited.has(l.target)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
visited.add(l.target);
|
||||||
|
if (selectedNodes.has(l.target)) {
|
||||||
|
// internal link
|
||||||
|
stack.push(l.target)
|
||||||
|
} else {
|
||||||
|
targetNodes.add(l.target)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
targetNodes.forEach(target => {
|
||||||
|
let linkId = `${sourceNode.id}[${inLink.sourcePort}] -> ${target.id}`
|
||||||
|
if (!createdLinkIds.has(linkId)) {
|
||||||
|
createdLinkIds.add(linkId);
|
||||||
|
let link = {
|
||||||
|
source: sourceNode,
|
||||||
|
sourcePort: inLink.sourcePort,
|
||||||
|
target: target
|
||||||
|
}
|
||||||
|
let existingLinks = RED.nodes.filterLinks(link)
|
||||||
|
if (existingLinks.length === 0) {
|
||||||
|
newLinks.push(link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// 2. delete all those links
|
||||||
|
allInboundLinks.forEach(l => { RED.nodes.removeLink(l); removedLinks.push(l)})
|
||||||
|
allOutboundLinks.forEach(l => { RED.nodes.removeLink(l); removedLinks.push(l)})
|
||||||
|
})
|
||||||
|
|
||||||
|
newLinks.forEach(l => RED.nodes.addLink(l));
|
||||||
|
return {
|
||||||
|
newLinks,
|
||||||
|
removedLinks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
init: function() {
|
init: function() {
|
||||||
RED.events.on("registry:node-type-added",function(type) {
|
RED.events.on("registry:node-type-added",function(type) {
|
||||||
@ -2539,7 +2680,7 @@ RED.nodes = (function() {
|
|||||||
add: addNode,
|
add: addNode,
|
||||||
remove: removeNode,
|
remove: removeNode,
|
||||||
clear: clear,
|
clear: clear,
|
||||||
|
detachNodes: detachNodes,
|
||||||
moveNodesForwards: moveNodesForwards,
|
moveNodesForwards: moveNodesForwards,
|
||||||
moveNodesBackwards: moveNodesBackwards,
|
moveNodesBackwards: moveNodesBackwards,
|
||||||
moveNodesToFront: moveNodesToFront,
|
moveNodesToFront: moveNodesToFront,
|
||||||
@ -2552,6 +2693,9 @@ RED.nodes = (function() {
|
|||||||
addLink: addLink,
|
addLink: addLink,
|
||||||
removeLink: removeLink,
|
removeLink: removeLink,
|
||||||
getNodeLinks: function(id, portType) {
|
getNodeLinks: function(id, portType) {
|
||||||
|
if (typeof id !== 'string') {
|
||||||
|
id = id.id;
|
||||||
|
}
|
||||||
if (nodeLinks[id]) {
|
if (nodeLinks[id]) {
|
||||||
if (portType === 1) {
|
if (portType === 1) {
|
||||||
// Return cloned arrays so they can be safely modified by caller
|
// Return cloned arrays so they can be safely modified by caller
|
||||||
@ -2635,6 +2779,7 @@ RED.nodes = (function() {
|
|||||||
getAllFlowNodes: getAllFlowNodes,
|
getAllFlowNodes: getAllFlowNodes,
|
||||||
getAllUpstreamNodes: getAllUpstreamNodes,
|
getAllUpstreamNodes: getAllUpstreamNodes,
|
||||||
getAllDownstreamNodes: getAllDownstreamNodes,
|
getAllDownstreamNodes: getAllDownstreamNodes,
|
||||||
|
getNodeIslands: getNodeIslands,
|
||||||
createExportableNodeSet: createExportableNodeSet,
|
createExportableNodeSet: createExportableNodeSet,
|
||||||
createCompleteNodeSet: createCompleteNodeSet,
|
createCompleteNodeSet: createCompleteNodeSet,
|
||||||
updateConfigNodeUsers: updateConfigNodeUsers,
|
updateConfigNodeUsers: updateConfigNodeUsers,
|
||||||
|
@ -590,12 +590,14 @@ RED.group = (function() {
|
|||||||
markDirty(group);
|
markDirty(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNodes(group,recursive) {
|
function getNodes(group,recursive,excludeGroup) {
|
||||||
var nodes = [];
|
var nodes = [];
|
||||||
group.nodes.forEach(function(n) {
|
group.nodes.forEach(function(n) {
|
||||||
|
if (n.type !== 'group' || !excludeGroup) {
|
||||||
nodes.push(n);
|
nodes.push(n);
|
||||||
|
}
|
||||||
if (recursive && n.type === 'group') {
|
if (recursive && n.type === 'group') {
|
||||||
nodes = nodes.concat(getNodes(n,recursive))
|
nodes = nodes.concat(getNodes(n,recursive,excludeGroup))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return nodes;
|
return nodes;
|
||||||
|
@ -27,5 +27,6 @@ RED.state = {
|
|||||||
PANNING: 10,
|
PANNING: 10,
|
||||||
SELECTING_NODE: 11,
|
SELECTING_NODE: 11,
|
||||||
GROUP_DRAGGING: 12,
|
GROUP_DRAGGING: 12,
|
||||||
GROUP_RESIZE: 13
|
GROUP_RESIZE: 13,
|
||||||
|
DETACHED_DRAGGING: 14
|
||||||
}
|
}
|
||||||
|
@ -538,6 +538,8 @@ RED.view = (function() {
|
|||||||
RED.actions.add("core:cut-selection-to-internal-clipboard",function(){copySelection();deleteSelection();});
|
RED.actions.add("core:cut-selection-to-internal-clipboard",function(){copySelection();deleteSelection();});
|
||||||
RED.actions.add("core:paste-from-internal-clipboard",function(){importNodes(clipboard,{generateIds: true});});
|
RED.actions.add("core:paste-from-internal-clipboard",function(){importNodes(clipboard,{generateIds: true});});
|
||||||
|
|
||||||
|
RED.actions.add("core:detach-selected-nodes", function() { detachSelectedNodes() })
|
||||||
|
|
||||||
RED.events.on("view:selection-changed", function(selection) {
|
RED.events.on("view:selection-changed", function(selection) {
|
||||||
var hasSelection = (selection.nodes && selection.nodes.length > 0);
|
var hasSelection = (selection.nodes && selection.nodes.length > 0);
|
||||||
var hasMultipleSelection = hasSelection && selection.nodes.length > 1;
|
var hasMultipleSelection = hasSelection && selection.nodes.length > 1;
|
||||||
@ -560,6 +562,7 @@ RED.view = (function() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
RED.actions.add("core:delete-selection",deleteSelection);
|
RED.actions.add("core:delete-selection",deleteSelection);
|
||||||
|
RED.actions.add("core:delete-selection-and-reconnect",function() { deleteSelection(true) });
|
||||||
RED.actions.add("core:edit-selected-node",editSelection);
|
RED.actions.add("core:edit-selected-node",editSelection);
|
||||||
RED.actions.add("core:go-to-selection",function() {
|
RED.actions.add("core:go-to-selection",function() {
|
||||||
if (movingSet.length() > 0) {
|
if (movingSet.length() > 0) {
|
||||||
@ -1384,7 +1387,7 @@ RED.view = (function() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mouse_mode != RED.state.QUICK_JOINING && mouse_mode != RED.state.IMPORT_DRAGGING && !mousedown_node && !mousedown_group && selectedLinks.length() === 0) {
|
if (mouse_mode != RED.state.QUICK_JOINING && mouse_mode != RED.state.IMPORT_DRAGGING && mouse_mode != RED.state.DETACHED_DRAGGING && !mousedown_node && !mousedown_group && selectedLinks.length() === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1489,7 +1492,7 @@ RED.view = (function() {
|
|||||||
RED.nodes.filterLinks({ target: node.n }).length === 0;
|
RED.nodes.filterLinks({ target: node.n }).length === 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (mouse_mode == RED.state.MOVING_ACTIVE || mouse_mode == RED.state.IMPORT_DRAGGING) {
|
} else if (mouse_mode == RED.state.MOVING_ACTIVE || mouse_mode == RED.state.IMPORT_DRAGGING || mouse_mode == RED.state.DETACHED_DRAGGING) {
|
||||||
mousePos = mouse_position;
|
mousePos = mouse_position;
|
||||||
var minX = 0;
|
var minX = 0;
|
||||||
var minY = 0;
|
var minY = 0;
|
||||||
@ -1845,10 +1848,30 @@ RED.view = (function() {
|
|||||||
// movingSet.add(mousedown_node);
|
// movingSet.add(mousedown_node);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
if (mouse_mode == RED.state.MOVING || mouse_mode == RED.state.MOVING_ACTIVE) {
|
if (mouse_mode == RED.state.MOVING || mouse_mode == RED.state.MOVING_ACTIVE || mouse_mode == RED.state.DETACHED_DRAGGING) {
|
||||||
// if (mousedown_node) {
|
// if (mousedown_node) {
|
||||||
// delete mousedown_node.gSelected;
|
// delete mousedown_node.gSelected;
|
||||||
// }
|
// }
|
||||||
|
if (mouse_mode === RED.state.DETACHED_DRAGGING) {
|
||||||
|
var ns = [];
|
||||||
|
for (var j=0;j<movingSet.length();j++) {
|
||||||
|
var n = movingSet.get(j);
|
||||||
|
if (n.ox !== n.n.x || n.oy !== n.n.y) {
|
||||||
|
ns.push({n:n.n,ox:n.ox,oy:n.oy,moved:n.n.moved});
|
||||||
|
n.n.dirty = true;
|
||||||
|
n.n.moved = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var detachEvent = RED.history.peek();
|
||||||
|
// The last event in the stack *should* be a multi-event from
|
||||||
|
// where the links were added/removed
|
||||||
|
var historyEvent = {t:"move",nodes:ns,dirty:RED.nodes.dirty()}
|
||||||
|
if (detachEvent.t === "multi") {
|
||||||
|
detachEvent.events.push(historyEvent)
|
||||||
|
} else {
|
||||||
|
RED.history.push(historyEvent)
|
||||||
|
}
|
||||||
|
}
|
||||||
for (i=0;i<movingSet.length();i++) {
|
for (i=0;i<movingSet.length();i++) {
|
||||||
var node = movingSet.get(i);
|
var node = movingSet.get(i);
|
||||||
delete node.ox;
|
delete node.ox;
|
||||||
@ -1893,7 +1916,16 @@ RED.view = (function() {
|
|||||||
if (mouse_mode === RED.state.MOVING || mouse_mode === RED.state.MOVING_ACTIVE) {
|
if (mouse_mode === RED.state.MOVING || mouse_mode === RED.state.MOVING_ACTIVE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mouse_mode === RED.state.IMPORT_DRAGGING) {
|
if (mouse_mode === RED.state.DETACHED_DRAGGING) {
|
||||||
|
for (var j=0;j<movingSet.length();j++) {
|
||||||
|
var n = movingSet.get(j);
|
||||||
|
n.n.x = n.ox;
|
||||||
|
n.n.y = n.oy;
|
||||||
|
}
|
||||||
|
clearSelection();
|
||||||
|
RED.history.pop();
|
||||||
|
mouse_mode = 0;
|
||||||
|
} else if (mouse_mode === RED.state.IMPORT_DRAGGING) {
|
||||||
clearSelection();
|
clearSelection();
|
||||||
RED.history.pop();
|
RED.history.pop();
|
||||||
mouse_mode = 0;
|
mouse_mode = 0;
|
||||||
@ -2133,7 +2165,7 @@ RED.view = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function deleteSelection() {
|
function deleteSelection(reconnectWires) {
|
||||||
if (mouse_mode === RED.state.SELECTING_NODE) {
|
if (mouse_mode === RED.state.SELECTING_NODE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2191,6 +2223,16 @@ RED.view = (function() {
|
|||||||
var removedSubflowInputs = [];
|
var removedSubflowInputs = [];
|
||||||
var removedSubflowStatus;
|
var removedSubflowStatus;
|
||||||
var subflowInstances = [];
|
var subflowInstances = [];
|
||||||
|
var historyEvents = [];
|
||||||
|
|
||||||
|
if (reconnectWires) {
|
||||||
|
var reconnectResult = RED.nodes.detachNodes(movingSet.nodes())
|
||||||
|
var addedLinks = reconnectResult.newLinks;
|
||||||
|
if (addedLinks.length > 0) {
|
||||||
|
historyEvents.push({ t:'add', links: addedLinks })
|
||||||
|
}
|
||||||
|
removedLinks = removedLinks.concat(reconnectResult.removedLinks)
|
||||||
|
}
|
||||||
|
|
||||||
var startDirty = RED.nodes.dirty();
|
var startDirty = RED.nodes.dirty();
|
||||||
var startChanged = false;
|
var startChanged = false;
|
||||||
@ -2281,7 +2323,6 @@ RED.view = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var linkRemoveHistoryEvents = [];
|
|
||||||
if (selectedLinks.length() > 0) {
|
if (selectedLinks.length() > 0) {
|
||||||
selectedLinks.forEach(function(link) {
|
selectedLinks.forEach(function(link) {
|
||||||
if (link.link) {
|
if (link.link) {
|
||||||
@ -2289,31 +2330,22 @@ RED.view = (function() {
|
|||||||
var targetId = link.target.id;
|
var targetId = link.target.id;
|
||||||
var sourceIdIndex = link.target.links.indexOf(sourceId);
|
var sourceIdIndex = link.target.links.indexOf(sourceId);
|
||||||
var targetIdIndex = link.source.links.indexOf(targetId);
|
var targetIdIndex = link.source.links.indexOf(targetId);
|
||||||
|
historyEvents.push({
|
||||||
linkRemoveHistoryEvents.push({
|
|
||||||
t:"multi",
|
|
||||||
events: [
|
|
||||||
{
|
|
||||||
t: "edit",
|
t: "edit",
|
||||||
node: link.source,
|
node: link.source,
|
||||||
changed: link.source.changed,
|
changed: link.source.changed,
|
||||||
changes: {
|
changes: {
|
||||||
links: $.extend(true,{},{v:link.source.links}).v
|
links: $.extend(true,{},{v:link.source.links}).v
|
||||||
}
|
}
|
||||||
},
|
})
|
||||||
{
|
historyEvents.push({
|
||||||
t: "edit",
|
t: "edit",
|
||||||
node: link.target,
|
node: link.target,
|
||||||
changed: link.target.changed,
|
changed: link.target.changed,
|
||||||
changes: {
|
changes: {
|
||||||
links: $.extend(true,{},{v:link.target.links}).v
|
links: $.extend(true,{},{v:link.target.links}).v
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
],
|
|
||||||
dirty:startDirty
|
|
||||||
})
|
})
|
||||||
|
|
||||||
link.source.changed = true;
|
link.source.changed = true;
|
||||||
link.target.changed = true;
|
link.target.changed = true;
|
||||||
link.target.links.splice(sourceIdIndex,1);
|
link.target.links.splice(sourceIdIndex,1);
|
||||||
@ -2344,11 +2376,11 @@ RED.view = (function() {
|
|||||||
if (removedSubflowStatus) {
|
if (removedSubflowStatus) {
|
||||||
historyEvent.subflow.status = removedSubflowStatus;
|
historyEvent.subflow.status = removedSubflowStatus;
|
||||||
}
|
}
|
||||||
if (linkRemoveHistoryEvents.length > 0) {
|
if (historyEvents.length > 0) {
|
||||||
linkRemoveHistoryEvents.unshift(historyEvent);
|
historyEvents.unshift(historyEvent);
|
||||||
RED.history.push({
|
RED.history.push({
|
||||||
t:"multi",
|
t:"multi",
|
||||||
events: linkRemoveHistoryEvents
|
events: historyEvents
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
RED.history.push(historyEvent);
|
RED.history.push(historyEvent);
|
||||||
@ -2431,6 +2463,28 @@ RED.view = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function detachSelectedNodes() {
|
||||||
|
var selection = RED.view.selection();
|
||||||
|
if (selection.nodes) {
|
||||||
|
const {newLinks, removedLinks} = RED.nodes.detachNodes(selection.nodes);
|
||||||
|
if (removedLinks.length || newLinks.length) {
|
||||||
|
RED.history.push({
|
||||||
|
t: "multi",
|
||||||
|
events: [
|
||||||
|
{ t:'delete', links: removedLinks },
|
||||||
|
{ t:'add', links: newLinks }
|
||||||
|
],
|
||||||
|
dirty: RED.nodes.dirty()
|
||||||
|
})
|
||||||
|
RED.nodes.dirty(true)
|
||||||
|
}
|
||||||
|
prepareDrag([selection.nodes[0].x,selection.nodes[0].y]);
|
||||||
|
mouse_mode = RED.state.DETACHED_DRAGGING;
|
||||||
|
RED.view.redraw(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function calculateTextWidth(str, className) {
|
function calculateTextWidth(str, className) {
|
||||||
var result = convertLineBreakCharacter(str);
|
var result = convertLineBreakCharacter(str);
|
||||||
var width = 0;
|
var width = 0;
|
||||||
@ -2956,11 +3010,14 @@ RED.view = (function() {
|
|||||||
msn.dx = msn.n.x-mouse[0];
|
msn.dx = msn.n.x-mouse[0];
|
||||||
msn.dy = msn.n.y-mouse[1];
|
msn.dy = msn.n.y-mouse[1];
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
mouse_offset = d3.mouse(document.body);
|
mouse_offset = d3.mouse(document.body);
|
||||||
if (isNaN(mouse_offset[0])) {
|
if (isNaN(mouse_offset[0])) {
|
||||||
mouse_offset = d3.touches(document.body)[0];
|
mouse_offset = d3.touches(document.body)[0];
|
||||||
}
|
}
|
||||||
|
} catch(err) {
|
||||||
|
mouse_offset = [0,0]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function nodeMouseUp(d) {
|
function nodeMouseUp(d) {
|
||||||
@ -3040,7 +3097,7 @@ RED.view = (function() {
|
|||||||
//var touch0 = d3.event;
|
//var touch0 = d3.event;
|
||||||
//var pos = [touch0.pageX,touch0.pageY];
|
//var pos = [touch0.pageX,touch0.pageY];
|
||||||
//RED.touch.radialMenu.show(d3.select(this),pos);
|
//RED.touch.radialMenu.show(d3.select(this),pos);
|
||||||
if (mouse_mode == RED.state.IMPORT_DRAGGING) {
|
if (mouse_mode == RED.state.IMPORT_DRAGGING || mouse_mode == RED.state.DETACHED_DRAGGING) {
|
||||||
var historyEvent = RED.history.peek();
|
var historyEvent = RED.history.peek();
|
||||||
if (activeSpliceLink) {
|
if (activeSpliceLink) {
|
||||||
// TODO: DRY - droppable/nodeMouseDown/canvasMouseUp
|
// TODO: DRY - droppable/nodeMouseDown/canvasMouseUp
|
||||||
@ -3078,6 +3135,18 @@ RED.view = (function() {
|
|||||||
activeHoverGroup = null;
|
activeHoverGroup = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mouse_mode == RED.state.DETACHED_DRAGGING) {
|
||||||
|
var ns = [];
|
||||||
|
for (var j=0;j<movingSet.length();j++) {
|
||||||
|
var n = movingSet.get(j);
|
||||||
|
if (n.ox !== n.n.x || n.oy !== n.n.y) {
|
||||||
|
ns.push({n:n.n,ox:n.ox,oy:n.oy,moved:n.n.moved});
|
||||||
|
n.n.dirty = true;
|
||||||
|
n.n.moved = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RED.history.replace({t:"multi",events:[historyEvent,{t:"move",nodes:ns}],dirty: historyEvent.dirty})
|
||||||
|
}
|
||||||
|
|
||||||
updateSelection();
|
updateSelection();
|
||||||
RED.nodes.dirty(true);
|
RED.nodes.dirty(true);
|
||||||
|
Loading…
Reference in New Issue
Block a user