From 0df1b1d83ca97ae2f9fe5bb9ee6c5303e609fc16 Mon Sep 17 00:00:00 2001 From: Simon Hunt Date: Tue, 4 Nov 2014 22:58:29 -0800 Subject: [PATCH] GUI -- Added key handler mechanism. --- web/gui/src/main/webapp/index2.html | 2 + web/gui/src/main/webapp/network.js | 2 +- web/gui/src/main/webapp/onos2.js | 67 ++++++++++++++++++-- web/gui/src/main/webapp/sampleKeys.js | 90 +++++++++++++++++++++++++++ 4 files changed, 154 insertions(+), 7 deletions(-) create mode 100644 web/gui/src/main/webapp/sampleKeys.js diff --git a/web/gui/src/main/webapp/index2.html b/web/gui/src/main/webapp/index2.html index 703a2402a5..1ddc3183f9 100644 --- a/web/gui/src/main/webapp/index2.html +++ b/web/gui/src/main/webapp/index2.html @@ -71,6 +71,7 @@ var ONOS = $.onos({ comment: "configuration options", startVid: 'topo', +// startVid: 'sampleKeys', trace: false }); @@ -82,6 +83,7 @@ + diff --git a/web/gui/src/main/webapp/network.js b/web/gui/src/main/webapp/network.js index b249c09654..01e4acdeff 100644 --- a/web/gui/src/main/webapp/network.js +++ b/web/gui/src/main/webapp/network.js @@ -28,7 +28,7 @@ // configuration data var config = { - useLiveData: true, + useLiveData: false, debugOn: false, debug: { showNodeXY: false, diff --git a/web/gui/src/main/webapp/onos2.js b/web/gui/src/main/webapp/onos2.js index 6353a6e105..f509757068 100644 --- a/web/gui/src/main/webapp/onos2.js +++ b/web/gui/src/main/webapp/onos2.js @@ -49,13 +49,40 @@ ctx: '' }, built = false, - errorCount = 0; + errorCount = 0, + keyHandler = {}; // DOM elements etc. var $view, $mastRadio; + function whatKey(code) { + switch (code) { + case 13: return 'enter'; + case 16: return 'shift'; + case 17: return 'ctrl'; + case 18: return 'alt'; + case 27: return 'esc'; + case 32: return 'space'; + case 37: return 'leftArrow'; + case 38: return 'upArrow'; + case 39: return 'rightArrow'; + case 40: return 'downArrow'; + case 91: return 'cmdLeft'; + case 93: return 'cmdRight'; + default: + if ((code >= 48 && code <= 57) || + (code >= 65 && code <= 90)) { + return String.fromCharCode(code); + } else if (code >= 112 && code <= 123) { + return 'F' + (code - 111); + } + return '.'; + } + } + + // .......................................................... // Internal functions @@ -206,9 +233,11 @@ // the incoming view, then unload it... if (current.view && (current.view.vid !== view.vid)) { current.view.unload(); - // detach radio buttons, if they were there.. - $('#mastRadio').children().detach(); + // detach radio buttons, key handlers, etc. + $('#mastRadio').children().detach(); + keyHandler.fn = null; + keyHandler.map = {}; } // cache new view and context @@ -283,6 +312,27 @@ $mastRadio.node().appendChild(btnG.node()); } + function setKeyBindings(keyArg) { + if ($.isFunction(keyArg)) { + // set general key handler callback + keyHandler.fn = keyArg; + } else { + // set specific key filter map + keyHandler.map = keyArg; + } + } + + function keyIn() { + var event = d3.event, + keyCode = event.keyCode, + key = whatKey(keyCode), + cb = isF(keyHandler.map[key]) || isF(keyHandler.fn); + + if (cb) { + cb(current.view.token(), key, keyCode, event); + } + } + function resize(e) { d3.selectAll('.onosView').call(setViewDimensions); // allow current view to react to resize event... @@ -320,7 +370,6 @@ this.radioButtons = null; // no radio buttons yet this.ok = true; // valid view } - } function validateViewArgs(vid) { @@ -348,7 +397,8 @@ width: this.width, height: this.height, uid: this.uid, - setRadio: this.setRadio + setRadio: this.setRadio, + setKeys: this.setKeys } }, @@ -433,6 +483,10 @@ setRadioButtons(this.vid, btnSet, cb); }, + setKeys: function (keyArg) { + setKeyBindings(keyArg); + }, + uid: function (id) { return uid(this, id); } @@ -536,6 +590,8 @@ $(window).on('hashchange', hash); $(window).on('resize', resize); + d3.select('body').on('keydown', keyIn); + // Invoke hashchange callback to navigate to content // indicated by the window location hash. hash(); @@ -544,7 +600,6 @@ reportBuildErrors(); } - // export the api and build-UI function return { ui: uiApi, diff --git a/web/gui/src/main/webapp/sampleKeys.js b/web/gui/src/main/webapp/sampleKeys.js new file mode 100644 index 0000000000..350f46e422 --- /dev/null +++ b/web/gui/src/main/webapp/sampleKeys.js @@ -0,0 +1,90 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * 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. + */ + +/* + Sample view to illustrate key bindings. + + @author Simon Hunt + */ + +(function (onos) { + 'use strict'; + + var keyDispatch = { + Z: keyUndo, + X: keyCut, + C: keyCopy, + V: keyPaste, + space: keySpace + }; + + function keyUndo(view) { + note(view, 'Z = UNDO'); + } + + function keyCut(view) { + note(view, 'X = CUT'); + } + + function keyCopy(view) { + note(view, 'C = COPY'); + } + + function keyPaste(view) { + note(view, 'V = PASTE'); + } + + function keySpace(view) { + note(view, 'The SpaceBar'); + } + + function note(view, msg) { + view.$div.append('p') + .text(msg) + .style({ + 'font-size': '10pt', + color: 'darkorange', + padding: '0 20px', + margin: 0 + }); + } + + function keyCallback(view, key, keyCode, event) { + note(view, 'Key = ' + key + ' KeyCode = ' + keyCode); + } + + // Keys using a keyset to target specific keys only + function load(view, ctx) { + // this maps specific keys to specific functions (1) + view.setKeys(keyDispatch); + // whereas, this installs a general key handler function (2) + view.setKeys(keyCallback); + + // Note that (1) takes precedence over (2) + + view.$div.append('p') + .text('Press a key or two (try Z,X,C,V and others) ...') + .style('padding', '2px 8px'); + } + + // == register the view here, with links to lifecycle callbacks + + onos.ui.addView('sampleKeys', { + reset: true, // empty the div on reset + load: load + }); + +}(ONOS));