ONOS-3518: Refactored badge-rendering code.
 - augmented badges test scenario.

Change-Id: I7cef224daacfd52056440fb2ad068002f740b51f
diff --git a/web/gui/src/main/webapp/app/fw/svg/icon.js b/web/gui/src/main/webapp/app/fw/svg/icon.js
index cc26360..d6a517f 100644
--- a/web/gui/src/main/webapp/app/fw/svg/icon.js
+++ b/web/gui/src/main/webapp/app/fw/svg/icon.js
@@ -149,6 +149,10 @@
             rx: 4
         },
         host: {
+            badge: {
+                dx: 14,
+                dy: -14
+            },
             radius: {
                 noGlyph: 9,
                 withGlyph: 14
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 c8df20e..0319b9b 100644
--- a/web/gui/src/main/webapp/app/view/topo/topo.css
+++ b/web/gui/src/main/webapp/app/view/topo/topo.css
@@ -452,7 +452,7 @@
 }
 
 #ov-topo svg .node .badge.badgeInfo circle {
-    fill: #ccf;
+    fill: #99d;
 }
 
 #ov-topo svg .node .badge.badgeWarn circle {
@@ -464,7 +464,7 @@
 }
 
 #ov-topo svg .node .badge use {
-    fill: white;
+    fill: white !important;
 }
 
 #ov-topo svg .node .badge.badgeInfo use {
@@ -472,7 +472,7 @@
 }
 
 #ov-topo svg .node .badge text {
-    fill: white;
+    fill: white !important;
 }
 
 #ov-topo svg .node .badge.badgeInfo text {
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 168e9ce..5bf2eb4 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoD3.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoD3.js
@@ -200,7 +200,6 @@
         };
     }
 
-
     function updateDeviceRendering(d) {
         var label = trimLabel(deviceLabel(d)),
             noLabel = !label,
@@ -237,76 +236,50 @@
 
         // handle badge, if defined
         if (bdg) {
-            node.select('g.badge').remove();
-
-            bsel = node.append('g')
-                .classed('badge', true)
-                .classed(badgeStatus(bdg), true)
-                .attr('transform', sus.translate(dx + dim, dy));
-
-            bsel.append('circle')
-                .attr('r', bcr);
-
-            if (bdg.txt) {
-                bsel.append('text')
-                    .attr('dy', badgeConfig.yoff)
-                    .attr('text-anchor', 'middle')
-                    .text(bdg.txt);
-            } else if (bdg.gid) {
-                bsel.append('use')
-                    .attr({
-                        width: bcgd * 2,
-                        height: bcgd * 2,
-                        transform: sus.translate(-bcgd, -bcgd),
-                        'xlink:href': '#' + bdg.gid
-                    });
-
-            }
+            renderBadge(node, bdg, { dx: dx + dim, dy: dy });
         }
     }
 
     function updateHostRendering(d) {
         var node = d.el,
-            dim = icfg.host.radius.withGlyph,
-            box, dx, dy, bsel,
-            bdg = d.badge,
-            bcr = badgeConfig.radius,
-            bcgd = badgeConfig.gdelta;
-
+            bdg = d.badge;
 
         updateHostLabel(d);
-        
-        // TODO: fine-tune dx, dy for badge placement relative to host Circle.
-            dx = -dim/2;
-            dy = -dim/2;
 
         // handle badge, if defined
         if (bdg) {
-            node.select('g.badge').remove();
+            renderBadge(node, bdg, icfg.host.badge);
+        }
+    }
 
