mirror of https://github.com/node-red/node-red.git
218 lines
6.6 KiB
JavaScript
218 lines
6.6 KiB
JavaScript
|
/**
|
||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
**/
|
||
|
|
||
|
RED.group = (function() {
|
||
|
|
||
|
var _groupEditTemplate = '<script type="text/x-red" data-template-name="group">'+
|
||
|
'<div class="form-row">'+
|
||
|
'<label for="node-input-name" data-i18n="[append]editor:common.label.name"><i class="fa fa-tag"></i> </label>'+
|
||
|
'<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">'+
|
||
|
'</div>'+
|
||
|
|
||
|
'<div class="form-row">'+
|
||
|
'<label for="node-input-style-stroke" data-i18n="[append]editor:group.label.stroke">Stroke</label>'+
|
||
|
'<input type="text" id="node-input-style-stroke">'+
|
||
|
'</div>'+
|
||
|
|
||
|
'<div class="form-row">'+
|
||
|
'<label for="node-input-style-fill" data-i18n="[append]editor:group.label.fill">Fill</label>'+
|
||
|
'<input type="text" id="node-input-style-fill">'+
|
||
|
'</div>'+
|
||
|
|
||
|
'</script>';
|
||
|
|
||
|
var groupDef = {
|
||
|
defaults:{
|
||
|
name:{value:""},
|
||
|
style:{value:{}}
|
||
|
},
|
||
|
category: "config",
|
||
|
oneditprepare: function() {
|
||
|
var style = this.style || {};
|
||
|
$("#node-input-style-stroke").val(style.stroke || "#eeeeee")
|
||
|
$("#node-input-style-fill").val(style.fill || "none")
|
||
|
},
|
||
|
oneditresize: function(size) {
|
||
|
},
|
||
|
oneditsave: function() {
|
||
|
this.style.stroke = $("#node-input-style-stroke").val();
|
||
|
this.style.fill = $("#node-input-style-fill").val();
|
||
|
},
|
||
|
set:{
|
||
|
module: "node-red"
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function init() {
|
||
|
|
||
|
|
||
|
RED.actions.add("core:group-selection", function() { groupSelection() })
|
||
|
|
||
|
$(_groupEditTemplate).appendTo("#red-ui-editor-node-configs");
|
||
|
|
||
|
}
|
||
|
|
||
|
function groupSelection() {
|
||
|
var selection = RED.view.selection();
|
||
|
// var groupNodes = new Set();
|
||
|
//
|
||
|
// if (selection.groups) {
|
||
|
// selection.groups.forEach(function(g) {
|
||
|
// g.nodes.forEach()
|
||
|
// })
|
||
|
// }
|
||
|
//
|
||
|
// if (selection.nodes) {
|
||
|
//
|
||
|
// }
|
||
|
|
||
|
if (selection.nodes) {
|
||
|
var group = createGroup(selection.nodes);
|
||
|
if (group) {
|
||
|
RED.view.select({groups:[group]})
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
function createGroup(nodes) {
|
||
|
if (nodes.length === 0) {
|
||
|
return;
|
||
|
}
|
||
|
// nodes is an array
|
||
|
// each node must be on the same tab (z)
|
||
|
var group = {
|
||
|
id: RED.nodes.id(),
|
||
|
type: 'group',
|
||
|
nodes: [],
|
||
|
style: {
|
||
|
stroke: "#999",
|
||
|
fill: "none"
|
||
|
},
|
||
|
x: Number.POSITIVE_INFINITY,
|
||
|
y: Number.POSITIVE_INFINITY,
|
||
|
w: 0,
|
||
|
h: 0,
|
||
|
_def: RED.group.def
|
||
|
}
|
||
|
try {
|
||
|
addToGroup(group,nodes);
|
||
|
} catch(err) {
|
||
|
RED.notify(err,"error");
|
||
|
return;
|
||
|
}
|
||
|
group.z = nodes[0].z;
|
||
|
|
||
|
RED.nodes.addGroup(group);
|
||
|
return group;
|
||
|
}
|
||
|
|
||
|
function addToGroup(group,nodes) {
|
||
|
if (!Array.isArray(nodes)) {
|
||
|
nodes = [nodes];
|
||
|
}
|
||
|
var i,n,z;
|
||
|
var g;
|
||
|
// First pass - validate we can safely add these nodes to the group
|
||
|
for (i=0;i<nodes.length;i++) {
|
||
|
n = nodes[i]
|
||
|
if (!n.z) {
|
||
|
throw new Error("Cannot add node without a z property to a group")
|
||
|
}
|
||
|
if (!z) {
|
||
|
z = n.z;
|
||
|
} else if (z !== n.z) {
|
||
|
throw new Error("Cannot create group using nodes with different z properties")
|
||
|
}
|
||
|
if (n.g) {
|
||
|
// This is already in a group.
|
||
|
// - check they are all in the same group
|
||
|
if (!g) {
|
||
|
if (i!==0) {
|
||
|
// TODO: this might be ok when merging groups
|
||
|
throw new Error("Cannot create group using nodes from different groups")
|
||
|
}
|
||
|
g = n.g
|
||
|
}
|
||
|
}
|
||
|
if (g !== n.g) {
|
||
|
throw new Error("Cannot create group using nodes from different groups")
|
||
|
}
|
||
|
}
|
||
|
if (g) {
|
||
|
g = RED.nodes.group(g);
|
||
|
g.nodes.push(group);
|
||
|
group.g = g.id;
|
||
|
}
|
||
|
// Second pass - add them to the group
|
||
|
for (i=0;i<nodes.length;i++) {
|
||
|
n = nodes[i];
|
||
|
if (g && n.g === g.id) {
|
||
|
var ni = g.nodes.indexOf(n);
|
||
|
if (ni > -1) {
|
||
|
g.nodes.splice(ni,1)
|
||
|
}
|
||
|
}
|
||
|
n.g = group.id;
|
||
|
group.nodes.push(n);
|
||
|
group.x = Math.min(group.x,n.x-n.w/2-25-((n._def.button && n._def.align!=="right")?20:0));
|
||
|
group.y = Math.min(group.y,n.y-n.h/2-25);
|
||
|
group.w = Math.max(group.w,n.x+n.w/2+25+((n._def.button && n._def.align=="right")?20:0) - group.x),
|
||
|
group.h = Math.max(group.h,n.y+n.h/2+25-group.y);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function getNodes(group,recursive) {
|
||
|
var nodes = [];
|
||
|
group.nodes.forEach(function(n) {
|
||
|
if (!recursive || n.type !== 'group') {
|
||
|
nodes.push(n);
|
||
|
} else {
|
||
|
nodes = nodes.concat(getNodes(n,recursive))
|
||
|
}
|
||
|
})
|
||
|
return nodes;
|
||
|
}
|
||
|
|
||
|
function groupContains(group,item) {
|
||
|
if (item.g === group.id) {
|
||
|
return true;
|
||
|
}
|
||
|
for (var i=0;i<group.nodes.length;i++) {
|
||
|
if (group.nodes[i].type === "group") {
|
||
|
if (groupContains(group.nodes[i],item)) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
function getRootGroup(group) {
|
||
|
if (!group.g) {
|
||
|
return group;
|
||
|
}
|
||
|
return getRootGroup(RED.nodes.group(group.g))
|
||
|
}
|
||
|
|
||
|
|
||
|
return {
|
||
|
def: groupDef,
|
||
|
init: init,
|
||
|
createGroup: createGroup,
|
||
|
addToGroup: addToGroup,
|
||
|
getNodes: getNodes,
|
||
|
contains: groupContains
|
||
|
}
|
||
|
})();
|