Simon Hunt

ONOS-4359: continued work on theming UI

- topo view: device icon and label re-theming (WIP)

Change-Id: I5ecbc1c5b8a8315bfadfaacf62cfdb0e6d1f5a9c
...@@ -149,8 +149,7 @@ ...@@ -149,8 +149,7 @@
149 // configuration for device and host icons in the topology view 149 // configuration for device and host icons in the topology view
150 var config = { 150 var config = {
151 device: { 151 device: {
152 - dim: 36, 152 + dim: 36
153 - rx: 4
154 }, 153 },
155 host: { 154 host: {
156 badge: { 155 badge: {
...@@ -170,30 +169,15 @@ ...@@ -170,30 +169,15 @@
170 }; 169 };
171 170
172 171
173 - // Adds a device icon to the specified element, using the given glyph. 172 + // Adds a device glyph to the specified element.
174 - // Returns the D3 selection of the icon. 173 + // Returns the D3 selection of the glyph (use) element.
175 - function addDeviceIcon(elem, glyphId) { 174 + function addDeviceIcon(elem, glyphId, iconDim) {
176 - var cfg = config.device, 175 + var gid = gs.glyphDefined(glyphId) ? glyphId : 'query';
177 - gid = gs.glyphDefined(glyphId) ? glyphId : 'query', 176 + return elem.append('use').attr({
178 - g = elem.append('g')
179 - .attr('class', 'svgIcon deviceIcon');
180 -
181 - g.append('rect').attr({
182 - x: 0,
183 - y: 0,
184 - rx: cfg.rx,
185 - width: cfg.dim,
186 - height: cfg.dim
187 - });
188 -
189 - g.append('use').attr({
190 'xlink:href': '#' + gid, 177 'xlink:href': '#' + gid,
191 - width: cfg.dim, 178 + width: iconDim,
192 - height: cfg.dim 179 + height: iconDim
193 }); 180 });
194 -
195 - g.dim = cfg.dim;
196 - return g;
197 } 181 }
198 182
199 function addHostIcon(elem, radius, glyphId) { 183 function addHostIcon(elem, radius, glyphId) {
......
...@@ -179,6 +179,7 @@ html[data-platform='iPad'] #topo-p-detail { ...@@ -179,6 +179,7 @@ html[data-platform='iPad'] #topo-p-detail {
179 179
180 #ov-topo svg .node { 180 #ov-topo svg .node {
181 cursor: pointer; 181 cursor: pointer;
182 + fill-rule: evenodd;
182 } 183 }
183 184
184 #ov-topo svg .node text { 185 #ov-topo svg .node text {
......
...@@ -39,28 +39,17 @@ ...@@ -39,28 +39,17 @@
39 */ 39 */
40 40
41 // configuration 41 // configuration
42 - var devCfg = { 42 + var devIconDim = 36;
43 - xoff: -20, 43 + var labelPad = 4;
44 - yoff: -18 44 +
45 - }, 45 + var badgeConfig = {
46 - labelConfig = {
47 - imgPad: 16,
48 - padLR: 4,
49 - padTB: 3,
50 - marginLR: 3,
51 - marginTB: 2,
52 - port: {
53 - gap: 3,
54 - width: 18,
55 - height: 14
56 - }
57 - },
58 - badgeConfig = {
59 radius: 12, 46 radius: 12,
60 yoff: 5, 47 yoff: 5,
61 gdelta: 10 48 gdelta: 10
62 - }, 49 + };
63 - icfg; 50 +
51 + // TODO: remove dependence on this
52 + var icfg;
64 53
65 var status = { 54 var status = {
66 i: 'badgeInfo', 55 i: 'badgeInfo',
...@@ -87,77 +76,32 @@ ...@@ -87,77 +76,32 @@
87 var deviceLabelIndex = 0, 76 var deviceLabelIndex = 0,
88 hostLabelIndex = 0; 77 hostLabelIndex = 0;
89 78
90 -
91 - var dCol = {
92 - black: '#000',
93 - paleblue: '#acf',
94 - offwhite: '#ddd',
95 - darkgrey: '#444',
96 - midgrey: '#888',
97 - lightgrey: '#bbb',
98 - orange: '#f90'
99 - };
100 -
101 // note: these are the device icon colors without affinity 79 // note: these are the device icon colors without affinity
102 var dColTheme = { 80 var dColTheme = {
103 light: { 81 light: {
104 - rfill: dCol.offwhite, 82 + online: '#444444',
105 - online: { 83 + offline: '#cccccc'
106 - glyph: dCol.darkgrey,
107 - rect: dCol.paleblue
108 - },
109 - offline: {
110 - glyph: dCol.midgrey,
111 - rect: dCol.lightgrey
112 - }
113 }, 84 },
114 dark: { 85 dark: {
115 - rfill: dCol.midgrey, 86 + // TODO: theme
116 - online: { 87 + online: '#444444',
117 - glyph: dCol.darkgrey, 88 + offline: '#cccccc'
118 - rect: dCol.paleblue
119 - },
120 - offline: {
121 - glyph: dCol.midgrey,
122 - rect: dCol.darkgrey
123 - }
124 } 89 }
125 }; 90 };
126 91
127 - function devBaseColor(d) { 92 + function devGlyphColor(d) {
128 - var o = d.online ? 'online' : 'offline';
129 - return dColTheme[ts.theme()][o];
130 - }
131 -
132 - function setDeviceColor(d) {
133 var o = d.online, 93 var o = d.online,
134 - s = d.el.classed('selected'), 94 + id = d.master,
135 - c = devBaseColor(d), 95 + otag = o ? 'online' : 'offline';
136 - a = instColor(d.master, o), 96 + return o ? sus.cat7().getColor(id, 0, ts.theme())
137 - icon = d.el.select('g.deviceIcon'), 97 + : dColTheme[ts.theme()][otag];
138 - g, r;
139 -
140 - if (s) {
141 - g = c.glyph;
142 - r = dCol.orange;
143 - } else if (api.instVisible()) {
144 - g = o ? a : c.glyph;
145 - r = o ? c.rfill : a;
146 - } else {
147 - g = c.glyph;
148 - r = c.rect;
149 - }
150 -
151 - icon.select('use').style('fill', g);
152 - icon.select('rect').style('fill', r);
153 } 98 }
154 99
155 - function instColor(id, online) { 100 + function setDeviceColor(d) {
156 - return sus.cat7().getColor(id, !online, ts.theme()); 101 + d.el.select('use')
102 + .style('fill', devGlyphColor(d));
157 } 103 }
158 104
159 - // ====
160 -
161 function incDevLabIndex() { 105 function incDevLabIndex() {
162 setDevLabIndex(deviceLabelIndex+1); 106 setDevLabIndex(deviceLabelIndex+1);
163 switch(deviceLabelIndex) { 107 switch(deviceLabelIndex) {
...@@ -174,82 +118,51 @@ ...@@ -174,82 +118,51 @@
174 ps.setPrefs('topo_prefs', p); 118 ps.setPrefs('topo_prefs', p);
175 } 119 }
176 120
177 - // Returns the newly computed bounding box of the rectangle
178 - function adjustRectToFitText(n) {
179 - var text = n.select('text'),
180 - box = text.node().getBBox(),
181 - lab = labelConfig;
182 -
183 - text.attr('text-anchor', 'middle')
184 - .attr('y', '-0.8em')
185 - .attr('x', lab.imgPad/2);
186 -
187 - // translate the bbox so that it is centered on [x,y]
188 - box.x = -box.width / 2;
189 - box.y = -box.height / 2;
190 -
191 - // add padding
192 - box.x -= (lab.padLR + lab.imgPad/2);
193 - box.width += lab.padLR * 2 + lab.imgPad;
194 - box.y -= lab.padTB;
195 - box.height += lab.padTB * 2;
196 -
197 - return box;
198 - }
199 -
200 function hostLabel(d) { 121 function hostLabel(d) {
201 var idx = (hostLabelIndex < d.labels.length) ? hostLabelIndex : 0; 122 var idx = (hostLabelIndex < d.labels.length) ? hostLabelIndex : 0;
202 return d.labels[idx]; 123 return d.labels[idx];
203 } 124 }
125 +
204 function deviceLabel(d) { 126 function deviceLabel(d) {
205 var idx = (deviceLabelIndex < d.labels.length) ? deviceLabelIndex : 0; 127 var idx = (deviceLabelIndex < d.labels.length) ? deviceLabelIndex : 0;
206 return d.labels[idx]; 128 return d.labels[idx];
207 } 129 }
130 +
208 function trimLabel(label) { 131 function trimLabel(label) {
209 return (label && label.trim()) || ''; 132 return (label && label.trim()) || '';
210 } 133 }
211 134
212 - function emptyBox() { 135 + function computeLabelWidth(n) {
136 + var text = n.select('text'),
137 + box = text.node().getBBox();
138 + return box.width + labelPad * 2;
139 + }
140 +
141 + function iconBox(dim, labelWidth) {
213 return { 142 return {
214 - x: -2, 143 + x: -dim/2,
215 - y: -2, 144 + y: -dim/2,
216 - width: 4, 145 + width: dim + labelWidth,
217 - height: 4 146 + height: dim
218 - }; 147 + }
219 } 148 }
220 149
221 function updateDeviceRendering(d) { 150 function updateDeviceRendering(d) {
222 - var label = trimLabel(deviceLabel(d)), 151 + var node = d.el,
223 - noLabel = !label, 152 + bdg = d.badge,
224 - node = d.el, 153 + label = trimLabel(deviceLabel(d)),
225 - dim = icfg.device.dim, 154 + labelWidth;
226 - box, dx, dy,
227 - bdg = d.badge;
228 -
229 - node.select('text')
230 - .text(label);
231 155
232 - if (noLabel) { 156 + node.select('text').text(label);
233 - box = emptyBox(); 157 + labelWidth = label ? computeLabelWidth(node) : 0;
234 - dx = -dim/2;
235 - dy = -dim/2;
236 - } else {
237 - box = adjustRectToFitText(node);
238 - dx = box.x + devCfg.xoff;
239 - dy = box.y + devCfg.yoff;
240 - }
241 158
242 node.select('rect') 159 node.select('rect')
243 .transition() 160 .transition()
244 - .attr(box); 161 + .attr(iconBox(devIconDim, labelWidth));
245 162
246 - node.select('g.deviceIcon') 163 + // TODO: verify badge placement
247 - .transition()
248 - .attr('transform', sus.translate(dx, dy));
249 -
250 - // handle badge, if defined
251 if (bdg) { 164 if (bdg) {
252 - renderBadge(node, bdg, { dx: dx + dim, dy: dy }); 165 + renderBadge(node, bdg, { dx: devIconDim, dy: 0 });
253 } 166 }
254 } 167 }
255 168
...@@ -259,7 +172,6 @@ ...@@ -259,7 +172,6 @@
259 172
260 updateHostLabel(d); 173 updateHostLabel(d);
261 174
262 - // handle badge, if defined
263 if (bdg) { 175 if (bdg) {
264 renderBadge(node, bdg, icfg.host.badge); 176 renderBadge(node, bdg, icfg.host.badge);
265 } 177 }
...@@ -331,28 +243,26 @@ ...@@ -331,28 +243,26 @@
331 var node = d3.select(this), 243 var node = d3.select(this),
332 glyphId = mapDeviceTypeToGlyph(d.type), 244 glyphId = mapDeviceTypeToGlyph(d.type),
333 label = trimLabel(deviceLabel(d)), 245 label = trimLabel(deviceLabel(d)),
334 - noLabel = !label, 246 + xlate = -devIconDim/2,
335 - box, dx, dy, icon; 247 + rect, text, glyph, labelWidth;
336 248
337 d.el = node; 249 d.el = node;
338 250
339 - node.append('rect').attr({ rx: 5, ry: 5 }); 251 + rect = node.append('rect');
340 - node.append('text').text(label).attr('dy', '1.1em');
341 - box = adjustRectToFitText(node);
342 - node.select('rect').attr(box);
343 252
344 - icon = is.addDeviceIcon(node, glyphId); 253 + text = node.append('text').text(label)
254 + .attr('text-anchor', 'left')
255 + .attr('y', '0.3em')
256 + .attr('x', devIconDim / 2 + labelPad);
345 257
346 - if (noLabel) { 258 + glyph = is.addDeviceIcon(node, glyphId, devIconDim);
347 - dx = -icon.dim/2; 259 +
348 - dy = -icon.dim/2; 260 + labelWidth = label ? computeLabelWidth(node) : 0;
349 - } else { 261 +
350 - box = adjustRectToFitText(node); 262 + rect.attr(iconBox(devIconDim, labelWidth));
351 - dx = box.x + devCfg.xoff; 263 + glyph.attr(iconBox(devIconDim, 0));
352 - dy = box.y + devCfg.yoff;
353 - }
354 264
355 - icon.attr('transform', sus.translate(dx, dy)); 265 + node.attr('transform', sus.translate(xlate, xlate));
356 } 266 }
357 267
358 function hostEnter(d) { 268 function hostEnter(d) {
...@@ -631,7 +541,6 @@ ...@@ -631,7 +541,6 @@
631 541
632 incDevLabIndex: incDevLabIndex, 542 incDevLabIndex: incDevLabIndex,
633 setDevLabIndex: setDevLabIndex, 543 setDevLabIndex: setDevLabIndex,
634 - adjustRectToFitText: adjustRectToFitText,
635 hostLabel: hostLabel, 544 hostLabel: hostLabel,
636 deviceLabel: deviceLabel, 545 deviceLabel: deviceLabel,
637 trimLabel: trimLabel, 546 trimLabel: trimLabel,
......
...@@ -29,14 +29,15 @@ ...@@ -29,14 +29,15 @@
29 // configuration 29 // configuration
30 var linkConfig = { 30 var linkConfig = {
31 light: { 31 light: {
32 - baseColor: '#666', 32 + baseColor: '#939598',
33 inColor: '#66f', 33 inColor: '#66f',
34 outColor: '#f00' 34 outColor: '#f00'
35 }, 35 },
36 dark: { 36 dark: {
37 - baseColor: '#aaa', 37 + // TODO : theme
38 + baseColor: '#939598',
38 inColor: '#66f', 39 inColor: '#66f',
39 - outColor: '#f66' 40 + outColor: '#f00'
40 }, 41 },
41 inWidth: 12, 42 inWidth: 12,
42 outWidth: 10 43 outWidth: 10
...@@ -337,7 +338,7 @@ ...@@ -337,7 +338,7 @@
337 modeCls = ldata.expected() ? 'inactive' : 'not-permitted', 338 modeCls = ldata.expected() ? 'inactive' : 'not-permitted',
338 delay = immediate ? 0 : 1000; 339 delay = immediate ? 0 : 1000;
339 340
340 - // FIXME: understand why el is sometimes undefined on addLink events... 341 + // NOTE: understand why el is sometimes undefined on addLink events...
341 // Investigated: 342 // Investigated:
342 // el is undefined when it's a reverse link that is being added. 343 // el is undefined when it's a reverse link that is being added.
343 // updateLinks (which sets ldata.el) isn't called before this is called. 344 // updateLinks (which sets ldata.el) isn't called before this is called.
......

42.6 KB | W: | H:

42.9 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin

668 Bytes | W: | H:

665 Bytes | W: | H:

  • 2-up
  • Swipe
  • Onion skin
1 +{
2 + "event": "updateInstance",
3 + "payload": {
4 + "id": "192.168.56.101",
5 + "ip": "192.168.56.101",
6 + "online": true,
7 + "ready": true,
8 + "uiAttached": true,
9 + "switches": 0
10 + }
11 +}
1 +{
2 + "event": "updateInstance",
3 + "payload": {
4 + "id": "ONOS-2",
5 + "ip": "192.168.56.102",
6 + "online": true,
7 + "ready": true,
8 + "uiAttached": false,
9 + "switches": 0
10 + }
11 +}
1 +{
2 + "event": "updateInstance",
3 + "payload": {
4 + "id": "ONOS-3",
5 + "ip": "192.168.56.103",
6 + "online": true,
7 + "ready": true,
8 + "uiAttached": false,
9 + "switches": 0
10 + }
11 +}
1 +{
2 + "event": "addDevice",
3 + "payload": {
4 + "id": "of:0000ffffffff000a",
5 + "type": "switch",
6 + "online": false,
7 + "master": "192.168.56.101",
8 + "x-location": {
9 + "type": "lnglat",
10 + "lat": 37.7833,
11 + "lng": -122.4167
12 + },
13 + "labels": [
14 + "",
15 + "sw-A",
16 + "0000ffffffff000a"
17 + ],
18 + "metaUi": {
19 + "x": 520,
20 + "y": 350
21 + }
22 + }
23 +}
1 +{
2 + "event": "addDevice",
3 + "payload": {
4 + "id": "of:0000ffffffff000b",
5 + "type": "switch",
6 + "online": false,
7 + "master": "ONOS-2",
8 + "x-location": {
9 + "type": "lnglat",
10 + "lat": 37.7833,
11 + "lng": -120.4167
12 + },
13 + "labels": [
14 + "",
15 + "sw-B",
16 + "0000ffffffff000b"
17 + ],
18 + "metaUi": {
19 + "x": 720,
20 + "y": 300
21 + }
22 + }
23 +}
1 +{
2 + "event": "addDevice",
3 + "payload": {
4 + "id": "of:0000ffffffff000c",
5 + "type": "switch",
6 + "online": false,
7 + "master": "ONOS-3",
8 + "x-location": {
9 + "type": "lnglat",
10 + "lat": 37.7833,
11 + "lng": -118.4167
12 + },
13 + "labels": [
14 + "",
15 + "sw-C",
16 + "0000ffffffff000c"
17 + ],
18 + "metaUi": {
19 + "x": 920,
20 + "y": 360
21 + }
22 + }
23 +}
1 +{
2 + "event": "addDevice",
3 + "payload": {
4 + "id": "of:0000ffffffff000a",
5 + "type": "switch",
6 + "online": true,
7 + "master": "192.168.56.101",
8 + "x-location": {
9 + "type": "lnglat",
10 + "lat": 37.7833,
11 + "lng": -122.4167
12 + },
13 + "labels": [
14 + "",
15 + "sw-A",
16 + "0000ffffffff000a"
17 + ],
18 + "metaUi": {
19 + "x": 520,
20 + "y": 350
21 + }
22 + }
23 +}
1 +{
2 + "event": "addDevice",
3 + "payload": {
4 + "id": "of:0000ffffffff000b",
5 + "type": "switch",
6 + "online": true,
7 + "master": "ONOS-2",
8 + "x-location": {
9 + "type": "lnglat",
10 + "lat": 37.7833,
11 + "lng": -120.4167
12 + },
13 + "labels": [
14 + "",
15 + "sw-B",
16 + "0000ffffffff000b"
17 + ],
18 + "metaUi": {
19 + "x": 720,
20 + "y": 300
21 + }
22 + }
23 +}
1 +{
2 + "event": "addDevice",
3 + "payload": {
4 + "id": "of:0000ffffffff000c",
5 + "type": "switch",
6 + "online": true,
7 + "master": "ONOS-3",
8 + "x-location": {
9 + "type": "lnglat",
10 + "lat": 37.7833,
11 + "lng": -118.4167
12 + },
13 + "labels": [
14 + "",
15 + "sw-C",
16 + "0000ffffffff000c"
17 + ],
18 + "metaUi": {
19 + "x": 920,
20 + "y": 360
21 + }
22 + }
23 +}
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "id": "of:0000ffffffff000a/11-of:0000ffffffff000b/10",
5 + "type": "direct",
6 + "online": true,
7 + "linkWidth": 2,
8 + "src": "of:0000ffffffff000a",
9 + "srcPort": "11",
10 + "dst": "of:0000ffffffff000b",
11 + "dstPort": "10"
12 + }
13 +}
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "id": "of:0000ffffffff000b/10-of:0000ffffffff000a/11",
5 + "type": "direct",
6 + "online": true,
7 + "linkWidth": 2,
8 + "src": "of:0000ffffffff000b",
9 + "srcPort": "10",
10 + "dst": "of:0000ffffffff000a",
11 + "dstPort": "11"
12 + }
13 +}
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "id": "of:0000ffffffff000a/12-of:0000ffffffff000c/10",
5 + "type": "direct",
6 + "online": true,
7 + "linkWidth": 2,
8 + "src": "of:0000ffffffff000a",
9 + "srcPort": "12",
10 + "dst": "of:0000ffffffff000c",
11 + "dstPort": "10"
12 + }
13 +}
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "id": "of:0000ffffffff000c/10-of:0000ffffffff000a/12",
5 + "type": "direct",
6 + "online": true,
7 + "linkWidth": 2,
8 + "src": "of:0000ffffffff000c",
9 + "srcPort": "10",
10 + "dst": "of:0000ffffffff000a",
11 + "dstPort": "12"
12 + }
13 +}
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "id": "of:0000ffffffff000b/12-of:0000ffffffff000c/11",
5 + "type": "direct",
6 + "online": true,
7 + "linkWidth": 2,
8 + "src": "of:0000ffffffff000b",
9 + "srcPort": "12",
10 + "dst": "of:0000ffffffff000c",
11 + "dstPort": "11"
12 + }
13 +}
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "id": "of:0000ffffffff000c/11-of:0000ffffffff000b/12",
5 + "type": "direct",
6 + "online": true,
7 + "linkWidth": 2,
8 + "src": "of:0000ffffffff000c",
9 + "srcPort": "11",
10 + "dst": "of:0000ffffffff000b",
11 + "dstPort": "12"
12 + }
13 +}
1 +{
2 + "event": "addHost",
3 + "payload": {
4 + "id": "0E:2A:69:30:13:86/-1",
5 + "ingress": "0E:2A:69:30:13:86/-1/0-of:0000ffffffff000a/2",
6 + "egress": "of:0000ffffffff000a/2-0E:2A:69:30:13:86/-1/0",
7 + "cp": {
8 + "device": "of:0000ffffffff000a",
9 + "port": 2
10 + },
11 + "labels": [
12 + "192.168.222.10",
13 + "0E:2A:69:30:13:86"
14 + ],
15 + "metaUi": {
16 + "Xx": 800,
17 + "Xy": 180
18 + }
19 + }
20 +}
1 +{
2 + "event": "addHost",
3 + "payload": {
4 + "id": "0E:2A:69:30:13:87/-1",
5 + "ingress": "0E:2A:69:30:13:87/-1/0-of:0000ffffffff000b/2",
6 + "egress": "of:0000ffffffff000b/2-0E:2A:69:30:13:87/-1/0",
7 + "cp": {
8 + "device": "of:0000ffffffff000b",
9 + "port": 2
10 + },
11 + "labels": [
12 + "192.168.222.11",
13 + "0E:2A:69:30:13:87"
14 + ],
15 + "metaUi": {
16 + "Xx": 800,
17 + "Xy": 180
18 + }
19 + }
20 +}
1 +{
2 + "event": "addHost",
3 + "payload": {
4 + "id": "0E:2A:69:30:13:88/-1",
5 + "ingress": "0E:2A:69:30:13:88/-1/0-of:0000ffffffff000c/2",
6 + "egress": "of:0000ffffffff000c/2-0E:2A:69:30:13:88/-1/0",
7 + "cp": {
8 + "device": "of:0000ffffffff000c",
9 + "port": 2
10 + },
11 + "labels": [
12 + "192.168.222.12",
13 + "0E:2A:69:30:13:88"
14 + ],
15 + "metaUi": {
16 + "Xx": 800,
17 + "Xy": 180
18 + }
19 + }
20 +}
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
4 ], 4 ],
5 "title": "Color-Tweaking Scenario for Mojo Palette", 5 "title": "Color-Tweaking Scenario for Mojo Palette",
6 "params": { 6 "params": {
7 - "lastAuto": 7 7 + "lastAuto": 19
8 }, 8 },
9 "description": [ 9 "description": [
10 "Press 'a' to load initial events.", 10 "Press 'a' to load initial events.",
......