GUI -- Created sprite layout for Menlo Office Floor Plan.
- Still need to fix layout.json as the sample. This is WIP!

Change-Id: I060cf1bd69d7b0b0b1cd692ec4f10532756cb01f
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 a254277..0caeec7 100644
--- a/web/gui/src/main/webapp/app/view/topo/topo.css
+++ b/web/gui/src/main/webapp/app/view/topo/topo.css
@@ -546,11 +546,11 @@
 /* Sprite Layer */
 
 #ov-topo svg #topo-sprites use {
-    stroke-width: 1.0;
+    stroke-width: 2;
 }
 #ov-topo svg #topo-sprites text {
     text-anchor: middle;
-    font-size: 10pt;
+    font-size: 20pt;
     font-style: italic;
 }
 
@@ -585,7 +585,7 @@
 }
 
 .light #ov-topo svg #topo-sprites .gray1 use {
-    stroke: #bbb;
+    stroke: #ccc;
     fill: none;
 }
 .dark #ov-topo svg #topo-sprites .gray1 use {
@@ -593,7 +593,7 @@
     fill: none;
 }
 .light #ov-topo svg #topo-sprites .gray1 text {
-    fill: #ccc;
+    fill: #ddd;
 }
 .dark #ov-topo svg #topo-sprites .gray1 text {
     fill: #444;
diff --git a/web/gui/src/main/webapp/app/view/topo/topoSprite.js b/web/gui/src/main/webapp/app/view/topo/topoSprite.js
index 722feb0..3b1115a 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoSprite.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoSprite.js
@@ -25,7 +25,9 @@
     // injected refs
     var $log, $http, fs, gs, sus, wss;
 
-    var tssid = 'TopoSpriteService: ';
+    // constants
+    var tssid = 'TopoSpriteService: ',
+        fontsize = 20;  // default font size 20pt.
 
     // internal state
     var spriteLayer, defsElement;
@@ -51,47 +53,61 @@
         }
     }
 
