diff --git a/web/gui/src/main/webapp/onos2.js b/web/gui/src/main/webapp/onos2.js index 87aa63d231..20c679a79e 100644 --- a/web/gui/src/main/webapp/onos2.js +++ b/web/gui/src/main/webapp/onos2.js @@ -347,7 +347,8 @@ function setRadioButtons(vid, btnSet) { var view = views[vid], - btnG; + btnG, + api = {}; // lazily create the buttons... if (!(btnG = view.radioButtons)) { @@ -365,10 +366,12 @@ }) .text(txt); + btn.id = bid; btnG.buttonDef[uid] = btn; if (i === 0) { button.classed('active', true); + btnG.selected = bid; } }); @@ -382,6 +385,7 @@ if (!act) { btnG.selectAll('span').classed('active', false); button.classed('active', true); + btnG.selected = btn.id; if (isF(btn.cb)) { btn.cb(view.token(), btn); } @@ -389,10 +393,16 @@ }); view.radioButtons = btnG; + + api.selected = function () { + return btnG.selected; + } } // attach the buttons to the masthead $mastRadio.node().appendChild(btnG.node()); + // return an api for interacting with the button set + return api; } function setupGlobalKeys() { @@ -662,7 +672,7 @@ }, setRadio: function (btnSet) { - setRadioButtons(this.vid, btnSet); + return setRadioButtons(this.vid, btnSet); }, setKeys: function (keyArg) { diff --git a/web/gui/src/main/webapp/topo2.css b/web/gui/src/main/webapp/topo2.css index f485e1eda9..94e6477cec 100644 --- a/web/gui/src/main/webapp/topo2.css +++ b/web/gui/src/main/webapp/topo2.css @@ -225,8 +225,15 @@ border: 2px solid #555; } -#topo svg .suppressed, -#topo-oibox .suppressed { +#topo-oibox .onosInst.mastership { + opacity: 0.3; +} +#topo-oibox .onosInst.mastership.affinity { + opacity: 1.0; +} + + +#topo svg .suppressed { opacity: 0.2; } diff --git a/web/gui/src/main/webapp/topo2.js b/web/gui/src/main/webapp/topo2.js index e14f0207bd..3a5baccba9 100644 --- a/web/gui/src/main/webapp/topo2.js +++ b/web/gui/src/main/webapp/topo2.js @@ -112,11 +112,17 @@ }; // radio buttons - var btnSet = [ - { text: 'All Layers', cb: showAllLayers }, - { text: 'Packet Only', cb: showPacketLayer }, - { text: 'Optical Only', cb: showOpticalLayer } - ]; + var layerButtons = [ + { text: 'All Layers', id: 'all', cb: showAllLayers }, + { text: 'Packet Only', id: 'pkt', cb: showPacketLayer }, + { text: 'Optical Only', id: 'opt', cb: showOpticalLayer } + ], + layerBtnSet, + layerBtnDispatch = { + all: showAllLayers, + pkt: showPacketLayer, + opt: showOpticalLayer + }; // key bindings var keyDispatch = { @@ -129,7 +135,7 @@ P: togglePorts, U: unpin, R: resetZoomPan, - esc: deselectAll + esc: handleEscape }; // state variables @@ -163,8 +169,8 @@ onosInstances = {}, onosOrder = [], oiBox, + oiShowMaster = false, - viewMode = 'showAll', portLabelsOn = false; // D3 selections @@ -311,6 +317,14 @@ } } + function handleEscape(view) { + if (oiShowMaster) { + cancelAffinity(); + } else { + deselectAll(); + } + } + // ============================== // Radio Button Callbacks @@ -352,13 +366,17 @@ }); } - function showAllLayers() { - node.classed('suppressed', false); - link.classed('suppressed', false); + function suppressLayers(b) { + node.classed('suppressed', b); + link.classed('suppressed', b); // d3.selectAll('svg .port').classed('inactive', false); // d3.selectAll('svg .portText').classed('inactive', false); } + function showAllLayers() { + suppressLayers(false); + } + function showPacketLayer() { node.classed('suppressed', true); link.classed('suppressed', true); @@ -371,6 +389,10 @@ unsuppressLayer('opt'); } + function restoreLayerState() { + layerBtnDispatch[layerBtnSet.selected()](); + } + // ============================== // Private functions @@ -674,6 +696,7 @@ .append('div') .attr('class', 'onosInst') .classed('online', function (d) { return d.online; }) + .on('click', clickInst) .text(function (d) { return d.id; }); // operate on existing + new onoses here @@ -685,6 +708,38 @@ .remove(); } + function clickInst(d) { + var el = d3.select(this), + aff = el.classed('affinity'); + if (!aff) { + setAffinity(el, d); + } else { + cancelAffinity(); + } + } + + function setAffinity(el, d) { + d3.selectAll('.onosInst') + .classed('mastership', true) + .classed('affinity', false); + el.classed('affinity', true); + + suppressLayers(true); + node.each(function (n) { + if (n.master === d.id) { + n.el.classed('suppressed', false); + } + }); + oiShowMaster = true; + } + + function cancelAffinity() { + d3.selectAll('.onosInst') + .classed('mastership affinity', false); + restoreLayerState(); + oiShowMaster = false; + } + // ============================== // force layout modification functions @@ -1682,7 +1737,7 @@ } // set our radio buttons and key bindings - view.setRadio(btnSet); + layerBtnSet = view.setRadio(layerButtons); view.setKeys(keyDispatch); // patch in our "button bar" for now