Simon Hunt
Committed by Gerrit Code Review

GUI -- implemented ONOS instance affinity display.

- augmented ESC key handling to cancel affinity display before deslecting nodes.
- augmented setRadioButtons to return buttonset api, so we can query what is currently selected.

Change-Id: I17532bae7ea5fa639ce5d600c67e6c44728ff67f
...@@ -347,7 +347,8 @@ ...@@ -347,7 +347,8 @@
347 347
348 function setRadioButtons(vid, btnSet) { 348 function setRadioButtons(vid, btnSet) {
349 var view = views[vid], 349 var view = views[vid],
350 - btnG; 350 + btnG,
351 + api = {};
351 352
352 // lazily create the buttons... 353 // lazily create the buttons...
353 if (!(btnG = view.radioButtons)) { 354 if (!(btnG = view.radioButtons)) {
...@@ -365,10 +366,12 @@ ...@@ -365,10 +366,12 @@
365 }) 366 })
366 .text(txt); 367 .text(txt);
367 368
369 + btn.id = bid;
368 btnG.buttonDef[uid] = btn; 370 btnG.buttonDef[uid] = btn;
369 371
370 if (i === 0) { 372 if (i === 0) {
371 button.classed('active', true); 373 button.classed('active', true);
374 + btnG.selected = bid;
372 } 375 }
373 }); 376 });
374 377
...@@ -382,6 +385,7 @@ ...@@ -382,6 +385,7 @@
382 if (!act) { 385 if (!act) {
383 btnG.selectAll('span').classed('active', false); 386 btnG.selectAll('span').classed('active', false);
384 button.classed('active', true); 387 button.classed('active', true);
388 + btnG.selected = btn.id;
385 if (isF(btn.cb)) { 389 if (isF(btn.cb)) {
386 btn.cb(view.token(), btn); 390 btn.cb(view.token(), btn);
387 } 391 }
...@@ -389,10 +393,16 @@ ...@@ -389,10 +393,16 @@
389 }); 393 });
390 394
391 view.radioButtons = btnG; 395 view.radioButtons = btnG;
396 +
397 + api.selected = function () {
398 + return btnG.selected;
399 + }
392 } 400 }
393 401
394 // attach the buttons to the masthead 402 // attach the buttons to the masthead
395 $mastRadio.node().appendChild(btnG.node()); 403 $mastRadio.node().appendChild(btnG.node());
404 + // return an api for interacting with the button set
405 + return api;
396 } 406 }
397 407
398 function setupGlobalKeys() { 408 function setupGlobalKeys() {
...@@ -662,7 +672,7 @@ ...@@ -662,7 +672,7 @@
662 }, 672 },
663 673
664 setRadio: function (btnSet) { 674 setRadio: function (btnSet) {
665 - setRadioButtons(this.vid, btnSet); 675 + return setRadioButtons(this.vid, btnSet);
666 }, 676 },
667 677
668 setKeys: function (keyArg) { 678 setKeys: function (keyArg) {
......
...@@ -225,8 +225,15 @@ ...@@ -225,8 +225,15 @@
225 border: 2px solid #555; 225 border: 2px solid #555;
226 } 226 }
227 227
228 -#topo svg .suppressed, 228 +#topo-oibox .onosInst.mastership {
229 -#topo-oibox .suppressed { 229 + opacity: 0.3;
230 +}
231 +#topo-oibox .onosInst.mastership.affinity {
232 + opacity: 1.0;
233 +}
234 +
235 +
236 +#topo svg .suppressed {
230 opacity: 0.2; 237 opacity: 0.2;
231 } 238 }
232 239
......
...@@ -112,11 +112,17 @@ ...@@ -112,11 +112,17 @@
112 }; 112 };
113 113
114 // radio buttons 114 // radio buttons
115 - var btnSet = [ 115 + var layerButtons = [
116 - { text: 'All Layers', cb: showAllLayers }, 116 + { text: 'All Layers', id: 'all', cb: showAllLayers },
117 - { text: 'Packet Only', cb: showPacketLayer }, 117 + { text: 'Packet Only', id: 'pkt', cb: showPacketLayer },
118 - { text: 'Optical Only', cb: showOpticalLayer } 118 + { text: 'Optical Only', id: 'opt', cb: showOpticalLayer }
119 - ]; 119 + ],
120 + layerBtnSet,
121 + layerBtnDispatch = {
122 + all: showAllLayers,
123 + pkt: showPacketLayer,
124 + opt: showOpticalLayer
125 + };
120 126
121 // key bindings 127 // key bindings
122 var keyDispatch = { 128 var keyDispatch = {
...@@ -129,7 +135,7 @@ ...@@ -129,7 +135,7 @@
129 P: togglePorts, 135 P: togglePorts,
130 U: unpin, 136 U: unpin,
131 R: resetZoomPan, 137 R: resetZoomPan,
132 - esc: deselectAll 138 + esc: handleEscape
133 }; 139 };
134 140
135 // state variables 141 // state variables
...@@ -163,8 +169,8 @@ ...@@ -163,8 +169,8 @@
163 onosInstances = {}, 169 onosInstances = {},
164 onosOrder = [], 170 onosOrder = [],
165 oiBox, 171 oiBox,
172 + oiShowMaster = false,
166 173
167 - viewMode = 'showAll',
168 portLabelsOn = false; 174 portLabelsOn = false;
169 175
170 // D3 selections 176 // D3 selections
...@@ -311,6 +317,14 @@ ...@@ -311,6 +317,14 @@
311 } 317 }
312 } 318 }
313 319
320 + function handleEscape(view) {
321 + if (oiShowMaster) {
322 + cancelAffinity();
323 + } else {
324 + deselectAll();
325 + }
326 + }
327 +
314 // ============================== 328 // ==============================
315 // Radio Button Callbacks 329 // Radio Button Callbacks
316 330
...@@ -352,13 +366,17 @@ ...@@ -352,13 +366,17 @@
352 }); 366 });
353 } 367 }
354 368
355 - function showAllLayers() { 369 + function suppressLayers(b) {
356 - node.classed('suppressed', false); 370 + node.classed('suppressed', b);
357 - link.classed('suppressed', false); 371 + link.classed('suppressed', b);
358 // d3.selectAll('svg .port').classed('inactive', false); 372 // d3.selectAll('svg .port').classed('inactive', false);
359 // d3.selectAll('svg .portText').classed('inactive', false); 373 // d3.selectAll('svg .portText').classed('inactive', false);
360 } 374 }
361 375
376 + function showAllLayers() {
377 + suppressLayers(false);
378 + }
379 +
362 function showPacketLayer() { 380 function showPacketLayer() {
363 node.classed('suppressed', true); 381 node.classed('suppressed', true);
364 link.classed('suppressed', true); 382 link.classed('suppressed', true);
...@@ -371,6 +389,10 @@ ...@@ -371,6 +389,10 @@
371 unsuppressLayer('opt'); 389 unsuppressLayer('opt');
372 } 390 }
373 391
392 + function restoreLayerState() {
393 + layerBtnDispatch[layerBtnSet.selected()]();
394 + }
395 +
374 // ============================== 396 // ==============================
375 // Private functions 397 // Private functions
376 398
...@@ -674,6 +696,7 @@ ...@@ -674,6 +696,7 @@
674 .append('div') 696 .append('div')
675 .attr('class', 'onosInst') 697 .attr('class', 'onosInst')
676 .classed('online', function (d) { return d.online; }) 698 .classed('online', function (d) { return d.online; })
699 + .on('click', clickInst)
677 .text(function (d) { return d.id; }); 700 .text(function (d) { return d.id; });
678 701
679 // operate on existing + new onoses here 702 // operate on existing + new onoses here
...@@ -685,6 +708,38 @@ ...@@ -685,6 +708,38 @@
685 .remove(); 708 .remove();
686 } 709 }
687 710
711 + function clickInst(d) {
712 + var el = d3.select(this),
713 + aff = el.classed('affinity');
714 + if (!aff) {
715 + setAffinity(el, d);
716 + } else {
717 + cancelAffinity();
718 + }
719 + }
720 +
721 + function setAffinity(el, d) {
722 + d3.selectAll('.onosInst')
723 + .classed('mastership', true)
724 + .classed('affinity', false);
725 + el.classed('affinity', true);
726 +
727 + suppressLayers(true);
728 + node.each(function (n) {
729 + if (n.master === d.id) {
730 + n.el.classed('suppressed', false);
731 + }
732 + });
733 + oiShowMaster = true;
734 + }
735 +
736 + function cancelAffinity() {
737 + d3.selectAll('.onosInst')
738 + .classed('mastership affinity', false);
739 + restoreLayerState();
740 + oiShowMaster = false;
741 + }
742 +
688 // ============================== 743 // ==============================
689 // force layout modification functions 744 // force layout modification functions
690 745
...@@ -1682,7 +1737,7 @@ ...@@ -1682,7 +1737,7 @@
1682 } 1737 }
1683 1738
1684 // set our radio buttons and key bindings 1739 // set our radio buttons and key bindings
1685 - view.setRadio(btnSet); 1740 + layerBtnSet = view.setRadio(layerButtons);
1686 view.setKeys(keyDispatch); 1741 view.setKeys(keyDispatch);
1687 1742
1688 // patch in our "button bar" for now 1743 // patch in our "button bar" for now
......