GUI -- Modified Toolbar service to have multiple rows of buttons. Added more buttons in topoToolbar - WIP.

Change-Id: Ibc749b4ecdcb07ecf63d50817f8af3d455b4cde0
diff --git a/web/gui/src/main/webapp/app/fw/svg/glyph.js b/web/gui/src/main/webapp/app/fw/svg/glyph.js
index e707808..8e82fa6 100644
--- a/web/gui/src/main/webapp/app/fw/svg/glyph.js
+++ b/web/gui/src/main/webapp/app/fw/svg/glyph.js
@@ -171,7 +171,31 @@
             "-3.5,3.9-7.4,8.9-11.7,15.1c0,0-3.1,3.4-5.2,0.9C52.9,51.5,61," +
             "39.3,61,39.3s2.2-3.1,5.6-7c-2.9-3-5.9-6.3-6.6-7.3c0,0-3.7-5-1.3" +
             "-6.6c3.2-2.1,6.3,0.8,6.3,0.8s3.1,3.3,7,7.2c4.7-4.7,10.1-9.2," +
-            "14.7-10c0,0,3.3-1,5.2,1.7C92.5,18.8,92.4,19.6,91.9,20.4z"
+            "14.7-10c0,0,3.3-1,5.2,1.7C92.5,18.8,92.4,19.6,91.9,20.4z",
+
+            resetZoom: "M86.4,81.6L60.3,54.2c1.9-3.1,3-6.8,3.1-10.7c0.3-12" +
+            "-9.2-22.1-21.2-22.4c-12-0.3-22.1,9.2-22.4,21.2c-0.3,12,9.2," +
+            "22.1,21.2,22.4c4.3,0.1,9.6-0.9,12.8-3.9l25.5,26.8c1.6,1.7,4.3," +
+            "2.4,5.7,1.1l1.8-1.7C88.2,85.8,88,83.3,86.4,81.6z M27.8," +
+            "42.5C28,34.8,34.4,28.8,42,29c7.7,0.2,13.7,6.6,13.5,14.2c" +
+            "-0.2,7.7-6.6,13.7-14.2,13.5C33.6,56.5,27.6,50.2,27.8,42.5z " +
+            "M10.4,27.2c-1.7,0-3-1.3-3-3V7.1h16.2c1.7,0,3,1.3,3,3s-1.3,3-3," +
+            "3H13.4v11.2C13.4,25.9,12.1,27.2,10.4,27.2z M23.7,102.3H7.5" +
+            "V85.2c0-1.7,1.3-3,3-3s3,1.3,3,3v11.2h10.2c1.7,0,3,1.3,3,3S25.3," +
+            "102.3,23.7,102.3z M102.6,103.4H86.4c-1.7,0-3-1.3-3-3c0-1.7,1.3" +
+            "-3,3-3h10.2V86.2c0-1.7,1.3-3,3-3c1.7,0,3,1.3,3,3V103.4z M99.6," +
+            "27.2c-1.7,0-3-1.3-3-3V13.1H86.4c-1.7,0-3-1.3-3-3s1.3-3,3" +
+            "-3h16.2v17.2C102.6,25.9,101.3,27.2,99.6,27.2z",
+
+            nextIntent: "M88.1,55.7L34.6,13.1c0,0-1.6-0.5-2.1-0.2c-1.9,1.2" +
+            "-6.5,13.8-3.1,17.2c7,6.9,30.6,24.5,32.4,25.9c-1.8,1.4-25.4,19" +
+            "-32.4,25.9c-3.4,3.4,1.2,16,3.1,17.2c0.6,0.4,2.1-0.2,2.1-0.2" +
+            "s53.1-42.4,53.5-42.7C88.5,56,88.1,55.7,88.1,55.7z",
+
+            prevIntent: "M22.5,55.6L76,12.9c0,0,1.6-0.5,2.2-0.2c1.9,1.2," +
+            "6.5,13.8,3.1,17.2c-7,6.9-30.6,24.5-32.4,25.9c1.8,1.4,25.4,19," +
+            "32.4,25.9c3.4,3.4-1.2,16-3.1,17.2c-0.6,0.4-2.2-0.2-2.2-0.2" +
+            "S22.9,56.3,22.5,56C22.2,55.8,22.5,55.6,22.5,55.6z"
         },
 
         badgeViewBox = '0 0 10 10',
