Simon Hunt

GUI -- Added KeyService and FnService; implemented 'T' key for toggle theme.

Change-Id: I6ae3cb76aaa5c72422eac180cb46d604ead21afc
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 + ONOS GUI -- General Purpose Functions
19 +
20 + @author Simon Hunt
21 + */
22 +(function (onos) {
23 + 'use strict';
24 +
25 + onos.factory('FnService', [function () {
26 + return {
27 + isF: function (f) {
28 + return $.isFunction(f) ? f : null;
29 + },
30 + isA: function (a) {
31 + return $.isArray(a) ? a : null;
32 + },
33 + isS: function (s) {
34 + return typeof s === 'string' ? s : null;
35 + },
36 + isO: function (o) {
37 + return $.isPlainObject(o) ? o : null;
38 + }
39 + };
40 + }]);
41 +
42 +}(ONOS));
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 + ONOS GUI -- Key Handler Service
19 +
20 + @author Simon Hunt
21 + */
22 +(function (onos) {
23 + 'use strict';
24 +
25 + // references to injected services
26 + var f;
27 +
28 + // internal state
29 + var keyHandler = {
30 + globalKeys: {},
31 + maskedKeys: {},
32 + viewKeys: {},
33 + viewFn: null,
34 + viewGestures: []
35 + },
36 + theme = 'light';
37 +
38 + // TODO: we need to have the concept of view token here..
39 + function getViewToken() {
40 + return 'NotYetAViewToken';
41 + }
42 +
43 + function whatKey(code) {
44 + switch (code) {
45 + case 13: return 'enter';
46 + case 16: return 'shift';
47 + case 17: return 'ctrl';
48 + case 18: return 'alt';
49 + case 27: return 'esc';
50 + case 32: return 'space';
51 + case 37: return 'leftArrow';
52 + case 38: return 'upArrow';
53 + case 39: return 'rightArrow';
54 + case 40: return 'downArrow';
55 + case 91: return 'cmdLeft';
56 + case 93: return 'cmdRight';
57 + case 187: return 'equals';
58 + case 189: return 'dash';
59 + case 191: return 'slash';
60 + case 192: return 'backQuote';
61 + case 220: return 'backSlash';
62 + default:
63 + if ((code >= 48 && code <= 57) ||
64 + (code >= 65 && code <= 90)) {
65 + return String.fromCharCode(code);
66 + } else if (code >= 112 && code <= 123) {
67 + return 'F' + (code - 111);
68 + }
69 + return '.';
70 + }
71 + }
72 +
73 + function keyIn() {
74 + var event = d3.event,
75 + keyCode = event.keyCode,
76 + key = whatKey(keyCode),
77 + kh = keyHandler,
78 + gk = kh.globalKeys[key],
79 + gcb = f.isF(gk) || (f.isA(gk) && f.isF(gk[0])),
80 + vk = kh.viewKeys[key],
81 + vcb = f.isF(vk) || (f.isA(vk) && f.isF(vk[0])) || f.isF(kh.viewFn),
82 + token = getViewToken();
83 +
84 + // global callback?
85 + if (gcb && gcb(token, key, keyCode, event)) {
86 + // if the event was 'handled', we are done
87 + return;
88 + }
89 + // otherwise, let the view callback have a shot
90 + if (vcb) {
91 + vcb(token, key, keyCode, event);
92 + }
93 + }
94 +
95 + function setupGlobalKeys() {
96 + $.extend(keyHandler, {
97 + globalKeys: {
98 + backSlash: [quickHelp, 'Show / hide Quick Help'],
99 + slash: [quickHelp, 'Show / hide Quick Help'],
100 + esc: [escapeKey, 'Dismiss dialog or cancel selections'],
101 + T: [toggleTheme, "Toggle theme"]
102 + },
103 + globalFormat: ['backSlash', 'slash', 'esc', 'T'],
104 +
105 + // Masked keys are global key handlers that always return true.
106 + // That is, the view will never see the event for that key.
107 + maskedKeys: {
108 + slash: true,
109 + backSlash: true,
110 + T: true
111 + }
112 + });
113 + }
114 +
115 + function quickHelp(view, key, code, ev) {
116 + // TODO: show quick help
117 + //libApi.quickHelp.show(keyHandler);
118 + console.log('QUICK-HELP');
119 + return true;
120 + }
121 +
122 + function escapeKey(view, key, code, ev) {
123 + // TODO: plumb in handling of alerts and quick help dismissal
124 +/*
125 + if (alerts.open) {
126 + closeAlerts();
127 + return true;
128 + }
129 + if (libApi.quickHelp.hide()) {
130 + return true;
131 + }
132 +*/
133 + console.log('ESCAPE');
134 + return false;
135 + }
136 +
137 + function toggleTheme(view, key, code, ev) {
138 + var body = d3.select('body');
139 + theme = (theme === 'light') ? 'dark' : 'light';
140 + body.classed('light dark', false);
141 + body.classed(theme, true);
142 + // TODO: emit theme-change event to current view...
143 + //theme(view);
144 + return true;
145 + }
146 +
147 + onos.factory('KeyService', ['FnService', function (fs) {
148 + f = fs;
149 + return {
150 + init: function () {
151 + console.log('initializing keydown handler....');
152 + d3.select('body').on('keydown', keyIn);
153 + setupGlobalKeys();
154 + }
155 + };
156 + }]);
157 +
158 +}(ONOS));
...@@ -27,13 +27,13 @@ ...@@ -27,13 +27,13 @@
27 27
28 <script src="../tp/d3.js"></script> 28 <script src="../tp/d3.js"></script>
29 <script src="../tp/topojson.v1.min.js"></script> 29 <script src="../tp/topojson.v1.min.js"></script>
30 - 30 + <script src="../tp/jquery-2.1.1.min.js"></script>
31 - <!-- NOTE: We are going to see if we can dispense with jQuery... -->
32 - <!--<script src="../tp/jquery-2.1.1.min.js"></script>-->
33 31
34 <!-- ONOS UI Framework included here --> 32 <!-- ONOS UI Framework included here -->
35 <!-- TODO: use a single catenated-minified file here --> 33 <!-- TODO: use a single catenated-minified file here -->
36 <script src="onos.js"></script> 34 <script src="onos.js"></script>
35 + <script src="fw/lib/fn.js"></script>
36 + <script src="fw/lib/keys.js"></script>
37 <script src="fw/mast/mast.js"></script> 37 <script src="fw/mast/mast.js"></script>
38 38
39 <!-- Framework and library stylesheets included here --> 39 <!-- Framework and library stylesheets included here -->
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
50 <!-- TODO: inject style-sheet refs server-side --> 50 <!-- TODO: inject style-sheet refs server-side -->
51 </head> 51 </head>
52 <body class="light" ng-app="onosApp"> 52 <body class="light" ng-app="onosApp">
53 + <div id="frame" ng-controller="OnosCtrl as onosCtrl">
53 <div id="mast" 54 <div id="mast"
54 ng-controller="MastCtrl as mastCtrl" 55 ng-controller="MastCtrl as mastCtrl"
55 ng-include="'fw/mast/mast.html'"></div> 56 ng-include="'fw/mast/mast.html'"></div>
...@@ -61,5 +62,6 @@ ...@@ -61,5 +62,6 @@
61 <div id="flash"></div> 62 <div id="flash"></div>
62 <div id="quickhelp"></div> 63 <div id="quickhelp"></div>
63 <div id="deathmask"></div> 64 <div id="deathmask"></div>
65 + </div>
64 </body> 66 </body>
65 </html> 67 </html>
......
...@@ -19,13 +19,17 @@ ...@@ -19,13 +19,17 @@
19 19
20 @author Simon Hunt 20 @author Simon Hunt
21 */ 21 */
22 +
23 +// our one global variable
24 +var ONOS;
25 +
22 (function () { 26 (function () {
23 'use strict'; 27 'use strict';
24 28
25 - angular.module('onosApp', ['onosMast']) 29 + ONOS = angular.module('onosApp', ['onosMast'])
26 - .controller('OnosCtrl', [function () { 30 + .controller('OnosCtrl', ['KeyService', function (ks) {
27 - // controller logic here
28 console.log('OnosCtrl has been created'); 31 console.log('OnosCtrl has been created');
32 + ks.init();
29 }]); 33 }]);
30 34
31 }()); 35 }());
......