ONOS-5831 - retro fit icon and link scale from topo2

Change-Id: Iaa94929d324ba51e5a3056eb3a59d29be6d3d775
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 0623478..8acebcc 100644
--- a/web/gui/src/main/webapp/app/view/topo/topo.js
+++ b/web/gui/src/main/webapp/app/view/topo/topo.js
@@ -262,6 +262,8 @@
 
         // keep the map lines constant width while zooming
         mapG.style('stroke-width', (2.0 / sc) + 'px');
+
+        tfs.setNodeScale(sc);
     }
 
     function setUpZoom() {
diff --git a/web/gui/src/main/webapp/app/view/topo/topoD3.js b/web/gui/src/main/webapp/app/view/topo/topoD3.js
index 80413aa..e45f491 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoD3.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoD3.js
@@ -26,7 +26,7 @@
     var $log, fs, sus, is, ts, ps, ttbs;
 
     // api to topoForce
-    var api;
+    var zoomer, api;
     /*
      node()                 // get ref to D3 selection of nodes
      link()                 // get ref to D3 selection of links
@@ -51,6 +51,7 @@
         halfDevIcon = devIconDim / 2,
         devBadgeOff = { dx: -halfDevIcon, dy: -halfDevIcon },
         hostBadgeOff = { dx: -hostRadius, dy: -hostRadius },
+        portLabelDim = 30,
         status = {
             i: 'badgeInfo',
             w: 'badgeWarn',
@@ -283,6 +284,9 @@
         glyph.attr(iconBox(devIconDim, 0));
 
         node.attr('transform', sus.translate(-halfDevIcon, -halfDevIcon));
+
+        d.el.selectAll('*')
+            .style('transform', 'scale(' + api.deviceScale() + ')');
     }
 
     function hostEnter(d) {
@@ -299,6 +303,9 @@
             .text(hostLabel)
             .attr('dy', textDy)
             .attr('text-anchor', 'middle');
+
+        d.el.selectAll('g').style('transform', 'scale(' + api.deviceScale() + ')');
+        d.el.selectAll('text').style('transform', 'scale(' + api.deviceScale() + ')');
     }
 
     function hostExit(d) {
@@ -346,6 +353,7 @@
 
         var link = d3.select(this);
         d.el = link;
+        d.el.style('stroke-width', api.linkWidthScale() + 'px');
         api.restyleLinkElement(d);
         if (d.type() === 'hostLink') {
             sus.visible(link, api.showHosts());
@@ -469,13 +477,18 @@
             .classed('portLabel', true)
             .attr('id', function (d) { return d.id; });
 
+        var labelScale = portLabelDim / (portLabelDim * zoomer.scale());
+
         entering.each(function (d) {
             var el = d3.select(this),
                 rect = el.append('rect'),
                 text = el.append('text').text(d.num);
 
-            rect.attr(rectAroundText(el));
-            text.attr('dy', linkLabelOffset);
+            rect.attr(rectAroundText(el))
+                .style('transform', 'scale(' + labelScale + ')');
+            text.attr('dy', linkLabelOffset)
+                .style('transform', 'scale(' + labelScale + ')');
+
             el.attr('transform', sus.translate(d.x, d.y));
         });
     }
@@ -591,8 +604,9 @@
             ps = _ps_;
             ttbs = _ttbs_;
 
-            function initD3(_api_) {
+            function initD3(_api_, _zoomer_) {
                 api = _api_;
+                zoomer = _zoomer_;
             }
 
             function destroyD3() { }
diff --git a/web/gui/src/main/webapp/app/view/topo/topoForce.js b/web/gui/src/main/webapp/app/view/topo/topoForce.js
index 0808271..c33a232 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoForce.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoForce.js
@@ -63,7 +63,11 @@
         fNodesTimer,            // timer for delayed nodes update
         fLinksTimer,            // timer for delayed links update
         dim,                    // the dimensions of the force layout [w,h]
-        linkNums = [];          // array of link number labels
+        linkNums = [],          // array of link number labels
+        devIconDim = 36,        // node target dimension
+        devIconDimMin = 20,     // node minimum dimension when zoomed out
+        devIconDimMax = 40,     // node maximum dimension when zoomed in
+        portLabelDim = 30;
 
     // SVG elements;
     var linkG, linkLabelG, numLinkLblsG, portLabelG, nodeG;
@@ -588,6 +592,53 @@
         $timeout(updateLinks, 2000);
     }
 
+    function deviceScale() {
+        var scale = uplink.zoomer().scale(),
+            dim = devIconDim,
+            multiplier = 1;
+
+        if (dim * scale < devIconDimMin) {
+            multiplier = devIconDimMin / (dim * scale);
+        } else if (dim * scale > devIconDimMax) {
+            multiplier = devIconDimMax / (dim * scale);
+        }
+
+        return multiplier;
+    }
+
+    function linkWidthScale(scale) {
+        var scale = uplink.zoomer().scale();
+        return linkScale(widthRatio) / scale;
+    }
+
+    function portLabelScale(scale) {
+        var scale = uplink.zoomer().scale();
+        return portLabelDim / (portLabelDim * scale);
+    }
+
+    function setNodeScale(scale) {
+        // Scale the network nodes
+        _.each(network.nodes, function (node) {
+            if (node.class === 'host') {
+                node.el.selectAll('g').style('transform', 'scale(' + deviceScale(scale) + ')');
+                node.el.selectAll('text').style('transform', 'scale(' + deviceScale(scale) + ')');
+                return;
+            }
+            node.el.selectAll('*')
+                .style('transform', 'scale(' + deviceScale(scale) + ')');
+        });
+
+        // Scale the network links
+        _.each(network.links, function (link) {
+            link.el.style('stroke-width', linkWidthScale(scale) + 'px');
+        });
+
+        d3.select('#topo-portLabels')
+            .selectAll('.portLabel')
+            .selectAll('*')
+            .style('transform', 'scale(' + portLabelScale(scale) + ')');
+    }
+
     function resetAllLocations() {
         tms.resetAllLocations();
         updateNodes();
@@ -607,6 +658,8 @@
     // IMPLEMENTATION NOTE: _updateNodes() should NOT stop, start, or resume
     //  the force layout; that needs to be determined and implemented elsewhere
     function _updateNodes() {
+
+        var scale = uplink.zoomer().scale();
         // select all the nodes in the layout:
         node = nodeG.selectAll('.node')
             .data(network.nodes, function (d) { return d.id; });
@@ -962,7 +1015,9 @@
             showHosts: function () { return showHosts; },
             restyleLinkElement: restyleLinkElement,
             updateLinkLabelModel: updateLinkLabelModel,
-            linkConfig: function () { return linkConfig; }
+            linkConfig: function () { return linkConfig; },
+            deviceScale: deviceScale,
+            linkWidthScale: linkWidthScale,
         };
     }
 
@@ -1092,7 +1147,7 @@
 
                 tov.setApi(mkOverlayApi(), tss);
                 tms.initModel(mkModelApi(uplink), dim);
-                td3.initD3(mkD3Api());
+                td3.initD3(mkD3Api(), uplink.zoomer());
                 tss.initSelect(mkSelectApi());
                 tts.initTraffic(mkTrafficApi());
                 tpis.initProtectedIntents(mkTrafficApi());
@@ -1188,6 +1243,7 @@
                 unpin: unpin,
                 showMastership: showMastership,
                 showBadLinks: showBadLinks,
+                setNodeScale: setNodeScale,
 
                 resetAllLocations: resetAllLocations,
                 addDevice: addDevice,
diff --git a/web/gui/src/main/webapp/tests/app/view/topo/topoForce-spec.js b/web/gui/src/main/webapp/tests/app/view/topo/topoForce-spec.js
index 101dda8..f0a2914 100644
--- a/web/gui/src/main/webapp/tests/app/view/topo/topoForce-spec.js
+++ b/web/gui/src/main/webapp/tests/app/view/topo/topoForce-spec.js
@@ -42,6 +42,7 @@
             'updateDeviceColors', 'toggleHosts',
             'togglePorts', 'toggleOffline',
             'cycleDeviceLabels', 'unpin', 'showMastership', 'showBadLinks',
+            'setNodeScale',
 
             'resetAllLocations', 'addDevice', 'updateDevice', 'removeDevice',
             'addHost', 'updateHost', 'moveHost', 'removeHost',