GUI -- [ONOS-89] - completed device mastership affinity coloring work.

Change-Id: I6d42c41cf30c042171550352ce05325b53560841
diff --git a/web/gui/src/main/webapp/d3Utils.css b/web/gui/src/main/webapp/d3Utils.css
new file mode 100644
index 0000000..778ce2c
--- /dev/null
+++ b/web/gui/src/main/webapp/d3Utils.css
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ D3 Utilities CSS file
+
+ @author Simon Hunt
+ */
+
+#d3u .light.norm.c1 {
+  color: #1f77b4;
+}
+
+#d3u .light.norm.c2 {
+  color: #2ca02c;
+}
+
+#d3u .light.norm.c3 {
+  color: #d62728;
+}
+
+#d3u .light.norm.c4 {
+  color: #9467bd;
+}
+
+#d3u .light.norm.c5 {
+  color: #e377c2;
+}
+
+#d3u .light.norm.c6 {
+  color: #bcbd22;
+}
+
+#d3u .light.norm.c7 {
+  color: #17becf;
+}
+
+
+
+#d3u .light.mute.c1 {
+  color: #aec7e8;
+}
+
+#d3u .light.mute.c2 {
+  color: #98df8a;
+}
+
+#d3u .light.mute.c3 {
+  color: #ff9896;
+}
+
+#d3u .light.mute.c4 {
+  color: #c5b0d5;
+}
+
+#d3u .light.mute.c5 {
+  color: #f7b6d2;
+}
+
+#d3u .light.mute.c6 {
+  color: #dbdb8d;
+}
+
+#d3u .light.mute.c7 {
+  color: #9edae5;
+}
+
+
+
+#d3u .dark.norm.c1 {
+  color: #1f77b4;
+}
+
+#d3u .dark.norm.c2 {
+  color: #2ca02c;
+}
+
+#d3u .dark.norm.c3 {
+  color: #d62728;
+}
+
+#d3u .dark.norm.c4 {
+  color: #9467bd;
+}
+
+#d3u .dark.norm.c5 {
+  color: #e377c2;
+}
+
+#d3u .dark.norm.c6 {
+  color: #bcbd22;
+}
+
+#d3u .dark.norm.c7 {
+  color: #17becf;
+}
+
+
+
+#d3u .dark.mute.c1 {
+  color: #aec7e8;
+}
+
+#d3u .dark.mute.c2 {
+  color: #639a56;
+}
+
+#d3u .dark.mute.c3 {
+  color: #ff9896;
+}
+
+#d3u .dark.mute.c4 {
+  color: #c5b0d5;
+}
+
+#d3u .dark.mute.c5 {
+  color: #f7b6d2;
+}
+
+#d3u .dark.mute.c6 {
+  color: #dbdb8d;
+}
+
+#d3u .dark.mute.c7 {
+  color: #9edae5;
+}
+
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_15_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_15_onos.json
new file mode 100644
index 0000000..eef2964
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_15_onos.json
@@ -0,0 +1,14 @@
+{
+  "event": "addInstance",
+  "payload": {
+    "id": "onos-leader",
+    "ip": "192.168.0.5",
+    "online": true,
+    "uiAttached": false,
+    "switches": 0,
+    "labels": [
+      "onos-leader",
+      "192.168.0.5"
+    ]
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_16_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_16_onos.json
new file mode 100644
index 0000000..1367251
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_16_onos.json
@@ -0,0 +1,14 @@
+{
+  "event": "addInstance",
+  "payload": {
+    "id": "onos-6",
+    "ip": "192.168.0.66",
+    "online": true,
+    "uiAttached": false,
+    "switches": 0,
+    "labels": [
+      "onos-6",
+      "192.168.0.66"
+    ]
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_17_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_17_onos.json
new file mode 100644
index 0000000..c080d56
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_17_onos.json
@@ -0,0 +1,14 @@
+{
+  "event": "addInstance",
+  "payload": {
+    "id": "onos-7",
+    "ip": "192.168.0.77",
+    "online": true,
+    "uiAttached": false,
+    "switches": 0,
+    "labels": [
+      "onos-7",
+      "192.168.0.77"
+    ]
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_18_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_18_onos.json
new file mode 100644
index 0000000..c195585
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_18_onos.json
@@ -0,0 +1,14 @@
+{
+  "event": "updateInstance",
+  "payload": {
+    "id": "onos-master",
+    "ip": "192.168.0.7",
+    "online": true,
+    "uiAttached": false,
+    "switches": 300,
+    "labels": [
+      "onos-master",
+      "192.168.0.7"
+    ]
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_19_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_19_onos.json
new file mode 100644
index 0000000..bd536da
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_19_onos.json
@@ -0,0 +1,18 @@
+{
+  "event": "addDevice",
+  "payload": {
+    "id": "of:0000ffffffff0002",
+    "type": "switch",
+    "online": false,
+    "master": "192.168.56.101",
+    "labels": [
+      "",
+      "sw-2",
+      "0000ffffffff0002"
+    ],
+    "metaUi": {
+      "x": 142,
+      "y": 503
+    }
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_20_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_20_onos.json
new file mode 100644
index 0000000..faf0a77
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_20_onos.json
@@ -0,0 +1,18 @@
+{
+  "event": "addDevice",
+  "payload": {
+    "id": "of:0000ffffffffff02",
+    "type": "roadm",
+    "online": false,
+    "master": "192.168.56.101",
+    "labels": [
+      "",
+      "opt-2",
+      "0000ffffffffff02"
+    ],
+    "metaUi": {
+      "x": 142,
+      "y": 603
+    }
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_21_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_21_onos.json
new file mode 100644
index 0000000..5d44197
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_21_onos.json
@@ -0,0 +1,18 @@
+{
+  "event": "addDevice",
+  "payload": {
+    "id": "of:0000ffffffff0006",
+    "type": "switch",
+    "online": false,
+    "master": "onos-master",
+    "labels": [
+      "",
+      "sw-6",
+      "0000ffffffff0006"
+    ],
+    "metaUi": {
+      "x": 382,
+      "y": 333
+    }
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_22_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_22_onos.json
new file mode 100644
index 0000000..02e3d6e
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_22_onos.json
@@ -0,0 +1,18 @@
+{
+  "event": "addDevice",
+  "payload": {
+    "id": "of:0000ffffffff000a",
+    "type": "switch",
+    "online": true,
+    "master": "onos-slave",
+    "labels": [
+      "",
+      "sw-A",
+      "0000ffffffff000a"
+    ],
+    "metaUi": {
+      "x": 195,
+      "y": 259
+    }
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_23_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_23_onos.json
new file mode 100644
index 0000000..547d6a0
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_23_onos.json
@@ -0,0 +1,18 @@
+{
+  "event": "addDevice",
+  "payload": {
+    "id": "of:0000ffffffff000b",
+    "type": "switch",
+    "online": false,
+    "master": "onos-slave",
+    "labels": [
+      "",
+      "sw-B",
+      "0000ffffffff000b"
+    ],
+    "metaUi": {
+      "x": 52,
+      "y": 262
+    }
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_24_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_24_onos.json
new file mode 100644
index 0000000..d7de3c1
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_24_onos.json
@@ -0,0 +1,18 @@
+{
+  "event": "addDevice",
+  "payload": {
+    "id": "of:0000ffffffff000c",
+    "type": "switch",
+    "online": true,
+    "master": "onos-leader",
+    "labels": [
+      "",
+      "sw-C",
+      "0000ffffffff000c"
+    ],
+    "metaUi": {
+      "x": 229,
+      "y": 354
+    }
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_25_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_25_onos.json
new file mode 100644
index 0000000..cade64c
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_25_onos.json
@@ -0,0 +1,18 @@
+{
+  "event": "addDevice",
+  "payload": {
+    "id": "of:0000ffffffff000d",
+    "type": "switch",
+    "online": false,
+    "master": "onos-leader",
+    "labels": [
+      "",
+      "sw-D",
+      "0000ffffffff000d"
+    ],
+    "metaUi": {
+      "x": 100,
+      "y": 357
+    }
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_26_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_26_onos.json
new file mode 100644
index 0000000..9f21a7c
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_26_onos.json
@@ -0,0 +1,18 @@
+{
+  "event": "addDevice",
+  "payload": {
+    "id": "of:0000ffffffff000e",
+    "type": "switch",
+    "online": true,
+    "master": "onos-6",
+    "labels": [
+      "",
+      "sw-E",
+      "0000ffffffff000e"
+    ],
+    "metaUi": {
+      "x": 757,
+      "y": 267
+    }
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_27_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_27_onos.json
new file mode 100644
index 0000000..9f9b70a
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_27_onos.json
@@ -0,0 +1,18 @@
+{
+  "event": "addDevice",
+  "payload": {
+    "id": "of:0000ffffffff000f",
+    "type": "switch",
+    "online": false,
+    "master": "onos-6",
+    "labels": [
+      "",
+      "sw-F",
+      "0000ffffffff000f"
+    ],
+    "metaUi": {
+      "x": 877,
+      "y": 267
+    }
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_28_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_28_onos.json
new file mode 100644
index 0000000..a60b43e
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_28_onos.json
@@ -0,0 +1,18 @@
+{
+  "event": "addDevice",
+  "payload": {
+    "id": "of:0000ffffffff0010",
+    "type": "switch",
+    "online": true,
+    "master": "onos-7",
+    "labels": [
+      "",
+      "sw-1-0",
+      "0000ffffffff0010"
+    ],
+    "metaUi": {
+      "x": 442,
+      "y": 508
+    }
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_29_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_29_onos.json
new file mode 100644
index 0000000..ae45cd2
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_29_onos.json
@@ -0,0 +1,18 @@
+{
+  "event": "addDevice",
+  "payload": {
+    "id": "of:0000ffffffff0011",
+    "type": "switch",
+    "online": false,
+    "master": "onos-7",
+    "labels": [
+      "",
+      "sw-1-1",
+      "0000ffffffff0011"
+    ],
+    "metaUi": {
+      "x": 576,
+      "y": 519
+    }
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_30_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_30_onos.json
new file mode 100644
index 0000000..327e264
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_30_onos.json
@@ -0,0 +1,14 @@
+{
+  "event": "updateInstance",
+  "payload": {
+    "id": "192.168.56.101",
+    "ip": "192.168.56.101",
+    "online": false,
+    "uiAttached": false,
+    "switches": 4,
+    "labels": [
+      "192.168.56.101",
+      "192.168.56.101"
+    ]
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_31_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_31_onos.json
new file mode 100644
index 0000000..dad87a2
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_31_onos.json
@@ -0,0 +1,14 @@
+{
+  "event": "updateInstance",
+  "payload": {
+    "id": "onos-2",
+    "ip": "192.168.0.2",
+    "online": false,
+    "uiAttached": false,
+    "switches": 3,
+    "labels": [
+      "onos-2",
+      "192.168.0.2"
+    ]
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_32_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_32_onos.json
new file mode 100644
index 0000000..6efdfc5
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_32_onos.json
@@ -0,0 +1,14 @@
+{
+  "event": "updateInstance",
+  "payload": {
+    "id": "onos-leader",
+    "ip": "192.168.0.5",
+    "online": false,
+    "uiAttached": false,
+    "switches": 0,
+    "labels": [
+      "onos-leader",
+      "192.168.0.5"
+    ]
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_33_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_33_onos.json
new file mode 100644
index 0000000..2751055
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_33_onos.json
@@ -0,0 +1,14 @@
+{
+  "event": "updateInstance",
+  "payload": {
+    "id": "onos-master",
+    "ip": "192.168.0.7",
+    "online": true,
+    "uiAttached": true,
+    "switches": 300,
+    "labels": [
+      "onos-master",
+      "192.168.0.7"
+    ]
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_34_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_34_onos.json
new file mode 100644
index 0000000..1cab6fd
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_34_onos.json
@@ -0,0 +1,14 @@
+{
+  "event": "updateInstance",
+  "payload": {
+    "id": "onos-slave",
+    "ip": "192.168.0.11",
+    "online": false,
+    "uiAttached": false,
+    "switches": 17,
+    "labels": [
+      "onos-slave",
+      "192.168.0.11"
+    ]
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_35_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_35_onos.json
new file mode 100644
index 0000000..142bd36
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_35_onos.json
@@ -0,0 +1,14 @@
+{
+  "event": "updateInstance",
+  "payload": {
+    "id": "onos-6",
+    "ip": "192.168.0.66",
+    "online": false,
+    "uiAttached": false,
+    "switches": 17,
+    "labels": [
+      "onos-6",
+      "192.168.0.66"
+    ]
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_36_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_36_onos.json
new file mode 100644
index 0000000..a4d8dfa
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_36_onos.json
@@ -0,0 +1,14 @@
+{
+  "event": "updateInstance",
+  "payload": {
+    "id": "onos-7",
+    "ip": "192.168.0.77",
+    "online": false,
+    "uiAttached": false,
+    "switches": 17,
+    "labels": [
+      "onos-7",
+      "192.168.0.77"
+    ]
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/colors/ev_8_onos.json b/web/gui/src/main/webapp/json/ev/colors/ev_8_onos.json
index c4a9e49..7967c0e 100644
--- a/web/gui/src/main/webapp/json/ev/colors/ev_8_onos.json
+++ b/web/gui/src/main/webapp/json/ev/colors/ev_8_onos.json
@@ -4,7 +4,7 @@
     "id": "of:0000ffffffff0007",
     "type": "switch",
     "online": true,
-    "master": "192.168.56.101",
+    "master": "onos-master",
     "labels": [
       "",
       "sw-7",
diff --git a/web/gui/src/main/webapp/json/ev/colors/scenario.json b/web/gui/src/main/webapp/json/ev/colors/scenario.json
index c978bb3..a457123 100644
--- a/web/gui/src/main/webapp/json/ev/colors/scenario.json
+++ b/web/gui/src/main/webapp/json/ev/colors/scenario.json
@@ -4,7 +4,7 @@
   ],
   "title": "Color-Tweaking Scenario",
   "params": {
-    "lastAuto": 12
+    "lastAuto": 29
   },
   "description": [
     "Press 'S' to load initial events."
diff --git a/web/gui/src/main/webapp/topo2.css b/web/gui/src/main/webapp/topo2.css
index ef0baf5..cfefba9 100644
--- a/web/gui/src/main/webapp/topo2.css
+++ b/web/gui/src/main/webapp/topo2.css
@@ -79,12 +79,12 @@
 }
 
 #topo svg .node.device.online {
-    fill: #17f;
+    fill: #6e7fa3;
 }
 
 /* note: device is offline without the 'online' class */
 #topo svg .node.device text {
-    fill: #aaa;
+    fill: #bbb;
     font: 10pt sans-serif;
 }
 
@@ -102,7 +102,7 @@
     fill: #f90;
 }
 #topo svg .node.device.online .glyphIcon rect {
-    fill: #8ab;
+    fill: #ccc;
 }
 #topo svg .node.device.online .glyphIcon use {
     fill: #000;
diff --git a/web/gui/src/main/webapp/topo2.js b/web/gui/src/main/webapp/topo2.js
index 475f02f..1acfd76 100644
--- a/web/gui/src/main/webapp/topo2.js
+++ b/web/gui/src/main/webapp/topo2.js
@@ -190,7 +190,8 @@
         oiBox,
         oiShowMaster = false,
         portLabelsOn = false,
-        cat7 = d3u.cat7();
+        cat7 = d3u.cat7(),
+        colorAffinity = false;
 
     var hoverModeAll = 1,
         hoverModeFlows = 2,
@@ -349,7 +350,7 @@
         } else if (detailPane.isVisible()) {
             deselectAll();
         } else if (oiBox.isVisible()) {
-            oiBox.hide();
+            hideInstances();
         } else if (summaryPane.isVisible()) {
             cancelSummary();
         }
@@ -864,20 +865,28 @@
         return true;
     }
 
-    function colorAffinity(on) {
-        // FIXME: need to code this portion up.
-    }
-
     function toggleInstances() {
         if (!oiBox.isVisible()) {
-            oiBox.show();
-            colorAffinity(true);
+            showInstances();
         } else {
-            oiBox.hide();
-            colorAffinity(false);
+            hideInstances();
         }
     }
 
+    function showInstances() {
+        oiBox.show();
+        colorAffinity = true;
+        updateDeviceColors();
+    }
+
+    function hideInstances() {
+        oiBox.hide();
+        colorAffinity = false;
+        cancelAffinity();
+        updateDeviceColors();
+    }
+
+
     function toggleSummary() {
         if (!summaryPane.isVisible()) {
             requestSummary();
@@ -1024,7 +1033,7 @@
             y: pad,
             width: dim.w - pad*2,
             height: dim.h - pad*2,
-            rx: 8
+            rx: 6
         };
     }
 
@@ -1691,7 +1700,6 @@
         });
 
         node.filter('.host').each(function (d) {
-            //var node = d3.select(this);
             var node = d.el;
             // TODO: appropriate update of host visuals
         });
@@ -1753,7 +1761,7 @@
         });
 
         // operate on both existing and new nodes, if necessary
-        //node .foo() .bar() ...
+        updateDeviceColors();
 
         // operate on exiting nodes:
         // Note that the node is removed after 2 seconds.
@@ -1791,6 +1799,62 @@
         network.force.resume();
     }
 
+    // note: these are the device icon colors without affinity
+    var deviceColor = {
+        sel: '#f90',
+        light: {
+            online: {
+                glyph: '#000',
+                rect: '#ddd',
+            },
+            offline: {
+                glyph: '#888',
+                rect: '#bbb'
+            }
+        },
+        dark: {
+            online: {
+                glyph: '#000',
+                rect: '#ddd'
+            },
+            offline: {
+                glyph: '#888',
+                rect: '#bbb'
+            }
+        }
+    };
+
+    function devBaseColor(d) {
+        var t = network.view.getTheme(),
+            o = d.online ? 'online' : 'offline';
+        return deviceColor[t][o];
+    }
+
+    function setDeviceColor(d) {
+        var o = d.online,
+            s = d.el.classed('selected'),
+            c = devBaseColor(d),
+            a = instColor(d.master, o),
+            g, r,
+            icon = d.el.select('g.deviceIcon');
+
+        if (s) {
+            g = c.glyph;
+            r = deviceColor.sel;
+        } else if (colorAffinity) {
+            g = o ? a : c.glyph;
+            r = o ? c.rect : a;
+        } else {
+            g = c.glyph;
+            r = c.rect;
+        }
+
+        icon.select('use')
+            .style('fill', g);
+        icon.select('rect')
+            .style('fill', r);
+    }
+
     function addDeviceIcon(node, box, noLabel, iid) {
         var cfg = config.icons.device,
             dx,
@@ -1915,7 +1979,7 @@
             webSock.ws.onopen = function() {
                 noWebSock(false);
                 requestSummary();
-                oiBox.show();
+                showInstances();
             };
 
             webSock.ws.onmessage = function(m) {
@@ -2053,6 +2117,7 @@
         selectOrder.push(obj.id);
 
         n.classed('selected', true);
+        updateDeviceColors(obj);
         updateDetailPane();
     }
 
@@ -2066,6 +2131,7 @@
             if (idx >= 0) {
                 selectOrder.splice(idx, 1);
             }
+            updateDeviceColors(obj.obj);
         }
     }
 
@@ -2074,12 +2140,18 @@
         node.classed('selected', false);
         selections = {};
         selectOrder = [];
+        updateDeviceColors();
         updateDetailPane();
     }
 
-    // update the state of the sumary pane
-    function updateSummaryPane() {
-
+    function updateDeviceColors(d) {
+        if (d) {
+            setDeviceColor(d);
+        } else {
+            node.filter('.device').each(function (d) {
+                setDeviceColor(d);
+            });
+        }
     }
 
     // update the state of the detail pane, based on current selections
@@ -2591,8 +2663,7 @@
 
     function theme(view, ctx, flags) {
         updateInstances();
-        // TODO: update other theme-affected elements
-
+        updateDeviceColors();
     }
 
     function birdTranslate(w, h) {