Keep track of pan and zoom of layouts in metaUI data (no longer in user preferences).

Change-Id: I4a2c6941d5dd4586b732278c583974e85d9a9321
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 a50401b..e133775 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
@@ -55,7 +55,6 @@
 import org.onosproject.ui.model.topo.UiRegion;
 import org.onosproject.ui.model.topo.UiSynthLink;
 import org.onosproject.ui.model.topo.UiTopoLayout;
-import org.onosproject.ui.model.topo.UiTopoLayoutId;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -87,6 +86,7 @@
 
     private static final String CONTEXT_KEY_DELIM = "_";
     private static final String NO_CONTEXT = "";
+    private static final String ZOOM_KEY = "layoutZoom";
 
     private static final String REGION = "region";
     private static final String DEVICE = "device";
@@ -98,12 +98,6 @@
 
     private static final String GEO = "geo";
     private static final String GRID = "grid";
-    private static final String PKEY_TOPO_ZOOM = "topo2_zoom";
-    private static final String ZOOM_SCALE = "zoomScale";
-    private static final String ZOOM_PAN_X = "zoomPanX";
-    private static final String ZOOM_PAN_Y = "zoomPanY";
-    private static final String DEFAULT_SCALE = "1.0";
-    private static final String DEFAULT_PAN = "0.0";
 
     private final Logger log = LoggerFactory.getLogger(getClass());
 
@@ -216,20 +210,21 @@
      *
      * @param layout the layout to transform
      * @param crumbs list of layouts in bread-crumb order
+     * @param rid    current region id
      * @return a JSON representation of the data
      */
