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