GUI -- Created sample subnet sprite layout (clouds.json).
- Made paths, defn, load mandatory properties of the sprite definition file. - (layout.json still a WIP) Change-Id: I323a7ec7317f0837ff3319d67956cb4f836405eb
Showing
4 changed files
with
140 additions
and
53 deletions
... | @@ -555,7 +555,7 @@ | ... | @@ -555,7 +555,7 @@ |
555 | } | 555 | } |
556 | 556 | ||
557 | .light #ov-topo svg #topo-sprites .gold1 use { | 557 | .light #ov-topo svg #topo-sprites .gold1 use { |
558 | - stroke: #da2; | 558 | + stroke: #fda; |
559 | fill: none; | 559 | fill: none; |
560 | } | 560 | } |
561 | .dark #ov-topo svg #topo-sprites .gold1 use { | 561 | .dark #ov-topo svg #topo-sprites .gold1 use { | ... | ... |
... | @@ -32,6 +32,7 @@ | ... | @@ -32,6 +32,7 @@ |
32 | // internal state | 32 | // internal state |
33 | var spriteLayer, defsElement; | 33 | var spriteLayer, defsElement; |
34 | 34 | ||
35 | + | ||
35 | function registerPathsAsGlyphs(paths) { | 36 | function registerPathsAsGlyphs(paths) { |
36 | var custom = {}, | 37 | var custom = {}, |
37 | ids = []; | 38 | ids = []; |
... | @@ -40,21 +41,25 @@ | ... | @@ -40,21 +41,25 @@ |
40 | return fs.isA(d) ? d.join('') : d; | 41 | return fs.isA(d) ? d.join('') : d; |
41 | } | 42 | } |
42 | 43 | ||
43 | - if (paths) { | 44 | + paths.forEach(function (path) { |
44 | - paths.forEach(function (path) { | 45 | + var tag = 'spr_' + path.tag; |
45 | - var tag = 'spr_' + path.tag; | ||
46 | - custom['_' + tag] = path.viewbox || '0 0 1000 1000'; | ||
47 | - custom[tag] = mkd(path.d); | ||
48 | - ids.push(tag); | ||
49 | - }); | ||
50 | 46 | ||
51 | - gs.registerGlyphs(custom); | 47 | + if (path.glyph) { |
52 | - gs.loadDefs(defsElement, ids, true); | 48 | + // assumption is that we are using a built-in glyph |
53 | - } | 49 | + return; |
50 | + } | ||
51 | + | ||
52 | + custom['_' + tag] = path.viewbox || '0 0 1000 1000'; | ||
53 | + custom[tag] = mkd(path.d); | ||
54 | + ids.push(tag); | ||
55 | + }); | ||
56 | + | ||
57 | + gs.registerGlyphs(custom); | ||
58 | + gs.loadDefs(defsElement, ids, true); | ||
54 | } | 59 | } |
55 | 60 | ||
56 | 61 | ||
57 | - function doSprite(spr, def, pstrk) { | 62 | + function doSprite(spr, def, pmeta) { |
58 | var c = spr.class || 'gray1', | 63 | var c = spr.class || 'gray1', |
59 | p = spr.pos || [0,0], | 64 | p = spr.pos || [0,0], |
60 | lab = spr.label, | 65 | lab = spr.label, |
... | @@ -64,7 +69,6 @@ | ... | @@ -64,7 +69,6 @@ |
64 | dy = def.labelyoff || 1, | 69 | dy = def.labelyoff || 1, |
65 | sc = def.scale, | 70 | sc = def.scale, |
66 | xfm = sus.translate(p), | 71 | xfm = sus.translate(p), |
67 | - useId = def.glyph || 'spr_' + def.path, | ||
68 | g, attr, use, style; | 72 | g, attr, use, style; |
69 | 73 | ||
70 | if (sc) { | 74 | if (sc) { |
... | @@ -78,14 +82,14 @@ | ... | @@ -78,14 +82,14 @@ |
78 | attr = { | 82 | attr = { |
79 | width: w, | 83 | width: w, |
80 | height: h, | 84 | height: h, |
81 | - 'xlink:href': '#' + useId | 85 | + 'xlink:href': '#' + pmeta.u |
82 | }; | 86 | }; |
83 | 87 | ||
84 | use = g.append('use').attr(attr); | 88 | use = g.append('use').attr(attr); |
85 | 89 | ||
86 | - if (pstrk) { | 90 | + if (pmeta.s) { |
87 | style = {}; | 91 | style = {}; |
88 | - angular.forEach(pstrk, function (value, key) { | 92 | + angular.forEach(pmeta.s, function (value, key) { |
89 | style['stroke-' + key] = value; | 93 | style['stroke-' + key] = value; |
90 | }); | 94 | }); |
91 | use.style(style); | 95 | use.style(style); |
... | @@ -127,47 +131,66 @@ | ... | @@ -127,47 +131,66 @@ |
127 | // data for the requested sprite definition. | 131 | // data for the requested sprite definition. |
128 | function inData(payload) { | 132 | function inData(payload) { |
129 | var data = payload.data, | 133 | var data = payload.data, |
130 | - name, desc, sprites, labels, alpha, | 134 | + name, desc, pfx, sprites, labels, alpha, |
131 | - pathstrokes = {}, | 135 | + paths, defn, load, |
132 | - defs = {}; | 136 | + pathmeta = {}, |
137 | + defs = {}, | ||
138 | + warn = []; | ||
133 | 139 | ||
134 | if (!data) { | 140 | if (!data) { |
135 | - $log.warn(tssid + 'No sprite data loaded.') | 141 | + $log.warn(tssid + 'No sprite data loaded.'); |
136 | return; | 142 | return; |
137 | } | 143 | } |
138 | name = data.defn_name; | 144 | name = data.defn_name; |
139 | desc = data.defn_desc; | 145 | desc = data.defn_desc; |
146 | + paths = data.paths; | ||
147 | + defn = data.defn; | ||
148 | + load = data.load; | ||
149 | + pfx = tssid + '[' + name + ']: '; | ||
140 | 150 | ||
141 | $log.debug("Loading sprites...[" + name + "]", desc); | 151 | $log.debug("Loading sprites...[" + name + "]", desc); |
142 | 152 | ||
143 | - if (data.paths) { | 153 | + function no(what) { |
144 | - registerPathsAsGlyphs(data.paths); | 154 | + warn.push(pfx + 'No ' + what + ' property defined'); |
145 | - data.paths.forEach(function (p) { | ||
146 | - pathstrokes[p.tag] = p.stroke; | ||
147 | - }); | ||
148 | } | 155 | } |
149 | 156 | ||
150 | - if (data.defn) { | 157 | + if (!paths) no('paths'); |
151 | - data.defn.forEach(function (d) { | 158 | + if (!defn) no('defn'); |
152 | - defs[d.id] = d; | 159 | + if (!load) no('load'); |
153 | - }); | 160 | + |
161 | + if (warn.length) { | ||
162 | + $log.error(warn.join('\n')); | ||
163 | + return; | ||
154 | } | 164 | } |
155 | 165 | ||
156 | - // pull out the sprite and label items | 166 | + // any custom paths need to be added to the glyph DB, and imported |
157 | - if (data.load) { | 167 | + registerPathsAsGlyphs(paths); |
158 | - sprites = data.load.sprites; | 168 | + |
159 | - labels = data.load.labels; | 169 | + paths.forEach(function (p) { |
160 | - alpha = data.load.alpha; | 170 | + pathmeta[p.tag] = { |
161 | - if (alpha) { | 171 | + s: p.stroke, |
162 | - spriteLayer.style('opacity', alpha); | 172 | + u: p.glyph || 'spr_' + p.tag |
163 | - } | 173 | + }; |
174 | + }); | ||
175 | + | ||
176 | + defn.forEach(function (d) { | ||
177 | + defs[d.id] = d; | ||
178 | + }); | ||
179 | + | ||
180 | + // sprites, labels and alpha are each optional components of the load | ||
181 | + sprites = load.sprites; | ||
182 | + labels = load.labels; | ||
183 | + alpha = load.alpha; | ||
184 | + | ||
185 | + if (alpha) { | ||
186 | + spriteLayer.style('opacity', alpha); | ||
164 | } | 187 | } |
165 | 188 | ||
166 | if (sprites) { | 189 | if (sprites) { |
167 | sprites.forEach(function (spr) { | 190 | sprites.forEach(function (spr) { |
168 | var def = defs[spr.id], | 191 | var def = defs[spr.id], |
169 | - pstrk = def.path && pathstrokes[def.path]; | 192 | + pmeta = pathmeta[def.path]; |
170 | - doSprite(spr, def, pstrk); | 193 | + doSprite(spr, def, pmeta); |
171 | }); | 194 | }); |
172 | } | 195 | } |
173 | 196 | ... | ... |
1 | +{ | ||
2 | + "defn_name": "clouds", | ||
3 | + "defn_desc": "Sample Subnet Cloud layout", | ||
4 | + | ||
5 | + "_comment": [ | ||
6 | + "Sample cloud sprite layout", | ||
7 | + "(1) Register on the server with ...", | ||
8 | + " onos-upload-sprites localhost clouds.json", | ||
9 | + "(2) Load into topology view with ...", | ||
10 | + " http://localhost:8181/onos/ui/index.html#/topo?sprites=clouds" | ||
11 | + ], | ||
12 | + | ||
13 | + "paths": [ | ||
14 | + { | ||
15 | + "tag": "cloud-dashed", | ||
16 | + "stroke": { | ||
17 | + "width": 0.8, | ||
18 | + "dasharray": [4,2] | ||
19 | + }, | ||
20 | + "glyph": "cloud" | ||
21 | + }, | ||
22 | + { | ||
23 | + "tag": "cloud-solid", | ||
24 | + "stroke": { | ||
25 | + "width": 1 | ||
26 | + }, | ||
27 | + "glyph": "cloud" | ||
28 | + } | ||
29 | + ], | ||
30 | + | ||
31 | + "defn": [ | ||
32 | + { | ||
33 | + "id": "subnetA", | ||
34 | + "path": "cloud-dashed", | ||
35 | + "dim": [400,400], | ||
36 | + "labelyoff": 0.35 | ||
37 | + }, | ||
38 | + { | ||
39 | + "id": "subnetB", | ||
40 | + "path": "cloud-solid", | ||
41 | + "dim": [600,600], | ||
42 | + "labelyoff": 0.35 | ||
43 | + } | ||
44 | + ], | ||
45 | + | ||
46 | + "load": { | ||
47 | + "sprites": [ | ||
48 | + { "id": "subnetA", "pos":[-200,40], "label":"apples", "class":"blue1" }, | ||
49 | + { "id": "subnetA", "pos":[250,40], "label":"bananas", "class":"blue1" }, | ||
50 | + { "id": "subnetA", "pos":[700,40], "label":"cherries", "class":"blue1" }, | ||
51 | + { "id": "subnetB", "pos":[-200,400], "label":"Menlo Park", "class":"gold1" }, | ||
52 | + { "id": "subnetB", "pos":[500,400], "label":"Stanford", "class":"gold1" } | ||
53 | + ], | ||
54 | + "labels": [ | ||
55 | + { "pos":[0,50], "text":"Sample Subnets", "size":1.4 } | ||
56 | + ] | ||
57 | + } | ||
58 | + | ||
59 | +} |
... | @@ -18,16 +18,18 @@ | ... | @@ -18,16 +18,18 @@ |
18 | "paths": [ | 18 | "paths": [ |
19 | { | 19 | { |
20 | "tag": "border", | 20 | "tag": "border", |
21 | - "d": "M0,0h1000v1000h-1000z", | 21 | + "viewbox": "0 0 1 1", |
22 | - "_comment": "bounds of viewbox 0 0 1000 1000" | 22 | + "d": "M0,0h1v1h-1z", |
23 | + "_comment": "path defined in single string" | ||
23 | }, | 24 | }, |
24 | { | 25 | { |
25 | - "tag": "multi", | 26 | + "tag": "banner", |
27 | + "viewbox": "0 0 4 8", | ||
26 | "d": [ | 28 | "d": [ |
27 | - "M500,500l-50,50v-200h100v200z", | 29 | + "M0,0h4v6l-2,-2l-2,2z", |
28 | - "M600,400h200v50h-200z" | 30 | + "M1,6h2v2h-2z" |
29 | ], | 31 | ], |
30 | - "_comment": "shows path constructed from multiple strings" | 32 | + "_comment": "path defined in multiple strings" |
31 | }, | 33 | }, |
32 | { | 34 | { |
33 | "tag": "triangle", | 35 | "tag": "triangle", |
... | @@ -49,18 +51,20 @@ | ... | @@ -49,18 +51,20 @@ |
49 | "", | 51 | "", |
50 | "The 'glyph' property refers to glyphs registered with the UI.", | 52 | "The 'glyph' property refers to glyphs registered with the UI.", |
51 | "Alternatively, the 'path' property refers to a custom path defined in", | 53 | "Alternatively, the 'path' property refers to a custom path defined in", |
52 | - "the path array above. The 'dim' property provides the [width,height]", | 54 | + " the path array above.", |
53 | - "bounds within which the glyph/path is drawn. The 'labelyoff' property", | 55 | + "The 'dim' property provides the [width,height] bounds within which the", |
54 | - "defines the Y-offset of the label as a percentage from the top of the", | 56 | + " glyph/path is drawn. (default is [40,40])", |
55 | - "sprite; for example, 0.4 = 40%. The label is centered horizontally.", | 57 | + "The 'labelyoff' property defines the Y-offset of the label as a", |
56 | - "", | 58 | + " percentage from the top of the sprite; for example, 0.4 = 40%. The", |
57 | - "Note that dimension (dim) defaults to [40,40] which is the", | 59 | + " label is centered horizontally.", |
58 | - "approximate size of a device icon." | 60 | + "The 'scale' property (default is 1) defines the scaling factor, which", |
61 | + " is applied after the sprite has been translated to its position." | ||
59 | ], | 62 | ], |
60 | "defn": [ | 63 | "defn": [ |
61 | { | 64 | { |
62 | "id": "border", | 65 | "id": "border", |
63 | - "path": "border" | 66 | + "path": "border", |
67 | + "dim":[1000,1000] | ||
64 | }, | 68 | }, |
65 | { | 69 | { |
66 | "id": "multi", | 70 | "id": "multi", |
... | @@ -103,6 +107,7 @@ | ... | @@ -103,6 +107,7 @@ |
103 | ], | 107 | ], |
104 | "load": { | 108 | "load": { |
105 | "sprites": [ | 109 | "sprites": [ |
110 | + { "id": "border", "class": "gold1" }, | ||
106 | { "id": "subnet", "pos":[-40,20], "label":"apples", "class": "blue1" }, | 111 | { "id": "subnet", "pos":[-40,20], "label":"apples", "class": "blue1" }, |
107 | { "id": "subnet", "pos":[400,40], "label":"bananas", "class": "blue1" }, | 112 | { "id": "subnet", "pos":[400,40], "label":"bananas", "class": "blue1" }, |
108 | { "id": "subnet", "pos":[840,60], "label":"cherries", "class": "blue1" }, | 113 | { "id": "subnet", "pos":[840,60], "label":"cherries", "class": "blue1" }, | ... | ... |
-
Please register or login to post a comment