Simon Hunt

GUI - Implemented link labels showing data on links when traffic is flowing..

Change-Id: I3fe602d20c5756620d2c4eb793dac2a0c8d1379c
...@@ -12,9 +12,9 @@ ...@@ -12,9 +12,9 @@
12 "of:0000ffffffff0007/1-0E:2A:69:30:13:89/-1/0" 12 "of:0000ffffffff0007/1-0E:2A:69:30:13:89/-1/0"
13 ], 13 ],
14 "labels": [ 14 "labels": [
15 - "Load{rate=98, latest=38080}", 15 + "Load{rate=20, latest=20000}",
16 - "Load{rate=98, latest=38080}", 16 + "Load{rate=10, latest=20000}",
17 - "Load{rate=98, latest=38080}" 17 + ""
18 ] 18 ]
19 } 19 }
20 ] 20 ]
......
...@@ -12,9 +12,9 @@ ...@@ -12,9 +12,9 @@
12 "of:0000ffffffff0007/1-0E:2A:69:30:13:89/-1/0" 12 "of:0000ffffffff0007/1-0E:2A:69:30:13:89/-1/0"
13 ], 13 ],
14 "labels": [ 14 "labels": [
15 - "Load{rate=98, latest=38080}", 15 + "",
16 - "Load{rate=98, latest=38080}", 16 + "Load{rate=98, latest=38456}",
17 - "Load{rate=98, latest=38080}" 17 + "Load{rate=98, latest=38789}"
18 ] 18 ]
19 } 19 }
20 ] 20 ]
......
...@@ -154,6 +154,17 @@ svg .node.host circle { ...@@ -154,6 +154,17 @@ svg .node.host circle {
154 stroke-dasharray: 8 8 154 stroke-dasharray: 8 8
155 } 155 }
156 156
157 +#topo svg .linkLabel rect {
158 + fill: #eef;
159 + stroke: blue;
160 + stroke-width: 0.3;
161 +}
162 +#topo svg .linkLabel text {
163 + text-anchor: middle;
164 + fill: #a13d11;
165 + stroke: none;
166 + font-size: 8pt;
167 +}
157 168
158 /* Fly-in details pane */ 169 /* Fly-in details pane */
159 170
......
...@@ -186,8 +186,10 @@ ...@@ -186,8 +186,10 @@
186 topoG, 186 topoG,
187 nodeG, 187 nodeG,
188 linkG, 188 linkG,
189 + linkLabelG,
189 node, 190 node,
190 link, 191 link,
192 + linkLabel,
191 mask; 193 mask;
192 194
193 // the projection for the map background 195 // the projection for the map background
...@@ -710,17 +712,25 @@ ...@@ -710,17 +712,25 @@
710 712
711 // Revert any links hilighted previously. 713 // Revert any links hilighted previously.
712 link.classed('primary secondary animated optical', false); 714 link.classed('primary secondary animated optical', false);
715 + // Remove all previous labels.
716 + removeLinkLabels();
713 717
714 - // Now hilight all links in the paths payload. 718 + // Now hilight all links in the paths payload, and attach
719 + // labels to them, if they are defined.
715 paths.forEach(function (p) { 720 paths.forEach(function (p) {
716 - var cls = p.class; 721 + var n = p.links.length,
717 - p.links.forEach(function (id) { 722 + i,
718 - var lnk = findLinkById(id); 723 + ldata;
719 - if (lnk) { 724 +
720 - lnk.el.classed(cls, true); 725 + for (i=0; i<n; i++) {
726 + ldata = findLinkById(p.links[i]);
727 + if (ldata) {
728 + ldata.el.classed(p.class, true);
729 + ldata.label = p.labels[i];
730 + }
721 } 731 }
722 }); 732 });
723 - }); 733 + updateLinks();
724 } 734 }
725 735
726 // ............................... 736 // ...............................
...@@ -891,6 +901,10 @@ ...@@ -891,6 +901,10 @@
891 return 'translate(' + x + ',' + y + ')'; 901 return 'translate(' + x + ',' + y + ')';
892 } 902 }
893 903
904 + function rotate(deg) {
905 + return 'rotate(' + deg + ')';
906 + }
907 +
894 function missMsg(what, id) { 908 function missMsg(what, id) {
895 return '\n[' + what + '] "' + id + '" missing '; 909 return '\n[' + what + '] "' + id + '" missing ';
896 } 910 }
...@@ -973,6 +987,12 @@ ...@@ -973,6 +987,12 @@
973 return lnk; 987 return lnk;
974 } 988 }
975 989
990 + function removeLinkLabels() {
991 + network.links.forEach(function (d) {
992 + d.label = '';
993 + });
994 + }
995 +
976 var widthRatio = 1.4, 996 var widthRatio = 1.4,
977 linkScale = d3.scale.linear() 997 linkScale = d3.scale.linear()
978 .domain([1, 12]) 998 .domain([1, 12])
...@@ -1004,13 +1024,15 @@ ...@@ -1004,13 +1024,15 @@
1004 // provide ref to element selection from backing data.... 1024 // provide ref to element selection from backing data....
1005 d.el = link; 1025 d.el = link;
1006 restyleLinkElement(d); 1026 restyleLinkElement(d);
1007 -
1008 - // TODO: add src/dst port labels etc.
1009 }); 1027 });
1010 1028
1011 // operate on both existing and new links, if necessary 1029 // operate on both existing and new links, if necessary
1012 //link .foo() .bar() ... 1030 //link .foo() .bar() ...
1013 1031
1032 + // apply or remove labels
1033 + var labelData = getLabelData();
1034 + applyLinkLabels(labelData);
1035 +
1014 // operate on exiting links: 1036 // operate on exiting links:
1015 link.exit() 1037 link.exit()
1016 .attr('stroke-dasharray', '3, 3') 1038 .attr('stroke-dasharray', '3, 3')
...@@ -1024,6 +1046,95 @@ ...@@ -1024,6 +1046,95 @@
1024 }) 1046 })
1025 .style('opacity', 0.0) 1047 .style('opacity', 0.0)
1026 .remove(); 1048 .remove();
1049 +
1050 + // NOTE: invoke a single tick to force the labels to position
1051 + // onto their links.
1052 + tick();
1053 + }
1054 +
1055 + function getLabelData() {
1056 + // create the backing data for showing labels..
1057 + var data = [];
1058 + link.each(function (d) {
1059 + if (d.label) {
1060 + data.push({
1061 + id: 'lab-' + d.key,
1062 + key: d.key,
1063 + label: d.label,
1064 + ldata: d
1065 + });
1066 + }
1067 + });
1068 + return data;
1069 + }
1070 +
1071 + var linkLabelOffset = '0.3em';
1072 +
1073 + function applyLinkLabels(data) {
1074 + var entering;
1075 +
1076 + linkLabel = linkLabelG.selectAll('.linkLabel')
1077 + .data(data, function (d) { return d.id; });
1078 +
1079 + entering = linkLabel.enter().append('g')
1080 + .classed('linkLabel', true)
1081 + .attr('id', function (d) { return d.id; });
1082 +
1083 + entering.each(function (d) {
1084 + var el = d3.select(this),
1085 + rect,
1086 + text,
1087 + parms = {
1088 + x1: d.ldata.x1,
1089 + y1: d.ldata.y1,
1090 + x2: d.ldata.x2,
1091 + y2: d.ldata.y2
1092 + };
1093 +
1094 + d.el = el;
1095 + rect = el.append('rect');
1096 + text = el.append('text').text(d.label);
1097 + rect.attr(rectAroundText(el));
1098 + text.attr('dy', linkLabelOffset);
1099 +
1100 + el.attr('transform', transformLabel(parms));
1101 + });
1102 +
1103 + // Remove any links that are no longer required.
1104 + linkLabel.exit().remove();
1105 + }
1106 +
1107 + function rectAroundText(el) {
1108 + var text = el.select('text'),
1109 + box = text.node().getBBox();
1110 +
1111 + // translate the bbox so that it is centered on [x,y]
1112 + box.x = -box.width / 2;
1113 + box.y = -box.height / 2;
1114 +
1115 + // add padding
1116 + box.x -= 1;
1117 + box.width += 2;
1118 + return box;
1119 + }
1120 +
1121 + function transformLabel(p) {
1122 + var dx = p.x2 - p.x1,
1123 + dy = p.y2 - p.y1,
1124 + xMid = dx/2 + p.x1,
1125 + yMid = dy/2 + p.y1;
1126 + //length = Math.sqrt(dx*dx + dy*dy),
1127 + //rads = Math.asin(dy/length),
1128 + //degs = rads / (Math.PI*2) * 360;
1129 +
1130 + return translate(xMid, yMid);
1131 +
1132 + // TODO: consider making label parallel to line
1133 + //return [
1134 + // translate(xMid, yMid),
1135 + // rotate(degs),
1136 + // translate(0, 8)
1137 + //].join('');
1027 } 1138 }
1028 1139
1029 function createDeviceNode(device) { 1140 function createDeviceNode(device) {
...@@ -1443,6 +1554,18 @@ ...@@ -1443,6 +1554,18 @@
1443 x2: function (d) { return d.target.x; }, 1554 x2: function (d) { return d.target.x; },
1444 y2: function (d) { return d.target.y; } 1555 y2: function (d) { return d.target.y; }
1445 }); 1556 });
1557 +
1558 + linkLabel.each(function (d) {
1559 + var el = d3.select(this);
1560 + var lnk = findLinkById(d.key),
1561 + parms = {
1562 + x1: lnk.source.x,
1563 + y1: lnk.source.y,
1564 + x2: lnk.target.x,
1565 + y2: lnk.target.y
1566 + };
1567 + el.attr('transform', transformLabel(parms));
1568 + });
1446 } 1569 }
1447 1570
1448 // ============================== 1571 // ==============================
...@@ -1839,12 +1962,14 @@ ...@@ -1839,12 +1962,14 @@
1839 .attr('id', 'topo-G') 1962 .attr('id', 'topo-G')
1840 .attr('transform', fcfg.translate()); 1963 .attr('transform', fcfg.translate());
1841 1964
1842 - // subgroups for links and nodes 1965 + // subgroups for links, link labels, and nodes
1843 linkG = topoG.append('g').attr('id', 'links'); 1966 linkG = topoG.append('g').attr('id', 'links');
1967 + linkLabelG = topoG.append('g').attr('id', 'linkLabels');
1844 nodeG = topoG.append('g').attr('id', 'nodes'); 1968 nodeG = topoG.append('g').attr('id', 'nodes');
1845 1969
1846 - // selection of nodes and links 1970 + // selection of links, linkLabels, and nodes
1847 link = linkG.selectAll('.link'); 1971 link = linkG.selectAll('.link');
1972 + linkLabel = linkLabelG.selectAll('.linkLabel');
1848 node = nodeG.selectAll('.node'); 1973 node = nodeG.selectAll('.node');
1849 1974
1850 function chrg(d) { 1975 function chrg(d) {
......