lami.ui: Replace LAMI charts with custom charts
authorGabriel-Andrew Pollo-Guilbert <gabrielpolloguilbert@gmail.com>
Wed, 27 Jul 2016 17:43:42 +0000 (13:43 -0400)
committerGenevieve Bastien <gbastien+lttng@versatic.net>
Fri, 10 Mar 2017 14:58:38 +0000 (09:58 -0500)
This patch makes the LAMI analyses use the new chart
plugin instead of their own charts.

Change-Id: Ic0bf607a68b7057b365ae2f40bb40f96895cfbaf
Signed-off-by: Gabriel-Andrew Pollo-Guilbert <gabrielpolloguilbert@gmail.com>
Signed-off-by: Geneviève Bastien <gbastien+lttng@versatic.net>
Reviewed-on: https://git.eclipse.org/r/78012
Reviewed-by: Hudson CI
16 files changed:
analysis/org.eclipse.tracecompass.analysis.lami.core/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/core/module/LamiChartModel.java
analysis/org.eclipse.tracecompass.analysis.lami.ui/META-INF/MANIFEST.MF
analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/LamiBarChartViewer.java
analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/LamiScatterViewer.java
analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/LamiTableViewer.java
analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/LamiReportView.java
analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/LamiReportViewTabPage.java
analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/LamiSeriesDialog.java
analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/LamiViewerControl.java
analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/Messages.java
analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/messages.properties
tmf/org.eclipse.tracecompass.tmf.chart.core/META-INF/MANIFEST.MF
tmf/org.eclipse.tracecompass.tmf.chart.ui/META-INF/MANIFEST.MF
tmf/org.eclipse.tracecompass.tmf.chart.ui/src/org/eclipse/tracecompass/internal/provisional/tmf/chart/ui/dialog/ChartMakerDialog.java
tmf/org.eclipse.tracecompass.tmf.chart.ui/src/org/eclipse/tracecompass/internal/tmf/chart/ui/data/ChartRangeMap.java
tmf/org.eclipse.tracecompass.tmf.chart.ui/src/org/eclipse/tracecompass/internal/tmf/chart/ui/dialog/messages.properties

