From b9fff7ad3ad3a4836ed0876d592455b58b82f780 Mon Sep 17 00:00:00 2001 From: Bernd Hufmann Date: Tue, 13 Oct 2015 14:17:11 -0400 Subject: [PATCH] analysis: introduce abstract latency analysis table Change-Id: I29a893ad5ae3cca3bdf8450921467249a8bfd5a9 Signed-off-by: Bernd Hufmann Reviewed-on: https://git.eclipse.org/r/58093 Reviewed-by: Hudson CI Reviewed-by: Matthew Khouzam Tested-by: Matthew Khouzam Reviewed-by: Bernd Hufmann --- .../META-INF/MANIFEST.MF | 3 +- .../ui/views/latency/LatencyTableViewer.java | 298 +-------------- .../linux/ui/views/latency/LatencyView.java | 57 +-- .../META-INF/MANIFEST.MF | 4 +- .../AbstractSegmentStoreTableView.java | 96 +++++ .../AbstractSegmentStoreTableViewer.java | 349 ++++++++++++++++++ .../ui/views/segmentstore/package-info.java | 11 + .../ui/views/segmentstore/Messages.java | 73 ++++ .../SegmentStoreContentProvider.java} | 6 +- .../ui/views/segmentstore/messages.properties | 8 + .../ui/views/segmentstore/package-info.java | 11 + .../META-INF/MANIFEST.MF | 3 +- 12 files changed, 569 insertions(+), 350 deletions(-) create mode 100644 analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/AbstractSegmentStoreTableView.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/AbstractSegmentStoreTableViewer.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/package-info.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/Messages.java rename analysis/{org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/latency/LatencyContentProvider.java => org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/SegmentStoreContentProvider.java} (93%) create mode 100644 analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/messages.properties create mode 100644 analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/package-info.java diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/META-INF/MANIFEST.MF b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/META-INF/MANIFEST.MF index 52578f922e..38f1d7dced 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/META-INF/MANIFEST.MF +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/META-INF/MANIFEST.MF @@ -18,7 +18,8 @@ Require-Bundle: org.eclipse.ui, org.eclipse.tracecompass.tmf.ui, org.eclipse.tracecompass.tmf.ctf.core, org.eclipse.tracecompass.segmentstore.core, - org.eclipse.tracecompass.analysis.timing.core + org.eclipse.tracecompass.analysis.timing.core, + org.eclipse.tracecompass.analysis.timing.ui Import-Package: com.google.common.collect, org.swtchart Export-Package: org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow, diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/latency/LatencyTableViewer.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/latency/LatencyTableViewer.java index 1904f8040a..46fcfcdf2c 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/latency/LatencyTableViewer.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/latency/LatencyTableViewer.java @@ -13,111 +13,19 @@ package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency; 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.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.widgets.Display; import org.eclipse.tracecompass.analysis.os.linux.core.latency.LatencyAnalysis; 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.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.analysis.timing.ui.views.segmentstore.AbstractSegmentStoreTableViewer; import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; -import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager; import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils; -import org.eclipse.tracecompass.tmf.ui.viewers.table.TmfSimpleTableViewer; /** * Displays the latency analysis data in a column table * * @author France Lapointe Nguyen */ -public class LatencyTableViewer extends TmfSimpleTableViewer { - - // ------------------------------------------------------------------------ - // Attributes - // ------------------------------------------------------------------------ - - - /** - * Abstract class for the column label provider for the latency analysis - * table viewer - */ - private abstract class LatencyTableColumnLabelProvider 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 latency analysis results once the - * latency analysis is fully completed - */ - private final class AnalysisProgressListener implements IAnalysisProgressListener { - @Override - public void onComplete(AbstractSegmentStoreAnalysisModule activeAnalysis, ISegmentStore 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 latency - * table view is selected - */ - private class LatencyTableSelectionListener 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(LatencyTableViewer.this, start, end)); - } - } - - /** - * Current latency analysis module - */ - private @Nullable AbstractSegmentStoreAnalysisModule fAnalysisModule = null; - - /** - * Latency analysis completion listener - */ - private AnalysisProgressListener fListener; - - /** - * Flag to create columns once - */ - boolean fColumnsCreated = false; +public class LatencyTableViewer extends AbstractSegmentStoreTableViewer { // ------------------------------------------------------------------------ // Constructor @@ -127,214 +35,18 @@ public class LatencyTableViewer extends TmfSimpleTableViewer { * Constructor * * @param tableViewer - * Table viewer of the view + * The table viewer */ public LatencyTableViewer(TableViewer tableViewer) { super(tableViewer); - // Sort order of the content provider is by start time by default - getTableViewer().setContentProvider(new LatencyContentProvider()); - ITmfTrace trace = TmfTraceManager.getInstance().getActiveTrace(); - if (trace != null) { - fAnalysisModule = TmfTraceUtils.getAnalysisModuleOfClass(trace, LatencyAnalysis.class, LatencyAnalysis.ID); - } - createColumns(); - getTableViewer().getTable().addSelectionListener(new LatencyTableSelectionListener()); - fListener = new AnalysisProgressListener(); } // ------------------------------------------------------------------------ // Operations // ------------------------------------------------------------------------ - /** - * Create default columns for start time, end time and duration - */ - private void createColumns() { - createColumn(Messages.LatencyTableViewer_startTime, new LatencyTableColumnLabelProvider() { - @Override - public String getTextForSegment(ISegment input) { - return NonNullUtils.nullToEmptyString(TmfTimestampFormat.getDefaulTimeFormat().format(input.getStart())); - } - }, SegmentComparators.INTERVAL_START_COMPARATOR); - - createColumn(Messages.LatencyTableViewer_endTime, new LatencyTableColumnLabelProvider() { - @Override - public String getTextForSegment(ISegment input) { - return NonNullUtils.nullToEmptyString(TmfTimestampFormat.getDefaulTimeFormat().format(input.getEnd())); - } - }, SegmentComparators.INTERVAL_END_COMPARATOR); - - createColumn(Messages.LatencyTableViewer_duration, new LatencyTableColumnLabelProvider() { - @Override - public String getTextForSegment(ISegment input) { - return NonNullUtils.nullToEmptyString(Long.toString(input.getLength())); - } - }, SegmentComparators.INTERVAL_LENGTH_COMPARATOR); - } - - /** - * Create columns specific to the analysis - */ - private void createAnalysisColumns() { - if (!fColumnsCreated) { - AbstractSegmentStoreAnalysisModule analysis = getAnalysisModule(); - if (analysis != null) { - for (final ISegmentAspect aspect : analysis.getSegmentAspects()) { - createColumn(aspect.getName(), new LatencyTableColumnLabelProvider() { - @Override - public String getTextForSegment(ISegment input) { - return NonNullUtils.nullToEmptyString(aspect.resolve(input)); - } - }, - null); - } - } - fColumnsCreated = true; - } - } - - /** - * Update the data in the table viewer - * - * @param dataInput - * New data input - */ - public void updateModel(final @Nullable ISegmentStore 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; - } - tableViewer.setInput(dataInput); - LatencyContentProvider latencyContentProvider = (LatencyContentProvider) getTableViewer().getContentProvider(); - tableViewer.setItemCount(latencyContentProvider.getSegmentCount()); - } - } - }); - } - - /** - * Set the data into the viewer. Will update model is analysis is completed - * or run analysis if not completed - * - * @param analysis - * Latency analysis module - */ - public void setData(@Nullable AbstractSegmentStoreAnalysisModule analysis) { - // Set the current latency analysis module - fAnalysisModule = analysis; - if (analysis == null) { - updateModel(null); - return; - } - - createAnalysisColumns(); - - ISegmentStore 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(); - } - @Override - protected void appendToTablePopupMenu(IMenuManager manager, IStructuredSelection sel) { - final ISegment segment = (ISegment) sel.getFirstElement(); - - IAction gotoStartTime = new Action(Messages.LatencyView_goToStartEvent) { - @Override - public void run() { - broadcast(new TmfSelectionRangeUpdatedSignal(LatencyTableViewer.this, new TmfNanoTimestamp(segment.getStart()))); - } - }; - - IAction gotoEndTime = new Action(Messages.LatencyView_goToEndEvent) { - @Override - public void run() { - broadcast(new TmfSelectionRangeUpdatedSignal(LatencyTableViewer.this, new TmfNanoTimestamp(segment.getEnd()))); - } - }; - - manager.add(gotoStartTime); - manager.add(gotoEndTime); - } - - // ------------------------------------------------------------------------ - // Getters - // ------------------------------------------------------------------------ - - /** - * Get current latency analysis module - * - * @return current latency analysis module - */ - public @Nullable AbstractSegmentStoreAnalysisModule getAnalysisModule() { - return fAnalysisModule; - } - - // ------------------------------------------------------------------------ - // Signal handlers - // ------------------------------------------------------------------------ - - /** - * Trace selected handler - * - * @param signal - * Different opened trace (on which latency analysis as already - * been performed) has been selected - */ - @TmfSignalHandler - public void traceSelected(TmfTraceSelectedSignal signal) { - ITmfTrace trace = signal.getTrace(); - if (trace != null) { - setData(TmfTraceUtils.getAnalysisModuleOfClass(trace, LatencyAnalysis.class, LatencyAnalysis.ID)); - } - } - - /** - * Trace opened handler - * - * @param signal - * New trace (on which latency analysis has not been performed) - * is opened - */ - @TmfSignalHandler - public void traceOpened(TmfTraceOpenedSignal signal) { - ITmfTrace trace = signal.getTrace(); - if (trace != null) { - setData(TmfTraceUtils.getAnalysisModuleOfClass(trace, LatencyAnalysis.class, LatencyAnalysis.ID)); - } - } - - /** - * 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); - refresh(); - } - } + protected @Nullable AbstractSegmentStoreAnalysisModule getSegmentStoreAnalysisModule(ITmfTrace trace) { + return TmfTraceUtils.getAnalysisModuleOfClass(trace, LatencyAnalysis.class, LatencyAnalysis.ID); } } diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/latency/LatencyView.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/latency/LatencyView.java index b0fd96a713..08ee1919ea 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/latency/LatencyView.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/latency/LatencyView.java @@ -12,19 +12,16 @@ package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency; -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; +import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.AbstractSegmentStoreTableView; +import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.AbstractSegmentStoreTableViewer; /** * View for the latency analysis * * @author France Lapointe Nguyen */ -public class LatencyView extends TmfView { +public class LatencyView extends AbstractSegmentStoreTableView { // ------------------------------------------------------------------------ // Attributes @@ -33,56 +30,12 @@ public class LatencyView extends TmfView { /** The view's ID */ public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.views.latency"; //$NON-NLS-1$ - private @Nullable LatencyTableViewer fTableViewer; - // ------------------------------------------------------------------------ // Constructor // ------------------------------------------------------------------------ - /** - * Constructor - */ - public LatencyView() { - super(ID); - } - - // ------------------------------------------------------------------------ - // 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); - fTableViewer = new LatencyTableViewer(tableViewer); - setInitialData(); - } - - // ------------------------------------------------------------------------ - // Operations - // ------------------------------------------------------------------------ - - @Override - public void setFocus() { - if (fTableViewer != null) { - fTableViewer.getTableViewer().getControl().setFocus(); - } - } - - @Override - public void dispose() { - super.dispose(); - if (fTableViewer != null) { - fTableViewer.dispose(); - } - } - - /** - * Set initial data into the viewer - */ - private void setInitialData() { - if (fTableViewer != null) { - fTableViewer.setData(fTableViewer.getAnalysisModule()); - } + protected AbstractSegmentStoreTableViewer getSegmentStoreViewer(TableViewer tableViewer) { + return new LatencyTableViewer(tableViewer); } } diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/META-INF/MANIFEST.MF b/analysis/org.eclipse.tracecompass.analysis.timing.ui/META-INF/MANIFEST.MF index a5bd3cc46d..50f4a9c3ed 100644 --- a/analysis/org.eclipse.tracecompass.analysis.timing.ui/META-INF/MANIFEST.MF +++ b/analysis/org.eclipse.tracecompass.analysis.timing.ui/META-INF/MANIFEST.MF @@ -16,4 +16,6 @@ Require-Bundle: org.eclipse.ui, org.eclipse.tracecompass.segmentstore.core, org.eclipse.tracecompass.tmf.core, org.eclipse.tracecompass.tmf.ui -Export-Package: org.eclipse.tracecompass.internal.analysis.timing.ui +Export-Package: org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore, + org.eclipse.tracecompass.internal.analysis.timing.ui, + org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/AbstractSegmentStoreTableView.java b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/AbstractSegmentStoreTableView.java new file mode 100644 index 0000000000..11c9faff4a --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/AbstractSegmentStoreTableView.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * 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 fTableViewer; + + // ------------------------------------------------------------------------ + // 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); + fTableViewer = getSegmentStoreViewer(tableViewer); + setInitialData(); + } + + // ------------------------------------------------------------------------ + // Operations + // ------------------------------------------------------------------------ + + @Override + public void setFocus() { + if (fTableViewer != null) { + fTableViewer.getTableViewer().getControl().setFocus(); + } + } + + @Override + public void dispose() { + super.dispose(); + if (fTableViewer != null) { + fTableViewer.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 getSegmentStoreViewer(TableViewer tableViewer); + + /** + * Set initial data into the viewer + */ + private void setInitialData() { + if (fTableViewer != null) { + fTableViewer.setData(fTableViewer.getAnalysisModule()); + } + } +} diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/AbstractSegmentStoreTableViewer.java b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/AbstractSegmentStoreTableViewer.java new file mode 100644 index 0000000000..aabe29c499 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/AbstractSegmentStoreTableViewer.java @@ -0,0 +1,349 @@ +/******************************************************************************* + * 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.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +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.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 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()); + 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)); + } + }, + null); + } + } + fColumnsCreated = true; + } + } + + /** + * Update the data in the table viewer + * + * @param dataInput + * New data input + */ + public void updateModel(final @Nullable ISegmentStore 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; + } + 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 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(); + + 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); + refresh(); + } + } + } +} diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/package-info.java b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/package-info.java new file mode 100644 index 0000000000..3ed13b7909 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/package-info.java @@ -0,0 +1,11 @@ +/******************************************************************************* + * 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.analysis.timing.ui.views.segmentstore; diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/Messages.java b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/Messages.java new file mode 100644 index 0000000000..5c0f92e53f --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/Messages.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * 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(false) +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 the scatter graph + */ + public static String LatencyView_title; + + /** + * Title of the x axis of the scatter graph + */ + public static String LatencyView_xAxis; + + /** + * Title of the y axis of the scatter graph + */ + public static String LatencyView_yAxis; + + /** + * 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() { + } +} diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/latency/LatencyContentProvider.java b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/SegmentStoreContentProvider.java similarity index 93% rename from analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/latency/LatencyContentProvider.java rename to analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/SegmentStoreContentProvider.java index ec15245cbb..9a6919a7ef 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/latency/LatencyContentProvider.java +++ b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/SegmentStoreContentProvider.java @@ -8,9 +8,10 @@ * * Contributors: * France Lapointe Nguyen - Initial API and implementation + * Bernd Hufmann - MOve abstract class to TMF *******************************************************************************/ -package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency; +package org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore; import java.util.Arrays; import java.util.Comparator; @@ -28,8 +29,9 @@ import com.google.common.collect.Iterables; * Content provider for the latency table viewers. * * @author France Lapointe Nguyen + * @since 2.0 */ -public class LatencyContentProvider implements ISortingLazyContentProvider { +public class SegmentStoreContentProvider implements ISortingLazyContentProvider { /** * Array of all the segments in the segment store of the current trace diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/messages.properties b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/messages.properties new file mode 100644 index 0000000000..e9fc9ef994 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/messages.properties @@ -0,0 +1,8 @@ +SegmentStoreTableViewer_duration=Duration +SegmentStoreTableViewer_endTime=End Time +SegmentStoreTableViewer_startTime=Start Time +LatencyView_title=Latency vs Time +LatencyView_xAxis=Time +LatencyView_yAxis=Latency +SegmentStoreTableViewer_goToStartEvent=Go to start time +SegmentStoreTableViewer_goToEndEvent=Go to end time diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/package-info.java b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/package-info.java new file mode 100644 index 0000000000..11c569e37c --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/package-info.java @@ -0,0 +1,11 @@ +/******************************************************************************* + * 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; diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/META-INF/MANIFEST.MF b/tmf/org.eclipse.tracecompass.tmf.ui/META-INF/MANIFEST.MF index ca4e37e5e7..cfa50dca6a 100644 --- a/tmf/org.eclipse.tracecompass.tmf.ui/META-INF/MANIFEST.MF +++ b/tmf/org.eclipse.tracecompass.tmf.ui/META-INF/MANIFEST.MF @@ -20,7 +20,8 @@ Require-Bundle: org.eclipse.core.expressions, org.eclipse.ui.navigator.resources, org.swtchart, com.ibm.icu, - org.eclipse.linuxtools.dataviewers.piechart + org.eclipse.linuxtools.dataviewers.piechart, + org.eclipse.tracecompass.segmentstore.core;bundle-version="1.0.0" Export-Package: org.eclipse.tracecompass.internal.tmf.ui;x-friends:="org.eclipse.tracecompass.tmf.ui.tests,org.eclipse.tracecompass.tmf.ctf.ui.tests", org.eclipse.tracecompass.internal.tmf.ui.commands;x-internal:=true, org.eclipse.tracecompass.internal.tmf.ui.dialogs;x-internal:=true, -- 2.34.1