mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	[groups] Support nested groups in editor
This commit is contained in:
		
							
								
								
									
										217
									
								
								packages/node_modules/@node-red/editor-client/src/js/ui/group.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										217
									
								
								packages/node_modules/@node-red/editor-client/src/js/ui/group.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,217 @@ | ||||
| /** | ||||
|  * 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 | ||||
|     } | ||||
| })(); | ||||
| @@ -1122,18 +1122,19 @@ if (DEBUG_EVENTS) { console.warn("canvasMouseDown", mouse_mode); } | ||||
|         } | ||||
|  | ||||
|         var mousePos; | ||||
|         if (mouse_mode === RED.state.GROUP_RESIZE) { | ||||
|             mousePos = mouse_position; | ||||
|             var nx = mousePos[0] + mousedown_group.dx; | ||||
|             var ny = mousePos[1] + mousedown_group.dy; | ||||
|             switch(mousedown_group.activeHandle) { | ||||
|                 case 0: mousedown_group.pos.x0 = nx; mousedown_group.pos.y0 = ny; break; | ||||
|                 case 1: mousedown_group.pos.x1 = nx; mousedown_group.pos.y0 = ny; break; | ||||
|                 case 2: mousedown_group.pos.x1 = nx; mousedown_group.pos.y1 = ny; break; | ||||
|                 case 3: mousedown_group.pos.x0 = nx; mousedown_group.pos.y1 = ny; break; | ||||
|             } | ||||
|             mousedown_group.dirty = true; | ||||
|         } else if (mouse_mode == RED.state.JOINING || mouse_mode === RED.state.QUICK_JOINING) { | ||||
|         // if (mouse_mode === RED.state.GROUP_RESIZE) { | ||||
|         //     mousePos = mouse_position; | ||||
|         //     var nx = mousePos[0] + mousedown_group.dx; | ||||
|         //     var ny = mousePos[1] + mousedown_group.dy; | ||||
|         //     switch(mousedown_group.activeHandle) { | ||||
|         //         case 0: mousedown_group.pos.x0 = nx; mousedown_group.pos.y0 = ny; break; | ||||
|         //         case 1: mousedown_group.pos.x1 = nx; mousedown_group.pos.y0 = ny; break; | ||||
|         //         case 2: mousedown_group.pos.x1 = nx; mousedown_group.pos.y1 = ny; break; | ||||
|         //         case 3: mousedown_group.pos.x0 = nx; mousedown_group.pos.y1 = ny; break; | ||||
|         //     } | ||||
|         //     mousedown_group.dirty = true; | ||||
|         // } | ||||
|         if (mouse_mode == RED.state.JOINING || mouse_mode === RED.state.QUICK_JOINING) { | ||||
|             // update drag line | ||||
|             if (drag_lines.length === 0 && mousedown_port_type !== null) { | ||||
|                 if (d3.event.shiftKey) { | ||||
| @@ -1253,13 +1254,11 @@ if (DEBUG_EVENTS) { console.warn("canvasMouseDown", mouse_mode); } | ||||
|                     node.n.y -= (maxY - space_height); | ||||
|                 } | ||||
|             } | ||||
|             if (mousedown_group) { | ||||
|                 mousedown_group.pos.x0 = mousePos[0] + mousedown_group.dx0; | ||||
|                 mousedown_group.pos.y0 = mousePos[1] + mousedown_group.dy0; | ||||
|                 mousedown_group.pos.x1 = mousePos[0] + mousedown_group.dx1; | ||||
|                 mousedown_group.pos.y1 = mousePos[1] + mousedown_group.dy1; | ||||
|                 mousedown_group.dirty = true; | ||||
|             } | ||||
|             // if (mousedown_group) { | ||||
|             //     mousedown_group.x = mousePos[0] + mousedown_group.dx; | ||||
|             //     mousedown_group.y = mousePos[1] + mousedown_group.dy; | ||||
|             //     mousedown_group.dirty = true; | ||||
|             // } | ||||
|             if (snapGrid != d3.event.shiftKey && moving_set.length > 0) { | ||||
|                 var gridOffset = [0,0]; | ||||
|                 node = moving_set[0]; | ||||
| @@ -1327,20 +1326,15 @@ if (DEBUG_EVENTS) { console.warn("canvasMouseDown", mouse_mode); } | ||||
|                 if (!node.n.g && activeGroups) { | ||||
|                     if (!groupHoverTimer) { | ||||
|                         groupHoverTimer = setTimeout(function() { | ||||
|                             activeHoverGroup = null; | ||||
|                             activeHoverGroup = getGroupAt(node.n.x,node.n.y); | ||||
|                             for (var i=0;i<activeGroups.length;i++) { | ||||
|                                 var g = activeGroups[i]; | ||||
|                                 if ( !activeHoverGroup && | ||||
|                                     node.n.x >= g.pos.x0 && node.n.x <= g.pos.x1 && | ||||
|                                     node.n.y >= g.pos.y0 && node.n.y <= g.pos.y1 | ||||
|                                 ) { | ||||
|                                     g.dirty = !g.hovered; | ||||
|                                 if (g === activeHoverGroup) { | ||||
|                                     g.hovered = true; | ||||
|                                     activeHoverGroup = g; | ||||
|                                 } else { | ||||
|                                     // Mark dirty if it is selected | ||||
|                                     g.dirty = g.hovered; | ||||
|                                     g.dirty = true; | ||||
|                                 } else if (g.hovered) { | ||||
|                                     g.hovered = false; | ||||
|                                     g.dirty = true; | ||||
|                                 } | ||||
|                             } | ||||
|                             groupHoverTimer = null; | ||||
| @@ -1972,7 +1966,7 @@ if (DEBUG_EVENTS) { console.warn("clearSelection", mouse_mode); } | ||||
|             RED.notify(RED._("clipboard.nodeCopied",{count:nns.length}),{id:"clipboard"}); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|  | ||||
|     function calculateTextWidth(str, className, offset) { | ||||
|         var result=convertLineBreakCharacter(str); | ||||
|         var width = 0; | ||||
| @@ -2714,11 +2708,12 @@ if (DEBUG_EVENTS) { console.warn("nodeMouseDown", mouse_mode,d); } | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     function groupMouseDown(g) { | ||||
|         var mouse = d3.touches(this.parentNode)[0]||d3.mouse(this.parentNode); | ||||
|         if (! (mouse[0] < g.pos.x0+10 || mouse[0] > g.pos.x1-10 || mouse[1] < g.pos.y0+10 || mouse[1] > g.pos.y1-10) ) { | ||||
|             return | ||||
|         } | ||||
|         // if (! (mouse[0] < g.x+10 || mouse[0] > g.x+g.w-10 || mouse[1] < g.y+10 || mouse[1] > g.y+g.h-10) ) { | ||||
|         //     return | ||||
|         // } | ||||
|  | ||||
|         focusView(); | ||||
|         if (d3.event.button === 1) { | ||||
| @@ -2768,10 +2763,8 @@ if (DEBUG_EVENTS) { console.warn("nodeMouseDown", mouse_mode,d); } | ||||
|             if (d3.event.button != 2) { | ||||
|                 var d = g.nodes[0]; | ||||
|                 prepareDrag(mouse); | ||||
|                 mousedown_group.dx0 = mousedown_group.pos.x0 - mouse[0]; | ||||
|                 mousedown_group.dy0 = mousedown_group.pos.y0 - mouse[1]; | ||||
|                 mousedown_group.dx1 = mousedown_group.pos.x1 - mouse[0]; | ||||
|                 mousedown_group.dy1 = mousedown_group.pos.y1 - mouse[1]; | ||||
|                 mousedown_group.dx = mousedown_group.x - mouse[0]; | ||||
|                 mousedown_group.dy = mousedown_group.y - mouse[1]; | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -2787,7 +2780,8 @@ if (DEBUG_EVENTS) { console.warn("nodeMouseDown", mouse_mode,d); } | ||||
|         } | ||||
|         if (includeNodes) { | ||||
|             var currentSet = new Set(moving_set.map(function(n) { return n.n })); | ||||
|             g.nodes.forEach(function(n) { | ||||
|             var allNodes = RED.group.getNodes(g,true); | ||||
|             allNodes.forEach(function(n) { | ||||
|                 if (!currentSet.has(n)) { | ||||
|                     moving_set.push({n:n}) | ||||
|                     // n.selected = true; | ||||
| @@ -2820,48 +2814,62 @@ if (DEBUG_EVENTS) { console.warn("nodeMouseDown", mouse_mode,d); } | ||||
|         } | ||||
|     } | ||||
|     function getGroupAt(x,y) { | ||||
|         var candidateGroups = {}; | ||||
|         for (var i=0;i<activeGroups.length;i++) { | ||||
|             var g = activeGroups[i]; | ||||
|             if (x >= g.pos.x0 && x <= g.pos.x1 && y >= g.pos.y0 && y <= g.pos.y1) { | ||||
|                 return g; | ||||
|             if (x >= g.x && x <= g.x + g.w && y >= g.y && y <= g.y + g.h) { | ||||
|                 candidateGroups[g.id] = g; | ||||
|             } | ||||
|         } | ||||
|         return null; | ||||
|         var ids = Object.keys(candidateGroups); | ||||
|         if (ids.length > 1) { | ||||
|             ids.forEach(function(id) { | ||||
|                 if (candidateGroups[id] && candidateGroups[id].g) { | ||||
|                     delete candidateGroups[candidateGroups[id].g] | ||||
|                 } | ||||
|             }) | ||||
|             ids = Object.keys(candidateGroups); | ||||
|         } | ||||
|         if (ids.length === 0) { | ||||
|             return null; | ||||
|         } else { | ||||
|             return candidateGroups[ids[0]] | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function groupHandleMouseDown(group, groupEl, handle,handleIndex) { | ||||
|         d3.event.stopPropagation(); | ||||
|         console.log("GHANDLE MD"); | ||||
|         if (d3.event.button != 2) { | ||||
|             mousedown_group = group; | ||||
|             group.activeHandle = handleIndex; | ||||
|             var mouse = d3.touches(handle.parentNode.parentNode)[0]||d3.mouse(handle.parentNode.parentNode); | ||||
|             switch(handleIndex) { | ||||
|                 case 0: group.ox = group.pos.x0; group.oy = group.pos.y0; break; | ||||
|                 case 1: group.ox = group.pos.x1; group.oy = group.pos.y0; break; | ||||
|                 case 2: group.ox = group.pos.x1; group.oy = group.pos.y1; break; | ||||
|                 case 3: group.ox = group.pos.x0; group.oy = group.pos.y1; break; | ||||
|             } | ||||
|             group.dx = group.ox - mouse[0]; | ||||
|             group.dy = group.oy - mouse[1]; | ||||
|             console.log("START",group.ox, group.oy); | ||||
|             mouse_offset = d3.mouse(document.body); | ||||
|             if (isNaN(mouse_offset[0])) { | ||||
|                 mouse_offset = d3.touches(document.body)[0]; | ||||
|             } | ||||
|             mouse_mode = RED.state.GROUP_RESIZE; | ||||
|         } | ||||
|     } | ||||
|     function groupHandleMouseUp(group,groupEl,handle,handleIndex) { | ||||
|         console.log("GHANDLE MU"); | ||||
|         d3.event.stopPropagation(); | ||||
|         delete group.ox; | ||||
|         delete group.oy; | ||||
|         delete group.dx; | ||||
|         delete group.dy; | ||||
|         resetMouseVars(); | ||||
|         mouse_mode = RED.state.DEFAULT; | ||||
|     } | ||||
|     // function groupHandleMouseDown(group, groupEl, handle,handleIndex) { | ||||
|     //     d3.event.stopPropagation(); | ||||
|     //     console.log("GHANDLE MD"); | ||||
|     //     if (d3.event.button != 2) { | ||||
|     //         mousedown_group = group; | ||||
|     //         group.activeHandle = handleIndex; | ||||
|     //         var mouse = d3.touches(handle.parentNode.parentNode)[0]||d3.mouse(handle.parentNode.parentNode); | ||||
|     //         switch(handleIndex) { | ||||
|     //             case 0: group.ox = group.pos.x0; group.oy = group.pos.y0; break; | ||||
|     //             case 1: group.ox = group.pos.x1; group.oy = group.pos.y0; break; | ||||
|     //             case 2: group.ox = group.pos.x1; group.oy = group.pos.y1; break; | ||||
|     //             case 3: group.ox = group.pos.x0; group.oy = group.pos.y1; break; | ||||
|     //         } | ||||
|     //         group.dx = group.ox - mouse[0]; | ||||
|     //         group.dy = group.oy - mouse[1]; | ||||
|     //         console.log("START",group.ox, group.oy); | ||||
|     //         mouse_offset = d3.mouse(document.body); | ||||
|     //         if (isNaN(mouse_offset[0])) { | ||||
|     //             mouse_offset = d3.touches(document.body)[0]; | ||||
|     //         } | ||||
|     //         mouse_mode = RED.state.GROUP_RESIZE; | ||||
|     //     } | ||||
|     // } | ||||
|     // function groupHandleMouseUp(group,groupEl,handle,handleIndex) { | ||||
|     //     console.log("GHANDLE MU"); | ||||
|     //     d3.event.stopPropagation(); | ||||
|     //     delete group.ox; | ||||
|     //     delete group.oy; | ||||
|     //     delete group.dx; | ||||
|     //     delete group.dy; | ||||
|     //     resetMouseVars(); | ||||
|     //     mouse_mode = RED.state.DEFAULT; | ||||
|     // } | ||||
|  | ||||
|     function isButtonEnabled(d) { | ||||
|         var buttonEnabled = true; | ||||
| @@ -3712,18 +3720,19 @@ if (DEBUG_EVENTS) { console.warn("nodeMouseDown", mouse_mode,d); } | ||||
|                         } | ||||
|  | ||||
|                         d.dirty = false; | ||||
|  | ||||
|                         if (d.g) { | ||||
|                             if (!dirtyGroups[d.g]) { | ||||
|                                 dirtyGroups[d.g] = RED.nodes.group(d.g); | ||||
|                             } | ||||
|                             var group = dirtyGroups[d.g]; | ||||
|                             group.pos = { | ||||
|                                 x0: Math.min(group.pos.x0,d.x-d.w/2-25-((d._def.button && d._def.align!=="right")?20:0)), | ||||
|                                 y0: Math.min(group.pos.y0,d.y-d.h/2-25), | ||||
|                                 x1: Math.max(group.pos.x1,d.x+d.w/2+25+((d._def.button && d._def.align=="right")?20:0)), | ||||
|                                 y1: Math.max(group.pos.y1,d.y+d.h/2+25) | ||||
|                                 var gg = d.g; | ||||
|                                 while (gg && !dirtyGroups[gg]) { | ||||
|                                     dirtyGroups[gg] = RED.nodes.group(gg); | ||||
|                                     gg = dirtyGroups[gg].g; | ||||
|                                 } | ||||
|                             } | ||||
|                         //     var group = dirtyGroups[d.g]; | ||||
|                         //     group.x = Math.min(group.x,d.x-d.w/2-25-((d._def.button && d._def.align!=="right")?20:0)); | ||||
|                         //     group.y = Math.min(group.y,d.y-d.h/2-25), | ||||
|                         //     group.w = Math.max(group.w, d.x+d.w/2+25+((d._def.button && d._def.align=="right")?20:0) - group.x), | ||||
|                         //     group.h = Math.max(group.h, d.y+d.h/2+25 - group.y) | ||||
|                         } | ||||
|                     } | ||||
|             }); | ||||
| @@ -3981,20 +3990,21 @@ if (DEBUG_EVENTS) { console.warn("nodeMouseDown", mouse_mode,d); } | ||||
|                     .attr('rx',1).attr('ry',1).style({ | ||||
|                         "fill":"none", | ||||
|                         "stroke": "#ff7f0e", | ||||
|                         "pointer-events": "stroke", | ||||
|                         "stroke-opacity": 0, | ||||
|                         "stroke-width": 15 | ||||
|                     }) | ||||
|  | ||||
|                 g.append('rect').classed("red-ui-flow-group-body",true) | ||||
|                     .attr('rx',1).attr('ry',1).style({ | ||||
|                         "pointer-events": "none", | ||||
|                         "fill":d.fill||"none", | ||||
|                         "stroke": d.stroke||"none", | ||||
|                         "stroke-width": 2 | ||||
|                     }) | ||||
|  | ||||
|  | ||||
|                 d.dirty = true; | ||||
|                 g.on("mousedown",groupMouseDown).on("mouseup",groupMouseUp) | ||||
|  | ||||
|                 d.dirty = true; | ||||
|             }); | ||||
|             group.each(function(d,i) { | ||||
|                 if (d.dirty || dirtyGroups[d.id]) { | ||||
| @@ -4004,26 +4014,33 @@ if (DEBUG_EVENTS) { console.warn("nodeMouseDown", mouse_mode,d); } | ||||
|                     var maxX = 0; | ||||
|                     var maxY = 0; | ||||
|                     d.nodes.forEach(function(n) { | ||||
|                         minX = Math.min(minX,n.x-n.w/2-25-((n._def.button && n._def.align!=="right")?20:0)); | ||||
|                         minY = Math.min(minY,n.y-n.h/2-25); | ||||
|                         maxX = Math.max(maxX,n.x+n.w/2+25+((n._def.button && n._def.align=="right")?20:0)); | ||||
|                         maxY = Math.max(maxY,n.y+n.h/2+25); | ||||
|                         if (n.type !== "group") { | ||||
|                             minX = Math.min(minX,n.x-n.w/2-25-((n._def.button && n._def.align!=="right")?20:0)); | ||||
|                             minY = Math.min(minY,n.y-n.h/2-25); | ||||
|                             maxX = Math.max(maxX,n.x+n.w/2+25+((n._def.button && n._def.align=="right")?20:0)); | ||||
|                             maxY = Math.max(maxY,n.y+n.h/2+25); | ||||
|                         } else { | ||||
|                             minX = Math.min(minX,n.x-25) | ||||
|                             minY = Math.min(minY,n.y-25) | ||||
|                             maxX = Math.max(maxX,n.x+n.w+25) | ||||
|                             maxY = Math.max(maxY,n.y+n.h+25) | ||||
|                         } | ||||
|                     }); | ||||
|  | ||||
|                     d.pos = { | ||||
|                         x0: minX, y0: minY, | ||||
|                         x1: maxX, y1: maxY | ||||
|                     } | ||||
|                     d.x = minX; | ||||
|                     d.y = minY; | ||||
|                     d.w = maxX - minX; | ||||
|                     d.h = maxY - minY; | ||||
|  | ||||
|                     g.attr("transform","translate("+d.pos.x0+","+d.pos.y0+")"); | ||||
|                     g.attr("transform","translate("+d.x+","+d.y+")"); | ||||
|                     g.selectAll(".red-ui-flow-group-outline") | ||||
|                         .attr("width",d.pos.x1-d.pos.x0) | ||||
|                         .attr("height",d.pos.y1-d.pos.y0) | ||||
|                         .attr("width",d.w) | ||||
|                         .attr("height",d.h) | ||||
|                         .style("stroke-opacity",function(d) { if (d.selected) { return 0.3 } return 0}); | ||||
|  | ||||
|                     g.selectAll(".red-ui-flow-group-body") | ||||
|                         .attr("width",d.pos.x1-d.pos.x0) | ||||
|                         .attr("height",d.pos.y1-d.pos.y0) | ||||
|                         .attr("width",d.w) | ||||
|                         .attr("height",d.h) | ||||
|                         .style("stroke",function(d) { /*if (d.selected) { return "#ff7f0e" } */return d.style.stroke || "none"}) | ||||
|                         .style("stroke-dasharray", function(d) { return (d.active||d.hovered)?"10 4":"none"}) | ||||
|                         .style("fill", function(d) { return d.style.fill || "none"}) | ||||
| @@ -4338,16 +4355,34 @@ if (DEBUG_EVENTS) { console.warn("nodeMouseDown", mouse_mode,d); } | ||||
|         }, | ||||
|         selection: function() { | ||||
|             var selection = {}; | ||||
|  | ||||
|             var allNodes = new Set(); | ||||
|  | ||||
|             if (moving_set.length > 0) { | ||||
|                 selection.nodes = moving_set.map(function(n) { return n.n;}); | ||||
|                 moving_set.forEach(function(n) { | ||||
|                     allNodes.add(n.n); | ||||
|                 }); | ||||
|             } | ||||
|             var selectedGroups =  activeGroups.filter(function(g) { return g.selected }); | ||||
|             if (selectedGroups.length > 0) { | ||||
|                 if (selectedGroups.length === 1 && selectedGroups[0].active) { | ||||
|                     // Let nodes be nodes | ||||
|                 } else { | ||||
|                     selectedGroups.forEach(function(g) { | ||||
|                         var groupNodes = RED.group.getNodes(g,true); | ||||
|                         groupNodes.forEach(function(n) { | ||||
|                             allNodes.delete(n); | ||||
|                         }); | ||||
|                         allNodes.add(g); | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|             if (allNodes.size > 0) { | ||||
|                 selection.nodes = Array.from(allNodes); | ||||
|             } | ||||
|             if (selected_link != null) { | ||||
|                 selection.link = selected_link; | ||||
|             } | ||||
|             selection.groups = activeGroups.filter(function(g) { return g.selected }) | ||||
|             if (selection.groups.length === 0) { | ||||
|                 delete selection.groups; | ||||
|             } | ||||
|             return selection; | ||||
|         }, | ||||
|         scale: function() { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user