GUI -- Re-worked ONOS Instance panel (WIP)
- added sample events, including updated addInstance event.
- cleaned up glyphs; added badges.
- fixed defect in floating panel .width(...) function.

Change-Id: I00d7ca38a1b291c4735b6dd5e39f0266549b545f
diff --git a/web/gui/src/main/webapp/glyphs.js b/web/gui/src/main/webapp/glyphs.js
index 6a01504..5e428dd 100644
--- a/web/gui/src/main/webapp/glyphs.js
+++ b/web/gui/src/main/webapp/glyphs.js
@@ -50,79 +50,78 @@
             .append('path').attr('d', birdData);
     }
 
-    var bullhornData = "M0,13c0,3.733,2.561,6.148,6.019,6.809 " +
-        "C6.013,19.873,6,19.935,6,20v8 c0,1.105,0.895,2,2,2h3 " +
-        "c1.105,0,2-0.896,2-2v-8h3V6H8C3.582,6,0,8.582,0,13z " +
-        "M18,20h3V6h-3V20z M30,0l-7,4.667v16.667L30,26 c1.105,0,2-0.895,2-2" +
-        "V2 C32,0.896,31.105,0,30,0z";
-
-    function defBullhorn(defs) {
-        defs.append('symbol')
-            .attr({
-                id: 'bullhorn',
-                viewBox: '-4 -5 40 40'
-            })
-            .append('path').attr('d', bullhornData);
-    }
-
     var glyphData = {
         unknown: "M-20 -15 a5 5 0 0 1 5 -5 h30 a5 5 0 0 1 5 5 v30 " +
-                "a5 5 0 0 1 -5 5 h-30 a5 5 0 0 1 -5 -5 z ",
-        router: "M-45 0 A45 45 0 0 1 45 0 A45 45 0 0 1 -45 0 M -35 -5 " +
-                "l 12 0, 0 -8, 18 13, -18 13, 0 -8, -12 0 z M 35 -5 " +
-                "l -12 0, 0 -8, -18 13, 18 13, 0 -8, 12 0 z M -5 -8 " +
-                "l 0 -12, -8 0, 13 -18, 13 18, -8 0, 0 12 z M -5 8 " +
-                "l 0 12, -8 0, 13 18, 13 -18, -8 0, 0 -12 z ",
-        bgpSpeaker: "M-45 -15 a45 35 0 0 1 90 0 Q45 22 0 45 Q-45 22 -45 -15 z " +
-                    "M -5 -26 l 12 0, 0 -8, 18 13, -18 13, 0 -8, -12 0 z M 5 2" +
-                    " l -12 0, 0 -8, -18 13, 18 13, 0 -8, 12 0 z ",
+            "a5 5 0 0 1 -5 5 h-30 a5 5 0 0 1 -5 -5 z",
 
-        switch: "M-45 -35 a10 10 0 0 1 10 -10 h70 a 10 10 0 0 1 10 10 v70 a 10 10 0 0 1 -10 10 h -70 a 10 10 0 0 1 -10 -10 z M 5 -29 l 12 0, 0 -8, 18 13, -18 13, 0 -8, -12 0 z M 5 5 l 12 0, 0 -8, 18 13, -18 13, 0 -8, -12 0 z M -5 -15 l -12 0, 0 -8, -18 13, 18 13, 0 -8, 12 0 z M -5 19 l -12 0, 0 -8, -18 13, 18 13, 0 -8, 12 0 z",
-
-
-        Xswitch: "M-45 -35 a10 10 0 0 1 10 -10 h70 a 10 10 0 0 1 10 10 v70 " +
-                "a 10 10 0 0 1 -10 10 h -70 a 10 10 0 0 1 -10 -10 z M 5 -29 " +
-                "l 12 0, 0 -8, 18 13, -18 13, 0 -8, -12 0 z M 5 5 " +
-                "l 12 0, 0 -8, 18 13, -18 13, 0 -8, -12 0 z M -5 -15 " +
-                "l -12 0, 0 -8, -18 13, 18 13, 0 -8, 12 0 z M -5 19 " +
-                "l -12 0, 0 -8, -18 13, 18 13, 0 -8, 12 0 z " ,
-        roadm: "M-45 -20 l25 -25 h40 l25 25 v40 l-25 25 h-40 l-25 -25 z " +
-                "M 3 -29 l 12 0, 0 -8, 18 13, -18 13, 0 -8, -12 0 z M 3 5 " +
-                "l 12 0, 0 -8, 18 13, -18 13, 0 -8, -12 0 z M -3 -15 " +
-                "l -12 0, 0 -8, -18 13, 18 13, 0 -8, 12 0 z M -3 19 " +
-                "l -12 0, 0 -8, -18 13, 18 13, 0 -8, 12 0 z ",
         node: "M-40 45 a5 5 0 0 1 -5 -5 v-65 a5 5 0 0 1 5 -5 h80 " +
-                "a5 5 0 0 1 5 5 v65 a5 5 0 0 1 -5 5 z M-41 -32.5 l11 -11  " +
-                "a10 3 0 0 1 10 -2 h40 a10 3 0 0 1 10 2 l11 11 z M-39 -20 " +
-                "a5 5 0 0 1 10 0 a5 5 0 0 1 -10 0 z ",
+            "a5 5 0 0 1 5 5 v65 a5 5 0 0 1 -5 5 z M-41 -32.5 l11 -11  " +
+            "a10 3 0 0 1 10 -2 h40 a10 3 0 0 1 10 2 l11 11 z M-39 -20 " +
+            "a5 5 0 0 1 10 0 a5 5 0 0 1 -10 0 z",
+
+        switch: "M-45 -35 a10 10 0 0 1 10 -10 h70 a 10 10 0 0 1 10 10 " +
+            "v70 a 10 10 0 0 1 -10 10 h -70 a 10 10 0 0 1 -10 -10 z " +
+            "M 5 -29 l 12 0, 0 -8, 18 13, -18 13, 0 -8, -12 0 z M 5 5 " +
+            "l 12 0, 0 -8, 18 13, -18 13, 0 -8, -12 0 z M -5 -15 " +
+            "l -12 0, 0 -8, -18 13, 18 13, 0 -8, 12 0 z M -5 19 " +
+            "l -12 0, 0 -8, -18 13, 18 13, 0 -8, 12 0 z",
+
+        roadm: "M-45 -20 l25 -25 h40 l25 25 v40 l-25 25 h-40 l-25 -25 z " +
+            "M 3 -29 l 12 0, 0 -8, 18 13, -18 13, 0 -8, -12 0 z M 3 5 " +
+            "l 12 0, 0 -8, 18 13, -18 13, 0 -8, -12 0 z M -3 -15 " +
+            "l -12 0, 0 -8, -18 13, 18 13, 0 -8, 12 0 z M -3 19 " +
+            "l -12 0, 0 -8, -18 13, 18 13, 0 -8, 12 0 z",
+
         endstation: "M-45 -40 a5 5 0 0 1 5 -5 h65 a5 5 0 0 1 5 5 v80 " +
-                "a5 5 0 0 1 -5 5 h-65 a5 5 0 0 1 -5 -5 z M32.5 -41 l11 11  " +
-                "a3 10 0 0 1 2 10 v40 a3 10 0 0 1 -2 10 l-11 11 z M-38 -36 " +
-                "a2 2 0 0 1 2 -2 h56 a2 2 0 0 1 2 2 v26 a2 2 0 0 1 -2 2 h-56 " +
-                "a2 2 0 0 1 -2 -2 z M-35 -35 h54 v10 h-54 z M-35 -22 h54 v10 " +
-                "h-54 z M-13 15 a5 5 0 0 1 10 0 a5 5 0 0 1 -10 0 z "
+            "a5 5 0 0 1 -5 5 h-65 a5 5 0 0 1 -5 -5 z M32.5 -41 l11 11  " +
+            "a3 10 0 0 1 2 10 v40 a3 10 0 0 1 -2 10 l-11 11 z M-38 -36 " +
+            "a2 2 0 0 1 2 -2 h56 a2 2 0 0 1 2 2 v26 a2 2 0 0 1 -2 2 h-56 " +
+            "a2 2 0 0 1 -2 -2 z M-35 -35 h54 v10 h-54 z M-35 -22 h54 v10 " +
+            "h-54 z M-13 15 a5 5 0 0 1 10 0 a5 5 0 0 1 -10 0 z",
+
+        router: "M-45 0 A45 45 0 0 1 45 0 A45 45 0 0 1 -45 0 M -35 -5 " +
+            "l 12 0, 0 -8, 18 13, -18 13, 0 -8, -12 0 z M 35 -5 " +
+            "l -12 0, 0 -8, -18 13, 18 13, 0 -8, 12 0 z M -5 -8 " +
+            "l 0 -12, -8 0, 13 -18, 13 18, -8 0, 0 12 z M -5 8 " +
+            "l 0 12, -8 0, 13 18, 13 -18, -8 0, 0 -12 z",
+
+        bgpSpeaker: "M-45 -15 a45 35 0 0 1 90 0 Q45 22 0 45 Q-45 22 -45 -15 z " +
+            "M -5 -26 l 12 0, 0 -8, 18 13, -18 13, 0 -8, -12 0 z M 5 2" +
+            " l -12 0, 0 -8, -18 13, 18 13, 0 -8, 12 0 z"
     };
 
     var glyphParams = {
         viewBox: '-55 -55 110 110'
     };
 
