ONOS-1479 - GUI Topology Overlay Work - (WIP)
- created TopoOverlayService to allow registration of topology overlays
- modified topoToolbar to include a radio button set for each registered overlay
- created seed traffic overlay

Change-Id: I70770cb1c691730914c81e497823ea08703587f1
diff --git a/web/gui/src/main/webapp/_sdh/overlaywork/topov.js b/web/gui/src/main/webapp/_sdh/overlaywork/topov.js
new file mode 100644
index 0000000..b845d54
--- /dev/null
+++ b/web/gui/src/main/webapp/_sdh/overlaywork/topov.js
@@ -0,0 +1,44 @@
+// sample topology overlay - client side
+(function () {
+    'use strict';
+
+    // injected refs
+    var $log;
+
+    // our overlay definition
+    var overlay = {
+        overlayId: 'sampleTopoOver',
+
+        // NOTE: for the glyph, could alternately use id: <existingGlyphId>
+        //       instead of defining viewbox and data (vb, d)
+        //       glyph: { id: 'crown' }
+        glyph: {
+            vb: '0 0 8 8',
+            d: 'M1,4l2,-1l1,-2l1,2l2,1l-2,1l-1,2l-1,-2z'
+        },
+        tooltip: 'Sample Topology Overlay',
+
+        activate: activateOverlay,
+        deactivate: deactivateOverlay
+    };
+
+    // === implementation of overlay API (essentially callbacks)
+    function activateOverlay() {
+        $log.debug("sample topology overlay ACTIVATED");
+    }
+
+    function deactivateOverlay() {
+        $log.debug("sample topology overlay DEACTIVATED");
+    }
+
+
+    // invoke code to register with the overlay service
+    angular.module('ovSample')
+        .run(['$log', 'TopoOverlayService',
+
+            function (_$log_, tov) {
+                $log = _$log_;
+                tov.register(overlay);
+            }]);
+
+}());
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 c28edb0..726e808 100644
--- a/web/gui/src/main/webapp/app/fw/svg/glyph.js
+++ b/web/gui/src/main/webapp/app/fw/svg/glyph.js
@@ -477,7 +477,6 @@
     }
 
     function init() {
-        clear();
         registerGlyphs(birdData);
         registerGlyphSet(glyphDataSet);
         registerGlyphSet(badgeDataSet);
@@ -595,6 +594,10 @@
                 addGlyph: addGlyph
             };
         }]
-    );
+    )
+    .run(['$log', function ($log) {
+        $log.debug('Clearing glyph cache');
+        clear();
+    }]);
 
 }());
diff --git a/web/gui/src/main/webapp/app/view/topo/topo.js b/web/gui/src/main/webapp/app/view/topo/topo.js
index 5727a78..cac8f4c 100644
--- a/web/gui/src/main/webapp/app/view/topo/topo.js
+++ b/web/gui/src/main/webapp/app/view/topo/topo.js
@@ -30,7 +30,7 @@
 
     // references to injected services etc.
     var $scope, $log, $cookies, fs, ks, zs, gs, ms, sus, flash, wss, ps,
-        tes, tfs, tps, tis, tss, tls, tts, tos, fltr, ttbs, ttip;
+        tes, tfs, tps, tis, tss, tls, tts, tos, fltr, ttbs, ttip, tov;
 
     // DOM elements
     var ovtopo, svg, defs, zoomLayer, mapG, spriteG, forceG, noDevsLayer;
@@ -396,11 +396,12 @@
             'TopoInstService', 'TopoSelectService', 'TopoLinkService',
             'TopoTrafficService', 'TopoObliqueService', 'TopoFilterService',
             'TopoToolbarService', 'TopoSpriteService', 'TooltipService',
+            'TopoOverlayService',
 
         function (_$scope_, _$log_, $loc, $timeout, _$cookies_, _fs_, mast, _ks_,
                   _zs_, _gs_, _ms_, _sus_, _flash_, _wss_, _ps_, _tes_, _tfs_,
                   _tps_, _tis_, _tss_, _tls_, _tts_, _tos_, _fltr_, _ttbs_, tspr,
-                  _ttip_) {
+                  _ttip_, _tov_) {
             var projection,
                 dim,
                 uplink = {
@@ -438,6 +439,7 @@
             fltr = _fltr_;
             ttbs = _ttbs_;
             ttip = _ttip_;
+            tov = _tov_;
 
             $scope.notifyResize = function () {
                 svgResized(fs.windowSize(mast.mastHeight()));
@@ -496,6 +498,8 @@
             // temporary solution for persisting user settings
             restoreConfigFromPrefs();
 
+            $log.debug('registered overlays...', tov.list());
+
             $log.log('OvTopoCtrl has been created');
         }]);
 }());
