')
+ .appendTo("body")
+ .dialog({
+ modal: true,
+ autoOpen: false,
+ width: 500,
+ resizable: false,
+ buttons: [
+ {
+ id: "clipboard-dialog-ok",
+ text: "Ok",
+ click: function() {
+ if (/Import/.test(dialog.dialog("option","title"))) {
+ RED.view.importNodes($("#clipboard-import").val());
+ }
+ $( this ).dialog( "close" );
+ }
+ },
+ {
+ id: "clipboard-dialog-cancel",
+ text: "Cancel",
+ click: function() {
+ $( this ).dialog( "close" );
+ }
+ },
+ {
+ id: "clipboard-dialog-close",
+ text: "Close",
+ click: function() {
+ $( this ).dialog( "close" );
+ }
+ }
+ ],
+ open: function(e) {
+ $(this).parent().find(".ui-dialog-titlebar-close").hide();
+ RED.keyboard.disable();
+ },
+ close: function(e) {
+ RED.keyboard.enable();
+ }
+ });
+
+ var dialogContainer = dialog.children(".dialog-form");
+
+ var exportNodesDialog = ''+
+ ''+
+ ''+
+ '
'+
+ ''+
+ 'Select the text above and copy to the clipboard with Ctrl-C.'+
+ '
';
+
+ var importNodesDialog = ''+
+ ''+
+ '
';
+
+
+ function importNodes() {
+ dialogContainer.empty();
+ dialogContainer.append($(importNodesDialog));
+ $("#clipboard-dialog-ok").show();
+ $("#clipboard-dialog-cancel").show();
+ $("#clipboard-dialog-close").hide();
+ $("#clipboard-dialog-ok").button("disable");
+ $("#clipboard-import").keyup(function() {
+ var v = $(this).val();
+ try {
+ JSON.parse(v);
+ $(this).removeClass("input-error");
+ $("#clipboard-dialog-ok").button("enable");
+ } catch(err) {
+ if (v !== "") {
+ $(this).addClass("input-error");
+ }
+ $("#clipboard-dialog-ok").button("disable");
+ }
+ });
+ dialog.dialog("option","title","Import nodes").dialog("open");
+ }
+
+ function exportNodes() {
+ dialogContainer.empty();
+ dialogContainer.append($(exportNodesDialog));
+ $("#clipboard-dialog-ok").hide();
+ $("#clipboard-dialog-cancel").hide();
+ $("#clipboard-dialog-close").show();
+ var selection = RED.view.selection();
+ if (selection.nodes) {
+ var nns = RED.nodes.createExportableNodeSet(selection.nodes);
+ $("#clipboard-export")
+ .val(JSON.stringify(nns))
+ .focus(function() {
+ var textarea = $(this);
+ textarea.select();
+ textarea.mouseup(function() {
+ textarea.unbind("mouseup");
+ return false;
+ })
+ });
+ dialog.dialog("option","title","Export nodes to clipboard").dialog( "open" );
+ }
+ }
+
+ return {
+ init: function() {
+ 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);
+ } else {
+ RED.menu.setDisabled("btn-export-menu",false);
+ RED.menu.setDisabled("btn-export-clipboard",false);
+ RED.menu.setDisabled("btn-export-library",false);
+ }
+ });
+ RED.keyboard.add(/* e */ 69,{ctrl:true},function(){exportNodes();d3.event.preventDefault();});
+ RED.keyboard.add(/* i */ 73,{ctrl:true},function(){importNodes();d3.event.preventDefault();});
+ },
+ import: importNodes,
+ export: exportNodes
+ }
+
+
+
+
+
+})();
diff --git a/public/red/ui/editor.js b/public/red/ui/editor.js
index 2bf9f4acd..31cae03b5 100644
--- a/public/red/ui/editor.js
+++ b/public/red/ui/editor.js
@@ -234,24 +234,20 @@ RED.editor = (function() {
editing_node.dirty = true;
validateNode(editing_node);
RED.view.redraw();
- } else if (RED.view.state() == RED.state.EXPORT) {
- if (/library/.test($( "#dialog" ).dialog("option","title"))) {
- //TODO: move this to RED.library
- var flowName = $("#node-input-filename").val();
- if (!/^\s*$/.test(flowName)) {
- $.ajax({
- url:'library/flows/'+flowName,
- type: "POST",
- data: $("#node-input-filename").attr('nodes'),
- contentType: "application/json; charset=utf-8"
- }).done(function() {
- RED.library.loadFlowLibrary();
- RED.notify("Saved nodes","success");
- });
- }
+ } else if (/Export nodes to library/.test($( "#dialog" ).dialog("option","title"))) {
+ //TODO: move this to RED.library
+ var flowName = $("#node-input-filename").val();
+ if (!/^\s*$/.test(flowName)) {
+ $.ajax({
+ url:'library/flows/'+flowName,
+ type: "POST",
+ data: $("#node-input-filename").attr('nodes'),
+ contentType: "application/json; charset=utf-8"
+ }).done(function() {
+ RED.library.loadFlowLibrary();
+ RED.notify("Saved nodes","success");
+ });
}
- } else if (RED.view.state() == RED.state.IMPORT) {
- RED.view.importNodes($("#node-input-import").val());
}
$( this ).dialog( "close" );
}
@@ -500,7 +496,7 @@ RED.editor = (function() {
class: 'leftButton',
text: "Edit flow",
click: function() {
- RED.view.showSubflow(id);
+ RED.workspaces.show(id);
$("#node-dialog-ok").click();
}
});
diff --git a/public/red/ui/library.js b/public/red/ui/library.js
index 28beb7e74..9cbafc429 100644
--- a/public/red/ui/library.js
+++ b/public/red/ui/library.js
@@ -380,6 +380,14 @@ RED.library = (function() {
}
+ function exportFlow() {
+ //TODO: don't rely on the main dialog
+ var nns = RED.nodes.createExportableNodeSet(RED.view.selection().nodes);
+ $("#dialog-form").html($("script[data-template-name='export-library-dialog']").html());
+ $("#node-input-filename").attr('nodes',JSON.stringify(nns));
+ $( "#dialog" ).dialog("option","title","Export nodes to library").dialog( "open" );
+ }
+
return {
init: function() {
RED.view.on("selection-changed",function(selection) {
@@ -397,7 +405,9 @@ RED.library = (function() {
loadFlowLibrary();
},
create: createUI,
- loadFlowLibrary: loadFlowLibrary
+ loadFlowLibrary: loadFlowLibrary,
+
+ export: exportFlow
}
})();
diff --git a/public/red/ui/sidebar.js b/public/red/ui/sidebar.js
index dda7f8d45..f23aa1dca 100644
--- a/public/red/ui/sidebar.js
+++ b/public/red/ui/sidebar.js
@@ -59,7 +59,6 @@ RED.sidebar = (function() {
$("#chart-zoom-controls").css("right",newChartRight+20);
$("#sidebar").width(0);
RED.menu.setSelected("btn-sidebar",true);
- RED.view.resize();
eventHandler.emit("resize");
}
sidebarSeparator.width = $("#sidebar").width();
@@ -100,11 +99,9 @@ RED.sidebar = (function() {
$("#sidebar").width(newSidebarWidth);
sidebar_tabs.resize();
- RED.view.resize();
eventHandler.emit("resize");
},
stop:function(event,ui) {
- RED.view.resize();
if (sidebarSeparator.closing) {
$("#sidebar").removeClass("closing");
RED.menu.setSelected("btn-sidebar",false);
diff --git a/public/red/ui/subflow.js b/public/red/ui/subflow.js
index d187f7140..50ada14fc 100644
--- a/public/red/ui/subflow.js
+++ b/public/red/ui/subflow.js
@@ -18,7 +18,7 @@ RED.subflow = (function() {
function getSubflow() {
- return RED.nodes.subflow(RED.view.getWorkspace());
+ return RED.nodes.subflow(RED.workspaces.active());
}
function findAvailableSubflowIOPosition(subflow) {
@@ -39,7 +39,7 @@ RED.subflow = (function() {
}
function addSubflowInput() {
- var subflow = RED.nodes.subflow(RED.view.getWorkspace());
+ var subflow = RED.nodes.subflow(RED.workspaces.active());
var position = findAvailableSubflowIOPosition(subflow);
var newInput = {
type:"subflow",
@@ -79,7 +79,7 @@ RED.subflow = (function() {
}
function addSubflowOutput(id) {
- var subflow = RED.nodes.subflow(RED.view.getWorkspace());
+ var subflow = RED.nodes.subflow(RED.workspaces.active());
var position = findAvailableSubflowIOPosition(subflow);
var newOutput = {
@@ -120,7 +120,7 @@ RED.subflow = (function() {
function init() {
$("#workspace-subflow-edit").click(function(event) {
- RED.editor.editSubflow(RED.nodes.subflow(RED.view.getWorkspace()));
+ RED.editor.editSubflow(RED.nodes.subflow(RED.workspaces.active()));
event.preventDefault();
});
$("#workspace-subflow-add-input").click(function(event) {
@@ -170,7 +170,7 @@ RED.subflow = (function() {
dirty:startDirty
});
- RED.view.removeWorkspace(activeSubflow);
+ RED.workspaces.remove(activeSubflow);
RED.view.dirty(true);
RED.view.redraw();
});
@@ -210,7 +210,7 @@ RED.subflow = (function() {
subflow: subflow,
dirty:RED.view.dirty()
});
- RED.view.showSubflow(subflowId);
+ RED.workspaces.show(subflowId);
}
function convertToSubflow() {
@@ -328,7 +328,7 @@ RED.subflow = (function() {
type:"subflow:"+subflow.id,
x: center[0],
y: center[1],
- z: RED.view.getWorkspace(),
+ z: RED.workspaces.active(),
inputs: subflow.in.length,
outputs: subflow.out.length,
h: Math.max(30/*node_height*/,(subflow.out.length||0) * 15),
@@ -381,7 +381,7 @@ RED.subflow = (function() {
links:new_links,
subflow: subflow,
- activeWorkspace: RED.view.getWorkspace(),
+ activeWorkspace: RED.workspaces.active(),
removedLinks: removedLinks,
dirty:RED.view.dirty()
diff --git a/public/red/ui/tab-info.js b/public/red/ui/tab-info.js
index 35ea9932e..848b07c5f 100644
--- a/public/red/ui/tab-info.js
+++ b/public/red/ui/tab-info.js
@@ -148,7 +148,7 @@ RED.sidebar.info = (function() {
}
}
} else {
- var subflow = RED.nodes.subflow(RED.view.getWorkspace());
+ var subflow = RED.nodes.subflow(RED.workspaces.active());
if (subflow) {
refresh(subflow);
} else {
diff --git a/public/red/ui/view.js b/public/red/ui/view.js
index f87abd41e..75288960a 100644
--- a/public/red/ui/view.js
+++ b/public/red/ui/view.js
@@ -29,14 +29,13 @@ RED.view = (function() {
moveTouchCenter = [],
touchStartTime = 0;
+ var workspaceScrollPositions = {};
+
- var activeWorkspace = 0;
var activeSubflow = null;
var activeNodes = [];
var activeLinks = [];
- var workspaceScrollPositions = {};
-
var selected_link = null,
mousedown_link = null,
mousedown_node = null,
@@ -234,40 +233,38 @@ RED.view = (function() {
var drag_line = vis.append("svg:path").attr("class", "drag_line");
function updateActiveNodes() {
+ //TODO: remove direct access to RED.nodes.nodes
activeNodes = RED.nodes.nodes.filter(function(d) {
- return d.z == activeWorkspace;
+ return d.z == RED.workspaces.active();
});
activeLinks = RED.nodes.links.filter(function(d) {
- return d.source.z == activeWorkspace && d.target.z == activeWorkspace;
+ return d.source.z == RED.workspaces.active() && d.target.z == RED.workspaces.active();
})
}
-
- var workspace_tabs = RED.tabs.create({
- id: "workspace-tabs",
- onchange: function(tab) {
- if (tab.type == "subflow") {
- $("#workspace-toolbar").show();
- } else {
- $("#workspace-toolbar").hide();
- }
+
+ function init() {
+ RED.workspaces.on("change",function(event) {
var chart = $("#chart");
- if (activeWorkspace !== 0) {
- workspaceScrollPositions[activeWorkspace] = {
+ if (event.old !== 0) {
+ workspaceScrollPositions[event.old] = {
left:chart.scrollLeft(),
top:chart.scrollTop()
};
}
var scrollStartLeft = chart.scrollLeft();
var scrollStartTop = chart.scrollTop();
-
- activeWorkspace = tab.id;
- activeSubflow = RED.nodes.subflow(activeWorkspace);
+
+ activeSubflow = RED.nodes.subflow(event.workspace);
if (activeSubflow) {
$("#workspace-subflow-add-input").toggleClass("disabled",activeSubflow.in.length > 0);
}
- if (workspaceScrollPositions[activeWorkspace]) {
- chart.scrollLeft(workspaceScrollPositions[activeWorkspace].left);
- chart.scrollTop(workspaceScrollPositions[activeWorkspace].top);
+
+ RED.menu.setDisabled("btn-workspace-edit", activeSubflow);
+ RED.menu.setDisabled("btn-workspace-delete",RED.workspaces.count() == 1 || activeSubflow);
+
+ if (workspaceScrollPositions[event.workspace]) {
+ chart.scrollLeft(workspaceScrollPositions[event.workspace].left);
+ chart.scrollTop(workspaceScrollPositions[event.workspace].top);
} else {
chart.scrollLeft(0);
chart.scrollTop(0);
@@ -278,10 +275,6 @@ RED.view = (function() {
mouse_position[0] += scrollDeltaLeft;
mouse_position[1] += scrollDeltaTop;
}
-
- RED.menu.setDisabled("btn-workspace-edit", activeSubflow);
- RED.menu.setDisabled("btn-workspace-delete",workspace_tabs.count() == 1 || activeSubflow);
-
clearSelection();
RED.nodes.eachNode(function(n) {
n.dirty = true;
@@ -289,69 +282,8 @@ RED.view = (function() {
updateSelection();
updateActiveNodes();
redraw();
- },
- ondblclick: function(tab) {
- if (tab.type != "subflow") {
- showRenameWorkspaceDialog(tab.id);
- } else {
- RED.editor.editSubflow(RED.nodes.subflow(tab.id));
- }
- },
- onadd: function(tab) {
- RED.menu.addItem("btn-workspace-menu",{
- id:"btn-workspace-menu-"+tab.id.replace(".","-"),
- label:tab.label,
- onselect:function() {
- workspace_tabs.activateTab(tab.id);
- }
- });
- RED.menu.setDisabled("btn-workspace-delete",workspace_tabs.count() == 1);
- updateActiveNodes();
- },
- onremove: function(tab) {
- RED.menu.setDisabled("btn-workspace-delete",workspace_tabs.count() == 1);
- RED.menu.removeItem("btn-workspace-menu-"+tab.id.replace(".","-"));
- updateActiveNodes();
- }
- });
- var workspaceIndex = 0;
-
- function addWorkspace() {
- var tabId = RED.nodes.id();
- do {
- workspaceIndex += 1;
- } while($("#workspace-tabs a[title='Sheet "+workspaceIndex+"']").size() !== 0);
-
- var ws = {type:"tab",id:tabId,label:"Sheet "+workspaceIndex};
- RED.nodes.addWorkspace(ws);
- workspace_tabs.addTab(ws);
- workspace_tabs.activateTab(tabId);
- RED.history.push({t:'add',workspaces:[ws],dirty:dirty});
- RED.view.dirty(true);
- }
-
- function init() {
- $('#btn-workspace-add-tab').on("click",addWorkspace);
-
- RED.menu.setAction('btn-workspace-add',addWorkspace);
- RED.menu.setAction('btn-workspace-edit',function() {
- showRenameWorkspaceDialog(activeWorkspace);
});
- RED.menu.setAction('btn-workspace-delete',function() {
- deleteWorkspace(activeWorkspace);
- });
- updateActiveNodes();
- }
-
- function deleteWorkspace(id) {
- if (workspace_tabs.count() == 1) {
- return;
- }
- var ws = RED.nodes.workspace(id);
- $( "#node-dialog-delete-workspace" ).dialog('option','workspace',ws);
- $( "#node-dialog-delete-workspace-name" ).text(ws.label);
- $( "#node-dialog-delete-workspace" ).dialog('open');
}
function canvasMouseDown() {
@@ -530,7 +462,7 @@ RED.view = (function() {
clearSelection();
}
RED.nodes.eachNode(function(n) {
- if (n.z == activeWorkspace && !n.selected) {
+ if (n.z == RED.workspaces.active() && !n.selected) {
n.selected = (n.x > x && n.x < x2 && n.y > y && n.y < y2);
if (n.selected) {
n.dirty = true;
@@ -625,7 +557,7 @@ RED.view = (function() {
mousePos[1] /= scaleFactor;
mousePos[0] /= scaleFactor;
- var nn = { id:(1+Math.random()*4294967295).toString(16),x: mousePos[0],y:mousePos[1],w:node_width,z:activeWorkspace};
+ var nn = { id:(1+Math.random()*4294967295).toString(16),x: mousePos[0],y:mousePos[1],w:node_width,z:RED.workspaces.active()};
nn.type = selected_tool;
nn._def = RED.nodes.getType(nn.type);
@@ -688,7 +620,7 @@ RED.view = (function() {
function selectAll() {
RED.nodes.eachNode(function(n) {
- if (n.z == activeWorkspace) {
+ if (n.z == RED.workspaces.active()) {
if (!n.selected) {
n.selected = true;
n.dirty = true;
@@ -960,7 +892,7 @@ RED.view = (function() {
if (mouse_mode == RED.state.JOINING && mousedown_node) {
if (typeof TouchEvent != "undefined" && d3.event instanceof TouchEvent) {
RED.nodes.eachNode(function(n) {
- if (n.z == activeWorkspace) {
+ if (n.z == RED.workspaces.active()) {
var hw = n.w/2;
var hh = n.h/2;
if (n.x-hw mouse_position[0] &&
@@ -1246,7 +1178,7 @@ RED.view = (function() {
vis.selectAll(".subflowinput").remove();
}
- //var node = vis.selectAll(".nodegroup").data(RED.nodes.nodes.filter(function(d) { return d.z == activeWorkspace }),function(d){return d.id});
+ //var node = vis.selectAll(".nodegroup").data(RED.nodes.nodes.filter(function(d) { return d.z == RED.workspaces.active() }),function(d){return d.id});
var node = vis.selectAll(".nodegroup").data(activeNodes,function(d){return d.id});
node.exit().remove();
@@ -1712,8 +1644,6 @@ RED.view = (function() {
RED.keyboard.add(/* - */ 189,{ctrl:true},function(){zoomOut();d3.event.preventDefault();});
RED.keyboard.add(/* 0 */ 48,{ctrl:true},function(){zoomZero();d3.event.preventDefault();});
RED.keyboard.add(/* v */ 86,{ctrl:true},function(){importNodes(clipboard);d3.event.preventDefault();});
- RED.keyboard.add(/* e */ 69,{ctrl:true},function(){showExportNodesDialog();d3.event.preventDefault();});
- RED.keyboard.add(/* i */ 73,{ctrl:true},function(){showImportNodesDialog();d3.event.preventDefault();});
// TODO: 'dirty' should be a property of RED.nodes - with an event callback for ui hooks
function setDirty(d) {
@@ -1744,7 +1674,7 @@ RED.view = (function() {
var new_workspaces = result[2];
var new_subflows = result[3];
- var new_ms = new_nodes.filter(function(n) { return n.z == activeWorkspace }).map(function(n) { return {n:n};});
+ var new_ms = new_nodes.filter(function(n) { return n.z == RED.workspaces.active() }).map(function(n) { return {n:n};});
var new_node_ids = new_nodes.map(function(n){ return n.id; });
// TODO: pick a more sensible root node
@@ -1816,136 +1746,6 @@ RED.view = (function() {
}
}
- function showExportNodesDialog() {
- mouse_mode = RED.state.EXPORT;
- var nns = RED.nodes.createExportableNodeSet(moving_set);
- $("#dialog-form").html($("script[data-template-name='export-clipboard-dialog']").html());
- $("#node-input-export").val(JSON.stringify(nns));
- $("#node-input-export").focus(function() {
- var textarea = $(this);
- textarea.select();
- textarea.mouseup(function() {
- textarea.unbind("mouseup");
- return false;
- });
- });
- $( "#dialog" ).dialog("option","title","Export nodes to clipboard").dialog( "open" );
- $("#node-input-export").focus();
- }
-
- function showExportNodesLibraryDialog() {
- mouse_mode = RED.state.EXPORT;
- var nns = RED.nodes.createExportableNodeSet(moving_set);
- $("#dialog-form").html($("script[data-template-name='export-library-dialog']").html());
- $("#node-input-filename").attr('nodes',JSON.stringify(nns));
- $( "#dialog" ).dialog("option","title","Export nodes to library").dialog( "open" );
- }
-
- function showImportNodesDialog() {
- mouse_mode = RED.state.IMPORT;
- $("#dialog-form").html($("script[data-template-name='import-dialog']").html());
- $("#node-input-import").val("");
- $( "#dialog" ).dialog("option","title","Import nodes").dialog( "open" );
- }
-
- function showRenameWorkspaceDialog(id) {
- var ws = RED.nodes.workspace(id);
- $( "#node-dialog-rename-workspace" ).dialog("option","workspace",ws);
-
- if (workspace_tabs.count() == 1) {
- $( "#node-dialog-rename-workspace").next().find(".leftButton")
- .prop('disabled',true)
- .addClass("ui-state-disabled");
- } else {
- $( "#node-dialog-rename-workspace").next().find(".leftButton")
- .prop('disabled',false)
- .removeClass("ui-state-disabled");
- }
-
- $( "#node-input-workspace-name" ).val(ws.label);
- $( "#node-dialog-rename-workspace" ).dialog("open");
- }
-
- $("#node-dialog-rename-workspace form" ).submit(function(e) { e.preventDefault();});
- $( "#node-dialog-rename-workspace" ).dialog({
- modal: true,
- autoOpen: false,
- width: 500,
- title: "Rename sheet",
- buttons: [
- {
- class: 'leftButton',
- text: "Delete",
- click: function() {
- var workspace = $(this).dialog('option','workspace');
- $( this ).dialog( "close" );
- deleteWorkspace(workspace.id);
- }
- },
- {
- text: "Ok",
- click: function() {
- var workspace = $(this).dialog('option','workspace');
- var label = $( "#node-input-workspace-name" ).val();
- if (workspace.label != label) {
- workspace_tabs.renameTab(workspace.id,label);
- RED.view.dirty(true);
- $("#btn-workspace-menu-"+workspace.id.replace(".","-")).text(label);
- // TODO: update entry in menu
- }
- $( this ).dialog( "close" );
- }
- },
- {
- text: "Cancel",
- click: function() {
- $( this ).dialog( "close" );
- }
- }
- ],
- open: function(e) {
- RED.keyboard.disable();
- },
- close: function(e) {
- RED.keyboard.enable();
- }
- });
- $( "#node-dialog-delete-workspace" ).dialog({
- modal: true,
- autoOpen: false,
- width: 500,
- title: "Confirm delete",
- buttons: [
- {
- text: "Ok",
- click: function() {
- var workspace = $(this).dialog('option','workspace');
- RED.view.removeWorkspace(workspace);
- var historyEvent = RED.nodes.removeWorkspace(workspace.id);
- historyEvent.t = 'delete';
- historyEvent.dirty = dirty;
- historyEvent.workspaces = [workspace];
- RED.history.push(historyEvent);
- RED.view.dirty(true);
- $( this ).dialog( "close" );
- }
- },
- {
- text: "Cancel",
- click: function() {
- $( this ).dialog( "close" );
- }
- }
- ],
- open: function(e) {
- RED.keyboard.disable();
- },
- close: function(e) {
- RED.keyboard.enable();
- }
-
- });
-
function hideDropTarget() {
$("#dropTarget").hide();
RED.keyboard.remove(/* ESCAPE */ 27);
@@ -2004,30 +1804,12 @@ RED.view = (function() {
mouse_mode = state;
}
},
- addWorkspace: function(ws) {
- workspace_tabs.addTab(ws);
- workspace_tabs.resize();
- },
- removeWorkspace: function(ws) {
- if (workspace_tabs.contains(ws.id)) {
- workspace_tabs.removeTab(ws.id);
- }
- },
- getWorkspace: function() {
- return activeWorkspace;
- },
- showWorkspace: function(id) {
- workspace_tabs.activateTab(id);
- },
+
redraw: function(updateActive) {
if (updateActive) {
updateActiveNodes();
}
- RED.nodes.eachSubflow(function(sf) {
- if (workspace_tabs.contains(sf.id)) {
- workspace_tabs.renameTab(sf.id,"Subflow: "+sf.name);
- }
- });
+ RED.workspaces.refresh();
redraw();
},
dirty: function(d) {
@@ -2039,14 +1821,15 @@ RED.view = (function() {
},
focus: focusView,
importNodes: importNodes,
- resize: function() {
- workspace_tabs.resize();
- },
status: function(s) {
- showStatus = s;
- RED.nodes.eachNode(function(n) { n.dirty = true;});
- //TODO: subscribe/unsubscribe here
- redraw();
+ if (s == null) {
+ return showStatus;
+ } else {
+ showStatus = s;
+ RED.nodes.eachNode(function(n) { n.dirty = true;});
+ //TODO: subscribe/unsubscribe here
+ redraw();
+ }
},
calculateTextWidth: calculateTextWidth,
select: function(selection) {
@@ -2073,26 +1856,6 @@ RED.view = (function() {
selection.link = selected_link;
}
return selection;
- },
- //TODO: should these move to an import/export module?
- showImportNodesDialog: showImportNodesDialog,
- showExportNodesDialog: showExportNodesDialog,
- showExportNodesLibraryDialog: showExportNodesLibraryDialog,
- addFlow: function() {
- var ws = {type:"subflow",id:RED.nodes.id(),label:"Flow 1", closeable: true};
- RED.nodes.addWorkspace(ws);
- workspace_tabs.addTab(ws);
- workspace_tabs.activateTab(ws.id);
- return ws;
- },
-
- showSubflow: function(id) {
- if (!workspace_tabs.contains(id)) {
- var sf = RED.nodes.subflow(id);
- workspace_tabs.addTab({type:"subflow",id:id,label:"Subflow: "+sf.name, closeable: true});
- workspace_tabs.resize();
- }
- workspace_tabs.activateTab(id);
}
};
})();
diff --git a/public/red/ui/workspaces.js b/public/red/ui/workspaces.js
new file mode 100644
index 000000000..ac004adcf
--- /dev/null
+++ b/public/red/ui/workspaces.js
@@ -0,0 +1,273 @@
+/**
+ * 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.workspaces = (function() {
+
+ var activeWorkspace = 0;
+ var workspaceIndex = 0;
+
+ function addWorkspace(ws) {
+ if (ws) {
+ workspace_tabs.addTab(ws);
+ workspace_tabs.resize();
+ } else {
+ var tabId = RED.nodes.id();
+ do {
+ workspaceIndex += 1;
+ } while($("#workspace-tabs a[title='Sheet "+workspaceIndex+"']").size() !== 0);
+
+ ws = {type:"tab",id:tabId,label:"Sheet "+workspaceIndex};
+ RED.nodes.addWorkspace(ws);
+ workspace_tabs.addTab(ws);
+ workspace_tabs.activateTab(tabId);
+ RED.history.push({t:'add',workspaces:[ws],dirty:RED.view.dirty()});
+ RED.view.dirty(true);
+ }
+ }
+ function deleteWorkspace(ws,force) {
+ if (workspace_tabs.count() == 1) {
+ return;
+ }
+ var nodes = [];
+ if (!force) {
+ //TODO: remove direct access to RED.nodes.nodes
+ nodes = RED.nodes.nodes.filter(function(d) {
+ return d.z == ws.id;
+ });
+ }
+ if (force || nodes.length === 0) {
+ removeWorkspace(ws);
+ var historyEvent = RED.nodes.removeWorkspace(ws.id);
+ historyEvent.t = 'delete';
+ historyEvent.dirty = RED.view.dirty();
+ historyEvent.workspaces = [ws];
+ RED.history.push(historyEvent);
+ RED.view.dirty(true);
+ } else {
+ $( "#node-dialog-delete-workspace" ).dialog('option','workspace',ws);
+ $( "#node-dialog-delete-workspace-name" ).text(ws.label);
+ $( "#node-dialog-delete-workspace" ).dialog('open');
+ }
+ }
+ function showRenameWorkspaceDialog(id) {
+ var ws = RED.nodes.workspace(id);
+ $( "#node-dialog-rename-workspace" ).dialog("option","workspace",ws);
+
+ if (workspace_tabs.count() == 1) {
+ $( "#node-dialog-rename-workspace").next().find(".leftButton")
+ .prop('disabled',true)
+ .addClass("ui-state-disabled");
+ } else {
+ $( "#node-dialog-rename-workspace").next().find(".leftButton")
+ .prop('disabled',false)
+ .removeClass("ui-state-disabled");
+ }
+
+ $( "#node-input-workspace-name" ).val(ws.label);
+ $( "#node-dialog-rename-workspace" ).dialog("open");
+ }
+
+ var workspace_tabs = RED.tabs.create({
+ id: "workspace-tabs",
+ onchange: function(tab) {
+ if (tab.type == "subflow") {
+ $("#workspace-toolbar").show();
+ } else {
+ $("#workspace-toolbar").hide();
+ }
+ var event = {
+ old: activeWorkspace
+ }
+ activeWorkspace = tab.id;
+ event.workspace = activeWorkspace;
+
+ eventHandler.emit("change",event);
+ },
+ ondblclick: function(tab) {
+ if (tab.type != "subflow") {
+ showRenameWorkspaceDialog(tab.id);
+ } else {
+ RED.editor.editSubflow(RED.nodes.subflow(tab.id));
+ }
+ },
+ onadd: function(tab) {
+ RED.menu.addItem("btn-workspace-menu",{
+ id:"btn-workspace-menu-"+tab.id.replace(".","-"),
+ label:tab.label,
+ onselect:function() {
+ workspace_tabs.activateTab(tab.id);
+ }
+ });
+ RED.menu.setDisabled("btn-workspace-delete",workspace_tabs.count() == 1);
+ },
+ onremove: function(tab) {
+ RED.menu.setDisabled("btn-workspace-delete",workspace_tabs.count() == 1);
+ RED.menu.removeItem("btn-workspace-menu-"+tab.id.replace(".","-"));
+ }
+ });
+
+ $("#node-dialog-rename-workspace form" ).submit(function(e) { e.preventDefault();});
+ $( "#node-dialog-rename-workspace" ).dialog({
+ modal: true,
+ autoOpen: false,
+ width: 500,
+ title: "Rename sheet",
+ buttons: [
+ {
+ class: 'leftButton',
+ text: "Delete",
+ click: function() {
+ var workspace = $(this).dialog('option','workspace');
+ $( this ).dialog( "close" );
+ deleteWorkspace(workspace);
+ }
+ },
+ {
+ text: "Ok",
+ click: function() {
+ var workspace = $(this).dialog('option','workspace');
+ var label = $( "#node-input-workspace-name" ).val();
+ if (workspace.label != label) {
+ workspace_tabs.renameTab(workspace.id,label);
+ RED.view.dirty(true);
+ $("#btn-workspace-menu-"+workspace.id.replace(".","-")).text(label);
+ // TODO: update entry in menu
+ }
+ $( this ).dialog( "close" );
+ }
+ },
+ {
+ text: "Cancel",
+ click: function() {
+ $( this ).dialog( "close" );
+ }
+ }
+ ],
+ open: function(e) {
+ RED.keyboard.disable();
+ },
+ close: function(e) {
+ RED.keyboard.enable();
+ }
+ });
+ $( "#node-dialog-delete-workspace" ).dialog({
+ modal: true,
+ autoOpen: false,
+ width: 500,
+ title: "Confirm delete",
+ buttons: [
+ {
+ text: "Ok",
+ click: function() {
+ var workspace = $(this).dialog('option','workspace');
+ deleteWorkspace(workspace,true);
+ $( this ).dialog( "close" );
+ }
+ },
+ {
+ text: "Cancel",
+ click: function() {
+ $( this ).dialog( "close" );
+ }
+ }
+ ],
+ open: function(e) {
+ RED.keyboard.disable();
+ },
+ close: function(e) {
+ RED.keyboard.enable();
+ }
+
+ });
+
+ function init() {
+ $('#btn-workspace-add-tab').on("click",function(e) {addWorkspace(); e.preventDefault()});
+ RED.sidebar.on("resize",workspace_tabs.resize);
+
+ RED.menu.setAction('btn-workspace-delete',function() {
+ deleteWorkspace(RED.nodes.workspace(activeWorkspace));
+ });
+ }
+
+ // TODO: DRY
+ var eventHandler = (function() {
+ var handlers = {};
+
+ return {
+ on: function(evt,func) {
+ handlers[evt] = handlers[evt]||[];
+ handlers[evt].push(func);
+ },
+ emit: function(evt,arg) {
+ if (handlers[evt]) {
+ for (var i=0;i