From 0b39ef68d9cc3588207954352a0a464f87738d21 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Wed, 10 Mar 2021 14:04:47 +0000 Subject: [PATCH] Use cursor keys to change selection in workspace --- .../editor-client/src/js/keymap.json | 21 +- .../editor-client/src/js/ui/actionList.js | 5 +- .../editor-client/src/js/ui/clipboard.js | 6 +- .../editor-client/src/js/ui/keyboard.js | 6 +- .../editor-client/src/js/ui/search.js | 4 +- .../editor-client/src/js/ui/typeSearch.js | 15 +- .../editor-client/src/js/ui/view-tools.js | 244 ++++++++++++++++++ .../@node-red/editor-client/src/js/ui/view.js | 83 ++++-- .../editor-client/src/js/ui/workspaces.js | 42 ++- 9 files changed, 362 insertions(+), 64 deletions(-) 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 6ce03e65c..c323b3e64 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 @@ -38,13 +38,14 @@ "backspace": "core:delete-selection", "delete": "core:delete-selection", "enter": "core:edit-selected-node", - "ctrl-enter": "core:go-to-selected-subflow", + "ctrl-enter": "core:go-to-selection", "ctrl-c": "core:copy-selection-to-internal-clipboard", "ctrl-x": "core:cut-selection-to-internal-clipboard", "ctrl-v": "core:paste-from-internal-clipboard", "ctrl-z": "core:undo", "ctrl-y": "core:redo", "ctrl-a": "core:select-all-nodes", + "escape": "core:select-none", "alt-s u": "core:select-upstream-nodes", "alt-s d": "core:select-downstream-nodes", "alt-s c": "core:select-connected-nodes", @@ -57,21 +58,25 @@ "shift-d": "core:step-view-right", "shift-s": "core:step-view-down", "shift-a": "core:step-view-left", - "up": "core:move-selection-up", - "right": "core:move-selection-right", - "down": "core:move-selection-down", - "left": "core:move-selection-left", + "ctrl-up": "core:move-selection-up", + "ctrl-right": "core:move-selection-right", + "ctrl-down": "core:move-selection-down", + "ctrl-left": "core:move-selection-left", "shift-up": "core:step-selection-up", "shift-right": "core:step-selection-right", "shift-down": "core:step-selection-down", "shift-left": "core:step-selection-left", - "ctrl-shift-j": "core:show-previous-tab", - "ctrl-shift-k": "core:show-next-tab", + "ctrl-[": "core:show-previous-tab", + "ctrl-]": "core:show-next-tab", "ctrl-shift-left": "core:go-to-previous-location", "ctrl-shift-right": "core:go-to-next-location", "ctrl-shift-g": "core:group-selection", "ctrl-shift-u": "core:ungroup-selection", "ctrl-shift-c": "core:copy-group-style", - "ctrl-shift-v": "core:paste-group-style" + "ctrl-shift-v": "core:paste-group-style", + "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" } } diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/actionList.js b/packages/node_modules/@node-red/editor-client/src/js/ui/actionList.js index ac8a06813..a1ed26afb 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/actionList.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/actionList.js @@ -151,7 +151,6 @@ RED.actionList = (function() { } if (!visible) { previousActiveElement = document.activeElement; - RED.keyboard.add("*","escape",function(){hide()}); $("#red-ui-header-shade").show(); $("#red-ui-editor-shade").show(); $("#red-ui-palette-shade").show(); @@ -185,7 +184,6 @@ RED.actionList = (function() { function hide() { if (visible) { - RED.keyboard.remove("escape"); visible = false; $("#red-ui-header-shade").hide(); $("#red-ui-editor-shade").hide(); @@ -215,6 +213,9 @@ RED.actionList = (function() { RED.events.on("type-search:open",function() { disabled = true; }); RED.events.on("type-search:close",function() { disabled = false; }); + RED.keyboard.add("red-ui-actionList","escape",function(){hide()}); + + $("#red-ui-header-shade").on('mousedown',hide); $("#red-ui-editor-shade").on('mousedown',hide); $("#red-ui-palette-shade").on('mousedown',hide); diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/clipboard.js b/packages/node_modules/@node-red/editor-client/src/js/ui/clipboard.js index d66f2ae89..5b831a942 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/clipboard.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/clipboard.js @@ -889,7 +889,6 @@ RED.clipboard = (function() { function hideDropTarget() { $("#red-ui-drop-target").hide(); - RED.keyboard.remove("escape"); } function copyText(value,element,msg) { var truncated = false; @@ -1266,11 +1265,12 @@ RED.clipboard = (function() { $('

').appendTo('#red-ui-editor'); + RED.keyboard.add("#red-ui-drop-target", "escape" ,hideDropTarget); + $('#red-ui-workspace-chart').on("dragenter",function(event) { if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1 || $.inArray("Files",event.originalEvent.dataTransfer.types) != -1) { - $("#red-ui-drop-target").css({display:'table'}); - RED.keyboard.add("*", "escape" ,hideDropTarget); + $("#red-ui-drop-target").css({display:'table'}).focus(); } }); diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/keyboard.js b/packages/node_modules/@node-red/editor-client/src/js/ui/keyboard.js index cca1ed90e..2c81cfe63 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/keyboard.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/keyboard.js @@ -44,7 +44,11 @@ RED.keyboard = (function() { "/":191, "\\":220, "'":222, - "?":191 // <- QWERTY specific + "?":191, // <- QWERTY specific + "[": 219, + "]": 221, + "{": 219,// <- QWERTY specific + "}": 221 // <- QWERTY specific } var metaKeyCodes = { 16: true, diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/search.js b/packages/node_modules/@node-red/editor-client/src/js/ui/search.js index 1751f524e..02c7735a7 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/search.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/search.js @@ -357,7 +357,6 @@ RED.search = (function() { } if (!visible) { previousActiveElement = document.activeElement; - RED.keyboard.add("*","escape",function(){hide()}); $("#red-ui-header-shade").show(); $("#red-ui-editor-shade").show(); $("#red-ui-palette-shade").show(); @@ -377,7 +376,6 @@ RED.search = (function() { function hide() { if (visible) { - RED.keyboard.remove("escape"); visible = false; $("#red-ui-header-shade").hide(); $("#red-ui-editor-shade").hide(); @@ -429,7 +427,7 @@ RED.search = (function() { RED.events.on("actionList:open",function() { disabled = true; }); RED.events.on("actionList:close",function() { disabled = false; }); - + RED.keyboard.add("red-ui-search","escape",hide); $("#red-ui-header-shade").on('mousedown',hide); $("#red-ui-editor-shade").on('mousedown',hide); diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/typeSearch.js b/packages/node_modules/@node-red/editor-client/src/js/ui/typeSearch.js index a5e84e294..fbd5cdc32 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/typeSearch.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/typeSearch.js @@ -224,14 +224,14 @@ RED.typeSearch = (function() { } function show(opts) { if (!visible) { - RED.keyboard.add("*","escape",function(){ - hide(); - if (cancelCallback) { - cancelCallback(); - } - }); if (dialog === null) { createDialog(); + RED.keyboard.add("red-ui-type-search","escape",function(){ + hide(); + if (cancelCallback) { + cancelCallback(); + } + }); } visible = true; } else { @@ -266,11 +266,10 @@ RED.typeSearch = (function() { if (!opts.disableFocus) { searchInput.trigger("focus"); } - },100); + },200); } function hide(fast) { if (visible) { - RED.keyboard.remove("escape"); visible = false; if (dialog !== null) { searchResultsDiv.slideUp(fast?50:200,function() { 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 d169282ba..2d9a9bc45 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 @@ -201,6 +201,237 @@ RED.view.tools = (function() { } + function selectFirstNode() { + var canidates; + var origin = {x:0, y:0}; + + var activeGroup = RED.view.getActiveGroup(); + + if (!activeGroup) { + candidates = RED.view.getActiveNodes(); + } else { + candidates = RED.group.getNodes(activeGroup,false); + origin = activeGroup; + } + + var distances = []; + candidates.forEach(function(node) { + var deltaX = node.x - origin.x; + var deltaY = node.y - origin.x; + var delta = deltaY*deltaY + deltaX*deltaX; + distances.push({node: node, delta: delta}) + }); + if (distances.length > 0) { + distances.sort(function(A,B) { + return A.delta - B.delta + }) + var newNode = distances[0].node; + if (newNode) { + RED.view.select({nodes:[newNode]}); + RED.view.reveal(newNode.id,false); + } + } + } + + function gotoNextNode() { + var selection = RED.view.selection(); + if (selection.nodes && selection.nodes.length === 1) { + var origin = selection.nodes[0]; + var links = RED.nodes.filterLinks({source:origin}); + if (links.length > 0) { + links.sort(function(A,B) { + return Math.abs(A.target.y - origin.y) - Math.abs(B.target.y - origin.y) + }) + var newNode = links[0].target; + if (newNode) { + RED.view.select({nodes:[newNode]}); + RED.view.reveal(newNode.id,false); + } + } + } else if (RED.workspaces.selection().length === 0) { + selectFirstNode(); + } + } + function gotoPreviousNode() { + var selection = RED.view.selection(); + if (selection.nodes && selection.nodes.length === 1) { + var origin = selection.nodes[0]; + var links = RED.nodes.filterLinks({target:origin}); + if (links.length > 0) { + links.sort(function(A,B) { + return Math.abs(A.source.y - origin.y) - Math.abs(B.source.y - origin.y) + }) + var newNode = links[0].source; + if (newNode) { + RED.view.select({nodes:[newNode]}); + RED.view.reveal(newNode.id,false); + } + } + } else if (RED.workspaces.selection().length === 0) { + selectFirstNode(); + } + } + + function getChildren(node) { + return RED.nodes.filterLinks({source:node}).map(function(l) { return l.target}) + } + function getParents(node) { + return RED.nodes.filterLinks({target:node}).map(function(l) { return l.source}) + } + + function getSiblings(node) { + var siblings = new Set(); + var parents = getParents(node); + parents.forEach(function(p) { + getChildren(p).forEach(function(c) { siblings.add(c) }) + }); + var children = getChildren(node); + children.forEach(function(p) { + getParents(p).forEach(function(c) { siblings.add(c) }) + }); + siblings.delete(node); + return Array.from(siblings); + } + function gotoNextSibling() { + // 'next' defined as nearest on the y-axis below this node + var selection = RED.view.selection(); + if (selection.nodes && selection.nodes.length === 1) { + var origin = selection.nodes[0]; + var siblings = getSiblings(origin); + if (siblings.length > 0) { + siblings = siblings.filter(function(n) { return n.y > origin. y}) + siblings.sort(function(A,B) { + return Math.abs(A.y - origin.y) - Math.abs(B.y - origin.y) + }) + var newNode = siblings[0]; + if (newNode) { + RED.view.select({nodes:[newNode]}); + RED.view.reveal(newNode.id,false); + } + } + } else if (RED.workspaces.selection().length === 0) { + selectFirstNode(); + } + } + function gotoPreviousSibling() { + // 'next' defined as nearest on the y-axis above this node + var selection = RED.view.selection(); + if (selection.nodes && selection.nodes.length === 1) { + var origin = selection.nodes[0]; + var siblings = getSiblings(origin); + if (siblings.length > 0) { + siblings = siblings.filter(function(n) { return n.y < origin. y}) + siblings.sort(function(A,B) { + return Math.abs(A.y - origin.y) - Math.abs(B.y - origin.y) + }) + var newNode = siblings[0]; + if (newNode) { + RED.view.select({nodes:[newNode]}); + RED.view.reveal(newNode.id,false); + } + } + } else if (RED.workspaces.selection().length === 0) { + selectFirstNode(); + } + + } + + function addNode() { + var selection = RED.view.selection(); + if (selection.nodes && selection.nodes.length === 1 && selection.nodes[0].outputs > 0) { + var selectedNode = selection.nodes[0]; + RED.view.showQuickAddDialog([ + selectedNode.x + selectedNode.w + 50,selectedNode.y + ]) + } else { + RED.view.showQuickAddDialog(); + } + } + + + function gotoNearestNode(direction) { + var selection = RED.view.selection(); + if (selection.nodes && selection.nodes.length === 1) { + var origin = selection.nodes[0]; + + var candidates = RED.nodes.filterNodes({z:origin.z}); + candidates = candidates.concat(RED.view.getSubflowPorts()); + var distances = []; + candidates.forEach(function(node) { + if (node === origin) { + return; + } + var deltaX = node.x - origin.x; + var deltaY = node.y - origin.y; + var delta = deltaY*deltaY + deltaX*deltaX; + var angle = (180/Math.PI)*Math.atan2(deltaY,deltaX); + if (angle < 0) { angle += 360 } + if (angle > 360) { angle -= 360 } + + var weight; + + // 0 - right + // 270 - above + // 90 - below + // 180 - left + switch(direction) { + case 'up': if (angle < 210 || angle > 330) { return }; + weight = Math.max(Math.abs(270 - angle)/60, 0.2); + break; + case 'down': if (angle < 30 || angle > 150) { return }; + weight = Math.max(Math.abs(90 - angle)/60, 0.2); + break; + case 'left': if (angle < 140 || angle > 220) { return }; + weight = Math.max(Math.abs(180 - angle)/40, 0.1 ); + break; + case 'right': if (angle > 40 && angle < 320) { return }; + weight = Math.max(Math.abs(angle)/40, 0.1); + break; + } + weight = Math.max(weight,0.1); + distances.push({ + node: node, + d: delta, + w: weight, + delta: delta*weight + }) + }) + if (distances.length > 0) { + distances.sort(function(A,B) { + return A.delta - B.delta + }) + var newNode = distances[0].node; + if (newNode) { + RED.view.select({nodes:[newNode]}); + RED.view.reveal(newNode.id,false); + } + } + } else if (RED.workspaces.selection().length === 0) { + var candidates = RED.view.getActiveNodes(); + + var distances = []; + candidates.forEach(function(node) { + var deltaX = node.x; + var deltaY = node.y; + var delta = deltaY*deltaY + deltaX*deltaX; + distances.push({node: node, delta: delta}) + }); + if (distances.length > 0) { + distances.sort(function(A,B) { + return A.delta - B.delta + }) + var newNode = distances[0].node; + if (newNode) { + RED.view.select({nodes:[newNode]}); + RED.view.reveal(newNode.id,false); + } + } + } + + + } + + return { init: function() { RED.actions.add("core:show-selected-node-labels", function() { setSelectedNodeLabelState(true); }) @@ -231,6 +462,19 @@ RED.view.tools = (function() { RED.actions.add("core:select-connected-nodes", function() { selectConnected("all") }); RED.actions.add("core:select-downstream-nodes", function() { selectConnected("down") }); RED.actions.add("core:select-upstream-nodes", function() { selectConnected("up") }); + + + RED.actions.add("core:go-to-next-node", function() { gotoNextNode() }) + RED.actions.add("core:go-to-previous-node", function() { gotoPreviousNode() }) + RED.actions.add("core:go-to-next-sibling", function() { gotoNextSibling() }) + RED.actions.add("core:go-to-previous-sibling", function() { gotoPreviousSibling() }) + + + RED.actions.add("core:go-to-nearest-node-on-left", function() { gotoNearestNode('left')}) + 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:add-node", function() { addNode() }) }, /** * Aligns all selected nodes to the current grid diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js index cd756cff4..e19387a1e 100755 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js @@ -86,7 +86,7 @@ RED.view = (function() { var quickAddLink = null; var showAllLinkPorts = -1; var groupNodeSelectPrimed = false; - + var lastClickPosition = []; var selectNodesOptions; var clipboard = ""; @@ -503,10 +503,21 @@ RED.view = (function() { RED.actions.add("core:paste-from-internal-clipboard",function(){importNodes(clipboard,{generateIds: true});}); RED.actions.add("core:delete-selection",deleteSelection); RED.actions.add("core:edit-selected-node",editSelection); - RED.actions.add("core:go-to-selected-subflow",editSelectedSubflow); + RED.actions.add("core:go-to-selection",function() { + if (movingSet.length() > 0) { + var node = movingSet.get(0).n; + if (/^subflow:/.test(node.type)) { + RED.workspaces.show(node.type.substring(8)) + } else if (node.type === 'group') { + enterActiveGroup(node); + redraw(); + } + } + }); RED.actions.add("core:undo",RED.history.pop); RED.actions.add("core:redo",RED.history.redo); RED.actions.add("core:select-all-nodes",selectAll); + RED.actions.add("core:select-none", selectNone); RED.actions.add("core:zoom-in",zoomIn); RED.actions.add("core:zoom-out",zoomOut); RED.actions.add("core:zoom-reset",zoomZero); @@ -849,7 +860,7 @@ RED.view = (function() { if (drag_lines.length > 0) { clickedGroup = clickedGroup || RED.nodes.group(drag_lines[0].node.g) } - showQuickAddDialog(point, null, clickedGroup); + showQuickAddDialog({position:point, group:clickedGroup}); } } if (mouse_mode === 0 && !(d3.event.metaKey || d3.event.ctrlKey)) { @@ -870,7 +881,13 @@ RED.view = (function() { } } - function showQuickAddDialog(point, spliceLink, targetGroup, touchTrigger) { + function showQuickAddDialog(options) { + options = options || {}; + var point = options.position || lastClickPosition; + var spliceLink = options.splice; + var targetGroup = options.group; + var touchTrigger = options.touchTrigger; + if (targetGroup && !targetGroup.active) { selectGroup(targetGroup,false); enterActiveGroup(targetGroup); @@ -1523,6 +1540,7 @@ RED.view = (function() { } function canvasMouseUp() { + lastClickPosition = [d3.event.offsetX/scaleFactor,d3.event.offsetY/scaleFactor]; if (RED.view.DEBUG) { console.warn("canvasMouseUp", mouse_mode); } var i; var historyEvent; @@ -1767,7 +1785,18 @@ RED.view = (function() { redraw(); } - + function selectNone() { + if (mouse_mode === RED.state.IMPORT_DRAGGING) { + clearSelection(); + RED.history.pop(); + mouse_mode = 0; + } else if (activeGroup) { + exitActiveGroup() + } else { + clearSelection(); + } + redraw(); + } function selectAll() { if (mouse_mode === RED.state.SELECTING_NODE && selectNodesOptions.single) { return; @@ -2206,15 +2235,6 @@ RED.view = (function() { } } - function editSelectedSubflow() { - if (movingSet.length() > 0) { - var node = movingSet.get(0).n; - if (/^subflow:/.test(node.type)) { - RED.workspaces.show(node.type.substring(8)) - } - } - } - function copySelection() { if (mouse_mode === RED.state.SELECTING_NODE) { return; @@ -2887,7 +2907,6 @@ RED.view = (function() { //var pos = [touch0.pageX,touch0.pageY]; //RED.touch.radialMenu.show(d3.select(this),pos); if (mouse_mode == RED.state.IMPORT_DRAGGING) { - RED.keyboard.remove("escape"); var historyEvent = RED.history.peek(); if (activeSpliceLink) { // TODO: DRY - droppable/nodeMouseDown/canvasMouseUp @@ -3258,7 +3277,7 @@ RED.view = (function() { d3.select(this).classed("red-ui-flow-link-splice",true); var point = d3.mouse(this); var clickedGroup = getGroupAt(point[0],point[1]); - showQuickAddDialog(point, selected_link, clickedGroup); + showQuickAddDialog({position:point, splice:selected_link, group:clickedGroup}); } } function linkTouchStart(d) { @@ -3304,9 +3323,8 @@ RED.view = (function() { if (d3.event.button === 1) { return; } - if (mouse_mode == RED.state.IMPORT_DRAGGING) { - RED.keyboard.remove("escape"); - } else if (mouse_mode == RED.state.QUICK_JOINING) { + + if (mouse_mode == RED.state.QUICK_JOINING) { d3.event.stopPropagation(); return; } else if (mouse_mode === RED.state.SELECTING_NODE) { @@ -3513,7 +3531,10 @@ RED.view = (function() { options.push({name:"undo",disabled:(RED.history.depth() === 0),onselect:function() {RED.history.pop();}}); options.push({name:"add",onselect:function() { chartPos = chart.offset(); - showQuickAddDialog([pos[0]-chartPos.left+chart.scrollLeft(),pos[1]-chartPos.top+chart.scrollTop()],undefined,undefined,true) + showQuickAddDialog({ + position:[pos[0]-chartPos.left+chart.scrollLeft(),pos[1]-chartPos.top+chart.scrollTop()], + touchTrigger:true + }) }}); RED.touch.radialMenu.show(obj,pos,options); @@ -4805,12 +4826,7 @@ RED.view = (function() { } } - RED.keyboard.add("*","escape",function(){ - RED.keyboard.remove("escape"); - clearSelection(); - RED.history.pop(); - mouse_mode = 0; - }); + } var historyEvent = { @@ -5138,6 +5154,18 @@ RED.view = (function() { getActiveNodes: function() { return activeNodes; }, + getSubflowPorts: function() { + var result = []; + if (activeSubflow) { + var subflowOutputs = nodeLayer.selectAll(".red-ui-flow-subflow-port-output").data(activeSubflow.out,function(d,i){ return d.id;}); + subflowOutputs.each(function(d,i) { result.push(d) }) + var subflowInputs = nodeLayer.selectAll(".red-ui-flow-subflow-port-input").data(activeSubflow.in,function(d,i){ return d.id;}); + subflowInputs.each(function(d,i) { result.push(d) }) + var subflowStatus = nodeLayer.selectAll(".red-ui-flow-subflow-port-status").data(activeSubflow.status?[activeSubflow.status]:[],function(d,i){ return d.id;}); + subflowStatus.each(function(d,i) { result.push(d) }) + } + return result; + }, selectNodes: function(options) { $("#red-ui-workspace-tabs-shade").show(); $("#red-ui-palette-shade").show(); @@ -5213,6 +5241,7 @@ RED.view = (function() { clipboard: function() { return clipboard }, - redrawStatus: redrawStatus + redrawStatus: redrawStatus, + showQuickAddDialog:showQuickAddDialog }; })(); diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js b/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js index 7ff15d2ee..606149bd5 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js @@ -23,6 +23,16 @@ RED.workspaces = (function() { var viewStack = []; var viewStackPos = 0; + + function addToViewStack(id) { + if (viewStackPos !== viewStack.length) { + viewStack.splice(viewStackPos); + } + viewStack.push(id); + viewStackPos = viewStack.length; + // console.warn("addToViewStack",id,viewStack); + } + function addWorkspace(ws,skipHistoryEntry,targetIndex) { if (ws) { workspace_tabs.addTab(ws,targetIndex); @@ -248,11 +258,9 @@ RED.workspaces = (function() { RED.view.focus(); }, onclick: function(tab) { - if (viewStackPos !== viewStack.length) { - viewStack.splice(viewStackPos); + if (tab.id !== activeWorkspace) { + addToViewStack(activeWorkspace); } - viewStack.push(activeWorkspace); - viewStackPos = viewStack.length; RED.view.focus(); }, ondblclick: function(tab) { @@ -336,8 +344,20 @@ RED.workspaces = (function() { createWorkspaceTabs(); RED.events.on("sidebar:resize",workspace_tabs.resize); - RED.actions.add("core:show-next-tab",workspace_tabs.nextTab); - RED.actions.add("core:show-previous-tab",workspace_tabs.previousTab); + RED.actions.add("core:show-next-tab",function() { + var oldActive = activeWorkspace; + workspace_tabs.nextTab(); + if (oldActive !== activeWorkspace) { + addToViewStack(oldActive) + } + }); + RED.actions.add("core:show-previous-tab",function() { + var oldActive = activeWorkspace; + workspace_tabs.previousTab(); + if (oldActive !== activeWorkspace) { + addToViewStack(oldActive) + } + }); RED.menu.setAction('menu-item-workspace-delete',function() { deleteWorkspace(RED.nodes.workspace(activeWorkspace)); @@ -360,6 +380,8 @@ RED.workspaces = (function() { RED.actions.add("core:go-to-previous-location", function() { if (viewStackPos > 0) { if (viewStackPos === viewStack.length) { + // We're at the end of the stack. Remember the activeWorkspace + // so we can come back to it. viewStack.push(activeWorkspace); } RED.workspaces.show(viewStack[--viewStackPos],true); @@ -476,12 +498,8 @@ RED.workspaces = (function() { return; } } - if (!skipStack) { - if (viewStackPos !== viewStack.length) { - viewStack.splice(viewStackPos); - } - viewStack.push(activeWorkspace); - viewStackPos = viewStack.length; + if (!skipStack && activeWorkspace !== id) { + addToViewStack(activeWorkspace) } workspace_tabs.activateTab(id); },