Simon Hunt

GUI -- Added key handler mechanism.

...@@ -71,6 +71,7 @@ ...@@ -71,6 +71,7 @@
71 var ONOS = $.onos({ 71 var ONOS = $.onos({
72 comment: "configuration options", 72 comment: "configuration options",
73 startVid: 'topo', 73 startVid: 'topo',
74 +// startVid: 'sampleKeys',
74 trace: false 75 trace: false
75 }); 76 });
76 </script> 77 </script>
...@@ -82,6 +83,7 @@ ...@@ -82,6 +83,7 @@
82 <script src="sample2.js"></script> 83 <script src="sample2.js"></script>
83 <script src="sampleAlt2.js"></script> 84 <script src="sampleAlt2.js"></script>
84 <script src="sampleRadio.js"></script> 85 <script src="sampleRadio.js"></script>
86 + <script src="sampleKeys.js"></script>
85 87
86 <!-- Contributed (application) views injected here --> 88 <!-- Contributed (application) views injected here -->
87 <!-- TODO: replace with template marker and inject refs server-side --> 89 <!-- TODO: replace with template marker and inject refs server-side -->
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
28 28
29 // configuration data 29 // configuration data
30 var config = { 30 var config = {
31 - useLiveData: true, 31 + useLiveData: false,
32 debugOn: false, 32 debugOn: false,
33 debug: { 33 debug: {
34 showNodeXY: false, 34 showNodeXY: false,
......
...@@ -49,13 +49,40 @@ ...@@ -49,13 +49,40 @@
49 ctx: '' 49 ctx: ''
50 }, 50 },
51 built = false, 51 built = false,
52 - errorCount = 0; 52 + errorCount = 0,
53 + keyHandler = {};
53 54
54 // DOM elements etc. 55 // DOM elements etc.
55 var $view, 56 var $view,
56 $mastRadio; 57 $mastRadio;
57 58
58 59
60 + function whatKey(code) {
61 + switch (code) {
62 + case 13: return 'enter';
63 + case 16: return 'shift';
64 + case 17: return 'ctrl';
65 + case 18: return 'alt';
66 + case 27: return 'esc';
67 + case 32: return 'space';
68 + case 37: return 'leftArrow';
69 + case 38: return 'upArrow';
70 + case 39: return 'rightArrow';
71 + case 40: return 'downArrow';
72 + case 91: return 'cmdLeft';
73 + case 93: return 'cmdRight';
74 + default:
75 + if ((code >= 48 && code <= 57) ||
76 + (code >= 65 && code <= 90)) {
77 + return String.fromCharCode(code);
78 + } else if (code >= 112 && code <= 123) {
79 + return 'F' + (code - 111);
80 + }
81 + return '.';
82 + }
83 + }
84 +
85 +
59 // .......................................................... 86 // ..........................................................
60 // Internal functions 87 // Internal functions
61 88
...@@ -206,9 +233,11 @@ ...@@ -206,9 +233,11 @@
206 // the incoming view, then unload it... 233 // the incoming view, then unload it...
207 if (current.view && (current.view.vid !== view.vid)) { 234 if (current.view && (current.view.vid !== view.vid)) {
208 current.view.unload(); 235 current.view.unload();
209 - // detach radio buttons, if they were there..
210 - $('#mastRadio').children().detach();
211 236
237 + // detach radio buttons, key handlers, etc.
238 + $('#mastRadio').children().detach();
239 + keyHandler.fn = null;
240 + keyHandler.map = {};
212 } 241 }
213 242
214 // cache new view and context 243 // cache new view and context
...@@ -283,6 +312,27 @@ ...@@ -283,6 +312,27 @@
283 $mastRadio.node().appendChild(btnG.node()); 312 $mastRadio.node().appendChild(btnG.node());
284 } 313 }
285 314
315 + function setKeyBindings(keyArg) {
316 + if ($.isFunction(keyArg)) {
317 + // set general key handler callback
318 + keyHandler.fn = keyArg;
319 + } else {
320 + // set specific key filter map
321 + keyHandler.map = keyArg;
322 + }
323 + }
324 +
325 + function keyIn() {
326 + var event = d3.event,
327 + keyCode = event.keyCode,
328 + key = whatKey(keyCode),
329 + cb = isF(keyHandler.map[key]) || isF(keyHandler.fn);
330 +
331 + if (cb) {
332 + cb(current.view.token(), key, keyCode, event);
333 + }
334 + }
335 +
286 function resize(e) { 336 function resize(e) {
287 d3.selectAll('.onosView').call(setViewDimensions); 337 d3.selectAll('.onosView').call(setViewDimensions);
288 // allow current view to react to resize event... 338 // allow current view to react to resize event...
...@@ -320,7 +370,6 @@ ...@@ -320,7 +370,6 @@
320 this.radioButtons = null; // no radio buttons yet 370 this.radioButtons = null; // no radio buttons yet
321 this.ok = true; // valid view 371 this.ok = true; // valid view
322 } 372 }
323 -
324 } 373 }
325 374
326 function validateViewArgs(vid) { 375 function validateViewArgs(vid) {
...@@ -348,7 +397,8 @@ ...@@ -348,7 +397,8 @@
348 width: this.width, 397 width: this.width,
349 height: this.height, 398 height: this.height,
350 uid: this.uid, 399 uid: this.uid,
351 - setRadio: this.setRadio 400 + setRadio: this.setRadio,
401 + setKeys: this.setKeys
352 } 402 }
353 }, 403 },
354 404
...@@ -433,6 +483,10 @@ ...@@ -433,6 +483,10 @@
433 setRadioButtons(this.vid, btnSet, cb); 483 setRadioButtons(this.vid, btnSet, cb);
434 }, 484 },
435 485
486 + setKeys: function (keyArg) {
487 + setKeyBindings(keyArg);
488 + },
489 +
436 uid: function (id) { 490 uid: function (id) {
437 return uid(this, id); 491 return uid(this, id);
438 } 492 }
...@@ -536,6 +590,8 @@ ...@@ -536,6 +590,8 @@
536 $(window).on('hashchange', hash); 590 $(window).on('hashchange', hash);
537 $(window).on('resize', resize); 591 $(window).on('resize', resize);
538 592
593 + d3.select('body').on('keydown', keyIn);
594 +
539 // Invoke hashchange callback to navigate to content 595 // Invoke hashchange callback to navigate to content
540 // indicated by the window location hash. 596 // indicated by the window location hash.
541 hash(); 597 hash();
...@@ -544,7 +600,6 @@ ...@@ -544,7 +600,6 @@
544 reportBuildErrors(); 600 reportBuildErrors();
545 } 601 }
546 602
547 -
548 // export the api and build-UI function 603 // export the api and build-UI function
549 return { 604 return {
550 ui: uiApi, 605 ui: uiApi,
......
1 +/*
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +/*
18 + Sample view to illustrate key bindings.
19 +
20 + @author Simon Hunt
21 + */
22 +
23 +(function (onos) {
24 + 'use strict';
25 +
26 + var keyDispatch = {
27 + Z: keyUndo,
28 + X: keyCut,
29 + C: keyCopy,
30 + V: keyPaste,
31 + space: keySpace
32 + };
33 +
34 + function keyUndo(view) {
35 + note(view, 'Z = UNDO');
36 + }
37 +
38 + function keyCut(view) {
39 + note(view, 'X = CUT');
40 + }
41 +
42 + function keyCopy(view) {
43 + note(view, 'C = COPY');
44 + }
45 +
46 + function keyPaste(view) {
47 + note(view, 'V = PASTE');
48 + }
49 +
50 + function keySpace(view) {
51 + note(view, 'The SpaceBar');
52 + }
53 +
54 + function note(view, msg) {
55 + view.$div.append('p')
56 + .text(msg)
57 + .style({
58 + 'font-size': '10pt',
59 + color: 'darkorange',
60 + padding: '0 20px',
61 + margin: 0
62 + });
63 + }
64 +
65 + function keyCallback(view, key, keyCode, event) {
66 + note(view, 'Key = ' + key + ' KeyCode = ' + keyCode);
67 + }
68 +
69 + // Keys using a keyset to target specific keys only
70 + function load(view, ctx) {
71 + // this maps specific keys to specific functions (1)
72 + view.setKeys(keyDispatch);
73 + // whereas, this installs a general key handler function (2)
74 + view.setKeys(keyCallback);
75 +
76 + // Note that (1) takes precedence over (2)
77 +
78 + view.$div.append('p')
79 + .text('Press a key or two (try Z,X,C,V and others) ...')
80 + .style('padding', '2px 8px');
81 + }
82 +
83 + // == register the view here, with links to lifecycle callbacks
84 +
85 + onos.ui.addView('sampleKeys', {
86 + reset: true, // empty the div on reset
87 + load: load
88 + });
89 +
90 +}(ONOS));