diff --git a/web/gui/src/main/webapp/app/view/topo/topoOverlay.js b/web/gui/src/main/webapp/app/view/topo/topoOverlay.js
new file mode 100644
index 0000000..e1efe47
--- /dev/null
+++ b/web/gui/src/main/webapp/app/view/topo/topoOverlay.js
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2015 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 -- Topology Overlay Module.
+
+ Provides overlay capabilities, allowing ONOS apps to provide additional
+ custom data/behavior for the topology view.
+
+ */
+
+(function () {
+    'use strict';
+
+    // constants
+    var tos = 'TopoOverlayService: ';
+
+    // injected refs
+    var $log, fs, gs;
+
+    // internal state
+    var overlays = {};
+
+    function error(fn, msg) {
+        $log.error(tos + fn + '(): ' + msg);
+    }
+
+    function warn(fn, msg) {
+        $log.warn(tos + fn + '(): ' + msg);
+    }
+
+    function handleGlyph(o) {
+        var gdata = fs.isO(o.glyph),
+            oid,
+            data = {};
+
+        if (!gdata) {
+            o._glyphId = 'unknown';
+        } else {
+            if (gdata.id) {
+                o._glyphId = gdata.id;
+            } else if (gdata.vb && gdata.d) {
+                oid = o.overlayId;
+                data['_' + oid] = gdata.vb;
+                data[oid] = gdata.d;
+                gs.registerGlyphs(data);
+                o._glyphId = oid;
+                $log.debug('registered overlay glyph:', oid);
+            } else {
+                warn('registerGlyph', 'problem with glyph data');
+            }
+        }
+    }
+
+    function register(overlay) {
+        var r = 'register',
+            over = fs.isO(overlay),
+            id = over ? over.overlayId : '';
+
+        if (!id) {
+            return error(r, 'not a recognized overlay');
+        }
+        if (overlays[id]) {
+            return warn(r, 'already registered: "' + id + '"');
+        }
+        overlays[id] = overlay;
+        handleGlyph(overlay);
+        $log.debug(tos + 'registered overlay: ' + id, overlay);
+    }
+
+    // NOTE: unregister needs to be called if an app is ever
+    //       deactivated/uninstalled via the applications view
+    function unregister(overlay) {
+        var u = 'unregister',
+            over = fs.isO(overlay),
+            id = over ? over.overlayId : '';
+
+        if (!id) {
+            return error(u, 'not a recognized overlay');
+        }
+        if (!overlays[id]) {
+            return warn(u, 'not registered: "' + id + "'")
+        }
+        delete overlays[id];
+        $log.debug(tos + 'unregistered overlay: ' + id);
+        // TODO: rebuild the toolbar overlay radio button set
+    }
+
+    function list() {
+        return d3.map(overlays).keys();
+    }
+
+    function overlay(id) {
+        return overlays[id];
+    }
+
+    angular.module('ovTopo')
+    .factory('TopoOverlayService',
+        ['$log', 'FnService', 'GlyphService',
+
+        function (_$log_, _fs_, _gs_) {
+            $log = _$log_;
+            fs = _fs_;
+            gs = _gs_;
+
+            return {
+                register: register,
+                unregister: unregister,
+                list: list,
+                overlay: overlay
+            }
+        }]);
+
+}());
\ No newline at end of file
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 8fec8cb..342e108 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoToolbar.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoToolbar.js
@@ -23,7 +23,7 @@
     'use strict';
 
     // injected references
-    var $log, fs, tbs, ps, api;
+    var $log, fs, tbs, ps, tov, api;
 
     // internal state
     var toolbar, keyData, cachedState;
@@ -142,13 +142,50 @@
         addToggle('B');
         addToggle('S', true);
     }
+
     function addSecondRow() {
         //addToggle('X');
         addToggle('Z');
         addButton('N');
         addButton('L');
         addButton('R');
+        toolbar.addSeparator();
+        addButton('E');
     }
