piecharts: add tree selection when a piechart slice is selected
authorAlexis Cabana-Loriaux <alex021994@gmail.com>
Fri, 21 Aug 2015 20:57:16 +0000 (16:57 -0400)
committerBernd Hufmann <bernd.hufmann@ericsson.com>
Mon, 24 Aug 2015 11:24:03 +0000 (07:24 -0400)
Change-Id: I2450a060cf72a2d2661b9196d87c693326cf7be5
Signed-off-by: Alexis Cabana-Loriaux <alex021994@gmail.com>
Reviewed-on: https://git.eclipse.org/r/54162
Reviewed-by: Hudson CI
Reviewed-by: Bernd Hufmann <bernd.hufmann@ericsson.com>
Tested-by: Bernd Hufmann <bernd.hufmann@ericsson.com>
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Tested-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/viewers/piecharts/TmfPieChartViewer.java
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/viewers/statistics/TmfStatisticsViewer.java
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/viewers/statistics/model/TmfStatisticsTreeNode.java

index d52fffc55f0d2b2f2c8e6f477aa0598ecc0850c8..5ffe9e9eeefc95d765a7f97002eecec288c786cb 100644 (file)
@@ -20,21 +20,25 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
+import org.eclipse.core.runtime.ListenerList;
 import org.eclipse.linuxtools.dataviewers.piechart.PieChart;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
 import org.eclipse.swt.layout.FillLayout;
 import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
 import org.eclipse.swt.widgets.Listener;
-import org.eclipse.tracecompass.internal.tmf.ui.viewers.piecharts.model.TmfPieChartStatisticsModel;
 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.internal.tmf.ui.viewers.piecharts.model.TmfPieChartStatisticsModel;
 
 /**
  * Creates a viewer containing 2 pie charts, one for showing information about
  * the current selection, and the second one for showing information about the
  * current time-range selection. It follows the MVC pattern, being a view.
  *
- * This class is closely related with the IPieChartViewerState interface
- * that acts as a state machine for the general layout of the charts.
+ * This class is closely related with the IPieChartViewerState interface that
+ * acts as a state machine for the general layout of the charts.
  *
  * @author Alexis Cabana-Loriaux
  * @since 2.0
@@ -65,9 +69,19 @@ public class TmfPieChartViewer extends Composite {
     private String fTimeRangePCname;
 
     /**
-     * The listener added to the charts every time they are created
+     * The listener for the mouse movement event.
+     */
+    private Listener fMouseMoveListener;
+
+    /**
+     * The listener for the mouse right click event.
      */
-    private Listener fMouseListener;
+    private MouseListener fMouseClickListener;
+
+    /**
+     * The list of listener to notify when an event type is selected
+     */
+    private ListenerList fEventTypeSelectedListeners = new ListenerList(ListenerList.IDENTITY);
 
     /**
      * The name of the slice containing the too little slices
@@ -125,11 +139,12 @@ public class TmfPieChartViewer extends Composite {
         fTimeRangePC = null;
 
         // Setup listeners for the tooltips
-        fMouseListener = new Listener() {
+        fMouseMoveListener = new Listener() {
             @Override
             public void handleEvent(org.eclipse.swt.widgets.Event event) {
                 PieChart pc = (PieChart) event.widget;
                 switch (event.type) {
+                /* Get tooltip information on the slice */
                 case SWT.MouseMove:
                     int sliceIndex = pc.getSliceIndexFromPosition(0, event.x, event.y);
                     if (sliceIndex < 0) {
@@ -141,17 +156,42 @@ public class TmfPieChartViewer extends Composite {
                     String percent = String.format("%.1f", percOfSlice); //$NON-NLS-1$
                     Long nbEvents = Long.valueOf((long) pc.getSeriesSet().getSeries()[sliceIndex].getXSeries()[0]);
 
-                    String text =   Messages.TmfStatisticsView_PieChartToolTipTextName + " = " + //$NON-NLS-1$
-                                    pc.getSeriesSet().getSeries()[sliceIndex].getId() + "\n"; //$NON-NLS-1$
+                    String text = Messages.TmfStatisticsView_PieChartToolTipTextName + " = " + //$NON-NLS-1$
+                            pc.getSeriesSet().getSeries()[sliceIndex].getId() + "\n"; //$NON-NLS-1$
 
-                    text +=         Messages.TmfStatisticsView_PieChartToolTipTextEventCount + " = "//$NON-NLS-1$
-                                    + nbEvents.toString() + " (" + percent + "%)"; //$NON-NLS-1$ //$NON-NLS-2$
+                    text += Messages.TmfStatisticsView_PieChartToolTipTextEventCount + " = "//$NON-NLS-1$
+                            + nbEvents.toString() + " (" + percent + "%)"; //$NON-NLS-1$ //$NON-NLS-2$
                     pc.setToolTipText(text);
                     return;
                 default:
                 }
             }
         };