diff --git a/web/gui/src/main/webapp/app/fw/widget/toolbar.css b/web/gui/src/main/webapp/app/fw/widget/toolbar.css
index da6165b..2862965 100644
--- a/web/gui/src/main/webapp/app/fw/widget/toolbar.css
+++ b/web/gui/src/main/webapp/app/fw/widget/toolbar.css
@@ -37,6 +37,15 @@
 }
 
 
+.toolbar {
+    line-height: 125%;
+}
+.tbar-row {
+    display: inline-block;
+}
+
+
+
 .separator {
     border: 1px solid;
     margin: 0 4px 0 4px;
diff --git a/web/gui/src/main/webapp/app/fw/widget/toolbar.js b/web/gui/src/main/webapp/app/fw/widget/toolbar.js
index 14a469c..f74e8cb 100644
--- a/web/gui/src/main/webapp/app/fw/widget/toolbar.js
+++ b/web/gui/src/main/webapp/app/fw/widget/toolbar.js
@@ -75,6 +75,10 @@
         return null;
     }
 
+    function noPxWidth(elem) {
+        return Number(elem.style('width').replace(/px$/, ''));
+    }
+
 
     // ==================================
 
@@ -87,8 +91,9 @@
             tbid = 'toolbar-' + id,
             panel = ps.createPanel(tbid, settings),
             arrowDiv = createArrow(panel),
-            tbWidth = arrowSize + 2;    // empty toolbar width
-
+            currentRow = panel.append('div').classed('tbar-row', true),
+            tbWidth = arrowSize + 2,    // empty toolbar width
+            maxWidth = panel.width();
 
         arrowDiv.on('click', toggle);
 
@@ -103,6 +108,7 @@
         panel.classed('toolbar', true)
             .style('top', settings.top);
 
+        // Helper functions
 
         function dupId(id, caller) {
             if (items[id]) {
@@ -112,17 +118,25 @@
             return false;
         }
 
+        function adjustWidth(btnWidth) {
+            if (noPxWidth(currentRow) >= 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(panel, bid, gid, cb, tooltip);
+                btn = bns.button(currentRow, bid, gid, cb, tooltip);
 
             items[id] = btn;
-            tbWidth += btn.width();
-            panel.width(tbWidth);
+            $log.debug('adding button');
+            adjustWidth(btn.width());
             return btn;
         }
 
@@ -130,11 +144,10 @@
             if (dupId(id, 'addToggle')) return null;
 
             var tid = tbid + '-' + id,
-                tog = bns.toggle(panel, tid, gid, initState, cb, tooltip);
+                tog = bns.toggle(currentRow, tid, gid, initState, cb, tooltip);
 
             items[id] = tog;
-            tbWidth += tog.width();
-            panel.width(tbWidth);
+            adjustWidth(tog.width());
             return tog;
         }
 
@@ -142,23 +155,33 @@
             if (dupId(id, 'addRadioSet')) return null;
 
             var rid = tbid + '-' + id,
-                rad = bns.radioSet(panel, rid, rset);
+                rad = bns.radioSet(currentRow, rid, rset);
 
             items[id] = rad;
-            tbWidth += rad.width();
-            panel.width(tbWidth);
+            adjustWidth(rad.width());
             return rad;
         }
 
         function addSeparator() {
-            panel.append('div')
+            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);
+            }
+        }
+
         function show(cb) {
             rotateArrowLeft(arrowDiv);
             panel.show(cb);
+            $log.debug('tbar width', tbWidth);
+            $log.debug('maxwidth', maxWidth);
+            $log.debug('panel width', panel.width());
         }
 
         function hide(cb) {
@@ -179,6 +202,7 @@
             addToggle: addToggle,
             addRadioSet: addRadioSet,
             addSeparator: addSeparator,
+            addRow: addRow,
 
             show: show,
             hide: hide,
diff --git a/web/gui/src/main/webapp/app/view/topo/topoToolbar.js b/web/gui/src/main/webapp/app/view/topo/topoToolbar.js
index 06ddc0c..c86857e 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoToolbar.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoToolbar.js
@@ -40,7 +40,21 @@
         H: { id: 'hosts-tog', gid: 'endstation', isel: false },
         M: { id: 'offline-tog', gid: 'switch', isel: true },
         P: { id: 'ports-tog', gid: 'ports', isel: true },
-        B: { id: 'bkgrnd-tog', gid: 'map', isel: true }
+        B: { id: 'bkgrnd-tog', gid: 'map', isel: true },
+
+        //X: { id: 'nodelock-tog', gid: 'lock', isel: false },
+        Z: { id: 'oblique-tog', gid: 'oblique', isel: false },
+        L: { id: 'cycleLabels-btn', gid: 'cycleLabels' },
+        R: { id: 'resetZoom-btn', gid: 'resetZoom' },
+
+        V: { id: 'allIntents-btn', gid: 'allIntents' },
+        leftArrow: { id: 'prevIntent-btn', gid: 'prevIntent' },
+        rightArrow: { id: 'nextIntent-btn', gid: 'nextIntent' },
+        W: { id: 'intentTraffic-btn', gid: 'intentTraffic' },
+        A: { id: 'allTraffic-btn', gid: 'allTraffic' },
+        F: { id: 'flows-btn', gid: 'flows' },
+
+        E: { id: 'eqMaster-btn', gid: 'eqMaster' }
     };
 
     function init(_api_) {
@@ -56,6 +70,10 @@
         });
     }
 
