toolbar.js 7.29 KB
/*
 * 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) {
            if (fs.noPxStyle(currentRow, 'width') >= 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)
                .html(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
            };
        }]);
}());