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