mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Overhaul keyboard handling and introduce editor actions
This commit is contained in:
		
							
								
								
									
										20
									
								
								Gruntfile.js
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								Gruntfile.js
									
									
									
									
									
								
							| @@ -117,6 +117,7 @@ module.exports = function(grunt) { | ||||
|                     "editor/js/ui/common/tabs.js", | ||||
|                     "editor/js/ui/common/typedInput.js", | ||||
|                     "editor/js/ui/utils.js", | ||||
|                     "editor/js/ui/actions.js", | ||||
|                     "editor/js/ui/deploy.js", | ||||
|                     "editor/js/ui/keyboard.js", | ||||
|                     "editor/js/ui/workspaces.js", | ||||
| @@ -194,6 +195,11 @@ module.exports = function(grunt) { | ||||
|                     'red/api/locales/en-US/editor.json', | ||||
|                     'red/runtime/locales/en-US/runtime.json' | ||||
|                 ] | ||||
|             }, | ||||
|             keymaps: { | ||||
|                 src: [ | ||||
|                     'editor/js/keymap.json' | ||||
|                 ] | ||||
|             } | ||||
|         }, | ||||
|         attachCopyright: { | ||||
| @@ -230,7 +236,7 @@ module.exports = function(grunt) { | ||||
|                 files: [ | ||||
|                     'editor/js/**/*.js' | ||||
|                 ], | ||||
|                 tasks: ['concat','uglify','attachCopyright:js'] | ||||
|                 tasks: ['copy:build','concat','uglify','attachCopyright:js'] | ||||
|             }, | ||||
|             sass: { | ||||
|                 files: [ | ||||
| @@ -246,6 +252,12 @@ module.exports = function(grunt) { | ||||
|                 ], | ||||
|                 tasks: ['jsonlint:messages'] | ||||
|             }, | ||||
|             keymaps: { | ||||
|                 files: [ | ||||
|                     'editor/js/keymap.json' | ||||
|                 ], | ||||
|                 tasks: ['jsonlint:keymaps','copy:build'] | ||||
|             }, | ||||
|             misc: { | ||||
|                 files: [ | ||||
|                     'CHANGELOG.md' | ||||
| @@ -284,6 +296,10 @@ module.exports = function(grunt) { | ||||
|                         src: 'editor/js/main.js', | ||||
|                         dest: 'public/red/main.js' | ||||
|                     }, | ||||
|                     { | ||||
|                         src: 'editor/js/keymap.json', | ||||
|                         dest: 'public/red/keymap.json' | ||||
|                     }, | ||||
|                     { | ||||
|                         cwd: 'editor/images', | ||||
|                         src: '**', | ||||
| @@ -443,7 +459,7 @@ module.exports = function(grunt) { | ||||
|  | ||||
|     grunt.registerTask('build', | ||||
|         'Builds editor content', | ||||
|         ['clean:build','concat:build','concat:vendor','copy:build','uglify:build','sass:build','jsonlint:messages','attachCopyright']); | ||||
|         ['clean:build','jsonlint','concat:build','concat:vendor','copy:build','uglify:build','sass:build','attachCopyright']); | ||||
|  | ||||
|     grunt.registerTask('dev', | ||||
|         'Developer mode: run node-red, watch for source changes and build/restart', | ||||
|   | ||||
							
								
								
									
										38
									
								
								editor/js/keymap.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								editor/js/keymap.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| { | ||||
|     "*": { | ||||
|         "ctrl-shift-p":"core:manage-palette", | ||||
|         "ctrl-f": "core:search", | ||||
|         "ctrl-=": "core:zoom-in", | ||||
|         "ctrl--": "core:zoom-out", | ||||
|         "ctrl-0": "core:zoom-reset", | ||||
|         "ctrl-enter": "core:confirm-edit-tray", | ||||
|         "ctrl-escape": "core:cancel-edit-tray", | ||||
|         "ctrl-g i": "core:show-info-tab", | ||||
|         "ctrl-g d": "core:show-debug-tab", | ||||
|         "ctrl-g c": "core:show-config-tab" | ||||
|     }, | ||||
|     "workspace": { | ||||
|         "ctrl-e": "core:export", | ||||
|         "ctrl-i": "core:import", | ||||
|         "backspace": "core:delete", | ||||
|         "delete": "core:delete", | ||||
|         "enter": "core:edit", | ||||
|         "ctrl-c": "core:copy", | ||||
|         "ctrl-x": "core:cut", | ||||
|         "ctrl-v": "core:paste", | ||||
|         "ctrl-z": "core:undo", | ||||
|         "ctrl-a": "core:select-all", | ||||
|         "shift-?": "core:show-help", | ||||
|         "ctrl-space": "core:toggle-sidebar", | ||||
|         "up": "core:move-selection-up", | ||||
|         "right": "core:move-selection-right", | ||||
|         "down": "core:move-selection-down", | ||||
|         "left": "core:move-selection-left", | ||||
|         "shift-up": "core:step-selection-up", | ||||
|         "shift-right": "core:step-selection-right", | ||||
|         "shift-down": "core:step-selection-down", | ||||
|         "shift-left": "core:step-selection-left", | ||||
|         "ctrl-shift-j": "core:show-previous-tab", | ||||
|         "ctrl-shift-k": "core:show-next-tab" | ||||
|      } | ||||
| } | ||||
| @@ -15,7 +15,6 @@ | ||||
|  **/ | ||||
| (function() { | ||||
|  | ||||
|  | ||||
|     function loadNodeList() { | ||||
|         $.ajax({ | ||||
|             headers: { | ||||
| @@ -170,12 +169,11 @@ | ||||
|     } | ||||
|  | ||||
|     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:RED.view.toggleShowGrid}, | ||||
|             {id:"menu-item-view-snap-grid",label:RED._("menu.label.view.snapGrid"),toggle:true,onselect:RED.view.toggleSnapGrid}, | ||||
|             {id:"menu-item-status",label:RED._("menu.label.displayStatus"),toggle:true,onselect:toggleStatus, selected: true}, | ||||
|             {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-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("")}}}, | ||||
| @@ -184,48 +182,46 @@ | ||||
|             //     {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:RED.sidebar.toggleSidebar, selected: true} | ||||
|             {id:"menu-item-sidebar",label:RED._("menu.label.sidebar.show"),toggle:true,onselect:"core:toggle-sidebar", selected: true} | ||||
|         ]}); | ||||
|         menuOptions.push(null); | ||||
|         menuOptions.push({id:"menu-item-import",label:RED._("menu.label.import"),options:[ | ||||
|             {id:"menu-item-import-clipboard",label:RED._("menu.label.clipboard"),onselect:RED.clipboard.import}, | ||||
|             {id:"menu-item-import-clipboard",label:RED._("menu.label.clipboard"),onselect:"core:import"}, | ||||
|             {id:"menu-item-import-library",label:RED._("menu.label.library"),options:[]} | ||||
|         ]}); | ||||
|         menuOptions.push({id:"menu-item-export",label:RED._("menu.label.export"),disabled:true,options:[ | ||||
|             {id:"menu-item-export-clipboard",label:RED._("menu.label.clipboard"),disabled:true,onselect:RED.clipboard.export}, | ||||
|             {id:"menu-item-export-library",label:RED._("menu.label.library"),disabled:true,onselect:RED.library.export} | ||||
|             {id:"menu-item-export-clipboard",label:RED._("menu.label.clipboard"),disabled:true,onselect:"core:export"}, | ||||
|             {id:"menu-item-export-library",label:RED._("menu.label.library"),disabled:true,onselect:"core:library-export"} | ||||
|         ]}); | ||||
|         menuOptions.push(null); | ||||
|         menuOptions.push({id:"menu-item-search",label:RED._("menu.label.search"),onselect:RED.search.show}); | ||||
|         menuOptions.push({id:"menu-item-search",label:RED._("menu.label.search"),onselect:"core:search"}); | ||||
|         menuOptions.push(null); | ||||
|         menuOptions.push({id:"menu-item-config-nodes",label:RED._("menu.label.displayConfig"),onselect:function() {}}); | ||||
|         menuOptions.push({id:"menu-item-config-nodes",label:RED._("menu.label.displayConfig"),onselect:"core:show-config-tab"}); | ||||
|         menuOptions.push({id:"menu-item-workspace",label:RED._("menu.label.flows"),options:[ | ||||
|             {id:"menu-item-workspace-add",label:RED._("menu.label.add"),onselect:RED.workspaces.add}, | ||||
|             {id:"menu-item-workspace-edit",label:RED._("menu.label.rename"),onselect:RED.workspaces.edit}, | ||||
|             {id:"menu-item-workspace-delete",label:RED._("menu.label.delete"),onselect:RED.workspaces.remove} | ||||
|             {id:"menu-item-workspace-add",label:RED._("menu.label.add"),onselect:"core:add-flow"}, | ||||
|             {id:"menu-item-workspace-edit",label:RED._("menu.label.rename"),onselect:"core:edit-flow"}, | ||||
|             {id:"menu-item-workspace-delete",label:RED._("menu.label.delete"),onselect:"core:remove-flow"} | ||||
|         ]}); | ||||
|         menuOptions.push({id:"menu-item-subflow",label:RED._("menu.label.subflows"), options: [ | ||||
|             {id:"menu-item-subflow-create",label:RED._("menu.label.createSubflow"),onselect:RED.subflow.createSubflow}, | ||||
|             {id:"menu-item-subflow-convert",label:RED._("menu.label.selectionToSubflow"),disabled:true,onselect:RED.subflow.convertToSubflow}, | ||||
|             {id:"menu-item-subflow-create",label:RED._("menu.label.createSubflow"),onselect:"core:create-subflow"}, | ||||
|             {id:"menu-item-subflow-convert",label:RED._("menu.label.selectionToSubflow"),disabled:true,onselect:"core:convert-to-subflow"}, | ||||
|         ]}); | ||||
|         menuOptions.push(null); | ||||
|         if (RED.settings.theme('palette.editable') !== false) { | ||||
|             RED.palette.editor.init(); | ||||
|             menuOptions.push({id:"menu-item-edit-palette",label:RED._("menu.label.editPalette"),onselect:RED.palette.editor.show}); | ||||
|             menuOptions.push({id:"menu-item-edit-palette",label:RED._("menu.label.editPalette"),onselect:"core:manage-palette"}); | ||||
|             menuOptions.push(null); | ||||
|         } | ||||
|  | ||||
|         menuOptions.push({id:"menu-item-keyboard-shortcuts",label:RED._("menu.label.keyboardShortcuts"),onselect:RED.keyboard.showHelp}); | ||||
|         menuOptions.push({id:"menu-item-keyboard-shortcuts",label:RED._("menu.label.keyboardShortcuts"),onselect:"core:show-help"}); | ||||
|         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") | ||||
|         }); | ||||
|         menuOptions.push({id:"menu-item-node-red-version", label:"v"+RED.settings.version, onselect: showAbout }); | ||||
|         menuOptions.push({id:"menu-item-node-red-version", label:"v"+RED.settings.version, onselect: "core:show-about" }); | ||||
|  | ||||
|         RED.menu.init({id:"btn-sidemenu",options: menuOptions}); | ||||
|  | ||||
|         RED.user.init(); | ||||
|  | ||||
|         RED.library.init(); | ||||
|         RED.palette.init(); | ||||
|         RED.sidebar.init(); | ||||
| @@ -235,15 +231,21 @@ | ||||
|         RED.search.init(); | ||||
|         RED.view.init(); | ||||
|         RED.editor.init(); | ||||
|         RED.keyboard.init(); | ||||
|  | ||||
|         RED.menu.init({id:"btn-sidemenu",options: menuOptions}); | ||||
|  | ||||
|  | ||||
|         RED.deploy.init(RED.settings.theme("deployButton",null)); | ||||
|  | ||||
|         RED.keyboard.add("workspace", /* ? */ 191,{shift:true},function() {RED.keyboard.showHelp();d3.event.preventDefault();}); | ||||
|         RED.actions.add("core:show-about", showAbout); | ||||
|  | ||||
|         RED.comms.connect(); | ||||
|  | ||||
|         $("#main-container").show(); | ||||
|         $(".header-toolbar").show(); | ||||
|  | ||||
|  | ||||
|         loadNodeList(); | ||||
|     } | ||||
|  | ||||
|   | ||||
							
								
								
									
										35
									
								
								editor/js/ui/actions.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								editor/js/ui/actions.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| RED.actions = (function() { | ||||
|     var actions = { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     function addAction(name,handler) { | ||||
|         actions[name] = handler; | ||||
|     } | ||||
|     function removeAction(name) { | ||||
|         delete actions[name]; | ||||
|     } | ||||
|     function getAction(name) { | ||||
|         return actions[name]; | ||||
|     } | ||||
|     function invokeAction(name) { | ||||
|         if (actions.hasOwnProperty(name)) { | ||||
|             actions[name](); | ||||
|         } | ||||
|     } | ||||
|     function listActions() { | ||||
|         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}) | ||||
|         }) | ||||
|         return result; | ||||
|     } | ||||
|     return { | ||||
|         add: addAction, | ||||
|         remove: removeAction, | ||||
|         get: getAction, | ||||
|         invoke: invokeAction, | ||||
|         list: listActions | ||||
|     } | ||||
| })(); | ||||
| @@ -257,7 +257,7 @@ RED.clipboard = (function() { | ||||
|  | ||||
|     function hideDropTarget() { | ||||
|         $("#dropTarget").hide(); | ||||
|         RED.keyboard.remove(/* ESCAPE */ 27); | ||||
|         RED.keyboard.remove("escape"); | ||||
|     } | ||||
|  | ||||
|     return { | ||||
| @@ -274,13 +274,15 @@ RED.clipboard = (function() { | ||||
|                     RED.menu.setDisabled("menu-item-export-library",false); | ||||
|                 } | ||||
|             }); | ||||
|             RED.keyboard.add("workspace", /* e */ 69,{ctrl:true},function(){exportNodes();d3.event.preventDefault();}); | ||||
|             RED.keyboard.add("workspace", /* i */ 73,{ctrl:true},function(){importNodes();d3.event.preventDefault();}); | ||||
|  | ||||
|             RED.actions.add("core:export",exportNodes); | ||||
|             RED.actions.add("core:import",importNodes); | ||||
|  | ||||
|  | ||||
|             $('#chart').on("dragenter",function(event) { | ||||
|                 if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) { | ||||
|                     $("#dropTarget").css({display:'table'}); | ||||
|                     RED.keyboard.add("*", /* ESCAPE */ 27,hideDropTarget); | ||||
|                     RED.keyboard.add("*", "escape" ,hideDropTarget); | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|   | ||||
| @@ -13,9 +13,6 @@ | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  **/ | ||||
|  | ||||
|  | ||||
|  | ||||
| RED.menu = (function() { | ||||
|  | ||||
|     var menuItems = {}; | ||||
| @@ -34,17 +31,17 @@ RED.menu = (function() { | ||||
|             var savedStateActive = isSavedStateActive(opt.id); | ||||
|             if (savedStateActive) { | ||||
|                 link.addClass("active"); | ||||
|                 opt.onselect.call(opt, true); | ||||
|                 triggerAction(opt.id,true); | ||||
|             } else if (savedStateActive === false) { | ||||
|                 link.removeClass("active"); | ||||
|                 opt.onselect.call(opt, false); | ||||
|                 triggerAction(opt.id,false); | ||||
|             } else if (opt.hasOwnProperty("selected")) { | ||||
|                 if (opt.selected) { | ||||
|                     link.addClass("active"); | ||||
|                 } else { | ||||
|                     link.removeClass("active"); | ||||
|                 } | ||||
|                 opt.onselect.call(opt, opt.selected); | ||||
|                 triggerAction(opt.id,opt.selected); | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -107,10 +104,12 @@ RED.menu = (function() { | ||||
|                             setSelected(opt.id, !selected); | ||||
|                         } | ||||
|                     } else { | ||||
|                         opt.onselect.call(opt); | ||||
|                         triggerAction(opt.id); | ||||
|                     } | ||||
|                 }); | ||||
|                 setInitialState(); | ||||
|                 if (opt.toggle) { | ||||
|                     setInitialState(); | ||||
|                 } | ||||
|             } else if (opt.href) { | ||||
|                 link.attr("target","_blank").attr("href",opt.href); | ||||
|             } else if (!opt.options) { | ||||
| @@ -164,6 +163,19 @@ RED.menu = (function() { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function triggerAction(id, args) { | ||||
|         var opt = menuItems[id]; | ||||
|         var callback = opt.onselect; | ||||
|         if (typeof opt.onselect === 'string') { | ||||
|             callback = RED.actions.get(opt.onselect); | ||||
|         } | ||||
|         if (callback) { | ||||
|             callback.call(opt,args); | ||||
|         } else { | ||||
|             console.log("No callback for",id,opt.onselect); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function isSavedStateActive(id) { | ||||
|         return RED.settings.get("menu-" + id); | ||||
|     } | ||||
| @@ -187,11 +199,15 @@ RED.menu = (function() { | ||||
|             $("#"+id).removeClass("active"); | ||||
|         } | ||||
|         if (opt && opt.onselect) { | ||||
|             opt.onselect.call(opt,state); | ||||
|             triggerAction(opt.id,state); | ||||
|         } | ||||
|         setSavedState(id, state); | ||||
|     } | ||||
|  | ||||
|     function toggleSelected(id) { | ||||
|         setSelected(id,!isSelected(id)); | ||||
|     } | ||||
|  | ||||
|     function setDisabled(id,state) { | ||||
|         if (state) { | ||||
|             $("#"+id).parent().addClass("disabled"); | ||||
| @@ -231,16 +247,6 @@ RED.menu = (function() { | ||||
|         var opt = menuItems[id]; | ||||
|         if (opt) { | ||||
|             opt.onselect = action; | ||||
|             // $("#"+id).click(function() { | ||||
|             //     if ($(this).parent().hasClass("disabled")) { | ||||
|             //         return; | ||||
|             //     } | ||||
|             //     if (menuItems[id].toggle) { | ||||
|             //         setSelected(id,!isSelected(id)); | ||||
|             //     } else { | ||||
|             //         menuItems[id].onselect.call(menuItems[id]); | ||||
|             //     } | ||||
|             // }); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -248,6 +254,7 @@ RED.menu = (function() { | ||||
|         init: createMenu, | ||||
|         setSelected: setSelected, | ||||
|         isSelected: isSelected, | ||||
|         toggleSelected: toggleSelected, | ||||
|         setDisabled: setDisabled, | ||||
|         addItem: addItem, | ||||
|         removeItem: removeItem, | ||||
|   | ||||
| @@ -126,6 +126,18 @@ RED.tabs = (function() { | ||||
|                 },100); | ||||
|             } | ||||
|         } | ||||
|         function activatePreviousTab() { | ||||
|             var previous = ul.find("li.active").prev(); | ||||
|             if (previous.length > 0) { | ||||
|                 activateTab(previous.find("a")); | ||||
|             } | ||||
|         } | ||||
|         function activateNextTab() { | ||||
|             var next = ul.find("li.active").next(); | ||||
|             if (next.length > 0) { | ||||
|                 activateTab(next.find("a")); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         function updateTabWidths() { | ||||
|             var tabs = ul.find("li.red-ui-tab"); | ||||
| @@ -303,6 +315,8 @@ RED.tabs = (function() { | ||||
|             }, | ||||
|             removeTab: removeTab, | ||||
|             activateTab: activateTab, | ||||
|             nextTab: activateNextTab, | ||||
|             previousTab: activatePreviousTab, | ||||
|             resize: updateTabWidths, | ||||
|             count: function() { | ||||
|                 return ul.find("li.red-ui-tab").size(); | ||||
|   | ||||
| @@ -1532,14 +1532,13 @@ RED.editor = (function() { | ||||
|     return { | ||||
|         init: function() { | ||||
|             RED.tray.init(); | ||||
|             $(window).on('keydown', function(evt) { | ||||
|                 if (evt.keyCode === $.ui.keyCode.ESCAPE && (evt.metaKey || evt.ctrlKey)) { | ||||
|                     $("#node-dialog-cancel").click(); | ||||
|                     $("#node-config-dialog-cancel").click(); | ||||
|                 } else if (evt.keyCode === $.ui.keyCode.ENTER && (evt.metaKey || evt.ctrlKey)) { | ||||
|                     $("#node-dialog-ok").click(); | ||||
|                     $("#node-config-dialog-ok").click(); | ||||
|                 } | ||||
|             RED.actions.add("core:confirm-edit-tray", function() { | ||||
|                 $("#node-dialog-ok").click(); | ||||
|                 $("#node-config-dialog-ok").click(); | ||||
|             }); | ||||
|             RED.actions.add("core:cancel-edit-tray", function() { | ||||
|                 $("#node-dialog-cancel").click(); | ||||
|                 $("#node-config-dialog-cancel").click(); | ||||
|             }); | ||||
|         }, | ||||
|         edit: showEditDialog, | ||||
|   | ||||
| @@ -16,9 +16,98 @@ | ||||
| RED.keyboard = (function() { | ||||
|  | ||||
|     var handlers = {}; | ||||
|     var partialState; | ||||
|  | ||||
|     var keyMap = { | ||||
|         "left":37, | ||||
|         "up":38, | ||||
|         "right":39, | ||||
|         "down":40, | ||||
|         "escape":27, | ||||
|         "enter": 13, | ||||
|         "backspace": 8, | ||||
|         "delete": 46, | ||||
|         "space": 32, | ||||
|         ";":186, | ||||
|         "=":187, | ||||
|         ",":188, | ||||
|         "-":189, | ||||
|         ".":190, | ||||
|         "/":191, | ||||
|         "\\":220, | ||||
|         "'":222, | ||||
|         "?":191 // <- QWERTY specific | ||||
|     } | ||||
|     var metaKeyCodes = { | ||||
|         16:true, | ||||
|         17:true, | ||||
|         18: true, | ||||
|         91:true, | ||||
|         93: true | ||||
|     } | ||||
|     var actionToKeyMap = {} | ||||
|  | ||||
|     // FF generates some different keycodes because reasons. | ||||
|     var firefoxKeyCodeMap = { | ||||
|         59:186, | ||||
|         61:187, | ||||
|         173:189 | ||||
|     } | ||||
|  | ||||
|     function init() { | ||||
|         $.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]); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         }) | ||||
|         RED.actions.add("core:show-help", showKeyboardHelp); | ||||
|  | ||||
|     } | ||||
|     function parseKeySpecifier(key) { | ||||
|         var parts = key.toLowerCase().split("-"); | ||||
|         var modifiers = {}; | ||||
|         var keycode; | ||||
|         var blank = 0; | ||||
|         for (var i=0;i<parts.length;i++) { | ||||
|             switch(parts[i]) { | ||||
|                 case "ctrl": | ||||
|                 case "cmd": | ||||
|                     modifiers.ctrl = true; | ||||
|                     modifiers.meta = true; | ||||
|                     break; | ||||
|                 case "alt": | ||||
|                     modifiers.alt = true; | ||||
|                     break; | ||||
|                 case "shift": | ||||
|                     modifiers.shift = true; | ||||
|                     break; | ||||
|                 case "": | ||||
|                     blank++; | ||||
|                     keycode = keyMap["-"]; | ||||
|                     break; | ||||
|                 default: | ||||
|                     if (keyMap.hasOwnProperty(parts[i])) { | ||||
|                         keycode = keyMap[parts[i]]; | ||||
|                     } else if (parts[i].length > 1) { | ||||
|                         return null; | ||||
|                     } else { | ||||
|                         keycode = parts[i].toUpperCase().charCodeAt(0); | ||||
|                     } | ||||
|                     break; | ||||
|             } | ||||
|         } | ||||
|         return [keycode,modifiers]; | ||||
|     } | ||||
|  | ||||
|     function resolveKeyEvent(evt) { | ||||
|         var slot = handlers; | ||||
|         var slot = partialState||handlers; | ||||
|         if (evt.ctrlKey || evt.metaKey) { | ||||
|             slot = slot.ctrl; | ||||
|         } | ||||
| @@ -28,9 +117,19 @@ RED.keyboard = (function() { | ||||
|         if (slot && evt.altKey) { | ||||
|             slot = slot.alt; | ||||
|         } | ||||
|         if (slot && slot[evt.keyCode]) { | ||||
|             var handler = slot[evt.keyCode]; | ||||
|             if (handler.scope && handler.scope !== "*") { | ||||
|         var keyCode = firefoxKeyCodeMap[evt.keyCode] || evt.keyCode; | ||||
|         if (slot && slot[keyCode]) { | ||||
|             var handler = slot[keyCode]; | ||||
|             if (!handler.scope) { | ||||
|                 if (partialState) { | ||||
|                     partialState = null; | ||||
|                     return resolveKeyEvent(evt); | ||||
|                 } else { | ||||
|                     partialState = handler; | ||||
|                     evt.preventDefault(); | ||||
|                     return null; | ||||
|                 } | ||||
|             } else if (handler.scope && handler.scope !== "*") { | ||||
|                 var target = evt.target; | ||||
|                 while (target.nodeName !== 'BODY' && target.id !== handler.scope) { | ||||
|                     target = target.parentElement; | ||||
| @@ -39,66 +138,124 @@ RED.keyboard = (function() { | ||||
|                     handler = null; | ||||
|                 } | ||||
|             } | ||||
|             partialState = null; | ||||
|             return handler; | ||||
|         } else if (partialState) { | ||||
|             partialState = null; | ||||
|             return resolveKeyEvent(evt); | ||||
|         } | ||||
|     } | ||||
|     d3.select(window).on("keydown",function() { | ||||
|         if (metaKeyCodes[d3.event.keyCode]) { | ||||
|             return; | ||||
|         } | ||||
|         var handler = resolveKeyEvent(d3.event); | ||||
|         if (handler && handler.ondown) { | ||||
|             handler.ondown(); | ||||
|         } | ||||
|     }); | ||||
|     d3.select(window).on("keyup",function() { | ||||
|         var handler = resolveKeyEvent(d3.event); | ||||
|         if (handler && handler.onup) { | ||||
|             handler.onup(); | ||||
|             if (typeof handler.ondown === "string") { | ||||
|                 RED.actions.invoke(handler.ondown); | ||||
|             } else { | ||||
|                 handler.ondown(); | ||||
|             } | ||||
|             d3.event.preventDefault(); | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     function addHandler(scope,key,modifiers,ondown,onup) { | ||||
|     function addHandler(scope,key,modifiers,ondown) { | ||||
|         var mod = modifiers; | ||||
|         var cbdown = ondown; | ||||
|         var cbup = onup; | ||||
|         if (typeof modifiers == "function") { | ||||
|         if (typeof modifiers == "function" || typeof modifiers === "string") { | ||||
|             mod = {}; | ||||
|             cbdown = modifiers; | ||||
|             cbup = ondown; | ||||
|         } | ||||
|         var keys = []; | ||||
|         var i=0; | ||||
|         if (typeof key === 'string') { | ||||
|             if (typeof cbdown === 'string') { | ||||
|                 actionToKeyMap[cbdown] = {scope:scope,key:key}; | ||||
|             } | ||||
|             var parts = key.split(" "); | ||||
|             for (i=0;i<parts.length;i++) { | ||||
|                 var parsedKey = parseKeySpecifier(parts[i]); | ||||
|                 if (parsedKey) { | ||||
|                     keys.push(parsedKey); | ||||
|                 } else { | ||||
|                     console.log("Unrecognised key specifier:",key) | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|         } else { | ||||
|             keys.push([key,mod]) | ||||
|         } | ||||
|         var slot = handlers; | ||||
|         if (mod.ctrl) { | ||||
|             slot.ctrl = slot.ctrl||{}; | ||||
|             slot = slot.ctrl; | ||||
|         for (i=0;i<keys.length;i++) { | ||||
|             key = keys[i][0]; | ||||
|             mod = keys[i][1]; | ||||
|             if (mod.ctrl) { | ||||
|                 slot.ctrl = slot.ctrl||{}; | ||||
|                 slot = slot.ctrl; | ||||
|             } | ||||
|             if (mod.shift) { | ||||
|                 slot.shift = slot.shift||{}; | ||||
|                 slot = slot.shift; | ||||
|             } | ||||
|             if (mod.alt) { | ||||
|                 slot.alt = slot.alt||{}; | ||||
|                 slot = slot.alt; | ||||
|             } | ||||
|             slot[key] = slot[key] || {}; | ||||
|             slot = slot[key]; | ||||
|             //slot[key] = {scope: scope, ondown:cbdown}; | ||||
|         } | ||||
|         if (mod.shift) { | ||||
|             slot.shift = slot.shift||{}; | ||||
|             slot = slot.shift; | ||||
|         } | ||||
|         if (mod.alt) { | ||||
|             slot.alt = slot.alt||{}; | ||||
|             slot = slot.alt; | ||||
|         } | ||||
|         slot[key] = {scope: scope, ondown:cbdown, onup:cbup}; | ||||
|         slot.scope = scope; | ||||
|         slot.ondown = cbdown; | ||||
|     } | ||||
|  | ||||
|     function removeHandler(key,modifiers) { | ||||
|         var mod = modifiers || {}; | ||||
|         var keys = []; | ||||
|         var i=0; | ||||
|         if (typeof key === 'string') { | ||||
|             delete actionToKeyMap[key]; | ||||
|             var parts = key.split(" "); | ||||
|             for (i=0;i<parts.length;i++) { | ||||
|                 var parsedKey = parseKeySpecifier(parts[i]); | ||||
|                 if (parsedKey) { | ||||
|                     keys.push(parsedKey); | ||||
|                 } else { | ||||
|                     console.log("Unrecognised key specifier:",key) | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|         } else { | ||||
|             keys.push([key,mod]) | ||||
|         } | ||||
|         var slot = handlers; | ||||
|         if (mod.ctrl) { | ||||
|             slot = slot.ctrl; | ||||
|         } | ||||
|         if (slot && mod.shift) { | ||||
|             slot = slot.shift; | ||||
|         } | ||||
|         if (slot && mod.alt) { | ||||
|             slot = slot.alt; | ||||
|         } | ||||
|         if (slot) { | ||||
|             delete slot[key]; | ||||
|         for (i=0;i<keys.length;i++) { | ||||
|             key = keys[i][0]; | ||||
|             mod = keys[i][1]; | ||||
|             if (mod.ctrl) { | ||||
|                 slot = slot.ctrl; | ||||
|             } | ||||
|             if (slot && mod.shift) { | ||||
|                 slot = slot.shift; | ||||
|             } | ||||
|             if (slot && mod.alt) { | ||||
|                 slot = slot.alt; | ||||
|             } | ||||
|             if (!slot[key]) { | ||||
|                 return; | ||||
|             } | ||||
|             slot = slot[key]; | ||||
|         } | ||||
|         delete slot.scope; | ||||
|         delete slot.ondown; | ||||
|     } | ||||
|  | ||||
|     var dialog = null; | ||||
|  | ||||
|     var isMac = /Mac/i.test(window.navigator.platform); | ||||
|     var cmdCtrlKey = '<span class="help-key">'+(isMac?'⌘':'Ctrl')+'</span>'; | ||||
|  | ||||
|     function showKeyboardHelp() { | ||||
|         if (!RED.settings.theme("menu.menu-item-keyboard-shortcuts",true)) { | ||||
|             return; | ||||
| @@ -107,30 +264,30 @@ RED.keyboard = (function() { | ||||
|             dialog = $('<div id="keyboard-help-dialog" class="hide">'+ | ||||
|                 '<div style="vertical-align: top;display:inline-block; box-sizing: border-box; width:50%; padding: 10px;">'+ | ||||
|                     '<table class="keyboard-shortcuts">'+ | ||||
|                         '<tr><td><span class="help-key">Ctrl/⌘</span> + <span class="help-key">a</span></td><td>'+RED._("keyboard.selectAll")+'</td></tr>'+ | ||||
|                         '<tr><td>'+cmdCtrlKey+' + <span class="help-key">a</span></td><td>'+RED._("keyboard.selectAll")+'</td></tr>'+ | ||||
|                         '<tr><td><span class="help-key">Shift</span> + <span class="help-key">Click</span></td><td>'+RED._("keyboard.selectAllConnected")+'</td></tr>'+ | ||||
|                         '<tr><td><span class="help-key">Ctrl/⌘</span> + <span class="help-key">Click</span></td><td>'+RED._("keyboard.addRemoveNode")+'</td></tr>'+ | ||||
|                         '<tr><td>'+cmdCtrlKey+' + <span class="help-key">Click</span></td><td>'+RED._("keyboard.addRemoveNode")+'</td></tr>'+ | ||||
|                         '<tr><td> </td><td></td></tr>'+ | ||||
|                         '<tr><td><span class="help-key">Enter</span></td><td>'+RED._("keyboard.editSelected")+'</td></tr>'+ | ||||
|                         '<tr><td><span class="help-key">Delete</span> / <span class="help-key">Backspace</span></td><td>'+RED._("keyboard.deleteSelected")+'</td></tr>'+ | ||||
|                         '<tr><td> </td><td></td></tr>'+ | ||||
|                         '<tr><td><span class="help-key">Ctrl/⌘</span> + <span class="help-key">i</span></td><td>'+RED._("keyboard.importNode")+'</td></tr>'+ | ||||
|                         '<tr><td><span class="help-key">Ctrl/⌘</span> + <span class="help-key">e</span></td><td>'+RED._("keyboard.exportNode")+'</td></tr>'+ | ||||
|                         '<tr><td>'+cmdCtrlKey+' + <span class="help-key">i</span></td><td>'+RED._("keyboard.importNode")+'</td></tr>'+ | ||||
|                         '<tr><td>'+cmdCtrlKey+' + <span class="help-key">e</span></td><td>'+RED._("keyboard.exportNode")+'</td></tr>'+ | ||||
|                     '</table>'+ | ||||
|                 '</div>'+ | ||||
|                 '<div style="vertical-align: top;display:inline-block; box-sizing: border-box; width:50%; padding: 10px;">'+ | ||||
|                     '<table class="keyboard-shortcuts">'+ | ||||
|                         '<tr><td><span class="help-key">Ctrl/⌘</span> + <span class="help-key">Space</span></td><td>'+RED._("keyboard.toggleSidebar")+'</td></tr>'+ | ||||
|                         '<tr><td><span class="help-key">Ctrl/⌘</span> + <span class="help-key">.</span></td><td>'+RED._("keyboard.searchBox")+'</td></tr>'+ | ||||
|                         '<tr><td><span class="help-key">Ctrl/⌘</span> + <span class="help-key">Shift</span> + <span class="help-key">p</span></td><td>'+RED._("keyboard.managePalette")+'</td></tr>'+ | ||||
|                         '<tr><td>'+cmdCtrlKey+' + <span class="help-key">Space</span></td><td>'+RED._("keyboard.toggleSidebar")+'</td></tr>'+ | ||||
|                         '<tr><td>'+cmdCtrlKey+' + <span class="help-key">f</span></td><td>'+RED._("keyboard.searchBox")+'</td></tr>'+ | ||||
|                         '<tr><td>'+cmdCtrlKey+' + <span class="help-key">Shift</span> + <span class="help-key">p</span></td><td>'+RED._("keyboard.managePalette")+'</td></tr>'+ | ||||
|                         '<tr><td> </td><td></td></tr>'+ | ||||
|                         '<tr><td><span class="help-key">←</span> <span class="help-key">↑</span> <span class="help-key">→</span> <span class="help-key">↓</span></td><td>'+RED._("keyboard.nudgeNode")+'</td></tr>'+ | ||||
|                         '<tr><td><span class="help-key">Shift</span> + <span class="help-key">←</span> <span class="help-key">↑</span> <span class="help-key">→</span> <span class="help-key">↓</span></td><td>'+RED._("keyboard.moveNode")+'</td></tr>'+ | ||||
|                         '<tr><td> </td><td></td></tr>'+ | ||||
|                         '<tr><td><span class="help-key">Ctrl/⌘</span> + <span class="help-key">c</span></td><td>'+RED._("keyboard.copyNode")+'</td></tr>'+ | ||||
|                         '<tr><td><span class="help-key">Ctrl/⌘</span> + <span class="help-key">x</span></td><td>'+RED._("keyboard.cutNode")+'</td></tr>'+ | ||||
|                         '<tr><td><span class="help-key">Ctrl/⌘</span> + <span class="help-key">v</span></td><td>'+RED._("keyboard.pasteNode")+'</td></tr>'+ | ||||
|                         '<tr><td><span class="help-key">Ctrl/⌘</span> + <span class="help-key">z</span></td><td>'+RED._("keyboard.undoChange")+'</td></tr>'+ | ||||
|                         '<tr><td>'+cmdCtrlKey+' + <span class="help-key">c</span></td><td>'+RED._("keyboard.copyNode")+'</td></tr>'+ | ||||
|                         '<tr><td>'+cmdCtrlKey+' + <span class="help-key">x</span></td><td>'+RED._("keyboard.cutNode")+'</td></tr>'+ | ||||
|                         '<tr><td>'+cmdCtrlKey+' + <span class="help-key">v</span></td><td>'+RED._("keyboard.pasteNode")+'</td></tr>'+ | ||||
|                         '<tr><td>'+cmdCtrlKey+' + <span class="help-key">z</span></td><td>'+RED._("keyboard.undoChange")+'</td></tr>'+ | ||||
|                     '</table>'+ | ||||
|                 '</div>'+ | ||||
|                 '</div>') | ||||
| @@ -148,9 +305,12 @@ RED.keyboard = (function() { | ||||
|     } | ||||
|  | ||||
|     return { | ||||
|         init: init, | ||||
|         add: addHandler, | ||||
|         remove: removeHandler, | ||||
|         showHelp: showKeyboardHelp | ||||
|         getShortcut: function(actionName) { | ||||
|             return actionToKeyMap[actionName]; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| })(); | ||||
|   | ||||
| @@ -410,6 +410,9 @@ RED.library = (function() { | ||||
|  | ||||
|     return { | ||||
|         init: function() { | ||||
|  | ||||
|             RED.actions.add("core:library-export",exportFlow); | ||||
|  | ||||
|             RED.events.on("view:selection-changed",function(selection) { | ||||
|                 if (!selection.nodes) { | ||||
|                     RED.menu.setDisabled("menu-item-export",true); | ||||
|   | ||||
| @@ -302,10 +302,10 @@ RED.palette.editor = (function() { | ||||
|             filterInput.focus(); | ||||
|         },250); | ||||
|         RED.events.emit("palette-editor:open"); | ||||
|         RED.keyboard.add("*",/* ESCAPE */ 27,function(){hidePaletteEditor();d3.event.preventDefault();}); | ||||
|         RED.keyboard.add("*","escape",function(){hidePaletteEditor()}); | ||||
|     } | ||||
|     function hidePaletteEditor() { | ||||
|         RED.keyboard.remove("*"); | ||||
|         RED.keyboard.remove("escape"); | ||||
|         $("#main-container").removeClass("palette-expanded"); | ||||
|         $("#header-shade").hide(); | ||||
|         $("#editor-shade").hide(); | ||||
| @@ -425,7 +425,7 @@ RED.palette.editor = (function() { | ||||
|         RED.events.on("type-search:open",function() { disabled = true; }); | ||||
|         RED.events.on("type-search:close",function() { disabled = false; }); | ||||
|  | ||||
|         RED.keyboard.add("*", /* p */ 80,{shift:true,ctrl:true},function() {RED.palette.editor.show();d3.event.preventDefault();}); | ||||
|         RED.actions.add("core:manage-palette",RED.palette.editor.show); | ||||
|  | ||||
|         editorTabs = RED.tabs.create({ | ||||
|             id:"palette-editor-tabs", | ||||
|   | ||||
| @@ -238,8 +238,11 @@ RED.search = (function() { | ||||
|     } | ||||
|  | ||||
|     function show() { | ||||
|         if (disabled) { | ||||
|             return; | ||||
|         } | ||||
|         if (!visible) { | ||||
|             RED.keyboard.add("*",/* ESCAPE */ 27,function(){hide();d3.event.preventDefault();}); | ||||
|             RED.keyboard.add("*","escape",function(){hide()}); | ||||
|             $("#header-shade").show(); | ||||
|             $("#editor-shade").show(); | ||||
|             $("#palette-shade").show(); | ||||
| @@ -257,7 +260,7 @@ RED.search = (function() { | ||||
|     } | ||||
|     function hide() { | ||||
|         if (visible) { | ||||
|             RED.keyboard.remove(/* ESCAPE */ 27); | ||||
|             RED.keyboard.remove("escape"); | ||||
|             visible = false; | ||||
|             $("#header-shade").hide(); | ||||
|             $("#editor-shade").hide(); | ||||
| @@ -274,7 +277,8 @@ RED.search = (function() { | ||||
|     } | ||||
|  | ||||
|     function init() { | ||||
|         RED.keyboard.add("*",/* . */ 190,{ctrl:true},function(){if (!disabled) { show(); } d3.event.preventDefault();}); | ||||
|         RED.actions.add("core:search",show); | ||||
|  | ||||
|         RED.events.on("editor:open",function() { disabled = true; }); | ||||
|         RED.events.on("editor:close",function() { disabled = false; }); | ||||
|         RED.events.on("palette-editor:open",function() { disabled = true; }); | ||||
|   | ||||
| @@ -202,12 +202,18 @@ RED.sidebar = (function() { | ||||
|     } | ||||
|  | ||||
|     function init () { | ||||
|         RED.keyboard.add("*",/* SPACE */ 32,{ctrl:true},function(){RED.menu.setSelected("menu-item-sidebar",!RED.menu.isSelected("menu-item-sidebar"));d3.event.preventDefault();}); | ||||
|         RED.actions.add("core:toggle-sidebar",function(state){ | ||||
|             if (state === undefined) { | ||||
|                 RED.menu.toggleSelected("menu-item-sidebar"); | ||||
|             } else { | ||||
|                 toggleSidebar(state); | ||||
|             } | ||||
|         }); | ||||
|         showSidebar(); | ||||
|         RED.sidebar.info.init(); | ||||
|         RED.sidebar.config.init(); | ||||
|         // hide info bar at start if screen rather narrow... | ||||
|         if ($(window).width() < 600) { toggleSidebar(); } | ||||
|         if ($(window).width() < 600) { RED.menu.setSelected("menu-item-sidebar",false); } | ||||
|     } | ||||
|  | ||||
|     return { | ||||
|   | ||||
| @@ -380,6 +380,8 @@ RED.subflow = (function() { | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         RED.actions.add("core:create-subflow",createSubflow); | ||||
|         RED.actions.add("core:convert-to-subflow",convertToSubflow); | ||||
|     } | ||||
|  | ||||
|     function createSubflow() { | ||||
|   | ||||
| @@ -236,10 +236,7 @@ RED.sidebar.config = (function() { | ||||
|             visible: false, | ||||
|             onchange: function() { refreshConfigNodeList(); } | ||||
|         }); | ||||
|  | ||||
|         RED.menu.setAction('menu-item-config-nodes',function() { | ||||
|             RED.sidebar.show('config'); | ||||
|         }) | ||||
|         RED.actions.add("core:show-config-tab",function() {RED.sidebar.show('config')}); | ||||
|  | ||||
|         $("#workspace-config-node-collapse-all").on("click", function(e) { | ||||
|             e.preventDefault(); | ||||
|   | ||||
| @@ -42,7 +42,7 @@ RED.sidebar.info = (function() { | ||||
|             content: content, | ||||
|             enableOnEdit: true | ||||
|         }); | ||||
|  | ||||
|         RED.actions.add("core:show-info-tab",show); | ||||
|     } | ||||
|  | ||||
|     function show() { | ||||
|   | ||||
| @@ -168,7 +168,7 @@ RED.typeSearch = (function() { | ||||
|     } | ||||
|     function show(opts) { | ||||
|         if (!visible) { | ||||
|             RED.keyboard.add("*",/* ESCAPE */ 27,function(){hide();d3.event.preventDefault();}); | ||||
|             RED.keyboard.add("*","escape",function(){hide()}); | ||||
|             if (dialog === null) { | ||||
|                 createDialog(); | ||||
|             } | ||||
| @@ -195,7 +195,7 @@ RED.typeSearch = (function() { | ||||
|     } | ||||
|     function hide(fast) { | ||||
|         if (visible) { | ||||
|             RED.keyboard.remove(/* ESCAPE */ 27); | ||||
|             RED.keyboard.remove("escape"); | ||||
|             visible = false; | ||||
|             if (dialog !== null) { | ||||
|                 searchResultsDiv.slideUp(fast?50:200,function() { | ||||
|   | ||||
| @@ -267,6 +267,7 @@ RED.view = (function() { | ||||
|     } | ||||
|  | ||||
|     function init() { | ||||
|  | ||||
|         RED.events.on("workspace:change",function(event) { | ||||
|             var chart = $("#chart"); | ||||
|             if (event.old !== 0) { | ||||
| @@ -384,28 +385,47 @@ RED.view = (function() { | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         RED.keyboard.add("workspace",/* backspace */ 8,function(){deleteSelection();d3.event.preventDefault();}); | ||||
|         RED.keyboard.add("workspace",/* delete */ 46,function(){deleteSelection();d3.event.preventDefault();}); | ||||
|         RED.keyboard.add("workspace",/* enter */ 13, function() { editSelection(); d3.event.preventDefault();}); | ||||
|         RED.actions.add("core:copy",copySelection); | ||||
|         RED.actions.add("core:cut",function(){copySelection();deleteSelection();}); | ||||
|         RED.actions.add("core:paste",function(){importNodes(clipboard);}); | ||||
|         RED.actions.add("core:delete",deleteSelection); | ||||
|         RED.actions.add("core:edit",editSelection); | ||||
|         RED.actions.add("core:undo",RED.history.pop); | ||||
|         RED.actions.add("core:select-all",selectAll); | ||||
|         RED.actions.add("core:zoom-in",zoomIn); | ||||
|         RED.actions.add("core:zoom-out",zoomOut); | ||||
|         RED.actions.add("core:zoom-reset",zoomZero); | ||||
|  | ||||
|         RED.keyboard.add("workspace",/* c */ 67,{ctrl:true},function(){copySelection();d3.event.preventDefault();}); | ||||
|         RED.keyboard.add("workspace",/* x */ 88,{ctrl:true},function(){copySelection();deleteSelection();d3.event.preventDefault();}); | ||||
|         RED.actions.add("core:toggle-show-grid",function(state) { | ||||
|             if (state === undefined) { | ||||
|                 RED.menu.toggleSelected("menu-item-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"); | ||||
|             } else { | ||||
|                 toggleSnapGrid(state); | ||||
|             } | ||||
|         }); | ||||
|         RED.actions.add("core:toggle-status",function(state) { | ||||
|             if (state === undefined) { | ||||
|                 RED.menu.toggleSelected("menu-item-status"); | ||||
|             } else { | ||||
|                 toggleStatus(state); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         RED.keyboard.add("workspace",/* z */ 90,{ctrl:true},function(){RED.history.pop();}); | ||||
|         RED.keyboard.add("workspace",/* a */ 65,{ctrl:true},function(){selectAll();d3.event.preventDefault();}); | ||||
|         RED.keyboard.add("*",/* = */ 187,{ctrl:true},function(){zoomIn();d3.event.preventDefault();}); | ||||
|         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("workspace",/* v */ 86,{ctrl:true},function(){importNodes(clipboard);d3.event.preventDefault();}); | ||||
|  | ||||
|         RED.keyboard.add("workspace",/* up    */ 38, function() { moveSelection(0,-1);d3.event.preventDefault();},endKeyboardMove); | ||||
|         RED.keyboard.add("workspace",/* up    */ 38, {shift:true}, function() { moveSelection(0,-20); d3.event.preventDefault();},endKeyboardMove); | ||||
|         RED.keyboard.add("workspace",/* down  */ 40, function() { moveSelection(0,1);d3.event.preventDefault();},endKeyboardMove); | ||||
|         RED.keyboard.add("workspace",/* down  */ 40, {shift:true}, function() { moveSelection(0,20); d3.event.preventDefault();},endKeyboardMove); | ||||
|         RED.keyboard.add("workspace",/* left  */ 37, function() { moveSelection(-1,0);d3.event.preventDefault();},endKeyboardMove); | ||||
|         RED.keyboard.add("workspace",/* left  */ 37, {shift:true}, function() { moveSelection(-20,0); d3.event.preventDefault();},endKeyboardMove); | ||||
|         RED.keyboard.add("workspace",/* right */ 39, function() { moveSelection(1,0);d3.event.preventDefault();},endKeyboardMove); | ||||
|         RED.keyboard.add("workspace",/* right */ 39, {shift:true}, function() { moveSelection(20,0); d3.event.preventDefault();},endKeyboardMove); | ||||
|         RED.actions.add("core:move-selection-up", function() { moveSelection(0,-1);}); | ||||
|         RED.actions.add("core:step-selection-up", function() { moveSelection(0,-20);}); | ||||
|         RED.actions.add("core:move-selection-right", function() { moveSelection(1,0);}); | ||||
|         RED.actions.add("core:step-selection-right", function() { moveSelection(20,0);}); | ||||
|         RED.actions.add("core:move-selection-down", function() { moveSelection(0,1);}); | ||||
|         RED.actions.add("core:step-selection-down", function() { moveSelection(0,20);}); | ||||
|         RED.actions.add("core:move-selection-left", function() { moveSelection(-1,0);}); | ||||
|         RED.actions.add("core:step-selection-left", function() { moveSelection(-20,0);}); | ||||
|     } | ||||
|  | ||||
|  | ||||
| @@ -959,7 +979,7 @@ RED.view = (function() { | ||||
|             } | ||||
|         } | ||||
|         if (mouse_mode == RED.state.IMPORT_DRAGGING) { | ||||
|             RED.keyboard.remove(/* ESCAPE */ 27); | ||||
|             RED.keyboard.remove("escape"); | ||||
|             updateActiveNodes(); | ||||
|             RED.nodes.dirty(true); | ||||
|         } | ||||
| @@ -1103,6 +1123,7 @@ RED.view = (function() { | ||||
|     } | ||||
|  | ||||
|     function endKeyboardMove() { | ||||
|         endMoveSet = false; | ||||
|         if (moving_set.length > 0) { | ||||
|             var ns = []; | ||||
|             for (var i=0;i<moving_set.length;i++) { | ||||
| @@ -1117,14 +1138,21 @@ RED.view = (function() { | ||||
|             RED.nodes.dirty(true); | ||||
|         } | ||||
|     } | ||||
|     var endMoveSet = false; | ||||
|     function moveSelection(dx,dy) { | ||||
|         if (moving_set.length > 0) { | ||||
|             if (!endMoveSet) { | ||||
|                 $(document).one('keyup',endKeyboardMove); | ||||
|                 endMoveSet = true; | ||||
|             } | ||||
|             var minX = 0; | ||||
|             var minY = 0; | ||||
|             var node; | ||||
|  | ||||
|             for (var i=0;i<moving_set.length;i++) { | ||||
|                 node = moving_set[i]; | ||||
|                 node.n.changed = true; | ||||
|                 node.n.dirty = true; | ||||
|                 if (node.ox == null && node.oy == null) { | ||||
|                     node.ox = node.n.x; | ||||
|                     node.oy = node.n.y; | ||||
| @@ -1440,7 +1468,7 @@ RED.view = (function() { | ||||
|         //var pos = [touch0.pageX,touch0.pageY]; | ||||
|         //RED.touch.radialMenu.show(d3.select(this),pos); | ||||
|         if (mouse_mode == RED.state.IMPORT_DRAGGING) { | ||||
|             RED.keyboard.remove(/* ESCAPE */ 27); | ||||
|             RED.keyboard.remove("escape"); | ||||
|  | ||||
|             if (activeSpliceLink) { | ||||
|                 // TODO: DRY - droppable/nodeMouseDown/canvasMouseUp | ||||
| @@ -2437,8 +2465,8 @@ RED.view = (function() { | ||||
|                                            node.n._def.outputs > 0; | ||||
|                         } | ||||
|                     } | ||||
|                     RED.keyboard.add("*",/* ESCAPE */ 27,function(){ | ||||
|                             RED.keyboard.remove(/* ESCAPE */ 27); | ||||
|                     RED.keyboard.add("*","escape",function(){ | ||||
|                             RED.keyboard.remove("escape"); | ||||
|                             clearSelection(); | ||||
|                             RED.history.pop(); | ||||
|                             mouse_mode = 0; | ||||
| @@ -2483,6 +2511,24 @@ RED.view = (function() { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function toggleShowGrid(state) { | ||||
|         if (state) { | ||||
|             grid.style("visibility","visible"); | ||||
|         } else { | ||||
|             grid.style("visibility","hidden"); | ||||
|         } | ||||
|     } | ||||
|     function toggleSnapGrid(state) { | ||||
|         snapGrid = state; | ||||
|         redraw(); | ||||
|     } | ||||
|     function toggleStatus(s) { | ||||
|         showStatus = s; | ||||
|         RED.nodes.eachNode(function(n) { n.dirty = true;}); | ||||
|         //TODO: subscribe/unsubscribe here | ||||
|         redraw(); | ||||
|     } | ||||
|  | ||||
|     return { | ||||
|         init: init, | ||||
|         state:function(state) { | ||||
| @@ -2502,16 +2548,6 @@ RED.view = (function() { | ||||
|         }, | ||||
|         focus: focusView, | ||||
|         importNodes: importNodes, | ||||
|         status: function(s) { | ||||
|             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) { | ||||
|             if (typeof selection !== "undefined") { | ||||
| @@ -2538,17 +2574,6 @@ RED.view = (function() { | ||||
|             } | ||||
|             return selection; | ||||
|         }, | ||||
|         toggleShowGrid: function(state) { | ||||
|             if (state) { | ||||
|                 grid.style("visibility","visible"); | ||||
|             } else { | ||||
|                 grid.style("visibility","hidden"); | ||||
|             } | ||||
|         }, | ||||
|         toggleSnapGrid: function(state) { | ||||
|             snapGrid = state; | ||||
|             redraw(); | ||||
|         }, | ||||
|         scale: function() { | ||||
|             return scaleFactor; | ||||
|         }, | ||||
|   | ||||
| @@ -170,6 +170,9 @@ RED.workspaces = (function() { | ||||
|         createWorkspaceTabs(); | ||||
|         RED.events.on("sidebar:resize",workspace_tabs.resize); | ||||
|  | ||||
|         RED.actions.add("core:show-next-tab",workspace_tabs.nextTab); | ||||
|         RED.actions.add("core:show-previous-tab",workspace_tabs.previousTab); | ||||
|  | ||||
|         RED.menu.setAction('menu-item-workspace-delete',function() { | ||||
|             deleteWorkspace(RED.nodes.workspace(activeWorkspace)); | ||||
|         }); | ||||
| @@ -177,6 +180,14 @@ RED.workspaces = (function() { | ||||
|         $(window).resize(function() { | ||||
|             workspace_tabs.resize(); | ||||
|         }); | ||||
|  | ||||
|         RED.actions.add("core:add-flow",addWorkspace); | ||||
|         RED.actions.add("core:edit-flow",editWorkspace); | ||||
|         RED.actions.add("core:remove-flow",removeWorkspace); | ||||
|     } | ||||
|  | ||||
|     function editWorkspace(id) { | ||||
|         showRenameWorkspaceDialog(id||activeWorkspace); | ||||
|     } | ||||
|  | ||||
|     function removeWorkspace(ws) { | ||||
| @@ -201,9 +212,7 @@ RED.workspaces = (function() { | ||||
|         add: addWorkspace, | ||||
|         remove: removeWorkspace, | ||||
|         order: setWorkspaceOrder, | ||||
|         edit: function(id) { | ||||
|             showRenameWorkspaceDialog(id||activeWorkspace); | ||||
|         }, | ||||
|         edit: editWorkspace, | ||||
|         contains: function(id) { | ||||
|             return workspace_tabs.contains(id); | ||||
|         }, | ||||
|   | ||||
| @@ -144,8 +144,7 @@ | ||||
|                 toolbar: uiComponents.footer, | ||||
|                 enableOnEdit: true | ||||
|             }); | ||||
|  | ||||
|  | ||||
|             RED.actions.add("core:show-debug-tab",function() { RED.sidebar.show('debug')}); | ||||
|  | ||||
|             var that = this; | ||||
|             RED._debug = function(msg) { | ||||
| @@ -222,6 +221,8 @@ | ||||
|             RED.sidebar.removeTab("debug"); | ||||
|             RED.events.off("workspace:change", this.refreshMessageList); | ||||
|             window.removeEventListener("message",this.handleWindowMessage); | ||||
|             RED.actions.remove("core:show-debug"); | ||||
|  | ||||
|             delete RED._debug; | ||||
|         }, | ||||
|         oneditprepare: function() { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user