1 /*******************************************************************************
2 * Copyright (c) 2015, 2016 Ericsson
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * France Lapointe Nguyen - Initial API and implementation
11 * Bernd Hufmann - Move abstract class to TMF
12 *******************************************************************************/
14 package org
.eclipse
.tracecompass
.analysis
.timing
.ui
.views
.segmentstore
.table
;
16 import org
.eclipse
.jdt
.annotation
.Nullable
;
17 import org
.eclipse
.jface
.action
.Action
;
18 import org
.eclipse
.jface
.action
.IAction
;
19 import org
.eclipse
.jface
.action
.IMenuManager
;
20 import org
.eclipse
.jface
.viewers
.ColumnLabelProvider
;
21 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
22 import org
.eclipse
.jface
.viewers
.StructuredSelection
;
23 import org
.eclipse
.jface
.viewers
.TableViewer
;
24 import org
.eclipse
.swt
.SWT
;
25 import org
.eclipse
.swt
.events
.SelectionAdapter
;
26 import org
.eclipse
.swt
.events
.SelectionEvent
;
27 import org
.eclipse
.swt
.widgets
.Display
;
28 import org
.eclipse
.swt
.widgets
.Event
;
29 import org
.eclipse
.swt
.widgets
.Listener
;
30 import org
.eclipse
.swt
.widgets
.TableColumn
;
31 import org
.eclipse
.tracecompass
.analysis
.timing
.core
.segmentstore
.IAnalysisProgressListener
;
32 import org
.eclipse
.tracecompass
.analysis
.timing
.core
.segmentstore
.ISegmentStoreProvider
;
33 import org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
;
34 import org
.eclipse
.tracecompass
.internal
.analysis
.timing
.ui
.views
.segmentstore
.table
.Messages
;
35 import org
.eclipse
.tracecompass
.internal
.analysis
.timing
.ui
.views
.segmentstore
.table
.SegmentStoreContentProvider
;
36 import org
.eclipse
.tracecompass
.segmentstore
.core
.ISegment
;
37 import org
.eclipse
.tracecompass
.segmentstore
.core
.ISegmentStore
;
38 import org
.eclipse
.tracecompass
.segmentstore
.core
.SegmentComparators
;
39 import org
.eclipse
.tracecompass
.tmf
.core
.analysis
.IAnalysisModule
;
40 import org
.eclipse
.tracecompass
.tmf
.core
.segment
.ISegmentAspect
;
41 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSelectionRangeUpdatedSignal
;
42 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalHandler
;
43 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalManager
;
44 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceClosedSignal
;
45 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceOpenedSignal
;
46 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceSelectedSignal
;
47 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
48 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfNanoTimestamp
;
49 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimestampFormat
;
50 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
51 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
52 import org
.eclipse
.tracecompass
.tmf
.ui
.viewers
.table
.TmfSimpleTableViewer
;
55 * Displays the segment store provider data in a column table
57 * @author France Lapointe Nguyen
60 public abstract class AbstractSegmentStoreTableViewer
extends TmfSimpleTableViewer
{
62 // ------------------------------------------------------------------------
64 // ------------------------------------------------------------------------
67 * Abstract class for the column label provider for the segment store
68 * provider table viewer
70 private abstract class SegmentStoreTableColumnLabelProvider
extends ColumnLabelProvider
{
73 public String
getText(@Nullable Object input
) {
74 if (!(input
instanceof ISegment
)) {
75 /* Doubles as a null check */
76 return ""; //$NON-NLS-1$
78 return getTextForSegment((ISegment
) input
);
81 public abstract String
getTextForSegment(ISegment input
);
85 * Listener to update the model with the segment store provider results once
86 * its store is fully completed
88 private final class SegmentStoreProviderProgressListener
implements IAnalysisProgressListener
{
90 public void onComplete(ISegmentStoreProvider activeProvider
, ISegmentStore
<ISegment
> data
) {
91 // Check if the active trace was changed while the provider was
92 // building its segment store
93 if (activeProvider
.equals(fSegmentProvider
)) {
100 * Listener to select a range in other viewers when a cell of the segment
101 * store table view is selected
103 private class TableSelectionListener
extends SelectionAdapter
{
105 public void widgetSelected(@Nullable SelectionEvent e
) {
106 ISegment selectedSegment
= ((ISegment
) NonNullUtils
.checkNotNull(e
).item
.getData());
107 ITmfTimestamp start
= new TmfNanoTimestamp(selectedSegment
.getStart());
108 ITmfTimestamp end
= new TmfNanoTimestamp(selectedSegment
.getEnd());
109 TmfSignalManager
.dispatchSignal(new TmfSelectionRangeUpdatedSignal(AbstractSegmentStoreTableViewer
.this, start
, end
));
114 * Current segment store provider
116 private @Nullable ISegmentStoreProvider fSegmentProvider
= null;
119 * provider progress listener
121 private SegmentStoreProviderProgressListener fListener
;
124 * Flag to create columns once
126 boolean fColumnsCreated
= false;
128 // ------------------------------------------------------------------------
130 // ------------------------------------------------------------------------
136 * Table viewer of the view
138 public AbstractSegmentStoreTableViewer(TableViewer tableViewer
) {
140 // Sort order of the content provider is by start time by default
141 getTableViewer().setContentProvider(new SegmentStoreContentProvider());
142 ITmfTrace trace
= TmfTraceManager
.getInstance().getActiveTrace();
144 fSegmentProvider
= getSegmentStoreProvider(trace
);
147 getTableViewer().getTable().addSelectionListener(new TableSelectionListener());
149 fListener
= new SegmentStoreProviderProgressListener();
152 // ------------------------------------------------------------------------
154 // ------------------------------------------------------------------------
157 * Create default columns for start time, end time and duration
159 private void createColumns() {
160 createColumn(Messages
.SegmentStoreTableViewer_startTime
, new SegmentStoreTableColumnLabelProvider() {
162 public String
getTextForSegment(ISegment input
) {
163 return NonNullUtils
.nullToEmptyString(TmfTimestampFormat
.getDefaulTimeFormat().format(input
.getStart()));
165 }, SegmentComparators
.INTERVAL_START_COMPARATOR
);
167 createColumn(Messages
.SegmentStoreTableViewer_endTime
, new SegmentStoreTableColumnLabelProvider() {
169 public String
getTextForSegment(ISegment input
) {
170 return NonNullUtils
.nullToEmptyString(TmfTimestampFormat
.getDefaulTimeFormat().format(input
.getEnd()));
172 }, SegmentComparators
.INTERVAL_END_COMPARATOR
);
174 createColumn(Messages
.SegmentStoreTableViewer_duration
, new SegmentStoreTableColumnLabelProvider() {
176 public String
getTextForSegment(ISegment input
) {
177 return NonNullUtils
.nullToEmptyString(Long
.toString(input
.getLength()));
179 }, SegmentComparators
.INTERVAL_LENGTH_COMPARATOR
);
183 * Create columns specific to the provider
185 protected void createProviderColumns() {
186 if (!fColumnsCreated
) {
187 ISegmentStoreProvider provider
= getSegmentProvider();
188 if (provider
!= null) {
189 for (final ISegmentAspect aspect
: provider
.getSegmentAspects()) {
190 createColumn(aspect
.getName(), new SegmentStoreTableColumnLabelProvider() {
192 public String
getTextForSegment(ISegment input
) {
193 return NonNullUtils
.nullToEmptyString(aspect
.resolve(input
));
196 aspect
.getComparator());
199 fColumnsCreated
= true;
204 * Update the data in the table viewer
209 public void updateModel(final @Nullable Object dataInput
) {
210 final TableViewer tableViewer
= getTableViewer();
211 Display
.getDefault().asyncExec(new Runnable() {
214 if (!tableViewer
.getTable().isDisposed()) {
215 // Go to the top of the table
216 tableViewer
.getTable().setTopIndex(0);
217 // Reset selected row
218 tableViewer
.setSelection(StructuredSelection
.EMPTY
);
219 if (dataInput
== null) {
220 tableViewer
.setInput(null);
221 tableViewer
.setItemCount(0);
225 tableViewer
.setInput(dataInput
);
226 SegmentStoreContentProvider contentProvider
= (SegmentStoreContentProvider
) getTableViewer().getContentProvider();
227 tableViewer
.setItemCount(contentProvider
.getSegmentCount());
234 * Set the data into the viewer. It will update the model. If the provider
235 * is an analysis, the analysis will be scheduled.
238 * segment store provider
240 public void setData(@Nullable ISegmentStoreProvider provider
) {
241 // Set the current segment store provider
242 fSegmentProvider
= provider
;
243 if (provider
== null) {
248 createProviderColumns();
250 ISegmentStore
<ISegment
> segStore
= provider
.getSegmentStore();
251 // If results are not null, then the segment of the provider is ready
252 // and model can be updated
253 if (segStore
!= null) {
254 updateModel(segStore
);
257 // If results are null, then add completion listener and if the provider
258 // is an analysis, run the analysis
260 provider
.addListener(fListener
);
261 if (provider
instanceof IAnalysisModule
) {
262 ((IAnalysisModule
) provider
).schedule();
267 * Returns the segment store provider
270 * The trace to consider
271 * @return the segment store provider
273 protected @Nullable abstract ISegmentStoreProvider
getSegmentStoreProvider(ITmfTrace trace
);
276 protected void appendToTablePopupMenu(IMenuManager manager
, IStructuredSelection sel
) {
277 final ISegment segment
= (ISegment
) sel
.getFirstElement();
278 if (segment
!= null) {
279 IAction gotoStartTime
= new Action(Messages
.SegmentStoreTableViewer_goToStartEvent
) {
282 broadcast(new TmfSelectionRangeUpdatedSignal(AbstractSegmentStoreTableViewer
.this, new TmfNanoTimestamp(segment
.getStart())));
286 IAction gotoEndTime
= new Action(Messages
.SegmentStoreTableViewer_goToEndEvent
) {
289 broadcast(new TmfSelectionRangeUpdatedSignal(AbstractSegmentStoreTableViewer
.this, new TmfNanoTimestamp(segment
.getEnd())));
293 manager
.add(gotoStartTime
);
294 manager
.add(gotoEndTime
);
298 // ------------------------------------------------------------------------
300 // ------------------------------------------------------------------------
303 * Get current segment store provider
305 * @return current segment store provider
307 public @Nullable ISegmentStoreProvider
getSegmentProvider() {
308 return fSegmentProvider
;
311 // ------------------------------------------------------------------------
313 // ------------------------------------------------------------------------
316 * Trace selected handler
319 * Different opened trace (on which segment store analysis as
320 * already been performed) has been selected
323 public void traceSelected(TmfTraceSelectedSignal signal
) {
324 ITmfTrace trace
= signal
.getTrace();
326 setData(getSegmentStoreProvider(trace
));
331 * Trace opened handler
334 * New trace (on which segment store analysis has not been
335 * performed) is opened
338 public void traceOpened(TmfTraceOpenedSignal signal
) {
339 ITmfTrace trace
= signal
.getTrace();
341 setData(getSegmentStoreProvider(trace
));
346 * Trace closed handler
349 * Last opened trace was closed
352 public void traceClosed(TmfTraceClosedSignal signal
) {
353 // Check if there is no more opened trace
354 if (TmfTraceManager
.getInstance().getActiveTrace() == null) {
355 if (!getTableViewer().getTable().isDisposed()) {
356 getTableViewer().setInput(null);
357 getTableViewer().setItemCount(0);
361 ISegmentStoreProvider provider
= getSegmentProvider();
362 if ((provider
!= null)) {
363 provider
.removeListener(fListener
);
368 // ------------------------------------------------------------------------
370 // ------------------------------------------------------------------------
373 * Add the listener for SetData on the table
375 private void addPackListener() {
376 getControl().addListener(SWT
.SetData
, new Listener() {
378 public void handleEvent(@Nullable Event event
) {
379 // Remove the listener before the pack
380 getControl().removeListener(SWT
.SetData
, this);
382 // Pack the column the first time data is set
383 TableViewer tableViewer
= getTableViewer();
384 if (tableViewer
!= null) {
385 for (TableColumn col
: tableViewer
.getTable().getColumns()) {