/*******************************************************************************
- * Copyright (c) 2010, 2011, 2012 Ericsson
+ * Copyright (c) 2010, 2013 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
* Francois Chouinard - Replaced Table by TmfVirtualTable
* Patrick Tasse - Filter implementation (inspired by www.eclipse.org/mat)
* Ansgar Radermacher - Support navigation to model URIs (Bug 396956)
+ * Bernd Hufmann - Updated call site and model URI implementation
*******************************************************************************/
package org.eclipse.linuxtools.tmf.ui.viewers.events;
+import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.util.OpenStrategy;
import org.eclipse.jface.util.SafeRunnable;
+import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.linuxtools.internal.tmf.ui.dialogs.MultiLineInputDialog;
import org.eclipse.linuxtools.tmf.core.component.ITmfDataProvider;
import org.eclipse.linuxtools.tmf.core.component.TmfComponent;
-import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfCustomAttributes;
-import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfEvent;
import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
import org.eclipse.linuxtools.tmf.core.event.ITmfEventField;
-import org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp;
import org.eclipse.linuxtools.tmf.core.event.TmfEventField;
-import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp;
+import org.eclipse.linuxtools.tmf.core.event.lookup.ITmfCallsite;
+import org.eclipse.linuxtools.tmf.core.event.lookup.ITmfModelLookup;
+import org.eclipse.linuxtools.tmf.core.event.lookup.ITmfSourceLookup;
import org.eclipse.linuxtools.tmf.core.filter.ITmfFilter;
import org.eclipse.linuxtools.tmf.core.filter.model.ITmfFilterTreeNode;
import org.eclipse.linuxtools.tmf.core.filter.model.TmfFilterAndNode;
import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal;
import org.eclipse.linuxtools.tmf.core.signal.TmfTraceUpdatedSignal;
+import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
+import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestamp;
import org.eclipse.linuxtools.tmf.core.trace.ITmfContext;
import org.eclipse.linuxtools.tmf.core.trace.ITmfLocation;
import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.ListDialog;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.ide.IGotoMarker;
import org.eclipse.ui.themes.ColorUtil;
private boolean fPackDone = false;
private HeaderState fHeaderState = HeaderState.SEARCH;
private long fSelectedRank = 0;
+ private ITmfTimestamp fSelectedBeginTimestamp = null;
+ private IStatusLineManager fStatusLineManager = null;
// Filter data
private long fFilterMatchCount;
fSashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
// Create a virtual table
- final int style = SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION;
+ final int style = SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION;
fTable = new TmfVirtualTable(fSashForm, style);
// Set the table layout
fTable.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
- final TableItem[] selection = fTable.getSelection();
- if (selection.length > 0) {
- final TableItem selectedTableItem = selection[0];
- if (selectedTableItem != null) {
- if (selectedTableItem.getData(Key.RANK) instanceof Long) {
- fSelectedRank = (Long) selectedTableItem.getData(Key.RANK);
- fRawViewer.selectAndReveal((Long) selectedTableItem.getData(Key.RANK));
+ if (e.item == null) {
+ return;
+ }
+ updateStatusLine(null);
+ if (fTable.getSelectionIndices().length > 0) {
+ if (e.item.getData(Key.RANK) instanceof Long) {
+ fSelectedRank = (Long) e.item.getData(Key.RANK);
+ fRawViewer.selectAndReveal((Long) e.item.getData(Key.RANK));
+ }
+ if (e.item.getData(Key.TIMESTAMP) instanceof ITmfTimestamp) {
+ final ITmfTimestamp ts = (ITmfTimestamp) e.item.getData(Key.TIMESTAMP);
+ if (fTable.getSelectionIndices().length == 1) {
+ fSelectedBeginTimestamp = ts;
}
- if (selectedTableItem.getData(Key.TIMESTAMP) instanceof TmfTimestamp) {
- final TmfTimestamp ts = (TmfTimestamp) selectedTableItem.getData(Key.TIMESTAMP);
- broadcast(new TmfTimeSynchSignal(TmfEventsTable.this, ts));
+ if (fSelectedBeginTimestamp != null) {
+ if (fSelectedBeginTimestamp.compareTo(ts) <= 0) {
+ broadcast(new TmfTimeSynchSignal(TmfEventsTable.this, fSelectedBeginTimestamp, ts));
+ if (fTable.getSelectionIndices().length == 2) {
+ updateStatusLine(ts.getDelta(fSelectedBeginTimestamp));
+ }
+ } else {
+ broadcast(new TmfTimeSynchSignal(TmfEventsTable.this, ts, fSelectedBeginTimestamp));
+ if (fStatusLineManager != null) {
+ updateStatusLine(fSelectedBeginTimestamp.getDelta(ts));
+ }
+ }
+ }
+ } else {
+ if (fTable.getSelectionIndices().length == 1) {
+ fSelectedBeginTimestamp = null;
}
}
}
- fireSelectionChanged(new SelectionChangedEvent(TmfEventsTable.this, getSelection()));
+ if (e.item.getData() != null) {
+ fireSelectionChanged(new SelectionChangedEvent(TmfEventsTable.this, new StructuredSelection(e.item.getData())));
+ } else {
+ fireSelectionChanged(new SelectionChangedEvent(TmfEventsTable.this, StructuredSelection.EMPTY));
+ }
}
});
}
fTable.setSelection(index + 1); // +1 for header row
fSelectedRank = rank;
+ updateStatusLine(null);
} else if (e.data instanceof ITmfLocation) {
// DOES NOT WORK: rank undefined in context from seekLocation()
// ITmfLocation<?> location = (ITmfLocation<?>) e.data;
}
};
- final IAction navigateToEventAction = new Action(Messages.TmfEventsTable_NavigateToModelActionText) {
+ final IAction openCallsiteAction = new Action(Messages.TmfEventsTable_OpenSourceCodeActionText) {
+ @Override
+ public void run() {
+ final TableItem items[] = fTable.getSelection();
+ if (items.length != 1) {
+ return;
+ }
+ final TableItem item = items[0];
+
+ final Object data = item.getData();
+ if (data instanceof ITmfSourceLookup) {
+ ITmfSourceLookup event = (ITmfSourceLookup) data;
+ ITmfCallsite cs = event.getCallsite();
+ if (cs == null || cs.getFileName() == null) {
+ return;
+ }
+ IMarker marker = null;
+ try {
+ String fileName = cs.getFileName();
+ final String trimmedPath = fileName.replaceAll("\\.\\./", ""); //$NON-NLS-1$ //$NON-NLS-2$
+ final ArrayList<IFile> files = new ArrayList<IFile>();
+ ResourcesPlugin.getWorkspace().getRoot().accept(new IResourceVisitor() {
+ @Override
+ public boolean visit(IResource resource) throws CoreException {
+ if (resource instanceof IFile && resource.getFullPath().toString().endsWith(trimmedPath)) {
+ files.add((IFile) resource);
+ }
+ return true;
+ }
+ });
+ IFile file = null;
+ if (files.size() > 1) {
+ ListDialog dialog = new ListDialog(getTable().getShell());
+ dialog.setContentProvider(ArrayContentProvider.getInstance());
+ dialog.setLabelProvider(new LabelProvider() {
+ @Override
+ public String getText(Object element) {
+ return ((IFile) element).getFullPath().toString();
+ }
+ });
+ dialog.setInput(files);
+ dialog.setTitle(Messages.TmfEventsTable_OpenSourceCodeSelectFileDialogTitle);
+ dialog.setMessage(Messages.TmfEventsTable_OpenSourceCodeSelectFileDialogTitle + '\n' + cs.toString());
+ dialog.open();
+ Object[] result = dialog.getResult();
+ if (result != null && result.length > 0) {
+ file = (IFile) result[0];
+ }
+ } else if (files.size() == 1) {
+ file = files.get(0);
+ }
+ if (file != null) {
+ marker = file.createMarker(IMarker.MARKER);
+ marker.setAttribute(IMarker.LINE_NUMBER, Long.valueOf(cs.getLineNumber()).intValue());
+ IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), marker);
+ marker.delete();
+ } else if (files.size() == 0){
+ displayException(new FileNotFoundException('\'' + cs.toString() + '\'' + '\n' + Messages.TmfEventsTable_OpenSourceCodeNotFound));
+ }
+ } catch (CoreException e) {
+ displayException(e);
+ }
+ }
+ }
+ };
+
+ final IAction openModelAction = new Action(Messages.TmfEventsTable_OpenModelActionText) {
@Override
public void run() {
final TableItem item = items[0];
final Object eventData = item.getData();
- if (eventData instanceof CtfTmfEvent) {
- String modelURI = ((CtfTmfEvent) eventData).getCustomAttribute(CtfCustomAttributes.MODEL_URI_KEY);
+ if (eventData instanceof ITmfModelLookup) {
+ String modelURI = ((ITmfModelLookup) eventData).getModelUri();
if (modelURI != null) {
IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
catch (CoreException e) {
displayException(e);
}
+ } else {
+ displayException(new FileNotFoundException('\'' + modelURI + '\'' + '\n' + Messages.TmfEventsTable_OpenModelUnsupportedURI));
}
}
}
}
};
+
final IAction showSearchBarAction = new Action(Messages.TmfEventsTable_ShowSearchBarActionText) {
@Override
public void run() {
return;
}
}
+
// Right-click on table
if (fTable.isVisible() && fRawViewer.isVisible()) {
tablePopupMenu.add(hideTableAction);
tablePopupMenu.add(showRawAction);
}
tablePopupMenu.add(new Separator());
+
if (item != null) {
- // add navigation action, if event meta data contain a model URI
- final Object eventData = item.getData();
- if (eventData instanceof CtfTmfEvent) {
- if (((CtfTmfEvent) eventData).listCustomAttributes().contains(CtfCustomAttributes.MODEL_URI_KEY)) {
- tablePopupMenu.add(navigateToEventAction);
- tablePopupMenu.add(new Separator());
+ final Object data = item.getData();
+ Separator separator = null;
+ if (data instanceof ITmfSourceLookup) {
+ ITmfSourceLookup event = (ITmfSourceLookup) data;
+ if (event.getCallsite() != null) {
+ tablePopupMenu.add(openCallsiteAction);
+ separator = new Separator();
+ }
+ }
+
+ if (data instanceof ITmfModelLookup) {
+ ITmfModelLookup event = (ITmfModelLookup) data;
+ if (event.getModelUri() != null) {
+ tablePopupMenu.add(openModelAction);
+ separator = new Separator();
+ }
+
+ if (separator != null) {
+ tablePopupMenu.add(separator);
}
}
}
+
tablePopupMenu.add(clearFiltersAction);
final ITmfFilterTreeNode[] savedFilters = FilterManager.getSavedFilters();
if (savedFilters.length > 0) {
} else if (fHeaderState == HeaderState.FILTER) {
fHeaderState = HeaderState.SEARCH;
}
+ fTable.setSelection(0);
fTable.refresh();
return;
}
fTable.setSelection(0);
}
fireFilterApplied(null);
+ updateStatusLine(null);
}
/**
return;
}
request = new TmfDataRequest(ITmfEvent.class, (int) fFilterCheckCount,
- nbRequested, fTrace.getCacheSize(), ExecutionType.BACKGROUND) {
+ nbRequested, ExecutionType.BACKGROUND) {
@Override
public void handleData(final ITmfEvent event) {
super.handleData(event);
final long rank = fFilterCheckCount;
final int index = (int) fFilterMatchCount;
fFilterMatchCount++;
- fCache.storeEvent(event.clone(), rank, index);
+ fCache.storeEvent(event, rank, index);
refreshTable();
} else if ((fFilterCheckCount % 100) == 0) {
refreshTable();
startIndex = Math.max(0, fTable.getTopIndex() - 1); // -1 for header row
}
final ITmfFilterTreeNode eventFilter = (ITmfFilterTreeNode) fTable.getData(Key.FILTER_OBJ);
- if (eventFilter != null)
- {
+ if (eventFilter != null) {
startIndex = Math.max(0, startIndex - 1); // -1 for top filter status row
}
fSearchThread = new SearchThread(searchFilter, eventFilter, startIndex, fSelectedRank, Direction.FORWARD);
startIndex = fTable.getTopIndex() - 2; // -1 for header row, -1 for previous event
}
final ITmfFilterTreeNode eventFilter = (ITmfFilterTreeNode) fTable.getData(Key.FILTER_OBJ);
- if (eventFilter != null)
- {
+ if (eventFilter != null) {
startIndex = startIndex - 1; // -1 for top filter status row
}
fSearchThread = new SearchThread(searchFilter, eventFilter, startIndex, fSelectedRank, Direction.BACKWARD);
if (direction == Direction.BACKWARD) {
rank = Math.max(0, rank - fTrace.getCacheSize() + 1);
}
- request = new TmfDataRequest(ITmfEvent.class, (int) rank, nbRequested, fTrace.getCacheSize(), ExecutionType.BACKGROUND) {
+ request = new TmfDataRequest(ITmfEvent.class, (int) rank, nbRequested, ExecutionType.BACKGROUND) {
long currentRank = rank;
@Override
if (foundTimestamp != null) {
broadcast(new TmfTimeSynchSignal(TmfEventsTable.this, foundTimestamp));
}
+ fireSelectionChanged(new SelectionChangedEvent(TmfEventsTable.this, getSelection()));
synchronized (fSearchSyncObj) {
fSearchThread = null;
}
+ updateStatusLine(null);
}
});
return Status.OK_STATUS;
final String reference = event.getReference();
final String content = event.getContent().toString();
fields = new TmfEventField[] {
- new TmfEventField(ITmfEvent.EVENT_FIELD_TIMESTAMP, timestamp),
- new TmfEventField(ITmfEvent.EVENT_FIELD_SOURCE, source),
- new TmfEventField(ITmfEvent.EVENT_FIELD_TYPE, type),
- new TmfEventField(ITmfEvent.EVENT_FIELD_REFERENCE, reference),
- new TmfEventField(ITmfEvent.EVENT_FIELD_CONTENT, content)
+ new TmfEventField(ITmfEvent.EVENT_FIELD_TIMESTAMP, timestamp, null),
+ new TmfEventField(ITmfEvent.EVENT_FIELD_SOURCE, source, null),
+ new TmfEventField(ITmfEvent.EVENT_FIELD_TYPE, type, null),
+ new TmfEventField(ITmfEvent.EVENT_FIELD_REFERENCE, reference, null),
+ new TmfEventField(ITmfEvent.EVENT_FIELD_CONTENT, content, null)
};
}
return fields;
});
}
+ /**
+ * Assign the status line manager
+ *
+ * @param statusLineManager
+ * The status line manager, or null to disable status line messages
+ * @since 3.0
+ */
+ public void setStatusLineManager(IStatusLineManager statusLineManager) {
+ if (fStatusLineManager != null && statusLineManager == null) {
+ fStatusLineManager.setMessage(""); //$NON-NLS-1$
+ }
+ fStatusLineManager = statusLineManager;
+ }
+
+ private void updateStatusLine(ITmfTimestamp delta) {
+ if (fStatusLineManager != null) {
+ if (delta != null) {
+ fStatusLineManager.setMessage("\u0394: " + delta); //$NON-NLS-1$
+ } else {
+ fStatusLineManager.setMessage(null);
+ }
+ }
+ }
+
// ------------------------------------------------------------------------
// Event cache
// ------------------------------------------------------------------------
// ISelectionProvider
// ------------------------------------------------------------------------
- /* (non-Javadoc)
- * @see org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
- */
/**
* @since 2.0
*/
selectionChangedListeners.add(listener);
}
- /* (non-Javadoc)
- * @see org.eclipse.jface.viewers.ISelectionProvider#getSelection()
- */
/**
* @since 2.0
*/
return new StructuredSelection(list);
}
- /* (non-Javadoc)
- * @see org.eclipse.jface.viewers.ISelectionProvider#removeSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
- */
/**
* @since 2.0
*/
selectionChangedListeners.remove(listener);
}
- /* (non-Javadoc)
- * @see org.eclipse.jface.viewers.ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection)
- */
/**
* @since 2.0
*/
if (tableItem.getData(Key.RANK) != null) {
final StringBuffer defaultMessage = new StringBuffer();
for (int i = 0; i < fTable.getColumns().length; i++) {
- if (i > 0)
- {
+ if (i > 0) {
defaultMessage.append(", "); //$NON-NLS-1$
}
defaultMessage.append(tableItem.getText(i));
} else if (rank >= fTable.getItemCount()) {
fPendingGotoRank = rank;
}
+ fSelectedRank = rank;
fTable.setSelection(index + 1); // +1 for header row
+ updateStatusLine(null);
}
}
// Listeners
// ------------------------------------------------------------------------
- /*
- * (non-Javadoc)
- *
- * @see org.eclipse.linuxtools.tmf.ui.views.colors.IColorSettingsListener#colorSettingsChanged(org.eclipse.linuxtools.tmf.ui.views.colors.ColorSetting[])
- */
@Override
public void colorSettingsChanged(final ColorSetting[] colorSettings) {
fTable.refresh();
if ((fPendingGotoRank != -1) && ((fPendingGotoRank + 1) < fTable.getItemCount())) { // +1 for header row
fTable.setSelection((int) fPendingGotoRank + 1); // +1 for header row
fPendingGotoRank = -1;
+ updateStatusLine(null);
}
} else {
startFilterThread();
// Create a request for one event that will be queued after other ongoing requests. When this request is completed
// do the work to select the actual event with the timestamp specified in the signal. This procedure prevents
// the method fTrace.getRank() from interfering and delaying ongoing requests.
- final TmfDataRequest subRequest = new TmfDataRequest(ITmfEvent.class, 0, 1, ExecutionType.FOREGROUND) {
+ final TmfDataRequest subRequest = new TmfDataRequest(ITmfEvent.class,
+ 0, 1, ExecutionType.FOREGROUND) {
- TmfTimestamp ts = new TmfTimestamp(signal.getCurrentTime());
+ TmfTimestamp ts = new TmfTimestamp(signal.getBeginTime());
@Override
public void handleData(final ITmfEvent event) {
if (fTable.isDisposed()) {
return;
}
- if (fTable.getData(Key.FILTER_OBJ) != null)
- {
+ if (fTable.getData(Key.FILTER_OBJ) != null) {
index = fCache.getFilteredEventIndex(rank) + 1; // +1 for top filter status row
}
fTable.setSelection(index + 1); // +1 for header row
fRawViewer.selectAndReveal(rank);
+ updateStatusLine(null);
}
});
}
*/
private static void displayException(final Exception e) {
final MessageBox mb = new MessageBox(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
- mb.setText(e.getClass().getName());
+ mb.setText(e.getClass().getSimpleName());
mb.setMessage(e.getMessage());
mb.open();
}