analysis.timing: remove deprecated code
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.timing.ui / src / org / eclipse / tracecompass / analysis / timing / ui / views / segmentstore / table / AbstractSegmentStoreTableViewer.java
CommitLineData
b9fff7ad 1/*******************************************************************************
edded5c1 2 * Copyright (c) 2015, 2016 Ericsson
b9fff7ad
BH
3 *
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
8 *
9 * Contributors:
10 * France Lapointe Nguyen - Initial API and implementation
11 * Bernd Hufmann - Move abstract class to TMF
12 *******************************************************************************/
13
edded5c1 14package org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.table;
b9fff7ad 15
ef47abba
GB
16import java.text.DecimalFormat;
17import java.text.Format;
18
b9fff7ad
BH
19import org.eclipse.jdt.annotation.Nullable;
20import org.eclipse.jface.action.Action;
21import org.eclipse.jface.action.IAction;
22import org.eclipse.jface.action.IMenuManager;
23import org.eclipse.jface.viewers.ColumnLabelProvider;
24import org.eclipse.jface.viewers.IStructuredSelection;
25import org.eclipse.jface.viewers.StructuredSelection;
26import org.eclipse.jface.viewers.TableViewer;
fce7c48b 27import org.eclipse.swt.SWT;
b9fff7ad
BH
28import org.eclipse.swt.events.SelectionAdapter;
29import org.eclipse.swt.events.SelectionEvent;
30import org.eclipse.swt.widgets.Display;
fce7c48b
BH
31import org.eclipse.swt.widgets.Event;
32import org.eclipse.swt.widgets.Listener;
101bcc65 33import org.eclipse.swt.widgets.Table;
fce7c48b 34import org.eclipse.swt.widgets.TableColumn;
b9fff7ad 35import org.eclipse.tracecompass.analysis.timing.core.segmentstore.IAnalysisProgressListener;
0f769d2b 36import org.eclipse.tracecompass.analysis.timing.core.segmentstore.ISegmentStoreProvider;
b9fff7ad 37import org.eclipse.tracecompass.common.core.NonNullUtils;
edded5c1
BH
38import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.table.Messages;
39import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.table.SegmentStoreContentProvider;
b9fff7ad
BH
40import org.eclipse.tracecompass.segmentstore.core.ISegment;
41import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
42import org.eclipse.tracecompass.segmentstore.core.SegmentComparators;
0f769d2b 43import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule;
b9fff7ad
BH
44import org.eclipse.tracecompass.tmf.core.segment.ISegmentAspect;
45import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
46import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
47import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager;
48import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
49import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
50import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
51import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
b2c971ec 52import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
b9fff7ad
BH
53import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestampFormat;
54import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
55import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
56import org.eclipse.tracecompass.tmf.ui.viewers.table.TmfSimpleTableViewer;
57
101bcc65
MK
58import com.google.common.annotations.VisibleForTesting;
59
b9fff7ad 60/**
0f769d2b 61 * Displays the segment store provider data in a column table
b9fff7ad
BH
62 *
63 * @author France Lapointe Nguyen
64 * @since 2.0
65 */
66public abstract class AbstractSegmentStoreTableViewer extends TmfSimpleTableViewer {
67
85c0f30a 68 private static final Format FORMATTER = new DecimalFormat("###,###.##"); //$NON-NLS-1$
ef47abba 69
b9fff7ad
BH
70 // ------------------------------------------------------------------------
71 // Attributes
72 // ------------------------------------------------------------------------
73
74 /**
75 * Abstract class for the column label provider for the segment store
0f769d2b 76 * provider table viewer
b9fff7ad
BH
77 */
78 private abstract class SegmentStoreTableColumnLabelProvider extends ColumnLabelProvider {
79
80 @Override
81 public String getText(@Nullable Object input) {
82 if (!(input instanceof ISegment)) {
83 /* Doubles as a null check */
84 return ""; //$NON-NLS-1$
85 }
86 return getTextForSegment((ISegment) input);
87 }
88
89 public abstract String getTextForSegment(ISegment input);
90 }
91
92 /**
0f769d2b
MK
93 * Listener to update the model with the segment store provider results once
94 * its store is fully completed
b9fff7ad 95 */
0f769d2b 96 private final class SegmentStoreProviderProgressListener implements IAnalysisProgressListener {
b9fff7ad 97 @Override
0f769d2b
MK
98 public void onComplete(ISegmentStoreProvider activeProvider, ISegmentStore<ISegment> data) {
99 // Check if the active trace was changed while the provider was
100 // building its segment store
101 if (activeProvider.equals(fSegmentProvider)) {
b9fff7ad
BH
102 updateModel(data);
103 }
104 }
105 }
106
107 /**
108 * Listener to select a range in other viewers when a cell of the segment
109 * store table view is selected
110 */
111 private class TableSelectionListener extends SelectionAdapter {
112 @Override
113 public void widgetSelected(@Nullable SelectionEvent e) {
114 ISegment selectedSegment = ((ISegment) NonNullUtils.checkNotNull(e).item.getData());
b2c971ec
MK
115 ITmfTimestamp start = TmfTimestamp.fromNanos(selectedSegment.getStart());
116 ITmfTimestamp end = TmfTimestamp.fromNanos(selectedSegment.getEnd());
b9fff7ad
BH
117 TmfSignalManager.dispatchSignal(new TmfSelectionRangeUpdatedSignal(AbstractSegmentStoreTableViewer.this, start, end));
118 }
119 }
120
121 /**
0f769d2b 122 * Current segment store provider
b9fff7ad 123 */
0f769d2b 124 private @Nullable ISegmentStoreProvider fSegmentProvider = null;
b9fff7ad
BH
125
126 /**
0f769d2b 127 * provider progress listener
b9fff7ad 128 */
f0b123a9 129 private final @Nullable SegmentStoreProviderProgressListener fListener;
b9fff7ad
BH
130
131 /**
132 * Flag to create columns once
133 */
134 boolean fColumnsCreated = false;
135
136 // ------------------------------------------------------------------------
137 // Constructor
138 // ------------------------------------------------------------------------
139
140 /**
141 * Constructor
142 *
143 * @param tableViewer
144 * Table viewer of the view
145 */
146 public AbstractSegmentStoreTableViewer(TableViewer tableViewer) {
f0b123a9
GB
147 this(tableViewer, true);
148 }
149
150 /**
151 * Constructor
152 *
153 * @param tableViewer
154 * Table viewer of the view
155 * @param withListener
156 * Whether to add a listener to this table viewer. For instance,
157 * for table viewers who are part of another view who update the
158 * table's data, this value can be <code>false</code> so only the
159 * other listeners will update the data
6dc61a6f 160 * @since 2.0
f0b123a9
GB
161 */
162 public AbstractSegmentStoreTableViewer(TableViewer tableViewer, boolean withListener) {
b9fff7ad
BH
163 super(tableViewer);
164 // Sort order of the content provider is by start time by default
165 getTableViewer().setContentProvider(new SegmentStoreContentProvider());
b9fff7ad
BH
166 createColumns();
167 getTableViewer().getTable().addSelectionListener(new TableSelectionListener());
fce7c48b 168 addPackListener();
f0b123a9 169 fListener = withListener ? new SegmentStoreProviderProgressListener() : null;
b9fff7ad
BH
170 }
171
172 // ------------------------------------------------------------------------
173 // Operations
174 // ------------------------------------------------------------------------
175
101bcc65
MK
176 /**
177 * Sets the segment provider, use only in test, only run in display thread
178 *
179 * @param segmentProvider
180 * the segment provider
181 * @since 1.2
182 */
183 @VisibleForTesting
184 public void setSegmentProvider(ISegmentStoreProvider segmentProvider) {
185 fSegmentProvider = segmentProvider;
186 // Sort order of the content provider is by start time by default
187 getTableViewer().setContentProvider(new SegmentStoreContentProvider());
188
189 Table table = getTableViewer().getTable();
190 table.setRedraw(false);
191 while (table.getColumnCount() > 0) {
192 table.getColumn(0).dispose();
193 }
194 createColumns();
195 createProviderColumns();
196 getTableViewer().getTable().addSelectionListener(new TableSelectionListener());
197 addPackListener();
101bcc65
MK
198 table.setRedraw(true);
199 }
200
b9fff7ad
BH
201 /**
202 * Create default columns for start time, end time and duration
203 */
204 private void createColumns() {
205 createColumn(Messages.SegmentStoreTableViewer_startTime, new SegmentStoreTableColumnLabelProvider() {
206 @Override
207 public String getTextForSegment(ISegment input) {
208 return NonNullUtils.nullToEmptyString(TmfTimestampFormat.getDefaulTimeFormat().format(input.getStart()));
209 }
210 }, SegmentComparators.INTERVAL_START_COMPARATOR);
211
212 createColumn(Messages.SegmentStoreTableViewer_endTime, new SegmentStoreTableColumnLabelProvider() {
213 @Override
214 public String getTextForSegment(ISegment input) {
215 return NonNullUtils.nullToEmptyString(TmfTimestampFormat.getDefaulTimeFormat().format(input.getEnd()));
216 }
217 }, SegmentComparators.INTERVAL_END_COMPARATOR);
218
219 createColumn(Messages.SegmentStoreTableViewer_duration, new SegmentStoreTableColumnLabelProvider() {
220 @Override
221 public String getTextForSegment(ISegment input) {
ef47abba 222 return NonNullUtils.nullToEmptyString(FORMATTER.format(input.getLength()));
b9fff7ad
BH
223 }
224 }, SegmentComparators.INTERVAL_LENGTH_COMPARATOR);
225 }
226
227 /**
0f769d2b 228 * Create columns specific to the provider
b9fff7ad 229 */
0f769d2b 230 protected void createProviderColumns() {
b9fff7ad 231 if (!fColumnsCreated) {
0f769d2b
MK
232 ISegmentStoreProvider provider = getSegmentProvider();
233 if (provider != null) {
234 for (final ISegmentAspect aspect : provider.getSegmentAspects()) {
b9fff7ad
BH
235 createColumn(aspect.getName(), new SegmentStoreTableColumnLabelProvider() {
236 @Override
237 public String getTextForSegment(ISegment input) {
238 return NonNullUtils.nullToEmptyString(aspect.resolve(input));
239 }
240 },
0f769d2b 241 aspect.getComparator());
b9fff7ad
BH
242 }
243 }
244 fColumnsCreated = true;
245 }
246 }
247
248 /**
249 * Update the data in the table viewer
250 *
251 * @param dataInput
252 * New data input
253 */
bd53eb28 254 public void updateModel(final @Nullable Object dataInput) {
b9fff7ad
BH
255 final TableViewer tableViewer = getTableViewer();
256 Display.getDefault().asyncExec(new Runnable() {
257 @Override
258 public void run() {
259 if (!tableViewer.getTable().isDisposed()) {
260 // Go to the top of the table
261 tableViewer.getTable().setTopIndex(0);
262 // Reset selected row
263 tableViewer.setSelection(StructuredSelection.EMPTY);
264 if (dataInput == null) {
265 tableViewer.setInput(null);
266 tableViewer.setItemCount(0);
267 return;
268 }
fce7c48b 269 addPackListener();
b9fff7ad
BH
270 tableViewer.setInput(dataInput);
271 SegmentStoreContentProvider contentProvider = (SegmentStoreContentProvider) getTableViewer().getContentProvider();
fc409c43 272 tableViewer.setItemCount((int) Math.min(Integer.MAX_VALUE, contentProvider.getSegmentCount()));
b9fff7ad
BH
273 }
274 }
275 });
276 }
277
278 /**
0f769d2b
MK
279 * Set the data into the viewer. It will update the model. If the provider
280 * is an analysis, the analysis will be scheduled.
b9fff7ad 281 *
0f769d2b
MK
282 * @param provider
283 * segment store provider
b9fff7ad 284 */
0f769d2b
MK
285 public void setData(@Nullable ISegmentStoreProvider provider) {
286 // Set the current segment store provider
287 fSegmentProvider = provider;
288 if (provider == null) {
b9fff7ad
BH
289 updateModel(null);
290 return;
291 }
292
0f769d2b 293 createProviderColumns();
b9fff7ad 294
0f769d2b
MK
295 ISegmentStore<ISegment> segStore = provider.getSegmentStore();
296 // If results are not null, then the segment of the provider is ready
297 // and model can be updated
73c74de7
JCK
298 if (segStore != null) {
299 updateModel(segStore);
b9fff7ad
BH
300 return;
301 }
0f769d2b
MK
302 // If results are null, then add completion listener and if the provider
303 // is an analysis, run the analysis
b9fff7ad 304 updateModel(null);
f0b123a9
GB
305 SegmentStoreProviderProgressListener listener = fListener;
306 if (listener != null) {
307 provider.addListener(listener);
308 }
0f769d2b
MK
309 if (provider instanceof IAnalysisModule) {
310 ((IAnalysisModule) provider).schedule();
311 }
b9fff7ad
BH
312 }
313
314 /**
0f769d2b
MK
315 * Returns the segment store provider
316 *
b9fff7ad
BH
317 * @param trace
318 * The trace to consider
0f769d2b 319 * @return the segment store provider
b9fff7ad 320 */
0f769d2b 321 protected @Nullable abstract ISegmentStoreProvider getSegmentStoreProvider(ITmfTrace trace);
b9fff7ad
BH
322
323 @Override
324 protected void appendToTablePopupMenu(IMenuManager manager, IStructuredSelection sel) {
325 final ISegment segment = (ISegment) sel.getFirstElement();
8ef16fe6
BH
326 if (segment != null) {
327 IAction gotoStartTime = new Action(Messages.SegmentStoreTableViewer_goToStartEvent) {
328 @Override
329 public void run() {
b2c971ec 330 broadcast(new TmfSelectionRangeUpdatedSignal(AbstractSegmentStoreTableViewer.this, TmfTimestamp.fromNanos(segment.getStart())));
8ef16fe6
BH
331 }
332 };
b9fff7ad 333
8ef16fe6
BH
334 IAction gotoEndTime = new Action(Messages.SegmentStoreTableViewer_goToEndEvent) {
335 @Override
336 public void run() {
b2c971ec 337 broadcast(new TmfSelectionRangeUpdatedSignal(AbstractSegmentStoreTableViewer.this, TmfTimestamp.fromNanos(segment.getEnd())));
8ef16fe6
BH
338 }
339 };
b9fff7ad 340
8ef16fe6
BH
341 manager.add(gotoStartTime);
342 manager.add(gotoEndTime);
343 }
b9fff7ad
BH
344 }
345
346 // ------------------------------------------------------------------------
347 // Getters
348 // ------------------------------------------------------------------------
349
350 /**
0f769d2b 351 * Get current segment store provider
b9fff7ad 352 *
0f769d2b 353 * @return current segment store provider
b9fff7ad 354 */
0f769d2b
MK
355 public @Nullable ISegmentStoreProvider getSegmentProvider() {
356 return fSegmentProvider;
b9fff7ad
BH
357 }
358
359 // ------------------------------------------------------------------------
360 // Signal handlers
361 // ------------------------------------------------------------------------
362
363 /**
364 * Trace selected handler
365 *
366 * @param signal
367 * Different opened trace (on which segment store analysis as
368 * already been performed) has been selected
369 */
370 @TmfSignalHandler
371 public void traceSelected(TmfTraceSelectedSignal signal) {
372 ITmfTrace trace = signal.getTrace();
373 if (trace != null) {
0f769d2b 374 setData(getSegmentStoreProvider(trace));
b9fff7ad
BH
375 }
376 }
377
378 /**
379 * Trace opened handler
380 *
381 * @param signal
382 * New trace (on which segment store analysis has not been
383 * performed) is opened
384 */
385 @TmfSignalHandler
386 public void traceOpened(TmfTraceOpenedSignal signal) {
387 ITmfTrace trace = signal.getTrace();
388 if (trace != null) {
0f769d2b 389 setData(getSegmentStoreProvider(trace));
b9fff7ad
BH
390 }
391 }
392
393 /**
394 * Trace closed handler
395 *
396 * @param signal
397 * Last opened trace was closed
398 */
399 @TmfSignalHandler
400 public void traceClosed(TmfTraceClosedSignal signal) {
401 // Check if there is no more opened trace
402 if (TmfTraceManager.getInstance().getActiveTrace() == null) {
403 if (!getTableViewer().getTable().isDisposed()) {
404 getTableViewer().setInput(null);
0945d5a8 405 getTableViewer().setItemCount(0);
b9fff7ad
BH
406 refresh();
407 }
76be6c00 408
0f769d2b
MK
409 ISegmentStoreProvider provider = getSegmentProvider();
410 if ((provider != null)) {
f0b123a9
GB
411 SegmentStoreProviderProgressListener listener = fListener;
412 if (listener != null) {
413 provider.removeListener(listener);
414 }
76be6c00 415 }
b9fff7ad
BH
416 }
417 }
fce7c48b
BH
418
419 // ------------------------------------------------------------------------
420 // Helper methods
421 // ------------------------------------------------------------------------
b2f6d73d 422
fce7c48b
BH
423 /*
424 * Add the listener for SetData on the table
425 */
426 private void addPackListener() {
427 getControl().addListener(SWT.SetData, new Listener() {
428 @Override
429 public void handleEvent(@Nullable Event event) {
b2f6d73d
PT
430 // Remove the listener before the pack
431 getControl().removeListener(SWT.SetData, this);
432
fce7c48b
BH
433 // Pack the column the first time data is set
434 TableViewer tableViewer = getTableViewer();
435 if (tableViewer != null) {
436 for (TableColumn col : tableViewer.getTable().getColumns()) {
437 col.pack();
438 }
fce7c48b
BH
439 }
440 }
441 });
442 }
b9fff7ad 443}
This page took 0.061795 seconds and 5 git commands to generate.