blob: fa86f828459e548341056e992e7d2c4bdd177e89 [file] [log] [blame]
Bri Prebilic Cole4db8dce2015-03-18 13:57:24 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Bri Prebilic Cole4db8dce2015-03-18 13:57:24 -07003 *
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 -- Topology Toolbar Module.
Simon Hunt09060142015-03-18 20:23:32 -070019 Functions for creating and interacting with the toolbar.
Bri Prebilic Cole4db8dce2015-03-18 13:57:24 -070020 */
21
22(function () {
Bri Prebilic Cole54d09382015-03-19 18:40:27 -070023 'use strict';
Bri Prebilic Cole4db8dce2015-03-18 13:57:24 -070024
25 // injected references
Simon Hunta211f7f2015-11-09 12:48:23 -080026 var $log, fs, tbs, ps, tov, tds, api;
Bri Prebilic Cole4db8dce2015-03-18 13:57:24 -070027
Simon Hunt8d22c4b2015-08-06 16:24:43 -070028 // API:
29 // getActionEntry
30 // setUpKeys
31
Simon Hunt09060142015-03-18 20:23:32 -070032 // internal state
Simon Hunta5b53af2015-10-12 15:56:40 -070033 var toolbar, keyData, cachedState, thirdRow, ovRset, ovIndex;
Bri Prebilic Cole4db8dce2015-03-18 13:57:24 -070034
Bri Prebilic Coled6219052015-03-19 14:34:02 -070035 // constants
Simon Huntc7ae7952015-04-08 18:59:27 -070036 var name = 'topo-tbar',
Simon Hunt8d22c4b2015-08-06 16:24:43 -070037 cooktag = 'topo_prefs',
38 soa = 'switchOverlayActions: ',
Simon Hunta5b53af2015-10-12 15:56:40 -070039 selOver = 'Select overlay here ⇧',
40 defaultOverlay = 'traffic';
Simon Hunt8d22c4b2015-08-06 16:24:43 -070041
Bri Prebilic Coled6219052015-03-19 14:34:02 -070042
Simon Hunt09060142015-03-18 20:23:32 -070043 // key to button mapping data
44 var k2b = {
Steven Burrows1c2a9682017-07-14 16:52:46 +010045 O: { id: 'summary-tog', gid: 'm_summary', isel: true },
Simon Huntc217cb92016-08-30 16:17:51 -070046 I: { id: 'instance-tog', gid: 'm_uiAttached', isel: true },
47 D: { id: 'details-tog', gid: 'm_details', isel: true },
48 H: { id: 'hosts-tog', gid: 'm_endstation', isel: false },
49 M: { id: 'offline-tog', gid: 'm_switch', isel: true },
50 P: { id: 'ports-tog', gid: 'm_ports', isel: true },
51 B: { id: 'bkgrnd-tog', gid: 'm_map', isel: false },
52 G: { id: 'bkgrnd-sel', gid: 'm_selectMap' },
53 S: { id: 'sprite-tog', gid: 'm_cloud', isel: false },
Bri Prebilic Cole812f6c02015-03-24 17:10:33 -070054
Simon Huntc217cb92016-08-30 16:17:51 -070055 Z: { id: 'oblique-tog', gid: 'm_oblique', isel: false },
56 N: { id: 'filters-btn', gid: 'm_filters' },
57 L: { id: 'cycleLabels-btn', gid: 'm_cycleLabels' },
58 R: { id: 'resetZoom-btn', gid: 'm_resetZoom' },
Bri Prebilic Cole812f6c02015-03-24 17:10:33 -070059
Steven Burrows1c2a9682017-07-14 16:52:46 +010060 E: { id: 'eqMaster-btn', gid: 'm_eqMaster' },
Simon Hunt09060142015-03-18 20:23:32 -070061 };
Bri Prebilic Cole4db8dce2015-03-18 13:57:24 -070062
Simon Hunt8d22c4b2015-08-06 16:24:43 -070063 var prohibited = [
64 'T', 'backSlash', 'slash',
Steven Burrows1c2a9682017-07-14 16:52:46 +010065 'X', // needed until we re-instate X above.
Simon Hunt8d22c4b2015-08-06 16:24:43 -070066 ];
67 prohibited = prohibited.concat(d3.map(k2b).keys());
68
69
Simon Huntc7ae7952015-04-08 18:59:27 -070070 // initial toggle state: default settings and tag to key mapping
71 var defaultPrefsState = {
Simon Huntfcbde892015-04-16 12:05:28 -070072 insts: 1,
Thomas Vachuska0af26912016-03-21 21:37:30 -070073 summary: 1,
Simon Huntc7ae7952015-04-08 18:59:27 -070074 detail: 1,
Simon Huntfcbde892015-04-16 12:05:28 -070075 hosts: 0,
76 offdev: 1,
Thomas Vachuska0af26912016-03-21 21:37:30 -070077 dlbls: 0,
Simon Hunt10618f62017-06-15 19:30:52 -070078 hlbls: 0,
Simon Huntfcbde892015-04-16 12:05:28 -070079 porthl: 1,
Simon Huntd0fe66c2015-06-10 10:16:36 -070080 bg: 0,
Simon Huntfcbde892015-04-16 12:05:28 -070081 spr: 0,
Steven Burrows1c2a9682017-07-14 16:52:46 +010082 ovid: 'traffic', // default to traffic overlay
83 toolbar: 0,
Simon Huntc7ae7952015-04-08 18:59:27 -070084 },
85 prefsMap = {
Simon Huntc7ae7952015-04-08 18:59:27 -070086 summary: 'O',
Simon Huntfcbde892015-04-16 12:05:28 -070087 insts: 'I',
88 detail: 'D',
89 hosts: 'H',
90 offdev: 'M',
91 porthl: 'P',
92 bg: 'B',
Steven Burrows1c2a9682017-07-14 16:52:46 +010093 spr: 'S',
Simon Huntfcbde892015-04-16 12:05:28 -070094 // NOTE: toolbar state is handled separately
Simon Huntc7ae7952015-04-08 18:59:27 -070095 };
96
Bri Prebilic Cole4db8dce2015-03-18 13:57:24 -070097 function init(_api_) {
98 api = _api_;
Simon Huntc7ae7952015-04-08 18:59:27 -070099 // retrieve initial toggle button settings from user prefs
100 setInitToggleState();
101 }
102
103 function topoDefPrefs() {
104 return angular.extend({}, defaultPrefsState);
105 }
106
107 function setInitToggleState() {
Simon Huntfc5c5842017-02-01 23:32:18 -0800108 cachedState = ps.asNumbers(
109 ps.getPrefs(cooktag, defaultPrefsState), ['ovid'], true
110 );
Simon Huntfcbde892015-04-16 12:05:28 -0700111 $log.debug('TOOLBAR---- read prefs state:', cachedState);
Simon Huntc7ae7952015-04-08 18:59:27 -0700112
Simon Huntfcbde892015-04-16 12:05:28 -0700113 if (!cachedState) {
114 cachedState = topoDefPrefs();
115 ps.setPrefs(cooktag, cachedState);
116 $log.debug('TOOLBAR---- Set default prefs state:', cachedState);
Simon Huntc7ae7952015-04-08 18:59:27 -0700117 }
118
119 angular.forEach(prefsMap, function (v, k) {
Simon Huntfcbde892015-04-16 12:05:28 -0700120 var cfg = k2b[v];
121 cfg && (cfg.isel = !!cachedState[k]);
Simon Huntc7ae7952015-04-08 18:59:27 -0700122 });
Bri Prebilic Cole4db8dce2015-03-18 13:57:24 -0700123 }
124
Simon Hunt09060142015-03-18 20:23:32 -0700125 function initKeyData() {
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700126 // TODO: use angular forEach instead of d3.map
Simon Hunt09060142015-03-18 20:23:32 -0700127 keyData = d3.map(k2b);
Steven Burrows1c2a9682017-07-14 16:52:46 +0100128 keyData.forEach(function (key, value) {
Simon Hunte1e968e2017-08-09 19:18:56 -0700129 var data = api.getActionEntry(key),
130 ttfn = data[1]; // tooltip-possibly-a-function
131
Simon Hunt5989ddf2017-08-02 20:38:12 -0700132 value.key = key;
Steven Burrows1c2a9682017-07-14 16:52:46 +0100133 value.cb = data[0]; // on-click callback
Simon Hunte1e968e2017-08-09 19:18:56 -0700134
135 // tooltip function invoked at the time the tooltip is displayed
136 value.tt = function () {
137 return fs.isF(ttfn) ? ttfn() : "" + ttfn;
138 };
Simon Hunt09060142015-03-18 20:23:32 -0700139 });
Bri Prebilic Cole4db8dce2015-03-18 13:57:24 -0700140 }
141
Simon Hunt5989ddf2017-08-02 20:38:12 -0700142 // returns a no-args function that returns the tooltip text
143 function deferredText(v) {
144 // this function will get invoked at the time the tooltip is displayed:
145 return function () {
Simon Hunte1e968e2017-08-09 19:18:56 -0700146 return (fs.isF(v.tt) ? v.tt() : v.tt) + ' (' + v.key + ')';
Simon Hunt5989ddf2017-08-02 20:38:12 -0700147 };
148 }
149
Bri Prebilic Cole812f6c02015-03-24 17:10:33 -0700150 function addButton(key) {
151 var v = keyData.get(key);
Simon Hunt5989ddf2017-08-02 20:38:12 -0700152 v.btn = toolbar.addButton(v.id, v.gid, v.cb, deferredText(v));
Bri Prebilic Cole812f6c02015-03-24 17:10:33 -0700153 }
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700154
Bri Prebilic Coled8745462015-06-01 16:08:57 -0700155 function addToggle(key, suppressIfMobile) {
Simon Hunt09060142015-03-18 20:23:32 -0700156 var v = keyData.get(key);
Bri Prebilic Coled8745462015-06-01 16:08:57 -0700157 if (suppressIfMobile && fs.isMobile()) { return; }
Simon Hunt5989ddf2017-08-02 20:38:12 -0700158 v.tog = toolbar.addToggle(v.id, v.gid, v.isel, v.cb, deferredText(v));
Bri Prebilic Cole4db8dce2015-03-18 13:57:24 -0700159 }
160
Bri Prebilic Cole04b41402015-03-18 17:25:34 -0700161 function addFirstRow() {
Simon Hunt09060142015-03-18 20:23:32 -0700162 addToggle('I');
Simon Huntda2f3cc2015-03-19 15:11:57 -0700163 addToggle('O');
Simon Hunt09060142015-03-18 20:23:32 -0700164 addToggle('D');
Bri Prebilic Cole4db8dce2015-03-18 13:57:24 -0700165 toolbar.addSeparator();
166
Simon Hunt09060142015-03-18 20:23:32 -0700167 addToggle('H');
168 addToggle('M');
Bri Prebilic Coled8745462015-06-01 16:08:57 -0700169 addToggle('P', true);
Simon Hunt09060142015-03-18 20:23:32 -0700170 addToggle('B');
Thomas Vachuska26be4f32016-03-31 01:10:27 -0700171 addButton('G');
Bri Prebilic Coled8745462015-06-01 16:08:57 -0700172 addToggle('S', true);
Bri Prebilic Cole04b41402015-03-18 17:25:34 -0700173 }
Simon Hunt72e44bf2015-07-21 21:34:20 -0700174
Bri Prebilic Cole812f6c02015-03-24 17:10:33 -0700175 function addSecondRow() {
Steven Burrows1c2a9682017-07-14 16:52:46 +0100176 // addToggle('X');
Bri Prebilic Cole812f6c02015-03-24 17:10:33 -0700177 addToggle('Z');
Bri Prebilic Coleb5f2b152015-04-07 14:58:09 -0700178 addButton('N');
Bri Prebilic Cole812f6c02015-03-24 17:10:33 -0700179 addButton('L');
180 addButton('R');
Simon Hunt72e44bf2015-07-21 21:34:20 -0700181 toolbar.addSeparator();
182 addButton('E');
Bri Prebilic Cole812f6c02015-03-24 17:10:33 -0700183 }
Simon Hunt72e44bf2015-07-21 21:34:20 -0700184
Simon Hunt72e44bf2015-07-21 21:34:20 -0700185 function addOverlays() {
186 toolbar.addSeparator();
187
188 // generate radio button set for overlays; start with 'none'
189 var rset = [{
Simon Huntc217cb92016-08-30 16:17:51 -0700190 gid: 'm_unknown',
Simon Hunt72e44bf2015-07-21 21:34:20 -0700191 tooltip: 'No Overlay',
Simon Hunte05cae42015-07-23 17:35:24 -0700192 cb: function () {
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700193 tov.tbSelection(null, switchOverlayActions);
Steven Burrows1c2a9682017-07-14 16:52:46 +0100194 },
Simon Hunt72e44bf2015-07-21 21:34:20 -0700195 }];
Simon Hunta5b53af2015-10-12 15:56:40 -0700196 ovIndex = tov.augmentRbset(rset, switchOverlayActions);
197 ovRset = toolbar.addRadioSet('topo-overlays', rset);
Simon Hunt72e44bf2015-07-21 21:34:20 -0700198 }
199
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700200 // invoked by overlay service to switch out old buttons and switch in new
201 function switchOverlayActions(oid, keyBindings) {
202 var prohibits = [],
203 kb = fs.isO(keyBindings) || {},
204 order = fs.isA(kb._keyOrder) || [];
205
206 if (keyBindings && !keyBindings._keyOrder) {
207 $log.warn(soa + 'no _keyOrder property defined');
208 } else {
209 // sanity removal of reserved property names
210 ['esc', '_keyListener', '_helpFormat'].forEach(function (k) {
211 fs.removeFromArray(k, order);
212 });
213 }
214
Simon Hunta211f7f2015-11-09 12:48:23 -0800215 // ensure dialog has closed (if opened by outgoing overlay)
216 tds.closeDialog();
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700217 thirdRow.clear();
218
Simon Hunt5ab45e12016-07-07 15:29:52 -0700219 // persist our choice of overlay...
Simon Huntfc5c5842017-02-01 23:32:18 -0800220 persistTopoPrefs('ovid', oid);
Simon Hunt5ab45e12016-07-07 15:29:52 -0700221
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700222 if (!order.length) {
223 thirdRow.setText(selOver);
224 thirdRow.classed('right', true);
225 api.setUpKeys(); // clear previous overlay key bindings
226
227 } else {
228 thirdRow.classed('right', false);
229 angular.forEach(order, function (key) {
230 var value, bid, gid, tt;
231
232 if (prohibited.indexOf(key) > -1) {
233 prohibits.push(key);
234
235 } else {
236 value = keyBindings[key];
237 bid = oid + '-' + key;
238 gid = tov.mkGlyphId(oid, value.gid);
239 tt = value.tt + ' (' + key + ')';
240 thirdRow.addButton(bid, gid, value.cb, tt);
241 }
242 });
243 api.setUpKeys(keyBindings); // add overlay key bindings
244 }
245
246 if (prohibits.length) {
247 $log.warn(soa + 'Prohibited key bindings ignored:', prohibits);
248 }
Bri Prebilic Cole812f6c02015-03-24 17:10:33 -0700249 }
Bri Prebilic Cole4db8dce2015-03-18 13:57:24 -0700250
Bri Prebilic Cole04b41402015-03-18 17:25:34 -0700251 function createToolbar() {
Simon Hunt09060142015-03-18 20:23:32 -0700252 initKeyData();
Bri Prebilic Coled6219052015-03-19 14:34:02 -0700253 toolbar = tbs.createToolbar(name);
Bri Prebilic Cole04b41402015-03-18 17:25:34 -0700254 addFirstRow();
Bri Prebilic Cole812f6c02015-03-24 17:10:33 -0700255 toolbar.addRow();
256 addSecondRow();
Simon Hunt72e44bf2015-07-21 21:34:20 -0700257 addOverlays();
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700258 thirdRow = toolbar.addRow();
259 thirdRow.setText(selOver);
260 thirdRow.classed('right', true);
Simon Hunt72e44bf2015-07-21 21:34:20 -0700261
Simon Huntfcbde892015-04-16 12:05:28 -0700262 if (cachedState.toolbar) {
263 toolbar.show();
264 } else {
265 toolbar.hide();
266 }
Bri Prebilic Cole4db8dce2015-03-18 13:57:24 -0700267 }
268
Bri Prebilic Coled6219052015-03-19 14:34:02 -0700269 function destroyToolbar() {
270 tbs.destroyToolbar(name);
Simon Hunt4a6b54b2015-10-27 22:08:25 -0700271 tov.resetOnToolbarDestroy();
Bri Prebilic Coled6219052015-03-19 14:34:02 -0700272 }
273
Simon Hunt09060142015-03-18 20:23:32 -0700274 // allows us to ensure the button states track key strokes
275 function keyListener(key) {
276 var v = keyData.get(key);
277
278 if (v) {
279 // we have a valid button mapping
280 if (v.tog) {
281 // it's a toggle button
282 v.tog.toggleNoCb();
283 }
284 }
285 }
286
Simon Hunt5ab45e12016-07-07 15:29:52 -0700287 function persistTopoPrefs(key, val) {
Thomas Vachuska0af26912016-03-21 21:37:30 -0700288 var prefs = ps.getPrefs(cooktag, defaultPrefsState);
Simon Hunt5ab45e12016-07-07 15:29:52 -0700289 prefs[key] = val === undefined ? !prefs[key] : val;
Thomas Vachuska0af26912016-03-21 21:37:30 -0700290 ps.setPrefs('topo_prefs', prefs);
Simon Hunt90dcc3e2015-03-25 15:01:27 -0700291 }
292
Simon Hunt5ab45e12016-07-07 15:29:52 -0700293 function toggleToolbar() {
294 toolbar.toggle();
295 persistTopoPrefs('toolbar');
296 }
Simon Hunt10618f62017-06-15 19:30:52 -0700297
Simon Huntfc5c5842017-02-01 23:32:18 -0800298 function selectOverlay(ovid) {
299 var idx = ovIndex[defaultOverlay] || 0,
300 pidx = (ovid === null) ? 0 : ovIndex[ovid] || -1;
301 if (pidx >= 0 && pidx < ovRset.size()) {
302 idx = pidx;
Simon Hunt5ab45e12016-07-07 15:29:52 -0700303 }
Simon Hunta5b53af2015-10-12 15:56:40 -0700304 ovRset.selectedIndex(idx);
305 }
306
Simon Hunt5b024d72016-01-29 11:02:43 -0800307 // an overlay was selected via Function-Key press
308 function fnkey(idx) {
309 if (idx < ovRset.size() && idx !== ovRset.selectedIndex()) {
310 ovRset.selectedIndex(idx);
311 }
312 }
313
Bri Prebilic Cole4db8dce2015-03-18 13:57:24 -0700314 angular.module('ovTopo')
Simon Huntc7ae7952015-04-08 18:59:27 -0700315 .factory('TopoToolbarService',
Bri Prebilic Coled8745462015-06-01 16:08:57 -0700316 ['$log', 'FnService', 'ToolbarService', 'PrefsService',
Simon Hunta211f7f2015-11-09 12:48:23 -0800317 'TopoOverlayService', 'TopoDialogService',
Bri Prebilic Cole4db8dce2015-03-18 13:57:24 -0700318
Simon Hunta211f7f2015-11-09 12:48:23 -0800319 function (_$log_, _fs_, _tbs_, _ps_, _tov_, _tds_) {
Bri Prebilic Cole4db8dce2015-03-18 13:57:24 -0700320 $log = _$log_;
Bri Prebilic Coled8745462015-06-01 16:08:57 -0700321 fs = _fs_;
Bri Prebilic Cole4db8dce2015-03-18 13:57:24 -0700322 tbs = _tbs_;
Simon Huntc7ae7952015-04-08 18:59:27 -0700323 ps = _ps_;
Simon Hunt72e44bf2015-07-21 21:34:20 -0700324 tov = _tov_;
Simon Hunta211f7f2015-11-09 12:48:23 -0800325 tds = _tds_;
Bri Prebilic Cole4db8dce2015-03-18 13:57:24 -0700326
327 return {
328 init: init,
Simon Hunt09060142015-03-18 20:23:32 -0700329 createToolbar: createToolbar,
Bri Prebilic Coled6219052015-03-19 14:34:02 -0700330 destroyToolbar: destroyToolbar,
Simon Hunt90dcc3e2015-03-25 15:01:27 -0700331 keyListener: keyListener,
Simon Hunta5b53af2015-10-12 15:56:40 -0700332 toggleToolbar: toggleToolbar,
Simon Huntfc5c5842017-02-01 23:32:18 -0800333 selectOverlay: selectOverlay,
Thomas Vachuska0af26912016-03-21 21:37:30 -0700334 defaultPrefs: defaultPrefsState,
Steven Burrows1c2a9682017-07-14 16:52:46 +0100335 fnkey: fnkey,
Bri Prebilic Cole4db8dce2015-03-18 13:57:24 -0700336 };
337 }]);
Steven Burrows1c2a9682017-07-14 16:52:46 +0100338}());