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