blob: 81d0bc3336a82d674222a1097c526750cf90b88d [file] [log] [blame]
Simon Hunt1eecfa22014-12-16 14:46:29 -08001/*
Simon Hunt8ead3a22015-01-06 11:00:15 -08002 * Copyright 2014,2015 Open Networking Laboratory
Simon Hunt1eecfa22014-12-16 14:46:29 -08003 *
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/*
Simon Huntdc6362a2014-12-18 19:55:23 -080018 ONOS GUI -- Util -- Key Handler Service
Simon Hunt1eecfa22014-12-16 14:46:29 -080019 */
Simon Huntdc6362a2014-12-18 19:55:23 -080020(function () {
Simon Hunt1eecfa22014-12-16 14:46:29 -080021 'use strict';
22
23 // references to injected services
Yuta HIGUCHI4f39bcd2014-12-18 20:46:14 -080024 var $log, fs, ts;
Simon Hunt1eecfa22014-12-16 14:46:29 -080025
26 // internal state
27 var keyHandler = {
28 globalKeys: {},
29 maskedKeys: {},
30 viewKeys: {},
31 viewFn: null,
32 viewGestures: []
Yuta HIGUCHI4f39bcd2014-12-18 20:46:14 -080033 };
Simon Hunt1eecfa22014-12-16 14:46:29 -080034
35 // TODO: we need to have the concept of view token here..
36 function getViewToken() {
37 return 'NotYetAViewToken';
38 }
39
40 function whatKey(code) {
41 switch (code) {
42 case 13: return 'enter';
43 case 16: return 'shift';
44 case 17: return 'ctrl';
45 case 18: return 'alt';
46 case 27: return 'esc';
47 case 32: return 'space';
48 case 37: return 'leftArrow';
49 case 38: return 'upArrow';
50 case 39: return 'rightArrow';
51 case 40: return 'downArrow';
52 case 91: return 'cmdLeft';
53 case 93: return 'cmdRight';
54 case 187: return 'equals';
55 case 189: return 'dash';
56 case 191: return 'slash';
57 case 192: return 'backQuote';
58 case 220: return 'backSlash';
59 default:
60 if ((code >= 48 && code <= 57) ||
61 (code >= 65 && code <= 90)) {
62 return String.fromCharCode(code);
63 } else if (code >= 112 && code <= 123) {
64 return 'F' + (code - 111);
65 }
66 return '.';
67 }
68 }
69
70 function keyIn() {
71 var event = d3.event,
72 keyCode = event.keyCode,
73 key = whatKey(keyCode),
74 kh = keyHandler,
75 gk = kh.globalKeys[key],
Yuta HIGUCHI4f39bcd2014-12-18 20:46:14 -080076 gcb = fs.isF(gk) || (fs.isA(gk) && fs.isF(gk[0])),
Simon Hunt1eecfa22014-12-16 14:46:29 -080077 vk = kh.viewKeys[key],
Yuta HIGUCHI4f39bcd2014-12-18 20:46:14 -080078 vcb = fs.isF(vk) || (fs.isA(vk) && fs.isF(vk[0])) || fs.isF(kh.viewFn),
Simon Hunt1eecfa22014-12-16 14:46:29 -080079 token = getViewToken();
80
Simon Huntdc6362a2014-12-18 19:55:23 -080081 d3.event.stopPropagation();
82
Simon Hunt1eecfa22014-12-16 14:46:29 -080083 // global callback?
84 if (gcb && gcb(token, key, keyCode, event)) {
85 // if the event was 'handled', we are done
86 return;
87 }
88 // otherwise, let the view callback have a shot
89 if (vcb) {
90 vcb(token, key, keyCode, event);
91 }
92 }
93
94 function setupGlobalKeys() {
Simon Hunt404f6b22015-01-21 14:00:56 -080095 angular.extend(keyHandler, {
Simon Hunt1eecfa22014-12-16 14:46:29 -080096 globalKeys: {
97 backSlash: [quickHelp, 'Show / hide Quick Help'],
98 slash: [quickHelp, 'Show / hide Quick Help'],
99 esc: [escapeKey, 'Dismiss dialog or cancel selections'],
100 T: [toggleTheme, "Toggle theme"]
101 },
102 globalFormat: ['backSlash', 'slash', 'esc', 'T'],
103
104 // Masked keys are global key handlers that always return true.
105 // That is, the view will never see the event for that key.
106 maskedKeys: {
107 slash: true,
108 backSlash: true,
109 T: true
110 }
111 });
112 }
113
114 function quickHelp(view, key, code, ev) {
115 // TODO: show quick help
Simon Hunt7256d082014-12-18 21:43:28 -0800116 // delegate to QuickHelp service.
Simon Hunt1eecfa22014-12-16 14:46:29 -0800117 //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
Simon Hunt7256d082014-12-18 21:43:28 -0800124 // We will delegate to the Alert / QuickHelp Services as appropriate.
Simon Hunt1eecfa22014-12-16 14:46:29 -0800125/*
126 if (alerts.open) {
127 closeAlerts();
128 return true;
129 }
130 if (libApi.quickHelp.hide()) {
131 return true;
132 }
133*/
134 console.log('ESCAPE');
135 return false;
136 }
137
138 function toggleTheme(view, key, code, ev) {
Yuta HIGUCHI4f39bcd2014-12-18 20:46:14 -0800139 ts.toggleTheme();
Simon Hunt1eecfa22014-12-16 14:46:29 -0800140 return true;
141 }
142
Simon Hunt59df0b22014-12-17 10:32:25 -0800143 function setKeyBindings(keyArg) {
144 var viewKeys,
145 masked = [];
146
Yuta HIGUCHI4f39bcd2014-12-18 20:46:14 -0800147 if (fs.isF(keyArg)) {
Simon Hunt59df0b22014-12-17 10:32:25 -0800148 // set general key handler callback
149 keyHandler.viewFn = keyArg;
150 } else {
151 // set specific key filter map
152 viewKeys = d3.map(keyArg).keys();
153 viewKeys.forEach(function (key) {
154 if (keyHandler.maskedKeys[key]) {
Simon Huntaf322072014-12-18 13:23:40 -0800155 masked.push('setKeyBindings(): Key "' + key + '" is reserved');
Simon Hunt59df0b22014-12-17 10:32:25 -0800156 }
157 });
158
159 if (masked.length) {
Simon Huntaf322072014-12-18 13:23:40 -0800160 $log.warn(masked.join('\n'));
Simon Hunt59df0b22014-12-17 10:32:25 -0800161 }
162 keyHandler.viewKeys = keyArg;
163 }
164 }
165
166 function getKeyBindings() {
167 var gkeys = d3.map(keyHandler.globalKeys).keys(),
168 masked = d3.map(keyHandler.maskedKeys).keys(),
169 vkeys = d3.map(keyHandler.viewKeys).keys(),
Yuta HIGUCHI4f39bcd2014-12-18 20:46:14 -0800170 vfn = !!fs.isF(keyHandler.viewFn);
Simon Hunt59df0b22014-12-17 10:32:25 -0800171
172 return {
173 globalKeys: gkeys,
174 maskedKeys: masked,
175 viewKeys: vkeys,
176 viewFunction: vfn
177 };
178 }
179
Simon Huntdc6362a2014-12-18 19:55:23 -0800180 angular.module('onosUtil')
Yuta HIGUCHI4f39bcd2014-12-18 20:46:14 -0800181 .factory('KeyService', ['$log', 'FnService', 'ThemeService',
182 function (_$log_, _fs_, _ts_) {
183 $log = _$log_;
184 fs = _fs_;
185 ts = _ts_;
186
Simon Huntdc6362a2014-12-18 19:55:23 -0800187 return {
188 installOn: function (elem) {
189 elem.on('keydown', keyIn);
190 setupGlobalKeys();
191 },
Simon Huntdc6362a2014-12-18 19:55:23 -0800192 keyBindings: function (x) {
193 if (x === undefined) {
194 return getKeyBindings();
195 } else {
196 setKeyBindings(x);
197 }
198 },
199 gestureNotes: function (g) {
200 if (g === undefined) {
201 return keyHandler.viewGestures;
202 } else {
Yuta HIGUCHI4f39bcd2014-12-18 20:46:14 -0800203 keyHandler.viewGestures = fs.isA(g) || [];
Simon Huntdc6362a2014-12-18 19:55:23 -0800204 }
Simon Hunt59df0b22014-12-17 10:32:25 -0800205 }
Simon Huntdc6362a2014-12-18 19:55:23 -0800206 };
Simon Hunt1eecfa22014-12-16 14:46:29 -0800207 }]);
208
Simon Huntdc6362a2014-12-18 19:55:23 -0800209}());