-    ObjectNode layout(UiTopoLayout layout, List<UiTopoLayout> crumbs) {
+    ObjectNode layout(UiTopoLayout layout, List<UiTopoLayout> crumbs, String rid) {
         ObjectNode result = objectNode()
                 .put("id", layout.id().toString())
                 .put("parent", nullIsEmpty(layout.parent()))
                 .put("region", nullIsEmpty(layout.regionId()))
                 .put("regionName", UiRegion.safeName(layout.region()));
         addCrumbs(result, crumbs);
-        addBgRef(result, layout);
+        addBgRef(result, layout, rid);
         return result;
     }
 
-    private void addBgRef(ObjectNode result, UiTopoLayout layout) {
+    private void addBgRef(ObjectNode result, UiTopoLayout layout, String rid) {
         String mapId = layout.geomap();
         String sprId = layout.sprites();
 
@@ -239,51 +234,31 @@
         } else if (sprId != null) {
             result.put("bgType", GRID).put("bgId", sprId);
         }
-        addZoomPan(result, layout.id());
+
+        attachZoomData(result, layout, rid);
     }
 
-    private ObjectNode initialZoomForLayout(ObjectNode zoomPrefs, String id) {
-        ObjectNode zoomForLayout = defaultZoomForLayout();
-        zoomPrefs.set(id, zoomForLayout);
-        prefService.setPreference(userName, PKEY_TOPO_ZOOM, zoomPrefs);
-        return zoomPrefs;
-    }
+    private void attachZoomData(ObjectNode result, UiTopoLayout layout, String rid) {
 
-    private ObjectNode defaultZoomForLayout() {
-        return objectNode()
-            .put(ZOOM_SCALE, DEFAULT_SCALE)
-            .put(ZOOM_PAN_X, DEFAULT_PAN)
-            .put(ZOOM_PAN_Y, DEFAULT_PAN);
-    }
+        ObjectNode zoomData = objectNode();
 
-    private void addZoomPan(ObjectNode result, UiTopoLayoutId layoutId) {
-        // need to look up topo_zoom settings from preferences service.
+        // first, set configured scale and offset
+        addCfgZoomData(zoomData, layout);
 
-        // NOTE:
-        // UiPreferencesService API only allows us to retrieve ALL prefs for
-        // the given user. It would be better if we could call something like:
-        //
-        //   ObjectNode value = prefService.getPreference(userName, prefKey);
-        //
-        // to get back a single value.
-
-        Map<String, ObjectNode> userPrefs = prefService.getPreferences(userName);
-        ObjectNode zoomPrefs = userPrefs.get(PKEY_TOPO_ZOOM);
-
-        if (zoomPrefs == null) {
-            zoomPrefs = initialZoomForLayout(objectNode(), layoutId.id());
+        // next, retrieve user-set zoom data, if we have it
+        ObjectNode userZoom = metaUi.get(contextKey(rid, ZOOM_KEY));
+        if (userZoom != null) {
+            zoomData.set("usr", userZoom);
         }
+        result.set("bgZoom", zoomData);
+    }
 
-        ObjectNode zoomData = (ObjectNode) zoomPrefs.get(layoutId.id());
-
-        if (zoomData == null) {
-            zoomPrefs = initialZoomForLayout(zoomPrefs, layoutId.id());
-            zoomData = (ObjectNode) zoomPrefs.get(layoutId.id());
-        }
-
-        result.put("bgZoomScale", zoomData.get(ZOOM_SCALE).asText());
-        result.put("bgZoomPanX", zoomData.get(ZOOM_PAN_X).asText());
-        result.put("bgZoomPanY", zoomData.get(ZOOM_PAN_Y).asText());
+    private void addCfgZoomData(ObjectNode data, UiTopoLayout layout) {
+        ObjectNode zoom = objectNode();
+        zoom.put("scale", layout.scale());
+        zoom.put("offsetX", layout.offsetX());
+        zoom.put("offsetY", layout.offsetY());
+        data.set("cfg", zoom);
     }
 
     private void addMapParameters(ObjectNode result, String mapId) {
@@ -623,7 +598,7 @@
      * being displayed in.
      *
      * @param ridStr region-id string
-     * @param nodes the nodes
+     * @param nodes  the nodes
      * @return a JSON representation of the nodes
      */
     public ArrayNode closedNodes(String ridStr, Set<UiNode> nodes) {
@@ -640,51 +615,6 @@
         return array;
     }
 
-    // TODO: These methods do not seem to be used; consider removing them.
-    /*
-     * Returns a JSON array representation of a list of regions. Note that the
-     * information about each region is limited to what needs to be used to
-     * show the regions as nodes on the view.
-     *
-     * @param regions the regions
-     * @return a JSON representation of the minimal region information
-     */
-//    public ArrayNode closedRegions(Set<UiRegion> regions) {
-//        ArrayNode array = arrayNode();
-//        for (UiRegion r : regions) {
-//            array.add(jsonClosedRegion(r));
-//        }
-//        return array;
-//    }
-
-    /*
-     * Returns a JSON array representation of a list of devices.
-     *
-     * @param devices the devices
-     * @return a JSON representation of the devices
-     */
-//    public ArrayNode devices(Set<UiDevice> devices) {
-//        ArrayNode array = arrayNode();
-//        for (UiDevice device : devices) {
-//            array.add(json(device));
-//        }
-//        return array;
-//    }
-
-    /*
-     * Returns a JSON array representation of a list of hosts.
-     *
-     * @param hosts the hosts
-     * @return a JSON representation of the hosts
-     */
-//    public ArrayNode hosts(Set<UiHost> hosts) {
-//        ArrayNode array = arrayNode();
-//        for (UiHost host : hosts) {
-//            array.add(json(host));
-//        }
-//        return array;
-//    }
-
     // package-private for unit testing
     List<Set<UiNode>> splitByLayer(List<String> layerTags,
                                    Set<? extends UiNode> nodes) {
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2ViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2ViewMessageHandler.java
index 801a970d..e5946f9 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2ViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2ViewMessageHandler.java
@@ -95,14 +95,14 @@
 
     // ==================================================================
 
-    private String safeId(Region r) {
-        return r == null ? "(root)" : r.id().toString();
+    private String currentRegionId() {
+        Region current = topoSession.currentLayout().region();
+        return current == null ? "(root)" : current.id().toString();
     }
 
-
     private ObjectNode mkLayoutMessage(UiTopoLayout currentLayout) {
         List<UiTopoLayout> crumbs = topoSession.breadCrumbs();
-        return t2json.layout(currentLayout, crumbs);
+        return t2json.layout(currentLayout, crumbs, currentRegionId());
     }
 
     private ObjectNode mkRegionMessage(UiTopoLayout currentLayout) {
@@ -114,9 +114,8 @@
 
     private ObjectNode mkPeersMessage(UiTopoLayout currentLayout) {
         Set<UiNode> peers = topoSession.getPeerNodes(currentLayout);
-        String ridStr = safeId(topoSession.currentLayout().region());
         ObjectNode peersPayload = objectNode();
-        peersPayload.set("peers", t2json.closedNodes(ridStr, peers));
+        peersPayload.set("peers", t2json.closedNodes(currentRegionId(), peers));
         return peersPayload;
     }
 
@@ -212,8 +211,7 @@
         public void process(ObjectNode payload) {
             // NOTE: metadata for a node is stored within the context of the
             //       current region.
-            String ridStr = safeId(topoSession.currentLayout().region());
-            t2json.updateMeta(ridStr, payload);
+            t2json.updateMeta(currentRegionId(), payload);
         }
     }
 
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2.js b/web/gui/src/main/webapp/app/view/topo2/topo2.js
index 77d0e0c3..775228c 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2.js
@@ -24,7 +24,7 @@
     'use strict';
 
     // references to injected services
-    var $scope, $log, fs, mast, ks,
+    var $scope, $log, fs, mast, ks, wss,
         gs, sus, ps, t2es, t2fs, t2is, t2bcs, t2kcs, t2ms, t2mcs, t2zs;
 
     // DOM elements
@@ -65,15 +65,21 @@
     function zoomCallback() {
         var sc = zoomer.scale(),
             tr = zoomer.translate(),
-            sparse = {};
+            metaUi = isNaN(sc) ? {
+                useCfg: 1
+            } : {
+                scale: sc,
+                offsetX: tr[0],
+                offsetY: tr[1]
+            };
 
-        sparse[currentLayoutId] =  {
-            zoomScale: sc,
-            zoomPanX: tr[0],
-            zoomPanY: tr[1]
-        };
+        // Note: Meta data stored in the context of the current layout,
+        //       automatically, by the server
 
-        ps.mergePrefs('topo2_zoom', sparse);
+        wss.sendEvent('updateMeta2', {
+            id: 'layoutZoom',
+            memento: metaUi
+        });
     }
 
     function setUpZoom() {
@@ -128,6 +134,7 @@
             fs = _fs_;
             mast = _mast_;
             ks = _ks_;
+            wss = _wss_;
             gs = _gs_;
             sus = _sus_;
             ps = _ps_;
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Background.js b/web/gui/src/main/webapp/app/view/topo2/topo2Background.js
index 8fa9822..29c6a93 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Background.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Background.js
@@ -25,6 +25,24 @@
 
     var instance;
 
+    function getZoom(z) {
+        var u = z.usr,
+            c = z.cfg;
+        return (u && !u.useCfg) ? u : c;
+    }
+
+    // returns the pan (offset) values as an array [x, y]
+    function zoomPan(z) {
+        var zoom = getZoom(z);
+        return [zoom.offsetX, zoom.offsetY];
+    }
+
+    // returns the scale value
+    function zoomScale(z) {
+        var zoom = getZoom(z);
+        return zoom.scale;
+    }
+
     angular.module('ovTopo2')
         .factory('Topo2BackgroundService', [
             '$log', 'Topo2ViewController', 'Topo2SpriteLayerService', 'Topo2MapService',
@@ -49,9 +67,10 @@
 
                         this.background = data;
                         this.bgType = data.bgType;
+                        this.zoomData = data.bgZoom;
 
                         var _this = this,
-                            pan = [this.background.bgZoomPanX, this.background.bgZoomPanY];
+                            pan = zoomPan(this.zoomData);
 
                         if (this.bgType === 'geo') {
 
@@ -59,16 +78,12 @@
                             t2sls.hide();
                             t2ms.show();
 
-                            t2ms.setUpMap(data.bgId, data.bgFilePath, data.bgZoomScale)
+                            t2ms.setUpMap(data.bgId, data.bgFilePath, zoomScale(data.bgZoom))
                             .then(function (proj) {
-                                // var z = ps.getPrefs('topo2_zoom', { tx: 0, ty: 0, sc: 1 });
-                                // zoomer.panZoom([z.tx, z.ty], z.sc);
-
                                 t2mcs.projection(proj);
-                                // $log.debug('** Zoom restored:', z);
                                 $log.debug('** We installed the projection:', proj);
                                 _this.region.loaded('bgRendered', true);
-                                t2zs.panAndZoom(pan, _this.background.bgZoomScale, 1000);
+                                t2zs.panAndZoom(pan, zoomScale(_this.zoomData), 1000);
                             });
                         } else if (this.bgType === 'grid') {
 
@@ -79,7 +94,7 @@
                             t2sls.loadLayout(data.bgId).then(function (spriteLayout) {
                                 _this.background.layout = spriteLayout;
                                 _this.region.loaded('bgRendered', true);
-                                t2zs.panAndZoom(pan, _this.background.bgZoomScale, 1000);
+                                t2zs.panAndZoom(pan, zoomScale(_this.zoomData), 1000);
                             });
                         } else {
                             // No background type - Tell the region the background is ready for placing nodes
@@ -98,7 +113,7 @@
                 });
 
 
-                return instance || new BackgroundView();;
+                return instance || new BackgroundView();
             }
         ]);
 })();
\ No newline at end of file