Topo2: ONOS Build Paris Demo tweaks

Change-Id: I93a01b077bdff4152f1ab3e7ebe8391232b846dc
diff --git a/tools/test/topos/regions-topo-2 b/tools/test/topos/regions-topo-2
index 29f632d..3f76066 100755
--- a/tools/test/topos/regions-topo-2
+++ b/tools/test/topos/regions-topo-2
@@ -21,17 +21,17 @@
 null-create-device switch DOVER 10 51.1295 1.3089
 
 # region 1
-null-create-device switch BRGHTN-A 10 50.9000 -0.1313
-null-create-device switch BRGHTN-B 10 50.8429 -0.1413
-null-create-device switch BRGHTN-C 10 50.8429 -0.1213
+null-create-device switch BRGHTN-A 10 50.95 -0.1313
+null-create-device switch BRGHTN-B 10 50.8429 -0.3013
+null-create-device switch BRGHTN-C 10 50.8429 0.2
 
 # region 2
-null-create-device switch LONDON-A 10 51.5091 -0.2704
-null-create-device switch LONDON-B 10 51.5091 0.0432
+null-create-device switch LONDON-A 10 51.5091 -0.3704
+null-create-device switch LONDON-B 10 51.5091 0.132
 # region 3 (subregion of 2)
 null-create-device switch LONDON-C 10 51.4513 -0.1058
-null-create-device switch LONDON-D 10 51.5418 -0.1931
-null-create-device switch LONDON-E 10 51.5072 -0.1175
+null-create-device switch LONDON-D 10 51.5518 -0.1031
+null-create-device switch LONDON-E 10 51.5072 -0.3075
 
 ## NOTE: create more than 9 devices seems to be broken
 
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2Jsonifier.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2Jsonifier.java
index 36118ab..9e02334 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2Jsonifier.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2Jsonifier.java
@@ -21,6 +21,7 @@
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.onlab.osgi.ServiceDirectory;
+import org.onlab.packet.IpAddress;
 import org.onosproject.cluster.ClusterService;
 import org.onosproject.cluster.NodeId;
 import org.onosproject.incubator.net.PortStatisticsService;
@@ -29,6 +30,7 @@
 import org.onosproject.net.Annotated;
 import org.onosproject.net.Annotations;
 import org.onosproject.net.Device;
+import org.onosproject.net.Host;
 import org.onosproject.net.device.DeviceService;
 import org.onosproject.net.flow.FlowRuleService;
 import org.onosproject.net.host.HostService;
@@ -327,6 +329,17 @@
         }
     }
 
+    private void addIps(ObjectNode node, Host h) {
+        Set<IpAddress> ips = h.ipAddresses();
+
+        ArrayNode a = arrayNode();
+        for (IpAddress ip : ips) {
+            a.add(ip.toString());
+        }
+
+        node.set("ips", a);
+    }
+
     // return list of string values from annotated instance, for given keys
     // return null if any keys are not present
     List<String> getAnnotValues(Annotated a, String... annotKeys) {
@@ -351,11 +364,18 @@
     }
 
     private ObjectNode json(UiHost host) {
-        return objectNode()
+        ObjectNode node = objectNode()
                 .put("id", host.idAsString())
                 .put("nodeType", HOST)
                 .put("layer", host.layer());
         // TODO: complete host details
+        Host h = host.backingHost();
+
+        addIps(node, h);
+        addGeoLocation(node, h);
+        addMetaUi(node, host.idAsString());
+
+        return node;
     }
 
     private ObjectNode json(UiSynthLink sLink) {
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2-theme.css b/web/gui/src/main/webapp/app/view/topo2/topo2-theme.css
index a5b996a..540fe5b 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2-theme.css
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2-theme.css
@@ -258,7 +258,7 @@
 
 #ov-topo2 svg .link.inactive {
     opacity: .5;
-    stroke-dasharray: 8 4;
+    stroke-dasharray: 4 2;
 }
 /* TODO: Review for not-permitted links */
 #ov-topo2 svg .link.not-permitted {
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Host.js b/web/gui/src/main/webapp/app/view/topo2/topo2Host.js
index 9cc9f7e..3fdbeb5 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Host.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Host.js
@@ -59,6 +59,20 @@
                     var type = this.get('type');
                     return remappedDeviceTypes[type] || type || 'endstation';
                 },
