Simon Hunt

GUI -- Completed icon directive definition, and wired up device view.

Change-Id: Ia3cf0655fb17d47adc54f9f4540bb25eacbaaa62
...@@ -59,20 +59,16 @@ ...@@ -59,20 +59,16 @@
59 59
60 // create icon directive, so that we can inject icons into 60 // create icon directive, so that we can inject icons into
61 // HTML tables etc. 61 // HTML tables etc.
62 - .directive('icon', ['GlyphService', function (gs) { 62 + .directive('icon', ['IconService', function (is) {
63 return { 63 return {
64 - templateUrl: 'toBeDecided-iconContext.html',
65 restrict: 'A', 64 restrict: 'A',
65 + scope: {
66 + iconId: '@'
67 + },
66 link: function (scope, element, attrs) { 68 link: function (scope, element, attrs) {
67 - // TODO: implement this 69 + is.loadEmbeddedIcon(d3.select(element[0]), scope.iconId);
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 } 70 }
74 }; 71 };
75 72
76 -
77 }]); 73 }]);
78 }()); 74 }());
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
35 "devices": [{ 35 "devices": [{
36 "id": "of:0000000000000001", 36 "id": "of:0000000000000001",
37 "available": true, 37 "available": true,
38 + "_iconid_available": "deviceOnline",
38 "role": "MASTER", 39 "role": "MASTER",
39 "mfr": "Nicira, Inc.", 40 "mfr": "Nicira, Inc.",
40 "hw": "Open vSwitch", 41 "hw": "Open vSwitch",
...@@ -44,23 +45,38 @@ ...@@ -44,23 +45,38 @@
44 "protocol": "OF_10" 45 "protocol": "OF_10"
45 } 46 }
46 }, 47 },
47 - { 48 + {
48 - "id": "of:0000000000000004", 49 + "id": "of:0000000000000004",
49 - "available": true, 50 + "available": false,
50 - "role": "MASTER", 51 + "_iconid_available": "deviceOffline",
51 - "mfr": "Nicira, Inc.", 52 + "role": "MASTER",
52 - "hw": "Open vSwitch", 53 + "mfr": "Nicira, Inc.",
53 - "sw": "2.0.1", 54 + "hw": "Open vSwitch",
54 - "serial": "None", 55 + "sw": "2.0.1",
55 - "annotations": { 56 + "serial": "None",
56 - "protocol": "OF_10" 57 + "annotations": {
57 - } 58 + "protocol": "OF_10"
58 - }] 59 + }
60 + },
61 + {
62 + "id": "of:0000000000000092",
63 + "available": false,
64 + "_iconid_available": "deviceOffline",
65 + "role": "MASTER",
66 + "mfr": "Nicira, Inc.",
67 + "hw": "Open vSwitch",
68 + "sw": "2.0.1",
69 + "serial": "None",
70 + "annotations": {
71 + "protocol": "OF_10"
72 + }
73 + }]
59 }, 74 },
60 '2': { 75 '2': {
61 "devices": [{ 76 "devices": [{
62 "id": "of:0000000000000002", 77 "id": "of:0000000000000002",
63 "available": true, 78 "available": true,
79 + "_iconid_available": "deviceOnline",
64 "role": "MASTER", 80 "role": "MASTER",
65 "mfr": "Nicira, Inc.", 81 "mfr": "Nicira, Inc.",
66 "hw": "Open vSwitch", 82 "hw": "Open vSwitch",
...@@ -70,18 +86,19 @@ ...@@ -70,18 +86,19 @@
70 "protocol": "OF_10" 86 "protocol": "OF_10"
71 } 87 }
72 }, 88 },
73 - { 89 + {
74 - "id": "of:0000000000000006", 90 + "id": "of:0000000000000006",
75 - "available": true, 91 + "available": true,
76 - "role": "MASTER", 92 + "_iconid_available": "deviceOnline",
77 - "mfr": "Nicira, Inc.", 93 + "role": "MASTER",
78 - "hw": "Open vSwitch", 94 + "mfr": "Nicira, Inc.",
79 - "sw": "2.1.1", 95 + "hw": "Open vSwitch",
80 - "serial": "None", 96 + "sw": "2.1.1",
81 - "annotations": { 97 + "serial": "None",
82 - "protocol": "OF_10" 98 + "annotations": {
83 - } 99 + "protocol": "OF_10"
84 - }] 100 + }
101 + }]
85 }, 102 },
86 'empty': { 103 'empty': {
87 devices: [] 104 devices: []
......
...@@ -168,16 +168,25 @@ ...@@ -168,16 +168,25 @@
168 } 168 }
169 169
170 // 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
171 - function loadDefs(defs, glyphIds) { 171 + function loadDefs(defs, glyphIds, noClear) {
172 - var list = fs.isA(glyphIds) || ids(); 172 + var list = fs.isA(glyphIds) || ids(),
173 + clearCache = !noClear;
173 174
174 - // remove all existing content 175 + if (clearCache) {
175 - defs.html(null); 176 + // remove all existing content
177 + defs.html(null);
178 + }
176 179
177 // load up the requested glyphs 180 // load up the requested glyphs
178 list.forEach(function (id) { 181 list.forEach(function (id) {
179 var g = glyph(id); 182 var g = glyph(id);
180 if (g) { 183 if (g) {
184 + if (noClear) {
185 + // quick exit if symbol is already present
186 + if (defs.select('symbol#' + g.id).size() > 0) {
187 + return;
188 + }
189 + }
181 defs.append('symbol') 190 defs.append('symbol')
182 .attr({ id: g.id, viewBox: g.vb }) 191 .attr({ id: g.id, viewBox: g.vb })
183 .append('path').attr('d', g.d); 192 .append('path').attr('d', g.d);
......
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 -- Icon Service -- CSS file
19 + */
20 +
21 +svg.embeddedIcon .icon .glyph {
22 + stroke: none;
23 + fill: white;
24 + fill-rule: evenodd;
25 +}
26 +
27 +svg.embeddedIcon .icon.deviceOnline {
28 + fill: green;
29 +}
30 +
31 +svg.embeddedIcon .icon.deviceOffline {
32 + fill: darkred;
33 +}
34 +
35 +svg.embeddedIcon .icon rect {
36 + stroke: black;
37 + stroke-width: 1px;
38 +}
...@@ -22,53 +22,89 @@ ...@@ -22,53 +22,89 @@
22 (function () { 22 (function () {
23 'use strict'; 23 'use strict';
24 24
25 - var $log, fs; 25 + var $log, fs, gs;
26 26
27 - var viewBoxDim = 50, 27 + var vboxSize = 50,
28 - viewBox = '0 0 ' + viewBoxDim + ' ' + viewBoxDim; 28 + cornerSize = vboxSize / 10,
29 + viewBox = '0 0 ' + vboxSize + ' ' + vboxSize;
29 30
30 // maps icon id to the glyph id it uses. 31 // maps icon id to the glyph id it uses.
31 // note: icon id maps to a CSS class for styling that icon 32 // note: icon id maps to a CSS class for styling that icon
32 var glyphMapping = { 33 var glyphMapping = {
33 - deviceOnline: 'checkMark', 34 + deviceOnline: 'crown',
34 - deviceOffline: 'xMark' 35 + deviceOffline: 'chain'
36 + //deviceOnline: 'checkMark',
37 + //deviceOffline: 'xMark'
35 }; 38 };
36 39
40 + function ensureIconLibDefs() {
41 + var body = d3.select('body'),
42 + svg = body.select('svg#IconLibDefs'),
43 + defs;
44 +
45 + if (svg.empty()) {
46 + svg = body.append('svg').attr('id', 'IconLibDefs');
47 + defs = svg.append('defs');
48 + }
49 + return svg.select('defs');
50 + }
51 +
37 angular.module('onosSvg') 52 angular.module('onosSvg')
38 - .factory('IconService', ['$log', 'FnService', function (_$log_, _fs_) { 53 + .factory('IconService', ['$log', 'FnService', 'GlyphService',
54 + function (_$log_, _fs_, _gs_) {
39 $log = _$log_; 55 $log = _$log_;
40 fs = _fs_; 56 fs = _fs_;
57 + gs = _gs_;
41 58
42 // div is a D3 selection of the <DIV> element into which icon should load 59 // div is a D3 selection of the <DIV> element into which icon should load
43 // iconCls is the CSS class used to identify the icon 60 // iconCls is the CSS class used to identify the icon
44 // size is dimension of icon in pixels. Defaults to 20. 61 // size is dimension of icon in pixels. Defaults to 20.
45 - function loadIcon(div, iconCls, size) { 62 + // installGlyph, if truthy, will cause the glyph to be added to
63 + // well-known defs element. Defaults to false.
64 + // svgClass is the CSS class used to identify the SVG layer.
65 + // Defaults to 'embeddedIcon'.
66 + function loadIcon(div, iconCls, size, installGlyph, svgClass) {
46 var dim = size || 20, 67 var dim = size || 20,
47 - gid = glyphMapping[iconCls] || 'unknown'; 68 + svgCls = svgClass || 'embeddedIcon',
69 + gid = glyphMapping[iconCls] || 'unknown',
70 + svg, g;
48 71
49 - var svg = div.append('svg').attr({ 72 + if (installGlyph) {
73 + gs.loadDefs(ensureIconLibDefs(), [gid], true);
74 + }
75 +
76 + svg = div.append('svg').attr({
77 + 'class': svgCls,
50 width: dim, 78 width: dim,
51 height: dim, 79 height: dim,
52 viewBox: viewBox 80 viewBox: viewBox
53 }); 81 });
54 - var g = svg.append('g').attr({ 82 +
83 + g = svg.append('g').attr({
55 'class': 'icon ' + iconCls 84 'class': 'icon ' + iconCls
56 }); 85 });
86 +
57 g.append('rect').attr({ 87 g.append('rect').attr({
58 - width: viewBoxDim, 88 + width: vboxSize,
59 - height: viewBoxDim, 89 + height: vboxSize,
60 - rx: 4 90 + rx: cornerSize
61 }); 91 });
92 +
62 g.append('use').attr({ 93 g.append('use').attr({
63 - width: viewBoxDim, 94 + width: vboxSize,
64 - height: viewBoxDim, 95 + height: vboxSize,
65 'class': 'glyph', 96 'class': 'glyph',
66 'xlink:href': '#' + gid 97 'xlink:href': '#' + gid
67 }); 98 });
68 } 99 }
69 100
101 + function loadEmbeddedIcon(div, iconCls, size) {
102 + loadIcon(div, iconCls, size, true);
103 + }
104 +
70 return { 105 return {
71 - loadIcon: loadIcon 106 + loadIcon: loadIcon,
107 + loadEmbeddedIcon: loadEmbeddedIcon
72 }; 108 };
73 }]); 109 }]);
74 110
......
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
58 <link rel="stylesheet" href="onos.css"> 58 <link rel="stylesheet" href="onos.css">
59 <link rel="stylesheet" href="common.css"> 59 <link rel="stylesheet" href="common.css">
60 <link rel="stylesheet" href="fw/mast/mast.css"> 60 <link rel="stylesheet" href="fw/mast/mast.css">
61 + <link rel="stylesheet" href="fw/svg/icon.css">
61 <link rel="stylesheet" href="fw/nav/nav.css"> 62 <link rel="stylesheet" href="fw/nav/nav.css">
62 63
63 <!-- This is where contributed javascript will get injected --> 64 <!-- This is where contributed javascript will get injected -->
......
...@@ -4,17 +4,19 @@ ...@@ -4,17 +4,19 @@
4 4
5 <table class="summary-list"> 5 <table class="summary-list">
6 <tr> 6 <tr>
7 + <th></th>
7 <th>ID</th> 8 <th>ID</th>
8 <th>Manufacturer</th> 9 <th>Manufacturer</th>
9 <th>Hardware Version</th> 10 <th>Hardware Version</th>
10 <th>Software Version</th> 11 <th>Software Version</th>
11 </tr> 12 </tr>
12 <tr ng-repeat="dev in ctrl.deviceData"> 13 <tr ng-repeat="dev in ctrl.deviceData">
13 - <!-- add more property fields for table from device data --> 14 + <td><div icon icon-id="{{dev._iconid_available}}"></div></td>
14 <td>{{dev.id}}</td> 15 <td>{{dev.id}}</td>
15 <td>{{dev.mfr}}</td> 16 <td>{{dev.mfr}}</td>
16 <td>{{dev.hw}}</td> 17 <td>{{dev.hw}}</td>
17 <td>{{dev.sw}}</td> 18 <td>{{dev.sw}}</td>
19 + <!-- add more property fields for table from device data -->
18 </tr> 20 </tr>
19 </table> 21 </table>
20 22
......
...@@ -65,7 +65,7 @@ describe('factory: fw/svg/icon.js', function() { ...@@ -65,7 +65,7 @@ describe('factory: fw/svg/icon.js', function() {
65 var rect = g.select('rect'); 65 var rect = g.select('rect');
66 expect(rect.size()).toBe(1); 66 expect(rect.size()).toBe(1);
67 checkElemSize(rect, gsz); 67 checkElemSize(rect, gsz);
68 - expect(rect.attr('rx')).toEqual('4'); 68 + expect(rect.attr('rx')).toEqual('5');
69 69
70 var use = g.select('use'); 70 var use = g.select('use');
71 expect(use.classed('glyph')).toBeTruthy(); 71 expect(use.classed('glyph')).toBeTruthy();
......