Simon Hunt

Added keydown handler.

Some refactoring.
Cleaned up debug configuration.
Links now clipped to edges of node rectangles.
Updated ONOS icon (just a placeholder for now)

16.9 KB | W: | H:

74.1 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
...@@ -26,13 +26,19 @@ ...@@ -26,13 +26,19 @@
26 (function (onos) { 26 (function (onos) {
27 'use strict'; 27 'use strict';
28 28
29 + // reference to the framework api
29 var api = onos.api; 30 var api = onos.api;
30 31
32 + // configuration data
31 var config = { 33 var config = {
34 + debugOn: false,
35 + debug: {
36 + showNodeXY: true,
37 + showKeyHandler: false
38 + },
32 options: { 39 options: {
33 layering: true, 40 layering: true,
34 - collisionPrevention: true, 41 + collisionPrevention: true
35 - showNodeXY: true
36 }, 42 },
37 XjsonUrl: 'rs/topology/graph', 43 XjsonUrl: 'rs/topology/graph',
38 jsonUrl: 'network.json', 44 jsonUrl: 'network.json',
...@@ -88,20 +94,28 @@ ...@@ -88,20 +94,28 @@
88 }, 94 },
89 hostLinkWidth: 1.0, 95 hostLinkWidth: 1.0,
90 mouseOutTimerDelayMs: 120 96 mouseOutTimerDelayMs: 120
91 - }, 97 + };
92 - view = {}, 98 +
99 + // state variables
100 + var view = {},
93 network = {}, 101 network = {},
94 selected = {}, 102 selected = {},
95 highlighted = null, 103 highlighted = null,
96 viewMode = 'showAll'; 104 viewMode = 'showAll';
97 105
98 106
107 + function debug(what) {
108 + return config.debugOn && config.debug[what];
109 + }
110 +
111 + // load the topology view of the network
99 function loadNetworkView() { 112 function loadNetworkView() {
100 // Hey, here I am, calling something on the ONOS api: 113 // Hey, here I am, calling something on the ONOS api:
101 api.printTime(); 114 api.printTime();
102 115
103 resize(); 116 resize();
104 117
118 + // go get our network data from the server...
105 d3.json(config.jsonUrl, function (err, data) { 119 d3.json(config.jsonUrl, function (err, data) {
106 if (err) { 120 if (err) {
107 alert('Oops! Error reading JSON...\n\n' + 121 alert('Oops! Error reading JSON...\n\n' +
...@@ -109,14 +123,23 @@ ...@@ -109,14 +123,23 @@
109 'Error: ' + err.message); 123 'Error: ' + err.message);
110 return; 124 return;
111 } 125 }
112 - console.log("here is the JSON data..."); 126 +// console.log("here is the JSON data...");
113 - console.log(data); 127 +// console.log(data);
114 128
115 network.data = data; 129 network.data = data;
116 drawNetwork(); 130 drawNetwork();
117 }); 131 });
118 132
119 - $(document).on('click', '.select-object', function() { 133 + // while we wait for the data, set up the handlers...
134 + setUpClickHandler();
135 + setUpRadioButtonHandler();
136 + setUpKeyHandler();
137 + $(window).on('resize', resize);
138 + }
139 +
140 + function setUpClickHandler() {
141 + // click handler for "selectable" objects
142 + $(document).on('click', '.select-object', function () {
120 // when any object of class "select-object" is clicked... 143 // when any object of class "select-object" is clicked...
121 // TODO: get a reference to the object via lookup... 144 // TODO: get a reference to the object via lookup...
122 var obj = network.lookup[$(this).data('id')]; 145 var obj = network.lookup[$(this).data('id')];
...@@ -126,25 +149,67 @@ ...@@ -126,25 +149,67 @@
126 // stop propagation of event (I think) ... 149 // stop propagation of event (I think) ...
127 return false; 150 return false;
128 }); 151 });
152 + }
129 153
130 - $(window).on('resize', resize); 154 + function setUpRadioButtonHandler() {
131 - 155 + d3.selectAll('#displayModes .radio').on('click', function () {
132 - // set up radio button behavior 156 + var id = d3.select(this).attr('id');
133 - d3.selectAll("#displayModes .radio").on('click', function() {
134 - var id = d3.select(this).attr("id");
135 if (id !== viewMode) { 157 if (id !== viewMode) {
136 radioButton('displayModes', id); 158 radioButton('displayModes', id);
137 viewMode = id; 159 viewMode = id;
138 - alert("action: " + id); 160 + alert('action: ' + id);
139 } 161 }
140 }); 162 });
141 } 163 }
142 164
165 + function setUpKeyHandler() {
166 + d3.select('body')
167 + .on('keydown', function () {
168 + processKeyEvent();
169 + if (debug('showKeyHandler')) {
170 + network.svg.append('text')
171 + .attr('x', 5)
172 + .attr('y', 15)
173 + .style('font-size', '20pt')
174 + .text('keyCode: ' + d3.event.keyCode +
175 + ' applied to : ' + contextLabel())
176 + .transition().duration(2000)
177 + .style('font-size', '2pt')
178 + .style('fill-opacity', 0.01)
179 + .remove();
180 + }
181 + });
182 + }
183 +
143 function radioButton(group, id) { 184 function radioButton(group, id) {
144 d3.selectAll("#" + group + " .radio").classed("active", false); 185 d3.selectAll("#" + group + " .radio").classed("active", false);
145 d3.select("#" + group + " #" + id).classed("active", true); 186 d3.select("#" + group + " #" + id).classed("active", true);
146 } 187 }
147 188
189 + function contextLabel() {
190 + return highlighted === null ? "(nothing)" : highlighted.id;
191 + }
192 +
193 + function processKeyEvent() {
194 + var code = d3.event.keyCode;
195 + switch (code) {
196 + case 76: // L
197 + cycleLabels();
198 + break;
199 + case 80: // P
200 + togglePorts();
201 + }
202 +
203 + }
204 +
205 + function cycleLabels() {
206 + alert('Cycle Labels - context = ' + contextLabel());
207 + }
208 +
209 + function togglePorts() {
210 + alert('Toggle Ports - context = ' + contextLabel());
211 + }
212 +
148 213
149 // ======================================================== 214 // ========================================================
150 215
...@@ -430,8 +495,9 @@ ...@@ -430,8 +495,9 @@
430 // adjusted the bounds of the rectangle... 495 // adjusted the bounds of the rectangle...
431 } 496 }
432 497
433 - // for debugging... 498 + // debug function to show the modelled x,y coordinates of nodes...
434 - if (config.options.showNodeXY) { 499 + if (debug('showNodeXY')) {
500 + node.select('rect').attr('fill-opacity', 0.5);
435 node.append('circle') 501 node.append('circle')
436 .attr({ 502 .attr({
437 class: 'debug', 503 class: 'debug',
...@@ -599,34 +665,41 @@ ...@@ -599,34 +665,41 @@
599 preventCollisions(); 665 preventCollisions();
600 } 666 }
601 667
602 - // TODO: use intersection technique for source end of link also 668 + // clip visualization of links at bounds of nodes...
603 - network.link 669 + network.link.each(function(d) {
604 - .attr('x1', function(d) { 670 + var xs = d.source.x,
605 - return d.source.x; 671 + ys = d.source.y,
606 - }) 672 + xt = d.target.x,
607 - .attr('y1', function(d) { 673 + yt = d.target.y,
608 - return d.source.y; 674 + line = new geo.LineSegment(xs, ys, xt, yt),
609 - }) 675 + e, ix;
610 - .each(function(d) { 676 +
611 - var x = d.target.x, 677 + for (e in d.source.edge) {
612 - y = d.target.y, 678 + ix = line.intersect(d.source.edge[e].offset(xs, ys));
613 - line = new geo.LineSegment(d.source.x, d.source.y, x, y); 679 + if (ix.in1 && ix.in2) {
680 + xs = ix.x;
681 + ys = ix.y;
682 + break;
683 + }
684 + }
614 685
615 - for (var e in d.target.edge) { 686 + for (e in d.target.edge) {
616 - var ix = line.intersect(d.target.edge[e].offset(x,y)); 687 + ix = line.intersect(d.target.edge[e].offset(xt, yt));
617 if (ix.in1 && ix.in2) { 688 if (ix.in1 && ix.in2) {
618 - x = ix.x; 689 + xt = ix.x;
619 - y = ix.y; 690 + yt = ix.y;
620 break; 691 break;
621 } 692 }
622 } 693 }
623 694
624 d3.select(this) 695 d3.select(this)
625 - .attr('x2', x) 696 + .attr('x1', xs)
626 - .attr('y2', y); 697 + .attr('y1', ys)
627 - 698 + .attr('x2', xt)
699 + .attr('y2', yt);
628 }); 700 });
629 701
702 + // position each node by translating the node (group) by x,y
630 network.node 703 network.node
631 .attr('transform', function(d) { 704 .attr('transform', function(d) {
632 return translate(d.x, d.y); 705 return translate(d.x, d.y);
......
...@@ -82,7 +82,7 @@ svg { ...@@ -82,7 +82,7 @@ svg {
82 svg .link { 82 svg .link {
83 fill: none; 83 fill: none;
84 stroke: #666; 84 stroke: #666;
85 - stroke-width: 1.5px; 85 + stroke-width: 2.0px;
86 opacity: .7; 86 opacity: .7;
87 /*marker-end: url(#end);*/ 87 /*marker-end: url(#end);*/
88 88
......