+                label: function () {
+                    var labelText = this.get('id'),
+                        ips = this.get('ips');
+
+                    if (this.labelIndex() === 0) {
+                        return '';
+                    }
+
+                    if (ips && ips.length > 0) {
+                        labelText = ips[0];
+                    }
+
+                    return labelText;
+                },
                 setScale: function () {
 
                     var dim = hostIconDim,
@@ -76,8 +90,9 @@
                 onEnter: function (el) {
                     var node = d3.select(el),
                         icon = this.icon(),
-                        textDy = hostIconDim + 15,
-                        iconDim = hostIconDim;
+                        iconDim = hostIconDim,
+                        textDy = 5,
+                        textDx = (hostIconDim * 2) + 20;
 
                     this.el = node;
 
@@ -93,9 +108,12 @@
                         y: -iconDim / 2
                     });
 
+                    var labelText = this.label();
+
                     g.append('text')
-                        .text(this.get('id'))
+                        .text(labelText)
                         .attr('dy', textDy)
+                        .attr('dx', textDx)
                         .attr('text-anchor', 'middle');
 
                     this.setScale();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2KeyCommands.js b/web/gui/src/main/webapp/app/view/topo2/topo2KeyCommands.js
index 8885a89..bc350c3 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2KeyCommands.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2KeyCommands.js
@@ -60,10 +60,22 @@
         ps.setPrefs('topo_prefs', prefsState);
     }
 
+    function deviceLabelFlashMessage(index) {
+
+        switch (index) {
+            case 0: return 'Hide device labels';
+            case 1: return 'Show friendly device labels';
+            case 2: return 'Show device ID labels';
+        }
+    }
+
     function cycleDeviceLabels() {
-        var deviceLabelIndex = t2ps.get('dlbls') + 1;
-        t2ps.set('dlbls', deviceLabelIndex % 3);
+        var deviceLabelIndex = t2ps.get('dlbls') + 1,
+            newDeviceLabelIndex =  deviceLabelIndex % 3;
+
+        t2ps.set('dlbls', newDeviceLabelIndex);
         t2fs.updateNodes();
+        flash.flash(deviceLabelFlashMessage(newDeviceLabelIndex));
     }
 
     function openMapSelection() {
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Layout.js b/web/gui/src/main/webapp/app/view/topo2/topo2Layout.js
index 9ffcbe0..7274761 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Layout.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Layout.js
@@ -24,11 +24,9 @@
 
     var $log, wss, sus, t2rs, t2d3, t2vs, t2ss;
 
-    var uplink, linkG, linkLabelG, nodeG;
+    var linkG, linkLabelG, nodeG;
     var link, node;
 
-    var highlightedLink;
-
     // default settings for force layout
     var defaultSettings = {
         gravity: 0.4,
@@ -36,14 +34,15 @@
         charge: {
             // note: key is node.class
             device: -8000,
-            host: -5000,
+            host: -20000,
+            region: -5000,
             _def_: -12000
         },
         linkDistance: {
             // note: key is link.type
             direct: 100,
             optical: 120,
-            hostLink: 3,
+            UiEdgeLink: 30,
             _def_: 50
         },
         linkStrength: {
@@ -51,7 +50,7 @@
             // range: {0.0 ... 1.0}
             direct: 1.0,
             optical: 1.0,
-            hostLink: 1.0,
+            UiEdgeLink: 15.0,
             _def_: 1.0
         }
     };
@@ -79,26 +78,9 @@
         drag,       // drag behavior handler
         nodeLock = false;       // whether nodes can be dragged or not (locked)
 
-    var tickStuff = {
-        nodeAttr: {
-            transform: function (d) {
-                var dx = isNaN(d.x) ? 0 : d.x,
-                    dy = isNaN(d.y) ? 0 : d.y;
-                return sus.translate(dx, dy);
-            }
-        },
-        linkAttr: {
-            x1: function (d) { return d.get('position').x1; },
-            y1: function (d) { return d.get('position').y1; },
-            x2: function (d) { return d.get('position').x2; },
-            y2: function (d) { return d.get('position').y2; }
-        }
-    };
-
     function init(_svg_, forceG, _uplink_, _dim_, opts) {
 
         $log.debug("Initialising Topology Layout");
-        uplink = _uplink_;
         settings = angular.extend({}, defaultSettings, opts);
 
         linkG = forceG.append('g').attr('id', 'topo-links');
@@ -112,6 +94,28 @@
         node = nodeG.selectAll('.node');
     }
 
+    function getDeviceChargeForType(node) {
+
+        var nodeType = node.get('nodeType');
+
+        return settings.charge[nodeType] ||
+            settings.charge._def_;
+    }
+
+    function getLinkDistanceForLinkType(node) {
+        var nodeType = node.get('type');
+
+        return settings.linkDistance[nodeType] ||
+            settings.linkDistance._def_;
+    }
+
+    function getLinkStrenghForLinkType(node) {
+        var nodeType = node.get('type');
+
+        return settings.linkStrength[nodeType] ||
+            settings.linkStrength._def_;
+    }
+
     function createForceLayout() {
 
         var regionLinks = t2rs.regionLinks(),
@@ -119,8 +123,11 @@
 
         force = d3.layout.force()
             .size(t2vs.getDimensions())
-            .charge(settings.charge._def_)
-            .linkDistance(settings.linkDistance._def_)
+            .gravity(settings.gravity)
+            .friction(settings.friction)
+            .charge(getDeviceChargeForType)
+            .linkDistance(getLinkDistanceForLinkType)
+            .linkStrength(getLinkStrenghForLinkType)
             .on("tick", tick);
 
         force
@@ -154,6 +161,7 @@
         d.fixed = true;
         d3.select(this).classed('fixed', true);
         sendUpdateMeta(d);
+        $log.debug(d);
         t2ss.clickConsumed(true);
     }
 
@@ -231,8 +239,6 @@
                 opacity: 0
             })
             .call(drag)