-            bsel = node.append('g')
-                .classed('badge', true)
-                .classed(badgeStatus(bdg), true)
-                .attr('transform', sus.translate(dx + dim, dy));
+    function renderBadge(node, bdg, boff) {
+        var bsel,
+            bcr = badgeConfig.radius,
+            bcgd = badgeConfig.gdelta;
 
-            bsel.append('circle')
-                .attr('r', bcr);
+        node.select('g.badge').remove();
 
-            if (bdg.txt) {
-                bsel.append('text')
-                    .attr('dy', badgeConfig.yoff)
-                    .attr('text-anchor', 'middle')
-                    .text(bdg.txt);
-            } else if (bdg.gid) {
-                bsel.append('use')
-                    .attr({
-                        width: bcgd * 2,
-                        height: bcgd * 2,
-                        transform: sus.translate(-bcgd, -bcgd),
-                        'xlink:href': '#' + bdg.gid
-                    });
+        bsel = node.append('g')
+            .classed('badge', true)
+            .classed(badgeStatus(bdg), true)
+            .attr('transform', sus.translate(boff.dx, boff.dy));
 
-            }
+        bsel.append('circle')
+            .attr('r', bcr);
+
+        if (bdg.txt) {
+            bsel.append('text')
+                .attr('dy', badgeConfig.yoff)
+                .attr('text-anchor', 'middle')
+                .text(bdg.txt);
+        } else if (bdg.gid) {
+            bsel.append('use')
+                .attr({
+                    width: bcgd * 2,
+                    height: bcgd * 2,
+                    transform: sus.translate(-bcgd, -bcgd),
+                    'xlink:href': '#' + bdg.gid
+                });
         }
     }
 
