blob: b765208cbf9c8ed298efc067e392c442f45edcd1 [file] [log] [blame]
/*
* Copyright 2015-present Open Networking Laboratory
*
* 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 -- Widget -- Toolbar Service
*/
// TODO: Augment service to allow toolbars to exist on right edge of screen
// TODO: also - make toolbar more object aware (rows etc.)
(function () {
'use strict';
// injected refs
var $log, fs, ps, bns, is;
// configuration
var arrowSize = 10,
sepWidth = 6,
defaultSettings = {
edge: 'left',
width: 20,
margin: 0,
hideMargin: -20,
top: 'auto',
bottom: '10px',
fade: false,
shown: false
};
// internal state
var tbars = {};
// === Helper functions --------------------------------------
// translate uses 50 because the svg viewbox is 50
function rotateArrowLeft(adiv) {
adiv.select('g')
.attr('transform', 'translate(0 50) rotate(-90)');
}
function rotateArrowRight(adiv) {
adiv.select('g')
.attr('transform', 'translate(50 0) rotate(90)');
}
function createArrow(panel) {
var arrowDiv = panel.append('div')
.classed('tbar-arrow', true);
is.loadIcon(arrowDiv, 'triangleUp', arrowSize, true);
return arrowDiv;
}
function warn(msg, id) {
$log.warn('createToolbar: ' + msg + ': [' + id + ']');
return null;
}
// ==================================
function createToolbar(id, opts) {
if (!id) return warn('no ID given');
if (tbars[id]) return warn('duplicate ID given', id);
var settings = angular.extend({}, defaultSettings, fs.isO(opts)),
items = {},
tbid = 'toolbar-' + id,
panel = ps.createPanel(tbid, settings),
arrowDiv = createArrow(panel),
currentRow = panel.append('div').classed('tbar-row', true),
rowButtonIds = [], // for removable buttons
tbWidth = arrowSize + 2, // empty toolbar width
maxWidth = panel.width();
arrowDiv.on('click', toggle);
// add a descriptor for this toolbar
tbars[id] = {
settings: settings,
items: items,
panel: panel,
panelId: tbid
};
panel.classed('toolbar', true)
.style('top', settings.top)
.style('bottom', settings.bottom);
// Helper functions
function dupId(id, caller) {
if (items[id]) {
$log.warn(caller + ': duplicate ID:', id);
return true;
}
return false;
}
function adjustWidth(btnWidth) {
// 0.1 fudge for rounding error
if (fs.noPxStyle(currentRow, 'width') + 0.1 >= maxWidth) {
tbWidth += btnWidth;
maxWidth = tbWidth;
}
panel.width(tbWidth);
}
// API functions
function addButton(id, gid, cb, tooltip) {
if (dupId(id, 'addButton')) return null;
var bid = tbid + '-' + id,
btn = bns.button(currentRow, bid, gid, cb, tooltip);
items[id] = btn;
adjustWidth(btn.width());
return btn;
}
function addToggle(id, gid, initState, cb, tooltip) {
if (dupId(id, 'addToggle')) return null;
var tid = tbid + '-' + id,
tog = bns.toggle(currentRow, tid, gid, initState, cb, tooltip);
items[id] = tog;
adjustWidth(tog.width());
return tog;
}
function addRadioSet(id, rset) {
if (dupId(id, 'addRadioSet')) return null;
var rid = tbid + '-' + id,
rad = bns.radioSet(currentRow, rid, rset);
items[id] = rad;
adjustWidth(rad.width());
return rad;
}
function addSeparator() {
currentRow.append('div')
.classed('separator', true);
tbWidth += sepWidth;
}
function addRow() {
if (currentRow.select('div').empty()) {
return null;
} else {
panel.append('br');
currentRow = panel.append('div').classed('tbar-row', true);
// return API to allow caller more access to the row
return {
clear: rowClear,
setText: rowSetText,
addButton: rowAddButton,
classed: rowClassed
};
}
}
function rowClear() {
currentRow.selectAll('*').remove();
rowButtonIds.forEach(function (bid) {
delete items[bid];
});
rowButtonIds = [];
}
// installs a div with text into the button row
function rowSetText(text) {
rowClear();
currentRow.append('div').classed('tbar-row-text', true)
.text(text);
}
function rowAddButton(id, gid, cb, tooltip) {
var b = addButton(id, gid, cb, tooltip);
if (b) {
rowButtonIds.push(id);
}
}
function rowClassed(classes, bool) {
currentRow.classed(classes, bool);
}
function show(cb) {
rotateArrowLeft(arrowDiv);
panel.show(cb);
}
function hide(cb) {
rotateArrowRight(arrowDiv);
panel.hide(cb);
}
function toggle(cb) {
if (panel.isVisible()) {
hide(cb);
} else {
show(cb);
}
}
function isVisible() {
return panel.isVisible();
}
return {
addButton: addButton,
addToggle: addToggle,
addRadioSet: addRadioSet,
addSeparator: addSeparator,
addRow: addRow,
show: show,
hide: hide,
toggle: toggle,
isVisible: isVisible
};
}
function destroyToolbar(id) {
var tb = tbars[id];
delete tbars[id];
if (tb) {
ps.destroyPanel(tb.panelId);
}
}
// === Module Definition ===
angular.module('onosWidget')
.factory('ToolbarService',
['$log', 'FnService', 'PanelService', 'ButtonService', 'IconService',
function (_$log_, _fs_, _ps_, _bns_, _is_) {
$log = _$log_;
fs = _fs_;
ps = _ps_;
bns = _bns_;
is = _is_;
// this function is only used in testing
function init() {
tbars = {};
}
return {
init: init,
createToolbar: createToolbar,
destroyToolbar: destroyToolbar
};
}]);
}());