Simon Hunt

ONOS-2186 - GUI Topo Overlay - (WIP)

- added isActive() predicate to UiTopoOverlay.
- auto-select single intent in an intent selection group.
- clean up mouse over/out handling.

Change-Id: I0f951bd26fcfc791d73bb8121ebbe002086294ea
...@@ -33,6 +33,8 @@ public class UiTopoOverlay { ...@@ -33,6 +33,8 @@ public class UiTopoOverlay {
33 33
34 private final String id; 34 private final String id;
35 35
36 + private boolean isActive = false;
37 +
36 /** 38 /**
37 * Creates a new user interface topology view overlay descriptor. 39 * Creates a new user interface topology view overlay descriptor.
38 * 40 *
...@@ -62,14 +64,23 @@ public class UiTopoOverlay { ...@@ -62,14 +64,23 @@ public class UiTopoOverlay {
62 * Callback invoked when this overlay is activated. 64 * Callback invoked when this overlay is activated.
63 */ 65 */
64 public void activate() { 66 public void activate() {
65 - log.debug("Overlay '{}' Activated", id); 67 + isActive = true;
66 } 68 }
67 69
68 /** 70 /**
69 * Callback invoked when this overlay is deactivated. 71 * Callback invoked when this overlay is deactivated.
70 */ 72 */
71 public void deactivate() { 73 public void deactivate() {
72 - log.debug("Overlay '{}' Deactivated", id); 74 + isActive = false;
75 + }
76 +
77 + /**
78 + * Returns true if this overlay is currently active.
79 + *
80 + * @return true if overlay active
81 + */
82 + public boolean isActive() {
83 + return isActive;
73 } 84 }
74 85
75 /** 86 /**
......
...@@ -30,6 +30,7 @@ import static com.google.common.base.Strings.isNullOrEmpty; ...@@ -30,6 +30,7 @@ import static com.google.common.base.Strings.isNullOrEmpty;
30 */ 30 */
31 public class TopoOverlayCache { 31 public class TopoOverlayCache {
32 32
33 + private static final String EMPTY = "";
33 private static final UiTopoOverlay NONE = new NullOverlay(); 34 private static final UiTopoOverlay NONE = new NullOverlay();
34 35
35 private final Map<String, UiTopoOverlay> overlays = new HashMap<>(); 36 private final Map<String, UiTopoOverlay> overlays = new HashMap<>();
...@@ -95,20 +96,21 @@ public class TopoOverlayCache { ...@@ -95,20 +96,21 @@ public class TopoOverlayCache {
95 return overlays.size(); 96 return overlays.size();
96 } 97 }
97 98
99 + /**
100 + * Returns true if the identifier of the currently active overlay
101 + * matches the given parameter.
102 + *
103 + * @param overlayId overlay identifier
104 + * @return true if this matches the ID of currently active overlay
105 + */
106 + public boolean isActive(String overlayId) {
107 + return currentOverlay().id().equals(overlayId);
108 + }
98 109
99 // overlay instance representing "no overlay selected" 110 // overlay instance representing "no overlay selected"
100 private static class NullOverlay extends UiTopoOverlay { 111 private static class NullOverlay extends UiTopoOverlay {
101 public NullOverlay() { 112 public NullOverlay() {
102 - super(null); 113 + super(EMPTY);
103 - }
104 -
105 - // override activate and deactivate, so no log messages are written
106 - @Override
107 - public void activate() {
108 - }
109 -
110 - @Override
111 - public void deactivate() {
112 } 114 }
113 } 115 }
114 } 116 }
......
...@@ -399,9 +399,11 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -399,9 +399,11 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
399 .build(); 399 .build();
400 400
401 intentService.submit(intent); 401 intentService.submit(intent);
402 + if (overlayCache.isActive(TrafficOverlay.TRAFFIC_ID)) {
402 traffic.monitor(intent); 403 traffic.monitor(intent);
403 } 404 }
404 } 405 }
406 + }
405 407
406 private final class AddMultiSourceIntent extends RequestHandler { 408 private final class AddMultiSourceIntent extends RequestHandler {
407 private AddMultiSourceIntent() { 409 private AddMultiSourceIntent() {
...@@ -432,9 +434,11 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -432,9 +434,11 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
432 .build(); 434 .build();
433 435
434 intentService.submit(intent); 436 intentService.submit(intent);
437 + if (overlayCache.isActive(TrafficOverlay.TRAFFIC_ID)) {
435 traffic.monitor(intent); 438 traffic.monitor(intent);
436 } 439 }
437 } 440 }
441 + }
438 442
439 // ========= ----------------------------------------------------------------- 443 // ========= -----------------------------------------------------------------
440 444
......
...@@ -25,7 +25,10 @@ import org.onosproject.ui.topo.PropertyPanel; ...@@ -25,7 +25,10 @@ import org.onosproject.ui.topo.PropertyPanel;
25 * Topology Overlay for network traffic. 25 * Topology Overlay for network traffic.
26 */ 26 */
27 public class TrafficOverlay extends UiTopoOverlay { 27 public class TrafficOverlay extends UiTopoOverlay {
28 - private static final String TRAFFIC_ID = "traffic"; 28 + /**
29 + * Traffic Overlay identifier.
30 + */
31 + public static final String TRAFFIC_ID = "traffic";
29 32
30 private static final String SDF_ID = "showDeviceFlows"; 33 private static final String SDF_ID = "showDeviceFlows";
31 private static final String SRT_ID = "showRelatedTraffic"; 34 private static final String SRT_ID = "showRelatedTraffic";
...@@ -38,10 +41,22 @@ public class TrafficOverlay extends UiTopoOverlay { ...@@ -38,10 +41,22 @@ public class TrafficOverlay extends UiTopoOverlay {
38 super(TRAFFIC_ID); 41 super(TRAFFIC_ID);
39 } 42 }
40 43
44 + // override activate and deactivate, to write log messages
45 + @Override
46 + public void activate() {
47 + super.activate();
48 + log.debug("TrafficOverlay Activated");
49 + }
50 +
51 + @Override
52 + public void deactivate() {
53 + super.deactivate();
54 + log.debug("TrafficOverlay Deactivated");
55 + }
56 +
41 @Override 57 @Override
42 public void modifyDeviceDetails(PropertyPanel pp) { 58 public void modifyDeviceDetails(PropertyPanel pp) {
43 pp.addButton(SHOW_DEVICE_FLOWS) 59 pp.addButton(SHOW_DEVICE_FLOWS)
44 .addButton(SHOW_RELATED_TRAFFIC); 60 .addButton(SHOW_RELATED_TRAFFIC);
45 } 61 }
46 -
47 } 62 }
......
...@@ -51,6 +51,9 @@ public class IntentSelection { ...@@ -51,6 +51,9 @@ public class IntentSelection {
51 public IntentSelection(NodeSelection nodes, TopoIntentFilter filter) { 51 public IntentSelection(NodeSelection nodes, TopoIntentFilter filter) {
52 this.nodes = nodes; 52 this.nodes = nodes;
53 intents = filter.findPathIntents(nodes.hosts(), nodes.devices()); 53 intents = filter.findPathIntents(nodes.hosts(), nodes.devices());
54 + if (intents.size() == 1) {
55 + index = 0; // pre-select a single intent
56 + }
54 } 57 }
55 58
56 /** 59 /**
......
...@@ -229,9 +229,9 @@ ...@@ -229,9 +229,9 @@
229 tps.displaySomething(); 229 tps.displaySomething();
230 } 230 }
231 231
232 - // returns true if we are hovering over a node, or any nodes are selected 232 + // returns true if one or more nodes are selected.
233 function somethingSelected() { 233 function somethingSelected() {
234 - return hovered || nSel(); 234 + return nSel();
235 } 235 }
236 236
237 function clickConsumed(x) { 237 function clickConsumed(x) {
......
...@@ -41,13 +41,15 @@ ...@@ -41,13 +41,15 @@
41 // Helper functions 41 // Helper functions
42 42
43 // invoked in response to change in selection and/or mouseover/out: 43 // invoked in response to change in selection and/or mouseover/out:
44 - function requestTrafficForMode() { 44 + function requestTrafficForMode(mouse) {
45 if (trafficMode === 'flows') { 45 if (trafficMode === 'flows') {
46 requestDeviceLinkFlows(); 46 requestDeviceLinkFlows();
47 } else if (trafficMode === 'intents') { 47 } else if (trafficMode === 'intents') {
48 + if (!mouse || hoverMode === 'intents') {
48 requestRelatedIntents(); 49 requestRelatedIntents();
50 + }
49 } else { 51 } else {
50 - cancelTraffic(); 52 + // do nothing
51 } 53 }
52 } 54 }
53 55
...@@ -89,8 +91,8 @@ ...@@ -89,8 +91,8 @@
89 // === ------------------------------------------------------------- 91 // === -------------------------------------------------------------
90 // Traffic requests invoked from keystrokes or toolbar buttons... 92 // Traffic requests invoked from keystrokes or toolbar buttons...
91 93
92 - function cancelTraffic() { 94 + function cancelTraffic(forced) {
93 - if (!trafficMode) { 95 + if (!trafficMode || (!forced && trafficMode === 'allFlowPort')) {
94 return false; 96 return false;
95 } 97 }
96 98
...@@ -101,15 +103,15 @@ ...@@ -101,15 +103,15 @@
101 } 103 }
102 104
103 function showAllFlowTraffic() { 105 function showAllFlowTraffic() {
104 - trafficMode = 'allFlow'; 106 + trafficMode = 'allFlowPort';
105 - hoverMode = 'all'; 107 + hoverMode = null;
106 wss.sendEvent('requestAllFlowTraffic'); 108 wss.sendEvent('requestAllFlowTraffic');
107 flash.flash('All Flow Traffic'); 109 flash.flash('All Flow Traffic');
108 } 110 }
109 111
110 function showAllPortTraffic() { 112 function showAllPortTraffic() {
111 - trafficMode = 'allPort'; 113 + trafficMode = 'allFlowPort';
112 - hoverMode = 'all'; 114 + hoverMode = null;
113 wss.sendEvent('requestAllPortTraffic'); 115 wss.sendEvent('requestAllPortTraffic');
114 flash.flash('All Port Traffic'); 116 flash.flash('All Port Traffic');
115 } 117 }
...@@ -161,6 +163,8 @@ ...@@ -161,6 +163,8 @@
161 two: so[1], 163 two: so[1],
162 ids: so 164 ids: so
163 }); 165 });
166 + trafficMode = 'intents';
167 + hoverMode = null;
164 flash.flash('Host-to-Host flow added'); 168 flash.flash('Host-to-Host flow added');
165 } 169 }
166 170
...@@ -171,6 +175,8 @@ ...@@ -171,6 +175,8 @@
171 dst: so[so.length - 1], 175 dst: so[so.length - 1],
172 ids: so 176 ids: so
173 }); 177 });
178 + trafficMode = 'intents';
179 + hoverMode = null;
174 flash.flash('Multi-Source flow added'); 180 flash.flash('Multi-Source flow added');
175 } 181 }
176 182
......
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
45 }, 45 },
46 46
47 deactivate: function () { 47 deactivate: function () {
48 - tts.cancelTraffic(); 48 + tts.cancelTraffic(true);
49 $log.debug("Traffic overlay DEACTIVATED"); 49 $log.debug("Traffic overlay DEACTIVATED");
50 }, 50 },
51 51
...@@ -69,7 +69,7 @@ ...@@ -69,7 +69,7 @@
69 // NOTE: fully qual. button ID is derived from overlay-id and key-name 69 // NOTE: fully qual. button ID is derived from overlay-id and key-name
70 keyBindings: { 70 keyBindings: {
71 0: { 71 0: {
72 - cb: function () { tts.cancelTraffic(); }, 72 + cb: function () { tts.cancelTraffic(true); },
73 tt: 'Cancel traffic monitoring', 73 tt: 'Cancel traffic monitoring',
74 gid: 'xMark' 74 gid: 'xMark'
75 }, 75 },
...@@ -137,10 +137,10 @@ ...@@ -137,10 +137,10 @@
137 // mouse hooks 137 // mouse hooks
138 mouseover: function (m) { 138 mouseover: function (m) {
139 // m has id, class, and type properties 139 // m has id, class, and type properties
140 - tts.requestTrafficForMode(); 140 + tts.requestTrafficForMode(true);
141 }, 141 },
142 mouseout: function () { 142 mouseout: function () {
143 - tts.requestTrafficForMode(); 143 + tts.requestTrafficForMode(true);
144 } 144 }
145 } 145 }
146 }; 146 };
......