blob: e45f491835423931f28a810773a52b2e34179a69 [file] [log] [blame]
Simon Hunta4242de2015-02-24 17:11:55 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Simon Hunta4242de2015-02-24 17:11:55 -08003 *
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
Thomas Vachuska0af26912016-03-21 21:37:30 -070026 var $log, fs, sus, is, ts, ps, ttbs;
Simon Hunta4242de2015-02-24 17:11:55 -080027
28 // api to topoForce
Steven Burrowsf17f0ab2017-04-11 11:03:58 -070029 var zoomer, api;
Simon Hunta4242de2015-02-24 17:11:55 -080030 /*
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
Simon Hunta5487ad2016-06-16 13:10:41 -070042 var devIconDim = 36,
Simon Hunte9062fc2016-12-22 11:40:06 -080043 devColorDim = 32,
Simon Hunta5487ad2016-06-16 13:10:41 -070044 labelPad = 4,
45 hostRadius = 14,
46 badgeConfig = {
Simon Hunt5674db92015-10-22 16:12:48 -070047 radius: 12,
Simon Hunt004fc2c2015-10-23 11:55:58 -070048 yoff: 5,
49 gdelta: 10
Simon Hunta5487ad2016-06-16 13:10:41 -070050 },
51 halfDevIcon = devIconDim / 2,
52 devBadgeOff = { dx: -halfDevIcon, dy: -halfDevIcon },
53 hostBadgeOff = { dx: -hostRadius, dy: -hostRadius },
Steven Burrowsf17f0ab2017-04-11 11:03:58 -070054 portLabelDim = 30,
Simon Hunta5487ad2016-06-16 13:10:41 -070055 status = {
56 i: 'badgeInfo',
57 w: 'badgeWarn',
58 e: 'badgeError'
Simon Huntf44d7262016-06-14 14:46:56 -070059 };
60
Simon Hunt1eee51d2016-02-26 19:12:13 -080061 // NOTE: this type of hack should go away once we have implemented
62 // the server-side UiModel code.
63 // {virtual -> cord} is for the E-CORD demo at ONS 2016
64 var remappedDeviceTypes = {
Simon Hunte9062fc2016-12-22 11:40:06 -080065 virtual: 'cord',
66
67 // for now, map to the new glyphs via this lookup.
68 // may have to find a better way to do this...
69 'switch': 'm_switch',
70 roadm: 'm_roadm',
71 otn: 'm_otn',
72 roadm_otn: 'm_roadm_otn',
73 fiber_switch: 'm_fiberSwitch',
74 microwave: 'm_microwave',
75 };
76
77 var remappedHostTypes = {
78 router: 'm_router',
79 endstation: 'm_endstation',
80 bgpSpeaker: 'm_bgpSpeaker'
Simon Hunt1eee51d2016-02-26 19:12:13 -080081 };
82
83 function mapDeviceTypeToGlyph(type) {
84 return remappedDeviceTypes[type] || type || 'unknown';
85 }
86
Simon Hunte9062fc2016-12-22 11:40:06 -080087 function mapHostTypeToGlyph(type) {
88 return remappedHostTypes[type] || type || 'unknown';
89 }
90
Simon Hunt5674db92015-10-22 16:12:48 -070091 function badgeStatus(badge) {
92 return status[badge.status] || status.i;
93 }
94
Simon Hunta4242de2015-02-24 17:11:55 -080095 // internal state
96 var deviceLabelIndex = 0,
97 hostLabelIndex = 0;
98
Simon Hunta5487ad2016-06-16 13:10:41 -070099 // note: these are the device icon colors without affinity (no master)
Simon Hunta4242de2015-02-24 17:11:55 -0800100 var dColTheme = {
101 light: {
Simon Huntf44d7262016-06-14 14:46:56 -0700102 online: '#444444',
103 offline: '#cccccc'
Simon Hunta4242de2015-02-24 17:11:55 -0800104 },
105 dark: {
Simon Huntf44d7262016-06-14 14:46:56 -0700106 // TODO: theme
107 online: '#444444',
108 offline: '#cccccc'
Simon Hunta4242de2015-02-24 17:11:55 -0800109 }
110 };
111
Simon Huntf44d7262016-06-14 14:46:56 -0700112 function devGlyphColor(d) {
113 var o = d.online,
114 id = d.master,
115 otag = o ? 'online' : 'offline';
116 return o ? sus.cat7().getColor(id, 0, ts.theme())
117 : dColTheme[ts.theme()][otag];
Simon Hunta4242de2015-02-24 17:11:55 -0800118 }
119
120 function setDeviceColor(d) {
Simon Hunte9062fc2016-12-22 11:40:06 -0800121 // want to color the square rectangle (no longer the 'use' glyph)
122 d.el.selectAll('rect').filter(function (d, i) {return i === 1;})
Simon Huntf44d7262016-06-14 14:46:56 -0700123 .style('fill', devGlyphColor(d));
Simon Hunta4242de2015-02-24 17:11:55 -0800124 }
125
Simon Hunta4242de2015-02-24 17:11:55 -0800126 function incDevLabIndex() {
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700127 setDevLabIndex(deviceLabelIndex+1);
Bri Prebilic Cole9cf1a8d2015-04-21 13:15:29 -0700128 switch(deviceLabelIndex) {
129 case 0: return 'Hide device labels';
130 case 1: return 'Show friendly device labels';
131 case 2: return 'Show device ID labels';
132 }
Simon Hunta4242de2015-02-24 17:11:55 -0800133 }
134
Thomas Vachuska0af26912016-03-21 21:37:30 -0700135 function setDevLabIndex(mode) {
136 deviceLabelIndex = mode % 3;
137 var p = ps.getPrefs('topo_prefs', ttbs.defaultPrefs);
138 p.dlbls = deviceLabelIndex;
139 ps.setPrefs('topo_prefs', p);
140 }
141
Simon Hunta4242de2015-02-24 17:11:55 -0800142 function hostLabel(d) {
143 var idx = (hostLabelIndex < d.labels.length) ? hostLabelIndex : 0;
144 return d.labels[idx];
145 }
Simon Huntf44d7262016-06-14 14:46:56 -0700146
Simon Hunta4242de2015-02-24 17:11:55 -0800147 function deviceLabel(d) {
148 var idx = (deviceLabelIndex < d.labels.length) ? deviceLabelIndex : 0;
149 return d.labels[idx];
150 }
Simon Huntf44d7262016-06-14 14:46:56 -0700151
Simon Hunta4242de2015-02-24 17:11:55 -0800152 function trimLabel(label) {
153 return (label && label.trim()) || '';
154 }
155
Simon Huntf44d7262016-06-14 14:46:56 -0700156 function computeLabelWidth(n) {
157 var text = n.select('text'),
158 box = text.node().getBBox();
159 return box.width + labelPad * 2;
160 }
161
162 function iconBox(dim, labelWidth) {
Simon Hunta4242de2015-02-24 17:11:55 -0800163 return {
Simon Huntf44d7262016-06-14 14:46:56 -0700164 x: -dim/2,
165 y: -dim/2,
166 width: dim + labelWidth,
167 height: dim
168 }
Simon Hunta4242de2015-02-24 17:11:55 -0800169 }
170
Simon Hunt5674db92015-10-22 16:12:48 -0700171 function updateDeviceRendering(d) {
Simon Huntf44d7262016-06-14 14:46:56 -0700172 var node = d.el,
173 bdg = d.badge,
174 label = trimLabel(deviceLabel(d)),
175 labelWidth;
Simon Hunta4242de2015-02-24 17:11:55 -0800176
Simon Huntf44d7262016-06-14 14:46:56 -0700177 node.select('text').text(label);
178 labelWidth = label ? computeLabelWidth(node) : 0;
Simon Hunta4242de2015-02-24 17:11:55 -0800179
180 node.select('rect')
181 .transition()
Simon Huntf44d7262016-06-14 14:46:56 -0700182 .attr(iconBox(devIconDim, labelWidth));
Simon Hunta4242de2015-02-24 17:11:55 -0800183
Simon Hunt5674db92015-10-22 16:12:48 -0700184 if (bdg) {
Simon Hunta5487ad2016-06-16 13:10:41 -0700185 renderBadge(node, bdg, devBadgeOff);
Simon Hunte9343f32015-10-21 18:07:46 -0700186 }
187 }
188
Andrea Campanella52125412015-12-03 14:50:40 -0800189 function updateHostRendering(d) {
190 var node = d.el,
Simon Huntc2bfe332015-12-04 11:01:24 -0800191 bdg = d.badge;
Andrea Campanella52125412015-12-03 14:50:40 -0800192
193 updateHostLabel(d);
Andrea Campanella52125412015-12-03 14:50:40 -0800194
Andrea Campanella52125412015-12-03 14:50:40 -0800195 if (bdg) {
Simon Hunta5487ad2016-06-16 13:10:41 -0700196 renderBadge(node, bdg, hostBadgeOff);
Simon Huntc2bfe332015-12-04 11:01:24 -0800197 }
198 }
Andrea Campanella52125412015-12-03 14:50:40 -0800199
Simon Huntc2bfe332015-12-04 11:01:24 -0800200 function renderBadge(node, bdg, boff) {
201 var bsel,
202 bcr = badgeConfig.radius,
203 bcgd = badgeConfig.gdelta;
Andrea Campanella52125412015-12-03 14:50:40 -0800204
Simon Huntc2bfe332015-12-04 11:01:24 -0800205 node.select('g.badge').remove();
Andrea Campanella52125412015-12-03 14:50:40 -0800206
Simon Huntc2bfe332015-12-04 11:01:24 -0800207 bsel = node.append('g')
208 .classed('badge', true)
209 .classed(badgeStatus(bdg), true)
210 .attr('transform', sus.translate(boff.dx, boff.dy));
Andrea Campanella52125412015-12-03 14:50:40 -0800211
Simon Huntc2bfe332015-12-04 11:01:24 -0800212 bsel.append('circle')
213 .attr('r', bcr);
214
215 if (bdg.txt) {
216 bsel.append('text')
217 .attr('dy', badgeConfig.yoff)
218 .attr('text-anchor', 'middle')
219 .text(bdg.txt);
220 } else if (bdg.gid) {
221 bsel.append('use')
222 .attr({
223 width: bcgd * 2,
224 height: bcgd * 2,
225 transform: sus.translate(-bcgd, -bcgd),
226 'xlink:href': '#' + bdg.gid
227 });
Andrea Campanella52125412015-12-03 14:50:40 -0800228 }
229 }
230
Simon Hunta4242de2015-02-24 17:11:55 -0800231 function updateHostLabel(d) {
232 var label = trimLabel(hostLabel(d));
233 d.el.select('text').text(label);
234 }
235
236 function updateDeviceColors(d) {
237 if (d) {
238 setDeviceColor(d);
239 } else {
240 api.node().filter('.device').each(function (d) {
241 setDeviceColor(d);
242 });
243 }
244 }
245
246
247 // ==========================
248 // updateNodes - subfunctions
249
250 function deviceExisting(d) {
251 var node = d.el;
252 node.classed('online', d.online);
Simon Hunt5674db92015-10-22 16:12:48 -0700253 updateDeviceRendering(d);
Simon Hunta4242de2015-02-24 17:11:55 -0800254 api.posNode(d, true);
255 }
256
257 function hostExisting(d) {
Andrea Campanella52125412015-12-03 14:50:40 -0800258 updateHostRendering(d);
Simon Hunta4242de2015-02-24 17:11:55 -0800259 api.posNode(d, true);
260 }
261
262 function deviceEnter(d) {
263 var node = d3.select(this),
Simon Hunt1eee51d2016-02-26 19:12:13 -0800264 glyphId = mapDeviceTypeToGlyph(d.type),
Simon Hunta4242de2015-02-24 17:11:55 -0800265 label = trimLabel(deviceLabel(d)),
Simon Hunte9062fc2016-12-22 11:40:06 -0800266 rect, crect, text, glyph, labelWidth;
Simon Hunta4242de2015-02-24 17:11:55 -0800267
268 d.el = node;
269
Simon Huntf44d7262016-06-14 14:46:56 -0700270 rect = node.append('rect');
Simon Hunte9062fc2016-12-22 11:40:06 -0800271 crect = node.append('rect');
Simon Hunta4242de2015-02-24 17:11:55 -0800272
Simon Huntf44d7262016-06-14 14:46:56 -0700273 text = node.append('text').text(label)
274 .attr('text-anchor', 'left')
275 .attr('y', '0.3em')
Simon Hunta5487ad2016-06-16 13:10:41 -0700276 .attr('x', halfDevIcon + labelPad);
Simon Hunta4242de2015-02-24 17:11:55 -0800277
Simon Huntf44d7262016-06-14 14:46:56 -0700278 glyph = is.addDeviceIcon(node, glyphId, devIconDim);
Simon Hunta4242de2015-02-24 17:11:55 -0800279
Simon Huntf44d7262016-06-14 14:46:56 -0700280 labelWidth = label ? computeLabelWidth(node) : 0;
281
282 rect.attr(iconBox(devIconDim, labelWidth));
Simon Hunte9062fc2016-12-22 11:40:06 -0800283 crect.attr(iconBox(devColorDim, 0));
Simon Huntf44d7262016-06-14 14:46:56 -0700284 glyph.attr(iconBox(devIconDim, 0));
285
Simon Hunta5487ad2016-06-16 13:10:41 -0700286 node.attr('transform', sus.translate(-halfDevIcon, -halfDevIcon));
Steven Burrowsf17f0ab2017-04-11 11:03:58 -0700287
288 d.el.selectAll('*')
289 .style('transform', 'scale(' + api.deviceScale() + ')');
Simon Hunta4242de2015-02-24 17:11:55 -0800290 }
291
292 function hostEnter(d) {
293 var node = d3.select(this),
Simon Hunte9062fc2016-12-22 11:40:06 -0800294 glyphId = mapHostTypeToGlyph(d.type),
Simon Hunta5487ad2016-06-16 13:10:41 -0700295 textDy = hostRadius + 10;
Simon Hunta4242de2015-02-24 17:11:55 -0800296
297 d.el = node;
298 sus.visible(node, api.showHosts());
299
Simon Hunte9062fc2016-12-22 11:40:06 -0800300 is.addHostIcon(node, hostRadius, glyphId);
Simon Hunta4242de2015-02-24 17:11:55 -0800301
302 node.append('text')
303 .text(hostLabel)
304 .attr('dy', textDy)
305 .attr('text-anchor', 'middle');
Steven Burrowsf17f0ab2017-04-11 11:03:58 -0700306
307 d.el.selectAll('g').style('transform', 'scale(' + api.deviceScale() + ')');
308 d.el.selectAll('text').style('transform', 'scale(' + api.deviceScale() + ')');
Simon Hunta4242de2015-02-24 17:11:55 -0800309 }
310
311 function hostExit(d) {
312 var node = d.el;
313 node.select('use')
314 .style('opacity', 0.5)
315 .transition()
316 .duration(800)
317 .style('opacity', 0);
318
319 node.select('text')
320 .style('opacity', 0.5)
321 .transition()
322 .duration(800)
323 .style('opacity', 0);
324
325 node.select('circle')
326 .style('stroke-fill', '#555')
327 .style('fill', '#888')
328 .style('opacity', 0.5)
329 .transition()
330 .duration(1500)
331 .attr('r', 0);
332 }
333
334 function deviceExit(d) {
335 var node = d.el;
336 node.select('use')
337 .style('opacity', 0.5)
338 .transition()
339 .duration(800)
340 .style('opacity', 0);
341
342 node.selectAll('rect')
343 .style('stroke-fill', '#555')
344 .style('fill', '#888')
345 .style('opacity', 0.5);
346 }
347
348
349 // ==========================
350 // updateLinks - subfunctions
351
Simon Hunta4242de2015-02-24 17:11:55 -0800352 function linkEntering(d) {
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100353
Simon Hunta4242de2015-02-24 17:11:55 -0800354 var link = d3.select(this);
355 d.el = link;
Steven Burrowsf17f0ab2017-04-11 11:03:58 -0700356 d.el.style('stroke-width', api.linkWidthScale() + 'px');
Simon Hunta4242de2015-02-24 17:11:55 -0800357 api.restyleLinkElement(d);
358 if (d.type() === 'hostLink') {
359 sus.visible(link, api.showHosts());
360 }
361 }
362
363 var linkLabelOffset = '0.3em';
364
365 function applyLinkLabels() {
366 var entering;
367
368 api.updateLinkLabelModel();
369
370 // for elements already existing, we need to update the text
371 // and adjust the rectangle size to fit
372 api.linkLabel().each(function (d) {
373 var el = d3.select(this),
374 rect = el.select('rect'),
375 text = el.select('text');
376 text.text(d.label);
377 rect.attr(rectAroundText(el));
378 });
379
380 entering = api.linkLabel().enter().append('g')
381 .classed('linkLabel', true)
382 .attr('id', function (d) { return d.id; });
383
384 entering.each(function (d) {
385 var el = d3.select(this),
386 rect,
Bri Prebilic Cole038aedd2015-07-13 15:25:16 -0700387 text;
Simon Hunta4242de2015-02-24 17:11:55 -0800388
389 if (d.ldata.type() === 'hostLink') {
390 el.classed('hostLinkLabel', true);
391 sus.visible(el, api.showHosts());
392 }
393
394 d.el = el;
395 rect = el.append('rect');
396 text = el.append('text').text(d.label);
397 rect.attr(rectAroundText(el));
398 text.attr('dy', linkLabelOffset);
399
Carmelo Casconed01eda62016-08-02 10:19:15 -0700400 el.attr('transform', transformLabel(d.ldata.position, d.key));
Simon Hunta4242de2015-02-24 17:11:55 -0800401 });
402
403 // Remove any labels that are no longer required.
404 api.linkLabel().exit().remove();
405 }
406
407 function rectAroundText(el) {
408 var text = el.select('text'),
409 box = text.node().getBBox();
410
411 // translate the bbox so that it is centered on [x,y]
412 box.x = -box.width / 2;
413 box.y = -box.height / 2;
414
415 // add padding
416 box.x -= 1;
417 box.width += 2;
418 return box;
419 }
420
Carmelo Casconed01eda62016-08-02 10:19:15 -0700421 function generateLabelFunction() {
Simon Hunte093e782017-03-31 10:19:08 -0700422 var labels = [],
423 xGap = 15,
424 yGap = 17;
Carmelo Casconed01eda62016-08-02 10:19:15 -0700425
Simon Hunte093e782017-03-31 10:19:08 -0700426 return function (newId, newX, newY) {
Carmelo Casconed01eda62016-08-02 10:19:15 -0700427 var idx = -1;
428
Simon Hunte093e782017-03-31 10:19:08 -0700429 labels.forEach(function (lab, i) {
430 var minX, maxX, minY, maxY;
431
432 if (lab.id === newId) {
Carmelo Casconed01eda62016-08-02 10:19:15 -0700433 idx = i;
434 return;
435 }
Simon Hunte093e782017-03-31 10:19:08 -0700436 minX = lab.x - xGap;
437 maxX = lab.x + xGap;
438 minY = lab.y - yGap;
439 maxY = lab.y + yGap;
Carmelo Casconed01eda62016-08-02 10:19:15 -0700440
441 if (newX > minX && newX < maxX && newY > minY && newY < maxY) {
442 // labels are overlapped
443 newX = newX - xGap;
444 newY = newY - yGap;
445 }
446 });
447
448 if (idx === -1) {
449 labels.push({id: newId, x: newX, y: newY});
Simon Hunte093e782017-03-31 10:19:08 -0700450 } else {
Carmelo Casconed01eda62016-08-02 10:19:15 -0700451 labels[idx] = {id: newId, x: newX, y: newY};
452 }
453
454 return {x: newX, y: newY};
455 }
456 }
457
Simon Hunte093e782017-03-31 10:19:08 -0700458 var getLabelPos = generateLabelFunction();
Carmelo Casconed01eda62016-08-02 10:19:15 -0700459
460 function transformLabel(p, id) {
Simon Hunta4242de2015-02-24 17:11:55 -0800461 var dx = p.x2 - p.x1,
462 dy = p.y2 - p.y1,
463 xMid = dx/2 + p.x1,
464 yMid = dy/2 + p.y1;
Carmelo Casconed01eda62016-08-02 10:19:15 -0700465
466 if (id) {
Simon Hunte093e782017-03-31 10:19:08 -0700467 var pos = getLabelPos(id, xMid, yMid);
Carmelo Casconed01eda62016-08-02 10:19:15 -0700468 return sus.translate(pos.x, pos.y);
469 }
470
Simon Hunta4242de2015-02-24 17:11:55 -0800471 return sus.translate(xMid, yMid);
472 }
473
Simon Hunt1a5301e2015-02-25 15:31:25 -0800474 function applyPortLabels(data, portLabelG) {
475 var entering = portLabelG.selectAll('.portLabel')
476 .data(data).enter().append('g')
477 .classed('portLabel', true)
478 .attr('id', function (d) { return d.id; });
479
Steven Burrowsf17f0ab2017-04-11 11:03:58 -0700480 var labelScale = portLabelDim / (portLabelDim * zoomer.scale());
481
Simon Hunt1a5301e2015-02-25 15:31:25 -0800482 entering.each(function (d) {
483 var el = d3.select(this),
484 rect = el.append('rect'),
485 text = el.append('text').text(d.num);
486
Steven Burrowsf17f0ab2017-04-11 11:03:58 -0700487 rect.attr(rectAroundText(el))
488 .style('transform', 'scale(' + labelScale + ')');
489 text.attr('dy', linkLabelOffset)
490 .style('transform', 'scale(' + labelScale + ')');
491
Simon Hunt969b3c92015-02-25 18:11:31 -0800492 el.attr('transform', sus.translate(d.x, d.y));
Simon Hunt1a5301e2015-02-25 15:31:25 -0800493 });
494 }
495
Bri Prebilic Cole80401762015-07-16 11:36:18 -0700496 function labelPoint(linkPos) {
497 var lengthUpLine = 1 / 3,
498 dx = linkPos.x2 - linkPos.x1,
499 dy = linkPos.y2 - linkPos.y1,
500 movedX = dx * lengthUpLine,
501 movedY = dy * lengthUpLine;
502
503 return {
504 x: movedX,
505 y: movedY
506 };
507 }
508
509 function calcGroupPos(linkPos) {
510 var moved = labelPoint(linkPos);
511 return sus.translate(linkPos.x1 + moved.x, linkPos.y1 + moved.y);
512 }
513
514 // calculates where on the link that the hash line for 5+ label appears
515 function hashAttrs(linkPos) {
516 var hashLength = 25,
517 halfLength = hashLength / 2,
518 dx = linkPos.x2 - linkPos.x1,
519 dy = linkPos.y2 - linkPos.y1,
520 length = Math.sqrt((dx * dx) + (dy * dy)),
521 moveAmtX = (dx / length) * halfLength,
522 moveAmtY = (dy / length) * halfLength,
523 mid = labelPoint(linkPos),
524 angle = Math.atan(dy / dx) + 45;
525
526 return {
527 x1: mid.x - moveAmtX,
528 y1: mid.y - moveAmtY,
529 x2: mid.x + moveAmtX,
530 y2: mid.y + moveAmtY,
531 stroke: api.linkConfig()[ts.theme()].baseColor,
532 transform: 'rotate(' + angle + ',' + mid.x + ',' + mid.y + ')'
533 };
534 }
535
536 function textLabelPos(linkPos) {
537 var point = labelPoint(linkPos),
538 dist = 20;
539 return {
540 x: point.x + dist,
541 y: point.y + dist
542 };
543 }
544
545 function applyNumLinkLabels(data, lblsG) {
546 var labels = lblsG.selectAll('g.numLinkLabel')
547 .data(data, function (d) { return 'pair-' + d.id; }),
548 entering;
549
550 // update existing labels
551 labels.each(function (d) {
552 var el = d3.select(this);
553
554 el.attr({
555 transform: function (d) { return calcGroupPos(d.linkCoords); }
556 });
557 el.select('line')
558 .attr(hashAttrs(d.linkCoords));
559 el.select('text')
560 .attr(textLabelPos(d.linkCoords))
561 .text(d.num);
562 });
563
564 // add new labels
565 entering = labels
566 .enter()
567 .append('g')
568 .attr({
569 transform: function (d) { return calcGroupPos(d.linkCoords); },
570 id: function (d) { return 'pair-' + d.id; }
571 })
572 .classed('numLinkLabel', true);
573
574 entering.each(function (d) {
575 var el = d3.select(this);
576
577 el.append('line')
578 .classed('numLinkHash', true)
579 .attr(hashAttrs(d.linkCoords));
580 el.append('text')
581 .classed('numLinkText', true)
582 .attr(textLabelPos(d.linkCoords))
583 .text(d.num);
584 });
585
586 // remove old labels
587 labels.exit().remove();
588 }
589
Simon Hunta4242de2015-02-24 17:11:55 -0800590 // ==========================
591 // Module definition
592
593 angular.module('ovTopo')
594 .factory('TopoD3Service',
595 ['$log', 'FnService', 'SvgUtilService', 'IconService', 'ThemeService',
Thomas Vachuska0af26912016-03-21 21:37:30 -0700596 'PrefsService', 'TopoToolbarService',
Simon Hunta4242de2015-02-24 17:11:55 -0800597
Thomas Vachuska0af26912016-03-21 21:37:30 -0700598 function (_$log_, _fs_, _sus_, _is_, _ts_, _ps_, _ttbs_) {
Simon Hunta4242de2015-02-24 17:11:55 -0800599 $log = _$log_;
600 fs = _fs_;
601 sus = _sus_;
602 is = _is_;
603 ts = _ts_;
Thomas Vachuska0af26912016-03-21 21:37:30 -0700604 ps = _ps_;
605 ttbs = _ttbs_;
Simon Hunta4242de2015-02-24 17:11:55 -0800606
Steven Burrowsf17f0ab2017-04-11 11:03:58 -0700607 function initD3(_api_, _zoomer_) {
Simon Hunta4242de2015-02-24 17:11:55 -0800608 api = _api_;
Steven Burrowsf17f0ab2017-04-11 11:03:58 -0700609 zoomer = _zoomer_;
Simon Hunta4242de2015-02-24 17:11:55 -0800610 }
611
612 function destroyD3() { }
613
614 return {
615 initD3: initD3,
616 destroyD3: destroyD3,
617
618 incDevLabIndex: incDevLabIndex,
Thomas Vachuska0af26912016-03-21 21:37:30 -0700619 setDevLabIndex: setDevLabIndex,
Simon Hunta4242de2015-02-24 17:11:55 -0800620 hostLabel: hostLabel,
621 deviceLabel: deviceLabel,
622 trimLabel: trimLabel,
623
Simon Hunt5674db92015-10-22 16:12:48 -0700624 updateDeviceLabel: updateDeviceRendering,
Simon Hunta4242de2015-02-24 17:11:55 -0800625 updateHostLabel: updateHostLabel,
626 updateDeviceColors: updateDeviceColors,
627
628 deviceExisting: deviceExisting,
629 hostExisting: hostExisting,
630 deviceEnter: deviceEnter,
631 hostEnter: hostEnter,
632 hostExit: hostExit,
633 deviceExit: deviceExit,
634
Simon Hunta4242de2015-02-24 17:11:55 -0800635 linkEntering: linkEntering,
636 applyLinkLabels: applyLinkLabels,
Simon Hunt1a5301e2015-02-25 15:31:25 -0800637 transformLabel: transformLabel,
Bri Prebilic Cole80401762015-07-16 11:36:18 -0700638 applyPortLabels: applyPortLabels,
639 applyNumLinkLabels: applyNumLinkLabels
Simon Hunta4242de2015-02-24 17:11:55 -0800640 };
641 }]);
642}());