analysis: fix @NonNull issues with SystemCallLatencyStatisticsViewer
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.timing.ui / src / org / eclipse / tracecompass / analysis / timing / ui / views / segmentstore / AbstractSegmentStoreTableViewer.java
CommitLineData
b9fff7ad
BH
1/*******************************************************************************
2 * Copyright (c) 2015 Ericsson
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
14package org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore;
15
16import org.eclipse.jdt.annotation.Nullable;
17import org.eclipse.jface.action.Action;
18import org.eclipse.jface.action.IAction;
19import org.eclipse.jface.action.IMenuManager;
20import org.eclipse.jface.viewers.ColumnLabelProvider;
21import org.eclipse.jface.viewers.IStructuredSelection;
22import org.eclipse.jface.viewers.StructuredSelection;
23import org.eclipse.jface.viewers.TableViewer;
fce7c48b 24import org.eclipse.swt.SWT;
b9fff7ad
BH
25import org.eclipse.swt.events.SelectionAdapter;
26import org.eclipse.swt.events.SelectionEvent;
27import org.eclipse.swt.widgets.Display;
fce7c48b
BH
28import org.eclipse.swt.widgets.Event;
29import org.eclipse.swt.widgets.Listener;
30import org.eclipse.swt.widgets.TableColumn;
b9fff7ad
BH
31import org.eclipse.tracecompass.analysis.timing.core.segmentstore.AbstractSegmentStoreAnalysisModule;
32import org.eclipse.tracecompass.analysis.timing.core.segmentstore.IAnalysisProgressListener;
33import org.eclipse.tracecompass.common.core.NonNullUtils;
34import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.Messages;
35import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.SegmentStoreContentProvider;
36import org.eclipse.tracecompass.segmentstore.core.ISegment;
37import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
38import org.eclipse.tracecompass.segmentstore.core.SegmentComparators;
39import org.eclipse.tracecompass.tmf.core.segment.ISegmentAspect;
40import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
41import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
42import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager;
43import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
44import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
45import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
46import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
47import org.eclipse.tracecompass.tmf.core.timestamp.TmfNanoTimestamp;
48import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestampFormat;
49import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
50import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
51import org.eclipse.tracecompass.tmf.ui.viewers.table.TmfSimpleTableViewer;
52
53/**
54 * Displays the segment store analysis data in a column table
55 *
56 * @author France Lapointe Nguyen
57 * @since 2.0
58 */
59public abstract class AbstractSegmentStoreTableViewer extends TmfSimpleTableViewer {
60
61 // ------------------------------------------------------------------------
62 // Attributes
63 // ------------------------------------------------------------------------
64
65 /**
66 * Abstract class for the column label provider for the segment store
67 * analysis table viewer
68 */
69 private abstract class SegmentStoreTableColumnLabelProvider extends ColumnLabelProvider {
70
71 @Override
72 public String getText(@Nullable Object input) {
73 if (!(input instanceof ISegment)) {
74 /* Doubles as a null check */
75 return ""; //$NON-NLS-1$
76 }
77 return getTextForSegment((ISegment) input);
78 }
79
80 public abstract String getTextForSegment(ISegment input);
81 }
82
83 /**
84 * Listener to update the model with the segment store analysis results
85 * once the analysis is fully completed
86 */
87 private final class AnalysisProgressListener implements IAnalysisProgressListener {
88 @Override
89 public void onComplete(AbstractSegmentStoreAnalysisModule activeAnalysis, ISegmentStore<ISegment> data) {
90 // Check if the active trace was changed while the analysis was
91 // running
92 if (activeAnalysis.equals(fAnalysisModule)) {
93 updateModel(data);
94 }
95 }
96 }
97
98 /**
99 * Listener to select a range in other viewers when a cell of the segment
100 * store table view is selected
101 */
102 private class TableSelectionListener extends SelectionAdapter {
103 @Override
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));
109 }
110 }
111
112 /**
113 * Current segment store analysis module
114 */
115 private @Nullable AbstractSegmentStoreAnalysisModule fAnalysisModule = null;
116
117 /**
118 * Analysis progress listener
119 */
120 private AnalysisProgressListener fListener;
121
122 /**
123 * Flag to create columns once
124 */
125 boolean fColumnsCreated = false;
126
127 // ------------------------------------------------------------------------
128 // Constructor
129 // ------------------------------------------------------------------------
130
131 /**
132 * Constructor
133 *
134 * @param tableViewer
135 * Table viewer of the view
136 */
137 public AbstractSegmentStoreTableViewer(TableViewer tableViewer) {
138 super(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();
142 if (trace != null) {
143 fAnalysisModule = getSegmentStoreAnalysisModule(trace);
144 }
145 createColumns();
146 getTableViewer().getTable().addSelectionListener(new TableSelectionListener());
fce7c48b 147 addPackListener();
b9fff7ad
BH
148 fListener = new AnalysisProgressListener();
149 }
150
151 // ------------------------------------------------------------------------
152 // Operations
153 // ------------------------------------------------------------------------
154
155 /**
156 * Create default columns for start time, end time and duration
157 */
158 private void createColumns() {
159 createColumn(Messages.SegmentStoreTableViewer_startTime, new SegmentStoreTableColumnLabelProvider() {
160 @Override
161 public String getTextForSegment(ISegment input) {
162 return NonNullUtils.nullToEmptyString(TmfTimestampFormat.getDefaulTimeFormat().format(input.getStart()));
163 }
164 }, SegmentComparators.INTERVAL_START_COMPARATOR);
165
166 createColumn(Messages.SegmentStoreTableViewer_endTime, new SegmentStoreTableColumnLabelProvider() {
167 @Override
168 public String getTextForSegment(ISegment input) {
169 return NonNullUtils.nullToEmptyString(TmfTimestampFormat.getDefaulTimeFormat().format(input.getEnd()));
170 }
171 }, SegmentComparators.INTERVAL_END_COMPARATOR);
172
173 createColumn(Messages.SegmentStoreTableViewer_duration, new SegmentStoreTableColumnLabelProvider() {
174 @Override
175 public String getTextForSegment(ISegment input) {
176 return NonNullUtils.nullToEmptyString(Long.toString(input.getLength()));
177 }
178 }, SegmentComparators.INTERVAL_LENGTH_COMPARATOR);
179 }
180
181 /**
182 * Create columns specific to the analysis
183 */
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() {
190 @Override
191 public String getTextForSegment(ISegment input) {
192 return NonNullUtils.nullToEmptyString(aspect.resolve(input));
193 }
194 },
6ad9d1cb 195 aspect.getComparator());
b9fff7ad
BH
196 }
197 }
198 fColumnsCreated = true;
199 }
200 }
201
202 /**
203 * Update the data in the table viewer
204 *
205 * @param dataInput
206 * New data input
207 */
bd53eb28 208 public void updateModel(final @Nullable Object dataInput) {
b9fff7ad
BH
209 final TableViewer tableViewer = getTableViewer();
210 Display.getDefault().asyncExec(new Runnable() {
211 @Override
212 public void run() {
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);
221 return;
222 }
fce7c48b 223 addPackListener();
b9fff7ad
BH
224 tableViewer.setInput(dataInput);
225 SegmentStoreContentProvider contentProvider = (SegmentStoreContentProvider) getTableViewer().getContentProvider();
226 tableViewer.setItemCount(contentProvider.getSegmentCount());
227 }
228 }
229 });
230 }
231
232 /**
233 * Set the data into the viewer. Will update model is analysis is completed
234 * or run analysis if not completed
235 *
236 * @param analysis
237 * segment store analysis module
238 */
239 public void setData(@Nullable AbstractSegmentStoreAnalysisModule analysis) {
240 // Set the current segment store analysis module
241 fAnalysisModule = analysis;
242 if (analysis == null) {
243 updateModel(null);
244 return;
245 }
246
247 createAnalysisColumns();
248
249 ISegmentStore<ISegment> results = analysis.getResults();
250 // If results are not null, then analysis is completed and model can be
251 // updated
252 if (results != null) {
253 updateModel(results);
254 return;
255 }
256 // If results are null, then add completion listener and run analysis
257 updateModel(null);
258 analysis.addListener(fListener);
259 analysis.schedule();
260 }
261
262 /**
263 * Returns the segment store analysis module
264 * @param trace
265 * The trace to consider
266 * @return the segment store analysis module
267 */
268 protected @Nullable abstract AbstractSegmentStoreAnalysisModule getSegmentStoreAnalysisModule(ITmfTrace trace);
269
270 @Override
271 protected void appendToTablePopupMenu(IMenuManager manager, IStructuredSelection sel) {
272 final ISegment segment = (ISegment) sel.getFirstElement();
8ef16fe6
BH
273 if (segment != null) {
274 IAction gotoStartTime = new Action(Messages.SegmentStoreTableViewer_goToStartEvent) {
275 @Override
276 public void run() {
277 broadcast(new TmfSelectionRangeUpdatedSignal(AbstractSegmentStoreTableViewer.this, new TmfNanoTimestamp(segment.getStart())));
278 }
279 };
b9fff7ad 280
8ef16fe6
BH
281 IAction gotoEndTime = new Action(Messages.SegmentStoreTableViewer_goToEndEvent) {
282 @Override
283 public void run() {
284 broadcast(new TmfSelectionRangeUpdatedSignal(AbstractSegmentStoreTableViewer.this, new TmfNanoTimestamp(segment.getEnd())));
285 }
286 };
b9fff7ad 287
8ef16fe6
BH
288 manager.add(gotoStartTime);
289 manager.add(gotoEndTime);
290 }
b9fff7ad
BH
291 }
292
293 // ------------------------------------------------------------------------
294 // Getters
295 // ------------------------------------------------------------------------
296
297 /**
298 * Get current segment store analysis module
299 *
300 * @return current segment store analysis module
301 */
302 public @Nullable AbstractSegmentStoreAnalysisModule getAnalysisModule() {
303 return fAnalysisModule;
304 }
305
306 // ------------------------------------------------------------------------
307 // Signal handlers
308 // ------------------------------------------------------------------------
309
310 /**
311 * Trace selected handler
312 *
313 * @param signal
314 * Different opened trace (on which segment store analysis as
315 * already been performed) has been selected
316 */
317 @TmfSignalHandler
318 public void traceSelected(TmfTraceSelectedSignal signal) {
319 ITmfTrace trace = signal.getTrace();
320 if (trace != null) {
321 setData(getSegmentStoreAnalysisModule(trace));
322 }
323 }
324
325 /**
326 * Trace opened handler
327 *
328 * @param signal
329 * New trace (on which segment store analysis has not been
330 * performed) is opened
331 */
332 @TmfSignalHandler
333 public void traceOpened(TmfTraceOpenedSignal signal) {
334 ITmfTrace trace = signal.getTrace();
335 if (trace != null) {
336 setData(getSegmentStoreAnalysisModule(trace));
337 }
338 }
339
340 /**
341 * Trace closed handler
342 *
343 * @param signal
344 * Last opened trace was closed
345 */
346 @TmfSignalHandler
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);
0945d5a8 352 getTableViewer().setItemCount(0);
b9fff7ad
BH
353 refresh();
354 }
76be6c00
BH
355
356 AbstractSegmentStoreAnalysisModule analysis = getAnalysisModule();
357 if ((analysis != null)) {
358 analysis.removeListener(fListener);
359 }
b9fff7ad
BH
360 }
361 }
fce7c48b
BH
362
363 // ------------------------------------------------------------------------
364 // Helper methods
365 // ------------------------------------------------------------------------
366 /*
367 * Add the listener for SetData on the table
368 */
369 private void addPackListener() {
370 getControl().addListener(SWT.SetData, new Listener() {
371 @Override
372 public void handleEvent(@Nullable Event event) {
373 // Pack the column the first time data is set
374 TableViewer tableViewer = getTableViewer();
375 if (tableViewer != null) {
376 for (TableColumn col : tableViewer.getTable().getColumns()) {
377 col.pack();
378 }
379 // Remove the listener after the pack
380 getControl().removeListener(SWT.SetData, this);
381 }
382 }
383 });
384 }
b9fff7ad 385}
This page took 0.042483 seconds and 5 git commands to generate.