-    function defGlyphs(defs) {
-        d3.map(glyphData).keys().forEach(function (key) {
-                defs.append('symbol')
-                    .attr({
-                        id: key,
-                        viewBox: glyphParams.viewBox
-                    })
-                    .append('path').attr('d', glyphData[key]);
+
+    var badgeData = {
+        uiAttached: "M-3-2.5 a.5 .5 0 0 1 .5-.5 h5 a.5 .5 0 0 1 .5 .5 v3 " +
+        "a.5 .5 0 0 1-.5 .5 h-5 a.5 .5 0 0 1-.5-.5 z M-2.5-2.2 " +
+        "a.3 .3 0 0 1 .3-.3 h4.4 a.3 .3 0 0 1 .3 .3 v2.4 a.3 .3 0 0 1-.3 .3 " +
+        "h-4.4 a.3 .3 0 0 1-.3-.3 z M-3 1.55 h6 l1 1.45 h-8 z"
+    };
+
+    var badgeParams = {
+        viewBox: '-5 -5 10 10'
+    };
+
+    function defStuff(defs, params, data) {
+        d3.map(data).keys().forEach(function (key) {
+            defs.append('symbol')
+                .attr({
+                    id: key,
+                    viewBox: params.viewBox
+                })
+                .append('path').attr('d', data[key]);
         });
     }
 
     // === register the functions as a library
     onos.ui.addLib('glyphs', {
         defBird: defBird,
-        defBullhorn: defBullhorn,
-        defGlyphs: defGlyphs
+        defGlyphs: function (defs) { defStuff(defs, glyphParams, glyphData); },
+        defBadges: function (defs) { defStuff(defs, badgeParams, badgeData); }
     });
 
 }(ONOS));
diff --git a/web/gui/src/main/webapp/json/ev/_capture/rx/addDevice_ex3.json b/web/gui/src/main/webapp/json/ev/_capture/rx/addDevice_ex3.json
new file mode 100644
index 0000000..e02f712
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/_capture/rx/addDevice_ex3.json
@@ -0,0 +1,24 @@
+{
+  "event": "addDevice",
+  "payload": {
+    "id": "of:000000000000000a",
+    "type": "switch",
+    "online": true,
+    "master": "local",
+    "labels": [
+      "",
+      "NWOR",
+      "of:000000000000000a"
+    ],
+    "props": {
+      "latitude": "29.951475",
+      "name": "NWOR",
+      "longitude": "-90.078434"
+    },
+    "location": {
+      "type": "latlng",
+      "lat": 29.951475,
+      "lng": -90.078434
+    }
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/_capture/rx/addHost_ex2.json b/web/gui/src/main/webapp/json/ev/_capture/rx/addHost_ex2.json
new file mode 100644
index 0000000..d47265b
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/_capture/rx/addHost_ex2.json
@@ -0,0 +1,27 @@
+{
+  "event": "addHost",
+  "payload": {
+    "id": "00:00:00:00:00:01/-1",
+    "type": "endstation",
+    "ingress": "00:00:00:00:00:01/-1/0-of:0000000000000001/1",
+    "egress": "of:0000000000000001/1-00:00:00:00:00:01/-1/0",
+    "cp": {
+      "device": "of:0000000000000001",
+      "port": 1
+    },
+    "labels": [
+      "10.0.0.1",
+      "00:00:00:00:00:01"
+    ],
+    "props": {
+      "name": "CMBR",
+      "latitude": "44.37373",
+      "longitude": "-71.109734"
+    },
+    "location": {
+      "type": "latlng",
+      "lat": 44.37373,
+      "lng": -71.109734
+    }
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/_capture/rx/addInstance_ex1.json b/web/gui/src/main/webapp/json/ev/_capture/rx/addInstance_ex1.json
index 5077182..0579c1d 100644
--- a/web/gui/src/main/webapp/json/ev/_capture/rx/addInstance_ex1.json
+++ b/web/gui/src/main/webapp/json/ev/_capture/rx/addInstance_ex1.json
@@ -1,7 +1,14 @@
 {
   "event": "addInstance",
   "payload": {
-    "id": "onos-1",
-    "online": "true"
+    "id": "local",
+    "ip": "127.0.0.1",
+    "online": true,
+    "uiAttached": true,
+    "switches": 25,
+    "labels": [
+      "local",
+      "127.0.0.1"
+    ]
   }
 }
diff --git a/web/gui/src/main/webapp/json/ev/_capture/rx/showSummary_ex1.json b/web/gui/src/main/webapp/json/ev/_capture/rx/showSummary_ex1.json
new file mode 100644
index 0000000..4d5bd30
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/_capture/rx/showSummary_ex1.json
@@ -0,0 +1,30 @@
+{
+  "event": "showSummary",
+  "sid": 1,
+  "payload": {
+    "id": "ONOS Summary",
+    "type": "node",
+    "propOrder": [
+      "Devices",
+      "Links",
+      "Hosts",
+      "Topology SCCs",
+      "Paths",
+      "-",
+      "Intents",
+      "Flows",
+      "Version"
+    ],
+    "props": {
+      "Devices": "25",
+      "Links": "112",
+      "Hosts": "25",
+      "Topology SCCs": "1",
+      "Paths": "1,272",
+      "-": "",
+      "Intents": "0",
+      "Flows": "0",
+      "Version": "1.0.0*"
+    }
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/_capture/tx/cancelSummary_ex1.json b/web/gui/src/main/webapp/json/ev/_capture/tx/cancelSummary_ex1.json
new file mode 100644
index 0000000..6418471
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/_capture/tx/cancelSummary_ex1.json
@@ -0,0 +1,5 @@
+{
+  "event": "cancelSummary",
+  "sid": 2,
+  "payload": {}
+}
diff --git a/web/gui/src/main/webapp/json/ev/_capture/tx/requestSummary_ex1.json b/web/gui/src/main/webapp/json/ev/_capture/tx/requestSummary_ex1.json
new file mode 100644
index 0000000..448d027
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/_capture/tx/requestSummary_ex1.json
@@ -0,0 +1,5 @@
+{
+  "event": "requestSummary",
+  "sid": 1,
+  "payload": {}
+}
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_1_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_1_onos.json
index 06d8680..0fac1a1 100644
--- a/web/gui/src/main/webapp/json/ev/colors/ev_1_onos.json
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_1_onos.json
@@ -2,10 +2,13 @@
   "event": "addInstance",
   "payload": {
     "id": "192.168.56.101",
+    "ip": "192.168.56.101",
     "online": true,
+    "uiAttached": true,
+    "switches": 4,
     "labels": [
       "192.168.56.101",
-      "127.0.0.1"
+      "192.168.56.101"
     ]
   }
 }
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_2_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_2_onos.json
index 644fd55..bbc587a 100644
--- a/web/gui/src/main/webapp/json/ev/colors/ev_2_onos.json
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_2_onos.json
@@ -2,11 +2,13 @@
   "event": "addInstance",
   "payload": {
     "id": "onos-2",
-    "uiAttached": true,
-    "online": false,
+    "ip": "192.168.0.2",
+    "online": true,
+    "uiAttached": false,
+    "switches": 3,
     "labels": [
       "onos-2",
-      "127.0.0.1"
+      "192.168.0.2"
     ]
   }
 }
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_3_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_3_onos.json
index 4e24bbd6..f7e1f49 100644
--- a/web/gui/src/main/webapp/json/ev/colors/ev_3_onos.json
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_3_onos.json
@@ -2,10 +2,13 @@
   "event": "addInstance",
   "payload": {
     "id": "onos-leader",
+    "ip": "192.168.0.5",
     "online": false,
+    "uiAttached": false,
+    "switches": 0,
     "labels": [
       "onos-leader",
-      "127.0.0.1"
+      "192.168.0.5"
     ]
   }
 }
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_4_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_4_onos.json
index d7768e2..3eeb99a 100644
--- a/web/gui/src/main/webapp/json/ev/colors/ev_4_onos.json
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_4_onos.json
@@ -2,10 +2,13 @@
   "event": "addInstance",
   "payload": {
     "id": "onos-master",
+    "ip": "192.168.0.7",
     "online": false,
+    "uiAttached": false,
+    "switches": 300,
     "labels": [
       "onos-master",
-      "127.0.0.1"
+      "192.168.0.7"
     ]
   }
 }
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_5_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_5_onos.json
index e74ba19..a41e1d7 100644
--- a/web/gui/src/main/webapp/json/ev/colors/ev_5_onos.json
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_5_onos.json
@@ -2,10 +2,13 @@
   "event": "addInstance",
   "payload": {
     "id": "onos-slave",
+    "ip": "192.168.0.11",
     "online": false,
+    "uiAttached": false,
+    "switches": 17,
     "labels": [
       "onos-slave",
-      "127.0.0.1"
+      "192.168.0.11"
     ]
   }
 }
diff --git a/web/gui/src/main/webapp/onos2.js b/web/gui/src/main/webapp/onos2.js
index a9cb1b0..2405988 100644
--- a/web/gui/src/main/webapp/onos2.js
+++ b/web/gui/src/main/webapp/onos2.js
@@ -821,7 +821,7 @@
                         if (w === undefined) {
                             return widthVal();
                         }
-                        el.style('width', w);
+                        el.style('width', w + 'px');
                     }
                 };
                 fpanels[id] = fp;
