GUI -- TopoView - Port numbers now appear when hovering over a link.
- (but they are centered on the node -- still need to move them away from the node).

Change-Id: I491851ef2f4d31b85db0dbc2b3145218a4913844
diff --git a/web/gui/src/main/webapp/app/view/topo/topo.css b/web/gui/src/main/webapp/app/view/topo/topo.css
index 5fe9c39..5f7e5c1 100644
--- a/web/gui/src/main/webapp/app/view/topo/topo.css
+++ b/web/gui/src/main/webapp/app/view/topo/topo.css
@@ -484,6 +484,8 @@
     stroke: #7352CD;
 }
 
+/* Link Labels */
+
 #ov-topo svg .linkLabel rect {
     stroke: none;
 }
@@ -506,6 +508,32 @@
     fill: #eee;
 }
 
+/* Port Labels */
+
+#ov-topo svg .portLabel rect {
+    stroke: none;
+}
+.light #ov-topo svg .portLabel rect {
+    fill: #eee;
+}
+.dark #ov-topo svg .portLabel rect {
+    fill: #555;
+}
+
+#ov-topo svg .portLabel text {
+    text-anchor: middle;
+    stroke-width: 0.1;
+    font-size: 9pt;
+}
+.light #ov-topo svg .portLabel text {
+    fill: #444;
+}
+.dark #ov-topo svg .portLabel text {
+    fill: #eee;
+}
+
+
+
 
 /* radio buttons injected into masthead */
 
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 a555ac1..7017a75 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoD3.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoD3.js
@@ -413,6 +413,27 @@
         return sus.translate(xMid, yMid);
     }
 
+    function applyPortLabels(data, portLabelG) {
+        var entering = portLabelG.selectAll('.portLabel')
+            .data(data).enter().append('g')
+            .classed('portLabel', true)
+            .attr('id', function (d) { return d.id; });
+
+        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);
+            el.attr('transform', transformPort(d));
+        });
+    }
+
+    function transformPort(d) {
+        // TODO: offset along the link, away from the node
+        return sus.translate(d.baseX, d.baseY);
+    }
 
     // ==========================
     // Module definition
@@ -459,8 +480,8 @@
 
                 linkEntering: linkEntering,
                 applyLinkLabels: applyLinkLabels,
-
-                transformLabel: transformLabel
+                transformLabel: transformLabel,
+                applyPortLabels: applyPortLabels
             };
         }]);
 }());
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 ea7cada..3660973 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoForce.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoForce.js
@@ -60,7 +60,7 @@
         dim;                    // the dimensions of the force layout [w,h]
 
     // SVG elements;
-    var linkG, linkLabelG, nodeG;
+    var linkG, linkLabelG, portLabelG, nodeG;
 
     // D3 selections;
     var link, linkLabel, node;
@@ -741,6 +741,7 @@
             forceG: forceG,
             zoomer: uplink.zoomer(),
             network: network,
+            portLabelG: function () { return portLabelG; },
             showHosts: function () { return showHosts; }
         };
     }
@@ -792,13 +793,14 @@
                 tts.initTraffic(mkTrafficApi(uplink));
                 tos.initOblique(mkObliqueApi(uplink, fltr));
                 fltr.initFilter(mkFilterApi(uplink), d3.select('#mast-right'));
-                tls.initLink(mkLinkApi(svg, forceG, uplink));
+                tls.initLink(mkLinkApi(svg, forceG, uplink), td3);
 
                 settings = angular.extend({}, defaultSettings, opts);
 
                 linkG = forceG.append('g').attr('id', 'topo-links');
                 linkLabelG = forceG.append('g').attr('id', 'topo-linkLabels');
                 nodeG = forceG.append('g').attr('id', 'topo-nodes');
+                portLabelG = forceG.append('g').attr('id', 'topo-portLabels');
 
                 link = linkG.selectAll('.link');
                 linkLabel = linkLabelG.selectAll('.linkLabel');
diff --git a/web/gui/src/main/webapp/app/view/topo/topoLink.js b/web/gui/src/main/webapp/app/view/topo/topoLink.js
index 05041c4..2ac1b60 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoLink.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoLink.js
@@ -26,6 +26,7 @@
     var $log, fs, sus, ts;
 
     var api,
+        td3,
         network,
         enhancedLink = null;    // the link which the mouse is hovering over
 
@@ -190,16 +191,33 @@
 
     function unenhance(d) {
         d.el.classed('enhanced', false);
+        api.portLabelG().selectAll('.portLabel').remove();
     }
 
     function enhance(d) {
         d.el.classed('enhanced', true);
         $log.debug('[' + (d.srcPort || 'H') + '] ---> [' + d.tgtPort + ']', d.key);
+
+        // define port label data objects
+        var data = [
+            {
+                id: 'topo-port-src',
+                num: d.srcPort,
+                baseX: d.source.x,
+                baseY: d.source.y
+            },
+            {
+                id: 'topo-port-tgt',
+                num: d.tgtPort,
+                baseX: d.target.x,
+                baseY: d.target.y
+            }
+        ];
+
+        td3.applyPortLabels(data, api.portLabelG());
     }
 
 
-
-
     // ==========================
     // Module definition
 
@@ -213,8 +231,9 @@
                 sus = _sus_;
                 ts = _ts_;
 
-                function initLink(_api_) {
+                function initLink(_api_, _td3_) {
                     api = _api_;
+                    td3 = _td3_;
                     svg = api.svg;
                     network = api.network;
                     setupMouse(api.forceG, api.zoomer);