Bri Prebilic Cole
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
...@@ -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);
......