/**
* Supported types of charts
*/
- public enum ChartType {
+ public enum LamiChartType {
/** Bar chart */
BAR_CHART("Bar"), //$NON-NLS-1$
private final String fText;
- private ChartType(final String text) {
+ private LamiChartType(final String text) {
fText = text;
}
}
}
- private final ChartType fType;
+ private final LamiChartType fType;
private final String fName;
private final List<String> fXSeriesColumns;
private final List<String> fYSeriesColumns;
* @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;
*
* @return The chart type
*/
- public ChartType getChartType() {
+ public LamiChartType getChartType() {
return fType;
}
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,
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;
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$
}
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;
*/
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$
}
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;
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;
* Table viewer to use in {@link LamiReportView}s.
*
* @author Alexandre Montplaisir
+ * @author Gabriel-Andrew Pollo-Guilbert
*/
public final class LamiTableViewer extends TmfSimpleTableViewer implements ILamiViewer {
private final LamiReportViewTabPage fPage;
private Set<Integer> fSelections;
+ private Set<Object> fSelection;
// ------------------------------------------------------------------------
// Inner class definitions
/**
* 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) {
@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));
/* 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
// ------------------------------------------------------------------------
/**
*/
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());
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()) {
});
}
+ // ------------------------------------------------------------------------
+ // Signals
+ // ------------------------------------------------------------------------
+
/**
* The signal handler for selection update.
*
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();
+ });
+ }
+
}
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;
private class NewChartAction extends Action {
- private final ChartType fChartType;
+ private final LamiChartType fChartType;
- public NewChartAction(ChartType chartType) {
+ public NewChartAction(LamiChartType chartType) {
fChartType = chartType;
}
}
}
+ private class NewCustomChartAction extends Action {
+
+ @Override
+ public void run() {
+ LamiReportViewTabPage page = getCurrentSelectedPage();
+ if (page == null) {
+ return;
+ }
+ page.createNewCustomChart();
+ }
+ }
+
// ------------------------------------------------------------------------
// Constructor
// ------------------------------------------------------------------------
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
menuMgr.add(newBarChartAction);
menuMgr.add(newXYScatterAction);
+ menuMgr.add(newChartAction);
menuMgr.add(new Separator());
menuMgr.add(clearCustomViewsAction);
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
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;
*
* @author Alexandre Montplaisir
* @author Jonathan Rajotte-Julien
+ * @author Gabriel-Andrew Pollo-Guilbert
*/
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
// ------------------------------------------------------------------------
*/
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();
}
// ------------------------------------------------------------------------
- // 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);
}
/**
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.
*
* @param chartType
* The type of chart to create
*/
- public void createNewCustomChart(ChartType chartType) {
+ public void createNewCustomChart(LamiChartType chartType) {
int xLogScaleOptionIndex = -1;
int yLogScaleOptionIndex = -1;
// Signals
// ------------------------------------------------------------------------
+ // Lami signals
/**
* Signal handler for selection update.
* Propagate a TmfSelectionRangeUpdatedSignal if possible.
* 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;
}
}
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) {
}
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;
+ }
}
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;
* @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,
}
}
- 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$
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;
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
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,
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,
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,
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);
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;
fAddButton.addListener(SWT.Selection, new AddButtonClickedEvent());
}
-
private void createOptionsGroup() {
GridLayout optionsLayout = new GridLayout();
optionsLayout.numColumns = 2;
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())
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())
###############################################################################
-# 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