+
+        fMouseClickListener = new MouseListener() {
+
+            @Override
+            public void mouseUp(MouseEvent e) {
+            }
+
+            @Override
+            public void mouseDown(MouseEvent e) {
+                PieChart pc = (PieChart) e.widget;
+                int slicenb = pc.getSliceIndexFromPosition(0, e.x, e.y);
+                if (slicenb < 0 || slicenb >= pc.getSeriesSet().getSeries().length) {
+                    // mouse is outside the chart
+                    return;
+                }
+                Event selectionEvent = new Event();
+                selectionEvent.text = pc.getSeriesSet().getSeries()[slicenb].getId();
+                notifyEventTypeSelectionListener(selectionEvent);
+            }
+
+            @Override
+            public void mouseDoubleClick(MouseEvent e) {
+            }
+        };
+
         // at creation no content is selected
         setCurrentState(new PieChartViewerStateNoContentSelected(this));
     }
@@ -178,14 +218,15 @@ public class TmfPieChartViewer extends Composite {
             getGlobalPC().getAxisSet().getXAxis(0).getTitle().setText(""); //Hide the title over the legend //$NON-NLS-1$
             getGlobalPC().getLegend().setVisible(true);
             getGlobalPC().getLegend().setPosition(SWT.RIGHT);
-            getGlobalPC().addListener(SWT.MouseMove, fMouseListener);
+            getGlobalPC().addListener(SWT.MouseMove, fMouseMoveListener);
+            getGlobalPC().addMouseListener(fMouseClickListener);
         } else if (getGlobalPC().isDisposed() || fModel == null || fModel.getPieChartGlobalModel() == null) {
             return;
         }
 
         Map<String, Long> totalEventCountForChart = getTotalEventCountForChart(true);
 