index c6cba4071ea04420ef8583db7fc514d33b483c8d..3c1933893fc1e27c5000421599529c26b3a307f7 100644 (file)
@@ -25,7 +25,7 @@ public class LamiChartModel {
     /**
      * Supported types of charts
      */
-    public enum ChartType {
+    public enum LamiChartType {
         /** Bar chart */
         BAR_CHART("Bar"), //$NON-NLS-1$
 
@@ -40,7 +40,7 @@ public class LamiChartModel {
 
         private final String fText;
 
-        private ChartType(final String text) {
+        private LamiChartType(final String text) {
              fText = text;
         }
 
@@ -50,7 +50,7 @@ public class LamiChartModel {
         }
     }
 
-    private final ChartType fType;
+    private final LamiChartType fType;
     private final String fName;
     private final List<String> fXSeriesColumns;
     private final List<String> fYSeriesColumns;
@@ -74,7 +74,7 @@ public class LamiChartModel {
      * @param yAxisIsLog
      *            If the Y-axis is log scale or not
      */
-    public LamiChartModel(ChartType type, String name, List<String> xSeriesColumn, List<String> ySeriesColumns,
+    public LamiChartModel(LamiChartType type, String name, List<String> xSeriesColumn, List<String> ySeriesColumns,
             boolean xAxisIsLog, boolean yAxisIsLog) {
         fType = type;
         fName = name;
@@ -89,7 +89,7 @@ public class LamiChartModel {
      *
      * @return The chart type
      */
-    public ChartType getChartType() {
+    public LamiChartType getChartType() {
         return fType;
     }
 
index a8afd45142cfda559c2b55cc554c1432ab6a632d..472ebddd257330bf2aa97913b0fd3b83fdc80b23 100644 (file)
@@ -16,7 +16,8 @@ Require-Bundle: org.eclipse.ui,
  org.eclipse.tracecompass.tmf.core,
  org.eclipse.tracecompass.tmf.ui,
  org.eclipse.tracecompass.analysis.lami.core,
- org.eclipse.tracecompass.tmf.chart.core
+ org.eclipse.tracecompass.tmf.chart.core,
+ org.eclipse.tracecompass.tmf.chart.ui
 Export-Package: org.eclipse.tracecompass.internal.analysis.lami.ui;x-internal:=true,
  org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.format;x-internal:=true,
  org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.handler;x-internal:=true,
index 43095b95800fb4adf0a6c7521f8384c1c5dcca73..86ddfbca642d30e861befccc79bcf137db126964 100644 (file)
@@ -37,7 +37,7 @@ import org.eclipse.swt.graphics.Rectangle;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.aspect.LamiTableEntryAspect;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiChartModel;
-import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiChartModel.ChartType;
+import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiChartModel.LamiChartType;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiTableEntry;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.signals.LamiSelectionUpdateSignal;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.views.LamiReportViewTabPage;
@@ -105,7 +105,7 @@ public class LamiBarChartViewer extends LamiXYChartViewer {
         List<LamiTableEntryAspect> yAxisAspects = getYAxisAspects();
 
         /* bar chart cannot deal with multiple X series */
-        if (getChartModel().getChartType() != ChartType.BAR_CHART && xAxisAspects.size() != 1) {
+        if (getChartModel().getChartType() != LamiChartType.BAR_CHART && xAxisAspects.size() != 1) {
             throw new IllegalArgumentException("Invalid configuration passed to a bar chart."); //$NON-NLS-1$
         }
 
index ba7a3ebc3e4f740a5fc83a27554b79a9b5207fce..2e512fc230396aedc4787ad627aa6951eddb55be 100644 (file)
@@ -42,7 +42,7 @@ import org.eclipse.swt.widgets.Event;
 import org.eclipse.swt.widgets.Listener;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.aspect.LamiTableEntryAspect;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiChartModel;
-import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiChartModel.ChartType;
+import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiChartModel.LamiChartType;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiTableEntry;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.format.LamiLabelFormat;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.format.LamiTimeStampFormat;
@@ -93,7 +93,7 @@ public class LamiScatterViewer extends LamiXYChartViewer {
      */
     public LamiScatterViewer(Composite parent, LamiReportViewTabPage page, LamiChartModel graphModel) {
         super(parent, page, graphModel);
-        if (getChartModel().getChartType() != ChartType.XY_SCATTER) {
+        if (getChartModel().getChartType() != LamiChartType.XY_SCATTER) {
             throw new IllegalStateException("Chart type not a Scatter Chart " + getChartModel().getChartType().toString()); //$NON-NLS-1$
         }
 
index 24ce4dd9657a5bd556ae7cdb6f376136600c57c0..439202a99051f6f57c092cdacd067ceb4033e851 100644 (file)
@@ -9,6 +9,7 @@
 
 package org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.viewers;
 
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
 import static org.eclipse.tracecompass.common.core.NonNullUtils.nullToEmptyString;
 
 import java.util.HashSet;
@@ -30,6 +31,7 @@ import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.L
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.signals.LamiSelectionUpdateSignal;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.views.LamiReportView;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.views.LamiReportViewTabPage;
+import org.eclipse.tracecompass.internal.provisional.tmf.chart.core.signal.ChartSelectionUpdateSignal;
 import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
 import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager;
 import org.eclipse.tracecompass.tmf.ui.viewers.table.TmfSimpleTableViewer;
@@ -38,6 +40,7 @@ import org.eclipse.tracecompass.tmf.ui.viewers.table.TmfSimpleTableViewer;
  * Table viewer to use in {@link LamiReportView}s.
  *
  * @author Alexandre Montplaisir
+ * @author Gabriel-Andrew Pollo-Guilbert
  */
 public final class LamiTableViewer extends TmfSimpleTableViewer implements ILamiViewer {
 
@@ -47,6 +50,7 @@ public final class LamiTableViewer extends TmfSimpleTableViewer implements ILami
 
     private final LamiReportViewTabPage fPage;
     private Set<Integer> fSelections;
+    private Set<Object> fSelection;
 
     // ------------------------------------------------------------------------
     // Inner class definitions
@@ -54,10 +58,9 @@ public final class LamiTableViewer extends TmfSimpleTableViewer implements ILami
 
     /**
      * Abstract class for the column label provider for the latency analysis
-     * table viewer
+     * table viewer.
      */
     private static class LamiTableColumnLabelProvider extends ColumnLabelProvider {
-
         private final LamiTableEntryAspect fColumnAspect;
 
         public LamiTableColumnLabelProvider(LamiTableEntryAspect aspect) {
@@ -66,25 +69,25 @@ public final class LamiTableViewer extends TmfSimpleTableViewer implements ILami
 
         @Override
         public String getText(@Nullable Object input) {
+            /* Doubles as a null check */
             if (!(input instanceof LamiTableEntry)) {
-                /* Doubles as a null check */
                 return ""; //$NON-NLS-1$
             }
-            LamiTableEntry entry = (LamiTableEntry) input;
-            return nullToEmptyString(fColumnAspect.resolveString(entry));
+
+            return nullToEmptyString(fColumnAspect.resolveString((LamiTableEntry) input));
         }
     }
 
     /**
-     * Listener to update in other viewers when a cell of the latency
-     * table view is selected
+     * Listener to update in other viewers when a cell of the latency table view
+     * is selected.
      */
     private class LamiTableSelectionListener extends SelectionAdapter {
         @Override
-        public void widgetSelected(@Nullable SelectionEvent e) {
-
+        public void widgetSelected(@Nullable SelectionEvent event) {
             IStructuredSelection selections = getTableViewer().getStructuredSelection();
 
+            // Lami selections
             Set<Integer> selectionIndexes = new HashSet<>();
             for (Object selectedEntry : selections.toArray() ) {
                 selectionIndexes.add(fPage.getResultTable().getEntries().indexOf(selectedEntry));
@@ -95,11 +98,23 @@ public final class LamiTableViewer extends TmfSimpleTableViewer implements ILami
             /* Signal all Lami viewers & views of the selection */
             LamiSelectionUpdateSignal signal = new LamiSelectionUpdateSignal(LamiTableViewer.this, selectionIndexes, fPage);
             TmfSignalManager.dispatchSignal(signal);
+
+            /* Find all selected entries */
+            Set<Object> selectionSet = new HashSet<>();
+            for (Object selectedEntry : selections.toArray()) {
+                selectionSet.add(checkNotNull(selectedEntry));
+            }
+            fSelection = selectionSet;
+
+
+            /* Signal all Lami viewers & views of the selection */
+            ChartSelectionUpdateSignal customSignal = new ChartSelectionUpdateSignal(LamiTableViewer.this, fPage.getResultTable(), selectionSet);
+            TmfSignalManager.dispatchSignal(customSignal);
         }
     }
 
     // ------------------------------------------------------------------------
-    // Constructor
+    // Constructors
     // ------------------------------------------------------------------------
 
     /**
@@ -112,13 +127,13 @@ public final class LamiTableViewer extends TmfSimpleTableViewer implements ILami
      */
     public LamiTableViewer(TableViewer tableViewer, LamiReportViewTabPage page) {
         super(tableViewer);
-        /*
-         * The table viewer should always be the first element in the control.
-         */
+
+        /* The viewer should always be the first element in the control. */
         tableViewer.getTable().moveAbove(null);
 
         fPage = page;
         fSelections = new HashSet<>();
+        fSelection = new HashSet<>();
 
         /* Default sort order of the content provider is by its first column */
         getTableViewer().setContentProvider(new LamiTableContentProvider());
@@ -194,6 +209,21 @@ public final class LamiTableViewer extends TmfSimpleTableViewer implements ILami
                     getTableViewer().getTable().redraw();
                 });
             }
+            if (!fSelection.isEmpty()) {
+                LamiTableContentProvider provider = (LamiTableContentProvider) getTableViewer().getContentProvider();
+
+                /* Find the indexes in the UI table of the selected objects */
+                int[] selectionsIndexes = fSelection.stream()
+                        .map(obj -> (LamiTableEntry) obj)
+                        .mapToInt(entry -> provider.getIndexOf(checkNotNull(entry)))
+                        .toArray();
+
+                /* Update the selection in the UI table */
+                Display.getDefault().asyncExec(() -> {
+                    getTableViewer().getTable().setSelection(selectionsIndexes);
+                    getTableViewer().getTable().redraw();
+                });
+            }
         });
         Display.getDefault().asyncExec(() -> {
             if (tableViewer.getTable().isDisposed()) {
@@ -207,6 +237,10 @@ public final class LamiTableViewer extends TmfSimpleTableViewer implements ILami
         });
     }
 
+    // ------------------------------------------------------------------------
+    // Signals
+    // ------------------------------------------------------------------------
+
     /**
      * The signal handler for selection update.
      *
@@ -237,4 +271,40 @@ public final class LamiTableViewer extends TmfSimpleTableViewer implements ILami
             getTableViewer().getTable().redraw();
         });
     }
+
+    /**
+     * The signal handler for selection update.
+     *
+     * @param signal
+     *            The selection update signal
+     */
+    @TmfSignalHandler
+    public void updateCustomSelection(ChartSelectionUpdateSignal signal) {
+        /* Make sure we are not sending a signal to ourself */
+        if (signal.getSource() == this) {
+            return;
+        }
+
+        /* Make sure the signal comes from the data provider's scope */
+        if (fPage.getResultTable().hashCode() != signal.getDataProvider().hashCode()) {
+            return;
+        }
+
+        /* Get the set of selected objects */
+        fSelection = signal.getSelectedObject();
+
+        /* Get the selected index in the UI table */
+        LamiTableContentProvider tableContentProvider = (LamiTableContentProvider) getTableViewer().getContentProvider();
+        int[] tableSelection = fSelection.stream()
+                .map(obj -> (LamiTableEntry) obj)
+                .mapToInt(entry -> tableContentProvider.getIndexOf(checkNotNull(entry)))
+                .toArray();
+
+        /* Update the selection in the UI table */
+        Display.getDefault().asyncExec(() -> {
+            getTableViewer().getTable().setSelection(tableSelection);
+            getTableViewer().getTable().redraw();
+        });
+    }
+
 }
index ed38dd6c26f529bea50e8f2c33a9785208b4ddbf..f32453811002021e40229768bb4af2d2ac0ed547 100644 (file)
@@ -27,7 +27,7 @@ import org.eclipse.swt.custom.SashForm;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.tracecompass.internal.analysis.lami.ui.Activator;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiAnalysisReport;
-import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiChartModel.ChartType;
+import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiChartModel.LamiChartType;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiResultTable;
 import org.eclipse.tracecompass.tmf.ui.views.TmfView;
 
@@ -70,9 +70,9 @@ public final class LamiReportView extends TmfView {
 
     private class NewChartAction extends Action {
 
-        private final ChartType fChartType;
+        private final LamiChartType fChartType;
 
-        public NewChartAction(ChartType chartType) {
+        public NewChartAction(LamiChartType chartType) {
             fChartType = chartType;
         }
 
@@ -86,6 +86,18 @@ public final class LamiReportView extends TmfView {
         }
     }
 
+    private class NewCustomChartAction extends Action {
+
+        @Override
+        public void run() {
+            LamiReportViewTabPage page = getCurrentSelectedPage();
+            if (page == null) {
+                return;
+            }
+            page.createNewCustomChart();
+        }
+    }
+
     // ------------------------------------------------------------------------
     // Constructor
     // ------------------------------------------------------------------------
@@ -136,12 +148,14 @@ public final class LamiReportView extends TmfView {
         toolbarMgr.add(toggleTableAction);
 
         IMenuManager menuMgr = getViewSite().getActionBars().getMenuManager();
-        IAction newBarChartAction = new NewChartAction(ChartType.BAR_CHART);
-        IAction newXYScatterAction = new NewChartAction(ChartType.XY_SCATTER);
+        IAction newBarChartAction = new NewChartAction(LamiChartType.BAR_CHART);
+        IAction newXYScatterAction = new NewChartAction(LamiChartType.XY_SCATTER);
 
         newBarChartAction.setText(Messages.LamiReportView_NewCustomBarChart);
         newXYScatterAction.setText(Messages.LamiReportView_NewCustomScatterChart);
 
+        IAction newChartAction = new NewCustomChartAction();
+        newChartAction.setText(Messages.LamiReportView_NewCustomChart);
 
         IAction clearCustomViewsAction = new Action() {
             @Override
@@ -158,6 +172,7 @@ public final class LamiReportView extends TmfView {
 
         menuMgr.add(newBarChartAction);
         menuMgr.add(newXYScatterAction);
+        menuMgr.add(newChartAction);
         menuMgr.add(new Separator());
         menuMgr.add(clearCustomViewsAction);
 
index e9e8781ada7abe97f93e127b5df369f1d912c70d..f75a85078d5bc657e8a4640ca9268e040b78d0d2 100644 (file)
@@ -14,6 +14,7 @@ import static org.eclipse.tracecompass.common.core.NonNullUtils.nullToEmptyStrin
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.List;
@@ -28,15 +29,21 @@ import org.eclipse.jface.viewers.IStructuredContentProvider;
 import org.eclipse.jface.viewers.LabelProvider;
 import org.eclipse.jface.window.Window;
 import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Shell;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.aspect.LamiEmptyAspect;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.aspect.LamiTableEntryAspect;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiChartModel;
-import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiChartModel.ChartType;
+import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiChartModel.LamiChartType;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiResultTable;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiTableEntry;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiXYSeriesDescription;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.types.LamiTimeRange;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.signals.LamiSelectionUpdateSignal;
+import org.eclipse.tracecompass.internal.provisional.tmf.chart.core.chart.ChartData;
+import org.eclipse.tracecompass.internal.provisional.tmf.chart.core.chart.ChartModel;
+import org.eclipse.tracecompass.internal.provisional.tmf.chart.core.signal.ChartSelectionUpdateSignal;
+import org.eclipse.tracecompass.internal.provisional.tmf.chart.ui.chart.IChartViewer;
+import org.eclipse.tracecompass.internal.provisional.tmf.chart.ui.dialog.ChartMakerDialog;
 import org.eclipse.tracecompass.tmf.core.component.TmfComponent;
 import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
 import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
@@ -55,6 +62,7 @@ import com.google.common.collect.Iterables;
  *
  * @author Alexandre Montplaisir
  * @author Jonathan Rajotte-Julien
+ * @author Gabriel-Andrew Pollo-Guilbert
  */
 public final class LamiReportViewTabPage extends TmfComponent {
 
@@ -63,13 +71,15 @@ public final class LamiReportViewTabPage extends TmfComponent {
     // ------------------------------------------------------------------------
 
     private final LamiResultTable fResultTable;
-
     private final LamiViewerControl fTableViewerControl;
     private final Set<LamiViewerControl> fCustomGraphViewerControls = new LinkedHashSet<>();
     private final Composite fControl;
 
     private Set<Integer> fSelectionIndexes;
 
+    private @Nullable IChartViewer fChart;
+    private Set<Object> fSelection;
+
     // ------------------------------------------------------------------------
     // Constructor
     // ------------------------------------------------------------------------
@@ -84,25 +94,31 @@ public final class LamiReportViewTabPage extends TmfComponent {
      */
     public LamiReportViewTabPage(Composite parent, LamiResultTable table) {
         super(table.getTableClass().getTableTitle());
+
         fResultTable = table;
         fSelectionIndexes = new HashSet<>();
         fSelectionIndexes = getIndexOfEntriesIntersectingTimerange(checkNotNull(fResultTable), TmfTraceManager.getInstance().getCurrentTraceContext().getSelectionRange());
 
         fControl = parent;
 
+        /* Map the current trace selection to our lami entry */
+        fSelection = getEntriesIntersectingTimerange(fResultTable, TmfTraceManager.getInstance().getCurrentTraceContext().getSelectionRange());
+
         /* Prepare the table viewer, which is always present */
         LamiViewerControl tableViewerControl = new LamiViewerControl(fControl, this);
         fTableViewerControl = tableViewerControl;
 
         /* Automatically open the table viewer initially */
-        tableViewerControl.getToggleAction().run();
+        fTableViewerControl.getToggleAction().run();
 
         /* Simulate a new external signal to the default viewer */
         LamiSelectionUpdateSignal signal = new LamiSelectionUpdateSignal(LamiReportViewTabPage.this, fSelectionIndexes, this);
         TmfSignalManager.dispatchSignal(signal);
+        ChartSelectionUpdateSignal chartSignal = new ChartSelectionUpdateSignal(this, fResultTable, fSelection);
+        TmfSignalManager.dispatchSignal(chartSignal);
 
+        /* Dispose this class's resource */
         fControl.addDisposeListener(e -> {
-            /* Dispose this class's resource */
             fTableViewerControl.dispose();
             clearAllCustomViewers();
             super.dispose();
@@ -110,31 +126,49 @@ public final class LamiReportViewTabPage extends TmfComponent {
     }
 
     // ------------------------------------------------------------------------
-    // Operations
+    // Overriden methods
     // ------------------------------------------------------------------------
 
     @Override
     public void dispose() {
+        /* fControl's listner will dispose other resources */
         fControl.dispose();
-        /* fControl's disposeListener will dispose the class's resources */
     }
 
-    /**
-     * Get the SWT control associated with this tab page.
-     *
-     * @return The SWT control
-     */
-    public Composite getControl() {
-        return fControl;
-    }
+    // ------------------------------------------------------------------------
+    // Operations
+    // ------------------------------------------------------------------------
 
     /**
-     * Get the result table shown in this tab.
-     *
-     * @return The report result table
+     * This method is used for creating a chart from the result table of the
+     * analyse. It uses the custom charts plugin to configure and create the
+     * chart.
      */
-    public LamiResultTable getResultTable() {
-        return fResultTable;
+    public void createNewCustomChart() {
+        Shell shell = this.getControl().getShell();
+        if (shell == null) {
+            return;
+        }
+
+        /* Open the chart maker dialog */
+        ChartMakerDialog dialog = new ChartMakerDialog(shell, fResultTable);
+        if (dialog.open() != Window.OK) {
+            return;
+        }
+
+        /* Make sure the data for making a chart was generated */
+        ChartData data = dialog.getDataSeries();
+        ChartModel model = dialog.getChartModel();
+        if (data == null || model == null) {
+            return;
+        }
+
+        /* Make a chart with the factory constructor */
+        fChart = IChartViewer.createChart(fControl, data, model);
+        /* Signal the current selection to the newly created graph */
+        ChartSelectionUpdateSignal signal = new ChartSelectionUpdateSignal(LamiReportViewTabPage.this,
+                fResultTable, fSelection);
+        TmfSignalManager.dispatchSignal(signal);
     }
 
     /**
@@ -153,6 +187,28 @@ public final class LamiReportViewTabPage extends TmfComponent {
         fTableViewerControl.getToggleAction().run();
     }
 
+    // ------------------------------------------------------------------------
+    // Accessors
+    // ------------------------------------------------------------------------
+
+    /**
+     * Get the SWT control associated with this tab page.
+     *
+     * @return The SWT control
+     */
+    public Composite getControl() {
+        return fControl;
+    }
+
+    /**
+     * Get the result table shown in this tab.
+     *
+     * @return The report result table
+     */
+    public LamiResultTable getResultTable() {
+        return fResultTable;
+    }
+
     /**
      * Add a new chart viewer to this tab.
      *
@@ -163,7 +219,7 @@ public final class LamiReportViewTabPage extends TmfComponent {
      * @param chartType
      *            The type of chart to create
      */
-    public void createNewCustomChart(ChartType chartType) {
+    public void createNewCustomChart(LamiChartType chartType) {
         int xLogScaleOptionIndex = -1;
         int yLogScaleOptionIndex = -1;
 
@@ -326,6 +382,7 @@ public final class LamiReportViewTabPage extends TmfComponent {
     // Signals
     // ------------------------------------------------------------------------
 
+    // Lami signals
     /**
      * Signal handler for selection update.
      * Propagate a TmfSelectionRangeUpdatedSignal if possible.
@@ -363,6 +420,8 @@ public final class LamiReportViewTabPage extends TmfComponent {
              * there is no notion of "unselected state" in most of the viewers so
              * we do not update/clear the last timerange and show false information to the user.
              */
+            ChartSelectionUpdateSignal customSignal = new ChartSelectionUpdateSignal(LamiReportViewTabPage.this, fResultTable, Collections.EMPTY_SET);
+            TmfSignalManager.dispatchSignal(customSignal);
             return;
         }
 
@@ -384,29 +443,20 @@ public final class LamiReportViewTabPage extends TmfComponent {
         }
 
         fSelectionIndexes = entryIndex;
-    }
-
-    /**
-     * Signal handler for time range selections
-     *
-     * @param signal
-     *            The received signal
-     */
-    @TmfSignalHandler
-    public void externalUpdateSelection(TmfSelectionRangeUpdatedSignal signal) {
-        LamiResultTable table = fResultTable;
 
-        if (signal.getSource() == this) {
-            /* We are the source */
-            return;
+        // Create the signal for the custom chart
+        List<LamiTableEntry> entries = fResultTable.getEntries();
+        Set<Object> selectionSet = new HashSet<>();
+        for (Integer selectionIndex : entryIndex) {
+            selectionSet.add(entries.get(selectionIndex));
         }
-        TmfTimeRange range = new TmfTimeRange(signal.getBeginTime(), signal.getEndTime());
+        fSelection = selectionSet;
+        ChartSelectionUpdateSignal customSignal = new ChartSelectionUpdateSignal(LamiReportViewTabPage.this, fResultTable, selectionSet);
+        TmfSignalManager.dispatchSignal(customSignal);
 
-        Set<Integer> selections = getIndexOfEntriesIntersectingTimerange(table, range);
-
-        /* Update all LamiViewer */
-        LamiSelectionUpdateSignal signal1 = new LamiSelectionUpdateSignal(LamiReportViewTabPage.this, selections, this);
-        TmfSignalManager.dispatchSignal(signal1);
+//        /* Update all LamiViewer */
+//        LamiSelectionUpdateSignal signal1 = new LamiSelectionUpdateSignal(LamiReportViewTabPage.this, selections, this);
+//        TmfSignalManager.dispatchSignal(signal1);
     }
 
     private static Set<Integer> getIndexOfEntriesIntersectingTimerange(LamiResultTable table, TmfTimeRange range) {
@@ -434,4 +484,174 @@ public final class LamiReportViewTabPage extends TmfComponent {
         }
         return selections;
     }
+
+    // Custom chart signals
+    /**
+     * Signal handler for a chart selection update. It will try to propagate a
+     * {@link TmfSelectionRangeUpdatedSignal} if possible.
+     *
+     * @param signal
+     *            The selection update signal
+     */
+    @TmfSignalHandler
+    public void updateSelection(ChartSelectionUpdateSignal signal) {
+        IChartViewer chart = fChart;
+        if (chart == null) {
+            return;
+        }
+
+        /* Make sure we are not sending a signal to ourself */
+        if (signal.getSource() == this) {
+            return;
+        }
+
+        /* Make sure the signal comes from the data provider's scope */
+        if (fResultTable.hashCode() != signal.getDataProvider().hashCode()) {
+            return;
+        }
+
+        /* Find which index row has been selected */
+        Set<Object> entries = signal.getSelectedObject();
+
+        /*
+         * Since most of the external viewer deal only with continuous timerange
+         * and do not allow multi time range selection simply signal only when
+         * only one selection is present.
+         */
+        if (entries.isEmpty()) {
+            /*
+             * In an ideal world we would send a null signal to reset all view
+             * and simply show no selection. But since this is Tracecompass
+             * there is no notion of "unselected state" in most of the viewers
+             * so we do not update/clear the last timerange and show false
+             * information to the user.
+             */
+            /* Signal all Lami viewers & views of the selection */
+            LamiSelectionUpdateSignal lamiSignal = new LamiSelectionUpdateSignal(LamiReportViewTabPage.this, Collections.EMPTY_SET, this);
+            TmfSignalManager.dispatchSignal(lamiSignal);
+            return;
+        }
+
+        /* Update the selection */
+        fSelection = entries;
+
+        // Create the signal for the LAMI selection
+        Set<Integer> selectionIndexes = new HashSet<>();
+        for (Object entry : entries ) {
+            selectionIndexes.add(fResultTable.getEntries().indexOf(entry));
+        }
+
+        fSelectionIndexes = selectionIndexes;
+
+        /* Signal all Lami viewers & views of the selection */
+        LamiSelectionUpdateSignal lamiSignal = new LamiSelectionUpdateSignal(LamiReportViewTabPage.this, selectionIndexes, this);
+        TmfSignalManager.dispatchSignal(lamiSignal);
+
+        /* Only propagate to all TraceCompass if there is a single selection */
+        if (entries.size() == 1) {
+            LamiTableEntry entry = (LamiTableEntry) Iterables.getOnlyElement(entries);
+
+            /* Make sure the selection represent a time range */
+            LamiTimeRange timeRange = entry.getCorrespondingTimeRange();
+            if (timeRange == null) {
+                return;
+            }
+
+            /* Get the timestamps from the time range */
+            /**
+             * TODO: Consider low and high limits of timestamps here.
+             */
+            Number tsBeginValueNumber = timeRange.getBegin().getValue();
+            Number tsEndValueNumber = timeRange.getEnd().getValue();
+            if(tsBeginValueNumber == null || tsEndValueNumber == null) {
+                return;
+            }
+
+            /* Send Range update to other views */
+            ITmfTimestamp start = TmfTimestamp.fromNanos(tsBeginValueNumber.longValue());
+            ITmfTimestamp end = TmfTimestamp.fromNanos(tsEndValueNumber.longValue());
+            TmfSignalManager.dispatchSignal(new TmfSelectionRangeUpdatedSignal(this, start, end));
+        }
+
+    }
+
+    /**
+     * Signal handler for a trace selection range update signal. It will try to
+     * map the external selection to our lami table entry.
+     *
+     * @param signal
+     *            The received signal
+     */
+    @TmfSignalHandler
+    public void externalUpdateSelectionCustomCharts(TmfSelectionRangeUpdatedSignal signal) {
+        /* Make sure we are not sending a signal to ourself */
+        if (signal.getSource() == this) {
+            return;
+        }
+
+        TmfTimeRange range = new TmfTimeRange(signal.getBeginTime(), signal.getEndTime());
+
+        // Lami signal
+        Set<Integer> selections = getIndexOfEntriesIntersectingTimerange(fResultTable, range);
+
+        /* Update all LamiViewer */
+        LamiSelectionUpdateSignal signal1 = new LamiSelectionUpdateSignal(LamiReportViewTabPage.this, selections, this);
+        TmfSignalManager.dispatchSignal(signal1);
+
+        // Custom chart signal
+        /* Find which lami table entry intersects the signal */
+        Set<Object> selection = getEntriesIntersectingTimerange(fResultTable, range);
+
+        /* Update all LamiViewer */
+        ChartSelectionUpdateSignal updateSignal = new ChartSelectionUpdateSignal(this, fResultTable, selection);
+        TmfSignalManager.dispatchSignal(updateSignal);
+    }
+
+    // ------------------------------------------------------------------------
+    // Util methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Util method that returns {@link LamiTableEntry} that intersects a
+     * {@link TmfTimeRange}.
+     *
+     * @param table
+     *            The result table to search for entries
+     * @param range
+     *            The time range itself
+     * @return The set of entries that intersect with the time range
+     */
+    private static Set<Object> getEntriesIntersectingTimerange(LamiResultTable table, TmfTimeRange range) {
+        Set<Object> entries = new HashSet<>();
+        for (LamiTableEntry entry : table.getEntries()) {
+            LamiTimeRange lamiTimeRange = entry.getCorrespondingTimeRange();
+
+            /* Make sure the table has time ranges */
+            if (lamiTimeRange == null) {
+                return entries;
+            }
+
+            /* Get the timestamps from the time range */
+            /**
+             * TODO: Consider low and high limits of timestamps here.
+             */
+            Number tsBeginValueNumber = lamiTimeRange.getBegin().getValue();
+            Number tsEndValueNumber = lamiTimeRange.getEnd().getValue();
+            if(tsBeginValueNumber == null || tsEndValueNumber == null) {
+                return entries;
+            }
+
+            /* Convert the timestamps into TMF timestamps */
+            ITmfTimestamp start = TmfTimestamp.fromNanos(tsBeginValueNumber.longValue());
+            ITmfTimestamp end = TmfTimestamp.fromNanos(tsEndValueNumber.longValue());
+
+            /* Add iff the time range intersects the the signal */
+            TmfTimeRange tempTimeRange = new TmfTimeRange(start, end);
+            if (tempTimeRange.getIntersection(range) != null) {
+                entries.add(entry);
+            }
+        }
+
+        return entries;
+    }
 }
index ddb36a022ddbabe2442ae9ed641a67dd71e2add6..c5271ae5cea76f856b4c19777ef08ccf30135675 100644 (file)
@@ -46,7 +46,7 @@ import org.eclipse.swt.widgets.Shell;
 import org.eclipse.swt.widgets.TableColumn;
 import org.eclipse.swt.widgets.TableItem;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.aspect.LamiTableEntryAspect;
-import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiChartModel.ChartType;
+import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiChartModel.LamiChartType;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiXYSeriesDescription;
 import org.eclipse.ui.dialogs.SelectionDialog;
 
@@ -102,7 +102,7 @@ public class LamiSeriesDialog extends SelectionDialog {
      * @param yLabelProvider
      *            The label provider for the Y axis set
      */
-    public LamiSeriesDialog(Shell parentShell, ChartType chartType, Object xInput,
+    public LamiSeriesDialog(Shell parentShell, LamiChartType chartType, Object xInput,
             Object yInput,
             IStructuredContentProvider xContentProvider,
             ILabelProvider xLabelProvider,
index 379b4b41c6e96825f3c7fa604a971ca251570f30..188f6fcb6fafb3538425189d0c9f60e6a1d9f4cf 100644 (file)
@@ -115,7 +115,7 @@ public final class LamiViewerControl {
         }
     }
 
-    private static @Nullable ImageDescriptor getIconForGraphType(LamiChartModel.ChartType graphType) {
+    private static @Nullable ImageDescriptor getIconForGraphType(LamiChartModel.LamiChartType graphType) {
         switch (graphType) {
         case BAR_CHART:
             return Activator.getDefault().getImageDescripterFromPath("icons/histogram.gif"); //$NON-NLS-1$
index f6cb479a66105d5aef06f59bd9411644c831f353..a80648990e01e1c0fa6d7103eea8f0b76b9840c9 100644 (file)
@@ -29,6 +29,7 @@ public class Messages extends NLS {
     public static String LamiReportView_ToggleAction_ButtonNamePrefix;
     public static String LamiReportView_ToggleAction_ButtonTooltip;
 
+    public static String LamiReportView_NewCustomChart;
     public static String LamiReportView_NewCustomBarChart;
     public static String LamiReportView_NewCustomScatterChart;
     public static String LamiReportView_ClearAllCustomViews;
index bd16a409dd04c6c170c4fc5f9b88148df4785948..6493098e03e64e6f9bb3cbb900f336f61c19d8e6 100644 (file)
@@ -13,6 +13,7 @@ LamiReportView_ActivateTableAction_ButtonTooltip = Toggle the Table view of the
 LamiReportView_ToggleAction_ButtonNamePrefix = Toggle
 LamiReportView_ToggleAction_ButtonTooltip = Toggle showing this graph in the view
 
+LamiReportView_NewCustomChart = New custom chart
 LamiReportView_NewCustomBarChart = New custom bar chart
 LamiReportView_NewCustomScatterChart = New custom scatter chart
 LamiReportView_ClearAllCustomViews = Clear all custom views
index 403b65f41736f6d9d3a551bc25967e8506358c40..0eb0038a1facb082af40d711f8e0b493128af1b2 100644 (file)
@@ -13,7 +13,8 @@ Require-Bundle: org.eclipse.core.runtime,
  org.eclipse.tracecompass.tmf.core
 Export-Package: org.eclipse.tracecompass.internal.provisional.tmf.chart.core.chart;
   x-friends:="org.eclipse.tracecompass.tmf.chart.ui,
-   org.eclipse.tracecompass.tmf.chart.core.tests",
+   org.eclipse.tracecompass.tmf.chart.core.tests,
+   org.eclipse.tracecompass.analysis.lami.ui",
  org.eclipse.tracecompass.internal.provisional.tmf.chart.core.descriptor;
   x-friends:="org.eclipse.tracecompass.tmf.chart.ui,
    org.eclipse.tracecompass.tmf.chart.core.tests,
@@ -28,7 +29,7 @@ Export-Package: org.eclipse.tracecompass.internal.provisional.tmf.chart.core.cha
   x-friends:="org.eclipse.tracecompass.tmf.chart.ui,
    org.eclipse.tracecompass.tmf.chart.core.tests,
    org.eclipse.tracecompass.analysis.lami.core",
- org.eclipse.tracecompass.internal.provisional.tmf.chart.core.signal;x-friends:="org.eclipse.tracecompass.tmf.chart.ui",
+ org.eclipse.tracecompass.internal.provisional.tmf.chart.core.signal;x-friends:="org.eclipse.tracecompass.tmf.chart.ui,org.eclipse.tracecompass.analysis.lami.ui",
  org.eclipse.tracecompass.internal.tmf.chart.core;x-internal:=true,
  org.eclipse.tracecompass.internal.tmf.chart.core.aggregator;x-friends:="org.eclipse.tracecompass.tmf.chart.ui,org.eclipse.tracecompass.tmf.chart.core.tests",
  org.eclipse.tracecompass.internal.tmf.chart.core.chart;x-internal:=true,
index 0066cefc6f06a052487465b3bf296b85c6ad8059..dfcc75a0d643d6d32f61937de36e39d36516b591 100644 (file)
@@ -15,8 +15,8 @@ Require-Bundle: org.eclipse.ui,
  org.eclipse.tracecompass.tmf.chart.core,
  org.eclipse.tracecompass.tmf.core,
  org.eclipse.tracecompass.tmf.ui
-Export-Package: org.eclipse.tracecompass.internal.provisional.tmf.chart.ui.chart;x-internal:=true,
- org.eclipse.tracecompass.internal.provisional.tmf.chart.ui.dialog;x-internal:=true,
+Export-Package: org.eclipse.tracecompass.internal.provisional.tmf.chart.ui.chart;x-friends:="org.eclipse.tracecompass.analysis.lami.ui",
+ org.eclipse.tracecompass.internal.provisional.tmf.chart.ui.dialog;x-friends:="org.eclipse.tracecompass.analysis.lami.ui",
  org.eclipse.tracecompass.internal.tmf.chart.ui;x-internal:=true,
  org.eclipse.tracecompass.internal.tmf.chart.ui.aggregator;x-internal:=true,
  org.eclipse.tracecompass.internal.tmf.chart.ui.consumer;x-internal:=true,
index 7a4edeb7d88322cf31f319a9b5ac9023e549ff61..756195c260130f8d6773fb829dc0f3fcae052091 100644 (file)
@@ -319,6 +319,7 @@ public class ChartMakerDialog extends Dialog {
     private void createSeriesCreatorGroup(GridData genericFillGridData) {
         GridLayout creatorLayout = new GridLayout();
         creatorLayout.numColumns = 2;
+        creatorLayout.makeColumnsEqualWidth = true;
 
         Group creatorGroup = new Group(fComposite, SWT.BORDER);
         creatorGroup.setText(Messages.ChartMakerDialog_SeriesCreator);
@@ -381,9 +382,6 @@ public class ChartMakerDialog extends Dialog {
         fWarningLabel.setVisible(false);
 
         /* Add button */
-        Label creatorLabelEmpty = new Label(creatorGroup, SWT.NONE);
-        creatorLabelEmpty.setText(""); //$NON-NLS-1$
-
         GridData creatorButtonGridData = new GridData();
         creatorButtonGridData.horizontalAlignment = SWT.RIGHT;
         creatorButtonGridData.widthHint = 30;
@@ -396,7 +394,6 @@ public class ChartMakerDialog extends Dialog {
         fAddButton.addListener(SWT.Selection, new AddButtonClickedEvent());
     }
 
-
     private void createOptionsGroup() {
         GridLayout optionsLayout = new GridLayout();
         optionsLayout.numColumns = 2;
index 0ac956c41d4317efd7b3f7462fa9c0cf7f3ab369..a992fb4bf956ca8e611ce0dd64bbe3dc2e1320b2 100644 (file)
@@ -151,6 +151,10 @@ public class ChartRangeMap {
         ChartRange internal = getPlottedRange();
         ChartRange external = getInputDataRange();
 
+        if (external.getDelta().compareTo(BigDecimal.ZERO) == 0) {
+            return internal.getMinimum().doubleValue();
+        }
+
         /* Apply the formula */
         BigDecimal internalValue = value
                 .subtract(external.getMinimum())
@@ -177,6 +181,10 @@ public class ChartRangeMap {
         ChartRange internal = getPlottedRange();
         ChartRange external = getInputDataRange();
 
+        if (internal.getDelta().compareTo(BigDecimal.ZERO) == 0) {
+            return external.getMinimum();
+        }
+
         /* Apply the formula in reverse */
         BigDecimal externalValue = (new BigDecimal(number.toString()))
                 .subtract(internal.getMinimum())
index 834c801b295fb74b052ca998589b85cfab546c3c..3e300bb76aee02fa1cb07668bc60c9a2d1e8186c 100644 (file)
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2016 École Polytechnique de Montréal
+# Copyright (c) 2016 École Polytechnique de Montréal
 #
 # All rights reserved. This program and the accompanying materials are
 # made available under the terms of the Eclipse Public License v1.0 which
This page took 0.04186 seconds and 5 git commands to generate.