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
diff --git a/core/api/src/main/java/org/onosproject/ui/UiTopoOverlay.java b/core/api/src/main/java/org/onosproject/ui/UiTopoOverlay.java
index 4c6d5d1..2889422 100644
--- a/core/api/src/main/java/org/onosproject/ui/UiTopoOverlay.java
+++ b/core/api/src/main/java/org/onosproject/ui/UiTopoOverlay.java
@@ -33,6 +33,8 @@
 
     private final String id;
 
+    private boolean isActive = false;
+
     /**
      * Creates a new user interface topology view overlay descriptor.
      *
@@ -62,14 +64,23 @@
      * Callback invoked when this overlay is activated.
      */
     public void activate() {
-        log.debug("Overlay '{}' Activated", id);
+        isActive = true;
     }
 
     /**
      * Callback invoked when this overlay is deactivated.
      */
     public void deactivate() {
-        log.debug("Overlay '{}' Deactivated", id);
+        isActive = false;
+    }
+
+    /**
+     * Returns true if this overlay is currently active.
+     *
+     * @return true if overlay active
+     */
+    public boolean isActive() {
+        return isActive;
     }
 
     /**
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/TopoOverlayCache.java b/web/gui/src/main/java/org/onosproject/ui/impl/TopoOverlayCache.java
index f7690e8..99557c2 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/TopoOverlayCache.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/TopoOverlayCache.java
@@ -30,6 +30,7 @@
  */
 public class TopoOverlayCache {
 
+    private static final String EMPTY = "";
     private static final UiTopoOverlay NONE = new NullOverlay();
 
     private final Map<String, UiTopoOverlay> overlays = new HashMap<>();
@@ -95,20 +96,21 @@
         return overlays.size();
     }
 
+    /**
+     * Returns true if the identifier of the currently active overlay
+     * matches the given parameter.
+     *
+     * @param overlayId overlay identifier
+     * @return true if this matches the ID of currently active overlay
+     */
+    public boolean isActive(String overlayId) {
+        return currentOverlay().id().equals(overlayId);
+    }
 
     // overlay instance representing "no overlay selected"
     private static class NullOverlay extends UiTopoOverlay {
         public NullOverlay() {
-            super(null);
-        }
-
-        // override activate and deactivate, so no log messages are written
-        @Override
-        public void activate() {
-        }
-
-        @Override
-        public void deactivate() {
+            super(EMPTY);
         }
     }
 }
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java
index 57054e0..1c629c7 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java
@@ -399,7 +399,9 @@
                     .build();
 
             intentService.submit(intent);
-            traffic.monitor(intent);
+            if (overlayCache.isActive(TrafficOverlay.TRAFFIC_ID)) {
+                traffic.monitor(intent);
+            }
         }
     }
 
@@ -432,7 +434,9 @@
                             .build();
 
             intentService.submit(intent);
-            traffic.monitor(intent);
+            if (overlayCache.isActive(TrafficOverlay.TRAFFIC_ID)) {
+                traffic.monitor(intent);
+            }
         }
     }
 
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/TrafficOverlay.java b/web/gui/src/main/java/org/onosproject/ui/impl/TrafficOverlay.java
index 6eec92f..ea8ca3e 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/TrafficOverlay.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/TrafficOverlay.java
@@ -25,7 +25,10 @@
  * Topology Overlay for network traffic.
  */
 public class TrafficOverlay extends UiTopoOverlay {
-    private static final String TRAFFIC_ID = "traffic";
+    /**
+     * Traffic Overlay identifier.
+     */
+    public static final String TRAFFIC_ID = "traffic";
 
     private static final String SDF_ID = "showDeviceFlows";
     private static final String SRT_ID = "showRelatedTraffic";
@@ -38,10 +41,22 @@
         super(TRAFFIC_ID);
     }
 
+    // override activate and deactivate, to write log messages
+    @Override
+    public void activate() {
+        super.activate();
+        log.debug("TrafficOverlay Activated");
+    }
+
+    @Override
+    public void deactivate() {
+        super.deactivate();
+        log.debug("TrafficOverlay Deactivated");
+    }
+
     @Override
     public void modifyDeviceDetails(PropertyPanel pp) {
         pp.addButton(SHOW_DEVICE_FLOWS)
             .addButton(SHOW_RELATED_TRAFFIC);
     }