-        if(totalEventCountForChart == null){
+        if (totalEventCountForChart == null) {
             return;
         }
 
@@ -203,7 +244,8 @@ public class TmfPieChartViewer extends Composite {
             getTimeRangePC().getAxisSet().getXAxis(0).getTitle().setText(""); //Hide the title over the legend //$NON-NLS-1$
             getTimeRangePC().getLegend().setPosition(SWT.BOTTOM);
             getTimeRangePC().getLegend().setVisible(true);
-            getTimeRangePC().addListener(SWT.MouseMove, fMouseListener);
+            getTimeRangePC().addListener(SWT.MouseMove, fMouseMoveListener);
+            getTimeRangePC().addMouseListener(fMouseClickListener);
         }
         else if (getTimeRangePC().isDisposed()) {
             return;
@@ -211,7 +253,7 @@ public class TmfPieChartViewer extends Composite {
 
         Map<String, Long> totalEventCountForChart = getTotalEventCountForChart(false);
 
-        if(totalEventCountForChart == null){
+        if (totalEventCountForChart == null) {
             return;
         }
 
@@ -219,28 +261,28 @@ public class TmfPieChartViewer extends Composite {
     }
 
     /* return the chart-friendly map given by the TmfPieChartStatisticsModel */
-    private Map<String,Long> getTotalEventCountForChart(boolean isGlobal){
-        if(fModel == null){
+    private Map<String, Long> getTotalEventCountForChart(boolean isGlobal) {
+        if (fModel == null) {
             return null;
         }
         Map<ITmfTrace, Map<String, Long>> chartModel;
-        if(isGlobal){
+        if (isGlobal) {
             chartModel = fModel.getPieChartGlobalModel();
         } else {
             chartModel = fModel.getPieChartSelectionModel();
         }
-        if(chartModel == null){
+        if (chartModel == null) {
             return null;
         }
 
         Map<String, Long> totalEventCountForChart = new HashMap<>();
-        for(Entry<ITmfTrace, Map<String, Long>> entry : chartModel.entrySet()){
+        for (Entry<ITmfTrace, Map<String, Long>> entry : chartModel.entrySet()) {
             Map<String, Long> traceEventCount = entry.getValue();
-            if(traceEventCount == null){
+            if (traceEventCount == null) {
                 continue;
             }
-            for(Entry<String, Long> event : traceEventCount.entrySet()){
-                if(totalEventCountForChart.containsKey(event.getKey())){
+            for (Entry<String, Long> event : traceEventCount.entrySet()) {
+                if (totalEventCountForChart.containsKey(event.getKey())) {
                     totalEventCountForChart.put(event.getKey(), totalEventCountForChart.get(event.getKey()) + event.getValue());
                 } else {
                     totalEventCountForChart.put(event.getKey(), event.getValue());
@@ -255,7 +297,7 @@ public class TmfPieChartViewer extends Composite {
      * Reinitializes the charts to their initial state, without any data
      */
     synchronized public void reinitializeCharts() {
-        if(isDisposed()){
+        if (isDisposed()) {
             return;
         }
 
@@ -336,24 +378,27 @@ public class TmfPieChartViewer extends Composite {
 
     /**
      * Refresh this viewer
-     * @param refreshGlobal if we have to refresh the global piechart
-     * @param refreshSelection if we have to refresh the selection piechart
+     *
+     * @param refreshGlobal
+     *            if we have to refresh the global piechart
+     * @param refreshSelection
+     *            if we have to refresh the selection piechart
      */
     public synchronized void refresh(boolean refreshGlobal, boolean refreshSelection) {
-        if(fModel == null){
+        if (fModel == null) {
             reinitializeCharts();
         } else {
-            if(refreshGlobal){
+            if (refreshGlobal) {
                 /* will update the global pc */
                 getCurrentState().newGlobalEntries(this);
             }
 
-            if(refreshSelection){
+            if (refreshSelection) {
                 // Check if the selection is empty
                 int nbEventsType = 0;
                 Map<String, Long> selectionModel = getTotalEventCountForChart(false);
                 for (Long l : selectionModel.values()) {
-                    if(l != 0){
+                    if (l != 0) {
                         nbEventsType++;
                     }
                 }
@@ -369,6 +414,29 @@ public class TmfPieChartViewer extends Composite {
         }
     }
 
+    /**
+     * @param l
+     *            the listener to add
+     */
+    public void addEventTypeSelectionListener(Listener l) {
+        fEventTypeSelectedListeners.add(l);
+    }
+
+    /**
+     * @param l
+     *            the listener to remove
+     */
+    public void removeEventTypeSelectionListener(Listener l) {
+        fEventTypeSelectedListeners.remove(l);
+    }
+
+    /* Notify all listeners that an event type has been selected */
+    private void notifyEventTypeSelectionListener(Event e) {
+        for (Object o : fEventTypeSelectedListeners.getListeners()) {
+            ((Listener) o).handleEvent(e);
+        }
+    }
+
     // ------------------------------------------------------------------------
     // Getters
     // ------------------------------------------------------------------------
@@ -406,7 +474,8 @@ public class TmfPieChartViewer extends Composite {
     }
 
     /**
-     * @param model the model to set
+     * @param model
+     *            the model to set
      */
     public void setInput(TmfPieChartStatisticsModel model) {
         fModel = model;
index cb1dd53609c2460da913551fb362c511c9b6b22f..94eab5246ddcacfe8ce0ba8730f782d04a3a1994 100644 (file)
@@ -21,9 +21,9 @@ import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 
 import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.viewers.StructuredSelection;
 import org.eclipse.jface.viewers.TreeViewer;
 import org.eclipse.jface.viewers.TreeViewerColumn;
 import org.eclipse.jface.viewers.Viewer;
@@ -39,15 +39,6 @@ import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Event;
 import org.eclipse.swt.widgets.Listener;
-import org.eclipse.tracecompass.internal.tmf.ui.viewers.piecharts.TmfPieChartViewer;
-import org.eclipse.tracecompass.internal.tmf.ui.viewers.piecharts.model.TmfPieChartStatisticsModel;
-import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfBaseColumnData;
-import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfBaseColumnDataProvider;
-import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfStatisticsFormatter;
-import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfStatisticsTree;
-import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfStatisticsTreeManager;
-import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfStatisticsTreeNode;
-import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfTreeContentProvider;
 import org.eclipse.tracecompass.tmf.core.component.TmfComponent;
 import org.eclipse.tracecompass.tmf.core.request.ITmfEventRequest;
 import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
@@ -61,8 +52,16 @@ import org.eclipse.tracecompass.tmf.core.trace.TmfTraceContext;
 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
 import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment;
-import org.eclipse.tracecompass.tmf.ui.TmfUiRefreshHandler;
 import org.eclipse.tracecompass.tmf.ui.viewers.TmfViewer;
+import org.eclipse.tracecompass.internal.tmf.ui.viewers.piecharts.TmfPieChartViewer;
+import org.eclipse.tracecompass.internal.tmf.ui.viewers.piecharts.model.TmfPieChartStatisticsModel;
+import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfBaseColumnData;
+import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfBaseColumnDataProvider;
+import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfStatisticsFormatter;
+import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfStatisticsTree;
+import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfStatisticsTreeManager;
+import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfStatisticsTreeNode;
+import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfTreeContentProvider;
 
 /**
  * A basic viewer to display statistics in the statistics view.
@@ -330,25 +329,6 @@ public class TmfStatisticsViewer extends TmfViewer {
             return;
         }
 
-        TmfPieChartStatisticsModel pieChartModel = getPieChartModel();
-        if (pieChartModel == null || pieChartModel.getPieChartGlobalModel() == null) {
-            return;
-        }
-        /* If there's only one event type, don't show any piechart */
-        boolean moreThanOne = false;
-        for (Entry<ITmfTrace, Map<String, Long>> entry : pieChartModel.getPieChartGlobalModel().entrySet()) {
-            if(entry.getValue() != null && entry.getValue().size() > 1) {
-                moreThanOne = true;
-                break;
-            }
-        }
-
-        if (!moreThanOne) {
-            setPieChartsVisible(false);
-        } else {
-            setPieChartsVisible(true);
-        }
-
         Display.getDefault().asyncExec(new Runnable() {
             @Override
             public void run() {
@@ -411,8 +391,29 @@ public class TmfStatisticsViewer extends TmfViewer {
 
         fTreeViewer = new TreeViewer(fSash, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
         fPieChartViewer = new TmfPieChartViewer(fSash);
-        fPieChartViewer.setVisible(false);
-        fSash.setWeights(new int[] { 1, 1 });
+        fPieChartViewer.addEventTypeSelectionListener(new Listener() {
+
+            @Override
+            public void handleEvent(Event event) {
+                String eventTypeName = event.text;
+                if (getStatisticData().getRootNode() == null ||
+                        fTreeViewer == null ||
+                        fTreeViewer.getTree() == null) {
+                    return;
+                }
+                /* Get all the nodes corresponding to the event name */
+                List<TmfStatisticsTreeNode> nodes = (List<TmfStatisticsTreeNode>) getStatisticData().getRootNode().findChildren(eventTypeName, true);
+                if (nodes.isEmpty()) {
+                    /* Shouldn't happen, except for when selecting "Others" */
+                    return;
+                }
+                /* Only select the first in the collection */
+                fTreeViewer.setSelection(new StructuredSelection(nodes.get(0)), true);
+            }
+        });
+
+        /* Make sure the sash is split in 2 equal parts */
+        fSash.setWeights(new int[] { 100, 100 });
 
         fTreeViewer.setContentProvider(new TmfTreeContentProvider());
         fTreeViewer.getTree().setHeaderVisible(true);
@@ -711,21 +712,6 @@ public class TmfStatisticsViewer extends TmfViewer {
         }
     }
 
-    private void setPieChartsVisible(final boolean visible) {
-        if (fPieChartViewer.isDisposed()) {
-            return;
-        }
-        TmfUiRefreshHandler.getInstance().queueUpdate(fPieChartViewer, new Runnable() {
-            @Override
-            public void run() {
-                if (!fPieChartViewer.isDisposed()) {
-                    fPieChartViewer.setVisible(visible);
-                    fPieChartViewer.getParent().layout();
-                }
-            }
-        });
-    }
-
     /**
      * Resets the number of events within the time range
      */
index 066dc9bdd8821add10db63b4bce61c074ed9742f..24a603013cf558b6f978431eae5ae90fe07f318e 100755 (executable)
@@ -17,6 +17,9 @@ package org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model;
 
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -132,6 +135,38 @@ public class TmfStatisticsTreeNode {
         return fChildren.values();
     }
 
+    /**
+     * @param childrenName
+     *            the name to search for
+     * @param recursive
+     *            if the search should be recursive
+     * @return a Collection of children node (could be empty) with the same name
+     *         as childrenName
+     */
+    public Collection<TmfStatisticsTreeNode> findChildren(String childrenName, boolean recursive) {
+
+        if(childrenName.equals(getName())){
+            return Collections.singletonList(this);
+        }
+
+        if (fChildren.isEmpty()) {
+            return Collections.emptyList();
+        }
+
+        if (!recursive) {
+            if (!fChildren.containsKey(childrenName)) {
+                return Collections.emptyList();
+            }
+            return Collections.singletonList(fChildren.get(childrenName));
+        }
+
+        List<TmfStatisticsTreeNode> returnList = new LinkedList<>();
+        for (TmfStatisticsTreeNode node : fChildren.values()) {
+            returnList.addAll(node.findChildren(childrenName, true));
+        }
+        return returnList;
+    }
+
     /**
      * Add a child to this node.
      *
This page took 0.033025 seconds and 5 git commands to generate.