Update usage of IAdaptable#getAdapter
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / editors / TmfEventsEditor.java
1 /*******************************************************************************
2 * Copyright (c) 2010, 2015 Ericsson, École Polytechnique de Montréal
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 * Patrick Tasse - Initial API and implementation
11 * Geneviève Bastien - Experiment instantiated with experiment type
12 *******************************************************************************/
13
14 package org.eclipse.tracecompass.tmf.ui.editors;
15
16 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
17
18 import java.util.List;
19
20 import org.eclipse.core.resources.IFile;
21 import org.eclipse.core.resources.IMarker;
22 import org.eclipse.core.resources.IMarkerDelta;
23 import org.eclipse.core.resources.IResource;
24 import org.eclipse.core.resources.IResourceChangeEvent;
25 import org.eclipse.core.resources.IResourceChangeListener;
26 import org.eclipse.core.resources.IResourceDelta;
27 import org.eclipse.core.resources.ResourcesPlugin;
28 import org.eclipse.core.runtime.CoreException;
29 import org.eclipse.core.runtime.IProgressMonitor;
30 import org.eclipse.core.runtime.InvalidRegistryObjectException;
31 import org.eclipse.core.runtime.ListenerList;
32 import org.eclipse.jdt.annotation.NonNull;
33 import org.eclipse.jdt.annotation.Nullable;
34 import org.eclipse.jface.action.IStatusLineManager;
35 import org.eclipse.jface.util.SafeRunnable;
36 import org.eclipse.jface.viewers.ISelection;
37 import org.eclipse.jface.viewers.ISelectionChangedListener;
38 import org.eclipse.jface.viewers.ISelectionProvider;
39 import org.eclipse.jface.viewers.SelectionChangedEvent;
40 import org.eclipse.jface.viewers.StructuredSelection;
41 import org.eclipse.swt.widgets.Composite;
42 import org.eclipse.swt.widgets.Display;
43 import org.eclipse.tracecompass.internal.tmf.ui.Activator;
44 import org.eclipse.tracecompass.internal.tmf.ui.editors.ITmfEventsEditorConstants;
45 import org.eclipse.tracecompass.tmf.core.TmfCommonConstants;
46 import org.eclipse.tracecompass.tmf.core.event.aspect.ITmfEventAspect;
47 import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
48 import org.eclipse.tracecompass.tmf.core.signal.TmfTimestampFormatUpdateSignal;
49 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
50 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
51 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
52 import org.eclipse.tracecompass.tmf.core.trace.ITmfContext;
53 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
54 import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment;
55 import org.eclipse.tracecompass.tmf.ui.project.model.Messages;
56 import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentElement;
57 import org.eclipse.tracecompass.tmf.ui.project.model.TmfOpenTraceHelper;
58 import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectElement;
59 import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectRegistry;
60 import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
61 import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceTypeUIUtils;
62 import org.eclipse.tracecompass.tmf.ui.viewers.events.TmfEventsTable;
63 import org.eclipse.ui.IEditorInput;
64 import org.eclipse.ui.IEditorPart;
65 import org.eclipse.ui.IEditorSite;
66 import org.eclipse.ui.IFileEditorInput;
67 import org.eclipse.ui.IPartListener;
68 import org.eclipse.ui.IPropertyListener;
69 import org.eclipse.ui.IReusableEditor;
70 import org.eclipse.ui.IWorkbenchPart;
71 import org.eclipse.ui.PartInitException;
72 import org.eclipse.ui.ide.IGotoMarker;
73 import org.eclipse.ui.part.FileEditorInput;
74 import org.eclipse.ui.views.properties.IPropertySheetPage;
75
76 import com.google.common.collect.ImmutableSet;
77 import com.google.common.collect.Iterables;
78
79 /**
80 * Editor for TMF events
81 *
82 * @author Patrick Tasse
83 */
84 public class TmfEventsEditor extends TmfEditor implements ITmfTraceEditor, IReusableEditor, IPropertyListener, IResourceChangeListener, ISelectionProvider, ISelectionChangedListener, IPartListener, IGotoMarker {
85
86 /** ID for this class */
87 public static final String ID = "org.eclipse.linuxtools.tmf.ui.editors.events"; //$NON-NLS-1$
88
89 private TmfEventsTable fEventsTable;
90 private IFile fFile;
91 private ITmfTrace fTrace;
92 private Composite fParent;
93 private ListenerList fSelectionChangedListeners = new ListenerList();
94 private boolean fTraceSelected;
95 private IMarker fPendingGotoMarker;
96
97 @Override
98 public void doSave(final IProgressMonitor monitor) {
99 }
100
101 @Override
102 public void doSaveAs() {
103 }
104
105 @Override
106 public void init(final IEditorSite site, IEditorInput input) throws PartInitException {
107 IFileEditorInput fileEditorInput;
108 if (input instanceof TmfEditorInput) {
109 fFile = ((TmfEditorInput) input).getFile();
110 fTrace = ((TmfEditorInput) input).getTrace();
111 /* change the input to a FileEditorInput to allow open handlers to find this editor */
112 fileEditorInput = new FileEditorInput(fFile);
113 } else if (input instanceof IFileEditorInput) {
114 fileEditorInput = (IFileEditorInput) input;
115 fFile = fileEditorInput.getFile();
116 if (fFile == null) {
117 throw new PartInitException("Invalid IFileEditorInput: " + fileEditorInput); //$NON-NLS-1$
118 }
119 try {
120 final String traceTypeId = fFile.getPersistentProperty(TmfCommonConstants.TRACETYPE);
121 if (traceTypeId == null) {
122 throw new PartInitException(Messages.TmfOpenTraceHelper_NoTraceType);
123 }
124 if (ITmfEventsEditorConstants.EXPERIMENT_INPUT_TYPE_CONSTANTS.contains(traceTypeId)) {
125 // Special case: experiment bookmark resource
126 final TmfProjectElement project = TmfProjectRegistry.getProject(fFile.getProject(), true);
127 if (project == null) {
128 throw new PartInitException(Messages.TmfOpenTraceHelper_NoTraceType);
129 }
130 for (final TmfExperimentElement experimentElement : project.getExperimentsFolder().getExperiments()) {
131 if (experimentElement.getResource().equals(fFile.getParent())) {
132 setPartName(experimentElement.getName());
133 super.setSite(site);
134 super.setInput(fileEditorInput);
135 TmfOpenTraceHelper.reopenTraceFromElement(experimentElement, this);
136 return;
137 }
138 }
139 } else if (ITmfEventsEditorConstants.TRACE_INPUT_TYPE_CONSTANTS.contains(traceTypeId)) {
140 // Special case: trace bookmark resource
141 final TmfProjectElement project = TmfProjectRegistry.getProject(fFile.getProject(), true);
142 for (final TmfTraceElement traceElement : project.getTracesFolder().getTraces()) {
143 if (traceElement.getResource().equals(fFile.getParent())) {
144 setPartName(traceElement.getElementPath());
145 super.setSite(site);
146 super.setInput(fileEditorInput);
147 TmfOpenTraceHelper.reopenTraceFromElement(traceElement, this);
148 return;
149 }
150 }
151 } else {
152 final TmfProjectElement project = TmfProjectRegistry.getProject(fFile.getProject(), true);
153 for (final TmfTraceElement traceElement : project.getTracesFolder().getTraces()) {
154 if (traceElement.getResource().equals(fFile)) {
155 setPartName(traceElement.getElementPath());
156 super.setSite(site);
157 super.setInput(fileEditorInput);
158 TmfOpenTraceHelper.reopenTraceFromElement(traceElement, this);
159 return;
160 }
161 }
162 }
163 } catch (final PartInitException e) {
164 throw e;
165 } catch (final InvalidRegistryObjectException e) {
166 Activator.getDefault().logError("Error initializing TmfEventsEditor", e); //$NON-NLS-1$
167 } catch (final CoreException e) {
168 Activator.getDefault().logError("Error initializing TmfEventsEditor", e); //$NON-NLS-1$
169 }
170 } else {
171 throw new PartInitException("Invalid IEditorInput: " + input.getClass()); //$NON-NLS-1$
172 }
173 if (fTrace == null) {
174 throw new PartInitException("Invalid IEditorInput: " + fFile.getName()); //$NON-NLS-1$
175 }
176 super.setSite(site);
177 super.setInput(fileEditorInput);
178 }
179
180 @Override
181 public boolean isDirty() {
182 return false;
183 }
184
185 @Override
186 public boolean isSaveAsAllowed() {
187 return false;
188 }
189
190 @Override
191 public void setInput(final IEditorInput input) {
192 super.setInput(input);
193 firePropertyChange(IEditorPart.PROP_INPUT);
194 }
195
196 @Override
197 public void propertyChanged(final Object source, final int propId) {
198 if (propId == IEditorPart.PROP_INPUT && getEditorInput() instanceof TmfEditorInput) {
199 if (fTrace != null) {
200 broadcast(new TmfTraceClosedSignal(this, fTrace));
201 TmfTraceColumnManager.saveColumnOrder(fTrace.getTraceTypeId(), fEventsTable.getColumnOrder());
202 }
203 fEventsTable.dispose();
204 fTraceSelected = false;
205 fFile = ((TmfEditorInput) getEditorInput()).getFile();
206 fTrace = ((TmfEditorInput) getEditorInput()).getTrace();
207 /* change the input to a FileEditorInput to allow open handlers to find this editor */
208 super.setInput(new FileEditorInput(fFile));
209 createAndInitializeTable();
210 fParent.layout();
211 }
212 }
213
214 @Override
215 public void createPartControl(final Composite parent) {
216 fParent = parent;
217 createAndInitializeTable();
218 addPropertyListener(this);
219 ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
220 // we need to wrap the ISelectionProvider interface in the editor because
221 // the events table can be replaced later while the selection changed listener
222 // is only added once by the platform to the selection provider set here
223 getSite().setSelectionProvider(this);
224 getSite().getPage().addPartListener(this);
225 }
226
227 private void createAndInitializeTable() {
228 if (fTrace != null) {
229 setPartName(fTrace.getName());
230 fEventsTable = createEventsTable(fParent, fTrace.getCacheSize());
231 fEventsTable.setColumnOrder(TmfTraceColumnManager.loadColumnOrder(fTrace.getTraceTypeId()));
232 fEventsTable.addSelectionChangedListener(this);
233 fEventsTable.setTrace(fTrace, true);
234 fEventsTable.refreshBookmarks(fFile);
235 if (fPendingGotoMarker != null) {
236 fEventsTable.gotoMarker(fPendingGotoMarker);
237 fPendingGotoMarker = null;
238 }
239
240 /* ensure start time is set */
241 final ITmfContext context = fTrace.seekEvent(0);
242 fTrace.getNext(context);
243 context.dispose();
244
245 broadcast(new TmfTraceOpenedSignal(this, fTrace, fFile));
246 } else {
247 fEventsTable = new TmfEventsTable(fParent, 0);
248 fEventsTable.addSelectionChangedListener(this);
249 }
250 IStatusLineManager statusLineManager = getEditorSite().getActionBars().getStatusLineManager();
251 fEventsTable.setStatusLineManager(statusLineManager);
252 }
253
254 @Override
255 public void dispose() {
256 if (getSite() != null) {
257 getSite().getPage().removePartListener(this);
258 }
259 ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
260 removePropertyListener(this);
261 if (fTrace != null) {
262 broadcast(new TmfTraceClosedSignal(this, fTrace));
263 if (fEventsTable != null) {
264 TmfTraceColumnManager.saveColumnOrder(fTrace.getTraceTypeId(), fEventsTable.getColumnOrder());
265 }
266 }
267 if (fEventsTable != null) {
268 fEventsTable.dispose();
269 }
270 super.dispose();
271 }
272
273 /**
274 * Create the event table
275 *
276 * @param parent
277 * The parent composite
278 * @param cacheSize
279 * The cache size
280 * @return The event table instance
281 */
282 protected @NonNull TmfEventsTable createEventsTable(final Composite parent, final int cacheSize) {
283 ITmfTrace trace = fTrace;
284
285 /*
286 * Check if the trace (or experiment type) defines a specific event
287 * table in its extension point.
288 */
289 TmfEventsTable table = TmfTraceTypeUIUtils.getEventTable(trace, parent, cacheSize);
290 if (table != null) {
291 return table;
292 }
293
294 /*
295 * Use the aspects defined by the trace type (or each trace type in an
296 * experiment) to build a table consisting of these.
297 */
298 Iterable<ITmfEventAspect> aspects = getTraceAspects(trace);
299 if (Iterables.isEmpty(aspects)) {
300 /* Couldn't find any event aspects, use a default table */
301 return new TmfEventsTable(parent, cacheSize);
302 }
303 return new TmfEventsTable(parent, cacheSize, aspects);
304 }
305
306 /**
307 * Get the event table for the given trace. It will be of the type defined
308 * by the extension point if applicable, else it will be a default table
309 * with the extension-point-defined columns (if any).
310 *
311 * @param trace
312 * The event table is for this trace
313 * @param parent
314 * The parent composite of the table
315 * @param cacheSize
316 * The cache size to use
317 * @return The event table for the trace
318 */
319 private static @NonNull Iterable<ITmfEventAspect> getTraceAspects(ITmfTrace trace) {
320 if (trace instanceof TmfExperiment) {
321 return getExperimentAspects((TmfExperiment) trace);
322 }
323 return trace.getEventAspects();
324 }
325
326 /**
327 * Get the events table for an experiment. If all traces in the experiment
328 * are of the same type, use the same behavior as if it was one trace of
329 * that type.
330 *
331 * @param experiment
332 * the experiment
333 * @param parent
334 * the parent Composite
335 * @param cacheSize
336 * the event table cache size
337 * @return An event table of the appropriate type
338 */
339 private static @NonNull Iterable<ITmfEventAspect> getExperimentAspects(
340 final TmfExperiment experiment) {
341 List<ITmfTrace> traces = experiment.getTraces();
342 ImmutableSet.Builder<ITmfEventAspect> builder = new ImmutableSet.Builder<>();
343
344 /* For experiments, we'll add a "trace name" aspect/column */
345 builder.add(ITmfEventAspect.BaseAspects.TRACE_NAME);
346
347 String commonTraceType = getCommonTraceType(experiment);
348 if (commonTraceType != null) {
349 /*
350 * All the traces in this experiment are of the same type, let's
351 * just use the normal table for that type.
352 */
353 builder.addAll(traces.get(0).getEventAspects());
354
355 } else {
356 /*
357 * There are different trace types in the experiment, so we are
358 * definitely using a TmfEventsTable. Aggregate the columns from all
359 * trace types.
360 */
361 for (ITmfTrace trace : traces) {
362 Iterable<ITmfEventAspect> traceAspects = trace.getEventAspects();
363 builder.addAll(traceAspects);
364 }
365 }
366 return checkNotNull(builder.build());
367 }
368
369 /**
370 * Check if an experiment contains traces of all the same type. If so,
371 * returns this type as a String. If not, returns null.
372 *
373 * @param experiment
374 * The experiment
375 * @return The common trace type if there is one, or 'null' if there are
376 * different types.
377 */
378 private static @Nullable String getCommonTraceType(TmfExperiment experiment) {
379 String commonTraceType = null;
380 try {
381 for (final ITmfTrace trace : experiment.getTraces()) {
382 final IResource resource = trace.getResource();
383 if (resource == null) {
384 return null;
385 }
386
387 final String traceType = resource.getPersistentProperty(TmfCommonConstants.TRACETYPE);
388 if ((commonTraceType != null) && !commonTraceType.equals(traceType)) {
389 return null;
390 }
391 commonTraceType = traceType;
392 }
393 } catch (CoreException e) {
394 /*
395 * One of the traces didn't advertise its type, we can't infer
396 * anything.
397 */
398 return null;
399 }
400 return commonTraceType;
401 }
402
403 @Override
404 public ITmfTrace getTrace() {
405 return fTrace;
406 }
407
408 @Override
409 public void setFocus() {
410 fEventsTable.setFocus();
411 }
412
413 @Override
414 public <T> T getAdapter(final Class<T> adapter) {
415 if (IGotoMarker.class.equals(adapter)) {
416 if (fTrace == null || fEventsTable == null) {
417 return adapter.cast(this);
418 }
419 return adapter.cast(fEventsTable);
420 } else if (IPropertySheetPage.class.equals(adapter)) {
421 return adapter.cast(new UnsortedPropertySheetPage());
422 }
423 return super.getAdapter(adapter);
424 }
425
426 @Override
427 public void gotoMarker(IMarker marker) {
428 if (fTrace == null || fEventsTable == null) {
429 fPendingGotoMarker = marker;
430 } else {
431 fEventsTable.gotoMarker(marker);
432 }
433 }
434
435 @Override
436 public void resourceChanged(final IResourceChangeEvent event) {
437 for (final IMarkerDelta delta : event.findMarkerDeltas(IMarker.BOOKMARK, false)) {
438 if (delta.getResource().equals(fFile)) {
439 if (delta.getKind() == IResourceDelta.REMOVED) {
440 final IMarker bookmark = delta.getMarker();
441 Display.getDefault().asyncExec(new Runnable() {
442 @Override
443 public void run() {
444 fEventsTable.removeBookmark(bookmark);
445 }
446 });
447 } else if (delta.getKind() == IResourceDelta.CHANGED) {
448 Display.getDefault().asyncExec(new Runnable() {
449 @Override
450 public void run() {
451 fEventsTable.getTable().refresh();
452 }
453 });
454 }
455 }
456 }
457 }
458
459 // ------------------------------------------------------------------------
460 // ISelectionProvider
461 // ------------------------------------------------------------------------
462
463 @Override
464 public void addSelectionChangedListener(ISelectionChangedListener listener) {
465 fSelectionChangedListeners.add(listener);
466 }
467
468 @Override
469 public ISelection getSelection() {
470 if (fEventsTable == null) {
471 return StructuredSelection.EMPTY;
472 }
473 return fEventsTable.getSelection();
474 }
475
476 @Override
477 public void removeSelectionChangedListener(ISelectionChangedListener listener) {
478 fSelectionChangedListeners.remove(listener);
479 }
480
481 @Override
482 public void setSelection(ISelection selection) {
483 // not implemented
484 }
485
486 /**
487 * Notifies any selection changed listeners that the viewer's selection has changed.
488 * Only listeners registered at the time this method is called are notified.
489 *
490 * @param event a selection changed event
491 *
492 * @see ISelectionChangedListener#selectionChanged
493 */
494 protected void fireSelectionChanged(final SelectionChangedEvent event) {
495 Object[] listeners = fSelectionChangedListeners.getListeners();
496 for (int i = 0; i < listeners.length; ++i) {
497 final ISelectionChangedListener l = (ISelectionChangedListener) listeners[i];
498 SafeRunnable.run(new SafeRunnable() {
499 @Override
500 public void run() {
501 l.selectionChanged(event);
502 }
503 });
504 }
505 }
506
507 // ------------------------------------------------------------------------
508 // ISelectionChangedListener
509 // ------------------------------------------------------------------------
510
511 @Override
512 public void selectionChanged(SelectionChangedEvent event) {
513 fireSelectionChanged(event);
514 }
515
516 // ------------------------------------------------------------------------
517 // IPartListener
518 // ------------------------------------------------------------------------
519
520 @Override
521 public void partActivated(IWorkbenchPart part) {
522 if (part == this && fTrace != null) {
523 if (fTraceSelected) {
524 return;
525 }
526 fTraceSelected = true;
527 broadcast(new TmfTraceSelectedSignal(this, fTrace));
528 }
529 }
530
531 @Override
532 public void partBroughtToTop(IWorkbenchPart part) {
533 if (part == this && fTrace != null) {
534 if (fTraceSelected) {
535 return;
536 }
537 fTraceSelected = true;
538 broadcast(new TmfTraceSelectedSignal(this, fTrace));
539 }
540 }
541
542 @Override
543 public void partClosed(IWorkbenchPart part) {
544 }
545
546 @Override
547 public void partDeactivated(IWorkbenchPart part) {
548 }
549
550 @Override
551 public void partOpened(IWorkbenchPart part) {
552 }
553
554 // ------------------------------------------------------------------------
555 // Global commands
556 // ------------------------------------------------------------------------
557
558 /**
559 * Add a bookmark
560 */
561 public void addBookmark() {
562 fEventsTable.addBookmark(fFile);
563 }
564
565
566 // ------------------------------------------------------------------------
567 // Signal handlers
568 // ------------------------------------------------------------------------
569
570 /**
571 * Handler for the Trace Selected signal
572 *
573 * @param signal The incoming signal
574 */
575 @TmfSignalHandler
576 public void traceSelected(final TmfTraceSelectedSignal signal) {
577 if ((signal.getSource() != this)) {
578 if (signal.getTrace().equals(fTrace)) {
579 getSite().getPage().bringToTop(this);
580 } else {
581 fTraceSelected = false;
582 }
583 }
584 }
585
586 /**
587 * Update the display to use the updated timestamp format
588 *
589 * @param signal the incoming signal
590 */
591 @TmfSignalHandler
592 public void timestampFormatUpdated(TmfTimestampFormatUpdateSignal signal) {
593 if (fEventsTable != null) {
594 fEventsTable.refresh();
595 }
596 }
597
598 }
This page took 0.045867 seconds and 5 git commands to generate.