Simon Hunt
Committed by Gerrit Code Review

GUI -- Augmented sprite JSON definition.

- refactored topoSprite.js to handle the changes.

Change-Id: Ib0ed7dbacbc93777d8849bf82f52ad6ac974af2c
...@@ -542,46 +542,60 @@ ...@@ -542,46 +542,60 @@
542 fill: #eee; 542 fill: #eee;
543 } 543 }
544 544
545 +/* ------------------------------------------------- */
545 /* Sprite Layer */ 546 /* Sprite Layer */
546 547
548 +#ov-topo svg #topo-sprites use {
549 + stroke-width: 1.0;
550 +}
547 #ov-topo svg #topo-sprites text { 551 #ov-topo svg #topo-sprites text {
548 text-anchor: middle; 552 text-anchor: middle;
549 font-size: 10pt; 553 font-size: 10pt;
550 font-style: italic; 554 font-style: italic;
551 } 555 }
552 556
553 -.light #ov-topo svg #topo-sprites .sprite1 use { 557 +.light #ov-topo svg #topo-sprites .gold1 use {
554 - stroke-width: 1.0; 558 + stroke: #da2;
555 - stroke: goldenrod;
556 fill: none; 559 fill: none;
557 } 560 }
558 -.dark #ov-topo svg #topo-sprites .sprite1 use { 561 +.dark #ov-topo svg #topo-sprites .gold1 use {
559 - stroke-width: 1.0;
560 stroke: #541; 562 stroke: #541;
561 fill: none; 563 fill: none;
562 } 564 }
563 - 565 +.light #ov-topo svg #topo-sprites .gold1 text {
564 -.light #ov-topo svg #topo-sprites .sprite1 text {
565 fill: #eda; 566 fill: #eda;
566 } 567 }
567 -.dark #ov-topo svg #topo-sprites .sprite1 text { 568 +.dark #ov-topo svg #topo-sprites .gold1 text {
568 fill: #543; 569 fill: #543;
569 } 570 }
570 571
571 -.light #ov-topo svg #topo-sprites .sprite2 use { 572 +.light #ov-topo svg #topo-sprites .blue1 use {
572 stroke: #bbd; 573 stroke: #bbd;
573 - stroke-width: 1.0;
574 fill: none; 574 fill: none;
575 } 575 }
576 -.dark #ov-topo svg #topo-sprites .sprite2 use { 576 +.dark #ov-topo svg #topo-sprites .blue1 use {
577 stroke: #445; 577 stroke: #445;
578 - stroke-width: 1.0;
579 fill: none; 578 fill: none;
580 } 579 }
581 - 580 +.light #ov-topo svg #topo-sprites .blue1 text {
582 -.light #ov-topo svg #topo-sprites .sprite2 text {
583 fill: #cce; 581 fill: #cce;
584 } 582 }
585 -.dark #ov-topo svg #topo-sprites .sprite2 text { 583 +.dark #ov-topo svg #topo-sprites .blue1 text {
586 fill: #446; 584 fill: #446;
587 } 585 }
586 +
587 +.light #ov-topo svg #topo-sprites .gray1 use {
588 + stroke: #bbb;
589 + fill: none;
590 +}
591 +.dark #ov-topo svg #topo-sprites .gray1 use {
592 + stroke: #333;
593 + fill: none;
594 +}
595 +.light #ov-topo svg #topo-sprites .gray1 text {
596 + fill: #ccc;
597 +}
598 +.dark #ov-topo svg #topo-sprites .gray1 text {
599 + fill: #444;
600 +}
601 +
......
...@@ -366,7 +366,7 @@ ...@@ -366,7 +366,7 @@
366 } 366 }
367 ); 367 );
368 spriteG = zoomLayer.append ('g').attr('id', 'topo-sprites'); 368 spriteG = zoomLayer.append ('g').attr('id', 'topo-sprites');
369 - tspr.loadSprites(spriteG, $loc.search().sprites); 369 + tspr.loadSprites(spriteG, defs, $loc.search().sprites);
370 370
371 forceG = zoomLayer.append('g').attr('id', 'topo-force'); 371 forceG = zoomLayer.append('g').attr('id', 'topo-force');
372 tfs.initForce(svg, forceG, uplink, dim); 372 tfs.initForce(svg, forceG, uplink, dim);
......
...@@ -16,47 +16,85 @@ ...@@ -16,47 +16,85 @@
16 16
17 /* 17 /*
18 ONOS GUI -- Topology Sprite Module. 18 ONOS GUI -- Topology Sprite Module.
19 - Defines behavior for loading sprites. 19 + Defines behavior for loading sprites into the sprite layer.
20 */ 20 */
21 21
22 (function () { 22 (function () {
23 'use strict'; 23 'use strict';
24 24
25 // injected refs 25 // injected refs
26 - var $log, $http, fs, sus, wss; 26 + var $log, $http, fs, gs, sus, wss;
27 27
28 var tssid = 'TopoSpriteService: '; 28 var tssid = 'TopoSpriteService: ';
29 29
30 // internal state 30 // internal state
31 - var spriteLayer; 31 + var spriteLayer, defsElement;
32 32
33 - function doSprite(def, item) { 33 + function registerPathsAsGlyphs(paths) {
34 - var g; 34 + var custom = {},
35 + ids = [];
35 36
36 - function xfm(x, y, s) { 37 + function mkd(d) {
37 - return sus.translate([x,y]) + sus.scale(s, s); 38 + return fs.isA(d) ? d.join('') : d;
38 } 39 }
39 40
40 - g = spriteLayer.append('g') 41 + if (paths) {
41 - .classed(def['class'], true) 42 + paths.forEach(function (path) {
42 - .attr('transform', xfm(item.x, item.y, def.scale)); 43 + var tag = 'spr_' + path.tag;
44 + custom['_' + tag] = path.viewbox || '0 0 1000 1000';
45 + custom[tag] = mkd(path.d);
46 + ids.push(tag);
47 + });
43 48
44 - if (item.label) { 49 + gs.registerGlyphs(custom);
45 - g.append('text') 50 + gs.loadDefs(defsElement, ids, true);
46 - .text(item.label)
47 - .attr({
48 - x: def.width / 2,
49 - y: def.height * def.textyoff
50 - });
51 } 51 }
52 + }
53 +
54 + function labAttr(def) {
55 + var dim = def.dim || [1000,1000],
56 + w = dim[0],
57 + h = dim[1],
58 + dy = def.labelyoff || 1;
59 +
60 + return { x: w / 2, y: h * dy };
61 + }
62 +
63 + function doSprite(spr, def) {
64 + var c = spr.class || 'gray1',
65 + p = spr.pos || [0,0],
66 + lab = spr.label,
67 + dim = def.dim || [1000,1000],
68 + w = dim[0],
69 + h = dim[1],
70 + use = def.glyph || 'spr_' + def.path,
71 + g = spriteLayer.append('g')
72 + .classed(c, true)
73 + .attr('transform', sus.translate(p));
52 74
53 g.append('use').attr({ 75 g.append('use').attr({
54 - width: def.width, 76 + width: w,
55 - height: def.height, 77 + height: h,
56 - 'xlink:href': '#' + def.use 78 + 'xlink:href': '#' + use
57 }); 79 });
80 +
81 + if (lab) {
82 + g.append('text')
83 + .text(lab)
84 + .attr(labAttr(def));
85 + }
86 + }
87 +
88 + function doLabel(label) {
89 + var c = label.class || 'gray1',
90 + p = label.pos || [0,0];
91 + spriteLayer.append('text')
92 + .text(label.text)
93 + .attr('transform', sus.translate(p))
94 + .classed(c, true);
58 } 95 }
59 96
97 +
60 // ========================== 98 // ==========================
61 // event handlers 99 // event handlers
62 100
...@@ -73,30 +111,49 @@ ...@@ -73,30 +111,49 @@
73 // data for the requested sprite definition. 111 // data for the requested sprite definition.
74 function inData(payload) { 112 function inData(payload) {
75 var data = payload.data, 113 var data = payload.data,
76 - name = data && data.defn_name, 114 + name, desc, sprites, labels,
77 - desc = data && data.defn_desc, 115 + paths = {},
78 defs = {}; 116 defs = {};
79 117
80 if (!data) { 118 if (!data) {
81 $log.warn(tssid + 'No sprite data loaded.') 119 $log.warn(tssid + 'No sprite data loaded.')
82 return; 120 return;
83 } 121 }
122 + name = data.defn_name;
123 + desc = data.defn_desc;
84 124
85 $log.debug("Loading sprites...[" + name + "]", desc); 125 $log.debug("Loading sprites...[" + name + "]", desc);
86 126
87 - data.defn.forEach(function (d) { 127 + registerPathsAsGlyphs(data.paths);
88 - defs[d.id] = d;
89 - });
90 128
91 - data.load.forEach(function (item) { 129 + if (data.defn) {
92 - doSprite(defs[item.id], item); 130 + data.defn.forEach(function (d) {
93 - }); 131 + defs[d.id] = d;
132 + });
133 + }
134 +
135 + // pull out the sprite and label items
136 + if (data.load) {
137 + sprites = data.load.sprites;
138 + labels = data.load.labels;
139 + }
140 +
141 + if (sprites) {
142 + sprites.forEach(function (spr) {
143 + doSprite(spr, defs[spr.id]);
144 + });
145 + }
146 +
147 + if (labels) {
148 + labels.forEach(doLabel);
149 + }
94 } 150 }
95 151
96 152
97 - function loadSprites(layer, defname) { 153 + function loadSprites(layer, defsElem, defname) {
98 var name = defname || 'sprites'; 154 var name = defname || 'sprites';
99 spriteLayer = layer; 155 spriteLayer = layer;
156 + defsElement = defsElem;
100 157
101 $log.info(tssid + 'Requesting sprite definition ['+name+']...'); 158 $log.info(tssid + 'Requesting sprite definition ['+name+']...');
102 159
...@@ -109,12 +166,14 @@ ...@@ -109,12 +166,14 @@
109 166
110 angular.module('ovTopo') 167 angular.module('ovTopo')
111 .factory('TopoSpriteService', 168 .factory('TopoSpriteService',
112 - ['$log', '$http', 'FnService', 'SvgUtilService', 'WebSocketService', 169 + ['$log', '$http', 'FnService', 'GlyphService',
170 + 'SvgUtilService', 'WebSocketService',
113 171
114 - function (_$log_, _$http_, _fs_, _sus_, _wss_) { 172 + function (_$log_, _$http_, _fs_, _gs_, _sus_, _wss_) {
115 $log = _$log_; 173 $log = _$log_;
116 $http = _$http_; 174 $http = _$http_;
117 fs = _fs_; 175 fs = _fs_;
176 + gs = _gs_;
118 sus = _sus_; 177 sus = _sus_;
119 wss = _wss_; 178 wss = _wss_;
120 179
......
1 +{
2 + "defn_name": "layout",
3 + "defn_desc": "Sample Layout Sprite Data",
4 +
5 + "_comment": [
6 + "Sample sprite layout file, demonstrating user-defined outlines",
7 + "(1) Register on the server with ...",
8 + " onos-upload-sprites localhost layout.json",
9 + "(2) Load into topology view with ...",
10 + " http://localhost:8181/onos/ui/index.html#/topo?sprites=layout"
11 + ],
12 +
13 + "_comment_paths": [
14 + "The 'paths' array contains custom path data.",
15 + "Note that viewbox defaults to [0 0 1000 1000], which is the logical",
16 + "coordinate space of the topology view."
17 + ],
18 + "paths": [
19 + {
20 + "tag": "border",
21 + "d": "M0,0h1000v1000h-1000z",
22 + "_comment": "bounds of viewbox 0 0 1000 1000"
23 + },
24 + {
25 + "tag": "multi",
26 + "d": [
27 + "M500,500l-50,50v-200h100v200z",
28 + "M600,400h200v50h-200z"
29 + ],
30 + "_comment": "shows path constructed from multiple strings"
31 + },
32 + {
33 + "tag": "triangle",
34 + "viewbox": "0 0 1 1",
35 + "d": "M.5,.2l.3,.6,h-.6z",
36 + "_comment": "defines its own viewbox"
37 + },
38 + {
39 + "tag": "diamond",
40 + "viewbox": "0 0 1 1",
41 + "d": "M.2,.5l.3,-.3l.3,.3l-.3,.3z"
42 + }
43 + ],
44 +
45 + "_comment_defn": [
46 + "The 'defn' array contains sprite definitions that combine",
47 + "path, dimensions, and label-offset into 'sprites' that can be",
48 + "replicated (stamped) in different positions in the view.",
49 + "",
50 + "The 'glyph' property refers to glyphs registered with the UI.",
51 + "Alternatively, the 'path' property refers to a custom path defined in",
52 + "the path array above. The 'dim' property provides the [width,height]",
53 + "bounds within which the glyph/path is drawn. The 'labelyoff' property",
54 + "defines the Y-offset of the label as a percentage from the top of the",
55 + "sprite; for example, 0.4 = 40%. The label is centered horizontally.",
56 + "",
57 + "Note that dimension (dim) defaults to [1000,1000] so that, by default,",
58 + "there is a 1:1 scale mapping of custom paths to the topology view."
59 + ],
60 + "defn": [
61 + {
62 + "id": "border",
63 + "path": "border"
64 + },
65 + {
66 + "id": "multi",
67 + "path": "multi"
68 + },
69 + {
70 + "id": "small_tri",
71 + "path": "triangle",
72 + "dim":[80,80]
73 + },
74 + {
75 + "id": "big_tri",
76 + "path": "triangle",
77 + "dim":[160,160]
78 + },
79 + {
80 + "id": "subnet",
81 + "glyph": "cloud",
82 + "dim":[120,120],
83 + "labelyoff": 0.4
84 + },
85 + {
86 + "id": "subnet2",
87 + "glyph": "cloud",
88 + "dim":[200,200],
89 + "labelyoff": 0.4
90 + }
91 + ],
92 +
93 + "_comment_load": [
94 + "The 'load' object contains sprites and labels to load into the view.",
95 + "",
96 + "Items in the sprite list associate sprites with a position,",
97 + "style class, and optional label. Note that the coordinates of",
98 + "the position define the top-left corner of the sprite.",
99 + "Default 'pos' is [0,0]. Default 'class' is 'gray1'.",
100 + "",
101 + "Items in the label list associate labels with a position and",
102 + "style class. Note that the text is centered on the x-coordinate."
103 + ],
104 + "load": {
105 + "sprites": [
106 + { "id": "border" },
107 + { "id": "multi", "class": "gray1" },
108 + { "id": "subnet", "pos":[-40,20], "label":"apples", "class": "blue1" },
109 + { "id": "subnet", "pos":[400,40], "label":"bananas", "class": "blue1" },
110 + { "id": "subnet", "pos":[840,60], "label":"cherries", "class": "blue1" },
111 + { "id": "subnet2", "pos":[300,400], "class": "gray1" },
112 + { "id": "small_tri", "pos":[10, 20] },
113 + { "id": "small_tri", "pos":[110, 20] },
114 + { "id": "small_tri", "pos":[210, 20] },
115 + { "id": "small_tri", "pos":[310, 20] }
116 + ],
117 + "labels": [
118 + { "pos":[500,940], "text":"Sample Layout", "class":"blue1" },
119 + { "pos":[500,1000], "text":"Illustrating Sprites", "class":"gray1" }
120 + ]
121 + }
122 +}