diff --git a/web/gui/src/test/_karma/ev/badges/ev_10_addHost_02.json b/web/gui/src/test/_karma/ev/badges/ev_10_addHost_02.json
new file mode 100644
index 0000000..db17014
--- /dev/null
+++ b/web/gui/src/test/_karma/ev/badges/ev_10_addHost_02.json
@@ -0,0 +1,21 @@
+{
+  "event": "addHost",
+  "payload": {
+    "id": "0E:2A:69:30:13:97/-1",
+    "ingress": "0E:2A:69:30:13:97/-1/0-of:0000000000000002/3",
+    "egress": "of:0000000000000002/3-0E:2A:69:30:13:97/-1/0",
+    "cp": {
+      "device": "of:0000000000000002",
+      "port": 3
+    },
+    "labels": [
+      "192.168.0.2",
+      "0E:2A:69:30:13:97"
+    ],
+    "metaUi": {
+      "x": 340,
+      "y": 100
+    },
+    "props": {}
+  }
+}
diff --git a/web/gui/src/test/_karma/ev/badges/ev_11_addHost_03.json b/web/gui/src/test/_karma/ev/badges/ev_11_addHost_03.json
new file mode 100644
index 0000000..5038df1
--- /dev/null
+++ b/web/gui/src/test/_karma/ev/badges/ev_11_addHost_03.json
@@ -0,0 +1,21 @@
+{
+  "event": "addHost",
+  "payload": {
+    "id": "0E:2A:69:30:13:a8/-1",
+    "ingress": "0E:2A:69:30:13:a8/-1/0-of:0000000000000002/4",
+    "egress": "of:0000000000000002/4-0E:2A:69:30:13:a8/-1/0",
+    "cp": {
+      "device": "of:0000000000000002",
+      "port": 4
+    },
+    "labels": [
+      "192.168.0.3",
+      "0E:2A:69:30:13:a8"
+    ],
+    "metaUi": {
+      "x": 480,
+      "y": 90
+    },
+    "props": {}
+  }
+}
diff --git a/web/gui/src/test/_karma/ev/badges/ev_11_showHighlights_clear.json b/web/gui/src/test/_karma/ev/badges/ev_12_showHighlights_clear.json
similarity index 100%
rename from web/gui/src/test/_karma/ev/badges/ev_11_showHighlights_clear.json
rename to web/gui/src/test/_karma/ev/badges/ev_12_showHighlights_clear.json
diff --git a/web/gui/src/test/_karma/ev/badges/ev_10_showHighlights_stuff.json b/web/gui/src/test/_karma/ev/badges/ev_13_showHighlights_devices.json
similarity index 100%
rename from web/gui/src/test/_karma/ev/badges/ev_10_showHighlights_stuff.json
rename to web/gui/src/test/_karma/ev/badges/ev_13_showHighlights_devices.json
diff --git a/web/gui/src/test/_karma/ev/badges/ev_14_showHighlights_hosts.json b/web/gui/src/test/_karma/ev/badges/ev_14_showHighlights_hosts.json
new file mode 100644
index 0000000..a935496
--- /dev/null
+++ b/web/gui/src/test/_karma/ev/badges/ev_14_showHighlights_hosts.json
@@ -0,0 +1,32 @@
+{
+  "event": "showHighlights",
+  "payload": {
+    "devices": [],
+    "hosts": [
+      {
+        "id": "0E:2A:69:30:13:86/-1",
+        "badge": {
+          "status": "e",
+          "txt": "99",
+          "msg": "cadbury's flake"
+        }
+      },
+      {
+        "id": "0E:2A:69:30:13:97/-1",
+        "badge": {
+          "status": "i",
+          "gid": "xMark",
+          "msg": "x marks the spot"
+        }
+      },
+      {
+        "id": "0E:2A:69:30:13:a8/-1",
+        "badge": {
+          "status": "w",
+          "gid": "crown"
+        }
+      }
+    ],
+    "links": []
+  }
+}
diff --git a/web/gui/src/test/_karma/ev/badges/ev_11_showHighlights_clear.json b/web/gui/src/test/_karma/ev/badges/ev_15_showHighlights_clear.json
similarity index 100%
copy from web/gui/src/test/_karma/ev/badges/ev_11_showHighlights_clear.json
copy to web/gui/src/test/_karma/ev/badges/ev_15_showHighlights_clear.json
diff --git a/web/gui/src/test/_karma/ev/badges/ev_9_addHost_01.json b/web/gui/src/test/_karma/ev/badges/ev_9_addHost_01.json
new file mode 100644
index 0000000..9604606
--- /dev/null
+++ b/web/gui/src/test/_karma/ev/badges/ev_9_addHost_01.json
@@ -0,0 +1,21 @@
+{
+  "event": "addHost",
+  "payload": {
+    "id": "0E:2A:69:30:13:86/-1",
+    "ingress": "0E:2A:69:30:13:86/-1/0-of:0000000000000001/2",
+    "egress": "of:0000000000000001/2-0E:2A:69:30:13:86/-1/0",
+    "cp": {
+      "device": "of:0000000000000001",
+      "port": 2
+    },
+    "labels": [
+      "192.168.0.1",
+      "0E:2A:69:30:13:86"
+    ],
+    "metaUi": {
+      "x": 210,
+      "y": 100
+    },
+    "props": {}
+  }
+}
diff --git a/web/gui/src/test/_karma/ev/badges/ev_9_showHighlights_clear.json b/web/gui/src/test/_karma/ev/badges/ev_9_showHighlights_clear.json
deleted file mode 100644
index 615efd2..0000000
--- a/web/gui/src/test/_karma/ev/badges/ev_9_showHighlights_clear.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "event": "showHighlights",
-  "payload": {
-    "devices": [],
-    "hosts": [],
-    "links": []
-  }
-}
diff --git a/web/gui/src/test/_karma/ev/badges/scenario.json b/web/gui/src/test/_karma/ev/badges/scenario.json
index ae093d6..c5bad4f 100644
--- a/web/gui/src/test/_karma/ev/badges/scenario.json
+++ b/web/gui/src/test/_karma/ev/badges/scenario.json
@@ -1,12 +1,12 @@
 {
   "comments": [
-    "Demo of adding badges to devices"
+    "Demo of adding badges to devices and hosts"
   ],
   "title": "Demo adding badges",
   "params": {
-    "lastAuto": 9
+    "lastAuto": 12
   },
   "description": [
-    "Demonstrate the device badging feature."
+    "Demonstrate the device/host badging feature."
   ]
 }