| /* |
| * Copyright 2015-present Open Networking Foundation |
| * |
| * 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. |
| */ |
| |
| /* |
| ONOS GUI -- Topology Toolbar Module. |
| Functions for creating and interacting with the toolbar. |
| */ |
| |
| (function () { |
| 'use strict'; |
| |
| // injected references |
| var $log, fs, tbs, ps, tov, tds, api; |
| |
| // API: |
| // getActionEntry |
| // setUpKeys |
| |
| // function to be replaced by the localization bundle function |
| var topoLion = function (x) { |
| return '#ttbar#' + x + '#'; |
| }; |
| |
| // internal state |
| var toolbar, keyData, cachedState, thirdRow, ovRset, ovIndex; |
| |
| // constants |
| var name = 'topo-tbar', |
| cooktag = 'topo_prefs', |
| soa = 'switchOverlayActions: ', |
| selOver = '************', |
| defaultOverlay = 'traffic'; |
| |
| |
| // key to button mapping data |
| var k2b = { |
| O: { id: 'summary-tog', gid: 'm_summary', isel: true }, |
| I: { id: 'instance-tog', gid: 'm_uiAttached', isel: true }, |
| D: { id: 'details-tog', gid: 'm_details', isel: true }, |
| H: { id: 'hosts-tog', gid: 'm_endstation', isel: false }, |
| M: { id: 'offline-tog', gid: 'm_switch', isel: true }, |
| P: { id: 'ports-tog', gid: 'm_ports', isel: true }, |
| B: { id: 'bkgrnd-tog', gid: 'm_map', isel: false }, |
| G: { id: 'bkgrnd-sel', gid: 'm_selectMap' }, |
| S: { id: 'sprite-tog', gid: 'm_cloud', isel: false }, |
| |
| Z: { id: 'oblique-tog', gid: 'm_oblique', isel: false }, |
| N: { id: 'filters-btn', gid: 'm_filters' }, |
| L: { id: 'cycleLabels-btn', gid: 'm_cycleLabels' }, |
| R: { id: 'resetZoom-btn', gid: 'm_resetZoom' }, |
| |
| E: { id: 'eqMaster-btn', gid: 'm_eqMaster' }, |
| }; |
| |
| var prohibited = [ |
| 'T', 'backSlash', 'slash', |
| 'X', // needed until we re-instate X above. |
| ]; |
| prohibited = prohibited.concat(d3.map(k2b).keys()); |
| |
| |
| // initial toggle state: default settings and tag to key mapping |
| var defaultPrefsState = { |
| insts: 1, |
| summary: 1, |
| detail: 1, |
| hosts: 0, |
| offdev: 1, |
| dlbls: 0, |
| hlbls: 0, |
| porthl: 1, |
| bg: 0, |
| spr: 0, |
| ovid: 'traffic', // default to traffic overlay |
| toolbar: 0, |
| }, |
| prefsMap = { |
| summary: 'O', |
| insts: 'I', |
| detail: 'D', |
| hosts: 'H', |
| offdev: 'M', |
| porthl: 'P', |
| bg: 'B', |
| spr: 'S', |
| // NOTE: toolbar state is handled separately |
| }; |
| |
| function init(_api_) { |
| api = _api_; |
| // retrieve initial toggle button settings from user prefs |
| setInitToggleState(); |
| } |
| |
| function topoDefPrefs() { |
| return angular.extend({}, defaultPrefsState); |
| } |
| |
| function setInitToggleState() { |
| cachedState = ps.asNumbers( |
| ps.getPrefs(cooktag, defaultPrefsState), ['ovid'], true |
| ); |
| $log.debug('TOOLBAR---- read prefs state:', cachedState); |
| |
| if (!cachedState) { |
| cachedState = topoDefPrefs(); |
| ps.setPrefs(cooktag, cachedState); |
| $log.debug('TOOLBAR---- Set default prefs state:', cachedState); |
| } |
| |
| angular.forEach(prefsMap, function (v, k) { |
| var cfg = k2b[v]; |
| cfg && (cfg.isel = !!cachedState[k]); |
| }); |
| } |
| |
| function initKeyData() { |
| // TODO: use angular forEach instead of d3.map |
| keyData = d3.map(k2b); |
| keyData.forEach(function (key, value) { |
| var data = api.getActionEntry(key), |
| ttfn = data[1]; // tooltip-possibly-a-function |
| |
| value.key = key; |
| value.cb = data[0]; // on-click callback |
| |
| // tooltip function invoked at the time the tooltip is displayed |
| value.tt = function () { |
| return fs.isF(ttfn) ? ttfn() : '' + ttfn; |
| }; |
| }); |
| } |
| |
| // returns a no-args function that returns the tooltip text |
| function deferredText(v) { |
| // this function will get invoked at the time the tooltip is displayed: |
| return function () { |
| return (fs.isF(v.tt) ? v.tt() : v.tt) + ' (' + v.key + ')'; |
| }; |
| } |
| |
| function addButton(key) { |
| var v = keyData.get(key); |
| v.btn = toolbar.addButton(v.id, v.gid, v.cb, deferredText(v)); |
| } |
| |
| function addToggle(key, suppressIfMobile) { |
| var v = keyData.get(key); |
| if (suppressIfMobile && fs.isMobile()) { return; } |
| v.tog = toolbar.addToggle(v.id, v.gid, v.isel, v.cb, deferredText(v)); |
| } |
| |
| function addFirstRow() { |
| addToggle('I'); |
| addToggle('O'); |
| addToggle('D'); |
| toolbar.addSeparator(); |
| |
| addToggle('H'); |
| addToggle('M'); |
| addToggle('P', true); |
| addToggle('B'); |
| addButton('G'); |
| addToggle('S', true); |
| } |
| |
| function addSecondRow() { |
| // addToggle('X'); |
| addToggle('Z'); |
| addButton('N'); |
| addButton('L'); |
| addButton('R'); |
| toolbar.addSeparator(); |
| addButton('E'); |
| } |
| |
| function addOverlays() { |
| toolbar.addSeparator(); |
| |
| // generate radio button set for overlays; start with 'none' |
| var rset = [{ |
| gid: 'm_unknown', |
| tooltip: topoLion('ov_tt_none'), |
| cb: function () { |
| tov.tbSelection(null, switchOverlayActions); |
| }, |
| }]; |
| ovIndex = tov.augmentRbset(rset, switchOverlayActions); |
| ovRset = toolbar.addRadioSet('topo-overlays', rset); |
| } |
| |
| // invoked by overlay service to switch out old buttons and switch in new |
| function switchOverlayActions(oid, keyBindings) { |
| var prohibits = [], |
| kb = fs.isO(keyBindings) || {}, |
| order = fs.isA(kb._keyOrder) || []; |
| |
| if (keyBindings && !keyBindings._keyOrder) { |
| $log.warn(soa + 'no _keyOrder property defined'); |
| } else { |
| // sanity removal of reserved property names |
| ['esc', '_keyListener', '_helpFormat'].forEach(function (k) { |
| fs.removeFromArray(k, order); |
| }); |
| } |
| |
| // ensure dialog has closed (if opened by outgoing overlay) |
| tds.closeDialog(); |
| thirdRow.clear(); |
| |
| // persist our choice of overlay... |
| persistTopoPrefs('ovid', oid); |
| |
| if (!order.length) { |
| thirdRow.setText(selOver); |
| thirdRow.classed('right', true); |
| api.setUpKeys(); // clear previous overlay key bindings |
| |
| } else { |
| thirdRow.classed('right', false); |
| angular.forEach(order, function (key) { |
| var value, bid, gid, tt; |
| |
| if (prohibited.indexOf(key) > -1) { |
| prohibits.push(key); |
| |
| } else { |
| value = keyBindings[key]; |
| bid = oid + '-' + key; |
| gid = tov.mkGlyphId(oid, value.gid); |
| tt = function () { |
| var ttfn = value.tt, |
| txt = fs.isF(ttfn) ? ttfn() : ttfn; |
| return txt + ' (' + key + ')'; |
| }; |
| thirdRow.addButton(bid, gid, value.cb, tt); |
| } |
| }); |
| api.setUpKeys(keyBindings); // add overlay key bindings |
| } |
| |
| if (prohibits.length) { |
| $log.warn(soa + 'Prohibited key bindings ignored:', prohibits); |
| } |
| } |
| |
| function createToolbar() { |
| initKeyData(); |
| toolbar = tbs.createToolbar(name); |
| addFirstRow(); |
| toolbar.addRow(); |
| addSecondRow(); |
| addOverlays(); |
| thirdRow = toolbar.addRow(); |
| thirdRow.setText(selOver); |
| thirdRow.classed('right', true); |
| |
| if (cachedState.toolbar) { |
| toolbar.show(); |
| } else { |
| toolbar.hide(); |
| } |
| } |
| |
| function destroyToolbar() { |
| tbs.destroyToolbar(name); |
| tov.resetOnToolbarDestroy(); |
| } |
| |
| // allows us to ensure the button states track key strokes |
| function keyListener(key) { |
| var v = keyData.get(key); |
| |
| if (v) { |
| // we have a valid button mapping |
| if (v.tog) { |
| // it's a toggle button |
| v.tog.toggleNoCb(); |
| } |
| } |
| } |
| |
| function persistTopoPrefs(key, val) { |
| var prefs = ps.getPrefs(cooktag, defaultPrefsState); |
| prefs[key] = val === undefined ? !prefs[key] : val; |
| ps.setPrefs('topo_prefs', prefs); |
| } |
| |
| function toggleToolbar() { |
| toolbar.toggle(); |
| persistTopoPrefs('toolbar'); |
| } |
| |
| function setToolbar(state) { |
| if (state) { |
| toolbar.show(); |
| } else { |
| toolbar.hide(); |
| } |
| } |
| |
| function selectOverlay(ovid) { |
| var idx = ovIndex[defaultOverlay] || 0, |
| pidx = (ovid === null) ? 0 : ovIndex[ovid] || -1; |
| if (pidx >= 0 && pidx < ovRset.size()) { |
| idx = pidx; |
| } |
| ovRset.selectedIndex(idx); |
| } |
| |
| // an overlay was selected via Function-Key press |
| function fnkey(idx) { |
| if (idx < ovRset.size() && idx !== ovRset.selectedIndex()) { |
| ovRset.selectedIndex(idx); |
| } |
| } |
| |
| angular.module('ovTopo') |
| .factory('TopoToolbarService', |
| ['$log', 'FnService', 'ToolbarService', 'PrefsService', |
| 'TopoOverlayService', 'TopoDialogService', |
| |
| function (_$log_, _fs_, _tbs_, _ps_, _tov_, _tds_) { |
| $log = _$log_; |
| fs = _fs_; |
| tbs = _tbs_; |
| ps = _ps_; |
| tov = _tov_; |
| tds = _tds_; |
| |
| return { |
| init: init, |
| createToolbar: createToolbar, |
| destroyToolbar: destroyToolbar, |
| keyListener: keyListener, |
| toggleToolbar: toggleToolbar, |
| setToolbar: setToolbar, |
| selectOverlay: selectOverlay, |
| defaultPrefs: defaultPrefsState, |
| fnkey: fnkey, |
| setLionBundle: function (bundle) { topoLion = bundle; }, |
| }; |
| }]); |
| }()); |