Simon Hunt

GUI -- Working towards embedding icons in tables. WIP.

- Skeleton of icon directive added.
- icons embedded in table - test HTML file.
- Augmented GlyphService.loadDefs() to allow subset of glyph ids to be specified.

Change-Id: I775a958ef9dc35b0b89a126d5c0497f72a721b71
1 +<!DOCTYPE html>
2 +<!--
3 + ~ Copyright 2015 Open Networking Laboratory
4 + ~
5 + ~ Licensed under the Apache License, Version 2.0 (the "License");
6 + ~ you may not use this file except in compliance with the License.
7 + ~ You may obtain a copy of the License at
8 + ~
9 + ~ http://www.apache.org/licenses/LICENSE-2.0
10 + ~
11 + ~ Unless required by applicable law or agreed to in writing, software
12 + ~ distributed under the License is distributed on an "AS IS" BASIS,
13 + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 + ~ See the License for the specific language governing permissions and
15 + ~ limitations under the License.
16 + -->
17 +
18 +<!--
19 + ONOS -- Embedded icon test page
20 +
21 + @author Simon Hunt
22 + @author Bri Prebilic Cole
23 + -->
24 +<html>
25 +<head>
26 + <meta charset="utf-8">
27 + <title>Embedded Icons</title>
28 +
29 + <script src="../tp/d3.js"></script>
30 +
31 + <link rel="stylesheet" href="../app/common.css">
32 +
33 + <style>
34 + html,
35 + body {
36 + background-color: #fff;
37 + font-family: Arial, Helvetica, sans-serif;
38 + font-size: 9pt;
39 + }
40 +
41 + svg .icon .glyph {
42 + stroke: none;
43 + fill: white;
44 + fill-rule: evenodd;
45 + }
46 +
47 + svg .icon.deviceOnline {
48 + fill: green;
49 + }
50 +
51 + svg .icon.deviceOffline {
52 + fill: darkred;
53 + }
54 +
55 + svg .icon rect {
56 + stroke: black;
57 + stroke-width: 1px;
58 + }
59 +
60 + </style>
61 +</head>
62 +<body class="light">
63 +<!-- minimal framework to access glyphs library module -->
64 +<script>
65 + var libs = {};
66 + var ONOS = { ui: { addLib: function (id, things) { libs[id] = things; }}};
67 +
68 +
69 +</script>
70 +
71 +<!-- Test HTML -->
72 +
73 +<div>
74 + <table class="summary-list">
75 + <tr> <th>One</th> <th>Two</th> <th>Three</th> </tr>
76 + <tr>
77 + <td>
78 + <div icon icon-id="deviceOnline">
79 +
80 + <!-- icon directive needs to inject the following structure -->
81 + <!-- ------------------------------------------------ -->
82 + <svg width="20" height="20" viewBox="0 0 50 50">
83 + <g class="icon deviceOnline">
84 + <rect width="50" height="50" rx="4"></rect>
85 + <use class="glyph" xlink:href="#ui" width="50" height="50"></use>
86 + </g>
87 + </svg>
88 + <!-- ------------------------------------------------ -->
89 +
90 + </div>
91 + </td>
92 + <td>Some text</td>
93 + <td>Some text</td>
94 + </tr>
95 + <tr>
96 + <td>
97 + <div icon icon-id="deviceOffline">
98 +
99 + <!-- icon directive needs to inject the following structure -->
100 + <!-- ------------------------------------------------ -->
101 + <svg width="20" height="20" viewBox="0 0 50 50">
102 + <g class="icon deviceOffline">
103 + <rect width="50" height="50" rx="4"></rect>
104 + <use class="glyph" xlink:href="#ui" width="50" height="50"></use>
105 + </g>
106 + </svg>
107 + <!-- ------------------------------------------------ -->
108 +
109 +
110 + </div>
111 + </td>
112 + <td>Some text</td>
113 + <td>Some Other text</td>
114 + </tr>
115 + </table>
116 +</div>
117 +
118 +<!-- common definitions for other SVG elements to use -->
119 +<svg width="0" height="0">
120 + <defs>
121 + <symbol id="ui" viewBox="0 0 10 10">
122 + <path d="M2,2.5a.5,.5,0,0,1,.5-.5h5
123 + a.5,.5,0,0,1,.5,.5v3a.5,.5,0,0,1-.5,.5h-5a.5,
124 + .5,0,0,1-.5-.5zM2.5,2.8a.3,.3,0,0,1,.3-.3
125 + h4.4a.3,.3,0,0,1,.3,.3v2.4a.3,.3,0,0,1-.3,
126 + .3h-4.4a.3,.3,0,0,1-.3-.3zM2,6.55h6l1,1.45h-8z">
127 + </path>
128 + </symbol>
129 + </defs>
130 +</svg>
131 +
132 +</body>
133 +</html>
...@@ -22,8 +22,7 @@ ...@@ -22,8 +22,7 @@
22 */ 22 */
23 23
24 table.summary-list { 24 table.summary-list {
25 - /*border: 1px solid red;*/ 25 + margin: 4px 4px;
26 - margin: 4px 50px;
27 font-size: 10pt; 26 font-size: 10pt;
28 } 27 }
29 28
......
...@@ -56,4 +56,23 @@ ...@@ -56,4 +56,23 @@
56 }; 56 };
57 }]) 57 }])
58 58
59 +
60 + // create icon directive, so that we can inject icons into
61 + // HTML tables etc.
62 + .directive('icon', ['GlyphService', function (gs) {
63 + return {
64 + templateUrl: 'toBeDecided-iconContext.html',
65 + restrict: 'A',
66 + link: function (scope, element, attrs) {
67 + // TODO: implement this
68 + // needs to pull out the parameters for the icon
69 + // from the attributes of the element, and use those
70 + // as arguments to the IconService.addIcon(...) call.
71 +
72 +
73 + }
74 + };
75 +
76 +
77 + }]);
59 }()); 78 }());
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
23 'use strict'; 23 'use strict';
24 24
25 var $log, 25 var $log,
26 + fs,
26 glyphs = d3.map(), 27 glyphs = d3.map(),
27 msgGS = 'GlyphService.'; 28 msgGS = 'GlyphService.';
28 29
...@@ -121,8 +122,9 @@ ...@@ -121,8 +122,9 @@
121 // ---------------------------------------------------------------------- 122 // ----------------------------------------------------------------------
122 123
123 angular.module('onosSvg') 124 angular.module('onosSvg')
124 - .factory('GlyphService', ['$log', function (_$log_) { 125 + .factory('GlyphService', ['$log', 'FnService', function (_$log_, _fs_) {
125 $log = _$log_; 126 $log = _$log_;
127 + fs = _fs_;
126 128
127 function clear() { 129 function clear() {
128 // start with a fresh map 130 // start with a fresh map
...@@ -166,15 +168,20 @@ ...@@ -166,15 +168,20 @@
166 } 168 }
167 169
168 // Note: defs should be a D3 selection of a single <defs> element 170 // Note: defs should be a D3 selection of a single <defs> element
169 - function loadDefs(defs) { 171 + function loadDefs(defs, glyphIds) {
172 + var list = fs.isA(glyphIds) || ids();
173 +
170 // remove all existing content 174 // remove all existing content
171 defs.html(null); 175 defs.html(null);
172 176
173 - // load up the currently registered glyphs 177 + // load up the requested glyphs
174 - glyphs.values().forEach(function (g) { 178 + list.forEach(function (id) {
175 - defs.append('symbol') 179 + var g = glyph(id);
176 - .attr({ id: g.id, viewBox: g.vb }) 180 + if (g) {
177 - .append('path').attr('d', g.d); 181 + defs.append('symbol')
182 + .attr({ id: g.id, viewBox: g.vb })
183 + .append('path').attr('d', g.d);
184 + }
178 }); 185 });
179 } 186 }
180 187
......
...@@ -25,7 +25,24 @@ describe('factory: fw/svg/glyph.js', function() { ...@@ -25,7 +25,24 @@ describe('factory: fw/svg/glyph.js', function() {
25 var numBaseGlyphs = 11, 25 var numBaseGlyphs = 11,
26 vbBird = '352 224 113 112', 26 vbBird = '352 224 113 112',
27 vbGlyph = '0 0 110 110', 27 vbGlyph = '0 0 110 110',
28 - vbBadge = '0 0 10 10'; 28 + vbBadge = '0 0 10 10',
29 + prefixLookup = {
30 + bird: 'M427.7,300.4',
31 + unknown: 'M35,40a5',
32 + node: 'M15,100a5',
33 + switch: 'M10,20a10',
34 + roadm: 'M10,35l25-',
35 + endstation: 'M10,15a5,5',
36 + router: 'M10,55A45,45',
37 + bgpSpeaker: 'M10,40a45,35',
38 + chain: 'M60.4,77.6c-',
39 + crown: 'M99.5,21.6c0,',
40 + uiAttached: 'M2,2.5a.5,.5',
41 +
42 + // our test ones..
43 + triangle: 'M.5,.2',
44 + diamond: 'M.2,.5'
45 + };
29 46
30 beforeEach(module('onosUtil', 'onosSvg')); 47 beforeEach(module('onosUtil', 'onosSvg'));
31 48
...@@ -47,7 +64,7 @@ describe('factory: fw/svg/glyph.js', function() { ...@@ -47,7 +64,7 @@ describe('factory: fw/svg/glyph.js', function() {
47 64
48 it('should define api functions', function () { 65 it('should define api functions', function () {
49 expect(fs.areFunctions(gs, [ 66 expect(fs.areFunctions(gs, [
50 - 'init', 'register', 'ids', 'glyph', 'loadDefs' 67 + 'clear', 'init', 'register', 'ids', 'glyph', 'loadDefs'
51 ])).toBeTruthy(); 68 ])).toBeTruthy();
52 }); 69 });
53 70
...@@ -55,20 +72,22 @@ describe('factory: fw/svg/glyph.js', function() { ...@@ -55,20 +72,22 @@ describe('factory: fw/svg/glyph.js', function() {
55 expect(gs.ids()).toEqual([]); 72 expect(gs.ids()).toEqual([]);
56 }); 73 });
57 74
58 - it('should load the base set of glyphs', function () { 75 + it('should load the base set of glyphs into the cache', function () {
59 gs.init(); 76 gs.init();
60 expect(gs.ids().length).toEqual(numBaseGlyphs); 77 expect(gs.ids().length).toEqual(numBaseGlyphs);
61 }); 78 });
62 79
63 - it('should remove glyphs on clear', function () { 80 + it('should remove glyphs from the cache on clear', function () {
64 gs.init(); 81 gs.init();
65 expect(gs.ids().length).toEqual(numBaseGlyphs); 82 expect(gs.ids().length).toEqual(numBaseGlyphs);
66 gs.clear(); 83 gs.clear();
67 expect(gs.ids().length).toEqual(0); 84 expect(gs.ids().length).toEqual(0);
68 }); 85 });
69 86
70 - function verifyGlyphLoaded(id, vbox, prefix) { 87 + function verifyGlyphLoadedInCache(id, vbox, expPfxId) {
71 - var glyph = gs.glyph(id), 88 + var pfxId = expPfxId || id,
89 + glyph = gs.glyph(id),
90 + prefix = prefixLookup[pfxId],
72 plen = prefix.length; 91 plen = prefix.length;
73 expect(fs.contains(gs.ids(), id)).toBeTruthy(); 92 expect(fs.contains(gs.ids(), id)).toBeTruthy();
74 expect(glyph).toBeDefined(); 93 expect(glyph).toBeDefined();
...@@ -79,47 +98,47 @@ describe('factory: fw/svg/glyph.js', function() { ...@@ -79,47 +98,47 @@ describe('factory: fw/svg/glyph.js', function() {
79 98
80 it('should load the bird glyph', function() { 99 it('should load the bird glyph', function() {
81 gs.init(); 100 gs.init();
82 - verifyGlyphLoaded('bird', vbBird, 'M427.7,300.4'); 101 + verifyGlyphLoadedInCache('bird', vbBird);
83 }); 102 });
84 it('should load the unknown glyph', function() { 103 it('should load the unknown glyph', function() {
85 gs.init(); 104 gs.init();
86 - verifyGlyphLoaded('unknown', vbGlyph, 'M35,40a5'); 105 + verifyGlyphLoadedInCache('unknown', vbGlyph);
87 }); 106 });
88 it('should load the node glyph', function() { 107 it('should load the node glyph', function() {
89 gs.init(); 108 gs.init();
90 - verifyGlyphLoaded('node', vbGlyph, 'M15,100a5'); 109 + verifyGlyphLoadedInCache('node', vbGlyph);
91 }); 110 });
92 it('should load the switch glyph', function() { 111 it('should load the switch glyph', function() {
93 gs.init(); 112 gs.init();
94 - verifyGlyphLoaded('switch', vbGlyph, 'M10,20a10'); 113 + verifyGlyphLoadedInCache('switch', vbGlyph);
95 }); 114 });
96 it('should load the roadm glyph', function() { 115 it('should load the roadm glyph', function() {
97 gs.init(); 116 gs.init();
98 - verifyGlyphLoaded('roadm', vbGlyph, 'M10,35l25-'); 117 + verifyGlyphLoadedInCache('roadm', vbGlyph);
99 }); 118 });
100 it('should load the endstation glyph', function() { 119 it('should load the endstation glyph', function() {
101 gs.init(); 120 gs.init();
102 - verifyGlyphLoaded('endstation', vbGlyph, 'M10,15a5,5'); 121 + verifyGlyphLoadedInCache('endstation', vbGlyph);
103 }); 122 });
104 it('should load the router glyph', function() { 123 it('should load the router glyph', function() {
105 gs.init(); 124 gs.init();
106 - verifyGlyphLoaded('router', vbGlyph, 'M10,55A45,45'); 125 + verifyGlyphLoadedInCache('router', vbGlyph);
107 }); 126 });
108 it('should load the bgpSpeaker glyph', function() { 127 it('should load the bgpSpeaker glyph', function() {
109 gs.init(); 128 gs.init();
110 - verifyGlyphLoaded('bgpSpeaker', vbGlyph, 'M10,40a45,35'); 129 + verifyGlyphLoadedInCache('bgpSpeaker', vbGlyph);
111 }); 130 });
112 it('should load the chain glyph', function() { 131 it('should load the chain glyph', function() {
113 gs.init(); 132 gs.init();
114 - verifyGlyphLoaded('chain', vbGlyph, 'M60.4,77.6c-'); 133 + verifyGlyphLoadedInCache('chain', vbGlyph);
115 }); 134 });
116 it('should load the crown glyph', function() { 135 it('should load the crown glyph', function() {
117 gs.init(); 136 gs.init();
118 - verifyGlyphLoaded('crown', vbGlyph, 'M99.5,21.6c0'); 137 + verifyGlyphLoadedInCache('crown', vbGlyph);
119 }); 138 });
120 it('should load the uiAttached glyph', function() { 139 it('should load the uiAttached glyph', function() {
121 gs.init(); 140 gs.init();
122 - verifyGlyphLoaded('uiAttached', vbBadge, 'M2,2.5a.5,.5'); 141 + verifyGlyphLoadedInCache('uiAttached', vbBadge);
123 }); 142 });
124 143
125 // define some glyphs that we want to install 144 // define some glyphs that we want to install
...@@ -147,8 +166,8 @@ describe('factory: fw/svg/glyph.js', function() { ...@@ -147,8 +166,8 @@ describe('factory: fw/svg/glyph.js', function() {
147 expect($log.warn).not.toHaveBeenCalled(); 166 expect($log.warn).not.toHaveBeenCalled();
148 167
149 expect(gs.ids().length).toEqual(numBaseGlyphs + 2); 168 expect(gs.ids().length).toEqual(numBaseGlyphs + 2);
150 - verifyGlyphLoaded('triangle', testVbox, 'M.5,.2'); 169 + verifyGlyphLoadedInCache('triangle', testVbox);
151 - verifyGlyphLoaded('diamond', testVbox, 'M.2,.5'); 170 + verifyGlyphLoadedInCache('diamond', testVbox);
152 }); 171 });
153 172
154 it('should not overwrite glyphs with dup IDs', function () { 173 it('should not overwrite glyphs with dup IDs', function () {
...@@ -163,8 +182,8 @@ describe('factory: fw/svg/glyph.js', function() { ...@@ -163,8 +182,8 @@ describe('factory: fw/svg/glyph.js', function() {
163 182
164 expect(gs.ids().length).toEqual(numBaseGlyphs); 183 expect(gs.ids().length).toEqual(numBaseGlyphs);
165 // verify original glyphs still exist... 184 // verify original glyphs still exist...
166 - verifyGlyphLoaded('router', vbGlyph, 'M10,55A45,45'); 185 + verifyGlyphLoadedInCache('router', vbGlyph);
167 - verifyGlyphLoaded('switch', vbGlyph, 'M10,20a10'); 186 + verifyGlyphLoadedInCache('switch', vbGlyph);
168 }); 187 });
169 188
170 it('should replace glyphs if asked nicely', function () { 189 it('should replace glyphs if asked nicely', function () {
...@@ -178,8 +197,8 @@ describe('factory: fw/svg/glyph.js', function() { ...@@ -178,8 +197,8 @@ describe('factory: fw/svg/glyph.js', function() {
178 197
179 expect(gs.ids().length).toEqual(numBaseGlyphs); 198 expect(gs.ids().length).toEqual(numBaseGlyphs);
180 // verify glyphs have been overwritten... 199 // verify glyphs have been overwritten...
181 - verifyGlyphLoaded('router', testVbox, 'M.5,.2'); 200 + verifyGlyphLoadedInCache('router', testVbox, 'triangle');
182 - verifyGlyphLoaded('switch', testVbox, 'M.2,.5'); 201 + verifyGlyphLoadedInCache('switch', testVbox, 'diamond');
183 }); 202 });
184 203
185 function verifyPathPrefix(elem, prefix) { 204 function verifyPathPrefix(elem, prefix) {
...@@ -188,16 +207,19 @@ describe('factory: fw/svg/glyph.js', function() { ...@@ -188,16 +207,19 @@ describe('factory: fw/svg/glyph.js', function() {
188 expect(d.slice(0, plen)).toEqual(prefix); 207 expect(d.slice(0, plen)).toEqual(prefix);
189 } 208 }
190 209
210 + function verifyLoadedInDom(id, vb, expPfxId) {
211 + var pfxId = expPfxId || id,
212 + symbol = d3Elem.select('#' + id);
213 + expect(symbol.size()).toEqual(1);
214 + expect(symbol.attr('viewBox')).toEqual(vb);
215 + verifyPathPrefix(symbol, prefixLookup[pfxId]);
216 + }
217 +
191 it('should load base glyphs into the DOM', function () { 218 it('should load base glyphs into the DOM', function () {
192 gs.init(); 219 gs.init();
193 gs.loadDefs(d3Elem); 220 gs.loadDefs(d3Elem);
194 expect(d3Elem.selectAll('symbol').size()).toEqual(numBaseGlyphs); 221 expect(d3Elem.selectAll('symbol').size()).toEqual(numBaseGlyphs);
195 - 222 + verifyLoadedInDom('bgpSpeaker', vbGlyph);
196 - // verify bgpSpeaker
197 - var bs = d3Elem.select('#bgpSpeaker');
198 - expect(bs.size()).toEqual(1);
199 - expect(bs.attr('viewBox')).toEqual(vbGlyph);
200 - verifyPathPrefix(bs, 'M10,40a45,35');
201 }); 223 });
202 224
203 it('should load custom glyphs into the DOM', function () { 225 it('should load custom glyphs into the DOM', function () {
...@@ -205,11 +227,15 @@ describe('factory: fw/svg/glyph.js', function() { ...@@ -205,11 +227,15 @@ describe('factory: fw/svg/glyph.js', function() {
205 gs.register(testVbox, newGlyphs); 227 gs.register(testVbox, newGlyphs);
206 gs.loadDefs(d3Elem); 228 gs.loadDefs(d3Elem);
207 expect(d3Elem.selectAll('symbol').size()).toEqual(numBaseGlyphs + 2); 229 expect(d3Elem.selectAll('symbol').size()).toEqual(numBaseGlyphs + 2);
230 + verifyLoadedInDom('diamond', testVbox);
231 + });
208 232
209 - // verify diamond 233 + it('should load only specified glyphs into the DOM', function () {
210 - var dia = d3Elem.select('#diamond'); 234 + gs.init();
211 - expect(dia.size()).toEqual(1); 235 + gs.loadDefs(d3Elem, ['crown', 'chain', 'node']);
212 - expect(dia.attr('viewBox')).toEqual(testVbox); 236 + expect(d3Elem.selectAll('symbol').size()).toEqual(3);
213 - verifyPathPrefix(dia, 'M.2,.5l.3,-.3'); 237 + verifyLoadedInDom('crown', vbGlyph);
238 + verifyLoadedInDom('chain', vbGlyph);
239 + verifyLoadedInDom('node', vbGlyph);
214 }); 240 });
215 }); 241 });
......