GUI -- Completed Show Summary panel.
- added GlyphService.addGlyph(). - added SvgUtilService.translate(). Change-Id: I0bbc51a8f1d9c24b8b4f1377236570070da6f160
Showing
8 changed files
with
143 additions
and
36 deletions
web/gui/src/main/webapp/app/fw/svg/glyph.css
0 → 100644
| 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,11 +135,6 @@ | ... | @@ -133,11 +135,6 @@ |
| 133 | 135 | ||
| 134 | // ---------------------------------------------------------------------- | 136 | // ---------------------------------------------------------------------- |
| 135 | 137 | ||
| 136 | - angular.module('onosSvg') | ||
| 137 | - .factory('GlyphService', ['$log', 'FnService', function (_$log_, _fs_) { | ||
| 138 | - $log = _$log_; | ||
| 139 | - fs = _fs_; | ||
| 140 | - | ||
| 141 | function clear() { | 138 | function clear() { |
| 142 | // start with a fresh map | 139 | // start with a fresh map |
| 143 | glyphs = d3.map(); | 140 | glyphs = d3.map(); |
| ... | @@ -206,14 +203,45 @@ | ... | @@ -206,14 +203,45 @@ |
| 206 | }); | 203 | }); |
| 207 | } | 204 | } |
| 208 | 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 | + }; | ||
| 216 | + | ||
| 217 | + if (xns) { | ||
| 218 | + atr.transform = sus.translate(trans); | ||
| 219 | + } | ||
| 220 | + elem.append('use').attr(atr).classed('overlay', ovr); | ||
| 221 | + | ||
| 222 | + } | ||
| 223 | + | ||
| 224 | + // ---------------------------------------------------------------------- | ||
| 225 | + | ||
| 226 | + angular.module('onosSvg') | ||
| 227 | + .factory('GlyphService', | ||
| 228 | + ['$log', 'FnService', 'SvgUtilService', | ||
| 229 | + | ||
| 230 | + function (_$log_, _fs_, _sus_) { | ||
| 231 | + $log = _$log_; | ||
| 232 | + fs = _fs_; | ||
| 233 | + sus = _sus_; | ||
| 234 | + | ||
| 209 | return { | 235 | return { |
| 210 | clear: clear, | 236 | clear: clear, |
| 211 | init: init, | 237 | init: init, |
| 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 | }); | ... | ... |
-
Please register or login to post a comment