tmf: Use tabs in statistics view for each traces
authorMathieu Denis <mathieu.denis@polymtl.ca>
Fri, 10 Aug 2012 19:15:25 +0000 (15:15 -0400)
committerBernd Hufmann <bhufmann@gmail.com>
Fri, 17 Aug 2012 20:14:42 +0000 (16:14 -0400)
When an experiment/trace is selected, the statistics view creates a
global viewer and a specific viewer for each trace contained in the
experiment. These viewers are placed in tabs and shown in the
statistics view. Also, a factory is now used to create a viewer based
on his definition in the plug-in.xml from the trace type. An
extension point element has been added to the trace type extension
point to provide custom statistics viewer.

Fixes bug 387217 on bugs.eclipse.org

Signed-off-by: Mathieu Denis <mathieu.denis@polymtl.ca>
Change-Id: I8d380e8c28cba855b5361069200e50ab0cbca7f3
Reviewed-on: https://git.eclipse.org/r/7042
Reviewed-by: Bernd Hufmann <bhufmann@gmail.com>
IP-Clean: Bernd Hufmann <bhufmann@gmail.com>
Tested-by: Bernd Hufmann <bhufmann@gmail.com>
18 files changed:
org.eclipse.linuxtools.tmf.ui.tests/src/org/eclipse/linuxtools/tmf/ui/tests/statistics/TmfBaseColumnDataProviderTest.java
org.eclipse.linuxtools.tmf.ui/META-INF/MANIFEST.MF
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfTraceType.java
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/ITmfViewer.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/TmfViewer.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/statistics/ITmfExtraEventInfo.java
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/statistics/Messages.java [changed mode: 0755->0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/statistics/TmfStatisticsRequest.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/statistics/TmfStatisticsViewer.java
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/statistics/messages.properties [changed mode: 0755->0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/statistics/model/Messages.java
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/statistics/model/TmfBaseColumnDataProvider.java
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/statistics/model/messages.properties
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/statistics/Messages.java [new file with mode: 0755]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/statistics/TmfStatisticsRequest.java [deleted file]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/statistics/TmfStatisticsView.java
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/statistics/messages.properties [new file with mode: 0755]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/widgets/tabsview/TmfViewerFolder.java [new file with mode: 0644]

index 1586ea5beba691c0f441fe6c55a828a45c961465..74ff5867515aa9c30fe3402d18e38dc3ec85d0ff 100644 (file)
@@ -41,8 +41,8 @@ public class TmfBaseColumnDataProviderTest extends TestCase {
     // ------------------------------------------------------------------------
     // Fields
     // ------------------------------------------------------------------------
-    private final static String LEVEL_COLUMN = org.eclipse.linuxtools.tmf.ui.viewers.statistics.Messages.TmfStatisticsView_LevelColumn;
-    private final static String EVENTS_COUNT_COLUMN = org.eclipse.linuxtools.tmf.ui.viewers.statistics.Messages.TmfStatisticsView_NbEventsColumn;
+    private final static String LEVEL_COLUMN = Messages.TmfStatisticsView_LevelColumn;
+    private final static String EVENTS_COUNT_COLUMN = Messages.TmfStatisticsView_NbEventsColumn;
 
     private TmfBaseColumnDataProvider provider;
 
index 536752a6b3e09c5fcb67b22aec8005e7788bd771..b511acf8bc09876eeb450eb48aeca6e4b9f7a551 100644 (file)
@@ -29,6 +29,7 @@ Export-Package: org.eclipse.linuxtools.internal.tmf.ui;x-friends:="org.eclipse.l
  org.eclipse.linuxtools.tmf.ui.project.model,
  org.eclipse.linuxtools.tmf.ui.project.wizards,
  org.eclipse.linuxtools.tmf.ui.signal,
+ org.eclipse.linuxtools.tmf.ui.viewers,
  org.eclipse.linuxtools.tmf.ui.viewers.events,
  org.eclipse.linuxtools.tmf.ui.viewers.statistics,
  org.eclipse.linuxtools.tmf.ui.viewers.statistics.model,
@@ -53,6 +54,7 @@ Export-Package: org.eclipse.linuxtools.internal.tmf.ui;x-friends:="org.eclipse.l
  org.eclipse.linuxtools.tmf.ui.views.uml2sd.preferences,
  org.eclipse.linuxtools.tmf.ui.views.uml2sd.util,
  org.eclipse.linuxtools.tmf.ui.widgets.rawviewer,
+ org.eclipse.linuxtools.tmf.ui.widgets.tabsview,
  org.eclipse.linuxtools.tmf.ui.widgets.timegraph,
  org.eclipse.linuxtools.tmf.ui.widgets.timegraph.dialogs,
  org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model,
index dc0c2064964214b7d2b182a91dd811ebc24c6b24..0d9b8d951e8b0a195a21fec9e98d2681b3719133 100644 (file)
@@ -15,8 +15,12 @@ package org.eclipse.linuxtools.tmf.ui.project.model;
 import java.util.LinkedList;
 import java.util.List;
 
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IConfigurationElement;
 import org.eclipse.core.runtime.Platform;
+import org.eclipse.linuxtools.internal.tmf.ui.Activator;
+import org.eclipse.linuxtools.tmf.core.TmfCommonConstants;
 
 /**
  * Utility class for accessing TMF trace type extensions from the platform's extensions registry.
@@ -100,6 +104,46 @@ public class TmfTraceType {
         return ""; //$NON-NLS-1$
     }
 
+    /**
+     * Retrieves and instantiates an element's object based on his plug-in
+     * definition for a specific trace type.
+     *
+     * The element's object is instantiated using its 0-argument constructor.
+     *
+     * @param resource
+     *            The resource where to find the information about the trace
+     *            properties
+     * @param element
+     *            The name of the element to find under the trace type
+     *            definition
+     * @return a new Object based on his definition in plugin.xml, or null if no
+     *         definition was found
+     * @since 2.0
+     */
+    public static Object getTraceTypeElement(IResource resource, String element) {
+        try {
+            if (resource != null) {
+                String traceType = resource.getPersistentProperty(TmfCommonConstants.TRACETYPE);
+                /*
+                 * Search in the configuration if there is any viewer specified
+                 * for this kind of trace type.
+                 */
+                for (IConfigurationElement ce : TmfTraceType.getTypeElements()) {
+                    if (ce.getAttribute(TmfTraceType.ID_ATTR).equals(traceType)) {
+                        IConfigurationElement[] viewerCE = ce.getChildren(element);
+                        if (viewerCE.length != 1) {
+                            break;
+                        }
+                        return viewerCE[0].createExecutableExtension(TmfTraceType.CLASS_ATTR);
+                    }
+                }
+            }
+        } catch (CoreException e) {
+            Activator.getDefault().logError("Error creating the element from the resource", e); //$NON-NLS-1$
+        }
+        return null;
+    }
+
     /**
      * Retrieves all configuration elements from the platform extension registry
      * for the trace type extension.
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/ITmfViewer.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/ITmfViewer.java
new file mode 100644 (file)
index 0000000..fbed37a
--- /dev/null
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *   Mathieu Denis <mathieu.denis@polymtl.ca> - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.tmf.ui.viewers;
+
+import org.eclipse.linuxtools.tmf.core.component.ITmfComponent;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * Interface to viewers.
+ *
+ * Viewers are to be put into views which need to know how to refresh the
+ * viewer's contents.
+ *
+ * @author Mathieu Denis
+ * @version 2.0
+ * @since 2.0
+ */
+public interface ITmfViewer extends ITmfComponent {
+
+    /**
+     * Returns the primary control associated with this viewer.
+     *
+     * @return the SWT control which displays this viewer's contents
+     */
+    public Control getControl();
+
+    /**
+     * Tells the viewer to refresh its contents.
+     */
+    public void refresh();
+}
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/TmfViewer.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/TmfViewer.java
new file mode 100644 (file)
index 0000000..82fea07
--- /dev/null
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *   Mathieu Denis <mathieu.denis@polymtl.ca> - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.tmf.ui.viewers;
+
+import org.eclipse.linuxtools.tmf.core.component.TmfComponent;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * Abstract class that extends {@link TmfComponent} to be specific to viewers.
+ *
+ * It allows the access to the control and the parent of a viewer.
+ *
+ * @author Mathieu Denis
+ * @version 2.0
+ * @since 2.0
+ */
+public abstract class TmfViewer extends TmfComponent implements ITmfViewer {
+
+    /**
+     * The parent composite that holds the viewer
+     */
+    protected Composite fParent;
+
+    /**
+     * Default constructor. The viewer have to be initialize through the
+     * {@link TmfViewer#init(Composite, String)} function later on.
+     */
+    public TmfViewer() {
+        super();
+    }
+
+    /**
+     * Constructor that initializes the parent of the viewer
+     *
+     * @param parent
+     *            The parent composite that holds this viewer
+     *
+     * @see TmfComponent#TmfComponent(String)
+     */
+    public TmfViewer(Composite parent) {
+        this(parent, ""); //$NON-NLS-1$
+    }
+
+    /**
+     * Constructor that initializes the parent of the viewer and that sets the
+     * name of the viewer
+     *
+     * @param parent
+     *            The parent composite that holds this viewer
+     * @param name
+     *            The name of the viewer
+     */
+    public TmfViewer(Composite parent, String name) {
+        init(parent, name);
+    }
+
+    /**
+     * Performs initialization of the viewer. It initializes the component. Need
+     * to be called when the default constructor is used.
+     *
+     * @param parent
+     *            The parent composite of the viewer
+     * @param name
+     *            The name to give to this viewer
+     * @see TmfComponent#init(String)
+     */
+    public void init(Composite parent, String name) {
+        super.init(name);
+        fParent = parent;
+    }
+
+    /**
+     * @return the parent of this viewer
+     */
+    public Composite getParent() {
+        return fParent;
+    }
+}
index 0a507ebb826c33c4b3ae115a7b7d664b16f93d56..8cac72343064acef551d1d1502024aa685010b72 100755 (executable)
@@ -24,7 +24,7 @@ package org.eclipse.linuxtools.tmf.ui.viewers.statistics;
 public interface ITmfExtraEventInfo {
 
     /**
-     * Returns the trace name.
+     * Returns the name of the trace.
      *
      * @return the name of the trace.
      */
old mode 100755 (executable)
new mode 100644 (file)
index a27be40..202aa36
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2011, 2012 Ericsson
+ * Copyright (c) 2012 Ericsson
  *
  * All rights reserved. This program and the accompanying materials are
  * made available under the terms of the Eclipse Public License v1.0 which
@@ -17,46 +17,14 @@ import org.eclipse.osgi.util.NLS;
 /**
  * Messages file for statistics view strings.
  *
- * @version 2.0
  * @author Mathieu Denis
  * @since 2.0
+ * @version 2.0
  */
 public class Messages extends NLS {
 
     private static final String BUNDLE_NAME = "org.eclipse.linuxtools.tmf.ui.viewers.statistics.messages"; //$NON-NLS-1$
 
-    /**
-     * Level column name
-     */
-    public static String TmfStatisticsView_LevelColumn;
-
-    /**
-     * Level column tool tip.
-     */
-    public static String TmfStatisticsView_LevelColumnTip;
-
-    /**
-     * Number of events column name.
-     */
-    public static String TmfStatisticsView_NbEventsColumn;
-
-    /**
-     * Number of events column tool tip.
-     */
-    public static String TmfStatisticsView_NbEventsTip;
-
-    /**
-     * Partial number of events column.
-     * @since 2.0
-     */
-    public static String TmfStatisticsView_NbEventsTimeRangeColumn;
-
-    /**
-     * Partial number of events column tool tip.
-     * @since 2.0
-     */
-    public static String TmfStatisticsView_NbEventsTimeRangeTip;
-
     /**
      * String for unknown trace name.
      */
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/statistics/TmfStatisticsRequest.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/statistics/TmfStatisticsRequest.java
new file mode 100644 (file)
index 0000000..ec09c92
--- /dev/null
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2012 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *   Mathieu Denis <mathieu.denis@polymtl.ca> - Initial implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.tmf.ui.viewers.statistics;
+
+import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
+import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange;
+import org.eclipse.linuxtools.tmf.core.request.TmfDataRequest;
+import org.eclipse.linuxtools.tmf.core.request.TmfEventRequest;
+import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.AbsTmfStatisticsTree;
+
+/**
+ * Class for the TMF event requests specific to the statistics view.
+ *
+ * @version 2.0
+ * @since 2.0
+ */
+public class TmfStatisticsRequest extends TmfEventRequest {
+
+    /**
+     * Reference to the statistics viewer that sent the request.
+     */
+    private final TmfStatisticsViewer fSender;
+
+    /**
+     * Reference to the statistics tree.
+     */
+    private final AbsTmfStatisticsTree fStatisticsData;
+
+    /**
+     * Tells if the request is for the whole trace or for a smaller time range.
+     */
+    private final boolean fGlobal;
+
+    /**
+     * Index of the last event retrieved.
+     */
+    private long fLastEventIndex;
+
+    /**
+     * Constructor
+     *
+     * @param sender
+     *            Sender of this request
+     * @param range
+     *            The target time range
+     * @param index
+     *            The starting index
+     * @param global
+     *            Is this for a global statistics request (true), or a partial
+     *            one (false)?
+     */
+    public TmfStatisticsRequest(TmfStatisticsViewer sender, TmfTimeRange range, long index, boolean global) {
+        super(ITmfEvent.class, range, index, TmfDataRequest.ALL_DATA, sender.getPageSize(), ExecutionType.BACKGROUND);
+        fGlobal = global;
+        fSender = sender;
+        fStatisticsData = fSender.getStatisticData();
+        fLastEventIndex = index;
+    }
+
+
+    @Override
+    public void handleData(ITmfEvent data) {
+        ++fLastEventIndex;
+
+        if (data != null) {
+            final String traceName = data.getTrace().getName();
+            if (fSender.isListeningTo(traceName)) {
+                super.handleData(data);
+
+                ITmfExtraEventInfo extraInfo = new ITmfExtraEventInfo() {
+                    @Override
+                    public String getTraceName() {
+                        if (traceName == null) {
+                            return Messages.TmfStatisticsView_UnknownTraceName;
+                        }
+                        return traceName;
+                    }
+                };
+
+                if (fGlobal) {
+                    fStatisticsData.registerEvent(data, extraInfo);
+                } else {
+                    fStatisticsData.registerEventInTimeRange(data, extraInfo);
+                }
+
+                if (getNbRead() % fSender.getRefreshRate() == 0) {
+                    fSender.refresh();
+                }
+            }
+        }
+    }
+
+    @Override
+    public void handleSuccess() {
+        super.handleSuccess();
+        handleFinish(true);
+    }
+
+    @Override
+    public void handleFailure() {
+        super.handleFailure();
+        handleFinish(false);
+    }
+
+    @Override
+    public void handleCancel() {
+        super.handleCancel();
+        handleFinish(false);
+    }
+
+    /**
+     * @return the index of the last event read in the experiment so far
+     */
+    protected long getLastEventIndex() {
+        return fLastEventIndex;
+    }
+
+    /**
+     * Handles the end of the request whether it is successful or not.
+     *
+     * @param isSuccessful
+     *            Tells if the request has finished successfully or not and
+     *            calls the right method from the sender in each case.
+     */
+    protected void handleFinish(boolean isSuccessful) {
+        if (isSuccessful) {
+            fSender.modelComplete(fGlobal);
+        } else {
+            fSender.modelIncomplete(fGlobal);
+        }
+    }
+}
index 103913cf6124f9dfba3faa509736eafa69f63b18..54f4e892d0f75d8414fe60c6e038f5fbdf5695d3 100644 (file)
@@ -19,6 +19,16 @@ import org.eclipse.jface.viewers.TreeViewerColumn;
 import org.eclipse.jface.viewers.Viewer;
 import org.eclipse.jface.viewers.ViewerComparator;
 import org.eclipse.linuxtools.tmf.core.component.TmfComponent;
+import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange;
+import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp;
+import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest;
+import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentRangeUpdatedSignal;
+import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentUpdatedSignal;
+import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal;
+import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
+import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
+import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment;
+import org.eclipse.linuxtools.tmf.ui.viewers.TmfViewer;
 import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.AbsTmfStatisticsTree;
 import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.ITmfColumnDataProvider;
 import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfBaseColumnData;
@@ -32,7 +42,6 @@ import org.eclipse.swt.events.SelectionAdapter;
 import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.graphics.Color;
 import org.eclipse.swt.graphics.Cursor;
-import org.eclipse.swt.layout.FillLayout;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Display;
@@ -46,12 +55,37 @@ import org.eclipse.swt.widgets.Listener;
  * @version 2.0
  * @since 2.0
  */
-public class TmfStatisticsViewer extends TmfComponent {
+public class TmfStatisticsViewer extends TmfViewer {
 
     /**
-     * Refresh frequency
+     * The initial window span (in nanoseconds)
      */
-    protected static final Long STATS_INPUT_CHANGED_REFRESH = 5000L;
+    public static final long INITIAL_WINDOW_SPAN = (1L * 100 * 1000 * 1000); // .1sec
+
+    /**
+     * Timestamp scale (nanosecond)
+     */
+    public static final byte TIME_SCALE = -9;
+
+    /**
+     * Default PAGE_SIZE for background requests.
+     */
+    protected static final int PAGE_SIZE = 50000;
+
+    /**
+     * Refresh frequency.
+     */
+    protected final Long STATS_INPUT_CHANGED_REFRESH = 5000L;
+
+    /**
+     * Stores the request to the experiment
+     */
+    protected TmfStatisticsRequest fRequest = null;
+
+    /**
+     * Stores the ranged request to the experiment
+     */
+    protected TmfStatisticsRequest fRequestRange = null;
 
     /**
      * The actual tree viewer to display
@@ -59,7 +93,40 @@ public class TmfStatisticsViewer extends TmfComponent {
     protected TreeViewer fTreeViewer;
 
     /**
-     * View instance counter (for multiple statistic views)
+     * The statistics tree linked to this viewer
+     */
+    protected AbsTmfStatisticsTree fStatisticsData;
+
+    /**
+     * Update synchronization parameter (used for streaming): Update busy
+     * indicator.
+     */
+    protected boolean fStatisticsUpdateBusy = false;
+
+    /**
+     * Update synchronization parameter (used for streaming): Update pending
+     * indicator.
+     */
+    protected boolean fStatisticsUpdatePending = false;
+
+    /**
+     * Update synchronization parameter (used for streaming): Pending Update
+     * time range.
+     */
+    protected TmfTimeRange fStatisticsUpdateRange = null;
+
+    /**
+     * Update synchronization object.
+     */
+    protected final Object fStatisticsUpdateSyncObj = new Object();
+
+    /**
+     * Indicates to process all events
+     */
+    private boolean fProcessAll;
+
+    /**
+     * View instance counter (for multiple statistics views)
      */
     private static int fCountInstance = 0;
 
@@ -68,24 +135,295 @@ public class TmfStatisticsViewer extends TmfComponent {
      */
     private int fInstanceNb;
 
+    /**
+     * The trace that is displayed by this viewer
+     */
+    private ITmfTrace fTrace;
+
     /**
      * Object to store the cursor while waiting for the experiment to load
      */
     private Cursor fWaitCursor = null;
 
     /**
-     * Default constructor
+     * Counts the number of times waitCursor() has been called. It avoids
+     * removing the waiting cursor, since there may be multiple requests running
+     * at the same time.
+     */
+    private int fWaitCursorCount = 0;
+
+    /**
+     * Tells to send a time range request when the experiment gets updated.
+     */
+    private boolean fSendRangeRequest = true;
+
+    /**
+     * Empty constructor. To be used in conjunction with
+     * {@link TmfStatisticsViewer#init(Composite, String, ITmfTrace)}
+     */
+    public TmfStatisticsViewer() {
+        super();
+    }
+
+    /**
+     * Create a basic statistics viewer. To be used in conjunction with
+     * {@link TmfStatisticsViewer#init(Composite, String, ITmfTrace)}
+     *
+     * @param parent
+     *            The parent composite that will hold the viewer
+     * @param viewerName
+     *            The name that will be assigned to this viewer
+     * @param trace
+     *            The trace that is displayed by this viewer
+     * @see TmfComponent
+     */
+    public TmfStatisticsViewer(Composite parent, String viewerName, ITmfTrace trace) {
+        init(parent, viewerName, trace);
+    }
+
+    /**
+     * Initialize the statistics viewer.
      *
      * @param parent
-     *            The parent of this viewer
+     *            The parent component of the viewer.
+     * @param viewerName
+     *            The name to give to the viewer.
+     * @param trace
+     *            The trace that will be displayed by the viewer.
      */
-    public TmfStatisticsViewer(Composite parent) {
+    public void init(Composite parent, String viewerName, ITmfTrace trace) {
+        super.init(parent, viewerName);
         // Increment a counter to make sure the tree ID is unique.
         fCountInstance++;
         fInstanceNb = fCountInstance;
+        fTrace = trace;
+
+        // The viewer will process all events if he is assigned to the experiment
+        fProcessAll = (trace instanceof TmfExperiment);
+
+        initContent(parent);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.eclipse.linuxtools.tmf.core.component.TmfComponent#dispose()
+     */
+    @Override
+    public void dispose() {
+        super.dispose();
+        if (fWaitCursor != null) {
+            fWaitCursor.dispose();
+        }
+        /*
+         * Make sure there is no request running before removing the statistics
+         * tree
+         */
+        cancelOngoingRequest(fRequestRange);
+        cancelOngoingRequest(fRequest);
+    }
+
+    /**
+     * Handles the signal about new experiment range.
+     *
+     * @param signal
+     *            The experiment range updated signal
+     */
+    @TmfSignalHandler
+    public void experimentRangeUpdated(TmfExperimentRangeUpdatedSignal signal) {
+        TmfExperiment experiment = signal.getExperiment();
+        // validate
+        if (!experiment.equals(TmfExperiment.getCurrentExperiment())) {
+            return;
+        }
+
+        // Sends the time range request only once in this method.
+        if (fSendRangeRequest) {
+            fSendRangeRequest = false;
+            // Calculate the selected time range to request
+            long startTime = signal.getRange().getStartTime().normalize(0, TIME_SCALE).getValue();
+            TmfTimestamp startTS = new TmfTimestamp(startTime, TIME_SCALE);
+            TmfTimestamp endTS = new TmfTimestamp(startTime + INITIAL_WINDOW_SPAN, TIME_SCALE);
+            TmfTimeRange timeRange = new TmfTimeRange(startTS, endTS);
+
+            requestTimeRangeData(experiment, timeRange);
+        }
+        requestData(experiment, signal.getRange());
+    }
+
+    /**
+     * Handles the experiment updated signal. This will detect new events in
+     * case the indexing is not coalesced with a statistics request.
+     *
+     * @param signal
+     *            The experiment updated signal
+     */
+    @TmfSignalHandler
+    public void experimentUpdated(TmfExperimentUpdatedSignal signal) {
+        TmfExperiment experiment = signal.getExperiment();
+        if (!experiment.equals(TmfExperiment.getCurrentExperiment())) {
+            return;
+        }
+
+        long nbEvents = 0;
+        if (fRequest != null) {
+            nbEvents = fRequest.getLastEventIndex();
+        }
+        /*
+         * In the normal case, the statistics request is coalesced with indexing
+         * and the number of events are the same, there is nothing to do. But if
+         * it's not the case, trigger a new request to count the new events.
+         */
+        if (nbEvents < experiment.getNbEvents()) {
+            requestData(experiment, experiment.getTimeRange());
+        }
+    }
+
+    /**
+     * * Handles the time range updated signal. It updates the time range
+     * statistics.
+     *
+     * @param signal
+     *            Contains the information about the new selected time range.
+     */
+    @TmfSignalHandler
+    public void timeRangeUpdated(TmfRangeSynchSignal signal) {
+        /*
+         * It is possible that the time range changes while a request is
+         * processing.
+         */
+        cancelOngoingRequest(fRequestRange);
+
+        requestTimeRangeData(TmfExperiment.getCurrentExperiment(), signal.getCurrentRange());
+    }
+
+    /*
+     * Returns the primary control associated with this viewer.
+     *
+     * @return the SWT control which displays this viewer's content
+     */
+    @Override
+    public Control getControl() {
+        return fTreeViewer.getControl();
+    }
+
+    /**
+     * Get the input of the viewer.
+     *
+     * @return an object representing the input of the statistics viewer.
+     */
+    public Object getInput() {
+        return fTreeViewer.getInput();
+    }
+
+    /**
+     * Return the size of the request when performing background request.
+     *
+     * @return the block size for background request.
+     */
+    public int getPageSize() {
+        return PAGE_SIZE;
+    }
+
+    /**
+     * Return the number of events to receive before a refresh of the viewer is
+     * performed.
+     *
+     * @return the input refresh rate
+     */
+    public long getRefreshRate() {
+        return STATS_INPUT_CHANGED_REFRESH;
+    }
+
+    /**
+     * This method can be overridden to implement another way of representing
+     * the statistics data and to retrieve the information for display.
+     *
+     * @return a TmfStatisticsData object.
+     */
+    public AbsTmfStatisticsTree getStatisticData() {
+        if (fStatisticsData == null) {
+            fStatisticsData = new TmfBaseStatisticsTree();
+        }
+        return fStatisticsData;
+    }
+
+    /**
+     * Returns a unique ID based on name to be associated with the statistics
+     * tree for this viewer. For a same name, it will always return the same ID.
+     *
+     * @return a unique statistics tree ID.
+     */
+    public String getTreeID() {
+        return getName() + fInstanceNb;
+    }
+
+    @Override
+    public void refresh() {
+        final Control viewerControl = getControl();
+        // Ignore update if disposed
+        if (viewerControl.isDisposed()) {
+            return;
+        }
+
+        viewerControl.getDisplay().asyncExec(new Runnable() {
+            @Override
+            public void run() {
+                if (!viewerControl.isDisposed()) {
+                    fTreeViewer.refresh();
+                }
+            }
+        });
+    }
+
+    /**
+     * Focus on the statistics tree of the viewer
+     */
+    public void setFocus() {
+        fTreeViewer.getTree().setFocus();
+    }
+
+    /**
+     * Sets or clears the input for this viewer.
+     *
+     * @param input
+     *            The input of this viewer, or <code>null</code> if none
+     */
+    public void setInput(TmfStatisticsTreeNode input) {
+        resetUpdateSynchronization();
+        fTreeViewer.setInput(input);
+    }
+
+    /**
+     * Cancels the request if it is not already completed
+     *
+     * @param request
+     *            The request to be canceled
+     */
+    protected void cancelOngoingRequest(ITmfDataRequest request) {
+        if (request != null && !request.isCompleted()) {
+            request.cancel();
+        }
+    }
+
+    /**
+     * This method can be overridden to change the representation of the data in
+     * the columns.
+     *
+     * @return an object implementing ITmfBaseColumnDataProvider.
+     */
+    protected ITmfColumnDataProvider getColumnDataProvider() {
+        return new TmfBaseColumnDataProvider();
+    }
 
+    /**
+     * Initialize the content that will be drawn in this viewer
+     *
+     * @param parent
+     *            The parent of the control to create
+     */
+    protected void initContent(Composite parent) {
         final List<TmfBaseColumnData> columnDataList = getColumnDataProvider().getColumnData();
-        parent.setLayout(new FillLayout());
 
         fTreeViewer = new TreeViewer(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
         fTreeViewer.setContentProvider(new TmfTreeContentProvider());
@@ -187,137 +525,215 @@ public class TmfStatisticsViewer extends TmfComponent {
     }
 
     /**
-     * Refreshes this viewer completely with information freshly obtained from
-     * this viewer's model.
-     */
-    public void refresh() {
-        fTreeViewer.refresh();
-    }
-
-    /*
-     * (non-Javadoc)
+     * Tells if the viewer is listening to a trace from the selected experiment.
      *
-     * @see org.eclipse.linuxtools.tmf.core.component.TmfComponent#dispose()
+     * @param traceName
+     *            The trace that the viewer may be listening
+     * @return true if the viewer is listening to the trace, false otherwise
      */
-    @Override
-    public void dispose() {
-        if (fWaitCursor != null) {
-            fWaitCursor.dispose();
+    protected boolean isListeningTo(String traceName) {
+        if (fProcessAll || traceName.equals(fTrace.getName())) {
+            return true;
         }
-        fTreeViewer.getControl().dispose();
-        super.dispose();
-        // clean the model
-        TmfStatisticsTreeRootFactory.removeAll();
-    }
-
-    /**
-     * Focus on the statistics tree of the viewer
-     */
-    public void setFocus() {
-        fTreeViewer.getTree().setFocus();
+        return false;
     }
 
     /**
-     * Sets or clears the input for this viewer.
+     * Called when an experiment request has been completed successfully.
      *
-     * @param input
-     *            The input of this viewer, or <code>null</code> if none
+     * @param global
+     *            Tells if the request is a global or time range (partial)
+     *            request.
      */
-    public void setInput(TmfStatisticsTreeNode input) {
-        fTreeViewer.setInput(input);
+    protected void modelComplete(boolean global) {
+        refresh();
+        waitCursor(false);
+        if (global) {
+            sendPendingUpdate();
+        }
     }
 
     /**
-     * Returns the quantity of data to retrieve before a refresh of the view is
-     * performed
+     * Called when an experiment request has failed or has been cancelled.
      *
-     * @return the quantity of data to retrieve before a refresh of the view is
-     *         performed.
+     * @param isGlobalRequest
+     *            Tells if the request is a global or time range (partial)
+     *            request.
      */
-    public long getInputChangedRefresh() {
-        return STATS_INPUT_CHANGED_REFRESH;
+    protected void modelIncomplete(boolean isGlobalRequest) {
+        if (isGlobalRequest) {  // Clean the global statistics
+            /*
+             * The data is invalid and shall be removed to refresh upon next
+             * selection
+             */
+            Object input = getInput();
+            if (input instanceof TmfStatisticsTreeNode) {
+                TmfStatisticsTreeRootFactory.removeStatTreeRoot(getTreeID());
+            }
+            resetUpdateSynchronization();
+            sendPendingUpdate();
+        } else {    // Clean the partial statistics
+            resetTimeRangeValue();
+        }
+        refresh();
+        waitCursor(false);
     }
 
     /**
-     * This method can be overridden to implement another way to represent the
-     * statistics data and to retrieve the information for display.
+     * Sends the request to the experiment for the whole trace
      *
-     * @return a TmfStatisticsData object.
+     * @param experiment
+     *            The experiment used to send the request
+     * @param range
+     *            The range to request to the experiment
      */
-    public AbsTmfStatisticsTree getStatisticData() {
-        return new TmfBaseStatisticsTree();
+    protected void requestData(TmfExperiment experiment, TmfTimeRange range) {
+        // Check if an update is already ongoing
+        if (checkUpdateBusy(range)) {
+            return;
+        }
+
+        long index = 0;
+        /*
+         * Sets the index to the last event retrieved from the experiment during
+         * the last request.
+         */
+        if (fRequest != null) {
+            index = fRequest.getLastEventIndex();
+        }
+
+        fRequest = new TmfStatisticsRequest(this, range, index, true);
+        waitCursor(true);
+        experiment.sendRequest(fRequest);
     }
 
     /**
-     * Get the input of the viewer
+     * Sends the time range request from the experiment
      *
-     * @return an object representing the input of the statistics viewer
+     * @param experiment
+     *            The experiment used to send the request
+     * @param range
+     *            The range to request to the experiment
      */
-    public Object getInput() {
-        return fTreeViewer.getInput();
+    protected void requestTimeRangeData(TmfExperiment experiment, TmfTimeRange range) {
+        resetTimeRangeValue();
+        fRequestRange = new TmfStatisticsRequest(this, range, 0, false);
+        waitCursor(true);
+        experiment.sendRequest(fRequestRange);
     }
 
     /**
-     * Returns the primary control associated with this viewer.
-     *
-     * @return the SWT control which displays this viewer's content
+     * Resets the number of events within the time range
      */
-    public Control getControl() {
-        return fTreeViewer.getControl();
+    protected void resetTimeRangeValue() {
+        TmfStatisticsTreeNode treeModelRoot = TmfStatisticsTreeRootFactory.getStatTreeRoot(getTreeID());
+        if (treeModelRoot != null && treeModelRoot.hasChildren()) {
+            treeModelRoot.resetTimeRangeValue();
+        }
     }
 
     /**
      * When the experiment is loading the cursor will be different so the user
-     * know the processing is not finished yet.
+     * knows that the processing is not finished yet.
+     *
+     * Calls to this method are stacked.
      *
-     * @param waitInd
+     * @param waitRequested
      *            Indicates if we need to show the waiting cursor, or the
-     *            default one
+     *            default one.
      */
-    public void waitCursor(final boolean waitInd) {
+    protected void waitCursor(final boolean waitRequested) {
         if ((fTreeViewer == null) || (fTreeViewer.getTree().isDisposed())) {
             return;
         }
 
+        boolean needsUpdate = false;
         Display display = fTreeViewer.getControl().getDisplay();
-        if (fWaitCursor == null) {
-            fWaitCursor = new Cursor(display, SWT.CURSOR_WAIT);
+        if (waitRequested) {
+            fWaitCursorCount++;
+            if (fWaitCursor == null) { // The cursor hasn't been initialized yet
+                fWaitCursor = new Cursor(display, SWT.CURSOR_WAIT);
+            }
+            if (fWaitCursorCount == 1) { // The cursor is not in waiting mode
+                needsUpdate = true;
+            }
+        } else {
+            if (fWaitCursorCount > 0) { // The cursor is in waiting mode
+                fWaitCursorCount--;
+                if (fWaitCursorCount == 0) { // No more reason to wait
+                    // Put back the default cursor
+                    needsUpdate = true;
+                }
+            }
         }
 
-        // Perform the updates on the UI thread
-        display.asyncExec(new Runnable() {
-            @Override
-            public void run() {
-                if ((fTreeViewer != null)
-                        && (!fTreeViewer.getTree().isDisposed())) {
-                    Cursor cursor = null; /* indicates default */
-                    if (waitInd) {
-                        cursor = fWaitCursor;
+        if (needsUpdate) {
+            // Performs the updates on the UI thread
+            display.asyncExec(new Runnable() {
+                @Override
+                public void run() {
+                    if ((fTreeViewer != null)
+                            && (!fTreeViewer.getTree().isDisposed())) {
+                        Cursor cursor = null; // indicates default
+                        if (waitRequested) {
+                            cursor = fWaitCursor;
+                        }
+                        fTreeViewer.getControl().setCursor(cursor);
                     }
-                    fTreeViewer.getControl().setCursor(cursor);
                 }
-            }
-        });
+            });
+        }
     }
 
+    // ------------------------------------------------------------------------
+    // Methods reserved for the streaming functionality
+    // ------------------------------------------------------------------------
+
     /**
-     * Constructs the ID based on the experiment name and the instance number
-     *
-     * @param name
-     *            The name of the trace to show in the view
-     * @return a view ID
+     * Resets update synchronization information
      */
-    public String getTreeID(String name) {
-        return name + fInstanceNb;
+    protected void resetUpdateSynchronization() {
+        synchronized (fStatisticsUpdateSyncObj) {
+            fStatisticsUpdateBusy = false;
+            fStatisticsUpdatePending = false;
+            fStatisticsUpdateRange = null;
+        }
     }
 
     /**
-     * This method can be overridden to change the representation of the data in
-     * the columns.
+     * Checks if statistics update is ongoing. If it is ongoing, the new time
+     * range is stored as pending
      *
-     * @return an object implementing ITmfBaseColumnDataProvider.
+     * @param timeRange
+     *            - new time range
+     * @return true if statistic update is ongoing else false
      */
-    protected ITmfColumnDataProvider getColumnDataProvider() {
-        return new TmfBaseColumnDataProvider();
+    protected boolean checkUpdateBusy(TmfTimeRange timeRange) {
+        synchronized (fStatisticsUpdateSyncObj) {
+            if (fStatisticsUpdateBusy) {
+                fStatisticsUpdatePending = true;
+                if (fStatisticsUpdateRange == null
+                        || timeRange.getEndTime().compareTo(fStatisticsUpdateRange.getEndTime()) > 0) {
+                    fStatisticsUpdateRange = timeRange;
+                }
+                return true;
+            }
+            fStatisticsUpdateBusy = true;
+            return false;
+        }
+    }
+
+    /**
+     * Sends pending request (if any)
+     */
+    protected void sendPendingUpdate() {
+        synchronized (fStatisticsUpdateSyncObj) {
+            fStatisticsUpdateBusy = false;
+            if (fStatisticsUpdatePending) {
+                fStatisticsUpdatePending = false;
+                requestData(TmfExperiment.getCurrentExperiment(), fStatisticsUpdateRange);
+                fStatisticsUpdateRange = null;
+            }
+        }
     }
 }
old mode 100755 (executable)
new mode 100644 (file)
index 2542d73..9009fe0
@@ -1,7 +1 @@
-TmfStatisticsView_LevelColumn=Level
-TmfStatisticsView_LevelColumnTip=Level at which statistics apply.
-TmfStatisticsView_NbEventsColumn=Global event count
-TmfStatisticsView_NbEventsTip=Total amount of events that are tied to given resource.
-TmfStatisticsView_NbEventsTimeRangeColumn=Partial event count
-TmfStatisticsView_NbEventsTimeRangeTip=Number of events in the selected time range
-TmfStatisticsView_UnknownTraceName=Unknown_Trace
+TmfStatisticsView_UnknownTraceName=Unknown_Trace
\ No newline at end of file
index 08c95aeadb7b6517f2b41996d9e9fbf08ebc29a1..2a50be45549f554f3cab976e8c0542471bae40f2 100755 (executable)
@@ -35,6 +35,38 @@ public class Messages extends NLS {
      */
     public static String TmfStatisticsData_EventTypes;
 
+    /**
+     * Level column name
+     */
+    public static String TmfStatisticsView_LevelColumn;
+
+    /**
+     * Level column tool tip.
+     */
+    public static String TmfStatisticsView_LevelColumnTip;
+
+    /**
+     * Number of events column name.
+     */
+    public static String TmfStatisticsView_NbEventsColumn;
+
+    /**
+     * Number of events column tool tip.
+     */
+    public static String TmfStatisticsView_NbEventsTip;
+
+    /**
+     * Partial number of events column.
+     * @since 2.0
+     */
+    public static String TmfStatisticsView_NbEventsTimeRangeColumn;
+
+    /**
+     * Partial number of events column tool tip.
+     * @since 2.0
+     */
+    public static String TmfStatisticsView_NbEventsTimeRangeTip;
+
     static {
         // initialize resource bundle
         NLS.initializeMessages(BUNDLE_NAME, Messages.class);
index 29d6e4e49691d7c9686b10ddf882916e87892903..4edced393a61ab34cc782469532137e083731052 100755 (executable)
@@ -21,7 +21,6 @@ import java.util.Vector;
 import org.eclipse.jface.viewers.ColumnLabelProvider;
 import org.eclipse.jface.viewers.Viewer;
 import org.eclipse.jface.viewers.ViewerComparator;
-import org.eclipse.linuxtools.tmf.ui.viewers.statistics.Messages;
 import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfBaseColumnData.ITmfColumnPercentageProvider;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.graphics.Image;
index 442d278a76b0a4cb8ecab1ef33ed647b06ef8666..183c928ddc0eb41e72834ddfc733ed891186b528 100755 (executable)
@@ -1,2 +1,8 @@
 TmfStatisticsData_CPUs=CPUs
-TmfStatisticsData_EventTypes=Event Types
\ No newline at end of file
+TmfStatisticsData_EventTypes=Event Types
+TmfStatisticsView_LevelColumn=Level
+TmfStatisticsView_LevelColumnTip=Level at which statistics apply.
+TmfStatisticsView_NbEventsColumn=Global event count
+TmfStatisticsView_NbEventsTip=Total amount of events contained in the trace/experiment.
+TmfStatisticsView_NbEventsTimeRangeColumn=Partial event count
+TmfStatisticsView_NbEventsTimeRangeTip=Number of events in the selected time range
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/statistics/Messages.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/statistics/Messages.java
new file mode 100755 (executable)
index 0000000..cd8abf5
--- /dev/null
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2012 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *   Mathieu Denis <mathieu.denis@polymtl.ca> - Initial API and Implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.tmf.ui.views.statistics;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Messages file for statistics view strings.
+ *
+ * @version 2.0
+ * @author Mathieu Denis
+ * @since 2.0
+ */
+public class Messages extends NLS {
+
+    private static final String BUNDLE_NAME = "org.eclipse.linuxtools.tmf.ui.views.statistics.messages"; //$NON-NLS-1$
+
+    /**
+     * String for unknown trace name.
+     */
+    public static String TmfStatisticsView_UnknownTraceName;
+
+    /**
+     * String for the global tab name
+     * @since 2.0
+     */
+    public static String TmfStatisticsView_GlobalTabName;
+
+    static {
+        // initialize resource bundle
+        NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+    }
+
+    private Messages() {
+    }
+}
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/statistics/TmfStatisticsRequest.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/statistics/TmfStatisticsRequest.java
deleted file mode 100644 (file)
index 980b523..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2011, 2012 Ericsson
- *
- * All rights reserved. This program and the accompanying materials are
- * made available under the terms of the Eclipse Public License v1.0 which
- * accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *   Mathieu Denis <mathieu.denis@polymtl.ca> - Initial implementation
- *******************************************************************************/
-
-package org.eclipse.linuxtools.tmf.ui.views.statistics;
-
-import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
-import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange;
-import org.eclipse.linuxtools.tmf.core.request.TmfDataRequest;
-import org.eclipse.linuxtools.tmf.core.request.TmfEventRequest;
-import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment;
-import org.eclipse.linuxtools.tmf.ui.viewers.statistics.ITmfExtraEventInfo;
-import org.eclipse.linuxtools.tmf.ui.viewers.statistics.Messages;
-import org.eclipse.linuxtools.tmf.ui.viewers.statistics.TmfStatisticsViewer;
-import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.AbsTmfStatisticsTree;
-import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfStatisticsTreeRootFactory;
-
-/**
- * Class for the TMF event requests specific to the statistics view.
- * @version 2.0
- */
-class TmfStatisticsRequest extends TmfEventRequest {
-
-    /**
-     * Reference to the statistics viewer that sent the request
-     */
-    private final TmfStatisticsView fSender;
-
-    /**
-     * The viewer that displays the statistics data
-     */
-    private TmfStatisticsViewer fViewer;
-
-    /**
-     * The experiment for which to send the request
-     */
-    private final TmfExperiment fExperiment;
-
-    /**
-     * Tells if the request is for the whole trace or for a smaller time range
-     */
-    private final boolean fGlobal;
-
-    /**
-     * The statistics tree that will be updated from the requested data
-     */
-    private final AbsTmfStatisticsTree fStatisticsData;
-
-    /**
-     * Constructor
-     *
-     * @param sender
-     *            Sender of this request
-     * @param experiment
-     *            Experiment targeted by this request
-     * @param range
-     *            The target time range
-     * @param index
-     *            The starting index
-     * @param prio
-     *            The priority of the request
-     * @param global
-     *            Is this for a global statistics request (true), or a partial
-     *            one (false)?
-     */
-    TmfStatisticsRequest(TmfStatisticsView sender, TmfStatisticsViewer viewer, TmfExperiment experiment, TmfTimeRange range, long index, ExecutionType prio, boolean global) {
-        super(ITmfEvent.class, range, index, TmfDataRequest.ALL_DATA, sender.getIndexPageSize(), prio);
-        String treeID = viewer.getTreeID(experiment.getName());
-
-        fSender = sender;
-        fViewer = viewer;
-        fExperiment = experiment;
-        fGlobal = global;
-        fStatisticsData = TmfStatisticsTreeRootFactory.getStatTree(treeID);
-    }
-
-    @Override
-    public void handleData(ITmfEvent data) {
-        super.handleData(data);
-        if (data != null) {
-            final String traceName = data.getTrace().getName();
-            ITmfExtraEventInfo extraInfo = new ITmfExtraEventInfo() {
-                @Override
-                public String getTraceName() {
-                    if (traceName == null) {
-                        return Messages.TmfStatisticsView_UnknownTraceName;
-                    }
-                    return traceName;
-                }
-            };
-            if (fGlobal) {
-                fStatisticsData.registerEvent(data, extraInfo);
-            } else {
-                fStatisticsData.registerEventInTimeRange(data, extraInfo);
-            }
-            fStatisticsData.increase(data, extraInfo, 1);
-            // Refresh view
-            if ((getNbRead() % fViewer.getInputChangedRefresh()) == 0) {
-                fSender.modelInputChanged(false);
-            }
-        }
-    }
-
-    @Override
-    public void handleSuccess() {
-        super.handleSuccess();
-        fSender.modelInputChanged(true);
-        if (fGlobal) {
-            fViewer.waitCursor(false);
-        }
-    }
-
-    @Override
-    public void handleFailure() {
-        super.handleFailure();
-        fSender.modelIncomplete(fExperiment.getName());
-    }
-
-    @Override
-    public void handleCancel() {
-        super.handleCancel();
-        /*
-         * The global request can be cancelled when another experiment is
-         * selected, but a time range request can also be cancelled when there is
-         * a time range update, which means the model must not be deleted.
-         */
-        if (fGlobal) {
-            fSender.modelIncomplete(fExperiment.getName());
-        }
-    }
-}
index efe06082156ab914f29809ed4b44cc469d3252a7..68b4820047c6c40db318a0a85a953cb9266af483 100755 (executable)
 
 package org.eclipse.linuxtools.tmf.ui.views.statistics;
 
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-
 import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IConfigurationElement;
-import org.eclipse.core.runtime.Platform;
 import org.eclipse.linuxtools.internal.tmf.ui.Activator;
-import org.eclipse.linuxtools.tmf.core.TmfCommonConstants;
-import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange;
-import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp;
-import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest.ExecutionType;
-import org.eclipse.linuxtools.tmf.core.request.ITmfEventRequest;
-import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentDisposedSignal;
+import org.eclipse.linuxtools.tmf.core.signal.TmfEndSynchSignal;
 import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentRangeUpdatedSignal;
 import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentSelectedSignal;
-import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentUpdatedSignal;
-import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal;
 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
+import org.eclipse.linuxtools.tmf.core.signal.TmfStartSynchSignal;
 import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
 import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment;
 import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceType;
+import org.eclipse.linuxtools.tmf.ui.viewers.ITmfViewer;
 import org.eclipse.linuxtools.tmf.ui.viewers.statistics.TmfStatisticsViewer;
 import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfStatisticsTreeNode;
 import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfStatisticsTreeRootFactory;
 import org.eclipse.linuxtools.tmf.ui.views.TmfView;
+import org.eclipse.linuxtools.tmf.ui.widgets.tabsview.TmfViewerFolder;
+import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.osgi.framework.Bundle;
+import org.eclipse.swt.widgets.Shell;
 
 /**
  * The generic Statistics View displays statistics for any kind of traces.
@@ -60,7 +50,7 @@ import org.osgi.framework.Bundle;
 public class TmfStatisticsView extends TmfView {
 
     /**
-     * The ID correspond to the package in which this class is embedded
+     * The ID corresponds to the package in which this class is embedded.
      */
     public static final String ID = "org.eclipse.linuxtools.tmf.ui.views.statistics"; //$NON-NLS-1$
 
@@ -70,77 +60,21 @@ public class TmfStatisticsView extends TmfView {
     public static final String TMF_STATISTICS_VIEW = "StatisticsView"; //$NON-NLS-1$
 
     /**
-     * Stores the request to the experiment
-     */
-    protected ITmfEventRequest fRequest = null;
-
-    /**
-     * The viewer that builds the columns to show the statistics
-     */
-    private TmfStatisticsViewer fStatsViewer;
-
-    /**
-     * The initial window span (in nanoseconds)
-     *
-     * @since 2.0
-     */
-    public static final long INITIAL_WINDOW_SPAN = (1L * 100 * 1000 * 1000); // .1sec
-
-    /**
-     * Timestamp scale (nanosecond)
+     * The viewer that builds the columns to show the statistics.
      *
      * @since 2.0
      */
-    public static final byte TIME_SCALE = -9;
+    protected final TmfViewerFolder fStatsViewers;
 
     /**
-     * Stores a reference to the parent composite of this view
-     */
-    private Composite fParent;
-
-    /**
-     * Stores a reference to the experiment
-     */
-    private TmfExperiment fExperiment;
-
-    /**
-     * Flag to force request the data from trace
+     * Flag to force request the data from trace.
      */
     protected boolean fRequestData = false;
 
     /**
-     * Default PAGE_SIZE for background requests
-     */
-    protected static final int PAGE_SIZE = 50000;
-
-    /**
-     * Stores the ranged request to the experiment
-     * @since 2.0
+     * Stores a reference to the selected experiment.
      */
-    protected ITmfEventRequest fRequestRange = null;
-
-    /**
-     * Update synchronization parameter (used for streaming): Update busy
-     * indicator
-     */
-    protected boolean fStatisticsUpdateBusy = false;
-
-    /**
-     * Update synchronization parameter (used for streaming): Update pending
-     * indicator
-     */
-    protected boolean fStatisticsUpdatePending = false;
-
-    /**
-     * Update synchronization parameter (used for streaming): Pending Update
-     * time range
-     */
-    protected TmfTimeRange fStatisticsUpdateRange = null;
-
-    /**
-     * Update synchronization object.
-     */
-    protected final Object fStatisticsUpdateSyncObj = new Object();
+    private TmfExperiment fExperiment;
 
     /**
      * Constructor of a statistics view.
@@ -149,6 +83,12 @@ public class TmfStatisticsView extends TmfView {
      */
     public TmfStatisticsView(String viewName) {
         super(viewName);
+        /*
+         * Create a fake parent for initialization purpose, than set the parent
+         * as soon as createPartControl is called.
+         */
+        Composite temporaryParent = new Shell();
+        fStatsViewers = new TmfViewerFolder(temporaryParent);
     }
 
     /**
@@ -166,7 +106,7 @@ public class TmfStatisticsView extends TmfView {
      */
     @Override
     public void createPartControl(Composite parent) {
-        fParent = parent;
+        fStatsViewers.setParent(parent);
         TmfExperiment currentExperiment = TmfExperiment.getCurrentExperiment();
         // Read current data if any available
         if (currentExperiment != null) {
@@ -176,7 +116,7 @@ public class TmfStatisticsView extends TmfView {
             experimentSelected(signal);
             return;
         }
-        fStatsViewer = createStatisticsViewer();
+        createStatisticsViewers();
         /*
          * Updates the experiment field only at the end because
          * experimentSelected signal verifies the old selected experiment to
@@ -185,26 +125,6 @@ public class TmfStatisticsView extends TmfView {
         fExperiment = currentExperiment;
     }
 
-    /**
-     * Handles the signal about disposal of the current experiment.
-     *
-     * @param signal
-     *            The disposed signal
-     */
-    @TmfSignalHandler
-    public void experimentDisposed(TmfExperimentDisposedSignal signal) {
-        if (signal.getExperiment() != TmfExperiment.getCurrentExperiment()) {
-            return;
-        }
-
-        /*
-         * Make sure there is no request running before removing the statistics
-         * tree
-         */
-        cancelOngoingRequest(fRequestRange);
-        cancelOngoingRequest(fRequest);
-    }
-
     /**
      * Handler called when an experiment is selected. Checks if the experiment
      * has changed and requests the selected experiment if it has not yet been
@@ -223,21 +143,36 @@ public class TmfStatisticsView extends TmfView {
                  * Dispose the current viewer and adapt the new one to the trace
                  * type of the experiment selected
                  */
-                if (fStatsViewer != null) {
-                    fStatsViewer.dispose();
-                }
+                fStatsViewers.clear();
                 // Update the current experiment
                 fExperiment = signal.getExperiment();
-                fStatsViewer = createStatisticsViewer();
-                fParent.layout();
-
-                String experimentName = fExperiment.getName();
-                String treeID = fStatsViewer.getTreeID(experimentName);
-
-                setInput(treeID, fExperiment.getTraces());
+                createStatisticsViewers();
+                fStatsViewers.layout();
+
+                TmfStatisticsViewer statViewer;
+                for (ITmfViewer viewer : fStatsViewers.getViewers()) {
+                    if (!(viewer instanceof TmfStatisticsViewer)) {
+                        Activator.getDefault().logError("Error - cannot cast viewer to a statistics viewer"); //$NON-NLS-1$
+                        continue;
+                    }
+                    statViewer = (TmfStatisticsViewer) viewer;
+                    setInput(statViewer, fExperiment.getTraces());
+                }
 
                 if (fRequestData) {
-                    requestData(fExperiment, fExperiment.getTimeRange());
+                    TmfExperimentRangeUpdatedSignal updateSignal = new TmfExperimentRangeUpdatedSignal(null, fExperiment, fExperiment.getTimeRange());
+                    TmfStatisticsViewer statsViewer;
+                    // Synchronizes the request to make them coalesced
+                    fExperiment.startSynch(new TmfStartSynchSignal(0));
+                    for (ITmfViewer viewer : fStatsViewers.getViewers()) {
+                        if (!(viewer instanceof TmfStatisticsViewer)) {
+                            Activator.getDefault().logError("Error - cannot cast viewer to a statistics viewer"); //$NON-NLS-1$
+                            continue;
+                        }
+                        statsViewer = (TmfStatisticsViewer) viewer;
+                        statsViewer.experimentRangeUpdated(updateSignal);
+                    }
+                    fExperiment.endSynch(new TmfEndSynchSignal(0));
                     fRequestData = false;
                 }
             }
@@ -245,16 +180,16 @@ public class TmfStatisticsView extends TmfView {
     }
 
     /**
-     * Initialize the viewer with the information received.
+     * Initializes the viewer with the information received.
      *
-     * @param treeID
-     *            The unique ID of the tree that is returned by
-     *            {@link TmfStatisticsViewer#getTreeID(String)}
+     * @param statViewer
+     *            The statistics viewer for which the input will be set
      * @param traces
-     *            The list of the traces to add in the tree.
+     *            The list of traces to add in the tree.
      * @since 2.0
      */
-    public void setInput(String treeID, ITmfTrace[] traces) {
+    public void setInput(TmfStatisticsViewer statViewer, ITmfTrace[] traces) {
+        String treeID = statViewer.getTreeID();
         if (TmfStatisticsTreeRootFactory.containsTreeRoot(treeID)) {
             // The experiment root is already present
             TmfStatisticsTreeNode experimentTreeNode = TmfStatisticsTreeRootFactory.getStatTreeRoot(treeID);
@@ -279,20 +214,16 @@ public class TmfStatisticsView extends TmfView {
 
                 if (same) {
                     // no need to reload data, all traces are already loaded
-                    fStatsViewer.setInput(experimentTreeNode);
-
-                    resetUpdateSynchronization();
+                    statViewer.setInput(experimentTreeNode);
 
                     return;
                 }
                 experimentTreeNode.reset();
             }
         } else {
-            TmfStatisticsTreeRootFactory.addStatsTreeRoot(treeID, fStatsViewer.getStatisticData());
+            TmfStatisticsTreeRootFactory.addStatsTreeRoot(treeID, statViewer.getStatisticData());
         }
 
-        resetUpdateSynchronization();
-
         TmfStatisticsTreeNode treeModelRoot = TmfStatisticsTreeRootFactory.getStatTreeRoot(treeID);
 
         // if the model has contents, clear to start over
@@ -301,80 +232,7 @@ public class TmfStatisticsView extends TmfView {
         }
 
         // set input to a clean data model
-        fStatsViewer.setInput(treeModelRoot);
-    }
-
-    /**
-     * Refresh the view.
-     *
-     * @param complete Should a pending update be sent afterwards or not
-     */
-    public void modelInputChanged(boolean complete) {
-        Control viewerControl = fStatsViewer.getControl();
-        // Ignore update if disposed
-        if (viewerControl.isDisposed()) {
-            return;
-        }
-
-        fStatsViewer.getControl().getDisplay().asyncExec(new Runnable() {
-            @Override
-            public void run() {
-                if (!fStatsViewer.getControl().isDisposed()) {
-                    fStatsViewer.refresh();
-                }
-            }
-        });
-
-        if (complete) {
-            sendPendingUpdate();
-        }
-    }
-
-    /**
-     * Called when an experiment request has failed or has been cancelled.
-     * Remove the data retrieved from the experiment from the statistics tree.
-     *
-     * @param name
-     *            The experiment name
-     */
-    public void modelIncomplete(String name) {
-        Object input = fStatsViewer.getInput();
-        if (input != null && input instanceof TmfStatisticsTreeNode) {
-            /*
-             * The data from this experiment is invalid and shall be removed to
-             * refresh upon next selection
-             */
-            TmfStatisticsTreeRootFactory.removeStatTreeRoot(fStatsViewer.getTreeID(name));
-
-            // Reset synchronization information
-            resetUpdateSynchronization();
-            modelInputChanged(false);
-        }
-        fStatsViewer.waitCursor(false);
-    }
-
-    /**
-     * Handles the signal about new experiment range.
-     *
-     * @param signal
-     *            The experiment range updated signal
-     */
-    @TmfSignalHandler
-    public void experimentRangeUpdated(TmfExperimentRangeUpdatedSignal signal) {
-        TmfExperiment experiment = signal.getExperiment();
-        // validate
-        if (!experiment.equals(TmfExperiment.getCurrentExperiment())) {
-            return;
-        }
-
-        // Calculate the selected timerange to request
-        long startTime = signal.getRange().getStartTime().normalize(0, TIME_SCALE).getValue();
-        TmfTimestamp startTS  = new TmfTimestamp(startTime, TIME_SCALE);
-        TmfTimestamp endTS    = new TmfTimestamp(startTime + INITIAL_WINDOW_SPAN, TIME_SCALE);
-        TmfTimeRange timeRange = new TmfTimeRange(startTS, endTS);
-
-        requestTimeRangeData(experiment, timeRange);
-        requestData(experiment, signal.getRange());
+        statViewer.setInput(treeModelRoot);
     }
 
     /*
@@ -385,14 +243,7 @@ public class TmfStatisticsView extends TmfView {
     @Override
     public void dispose() {
         super.dispose();
-        fStatsViewer.dispose();
-
-        /*
-         * Make sure there is no request running before removing the statistics
-         * tree.
-         */
-        cancelOngoingRequest(fRequestRange);
-        cancelOngoingRequest(fRequest);
+        fStatsViewers.dispose();
         // clean the model
         TmfStatisticsTreeRootFactory.removeAll();
     }
@@ -404,260 +255,77 @@ public class TmfStatisticsView extends TmfView {
      */
     @Override
     public void setFocus() {
-        fStatsViewer.setFocus();
+        fStatsViewers.setFocus();
     }
 
     /**
-     * Handles the experiment updated signal. This will detect new events in
-     * case the indexing is not coalesced with a statistics request.
+     * Creates the statistics viewers for all traces in the experiment and
+     * popupale a viewer folder. Each viewer is placed in a different tab and
+     * the first one is selected automatically.
      *
-     * @param signal
-     *            The experiment updated signal
+     * It uses the extension point that defines the statistics viewer to build
+     * from the trace type. If no viewer is defined, another tab won't be
+     * created, since the global viewer already contains all the basic
+     * statistics. If the experiment is empty, a global statistics viewer will
+     * still be created.
      *
-     * @since 1.1
-     */
-    @TmfSignalHandler
-    public void experimentUpdated(TmfExperimentUpdatedSignal signal) {
-        TmfExperiment experiment = signal.getExperiment();
-        if (!experiment.equals(TmfExperiment.getCurrentExperiment())) {
-            return;
-        }
-
-        int nbEvents = 0;
-        for (TmfStatisticsTreeNode node : ((TmfStatisticsTreeNode) fStatsViewer.getInput()).getChildren()) {
-            nbEvents += (int) node.getValue().getTotal();
-        }
-
-        /*
-         * In the normal case, the statistics request is coalesced with indexing
-         * and the number of events are the same, there is nothing to do. But if
-         * it's not the case, trigger a new request to count the new events.
-         */
-        if (nbEvents < experiment.getNbEvents()) {
-            requestData(experiment, experiment.getTimeRange());
-        }
-    }
-
-    /**
-     * * Handles the time range updated signal. It updates the time range
-     * statistics.
-     *
-     * @param signal
-     *            Contains the information about the new selected time range.
      * @since 2.0
      */
-    @TmfSignalHandler
-    public void timeRangeUpdated(TmfRangeSynchSignal signal) {
-        /*
-         * It is possible that the time range changes while a request is
-         * processing
-         */
-        cancelOngoingRequest(fRequestRange);
+    protected void createStatisticsViewers() {
+        // Default style for the tabs that will be created
+        int defaultStyle = SWT.NONE;
 
-        requestTimeRangeData(TmfExperiment.getCurrentExperiment(), signal.getCurrentRange());
-    }
+        // The folder composite that will contain the tabs
+        Composite folder = fStatsViewers.getParentFolder();
 
-    /**
-     * Get the statistics viewer for an experiment. If all traces in the
-     * experiment are of the same type, use the extension point specified.
-     *
-     * @return a statistics viewer of the appropriate type
-     * @since 2.0
-     */
-    protected TmfStatisticsViewer createStatisticsViewer() {
-        if (fExperiment == null) {
-            return new TmfStatisticsViewer(fParent);
-        }
-        String commonTraceType = null;
-        try {
-            /*
-             * Determine if the traces of the experiment are of the same type.
-             * If not, it uses the most generic one.
-             */
+        // Instantiation of the global viewer
+        TmfStatisticsViewer globalViewer = new TmfStatisticsViewer();
+        if (fExperiment != null) {
+            // Shows the name of the experiment in the global tab
+            globalViewer.init( folder, Messages.TmfStatisticsView_GlobalTabName + " - " + fExperiment.getName(), fExperiment); //$NON-NLS-1$
+            fStatsViewers.addTab(globalViewer, Messages.TmfStatisticsView_GlobalTabName, defaultStyle);
+
+            String traceName;
+            IResource traceResource;
+            // Creates a statistics viewer for each traces.
             for (ITmfTrace trace : fExperiment.getTraces()) {
-                IResource resource = trace.getResource();
-                if (resource == null) {
-                    return new TmfStatisticsViewer(fParent);
-                }
-                String traceType = resource.getPersistentProperty(TmfCommonConstants.TRACETYPE);
-                if (commonTraceType != null && !commonTraceType.equals(traceType)) {
-                    return new TmfStatisticsViewer(fParent);
-                }
-                commonTraceType = traceType;
-            }
-            if (commonTraceType == null) {
-                return new TmfStatisticsViewer(fParent);
-            }
-            /*
-             * Search in the configuration if there is any viewer specified for
-             * this kind of trace type.
-             */
-            for (IConfigurationElement ce : TmfTraceType.getTypeElements()) {
-                if (ce.getAttribute(TmfTraceType.ID_ATTR).equals(commonTraceType)) {
-                    IConfigurationElement[] statisticsViewerCE = ce.getChildren(TmfTraceType.STATISTICS_VIEWER_ELEM);
-                    if (statisticsViewerCE.length != 1) {
-                        break;
-                    }
-                    String statisticsViewer = statisticsViewerCE[0].getAttribute(TmfTraceType.CLASS_ATTR);
-                    if (statisticsViewer == null || statisticsViewer.length() == 0) {
-                        break;
-                    }
-                    Bundle bundle = Platform.getBundle(ce.getContributor().getName());
-                    Class<?> c = bundle.loadClass(statisticsViewer);
-                    Class<?>[] constructorArgs = new Class[] { Composite.class };
-                    Constructor<?> constructor = c.getConstructor(constructorArgs);
-                    Object[] args = new Object[] { fParent };
-                    return (TmfStatisticsViewer) constructor.newInstance(args);
+                traceName = trace.getName();
+                traceResource = trace.getResource();
+                TmfStatisticsViewer viewer = getStatisticsViewer(traceResource);
+                /*
+                 * Adds a new viewer only if there is one defined for the
+                 * selected trace type, since the global tab already contains
+                 * all the basic event counts for the trace(s)
+                 */
+                if (viewer != null) {
+                    viewer.init(folder, traceName, trace);
+                    fStatsViewers.addTab(viewer, viewer.getName(), defaultStyle);
                 }
             }
-        } catch (CoreException e) {
-            Activator.getDefault().logError("Error creating statistics viewer : cannot find the property TmfCommonConstants.TRACETYPE", e); //$NON-NLS-1$
-        } catch (ClassNotFoundException e) {
-            Activator.getDefault().logError("Error creating statistics viewer : cannot load the statistics viewer class", e); //$NON-NLS-1$
-        } catch (NoSuchMethodException e) {
-            Activator.getDefault().logError("Error creating statistics viewer : constructor of the viewer doesn't exist", e); //$NON-NLS-1$
-        } catch (InstantiationException e) {
-            Activator.getDefault().logError("Error creating statistics viewer : cannot instantiate the statistics viewer", e); //$NON-NLS-1$
-        } catch (IllegalAccessException e) {
-            Activator.getDefault().logError("Error creating statistics viewer : cannot access the constructor of the viewer", e); //$NON-NLS-1$
-        } catch (IllegalArgumentException e) {
-            Activator.getDefault().logError("Error creating statistics viewer : argument(s) sent to the constructor are illegal", e); //$NON-NLS-1$
-        } catch (InvocationTargetException e) {
-            Activator.getDefault().logError("Error creating statistics viewer : the constructor of the viewer sent an exception", e); //$NON-NLS-1$
-        }
-        return new TmfStatisticsViewer(fParent);
-    }
-
-    /**
-     * Performs the request for an experiment and populates the statistics tree
-     * with events.
-     *
-     * @param experiment
-     *            Experiment for which we need the statistics data.
-     * @param timeRange
-     *            to request
-     */
-    protected void requestData(final TmfExperiment experiment, TmfTimeRange timeRange) {
-        if (experiment != null) {
-
-            // Check if an update is already ongoing
-            if (checkUpdateBusy(timeRange)) {
-                return;
-            }
-
-            int index = 0;
-            for (TmfStatisticsTreeNode node : ((TmfStatisticsTreeNode) fStatsViewer.getInput()).getChildren()) {
-                index += (int) node.getValue().getTotal();
-            }
-
-            // Prepare the global event request
-            fRequest = new TmfStatisticsRequest(this, fStatsViewer, experiment, timeRange, index, ExecutionType.BACKGROUND, true);
-
-            experiment.sendRequest(fRequest);
-            fStatsViewer.waitCursor(true);
+        } else {
+            // There is no experiment selected. Shows an empty global tab
+            globalViewer.init(folder, Messages.TmfStatisticsView_GlobalTabName, fExperiment);
+            fStatsViewers.addTab(globalViewer, Messages.TmfStatisticsView_GlobalTabName, defaultStyle);
         }
+        // Makes the global viewer visible
+        fStatsViewers.setSelection(0);
     }
 
     /**
-     * Performs the time range request for an experiment and populates the
-     * statistics tree with events.
+     * Retrieves and instantiates a viewer based on his plug-in definition for a
+     * specific trace type. It is specific to the statistics viewer.
      *
-     * @param experiment
-     *            Experiment for which we need the statistics data.
-     * @param timeRange
-     *            To request
-     * @since 2.0
-     */
-    protected void requestTimeRangeData(final TmfExperiment experiment, TmfTimeRange timeRange) {
-        if (experiment != null) {
-            resetTimeRangeValue();
-            // Prepare the partial event request
-            fRequestRange = new TmfStatisticsRequest(this, fStatsViewer, experiment, timeRange, 0, ExecutionType.FOREGROUND, false);
-            experiment.sendRequest(fRequestRange);
-        }
-    }
-
-    /**
-     * Reset the number of events within the time range
+     * It only calls the 0-parameter constructor without performing any other
+     * initialization on the viewer.
      *
+     * @param resource
+     *            The resource where to find the information about the trace
+     *            properties
+     * @return a new statistics viewer based on his plug-in definition, or null
+     *         if no statistics definition was found for the trace type.
      * @since 2.0
      */
-    protected void resetTimeRangeValue() {
-        // Reset the number of events in the time range
-        String treeID = fStatsViewer.getTreeID(TmfExperiment.getCurrentExperiment().getName());
-        TmfStatisticsTreeNode treeModelRoot = TmfStatisticsTreeRootFactory.getStatTreeRoot(treeID);
-        if (treeModelRoot.hasChildren()) {
-            treeModelRoot.resetTimeRangeValue();
-        }
-    }
-
-    /**
-     * Return the size of the request when performing background request.
-     *
-     * @return the block size for background request.
-     */
-    protected int getIndexPageSize() {
-        return PAGE_SIZE;
-    }
-
-    /**
-     * Cancels the current ongoing request
-     *
-     * @param request
-     *            The request to be canceled
-     * @since 2.0
-     */
-    protected void cancelOngoingRequest(ITmfEventRequest request) {
-        if (request != null && !request.isCompleted()) {
-            request.cancel();
-        }
-    }
-
-    /**
-     * Reset update synchronization information
-     */
-    protected void resetUpdateSynchronization() {
-        synchronized (fStatisticsUpdateSyncObj) {
-            fStatisticsUpdateBusy = false;
-            fStatisticsUpdatePending = false;
-            fStatisticsUpdateRange = null;
-        }
-    }
-
-    /**
-     * Checks if statistic update is ongoing. If it is ongoing the new time
-     * range is stored as pending
-     *
-     * @param timeRange
-     *            - new time range
-     * @return true if statistic update is ongoing else false
-     */
-    protected boolean checkUpdateBusy(TmfTimeRange timeRange) {
-        synchronized (fStatisticsUpdateSyncObj) {
-            if (fStatisticsUpdateBusy) {
-                fStatisticsUpdatePending = true;
-                if (fStatisticsUpdateRange == null
-                        || timeRange.getEndTime().compareTo(fStatisticsUpdateRange.getEndTime()) > 0) {
-                    fStatisticsUpdateRange = timeRange;
-                }
-                return true;
-            }
-            fStatisticsUpdateBusy = true;
-            return false;
-        }
-    }
-
-    /**
-     * Sends pending request (if any)
-     */
-    protected void sendPendingUpdate() {
-        synchronized (fStatisticsUpdateSyncObj) {
-            fStatisticsUpdateBusy = false;
-            if (fStatisticsUpdatePending) {
-                fStatisticsUpdatePending = false;
-                requestData(TmfExperiment.getCurrentExperiment(), fStatisticsUpdateRange);
-                fStatisticsUpdateRange = null;
-            }
-        }
+    protected static TmfStatisticsViewer getStatisticsViewer(IResource resource) {
+        return (TmfStatisticsViewer) TmfTraceType.getTraceTypeElement(resource, TmfTraceType.STATISTICS_VIEWER_ELEM);
     }
 }
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/statistics/messages.properties b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/statistics/messages.properties
new file mode 100755 (executable)
index 0000000..43d885e
--- /dev/null
@@ -0,0 +1 @@
+TmfStatisticsView_GlobalTabName=Global
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/widgets/tabsview/TmfViewerFolder.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/widgets/tabsview/TmfViewerFolder.java
new file mode 100644 (file)
index 0000000..2b6e2b8
--- /dev/null
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *   Mathieu Denis <mathieu.denis@polymtl.ca> - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.tmf.ui.widgets.tabsview;
+
+import java.util.Collection;
+import java.util.HashMap;
+
+import org.eclipse.linuxtools.tmf.ui.viewers.ITmfViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.custom.CTabItem;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * Allows the user to create multiple tabs which makes it look like folders. It
+ * simplifies the management of the viewer contained in each tab.
+ *
+ * The indexing of the viewers is based on their name.
+ *
+ * @author Mathieu Denis
+ * @version 2.0
+ * @since 2.0
+ */
+public class TmfViewerFolder extends Composite {
+
+    /**
+     * The list of viewers in the folder
+     */
+    private final HashMap<String, ITmfViewer> fViewers;
+
+    /**
+     * The parent folder that contains all viewers
+     */
+    private CTabFolder fFolder;
+
+    /**
+     * Constructor with empty style
+     *
+     * @param parent
+     *            The parent composite
+     */
+    public TmfViewerFolder(Composite parent) {
+        this(parent, SWT.NONE);
+    }
+
+    /**
+     * Constructor
+     *
+     * @param parent
+     *            The parent composite
+     * @param style
+     *            The style of the view that will be created
+     */
+    public TmfViewerFolder(Composite parent, int style) {
+        super(parent, style);
+        setLayout(new FillLayout());
+
+        fViewers = new HashMap<String, ITmfViewer>();
+        initFolder();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.eclipse.swt.widgets.Widget#dispose()
+     */
+    @Override
+    public void dispose() {
+        super.dispose();
+        for (ITmfViewer viewer : fViewers.values()) {
+            viewer.dispose();
+        }
+        if (fFolder != null) {
+            fFolder.dispose();
+        }
+    }
+
+    /**
+     * Disposes of all the viewers contained in the folder and restart to a
+     * clean state.
+     */
+    public void clear() {
+        for (ITmfViewer viewer : fViewers.values()) {
+            viewer.dispose();
+        }
+        fViewers.clear();
+        fFolder.dispose();
+        initFolder();
+    }
+
+    /**
+     * Create a new tab that will hold the viewer content. The viewer name will
+     * be used as the name for the tab. The viewer ID must be unique and can be
+     * used to retrieve the viewer from the folder.
+     *
+     * The parent of the viewer control must be the folder returned by
+     * {@link #getParentFolder()}
+     *
+     * @param viewer
+     *            The viewer to put in the new tab
+     * @param viewerID
+     *            The ID that will be assigned to this viewer for easy
+     *            retrieving
+     * @param style
+     *            The style of the widget to build
+     * @return true on success, false otherwise
+     */
+    public boolean addTab(ITmfViewer viewer, String viewerID, int style) {
+        if (fFolder == null
+                || viewer.getControl().getParent() != fFolder
+                || fViewers.containsKey(viewerID)) {
+            return false;
+        }
+        CTabItem item = new CTabItem(fFolder, style);
+        item.setText(viewer.getName());
+        item.setControl(viewer.getControl());
+        // Register the viewer in the map to dispose it at closing time
+        fViewers.put(viewerID, viewer);
+        return true;
+    }
+
+    /**
+     * Gets the folder that will be use as the parent of tabs that will hold the
+     * viewer.
+     *
+     * In order to be able to add new tabs in this view, the parent of the
+     * viewer control has to be this composite.
+     *
+     * @return the folder composite to use as the parent for the viewer control
+     *         to create.
+     */
+    public Composite getParentFolder() {
+        return fFolder;
+    }
+
+    /**
+     * Gets a viewer based on his name.
+     *
+     * @param viewerName
+     *            The name of the viewer to find in the folder
+     * @return The viewer which name is viewerName, or null if there is no such
+     *         viewer
+     */
+    public ITmfViewer getViewer(String viewerName) {
+        return fViewers.get(viewerName);
+    }
+
+    /**
+     * Gets the viewers list contained in the folder view. The list can return
+     * the viewers in any order. It is not to be assumed that the viewers are
+     * returned in the same order as they were inserted.
+     *
+     * @return a collection of viewers contained in this view.
+     */
+    public Collection<ITmfViewer> getViewers() {
+        return fViewers.values();
+    }
+
+    /**
+     * Selects the tab at the specified index from the insertion order
+     *
+     * @param index
+     *            The index of the tab to be selected
+     * @throws SWTException
+     *             <ul>
+     *             <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+     *             </li>
+     *             <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+     *             thread that created the receiver</li>
+     *             </ul>
+     */
+    public void setSelection(int index) throws SWTException {
+        fFolder.setSelection(index);
+    }
+
+    /**
+     * Initializes the folder or put it a back to a clean state.
+     */
+    private void initFolder() {
+        if (fFolder != null) {
+            fFolder.dispose();
+        }
+        fFolder = new CTabFolder(this, SWT.LEFT | SWT.BORDER);
+        fFolder.setSimple(false);
+    }
+}
This page took 0.050338 seconds and 5 git commands to generate.