diff --git a/editor/js/main.js b/editor/js/main.js
index 8af2c7a35..59ec5e814 100644
--- a/editor/js/main.js
+++ b/editor/js/main.js
@@ -171,10 +171,10 @@
function loadEditor() {
var menuOptions = [];
menuOptions.push({id:"menu-item-view-menu",label:RED._("menu.label.view.view"),options:[
- {id:"menu-item-view-show-grid",label:RED._("menu.label.view.showGrid"),toggle:true,onselect:"core:toggle-show-grid"},
- {id:"menu-item-view-snap-grid",label:RED._("menu.label.view.snapGrid"),toggle:true,onselect:"core:toggle-snap-grid"},
- {id:"menu-item-status",label:RED._("menu.label.displayStatus"),toggle:true,onselect:"core:toggle-status", selected: true},
- null,
+ // {id:"menu-item-view-show-grid",setting:"view-show-grid",label:RED._("menu.label.view.showGrid"),toggle:true,onselect:"core:toggle-show-grid"},
+ // {id:"menu-item-view-snap-grid",setting:"view-snap-grid",label:RED._("menu.label.view.snapGrid"),toggle:true,onselect:"core:toggle-snap-grid"},
+ // {id:"menu-item-status",setting:"node-show-status",label:RED._("menu.label.displayStatus"),toggle:true,onselect:"core:toggle-status", selected: true},
+ //null,
// {id:"menu-item-bidi",label:RED._("menu.label.view.textDir"),options:[
// {id:"menu-item-bidi-default",toggle:"text-direction",label:RED._("menu.label.view.defaultDir"),selected: true, onselect:function(s) { if(s){RED.text.bidi.setTextDirection("")}}},
// {id:"menu-item-bidi-ltr",toggle:"text-direction",label:RED._("menu.label.view.ltr"), onselect:function(s) { if(s){RED.text.bidi.setTextDirection("ltr")}}},
@@ -182,7 +182,8 @@
// {id:"menu-item-bidi-auto",toggle:"text-direction",label:RED._("menu.label.view.auto"), onselect:function(s) { if(s){RED.text.bidi.setTextDirection("auto")}}}
// ]},
// null,
- {id:"menu-item-sidebar",label:RED._("menu.label.sidebar.show"),toggle:true,onselect:"core:toggle-sidebar", selected: true}
+ {id:"menu-item-sidebar",label:RED._("menu.label.sidebar.show"),toggle:true,onselect:"core:toggle-sidebar", selected: true},
+ null
]});
menuOptions.push(null);
menuOptions.push({id:"menu-item-import",label:RED._("menu.label.import"),options:[
@@ -217,7 +218,6 @@
menuOptions.push(null);
menuOptions.push({id:"menu-item-keyboard-shortcuts",label:RED._("menu.label.keyboardShortcuts"),onselect:"core:show-help"});
- menuOptions.push({id:"menu-item-show-tips",label:RED._("menu.label.showTips"),toggle:true,selected:true,onselect:"core:toggle-show-tips"});
menuOptions.push({id:"menu-item-help",
label: RED.settings.theme("menu.menu-item-help.label","Node-RED website"),
href: RED.settings.theme("menu.menu-item-help.url","http://nodered.org/docs")
diff --git a/editor/js/ui/actions.js b/editor/js/ui/actions.js
index 78b9a4c99..a56069579 100644
--- a/editor/js/ui/actions.js
+++ b/editor/js/ui/actions.js
@@ -21,7 +21,7 @@ RED.actions = (function() {
var result = [];
Object.keys(actions).forEach(function(action) {
var shortcut = RED.keyboard.getShortcut(action);
- result.push({id:action,scope:shortcut?shortcut.scope:undefined,key:shortcut?shortcut.key:undefined})
+ result.push({id:action,scope:shortcut?shortcut.scope:undefined,key:shortcut?shortcut.key:undefined,user:shortcut?shortcut.user:undefined})
})
return result;
}
diff --git a/editor/js/ui/common/editableList.js b/editor/js/ui/common/editableList.js
index 33c5c9843..437da24e5 100644
--- a/editor/js/ui/common/editableList.js
+++ b/editor/js/ui/common/editableList.js
@@ -170,7 +170,7 @@
var that = this;
var count = 0;
if (!this.activeFilter) {
- this.element.children().show();
+ return this.element.children().show();
}
var items = this.items();
items.each(function (i,el) {
diff --git a/editor/js/ui/common/menu.js b/editor/js/ui/common/menu.js
index 89a783883..6f803a659 100644
--- a/editor/js/ui/common/menu.js
+++ b/editor/js/ui/common/menu.js
@@ -28,7 +28,17 @@ RED.menu = (function() {
}
function setInitialState() {
- var savedStateActive = isSavedStateActive(opt.id);
+ var savedStateActive = RED.settings.get("menu-" + opt.id);
+ if (opt.setting) {
+ // May need to migrate pre-0.17 setting
+
+ if (savedStateActive !== null) {
+ RED.settings.set(opt.setting,savedStateActive);
+ RED.settings.remove("menu-" + opt.id);
+ } else {
+ savedStateActive = RED.settings.get(opt.setting);
+ }
+ }
if (savedStateActive) {
link.addClass("active");
triggerAction(opt.id,true);
@@ -176,18 +186,10 @@ RED.menu = (function() {
}
}
- function isSavedStateActive(id) {
- return RED.settings.get("menu-" + id);
- }
-
function isSelected(id) {
return $("#" + id).hasClass("active");
}
- function setSavedState(id, state) {
- RED.settings.set("menu-" + id, state);
- }
-
function setSelected(id,state) {
if (isSelected(id) == state) {
return;
@@ -201,7 +203,7 @@ RED.menu = (function() {
if (opt && opt.onselect) {
triggerAction(opt.id,state);
}
- setSavedState(id, state);
+ RED.settings.set(opt.setting||("menu-"+opt.id), state);
}
function toggleSelected(id) {
diff --git a/editor/js/ui/common/tabs.js b/editor/js/ui/common/tabs.js
index ab5460e0a..d5e0c95b8 100644
--- a/editor/js/ui/common/tabs.js
+++ b/editor/js/ui/common/tabs.js
@@ -26,6 +26,9 @@ RED.tabs = (function() {
var wrapper = ul.wrap( "
" ).parent();
var scrollContainer = ul.wrap( "
" ).parent();
wrapper.addClass("red-ui-tabs");
+ if (options.vertical) {
+ wrapper.addClass("red-ui-tabs-vertical");
+ }
if (options.addButton && typeof options.addButton === 'function') {
wrapper.addClass("red-ui-tabs-add");
var addButton = $('
').appendTo(wrapper);
@@ -146,6 +149,9 @@ RED.tabs = (function() {
}
function updateTabWidths() {
+ if (options.vertical) {
+ return;
+ }
var tabs = ul.find("li.red-ui-tab");
var width = wrapper.width();
var tabCount = tabs.size();
diff --git a/editor/js/ui/keyboard.js b/editor/js/ui/keyboard.js
index 9d4a56466..f645b3b55 100644
--- a/editor/js/ui/keyboard.js
+++ b/editor/js/ui/keyboard.js
@@ -48,6 +48,7 @@ RED.keyboard = (function() {
93: true
}
var actionToKeyMap = {}
+ var defaultKeyMap = {};
// FF generates some different keycodes because reasons.
var firefoxKeyCodeMap = {
@@ -57,20 +58,45 @@ RED.keyboard = (function() {
}
function init() {
+ var userKeymap = RED.settings.get('keymap') || {};
$.getJSON("red/keymap.json",function(data) {
for (var scope in data) {
if (data.hasOwnProperty(scope)) {
var keys = data[scope];
for (var key in keys) {
if (keys.hasOwnProperty(key)) {
- addHandler(scope,key,keys[key]);
+ if (!userKeymap.hasOwnProperty(keys[key])) {
+ addHandler(scope,key,keys[key],false);
+ defaultKeyMap[keys[key]] = {
+ scope:scope,
+ key:key,
+ user:false
+ };
+ }
}
}
}
}
+ for (var action in userKeymap) {
+ if (userKeymap.hasOwnProperty(action)) {
+ var obj = userKeymap[action];
+ if (obj.hasOwnProperty('key')) {
+ addHandler(obj.scope, obj.key, action, true);
+ }
+ }
+ }
})
- RED.actions.add("core:show-help", showKeyboardHelp);
+ }
+ function revertToDefault(action) {
+ var currentAction = actionToKeyMap[action];
+ if (currentAction) {
+ removeHandler(currentAction.key);
+ }
+ if (defaultKeyMap.hasOwnProperty(action)) {
+ var obj = defaultKeyMap[action];
+ addHandler(obj.scope, obj.key, action, false);
+ }
}
function parseKeySpecifier(key) {
var parts = key.toLowerCase().split("-");
@@ -126,10 +152,12 @@ RED.keyboard = (function() {
if (partialState) {
partialState = null;
return resolveKeyEvent(evt);
- } else {
+ } else if (Object.keys(handler).length > 0) {
partialState = handler;
evt.preventDefault();
return null;
+ } else {
+ return null;
}
} else if (handler.scope && handler.scope !== "*") {
var target = evt.target;
@@ -174,6 +202,9 @@ RED.keyboard = (function() {
if (typeof key === 'string') {
if (typeof cbdown === 'string') {
actionToKeyMap[cbdown] = {scope:scope,key:key};
+ if (typeof ondown === 'boolean') {
+ actionToKeyMap[cbdown].user = ondown;
+ }
}
var parts = key.split(" ");
for (i=0;i
';
- function showKeyboardHelp() {
- if (!RED.settings.theme("menu.menu-item-keyboard-shortcuts",true)) {
- return;
- }
- if (!shortcutDialog) {
- shortcutDialog = $('')
- .appendTo("body");
-
- var shortcutList = $('#keyboard-shortcut-list').editableList({
- addButton: false,
- scrollOnAdd: false,
- addItem: function(container,i,object) {
- var item = $('').appendTo(container);
-
- var key = $('
').appendTo(item);
- if (object.key) {
- key.append(formatKey(object.key));
- } else {
- item.addClass("keyboard-shortcut-entry-unassigned");
- key.html(RED._('keyboard.unassigned'));
- }
-
- var text = object.id.replace(/(^.+:([a-z]))|(-([a-z]))/g,function() {
- if (arguments[5] === 0) {
- return arguments[2].toUpperCase();
- } else {
- return " "+arguments[4].toUpperCase();
- }
- });
- var label = $('
').html(text).appendTo(item);
- if (object.scope) {
- $('
').html(object.scope).appendTo(item);
- }
-
-
- },
- });
- var shortcuts = RED.actions.list();
- shortcuts.sort(function(A,B) {
- return A.id.localeCompare(B.id);
- });
- shortcuts.forEach(function(s) {
- shortcutList.editableList('addItem',s);
- })
-
- shortcutDialog.dialog({
- modal: true,
- autoOpen: false,
- width: "800",
- height: "400",
- title:RED._("keyboard.title"),
- resizable: false
- });
- }
-
- shortcutDialog.dialog("open");
- }
function formatKey(key) {
var formattedKey = isMac?key.replace(/ctrl-?/,"⌘"):key;
formattedKey = isMac?formattedKey.replace(/alt-?/,"⌥"):key;
@@ -332,6 +303,206 @@ RED.keyboard = (function() {
return '
'+formattedKey.split(" ").join(' ')+'';
}
+ function validateKey(key) {
+ key = key.trim();
+ var parts = key.split(" ");
+ for (i=0;i
').attr('placeholder',RED._('keyboard.unassigned')).val(object.key||"").appendTo(key);
+ keyInput.on("keyup",function(e) {
+ if (e.keyCode === 13) {
+ return endEditShortcut();
+ }
+ var currentVal = $(this).val();
+ currentVal = currentVal.trim();
+ var valid = (currentVal === "" || RED.keyboard.validateKey(currentVal));
+ $(this).toggleClass("input-error",!valid);
+ })
+
+ var scopeSelect = $('').appendTo(scope);
+ scopeSelect.val(object.scope||'*');
+
+ var div = $('').appendTo(scope);
+ var okButton = $('').appendTo(div);
+ var revertButton = $('').appendTo(div);
+
+ okButton.click(function(e) {
+ e.stopPropagation();
+ endEditShortcut();
+ });
+ revertButton.click(function(e) {
+ e.stopPropagation();
+ RED.keyboard.revertToDefault(object.id);
+ container.empty();
+ container.removeClass('keyboard-shortcut-entry-expanded');
+ var shortcut = RED.keyboard.getShortcut(object.id);
+ var userKeymap = RED.settings.get('keymap') || {};
+ delete userKeymap[object.id];
+ RED.settings.set('keymap',userKeymap);
+
+ var obj = {
+ id:object.id,
+ scope:shortcut?shortcut.scope:undefined,
+ key:shortcut?shortcut.key:undefined,
+ user:shortcut?shortcut.user:undefined
+ }
+ buildShortcutRow(container,obj);
+ })
+
+ keyInput.focus();
+ }
+ }
+
+ function endEditShortcut(cancel) {
+ var container = $('.keyboard-shortcut-entry-expanded');
+ if (container.length === 1) {
+ var object = container.data('data');
+ var keyInput = container.find(".keyboard-shortcut-entry-key input");
+ var scopeSelect = container.find(".keyboard-shortcut-entry-scope select");
+ if (!cancel) {
+ var key = keyInput.val().trim();
+ var scope = scopeSelect.val();
+ var valid = (key === "" || RED.keyboard.validateKey(key));
+ if (valid) {
+ var current = RED.keyboard.getShortcut(object.id);
+ if ((!current && key) || (current && (current.scope !== scope || current.key !== key))) {
+ var keyDiv = container.find(".keyboard-shortcut-entry-key");
+ var scopeDiv = container.find(".keyboard-shortcut-entry-scope");
+ keyDiv.empty();
+ scopeDiv.empty();
+ if (object.key) {
+ RED.keyboard.remove(object.key,true);
+ }
+ container.find(".keyboard-shortcut-entry-text i").css("opacity",1);
+ if (key === "") {
+ keyDiv.parent().addClass("keyboard-shortcut-entry-unassigned");
+ keyDiv.append($('').text(RED._('keyboard.unassigned')) );
+ delete object.key;
+ delete object.scope;
+ } else {
+ keyDiv.parent().removeClass("keyboard-shortcut-entry-unassigned");
+ keyDiv.append(RED.keyboard.formatKey(key))
+ $("").text(scope).appendTo(scopeDiv);
+ object.key = key;
+ object.scope = scope;
+ RED.keyboard.add(object.scope,object.key,object.id,true);
+ }
+ var userKeymap = RED.settings.get('keymap') || {};
+ userKeymap[object.id] = RED.keyboard.getShortcut(object.id);
+ RED.settings.set('keymap',userKeymap);
+ }
+ }
+ }
+ keyInput.remove();
+ scopeSelect.remove();
+ $('.keyboard-shortcut-edit').remove();
+ container.removeClass('keyboard-shortcut-entry-expanded');
+ }
+ }
+
+ function buildShortcutRow(container,object) {
+ var item = $('').appendTo(container);
+ container.data('data',object);
+
+ var text = object.id.replace(/(^.+:([a-z]))|(-([a-z]))/g,function() {
+ if (arguments[5] === 0) {
+ return arguments[2].toUpperCase();
+ } else {
+ return " "+arguments[4].toUpperCase();
+ }
+ });
+ var label = $('
').addClass("keyboard-shortcut-entry-text").text(text).appendTo(item);
+
+ var user = $('
').prependTo(label);
+
+ if (!object.user) {
+ user.css("opacity",0);
+ }
+
+ var key = $('
').appendTo(item);
+ if (object.key) {
+ key.append(RED.keyboard.formatKey(object.key));
+ } else {
+ item.addClass("keyboard-shortcut-entry-unassigned");
+ key.append($('
').text(RED._('keyboard.unassigned')) );
+ }
+
+ var scope = $('').appendTo(item);
+
+ $("
").text(object.scope === '*'?'global':object.scope||"").appendTo(scope);
+ container.click(editShortcut);
+ }
+
+ function getSettingsPane() {
+ var pane = $('');
+
+ $('').appendTo(pane);
+
+ pane.find("input").searchBox({
+ delay: 100,
+ change: function() {
+ var filterValue = $(this).val().trim();
+ if (filterValue === "") {
+ shortcutList.editableList('filter', null);
+ } else {
+ filterValue = filterValue.replace(/\s/g,"");
+ shortcutList.editableList('filter', function(data) {
+ return data.id.toLowerCase().replace(/^.*:/,"").replace("-","").indexOf(filterValue) > -1;
+ })
+ }
+ }
+ });
+
+ var shortcutList = $('
').css({
+ position: "absolute",
+ top: "32px",
+ bottom: "0",
+ left: "0",
+ right: "0"
+ }).appendTo(pane).editableList({
+ addButton: false,
+ scrollOnAdd: false,
+ addItem: function(container,i,object) {
+ buildShortcutRow(container,object);
+ },
+
+ });
+ var shortcuts = RED.actions.list();
+ shortcuts.sort(function(A,B) {
+ var Aid = A.id.replace(/^.*:/,"").replace(/[ -]/g,"").toLowerCase();
+ var Bid = B.id.replace(/^.*:/,"").replace(/[ -]/g,"").toLowerCase();
+ return Aid.localeCompare(Bid);
+ });
+ shortcuts.forEach(function(s) {
+ shortcutList.editableList('addItem',s);
+ });
+ return pane;
+ }
+
return {
init: init,
add: addHandler,
@@ -339,7 +510,10 @@ RED.keyboard = (function() {
getShortcut: function(actionName) {
return actionToKeyMap[actionName];
},
- formatKey: formatKey
+ revertToDefault: revertToDefault,
+ formatKey: formatKey,
+ validateKey: validateKey,
+ getSettingsPane: getSettingsPane
}
})();
diff --git a/editor/js/ui/tab-info.js b/editor/js/ui/tab-info.js
index be97a7da9..1210b8449 100644
--- a/editor/js/ui/tab-info.js
+++ b/editor/js/ui/tab-info.js
@@ -74,7 +74,7 @@ RED.sidebar.info = (function() {
tipClose.click(function(e) {
e.preventDefault();
RED.actions.invoke("core:toggle-show-tips");
- RED.notify("You can re-open the tips from the side menu");
+ RED.notify(RED._("sidebar.info.showTips"));
});
RED.sidebar.addTab({
@@ -267,7 +267,7 @@ RED.sidebar.info = (function() {
RED.actions.add("core:toggle-show-tips",function(state) {
if (state === undefined) {
- RED.menu.toggleSelected("menu-item-show-tips");
+ RED.userSettings.toggle("view-show-tips");
} else {
enabled = state;
if (enabled) {
diff --git a/editor/js/ui/userSettings.js b/editor/js/ui/userSettings.js
index 393422c93..1a43de726 100644
--- a/editor/js/ui/userSettings.js
+++ b/editor/js/ui/userSettings.js
@@ -16,14 +16,15 @@
RED.userSettings = (function() {
- var trayWidth = null;
+ var trayWidth = 700;
var settingsVisible = false;
- function show() {
+ function show(initialTab) {
if (settingsVisible) {
return;
}
settingsVisible = true;
+ var tabContainer;
var trayOptions = {
title: "User Settings",
@@ -42,17 +43,20 @@ RED.userSettings = (function() {
},
open: function(tray) {
var trayBody = tray.find('.editor-tray-body');
+ var tabContainer = $('',{id:"user-settings-tabs-container"}).appendTo(trayBody);
- $('',{id:"user-settings-tabs"}).appendTo(trayBody);
+ $('',{id:"user-settings-tabs"}).appendTo(tabContainer);
var tabContents = $('',{id:"user-settings-tabs-content"}).appendTo(trayBody);
- $('View Tab
').appendTo(tabContents);
- $('Keyboard Tab
').appendTo(tabContents);
- $('Something Tab
').appendTo(tabContents);
+ createViewPane().hide().appendTo(tabContents);
+ RED.keyboard.getSettingsPane().hide().appendTo(tabContents);
+
+ $('').appendTo(tabContents);
var tabs = RED.tabs.create({
id: "user-settings-tabs",
+ vertical: true,
onchange: function(tab) {
$("#user-settings-tabs-content").children().hide();
$("#" + tab.id).show();
@@ -64,15 +68,31 @@ RED.userSettings = (function() {
});
tabs.addTab({
id: "user-settings-tab-keyboard",
- label: "Keyboard Shortcuts"
+ label: "Keyboard"
});
tabs.addTab({
- id: "user-settings-tab-something",
- label: "Something Else"
+ id: "user-settings-tab-palette",
+ label: "Palette"
});
+ if (initialTab) {
+ tabs.activateTab("user-settings-tab-"+initialTab)
+ }
},
close: function() {
settingsVisible = false;
+
+ viewSettings.forEach(function(section) {
+ section.options.forEach(function(opt) {
+ var input = $("#user-settings-"+opt.setting);
+ if (opt.toggle) {
+ setSelected(opt.setting,input.prop('checked'));
+ } else {
+ setSelected(opt.setting,input.val());
+ }
+ });
+ })
+
+
},
show: function() {}
}
@@ -82,10 +102,99 @@ RED.userSettings = (function() {
RED.tray.show(trayOptions);
}
+ var viewSettings = [
+ {
+ title: "Grid",
+ options: [
+ {setting:"view-show-grid",label:"menu.label.view.showGrid",toggle:true,onchange:"core:toggle-show-grid"},
+ {setting:"view-snap-grid",label:"menu.label.view.snapGrid",toggle:true,onchange:"core:toggle-snap-grid"},
+ {setting:"view-grid-size",label:"menu.label.view.gridSize",type:"number",default: 20, onchange:RED.view.gridSize}
+ ]
+ },
+ {
+ title: "Nodes",
+ options: [
+ {setting:"view-node-status",label:"menu.label.displayStatus",toggle:true,onchange:"core:toggle-status", selected: true}
+ ]
+ },
+ {
+ title: "Other",
+ options: [
+ {setting:"view-show-tips",label:"menu.label.showTips",toggle:true,default:true,onchange:"core:toggle-show-tips"}
+ ]
+ }
+ ];
+
+ var allSettings = {};
+
+ function createViewPane() {
+
+ var pane = $('');
+
+ viewSettings.forEach(function(section) {
+ $('').text(section.title).appendTo(pane);
+ section.options.forEach(function(opt) {
+ var initialState = RED.settings.get(opt.setting);
+ var row = $('').appendTo(pane);
+ var input;
+ if (opt.toggle) {
+ input = $('').appendTo(row).find("input");
+ input.prop('checked',initialState);
+ } else {
+ $('').appendTo(row);
+ $('').appendTo(row).val(initialState);
+ }
+ });
+ })
+ return pane;
+ }
+
+ function setSelected(id, value) {
+ var opt = allSettings[id];
+ RED.settings.set(opt.setting,value);
+ var callback = opt.onchange;
+ if (typeof callback === 'string') {
+ callback = RED.actions.get(callback);
+ }
+ if (callback) {
+ callback.call(opt,value);
+ }
+ }
+ function toggle(id) {
+ var opt = allSettings[id];
+ var state = RED.settings.get(opt.setting);
+ setSelected(id,!state);
+ }
+
+
function init() {
RED.actions.add("core:show-user-settings",show);
+ RED.actions.add("core:show-help", function() { show('keyboard')});
+
+ viewSettings.forEach(function(section) {
+ section.options.forEach(function(opt) {
+ allSettings[opt.setting] = opt;
+ if (opt.onchange) {
+ var value = RED.settings.get(opt.setting);
+ if (value === null && opt.hasOwnProperty('default')) {
+ value = opt.default;
+ RED.settings.set(opt.setting,value);
+ }
+
+ var callback = opt.onchange;
+ if (typeof callback === 'string') {
+ callback = RED.actions.get(callback);
+ }
+ if (callback) {
+ callback.call(opt,value);
+ }
+ }
+ });
+ });
+
}
return {
- init: init
+ init: init,
+ toggle: toggle
};
})();
diff --git a/editor/js/ui/view.js b/editor/js/ui/view.js
index b67a91d0a..926503639 100644
--- a/editor/js/ui/view.js
+++ b/editor/js/ui/view.js
@@ -239,6 +239,41 @@ RED.view = (function() {
});
grid.style("visibility","hidden");
+ updateGrid();
+
+ function updateGrid() {
+ grid.selectAll("line.horizontal").remove();
+ grid.selectAll("line.horizontal").data(gridScale.ticks(space_width/gridSize)).enter()
+ .append("line")
+ .attr(
+ {
+ "class":"horizontal",
+ "x1" : 0,
+ "x2" : space_width,
+ "y1" : function(d){ return gridScale(d);},
+ "y2" : function(d){ return gridScale(d);},
+ "fill" : "none",
+ "shape-rendering" : "crispEdges",
+ "stroke" : "#eee",
+ "stroke-width" : "1px"
+ });
+ grid.selectAll("line.vertical").remove();
+ grid.selectAll("line.vertical").data(gridScale.ticks(space_width/gridSize)).enter()
+ .append("line")
+ .attr(
+ {
+ "class":"vertical",
+ "y1" : 0,
+ "y2" : space_width,
+ "x1" : function(d){ return gridScale(d);},
+ "x2" : function(d){ return gridScale(d);},
+ "fill" : "none",
+ "shape-rendering" : "crispEdges",
+ "stroke" : "#eee",
+ "stroke-width" : "1px"
+ });
+ }
+
var dragGroup = vis.append("g");
var drag_lines = [];
@@ -408,21 +443,21 @@ RED.view = (function() {
RED.actions.add("core:toggle-show-grid",function(state) {
if (state === undefined) {
- RED.menu.toggleSelected("menu-item-view-show-grid");
+ RED.userSettings.toggle("view-show-grid");
} else {
toggleShowGrid(state);
}
});
RED.actions.add("core:toggle-snap-grid",function(state) {
if (state === undefined) {
- RED.menu.toggleSelected("menu-item-view-snap-grid");
+ RED.userSettings.toggle("view-snap-grid");
} else {
toggleSnapGrid(state);
}
});
RED.actions.add("core:toggle-status",function(state) {
if (state === undefined) {
- RED.menu.toggleSelected("menu-item-status");
+ RED.userSettings.toggle("view-node-status");
} else {
toggleStatus(state);
}
@@ -2743,6 +2778,14 @@ RED.view = (function() {
RED.sidebar.config.show(id);
}
}
+ },
+ gridSize: function(v) {
+ if (v === undefined) {
+ return gridSize;
+ } else {
+ gridSize = v;
+ updateGrid();
+ }
}
};
diff --git a/editor/sass/editor.scss b/editor/sass/editor.scss
index 499b33a8e..01ca54bca 100644
--- a/editor/sass/editor.scss
+++ b/editor/sass/editor.scss
@@ -46,6 +46,7 @@
overflow: auto;
}
.editor-tray-body {
+ position: relative;
form {
margin: 20px;
}
diff --git a/editor/sass/keyboard.scss b/editor/sass/keyboard.scss
index e272b238a..27eca649f 100644
--- a/editor/sass/keyboard.scss
+++ b/editor/sass/keyboard.scss
@@ -19,31 +19,88 @@
padding-top: 10px;
}
+
+#user-settings-tab-keyboard .red-ui-editableList-container {
+ border-radius: 0;
+ border: none;
+ padding: 0;
+}
+
+
.keyboard-shortcut-entry.keyboard-shortcut-list-header {
- padding:0 30px 0 5px;
+ padding:0 5px 0 5px;
div {
color: #666 !important;
}
+ .red-ui-searchBox-container {
+ width: calc(100% - 20px);
+ }
+ .keyboard-shortcut-entry-scope {
+ text-align: center;
+ }
}
-#keyboard-shortcut-list {
+
+.keyboard-shortcut-list-header {
+ border-bottom: 1px solid $primary-border-color;
+
+}
+.keyboard-shortcut-list {
position: absolute;
top:30px;
left:10px;
right:10px;
bottom:10px;
+ li {
+ padding: 0;
+ .red-ui-editableList-item-content {
+ padding: 8px;
+ cursor: pointer;
+ }
+ }
+ li:hover {
+ background: #f6f6f6;
+ }
}
.keyboard-shortcut-entry {
- padding: 0px 20px 0 10px;
div {
display: inline-block;
}
+ // white-space: nowrap;
+
+ select {
+ margin: 0;
+ width: calc(100% - 30px);
+ font-size: 0.9em;
+ margin-right: 5px;
+ }
}
.keyboard-shortcut-entry-key {
- width:150px;
+ width:160px;
+ vertical-align: middle;
+ input {
+ margin:0;
+ width: calc(100% - 5px);
+ }
+}
+.keyboard-shortcut-entry-text {
+ vertical-align: middle;
+ width: calc(100% - 160px - 100px - 10px);
+ overflow: hidden;
+ i {
+ color: #ccc;
+ margin-right: 5px;
+ }
}
.keyboard-shortcut-entry-scope {
- float: right;
+ width:100px;
color: #999;
+ vertical-align: middle;
+ text-align: right;
+}
+.keyboard-shortcut-entry:not(.keyboard-shortcut-list-header) {
+ .keyboard-shortcut-entry-scope {
+ font-size: 0.8em;
+ }
}
.keyboard-shortcut-entry-unassigned {
color: #999;
@@ -51,7 +108,21 @@
font-style: italic;
}
}
-
+.keyboard-shortcut-entry-expanded {
+ .keyboard-shortcut-entry-key {
+ width: 150px;
+ }
+ .keyboard-shortcut-entry-text {
+ }
+ .keyboard-shortcut-entry-scope {
+ width: 110px;
+ }
+ span {
+ display: none;
+ }
+}
+.keyboard-shortcut-edit {
+}
.help-key {
border: 1px solid #ddd;
padding: 4px;
diff --git a/editor/sass/mixins.scss b/editor/sass/mixins.scss
index 9896cb102..e817ec40b 100644
--- a/editor/sass/mixins.scss
+++ b/editor/sass/mixins.scss
@@ -80,12 +80,28 @@
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
+ .button-group-vertical & {
+ display: block;
+ min-width: 22px;
+ }
+ .button-group-vertical &:not(:first-child) {
+ border-top: none;
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+ }
+ .button-group-vertical &:not(:last-child) {
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+ }
&:focus {
outline: 1px solid $workspace-button-color-focus-outline;
}
}
-
+.button-group-vertical {
+ display: inline-block;
+ vertical-align: middle;
+}
.button-group:not(:last-child) {
margin-right: 10px;
}
diff --git a/editor/sass/style.scss b/editor/sass/style.scss
index f6b267e7b..c8022a6f8 100644
--- a/editor/sass/style.scss
+++ b/editor/sass/style.scss
@@ -45,6 +45,8 @@
@import "palette-editor";
@import "diff";
+@import "userSettings";
+
@import "ui/common/editableList";
@import "ui/common/searchBox";
diff --git a/editor/sass/tabs.scss b/editor/sass/tabs.scss
index 636dabd51..4b2dc7f5d 100644
--- a/editor/sass/tabs.scss
+++ b/editor/sass/tabs.scss
@@ -113,6 +113,50 @@
&.red-ui-tabs-add.red-ui-tabs-scrollable {
padding-right: 59px;
}
+
+ &.red-ui-tabs-vertical {
+ box-sizing: border-box;
+ height: 100%;
+ border-right: 1px solid $primary-border-color;
+ margin: 0;
+ background: #f3f3f3;
+ overflow: visible;
+
+ .red-ui-tabs-scroll-container {
+ height: auto;
+ overflow-x:visible;
+ overflow-y: scroll;
+ }
+
+ & ul {
+ padding: 0;
+ height: auto;
+ border: none;
+ width: calc(100% + 1px);
+ li {
+ width: 100%;
+ display: block;
+ margin: 0;
+ border: none;
+ border-right: 1px solid $primary-border-color;
+ height: auto;
+ &:not(:first-child) {
+ border-top: 1px solid $secondary-border-color;
+ }
+ &:last-child {
+ border-bottom: 1px solid $secondary-border-color;
+ }
+
+ a.red-ui-tab-label {
+ padding: 9px;
+ }
+
+ &.active {
+ border-right: 1px solid #fff;
+ }
+ }
+ }
+ }
}
.red-ui-tab-button {
position: absolute;
diff --git a/editor/sass/userSettings.scss b/editor/sass/userSettings.scss
new file mode 100644
index 000000000..0fe07409e
--- /dev/null
+++ b/editor/sass/userSettings.scss
@@ -0,0 +1,59 @@
+/**
+ * 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.
+ **/
+
+#user-settings-tabs-container {
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ width: 120px;
+ background: #f3f3f3;
+}
+#user-settings-tabs-content {
+ position: absolute;
+ top: 0;
+ left: 120px;
+ right: 0;
+ bottom: 0;
+ padding: 0;
+ h3:not(:first-child) {
+ border-top: 1px solid $secondary-border-color;
+ margin-top: 15px;
+ margin-bottom: 10px;
+ padding-top: 20px;
+ }
+ label {
+ display: inline-block;
+ min-width: 100px;
+ input {
+ vertical-align: top;
+ padding-bottom: 0;
+ }
+ }
+ input {
+ margin-bottom: 0;
+ }
+ input[type='number'] {
+ width: 60px;
+ }
+}
+
+#user-settings-tab-view {
+ padding: 8px 20px 20px;
+}
+.user-settings-row {
+ padding: 5px 10px 2px;
+}
diff --git a/red/api/locales/en-US/editor.json b/red/api/locales/en-US/editor.json
index 4084b1cea..c572ed4b0 100644
--- a/red/api/locales/en-US/editor.json
+++ b/red/api/locales/en-US/editor.json
@@ -31,6 +31,7 @@
"view": "View",
"showGrid": "Show grid",
"snapGrid": "Snap to grid",
+ "gridSize": "Grid size",
"textDir": "Text Direction",
"defaultDir": "Default",
"ltr": "Left-to-right",
@@ -354,7 +355,8 @@
"info": "Information",
"blank": "blank",
"null": "null",
- "arrayItems": "__count__ items"
+ "arrayItems": "__count__ items",
+ "showTips":"You can open the tips from the settings panel"
},
"config": {
"name": "Configuration nodes",
diff --git a/red/api/locales/en-US/infotips.json b/red/api/locales/en-US/infotips.json
index 46ce4502c..1f3a4f9a0 100644
--- a/red/api/locales/en-US/infotips.json
+++ b/red/api/locales/en-US/infotips.json
@@ -5,7 +5,7 @@
"tip2" : "{{core:toggle-sidebar}} will toggle the view of this sidebar",
"tip3" : "You can manage your palette of nodes with {{core:manage-palette}}",
"tip4" : "Your flow configuration nodes are listed in the sidebar panel. It can been accessed from the menu or with {{core:show-config-tab}}",
- "tip5" : "Enable or disable these tips from the option in the menu",
+ "tip5" : "Enable or disable these tips from the option in the settings",
"tip6" : "Move the selected nodes using the [left] [up] [down] and [right] keys. Hold [shift] to nudge them further",
"tip7" : "Dragging a node onto a wire will splice it into the link",
"tip8" : "Export the selected nodes, or the current tab with {{core:show-export-dialog}}",
@@ -19,15 +19,5 @@
"tip16" : "Switch flow tabs with {{core:show-previous-tab}} and {{core:show-next-tab}}",
"tip17" : "You can confirm your changes in the node edit tray with {{core:confirm-edit-tray}} or cancel them with {{core:cancel-edit-tray}}",
"tip18" : "Pressing {{core:edit-selected-node}} will edit the first node in the current selection"
- },
- "info-tbd": {
- "tip1" : "Press the Deploy
button above to start the flow running. You can choose to deploy the whole flow or just the changes.",
- "tip2" : "Options like Show grid and Snap to grid are under the menu icon
View",
- "tip4" : " Manage palette can be used to find, add and remove extra nodes.",
- "tip5" : "Nodes may install examples under
Import Examples",
- "tip6" : "Lots of example flows can be found on flows.nodered.org
They can then be imported by drag and drop to the workspace.",
- "tip7" : "Shift-click and drag on a connector to move all the attached wires in one go.",
- "tip8" : "The Node-RED Dashboard package can be used to create simple User Interfaces.",
- "tip10": "Got a question?
Join us on Slack
or the
Node-RED Google group"
}
}