diff --git a/web/gui/src/main/webapp/topo2.css b/web/gui/src/main/webapp/topo2.css
index d982ee2..50b3493 100644
--- a/web/gui/src/main/webapp/topo2.css
+++ b/web/gui/src/main/webapp/topo2.css
@@ -32,7 +32,6 @@
 
 /* TODO: move glyphs into framework */
 
-#topo-oibox svg .glyphIcon,
 #topo svg .glyphIcon {
     fill: black;
     stroke: none;
@@ -43,6 +42,7 @@
     stroke: none;
 }
 
+
 /* NODES */
 
 #topo svg .node {
@@ -313,10 +313,59 @@
 /* ONOS instance stuff */
 
 #topo-oibox {
-    width: 120px;
+    height: 100px;
 }
 
-#topo-oibox .onosInst {
+#topo-oibox div.onosInst {
+    display: inline-block;
+    width: 120px;
+    height: 100px;
+}
+
+#topo-oibox svg rect {
+    fill: #ccc;
+    stroke: #aaa;
+    stroke-width: 3.5;
+}
+#topo-oibox .online svg rect {
+    opacity: 1;
+    fill: #9cf;
+    stroke: #357;
+}
+
+#topo-oibox svg .glyphIcon {
+    fill: #888;
+    fill-rule: evenodd;
+}
+#topo-oibox .online svg .glyphIcon {
+    fill: #000;
+}
+
+#topo-oibox svg .badgeIcon {
+    fill: #aaa;
+    fill-rule: evenodd;
+}
+
+#topo-oibox .online svg .badgeIcon {
+    fill: #fff;
+}
+
+
+#topo-oibox .onosInst.mastership {
+    opacity: 0.3;
+}
+#topo-oibox .onosInst.mastership.affinity {
+    opacity: 1.0;
+}
+#topo-oibox .onosInst.mastership.affinity svg rect {
+    filter: url(#blue-glow);
+}
+
+/* ------------------------------------------------------ */
+/* ------------------------------------------------------ */
+/* ------------------------------------------------------ */
+
+#topo-oibox .onosInst_OLD {
     position: relative;
     width: 88%;
     left: 4%;
