Committed by
Gerrit Code Review
ONOS-2385 -- Bug fixes for removing individual links on the Topo View. 5 or more…
… links between devices have a label indicating how many there are between each one. Change-Id: I301ca6da8c453b54e16980a47e09dfd9f2f80f8b
Showing
5 changed files
with
148 additions
and
10 deletions
... | @@ -579,6 +579,26 @@ html[data-platform='iPad'] #topo-p-detail { | ... | @@ -579,6 +579,26 @@ html[data-platform='iPad'] #topo-p-detail { |
579 | fill: #eee; | 579 | fill: #eee; |
580 | } | 580 | } |
581 | 581 | ||
582 | +/* Number of Links Labels */ | ||
583 | +#ov-topo line.numLinkHash { | ||
584 | + stroke-width: 3; | ||
585 | +} | ||
586 | + | ||
587 | +#ov-topo text.numLinkText { | ||
588 | + font-size: 15pt; | ||
589 | +} | ||
590 | + | ||
591 | +#ov-topo text.numLinkText { | ||
592 | + text-anchor: middle; | ||
593 | +} | ||
594 | + | ||
595 | +.light #ov-topo text.numLinkText { | ||
596 | + fill: #444; | ||
597 | +} | ||
598 | +.dark #ov-topo text.numLinkText { | ||
599 | + fill: #eee; | ||
600 | +} | ||
601 | + | ||
582 | /* ------------------------------------------------- */ | 602 | /* ------------------------------------------------- */ |
583 | /* Sprite Layer */ | 603 | /* Sprite Layer */ |
584 | 604 | ... | ... |
... | @@ -429,6 +429,100 @@ | ... | @@ -429,6 +429,100 @@ |
429 | }); | 429 | }); |
430 | } | 430 | } |
431 | 431 | ||
432 | + function labelPoint(linkPos) { | ||
433 | + var lengthUpLine = 1 / 3, | ||
434 | + dx = linkPos.x2 - linkPos.x1, | ||
435 | + dy = linkPos.y2 - linkPos.y1, | ||
436 | + movedX = dx * lengthUpLine, | ||
437 | + movedY = dy * lengthUpLine; | ||
438 | + | ||
439 | + return { | ||
440 | + x: movedX, | ||
441 | + y: movedY | ||
442 | + }; | ||
443 | + } | ||
444 | + | ||
445 | + function calcGroupPos(linkPos) { | ||
446 | + var moved = labelPoint(linkPos); | ||
447 | + return sus.translate(linkPos.x1 + moved.x, linkPos.y1 + moved.y); | ||
448 | + } | ||
449 | + | ||
450 | + // calculates where on the link that the hash line for 5+ label appears | ||
451 | + function hashAttrs(linkPos) { | ||
452 | + var hashLength = 25, | ||
453 | + halfLength = hashLength / 2, | ||
454 | + dx = linkPos.x2 - linkPos.x1, | ||
455 | + dy = linkPos.y2 - linkPos.y1, | ||
456 | + length = Math.sqrt((dx * dx) + (dy * dy)), | ||
457 | + moveAmtX = (dx / length) * halfLength, | ||
458 | + moveAmtY = (dy / length) * halfLength, | ||
459 | + mid = labelPoint(linkPos), | ||
460 | + angle = Math.atan(dy / dx) + 45; | ||
461 | + | ||
462 | + return { | ||
463 | + x1: mid.x - moveAmtX, | ||
464 | + y1: mid.y - moveAmtY, | ||
465 | + x2: mid.x + moveAmtX, | ||
466 | + y2: mid.y + moveAmtY, | ||
467 | + stroke: api.linkConfig()[ts.theme()].baseColor, | ||
468 | + transform: 'rotate(' + angle + ',' + mid.x + ',' + mid.y + ')' | ||
469 | + }; | ||
470 | + } | ||
471 | + | ||
472 | + function textLabelPos(linkPos) { | ||
473 | + var point = labelPoint(linkPos), | ||
474 | + dist = 20; | ||
475 | + return { | ||
476 | + x: point.x + dist, | ||
477 | + y: point.y + dist | ||
478 | + }; | ||
479 | + } | ||
480 | + | ||
481 | + function applyNumLinkLabels(data, lblsG) { | ||
482 | + var labels = lblsG.selectAll('g.numLinkLabel') | ||
483 | + .data(data, function (d) { return 'pair-' + d.id; }), | ||
484 | + entering; | ||
485 | + | ||
486 | + // update existing labels | ||
487 | + labels.each(function (d) { | ||
488 | + var el = d3.select(this); | ||
489 | + | ||
490 | + el.attr({ | ||
491 | + transform: function (d) { return calcGroupPos(d.linkCoords); } | ||
492 | + }); | ||
493 | + el.select('line') | ||
494 | + .attr(hashAttrs(d.linkCoords)); | ||
495 | + el.select('text') | ||
496 | + .attr(textLabelPos(d.linkCoords)) | ||
497 | + .text(d.num); | ||
498 | + }); | ||
499 | + | ||
500 | + // add new labels | ||
501 | + entering = labels | ||
502 | + .enter() | ||
503 | + .append('g') | ||
504 | + .attr({ | ||
505 | + transform: function (d) { return calcGroupPos(d.linkCoords); }, | ||
506 | + id: function (d) { return 'pair-' + d.id; } | ||
507 | + }) | ||
508 | + .classed('numLinkLabel', true); | ||
509 | + | ||
510 | + entering.each(function (d) { | ||
511 | + var el = d3.select(this); | ||
512 | + | ||
513 | + el.append('line') | ||
514 | + .classed('numLinkHash', true) | ||
515 | + .attr(hashAttrs(d.linkCoords)); | ||
516 | + el.append('text') | ||
517 | + .classed('numLinkText', true) | ||
518 | + .attr(textLabelPos(d.linkCoords)) | ||
519 | + .text(d.num); | ||
520 | + }); | ||
521 | + | ||
522 | + // remove old labels | ||
523 | + labels.exit().remove(); | ||
524 | + } | ||
525 | + | ||
432 | // ========================== | 526 | // ========================== |
433 | // Module definition | 527 | // Module definition |
434 | 528 | ||
... | @@ -475,7 +569,8 @@ | ... | @@ -475,7 +569,8 @@ |
475 | linkEntering: linkEntering, | 569 | linkEntering: linkEntering, |
476 | applyLinkLabels: applyLinkLabels, | 570 | applyLinkLabels: applyLinkLabels, |
477 | transformLabel: transformLabel, | 571 | transformLabel: transformLabel, |
478 | - applyPortLabels: applyPortLabels | 572 | + applyPortLabels: applyPortLabels, |
573 | + applyNumLinkLabels: applyNumLinkLabels | ||
479 | }; | 574 | }; |
480 | }]); | 575 | }]); |
481 | }()); | 576 | }()); | ... | ... |
... | @@ -61,10 +61,11 @@ | ... | @@ -61,10 +61,11 @@ |
61 | fTimer, // timer for delayed force layout | 61 | fTimer, // timer for delayed force layout |
62 | fNodesTimer, // timer for delayed nodes update | 62 | fNodesTimer, // timer for delayed nodes update |
63 | fLinksTimer, // timer for delayed links update | 63 | fLinksTimer, // timer for delayed links update |
64 | - dim; // the dimensions of the force layout [w,h] | 64 | + dim, // the dimensions of the force layout [w,h] |
65 | + linkNums = []; // array of link number labels | ||
65 | 66 | ||
66 | // SVG elements; | 67 | // SVG elements; |
67 | - var linkG, linkLabelG, portLabelG, nodeG; | 68 | + var linkG, linkLabelG, numLinkLblsG, portLabelG, nodeG; |
68 | 69 | ||
69 | // D3 selections; | 70 | // D3 selections; |
70 | var link, linkLabel, node; | 71 | var link, linkLabel, node; |
... | @@ -608,6 +609,7 @@ | ... | @@ -608,6 +609,7 @@ |
608 | function calcPosition() { | 609 | function calcPosition() { |
609 | var lines = this, | 610 | var lines = this, |
610 | linkSrcId; | 611 | linkSrcId; |
612 | + linkNums = []; | ||
611 | lines.each(function (d) { | 613 | lines.each(function (d) { |
612 | if (d.type() === 'hostLink') { | 614 | if (d.type() === 'hostLink') { |
613 | d.position = getDefaultPos(d); | 615 | d.position = getDefaultPos(d); |
... | @@ -625,13 +627,14 @@ | ... | @@ -625,13 +627,14 @@ |
625 | return link.source.id !== linkSrcId; | 627 | return link.source.id !== linkSrcId; |
626 | } | 628 | } |
627 | 629 | ||
628 | - angular.forEach(network.linksByDevice, function (linkArr) { | 630 | + angular.forEach(network.linksByDevice, function (linkArr, key) { |
629 | var numLinks = linkArr.length, | 631 | var numLinks = linkArr.length, |
630 | link; | 632 | link; |
631 | 633 | ||
632 | if (numLinks === 1) { | 634 | if (numLinks === 1) { |
633 | link = linkArr[0]; | 635 | link = linkArr[0]; |
634 | link.position = getDefaultPos(link); | 636 | link.position = getDefaultPos(link); |
637 | + link.position.multiLink = false; | ||
635 | } else if (numLinks >= 5) { | 638 | } else if (numLinks >= 5) { |
636 | // this code is inefficient, in the future the way links | 639 | // this code is inefficient, in the future the way links |
637 | // are modeled will be changed | 640 | // are modeled will be changed |
... | @@ -639,13 +642,18 @@ | ... | @@ -639,13 +642,18 @@ |
639 | link.position = getDefaultPos(link); | 642 | link.position = getDefaultPos(link); |
640 | link.position.multiLink = true; | 643 | link.position.multiLink = true; |
641 | }); | 644 | }); |
645 | + linkNums.push({ | ||
646 | + id: key, | ||
647 | + num: numLinks, | ||
648 | + linkCoords: linkArr[0].position | ||
649 | + }); | ||
642 | } else { | 650 | } else { |
643 | - // calculate position of links | ||
644 | linkSrcId = null; | 651 | linkSrcId = null; |
645 | angular.forEach(linkArr, function (link, index) { | 652 | angular.forEach(linkArr, function (link, index) { |
646 | var offsetAmt = amt(numLinks, index), | 653 | var offsetAmt = amt(numLinks, index), |
647 | needToFlip = normalizeLinkSrc(link); | 654 | needToFlip = normalizeLinkSrc(link); |
648 | link.position = calcMovement(link, offsetAmt, needToFlip); | 655 | link.position = calcMovement(link, offsetAmt, needToFlip); |
656 | + link.position.multiLink = false; | ||
649 | }); | 657 | }); |
650 | } | 658 | } |
651 | }); | 659 | }); |
... | @@ -696,6 +704,9 @@ | ... | @@ -696,6 +704,9 @@ |
696 | // operate on both existing and new links: | 704 | // operate on both existing and new links: |
697 | //link.each(...) | 705 | //link.each(...) |
698 | 706 | ||
707 | + // add labels for how many links are in a thick line | ||
708 | + td3.applyNumLinkLabels(linkNums, numLinkLblsG); | ||
709 | + | ||
699 | // apply or remove labels | 710 | // apply or remove labels |
700 | td3.applyLinkLabels(); | 711 | td3.applyLinkLabels(); |
701 | 712 | ||
... | @@ -764,6 +775,7 @@ | ... | @@ -764,6 +775,7 @@ |
764 | if (link) { | 775 | if (link) { |
765 | link.call(calcPosition) | 776 | link.call(calcPosition) |
766 | .attr(tickStuff.linkAttr); | 777 | .attr(tickStuff.linkAttr); |
778 | + td3.applyNumLinkLabels(linkNums, numLinkLblsG); | ||
767 | } | 779 | } |
768 | if (linkLabel) { | 780 | if (linkLabel) { |
769 | linkLabel.attr(tickStuff.linkLabelAttr); | 781 | linkLabel.attr(tickStuff.linkLabelAttr); |
... | @@ -855,7 +867,8 @@ | ... | @@ -855,7 +867,8 @@ |
855 | posNode: tms.positionNode, | 867 | posNode: tms.positionNode, |
856 | showHosts: function () { return showHosts; }, | 868 | showHosts: function () { return showHosts; }, |
857 | restyleLinkElement: restyleLinkElement, | 869 | restyleLinkElement: restyleLinkElement, |
858 | - updateLinkLabelModel: updateLinkLabelModel | 870 | + updateLinkLabelModel: updateLinkLabelModel, |
871 | + linkConfig: function () { return linkConfig; } | ||
859 | }; | 872 | }; |
860 | } | 873 | } |
861 | 874 | ||
... | @@ -897,7 +910,10 @@ | ... | @@ -897,7 +910,10 @@ |
897 | }, | 910 | }, |
898 | opacifyMap: uplink.opacifyMap, | 911 | opacifyMap: uplink.opacifyMap, |
899 | inLayer: fltr.inLayer, | 912 | inLayer: fltr.inLayer, |
900 | - calcLinkPos: calcPosition | 913 | + calcLinkPos: calcPosition, |
914 | + applyNumLinkLabels: function () { | ||
915 | + td3.applyNumLinkLabels(linkNums, numLinkLblsG); | ||
916 | + } | ||
901 | }; | 917 | }; |
902 | } | 918 | } |
903 | 919 | ||
... | @@ -975,6 +991,7 @@ | ... | @@ -975,6 +991,7 @@ |
975 | 991 | ||
976 | linkG = forceG.append('g').attr('id', 'topo-links'); | 992 | linkG = forceG.append('g').attr('id', 'topo-links'); |
977 | linkLabelG = forceG.append('g').attr('id', 'topo-linkLabels'); | 993 | linkLabelG = forceG.append('g').attr('id', 'topo-linkLabels'); |
994 | + numLinkLblsG = forceG.append('g').attr('id', 'topo-numLinkLabels'); | ||
978 | nodeG = forceG.append('g').attr('id', 'topo-nodes'); | 995 | nodeG = forceG.append('g').attr('id', 'topo-nodes'); |
979 | portLabelG = forceG.append('g').attr('id', 'topo-portLabels'); | 996 | portLabelG = forceG.append('g').attr('id', 'topo-portLabels'); |
980 | 997 | ||
... | @@ -1026,7 +1043,9 @@ | ... | @@ -1026,7 +1043,9 @@ |
1026 | network.lookup = {}; | 1043 | network.lookup = {}; |
1027 | network.revLinkToKey = {}; | 1044 | network.revLinkToKey = {}; |
1028 | 1045 | ||
1029 | - linkG = linkLabelG = nodeG = portLabelG = null; | 1046 | + linkNums = []; |
1047 | + | ||
1048 | + linkG = linkLabelG = numLinkLblsG = nodeG = portLabelG = null; | ||
1030 | link = linkLabel = node = null; | 1049 | link = linkLabel = node = null; |
1031 | force = drag = null; | 1050 | force = drag = null; |
1032 | 1051 | ... | ... |
... | @@ -301,7 +301,10 @@ | ... | @@ -301,7 +301,10 @@ |
301 | // remove link out of aggregate linksByDevice list | 301 | // remove link out of aggregate linksByDevice list |
302 | var linksForDevPair = linksByDevice[ldata.devicePair], | 302 | var linksForDevPair = linksByDevice[ldata.devicePair], |
303 | rmvIdx = fs.find(ldata.key, linksForDevPair, 'key'); | 303 | rmvIdx = fs.find(ldata.key, linksForDevPair, 'key'); |
304 | - linksForDevPair.splice(rmvIdx, 1); | 304 | + if (rmvIdx >= 0) { |
305 | + linksForDevPair.splice(rmvIdx, 1); | ||
306 | + } | ||
307 | + ldata.position.multilink = linksForDevPair.length >= 5; | ||
305 | 308 | ||
306 | if (link) { | 309 | if (link) { |
307 | // remove fromSource | 310 | // remove fromSource | ... | ... |
... | @@ -157,7 +157,8 @@ | ... | @@ -157,7 +157,8 @@ |
157 | api.link().transition() | 157 | api.link().transition() |
158 | .duration(time) | 158 | .duration(time) |
159 | .call(api.calcLinkPos) | 159 | .call(api.calcLinkPos) |
160 | - .attr(api.tickStuff.linkAttr); | 160 | + .attr(api.tickStuff.linkAttr) |
161 | + .call(api.applyNumLinkLabels); | ||
161 | api.linkLabel().transition() | 162 | api.linkLabel().transition() |
162 | .duration(time) | 163 | .duration(time) |
163 | .attr(api.tickStuff.linkLabelAttr); | 164 | .attr(api.tickStuff.linkLabelAttr); | ... | ... |
-
Please register or login to post a comment