Simon Hunt

GUI -- Completed Show Summary panel.

- added GlyphService.addGlyph().
- added SvgUtilService.translate().

Change-Id: I0bbc51a8f1d9c24b8b4f1377236570070da6f160
1 +/*
2 + * Copyright 2014,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 -- Glyph Service -- CSS file
19 + */
20 +
21 +svg .glyph {
22 + stroke: none;
23 + fill-rule: evenodd;
24 +}
25 +
26 +.light svg .glyph,
27 +.dark svg .glyph.overlay {
28 + fill: black;
29 +}
30 +
31 +.dark svg .glyph,
32 +.light svg .glyph.overlay {
33 + fill: white;
34 +}
...@@ -20,9 +20,11 @@ ...@@ -20,9 +20,11 @@
20 (function () { 20 (function () {
21 'use strict'; 21 'use strict';
22 22
23 - var $log, 23 + // injected references
24 - fs, 24 + var $log, fs, sus;
25 - glyphs = d3.map(), 25 +
26 + // internal state
27 + var glyphs = d3.map(),
26 msgGS = 'GlyphService.'; 28 msgGS = 'GlyphService.';
27 29
28 // ---------------------------------------------------------------------- 30 // ----------------------------------------------------------------------
...@@ -133,78 +135,102 @@ ...@@ -133,78 +135,102 @@
133 135
134 // ---------------------------------------------------------------------- 136 // ----------------------------------------------------------------------
135 137
136 - angular.module('onosSvg') 138 + function clear() {
137 - .factory('GlyphService', ['$log', 'FnService', function (_$log_, _fs_) { 139 + // start with a fresh map
138 - $log = _$log_; 140 + glyphs = d3.map();
139 - fs = _fs_; 141 + }
140 - 142 +
141 - function clear() { 143 + function init() {
142 - // start with a fresh map 144 + clear();
143 - glyphs = d3.map(); 145 + register(birdViewBox, birdData);
146 + register(glyphViewBox, glyphData);
147 + register(badgeViewBox, badgeData);
148 + }
149 +
150 + function register(viewBox, data, overwrite) {
151 + var dmap = d3.map(data),
152 + dups = [],
153 + ok;
154 +
155 + dmap.forEach(function (key, value) {
156 + if (!overwrite && glyphs.get(key)) {
157 + dups.push(key);
158 + } else {
159 + glyphs.set(key, {id: key, vb: viewBox, d: value});
144 } 160 }
145 - 161 + });
146 - function init() { 162 + ok = (dups.length == 0);
147 - clear(); 163 + if (!ok) {
148 - register(birdViewBox, birdData); 164 + dups.forEach(function (id) {
149 - register(glyphViewBox, glyphData); 165 + $log.warn(msgGS + 'register(): ID collision: "'+id+'"');
150 - register(badgeViewBox, badgeData); 166 + });
151 - } 167 + }
152 - 168 + return ok;
153 - function register(viewBox, data, overwrite) { 169 + }
154 - var dmap = d3.map(data), 170 +
155 - dups = [], 171 + function ids() {
156 - ok; 172 + return glyphs.keys();
157 - 173 + }
158 - dmap.forEach(function (key, value) { 174 +
159 - if (!overwrite && glyphs.get(key)) { 175 + function glyph(id) {
160 - dups.push(key); 176 + return glyphs.get(id);
161 - } else { 177 + }
162 - glyphs.set(key, {id: key, vb: viewBox, d: value}); 178 +
179 + // Note: defs should be a D3 selection of a single <defs> element
180 + function loadDefs(defs, glyphIds, noClear) {
181 + var list = fs.isA(glyphIds) || ids(),
182 + clearCache = !noClear;
183 +
184 + if (clearCache) {
185 + // remove all existing content
186 + defs.html(null);
187 + }
188 +
189 + // load up the requested glyphs
190 + list.forEach(function (id) {
191 + var g = glyph(id);
192 + if (g) {
193 + if (noClear) {
194 + // quick exit if symbol is already present
195 + if (defs.select('symbol#' + g.id).size() > 0) {
196 + return;
163 } 197 }
164 - });
165 - ok = (dups.length == 0);
166 - if (!ok) {
167 - dups.forEach(function (id) {
168 - $log.warn(msgGS + 'register(): ID collision: "'+id+'"');
169 - });
170 } 198 }
171 - return ok; 199 + defs.append('symbol')
200 + .attr({ id: g.id, viewBox: g.vb })
201 + .append('path').attr('d', g.d);
172 } 202 }
203 + });
204 + }
205 +
206 + function addGlyph(elem, glyphId, size, overlay, trans) {
207 + var sz = size || 40,
208 + ovr = !!overlay,
209 + xns = fs.isA(trans),
210 + atr = {
211 + width: sz,
212 + height: sz,
213 + 'class': 'glyph',
214 + 'xlink:href': '#' + glyphId
215 + };
173 216
174 - function ids() { 217 + if (xns) {
175 - return glyphs.keys(); 218 + atr.transform = sus.translate(trans);
176 - } 219 + }
220 + elem.append('use').attr(atr).classed('overlay', ovr);
177 221
178 - function glyph(id) { 222 + }
179 - return glyphs.get(id);
180 - }
181 223
182 - // Note: defs should be a D3 selection of a single <defs> element 224 + // ----------------------------------------------------------------------
183 - function loadDefs(defs, glyphIds, noClear) {
184 - var list = fs.isA(glyphIds) || ids(),
185 - clearCache = !noClear;
186 225
187 - if (clearCache) { 226 + angular.module('onosSvg')
188 - // remove all existing content 227 + .factory('GlyphService',
189 - defs.html(null); 228 + ['$log', 'FnService', 'SvgUtilService',
190 - }
191 229
192 - // load up the requested glyphs 230 + function (_$log_, _fs_, _sus_) {
193 - list.forEach(function (id) { 231 + $log = _$log_;
194 - var g = glyph(id); 232 + fs = _fs_;
195 - if (g) { 233 + sus = _sus_;
196 - if (noClear) {
197 - // quick exit if symbol is already present
198 - if (defs.select('symbol#' + g.id).size() > 0) {
199 - return;
200 - }
201 - }
202 - defs.append('symbol')
203 - .attr({ id: g.id, viewBox: g.vb })
204 - .append('path').attr('d', g.d);
205 - }
206 - });
207 - }
208 234
209 return { 235 return {
210 clear: clear, 236 clear: clear,
...@@ -212,8 +238,10 @@ ...@@ -212,8 +238,10 @@
212 register: register, 238 register: register,
213 ids: ids, 239 ids: ids,
214 glyph: glyph, 240 glyph: glyph,
215 - loadDefs: loadDefs 241 + loadDefs: loadDefs,
242 + addGlyph: addGlyph
216 }; 243 };
217 - }]); 244 + }]
245 + );
218 246
219 }()); 247 }());
......
...@@ -136,10 +136,18 @@ ...@@ -136,10 +136,18 @@
136 $log.warn('SvgUtilService: cat7 -- To Be Implemented'); 136 $log.warn('SvgUtilService: cat7 -- To Be Implemented');
137 } 137 }
138 138
139 + function translate(x, y) {
140 + if (fs.isA(x) && x.length === 2 && !y) {
141 + return 'translate(' + x[0] + ',' + x[1] + ')';
142 + }
143 + return 'translate(' + x + ',' + y + ')';
144 + }
145 +
139 return { 146 return {
140 createDragBehavior: createDragBehavior, 147 createDragBehavior: createDragBehavior,
141 loadGlow: loadGlow, 148 loadGlow: loadGlow,
142 - cat7: cat7 149 + cat7: cat7,
150 + translate: translate
143 }; 151 };
144 }]); 152 }]);
145 }()); 153 }());
......
...@@ -66,6 +66,7 @@ ...@@ -66,6 +66,7 @@
66 <link rel="stylesheet" href="onos.css"> 66 <link rel="stylesheet" href="onos.css">
67 <link rel="stylesheet" href="common.css"> 67 <link rel="stylesheet" href="common.css">
68 <link rel="stylesheet" href="fw/mast/mast.css"> 68 <link rel="stylesheet" href="fw/mast/mast.css">
69 + <link rel="stylesheet" href="fw/svg/glyph.css">
69 <link rel="stylesheet" href="fw/svg/icon.css"> 70 <link rel="stylesheet" href="fw/svg/icon.css">
70 <link rel="stylesheet" href="fw/layer/panel.css"> 71 <link rel="stylesheet" href="fw/layer/panel.css">
71 <link rel="stylesheet" href="fw/nav/nav.css"> 72 <link rel="stylesheet" href="fw/nav/nav.css">
......
...@@ -56,17 +56,6 @@ ...@@ -56,17 +56,6 @@
56 height: 42px; 56 height: 42px;
57 } 57 }
58 58
59 -#topo-p-summary svg .glyphIcon {
60 - stroke: none;
61 - fill-rule: evenodd;
62 -}
63 -.light #topo-p-summary svg .glyphIcon {
64 - fill: black;
65 -}
66 -.dark #topo-p-summary svg .glyphIcon {
67 - fill: #ddd;
68 -}
69 -
70 #topo-p-summary h2 { 59 #topo-p-summary h2 {
71 position: absolute; 60 position: absolute;
72 margin: 0 4px; 61 margin: 0 4px;
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
23 'use strict'; 23 'use strict';
24 24
25 // injected refs 25 // injected refs
26 - var $log, ps; 26 + var $log, ps, gs;
27 27
28 // constants 28 // constants
29 var idSum = 'topo-p-summary', 29 var idSum = 'topo-p-summary',
...@@ -70,18 +70,15 @@ ...@@ -70,18 +70,15 @@
70 function populateSummary(data) { 70 function populateSummary(data) {
71 summaryPanel.empty(); 71 summaryPanel.empty();
72 72
73 - var svg = summaryPanel.append('svg').attr({ 73 + var svg = summaryPanel.append('svg'); //.style('background-color', 'goldenrod'),
74 - width: 40, 74 + //iid = '#' + (data.type || 'unknown');
75 - height: 40
76 - }).style('background-color', 'goldenrod'),
77 - iid = '#' + (data.type || 'unknown');
78 75
79 var title = summaryPanel.append('h2'), 76 var title = summaryPanel.append('h2'),
80 table = summaryPanel.append('table'), 77 table = summaryPanel.append('table'),
81 tbody = table.append('tbody'); 78 tbody = table.append('tbody');
82 79
83 - // append glyph iid to SVG // black fill 80 + gs.addGlyph(svg, 'node', 40);
84 - // append glyph bird to SVG // white fill 81 + gs.addGlyph(svg, 'bird', 24, true, [8,12]);
85 82
86 title.text(data.id); 83 title.text(data.id);
87 84
...@@ -103,11 +100,12 @@ ...@@ -103,11 +100,12 @@
103 100
104 angular.module('ovTopo') 101 angular.module('ovTopo')
105 .factory('TopoPanelService', 102 .factory('TopoPanelService',
106 - ['$log', 'PanelService', 103 + ['$log', 'PanelService', 'GlyphService',
107 104
108 - function (_$log_, _ps_) { 105 + function (_$log_, _ps_, _gs_) {
109 $log = _$log_; 106 $log = _$log_;
110 ps = _ps_; 107 ps = _ps_;
108 + gs = _gs_;
111 109
112 function initPanels() { 110 function initPanels() {
113 summaryPanel = ps.createPanel(idSum, panelOpts); 111 summaryPanel = ps.createPanel(idSum, panelOpts);
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
18 ONOS GUI -- SVG -- Glyph Service - Unit Tests 18 ONOS GUI -- SVG -- Glyph Service - Unit Tests
19 */ 19 */
20 describe('factory: fw/svg/glyph.js', function() { 20 describe('factory: fw/svg/glyph.js', function() {
21 - var $log, fs, gs, d3Elem; 21 + var $log, fs, gs, d3Elem, svg;
22 22
23 var numBaseGlyphs = 13, 23 var numBaseGlyphs = 13,
24 vbBird = '352 224 113 112', 24 vbBird = '352 224 113 112',
...@@ -47,13 +47,16 @@ describe('factory: fw/svg/glyph.js', function() { ...@@ -47,13 +47,16 @@ describe('factory: fw/svg/glyph.js', function() {
47 beforeEach(module('onosUtil', 'onosSvg')); 47 beforeEach(module('onosUtil', 'onosSvg'));
48 48
49 beforeEach(inject(function (_$log_, FnService, GlyphService) { 49 beforeEach(inject(function (_$log_, FnService, GlyphService) {
50 + var body = d3.select('body');
50 $log = _$log_; 51 $log = _$log_;
51 fs = FnService; 52 fs = FnService;
52 gs = GlyphService; 53 gs = GlyphService;
53 - d3Elem = d3.select('body').append('defs').attr('id', 'myDefs'); 54 + d3Elem = body.append('defs').attr('id', 'myDefs');
55 + svg = body.append('svg').attr('id', 'mySvg');
54 })); 56 }));
55 57
56 afterEach(function () { 58 afterEach(function () {
59 + d3.select('#mySvg').remove();
57 d3.select('#myDefs').remove(); 60 d3.select('#myDefs').remove();
58 gs.clear(); 61 gs.clear();
59 }); 62 });
...@@ -64,7 +67,7 @@ describe('factory: fw/svg/glyph.js', function() { ...@@ -64,7 +67,7 @@ describe('factory: fw/svg/glyph.js', function() {
64 67
65 it('should define api functions', function () { 68 it('should define api functions', function () {
66 expect(fs.areFunctions(gs, [ 69 expect(fs.areFunctions(gs, [
67 - 'clear', 'init', 'register', 'ids', 'glyph', 'loadDefs' 70 + 'clear', 'init', 'register', 'ids', 'glyph', 'loadDefs', 'addGlyph'
68 ])).toBeTruthy(); 71 ])).toBeTruthy();
69 }); 72 });
70 73
...@@ -246,4 +249,40 @@ describe('factory: fw/svg/glyph.js', function() { ...@@ -246,4 +249,40 @@ describe('factory: fw/svg/glyph.js', function() {
246 verifyLoadedInDom('chain', vbGlyph); 249 verifyLoadedInDom('chain', vbGlyph);
247 verifyLoadedInDom('node', vbGlyph); 250 verifyLoadedInDom('node', vbGlyph);
248 }); 251 });
252 +
253 + it('should add a glyph with default size', function () {
254 + gs.init();
255 + gs.addGlyph(svg, 'crown');
256 + var what = svg.selectAll('use');
257 + expect(what.size()).toEqual(1);
258 + expect(what.attr('width')).toEqual('40');
259 + expect(what.attr('height')).toEqual('40');
260 + expect(what.attr('xlink:href')).toEqual('#crown');
261 + expect(what.classed('glyph')).toBeTruthy();
262 + expect(what.classed('overlay')).toBeFalsy();
263 + });
264 +
265 + it('should add a glyph with given size', function () {
266 + gs.init();
267 + gs.addGlyph(svg, 'crown', 37);
268 + var what = svg.selectAll('use');
269 + expect(what.size()).toEqual(1);
270 + expect(what.attr('width')).toEqual('37');
271 + expect(what.attr('height')).toEqual('37');
272 + expect(what.attr('xlink:href')).toEqual('#crown');
273 + expect(what.classed('glyph')).toBeTruthy();
274 + expect(what.classed('overlay')).toBeFalsy();
275 + });
276 +
277 + it('should add a glyph marked as overlay', function () {
278 + gs.init();
279 + gs.addGlyph(svg, 'crown', 20, true);
280 + var what = svg.selectAll('use');
281 + expect(what.size()).toEqual(1);
282 + expect(what.attr('width')).toEqual('20');
283 + expect(what.attr('height')).toEqual('20');
284 + expect(what.attr('xlink:href')).toEqual('#crown');
285 + expect(what.classed('glyph')).toBeTruthy();
286 + expect(what.classed('overlay')).toBeTruthy();
287 + });
249 }); 288 });
......
...@@ -39,8 +39,18 @@ describe('factory: fw/svg/svgUtil.js', function() { ...@@ -39,8 +39,18 @@ describe('factory: fw/svg/svgUtil.js', function() {
39 39
40 it('should define api functions', function () { 40 it('should define api functions', function () {
41 expect(fs.areFunctions(sus, [ 41 expect(fs.areFunctions(sus, [
42 - 'createDragBehavior', 'loadGlow', 'cat7' 42 + 'createDragBehavior', 'loadGlow', 'cat7', 'translate'
43 ])).toBeTruthy(); 43 ])).toBeTruthy();
44 }); 44 });
45 45
46 + // TODO: add unit tests for drag behavior etc.
47 +
48 + it('should translate from two args', function () {
49 + expect(sus.translate(1,2)).toEqual('translate(1,2)');
50 + });
51 +
52 + it('should translate from an array', function () {
53 + expect(sus.translate([3,4])).toEqual('translate(3,4)');
54 + });
55 +
46 }); 56 });
......