1 /*******************************************************************************
2 * Copyright (c) 2015 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
;
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
.AbstractSegmentStoreAnalysisModule
;
32 import org
.eclipse
.tracecompass
.analysis
.timing
.core
.segmentstore
.IAnalysisProgressListener
;
33 import org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
;
34 import org
.eclipse
.tracecompass
.internal
.analysis
.timing
.ui
.views
.segmentstore
.Messages
;
35 import org
.eclipse
.tracecompass
.internal
.analysis
.timing
.ui
.views
.segmentstore
.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
.segment
.ISegmentAspect
;
40 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSelectionRangeUpdatedSignal
;
41 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalHandler
;
42 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalManager
;
43 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceClosedSignal
;
44 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceOpenedSignal
;
45 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceSelectedSignal
;
46 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
47 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfNanoTimestamp
;
48 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimestampFormat
;
49 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
50 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
51 import org
.eclipse
.tracecompass
.tmf
.ui
.viewers
.table
.TmfSimpleTableViewer
;
54 * Displays the segment store analysis data in a column table
56 * @author France Lapointe Nguyen
59 public abstract class AbstractSegmentStoreTableViewer
extends TmfSimpleTableViewer
{
61 // ------------------------------------------------------------------------
63 // ------------------------------------------------------------------------
66 * Abstract class for the column label provider for the segment store
67 * analysis table viewer
69 private abstract class SegmentStoreTableColumnLabelProvider
extends ColumnLabelProvider
{
72 public String
getText(@Nullable Object input
) {
73 if (!(input
instanceof ISegment
)) {
74 /* Doubles as a null check */
75 return ""; //$NON-NLS-1$
77 return getTextForSegment((ISegment
) input
);
80 public abstract String
getTextForSegment(ISegment input
);
84 * Listener to update the model with the segment store analysis results
85 * once the analysis is fully completed
87 private final class AnalysisProgressListener
implements IAnalysisProgressListener
{
89 public void onComplete(AbstractSegmentStoreAnalysisModule activeAnalysis
, ISegmentStore
<ISegment
> data
) {
90 // Check if the active trace was changed while the analysis was
92 if (activeAnalysis
.equals(fAnalysisModule
)) {
99 * Listener to select a range in other viewers when a cell of the segment
100 * store table view is selected
102 private class TableSelectionListener
extends SelectionAdapter
{
104 public void widgetSelected(@Nullable SelectionEvent e
) {
105 ISegment selectedSegment
= ((ISegment
) NonNullUtils
.checkNotNull(e
).item
.getData());
106 ITmfTimestamp start
= new TmfNanoTimestamp(selectedSegment
.getStart());
107 ITmfTimestamp end
= new TmfNanoTimestamp(selectedSegment
.getEnd());
108 TmfSignalManager
.dispatchSignal(new TmfSelectionRangeUpdatedSignal(AbstractSegmentStoreTableViewer
.this, start
, end
));
113 * Current segment store analysis module
115 private @Nullable AbstractSegmentStoreAnalysisModule fAnalysisModule
= null;
118 * Analysis progress listener
120 private AnalysisProgressListener fListener
;
123 * Flag to create columns once
125 boolean fColumnsCreated
= false;
127 // ------------------------------------------------------------------------
129 // ------------------------------------------------------------------------
135 * Table viewer of the view
137 public AbstractSegmentStoreTableViewer(TableViewer tableViewer
) {
139 // Sort order of the content provider is by start time by default
140 getTableViewer().setContentProvider(new SegmentStoreContentProvider());
141 ITmfTrace trace
= TmfTraceManager
.getInstance().getActiveTrace();
143 fAnalysisModule
= getSegmentStoreAnalysisModule(trace
);
146 getTableViewer().getTable().addSelectionListener(new TableSelectionListener());
148 fListener
= new AnalysisProgressListener();
151 // ------------------------------------------------------------------------
153 // ------------------------------------------------------------------------
156 * Create default columns for start time, end time and duration
158 private void createColumns() {
159 createColumn(Messages
.SegmentStoreTableViewer_startTime
, new SegmentStoreTableColumnLabelProvider() {
161 public String
getTextForSegment(ISegment input
) {
162 return NonNullUtils
.nullToEmptyString(TmfTimestampFormat
.getDefaulTimeFormat().format(input
.getStart()));
164 }, SegmentComparators
.INTERVAL_START_COMPARATOR
);
166 createColumn(Messages
.SegmentStoreTableViewer_endTime
, new SegmentStoreTableColumnLabelProvider() {
168 public String
getTextForSegment(ISegment input
) {
169 return NonNullUtils
.nullToEmptyString(TmfTimestampFormat
.getDefaulTimeFormat().format(input
.getEnd()));
171 }, SegmentComparators
.INTERVAL_END_COMPARATOR
);
173 createColumn(Messages
.SegmentStoreTableViewer_duration
, new SegmentStoreTableColumnLabelProvider() {
175 public String
getTextForSegment(ISegment input
) {
176 return NonNullUtils
.nullToEmptyString(Long
.toString(input
.getLength()));
178 }, SegmentComparators
.INTERVAL_LENGTH_COMPARATOR
);
182 * Create columns specific to the analysis
184 protected void createAnalysisColumns() {
185 if (!fColumnsCreated
) {
186 AbstractSegmentStoreAnalysisModule analysis
= getAnalysisModule();
187 if (analysis
!= null) {
188 for (final ISegmentAspect aspect
: analysis
.getSegmentAspects()) {
189 createColumn(aspect
.getName(), new SegmentStoreTableColumnLabelProvider() {
191 public String
getTextForSegment(ISegment input
) {
192 return NonNullUtils
.nullToEmptyString(aspect
.resolve(input
));
195 aspect
.getComparator());
198 fColumnsCreated
= true;
203 * Update the data in the table viewer
208 public void updateModel(final @Nullable Object dataInput
) {
209 final TableViewer tableViewer
= getTableViewer();
210 Display
.getDefault().asyncExec(new Runnable() {
213 if (!tableViewer
.getTable().isDisposed()) {
214 // Go to the top of the table
215 tableViewer
.getTable().setTopIndex(0);
216 // Reset selected row
217 tableViewer
.setSelection(StructuredSelection
.EMPTY
);
218 if (dataInput
== null) {
219 tableViewer
.setInput(null);
220 tableViewer
.setItemCount(0);
224 tableViewer
.setInput(dataInput
);
225 SegmentStoreContentProvider contentProvider
= (SegmentStoreContentProvider
) getTableViewer().getContentProvider();
226 tableViewer
.setItemCount(contentProvider
.getSegmentCount());
233 * Set the data into the viewer. Will update model is analysis is completed
234 * or run analysis if not completed
237 * segment store analysis module
239 public void setData(@Nullable AbstractSegmentStoreAnalysisModule analysis
) {
240 // Set the current segment store analysis module
241 fAnalysisModule
= analysis
;
242 if (analysis
== null) {
247 createAnalysisColumns();
249 ISegmentStore
<ISegment
> results
= analysis
.getResults();
250 // If results are not null, then analysis is completed and model can be
252 if (results
!= null) {
253 updateModel(results
);
256 // If results are null, then add completion listener and run analysis
258 analysis
.addListener(fListener
);
263 * Returns the segment store analysis module
265 * The trace to consider
266 * @return the segment store analysis module
268 protected @Nullable abstract AbstractSegmentStoreAnalysisModule
getSegmentStoreAnalysisModule(ITmfTrace trace
);
271 protected void appendToTablePopupMenu(IMenuManager manager
, IStructuredSelection sel
) {
272 final ISegment segment
= (ISegment
) sel
.getFirstElement();
273 if (segment
!= null) {
274 IAction gotoStartTime
= new Action(Messages
.SegmentStoreTableViewer_goToStartEvent
) {
277 broadcast(new TmfSelectionRangeUpdatedSignal(AbstractSegmentStoreTableViewer
.this, new TmfNanoTimestamp(segment
.getStart())));
281 IAction gotoEndTime
= new Action(Messages
.SegmentStoreTableViewer_goToEndEvent
) {
284 broadcast(new TmfSelectionRangeUpdatedSignal(AbstractSegmentStoreTableViewer
.this, new TmfNanoTimestamp(segment
.getEnd())));
288 manager
.add(gotoStartTime
);
289 manager
.add(gotoEndTime
);
293 // ------------------------------------------------------------------------
295 // ------------------------------------------------------------------------
298 * Get current segment store analysis module
300 * @return current segment store analysis module
302 public @Nullable AbstractSegmentStoreAnalysisModule
getAnalysisModule() {
303 return fAnalysisModule
;
306 // ------------------------------------------------------------------------
308 // ------------------------------------------------------------------------
311 * Trace selected handler
314 * Different opened trace (on which segment store analysis as
315 * already been performed) has been selected
318 public void traceSelected(TmfTraceSelectedSignal signal
) {
319 ITmfTrace trace
= signal
.getTrace();
321 setData(getSegmentStoreAnalysisModule(trace
));
326 * Trace opened handler
329 * New trace (on which segment store analysis has not been
330 * performed) is opened
333 public void traceOpened(TmfTraceOpenedSignal signal
) {
334 ITmfTrace trace
= signal
.getTrace();
336 setData(getSegmentStoreAnalysisModule(trace
));
341 * Trace closed handler
344 * Last opened trace was closed
347 public void traceClosed(TmfTraceClosedSignal signal
) {
348 // Check if there is no more opened trace
349 if (TmfTraceManager
.getInstance().getActiveTrace() == null) {
350 if (!getTableViewer().getTable().isDisposed()) {
351 getTableViewer().setInput(null);
352 getTableViewer().setItemCount(0);
356 AbstractSegmentStoreAnalysisModule analysis
= getAnalysisModule();
357 if ((analysis
!= null)) {
358 analysis
.removeListener(fListener
);
363 // ------------------------------------------------------------------------
365 // ------------------------------------------------------------------------
368 * Add the listener for SetData on the table
370 private void addPackListener() {
371 getControl().addListener(SWT
.SetData
, new Listener() {
373 public void handleEvent(@Nullable Event event
) {
374 // Remove the listener before the pack
375 getControl().removeListener(SWT
.SetData
, this);
377 // Pack the column the first time data is set
378 TableViewer tableViewer
= getTableViewer();
379 if (tableViewer
!= null) {
380 for (TableColumn col
: tableViewer
.getTable().getColumns()) {