@@ -333,31 +382,24 @@
     border: 4px solid #aaa;
 }
 
-#topo-oibox .onosInst.online {
-    /* theme-related */
-    color: #113;
-    background-color: #9cf;
-    border: 4px solid #357;
-}
-
-#topo-oibox .onosInst .onosTitle {
+#topo-oibox .onosInst_OLD .onosTitle {
     text-align: center;
     font-size: 10pt;
     margin-top: 6px;
     color: #888;
 }
 
-#topo-oibox .onosInst.online .onosTitle {
+#topo-oibox .onosInst_OLD.online .onosTitle {
     color: black;
 }
 
-#topo-oibox .onosInst svg .glyphIcon {
+#topo-oibox .onosInst_OLD svg .glyphIcon {
     opacity: 0.5;
     fill: black;
     stroke: none;
     fill-rule: evenodd;
 }
-#topo-oibox .onosInst.online svg .glyphIcon {
+#topo-oibox .onosInst_OLD.online svg .glyphIcon {
     opacity: 1;
     fill: black;
     stroke: none;
@@ -365,12 +407,12 @@
 }
 
 
-#topo-oibox .onosInst.online img {
+#topo-oibox .onosInst_OLD.online img {
     opacity: 1.0;
     padding: 3px;
 }
 
-#topo-oibox .onosInst img.ui {
+#topo-oibox .onosInst_OLD img.ui {
     opacity: 1;
     position: absolute;
     top: 3px;