+
+    function setOverlay(overlayId) {
+        if (!overlayId) {
+            $log.debug('CLEAR overlay');
+        } else {
+            $log.debug('SET overlay', overlayId);
+        }
+    }
+
+    function addOverlays() {
+        toolbar.addSeparator();
+
+        // generate radio button set for overlays; start with 'none'
+        var rset = [{
+                gid: 'unknown',
+                tooltip: 'No Overlay',
+                cb: function () { setOverlay(); }
+            }];
+
+        tov.list().forEach(function (key) {
+            var ov = tov.overlay(key);
+            rset.push({
+                gid: ov._glyphId,
+                tooltip: (ov.tooltip || '(no tooltip)'),
+                cb: function () {
+                    setOverlay(ov.overlayId);
+                }
+            });
+        });
+
+        toolbar.addRadioSet('topo-overlays', rset);
+    }
+
+    // TODO: 3rd row needs to be swapped in/out based on selected overlay
     function addThirdRow() {
         addButton('V');
         addButton('leftArrow');
@@ -156,8 +193,6 @@
         addButton('W');
         addButton('A');
         addButton('F');
-        toolbar.addSeparator();
-        addButton('E');
     }
 
     function createToolbar() {
@@ -166,8 +201,10 @@
         addFirstRow();
         toolbar.addRow();
         addSecondRow();
+        addOverlays();
         toolbar.addRow();
         addThirdRow();
+
         if (cachedState.toolbar) {
             toolbar.show();
         } else {
@@ -199,12 +236,14 @@
     angular.module('ovTopo')
         .factory('TopoToolbarService',
         ['$log', 'FnService', 'ToolbarService', 'PrefsService',
+            'TopoOverlayService',
 
-        function (_$log_, _fs_, _tbs_, _ps_) {
+        function (_$log_, _fs_, _tbs_, _ps_, _tov_) {
             $log = _$log_;
             fs = _fs_;
             tbs = _tbs_;
             ps = _ps_;
+            tov = _tov_;
 
             return {
                 init: init,
diff --git a/web/gui/src/main/webapp/app/view/topo/topoTrafficNew.js b/web/gui/src/main/webapp/app/view/topo/topoTrafficNew.js
new file mode 100644
index 0000000..1da60c1
--- /dev/null
+++ b/web/gui/src/main/webapp/app/view/topo/topoTrafficNew.js
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2015 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 -- Topology Traffic Module.
+ Defines behavior for viewing different traffic modes.
+ Installed as a Topology Overlay.
+ */
+(function () {
+    'use strict';
+
+    // injected refs
+    var $log;
+
+    // traffic overlay definition
+    var overlay = {
+        overlayId: 'traffic',
+        glyph: { id: 'allTraffic' },
+        tooltip: 'Traffic Overlay',
+
+        activate: activateTraffic,
+        deactivate: deactivateTraffic
+    };
+
+    // === implementation of overlay API (essentially callbacks)
+    function activateTraffic() {
+        $log.debug("Topology traffic overlay ACTIVATED");
+    }
+
+    function deactivateTraffic() {
+        $log.debug("Topology traffic overlay DEACTIVATED");
+    }
+
+
+    // invoke code to register with the overlay service
+    angular.module('ovTopo')
+        .run(['$log', 'TopoOverlayService',
+
+        function (_$log_, tov) {
+            $log = _$log_;
+            tov.register(overlay);
+        }]);
+
+}());
diff --git a/web/gui/src/main/webapp/index.html b/web/gui/src/main/webapp/index.html
index d800d34..c571a0f 100644
--- a/web/gui/src/main/webapp/index.html
+++ b/web/gui/src/main/webapp/index.html
@@ -104,10 +104,12 @@
     <script src="app/view/topo/topoLink.js"></script>
     <script src="app/view/topo/topoModel.js"></script>
     <script src="app/view/topo/topoOblique.js"></script>
+    <script src="app/view/topo/topoOverlay.js"></script>
     <script src="app/view/topo/topoPanel.js"></script>
     <script src="app/view/topo/topoSelect.js"></script>
     <script src="app/view/topo/topoSprite.js"></script>
     <script src="app/view/topo/topoTraffic.js"></script>
+    <script src="app/view/topo/topoTrafficNew.js"></script>
     <script src="app/view/topo/topoToolbar.js"></script>
     <script src="app/view/device/device.js"></script>
     <script src="app/view/flow/flow.js"></script>