diff --git a/public/index.html b/public/index.html index ae871f541..4df3e636e 100644 --- a/public/index.html +++ b/public/index.html @@ -268,6 +268,7 @@ + diff --git a/public/red/history.js b/public/red/history.js index c0dd4648c..91afc810c 100644 --- a/public/red/history.js +++ b/public/red/history.js @@ -1,5 +1,5 @@ /** - * Copyright 2013 IBM Corp. + * Copyright 2013, 2015 IBM Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/public/red/main.js b/public/red/main.js index 519536412..383fe94b5 100644 --- a/public/red/main.js +++ b/public/red/main.js @@ -286,8 +286,8 @@ var RED = (function() { {id:"btn-config-nodes",label:"Configuration nodes",onselect:RED.sidebar.config.show}, null, {id:"btn-subflow-menu",label:"Subflows", options: [ - {id:"btn-create-subflow",label:"Create subflow",onselect:RED.view.createSubflow}, - {id:"btn-convert-subflow",label:"Selection to subflow",disabled:true,onselect:RED.view.convertToSubflow}, + {id:"btn-create-subflow",label:"Create subflow",onselect:RED.subflow.createSubflow}, + {id:"btn-convert-subflow",label:"Selection to subflow",disabled:true,onselect:RED.subflow.convertToSubflow}, ]}, null, {id:"btn-workspace-menu",label:"Workspaces",options:[ @@ -356,8 +356,24 @@ var RED = (function() { RED.library.init(); RED.palette.init(); RED.sidebar.init(); + RED.subflow.init(); RED.view.init(); + RED.view.on("selection-changed",function(selection) { + if (!selection.nodes) { + RED.menu.setDisabled("btn-export-menu",true); + RED.menu.setDisabled("btn-export-clipboard",true); + RED.menu.setDisabled("btn-export-library",true); + RED.menu.setDisabled("btn-convert-subflow",true); + } else { + RED.menu.setDisabled("btn-export-menu",false); + RED.menu.setDisabled("btn-export-clipboard",false); + RED.menu.setDisabled("btn-export-library",false); + RED.menu.setDisabled("btn-convert-subflow",false); + } + }); + + RED.keyboard.add(/* ? */ 191,{shift:true},function(){showHelp();d3.event.preventDefault();}); RED.comms.connect(); loadNodeList(); diff --git a/public/red/ui/palette.js b/public/red/ui/palette.js index 42bf04af9..60cb44fe7 100644 --- a/public/red/ui/palette.js +++ b/public/red/ui/palette.js @@ -1,5 +1,5 @@ /** - * Copyright 2013 IBM Corp. + * Copyright 2013, 2015 IBM Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/public/red/ui/subflow.js b/public/red/ui/subflow.js new file mode 100644 index 000000000..d0edb952d --- /dev/null +++ b/public/red/ui/subflow.js @@ -0,0 +1,392 @@ +/** + * Copyright 2015 IBM Corp. + * + * 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.subflow = (function() { + + + function getSubflow() { + return RED.nodes.subflow(RED.view.getWorkspace()); + } + + function findAvailableSubflowIOPosition(subflow) { + var pos = {x:70,y:70}; + for (var i=0;iCannot create subflow: no nodes selected","error"); + return; + } + var i; + var nodes = {}; + var new_links = []; + var removedLinks = []; + + var candidateInputs = []; + var candidateOutputs = []; + + var boundingBox = [selection.nodes[0].x, + selection.nodes[0].y, + selection.nodes[0].x, + selection.nodes[0].y]; + + for (i=0;i 1) { + RED.notify("Cannot create subflow: multiple inputs to selection","error"); + return; + } + //if (candidateInputs.length == 0) { + // RED.notify("Cannot create subflow: no input to selection","error"); + // return; + //} + + + var lastIndex = 0; + RED.nodes.eachSubflow(function(sf) { + var m = (new RegExp("^Subflow (\\d+)$")).exec(sf.name); + if (m) { + lastIndex = Math.max(lastIndex,m[1]); + } + }); + + var name = "Subflow "+(lastIndex+1); + + var subflowId = RED.nodes.id(); + var subflow = { + type:"subflow", + id:subflowId, + name:name, + in: candidateInputs.map(function(v,i) { var index = i; return { + type:"subflow", + direction:"in", + x:v.target.x-(v.target.w/2)-80, + y:v.target.y, + z:subflowId, + i:index, + id:RED.nodes.id(), + wires:[{id:v.target.id}] + }}), + out: candidateOutputs.map(function(v,i) { var index = i; return { + type:"subflow", + direction:"in", + x:v.source.x+(v.source.w/2)+80, + y:v.source.y, + z:subflowId, + i:index, + id:RED.nodes.id(), + wires:[{id:v.source.id,port:v.sourcePort}] + }}) + }; + RED.nodes.addSubflow(subflow); + + var subflowInstance = { + id:RED.nodes.id(), + type:"subflow:"+subflow.id, + x: center[0], + y: center[1], + z: RED.view.getWorkspace(), + inputs: subflow.in.length, + outputs: subflow.out.length, + h: Math.max(30/*node_height*/,(subflow.out.length||0) * 15), + changed:true + } + subflowInstance._def = RED.nodes.getType(subflowInstance.type); + RED.editor.validateNode(subflowInstance); + RED.nodes.add(subflowInstance); + + candidateInputs.forEach(function(l) { + var link = {source:l.source, sourcePort:l.sourcePort, target: subflowInstance}; + new_links.push(link); + RED.nodes.addLink(link); + }); + + candidateOutputs.forEach(function(output,i) { + output.targets.forEach(function(target) { + var link = {source:subflowInstance, sourcePort:i, target: target}; + new_links.push(link); + RED.nodes.addLink(link); + }); + }); + + subflow.in.forEach(function(input) { + input.wires.forEach(function(wire) { + var link = {source: input, sourcePort: 0, target: RED.nodes.node(wire.id) } + new_links.push(link); + RED.nodes.addLink(link); + }); + }); + subflow.out.forEach(function(output,i) { + output.wires.forEach(function(wire) { + var link = {source: RED.nodes.node(wire.id), sourcePort: wire.port , target: output } + new_links.push(link); + RED.nodes.addLink(link); + }); + }); + + for (i=0;i 0) { @@ -809,21 +746,8 @@ RED.view = (function() { } eventHandler.emit("selection-changed",selection); - - if (moving_set.length == 1) { - if (moving_set[0].n.type === "subflow" && moving_set[0].n.direction) { - RED.sidebar.info.refresh(RED.nodes.subflow(moving_set[0].n.z)); - } else { - RED.sidebar.info.refresh(moving_set[0].n); - } - } else if (moving_set.length === 0 && activeSubflow) { - RED.sidebar.info.refresh(activeSubflow); - } else { - RED.sidebar.info.clear(); - } - - } + function endKeyboardMove() { var ns = []; for (var i=0;i 0) { + selection.nodes = moving_set.map(function(n) { return n.n;}); + } + if (selected_link != null) { + selection.link = selected_link; + } + return selection; + }, //TODO: should these move to an import/export module? showImportNodesDialog: showImportNodesDialog, showExportNodesDialog: showExportNodesDialog, @@ -2209,208 +2043,6 @@ RED.view = (function() { workspace_tabs.resize(); } workspace_tabs.activateTab(id); - }, - - createSubflow: function() { - var lastIndex = 0; - RED.nodes.eachSubflow(function(sf) { - var m = (new RegExp("^Subflow (\\d+)$")).exec(sf.name); - if (m) { - lastIndex = Math.max(lastIndex,m[1]); - } - }); - - var name = "Subflow "+(lastIndex+1); - - var subflowId = RED.nodes.id(); - var subflow = { - type:"subflow", - id:subflowId, - name:name, - in: [], - out: [] - }; - RED.nodes.addSubflow(subflow); - RED.history.push({ - t:'createSubflow', - subflow: subflow, - dirty:RED.view.dirty() - }); - RED.view.showSubflow(subflowId); - }, - - convertToSubflow: function() { - if (moving_set.length === 0) { - RED.notify("Cannot create subflow: no nodes selected","error"); - return; - } - var i; - var nodes = {}; - var new_links = []; - var removedLinks = []; - - var candidateInputs = []; - var candidateOutputs = []; - - var boundingBox = [moving_set[0].n.x,moving_set[0].n.y,moving_set[0].n.x,moving_set[0].n.y]; - - for (i=0;i 1) { - RED.notify("Cannot create subflow: multiple inputs to selection","error"); - return; - } - //if (candidateInputs.length == 0) { - // RED.notify("Cannot create subflow: no input to selection","error"); - // return; - //} - - - var lastIndex = 0; - RED.nodes.eachSubflow(function(sf) { - var m = (new RegExp("^Subflow (\\d+)$")).exec(sf.name); - if (m) { - lastIndex = Math.max(lastIndex,m[1]); - } - }); - - var name = "Subflow "+(lastIndex+1); - - var subflowId = RED.nodes.id(); - var subflow = { - type:"subflow", - id:subflowId, - name:name, - in: candidateInputs.map(function(v,i) { var index = i; return { - type:"subflow", - direction:"in", - x:v.target.x-(v.target.w/2)-80, - y:v.target.y, - z:subflowId, - i:index, - id:RED.nodes.id(), - wires:[{id:v.target.id}] - }}), - out: candidateOutputs.map(function(v,i) { var index = i; return { - type:"subflow", - direction:"in", - x:v.source.x+(v.source.w/2)+80, - y:v.source.y, - z:subflowId, - i:index, - id:RED.nodes.id(), - wires:[{id:v.source.id,port:v.sourcePort}] - }}) - }; - RED.nodes.addSubflow(subflow); - - var subflowInstance = { - id:RED.nodes.id(), - type:"subflow:"+subflow.id, - x: center[0], - y: center[1], - z: activeWorkspace, - inputs: subflow.in.length, - outputs: subflow.out.length, - h: Math.max(node_height,(subflow.out.length||0) * 15), - changed:true - } - subflowInstance._def = RED.nodes.getType(subflowInstance.type); - RED.editor.validateNode(subflowInstance); - RED.nodes.add(subflowInstance); - - candidateInputs.forEach(function(l) { - var link = {source:l.source, sourcePort:l.sourcePort, target: subflowInstance}; - new_links.push(link); - RED.nodes.addLink(link); - }); - - candidateOutputs.forEach(function(output,i) { - output.targets.forEach(function(target) { - var link = {source:subflowInstance, sourcePort:i, target: target}; - new_links.push(link); - RED.nodes.addLink(link); - }); - }); - - subflow.in.forEach(function(input) { - input.wires.forEach(function(wire) { - var link = {source: input, sourcePort: 0, target: RED.nodes.node(wire.id) } - new_links.push(link); - RED.nodes.addLink(link); - }); - }); - subflow.out.forEach(function(output,i) { - output.wires.forEach(function(wire) { - var link = {source: RED.nodes.node(wire.id), sourcePort: wire.port , target: output } - new_links.push(link); - RED.nodes.addLink(link); - }); - }); - - for (i=0;i