-    function labAttr(def) {
-        var dim = def.dim || [1000,1000],
-            w = dim[0],
-            h = dim[1],
-            dy = def.labelyoff || 1;
 
-        return { x: w / 2, y: h * dy };
-    }
-
-    function doSprite(spr, def) {
+    function doSprite(spr, def, pstrk) {
         var c = spr.class || 'gray1',
             p = spr.pos || [0,0],
             lab = spr.label,
-            dim = def.dim || [1000,1000],
+            dim = def.dim || [40,40],
             w = dim[0],
             h = dim[1],
-            use = def.glyph || 'spr_' + def.path,
-            g = spriteLayer.append('g')
-                .classed(c, true)
-                .attr('transform', sus.translate(p));
+            dy = def.labelyoff || 1,
+            sc = def.scale,
+            xfm = sus.translate(p),
+            useId = def.glyph || 'spr_' + def.path,
+            g, attr, use, style;
 
-        g.append('use').attr({
+        if (sc) {
+            xfm += sus.scale(sc, sc);
+        }
+
+        g = spriteLayer.append('g')
+            .classed(c, true)
+            .attr('transform', xfm);
+
+        attr = {
             width: w,
             height: h,
-            'xlink:href': '#' + use
-        });
+            'xlink:href': '#' + useId
+        };
+
+        use = g.append('use').attr(attr);
+
+        if (pstrk) {
+            style = {};
+            angular.forEach(pstrk, function (value, key) {
+                style['stroke-' + key] = value;
+            });
+            use.style(style);
+        }
 
         if (lab) {
             g.append('text')
                 .text(lab)
-                .attr(labAttr(def));
+                .attr({ x: w / 2, y: h * dy });
         }
     }
 
     function doLabel(label) {
         var c = label.class || 'gray1',
-            p = label.pos || [0,0];
-        spriteLayer.append('text')
-            .text(label.text)
-            .attr('transform', sus.translate(p))
-            .classed(c, true);
+            p = label.pos || [0,0],
+            sz = label.size || 1.0,
+            g = spriteLayer.append('g')
+                .classed(c, true)
+                .attr('transform', sus.translate(p))
+                .append('text')
+                .text(label.text)
+                .style('font-size', (fontsize * sz)+'pt');
     }
 
 
@@ -111,8 +127,8 @@
     //  data for the requested sprite definition.
     function inData(payload) {
         var data = payload.data,
-            name, desc, sprites, labels,
-            paths = {},
+            name, desc, sprites, labels, alpha,
+            pathstrokes = {},
             defs = {};
 
         if (!data) {
@@ -124,7 +140,12 @@
 
         $log.debug("Loading sprites...[" + name + "]", desc);
 
-        registerPathsAsGlyphs(data.paths);
+        if (data.paths) {
+            registerPathsAsGlyphs(data.paths);
+            data.paths.forEach(function (p) {
+                pathstrokes[p.tag] = p.stroke;
+            });
+        }
 
         if (data.defn) {
             data.defn.forEach(function (d) {
@@ -136,11 +157,17 @@
         if (data.load) {
             sprites = data.load.sprites;
             labels = data.load.labels;
+            alpha = data.load.alpha;
+            if (alpha) {
+                spriteLayer.style('opacity', alpha);
+            }
         }
 
         if (sprites) {
             sprites.forEach(function (spr) {
-               doSprite(spr, defs[spr.id]);
+                var def = defs[spr.id],
+                    pstrk = def.path && pathstrokes[def.path];
+                doSprite(spr, def, pstrk);
             });
         }
 
diff --git a/web/gui/src/main/webapp/data/sprites/layout.json b/web/gui/src/main/webapp/data/sprites/layout.json
index fac4768..3e41939 100644
--- a/web/gui/src/main/webapp/data/sprites/layout.json
+++ b/web/gui/src/main/webapp/data/sprites/layout.json
@@ -3,7 +3,7 @@
   "defn_desc": "Sample Layout Sprite Data",
 
   "_comment": [
-    "Sample sprite layout file, demonstrating user-defined outlines",
+    "Sample sprite layout file, demonstrating user-defined paths",
     "(1) Register on the server with ...",
     "    onos-upload-sprites localhost layout.json",
     "(2) Load into topology view with ...",
@@ -54,8 +54,8 @@
     "defines the Y-offset of the label as a percentage from the top of the",
     "sprite; for example, 0.4 = 40%. The label is centered horizontally.",
     "",
-    "Note that dimension (dim) defaults to [1000,1000] so that, by default,",
-    "there is a 1:1 scale mapping of custom paths to the topology view."
+    "Note that dimension (dim) defaults to [40,40] which is the",
+    "approximate size of a device icon."
   ],
   "defn": [
     {
@@ -69,17 +69,17 @@
     {
       "id": "small_tri",
       "path": "triangle",
-      "dim":[80,80]
+      "scale":4
     },
     {
       "id": "big_tri",
       "path": "triangle",
-      "dim":[160,160]
+      "scale":12
     },
     {
       "id": "subnet",
       "glyph": "cloud",
-      "dim":[120,120],
+      "scale":8,
       "labelyoff": 0.4
     },
     {
@@ -103,20 +103,22 @@
   ],
   "load": {
     "sprites": [
-      { "id": "border" },
-      { "id": "multi", "class": "gray1" },
       { "id": "subnet", "pos":[-40,20], "label":"apples", "class": "blue1" },
       { "id": "subnet", "pos":[400,40], "label":"bananas", "class": "blue1" },
       { "id": "subnet", "pos":[840,60], "label":"cherries", "class": "blue1" },
-      { "id": "subnet2", "pos":[300,400], "class": "gray1" },
-      { "id": "small_tri", "pos":[10, 20] },
-      { "id": "small_tri", "pos":[110, 20] },
-      { "id": "small_tri", "pos":[210, 20] },
-      { "id": "small_tri", "pos":[310, 20] }
+      { "id": "subnet2", "pos":[300,400], "class": "gray1" }
     ],
     "labels": [
-      { "pos":[500,940], "text":"Sample Layout", "class":"blue1" },
-      { "pos":[500,1000], "text":"Illustrating Sprites", "class":"gray1" }
+      { "pos":[500,850], "text":"Sample Layout", "class":"blue1", "size":1.6 },
+      { "pos":[500,900], "text":"Illustrating Sprites", "class":"gray1" }
     ]
-  }
+  },
+  "junk":[
+    { "id": "border" },
+    { "id": "multi", "class": "gray1" },
+    { "id": "small_tri", "pos":[10, 20] },
+    { "id": "small_tri", "pos":[110, 20] },
+    { "id": "small_tri", "pos":[210, 20] },
+    { "id": "small_tri", "pos":[310, 20] }
+  ]
 }
diff --git a/web/gui/src/main/webapp/data/sprites/menlo.json b/web/gui/src/main/webapp/data/sprites/menlo.json
new file mode 100644
index 0000000..68253d3
--- /dev/null
+++ b/web/gui/src/main/webapp/data/sprites/menlo.json
@@ -0,0 +1,76 @@
+{
+  "defn_name": "menlo",
+  "defn_desc": "Office Floor Plan of ONLab at Menlo Park",
+
+  "paths": [
+    {
+      "tag": "outerwalls",
+      "stroke": {
+        "width": 4
+      },
+      "viewbox": "0 0 925 550",
+      "d": [
+        "M36,342V516",
+        "M36,516H892",
+        "M36,24H892",
+        "M36,24V250",
+        "M892,516V274",
+        "M892,188V24"
+      ]
+    },
+    {
+      "tag": "innerwalls",
+      "stroke": {
+        "width": 2
+      },
+      "viewbox": "0 0 925 550",
+      "d": [
+        "M892,188H730V158",
+        "M640,24V254H676H676V368",
+        "M892,312H742",
+        "M742,342V516",
+        "M638,368H546V272",
+        "M544,282H674",
+        "M546,232V66H494V26",
+        "M494,130V60",
+        "M454,130H340",
+        "M400,24V130",
+        "M640,178H546",
+        "M638,188H672V158",
+        "M700,410H602",
+        "M518,410H444",
+        "M400,410H276",
+        "M238,408V516",
+        "M352,410V516",
+        "M444,410V516",
+        "M562,410V516",
+        "M650,410V516",
+        "M88,178H300V24",
+        "M88,60H186V178",
+        "M88,140H108V60"
+      ]
+    }
+  ],
+
+  "defn": [
+    { "id": "owalls", "path": "outerwalls", "dim":[1400,1400] },
+    { "id": "iwalls", "path": "innerwalls", "dim":[1400,1400] }
+  ],
+
+  "load": {
+    "alpha": 0.9,
+    "sprites": [
+      { "id": "owalls", "pos":[-200,-200] },
+      { "id": "iwalls", "pos":[-200,-200] }
+    ],
+    "labels": [
+      { "pos":[160,220], "text":"Kitchen", "class":"gold1" },
+      { "pos":[480,220], "text":"Guru", "class":"gold1" },
+      { "pos":[980,220], "text":"Admin", "class":"gold1" },
+      { "pos":[700,400], "text":"Servers", "class":"gold1" },
+      { "pos":[720,580], "text":"Sm.Conf.", "class":"gold1" },
+      { "pos":[1040,700], "text":"Lg.Conf.", "class":"gold1" },
+      { "pos":[500,80], "text":"ONLab at Menlo Park", "class":"blue1", "size":1.4 }
+    ]
+  }
+}
diff --git a/web/gui/src/main/webapp/data/sprites/sample.json b/web/gui/src/main/webapp/data/sprites/sample.json
deleted file mode 100644
index f92e705..0000000
--- a/web/gui/src/main/webapp/data/sprites/sample.json
+++ /dev/null
@@ -1,45 +0,0 @@
-{
-  "defn_name": "sample",
-  "defn_desc": "Sample Cloud Sprite Data",
-
-  "_comment": [
-    "configuration file for loading canned and/or custom sprites (and labels)",
-    "into the topology view. These appear above the map layer, but below",
-    "the nodes/links layer."
-  ],
-
-  "_comment_custom": "'custom' contains custom path data",
-  "custom": [
-
-  ],
-
-  "_comment_defn": "'defn' array contains sprite definitions",
-  "defn": [
-    {
-      "id": "subnet",
-      "class": "sprite1",
-      "use": "cloud",
-      "width": 120,
-      "height": 120,
-      "scale": 3.0,
-      "textyoff": 0.4
-    },
-    {
-      "id": "subnet2",
-      "class": "sprite2",
-      "use": "cloud",
-      "width": 200,
-      "height": 200,
-      "scale": 3.0,
-      "textyoff": 0.4
-    }
-  ],
-
-  "_comment_load": "'load' array contains list of sprites to load",
-  "load": [
-    { "id": "subnet", "x": -40, "y":20, "label":"apples" },
-    { "id": "subnet", "x":400, "y":40, "label":"bananas" },
-    { "id": "subnet", "x":840, "y":60, "label":"cherries" },
-    { "id": "subnet2", "x":300, "y":400 }
-  ]
-}