diff --git a/Gruntfile.js b/Gruntfile.js index 3738e60b4..6d53e4d29 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -144,6 +144,7 @@ module.exports = function(grunt) { "editor/js/ui/keyboard.js", "editor/js/ui/workspaces.js", "editor/js/ui/view.js", + "editor/js/ui/view-navigator.js", "editor/js/ui/sidebar.js", "editor/js/ui/palette.js", "editor/js/ui/tab-info.js", diff --git a/editor/icons/file-in.png b/editor/icons/file-in.png new file mode 100644 index 000000000..d3e5cd7fe Binary files /dev/null and b/editor/icons/file-in.png differ diff --git a/editor/icons/file-out.png b/editor/icons/file-out.png new file mode 100644 index 000000000..051f819c8 Binary files /dev/null and b/editor/icons/file-out.png differ diff --git a/editor/js/nodes.js b/editor/js/nodes.js index 433e400a2..12ff3e682 100644 --- a/editor/js/nodes.js +++ b/editor/js/nodes.js @@ -133,7 +133,7 @@ RED.nodes = (function() { registerNodeType: function(nt,def) { nodeDefinitions[nt] = def; def.type = nt; - if (def.category != "subflows") { + if (nt.substring(0,8) != "subflow:") { def.set = nodeSets[typeToId[nt]]; nodeSets[typeToId[nt]].added = true; nodeSets[typeToId[nt]].enabled = true; @@ -356,7 +356,7 @@ RED.nodes = (function() { defaults:{name:{value:""}}, info: sf.info, icon: function() { return sf.icon||"subflow.png" }, - category: "subflows", + category: sf.category || "subflows", inputs: sf.in.length, outputs: sf.out.length, color: "#da9", @@ -519,6 +519,7 @@ RED.nodes = (function() { node.type = n.type; node.name = n.name; node.info = n.info; + node.category = n.category; node.in = []; node.out = []; diff --git a/editor/js/ui/common/tabs.js b/editor/js/ui/common/tabs.js index 23b69f5d1..4ed7ffe53 100644 --- a/editor/js/ui/common/tabs.js +++ b/editor/js/ui/common/tabs.js @@ -170,8 +170,8 @@ RED.tabs = (function() { ul.children().css({"transition": "width 100ms"}); link.parent().addClass("active"); var parentId = link.parent().attr('id'); - wrapper.find(".red-ui-tab-link-button").removeClass("active"); - $("#"+parentId+"-link-button").addClass("active"); + wrapper.find(".red-ui-tab-link-button").removeClass("active selected"); + $("#"+parentId+"-link-button").addClass("active selected"); if (options.scrollable) { var pos = link.parent().position().left; if (pos-21 < 0) { diff --git a/editor/js/ui/editor.js b/editor/js/ui/editor.js index df50db725..0f6050b8a 100644 --- a/editor/js/ui/editor.js +++ b/editor/js/ui/editor.js @@ -108,17 +108,6 @@ RED.editor = (function() { } } } - if (node.icon) { - var iconPath = RED.utils.separateIconPath(node.icon); - if (!iconPath.module) { - return isValid; - } - var iconSets = RED.nodes.getIconSets(); - var iconFileList = iconSets[iconPath.module]; - if (!iconFileList || iconFileList.indexOf(iconPath.file) === -1) { - isValid = false; - } - } return isValid; } @@ -170,27 +159,6 @@ RED.editor = (function() { } } } - validateIcon(node); - } - - function validateIcon(node) { - if (node._def.hasOwnProperty("defaults") && !node._def.defaults.hasOwnProperty("icon") && node.icon) { - var iconPath = RED.utils.separateIconPath(node.icon); - var iconSets = RED.nodes.getIconSets(); - var iconFileList = iconSets[iconPath.module]; - var iconModule = $("#node-settings-icon-module"); - var iconFile = $("#node-settings-icon-file"); - if (!iconFileList) { - iconModule.addClass("input-error"); - iconFile.removeClass("input-error"); - } else if (iconFileList.indexOf(iconPath.file) === -1) { - iconModule.removeClass("input-error"); - iconFile.addClass("input-error"); - } else { - iconModule.removeClass("input-error"); - iconFile.removeClass("input-error"); - } - } } function validateNodeEditorProperty(node,defaults,property,prefix) { @@ -711,6 +679,97 @@ RED.editor = (function() { } return result; } + function showIconPicker(container, node, iconPath, done) { + var containerPos = container.offset(); + var pickerBackground = $('
').css({ + position: "absolute",top:0,bottom:0,left:0,right:0,zIndex:20 + }).appendTo("body"); + + var top = containerPos.top - 30; + + if (top+280 > $( window ).height()) { + top = $( window ).height() - 280; + } + var picker = $('
').css({ + top: top+"px", + left: containerPos.left+"px", + }).appendTo("body"); + + var hide = function() { + pickerBackground.remove(); + picker.remove(); + RED.keyboard.remove("escape"); + } + RED.keyboard.add("*","escape",function(){hide()}); + pickerBackground.on("mousedown", hide); + + var searchDiv = $("
",{class:"red-ui-search-container"}).appendTo(picker); + searchInput = $('').attr("placeholder","Search icons").appendTo(searchDiv).searchBox({ + delay: 50, + change: function() { + var searchTerm = $(this).val().trim(); + if (searchTerm === "") { + iconList.find(".red-ui-icon-list-module").show(); + iconList.find(".red-ui-icon-list-icon").show(); + } else { + iconList.find(".red-ui-icon-list-module").hide(); + iconList.find(".red-ui-icon-list-icon").each(function(i,n) { + if ($(n).data('icon').indexOf(searchTerm) === -1) { + $(n).hide(); + } else { + $(n).show(); + } + }); + } + } + }); + + var row = $('
').appendTo(picker); + var iconList = $('
').appendTo(picker); + var metaRow = $('
').appendTo(picker); + var summary = $('').appendTo(metaRow); + var resetButton = $('').appendTo(metaRow).click(function(e) { + e.preventDefault(); + hide(); + done(null); + }); + var iconSets = RED.nodes.getIconSets(); + Object.keys(iconSets).forEach(function(moduleName) { + var icons = iconSets[moduleName]; + if (icons.length > 0) { + // selectIconModule.append($("").val(moduleName).text(moduleName)); + var header = $('
').text(moduleName).appendTo(iconList); + $('').prependTo(header); + icons.forEach(function(icon) { + var iconDiv = $('
',{class:"red-ui-icon-list-icon"}).appendTo(iconList); + var nodeDiv = $('
',{class:"red-ui-search-result-node"}).appendTo(iconDiv); + var colour = node._def.color; + var icon_url = "icons/"+moduleName+"/"+icon; + iconDiv.data('icon',icon_url) + nodeDiv.css('backgroundColor',colour); + var iconContainer = $('
',{class:"palette_icon_container"}).appendTo(nodeDiv); + $('
',{class:"palette_icon",style:"background-image: url("+icon_url+")"}).appendTo(iconContainer); + + if (iconPath.module === moduleName && iconPath.file === icon) { + iconDiv.addClass("selected"); + } + iconDiv.on("mouseover", function() { + summary.text(icon); + }) + iconDiv.on("mouseout", function() { + summary.html(" "); + }) + iconDiv.click(function() { + hide(); + done(moduleName+"/"+icon); + }) + }) + } + }); + picker.slideDown(100); + searchInput.focus(); + } + function buildLabelForm(container,node) { var dialogForm = $('
').appendTo(container); @@ -748,81 +807,36 @@ RED.editor = (function() { } if ((!node._def.defaults || !node._def.defaults.hasOwnProperty("icon"))) { - $('
').appendTo(dialogForm); - var iconDiv = $("#node-settings-icon"); - $('