tmf: extract UpdateJob class and introduce TmfPieChartViewer
authorAlexis Cabana-Loriaux <alex021994@gmail.com>
Fri, 31 Jul 2015 22:07:24 +0000 (18:07 -0400)
committerMatthew Khouzam <matthew.khouzam@ericsson.com>
Wed, 19 Aug 2015 20:13:23 +0000 (16:13 -0400)
Change-Id: I0371ed878bce9e3121eed98141248dac80dec95d
Signed-off-by: Alexis Cabana-Loriaux <alex021994@gmail.com>
Reviewed-on: https://git.eclipse.org/r/53160
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>
17 files changed:
lttng/org.eclipse.tracecompass.lttng2.kernel.core.tests/perf/org/eclipse/tracecompass/lttng2/kernel/core/tests/perf/analysis/StatisticsAnalysisBenchmark.java
rcp/org.eclipse.tracecompass.rcp/feature.xml
rcp/org.eclipse.tracecompass.rcp/pom.xml
releng/org.eclipse.tracecompass.target/tracecompass-e4.5.target
releng/org.eclipse.tracecompass.target/tracecompass-eStaging.target
tmf/org.eclipse.tracecompass.tmf.ui/META-INF/MANIFEST.MF
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/piecharts/IPieChartViewerState.java [new file with mode: 0644]
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/piecharts/Messages.java [new file with mode: 0644]
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/piecharts/PieChartViewerStateContentSelected.java [new file with mode: 0644]
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/piecharts/PieChartViewerStateNoContentSelected.java [new file with mode: 0644]
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/piecharts/TmfPieChartViewer.java [new file with mode: 0644]
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/piecharts/messages.properties [new file with mode: 0644]
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/piecharts/model/TmfPieChartStatisticsModel.java [new file with mode: 0644]
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/statistics/Messages.java
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/statistics/StatisticsUpdateJob.java [new file with mode: 0644]
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/statistics/TmfStatisticsViewer.java
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/statistics/messages.properties