-
 }
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/IntentSelection.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/IntentSelection.java
index f99ff7c..01ae93d 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/IntentSelection.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/IntentSelection.java
@@ -51,6 +51,9 @@
     public IntentSelection(NodeSelection nodes, TopoIntentFilter filter) {
         this.nodes = nodes;
         intents = filter.findPathIntents(nodes.hosts(), nodes.devices());
+        if (intents.size() == 1) {
+            index = 0;  // pre-select a single intent
+        }
     }
 
     /**
diff --git a/web/gui/src/main/webapp/app/view/topo/topoSelect.js b/web/gui/src/main/webapp/app/view/topo/topoSelect.js
index 779e408..483c4ba 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoSelect.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoSelect.js
@@ -229,9 +229,9 @@
         tps.displaySomething();
     }
 
-    // returns true if we are hovering over a node, or any nodes are selected
+    // returns true if one or more nodes are selected.
     function somethingSelected() {
-        return hovered || nSel();
+        return nSel();
     }
 
     function clickConsumed(x) {
diff --git a/web/gui/src/main/webapp/app/view/topo/topoTraffic.js b/web/gui/src/main/webapp/app/view/topo/topoTraffic.js
index 9308542..a2cd818 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoTraffic.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoTraffic.js
@@ -41,13 +41,15 @@
     //  Helper functions
 
     // invoked in response to change in selection and/or mouseover/out:
-    function requestTrafficForMode() {
+    function requestTrafficForMode(mouse) {
         if (trafficMode === 'flows') {
             requestDeviceLinkFlows();
         } else if (trafficMode === 'intents') {
-            requestRelatedIntents();
+            if (!mouse || hoverMode === 'intents') {
+                requestRelatedIntents();
+            }
         } else {
-            cancelTraffic();
+            // do nothing
         }
     }
 
@@ -89,8 +91,8 @@
     // === -------------------------------------------------------------
     //  Traffic requests invoked from keystrokes or toolbar buttons...
 
-    function cancelTraffic() {
-        if (!trafficMode) {
+    function cancelTraffic(forced) {
+        if (!trafficMode || (!forced && trafficMode === 'allFlowPort')) {
             return false;
         }
 
@@ -101,15 +103,15 @@
     }
 
     function showAllFlowTraffic() {
-        trafficMode = 'allFlow';
-        hoverMode = 'all';
+        trafficMode = 'allFlowPort';
+        hoverMode = null;
         wss.sendEvent('requestAllFlowTraffic');
         flash.flash('All Flow Traffic');
     }
 
     function showAllPortTraffic() {
-        trafficMode = 'allPort';
-        hoverMode = 'all';
+        trafficMode = 'allFlowPort';
+        hoverMode = null;
         wss.sendEvent('requestAllPortTraffic');
         flash.flash('All Port Traffic');
     }
@@ -161,6 +163,8 @@
             two: so[1],
             ids: so
         });
+        trafficMode = 'intents';
+        hoverMode = null;
         flash.flash('Host-to-Host flow added');
     }
 
@@ -171,6 +175,8 @@
             dst: so[so.length - 1],
             ids: so
         });
+        trafficMode = 'intents';
+        hoverMode = null;
         flash.flash('Multi-Source flow added');
     }
 
diff --git a/web/gui/src/main/webapp/app/view/topo/topoTrafficNew.js b/web/gui/src/main/webapp/app/view/topo/topoTrafficNew.js
index a0e046c..ea5e24a 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoTrafficNew.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoTrafficNew.js
@@ -45,7 +45,7 @@
         },
 
         deactivate: function () {
-            tts.cancelTraffic();
+            tts.cancelTraffic(true);
             $log.debug("Traffic overlay DEACTIVATED");
         },
 
@@ -69,7 +69,7 @@
         // NOTE: fully qual. button ID is derived from overlay-id and key-name
         keyBindings: {
             0: {
-                cb: function () { tts.cancelTraffic(); },
+                cb: function () { tts.cancelTraffic(true); },
                 tt: 'Cancel traffic monitoring',
                 gid: 'xMark'
             },
@@ -137,10 +137,10 @@
             // mouse hooks
             mouseover: function (m) {
                 // m has id, class, and type properties
-                tts.requestTrafficForMode();
+                tts.requestTrafficForMode(true);
             },
             mouseout: function () {
-                tts.requestTrafficForMode();
+                tts.requestTrafficForMode(true);
             }
         }
     };