Simon Hunt

GUI -- Cleaned up sprite definition format in JSON.

- Implemented sprite layer in topology view.

Change-Id: I0861641684df12202d6ccd069d89375a8005d4a8
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
9 <script src="app/view/topo/topoOblique.js"></script> 9 <script src="app/view/topo/topoOblique.js"></script>
10 <script src="app/view/topo/topoPanel.js"></script> 10 <script src="app/view/topo/topoPanel.js"></script>
11 <script src="app/view/topo/topoSelect.js"></script> 11 <script src="app/view/topo/topoSelect.js"></script>
12 +<script src="app/view/topo/topoSprite.js"></script>
12 <script src="app/view/topo/topoTraffic.js"></script> 13 <script src="app/view/topo/topoTraffic.js"></script>
13 <script src="app/view/topo/topoToolbar.js"></script> 14 <script src="app/view/topo/topoToolbar.js"></script>
14 <script src="app/view/device/device.js"></script> 15 <script src="app/view/device/device.js"></script>
......
...@@ -542,3 +542,46 @@ ...@@ -542,3 +542,46 @@
542 fill: #eee; 542 fill: #eee;
543 } 543 }
544 544
545 +/* Sprite Layer */
546 +
547 +#ov-topo svg #topo-sprites text {
548 + text-anchor: middle;
549 + font-size: 10pt;
550 + font-style: italic;
551 +}
552 +
553 +.light #ov-topo svg #topo-sprites .sprite1 use {
554 + stroke-width: 1.0;
555 + stroke: goldenrod;
556 + fill: none;
557 +}
558 +.dark #ov-topo svg #topo-sprites .sprite1 use {
559 + stroke-width: 1.0;
560 + stroke: #541;
561 + fill: none;
562 +}
563 +
564 +.light #ov-topo svg #topo-sprites .sprite1 text {
565 + fill: #eda;
566 +}
567 +.dark #ov-topo svg #topo-sprites .sprite1 text {
568 + fill: #543;
569 +}
570 +
571 +.light #ov-topo svg #topo-sprites .sprite2 use {
572 + stroke: #bbd;
573 + stroke-width: 1.0;
574 + fill: none;
575 +}
576 +.dark #ov-topo svg #topo-sprites .sprite2 use {
577 + stroke: #445;
578 + stroke-width: 1.0;
579 + fill: none;
580 +}
581 +
582 +.light #ov-topo svg #topo-sprites .sprite2 text {
583 + fill: #cce;
584 +}
585 +.dark #ov-topo svg #topo-sprites .sprite2 text {
586 + fill: #446;
587 +}
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
33 tes, tfs, tps, tis, tss, tls, tts, tos, fltr, ttbs; 33 tes, tfs, tps, tis, tss, tls, tts, tos, fltr, ttbs;
34 34
35 // DOM elements 35 // DOM elements
36 - var ovtopo, svg, defs, zoomLayer, mapG, forceG, noDevsLayer; 36 + var ovtopo, svg, defs, zoomLayer, mapG, spriteG, forceG, noDevsLayer;
37 37
38 // Internal state 38 // Internal state
39 var zoomer, actionMap; 39 var zoomer, actionMap;
...@@ -53,6 +53,7 @@ ...@@ -53,6 +53,7 @@
53 P: [tfs.togglePorts, 'Toggle Port Highlighting'], 53 P: [tfs.togglePorts, 'Toggle Port Highlighting'],
54 dash: [tfs.showBadLinks, 'Show bad links'], 54 dash: [tfs.showBadLinks, 'Show bad links'],
55 B: [toggleMap, 'Toggle background map'], 55 B: [toggleMap, 'Toggle background map'],
56 + S: [toggleSprites, 'Toggle sprite layer'],
56 57
57 //X: [toggleNodeLock, 'Lock / unlock node positions'], 58 //X: [toggleNodeLock, 'Lock / unlock node positions'],
58 Z: [tos.toggleOblique, 'Toggle oblique view (Experimental)'], 59 Z: [tos.toggleOblique, 'Toggle oblique view (Experimental)'],
...@@ -116,6 +117,14 @@ ...@@ -116,6 +117,14 @@
116 flash.flash(verb + ' background map'); 117 flash.flash(verb + ' background map');
117 } 118 }
118 119
120 + function toggleSprites(x) {
121 + var on = (x === 'keyev') ? !sus.visible(spriteG) : !!x,
122 + verb = on ? 'Show' : 'Hide';
123 + sus.visible(spriteG, on);
124 + updatePrefsState('sprites', on);
125 + flash.flash(verb + ' sprite layer');
126 + }
127 +
119 function resetZoom() { 128 function resetZoom() {
120 zoomer.reset(); 129 zoomer.reset();
121 } 130 }
...@@ -247,24 +256,6 @@ ...@@ -247,24 +256,6 @@
247 .attr('opacity', b ? 1 : 0); 256 .attr('opacity', b ? 1 : 0);
248 } 257 }
249 258
250 - function addSprites() {
251 - var g = zoomLayer.append ('g').attr('id', 'topo-sprites');
252 -
253 - function cloud(g, x, y) {
254 - g.append('use').attr({
255 - width: 100,
256 - height: 100,
257 - 'xlink:href': '#cloud',
258 - transform: sus.translate([x, y]) + sus.scale(4,4)
259 - }).style('stroke', 'goldenrod')
260 - .style('fill', 'none')
261 - .style('stroke-width', 1.0);
262 - }
263 -
264 - cloud(g, 0, 50);
265 - cloud(g, 800, 40);
266 - cloud(g, 400, 450);
267 - }
268 259
269 // --- User Preferemces ---------------------------------------------- 260 // --- User Preferemces ----------------------------------------------
270 261
...@@ -285,6 +276,7 @@ ...@@ -285,6 +276,7 @@
285 toggleInstances(prefsState.insts); 276 toggleInstances(prefsState.insts);
286 toggleSummary(prefsState.summary); 277 toggleSummary(prefsState.summary);
287 toggleDetails(prefsState.detail); 278 toggleDetails(prefsState.detail);
279 + toggleSprites(prefsState.sprites);
288 } 280 }
289 281
290 282
...@@ -298,11 +290,11 @@ ...@@ -298,11 +290,11 @@
298 'TopoEventService', 'TopoForceService', 'TopoPanelService', 290 'TopoEventService', 'TopoForceService', 'TopoPanelService',
299 'TopoInstService', 'TopoSelectService', 'TopoLinkService', 291 'TopoInstService', 'TopoSelectService', 'TopoLinkService',
300 'TopoTrafficService', 'TopoObliqueService', 'TopoFilterService', 292 'TopoTrafficService', 'TopoObliqueService', 'TopoFilterService',
301 - 'TopoToolbarService', 293 + 'TopoToolbarService', 'TopoSpriteService',
302 294
303 function ($scope, _$log_, $loc, $timeout, _$cookies_, _fs_, mast, _ks_, 295 function ($scope, _$log_, $loc, $timeout, _$cookies_, _fs_, mast, _ks_,
304 _zs_, _gs_, _ms_, _sus_, _flash_, _wss_, _ps_, _tes_, _tfs_, 296 _zs_, _gs_, _ms_, _sus_, _flash_, _wss_, _ps_, _tes_, _tfs_,
305 - _tps_, _tis_, _tss_, _tls_, _tts_, _tos_, _fltr_, _ttbs_) { 297 + _tps_, _tis_, _tss_, _tls_, _tts_, _tos_, _fltr_, _ttbs_, tspr) {
306 var self = this, 298 var self = this,
307 projection, 299 projection,
308 dim, 300 dim,
...@@ -373,7 +365,8 @@ ...@@ -373,7 +365,8 @@
373 toggleMap(prefsState.bg); 365 toggleMap(prefsState.bg);
374 } 366 }
375 ); 367 );
376 - // addSprites(); 368 + spriteG = zoomLayer.append ('g').attr('id', 'topo-sprites');
369 + tspr.loadSprites(spriteG);
377 370
378 forceG = zoomLayer.append('g').attr('id', 'topo-force'); 371 forceG = zoomLayer.append('g').attr('id', 'topo-force');
379 tfs.initForce(svg, forceG, uplink, dim); 372 tfs.initForce(svg, forceG, uplink, dim);
......
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +/*
18 + ONOS GUI -- Topology Sprite Module.
19 + Defines behavior for loading sprites.
20 + */
21 +
22 +(function () {
23 + 'use strict';
24 +
25 + // injected refs
26 + var $log, $http, fs, sus;
27 +
28 + // internal state
29 + var spriteLayer,
30 + cache = d3.map();
31 +
32 + // constants
33 + var urlPrefix = 'data/ext/';
34 +
35 + function getUrl(id) {
36 + return urlPrefix + id + '.json';
37 + }
38 +
39 + // =========================
40 +
41 + function clearCache() {
42 + cache = d3.map();
43 + }
44 +
45 +
46 + function loadSpriteData(id, cb) {
47 + var url = getUrl(id),
48 + promise = cache.get(id);
49 +
50 + if (!promise) {
51 + // need to fetch data and cache it
52 + promise = $http.get(url);
53 +
54 + promise.meta = {
55 + id: id,
56 + url: url,
57 + wasCached: false
58 + };
59 +
60 + promise.then(function (response) {
61 + // success
62 + promise.spriteData = response.data;
63 + cb(promise.spriteData);
64 + }, function (response) {
65 + // error
66 + $log.warn('Failed to retrieve sprite data: ' + url,
67 + response.status, response.data);
68 + });
69 +
70 + } else {
71 + promise.meta.wasCached = true;
72 + cb(promise.spriteData);
73 + }
74 + }
75 +
76 + function doSprite(def, item) {
77 + var g;
78 +
79 + function xfm(x, y, s) {
80 + return sus.translate([x,y]) + sus.scale(s, s);
81 + }
82 +
83 + g = spriteLayer.append('g')
84 + .classed(def['class'], true)
85 + .attr('transform', xfm(item.x, item.y, def.scale));
86 +
87 + if (item.label) {
88 + g.append('text')
89 + .text(item.label)
90 + .attr({
91 + x: def.width / 2,
92 + y: def.height * def.textyoff
93 + });
94 + }
95 +
96 + g.append('use').attr({
97 + width: def.width,
98 + height: def.height,
99 + 'xlink:href': '#' + def.use
100 + });
101 + }
102 +
103 + function loadSprites(layer) {
104 + spriteLayer = layer;
105 +
106 + loadSpriteData('sprites', function (data) {
107 + var defs = {};
108 +
109 + $log.debug("Loading sprites...", data.file_desc);
110 +
111 + data.defn.forEach(function (d) {
112 + defs[d.id] = d;
113 + });
114 +
115 + data.load.forEach(function (item) {
116 + doSprite(defs[item.id], item);
117 + });
118 + });
119 +
120 + }
121 +
122 +
123 + // === -----------------------------------------------------
124 + // === MODULE DEFINITION ===
125 +
126 + angular.module('ovTopo')
127 + .factory('TopoSpriteService',
128 + ['$log', '$http', 'FnService', 'SvgUtilService',
129 +
130 + function (_$log_, _$http_, _fs_, _sus_) {
131 + $log = _$log_;
132 + $http = _$http_;
133 + fs = _fs_;
134 + sus = _sus_;
135 +
136 + return {
137 + clearCache: clearCache,
138 + loadSprites: loadSprites
139 + };
140 + }]);
141 +
142 +}());
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
42 M: { id: 'offline-tog', gid: 'switch', isel: true }, 42 M: { id: 'offline-tog', gid: 'switch', isel: true },
43 P: { id: 'ports-tog', gid: 'ports', isel: true }, 43 P: { id: 'ports-tog', gid: 'ports', isel: true },
44 B: { id: 'bkgrnd-tog', gid: 'map', isel: true }, 44 B: { id: 'bkgrnd-tog', gid: 'map', isel: true },
45 + S: { id: 'sprite-tog', gid: 'cloud', isel: false },
45 46
46 //X: { id: 'nodelock-tog', gid: 'lock', isel: false }, 47 //X: { id: 'nodelock-tog', gid: 'lock', isel: false },
47 Z: { id: 'oblique-tog', gid: 'oblique', isel: false }, 48 Z: { id: 'oblique-tog', gid: 'oblique', isel: false },
...@@ -62,6 +63,7 @@ ...@@ -62,6 +63,7 @@
62 // initial toggle state: default settings and tag to key mapping 63 // initial toggle state: default settings and tag to key mapping
63 var defaultPrefsState = { 64 var defaultPrefsState = {
64 bg: 1, 65 bg: 1,
66 + sprites: 0,
65 insts: 1, 67 insts: 1,
66 summary: 1, 68 summary: 1,
67 detail: 1, 69 detail: 1,
...@@ -69,6 +71,7 @@ ...@@ -69,6 +71,7 @@
69 }, 71 },
70 prefsMap = { 72 prefsMap = {
71 bg: 'B', 73 bg: 'B',
74 + sprites: 'S',
72 insts: 'I', 75 insts: 'I',
73 summary: 'O', 76 summary: 'O',
74 details: 'D', 77 details: 'D',
...@@ -129,6 +132,7 @@ ...@@ -129,6 +132,7 @@
129 addToggle('M'); 132 addToggle('M');
130 addToggle('P'); 133 addToggle('P');
131 addToggle('B'); 134 addToggle('B');
135 + addToggle('S');
132 } 136 }
133 function addSecondRow() { 137 function addSecondRow() {
134 //addToggle('X'); 138 //addToggle('X');
......
1 { 1 {
2 + "file_desc": "Cloud Sprite Data",
3 +
2 "_comment": [ 4 "_comment": [
3 "configuration file for loading canned and/or custom sprites (and labels)", 5 "configuration file for loading canned and/or custom sprites (and labels)",
4 "into the topology view. These appear above the map layer, but below", 6 "into the topology view. These appear above the map layer, but below",
5 "the nodes/links layer." 7 "the nodes/links layer."
6 ], 8 ],
7 9
8 - "_comment_defn": "'defn' array contains custom sprite definitions", 10 + "_comment_custom": "'custom' contains custom path data",
9 - "defn": [ 11 + "custom": [
10 12
11 ], 13 ],
12 14
13 - "_comment_defstyle": "'defstyle' defines default styles to apply", 15 + "_comment_defn": "'defn' array contains sprite definitions",
14 - "defstyle": { 16 + "defn": [
15 - "sprite": { 17 + {
16 - "stroke": "goldenrod", 18 + "id": "subnet",
17 - "stroke-width": 1.0, 19 + "class": "sprite1",
18 - "fill": "none" 20 + "use": "cloud",
21 + "width": 120,
22 + "height": 120,
23 + "scale": 3.0,
24 + "textyoff": 0.4
19 }, 25 },
20 - "text": { 26 + {
21 - "text-style": "italic", 27 + "id": "subnet2",
22 - "test-size": "20pt" 28 + "class": "sprite2",
29 + "use": "cloud",
30 + "width": 200,
31 + "height": 200,
32 + "scale": 3.0,
33 + "textyoff": 0.4
23 } 34 }
24 - },
25 -
26 - "_comment_load": [
27 - "'load' array contains list of sprites/labels to load",
28 - " note that 'copies' array defines [x,y] coords to position copies"
29 ], 35 ],
36 +
37 + "_comment_load": "'load' array contains list of sprites to load",
30 "load": [ 38 "load": [
31 - { 39 + { "id": "subnet", "x": -40, "y":20, "label":"apples" },
32 - "id": "cloud", 40 + { "id": "subnet", "x":400, "y":40, "label":"bananas" },
33 - "width": 100, 41 + { "id": "subnet", "x":840, "y":60, "label":"cherries" },
34 - "height": 100, 42 + { "id": "subnet2", "x":300, "y":400 }
35 - "scale": 4.0,
36 - "copies": [
37 - [0, 50], [800, 40], [400, 450]
38 - ],
39 - "style": {
40 - "stroke": "green"
41 - }
42 - }
43 ] 43 ]
44 } 44 }
......
...@@ -107,6 +107,7 @@ ...@@ -107,6 +107,7 @@
107 <script src="app/view/topo/topoOblique.js"></script> 107 <script src="app/view/topo/topoOblique.js"></script>
108 <script src="app/view/topo/topoPanel.js"></script> 108 <script src="app/view/topo/topoPanel.js"></script>
109 <script src="app/view/topo/topoSelect.js"></script> 109 <script src="app/view/topo/topoSelect.js"></script>
110 + <script src="app/view/topo/topoSprite.js"></script>
110 <script src="app/view/topo/topoTraffic.js"></script> 111 <script src="app/view/topo/topoTraffic.js"></script>
111 <script src="app/view/topo/topoToolbar.js"></script> 112 <script src="app/view/topo/topoToolbar.js"></script>
112 <script src="app/view/device/device.js"></script> 113 <script src="app/view/device/device.js"></script>
......