index 4e7f3788131007426567d228863d63ca76e653f6..4051051dac152a76540e9d4a909f72ead08a1a27 100644 (file)
@@ -97,7 +97,7 @@ public class StatisticsAnalysisBenchmark {
         PerformanceMeter pm = perf.createPerformanceMeter(TEST_ID + '#' + testName);
         perf.tagAsSummary(pm, "Statistics Analysis: " + testName, Dimension.CPU_TIME);
 
-        if (testTrace == CtfTmfTestTrace.DJANGO_CLIENT) {
+        if (testTrace == CtfTmfTestTrace.DJANGO_CLIENT || testTrace == CtfTmfTestTrace.DJANGO_HTTPD) {
             /* Do not show all traces in the global summary */
             perf.tagAsGlobalSummary(pm, "Statistics Analysis: " + testName, Dimension.CPU_TIME);
         }
index 923cfe8d83c80409f2e79595f904fa13b99fe20d..bd3be349c54488a2dc77f3a9629f6a7dfc74c3d7 100644 (file)
          version="0.0.0"
          unpack="false"/>
 
+   <plugin
+         id="org.eclipse.linuxtools.dataviewers.piechart"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
 </feature>
index 671ae55f64574c0a7ca81733f719f6fcc26af4b4..d3113e29441da416969040f10dae335428a29f2b 100644 (file)
@@ -69,6 +69,7 @@
                 <plugin id="org.eclipse.equinox.launcher.cocoa.macosx.x86_64"/>
                 <plugin id="org.eclipse.core.net.win32.x86"/>
                 <plugin id="org.eclipse.core.net.linux.x86"/>
+                <plugin id="org.eclipse.linuxtools.dataviewers.piechart"/>
                 <plugin id="org.eclipse.tracecompass.tracing.rcp.help"/>
                 <plugin id="org.sat4j.core"/>
                 <plugin id="org.sat4j.pb"/>
index f71ce9bd2656ea82698d2892ec410382c6ff521d..0e0c2011b814c8bfe8becdf528d176b11ca7438a 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<?pde version="3.8"?><target name="tracecompass-e4.5" sequenceNumber="52">
+<?pde version="3.8"?><target name="tracecompass-e4.5" sequenceNumber="53">
 <locations>
 <location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
 <unit id="org.eclipse.cdt.gnu.dsf.feature.group" version="0.0.0"/>
 <repository location="http://download.eclipse.org/mylyn/releases/3.16"/>
 </location>
 <location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
+<unit id="org.eclipse.linuxtools.dataviewers.feature.feature.group" version="0.0.0"/>
+<repository location="http://download.eclipse.org/linuxtools/update-4.0"/>
+</location>
+<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
 <unit id="org.eclipse.swtbot.eclipse.feature.group" version="0.0.0"/>
 <unit id="org.eclipse.swtbot.feature.group" version="0.0.0"/>
 <repository location="http://download.eclipse.org/technology/swtbot/snapshots"/>
index 05a7b29bd659bad551ea5c3cc1a3424bda064a60..bc24834d3c6375039d5f0a0d198ab4265b3b65b5 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<?pde version="3.8"?><target name="tracecompass-eStaging" sequenceNumber="45">
+<?pde version="3.8"?><target name="tracecompass-eStaging" sequenceNumber="47">
 <locations>
 <location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
 <unit id="org.eclipse.cdt.gnu.dsf.feature.group" version="0.0.0"/>
 <repository location="http://download.eclipse.org/releases/staging"/>
 </location>
 <location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
+<unit id="org.eclipse.linuxtools.dataviewers.feature.feature.group" version="0.0.0"/>
+<repository location="http://download.eclipse.org/linuxtools/update-4.0"/>
+</location>
+<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
 <unit id="org.eclipse.swtbot.eclipse.feature.group" version="0.0.0"/>
 <unit id="org.eclipse.swtbot.feature.group" version="0.0.0"/>
 <repository location="http://download.eclipse.org/technology/swtbot/snapshots"/>
index cb34f7f3675913e12151be477b83d9e56f89ffa2..b1d7a44ca7491140fb1f060faab999609e2bab67 100644 (file)
@@ -19,7 +19,8 @@ Require-Bundle: org.eclipse.core.expressions,
  org.eclipse.ui.navigator,
  org.eclipse.ui.navigator.resources,
  org.swtchart,
- com.ibm.icu
+ com.ibm.icu,
+ org.eclipse.linuxtools.dataviewers.piechart
 Export-Package: org.eclipse.tracecompass.internal.tmf.ui;x-friends:="org.eclipse.tracecompass.tmf.ui.tests,org.eclipse.tracecompass.tmf.ctf.ui.tests",
  org.eclipse.tracecompass.internal.tmf.ui.commands;x-internal:=true,
  org.eclipse.tracecompass.internal.tmf.ui.dialogs;x-internal:=true,
@@ -53,6 +54,7 @@ Export-Package: org.eclipse.tracecompass.internal.tmf.ui;x-friends:="org.eclipse
  org.eclipse.tracecompass.tmf.ui.viewers.events,
  org.eclipse.tracecompass.tmf.ui.viewers.events.columns,
  org.eclipse.tracecompass.tmf.ui.viewers.events.text,
+ org.eclipse.tracecompass.tmf.ui.viewers.piecharts,
  org.eclipse.tracecompass.tmf.ui.viewers.statistics,
  org.eclipse.tracecompass.tmf.ui.viewers.statistics.model,
  org.eclipse.tracecompass.tmf.ui.viewers.table,
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/piecharts/IPieChartViewerState.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/piecharts/IPieChartViewerState.java
new file mode 100644 (file)
index 0000000..8372986
--- /dev/null
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2015 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:
+ *   Alexis Cabana-Loriaux - Initial API and implementation
+ *
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.tmf.ui.viewers.piecharts;
+
+/**
+ * Interface used to take control of a {@link TmfPieChartViewer} as part of the
+ * State design pattern. Thus it is closely related with the TmfPieChartViewer
+ *
+ * @author Alexis Cabana-Loriaux
+ * @since 2.0
+ */
+interface IPieChartViewerState {
+
+    /**
+     * To be called when the current selection has changed
+     *
+     * @param context
+     *            The context in which to apply the changes
+     */
+    void newSelection(final TmfPieChartViewer context);
+
+    /**
+     * To be called when the current selection changes to "empty"
+     *
+     * @param context
+     *            The context in which to apply the changes
+     */
+    void newEmptySelection(final TmfPieChartViewer context);
+
+    /**
+     * To be called when there are new global entries to show
+     *
+     * @param context
+     *            The context in which to apply the changes
+     */
+    void newGlobalEntries(final TmfPieChartViewer context);
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/piecharts/Messages.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/piecharts/Messages.java
new file mode 100644 (file)
index 0000000..6256b23
--- /dev/null
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2015 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:
+ *   Alexis Cabana-Loriaux - Initial API and Implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.tmf.ui.viewers.piecharts;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Messages file for statistics view strings.
+ *
+ * @author Alexis Cabana-Loriaux
+ * @since 2.0
+ */
+public class Messages extends NLS {
+
+    private static final String BUNDLE_NAME = "org.eclipse.tracecompass.tmf.ui.viewers.piecharts.messages"; //$NON-NLS-1$
+
+    /**
+     * String shown on top of the time-range selection piechart
+     */
+    public static String TmfStatisticsView_TimeRangeSelectionPieChartName;
+
+    /**
+     * String given to the slice in the piechart containing the too little
+     * slices
+     */
+    public static String TmfStatisticsView_PieChartOthersSliceName;
+
+    /**
+     * String for the top of the global selection piechart
+     */
+    public static String TmfStatisticsView_GlobalSelectionPieChartName;
+
+    /**
+     * The string in the tooltip text of the piecharts
+     */
+    public static String TmfStatisticsView_PieChartToolTipTextName;
+
+    /**
+     * The string in the tooltip text of the piecharts
+     */
+    public static String TmfStatisticsView_PieChartToolTipTextEventCount;
+
+    static {
+        // initialize resource bundle
+        NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+    }
+
+    private Messages() {
+    }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/piecharts/PieChartViewerStateContentSelected.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/piecharts/PieChartViewerStateContentSelected.java
new file mode 100644 (file)
index 0000000..79a7dc6
--- /dev/null
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2015 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:
+ *   Alexis Cabana-Loriaux - Initial API and implementation
+ *
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.tmf.ui.viewers.piecharts;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Implementation of the IPieChartViewerState interface to represent the state
+ * of the layout when there is content currently selected.
+ *
+ * @author Alexis Cabana-Loriaux
+ * @since 2.0
+ *
+ */
+public class PieChartViewerStateContentSelected implements IPieChartViewerState {
+
+    /**
+     * Default constructor
+     *
+     * @param context
+     *            The context to apply the changes
+     */
+    public PieChartViewerStateContentSelected(final TmfPieChartViewer context) {
+        if (context.isDisposed()) {
+            return;
+        }
+
+        Display.getDefault().asyncExec(new Runnable() {
+            @Override
+            public void run() {
+                synchronized (context) {
+                    if (!context.isDisposed()) {
+                        context.updateGlobalPieChart();
+                        context.updateTimeRangeSelectionPieChart();
+                        context.getTimeRangePC().redraw();
+                        context.getGlobalPC().getLegend().setPosition(SWT.BOTTOM);
+                        context.layout();
+                    }
+                }
+            }
+        });
+
+    }
+
+    @Override
+    public void newSelection(final TmfPieChartViewer context) {
+        if (context.isDisposed()) {
+            return;
+        }
+
+        Display.getDefault().asyncExec(new Runnable() {
+            @Override
+            public void run() {
+                synchronized (context) {
+                    if (!context.isDisposed()) {
+                        context.updateTimeRangeSelectionPieChart();
+                        context.getTimeRangePC().redraw();
+                        context.layout();
+                    }
+                }
+            }
+        });
+    }
+
+    @Override
+    public void newEmptySelection(final TmfPieChartViewer context) {
+        context.setCurrentState(new PieChartViewerStateNoContentSelected(context));
+    }
+
+    @Override
+    public void newGlobalEntries(final TmfPieChartViewer context) {
+        // when new global entries, don't show the selection pie-chart anymore
+        context.setCurrentState(new PieChartViewerStateNoContentSelected(context));
+    }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/piecharts/PieChartViewerStateNoContentSelected.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/piecharts/PieChartViewerStateNoContentSelected.java
new file mode 100644 (file)
index 0000000..6658342
--- /dev/null
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2015 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:
+ *   Alexis Cabana-Loriaux - Initial API and implementation
+ *
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.tmf.ui.viewers.piecharts;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Implementation of the IPieChartViewerState interface to represent the state
+ * of the layout when there is no content currently selected.
+ *
+ * @author Alexis Cabana-Loriaux
+ * @since 2.0
+ *
+ */
+public class PieChartViewerStateNoContentSelected implements IPieChartViewerState {
+
+    /**
+     * Default constructor
+     *
+     * @param context
+     *            The current context
+     */
+    public PieChartViewerStateNoContentSelected(final TmfPieChartViewer context) {
+        if (context.isDisposed()) {
+            return;
+        }
+
+        Display.getDefault().asyncExec(new Runnable() {
+            @Override
+            public void run() {
+                synchronized (context) {
+                    if (!context.isDisposed()) {
+                        // Have to get rid of the time-range PieChart
+                        if (context.getTimeRangePC() != null) {
+                            if (!context.getTimeRangePC().isDisposed()) {
+                                context.getTimeRangePC().dispose();
+                            }
+                            context.setTimeRangePC(null);
+                        }
+
+                        context.updateGlobalPieChart();
+                        // update the global chart so it takes all the place
+                        context.getGlobalPC().getLegend().setPosition(SWT.RIGHT);
+                        context.layout();
+                    }
+                }
+            }
+        });
+    }
+
+    @Override
+    public void newSelection(final TmfPieChartViewer context) {
+        context.setCurrentState(new PieChartViewerStateContentSelected(context));
+    }
+
+    @Override
+    public void newEmptySelection(final TmfPieChartViewer context) {
+        // do nothing
+    }
+
+    @Override
+    public void newGlobalEntries(final TmfPieChartViewer context) {
+        Display.getDefault().asyncExec(new Runnable() {
+            @Override
+            public void run() {
+                synchronized (context) {
+                    if (!context.isDisposed()) {
+                        context.updateGlobalPieChart();
+                        context.getGlobalPC().redraw();
+                    }
+                }
+            }
+        });
+    }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/piecharts/TmfPieChartViewer.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/piecharts/TmfPieChartViewer.java
new file mode 100644 (file)
index 0000000..56fd643
--- /dev/null
@@ -0,0 +1,467 @@
+/*******************************************************************************
+ * Copyright (c) 2015 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:
+ *   Alexis Cabana-Loriaux - Initial API and implementation
+ *
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.tmf.ui.viewers.piecharts;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.eclipse.linuxtools.dataviewers.piechart.PieChart;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.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.
+ *
+ * @author Alexis Cabana-Loriaux
+ * @since 2.0
+ *
+ */
+public class TmfPieChartViewer extends Composite {
+
+    /**
+     * The pie chart containing global information about the trace
+     */
+    private PieChart fGlobalPC;
+
+    /**
+     * The name of the piechart containing the statistics about the global trace
+     */
+    private String fGlobalPCname;
+
+    /**
+     * The pie chart containing information about the current time-range
+     * selection
+     */
+    private PieChart fTimeRangePC;
+
+    /**
+     * The name of the piechart containing the statistics about the current
+     * selection
+     */
+    private String fTimeRangePCname;
+
+    /**
+     * The listener added to the charts every time they are created
+     */
+    private Listener fMouseListener;
+
+    /**
+     * The name of the slice containing the too little slices
+     */
+    private String fOthersSliceName;
+
+    /**
+     * Implementation of the State design pattern to reorder the layout
+     * depending on the selection. This variable holds the current state of the
+     * layout.
+     */
+    private IPieChartViewerState fCurrentState;
+
+    /**
+     * Represents the minimum percentage a slice of pie must have in order to be
+     * shown
+     */
+    private static final float MIN_PRECENTAGE_TO_SHOW_SLICE = 0.025F;// 2.5%
+
+    /**
+     * Represents the maximum number of slices of the pie charts. WE don't want
+     * to pollute the viewer with too much slice entries.
+     */
+    private static final int NB_MAX_SLICES = 10;
+
+    /**
+     * The data that has to be presented by the pie charts
+     */
+    private TmfPieChartStatisticsModel fModel = null;
+
+    /**
+     * @param parent
+     *            The parent composite that will hold the viewer
+     */
+    public TmfPieChartViewer(Composite parent) {
+        super(parent, SWT.NONE);
+        fGlobalPCname = Messages.TmfStatisticsView_GlobalSelectionPieChartName;
+        fTimeRangePCname = Messages.TmfStatisticsView_TimeRangeSelectionPieChartName;
+        fOthersSliceName = Messages.TmfStatisticsView_PieChartOthersSliceName;
+        initContent();
+    }
+
+    // ------------------------------------------------------------------------
+    // Class methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Called by this class' constructor. Constructs the basic viewer containing
+     * the charts, as well as their listeners
+     */
+    private void initContent() {
+        setLayout(new FillLayout());
+
+        fGlobalPC = null;
+        fTimeRangePC = null;
+
+        // Setup listeners for the tooltips
+        fMouseListener = new Listener() {
+            @Override
+            public void handleEvent(org.eclipse.swt.widgets.Event event) {
+                PieChart pc = (PieChart) event.widget;
+                switch (event.type) {
+                case SWT.MouseMove:
+                    int sliceIndex = pc.getSliceIndexFromPosition(0, event.x, event.y);
+                    if (sliceIndex < 0) {
+                        // mouse is outside the chart
+                        pc.setToolTipText(null);
+                        break;
+                    }
+                    float percOfSlice = (float) pc.getSlicePercent(0, sliceIndex);
+                    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$
+
+                    text +=         Messages.TmfStatisticsView_PieChartToolTipTextEventCount + " = "//$NON-NLS-1$
+                                    + nbEvents.toString() + " (" + percent + "%)"; //$NON-NLS-1$ //$NON-NLS-2$
+                    pc.setToolTipText(text);
+                    return;
+                default:
+                }
+            }
+        };
+        // at creation no content is selected
+        setCurrentState(new PieChartViewerStateNoContentSelected(this));
+    }
+
+    @Override
+    public void dispose() {
+        if (fGlobalPC != null) {
+            fGlobalPC.dispose();
+        }
+        if (fTimeRangePC != null) {
+            fTimeRangePC.dispose();
+        }
+        super.dispose();
+    }
+
+    /**
+     * Updates the data contained in the Global PieChart by using a Map.
+     * Normally, this method is only called by the state machine.
+     */
+    synchronized void updateGlobalPieChart() {
+        if (getGlobalPC() == null) {
+            fGlobalPC = new PieChart(this, SWT.NONE);
+            getGlobalPC().getTitle().setText(fGlobalPCname);
+            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);
+        } else if (getGlobalPC().isDisposed() || fModel == null || fModel.getPieChartGlobalModel() == null) {
+            return;
+        }
+
+        Map<String, Long> totalEventCountForChart = getTotalEventCountForChart(true);
+
+        if(totalEventCountForChart == null){
+            return;
+        }
+
+        updatePieChartWithData(fGlobalPC, totalEventCountForChart, MIN_PRECENTAGE_TO_SHOW_SLICE, fOthersSliceName);
+    }
+
+    /**
+     * Updates the data contained in the Time-Range PieChart by using a Map.
+     * Normally, this method is only called by the state machine.
+     */
+    synchronized void updateTimeRangeSelectionPieChart() {
+        if (getTimeRangePC() == null) {
+            fTimeRangePC = new PieChart(this, SWT.NONE);
+            getTimeRangePC().getTitle().setText(fTimeRangePCname);
+            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);
+        }
+        else if (getTimeRangePC().isDisposed()) {
+            return;
+        }
+
+        Map<String, Long> totalEventCountForChart = getTotalEventCountForChart(false);
+
+        if(totalEventCountForChart == null){
+            return;
+        }
+
+        updatePieChartWithData(fTimeRangePC, totalEventCountForChart, MIN_PRECENTAGE_TO_SHOW_SLICE, fOthersSliceName);
+    }
+
+    /* return the chart-friendly map given by the TmfPieChartStatisticsModel */
+    private Map<String,Long> getTotalEventCountForChart(boolean isGlobal){
+        if(fModel == null){
+            return null;
+        }
+        Map<ITmfTrace, Map<String, Long>> chartModel;
+        if(isGlobal){
+            chartModel = fModel.getPieChartGlobalModel();
+        } else {
+            chartModel = fModel.getPieChartSelectionModel();
+        }
+        if(chartModel == null){
+            return null;
+        }
+
+        Map<String, Long> totalEventCountForChart = new HashMap<>();
+        for(Entry<ITmfTrace, Map<String, Long>> entry : chartModel.entrySet()){
+            Map<String, Long> traceEventCount = entry.getValue();
+            if(traceEventCount == null){
+                continue;
+            }
+            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());
+                }
+            }
+        }
+
+        return totalEventCountForChart;
+    }
+
+    /**
+     * Reinitializes the charts to their initial state, without any data
+     */
+    synchronized public void reinitializeCharts() {
+        if(isDisposed()){
+            return;
+        }
+
+        if (getGlobalPC() != null && !getGlobalPC().isDisposed()) {
+            getGlobalPC().dispose();
+        }
+        fGlobalPC = new PieChart(this, SWT.NONE);
+        getGlobalPC().getTitle().setText(fGlobalPCname);
+        getGlobalPC().getAxisSet().getXAxis(0).getTitle().setText(""); //Hide the title over the legend //$NON-NLS-1$
+        if (getTimeRangePC() != null && !getTimeRangePC().isDisposed()) {
+            getTimeRangePC().dispose();
+            fTimeRangePC = null;
+        }
+        layout();
+        setCurrentState(new PieChartViewerStateNoContentSelected(this));
+    }
+
+    /**
+     * Function used to update or create the slices of a PieChart to match the
+     * content of a Map passed in parameter. It also provides a facade to use
+     * the PieChart API
+     */
+    private static void updatePieChartWithData(
+            final PieChart chart,
+            final Map<String, Long> slices,
+            final float minimumSizeOfSlice,
+            final String nameOfOthers) {
+
+        List<EventOccurrenceObject> chartValues = new ArrayList<>();
+        Long eventTotal = 0L;
+        for (Entry<String, Long> entry : slices.entrySet()) {
+            eventTotal += entry.getValue();
+            chartValues.add(new EventOccurrenceObject(entry.getKey(), entry.getValue()));
+        }
+
+        // No events in the selection
+        if (eventTotal == 0) {
+            // clear the chart and show "NO DATA"
+
+            return;
+        }
+
+        /*
+         * filter out the event types taking too little space in the chart and
+         * label the whole group together. The remaining slices will be showing
+         */
+        List<EventOccurrenceObject> filteredChartValues = new ArrayList<>();
+        Long othersEntryCount = 0L;
+        int nbSlices = 0;
+        for (EventOccurrenceObject entry : chartValues) {
+            if (entry.getNbOccurence() / eventTotal.floatValue() > minimumSizeOfSlice && nbSlices <= NB_MAX_SLICES) {
+                filteredChartValues.add(entry);
+                nbSlices++;
+            } else {
+                othersEntryCount += entry.getNbOccurence();
+            }
+        }
+
+        Collections.sort(filteredChartValues);
+
+        // Add the "Others" slice in the pie if its not empty
+        if (othersEntryCount != 0) {
+            filteredChartValues.add(new EventOccurrenceObject(nameOfOthers, othersEntryCount));
+        }
+
+        // put the entries in the chart and add their percentage
+        double[][] tempValues = new double[filteredChartValues.size()][1];
+        String[] tempNames = new String[filteredChartValues.size()];
+        int index = 0;
+        for (EventOccurrenceObject entry : filteredChartValues) {
+            tempValues[index][0] = entry.getNbOccurence();
+            tempNames[index] = entry.getName();
+            index++;
+        }
+
+        chart.addPieChartSeries(tempNames, tempValues);
+    }
+
+    /**
+     * Refresh this viewer
+     * @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){
+            reinitializeCharts();
+        } else {
+            if(refreshGlobal){
+                /* will update the global pc */
+                getCurrentState().newGlobalEntries(this);
+            }
+
+            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){
+                        nbEventsType++;
+                    }
+                }
+
+                // Check if the selection is empty or if
+                // there is enough event types to show in the piecharts
+                if (nbEventsType < 2) {
+                    getCurrentState().newEmptySelection(this);
+                } else {
+                    getCurrentState().newSelection(this);
+                }
+            }
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Getters
+    // ------------------------------------------------------------------------
+
+    /**
+     * @return the global piechart
+     */
+    synchronized PieChart getGlobalPC() {
+        return fGlobalPC;
+    }
+
+    /**
+     * @return the time-range selection piechart
+     */
+    synchronized PieChart getTimeRangePC() {
+        return fTimeRangePC;
+    }
+
+    /**
+     * @return the current state of the viewer
+     */
+    synchronized IPieChartViewerState getCurrentState() {
+        return fCurrentState;
+    }
+
+    // ------------------------------------------------------------------------
+    // Setters
+    // ------------------------------------------------------------------------
+
+    /**
+     * @return the model
+     */
+    public TmfPieChartStatisticsModel getModel() {
+        return fModel;
+    }
+
+    /**
+     * @param model the model to set
+     */
+    public void setInput(TmfPieChartStatisticsModel model) {
+        fModel = model;
+    }
+
+    /**
+     * Normally, this method is only called by the state machine
+     *
+     * @param newChart
+     *            the new PieChart
+     */
+    public synchronized void setTimeRangePC(PieChart newChart) {
+        fTimeRangePC = newChart;
+    }
+
+    /**
+     * Setter method for the state.
+     *
+     * @param newState
+     *            The new state of the viewer Normally only called by classes
+     *            implementing the IPieChartViewerState interface.
+     */
+    public synchronized void setCurrentState(final IPieChartViewerState newState) {
+        fCurrentState = newState;
+    }
+
+    /**
+     * Nested class used to handle and sort more easily the pair (Name, Number
+     * of occurrences)
+     *
+     * @author Alexis Cabana-Loriaux
+     */
+    private static class EventOccurrenceObject implements Comparable<EventOccurrenceObject> {
+
+        private String fName;
+
+        private Long fNbOccurrences;
+
+        EventOccurrenceObject(String name, Long nbOccurences) {
+            this.fName = name;
+            this.fNbOccurrences = nbOccurences;
+        }
+
+        @Override
+        public int compareTo(EventOccurrenceObject other) {
+            // descending order
+            return -Long.compare(this.getNbOccurence(), other.getNbOccurence());
+        }
+
+        public String getName() {
+            return fName;
+        }
+
+        public Long getNbOccurence() {
+            return fNbOccurrences;
+        }
+    }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/piecharts/messages.properties b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/piecharts/messages.properties
new file mode 100644 (file)
index 0000000..ef7a127
--- /dev/null
@@ -0,0 +1,17 @@
+###############################################################################
+# Copyright (c) 2015 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:
+#     Ericsson - Initial API and implementation
+###############################################################################
+
+TmfStatisticsView_GlobalSelectionPieChartName=Global
+TmfStatisticsView_TimeRangeSelectionPieChartName=Events in selection
+TmfStatisticsView_PieChartOthersSliceName=Others
+TmfStatisticsView_PieChartToolTipTextName=Name
+TmfStatisticsView_PieChartToolTipTextEventCount=Event Count
\ No newline at end of file
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/piecharts/model/TmfPieChartStatisticsModel.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/piecharts/model/TmfPieChartStatisticsModel.java
new file mode 100644 (file)
index 0000000..f0a3e07
--- /dev/null
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2015 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:
+ *   Alexis Cabana-Loriaux - Initial API and implementation
+ *
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.tmf.ui.viewers.piecharts.model;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.ui.viewers.piecharts.TmfPieChartViewer;
+
+/**
+ * This class contains the model shown by the {@link TmfPieChartViewer}.
+ *
+ * @author Alexis Cabana-Loriaux
+ * @since 2.0
+ */
+public class TmfPieChartStatisticsModel {
+
+    /**
+     * The model for the PieChart viewer. For each chart, a trace has a group of
+     * events and an associated count
+     */
+    private final Map<ITmfTrace, Map<String, Long>> fPieChartGlobalModel = new ConcurrentHashMap<>();
+    private final Map<ITmfTrace, Map<String, Long>> fPieChartSelectionModel = new ConcurrentHashMap<>();
+
+    /**
+     * Default constructor
+     */
+    public TmfPieChartStatisticsModel() {
+    }
+
+    // ------------------------------------------------------------------------
+    // Class Methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Clean out the entire model
+     */
+    public void clear() {
+        fPieChartGlobalModel.clear();
+        fPieChartSelectionModel.clear();
+    }
+
+    // ------------------------------------------------------------------------
+    // Getters and setter
+    // ------------------------------------------------------------------------
+
+    /**
+     * @return the model to be applied to the global piechart
+     */
+    public Map<ITmfTrace, Map<String, Long>> getPieChartGlobalModel() {
+        return fPieChartGlobalModel;
+    }
+
+    /**
+     * @return the model to be applied to the global piechart
+     */
+    public Map<ITmfTrace, Map<String, Long>> getPieChartSelectionModel() {
+        return fPieChartSelectionModel;
+    }
+
+    /**
+     * Method used to set the model of one of the pie chart
+     *
+     * @param isGlobal if the model to update is global or selection piechart
+     * @param jobTrace the trace
+     * @param eventsPerType the map with pairs (Event, count)
+     */
+    public void setPieChartTypeCount(boolean isGlobal, ITmfTrace jobTrace, Map<String, Long> eventsPerType) {
+        Map<ITmfTrace,Map<String, Long>> chartModel;
+        if(isGlobal){
+            chartModel = fPieChartGlobalModel;
+        } else {
+            chartModel = fPieChartSelectionModel;
+        }
+
+        chartModel.put(jobTrace, eventsPerType);
+    }
+}
index e5e873bd0d49b237d0027ce658d904d5934ec53c..d4e06fcf30a4f4f6cb4ebe4adaa7bfe8f89a3dfc 100644 (file)
@@ -28,6 +28,26 @@ public class Messages extends NLS {
      */
     public static String TmfStatisticsView_UnknownTraceName;
 
+    /**
+     * String shown on top of the time-range selection piechart
+     *
+     * @since 2.0
+     */
+    public static String TmfStatisticsView_TimeRangeSelectionPieChartName;
+
+    /**
+     * String given to the slice in the piechart containing the too little
+     * slices
+     * @since 2.0
+     */
+    public static String TmfStatisticsView_PieChartOthersSliceName;
+
+    /**
+     * String for the top of the global selection piechart
+     * @since 2.0
+     */
+    public static String TmfStatisticsView_GlobalSelectionPieChartName;
+
     static {
         // initialize resource bundle
         NLS.initializeMessages(BUNDLE_NAME, Messages.class);
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/statistics/StatisticsUpdateJob.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/statistics/StatisticsUpdateJob.java
new file mode 100644 (file)
index 0000000..a5ac06c
--- /dev/null
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * Copyright (c) 2015 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 - Initial API and implementation
+ *   Alexis Cabana-Loriaux - Extract the class in a compilation unit
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.tmf.ui.viewers.statistics;
+
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
+import org.eclipse.tracecompass.tmf.core.statistics.ITmfStatistics;
+import org.eclipse.tracecompass.tmf.core.statistics.TmfStatisticsEventTypesModule;
+import org.eclipse.tracecompass.tmf.core.statistics.TmfStatisticsModule;
+import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
+import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.ui.viewers.piecharts.model.TmfPieChartStatisticsModel;
+import org.eclipse.tracecompass.tmf.ui.viewers.statistics.model.TmfStatisticsTree;
+import org.eclipse.tracecompass.tmf.ui.viewers.statistics.model.TmfStatisticsTreeManager;
+
+/**
+ * Class used to update the Statistics view. Normally, it should only be used by
+ * this class
+ *
+ * @author Mathieu Denis
+ */
+class StatisticsUpdateJob extends Job {
+
+    private final ITmfTrace fJobTrace;
+    private final boolean fIsGlobal;
+    private final TmfStatisticsModule fStatsMod;
+    private final TmfStatisticsViewer fViewer;
+
+    /**
+     * The delay (in ms) between each update in live-reading mode
+     */
+    private static final long LIVE_UPDATE_DELAY = 1000;
+
+    /**
+     * Timestamp scale used for all statistics (nanosecond)
+     */
+    private static final byte TIME_SCALE = ITmfTimestamp.NANOSECOND_SCALE;
+    private TmfTimeRange fTimerange;
+
+    /**
+     * @param name
+     *            The name of the working job
+     * @param trace
+     *            The trace to query
+     * @param isGlobal
+     *            If the query is for the global time-range or a selection
+     *            time-range
+     * @param timerange
+     *            The timerange of
+     * @param statsMod
+     *            The statistics module of the trace
+     * @param viewer
+     *            The viewer to update
+     */
+    public StatisticsUpdateJob(String name, ITmfTrace trace, boolean isGlobal, TmfTimeRange timerange, TmfStatisticsModule statsMod, TmfStatisticsViewer viewer) {
+        super(name);
+        fJobTrace = trace;
+        fIsGlobal = isGlobal;
+        fTimerange = timerange;
+        fStatsMod = statsMod;
+        fViewer = viewer;
+    }
+
+    @Override
+    protected IStatus run(IProgressMonitor monitor) {
+
+        /* Wait until the analysis is ready to be queried */
+        fStatsMod.waitForInitialization();
+        ITmfStatistics stats = fStatsMod.getStatistics();
+        if (stats == null) {
+            /* It should have worked, but didn't */
+            throw new IllegalStateException();
+        }
+
+        /*
+         * TODO Eventually this could be exposed through the
+         * TmfStateSystemAnalysisModule directly.
+         */
+        ITmfStateSystem ss = fStatsMod.getStateSystem(TmfStatisticsEventTypesModule.ID);
+        if (ss == null) {
+            /*
+             * It should be instantiated after the
+             * statsMod.waitForInitialization() above.
+             */
+            throw new IllegalStateException();
+        }
+
+        /*
+         * Periodically update the statistics while they are being built (or, if
+         * the back-end is already completely built, it will skip over the
+         * while() immediately.
+         */
+        long start = 0;
+        long end = 0;
+        boolean finished = false;
+        do {
+            /* This model update is done every second */
+            if (monitor.isCanceled()) {
+                fViewer.removeFromJobs(fIsGlobal, fJobTrace);
+                return Status.CANCEL_STATUS;
+            }
+            finished = ss.waitUntilBuilt(LIVE_UPDATE_DELAY);
+            TmfTimeRange localtimeRange = fTimerange;
+            /*
+             * The generic statistics are stored in nanoseconds, so we must make
+             * sure the time range is scaled correctly.
+             */
+            start = localtimeRange.getStartTime().normalize(0, TIME_SCALE).getValue();
+            end = localtimeRange.getEndTime().normalize(0, TIME_SCALE).getValue();
+
+            Map<String, Long> map = stats.getEventTypesInRange(start, end);
+            updateStats(map);
+        } while (!finished);
+
+        /* Query one last time for the final values */
+        Map<String, Long> map = stats.getEventTypesInRange(start, end);
+        updateStats(map);
+        fViewer.refreshPieCharts(fIsGlobal, !fIsGlobal);
+        /*
+         * Remove job from map so that new range selection updates can be
+         * processed.
+         */
+        fViewer.removeFromJobs(fIsGlobal, fJobTrace);
+        return Status.OK_STATUS;
+    }
+
+    /*
+     * Update the tree for a given trace
+     */
+    private void updateStats(Map<String, Long> eventsPerType) {
+
+        final TmfStatisticsTree statsData = TmfStatisticsTreeManager.getStatTree(fViewer.getTreeID());
+        if (statsData == null) {
+            /* The stat tree has been disposed, abort mission. */
+            return;
+        }
+
+        Map<String, Long> map = eventsPerType;
+        String name = fJobTrace.getName();
+
+        /**
+         * <pre>
+         * "Global", "partial", "total", etc., it's all very confusing...
+         *
+         * The base view shows the total count for the trace and for
+         * each even types, organized in columns like this:
+         *
+         *                   |  Global  |  Time range |
+         * trace name        |    A     |      B      |
+         *    Event Type     |          |             |
+         *       <event 1>   |    C     |      D      |
+         *       <event 2>   |   ...    |     ...     |
+         *         ...       |          |             |
+         *
+         * Here, we called the cells like this:
+         *  A : GlobalTotal
+         *  B : TimeRangeTotal
+         *  C : GlobalTypeCount(s)
+         *  D : TimeRangeTypeCount(s)
+         * </pre>
+         */
+
+        /* Fill in an the event counts (either cells C or D) */
+        for (Map.Entry<String, Long> entry : map.entrySet()) {
+            statsData.setTypeCount(name, entry.getKey(), fIsGlobal, entry.getValue());
+        }
+
+        /*
+         * Calculate the totals (cell A or B, depending if isGlobal). We will
+         * use the results of the previous request instead of sending another
+         * one.
+         */
+        long globalTotal = 0;
+        for (long val : map.values()) {
+            globalTotal += val;
+        }
+        /* Update both the tree model and the piechart model */
+        statsData.setTotal(name, fIsGlobal, globalTotal);
+        TmfPieChartStatisticsModel model = fViewer.getPieChartModel();
+        if (model != null) {
+            model.setPieChartTypeCount(fIsGlobal, fJobTrace, eventsPerType);
+        }
+        /* notify that the viewer needs to be refreshed */
+        fViewer.modelComplete(fIsGlobal);
+    }
+}
index cf6963845476f51b01792ac2f9a85c6b6ef6d2ae..2293b374cd3925880fd557885605c6b577b07606 100644 (file)
@@ -22,15 +22,13 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
 import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.jface.viewers.TreeViewer;
 import org.eclipse.jface.viewers.TreeViewerColumn;
 import org.eclipse.jface.viewers.Viewer;
 import org.eclipse.jface.viewers.ViewerComparator;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.SashForm;
 import org.eclipse.swt.events.SelectionAdapter;
 import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.graphics.Color;
@@ -40,14 +38,11 @@ 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.statesystem.core.ITmfStateSystem;
 import org.eclipse.tracecompass.tmf.core.component.TmfComponent;
 import org.eclipse.tracecompass.tmf.core.request.ITmfEventRequest;
-import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
 import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceRangeUpdatedSignal;
-import org.eclipse.tracecompass.tmf.core.statistics.ITmfStatistics;
-import org.eclipse.tracecompass.tmf.core.statistics.TmfStatisticsEventTypesModule;
 import org.eclipse.tracecompass.tmf.core.statistics.TmfStatisticsModule;
 import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
@@ -56,8 +51,9 @@ 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.tmf.ui.viewers.piecharts.TmfPieChartViewer;
+import org.eclipse.tracecompass.tmf.ui.viewers.piecharts.model.TmfPieChartStatisticsModel;
 import org.eclipse.tracecompass.tmf.ui.viewers.statistics.model.TmfBaseColumnData;
 import org.eclipse.tracecompass.tmf.ui.viewers.statistics.model.TmfBaseColumnDataProvider;
 import org.eclipse.tracecompass.tmf.ui.viewers.statistics.model.TmfStatisticsFormatter;
@@ -75,21 +71,15 @@ import org.eclipse.tracecompass.tmf.ui.viewers.statistics.model.TmfTreeContentPr
  */
 public class TmfStatisticsViewer extends TmfViewer {
 
-    /** Timestamp scale used for all statistics (nanosecond) */
-    private static final byte TIME_SCALE = ITmfTimestamp.NANOSECOND_SCALE;
-
-    /** The delay (in ms) between each update in live-reading mode */
-    private static final long LIVE_UPDATE_DELAY = 1000;
-
     /** The actual tree viewer to display */
     private TreeViewer fTreeViewer;
 
-    /** The statistics tree linked to this viewer */
-    private TmfStatisticsTree fStatisticsData;
-
     /** Update range synchronization object */
     private final Object fStatisticsRangeUpdateSyncObj = new Object();
 
+    /** The statistics tree linked to this viewer */
+    private TmfStatisticsTree fStatisticsData;
+
     /** The trace that is displayed by this viewer */
     private ITmfTrace fTrace;
 
@@ -118,9 +108,11 @@ public class TmfStatisticsViewer extends TmfViewer {
     private final Map<ITmfTrace, Job> fUpdateJobsPartial = new HashMap<>();
     private final Map<ITmfTrace, Job> fUpdateJobsGlobal = new HashMap<>();
 
-    private TmfTimeRange fTimeRange;
+    private TmfPieChartViewer fPieChartViewer;
+
+    private SashForm fSash;
 
-    private TmfTimeRange fTimeRangePartial;
+    private TmfPieChartStatisticsModel fPieChartModel;
 
     /**
      * Create a basic statistics viewer. To be used in conjunction with
@@ -179,6 +171,7 @@ public class TmfStatisticsViewer extends TmfViewer {
 
         // Clean the model for this viewer
         TmfStatisticsTreeManager.removeStatTreeRoot(getTreeID());
+        fPieChartViewer.reinitializeCharts();
     }
 
     // ------------------------------------------------------------------------
@@ -242,7 +235,7 @@ public class TmfStatisticsViewer extends TmfViewer {
      */
     @Override
     public Control getControl() {
-        return fTreeViewer.getControl();
+        return fSash;
     }
 
     /**
@@ -267,6 +260,17 @@ public class TmfStatisticsViewer extends TmfViewer {
         return fStatisticsData;
     }
 
+    /**
+     * @return the model of the piecharts in this viewer
+     * @since 2.0
+     */
+    public TmfPieChartStatisticsModel getPieChartModel(){
+        if (fPieChartModel == null) {
+            fPieChartModel = new TmfPieChartStatisticsModel();
+         }
+         return fPieChartModel;
+    }
+
     /**
      * 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.
@@ -284,8 +288,21 @@ public class TmfStatisticsViewer extends TmfViewer {
         if (viewerControl.isDisposed()) {
             return;
         }
+        refreshTree();
+        refreshPieCharts(true, true);
+    }
+
+    /**
+     * Only refreshes the Tree viewer
+     */
+    private void refreshTree(){
+        final Control viewerControl = getControl();
+        // Ignore update if disposed
+        if (viewerControl.isDisposed()) {
+            return;
+        }
 
-        TmfUiRefreshHandler.getInstance().queueUpdate(this, new Runnable() {
+        Display.getDefault().asyncExec(new Runnable() {
             @Override
             public void run() {
                 if (!viewerControl.isDisposed()) {
@@ -295,6 +312,29 @@ public class TmfStatisticsViewer extends TmfViewer {
         });
     }
 
+    /**
+     * Only refreshes the piecharts depending on the parameters
+     * @param refreshGlobal if we have to refresh the global piechart
+     * @param refreshSelection if we have to refresh the selection piechart
+     * @since 2.0
+     */
+    protected void refreshPieCharts(final boolean refreshGlobal, final boolean refreshSelection) {
+        final Control viewerControl = getControl();
+        // Ignore update if disposed
+        if (viewerControl.isDisposed()) {
+            return;
+        }
+
+        Display.getDefault().asyncExec(new Runnable() {
+            @Override
+            public void run() {
+                if (!viewerControl.isDisposed()) {
+                    fPieChartViewer.refresh(refreshGlobal, refreshSelection);
+                }
+            }
+        });
+    }
+
     /**
      * Will force a request on the partial event count if one is needed.
      */
@@ -340,9 +380,15 @@ public class TmfStatisticsViewer extends TmfViewer {
      *            The parent of the control to create
      */
     protected void initContent(Composite parent) {
+
         final List<TmfBaseColumnData> columnDataList = getColumnDataProvider().getColumnData();
 
-        fTreeViewer = new TreeViewer(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
+        fSash = new SashForm(parent, SWT.HORIZONTAL );
+
+        fTreeViewer = new TreeViewer(fSash, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
+        fPieChartViewer = new TmfPieChartViewer(fSash);
+        fSash.setWeights(new int[]{100,100});
+
         fTreeViewer.setContentProvider(new TmfTreeContentProvider());
         fTreeViewer.getTree().setHeaderVisible(true);
         fTreeViewer.setUseHashlookup(true);
@@ -532,6 +578,8 @@ public class TmfStatisticsViewer extends TmfViewer {
 
         // Sets the input to a clean data model
         fTreeViewer.setInput(statisticsTreeNode);
+        /* Set a new model for the piecharts and keep a reference */
+        fPieChartViewer.setInput(getPieChartModel());
     }
 
     /**
@@ -556,27 +604,7 @@ public class TmfStatisticsViewer extends TmfViewer {
      *            request.
      */
     protected void modelComplete(boolean global) {
-        refresh();
-        waitCursor(false);
-    }
-
-    /**
-     * Called when an trace request has failed or has been cancelled.
-     *
-     * @param isGlobalRequest
-     *            Tells if the request is a global or time range (partial)
-     *            request.
-     */
-    protected void modelIncomplete(boolean isGlobalRequest) {
-        if (isGlobalRequest) { // Clean the global statistics
-            /*
-             * No need to reset the global number of events, since the index of
-             * the last requested event is known.
-             */
-        } else { // Clean the partial statistics
-            resetTimeRangeValue();
-        }
-        refresh();
+        refreshTree();
         waitCursor(false);
     }
 
@@ -629,10 +657,8 @@ public class TmfStatisticsViewer extends TmfViewer {
         Map<ITmfTrace, Job> updateJobs;
         if (isGlobal) {
             updateJobs = fUpdateJobsGlobal;
-            fTimeRange = timeRange;
         } else {
             updateJobs = fUpdateJobsPartial;
-            fTimeRangePartial = timeRange;
         }
 
         for (ITmfTrace aTrace : TmfTraceManager.getTraceSet(trace)) {
@@ -650,7 +676,7 @@ public class TmfStatisticsViewer extends TmfViewer {
 
             Job job = updateJobs.get(aTrace);
             if (job == null) {
-                job = new UpdateJob("Statistics update", aTrace, isGlobal, statsMod); //$NON-NLS-1$
+                job = new StatisticsUpdateJob("Statistics update", aTrace, isGlobal, timeRange, statsMod, this); //$NON-NLS-1$
                 updateJobs.put(aTrace, job);
                 job.setSystem(true);
                 job.schedule();
@@ -658,141 +684,6 @@ public class TmfStatisticsViewer extends TmfViewer {
         }
     }
 
-    private class UpdateJob extends Job {
-
-        private final ITmfTrace fJobTrace;
-        private final boolean fIsGlobal;
-        private final TmfStatisticsModule fStatsMod;
-
-        private UpdateJob(String name, ITmfTrace trace, boolean isGlobal, TmfStatisticsModule statsMod) {
-            super(name);
-            fJobTrace = trace;
-            fIsGlobal = isGlobal;
-            fStatsMod = statsMod;
-        }
-
-        @Override
-        protected IStatus run(IProgressMonitor monitor) {
-
-            /* Wait until the analysis is ready to be queried */
-            fStatsMod.waitForInitialization();
-            ITmfStatistics stats = fStatsMod.getStatistics();
-            if (stats == null) {
-                /* It should have worked, but didn't */
-                throw new IllegalStateException();
-            }
-
-            /*
-             * TODO Eventually this could be exposed through the
-             * TmfStateSystemAnalysisModule directly.
-             */
-            ITmfStateSystem ss = fStatsMod.getStateSystem(TmfStatisticsEventTypesModule.ID);
-            if (ss == null) {
-                /* It should be instantiated after the
-                 * statsMod.waitForInitialization() above. */
-                throw new IllegalStateException();
-            }
-
-
-            /*
-             * Periodically update the statistics while they are
-             * being built (or, if the back-end is already completely
-             * built, it will skip over the while() immediately.
-             */
-            long start = 0;
-            long end = 0;
-            boolean finished = false;
-            do {
-                if (monitor.isCanceled()) {
-                    return Status.CANCEL_STATUS;
-                }
-                finished = ss.waitUntilBuilt(LIVE_UPDATE_DELAY);
-
-                TmfTimeRange localtimeRange = fIsGlobal ? fTimeRange : fTimeRangePartial;
-                /*
-                 * The generic statistics are stored in nanoseconds, so
-                 * we must make sure the time range is scaled correctly.
-                 */
-                start = localtimeRange.getStartTime().normalize(0, TIME_SCALE).getValue();
-                end = localtimeRange.getEndTime().normalize(0, TIME_SCALE).getValue();
-
-                Map<String, Long> map = stats.getEventTypesInRange(start, end);
-                updateStats(map);
-            } while (!finished);
-
-            /* Query one last time for the final values */
-            Map<String, Long> map = stats.getEventTypesInRange(start, end);
-            updateStats(map);
-
-            /*
-             * Remove job from map so that new range selection updates can
-             * be processed.
-             */
-            Map<ITmfTrace, Job> updateJobs;
-            if (fIsGlobal) {
-                updateJobs = fUpdateJobsGlobal;
-            } else {
-                updateJobs = fUpdateJobsPartial;
-            }
-            updateJobs.remove(fJobTrace);
-            return Status.OK_STATUS;
-        }
-
-        /*
-         * Update statistics for a given trace
-         */
-        private void updateStats(Map<String, Long> eventsPerType) {
-
-            final TmfStatisticsTree statsData = TmfStatisticsTreeManager.getStatTree(getTreeID());
-            if (statsData == null) {
-                /* The stat tree has been disposed, abort mission. */
-                return;
-            }
-
-            Map<String, Long> map = eventsPerType;
-            String name = fJobTrace.getName();
-
-
-            /*
-             * "Global", "partial", "total", etc., it's all very confusing...
-             *
-             * The base view shows the total count for the trace and for
-             * each even types, organized in columns like this:
-             *
-             *                   |  Global  |  Time range |
-             * trace name        |    A     |      B      |
-             *    Event Type     |          |             |
-             *       <event 1>   |    C     |      D      |
-             *       <event 2>   |   ...    |     ...     |
-             *         ...       |          |             |
-             *
-             * Here, we called the cells like this:
-             *  A : GlobalTotal
-             *  B : TimeRangeTotal
-             *  C : GlobalTypeCount(s)
-             *  D : TimeRangeTypeCount(s)
-             */
-
-            /* Fill in an the event counts (either cells C or D) */
-            for (Map.Entry<String, Long> entry : map.entrySet()) {
-                statsData.setTypeCount(name, entry.getKey(), fIsGlobal, entry.getValue());
-            }
-
-            /*
-             * Calculate the totals (cell A or B, depending if isGlobal). We will
-             * use the results of the previous request instead of sending another
-             * one.
-             */
-            long globalTotal = 0;
-            for (long val : map.values()) {
-                globalTotal += val;
-            }
-            statsData.setTotal(name, fIsGlobal, globalTotal);
-
-            modelComplete(fIsGlobal);
-        }
-    }
-
     /**
      * Resets the number of events within the time range
      */
@@ -855,4 +746,16 @@ public class TmfStatisticsViewer extends TmfViewer {
             });
         }
     }
+
+    /**
+     * @param isGlobal if the job to remove is global or partial
+     * @param jobTrace The trace
+     */
+    void removeFromJobs(boolean isGlobal, ITmfTrace jobTrace) {
+        Map<ITmfTrace, Job> updateJobs = isGlobal ? fUpdateJobsGlobal : fUpdateJobsPartial;
+        Job job = updateJobs.remove(jobTrace);
+        if (job != null) {
+            job.cancel();
+        }
+    }
 }
index 47b85cb874e3ac0a42c617734417e137060758b3..041877d18a7934f7611c3b853d4e0efc6245cbf1 100644 (file)
@@ -10,4 +10,4 @@
 #     Ericsson - Initial API and implementation
 ###############################################################################
 
-TmfStatisticsView_UnknownTraceName=Unknown_Trace
\ No newline at end of file
+TmfStatisticsView_UnknownTraceName=Unknown_Trace
This page took 0.04447 seconds and 5 git commands to generate.