1
/*******************************************************************************
2
* Copyright (c) 2010 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
* Patrick Tasse - Initial API and implementation
11
*******************************************************************************/
13
package org.eclipse.linuxtools.tmf.ui.editors;
15
import java.lang.reflect.Constructor;
16
import java.lang.reflect.InvocationTargetException;
17
import java.util.List;
19
import org.eclipse.core.resources.IFile;
20
import org.eclipse.core.resources.IMarker;
21
import org.eclipse.core.resources.IMarkerDelta;
22
import org.eclipse.core.resources.IResource;
23
import org.eclipse.core.resources.IResourceChangeEvent;
24
import org.eclipse.core.resources.IResourceChangeListener;
25
import org.eclipse.core.resources.IResourceDelta;
26
import org.eclipse.core.resources.ResourcesPlugin;
27
import org.eclipse.core.runtime.CoreException;
28
import org.eclipse.core.runtime.IConfigurationElement;
29
import org.eclipse.core.runtime.IProgressMonitor;
30
import org.eclipse.core.runtime.InvalidRegistryObjectException;
31
import org.eclipse.core.runtime.Platform;
32
import org.eclipse.linuxtools.internal.tmf.ui.Activator;
33
import org.eclipse.linuxtools.internal.tmf.ui.parsers.custom.CustomEventsTable;
34
import org.eclipse.linuxtools.internal.tmf.ui.parsers.custom.CustomTxtTrace;
35
import org.eclipse.linuxtools.internal.tmf.ui.parsers.custom.CustomXmlTrace;
36
import org.eclipse.linuxtools.internal.tmf.ui.project.handlers.Messages;
37
import org.eclipse.linuxtools.tmf.core.TmfCommonConstants;
38
import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
39
import org.eclipse.linuxtools.tmf.core.event.TmfEvent;
40
import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange;
41
import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException;
42
import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
43
import org.eclipse.linuxtools.tmf.core.signal.TmfTraceSelectedSignal;
44
import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
45
import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment;
46
import org.eclipse.linuxtools.tmf.core.trace.TmfTrace;
47
import org.eclipse.linuxtools.tmf.ui.project.model.ITmfProjectModelElement;
48
import org.eclipse.linuxtools.tmf.ui.project.model.TmfExperimentElement;
49
import org.eclipse.linuxtools.tmf.ui.project.model.TmfNavigatorContentProvider;
50
import org.eclipse.linuxtools.tmf.ui.project.model.TmfProjectElement;
51
import org.eclipse.linuxtools.tmf.ui.project.model.TmfProjectRegistry;
52
import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceElement;
53
import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceType;
54
import org.eclipse.linuxtools.tmf.ui.signal.TmfTraceClosedSignal;
55
import org.eclipse.linuxtools.tmf.ui.signal.TmfTraceOpenedSignal;
56
import org.eclipse.linuxtools.tmf.ui.signal.TmfTraceParserUpdatedSignal;
57
import org.eclipse.linuxtools.tmf.ui.viewers.events.TmfEventsTable;
58
import org.eclipse.swt.widgets.Composite;
59
import org.eclipse.swt.widgets.Display;
60
import org.eclipse.ui.IEditorInput;
61
import org.eclipse.ui.IEditorPart;
62
import org.eclipse.ui.IEditorSite;
63
import org.eclipse.ui.IFileEditorInput;
64
import org.eclipse.ui.IPropertyListener;
65
import org.eclipse.ui.IReusableEditor;
66
import org.eclipse.ui.PartInitException;
67
import org.eclipse.ui.ide.IGotoMarker;
68
import org.eclipse.ui.part.FileEditorInput;
69
import org.osgi.framework.Bundle;
72
* Editor for TMF events
75
* @author Patrick Tasse
77
public class TmfEventsEditor extends TmfEditor implements ITmfTraceEditor, IReusableEditor, IPropertyListener, IResourceChangeListener {
79
/** ID for this class */
80
public static final String ID = "org.eclipse.linuxtools.tmf.ui.editors.events"; //$NON-NLS-1$
82
private TmfEventsTable fEventsTable;
84
@SuppressWarnings("rawtypes")
85
private ITmfTrace fTrace;
86
private Composite fParent;
89
public void doSave(final IProgressMonitor monitor) {
93
public void doSaveAs() {
96
@SuppressWarnings({ "unchecked", "rawtypes" })
98
public void init(final IEditorSite site, IEditorInput input) throws PartInitException {
99
if (input instanceof TmfEditorInput) {
100
fFile = ((TmfEditorInput) input).getFile();
101
fTrace = ((TmfEditorInput) input).getTrace();
102
input = new FileEditorInput(fFile);
103
} else if (input instanceof IFileEditorInput) {
104
fFile = ((IFileEditorInput) input).getFile();
107
throw new PartInitException("Invalid IFileEditorInput: " + input); //$NON-NLS-1$
110
final String traceTypeId = fFile.getPersistentProperty(TmfCommonConstants.TRACETYPE);
111
if (traceTypeId == null) {
112
throw new PartInitException(Messages.OpenTraceHandler_NoTraceType);
114
if (traceTypeId.equals(TmfExperiment.class.getCanonicalName())) {
115
// Special case: experiment bookmark resource
116
final TmfNavigatorContentProvider ncp = new TmfNavigatorContentProvider();
117
ncp.getChildren(fFile.getProject()); // force the model to be populated
118
final TmfProjectElement project = TmfProjectRegistry.getProject(fFile.getProject());
119
if (project == null) {
120
throw new PartInitException(Messages.OpenExperimentHandler_NoTraceType);
122
for (final ITmfProjectModelElement projectElement : project.getExperimentsFolder().getChildren()) {
123
final String traceName = fFile.getParent().getName();
124
if (projectElement.getName().equals(traceName)) {
125
final TmfExperimentElement experimentElement = (TmfExperimentElement) projectElement;
126
// Instantiate the experiment's traces
127
final List<TmfTraceElement> traceEntries = experimentElement.getTraces();
128
final int nbTraces = traceEntries.size();
129
int cacheSize = Integer.MAX_VALUE;
130
final ITmfTrace<?>[] traces = new ITmfTrace[nbTraces];
131
for (int i = 0; i < nbTraces; i++) {
132
final TmfTraceElement traceElement = traceEntries.get(i);
133
final ITmfTrace trace = traceElement.instantiateTrace();
134
final ITmfEvent traceEvent = traceElement.instantiateEvent();
135
if ((trace == null) || (traceEvent == null)) {
136
for (int j = 0; j < i; j++) {
139
throw new PartInitException(Messages.OpenExperimentHandler_NoTraceType);
142
trace.initTrace(traceElement.getResource(), traceElement.getLocation().getPath(), traceEvent.getClass());
143
} catch (final TmfTraceException e) {
145
cacheSize = Math.min(cacheSize, trace.getCacheSize());
148
final TmfExperiment experiment = new TmfExperiment(ITmfEvent.class, experimentElement.getName(), traces, cacheSize) {
150
public void initTrace(IResource resource, String path, Class type) {
151
super.initTrace(resource, path, type);
152
getIndexer().buildIndex(getNbEvents(), TmfTimeRange.ETERNITY, false);
155
experiment.setBookmarksFile(fFile);
157
experiment.initTrace(null, null, null);
161
} else if (traceTypeId.equals(TmfTrace.class.getCanonicalName())) {
162
// Special case: trace bookmark resource
163
final TmfNavigatorContentProvider ncp = new TmfNavigatorContentProvider();
164
ncp.getChildren(fFile.getProject()); // force the model to be populated
165
final TmfProjectElement project = TmfProjectRegistry.getProject(fFile.getProject());
166
for (final ITmfProjectModelElement projectElement : project.getTracesFolder().getChildren()) {
167
final String traceName = fFile.getParent().getName();
168
if (projectElement.getName().equals(traceName)) {
169
final TmfTraceElement traceElement = (TmfTraceElement) projectElement;
170
// Instantiate the trace
171
final ITmfTrace trace = traceElement.instantiateTrace();
172
final ITmfEvent traceEvent = traceElement.instantiateEvent();
173
if ((trace == null) || (traceEvent == null)) {
174
throw new PartInitException(Messages.OpenTraceHandler_NoTraceType);
177
trace.initTrace(traceElement.getResource(), traceElement.getLocation().getPath(), traceEvent.getClass());
178
} catch (final TmfTraceException e) {
185
final TmfNavigatorContentProvider ncp = new TmfNavigatorContentProvider();
186
ncp.getChildren(fFile.getProject()); // force the model to be populated
187
final TmfProjectElement project = TmfProjectRegistry.getProject(fFile.getProject());
188
for (final ITmfProjectModelElement projectElement : project.getTracesFolder().getChildren()) {
189
if (projectElement.getResource().equals(fFile)) {
190
final TmfTraceElement traceElement = (TmfTraceElement) projectElement;
191
// Instantiate the trace
192
final ITmfTrace trace = traceElement.instantiateTrace();
193
final ITmfEvent traceEvent = traceElement.instantiateEvent();
194
if ((trace == null) || (traceEvent == null)) {
195
throw new PartInitException(Messages.OpenTraceHandler_NoTraceType);
198
trace.initTrace(traceElement.getResource(), traceElement.getLocation().getPath(), traceEvent.getClass());
199
} catch (final TmfTraceException e) {
206
} catch (final InvalidRegistryObjectException e) {
207
Activator.getDefault().logError("Error initializing TmfEventsEditor", e); //$NON-NLS-1$
208
} catch (final CoreException e) {
209
Activator.getDefault().logError("Error initializing TmfEventsEditor", e); //$NON-NLS-1$
213
throw new PartInitException("Invalid IEditorInput: " + input.getClass()); //$NON-NLS-1$
217
throw new PartInitException("Invalid IEditorInput: " + fFile.getName()); //$NON-NLS-1$
220
super.setInput(input);
224
public boolean isDirty() {
229
public boolean isSaveAsAllowed() {
234
public void setInput(final IEditorInput input) {
235
super.setInput(input);
236
firePropertyChange(IEditorPart.PROP_INPUT);
240
public void propertyChanged(final Object source, final int propId) {
241
if (propId == IEditorPart.PROP_INPUT) {
242
broadcast(new TmfTraceClosedSignal(this, fTrace));
243
fFile = ((TmfEditorInput) getEditorInput()).getFile();
244
fTrace = ((TmfEditorInput) getEditorInput()).getTrace();
245
super.setInput(new FileEditorInput(fFile));
246
fEventsTable.dispose();
247
if (fTrace != null) {
248
fEventsTable = createEventsTable(fParent, fTrace.getCacheSize());
249
fEventsTable.setTrace(fTrace, true);
250
fEventsTable.refreshBookmarks(fFile);
251
broadcast(new TmfTraceOpenedSignal(this, fTrace, fFile, fEventsTable));
253
fEventsTable = new TmfEventsTable(fParent, 0);
260
public void createPartControl(final Composite parent) {
262
if (fTrace != null) {
263
setPartName(fTrace.getName());
264
fEventsTable = createEventsTable(parent, fTrace.getCacheSize());
265
fEventsTable.setTrace(fTrace, true);
266
fEventsTable.refreshBookmarks(fFile);
267
broadcast(new TmfTraceOpenedSignal(this, fTrace, fFile, fEventsTable));
269
setPartName(getEditorInput().getName());
270
fEventsTable = new TmfEventsTable(parent, 0);
272
addPropertyListener(this);
273
ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
277
public void dispose() {
278
ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
279
removePropertyListener(this);
280
if (fTrace != null) {
281
broadcast(new TmfTraceClosedSignal(this, fTrace));
283
if (fEventsTable != null) {
284
fEventsTable.dispose();
289
protected TmfEventsTable createEventsTable(final Composite parent, final int cacheSize) {
290
TmfEventsTable eventsTable = getEventsTable(parent, cacheSize);
291
if (eventsTable == null) {
292
eventsTable = new TmfEventsTable(parent, cacheSize);
297
private TmfEventsTable getEventsTable(final Composite parent, final int cacheSize) {
298
if (fTrace instanceof TmfExperiment) {
299
return getExperimentEventsTable((TmfExperiment<?>) fTrace, parent, cacheSize);
301
TmfEventsTable eventsTable = null;
303
if (fTrace.getResource() == null) {
306
final String traceType = fTrace.getResource().getPersistentProperty(TmfCommonConstants.TRACETYPE);
307
if (traceType == null) {
310
if (traceType.startsWith(CustomTxtTrace.class.getCanonicalName())) {
311
return new CustomEventsTable(((CustomTxtTrace) fTrace).getDefinition(), parent, cacheSize);
313
if (traceType.startsWith(CustomXmlTrace.class.getCanonicalName())) {
314
return new CustomEventsTable(((CustomXmlTrace) fTrace).getDefinition(), parent, cacheSize);
316
for (final IConfigurationElement ce : TmfTraceType.getTypeElements()) {
317
if (ce.getAttribute(TmfTraceType.ID_ATTR).equals(traceType)) {
318
final IConfigurationElement[] eventsTableTypeCE = ce.getChildren(TmfTraceType.EVENTS_TABLE_TYPE_ELEM);
319
if (eventsTableTypeCE.length != 1) {
322
final String eventsTableType = eventsTableTypeCE[0].getAttribute(TmfTraceType.CLASS_ATTR);
323
if ((eventsTableType == null) || (eventsTableType.length() == 0)) {
326
final Bundle bundle = Platform.getBundle(ce.getContributor().getName());
327
final Class<?> c = bundle.loadClass(eventsTableType);
328
final Class<?>[] constructorArgs = new Class[] { Composite.class, int.class };
329
final Constructor<?> constructor = c.getConstructor(constructorArgs);
330
final Object[] args = new Object[] { parent, cacheSize };
331
eventsTable = (TmfEventsTable) constructor.newInstance(args);
335
} catch (final InvalidRegistryObjectException e) {
336
Activator.getDefault().logError("Error getting TmfEventsTable", e); //$NON-NLS-1$
337
} catch (final CoreException e) {
338
Activator.getDefault().logError("Error getting TmfEventsTable", e); //$NON-NLS-1$
339
} catch (final ClassNotFoundException e) {
340
Activator.getDefault().logError("Error getting TmfEventsTable", e); //$NON-NLS-1$
341
} catch (final SecurityException e) {
342
Activator.getDefault().logError("Error getting TmfEventsTable", e); //$NON-NLS-1$
343
} catch (final NoSuchMethodException e) {
344
Activator.getDefault().logError("Error getting TmfEventsTable", e); //$NON-NLS-1$
345
} catch (final IllegalArgumentException e) {
346
Activator.getDefault().logError("Error getting TmfEventsTable", e); //$NON-NLS-1$
347
} catch (final InstantiationException e) {
348
Activator.getDefault().logError("Error getting TmfEventsTable", e); //$NON-NLS-1$
349
} catch (final IllegalAccessException e) {
350
Activator.getDefault().logError("Error getting TmfEventsTable", e); //$NON-NLS-1$
351
} catch (final InvocationTargetException e) {
352
Activator.getDefault().logError("Error getting TmfEventsTable", e); //$NON-NLS-1$
358
* Get the events table for an experiment.
359
* If all traces in the experiment are of the same type,
360
* use the extension point specified event table
361
* @param experiment the experiment
362
* @param parent the parent Composite
363
* @param cacheSize the event table cache size
364
* @return an events table of the appropriate type
366
private TmfEventsTable getExperimentEventsTable(final TmfExperiment<?> experiment, final Composite parent, final int cacheSize) {
367
TmfEventsTable eventsTable = null;
368
String commonTraceType = null;
370
for (final ITmfTrace<?> trace : experiment.getTraces()) {
371
final IResource resource = trace.getResource();
372
if (resource == null) {
375
final String traceType = resource.getPersistentProperty(TmfCommonConstants.TRACETYPE);
376
if ((commonTraceType != null) && !commonTraceType.equals(traceType)) {
379
commonTraceType = traceType;
381
if (commonTraceType == null) {
384
if (commonTraceType.startsWith(CustomTxtTrace.class.getCanonicalName())) {
385
return new CustomEventsTable(((CustomTxtTrace) experiment.getTraces()[0]).getDefinition(), parent, cacheSize);
387
if (commonTraceType.startsWith(CustomXmlTrace.class.getCanonicalName())) {
388
return new CustomEventsTable(((CustomXmlTrace) experiment.getTraces()[0]).getDefinition(), parent, cacheSize);
390
for (final IConfigurationElement ce : TmfTraceType.getTypeElements()) {
391
if (ce.getAttribute(TmfTraceType.ID_ATTR).equals(commonTraceType)) {
392
final IConfigurationElement[] eventsTableTypeCE = ce.getChildren(TmfTraceType.EVENTS_TABLE_TYPE_ELEM);
393
if (eventsTableTypeCE.length != 1) {
396
final String eventsTableType = eventsTableTypeCE[0].getAttribute(TmfTraceType.CLASS_ATTR);
397
if ((eventsTableType == null) || (eventsTableType.length() == 0)) {
400
final Bundle bundle = Platform.getBundle(ce.getContributor().getName());
401
final Class<?> c = bundle.loadClass(eventsTableType);
402
final Class<?>[] constructorArgs = new Class[] { Composite.class, int.class };
403
final Constructor<?> constructor = c.getConstructor(constructorArgs);
404
final Object[] args = new Object[] { parent, cacheSize };
405
eventsTable = (TmfEventsTable) constructor.newInstance(args);
409
} catch (final CoreException e) {
410
Activator.getDefault().logError("Error getting TmfEventsTable for experiment", e); //$NON-NLS-1$
411
} catch (final InvalidRegistryObjectException e) {
412
Activator.getDefault().logError("Error getting TmfEventsTable for experiment", e); //$NON-NLS-1$
413
} catch (final SecurityException e) {
414
Activator.getDefault().logError("Error getting TmfEventsTable for experiment", e); //$NON-NLS-1$
415
} catch (final IllegalArgumentException e) {
416
Activator.getDefault().logError("Error getting TmfEventsTable for experiment", e); //$NON-NLS-1$
417
} catch (final ClassNotFoundException e) {
418
Activator.getDefault().logError("Error getting TmfEventsTable for experiment", e); //$NON-NLS-1$
419
} catch (final NoSuchMethodException e) {
420
Activator.getDefault().logError("Error getting TmfEventsTable for experiment", e); //$NON-NLS-1$
421
} catch (final InstantiationException e) {
422
Activator.getDefault().logError("Error getting TmfEventsTable for experiment", e); //$NON-NLS-1$
423
} catch (final IllegalAccessException e) {
424
Activator.getDefault().logError("Error getting TmfEventsTable for experiment", e); //$NON-NLS-1$
425
} catch (final InvocationTargetException e) {
426
Activator.getDefault().logError("Error getting TmfEventsTable for experiment", e); //$NON-NLS-1$
432
public ITmfTrace<?> getTrace() {
437
public IFile getBookmarksFile() {
442
public void setFocus() {
443
fEventsTable.setFocus();
444
if (fTrace != null) {
445
broadcast(new TmfTraceSelectedSignal(this, fTrace));
450
@SuppressWarnings("rawtypes")
451
public Object getAdapter(final Class adapter) {
452
if (IGotoMarker.class.equals(adapter)) {
455
return super.getAdapter(adapter);
459
public void resourceChanged(final IResourceChangeEvent event) {
460
for (final IMarkerDelta delta : event.findMarkerDeltas(IMarker.BOOKMARK, false)) {
461
if (delta.getResource().equals(fFile)) {
462
if (delta.getKind() == IResourceDelta.REMOVED) {
463
final IMarker bookmark = delta.getMarker();
464
Display.getDefault().asyncExec(new Runnable() {
467
fEventsTable.removeBookmark(bookmark);
470
} else if (delta.getKind() == IResourceDelta.CHANGED) {
471
Display.getDefault().asyncExec(new Runnable() {
474
fEventsTable.getTable().refresh();
482
// ------------------------------------------------------------------------
484
// ------------------------------------------------------------------------
489
public void addBookmark() {
490
fEventsTable.addBookmark(fFile);
494
// ------------------------------------------------------------------------
496
// ------------------------------------------------------------------------
499
* Handler for the Trace Parser Updated signal
501
* @param signal The incoming signal
503
@SuppressWarnings("unchecked")
505
public void traceParserUpdated(final TmfTraceParserUpdatedSignal signal) {
506
if (signal.getTraceResource().equals(fFile)) {
507
broadcast(new TmfTraceClosedSignal(this, fTrace));
511
final String traceTypeId = fFile.getPersistentProperty(TmfCommonConstants.TRACETYPE);
512
if (traceTypeId != null) {
513
for (final IConfigurationElement ce : TmfTraceType.getTypeElements()) {
514
if (traceTypeId.equals(ce.getAttribute(TmfTraceType.ID_ATTR))) {
515
fTrace = (ITmfTrace<?>) ce.createExecutableExtension(TmfTraceType.TRACE_TYPE_ATTR);
516
final ITmfEvent event = (TmfEvent) ce.createExecutableExtension(TmfTraceType.EVENT_TYPE_ATTR);
517
final String path = fFile.getLocationURI().getPath();
518
fTrace.initTrace(null, path, event.getClass());
523
} catch (final InvalidRegistryObjectException e) {
524
Activator.getDefault().logError("Error handling signal TmfTraceParserUpdatedSignal", e); //$NON-NLS-1$
525
} catch (final TmfTraceException e) {
526
Activator.getDefault().logError("Error handling signal TmfTraceParserUpdatedSignal", e); //$NON-NLS-1$
527
} catch (final CoreException e) {
528
Activator.getDefault().logError("Error handling signal TmfTraceParserUpdatedSignal", e); //$NON-NLS-1$
530
fEventsTable.dispose();
531
if (fTrace != null) {
532
fEventsTable = createEventsTable(fParent, fTrace.getCacheSize());
533
fEventsTable.setTrace(fTrace, true);
534
broadcast(new TmfTraceOpenedSignal(this, fTrace, fFile, fEventsTable));
536
fEventsTable = new TmfEventsTable(fParent, 0);
543
* Handler for the Trace Selected signal
545
* @param signal The incoming signal
548
public void traceSelected(final TmfTraceSelectedSignal signal) {
549
if ((signal.getSource() != this) && signal.getTrace().equals(fTrace)) {
550
getSite().getPage().bringToTop(this);