GUI -- Completed icon directive definition, and wired up device view.
Change-Id: Ia3cf0655fb17d47adc54f9f4540bb25eacbaaa62
Showing
8 changed files
with
154 additions
and
55 deletions
... | @@ -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); | ... | ... |
web/gui/src/main/webapp/app/fw/svg/icon.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 -- 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(); | ... | ... |
-
Please register or login to post a comment