import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences;
import org.eclipse.swtbot.swt.finder.widgets.AbstractSWTBotControl;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTable;
-import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.AbstractSegmentStoreTableViewer;
import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.density.AbstractSegmentStoreDensityView;
+import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.table.AbstractSegmentStoreTableViewer;
import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency.SystemCallLatencyDensityView;
import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
import org.eclipse.tracecompass.tmf.ui.swtbot.tests.shared.ConditionHelpers;
/*******************************************************************************
- * Copyright (c) 2015 Ericsson
+ * Copyright (c) 2015, 2016 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTable;
import org.eclipse.tracecompass.analysis.os.linux.core.latency.SystemCall;
import org.eclipse.tracecompass.analysis.os.linux.core.latency.SystemCall.InitialInfo;
-import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.AbstractSegmentStoreTableViewer;
+import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.table.AbstractSegmentStoreTableViewer;
import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency.SystemCallLatencyView;
import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
import org.eclipse.tracecompass.tmf.ui.swtbot.tests.shared.ConditionHelpers;
/******************************************************************************
- * Copyright (c) 2015 Ericsson
+ * Copyright (c) 2015, 2016 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
-import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.AbstractSegmentStoreTableViewer;
import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.density.AbstractSegmentStoreDensityView;
import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.density.AbstractSegmentStoreDensityViewer;
+import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.table.AbstractSegmentStoreTableViewer;
import org.eclipse.tracecompass.common.core.NonNullUtils;
/**
/******************************************************************************
- * Copyright (c) 2015 Ericsson
+ * Copyright (c) 2015, 2016 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
import org.eclipse.swt.widgets.Composite;
import org.eclipse.tracecompass.analysis.os.linux.core.latency.SystemCallLatencyAnalysis;
import org.eclipse.tracecompass.analysis.timing.core.segmentstore.AbstractSegmentStoreAnalysisModule;
-import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.AbstractSegmentStoreScatterGraphViewer;
+import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.scatter.AbstractSegmentStoreScatterGraphViewer;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
/*******************************************************************************
- * Copyright (c) 2015 Ericsson
+ * Copyright (c) 2015, 2016 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.swt.widgets.Composite;
-import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.AbstractSegmentStoreScatterGraphViewer;
+import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.scatter.AbstractSegmentStoreScatterGraphViewer;
import org.eclipse.tracecompass.common.core.NonNullUtils;
import org.eclipse.tracecompass.tmf.ui.viewers.xycharts.TmfXYChartViewer;
import org.eclipse.tracecompass.tmf.ui.views.TmfChartView;
/*******************************************************************************
- * Copyright (c) 2015 Ericsson
+ * Copyright (c) 2015, 2016 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.tracecompass.analysis.os.linux.core.latency.SystemCallLatencyAnalysis;
import org.eclipse.tracecompass.analysis.timing.core.segmentstore.AbstractSegmentStoreAnalysisModule;
-import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.AbstractSegmentStoreTableViewer;
+import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.table.AbstractSegmentStoreTableViewer;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
/*******************************************************************************
- * Copyright (c) 2015 Ericsson
+ * Copyright (c) 2015, 2016 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency;
import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.AbstractSegmentStoreTableView;
-import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.AbstractSegmentStoreTableViewer;
+import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.table.AbstractSegmentStoreTableView;
+import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.table.AbstractSegmentStoreTableViewer;
/**
* View for the latency analysis
org.swtchart
Export-Package: org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore,
org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.density,
+ org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.scatter,
+ org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.table,
org.eclipse.tracecompass.internal.analysis.timing.ui,
- org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore,
org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.density,
- org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.statistics;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui"
+ org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.scatter,
+ org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.statistics;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui",
+ org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.table
+++ /dev/null
-/******************************************************************************
- * 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:
- * France Lapointe Nguyen - Initial API and implementation
- * Bernd Hufmann - Extracted abstract class from LatencyScatterGraphViewer
- *******************************************************************************/
-
-package org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-
-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.jdt.annotation.Nullable;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.tracecompass.analysis.timing.core.segmentstore.AbstractSegmentStoreAnalysisModule;
-import org.eclipse.tracecompass.analysis.timing.core.segmentstore.IAnalysisProgressListener;
-import org.eclipse.tracecompass.common.core.NonNullUtils;
-import org.eclipse.tracecompass.internal.analysis.timing.ui.Activator;
-import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.Messages;
-import org.eclipse.tracecompass.segmentstore.core.ISegment;
-import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
-import org.eclipse.tracecompass.segmentstore.core.SegmentComparators;
-import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
-import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager;
-import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
-import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
-import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
-import org.eclipse.tracecompass.tmf.core.signal.TmfWindowRangeUpdatedSignal;
-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.core.trace.TmfTraceManager;
-import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentInfo;
-import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentSignal;
-import org.eclipse.tracecompass.tmf.ui.viewers.xycharts.TmfChartTimeStampFormat;
-import org.eclipse.tracecompass.tmf.ui.viewers.xycharts.linecharts.TmfCommonXLineChartViewer;
-import org.swtchart.Chart;
-import org.swtchart.IAxis;
-import org.swtchart.IAxisTick;
-import org.swtchart.ILineSeries;
-import org.swtchart.ILineSeries.PlotSymbolType;
-import org.swtchart.ISeries.SeriesType;
-import org.swtchart.ISeriesSet;
-import org.swtchart.LineStyle;
-import org.swtchart.Range;
-
-/**
- * Displays the segment store analysis data in a scatter graph
- *
- * @author France Lapointe Nguyen
- * @author Matthew Khouzam - reduced memory usage
- * @since 2.0
- */
-public abstract class AbstractSegmentStoreScatterGraphViewer extends TmfCommonXLineChartViewer {
-
- private final class CompactingSegmentStoreQuery extends Job {
- private static final long MAX_POINTS = 1000;
- private final TmfTimeRange fCurrentRange;
-
- private CompactingSegmentStoreQuery(TmfTimeRange currentRange) {
- super(Messages.SegmentStoreScatterGraphViewer_compactTitle);
- fCurrentRange = currentRange;
- }
-
- @Override
- protected IStatus run(@Nullable IProgressMonitor monitor) {
- final IProgressMonitor statusMonitor = monitor;
- if (statusMonitor == null) {
- return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Monitor is null"); //$NON-NLS-1$
- }
-
- AbstractSegmentStoreAnalysisModule module = getAnalysisModule();
- final long startTimeInNanos = getTimeInNanos(fCurrentRange.getStartTime());
- final long endTimeInNanos = getTimeInNanos(fCurrentRange.getEndTime());
- if (module == null) {
- setWindowRange(startTimeInNanos, endTimeInNanos);
- redraw(statusMonitor, startTimeInNanos, startTimeInNanos, Collections.EMPTY_LIST);
- return new Status(IStatus.WARNING, Activator.PLUGIN_ID, "Analysis module not available"); //$NON-NLS-1$
- }
-
- final ISegmentStore<ISegment> results = module.getResults();
- if (results == null) {
- setWindowRange(startTimeInNanos, endTimeInNanos);
- redraw(statusMonitor, startTimeInNanos, startTimeInNanos, Collections.EMPTY_LIST);
- return new Status(IStatus.INFO, Activator.PLUGIN_ID, "Analysis module does not have results"); //$NON-NLS-1$
- }
-
- final long startTime = fCurrentRange.getStartTime().getValue();
- final long endTime = fCurrentRange.getEndTime().getValue();
- fPixelStart = startTime;
- fPixelSize = (endTime - startTime) / MAX_POINTS;
- final Iterable<ISegment> intersectingElements = results.getIntersectingElements(startTime, endTime);
-
- final List<ISegment> list = convertIterableToList(intersectingElements, statusMonitor);
- final List<ISegment> displayData = (!list.isEmpty()) ? compactList(startTime, list, statusMonitor) : list;
-
- setWindowRange(startTimeInNanos, endTimeInNanos);
- redraw(statusMonitor, startTime, endTime, displayData);
-
- if (statusMonitor.isCanceled()) {
- return NonNullUtils.checkNotNull(Status.CANCEL_STATUS);
- }
- return NonNullUtils.checkNotNull(Status.OK_STATUS);
-
- }
-
- private void redraw(final IProgressMonitor statusMonitor, final long startTime, final long endTime, final List<ISegment> displayData) {
- fDisplayData = displayData;
- Display.getDefault().asyncExec(new Runnable() {
-
- @Override
- public void run() {
- updateData(startTime, endTime, displayData.size(), statusMonitor);
- }
- });
- }
-
- private List<ISegment> compactList(final long startTime, final List<ISegment> listToCompact, final IProgressMonitor statusMonitor) {
- List<ISegment> displayData = new ArrayList<>();
- ISegment last = listToCompact.get(0);
- if (last.getStart() >= startTime) {
- displayData.add(last);
- }
- for (ISegment next : listToCompact) {
- if (next.getStart() < startTime) {
- continue;
- }
- if (statusMonitor.isCanceled()) {
- return Collections.EMPTY_LIST;
- }
- if (!overlaps(last, next)) {
- displayData.add(next);
- last = next;
- }
- }
- return displayData;
- }
-
- private List<ISegment> convertIterableToList(final Iterable<ISegment> iterable, final IProgressMonitor statusMonitor) {
- final List<ISegment> list = new ArrayList<>();
- for (ISegment seg : iterable) {
- if (statusMonitor.isCanceled()) {
- return Collections.EMPTY_LIST;
- }
- list.add(seg);
- }
- Collections.sort(list, SegmentComparators.INTERVAL_START_COMPARATOR);
- return list;
- }
-
- private boolean overlaps(ISegment last, ISegment next) {
- long timePerPix = fPixelSize;
- final long start = last.getStart();
- final long pixelStart = fPixelStart;
- final long pixelDuration = start - pixelStart;
- long startPixBoundL = pixelDuration / timePerPix * timePerPix + pixelStart;
- long startPixBoundR = startPixBoundL + timePerPix;
- final long currentStart = next.getStart();
- if (currentStart >= startPixBoundL && currentStart <= startPixBoundR) {
- long length = last.getLength();
- long lengthNext = next.getLength();
- long lengthLow = length / timePerPix * timePerPix;
- long lengthHigh = lengthLow + timePerPix;
- return (lengthNext >= lengthLow && lengthNext <= lengthHigh);
- }
- return false;
- }
- }
-
- // ------------------------------------------------------------------------
- // Attributes
- // ------------------------------------------------------------------------
-
- /**
- * Listener to update the model with the semgent store analysis results
- * once the analysis is fully completed
- */
- private final class AnalysisProgressListener implements IAnalysisProgressListener {
-
- @Override
- public void onComplete(AbstractSegmentStoreAnalysisModule activeAnalysis, ISegmentStore<ISegment> results) {
- // Only update the model if trace that was analyzed is active trace
- if (activeAnalysis.equals(getAnalysisModule())) {
- updateModel(results);
- updateRange(TmfTraceManager.getInstance().getCurrentTraceContext().getWindowRange());
- }
- }
- }
-
- private long fPixelSize = -1;
-
- private long fPixelStart = 0;
- /**
- * Data to display
- */
- private Collection<ISegment> fDisplayData = Collections.EMPTY_LIST;
-
- /**
- * Analysis completion listener
- */
- private AnalysisProgressListener fListener;
-
- /**
- * Current analysis module
- */
- private @Nullable AbstractSegmentStoreAnalysisModule fAnalysisModule;
-
- private @Nullable Job fCompactingJob;
-
- // ------------------------------------------------------------------------
- // Constructor
- // ------------------------------------------------------------------------
-
- /**
- * Constructor
- *
- * @param parent
- * parent composite
- * @param title
- * name of the graph
- * @param xLabel
- * name of the x axis
- * @param yLabel
- * name of the y axis
- */
- public AbstractSegmentStoreScatterGraphViewer(Composite parent, String title, String xLabel, String yLabel) {
- super(parent, title, xLabel, yLabel);
- setTooltipProvider(new SegmentStoreScatterGraphTooltipProvider(this));
- fListener = new AnalysisProgressListener();
- ITmfTrace trace = TmfTraceManager.getInstance().getActiveTrace();
- initializeModule(trace);
- getSwtChart().getLegend().setVisible(false);
- }
-
- private final void initializeModule(@Nullable ITmfTrace trace) {
- if (trace != null) {
- final AbstractSegmentStoreAnalysisModule analysisModuleOfClass = getSegmentStoreAnalysisModule(trace);
- if (analysisModuleOfClass != null) {
- analysisModuleOfClass.addListener(fListener);
- setData(analysisModuleOfClass);
- updateRange(TmfTraceManager.getInstance().getCurrentTraceContext().getWindowRange());
- }
- }
- }
-
- // ------------------------------------------------------------------------
- // Operations
- // ------------------------------------------------------------------------
-
- /**
- * Update the data in the graph
- *
- * @param dataInput
- * new model
- */
- public void updateModel(@Nullable ISegmentStore<ISegment> dataInput) {
- // Update new window range
- TmfTimeRange currentRange = TmfTraceManager.getInstance().getCurrentTraceContext().getWindowRange();
- long currentStart = getTimeInNanos(currentRange.getStartTime());
- long currentEnd = getTimeInNanos(currentRange.getEndTime());
- if (dataInput == null) {
- if (!getDisplay().isDisposed()) {
- Display.getDefault().syncExec(new Runnable() {
- @Override
- public void run() {
- clearContent();
- }
- });
- }
- fDisplayData = Collections.EMPTY_LIST;
- } else {
- Collection<ISegment> elements = (Collection<ISegment>) dataInput.getIntersectingElements(currentStart, currentEnd);
- // getIntersectingElements can return an unsorted iterable, make
- // sure our collection is sorted
- ArrayList<ISegment> list = new ArrayList<>(elements);
- Collections.sort(list, SegmentComparators.INTERVAL_START_COMPARATOR);
- fDisplayData = list;
- }
- setWindowRange(currentStart, currentEnd);
- updateRange(currentRange);
- }
-
- @Override
- protected void initializeDataSource() {
- ITmfTrace trace = getTrace();
- initializeModule(trace);
- if (trace != null) {
- setData(getSegmentStoreAnalysisModule(trace));
- }
- }
-
- @Override
- protected void updateData(final long start, final long end, int nb, @Nullable IProgressMonitor monitor) {
- // Third parameter is not used by implementation
- // Determine data that needs to be visible
- Collection<ISegment> data = fDisplayData;
-
- final int dataSize = (nb == 0) ? data.size() : nb;
- if (dataSize == 0 || end == start) {
- return;
- }
-
- final double[] xSeries = new double[dataSize];
- final double[] ySeries = new double[dataSize];
- // For each visible segments, add start time to x value and duration
- // for y value
- Iterator<ISegment> modelIter = data.iterator();
- long maxTempY = 1;
- for (int i = 0; i < dataSize; i++) {
- if (modelIter.hasNext()) {
- ISegment segment = modelIter.next();
- xSeries[i] = segment.getStart() - start;
- ySeries[i] = segment.getLength();
- maxTempY = Math.max(maxTempY, segment.getLength());
- }
- }
- final long maxY = maxTempY;
- setXAxis(xSeries);
- final Chart swtChart = getSwtChart();
- if (swtChart.isDisposed() || xSeries.length < 1) {
- return;
- }
- swtChart.updateLayout();
- setSeries(Messages.SegmentStoreScatterGraphViewer_legend, ySeries); // $NON-NLS-1$
- final TmfChartTimeStampFormat tmfChartTimeStampFormat = new TmfChartTimeStampFormat(getTimeOffset());
- ILineSeries series = (ILineSeries) swtChart.getSeriesSet().getSeries(Messages.SegmentStoreScatterGraphViewer_legend);
- if (series == null) {
- series = addSeries(Messages.SegmentStoreScatterGraphViewer_legend);
- }
- series.setXSeries(xSeries);
- /* Find the minimal and maximum values in this series */
- series.setYSeries(ySeries);
-
- final IAxis xAxis = swtChart.getAxisSet().getXAxis(0);
- IAxisTick xTick = xAxis.getTick();
- xTick.setFormat(tmfChartTimeStampFormat);
- xAxis.setRange(new Range(0.0, end - start));
- if (maxY > 0.0) {
- swtChart.getAxisSet().getYAxis(0).setRange(new Range(0.0, maxY));
- }
- swtChart.redraw();
-
- if (isSendTimeAlignSignals()) {
- // The width of the chart might have changed and its
- // time axis might be misaligned with the other views
- Point viewPos = AbstractSegmentStoreScatterGraphViewer.this.getParent().getParent().toDisplay(0, 0);
- int axisPos = swtChart.toDisplay(0, 0).x + getPointAreaOffset();
- int timeAxisOffset = axisPos - viewPos.x;
- TmfTimeViewAlignmentInfo timeAlignmentInfo = new TmfTimeViewAlignmentInfo(getControl().getShell(), viewPos, timeAxisOffset);
- TmfSignalManager.dispatchSignal(new TmfTimeViewAlignmentSignal(AbstractSegmentStoreScatterGraphViewer.this, timeAlignmentInfo, true));
- }
- }
-
- @Override
- protected void setWindowRange(final long windowStartTime, final long windowEndTime) {
- super.setWindowRange(windowStartTime, windowEndTime);
- }
-
- @Override
- protected ILineSeries addSeries(@Nullable String seriesName) {
- ISeriesSet seriesSet = getSwtChart().getSeriesSet();
- ILineSeries series = (ILineSeries) seriesSet.createSeries(SeriesType.LINE, seriesName);
- series.setVisible(true);
- series.enableArea(false);
- series.setLineStyle(LineStyle.NONE);
- series.setSymbolType(PlotSymbolType.DIAMOND);
- return series;
- }
-
- /**
- * Set the data into the viewer. Will update model is analysis is completed
- * or run analysis if not completed
- *
- * @param analysis
- * Segment store analysis module
- */
- public void setData(@Nullable AbstractSegmentStoreAnalysisModule analysis) {
- if (analysis == null) {
- updateModel(null);
- return;
- }
- ISegmentStore<ISegment> results = analysis.getResults();
- // If results are not null, then analysis is completed and model can be
- // updated
- if (results != null) {
- updateModel(results);
- setAnalysisModule(analysis);
- return;
- }
- updateModel(null);
- analysis.addListener(fListener);
- analysis.schedule();
- setAnalysisModule(analysis);
- }
-
- /**
- * Returns the segment store analysis module
- *
- * @param trace
- * The trace to consider
- * @return the analysis module
- */
- protected @Nullable abstract AbstractSegmentStoreAnalysisModule getSegmentStoreAnalysisModule(ITmfTrace trace);
-
- // ------------------------------------------------------------------------
- // Signal handlers
- // ------------------------------------------------------------------------
-
- /**
- * @param signal
- * Signal received when a different trace is selected
- */
- @Override
- @TmfSignalHandler
- public void traceSelected(@Nullable TmfTraceSelectedSignal signal) {
- super.traceSelected(signal);
- if (signal == null) {
- return;
- }
- ITmfTrace trace = signal.getTrace();
- setTrace(trace);
- if (trace != null) {
- final TmfTimeRange timeRange = TmfTraceManager.getInstance().getCurrentTraceContext().getWindowRange();
- setWindowRange(
- timeRange.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(),
- timeRange.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue());
- setData(getSegmentStoreAnalysisModule(trace));
- updateRange(timeRange);
- }
- }
-
- /**
- * @param signal
- * Signal received when trace is opened
- */
- @Override
- @TmfSignalHandler
- public void traceOpened(@Nullable TmfTraceOpenedSignal signal) {
- super.traceOpened(signal);
- if (signal == null) {
- return;
- }
- ITmfTrace trace = signal.getTrace();
- setTrace(trace);
- if (trace != null) {
-
- final AbstractSegmentStoreAnalysisModule analysisModuleOfClass = getSegmentStoreAnalysisModule(trace);
- final TmfTimeRange timeRange = TmfTraceManager.getInstance().getCurrentTraceContext().getWindowRange();
- setWindowRange(
- getTimeInNanos(timeRange.getStartTime()),
- getTimeInNanos(timeRange.getEndTime()));
- setData(analysisModuleOfClass);
- }
-
- }
-
- private void updateRange(final @Nullable TmfTimeRange timeRange) {
- Job compactingJob = fCompactingJob;
- if (compactingJob != null && compactingJob.getState() == Job.RUNNING) {
- compactingJob.cancel();
- }
- compactingJob = new CompactingSegmentStoreQuery(NonNullUtils.checkNotNull(timeRange));
- fCompactingJob = compactingJob;
- compactingJob.schedule();
- }
-
- /**
- * @param signal
- * Signal received when last opened trace is closed
- */
- @Override
- @TmfSignalHandler
- public void traceClosed(@Nullable TmfTraceClosedSignal signal) {
- super.traceClosed(signal);
- if (signal != null) {
- // Check if there is no more opened trace
- if (TmfTraceManager.getInstance().getActiveTrace() == null) {
- AbstractSegmentStoreAnalysisModule analysis = getAnalysisModule();
- if (analysis != null) {
- analysis.removeListener(fListener);
- }
- clearContent();
- }
- }
- refresh();
- }
-
- /**
- * @param signal
- * Signal received when window range is updated
- */
- @Override
- @TmfSignalHandler
- public void windowRangeUpdated(@Nullable TmfWindowRangeUpdatedSignal signal) {
- super.windowRangeUpdated(signal);
- if (signal == null) {
- return;
- }
- if (getTrace() != null) {
- final TmfTimeRange currentRange = signal.getCurrentRange();
- updateRange(currentRange);
- } else {
- Activator.getDefault().logInfo("No Trace to update"); //$NON-NLS-1$
- }
- }
-
- private @Nullable AbstractSegmentStoreAnalysisModule getAnalysisModule() {
- return fAnalysisModule;
- }
-
- private void setAnalysisModule(AbstractSegmentStoreAnalysisModule analysisModule) {
- fAnalysisModule = analysisModule;
- }
-
- private static long getTimeInNanos(final ITmfTimestamp currentTime) {
- return currentTime.normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
- }
-}
\ No newline at end of file
+++ /dev/null
-/*******************************************************************************
- * 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:
- * France Lapointe Nguyen - Initial API and implementation
- * Bernd Hufmann - Move abstract class to TMF
- *******************************************************************************/
-
-package org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore;
-
-import org.eclipse.jdt.annotation.Nullable;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.SashForm;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.tracecompass.tmf.ui.views.TmfView;
-
-/**
- * View for displaying a segment store analysis in a table.
- *
- * @author France Lapointe Nguyen
- * @since 2.0
- */
-public abstract class AbstractSegmentStoreTableView extends TmfView {
-
- // ------------------------------------------------------------------------
- // Attributes
- // ------------------------------------------------------------------------
-
- private @Nullable AbstractSegmentStoreTableViewer fSegmentStoreViewer;
-
- // ------------------------------------------------------------------------
- // Constructor
- // ------------------------------------------------------------------------
-
- /**
- * Constructor
- */
- public AbstractSegmentStoreTableView() {
- super(""); //$NON-NLS-1$
- }
-
- // ------------------------------------------------------------------------
- // ViewPart
- // ------------------------------------------------------------------------
-
- @Override
- public void createPartControl(@Nullable Composite parent) {
- SashForm sf = new SashForm(parent, SWT.NONE);
- TableViewer tableViewer = new TableViewer(sf, SWT.FULL_SELECTION | SWT.VIRTUAL);
- fSegmentStoreViewer = createSegmentStoreViewer(tableViewer);
- setInitialData();
- }
-
- // ------------------------------------------------------------------------
- // Operations
- // ------------------------------------------------------------------------
-
- @Override
- public void setFocus() {
- if (fSegmentStoreViewer != null) {
- fSegmentStoreViewer.getTableViewer().getControl().setFocus();
- }
- }
-
- @Override
- public void dispose() {
- super.dispose();
- if (fSegmentStoreViewer != null) {
- fSegmentStoreViewer.dispose();
- }
- }
-
- /**
- * Returns the latency analysis table viewer instance
- *
- * @param tableViewer
- * the table viewer to use
- * @return the latency analysis table viewer instance
- */
- protected abstract AbstractSegmentStoreTableViewer createSegmentStoreViewer(TableViewer tableViewer);
-
- /**
- * Get the table viewer
- *
- * @return the table viewer, useful for testing
- */
- @Nullable
- public AbstractSegmentStoreTableViewer getSegmentStoreViewer() {
- return fSegmentStoreViewer;
- }
-
- /**
- * Set initial data into the viewer
- */
- private void setInitialData() {
- if (fSegmentStoreViewer != null) {
- fSegmentStoreViewer.setData(fSegmentStoreViewer.getAnalysisModule());
- }
- }
-}
+++ /dev/null
-/*******************************************************************************
- * 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:
- * France Lapointe Nguyen - Initial API and implementation
- * Bernd Hufmann - Move abstract class to TMF
- *******************************************************************************/
-
-package org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore;
-
-import org.eclipse.jdt.annotation.Nullable;
-import org.eclipse.jface.action.Action;
-import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.action.IMenuManager;
-import org.eclipse.jface.viewers.ColumnLabelProvider;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jface.viewers.StructuredSelection;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.tracecompass.analysis.timing.core.segmentstore.AbstractSegmentStoreAnalysisModule;
-import org.eclipse.tracecompass.analysis.timing.core.segmentstore.IAnalysisProgressListener;
-import org.eclipse.tracecompass.common.core.NonNullUtils;
-import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.Messages;
-import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.SegmentStoreContentProvider;
-import org.eclipse.tracecompass.segmentstore.core.ISegment;
-import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
-import org.eclipse.tracecompass.segmentstore.core.SegmentComparators;
-import org.eclipse.tracecompass.tmf.core.segment.ISegmentAspect;
-import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
-import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
-import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager;
-import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
-import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
-import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
-import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
-import org.eclipse.tracecompass.tmf.core.timestamp.TmfNanoTimestamp;
-import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestampFormat;
-import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
-import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
-import org.eclipse.tracecompass.tmf.ui.viewers.table.TmfSimpleTableViewer;
-
-/**
- * Displays the segment store analysis data in a column table
- *
- * @author France Lapointe Nguyen
- * @since 2.0
- */
-public abstract class AbstractSegmentStoreTableViewer extends TmfSimpleTableViewer {
-
- // ------------------------------------------------------------------------
- // Attributes
- // ------------------------------------------------------------------------
-
- /**
- * Abstract class for the column label provider for the segment store
- * analysis table viewer
- */
- private abstract class SegmentStoreTableColumnLabelProvider extends ColumnLabelProvider {
-
- @Override
- public String getText(@Nullable Object input) {
- if (!(input instanceof ISegment)) {
- /* Doubles as a null check */
- return ""; //$NON-NLS-1$
- }
- return getTextForSegment((ISegment) input);
- }
-
- public abstract String getTextForSegment(ISegment input);
- }
-
- /**
- * Listener to update the model with the segment store analysis results
- * once the analysis is fully completed
- */
- private final class AnalysisProgressListener implements IAnalysisProgressListener {
- @Override
- public void onComplete(AbstractSegmentStoreAnalysisModule activeAnalysis, ISegmentStore<ISegment> data) {
- // Check if the active trace was changed while the analysis was
- // running
- if (activeAnalysis.equals(fAnalysisModule)) {
- updateModel(data);
- }
- }
- }
-
- /**
- * Listener to select a range in other viewers when a cell of the segment
- * store table view is selected
- */
- private class TableSelectionListener extends SelectionAdapter {
- @Override
- public void widgetSelected(@Nullable SelectionEvent e) {
- ISegment selectedSegment = ((ISegment) NonNullUtils.checkNotNull(e).item.getData());
- ITmfTimestamp start = new TmfNanoTimestamp(selectedSegment.getStart());
- ITmfTimestamp end = new TmfNanoTimestamp(selectedSegment.getEnd());
- TmfSignalManager.dispatchSignal(new TmfSelectionRangeUpdatedSignal(AbstractSegmentStoreTableViewer.this, start, end));
- }
- }
-
- /**
- * Current segment store analysis module
- */
- private @Nullable AbstractSegmentStoreAnalysisModule fAnalysisModule = null;
-
- /**
- * Analysis progress listener
- */
- private AnalysisProgressListener fListener;
-
- /**
- * Flag to create columns once
- */
- boolean fColumnsCreated = false;
-
- // ------------------------------------------------------------------------
- // Constructor
- // ------------------------------------------------------------------------
-
- /**
- * Constructor
- *
- * @param tableViewer
- * Table viewer of the view
- */
- public AbstractSegmentStoreTableViewer(TableViewer tableViewer) {
- super(tableViewer);
- // Sort order of the content provider is by start time by default
- getTableViewer().setContentProvider(new SegmentStoreContentProvider());
- ITmfTrace trace = TmfTraceManager.getInstance().getActiveTrace();
- if (trace != null) {
- fAnalysisModule = getSegmentStoreAnalysisModule(trace);
- }
- createColumns();
- getTableViewer().getTable().addSelectionListener(new TableSelectionListener());
- addPackListener();
- fListener = new AnalysisProgressListener();
- }
-
- // ------------------------------------------------------------------------
- // Operations
- // ------------------------------------------------------------------------
-
- /**
- * Create default columns for start time, end time and duration
- */
- private void createColumns() {
- createColumn(Messages.SegmentStoreTableViewer_startTime, new SegmentStoreTableColumnLabelProvider() {
- @Override
- public String getTextForSegment(ISegment input) {
- return NonNullUtils.nullToEmptyString(TmfTimestampFormat.getDefaulTimeFormat().format(input.getStart()));
- }
- }, SegmentComparators.INTERVAL_START_COMPARATOR);
-
- createColumn(Messages.SegmentStoreTableViewer_endTime, new SegmentStoreTableColumnLabelProvider() {
- @Override
- public String getTextForSegment(ISegment input) {
- return NonNullUtils.nullToEmptyString(TmfTimestampFormat.getDefaulTimeFormat().format(input.getEnd()));
- }
- }, SegmentComparators.INTERVAL_END_COMPARATOR);
-
- createColumn(Messages.SegmentStoreTableViewer_duration, new SegmentStoreTableColumnLabelProvider() {
- @Override
- public String getTextForSegment(ISegment input) {
- return NonNullUtils.nullToEmptyString(Long.toString(input.getLength()));
- }
- }, SegmentComparators.INTERVAL_LENGTH_COMPARATOR);
- }
-
- /**
- * Create columns specific to the analysis
- */
- protected void createAnalysisColumns() {
- if (!fColumnsCreated) {
- AbstractSegmentStoreAnalysisModule analysis = getAnalysisModule();
- if (analysis != null) {
- for (final ISegmentAspect aspect : analysis.getSegmentAspects()) {
- createColumn(aspect.getName(), new SegmentStoreTableColumnLabelProvider() {
- @Override
- public String getTextForSegment(ISegment input) {
- return NonNullUtils.nullToEmptyString(aspect.resolve(input));
- }
- },
- aspect.getComparator());
- }
- }
- fColumnsCreated = true;
- }
- }
-
- /**
- * Update the data in the table viewer
- *
- * @param dataInput
- * New data input
- */
- public void updateModel(final @Nullable Object dataInput) {
- final TableViewer tableViewer = getTableViewer();
- Display.getDefault().asyncExec(new Runnable() {
- @Override
- public void run() {
- if (!tableViewer.getTable().isDisposed()) {
- // Go to the top of the table
- tableViewer.getTable().setTopIndex(0);
- // Reset selected row
- tableViewer.setSelection(StructuredSelection.EMPTY);
- if (dataInput == null) {
- tableViewer.setInput(null);
- tableViewer.setItemCount(0);
- return;
- }
- addPackListener();
- tableViewer.setInput(dataInput);
- SegmentStoreContentProvider contentProvider = (SegmentStoreContentProvider) getTableViewer().getContentProvider();
- tableViewer.setItemCount(contentProvider.getSegmentCount());
- }
- }
- });
- }
-
- /**
- * Set the data into the viewer. Will update model is analysis is completed
- * or run analysis if not completed
- *
- * @param analysis
- * segment store analysis module
- */
- public void setData(@Nullable AbstractSegmentStoreAnalysisModule analysis) {
- // Set the current segment store analysis module
- fAnalysisModule = analysis;
- if (analysis == null) {
- updateModel(null);
- return;
- }
-
- createAnalysisColumns();
-
- ISegmentStore<ISegment> results = analysis.getResults();
- // If results are not null, then analysis is completed and model can be
- // updated
- if (results != null) {
- updateModel(results);
- return;
- }
- // If results are null, then add completion listener and run analysis
- updateModel(null);
- analysis.addListener(fListener);
- analysis.schedule();
- }
-
- /**
- * Returns the segment store analysis module
- * @param trace
- * The trace to consider
- * @return the segment store analysis module
- */
- protected @Nullable abstract AbstractSegmentStoreAnalysisModule getSegmentStoreAnalysisModule(ITmfTrace trace);
-
- @Override
- protected void appendToTablePopupMenu(IMenuManager manager, IStructuredSelection sel) {
- final ISegment segment = (ISegment) sel.getFirstElement();
- if (segment != null) {
- IAction gotoStartTime = new Action(Messages.SegmentStoreTableViewer_goToStartEvent) {
- @Override
- public void run() {
- broadcast(new TmfSelectionRangeUpdatedSignal(AbstractSegmentStoreTableViewer.this, new TmfNanoTimestamp(segment.getStart())));
- }
- };
-
- IAction gotoEndTime = new Action(Messages.SegmentStoreTableViewer_goToEndEvent) {
- @Override
- public void run() {
- broadcast(new TmfSelectionRangeUpdatedSignal(AbstractSegmentStoreTableViewer.this, new TmfNanoTimestamp(segment.getEnd())));
- }
- };
-
- manager.add(gotoStartTime);
- manager.add(gotoEndTime);
- }
- }
-
- // ------------------------------------------------------------------------
- // Getters
- // ------------------------------------------------------------------------
-
- /**
- * Get current segment store analysis module
- *
- * @return current segment store analysis module
- */
- public @Nullable AbstractSegmentStoreAnalysisModule getAnalysisModule() {
- return fAnalysisModule;
- }
-
- // ------------------------------------------------------------------------
- // Signal handlers
- // ------------------------------------------------------------------------
-
- /**
- * Trace selected handler
- *
- * @param signal
- * Different opened trace (on which segment store analysis as
- * already been performed) has been selected
- */
- @TmfSignalHandler
- public void traceSelected(TmfTraceSelectedSignal signal) {
- ITmfTrace trace = signal.getTrace();
- if (trace != null) {
- setData(getSegmentStoreAnalysisModule(trace));
- }
- }
-
- /**
- * Trace opened handler
- *
- * @param signal
- * New trace (on which segment store analysis has not been
- * performed) is opened
- */
- @TmfSignalHandler
- public void traceOpened(TmfTraceOpenedSignal signal) {
- ITmfTrace trace = signal.getTrace();
- if (trace != null) {
- setData(getSegmentStoreAnalysisModule(trace));
- }
- }
-
- /**
- * Trace closed handler
- *
- * @param signal
- * Last opened trace was closed
- */
- @TmfSignalHandler
- public void traceClosed(TmfTraceClosedSignal signal) {
- // Check if there is no more opened trace
- if (TmfTraceManager.getInstance().getActiveTrace() == null) {
- if (!getTableViewer().getTable().isDisposed()) {
- getTableViewer().setInput(null);
- getTableViewer().setItemCount(0);
- refresh();
- }
-
- AbstractSegmentStoreAnalysisModule analysis = getAnalysisModule();
- if ((analysis != null)) {
- analysis.removeListener(fListener);
- }
- }
- }
-
- // ------------------------------------------------------------------------
- // Helper methods
- // ------------------------------------------------------------------------
-
- /*
- * Add the listener for SetData on the table
- */
- private void addPackListener() {
- getControl().addListener(SWT.SetData, new Listener() {
- @Override
- public void handleEvent(@Nullable Event event) {
- // Remove the listener before the pack
- getControl().removeListener(SWT.SetData, this);
-
- // Pack the column the first time data is set
- TableViewer tableViewer = getTableViewer();
- if (tableViewer != null) {
- for (TableColumn col : tableViewer.getTable().getColumns()) {
- col.pack();
- }
- }
- }
- });
- }
-}
+++ /dev/null
-/**********************************************************************
- * 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:
- * Bernd Hufmann - Initial API and implementation
- **********************************************************************/
-package org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore;
-
-import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
-
-import org.eclipse.jdt.annotation.Nullable;
-import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.Messages;
-import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
-import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
-import org.eclipse.tracecompass.tmf.ui.viewers.xycharts.ITmfChartTimeProvider;
-import org.eclipse.tracecompass.tmf.ui.viewers.xycharts.TmfClosestDataPointTooltipProvider;
-import org.swtchart.ISeries;
-
-/**
- * Tooltip provider for durations scatter charts. It displays the y value of
- * position x as well as it highlights the closest data point.
- *
- * @author Bernd Hufmann
- */
-public class SegmentStoreScatterGraphTooltipProvider extends TmfClosestDataPointTooltipProvider{
-
- // ------------------------------------------------------------------------
- // Constructors
- // ------------------------------------------------------------------------
- /**
- * Constructor for the segment store scatter chart tooltip provider.
- *
- * @param tmfChartViewer
- * - the parent chart viewer
- */
- public SegmentStoreScatterGraphTooltipProvider(ITmfChartTimeProvider tmfChartViewer) {
- super(tmfChartViewer);
- register();
- }
-
- // ------------------------------------------------------------------------
- // TmfClosestDataPointTooltipProvider
- // ------------------------------------------------------------------------
- @Override
- protected @Nullable String createToolTipText(Parameter param) {
- ISeries[] series = getChart().getSeriesSet().getSeries();
- int seriesIndex = param.getSeriesIndex();
- int dataIndex = param.getDataIndex();
- if ((series != null) && (seriesIndex < series.length)) {
- ISeries serie = series[seriesIndex];
- double[] xS = serie.getXSeries();
- double[] yS = serie.getYSeries();
- if ((xS != null) && (yS != null) && (dataIndex < xS.length) && (dataIndex < yS.length)) {
- StringBuffer buffer = new StringBuffer();
- buffer.append(checkNotNull(Messages.SegmentStoreScatterGraphViewer_xAxis)).append('=');
- buffer.append(new TmfTimestamp((long) xS[dataIndex] + getChartViewer().getTimeOffset(), ITmfTimestamp.NANOSECOND_SCALE).toString());
- buffer.append('\n');
- buffer.append(Messages.SegmentStoreScatterGraphViewer_yAxis).append('=');
- buffer.append((long) yS[dataIndex]);
- return buffer.toString();
- }
- }
- return null;
- }
-
-}
\ No newline at end of file
/******************************************************************************
- * Copyright (c) 2015 Ericsson
+ * Copyright (c) 2015, 2016 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.widgets.Composite;
-import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.AbstractSegmentStoreTableViewer;
+import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.table.AbstractSegmentStoreTableViewer;
import org.eclipse.tracecompass.segmentstore.core.ISegment;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
--- /dev/null
+/******************************************************************************
+ * Copyright (c) 2015, 2016 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:
+ * France Lapointe Nguyen - Initial API and implementation
+ * Bernd Hufmann - Extracted abstract class from LatencyScatterGraphViewer
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.scatter;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+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.jdt.annotation.Nullable;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.tracecompass.analysis.timing.core.segmentstore.AbstractSegmentStoreAnalysisModule;
+import org.eclipse.tracecompass.analysis.timing.core.segmentstore.IAnalysisProgressListener;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.internal.analysis.timing.ui.Activator;
+import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.scatter.SegmentStoreScatterGraphTooltipProvider;
+import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.scatter.Messages;
+import org.eclipse.tracecompass.segmentstore.core.ISegment;
+import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
+import org.eclipse.tracecompass.segmentstore.core.SegmentComparators;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager;
+import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
+import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
+import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
+import org.eclipse.tracecompass.tmf.core.signal.TmfWindowRangeUpdatedSignal;
+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.core.trace.TmfTraceManager;
+import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentInfo;
+import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentSignal;
+import org.eclipse.tracecompass.tmf.ui.viewers.xycharts.TmfChartTimeStampFormat;
+import org.eclipse.tracecompass.tmf.ui.viewers.xycharts.linecharts.TmfCommonXLineChartViewer;
+import org.swtchart.Chart;
+import org.swtchart.IAxis;
+import org.swtchart.IAxisTick;
+import org.swtchart.ILineSeries;
+import org.swtchart.ILineSeries.PlotSymbolType;
+import org.swtchart.ISeries.SeriesType;
+import org.swtchart.ISeriesSet;
+import org.swtchart.LineStyle;
+import org.swtchart.Range;
+
+/**
+ * Displays the segment store analysis data in a scatter graph
+ *
+ * @author France Lapointe Nguyen
+ * @author Matthew Khouzam - reduced memory usage
+ * @since 2.0
+ */
+public abstract class AbstractSegmentStoreScatterGraphViewer extends TmfCommonXLineChartViewer {
+
+ private final class CompactingSegmentStoreQuery extends Job {
+ private static final long MAX_POINTS = 1000;
+ private final TmfTimeRange fCurrentRange;
+
+ private CompactingSegmentStoreQuery(TmfTimeRange currentRange) {
+ super(Messages.SegmentStoreScatterGraphViewer_compactTitle);
+ fCurrentRange = currentRange;
+ }
+
+ @Override
+ protected IStatus run(@Nullable IProgressMonitor monitor) {
+ final IProgressMonitor statusMonitor = monitor;
+ if (statusMonitor == null) {
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Monitor is null"); //$NON-NLS-1$
+ }
+
+ AbstractSegmentStoreAnalysisModule module = getAnalysisModule();
+ final long startTimeInNanos = getTimeInNanos(fCurrentRange.getStartTime());
+ final long endTimeInNanos = getTimeInNanos(fCurrentRange.getEndTime());
+ if (module == null) {
+ setWindowRange(startTimeInNanos, endTimeInNanos);
+ redraw(statusMonitor, startTimeInNanos, startTimeInNanos, Collections.EMPTY_LIST);
+ return new Status(IStatus.WARNING, Activator.PLUGIN_ID, "Analysis module not available"); //$NON-NLS-1$
+ }
+
+ final ISegmentStore<ISegment> results = module.getResults();
+ if (results == null) {
+ setWindowRange(startTimeInNanos, endTimeInNanos);
+ redraw(statusMonitor, startTimeInNanos, startTimeInNanos, Collections.EMPTY_LIST);
+ return new Status(IStatus.INFO, Activator.PLUGIN_ID, "Analysis module does not have results"); //$NON-NLS-1$
+ }
+
+ final long startTime = fCurrentRange.getStartTime().getValue();
+ final long endTime = fCurrentRange.getEndTime().getValue();
+ fPixelStart = startTime;
+ fPixelSize = (endTime - startTime) / MAX_POINTS;
+ final Iterable<ISegment> intersectingElements = results.getIntersectingElements(startTime, endTime);
+
+ final List<ISegment> list = convertIterableToList(intersectingElements, statusMonitor);
+ final List<ISegment> displayData = (!list.isEmpty()) ? compactList(startTime, list, statusMonitor) : list;
+
+ setWindowRange(startTimeInNanos, endTimeInNanos);
+ redraw(statusMonitor, startTime, endTime, displayData);
+
+ if (statusMonitor.isCanceled()) {
+ return NonNullUtils.checkNotNull(Status.CANCEL_STATUS);
+ }
+ return NonNullUtils.checkNotNull(Status.OK_STATUS);
+
+ }
+
+ private void redraw(final IProgressMonitor statusMonitor, final long startTime, final long endTime, final List<ISegment> displayData) {
+ fDisplayData = displayData;
+ Display.getDefault().asyncExec(new Runnable() {
+
+ @Override
+ public void run() {
+ updateData(startTime, endTime, displayData.size(), statusMonitor);
+ }
+ });
+ }
+
+ private List<ISegment> compactList(final long startTime, final List<ISegment> listToCompact, final IProgressMonitor statusMonitor) {
+ List<ISegment> displayData = new ArrayList<>();
+ ISegment last = listToCompact.get(0);
+ if (last.getStart() >= startTime) {
+ displayData.add(last);
+ }
+ for (ISegment next : listToCompact) {
+ if (next.getStart() < startTime) {
+ continue;
+ }
+ if (statusMonitor.isCanceled()) {
+ return Collections.EMPTY_LIST;
+ }
+ if (!overlaps(last, next)) {
+ displayData.add(next);
+ last = next;
+ }
+ }
+ return displayData;
+ }
+
+ private List<ISegment> convertIterableToList(final Iterable<ISegment> iterable, final IProgressMonitor statusMonitor) {
+ final List<ISegment> list = new ArrayList<>();
+ for (ISegment seg : iterable) {
+ if (statusMonitor.isCanceled()) {
+ return Collections.EMPTY_LIST;
+ }
+ list.add(seg);
+ }
+ Collections.sort(list, SegmentComparators.INTERVAL_START_COMPARATOR);
+ return list;
+ }
+
+ private boolean overlaps(ISegment last, ISegment next) {
+ long timePerPix = fPixelSize;
+ final long start = last.getStart();
+ final long pixelStart = fPixelStart;
+ final long pixelDuration = start - pixelStart;
+ long startPixBoundL = pixelDuration / timePerPix * timePerPix + pixelStart;
+ long startPixBoundR = startPixBoundL + timePerPix;
+ final long currentStart = next.getStart();
+ if (currentStart >= startPixBoundL && currentStart <= startPixBoundR) {
+ long length = last.getLength();
+ long lengthNext = next.getLength();
+ long lengthLow = length / timePerPix * timePerPix;
+ long lengthHigh = lengthLow + timePerPix;
+ return (lengthNext >= lengthLow && lengthNext <= lengthHigh);
+ }
+ return false;
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Attributes
+ // ------------------------------------------------------------------------
+
+ /**
+ * Listener to update the model with the semgent store analysis results
+ * once the analysis is fully completed
+ */
+ private final class AnalysisProgressListener implements IAnalysisProgressListener {
+
+ @Override
+ public void onComplete(AbstractSegmentStoreAnalysisModule activeAnalysis, ISegmentStore<ISegment> results) {
+ // Only update the model if trace that was analyzed is active trace
+ if (activeAnalysis.equals(getAnalysisModule())) {
+ updateModel(results);
+ updateRange(TmfTraceManager.getInstance().getCurrentTraceContext().getWindowRange());
+ }
+ }
+ }
+
+ private long fPixelSize = -1;
+
+ private long fPixelStart = 0;
+ /**
+ * Data to display
+ */
+ private Collection<ISegment> fDisplayData = Collections.EMPTY_LIST;
+
+ /**
+ * Analysis completion listener
+ */
+ private AnalysisProgressListener fListener;
+
+ /**
+ * Current analysis module
+ */
+ private @Nullable AbstractSegmentStoreAnalysisModule fAnalysisModule;
+
+ private @Nullable Job fCompactingJob;
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructor
+ *
+ * @param parent
+ * parent composite
+ * @param title
+ * name of the graph
+ * @param xLabel
+ * name of the x axis
+ * @param yLabel
+ * name of the y axis
+ */
+ public AbstractSegmentStoreScatterGraphViewer(Composite parent, String title, String xLabel, String yLabel) {
+ super(parent, title, xLabel, yLabel);
+ setTooltipProvider(new SegmentStoreScatterGraphTooltipProvider(this));
+ fListener = new AnalysisProgressListener();
+ ITmfTrace trace = TmfTraceManager.getInstance().getActiveTrace();
+ initializeModule(trace);
+ getSwtChart().getLegend().setVisible(false);
+ }
+
+ private final void initializeModule(@Nullable ITmfTrace trace) {
+ if (trace != null) {
+ final AbstractSegmentStoreAnalysisModule analysisModuleOfClass = getSegmentStoreAnalysisModule(trace);
+ if (analysisModuleOfClass != null) {
+ analysisModuleOfClass.addListener(fListener);
+ setData(analysisModuleOfClass);
+ updateRange(TmfTraceManager.getInstance().getCurrentTraceContext().getWindowRange());
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Operations
+ // ------------------------------------------------------------------------
+
+ /**
+ * Update the data in the graph
+ *
+ * @param dataInput
+ * new model
+ */
+ public void updateModel(@Nullable ISegmentStore<ISegment> dataInput) {
+ // Update new window range
+ TmfTimeRange currentRange = TmfTraceManager.getInstance().getCurrentTraceContext().getWindowRange();
+ long currentStart = getTimeInNanos(currentRange.getStartTime());
+ long currentEnd = getTimeInNanos(currentRange.getEndTime());
+ if (dataInput == null) {
+ if (!getDisplay().isDisposed()) {
+ Display.getDefault().syncExec(new Runnable() {
+ @Override
+ public void run() {
+ clearContent();
+ }
+ });
+ }
+ fDisplayData = Collections.EMPTY_LIST;
+ } else {
+ Collection<ISegment> elements = (Collection<ISegment>) dataInput.getIntersectingElements(currentStart, currentEnd);
+ // getIntersectingElements can return an unsorted iterable, make
+ // sure our collection is sorted
+ ArrayList<ISegment> list = new ArrayList<>(elements);
+ Collections.sort(list, SegmentComparators.INTERVAL_START_COMPARATOR);
+ fDisplayData = list;
+ }
+ setWindowRange(currentStart, currentEnd);
+ updateRange(currentRange);
+ }
+
+ @Override
+ protected void initializeDataSource() {
+ ITmfTrace trace = getTrace();
+ initializeModule(trace);
+ if (trace != null) {
+ setData(getSegmentStoreAnalysisModule(trace));
+ }
+ }
+
+ @Override
+ protected void updateData(final long start, final long end, int nb, @Nullable IProgressMonitor monitor) {
+ // Third parameter is not used by implementation
+ // Determine data that needs to be visible
+ Collection<ISegment> data = fDisplayData;
+
+ final int dataSize = (nb == 0) ? data.size() : nb;
+ if (dataSize == 0 || end == start) {
+ return;
+ }
+
+ final double[] xSeries = new double[dataSize];
+ final double[] ySeries = new double[dataSize];
+ // For each visible segments, add start time to x value and duration
+ // for y value
+ Iterator<ISegment> modelIter = data.iterator();
+ long maxTempY = 1;
+ for (int i = 0; i < dataSize; i++) {
+ if (modelIter.hasNext()) {
+ ISegment segment = modelIter.next();
+ xSeries[i] = segment.getStart() - start;
+ ySeries[i] = segment.getLength();
+ maxTempY = Math.max(maxTempY, segment.getLength());
+ }
+ }
+ final long maxY = maxTempY;
+ setXAxis(xSeries);
+ final Chart swtChart = getSwtChart();
+ if (swtChart.isDisposed() || xSeries.length < 1) {
+ return;
+ }
+ swtChart.updateLayout();
+ setSeries(Messages.SegmentStoreScatterGraphViewer_legend, ySeries); // $NON-NLS-1$
+ final TmfChartTimeStampFormat tmfChartTimeStampFormat = new TmfChartTimeStampFormat(getTimeOffset());
+ ILineSeries series = (ILineSeries) swtChart.getSeriesSet().getSeries(Messages.SegmentStoreScatterGraphViewer_legend);
+ if (series == null) {
+ series = addSeries(Messages.SegmentStoreScatterGraphViewer_legend);
+ }
+ series.setXSeries(xSeries);
+ /* Find the minimal and maximum values in this series */
+ series.setYSeries(ySeries);
+
+ final IAxis xAxis = swtChart.getAxisSet().getXAxis(0);
+ IAxisTick xTick = xAxis.getTick();
+ xTick.setFormat(tmfChartTimeStampFormat);
+ xAxis.setRange(new Range(0.0, end - start));
+ if (maxY > 0.0) {
+ swtChart.getAxisSet().getYAxis(0).setRange(new Range(0.0, maxY));
+ }
+ swtChart.redraw();
+
+ if (isSendTimeAlignSignals()) {
+ // The width of the chart might have changed and its
+ // time axis might be misaligned with the other views
+ Point viewPos = AbstractSegmentStoreScatterGraphViewer.this.getParent().getParent().toDisplay(0, 0);
+ int axisPos = swtChart.toDisplay(0, 0).x + getPointAreaOffset();
+ int timeAxisOffset = axisPos - viewPos.x;
+ TmfTimeViewAlignmentInfo timeAlignmentInfo = new TmfTimeViewAlignmentInfo(getControl().getShell(), viewPos, timeAxisOffset);
+ TmfSignalManager.dispatchSignal(new TmfTimeViewAlignmentSignal(AbstractSegmentStoreScatterGraphViewer.this, timeAlignmentInfo, true));
+ }
+ }
+
+ @Override
+ protected void setWindowRange(final long windowStartTime, final long windowEndTime) {
+ super.setWindowRange(windowStartTime, windowEndTime);
+ }
+
+ @Override
+ protected ILineSeries addSeries(@Nullable String seriesName) {
+ ISeriesSet seriesSet = getSwtChart().getSeriesSet();
+ ILineSeries series = (ILineSeries) seriesSet.createSeries(SeriesType.LINE, seriesName);
+ series.setVisible(true);
+ series.enableArea(false);
+ series.setLineStyle(LineStyle.NONE);
+ series.setSymbolType(PlotSymbolType.DIAMOND);
+ return series;
+ }
+
+ /**
+ * Set the data into the viewer. Will update model is analysis is completed
+ * or run analysis if not completed
+ *
+ * @param analysis
+ * Segment store analysis module
+ */
+ public void setData(@Nullable AbstractSegmentStoreAnalysisModule analysis) {
+ if (analysis == null) {
+ updateModel(null);
+ return;
+ }
+ ISegmentStore<ISegment> results = analysis.getResults();
+ // If results are not null, then analysis is completed and model can be
+ // updated
+ if (results != null) {
+ updateModel(results);
+ setAnalysisModule(analysis);
+ return;
+ }
+ updateModel(null);
+ analysis.addListener(fListener);
+ analysis.schedule();
+ setAnalysisModule(analysis);
+ }
+
+ /**
+ * Returns the segment store analysis module
+ *
+ * @param trace
+ * The trace to consider
+ * @return the analysis module
+ */
+ protected @Nullable abstract AbstractSegmentStoreAnalysisModule getSegmentStoreAnalysisModule(ITmfTrace trace);
+
+ // ------------------------------------------------------------------------
+ // Signal handlers
+ // ------------------------------------------------------------------------
+
+ /**
+ * @param signal
+ * Signal received when a different trace is selected
+ */
+ @Override
+ @TmfSignalHandler
+ public void traceSelected(@Nullable TmfTraceSelectedSignal signal) {
+ super.traceSelected(signal);
+ if (signal == null) {
+ return;
+ }
+ ITmfTrace trace = signal.getTrace();
+ setTrace(trace);
+ if (trace != null) {
+ final TmfTimeRange timeRange = TmfTraceManager.getInstance().getCurrentTraceContext().getWindowRange();
+ setWindowRange(
+ timeRange.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(),
+ timeRange.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue());
+ setData(getSegmentStoreAnalysisModule(trace));
+ updateRange(timeRange);
+ }
+ }
+
+ /**
+ * @param signal
+ * Signal received when trace is opened
+ */
+ @Override
+ @TmfSignalHandler
+ public void traceOpened(@Nullable TmfTraceOpenedSignal signal) {
+ super.traceOpened(signal);
+ if (signal == null) {
+ return;
+ }
+ ITmfTrace trace = signal.getTrace();
+ setTrace(trace);
+ if (trace != null) {
+
+ final AbstractSegmentStoreAnalysisModule analysisModuleOfClass = getSegmentStoreAnalysisModule(trace);
+ final TmfTimeRange timeRange = TmfTraceManager.getInstance().getCurrentTraceContext().getWindowRange();
+ setWindowRange(
+ getTimeInNanos(timeRange.getStartTime()),
+ getTimeInNanos(timeRange.getEndTime()));
+ setData(analysisModuleOfClass);
+ }
+
+ }
+
+ private void updateRange(final @Nullable TmfTimeRange timeRange) {
+ Job compactingJob = fCompactingJob;
+ if (compactingJob != null && compactingJob.getState() == Job.RUNNING) {
+ compactingJob.cancel();
+ }
+ compactingJob = new CompactingSegmentStoreQuery(NonNullUtils.checkNotNull(timeRange));
+ fCompactingJob = compactingJob;
+ compactingJob.schedule();
+ }
+
+ /**
+ * @param signal
+ * Signal received when last opened trace is closed
+ */
+ @Override
+ @TmfSignalHandler
+ public void traceClosed(@Nullable TmfTraceClosedSignal signal) {
+ super.traceClosed(signal);
+ if (signal != null) {
+ // Check if there is no more opened trace
+ if (TmfTraceManager.getInstance().getActiveTrace() == null) {
+ AbstractSegmentStoreAnalysisModule analysis = getAnalysisModule();
+ if (analysis != null) {
+ analysis.removeListener(fListener);
+ }
+ clearContent();
+ }
+ }
+ refresh();
+ }
+
+ /**
+ * @param signal
+ * Signal received when window range is updated
+ */
+ @Override
+ @TmfSignalHandler
+ public void windowRangeUpdated(@Nullable TmfWindowRangeUpdatedSignal signal) {
+ super.windowRangeUpdated(signal);
+ if (signal == null) {
+ return;
+ }
+ if (getTrace() != null) {
+ final TmfTimeRange currentRange = signal.getCurrentRange();
+ updateRange(currentRange);
+ } else {
+ Activator.getDefault().logInfo("No Trace to update"); //$NON-NLS-1$
+ }
+ }
+
+ private @Nullable AbstractSegmentStoreAnalysisModule getAnalysisModule() {
+ return fAnalysisModule;
+ }
+
+ private void setAnalysisModule(AbstractSegmentStoreAnalysisModule analysisModule) {
+ fAnalysisModule = analysisModule;
+ }
+
+ private static long getTimeInNanos(final ITmfTimestamp currentTime) {
+ return currentTime.normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 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
+ *******************************************************************************/
+
+@org.eclipse.jdt.annotation.NonNullByDefault
+package org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.scatter;
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015, 2016 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:
+ * France Lapointe Nguyen - Initial API and implementation
+ * Bernd Hufmann - Move abstract class to TMF
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.table;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.tracecompass.tmf.ui.views.TmfView;
+
+/**
+ * View for displaying a segment store analysis in a table.
+ *
+ * @author France Lapointe Nguyen
+ * @since 2.0
+ */
+public abstract class AbstractSegmentStoreTableView extends TmfView {
+
+ // ------------------------------------------------------------------------
+ // Attributes
+ // ------------------------------------------------------------------------
+
+ private @Nullable AbstractSegmentStoreTableViewer fSegmentStoreViewer;
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructor
+ */
+ public AbstractSegmentStoreTableView() {
+ super(""); //$NON-NLS-1$
+ }
+
+ // ------------------------------------------------------------------------
+ // ViewPart
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void createPartControl(@Nullable Composite parent) {
+ SashForm sf = new SashForm(parent, SWT.NONE);
+ TableViewer tableViewer = new TableViewer(sf, SWT.FULL_SELECTION | SWT.VIRTUAL);
+ fSegmentStoreViewer = createSegmentStoreViewer(tableViewer);
+ setInitialData();
+ }
+
+ // ------------------------------------------------------------------------
+ // Operations
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void setFocus() {
+ if (fSegmentStoreViewer != null) {
+ fSegmentStoreViewer.getTableViewer().getControl().setFocus();
+ }
+ }
+
+ @Override
+ public void dispose() {
+ super.dispose();
+ if (fSegmentStoreViewer != null) {
+ fSegmentStoreViewer.dispose();
+ }
+ }
+
+ /**
+ * Returns the latency analysis table viewer instance
+ *
+ * @param tableViewer
+ * the table viewer to use
+ * @return the latency analysis table viewer instance
+ */
+ protected abstract AbstractSegmentStoreTableViewer createSegmentStoreViewer(TableViewer tableViewer);
+
+ /**
+ * Get the table viewer
+ *
+ * @return the table viewer, useful for testing
+ */
+ @Nullable
+ public AbstractSegmentStoreTableViewer getSegmentStoreViewer() {
+ return fSegmentStoreViewer;
+ }
+
+ /**
+ * Set initial data into the viewer
+ */
+ private void setInitialData() {
+ if (fSegmentStoreViewer != null) {
+ fSegmentStoreViewer.setData(fSegmentStoreViewer.getAnalysisModule());
+ }
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015, 2016 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:
+ * France Lapointe Nguyen - Initial API and implementation
+ * Bernd Hufmann - Move abstract class to TMF
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.table;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.tracecompass.analysis.timing.core.segmentstore.AbstractSegmentStoreAnalysisModule;
+import org.eclipse.tracecompass.analysis.timing.core.segmentstore.IAnalysisProgressListener;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.table.Messages;
+import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.table.SegmentStoreContentProvider;
+import org.eclipse.tracecompass.segmentstore.core.ISegment;
+import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
+import org.eclipse.tracecompass.segmentstore.core.SegmentComparators;
+import org.eclipse.tracecompass.tmf.core.segment.ISegmentAspect;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager;
+import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
+import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
+import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
+import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
+import org.eclipse.tracecompass.tmf.core.timestamp.TmfNanoTimestamp;
+import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestampFormat;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
+import org.eclipse.tracecompass.tmf.ui.viewers.table.TmfSimpleTableViewer;
+
+/**
+ * Displays the segment store analysis data in a column table
+ *
+ * @author France Lapointe Nguyen
+ * @since 2.0
+ */
+public abstract class AbstractSegmentStoreTableViewer extends TmfSimpleTableViewer {
+
+ // ------------------------------------------------------------------------
+ // Attributes
+ // ------------------------------------------------------------------------
+
+ /**
+ * Abstract class for the column label provider for the segment store
+ * analysis table viewer
+ */
+ private abstract class SegmentStoreTableColumnLabelProvider extends ColumnLabelProvider {
+
+ @Override
+ public String getText(@Nullable Object input) {
+ if (!(input instanceof ISegment)) {
+ /* Doubles as a null check */
+ return ""; //$NON-NLS-1$
+ }
+ return getTextForSegment((ISegment) input);
+ }
+
+ public abstract String getTextForSegment(ISegment input);
+ }
+
+ /**
+ * Listener to update the model with the segment store analysis results
+ * once the analysis is fully completed
+ */
+ private final class AnalysisProgressListener implements IAnalysisProgressListener {
+ @Override
+ public void onComplete(AbstractSegmentStoreAnalysisModule activeAnalysis, ISegmentStore<ISegment> data) {
+ // Check if the active trace was changed while the analysis was
+ // running
+ if (activeAnalysis.equals(fAnalysisModule)) {
+ updateModel(data);
+ }
+ }
+ }
+
+ /**
+ * Listener to select a range in other viewers when a cell of the segment
+ * store table view is selected
+ */
+ private class TableSelectionListener extends SelectionAdapter {
+ @Override
+ public void widgetSelected(@Nullable SelectionEvent e) {
+ ISegment selectedSegment = ((ISegment) NonNullUtils.checkNotNull(e).item.getData());
+ ITmfTimestamp start = new TmfNanoTimestamp(selectedSegment.getStart());
+ ITmfTimestamp end = new TmfNanoTimestamp(selectedSegment.getEnd());
+ TmfSignalManager.dispatchSignal(new TmfSelectionRangeUpdatedSignal(AbstractSegmentStoreTableViewer.this, start, end));
+ }
+ }
+
+ /**
+ * Current segment store analysis module
+ */
+ private @Nullable AbstractSegmentStoreAnalysisModule fAnalysisModule = null;
+
+ /**
+ * Analysis progress listener
+ */
+ private AnalysisProgressListener fListener;
+
+ /**
+ * Flag to create columns once
+ */
+ boolean fColumnsCreated = false;
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructor
+ *
+ * @param tableViewer
+ * Table viewer of the view
+ */
+ public AbstractSegmentStoreTableViewer(TableViewer tableViewer) {
+ super(tableViewer);
+ // Sort order of the content provider is by start time by default
+ getTableViewer().setContentProvider(new SegmentStoreContentProvider());
+ ITmfTrace trace = TmfTraceManager.getInstance().getActiveTrace();
+ if (trace != null) {
+ fAnalysisModule = getSegmentStoreAnalysisModule(trace);
+ }
+ createColumns();
+ getTableViewer().getTable().addSelectionListener(new TableSelectionListener());
+ addPackListener();
+ fListener = new AnalysisProgressListener();
+ }
+
+ // ------------------------------------------------------------------------
+ // Operations
+ // ------------------------------------------------------------------------
+
+ /**
+ * Create default columns for start time, end time and duration
+ */
+ private void createColumns() {
+ createColumn(Messages.SegmentStoreTableViewer_startTime, new SegmentStoreTableColumnLabelProvider() {
+ @Override
+ public String getTextForSegment(ISegment input) {
+ return NonNullUtils.nullToEmptyString(TmfTimestampFormat.getDefaulTimeFormat().format(input.getStart()));
+ }
+ }, SegmentComparators.INTERVAL_START_COMPARATOR);
+
+ createColumn(Messages.SegmentStoreTableViewer_endTime, new SegmentStoreTableColumnLabelProvider() {
+ @Override
+ public String getTextForSegment(ISegment input) {
+ return NonNullUtils.nullToEmptyString(TmfTimestampFormat.getDefaulTimeFormat().format(input.getEnd()));
+ }
+ }, SegmentComparators.INTERVAL_END_COMPARATOR);
+
+ createColumn(Messages.SegmentStoreTableViewer_duration, new SegmentStoreTableColumnLabelProvider() {
+ @Override
+ public String getTextForSegment(ISegment input) {
+ return NonNullUtils.nullToEmptyString(Long.toString(input.getLength()));
+ }
+ }, SegmentComparators.INTERVAL_LENGTH_COMPARATOR);
+ }
+
+ /**
+ * Create columns specific to the analysis
+ */
+ protected void createAnalysisColumns() {
+ if (!fColumnsCreated) {
+ AbstractSegmentStoreAnalysisModule analysis = getAnalysisModule();
+ if (analysis != null) {
+ for (final ISegmentAspect aspect : analysis.getSegmentAspects()) {
+ createColumn(aspect.getName(), new SegmentStoreTableColumnLabelProvider() {
+ @Override
+ public String getTextForSegment(ISegment input) {
+ return NonNullUtils.nullToEmptyString(aspect.resolve(input));
+ }
+ },
+ aspect.getComparator());
+ }
+ }
+ fColumnsCreated = true;
+ }
+ }
+
+ /**
+ * Update the data in the table viewer
+ *
+ * @param dataInput
+ * New data input
+ */
+ public void updateModel(final @Nullable Object dataInput) {
+ final TableViewer tableViewer = getTableViewer();
+ Display.getDefault().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ if (!tableViewer.getTable().isDisposed()) {
+ // Go to the top of the table
+ tableViewer.getTable().setTopIndex(0);
+ // Reset selected row
+ tableViewer.setSelection(StructuredSelection.EMPTY);
+ if (dataInput == null) {
+ tableViewer.setInput(null);
+ tableViewer.setItemCount(0);
+ return;
+ }
+ addPackListener();
+ tableViewer.setInput(dataInput);
+ SegmentStoreContentProvider contentProvider = (SegmentStoreContentProvider) getTableViewer().getContentProvider();
+ tableViewer.setItemCount(contentProvider.getSegmentCount());
+ }
+ }
+ });
+ }
+
+ /**
+ * Set the data into the viewer. Will update model is analysis is completed
+ * or run analysis if not completed
+ *
+ * @param analysis
+ * segment store analysis module
+ */
+ public void setData(@Nullable AbstractSegmentStoreAnalysisModule analysis) {
+ // Set the current segment store analysis module
+ fAnalysisModule = analysis;
+ if (analysis == null) {
+ updateModel(null);
+ return;
+ }
+
+ createAnalysisColumns();
+
+ ISegmentStore<ISegment> results = analysis.getResults();
+ // If results are not null, then analysis is completed and model can be
+ // updated
+ if (results != null) {
+ updateModel(results);
+ return;
+ }
+ // If results are null, then add completion listener and run analysis
+ updateModel(null);
+ analysis.addListener(fListener);
+ analysis.schedule();
+ }
+
+ /**
+ * Returns the segment store analysis module
+ * @param trace
+ * The trace to consider
+ * @return the segment store analysis module
+ */
+ protected @Nullable abstract AbstractSegmentStoreAnalysisModule getSegmentStoreAnalysisModule(ITmfTrace trace);
+
+ @Override
+ protected void appendToTablePopupMenu(IMenuManager manager, IStructuredSelection sel) {
+ final ISegment segment = (ISegment) sel.getFirstElement();
+ if (segment != null) {
+ IAction gotoStartTime = new Action(Messages.SegmentStoreTableViewer_goToStartEvent) {
+ @Override
+ public void run() {
+ broadcast(new TmfSelectionRangeUpdatedSignal(AbstractSegmentStoreTableViewer.this, new TmfNanoTimestamp(segment.getStart())));
+ }
+ };
+
+ IAction gotoEndTime = new Action(Messages.SegmentStoreTableViewer_goToEndEvent) {
+ @Override
+ public void run() {
+ broadcast(new TmfSelectionRangeUpdatedSignal(AbstractSegmentStoreTableViewer.this, new TmfNanoTimestamp(segment.getEnd())));
+ }
+ };
+
+ manager.add(gotoStartTime);
+ manager.add(gotoEndTime);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Getters
+ // ------------------------------------------------------------------------
+
+ /**
+ * Get current segment store analysis module
+ *
+ * @return current segment store analysis module
+ */
+ public @Nullable AbstractSegmentStoreAnalysisModule getAnalysisModule() {
+ return fAnalysisModule;
+ }
+
+ // ------------------------------------------------------------------------
+ // Signal handlers
+ // ------------------------------------------------------------------------
+
+ /**
+ * Trace selected handler
+ *
+ * @param signal
+ * Different opened trace (on which segment store analysis as
+ * already been performed) has been selected
+ */
+ @TmfSignalHandler
+ public void traceSelected(TmfTraceSelectedSignal signal) {
+ ITmfTrace trace = signal.getTrace();
+ if (trace != null) {
+ setData(getSegmentStoreAnalysisModule(trace));
+ }
+ }
+
+ /**
+ * Trace opened handler
+ *
+ * @param signal
+ * New trace (on which segment store analysis has not been
+ * performed) is opened
+ */
+ @TmfSignalHandler
+ public void traceOpened(TmfTraceOpenedSignal signal) {
+ ITmfTrace trace = signal.getTrace();
+ if (trace != null) {
+ setData(getSegmentStoreAnalysisModule(trace));
+ }
+ }
+
+ /**
+ * Trace closed handler
+ *
+ * @param signal
+ * Last opened trace was closed
+ */
+ @TmfSignalHandler
+ public void traceClosed(TmfTraceClosedSignal signal) {
+ // Check if there is no more opened trace
+ if (TmfTraceManager.getInstance().getActiveTrace() == null) {
+ if (!getTableViewer().getTable().isDisposed()) {
+ getTableViewer().setInput(null);
+ getTableViewer().setItemCount(0);
+ refresh();
+ }
+
+ AbstractSegmentStoreAnalysisModule analysis = getAnalysisModule();
+ if ((analysis != null)) {
+ analysis.removeListener(fListener);
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Helper methods
+ // ------------------------------------------------------------------------
+
+ /*
+ * Add the listener for SetData on the table
+ */
+ private void addPackListener() {
+ getControl().addListener(SWT.SetData, new Listener() {
+ @Override
+ public void handleEvent(@Nullable Event event) {
+ // Remove the listener before the pack
+ getControl().removeListener(SWT.SetData, this);
+
+ // Pack the column the first time data is set
+ TableViewer tableViewer = getTableViewer();
+ if (tableViewer != null) {
+ for (TableColumn col : tableViewer.getTable().getColumns()) {
+ col.pack();
+ }
+ }
+ }
+ });
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 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
+ *******************************************************************************/
+
+@org.eclipse.jdt.annotation.NonNullByDefault
+package org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.table;
+++ /dev/null
-/*******************************************************************************
- * 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:
- * France Lapointe Nguyen - Initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.osgi.util.NLS;
-
-/**
- * @author France Lapointe Nguyen
- * @since 2.0
- */
-@NonNullByDefault({})
-public class Messages extends NLS {
- private static final String BUNDLE_NAME = "org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.messages"; //$NON-NLS-1$
-
- /**
- * Name of the duration column
- */
- public static String SegmentStoreTableViewer_duration;
-
- /**
- * Name of the end time column
- */
- public static String SegmentStoreTableViewer_endTime;
-
- /**
- * Name of the start time column
- */
- public static String SegmentStoreTableViewer_startTime;
-
- /**
- * Title of action to goto start time time
- */
- public static String SegmentStoreTableViewer_goToStartEvent;
-
- /**
- * Title of action to goto end event
- */
- public static String SegmentStoreTableViewer_goToEndEvent;
- /**
- * Title of the scatter graph
- */
- public static String SegmentStoreScatterGraphViewer_title;
-
- /**
- * Title of the x axis of the scatter graph
- */
- public static String SegmentStoreScatterGraphViewer_xAxis;
-
- /**
- * Title of the y axis of the scatter graph
- */
- public static String SegmentStoreScatterGraphViewer_yAxis;
-
- /**
- * Legend
- */
- public static String SegmentStoreScatterGraphViewer_legend;
-
- /**
- * Name of the compacting job
- */
- public static String SegmentStoreScatterGraphViewer_compactTitle;
-
- static {
- // initialize resource bundle
- NLS.initializeMessages(BUNDLE_NAME, Messages.class);
- }
-
- private Messages() {
- }
-}
+++ /dev/null
-/*******************************************************************************
- * 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:
- * France Lapointe Nguyen - Initial API and implementation
- * Bernd Hufmann - MOve abstract class to TMF
- *******************************************************************************/
-
-package org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore;
-
-import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNullContents;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Comparator;
-
-import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.jdt.annotation.Nullable;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.tracecompass.segmentstore.core.ISegment;
-import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
-import org.eclipse.tracecompass.tmf.ui.viewers.table.ISortingLazyContentProvider;
-
-import com.google.common.collect.Iterables;
-
-/**
- * Content provider for the latency table viewers.
- *
- * @author France Lapointe Nguyen
- * @since 2.0
- */
-public class SegmentStoreContentProvider implements ISortingLazyContentProvider {
-
- /**
- * Array of all the segments in the segment store of the current trace
- */
- private ISegment @Nullable [] fSegmentArray = null;
-
- /**
- * Table viewer of the latency table viewer
- */
- private @Nullable TableViewer fTableViewer = null;
-
- /**
- * Segment comparator
- */
- private @Nullable Comparator<ISegment> fComparator = null;
-
- @Override
- public void updateElement(int index) {
- final TableViewer tableViewer = fTableViewer;
- final ISegment @Nullable [] segmentArray = fSegmentArray;
- if (tableViewer != null && segmentArray != null) {
- tableViewer.replace(segmentArray[index], index);
- }
- }
-
- @Override
- public void dispose() {
- fSegmentArray = null;
- fTableViewer = null;
- fComparator = null;
- }
-
- @Override
- public void inputChanged(@Nullable Viewer viewer, @Nullable Object oldInput, @Nullable Object newInput) {
- fTableViewer = (TableViewer) viewer;
- if (newInput instanceof Collection<?> || newInput instanceof ISegmentStore) {
- @SuppressWarnings("unchecked")
- Collection<ISegment> segmentStore = (Collection<@NonNull ISegment>) newInput;
- ISegment[] array = Iterables.toArray(segmentStore, ISegment.class);
- @NonNull ISegment[] checkedArray = checkNotNullContents(array);
- if (fComparator != null) {
- Arrays.sort(checkedArray, fComparator);
- }
- fSegmentArray = checkedArray;
- } else if (newInput instanceof ISegment[]) {
- /*
- * Ensure that there are no null elements in the array, so we can
- * set it back to fSegmentArray, which does not allow nulls.
- */
- @NonNull ISegment[] checkedArray = checkNotNullContents((@Nullable ISegment[]) newInput);
- if (fComparator != null) {
- Arrays.sort(checkedArray, fComparator);
- }
- fSegmentArray = checkedArray;
- } else {
- fSegmentArray = null;
- }
- }
-
- @Override
- public void setSortOrder(@Nullable Comparator<?> comparator) {
- @NonNull ISegment @Nullable [] segmentArray = fSegmentArray;
- if (comparator == null) {
- return;
- }
- if (segmentArray == null) {
- return;
- }
- final TableViewer tableViewer = fTableViewer;
- if (tableViewer == null) {
- return;
- }
- @SuppressWarnings("unchecked")
- Comparator<ISegment> comp = (Comparator<ISegment>) comparator;
- fComparator = comp;
- Arrays.sort(segmentArray, fComparator);
- tableViewer.refresh();
- }
-
- /**
- * Get the segment count
- *
- * @return the segment count
- */
- public int getSegmentCount() {
- ISegment[] segmentArray = fSegmentArray;
- return (segmentArray == null ? 0 : segmentArray.length);
- }
-}
+++ /dev/null
-SegmentStoreTableViewer_duration=Duration
-SegmentStoreTableViewer_endTime=End Time
-SegmentStoreTableViewer_startTime=Start Time
-SegmentStoreTableViewer_goToStartEvent=Go to start time
-SegmentStoreTableViewer_goToEndEvent=Go to end time
-
-SegmentStoreScatterGraphViewer_title=Latency vs Time
-SegmentStoreScatterGraphViewer_xAxis=Time
-SegmentStoreScatterGraphViewer_yAxis=Latency
-SegmentStoreScatterGraphViewer_legend=Duration
-SegmentStoreScatterGraphViewer_compactTitle=Compacting Duration Query
+++ /dev/null
-/*******************************************************************************
- * 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
- *******************************************************************************/
-
-@org.eclipse.jdt.annotation.NonNullByDefault
-package org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore;
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.scatter;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * @author France Bernd Hufmann
+ */
+@NonNullByDefault({})
+public class Messages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.scatter.messages"; //$NON-NLS-1$
+
+ /**
+ * Title of the scatter graph
+ */
+ public static String SegmentStoreScatterGraphViewer_title;
+
+ /**
+ * Title of the x axis of the scatter graph
+ */
+ public static String SegmentStoreScatterGraphViewer_xAxis;
+
+ /**
+ * Title of the y axis of the scatter graph
+ */
+ public static String SegmentStoreScatterGraphViewer_yAxis;
+
+ /**
+ * Legend
+ */
+ public static String SegmentStoreScatterGraphViewer_legend;
+
+ /**
+ * Name of the compacting job
+ */
+ public static String SegmentStoreScatterGraphViewer_compactTitle;
+
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+}
--- /dev/null
+/**********************************************************************
+ * Copyright (c) 2015, 2016 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:
+ * Bernd Hufmann - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.scatter;
+
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.scatter.Messages;
+import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
+import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
+import org.eclipse.tracecompass.tmf.ui.viewers.xycharts.ITmfChartTimeProvider;
+import org.eclipse.tracecompass.tmf.ui.viewers.xycharts.TmfClosestDataPointTooltipProvider;
+import org.swtchart.ISeries;
+
+/**
+ * Tooltip provider for durations scatter charts. It displays the y value of
+ * position x as well as it highlights the closest data point.
+ *
+ * @author Bernd Hufmann
+ */
+public class SegmentStoreScatterGraphTooltipProvider extends TmfClosestDataPointTooltipProvider{
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+ /**
+ * Constructor for the segment store scatter chart tooltip provider.
+ *
+ * @param tmfChartViewer
+ * - the parent chart viewer
+ */
+ public SegmentStoreScatterGraphTooltipProvider(ITmfChartTimeProvider tmfChartViewer) {
+ super(tmfChartViewer);
+ register();
+ }
+
+ // ------------------------------------------------------------------------
+ // TmfClosestDataPointTooltipProvider
+ // ------------------------------------------------------------------------
+ @Override
+ protected @Nullable String createToolTipText(Parameter param) {
+ ISeries[] series = getChart().getSeriesSet().getSeries();
+ int seriesIndex = param.getSeriesIndex();
+ int dataIndex = param.getDataIndex();
+ if ((series != null) && (seriesIndex < series.length)) {
+ ISeries serie = series[seriesIndex];
+ double[] xS = serie.getXSeries();
+ double[] yS = serie.getYSeries();
+ if ((xS != null) && (yS != null) && (dataIndex < xS.length) && (dataIndex < yS.length)) {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(checkNotNull(Messages.SegmentStoreScatterGraphViewer_xAxis)).append('=');
+ buffer.append(new TmfTimestamp((long) xS[dataIndex] + getChartViewer().getTimeOffset(), ITmfTimestamp.NANOSECOND_SCALE).toString());
+ buffer.append('\n');
+ buffer.append(Messages.SegmentStoreScatterGraphViewer_yAxis).append('=');
+ buffer.append((long) yS[dataIndex]);
+ return buffer.toString();
+ }
+ }
+ return null;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+###############################################################################
+# Copyright (c) 2016 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
+###############################################################################
+SegmentStoreScatterGraphViewer_title=Latency vs Time
+SegmentStoreScatterGraphViewer_xAxis=Time
+SegmentStoreScatterGraphViewer_yAxis=Latency
+SegmentStoreScatterGraphViewer_legend=Duration
+SegmentStoreScatterGraphViewer_compactTitle=Compacting Duration Query
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 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
+ *******************************************************************************/
+
+@org.eclipse.jdt.annotation.NonNullByDefault
+package org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.scatter;
--- /dev/null
+/*******************************************************************************
+ * 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:
+ * France Lapointe Nguyen - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.table;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * @author France Lapointe Nguyen
+ * @since 2.0
+ */
+@NonNullByDefault({})
+public class Messages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.table.messages"; //$NON-NLS-1$
+
+ /**
+ * Name of the duration column
+ */
+ public static String SegmentStoreTableViewer_duration;
+
+ /**
+ * Name of the end time column
+ */
+ public static String SegmentStoreTableViewer_endTime;
+
+ /**
+ * Name of the start time column
+ */
+ public static String SegmentStoreTableViewer_startTime;
+
+ /**
+ * Title of action to goto start time time
+ */
+ public static String SegmentStoreTableViewer_goToStartEvent;
+
+ /**
+ * Title of action to goto end event
+ */
+ public static String SegmentStoreTableViewer_goToEndEvent;
+
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * 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:
+ * France Lapointe Nguyen - Initial API and implementation
+ * Bernd Hufmann - MOve abstract class to TMF
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.table;
+
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNullContents;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.tracecompass.segmentstore.core.ISegment;
+import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
+import org.eclipse.tracecompass.tmf.ui.viewers.table.ISortingLazyContentProvider;
+
+import com.google.common.collect.Iterables;
+
+/**
+ * Content provider for the latency table viewers.
+ *
+ * @author France Lapointe Nguyen
+ * @since 2.0
+ */
+public class SegmentStoreContentProvider implements ISortingLazyContentProvider {
+
+ /**
+ * Array of all the segments in the segment store of the current trace
+ */
+ private ISegment @Nullable [] fSegmentArray = null;
+
+ /**
+ * Table viewer of the latency table viewer
+ */
+ private @Nullable TableViewer fTableViewer = null;
+
+ /**
+ * Segment comparator
+ */
+ private @Nullable Comparator<ISegment> fComparator = null;
+
+ @Override
+ public void updateElement(int index) {
+ final TableViewer tableViewer = fTableViewer;
+ final ISegment @Nullable [] segmentArray = fSegmentArray;
+ if (tableViewer != null && segmentArray != null) {
+ tableViewer.replace(segmentArray[index], index);
+ }
+ }
+
+ @Override
+ public void dispose() {
+ fSegmentArray = null;
+ fTableViewer = null;
+ fComparator = null;
+ }
+
+ @Override
+ public void inputChanged(@Nullable Viewer viewer, @Nullable Object oldInput, @Nullable Object newInput) {
+ fTableViewer = (TableViewer) viewer;
+ if (newInput instanceof Collection<?> || newInput instanceof ISegmentStore) {
+ @SuppressWarnings("unchecked")
+ Collection<ISegment> segmentStore = (Collection<@NonNull ISegment>) newInput;
+ ISegment[] array = Iterables.toArray(segmentStore, ISegment.class);
+ @NonNull ISegment[] checkedArray = checkNotNullContents(array);
+ if (fComparator != null) {
+ Arrays.sort(checkedArray, fComparator);
+ }
+ fSegmentArray = checkedArray;
+ } else if (newInput instanceof ISegment[]) {
+ /*
+ * Ensure that there are no null elements in the array, so we can
+ * set it back to fSegmentArray, which does not allow nulls.
+ */
+ @NonNull ISegment[] checkedArray = checkNotNullContents((@Nullable ISegment[]) newInput);
+ if (fComparator != null) {
+ Arrays.sort(checkedArray, fComparator);
+ }
+ fSegmentArray = checkedArray;
+ } else {
+ fSegmentArray = null;
+ }
+ }
+
+ @Override
+ public void setSortOrder(@Nullable Comparator<?> comparator) {
+ @NonNull ISegment @Nullable [] segmentArray = fSegmentArray;
+ if (comparator == null) {
+ return;
+ }
+ if (segmentArray == null) {
+ return;
+ }
+ final TableViewer tableViewer = fTableViewer;
+ if (tableViewer == null) {
+ return;
+ }
+ @SuppressWarnings("unchecked")
+ Comparator<ISegment> comp = (Comparator<ISegment>) comparator;
+ fComparator = comp;
+ Arrays.sort(segmentArray, fComparator);
+ tableViewer.refresh();
+ }
+
+ /**
+ * Get the segment count
+ *
+ * @return the segment count
+ */
+ public int getSegmentCount() {
+ ISegment[] segmentArray = fSegmentArray;
+ return (segmentArray == null ? 0 : segmentArray.length);
+ }
+}
--- /dev/null
+###############################################################################
+# Copyright (c) 2015, 2016 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
+###############################################################################
+SegmentStoreTableViewer_duration=Duration
+SegmentStoreTableViewer_endTime=End Time
+SegmentStoreTableViewer_startTime=Start Time
+SegmentStoreTableViewer_goToStartEvent=Go to start time
+SegmentStoreTableViewer_goToEndEvent=Go to end time
+
--- /dev/null
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+
+@org.eclipse.jdt.annotation.NonNullByDefault
+package org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.table;