mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
[outliner] Keep outliner selection in sync with workspace
This commit is contained in:
parent
f1bd3e1711
commit
fbd911ed27
@ -40,7 +40,8 @@
|
||||
* label: 'Local', // label for the item
|
||||
* sublabel: 'Local', // a sub-label for the item
|
||||
* icon: 'fa fa-rocket', // (optional) icon for the item
|
||||
* selected: true/false, // (optional) if present, display checkbox accordingly
|
||||
* checkbox: true/false, // (optional) if present, display checkbox accordingly
|
||||
* selected: true/false, // (optional) whether the item is selected or not
|
||||
* children: [] | function(done,item) // (optional) an array of child items, or a function
|
||||
* // that will call the `done` callback with an array
|
||||
* // of child items
|
||||
@ -163,6 +164,7 @@
|
||||
});
|
||||
this._data = [];
|
||||
this._items = {};
|
||||
this._selected = new Set();
|
||||
this._topList = $('<ol class="red-ui-treeList-list">').css({
|
||||
position:'absolute',
|
||||
top: 0,
|
||||
@ -318,6 +320,7 @@
|
||||
item.parent.children.splice(index,1)
|
||||
that._trigger("sort",null,item.parent);
|
||||
}
|
||||
delete item.treeList;
|
||||
delete(that._items[item.id]);
|
||||
}
|
||||
item.treeList.insertChildAt = function(newItem,position,select) {
|
||||
@ -564,7 +567,7 @@
|
||||
item.treeList.makeParent();
|
||||
}
|
||||
|
||||
if (item.hasOwnProperty('selected')) {
|
||||
if (item.checkbox) {
|
||||
var selectWrapper = $('<span class="red-ui-treeList-icon"></span>').appendTo(label);
|
||||
var cb = $('<input class="red-ui-treeList-checkbox" type="checkbox">').prop('checked',item.selected).appendTo(selectWrapper);
|
||||
label.toggleClass("selected",item.selected);
|
||||
@ -573,6 +576,11 @@
|
||||
});
|
||||
cb.on('change', function(e) {
|
||||
item.selected = this.checked;
|
||||
if (item.selected) {
|
||||
that._selected.add(item);
|
||||
} else {
|
||||
that._selected.delete(item);
|
||||
}
|
||||
label.toggleClass("selected",this.checked);
|
||||
that._trigger("select",e,item);
|
||||
})
|
||||
@ -590,9 +598,11 @@
|
||||
} else {
|
||||
label.on("click", function(e) {
|
||||
if (!that.options.multi) {
|
||||
that._topList.find(".selected").removeClass("selected");
|
||||
that.clearSelection();
|
||||
}
|
||||
label.addClass("selected");
|
||||
that._selected.add(item);
|
||||
|
||||
that._trigger("select",e,item)
|
||||
})
|
||||
label.on("dblclick", function(e) {
|
||||
@ -602,14 +612,21 @@
|
||||
})
|
||||
item.treeList.select = function(v) {
|
||||
if (!that.options.multi) {
|
||||
that._topList.find(".selected").removeClass("selected");
|
||||
that.clearSelection();
|
||||
}
|
||||
label.toggleClass("selected",v);
|
||||
if (v) {
|
||||
that._selected.add(item);
|
||||
that._trigger("select",null,item)
|
||||
} else {
|
||||
that._selected.delete(item);
|
||||
}
|
||||
that.reveal(item);
|
||||
}
|
||||
if (item.selected) {
|
||||
that._selected.add(item);
|
||||
}
|
||||
label.toggleClass("selected",!!item.selected);
|
||||
}
|
||||
if (item.icon) {
|
||||
if (typeof item.icon === "string") {
|
||||
@ -663,7 +680,7 @@
|
||||
return this._data;
|
||||
}
|
||||
},
|
||||
show: function(item) {
|
||||
show: function(item, done) {
|
||||
if (typeof item === "string") {
|
||||
item = this._items[item]
|
||||
}
|
||||
@ -684,6 +701,7 @@
|
||||
if (stack.length === 0) {
|
||||
setTimeout(function() {
|
||||
that.reveal(item);
|
||||
if (done) { done(); }
|
||||
},isOpening?200:0);
|
||||
} else {
|
||||
item.treeList.expand(handleStack)
|
||||
@ -710,36 +728,53 @@
|
||||
this._topList.parent().scrollTop(scrollTop+((itemOffset+2.5*itemHeight)-treeHeight));
|
||||
}
|
||||
},
|
||||
select: function(item, triggerEvent) {
|
||||
select: function(item, triggerEvent, deselectExisting) {
|
||||
var that = this;
|
||||
if (!this.options.multi && deselectExisting !== false) {
|
||||
this.clearSelection();
|
||||
}
|
||||
if (Array.isArray(item)) {
|
||||
item.forEach(function(i) {
|
||||
that.select(i,triggerEvent,false);
|
||||
})
|
||||
return;
|
||||
}
|
||||
if (typeof item === "string") {
|
||||
item = this._items[item]
|
||||
}
|
||||
if (!this.options.multi) {
|
||||
this._topList.find(".selected").removeClass("selected");
|
||||
}
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
this.show(item.id);
|
||||
// this.show(item.id);
|
||||
item.selected = true;
|
||||
this._selected.add(item);
|
||||
|
||||
if (item.treeList.label) {
|
||||
item.treeList.label.addClass("selected");
|
||||
}
|
||||
if (triggerEvent !== false) {
|
||||
this._trigger("select",null,item)
|
||||
}
|
||||
},
|
||||
clearSelection: function() {
|
||||
this._topList.find(".selected").removeClass("selected");
|
||||
this._selected.forEach(function(item) {
|
||||
item.selected = false;
|
||||
if (item.treeList.label) {
|
||||
item.treeList.label.removeClass("selected")
|
||||
}
|
||||
});
|
||||
this._selected.clear();
|
||||
},
|
||||
selected: function() {
|
||||
var s = this._topList.find(".selected");
|
||||
if (this.options.multi) {
|
||||
var res = [];
|
||||
s.each(function() {
|
||||
res.push($(this).parent().data('data'));
|
||||
var selected = [];
|
||||
this._selected.forEach(function(item) {
|
||||
selected.push(item);
|
||||
})
|
||||
return res;
|
||||
if (this.options.multi) {
|
||||
return selected;
|
||||
}
|
||||
if (s.length) {
|
||||
return s.parent().data('data');
|
||||
if (selected.length) {
|
||||
return selected[0]
|
||||
} else {
|
||||
// TODO: This may be a bug.. it causes the call to return itself
|
||||
// not undefined.
|
||||
|
@ -1092,6 +1092,7 @@ RED.editor = (function() {
|
||||
var defaultIcon;
|
||||
var nodeInfoEditor;
|
||||
var finishedBuilding = false;
|
||||
var skipInfoRefreshOnClose = false;
|
||||
|
||||
editStack.push(node);
|
||||
RED.view.state(RED.state.EDITING);
|
||||
@ -1532,9 +1533,6 @@ RED.editor = (function() {
|
||||
collapsible: true,
|
||||
menu: false
|
||||
});
|
||||
if (editing_node) {
|
||||
RED.sidebar.info.refresh(editing_node);
|
||||
}
|
||||
var ns;
|
||||
if (node._def.set.module === "node-red") {
|
||||
ns = "node-red";
|
||||
@ -1614,7 +1612,7 @@ RED.editor = (function() {
|
||||
if (RED.view.state() != RED.state.IMPORT_DRAGGING) {
|
||||
RED.view.state(RED.state.DEFAULT);
|
||||
}
|
||||
if (editing_node) {
|
||||
if (editing_node && !skipInfoRefreshOnClose) {
|
||||
RED.sidebar.info.refresh(editing_node);
|
||||
}
|
||||
RED.workspaces.refresh();
|
||||
@ -1642,6 +1640,7 @@ RED.editor = (function() {
|
||||
text: RED._("subflow.edit"),
|
||||
click: function() {
|
||||
RED.workspaces.show(id);
|
||||
skipInfoRefreshOnClose = true;
|
||||
$("#node-dialog-ok").trigger("click");
|
||||
}
|
||||
});
|
||||
|
@ -504,7 +504,9 @@ RED.group = (function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (g) {
|
||||
RED.events.emit("groups:change",group)
|
||||
}
|
||||
markDirty(group);
|
||||
}
|
||||
function removeFromGroup(group, nodes, reparent) {
|
||||
|
@ -59,7 +59,7 @@ RED.sidebar.help = (function() {
|
||||
panels = RED.panels.create({
|
||||
container: stackContainer
|
||||
})
|
||||
panels.ratio(0.5);
|
||||
panels.ratio(0.3);
|
||||
|
||||
helpSearch = $('<input type="text" data-i18n="[placeholder]sidebar.help.search">').appendTo(toolbar).searchBox({
|
||||
delay: 100,
|
||||
@ -255,6 +255,7 @@ RED.sidebar.help = (function() {
|
||||
if (ratio > 0.7) {
|
||||
panels.ratio(0.7)
|
||||
}
|
||||
treeList.treeList("show","node-type:"+nodeType)
|
||||
treeList.treeList("select","node-type:"+nodeType, false);
|
||||
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ RED.sidebar.info.outliner = (function() {
|
||||
}
|
||||
|
||||
function getNodeLabelText(n) {
|
||||
var label = n.name || n.id;
|
||||
var label = n.name || n.type+": "+n.id;
|
||||
if (n._def.label) {
|
||||
try {
|
||||
label = (typeof n._def.label === "function" ? n._def.label.call(n) : n._def.label)||"";
|
||||
@ -131,11 +131,11 @@ RED.sidebar.info.outliner = (function() {
|
||||
RED.view.clickNodeButton(n);
|
||||
})
|
||||
}
|
||||
$('<button type="button" class="red-ui-info-outline-item-control-reveal red-ui-button red-ui-button-small"><i class="fa fa-eye"></i></button>').appendTo(controls).on("click",function(evt) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
RED.view.reveal(n.id);
|
||||
})
|
||||
// $('<button type="button" class="red-ui-info-outline-item-control-reveal red-ui-button red-ui-button-small"><i class="fa fa-eye"></i></button>').appendTo(controls).on("click",function(evt) {
|
||||
// evt.preventDefault();
|
||||
// evt.stopPropagation();
|
||||
// RED.view.reveal(n.id);
|
||||
// })
|
||||
if (n.type !== 'group' && n.type !== 'subflow') {
|
||||
$('<button type="button" class="red-ui-info-outline-item-control-disable red-ui-button red-ui-button-small"><i class="fa fa-circle-thin"></i><i class="fa fa-ban"></i></button>').appendTo(controls).on("click",function(evt) {
|
||||
evt.preventDefault();
|
||||
@ -226,11 +226,16 @@ RED.sidebar.info.outliner = (function() {
|
||||
treeList = $("<div>").css({width: "100%"}).appendTo(container).treeList({
|
||||
data:getFlowData()
|
||||
})
|
||||
// treeList.on('treelistselect', function(e,item) {
|
||||
// console.log(item)
|
||||
// RED.view.reveal(item.id);
|
||||
// })
|
||||
// treeList.treeList('data',[ ... ] )
|
||||
treeList.on('treelistselect', function(e,item) {
|
||||
var node = RED.nodes.node(item.id) || RED.nodes.group(item.id);
|
||||
if (node) {
|
||||
if (node.type === 'group' || node._def.category !== "config") {
|
||||
RED.view.select({nodes:[node]})
|
||||
} else {
|
||||
RED.view.select({nodes:[]})
|
||||
}
|
||||
}
|
||||
})
|
||||
treeList.on('treelistconfirm', function(e,item) {
|
||||
var node = RED.nodes.node(item.id);
|
||||
if (node) {
|
||||
@ -276,7 +281,8 @@ RED.sidebar.info.outliner = (function() {
|
||||
element: getFlowLabel(ws),
|
||||
children:[getEmptyItem(ws.id)],
|
||||
deferBuild: true,
|
||||
icon: "red-ui-icons red-ui-icons-flow"
|
||||
icon: "red-ui-icons red-ui-icons-flow",
|
||||
gutter: getGutter(ws)
|
||||
}
|
||||
flowList.treeList.addChild(objects[ws.id])
|
||||
objects[ws.id].element.toggleClass("red-ui-info-outline-item-disabled", !!ws.disabled)
|
||||
@ -307,7 +313,8 @@ RED.sidebar.info.outliner = (function() {
|
||||
id: sf.id,
|
||||
element: getNodeLabel(sf),
|
||||
children:[getEmptyItem(sf.id)],
|
||||
deferBuild: true
|
||||
deferBuild: true,
|
||||
gutter: getGutter(sf)
|
||||
}
|
||||
subflowList.treeList.addChild(objects[sf.id])
|
||||
}
|
||||
@ -353,11 +360,20 @@ RED.sidebar.info.outliner = (function() {
|
||||
parent.treeList.addChild(getEmptyItem(parent.id));
|
||||
}
|
||||
}
|
||||
|
||||
function getGutter(n) {
|
||||
var span = $("<span>",{class:"red-ui-info-outline-gutter"});
|
||||
$('<button type="button" class="red-ui-info-outline-item-control-reveal red-ui-button red-ui-button-small"><i class="fa fa-search"></i></button>').appendTo(span).on("click",function(evt) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
RED.view.reveal(n.id);
|
||||
})
|
||||
return span;
|
||||
}
|
||||
function onNodeAdd(n) {
|
||||
objects[n.id] = {
|
||||
id: n.id,
|
||||
element: getNodeLabel(n)
|
||||
element: getNodeLabel(n),
|
||||
gutter: getGutter(n)
|
||||
}
|
||||
if (n.type === "group") {
|
||||
objects[n.id].children = [];
|
||||
@ -383,7 +399,7 @@ RED.sidebar.info.outliner = (function() {
|
||||
}
|
||||
|
||||
function onSelectionChanged(selection) {
|
||||
treeList.treeList('clearSelection');
|
||||
// treeList.treeList('clearSelection');
|
||||
}
|
||||
|
||||
return {
|
||||
@ -391,8 +407,20 @@ RED.sidebar.info.outliner = (function() {
|
||||
search: function(val) {
|
||||
searchInput.searchBox('value',val)
|
||||
},
|
||||
select: function(node) {
|
||||
if (node) {
|
||||
if (Array.isArray(node)) {
|
||||
treeList.treeList('select', node.map(function(n) { return objects[n.id] }), false)
|
||||
} else {
|
||||
treeList.treeList('select', objects[node.id], false)
|
||||
|
||||
}
|
||||
} else {
|
||||
treeList.treeList('clearSelection')
|
||||
}
|
||||
},
|
||||
reveal: function(node) {
|
||||
treeList.treeList('select', objects[node.id])
|
||||
treeList.treeList('show', objects[node.id])
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
@ -70,12 +70,12 @@ RED.sidebar.info = (function() {
|
||||
propertiesPanelHeaderHelp = $('<button class="red-ui-button red-ui-button-small"><i class="fa fa-book"></button>').css({
|
||||
position: 'absolute',
|
||||
top: '12px',
|
||||
right: '38px'
|
||||
right: '32px'
|
||||
}).on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
if (selectedObject) {
|
||||
RED.sidebar.help.show(selectedObject.type)
|
||||
RED.sidebar.help.show(selectedObject.type);
|
||||
}
|
||||
}).appendTo(propertiesPanelHeader);
|
||||
RED.popover.tooltip(propertiesPanelHeaderHelp,RED._("sidebar.help.showHelp"));
|
||||
@ -90,6 +90,7 @@ RED.sidebar.info = (function() {
|
||||
evt.stopPropagation();
|
||||
if (selectedObject) {
|
||||
RED.sidebar.info.outliner.reveal(selectedObject);
|
||||
RED.view.reveal(selectedObject.id);
|
||||
}
|
||||
}).appendTo(propertiesPanelHeader);
|
||||
RED.popover.tooltip(propertiesPanelHeaderReveal,RED._("sidebar.help.showInOutline"));
|
||||
@ -176,10 +177,12 @@ RED.sidebar.info = (function() {
|
||||
var subflowUserCount;
|
||||
|
||||
if (node === null) {
|
||||
RED.sidebar.info.outliner.select(null);
|
||||
return;
|
||||
} else if (Array.isArray(node)) {
|
||||
// Multiple things selected
|
||||
// - hide help and info sections
|
||||
RED.sidebar.info.outliner.select(node);
|
||||
|
||||
propertiesPanelHeaderIcon.empty();
|
||||
RED.utils.createNodeIcon({type:"_selection_"}).appendTo(propertiesPanelHeaderIcon);
|
||||
@ -226,6 +229,8 @@ RED.sidebar.info = (function() {
|
||||
} else {
|
||||
// A single 'thing' selected.
|
||||
|
||||
RED.sidebar.info.outliner.select(node);
|
||||
|
||||
// Check to see if this is a subflow or subflow instance
|
||||
var subflowRegex = /^subflow(:(.+))?$/.exec(node.type);
|
||||
if (subflowRegex) {
|
||||
@ -246,17 +251,30 @@ RED.sidebar.info = (function() {
|
||||
|
||||
propertiesPanelHeaderIcon.empty();
|
||||
RED.utils.createNodeIcon(node).appendTo(propertiesPanelHeaderIcon);
|
||||
propertiesPanelHeaderLabel.text(RED.utils.getNodeLabel(node, node.type+" "+node.id));
|
||||
propertiesPanelHeaderLabel.text(RED.utils.getNodeLabel(node, node.type+": "+node.id));
|
||||
propertiesPanelHeaderReveal.show();
|
||||
selectedObject = node;
|
||||
|
||||
propRow = $('<tr class="red-ui-help-info-row"><td></td><td></td></tr>').appendTo(tableBody);
|
||||
var objectType = "node";
|
||||
if (node.type === "subflow" || subflowRegex) {
|
||||
objectType = "subflow";
|
||||
} else if (node.type === "tab") {
|
||||
objectType = "flow";
|
||||
}else if (node.type === "group") {
|
||||
objectType = "group";
|
||||
}
|
||||
$(propRow.children()[0]).text(RED._("sidebar.info."+objectType))
|
||||
RED.utils.createObjectElement(node.id).appendTo(propRow.children()[1]);
|
||||
|
||||
if (node.type === "tab" || node.type === "subflow") {
|
||||
// If nothing is selected, but we're on a flow or subflow tab.
|
||||
propertiesPanelHeaderHelp.hide();
|
||||
|
||||
} else if (node.type === "group") {
|
||||
propertiesPanelHeaderHelp.hide();
|
||||
|
||||
propRow = $('<tr class="red-ui-help-info-row"><td>'+RED._("sidebar.info.group")+'</td><td></td></tr>').appendTo(tableBody);
|
||||
propRow = $('<tr class="red-ui-help-info-row"><td> </td><td></td></tr>').appendTo(tableBody);
|
||||
|
||||
var typeCounts = {
|
||||
nodes:0,
|
||||
@ -282,15 +300,6 @@ RED.sidebar.info = (function() {
|
||||
} else {
|
||||
propertiesPanelHeaderHelp.show();
|
||||
|
||||
propRow = $('<tr class="red-ui-help-info-row"><td></td><td></td></tr>').appendTo(tableBody);
|
||||
|
||||
if (!subflowRegex) {
|
||||
$(propRow.children()[0]).text(RED._("sidebar.info.node"))
|
||||
} else {
|
||||
$(propRow.children()[0]).text(RED._("sidebar.info.subflow"))
|
||||
}
|
||||
RED.utils.createObjectElement(node.id).appendTo(propRow.children()[1]);
|
||||
|
||||
if (!subflowRegex) {
|
||||
propRow = $('<tr class="red-ui-help-info-row"><td>'+RED._("sidebar.info.type")+'</td><td></td></tr>').appendTo(tableBody);
|
||||
$(propRow.children()[1]).text((node.type === "unknown")?node._orig.type:node.type);
|
||||
|
@ -4665,29 +4665,34 @@ if (DEBUG_EVENTS) { console.warn("nodeMouseDown", mouse_mode,d); }
|
||||
},
|
||||
getGroupAtPoint: getGroupAt,
|
||||
getActiveGroup: function() { return activeGroup },
|
||||
reveal: function(id) {
|
||||
reveal: function(id,triggerHighlight) {
|
||||
if (RED.nodes.workspace(id) || RED.nodes.subflow(id)) {
|
||||
RED.workspaces.show(id);
|
||||
} else {
|
||||
var node = RED.nodes.node(id) || RED.nodes.group(id);
|
||||
if (node) {
|
||||
if (node.z && (node.type === "group" || node._def.category !== 'config')) {
|
||||
node.highlighted = true;
|
||||
node.dirty = true;
|
||||
RED.workspaces.show(node.z);
|
||||
|
||||
var screenSize = [chart.width()/scaleFactor,chart.height()/scaleFactor];
|
||||
var scrollPos = [chart.scrollLeft()/scaleFactor,chart.scrollTop()/scaleFactor];
|
||||
|
||||
if (node.x < scrollPos[0] || node.y < scrollPos[1] || node.x > screenSize[0]+scrollPos[0] || node.y > screenSize[1]+scrollPos[1]) {
|
||||
var deltaX = '-='+(((scrollPos[0] - node.x) + screenSize[0]/2)*scaleFactor);
|
||||
var deltaY = '-='+(((scrollPos[1] - node.y) + screenSize[1]/2)*scaleFactor);
|
||||
var cx = node.x;
|
||||
var cy = node.y;
|
||||
if (node.type === "group") {
|
||||
cx += node.w/2;
|
||||
cy += node.h/2;
|
||||
}
|
||||
if (cx < scrollPos[0] || cy < scrollPos[1] || cx > screenSize[0]+scrollPos[0] || cy > screenSize[1]+scrollPos[1]) {
|
||||
var deltaX = '-='+(((scrollPos[0] - cx) + screenSize[0]/2)*scaleFactor);
|
||||
var deltaY = '-='+(((scrollPos[1] - cy) + screenSize[1]/2)*scaleFactor);
|
||||
chart.animate({
|
||||
scrollLeft: deltaX,
|
||||
scrollTop: deltaY
|
||||
},200);
|
||||
}
|
||||
|
||||
if (triggerHighlight !== false) {
|
||||
node.highlighted = true;
|
||||
if (!node._flashing) {
|
||||
node._flashing = true;
|
||||
var flash = 22;
|
||||
@ -4705,6 +4710,7 @@ if (DEBUG_EVENTS) { console.warn("nodeMouseDown", mouse_mode,d); }
|
||||
}
|
||||
flashFunc();
|
||||
}
|
||||
}
|
||||
} else if (node._def.category === 'config') {
|
||||
RED.sidebar.config.show(id);
|
||||
}
|
||||
|
@ -387,7 +387,7 @@ RED.workspaces = (function() {
|
||||
RED.nodes.dirty(true);
|
||||
RED.sidebar.config.refresh();
|
||||
var selection = RED.view.selection();
|
||||
if (!selection.nodes && !selection.links) {
|
||||
if (!selection.nodes && !selection.links && workspace.id === activeWorkspace) {
|
||||
RED.sidebar.info.refresh(workspace);
|
||||
}
|
||||
if (changes.hasOwnProperty('disabled')) {
|
||||
|
@ -391,7 +391,15 @@ div.red-ui-info-table {
|
||||
display: inline-block;
|
||||
width: 23px;
|
||||
}
|
||||
|
||||
.red-ui-info-outline-gutter {
|
||||
display:none;
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
.red-ui-treeList-label:hover & {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
.red-ui-info-outline-item-controls {
|
||||
position: absolute;
|
||||
top:0;
|
||||
|
Loading…
Reference in New Issue
Block a user