-            // .on('mouseover', tss.nodeMouseOver)
-            // .on('mouseout', tss.nodeMouseOut)
             .transition()
             .attr('opacity', 1);
 
@@ -245,7 +251,7 @@
         // Sub element animations should be shorter than 2 seconds.
         var exiting = node.exit()
             .transition()
-            .duration(2000)
+            .duration(300)
             .style('opacity', 0)
             .remove();
 
@@ -277,26 +283,11 @@
 
         entering.each(t2d3.linkEntering);
 
-        // operate on both existing and new links:
-        // link.each(...)
-
-        // add labels for how many links are in a thick line
-        // t2d3.applyNumLinkLabels(linkNums, numLinkLabelsG);
-
-        // apply or remove labels
-        // t2d3.applyLinkLabels();
-
         // operate on exiting links:
         link.exit()
-            .attr('stroke-dasharray', '3 3')
-            .attr('stroke', linkConfig.light.outColor)
-            .style('opacity', 0.5)
+            .style('opacity', 1)
             .transition()
-            .duration(1500)
-            .attr({
-                'stroke-dasharray': '3 12',
-                'stroke-width': linkConfig.outWidth
-            })
+            .duration(300)
             .style('opacity', 0.0)
             .remove();
     }
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Link.js b/web/gui/src/main/webapp/app/view/topo2/topo2Link.js
index f8f331c..419f688 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Link.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Link.js
@@ -31,8 +31,8 @@
             .domain([1, 12])
             .range([widthRatio, 12 * widthRatio])
             .clamp(true),
-        allLinkTypes = 'direct indirect optical tunnel UiDeviceLink',
-        allLinkSubTypes = 'inactive not-permitted',
+        allLinkTypes = 'direct optical tunnel UiDeviceLink',
+        allLinkSubTypes = 'not-permitted',
         labelDim = 30;
 
     // configuration
@@ -225,7 +225,7 @@
                     el = this.el,
                     type = this.get('type'),
                     online = this.online(),
-                    modeCls = this.expected() ? 'inactive' : 'not-permitted',
+                    modeCls = this.expected() ? '-inactive' : 'not-permitted',
                     delay = immediate ? 0 : 1000;
 
                 // NOTE: understand why el is sometimes undefined on addLink events...
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js b/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js
index 42275bf..048e2f9 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js
@@ -97,12 +97,15 @@
                 icon: function () {
                     return 'unknown';
                 },
+                labelIndex: function () {
+                    return ps.get('dlbls');
+                },
                 label: function () {
                     var props = this.get('props'),
                         id = this.get('id'),
                         friendlyName = props && props.name ? props.name : id,
                         labels = ['', friendlyName || id, id],
-                        nli = ps.get('dlbls'),
+                        nli = this.labelIndex(),
                         idx = (nli < labels.length) ? nli : 0;
 
                     return labels[idx];
@@ -225,7 +228,8 @@
                     glyph.attr(this.iconBox(devIconDim, 0));
                     glyph.style('fill', 'white');
 
-                    node.attr('transform', sus.translate(-halfDevIcon, -halfDevIcon));
+                    node.attr('transform',
+                        sus.translate(-halfDevIcon, -halfDevIcon));
 
                     if (this.events) {
                         this.setUpEvents();