+    function addButton(key) {
+        var v = keyData.get(key);
+        v.btn = toolbar.addButton(v.id, v.gid, v.cb, v.tt);
+    }
     function addToggle(key) {
         var v = keyData.get(key);
         v.tog = toolbar.addToggle(v.id, v.gid, v.isel, v.cb, v.tt);
@@ -72,11 +90,30 @@
         addToggle('P');
         addToggle('B');
     }
+    function addSecondRow() {
+        addToggle('Z');
+        addButton('L');
+        addButton('R');
+    }
+    function addThirdRow() {
+        addButton('V');
+        addButton('leftArrow');
+        addButton('rightArrow');
+        addButton('W');
+        addButton('A');
+        addButton('F');
+        toolbar.addSeparator();
+        addButton('E');
+    }
 
     function createToolbar() {
         initKeyData();
         toolbar = tbs.createToolbar(name);
         addFirstRow();
+        toolbar.addRow();
+        addSecondRow();
+        toolbar.addRow();
+        addThirdRow();
         toolbar.show();
     }
 
diff --git a/web/gui/src/main/webapp/tests/app/fw/widget/toolbar-spec.js b/web/gui/src/main/webapp/tests/app/fw/widget/toolbar-spec.js
index 63d77b5..10a22b4 100644
--- a/web/gui/src/main/webapp/tests/app/fw/widget/toolbar-spec.js
+++ b/web/gui/src/main/webapp/tests/app/fw/widget/toolbar-spec.js
@@ -141,8 +141,8 @@
 
     it('should create a separator div', function () {
         spyOn($log, 'warn');
-        var toolbar = tbs.createToolbar('foo');
-        var tbar = d3.select('#toolbar-foo');
+        var toolbar = tbs.createToolbar('foo'),
+            tbar = d3.select('#toolbar-foo');
 
         toolbar.addSeparator();
         expect($log.warn).not.toHaveBeenCalled();
@@ -150,4 +150,31 @@
         expect(tbar.select('.separator').size()).toBe(1);
     });
 
+    it('should add another row of buttons', function () {
+        var toolbar = tbs.createToolbar('foo'),
+            tbar = d3.select('#toolbar-foo'),
+            rows;
+        toolbar.addButton('btn0', 'gid');
+        toolbar.addRow();
+        toolbar.addButton('btn1', 'gid');
+
+        rows = tbar.selectAll('.tbar-row');
+        expect(rows.size()).toBe(2);
+        rows.each(function (d, i) {
+            expect(d3.select(this)
+                .select('div')
+                .attr('id','toolbar-foo-btn' + i)
+                .empty())
+                .toBe(false);
+        });
+    });
+
+    it('should not add a row if current row is empty', function () {
+        var toolbar = tbs.createToolbar('foo');
+        expect(toolbar.addRow()).toBeNull();
+        toolbar.addButton('btn0', 'gid');
+        expect(toolbar.addRow()).not.toBeNull();
+        expect(toolbar.addRow()).toBeNull();
+    });
+
 });