GUI -- Augmented sprite JSON definition.
- refactored topoSprite.js to handle the changes.
Change-Id: Ib0ed7dbacbc93777d8849bf82f52ad6ac974af2c
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 887c2fc..a254277 100644
--- a/web/gui/src/main/webapp/app/view/topo/topo.css
+++ b/web/gui/src/main/webapp/app/view/topo/topo.css
@@ -542,46 +542,60 @@
fill: #eee;
}
+/* ------------------------------------------------- */
/* Sprite Layer */
+#ov-topo svg #topo-sprites use {
+ stroke-width: 1.0;
+}
#ov-topo svg #topo-sprites text {
text-anchor: middle;
font-size: 10pt;
font-style: italic;
}
-.light #ov-topo svg #topo-sprites .sprite1 use {
- stroke-width: 1.0;
- stroke: goldenrod;
+.light #ov-topo svg #topo-sprites .gold1 use {
+ stroke: #da2;
fill: none;
}
-.dark #ov-topo svg #topo-sprites .sprite1 use {
- stroke-width: 1.0;
+.dark #ov-topo svg #topo-sprites .gold1 use {
stroke: #541;
fill: none;
}
-
-.light #ov-topo svg #topo-sprites .sprite1 text {
+.light #ov-topo svg #topo-sprites .gold1 text {
fill: #eda;
}
-.dark #ov-topo svg #topo-sprites .sprite1 text {
+.dark #ov-topo svg #topo-sprites .gold1 text {
fill: #543;
}
-.light #ov-topo svg #topo-sprites .sprite2 use {
+.light #ov-topo svg #topo-sprites .blue1 use {
stroke: #bbd;
- stroke-width: 1.0;
fill: none;
}
-.dark #ov-topo svg #topo-sprites .sprite2 use {
+.dark #ov-topo svg #topo-sprites .blue1 use {
stroke: #445;
- stroke-width: 1.0;
fill: none;
}
-
-.light #ov-topo svg #topo-sprites .sprite2 text {
+.light #ov-topo svg #topo-sprites .blue1 text {
fill: #cce;
}
-.dark #ov-topo svg #topo-sprites .sprite2 text {
+.dark #ov-topo svg #topo-sprites .blue1 text {
fill: #446;
}
+
+.light #ov-topo svg #topo-sprites .gray1 use {
+ stroke: #bbb;
+ fill: none;
+}
+.dark #ov-topo svg #topo-sprites .gray1 use {
+ stroke: #333;
+ fill: none;
+}
+.light #ov-topo svg #topo-sprites .gray1 text {
+ fill: #ccc;
+}
+.dark #ov-topo svg #topo-sprites .gray1 text {
+ fill: #444;
+}
+
diff --git a/web/gui/src/main/webapp/app/view/topo/topo.js b/web/gui/src/main/webapp/app/view/topo/topo.js
index f4d08f2..2233bb2 100644
--- a/web/gui/src/main/webapp/app/view/topo/topo.js
+++ b/web/gui/src/main/webapp/app/view/topo/topo.js
@@ -366,7 +366,7 @@
}
);
spriteG = zoomLayer.append ('g').attr('id', 'topo-sprites');
- tspr.loadSprites(spriteG, $loc.search().sprites);
+ tspr.loadSprites(spriteG, defs, $loc.search().sprites);
forceG = zoomLayer.append('g').attr('id', 'topo-force');
tfs.initForce(svg, forceG, uplink, dim);
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 1586a04..722feb0 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoSprite.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoSprite.js
@@ -16,47 +16,85 @@
/*
ONOS GUI -- Topology Sprite Module.
- Defines behavior for loading sprites.
+ Defines behavior for loading sprites into the sprite layer.
*/
(function () {
'use strict';
// injected refs
- var $log, $http, fs, sus, wss;
+ var $log, $http, fs, gs, sus, wss;
var tssid = 'TopoSpriteService: ';
// internal state
- var spriteLayer;
+ var spriteLayer, defsElement;
- function doSprite(def, item) {
- var g;
+ function registerPathsAsGlyphs(paths) {
+ var custom = {},
+ ids = [];
- function xfm(x, y, s) {
- return sus.translate([x,y]) + sus.scale(s, s);
+ function mkd(d) {
+ return fs.isA(d) ? d.join('') : d;
}
- g = spriteLayer.append('g')
- .classed(def['class'], true)
- .attr('transform', xfm(item.x, item.y, def.scale));
+ if (paths) {
+ paths.forEach(function (path) {
+ var tag = 'spr_' + path.tag;
+ custom['_' + tag] = path.viewbox || '0 0 1000 1000';
+ custom[tag] = mkd(path.d);
+ ids.push(tag);
+ });
- if (item.label) {
- g.append('text')
- .text(item.label)
- .attr({
- x: def.width / 2,
- y: def.height * def.textyoff
- });
+ gs.registerGlyphs(custom);
+ gs.loadDefs(defsElement, ids, true);
}
+ }
+
+ 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) {
+ var c = spr.class || 'gray1',
+ p = spr.pos || [0,0],
+ lab = spr.label,
+ dim = def.dim || [1000,1000],
+ w = dim[0],
+ h = dim[1],
+ use = def.glyph || 'spr_' + def.path,
+ g = spriteLayer.append('g')
+ .classed(c, true)
+ .attr('transform', sus.translate(p));
g.append('use').attr({
- width: def.width,
- height: def.height,
- 'xlink:href': '#' + def.use
+ width: w,
+ height: h,
+ 'xlink:href': '#' + use
});
+
+ if (lab) {
+ g.append('text')
+ .text(lab)
+ .attr(labAttr(def));
+ }
}
+ 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);
+ }
+
+
// ==========================
// event handlers
@@ -73,30 +111,49 @@
// data for the requested sprite definition.
function inData(payload) {
var data = payload.data,
- name = data && data.defn_name,
- desc = data && data.defn_desc,
+ name, desc, sprites, labels,
+ paths = {},
defs = {};
if (!data) {
$log.warn(tssid + 'No sprite data loaded.')
return;
}
+ name = data.defn_name;
+ desc = data.defn_desc;
$log.debug("Loading sprites...[" + name + "]", desc);
- data.defn.forEach(function (d) {
- defs[d.id] = d;
- });
+ registerPathsAsGlyphs(data.paths);
- data.load.forEach(function (item) {
- doSprite(defs[item.id], item);
- });
+ if (data.defn) {
+ data.defn.forEach(function (d) {
+ defs[d.id] = d;
+ });
+ }
+
+ // pull out the sprite and label items
+ if (data.load) {
+ sprites = data.load.sprites;
+ labels = data.load.labels;
+ }
+
+ if (sprites) {
+ sprites.forEach(function (spr) {
+ doSprite(spr, defs[spr.id]);
+ });
+ }
+
+ if (labels) {
+ labels.forEach(doLabel);
+ }
}
- function loadSprites(layer, defname) {
+ function loadSprites(layer, defsElem, defname) {
var name = defname || 'sprites';
spriteLayer = layer;
+ defsElement = defsElem;
$log.info(tssid + 'Requesting sprite definition ['+name+']...');
@@ -109,12 +166,14 @@
angular.module('ovTopo')
.factory('TopoSpriteService',
- ['$log', '$http', 'FnService', 'SvgUtilService', 'WebSocketService',
+ ['$log', '$http', 'FnService', 'GlyphService',
+ 'SvgUtilService', 'WebSocketService',
- function (_$log_, _$http_, _fs_, _sus_, _wss_) {
+ function (_$log_, _$http_, _fs_, _gs_, _sus_, _wss_) {
$log = _$log_;
$http = _$http_;
fs = _fs_;
+ gs = _gs_;
sus = _sus_;
wss = _wss_;
diff --git a/web/gui/src/main/webapp/data/sprites/layout.json b/web/gui/src/main/webapp/data/sprites/layout.json
new file mode 100644
index 0000000..fac4768
--- /dev/null
+++ b/web/gui/src/main/webapp/data/sprites/layout.json
@@ -0,0 +1,122 @@
+{
+ "defn_name": "layout",
+ "defn_desc": "Sample Layout Sprite Data",
+
+ "_comment": [
+ "Sample sprite layout file, demonstrating user-defined outlines",
+ "(1) Register on the server with ...",
+ " onos-upload-sprites localhost layout.json",
+ "(2) Load into topology view with ...",
+ " http://localhost:8181/onos/ui/index.html#/topo?sprites=layout"
+ ],
+
+ "_comment_paths": [
+ "The 'paths' array contains custom path data.",
+ "Note that viewbox defaults to [0 0 1000 1000], which is the logical",
+ "coordinate space of the topology view."
+ ],
+ "paths": [
+ {
+ "tag": "border",
+ "d": "M0,0h1000v1000h-1000z",
+ "_comment": "bounds of viewbox 0 0 1000 1000"
+ },
+ {
+ "tag": "multi",
+ "d": [
+ "M500,500l-50,50v-200h100v200z",
+ "M600,400h200v50h-200z"
+ ],
+ "_comment": "shows path constructed from multiple strings"
+ },
+ {
+ "tag": "triangle",
+ "viewbox": "0 0 1 1",
+ "d": "M.5,.2l.3,.6,h-.6z",
+ "_comment": "defines its own viewbox"
+ },
+ {
+ "tag": "diamond",
+ "viewbox": "0 0 1 1",
+ "d": "M.2,.5l.3,-.3l.3,.3l-.3,.3z"
+ }
+ ],
+
+ "_comment_defn": [
+ "The 'defn' array contains sprite definitions that combine",
+ "path, dimensions, and label-offset into 'sprites' that can be",
+ "replicated (stamped) in different positions in the view.",
+ "",
+ "The 'glyph' property refers to glyphs registered with the UI.",
+ "Alternatively, the 'path' property refers to a custom path defined in",
+ "the path array above. The 'dim' property provides the [width,height]",
+ "bounds within which the glyph/path is drawn. The 'labelyoff' property",
+ "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."
+ ],
+ "defn": [
+ {
+ "id": "border",
+ "path": "border"
+ },
+ {
+ "id": "multi",
+ "path": "multi"
+ },
+ {
+ "id": "small_tri",
+ "path": "triangle",
+ "dim":[80,80]
+ },
+ {
+ "id": "big_tri",
+ "path": "triangle",
+ "dim":[160,160]
+ },
+ {
+ "id": "subnet",
+ "glyph": "cloud",
+ "dim":[120,120],
+ "labelyoff": 0.4
+ },
+ {
+ "id": "subnet2",
+ "glyph": "cloud",
+ "dim":[200,200],
+ "labelyoff": 0.4
+ }
+ ],
+
+ "_comment_load": [
+ "The 'load' object contains sprites and labels to load into the view.",
+ "",
+ "Items in the sprite list associate sprites with a position,",
+ "style class, and optional label. Note that the coordinates of",
+ "the position define the top-left corner of the sprite.",
+ "Default 'pos' is [0,0]. Default 'class' is 'gray1'.",
+ "",
+ "Items in the label list associate labels with a position and",
+ "style class. Note that the text is centered on the x-coordinate."
+ ],
+ "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] }
+ ],
+ "labels": [
+ { "pos":[500,940], "text":"Sample Layout", "class":"blue1" },
+ { "pos":[500,1000], "text":"Illustrating Sprites", "class":"gray1" }
+ ]
+ }
+}
diff --git a/web/gui/src/main/webapp/data/sprites/sprites.json b/web/gui/src/main/webapp/data/sprites/sample.json
similarity index 100%
rename from web/gui/src/main/webapp/data/sprites/sprites.json
rename to web/gui/src/main/webapp/data/sprites/sample.json