@@ -379,14 +421,6 @@
     height: 20px;
 }
 
-#topo-oibox .onosInst.mastership {
-    opacity: 0.3;
-}
-#topo-oibox .onosInst.mastership.affinity {
-    opacity: 1.0;
-    box-shadow: 0 2px 8px #33e;
-}
-
 
 #topo svg .suppressed {
     opacity: 0.2;
diff --git a/web/gui/src/main/webapp/topo2.js b/web/gui/src/main/webapp/topo2.js
index 44b90f0..d58de15 100644
--- a/web/gui/src/main/webapp/topo2.js
+++ b/web/gui/src/main/webapp/topo2.js
@@ -946,64 +946,120 @@
         return s.replace(/px$/,'');
     }
 
-    function appendGlyph(svg, ox, oy, dim, iid) {
-        svg.append('use').attr({
-            class: 'glyphIcon',
+    function appendUse(svg, ox, oy, dim, iid, cls) {
+        var use = svg.append('use').attr({
             transform: translate(ox,oy),
             'xlink:href': iid,
             width: dim,
             height: dim
         });
+        if (cls) {
+            use.classed(cls, true);
+        }
+        return use;
+    }
+
+    function appendGlyph(svg, ox, oy, dim, iid, cls) {
+        appendUse(svg, ox, oy, dim, iid, cls).classed('glyphIcon', true);
+    }
+
+    function appendBadge(svg, ox, oy, dim, iid, cls) {
+        appendUse(svg, ox, oy, dim, iid,cls ).classed('badgeIcon', true);
+    }
+
+    function attachUiBadge(svg) {
+        appendBadge(svg, 12, 50, 30, '#uiAttached', 'uiBadge');
     }
 
     // ==============================
     // onos instance panel functions
+    var instW = 120;
+
+    function viewBox(w, h) {
+        return '0 0 ' + w + ' ' + h;
+    }
 
     function updateInstances() {
         var onoses = oiBox.el.selectAll('.onosInst')
-            .data(onosOrder, function (d) { return d.id; });
+                .data(onosOrder, function (d) { return d.id; }),
+            boxW = instW * onosOrder.length;
 
-        // operate on existing onoses if necessary
-        onoses.classed('online', function (d) { return d.online; });
+        // adjust the width of the panel based on number of instances...
+        oiBox.width(boxW);
 
+        // operate on existing onos instances if necessary
+        onoses.each(function (d) {
+            var el = d3.select(this),
+                svg = el.select('svg');
+
+            // update online state
+            el.classed('online', d.online);
+
+            // update ui-attached state
+            svg.select('use.uiBadge').remove();
+            if (d.uiAttached) {
+                attachUiBadge(svg);
+            }
+
+            // TODO: update title and property values
+        });
+
+
+        // operate on new onos instances
         var entering = onoses.enter()
             .append('div')
             .attr('class', 'onosInst')
             .classed('online', function (d) { return d.online; })
             .on('click', clickInst);
 
-        entering.each(function (d, i) {
+        entering.each(function (d) {
             var el = d3.select(this),
-                img;
-            var css = window.getComputedStyle(this),
+                css = window.getComputedStyle(this),
                 w = stripPx(css.width),
-                h = stripPx(css.height) / 2;
+                h = stripPx(css.height);
 
             var svg = el.append('svg').attr({
                 width: w,
-                height: h
+                height: h,
+                viewBox: viewBox(w, h)
             });
-            var dim = 30;
-            appendGlyph(svg, 2, 2, 30, '#node');
-            svg.append('use')
+
+            svg.append('rect')
                 .attr({
-                    class: 'birdBadge',
-                    transform: translate(8,10),
-                    'xlink:href': '#bird',
-                    width: 18,
-                    height: 18,
-                    fill: '#fff'
+                    x: 8,
+                    y: 8,
+                    width: 104,
+                    height: 84,
+                    rx: 12
                 });
 
-            $('<div>').attr('class', 'onosTitle').text(d.id).appendTo(el);
+
+            appendGlyph(svg, 9, 9, 36, '#node');
+            appendBadge(svg, 17, 19, 21, '#bird');
+
+            if (d.uiAttached) {
+                attachUiBadge(svg);
+            }
+
+            //svg.append('use')
+            //    .attr({
+            //        class: 'birdBadge',
+            //        transform: translate(8,10),
+            //        'xlink:href': '#bird',
+            //        width: 18,
+            //        height: 18,
+            //        fill: '#fff'
+            //    });
+            //
+            //$('<div>').attr('class', 'onosTitle').text(d.id).appendTo(el);
 
             // is the UI attached to this instance?
             // TODO: need uiAttached boolean in instance data
             // TODO: use SVG glyph, not png..
             //if (d.uiAttached) {
-            if (i === 0) {
-                $('<img src="img/ui.png">').attr('class','ui').appendTo(el);
-            }
+            //if (i === 0) {
+            //    $('<img src="img/ui.png">').attr('class','ui').appendTo(el);
+            //}
         });
 
         // operate on existing + new onoses here
@@ -2194,8 +2250,8 @@
     function loadGlyphs(svg) {
         var defs = svg.append('defs');
         gly.defBird(defs);
-        gly.defBullhorn(defs);
         gly.defGlyphs(defs);
+        gly.defBadges(defs);
     }
 
     // ==============================
@@ -2468,5 +2524,6 @@
     summaryPane = onos.ui.addFloatingPanel('topo-summary');
     detailPane = onos.ui.addFloatingPanel('topo-detail');
     oiBox = onos.ui.addFloatingPanel('topo-oibox', 'TL');
+    oiBox.width(20);
 
 }(ONOS));