Committed by
Gerrit Code Review
GUI -- TopoView - Refactored a bunch of functions out of topoForce into topoD3.
- finally, topoForce is a respectable sub-1000 LOC :) Change-Id: I2a9ac2881c9d54663faecf338c512a368f17bc34
Showing
4 changed files
with
534 additions
and
436 deletions
1 | <script src="app/view/sample/sample.js"></script> | 1 | <script src="app/view/sample/sample.js"></script> |
2 | <script src="app/view/topo/topo.js"></script> | 2 | <script src="app/view/topo/topo.js"></script> |
3 | +<script src="app/view/topo/topoD3.js"></script> | ||
3 | <script src="app/view/topo/topoEvent.js"></script> | 4 | <script src="app/view/topo/topoEvent.js"></script> |
4 | <script src="app/view/topo/topoFilter.js"></script> | 5 | <script src="app/view/topo/topoFilter.js"></script> |
5 | <script src="app/view/topo/topoForce.js"></script> | 6 | <script src="app/view/topo/topoForce.js"></script> | ... | ... |
1 | +/* | ||
2 | + * Copyright 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 -- Topology D3 Module. | ||
19 | + Functions for manipulating the D3 visualizations of the Topology | ||
20 | + */ | ||
21 | + | ||
22 | +(function () { | ||
23 | + 'use strict'; | ||
24 | + | ||
25 | + // injected refs | ||
26 | + var $log, fs, sus, is, ts; | ||
27 | + | ||
28 | + // api to topoForce | ||
29 | + var api; | ||
30 | + /* | ||
31 | + node() // get ref to D3 selection of nodes | ||
32 | + link() // get ref to D3 selection of links | ||
33 | + linkLabel() // get ref to D3 selection of link labels | ||
34 | + instVisible() // true if instances panel is visible | ||
35 | + posNode() // position node | ||
36 | + showHosts() // true if hosts are to be shown | ||
37 | + restyleLinkElement() // update link styles based on backing data | ||
38 | + updateLinkLabelModel() // update backing data for link labels | ||
39 | + */ | ||
40 | + | ||
41 | + // configuration | ||
42 | + var devCfg = { | ||
43 | + xoff: -20, | ||
44 | + yoff: -18 | ||
45 | + }, | ||
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 | + icfg; | ||
59 | + | ||
60 | + // internal state | ||
61 | + var deviceLabelIndex = 0, | ||
62 | + hostLabelIndex = 0; | ||
63 | + | ||
64 | + | ||
65 | + var dCol = { | ||
66 | + black: '#000', | ||
67 | + paleblue: '#acf', | ||
68 | + offwhite: '#ddd', | ||
69 | + darkgrey: '#444', | ||
70 | + midgrey: '#888', | ||
71 | + lightgrey: '#bbb', | ||
72 | + orange: '#f90' | ||
73 | + }; | ||
74 | + | ||
75 | + // note: these are the device icon colors without affinity | ||
76 | + var dColTheme = { | ||
77 | + light: { | ||
78 | + rfill: dCol.offwhite, | ||
79 | + online: { | ||
80 | + glyph: dCol.darkgrey, | ||
81 | + rect: dCol.paleblue | ||
82 | + }, | ||
83 | + offline: { | ||
84 | + glyph: dCol.midgrey, | ||
85 | + rect: dCol.lightgrey | ||
86 | + } | ||
87 | + }, | ||
88 | + dark: { | ||
89 | + rfill: dCol.midgrey, | ||
90 | + online: { | ||
91 | + glyph: dCol.darkgrey, | ||
92 | + rect: dCol.paleblue | ||
93 | + }, | ||
94 | + offline: { | ||
95 | + glyph: dCol.midgrey, | ||
96 | + rect: dCol.darkgrey | ||
97 | + } | ||
98 | + } | ||
99 | + }; | ||
100 | + | ||
101 | + function devBaseColor(d) { | ||
102 | + var o = d.online ? 'online' : 'offline'; | ||
103 | + return dColTheme[ts.theme()][o]; | ||
104 | + } | ||
105 | + | ||
106 | + function setDeviceColor(d) { | ||
107 | + var o = d.online, | ||
108 | + s = d.el.classed('selected'), | ||
109 | + c = devBaseColor(d), | ||
110 | + a = instColor(d.master, o), | ||
111 | + icon = d.el.select('g.deviceIcon'), | ||
112 | + g, r; | ||
113 | + | ||
114 | + if (s) { | ||
115 | + g = c.glyph; | ||
116 | + r = dCol.orange; | ||
117 | + } else if (api.instVisible()) { | ||
118 | + g = o ? a : c.glyph; | ||
119 | + r = o ? c.rfill : a; | ||
120 | + } else { | ||
121 | + g = c.glyph; | ||
122 | + r = c.rect; | ||
123 | + } | ||
124 | + | ||
125 | + icon.select('use').style('fill', g); | ||
126 | + icon.select('rect').style('fill', r); | ||
127 | + } | ||
128 | + | ||
129 | + function instColor(id, online) { | ||
130 | + return sus.cat7().getColor(id, !online, ts.theme()); | ||
131 | + } | ||
132 | + | ||
133 | + // ==== | ||
134 | + | ||
135 | + function incDevLabIndex() { | ||
136 | + deviceLabelIndex = (deviceLabelIndex+1) % 3; | ||
137 | + } | ||
138 | + | ||
139 | + // Returns the newly computed bounding box of the rectangle | ||
140 | + function adjustRectToFitText(n) { | ||
141 | + var text = n.select('text'), | ||
142 | + box = text.node().getBBox(), | ||
143 | + lab = labelConfig; | ||
144 | + | ||
145 | + text.attr('text-anchor', 'middle') | ||
146 | + .attr('y', '-0.8em') | ||
147 | + .attr('x', lab.imgPad/2); | ||
148 | + | ||
149 | + // translate the bbox so that it is centered on [x,y] | ||
150 | + box.x = -box.width / 2; | ||
151 | + box.y = -box.height / 2; | ||
152 | + | ||
153 | + // add padding | ||
154 | + box.x -= (lab.padLR + lab.imgPad/2); | ||
155 | + box.width += lab.padLR * 2 + lab.imgPad; | ||
156 | + box.y -= lab.padTB; | ||
157 | + box.height += lab.padTB * 2; | ||
158 | + | ||
159 | + return box; | ||
160 | + } | ||
161 | + | ||
162 | + function hostLabel(d) { | ||
163 | + var idx = (hostLabelIndex < d.labels.length) ? hostLabelIndex : 0; | ||
164 | + return d.labels[idx]; | ||
165 | + } | ||
166 | + function deviceLabel(d) { | ||
167 | + var idx = (deviceLabelIndex < d.labels.length) ? deviceLabelIndex : 0; | ||
168 | + return d.labels[idx]; | ||
169 | + } | ||
170 | + function trimLabel(label) { | ||
171 | + return (label && label.trim()) || ''; | ||
172 | + } | ||
173 | + | ||
174 | + function emptyBox() { | ||
175 | + return { | ||
176 | + x: -2, | ||
177 | + y: -2, | ||
178 | + width: 4, | ||
179 | + height: 4 | ||
180 | + }; | ||
181 | + } | ||
182 | + | ||
183 | + | ||
184 | + function updateDeviceLabel(d) { | ||
185 | + var label = trimLabel(deviceLabel(d)), | ||
186 | + noLabel = !label, | ||
187 | + node = d.el, | ||
188 | + dim = icfg.device.dim, | ||
189 | + box, dx, dy; | ||
190 | + | ||
191 | + node.select('text') | ||
192 | + .text(label) | ||
193 | + .style('opacity', 0) | ||
194 | + .transition() | ||
195 | + .style('opacity', 1); | ||
196 | + | ||
197 | + if (noLabel) { | ||
198 | + box = emptyBox(); | ||
199 | + dx = -dim/2; | ||
200 | + dy = -dim/2; | ||
201 | + } else { | ||
202 | + box = adjustRectToFitText(node); | ||
203 | + dx = box.x + devCfg.xoff; | ||
204 | + dy = box.y + devCfg.yoff; | ||
205 | + } | ||
206 | + | ||
207 | + node.select('rect') | ||
208 | + .transition() | ||
209 | + .attr(box); | ||
210 | + | ||
211 | + node.select('g.deviceIcon') | ||
212 | + .transition() | ||
213 | + .attr('transform', sus.translate(dx, dy)); | ||
214 | + } | ||
215 | + | ||
216 | + function updateHostLabel(d) { | ||
217 | + var label = trimLabel(hostLabel(d)); | ||
218 | + d.el.select('text').text(label); | ||
219 | + } | ||
220 | + | ||
221 | + function updateDeviceColors(d) { | ||
222 | + if (d) { | ||
223 | + setDeviceColor(d); | ||
224 | + } else { | ||
225 | + api.node().filter('.device').each(function (d) { | ||
226 | + setDeviceColor(d); | ||
227 | + }); | ||
228 | + } | ||
229 | + } | ||
230 | + | ||
231 | + | ||
232 | + // ========================== | ||
233 | + // updateNodes - subfunctions | ||
234 | + | ||
235 | + function deviceExisting(d) { | ||
236 | + var node = d.el; | ||
237 | + node.classed('online', d.online); | ||
238 | + updateDeviceLabel(d); | ||
239 | + api.posNode(d, true); | ||
240 | + } | ||
241 | + | ||
242 | + function hostExisting(d) { | ||
243 | + updateHostLabel(d); | ||
244 | + api.posNode(d, true); | ||
245 | + } | ||
246 | + | ||
247 | + function deviceEnter(d) { | ||
248 | + var node = d3.select(this), | ||
249 | + glyphId = d.type || 'unknown', | ||
250 | + label = trimLabel(deviceLabel(d)), | ||
251 | + //devCfg = deviceIconConfig, | ||
252 | + noLabel = !label, | ||
253 | + box, dx, dy, icon; | ||
254 | + | ||
255 | + d.el = node; | ||
256 | + | ||
257 | + node.append('rect').attr({ rx: 5, ry: 5 }); | ||
258 | + node.append('text').text(label).attr('dy', '1.1em'); | ||
259 | + box = adjustRectToFitText(node); | ||
260 | + node.select('rect').attr(box); | ||
261 | + | ||
262 | + icon = is.addDeviceIcon(node, glyphId); | ||
263 | + | ||
264 | + if (noLabel) { | ||
265 | + dx = -icon.dim/2; | ||
266 | + dy = -icon.dim/2; | ||
267 | + } else { | ||
268 | + box = adjustRectToFitText(node); | ||
269 | + dx = box.x + devCfg.xoff; | ||
270 | + dy = box.y + devCfg.yoff; | ||
271 | + } | ||
272 | + | ||
273 | + icon.attr('transform', sus.translate(dx, dy)); | ||
274 | + } | ||
275 | + | ||
276 | + function hostEnter(d) { | ||
277 | + var node = d3.select(this), | ||
278 | + gid = d.type || 'unknown', | ||
279 | + rad = icfg.host.radius, | ||
280 | + r = d.type ? rad.withGlyph : rad.noGlyph, | ||
281 | + textDy = r + 10; | ||
282 | + | ||
283 | + d.el = node; | ||
284 | + sus.visible(node, api.showHosts()); | ||
285 | + | ||
286 | + is.addHostIcon(node, r, gid); | ||
287 | + | ||
288 | + node.append('text') | ||
289 | + .text(hostLabel) | ||
290 | + .attr('dy', textDy) | ||
291 | + .attr('text-anchor', 'middle'); | ||
292 | + } | ||
293 | + | ||
294 | + function hostExit(d) { | ||
295 | + var node = d.el; | ||
296 | + node.select('use') | ||
297 | + .style('opacity', 0.5) | ||
298 | + .transition() | ||
299 | + .duration(800) | ||
300 | + .style('opacity', 0); | ||
301 | + | ||
302 | + node.select('text') | ||
303 | + .style('opacity', 0.5) | ||
304 | + .transition() | ||
305 | + .duration(800) | ||
306 | + .style('opacity', 0); | ||
307 | + | ||
308 | + node.select('circle') | ||
309 | + .style('stroke-fill', '#555') | ||
310 | + .style('fill', '#888') | ||
311 | + .style('opacity', 0.5) | ||
312 | + .transition() | ||
313 | + .duration(1500) | ||
314 | + .attr('r', 0); | ||
315 | + } | ||
316 | + | ||
317 | + function deviceExit(d) { | ||
318 | + var node = d.el; | ||
319 | + node.select('use') | ||
320 | + .style('opacity', 0.5) | ||
321 | + .transition() | ||
322 | + .duration(800) | ||
323 | + .style('opacity', 0); | ||
324 | + | ||
325 | + node.selectAll('rect') | ||
326 | + .style('stroke-fill', '#555') | ||
327 | + .style('fill', '#888') | ||
328 | + .style('opacity', 0.5); | ||
329 | + } | ||
330 | + | ||
331 | + | ||
332 | + // ========================== | ||
333 | + // updateLinks - subfunctions | ||
334 | + | ||
335 | + function linkExisting(d) { | ||
336 | + // this is supposed to be an existing link, but we have observed | ||
337 | + // occasions (where links are deleted and added rapidly?) where | ||
338 | + // the DOM element has not been defined. So protection against that... | ||
339 | + if (d.el) { | ||
340 | + api.restyleLinkElement(d, true); | ||
341 | + } | ||
342 | + } | ||
343 | + | ||
344 | + function linkEntering(d) { | ||
345 | + var link = d3.select(this); | ||
346 | + d.el = link; | ||
347 | + api.restyleLinkElement(d); | ||
348 | + if (d.type() === 'hostLink') { | ||
349 | + sus.visible(link, api.showHosts()); | ||
350 | + } | ||
351 | + } | ||
352 | + | ||
353 | + var linkLabelOffset = '0.3em'; | ||
354 | + | ||
355 | + function applyLinkLabels() { | ||
356 | + var entering; | ||
357 | + | ||
358 | + api.updateLinkLabelModel(); | ||
359 | + | ||
360 | + // for elements already existing, we need to update the text | ||
361 | + // and adjust the rectangle size to fit | ||
362 | + api.linkLabel().each(function (d) { | ||
363 | + var el = d3.select(this), | ||
364 | + rect = el.select('rect'), | ||
365 | + text = el.select('text'); | ||
366 | + text.text(d.label); | ||
367 | + rect.attr(rectAroundText(el)); | ||
368 | + }); | ||
369 | + | ||
370 | + entering = api.linkLabel().enter().append('g') | ||
371 | + .classed('linkLabel', true) | ||
372 | + .attr('id', function (d) { return d.id; }); | ||
373 | + | ||
374 | + entering.each(function (d) { | ||
375 | + var el = d3.select(this), | ||
376 | + rect, | ||
377 | + text, | ||
378 | + parms = { | ||
379 | + x1: d.ldata.source.x, | ||
380 | + y1: d.ldata.source.y, | ||
381 | + x2: d.ldata.target.x, | ||
382 | + y2: d.ldata.target.y | ||
383 | + }; | ||
384 | + | ||
385 | + if (d.ldata.type() === 'hostLink') { | ||
386 | + el.classed('hostLinkLabel', true); | ||
387 | + sus.visible(el, api.showHosts()); | ||
388 | + } | ||
389 | + | ||
390 | + d.el = el; | ||
391 | + rect = el.append('rect'); | ||
392 | + text = el.append('text').text(d.label); | ||
393 | + rect.attr(rectAroundText(el)); | ||
394 | + text.attr('dy', linkLabelOffset); | ||
395 | + | ||
396 | + el.attr('transform', transformLabel(parms)); | ||
397 | + }); | ||
398 | + | ||
399 | + // Remove any labels that are no longer required. | ||
400 | + api.linkLabel().exit().remove(); | ||
401 | + } | ||
402 | + | ||
403 | + function rectAroundText(el) { | ||
404 | + var text = el.select('text'), | ||
405 | + box = text.node().getBBox(); | ||
406 | + | ||
407 | + // translate the bbox so that it is centered on [x,y] | ||
408 | + box.x = -box.width / 2; | ||
409 | + box.y = -box.height / 2; | ||
410 | + | ||
411 | + // add padding | ||
412 | + box.x -= 1; | ||
413 | + box.width += 2; | ||
414 | + return box; | ||
415 | + } | ||
416 | + | ||
417 | + function transformLabel(p) { | ||
418 | + var dx = p.x2 - p.x1, | ||
419 | + dy = p.y2 - p.y1, | ||
420 | + xMid = dx/2 + p.x1, | ||
421 | + yMid = dy/2 + p.y1; | ||
422 | + return sus.translate(xMid, yMid); | ||
423 | + } | ||
424 | + | ||
425 | + | ||
426 | + // ========================== | ||
427 | + // Module definition | ||
428 | + | ||
429 | + angular.module('ovTopo') | ||
430 | + .factory('TopoD3Service', | ||
431 | + ['$log', 'FnService', 'SvgUtilService', 'IconService', 'ThemeService', | ||
432 | + | ||
433 | + function (_$log_, _fs_, _sus_, _is_, _ts_) { | ||
434 | + $log = _$log_; | ||
435 | + fs = _fs_; | ||
436 | + sus = _sus_; | ||
437 | + is = _is_; | ||
438 | + ts = _ts_; | ||
439 | + | ||
440 | + icfg = is.iconConfig(); | ||
441 | + | ||
442 | + function initD3(_api_) { | ||
443 | + api = _api_; | ||
444 | + } | ||
445 | + | ||
446 | + function destroyD3() { } | ||
447 | + | ||
448 | + return { | ||
449 | + initD3: initD3, | ||
450 | + destroyD3: destroyD3, | ||
451 | + | ||
452 | + incDevLabIndex: incDevLabIndex, | ||
453 | + adjustRectToFitText: adjustRectToFitText, | ||
454 | + hostLabel: hostLabel, | ||
455 | + deviceLabel: deviceLabel, | ||
456 | + trimLabel: trimLabel, | ||
457 | + | ||
458 | + updateDeviceLabel: updateDeviceLabel, | ||
459 | + updateHostLabel: updateHostLabel, | ||
460 | + updateDeviceColors: updateDeviceColors, | ||
461 | + | ||
462 | + deviceExisting: deviceExisting, | ||
463 | + hostExisting: hostExisting, | ||
464 | + deviceEnter: deviceEnter, | ||
465 | + hostEnter: hostEnter, | ||
466 | + hostExit: hostExit, | ||
467 | + deviceExit: deviceExit, | ||
468 | + | ||
469 | + linkExisting: linkExisting, | ||
470 | + linkEntering: linkEntering, | ||
471 | + applyLinkLabels: applyLinkLabels, | ||
472 | + | ||
473 | + transformLabel: transformLabel | ||
474 | + }; | ||
475 | + }]); | ||
476 | +}()); |
... | @@ -23,28 +23,10 @@ | ... | @@ -23,28 +23,10 @@ |
23 | 'use strict'; | 23 | 'use strict'; |
24 | 24 | ||
25 | // injected refs | 25 | // injected refs |
26 | - var $log, fs, sus, is, ts, flash, tis, tms, tss, tts, tos, fltr, | 26 | + var $log, fs, sus, is, ts, flash, tis, tms, td3, tss, tts, tos, fltr, |
27 | icfg, uplink; | 27 | icfg, uplink; |
28 | 28 | ||
29 | // configuration | 29 | // configuration |
30 | - var labelConfig = { | ||
31 | - imgPad: 16, | ||
32 | - padLR: 4, | ||
33 | - padTB: 3, | ||
34 | - marginLR: 3, | ||
35 | - marginTB: 2, | ||
36 | - port: { | ||
37 | - gap: 3, | ||
38 | - width: 18, | ||
39 | - height: 14 | ||
40 | - } | ||
41 | - }; | ||
42 | - | ||
43 | - var deviceIconConfig = { | ||
44 | - xoff: -20, | ||
45 | - yoff: -18 | ||
46 | - }; | ||
47 | - | ||
48 | var linkConfig = { | 30 | var linkConfig = { |
49 | light: { | 31 | light: { |
50 | baseColor: '#666', | 32 | baseColor: '#666', |
... | @@ -72,8 +54,6 @@ | ... | @@ -72,8 +54,6 @@ |
72 | }, | 54 | }, |
73 | lu = network.lookup, // shorthand | 55 | lu = network.lookup, // shorthand |
74 | rlk = network.revLinkToKey, | 56 | rlk = network.revLinkToKey, |
75 | - deviceLabelIndex = 0, // for device label cycling | ||
76 | - hostLabelIndex = 0, // for host label cycling | ||
77 | showHosts = false, // whether hosts are displayed | 57 | showHosts = false, // whether hosts are displayed |
78 | showOffline = true, // whether offline devices are displayed | 58 | showOffline = true, // whether offline devices are displayed |
79 | nodeLock = false, // whether nodes can be dragged or not (locked) | 59 | nodeLock = false, // whether nodes can be dragged or not (locked) |
... | @@ -152,9 +132,6 @@ | ... | @@ -152,9 +132,6 @@ |
152 | tms.findAttachedLinks(d.id).forEach(restyleLinkElement); | 132 | tms.findAttachedLinks(d.id).forEach(restyleLinkElement); |
153 | updateOfflineVisibility(d); | 133 | updateOfflineVisibility(d); |
154 | } | 134 | } |
155 | - } else { | ||
156 | - // TODO: decide whether we want to capture logic errors | ||
157 | - //logicError('updateDevice lookup fail. ID = "' + id + '"'); | ||
158 | } | 135 | } |
159 | } | 136 | } |
160 | 137 | ||
... | @@ -163,9 +140,6 @@ | ... | @@ -163,9 +140,6 @@ |
163 | d = lu[id]; | 140 | d = lu[id]; |
164 | if (d) { | 141 | if (d) { |
165 | removeDeviceElement(d); | 142 | removeDeviceElement(d); |
166 | - } else { | ||
167 | - // TODO: decide whether we want to capture logic errors | ||
168 | - //logicError('removeDevice lookup fail. ID = "' + id + '"'); | ||
169 | } | 143 | } |
170 | } | 144 | } |
171 | 145 | ||
... | @@ -206,9 +180,6 @@ | ... | @@ -206,9 +180,6 @@ |
206 | sendUpdateMeta(d); | 180 | sendUpdateMeta(d); |
207 | } | 181 | } |
208 | updateNodes(); | 182 | updateNodes(); |
209 | - } else { | ||
210 | - // TODO: decide whether we want to capture logic errors | ||
211 | - //logicError('updateHost lookup fail. ID = "' + id + '"'); | ||
212 | } | 183 | } |
213 | } | 184 | } |
214 | 185 | ||
... | @@ -217,9 +188,6 @@ | ... | @@ -217,9 +188,6 @@ |
217 | d = lu[id]; | 188 | d = lu[id]; |
218 | if (d) { | 189 | if (d) { |
219 | removeHostElement(d, true); | 190 | removeHostElement(d, true); |
220 | - } else { | ||
221 | - // may have already removed host, if attached to removed device | ||
222 | - //console.warn('removeHost lookup fail. ID = "' + id + '"'); | ||
223 | } | 191 | } |
224 | } | 192 | } |
225 | 193 | ||
... | @@ -260,15 +228,12 @@ | ... | @@ -260,15 +228,12 @@ |
260 | } | 228 | } |
261 | 229 | ||
262 | function removeLink(data) { | 230 | function removeLink(data) { |
263 | - var result = tms.findLink(data, 'remove'), | 231 | + var result = tms.findLink(data, 'remove'); |
264 | - bad = result.badLogic; | 232 | + |
265 | - if (bad) { | 233 | + if (!result.badLogic) { |
266 | - // may have already removed link, if attached to removed device | ||
267 | - //console.warn(bad + ': ' + link.id); | ||
268 | - return; | ||
269 | - } | ||
270 | result.removeRawLink(); | 234 | result.removeRawLink(); |
271 | } | 235 | } |
236 | + } | ||
272 | 237 | ||
273 | // ======================== | 238 | // ======================== |
274 | 239 | ||
... | @@ -417,107 +382,10 @@ | ... | @@ -417,107 +382,10 @@ |
417 | } | 382 | } |
418 | 383 | ||
419 | 384 | ||
420 | - // ========================== | ||
421 | - // === Devices and hosts - D3 rendering | ||
422 | - | ||
423 | - | ||
424 | - // Returns the newly computed bounding box of the rectangle | ||
425 | - function adjustRectToFitText(n) { | ||
426 | - var text = n.select('text'), | ||
427 | - box = text.node().getBBox(), | ||
428 | - lab = labelConfig; | ||
429 | - | ||
430 | - text.attr('text-anchor', 'middle') | ||
431 | - .attr('y', '-0.8em') | ||
432 | - .attr('x', lab.imgPad/2); | ||
433 | - | ||
434 | - // translate the bbox so that it is centered on [x,y] | ||
435 | - box.x = -box.width / 2; | ||
436 | - box.y = -box.height / 2; | ||
437 | - | ||
438 | - // add padding | ||
439 | - box.x -= (lab.padLR + lab.imgPad/2); | ||
440 | - box.width += lab.padLR * 2 + lab.imgPad; | ||
441 | - box.y -= lab.padTB; | ||
442 | - box.height += lab.padTB * 2; | ||
443 | - | ||
444 | - return box; | ||
445 | - } | ||
446 | - | ||
447 | function mkSvgClass(d) { | 385 | function mkSvgClass(d) { |
448 | return d.fixed ? d.svgClass + ' fixed' : d.svgClass; | 386 | return d.fixed ? d.svgClass + ' fixed' : d.svgClass; |
449 | } | 387 | } |
450 | 388 | ||
451 | - function hostLabel(d) { | ||
452 | - var idx = (hostLabelIndex < d.labels.length) ? hostLabelIndex : 0; | ||
453 | - return d.labels[idx]; | ||
454 | - } | ||
455 | - function deviceLabel(d) { | ||
456 | - var idx = (deviceLabelIndex < d.labels.length) ? deviceLabelIndex : 0; | ||
457 | - return d.labels[idx]; | ||
458 | - } | ||
459 | - function trimLabel(label) { | ||
460 | - return (label && label.trim()) || ''; | ||
461 | - } | ||
462 | - | ||
463 | - function emptyBox() { | ||
464 | - return { | ||
465 | - x: -2, | ||
466 | - y: -2, | ||
467 | - width: 4, | ||
468 | - height: 4 | ||
469 | - }; | ||
470 | - } | ||
471 | - | ||
472 | - | ||
473 | - function updateDeviceLabel(d) { | ||
474 | - var label = trimLabel(deviceLabel(d)), | ||
475 | - noLabel = !label, | ||
476 | - node = d.el, | ||
477 | - dim = icfg.device.dim, | ||
478 | - devCfg = deviceIconConfig, | ||
479 | - box, dx, dy; | ||
480 | - | ||
481 | - node.select('text') | ||
482 | - .text(label) | ||
483 | - .style('opacity', 0) | ||
484 | - .transition() | ||
485 | - .style('opacity', 1); | ||
486 | - | ||
487 | - if (noLabel) { | ||
488 | - box = emptyBox(); | ||
489 | - dx = -dim/2; | ||
490 | - dy = -dim/2; | ||
491 | - } else { | ||
492 | - box = adjustRectToFitText(node); | ||
493 | - dx = box.x + devCfg.xoff; | ||
494 | - dy = box.y + devCfg.yoff; | ||
495 | - } | ||
496 | - | ||
497 | - node.select('rect') | ||
498 | - .transition() | ||
499 | - .attr(box); | ||
500 | - | ||
501 | - node.select('g.deviceIcon') | ||
502 | - .transition() | ||
503 | - .attr('transform', sus.translate(dx, dy)); | ||
504 | - } | ||
505 | - | ||
506 | - function updateHostLabel(d) { | ||
507 | - var label = trimLabel(hostLabel(d)); | ||
508 | - d.el.select('text').text(label); | ||
509 | - } | ||
510 | - | ||
511 | - function updateDeviceColors(d) { | ||
512 | - if (d) { | ||
513 | - setDeviceColor(d); | ||
514 | - } else { | ||
515 | - node.filter('.device').each(function (d) { | ||
516 | - setDeviceColor(d); | ||
517 | - }); | ||
518 | - } | ||
519 | - } | ||
520 | - | ||
521 | function vis(b) { | 389 | function vis(b) { |
522 | return b ? 'visible' : 'hidden'; | 390 | return b ? 'visible' : 'hidden'; |
523 | } | 391 | } |
... | @@ -535,9 +403,9 @@ | ... | @@ -535,9 +403,9 @@ |
535 | } | 403 | } |
536 | 404 | ||
537 | function cycleDeviceLabels() { | 405 | function cycleDeviceLabels() { |
538 | - deviceLabelIndex = (deviceLabelIndex+1) % 3; | 406 | + td3.incDevLabIndex(); |
539 | tms.findDevices().forEach(function (d) { | 407 | tms.findDevices().forEach(function (d) { |
540 | - updateDeviceLabel(d); | 408 | + td3.updateDeviceLabel(d); |
541 | }); | 409 | }); |
542 | } | 410 | } |
543 | 411 | ||
... | @@ -583,84 +451,14 @@ | ... | @@ -583,84 +451,14 @@ |
583 | 451 | ||
584 | // ========================================== | 452 | // ========================================== |
585 | 453 | ||
586 | - var dCol = { | ||
587 | - black: '#000', | ||
588 | - paleblue: '#acf', | ||
589 | - offwhite: '#ddd', | ||
590 | - darkgrey: '#444', | ||
591 | - midgrey: '#888', | ||
592 | - lightgrey: '#bbb', | ||
593 | - orange: '#f90' | ||
594 | - }; | ||
595 | - | ||
596 | - // note: these are the device icon colors without affinity | ||
597 | - var dColTheme = { | ||
598 | - light: { | ||
599 | - rfill: dCol.offwhite, | ||
600 | - online: { | ||
601 | - glyph: dCol.darkgrey, | ||
602 | - rect: dCol.paleblue | ||
603 | - }, | ||
604 | - offline: { | ||
605 | - glyph: dCol.midgrey, | ||
606 | - rect: dCol.lightgrey | ||
607 | - } | ||
608 | - }, | ||
609 | - dark: { | ||
610 | - rfill: dCol.midgrey, | ||
611 | - online: { | ||
612 | - glyph: dCol.darkgrey, | ||
613 | - rect: dCol.paleblue | ||
614 | - }, | ||
615 | - offline: { | ||
616 | - glyph: dCol.midgrey, | ||
617 | - rect: dCol.darkgrey | ||
618 | - } | ||
619 | - } | ||
620 | - }; | ||
621 | - | ||
622 | - function devBaseColor(d) { | ||
623 | - var o = d.online ? 'online' : 'offline'; | ||
624 | - return dColTheme[ts.theme()][o]; | ||
625 | - } | ||
626 | - | ||
627 | - function setDeviceColor(d) { | ||
628 | - var o = d.online, | ||
629 | - s = d.el.classed('selected'), | ||
630 | - c = devBaseColor(d), | ||
631 | - a = instColor(d.master, o), | ||
632 | - icon = d.el.select('g.deviceIcon'), | ||
633 | - g, r; | ||
634 | - | ||
635 | - if (s) { | ||
636 | - g = c.glyph; | ||
637 | - r = dCol.orange; | ||
638 | - } else if (tis.isVisible()) { | ||
639 | - g = o ? a : c.glyph; | ||
640 | - r = o ? c.rfill : a; | ||
641 | - } else { | ||
642 | - g = c.glyph; | ||
643 | - r = c.rect; | ||
644 | - } | ||
645 | - | ||
646 | - icon.select('use').style('fill', g); | ||
647 | - icon.select('rect').style('fill', r); | ||
648 | - } | ||
649 | - | ||
650 | - function instColor(id, online) { | ||
651 | - return sus.cat7().getColor(id, !online, ts.theme()); | ||
652 | - } | ||
653 | - | ||
654 | - // ========================== | ||
655 | - | ||
656 | function updateNodes() { | 454 | function updateNodes() { |
657 | // select all the nodes in the layout: | 455 | // select all the nodes in the layout: |
658 | node = nodeG.selectAll('.node') | 456 | node = nodeG.selectAll('.node') |
659 | .data(network.nodes, function (d) { return d.id; }); | 457 | .data(network.nodes, function (d) { return d.id; }); |
660 | 458 | ||
661 | // operate on existing nodes: | 459 | // operate on existing nodes: |
662 | - node.filter('.device').each(deviceExisting); | 460 | + node.filter('.device').each(td3.deviceExisting); |
663 | - node.filter('.host').each(hostExisting); | 461 | + node.filter('.host').each(td3.hostExisting); |
664 | 462 | ||
665 | // operate on entering nodes: | 463 | // operate on entering nodes: |
666 | var entering = node.enter() | 464 | var entering = node.enter() |
... | @@ -678,11 +476,11 @@ | ... | @@ -678,11 +476,11 @@ |
678 | .attr('opacity', 1); | 476 | .attr('opacity', 1); |
679 | 477 | ||
680 | // augment entering nodes: | 478 | // augment entering nodes: |
681 | - entering.filter('.device').each(deviceEnter); | 479 | + entering.filter('.device').each(td3.deviceEnter); |
682 | - entering.filter('.host').each(hostEnter); | 480 | + entering.filter('.host').each(td3.hostEnter); |
683 | 481 | ||
684 | // operate on both existing and new nodes: | 482 | // operate on both existing and new nodes: |
685 | - updateDeviceColors(); | 483 | + td3.updateDeviceColors(); |
686 | 484 | ||
687 | // operate on exiting nodes: | 485 | // operate on exiting nodes: |
688 | // Note that the node is removed after 2 seconds. | 486 | // Note that the node is removed after 2 seconds. |
... | @@ -694,113 +492,14 @@ | ... | @@ -694,113 +492,14 @@ |
694 | .remove(); | 492 | .remove(); |
695 | 493 | ||
696 | // exiting node specifics: | 494 | // exiting node specifics: |
697 | - exiting.filter('.host').each(hostExit); | 495 | + exiting.filter('.host').each(td3.hostExit); |
698 | - exiting.filter('.device').each(deviceExit); | 496 | + exiting.filter('.device').each(td3.deviceExit); |
699 | 497 | ||
700 | // finally, resume the force layout | 498 | // finally, resume the force layout |
701 | fResume(); | 499 | fResume(); |
702 | } | 500 | } |
703 | 501 | ||
704 | // ========================== | 502 | // ========================== |
705 | - // updateNodes - subfunctions | ||
706 | - | ||
707 | - function deviceExisting(d) { | ||
708 | - var node = d.el; | ||
709 | - node.classed('online', d.online); | ||
710 | - updateDeviceLabel(d); | ||
711 | - tms.positionNode(d, true); | ||
712 | - } | ||
713 | - | ||
714 | - function hostExisting(d) { | ||
715 | - updateHostLabel(d); | ||
716 | - tms.positionNode(d, true); | ||
717 | - } | ||
718 | - | ||
719 | - function deviceEnter(d) { | ||
720 | - var node = d3.select(this), | ||
721 | - glyphId = d.type || 'unknown', | ||
722 | - label = trimLabel(deviceLabel(d)), | ||
723 | - devCfg = deviceIconConfig, | ||
724 | - noLabel = !label, | ||
725 | - box, dx, dy, icon; | ||
726 | - | ||
727 | - d.el = node; | ||
728 | - | ||
729 | - node.append('rect').attr({ rx: 5, ry: 5 }); | ||
730 | - node.append('text').text(label).attr('dy', '1.1em'); | ||
731 | - box = adjustRectToFitText(node); | ||
732 | - node.select('rect').attr(box); | ||
733 | - | ||
734 | - icon = is.addDeviceIcon(node, glyphId); | ||
735 | - | ||
736 | - if (noLabel) { | ||
737 | - dx = -icon.dim/2; | ||
738 | - dy = -icon.dim/2; | ||
739 | - } else { | ||
740 | - box = adjustRectToFitText(node); | ||
741 | - dx = box.x + devCfg.xoff; | ||
742 | - dy = box.y + devCfg.yoff; | ||
743 | - } | ||
744 | - | ||
745 | - icon.attr('transform', sus.translate(dx, dy)); | ||
746 | - } | ||
747 | - | ||
748 | - function hostEnter(d) { | ||
749 | - var node = d3.select(this), | ||
750 | - gid = d.type || 'unknown', | ||
751 | - rad = icfg.host.radius, | ||
752 | - r = d.type ? rad.withGlyph : rad.noGlyph, | ||
753 | - textDy = r + 10; | ||
754 | - | ||
755 | - d.el = node; | ||
756 | - sus.visible(node, showHosts); | ||
757 | - | ||
758 | - is.addHostIcon(node, r, gid); | ||
759 | - | ||
760 | - node.append('text') | ||
761 | - .text(hostLabel) | ||
762 | - .attr('dy', textDy) | ||
763 | - .attr('text-anchor', 'middle'); | ||
764 | - } | ||
765 | - | ||
766 | - function hostExit(d) { | ||
767 | - var node = d.el; | ||
768 | - node.select('use') | ||
769 | - .style('opacity', 0.5) | ||
770 | - .transition() | ||
771 | - .duration(800) | ||
772 | - .style('opacity', 0); | ||
773 | - | ||
774 | - node.select('text') | ||
775 | - .style('opacity', 0.5) | ||
776 | - .transition() | ||
777 | - .duration(800) | ||
778 | - .style('opacity', 0); | ||
779 | - | ||
780 | - node.select('circle') | ||
781 | - .style('stroke-fill', '#555') | ||
782 | - .style('fill', '#888') | ||
783 | - .style('opacity', 0.5) | ||
784 | - .transition() | ||
785 | - .duration(1500) | ||
786 | - .attr('r', 0); | ||
787 | - } | ||
788 | - | ||
789 | - function deviceExit(d) { | ||
790 | - var node = d.el; | ||
791 | - node.select('use') | ||
792 | - .style('opacity', 0.5) | ||
793 | - .transition() | ||
794 | - .duration(800) | ||
795 | - .style('opacity', 0); | ||
796 | - | ||
797 | - node.selectAll('rect') | ||
798 | - .style('stroke-fill', '#555') | ||
799 | - .style('fill', '#888') | ||
800 | - .style('opacity', 0.5); | ||
801 | - } | ||
802 | - | ||
803 | - // ========================== | ||
804 | 503 | ||
805 | function updateLinks() { | 504 | function updateLinks() { |
806 | var th = ts.theme(); | 505 | var th = ts.theme(); |
... | @@ -809,7 +508,7 @@ | ... | @@ -809,7 +508,7 @@ |
809 | .data(network.links, function (d) { return d.key; }); | 508 | .data(network.links, function (d) { return d.key; }); |
810 | 509 | ||
811 | // operate on existing links: | 510 | // operate on existing links: |
812 | - link.each(linkExisting); | 511 | + link.each(td3.linkExisting); |
813 | 512 | ||
814 | // operate on entering links: | 513 | // operate on entering links: |
815 | var entering = link.enter() | 514 | var entering = link.enter() |
... | @@ -824,14 +523,13 @@ | ... | @@ -824,14 +523,13 @@ |
824 | }); | 523 | }); |
825 | 524 | ||
826 | // augment links | 525 | // augment links |
827 | - entering.each(linkEntering); | 526 | + entering.each(td3.linkEntering); |
828 | 527 | ||
829 | // operate on both existing and new links: | 528 | // operate on both existing and new links: |
830 | //link.each(...) | 529 | //link.each(...) |
831 | 530 | ||
832 | // apply or remove labels | 531 | // apply or remove labels |
833 | - var labelData = getLabelData(); | 532 | + td3.applyLinkLabels(); |
834 | - applyLinkLabels(labelData); | ||
835 | 533 | ||
836 | // operate on exiting links: | 534 | // operate on exiting links: |
837 | link.exit() | 535 | link.exit() |
... | @@ -848,117 +546,6 @@ | ... | @@ -848,117 +546,6 @@ |
848 | .remove(); | 546 | .remove(); |
849 | } | 547 | } |
850 | 548 | ||
851 | - // ========================== | ||
852 | - // updateLinks - subfunctions | ||
853 | - | ||
854 | - function getLabelData() { | ||
855 | - // create the backing data for showing labels.. | ||
856 | - var data = []; | ||
857 | - link.each(function (d) { | ||
858 | - if (d.label) { | ||
859 | - data.push({ | ||
860 | - id: 'lab-' + d.key, | ||
861 | - key: d.key, | ||
862 | - label: d.label, | ||
863 | - ldata: d | ||
864 | - }); | ||
865 | - } | ||
866 | - }); | ||
867 | - return data; | ||
868 | - } | ||
869 | - | ||
870 | - function linkExisting(d) { | ||
871 | - // this is supposed to be an existing link, but we have observed | ||
872 | - // occasions (where links are deleted and added rapidly?) where | ||
873 | - // the DOM element has not been defined. So protection against that... | ||
874 | - if (d.el) { | ||
875 | - restyleLinkElement(d, true); | ||
876 | - } | ||
877 | - } | ||
878 | - | ||
879 | - function linkEntering(d) { | ||
880 | - var link = d3.select(this); | ||
881 | - d.el = link; | ||
882 | - restyleLinkElement(d); | ||
883 | - if (d.type() === 'hostLink') { | ||
884 | - sus.visible(link, showHosts); | ||
885 | - } | ||
886 | - } | ||
887 | - | ||
888 | - //function linkExiting(d) { } | ||
889 | - | ||
890 | - var linkLabelOffset = '0.3em'; | ||
891 | - | ||
892 | - function applyLinkLabels(data) { | ||
893 | - var entering; | ||
894 | - | ||
895 | - linkLabel = linkLabelG.selectAll('.linkLabel') | ||
896 | - .data(data, function (d) { return d.id; }); | ||
897 | - | ||
898 | - // for elements already existing, we need to update the text | ||
899 | - // and adjust the rectangle size to fit | ||
900 | - linkLabel.each(function (d) { | ||
901 | - var el = d3.select(this), | ||
902 | - rect = el.select('rect'), | ||
903 | - text = el.select('text'); | ||
904 | - text.text(d.label); | ||
905 | - rect.attr(rectAroundText(el)); | ||
906 | - }); | ||
907 | - | ||
908 | - entering = linkLabel.enter().append('g') | ||
909 | - .classed('linkLabel', true) | ||
910 | - .attr('id', function (d) { return d.id; }); | ||
911 | - | ||
912 | - entering.each(function (d) { | ||
913 | - var el = d3.select(this), | ||
914 | - rect, | ||
915 | - text, | ||
916 | - parms = { | ||
917 | - x1: d.ldata.source.x, | ||
918 | - y1: d.ldata.source.y, | ||
919 | - x2: d.ldata.target.x, | ||
920 | - y2: d.ldata.target.y | ||
921 | - }; | ||
922 | - | ||
923 | - if (d.ldata.type() === 'hostLink') { | ||
924 | - el.classed('hostLinkLabel', true); | ||
925 | - sus.visible(el, showHosts); | ||
926 | - } | ||
927 | - | ||
928 | - d.el = el; | ||
929 | - rect = el.append('rect'); | ||
930 | - text = el.append('text').text(d.label); | ||
931 | - rect.attr(rectAroundText(el)); | ||
932 | - text.attr('dy', linkLabelOffset); | ||
933 | - | ||
934 | - el.attr('transform', transformLabel(parms)); | ||
935 | - }); | ||
936 | - | ||
937 | - // Remove any labels that are no longer required. | ||
938 | - linkLabel.exit().remove(); | ||
939 | - } | ||
940 | - | ||
941 | - function rectAroundText(el) { | ||
942 | - var text = el.select('text'), | ||
943 | - box = text.node().getBBox(); | ||
944 | - | ||
945 | - // translate the bbox so that it is centered on [x,y] | ||
946 | - box.x = -box.width / 2; | ||
947 | - box.y = -box.height / 2; | ||
948 | - | ||
949 | - // add padding | ||
950 | - box.x -= 1; | ||
951 | - box.width += 2; | ||
952 | - return box; | ||
953 | - } | ||
954 | - | ||
955 | - function transformLabel(p) { | ||
956 | - var dx = p.x2 - p.x1, | ||
957 | - dy = p.y2 - p.y1, | ||
958 | - xMid = dx/2 + p.x1, | ||
959 | - yMid = dy/2 + p.y1; | ||
960 | - return sus.translate(xMid, yMid); | ||
961 | - } | ||
962 | 549 | ||
963 | // ========================== | 550 | // ========================== |
964 | // force layout tick function | 551 | // force layout tick function |
... | @@ -989,7 +576,7 @@ | ... | @@ -989,7 +576,7 @@ |
989 | transform: function (d) { | 576 | transform: function (d) { |
990 | var lnk = tms.findLinkById(d.key); | 577 | var lnk = tms.findLinkById(d.key); |
991 | if (lnk) { | 578 | if (lnk) { |
992 | - return transformLabel({ | 579 | + return td3.transformLabel({ |
993 | x1: lnk.source.x, | 580 | x1: lnk.source.x, |
994 | y1: lnk.source.y, | 581 | y1: lnk.source.y, |
995 | x2: lnk.target.x, | 582 | x2: lnk.target.x, |
... | @@ -1049,6 +636,24 @@ | ... | @@ -1049,6 +636,24 @@ |
1049 | }); | 636 | }); |
1050 | } | 637 | } |
1051 | 638 | ||
639 | + function updateLinkLabelModel() { | ||
640 | + // create the backing data for showing labels.. | ||
641 | + var data = []; | ||
642 | + link.each(function (d) { | ||
643 | + if (d.label) { | ||
644 | + data.push({ | ||
645 | + id: 'lab-' + d.key, | ||
646 | + key: d.key, | ||
647 | + label: d.label, | ||
648 | + ldata: d | ||
649 | + }); | ||
650 | + } | ||
651 | + }); | ||
652 | + | ||
653 | + linkLabel = linkLabelG.selectAll('.linkLabel') | ||
654 | + .data(data, function (d) { return d.id; }); | ||
655 | + } | ||
656 | + | ||
1052 | // ========================== | 657 | // ========================== |
1053 | // Module definition | 658 | // Module definition |
1054 | 659 | ||
... | @@ -1061,11 +666,24 @@ | ... | @@ -1061,11 +666,24 @@ |
1061 | }; | 666 | }; |
1062 | } | 667 | } |
1063 | 668 | ||
669 | + function mkD3Api(uplink) { | ||
670 | + return { | ||
671 | + node: function () { return node; }, | ||
672 | + link: function () { return link; }, | ||
673 | + linkLabel: function () { return linkLabel; }, | ||
674 | + instVisible: function () { return tis.isVisible(); }, | ||
675 | + posNode: tms.positionNode, | ||
676 | + showHosts: function () { return showHosts; }, | ||
677 | + restyleLinkElement: restyleLinkElement, | ||
678 | + updateLinkLabelModel: updateLinkLabelModel | ||
679 | + } | ||
680 | + } | ||
681 | + | ||
1064 | function mkSelectApi(uplink) { | 682 | function mkSelectApi(uplink) { |
1065 | return { | 683 | return { |
1066 | node: function () { return node; }, | 684 | node: function () { return node; }, |
1067 | zoomingOrPanning: zoomingOrPanning, | 685 | zoomingOrPanning: zoomingOrPanning, |
1068 | - updateDeviceColors: updateDeviceColors, | 686 | + updateDeviceColors: td3.updateDeviceColors, |
1069 | sendEvent: uplink.sendEvent | 687 | sendEvent: uplink.sendEvent |
1070 | }; | 688 | }; |
1071 | } | 689 | } |
... | @@ -1114,11 +732,11 @@ | ... | @@ -1114,11 +732,11 @@ |
1114 | .factory('TopoForceService', | 732 | .factory('TopoForceService', |
1115 | ['$log', 'FnService', 'SvgUtilService', 'IconService', 'ThemeService', | 733 | ['$log', 'FnService', 'SvgUtilService', 'IconService', 'ThemeService', |
1116 | 'FlashService', 'TopoInstService', 'TopoModelService', | 734 | 'FlashService', 'TopoInstService', 'TopoModelService', |
1117 | - 'TopoSelectService', 'TopoTrafficService', | 735 | + 'TopoD3Service', 'TopoSelectService', 'TopoTrafficService', |
1118 | 'TopoObliqueService', 'TopoFilterService', | 736 | 'TopoObliqueService', 'TopoFilterService', |
1119 | 737 | ||
1120 | function (_$log_, _fs_, _sus_, _is_, _ts_, _flash_, | 738 | function (_$log_, _fs_, _sus_, _is_, _ts_, _flash_, |
1121 | - _tis_, _tms_, _tss_, _tts_, _tos_, _fltr_) { | 739 | + _tis_, _tms_, _td3_, _tss_, _tts_, _tos_, _fltr_) { |
1122 | $log = _$log_; | 740 | $log = _$log_; |
1123 | fs = _fs_; | 741 | fs = _fs_; |
1124 | sus = _sus_; | 742 | sus = _sus_; |
... | @@ -1127,6 +745,7 @@ | ... | @@ -1127,6 +745,7 @@ |
1127 | flash = _flash_; | 745 | flash = _flash_; |
1128 | tis = _tis_; | 746 | tis = _tis_; |
1129 | tms = _tms_; | 747 | tms = _tms_; |
748 | + td3 = _td3_; | ||
1130 | tss = _tss_; | 749 | tss = _tss_; |
1131 | tts = _tts_; | 750 | tts = _tts_; |
1132 | tos = _tos_; | 751 | tos = _tos_; |
... | @@ -1150,6 +769,7 @@ | ... | @@ -1150,6 +769,7 @@ |
1150 | $log.debug('initForce().. dim = ' + dim); | 769 | $log.debug('initForce().. dim = ' + dim); |
1151 | 770 | ||
1152 | tms.initModel(mkModelApi(uplink), dim); | 771 | tms.initModel(mkModelApi(uplink), dim); |
772 | + td3.initD3(mkD3Api(uplink)); | ||
1153 | tss.initSelect(mkSelectApi(uplink)); | 773 | tss.initSelect(mkSelectApi(uplink)); |
1154 | tts.initTraffic(mkTrafficApi(uplink)); | 774 | tts.initTraffic(mkTrafficApi(uplink)); |
1155 | tos.initOblique(mkObliqueApi(uplink, fltr)); | 775 | tos.initOblique(mkObliqueApi(uplink, fltr)); |
... | @@ -1192,6 +812,7 @@ | ... | @@ -1192,6 +812,7 @@ |
1192 | tos.destroyOblique(); | 812 | tos.destroyOblique(); |
1193 | tts.destroyTraffic(); | 813 | tts.destroyTraffic(); |
1194 | tss.destroySelect(); | 814 | tss.destroySelect(); |
815 | + td3.destroyD3(); | ||
1195 | tms.destroyModel(); | 816 | tms.destroyModel(); |
1196 | ts.removeListener(themeListener); | 817 | ts.removeListener(themeListener); |
1197 | themeListener = null; | 818 | themeListener = null; |
... | @@ -1202,7 +823,7 @@ | ... | @@ -1202,7 +823,7 @@ |
1202 | newDim: newDim, | 823 | newDim: newDim, |
1203 | destroyForce: destroyForce, | 824 | destroyForce: destroyForce, |
1204 | 825 | ||
1205 | - updateDeviceColors: updateDeviceColors, | 826 | + updateDeviceColors: td3.updateDeviceColors, |
1206 | toggleHosts: toggleHosts, | 827 | toggleHosts: toggleHosts, |
1207 | toggleOffline: toggleOffline, | 828 | toggleOffline: toggleOffline, |
1208 | cycleDeviceLabels: cycleDeviceLabels, | 829 | cycleDeviceLabels: cycleDeviceLabels, | ... | ... |
... | @@ -86,6 +86,7 @@ | ... | @@ -86,6 +86,7 @@ |
86 | <!-- {INJECTED-JAVASCRIPT-START} --> | 86 | <!-- {INJECTED-JAVASCRIPT-START} --> |
87 | <script src="app/view/sample/sample.js"></script> | 87 | <script src="app/view/sample/sample.js"></script> |
88 | <script src="app/view/topo/topo.js"></script> | 88 | <script src="app/view/topo/topo.js"></script> |
89 | + <script src="app/view/topo/topoD3.js"></script> | ||
89 | <script src="app/view/topo/topoEvent.js"></script> | 90 | <script src="app/view/topo/topoEvent.js"></script> |
90 | <script src="app/view/topo/topoFilter.js"></script> | 91 | <script src="app/view/topo/topoFilter.js"></script> |
91 | <script src="app/view/topo/topoForce.js"></script> | 92 | <script src="app/view/topo/topoForce.js"></script> |
... | @@ -104,7 +105,6 @@ | ... | @@ -104,7 +105,6 @@ |
104 | <link rel="stylesheet" href="app/view/sample/sample.css"> | 105 | <link rel="stylesheet" href="app/view/sample/sample.css"> |
105 | <link rel="stylesheet" href="app/view/topo/topo.css"> | 106 | <link rel="stylesheet" href="app/view/topo/topo.css"> |
106 | <link rel="stylesheet" href="app/view/device/device.css"> | 107 | <link rel="stylesheet" href="app/view/device/device.css"> |
107 | - <!-- TODO: inject style-sheet refs server-side --> | ||
108 | <!-- {INJECTED-STYLESHEETS-END} --> | 108 | <!-- {INJECTED-STYLESHEETS-END} --> |
109 | 109 | ||
110 | </head> | 110 | </head> | ... | ... |
-
Please register or login to post a comment