Adding a listener mechanism for updated preferences.

Theme updates are now propagated to all user sessions.

Change-Id: If0e3f417294ee503c1186710c614d813b7cbd88e
diff --git a/web/gui/src/main/webapp/app/fw/util/prefs.js b/web/gui/src/main/webapp/app/fw/util/prefs.js
index ad3dc04..eb3b8bb 100644
--- a/web/gui/src/main/webapp/app/fw/util/prefs.js
+++ b/web/gui/src/main/webapp/app/fw/util/prefs.js
@@ -24,7 +24,7 @@
     var $log, fs, wss;
 
     // internal state
-    var cache = {};
+    var cache = {}, listeners = [];
 
     // returns the preference by the specified name
     function getPrefs(name, defaults) {
@@ -56,7 +56,16 @@
     
     function updatePrefs(data) {
         $log.info('User properties updated');
-        cache[data.key] = data.value;
+        cache = data;
+        listeners.forEach(function (l) { l(); });
+    }
+
+    function addListener(listener) {
+        listeners.push(listener);
+    }
+
+    function removeListener(listener) {
+        listeners = listeners.filter(function(obj) { return obj === listener; });
     }
 
     angular.module('onosUtil')
@@ -75,7 +84,9 @@
             return {
                 getPrefs: getPrefs,
                 asNumbers: asNumbers,
-                setPrefs: setPrefs
+                setPrefs: setPrefs,
+                addListener: addListener,
+                removeListener: removeListener
             };
         }]);
 
diff --git a/web/gui/src/main/webapp/app/fw/util/theme.js b/web/gui/src/main/webapp/app/fw/util/theme.js
index 4441402..baa13c1 100644
--- a/web/gui/src/main/webapp/app/fw/util/theme.js
+++ b/web/gui/src/main/webapp/app/fw/util/theme.js
@@ -24,6 +24,7 @@
 
     var themes = ['light', 'dark'],
         themeStr = themes.join(' '),
+        currentTheme,
         thidx,
         listeners = {},
         nextListenerId = 1;
@@ -42,8 +43,7 @@
         if (force || idx > -1 && idx !== thidx) {
             thidx = idx;
             ps.setPrefs('theme', { idx: thidx });
-            updateBodyClass();
-            themeEvent('set');
+            applyTheme();
         }
     }
 
@@ -51,15 +51,24 @@
         var i = thidx + 1;
         thidx = (i===themes.length) ? 0 : i;
         ps.setPrefs('theme', { idx: thidx });
-        updateBodyClass();
-        themeEvent('toggle');
+        applyTheme('toggle');
         return getTheme();
     }
 
+    function applyTheme(evt) {
+        thidx = ps.getPrefs('theme', { idx: thidx }).idx;
+        if (currentTheme != thidx) {
+            $log.info('Applying theme:', thidx);
+            updateBodyClass();
+            themeEvent(evt || 'set');
+        }
+    }
+
     function updateBodyClass() {
         var body = d3.select('body');
         body.classed(themeStr, false);
         body.classed(getTheme(), true);
+        currentTheme = thidx;
     }
 
     function themeEvent(w) {
@@ -67,9 +76,8 @@
             m = 'Theme-Change-('+w+'): ' + t;
         $log.debug(m);
         angular.forEach(listeners, function(value) {
-            value.cb(
-                {
-                    event: 'themeChange',
+            value.cb({
+                event: 'themeChange',
                     value: t
                 }
             );
@@ -105,6 +113,8 @@
             fs = _fs_;
             ps = _ps_;
 
+            ps.addListener(applyTheme);
+
             return {
                 init: init,
                 theme: function (x) {