import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+import java.io.File;
import java.io.FileNotFoundException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import org.eclipse.core.commands.ParameterizedCommand;
import org.eclipse.core.commands.common.NotDefinedException;
import org.eclipse.core.expressions.IEvaluationContext;
+import org.eclipse.core.filesystem.EFS;
+import org.eclipse.core.filesystem.IFileStore;
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.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
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.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.ColorRegistry;
import org.eclipse.jface.resource.FontRegistry;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.OpenStrategy;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.window.Window;
+import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.tracecompass.internal.tmf.ui.Messages;
import org.eclipse.tracecompass.internal.tmf.ui.commands.CopyToClipboardOperation;
import org.eclipse.tracecompass.internal.tmf.ui.commands.ExportToTextCommandHandler;
-import org.eclipse.tracecompass.internal.tmf.ui.dialogs.MultiLineInputDialog;
+import org.eclipse.tracecompass.internal.tmf.ui.dialogs.AddBookmarkDialog;
import org.eclipse.tracecompass.tmf.core.component.ITmfEventProvider;
import org.eclipse.tracecompass.tmf.core.component.TmfComponent;
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
import org.eclipse.tracecompass.tmf.core.filter.model.TmfFilterNode;
import org.eclipse.tracecompass.tmf.core.request.ITmfEventRequest.ExecutionType;
import org.eclipse.tracecompass.tmf.core.request.TmfEventRequest;
+import org.eclipse.tracecompass.tmf.core.resources.ITmfMarker;
import org.eclipse.tracecompass.tmf.core.signal.TmfEventFilterAppliedSignal;
import org.eclipse.tracecompass.tmf.core.signal.TmfEventSearchAppliedSignal;
import org.eclipse.tracecompass.tmf.core.signal.TmfEventSelectedSignal;
import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
import org.eclipse.tracecompass.tmf.core.signal.TmfTraceUpdatedSignal;
import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
+import org.eclipse.tracecompass.tmf.core.timestamp.TmfNanoTimestamp;
import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
import org.eclipse.tracecompass.tmf.core.trace.ITmfContext;
import org.eclipse.tracecompass.tmf.ui.widgets.rawviewer.TmfRawEventViewer;
import org.eclipse.tracecompass.tmf.ui.widgets.virtualtable.TmfVirtualTable;
import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.ide.IGotoMarker;
+import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.ui.themes.ColorUtil;
import org.eclipse.ui.themes.IThemeManager;
/**
* Empty string array, used by {@link #getItemStrings}.
*/
- protected static final @NonNull String[] EMPTY_STRING_ARRAY = new String[0];
+ protected static final String @NonNull [] EMPTY_STRING_ARRAY = new String[0];
/**
* Empty string
private static final int FILTER_SUMMARY_INDEX = 1;
private static final int EVENT_COLUMNS_START_INDEX = MARGIN_COLUMN_INDEX + 1;
+ private final class ColumnMovedListener extends ControlAdapter {
+ /*
+ * Make sure that the margin column is always first and keep the
+ * column order variable up to date.
+ */
+ @Override
+ public void controlMoved(ControlEvent e) {
+ int[] order = fTable.getColumnOrder();
+ if (order[0] == MARGIN_COLUMN_INDEX) {
+ fColumnOrder = order;
+ return;
+ }
+ for (int i = order.length - 1; i > 0; i--) {
+ if (order[i] == MARGIN_COLUMN_INDEX) {
+ order[i] = order[i - 1];
+ order[i - 1] = MARGIN_COLUMN_INDEX;
+ }
+ }
+ fTable.setColumnOrder(order);
+ fColumnOrder = fTable.getColumnOrder();
+ }
+ }
+
+ private final class TableSelectionListener extends SelectionAdapter {
+ @Override
+ public void widgetSelected(final SelectionEvent e) {
+ 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));
+ } else {
+ fSelectedRank = -1;
+ }
+ if (fTable.getSelectionIndices().length == 1) {
+ fSelectedBeginRank = fSelectedRank;
+ }
+ if (e.item.getData(Key.TIMESTAMP) instanceof ITmfTimestamp) {
+ final ITmfTimestamp ts = NonNullUtils.checkNotNull((ITmfTimestamp) e.item.getData(Key.TIMESTAMP));
+ if (fTable.getSelectionIndices().length == 1) {
+ fSelectedBeginTimestamp = ts;
+ }
+ ITmfTimestamp selectedBeginTimestamp = fSelectedBeginTimestamp;
+ if (selectedBeginTimestamp != null) {
+ broadcast(new TmfSelectionRangeUpdatedSignal(TmfEventsTable.this, selectedBeginTimestamp, ts));
+ if (fTable.getSelectionIndices().length == 2) {
+ updateStatusLine(ts.getDelta(selectedBeginTimestamp));
+ }
+ }
+ } else {
+ if (fTable.getSelectionIndices().length == 1) {
+ fSelectedBeginTimestamp = null;
+ }
+ }
+ }
+ if (e.item.getData() instanceof ITmfEvent) {
+ broadcast(new TmfEventSelectedSignal(TmfEventsTable.this, (ITmfEvent) e.item.getData()));
+ fireSelectionChanged(new SelectionChangedEvent(TmfEventsTable.this, new StructuredSelection(e.item.getData())));
+ } else {
+ fireSelectionChanged(new SelectionChangedEvent(TmfEventsTable.this, StructuredSelection.EMPTY));
+ }
+ }
+ }
+
+ private final class MouseDoubleClickListener extends MouseAdapter {
+ @Override
+ public void mouseDoubleClick(final MouseEvent event) {
+ if (event.button != 1) {
+ return;
+ }
+ // Identify the selected row
+ final Point point = new Point(event.x, event.y);
+ final TableItem item = fTable.getItem(point);
+ if (item != null) {
+ final Rectangle imageBounds = item.getImageBounds(0);
+ imageBounds.width = BOOKMARK_IMAGE.getBounds().width;
+ if (imageBounds.contains(point)) {
+ final Long rank = (Long) item.getData(Key.RANK);
+ if (rank != null) {
+ toggleBookmark(rank);
+ }
+ }
+ }
+ }
+ }
+
+ private final class RawSelectionListener implements Listener {
+ @Override
+ public void handleEvent(final Event e) {
+ if (fTrace == null) {
+ return;
+ }
+ long rank;
+ if (e.data instanceof Long) {
+ rank = (Long) e.data;
+ } else if (e.data instanceof ITmfLocation) {
+ rank = findRank((ITmfLocation) e.data);
+ } else {
+ return;
+ }
+ int index = (int) rank;
+ if (fTable.getData(Key.FILTER_OBJ) != null) {
+ // +1 for top filter status row
+ index = fCache.getFilteredEventIndex(rank) + 1;
+ }
+ // +1 for header row
+ fTable.setSelection(index + 1);
+ fSelectedRank = rank;
+ fSelectedBeginRank = fSelectedRank;
+ updateStatusLine(null);
+ final TableItem[] selection = fTable.getSelection();
+ if ((selection != null) && (selection.length > 0)) {
+ TableItem item = fTable.getSelection()[0];
+ final TmfTimestamp ts = (TmfTimestamp) item.getData(Key.TIMESTAMP);
+ if (ts != null) {
+ broadcast(new TmfSelectionRangeUpdatedSignal(TmfEventsTable.this, ts));
+ }
+ if (item.getData() instanceof ITmfEvent) {
+ broadcast(new TmfEventSelectedSignal(TmfEventsTable.this, (ITmfEvent) item.getData()));
+ fireSelectionChanged(new SelectionChangedEvent(TmfEventsTable.this, new StructuredSelection(item.getData())));
+ } else {
+ fireSelectionChanged(new SelectionChangedEvent(TmfEventsTable.this, StructuredSelection.EMPTY));
+ }
+ }
+ }
+
+ private long findRank(final ITmfLocation selectedLocation) {
+ final double selectedRatio = fTrace.getLocationRatio(selectedLocation);
+ long low = 0;
+ long high = fTrace.getNbEvents();
+ long rank = high / 2;
+ double ratio = -1;
+ while (ratio != selectedRatio) {
+ ITmfContext context = fTrace.seekEvent(rank);
+ ratio = fTrace.getLocationRatio(context.getLocation());
+ context.dispose();
+ if (ratio < selectedRatio) {
+ low = rank;
+ rank = (rank + high) / 2;
+ } else if (ratio > selectedRatio) {
+ high = rank;
+ rank = (rank + low) / 2;
+ }
+ if ((high - low) < 2) {
+ break;
+ }
+ }
+ return rank;
+ }
+ }
+
+ private final class SetDataListener implements Listener {
+ @Override
+ public void handleEvent(final Event event) {
+
+ final TableItem item = (TableItem) event.item;
+ int index = event.index - 1; // -1 for the header row
+
+ if (event.index == 0) {
+ setHeaderRowItemData(item);
+ return;
+ }
+
+ if (fTable.getData(Key.FILTER_OBJ) != null) {
+ if ((event.index == 1) || (event.index == (fTable.getItemCount() - 1))) {
+ setFilterStatusRowItemData(item);
+ return;
+ }
+ /* -1 for top filter status row */
+ index = index - 1;
+ }
+
+ final CachedEvent cachedEvent = fCache.getEvent(index);
+ if (cachedEvent != null) {
+ setItemData(item, cachedEvent, cachedEvent.rank);
+ return;
+ }
+
+ // Else, fill the cache asynchronously (and off the UI thread)
+ event.doit = false;
+ }
+ }
+
+ private final class PainItemListener implements Listener {
+ @Override
+ public void handleEvent(Event event) {
+ TableItem item = (TableItem) event.item;
+
+ // we promised to paint the table item's foreground
+ GC gc = event.gc;
+ Image image = item.getImage(event.index);
+ if (image != null) {
+ Rectangle imageBounds = item.getImageBounds(event.index);
+ /*
+ * The image bounds don't match the default image position.
+ */
+ if (IS_LINUX) {
+ gc.drawImage(image, imageBounds.x + 1, imageBounds.y + 3);
+ } else {
+ gc.drawImage(image, imageBounds.x, imageBounds.y + 1);
+ }
+ }
+ gc.setForeground(item.getForeground(event.index));
+ gc.setFont(item.getFont(event.index));
+ String text = item.getText(event.index);
+ Rectangle textBounds = item.getTextBounds(event.index);
+ /*
+ * The text bounds don't match the default text position.
+ */
+ if (IS_LINUX) {
+ gc.drawText(text, textBounds.x + 1, textBounds.y + 3, true);
+ } else {
+ gc.drawText(text, textBounds.x - 1, textBounds.y + 2, true);
+ }
+ }
+ }
+
+ private final class EraseItemListener implements Listener {
+ @Override
+ public void handleEvent(Event event) {
+ TableItem item = (TableItem) event.item;
+ List<?> styleRanges = (List<?>) item.getData(Key.STYLE_RANGES);
+
+ GC gc = event.gc;
+ Color background = item.getBackground(event.index);
+ /*
+ * Paint the background if it is not the default system color.
+ * In Windows, if you let the widget draw the background, it
+ * will not show the item's background color if the item is
+ * selected or hot. If there are no style ranges and the item
+ * background is the default system color, we do not want to
+ * paint it or otherwise we would override the platform theme
+ * (e.g. alternating colors).
+ */
+ if (styleRanges != null || !background.equals(item.getParent().getBackground())) {
+ // we will paint the table item's background
+ event.detail &= ~SWT.BACKGROUND;
+
+ // paint the item's default background
+ gc.setBackground(background);
+ gc.fillRectangle(event.x, event.y, event.width, event.height);
+ }
+
+ /*
+ * We will paint the table item's foreground. In Windows, if you
+ * paint the background but let the widget draw the foreground,
+ * it will override your background, unless the item is selected
+ * or hot.
+ */
+ event.detail &= ~SWT.FOREGROUND;
+
+ // paint the highlighted background for all style ranges
+ if (styleRanges != null) {
+ Rectangle textBounds = item.getTextBounds(event.index);
+ String text = item.getText(event.index);
+ for (Object o : styleRanges) {
+ if (o instanceof StyleRange) {
+ StyleRange styleRange = (StyleRange) o;
+ if (styleRange.data.equals(event.index)) {
+ int startIndex = styleRange.start;
+ int endIndex = startIndex + styleRange.length;
+ int startX = gc.textExtent(text.substring(0, startIndex)).x;
+ int endX = gc.textExtent(text.substring(0, endIndex)).x;
+ gc.setBackground(styleRange.background);
+ gc.fillRectangle(textBounds.x + startX, textBounds.y, (endX - startX), textBounds.height);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private final class TooltipListener implements Listener {
+ Shell tooltipShell = null;
+
+ @Override
+ public void handleEvent(final Event event) {
+ switch (event.type) {
+ case SWT.MouseHover:
+ final TableItem item = fTable.getItem(new Point(event.x, event.y));
+ if (item == null) {
+ return;
+ }
+ final Long rank = (Long) item.getData(Key.RANK);
+ if (rank == null) {
+ return;
+ }
+ final String tooltipText = (String) item.getData(Key.BOOKMARK);
+ final Rectangle bounds = item.getImageBounds(0);
+ bounds.width = BOOKMARK_IMAGE.getBounds().width;
+ if (!bounds.contains(event.x, event.y)) {
+ return;
+ }
+ if ((tooltipShell != null) && !tooltipShell.isDisposed()) {
+ tooltipShell.dispose();
+ }
+ tooltipShell = new Shell(fTable.getShell(), SWT.ON_TOP | SWT.NO_FOCUS | SWT.TOOL);
+ tooltipShell.setBackground(PlatformUI.getWorkbench().getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+ final FillLayout layout = new FillLayout();
+ layout.marginWidth = 2;
+ tooltipShell.setLayout(layout);
+ final Label label = new Label(tooltipShell, SWT.WRAP);
+ String text = rank.toString() + (tooltipText != null ? ": " + tooltipText : EMPTY_STRING); //$NON-NLS-1$
+ label.setForeground(PlatformUI.getWorkbench().getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND));
+ label.setBackground(PlatformUI.getWorkbench().getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+ label.setText(text);
+ label.addListener(SWT.MouseExit, this);
+ label.addListener(SWT.MouseDown, this);
+ label.addListener(SWT.MouseWheel, this);
+ final Point size = tooltipShell.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+ /*
+ * Bug in Linux. The coordinates of the event have an origin
+ * that excludes the table header but the method toDisplay()
+ * expects coordinates relative to an origin that includes
+ * the table header.
+ */
+ int y = event.y;
+ if (IS_LINUX) {
+ y += fTable.getHeaderHeight();
+ }
+ Point pt = fTable.toDisplay(event.x, y);
+ pt.x += BOOKMARK_IMAGE.getBounds().width;
+ pt.y += item.getBounds().height;
+ tooltipShell.setBounds(pt.x, pt.y, size.x, size.y);
+ tooltipShell.setVisible(true);
+ break;
+ case SWT.Dispose:
+ case SWT.KeyDown:
+ case SWT.MouseMove:
+ case SWT.MouseExit:
+ case SWT.MouseDown:
+ case SWT.MouseWheel:
+ if (tooltipShell != null) {
+ tooltipShell.dispose();
+ tooltipShell = null;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
/**
* The events table search/filter/data keys
*
/**
* The width of a table item
*
- * @since 2.0
+ * @since 1.1
*/
String WIDTH = "$width"; //$NON-NLS-1$
}
column.setMoveable(true);
column.setData(Key.WIDTH, -1);
}
- column.addControlListener(new ControlAdapter() {
- /*
- * Make sure that the margin column is always first and keep the
- * column order variable up to date.
- */
- @Override
- public void controlMoved(ControlEvent e) {
- int[] order = fTable.getColumnOrder();
- if (order[0] == MARGIN_COLUMN_INDEX) {
- fColumnOrder = order;
- return;
- }
- for (int i = order.length - 1; i > 0; i--) {
- if (order[i] == MARGIN_COLUMN_INDEX) {
- order[i] = order[i - 1];
- order[i - 1] = MARGIN_COLUMN_INDEX;
- }
- }
- fTable.setColumnOrder(order);
- fColumnOrder = fTable.getColumnOrder();
- }
- });
+ column.addControlListener(new ColumnMovedListener());
}
fColumnOrder = fTable.getColumnOrder();
createHeaderEditor();
// Handle the table item selection
- fTable.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(final SelectionEvent e) {
- 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));
- } else {
- fSelectedRank = -1;
- }
- if (fTable.getSelectionIndices().length == 1) {
- fSelectedBeginRank = fSelectedRank;
- }
- if (e.item.getData(Key.TIMESTAMP) instanceof ITmfTimestamp) {
- final ITmfTimestamp ts = NonNullUtils.checkNotNull((ITmfTimestamp) e.item.getData(Key.TIMESTAMP));
- if (fTable.getSelectionIndices().length == 1) {
- fSelectedBeginTimestamp = ts;
- }
- ITmfTimestamp selectedBeginTimestamp = fSelectedBeginTimestamp;
- if (selectedBeginTimestamp != null) {
- broadcast(new TmfSelectionRangeUpdatedSignal(TmfEventsTable.this, selectedBeginTimestamp, ts));
- if (fTable.getSelectionIndices().length == 2) {
- updateStatusLine(ts.getDelta(selectedBeginTimestamp));
- }
- }
- } else {
- if (fTable.getSelectionIndices().length == 1) {
- fSelectedBeginTimestamp = null;
- }
- }
- }
- if (e.item.getData() instanceof ITmfEvent) {
- broadcast(new TmfEventSelectedSignal(TmfEventsTable.this, (ITmfEvent) e.item.getData()));
- fireSelectionChanged(new SelectionChangedEvent(TmfEventsTable.this, new StructuredSelection(e.item.getData())));
- } else {
- fireSelectionChanged(new SelectionChangedEvent(TmfEventsTable.this, StructuredSelection.EMPTY));
- }
- }
- });
+ fTable.addSelectionListener(new TableSelectionListener());
int realCacheSize = Math.max(cacheSize, Display.getDefault().getBounds().height / fTable.getItemHeight());
realCacheSize = Math.min(realCacheSize, MAX_CACHE_SIZE);
fCache = new TmfEventsCache(realCacheSize, this);
// Handle the table item requests
- fTable.addListener(SWT.SetData, new Listener() {
-
- @Override
- public void handleEvent(final Event event) {
-
- final TableItem item = (TableItem) event.item;
- int index = event.index - 1; // -1 for the header row
-
- if (event.index == 0) {
- setHeaderRowItemData(item);
- return;
- }
-
- if (fTable.getData(Key.FILTER_OBJ) != null) {
- if ((event.index == 1) || (event.index == (fTable.getItemCount() - 1))) {
- setFilterStatusRowItemData(item);
- return;
- }
- /* -1 for top filter status row */
- index = index - 1;
- }
-
- final CachedEvent cachedEvent = fCache.getEvent(index);
- if (cachedEvent != null) {
- setItemData(item, cachedEvent, cachedEvent.rank);
- return;
- }
-
- // Else, fill the cache asynchronously (and off the UI thread)
- event.doit = false;
- }
- });
+ fTable.addListener(SWT.SetData, new SetDataListener());
fTable.addListener(SWT.MenuDetect, new Listener() {
@Override
}
});
- fTable.addMouseListener(new MouseAdapter() {
- @Override
- public void mouseDoubleClick(final MouseEvent event) {
- if (event.button != 1) {
- return;
- }
- // Identify the selected row
- final Point point = new Point(event.x, event.y);
- final TableItem item = fTable.getItem(point);
- if (item != null) {
- final Rectangle imageBounds = item.getImageBounds(0);
- imageBounds.width = BOOKMARK_IMAGE.getBounds().width;
- if (imageBounds.contains(point)) {
- final Long rank = (Long) item.getData(Key.RANK);
- if (rank != null) {
- toggleBookmark(rank);
- }
- }
- }
- }
- });
-
- final Listener tooltipListener = new Listener() {
- Shell tooltipShell = null;
+ fTable.addMouseListener(new MouseDoubleClickListener());
- @Override
- public void handleEvent(final Event event) {
- switch (event.type) {
- case SWT.MouseHover:
- final TableItem item = fTable.getItem(new Point(event.x, event.y));
- if (item == null) {
- return;
- }
- final Long rank = (Long) item.getData(Key.RANK);
- if (rank == null) {
- return;
- }
- final String tooltipText = (String) item.getData(Key.BOOKMARK);
- final Rectangle bounds = item.getImageBounds(0);
- bounds.width = BOOKMARK_IMAGE.getBounds().width;
- if (!bounds.contains(event.x, event.y)) {
- return;
- }
- if ((tooltipShell != null) && !tooltipShell.isDisposed()) {
- tooltipShell.dispose();
- }
- tooltipShell = new Shell(fTable.getShell(), SWT.ON_TOP | SWT.NO_FOCUS | SWT.TOOL);
- tooltipShell.setBackground(PlatformUI.getWorkbench().getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
- final FillLayout layout = new FillLayout();
- layout.marginWidth = 2;
- tooltipShell.setLayout(layout);
- final Label label = new Label(tooltipShell, SWT.WRAP);
- String text = rank.toString() + (tooltipText != null ? ": " + tooltipText : EMPTY_STRING); //$NON-NLS-1$
- label.setForeground(PlatformUI.getWorkbench().getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND));
- label.setBackground(PlatformUI.getWorkbench().getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
- label.setText(text);
- label.addListener(SWT.MouseExit, this);
- label.addListener(SWT.MouseDown, this);
- label.addListener(SWT.MouseWheel, this);
- final Point size = tooltipShell.computeSize(SWT.DEFAULT, SWT.DEFAULT);
- /*
- * Bug in Linux. The coordinates of the event have an origin
- * that excludes the table header but the method toDisplay()
- * expects coordinates relative to an origin that includes
- * the table header.
- */
- int y = event.y;
- if (IS_LINUX) {
- y += fTable.getHeaderHeight();
- }
- Point pt = fTable.toDisplay(event.x, y);
- pt.x += BOOKMARK_IMAGE.getBounds().width;
- pt.y += item.getBounds().height;
- tooltipShell.setBounds(pt.x, pt.y, size.x, size.y);
- tooltipShell.setVisible(true);
- break;
- case SWT.Dispose:
- case SWT.KeyDown:
- case SWT.MouseMove:
- case SWT.MouseExit:
- case SWT.MouseDown:
- case SWT.MouseWheel:
- if (tooltipShell != null) {
- tooltipShell.dispose();
- tooltipShell = null;
- }
- break;
- default:
- break;
- }
- }
- };
+ final Listener tooltipListener = new TooltipListener();
fTable.addListener(SWT.MouseHover, tooltipListener);
fTable.addListener(SWT.Dispose, tooltipListener);
fTable.addListener(SWT.MouseDown, tooltipListener);
fTable.addListener(SWT.MouseWheel, tooltipListener);
- fTable.addListener(SWT.EraseItem, new Listener() {
- @Override
- public void handleEvent(Event event) {
- TableItem item = (TableItem) event.item;
- List<?> styleRanges = (List<?>) item.getData(Key.STYLE_RANGES);
-
- GC gc = event.gc;
- Color background = item.getBackground(event.index);
- /*
- * Paint the background if it is not the default system color.
- * In Windows, if you let the widget draw the background, it
- * will not show the item's background color if the item is
- * selected or hot. If there are no style ranges and the item
- * background is the default system color, we do not want to
- * paint it or otherwise we would override the platform theme
- * (e.g. alternating colors).
- */
- if (styleRanges != null || !background.equals(item.getParent().getBackground())) {
- // we will paint the table item's background
- event.detail &= ~SWT.BACKGROUND;
-
- // paint the item's default background
- gc.setBackground(background);
- gc.fillRectangle(event.x, event.y, event.width, event.height);
- }
-
- /*
- * We will paint the table item's foreground. In Windows, if you
- * paint the background but let the widget draw the foreground,
- * it will override your background, unless the item is selected
- * or hot.
- */
- event.detail &= ~SWT.FOREGROUND;
-
- // paint the highlighted background for all style ranges
- if (styleRanges != null) {
- Rectangle textBounds = item.getTextBounds(event.index);
- String text = item.getText(event.index);
- for (Object o : styleRanges) {
- if (o instanceof StyleRange) {
- StyleRange styleRange = (StyleRange) o;
- if (styleRange.data.equals(event.index)) {
- int startIndex = styleRange.start;
- int endIndex = startIndex + styleRange.length;
- int startX = gc.textExtent(text.substring(0, startIndex)).x;
- int endX = gc.textExtent(text.substring(0, endIndex)).x;
- gc.setBackground(styleRange.background);
- gc.fillRectangle(textBounds.x + startX, textBounds.y, (endX - startX), textBounds.height);
- }
- }
- }
- }
- }
- });
-
- fTable.addListener(SWT.PaintItem, new Listener() {
- @Override
- public void handleEvent(Event event) {
- TableItem item = (TableItem) event.item;
+ fTable.addListener(SWT.EraseItem, new EraseItemListener());
- // we promised to paint the table item's foreground
- GC gc = event.gc;
- Image image = item.getImage(event.index);
- if (image != null) {
- Rectangle imageBounds = item.getImageBounds(event.index);
- /*
- * The image bounds don't match the default image position.
- */
- if (IS_LINUX) {
- gc.drawImage(image, imageBounds.x + 1, imageBounds.y + 3);
- } else {
- gc.drawImage(image, imageBounds.x, imageBounds.y + 1);
- }
- }
- gc.setForeground(item.getForeground(event.index));
- gc.setFont(item.getFont(event.index));
- String text = item.getText(event.index);
- Rectangle textBounds = item.getTextBounds(event.index);
- /*
- * The text bounds don't match the default text position.
- */
- if (IS_LINUX) {
- gc.drawText(text, textBounds.x + 1, textBounds.y + 3, true);
- } else {
- gc.drawText(text, textBounds.x - 1, textBounds.y + 2, true);
- }
- }
- });
+ fTable.addListener(SWT.PaintItem, new PainItemListener());
// Create resources
createResources();
fRawViewer = new TmfRawEventViewer(fSashForm, SWT.H_SCROLL | SWT.V_SCROLL);
- fRawViewer.addSelectionListener(new Listener() {
- @Override
- public void handleEvent(final Event e) {
- if (fTrace == null) {
- return;
- }
- long rank;
- if (e.data instanceof Long) {
- rank = (Long) e.data;
- } else if (e.data instanceof ITmfLocation) {
- rank = findRank((ITmfLocation) e.data);
- } else {
- return;
- }
- int index = (int) rank;
- if (fTable.getData(Key.FILTER_OBJ) != null) {
- // +1 for top filter status row
- index = fCache.getFilteredEventIndex(rank) + 1;
- }
- // +1 for header row
- fTable.setSelection(index + 1);
- fSelectedRank = rank;
- fSelectedBeginRank = fSelectedRank;
- updateStatusLine(null);
- final TableItem[] selection = fTable.getSelection();
- if ((selection != null) && (selection.length > 0)) {
- TableItem item = fTable.getSelection()[0];
- final TmfTimestamp ts = (TmfTimestamp) item.getData(Key.TIMESTAMP);
- if (ts != null) {
- broadcast(new TmfSelectionRangeUpdatedSignal(TmfEventsTable.this, ts));
- }
- if (item.getData() instanceof ITmfEvent) {
- broadcast(new TmfEventSelectedSignal(TmfEventsTable.this, (ITmfEvent) item.getData()));
- fireSelectionChanged(new SelectionChangedEvent(TmfEventsTable.this, new StructuredSelection(item.getData())));
- } else {
- fireSelectionChanged(new SelectionChangedEvent(TmfEventsTable.this, StructuredSelection.EMPTY));
- }
- }
- }
-
- private long findRank(final ITmfLocation selectedLocation) {
- final double selectedRatio = fTrace.getLocationRatio(selectedLocation);
- long low = 0;
- long high = fTrace.getNbEvents();
- long rank = high / 2;
- double ratio = -1;
- while (ratio != selectedRatio) {
- ITmfContext context = fTrace.seekEvent(rank);
- ratio = fTrace.getLocationRatio(context.getLocation());
- context.dispose();
- if (ratio < selectedRatio) {
- low = rank;
- rank = (rank + high) / 2;
- } else if (ratio > selectedRatio) {
- high = rank;
- rank = (rank + low) / 2;
- }
- if ((high - low) < 2) {
- break;
- }
- }
- return rank;
- }
- });
+ fRawViewer.addSelectionListener(new RawSelectionListener());
fSashForm.setWeights(new int[] { 1, 1 });
fRawViewer.setVisible(false);
for (int i : fTable.getColumnOrder()) {
TableColumn column = fTable.getColumns()[i];
// Omit the margin column and hidden columns
- if (i >= EVENT_COLUMNS_START_INDEX && (column.getResizable() || column.getWidth() > 0)) {
+ if (isVisibleEventColumn(column)) {
columns.add(fColumns.get(i));
}
}
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("\\.\\./", EMPTY_STRING); //$NON-NLS-1$
+ if (!(data instanceof ITmfSourceLookup)) {
+ return;
+ }
+ ITmfSourceLookup event = (ITmfSourceLookup) data;
+ ITmfCallsite cs = event.getCallsite();
+ if (cs == null) {
+ return;
+ }
+
+ String fileName = cs.getFileName();
+ final String trimmedPath = fileName.replaceAll("\\.\\./", EMPTY_STRING); //$NON-NLS-1$
+ File fileToOpen = new File(trimmedPath);
+
+ try {
+ if (fileToOpen.exists() && fileToOpen.isFile()) {
+ /*
+ * The path points to a "real" file, attempt to open
+ * that
+ */
+ IFileStore fileStore = EFS.getLocalFileSystem().getStore(fileToOpen.toURI());
+ IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+
+ IEditorPart editor = IDE.openEditorOnFileStore(page, fileStore);
+ if (editor instanceof ITextEditor) {
+ /*
+ * Calculate the "document offset" corresponding to
+ * the line number, then seek there.
+ */
+ ITextEditor textEditor = (ITextEditor) editor;
+ int lineNumber = Long.valueOf(cs.getLineNumber()).intValue();
+ IDocument document = textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
+
+ IRegion region = document.getLineInformation(lineNumber - 1);
+ if (region != null) {
+ textEditor.selectAndReveal(region.getOffset(), region.getLength());
+ }
+ }
+
+ } else {
+ /*
+ * The file was not found on disk, attempt to find it in
+ * the workspace instead.
+ */
+ IMarker marker = null;
final ArrayList<IFile> files = new ArrayList<>();
ResourcesPlugin.getWorkspace().getRoot().accept(new IResourceVisitor() {
@Override
marker.setAttribute(IMarker.LINE_NUMBER, Long.valueOf(cs.getLineNumber()).intValue());
IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), marker);
marker.delete();
- } else if (files.size() == 0) {
+ } else if (files.isEmpty()) {
displayException(new FileNotFoundException('\'' + cs.toString() + '\'' + '\n' + Messages.TmfEventsTable_OpenSourceCodeNotFound));
}
- } catch (CoreException e) {
- displayException(e);
}
+ } catch (BadLocationException | CoreException e) {
+ displayException(e);
}
}
};
for (int i : fTable.getColumnOrder()) {
TableColumn column = fTable.getColumns()[i];
// Omit the margin column and hidden columns
- if (i >= EVENT_COLUMNS_START_INDEX && (column.getResizable() || column.getWidth() > 0)) {
+ if (isVisibleEventColumn(column)) {
exportColumns.add(fColumns.get(i));
}
}
try {
for (long markerId : markerIds) {
final IMarker marker = fBookmarksFile.findMarker(markerId);
- parts.add(marker.getAttribute(IMarker.MESSAGE));
+ if (marker != null) {
+ parts.add(marker.getAttribute(IMarker.MESSAGE));
+ }
}
} catch (CoreException e) {
displayException(e);
}
}
+ /**
+ * Returns true if the column is a visible event column.
+ *
+ * @param column the column
+ * @return false if the column is the margin column or hidden, true otherwise
+ */
+ private static boolean isVisibleEventColumn(TableColumn column) {
+ if (column.getData(Key.ASPECT) == TmfMarginColumn.MARGIN_ASPECT) {
+ return false;
+ }
+ if (!column.getResizable() && column.getWidth() == 0) {
+ return false;
+ }
+ return true;
+ }
+
/**
* Get the array of item strings (e.g., what to display in each cell of the
* table row) corresponding to the columns and trace event passed in
final TableItem tableItem = selection[0];
if (tableItem.getData(Key.RANK) != null) {
final StringBuffer defaultMessage = new StringBuffer();
- for (int i = 0; i < fTable.getColumns().length; i++) {
- if (i > 0) {
- defaultMessage.append(", "); //$NON-NLS-1$
+ for (int i : fTable.getColumnOrder()) {
+ TableColumn column = fTable.getColumns()[i];
+ // Omit the margin column and hidden columns
+ if (isVisibleEventColumn(column)) {
+ if (defaultMessage.length() > 0) {
+ defaultMessage.append(", "); //$NON-NLS-1$
+ }
+ defaultMessage.append(tableItem.getText(i));
}
- defaultMessage.append(tableItem.getText(i));
}
- final InputDialog dialog = new MultiLineInputDialog(
- PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
- Messages.TmfEventsTable_AddBookmarkDialogTitle,
- Messages.TmfEventsTable_AddBookmarkDialogMessage,
- defaultMessage.toString());
+ final AddBookmarkDialog dialog = new AddBookmarkDialog(
+ PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), defaultMessage.toString());
if (dialog.open() == Window.OK) {
final String message = dialog.getValue();
try {
- final IMarker bookmark = bookmarksFile.createMarker(IMarker.BOOKMARK);
- if (bookmark.exists()) {
- bookmark.setAttribute(IMarker.MESSAGE, message.toString());
- final Long rank = (Long) tableItem.getData(Key.RANK);
- final int location = rank.intValue();
- bookmark.setAttribute(IMarker.LOCATION, Integer.valueOf(location));
- fBookmarksMap.put(rank, bookmark.getId());
- fTable.refresh();
- }
+ final Long rank = (Long) tableItem.getData(Key.RANK);
+ final String location = NLS.bind(Messages.TmfMarker_LocationRank, rank.toString());
+ final ITmfTimestamp timestamp = (ITmfTimestamp) tableItem.getData(Key.TIMESTAMP);
+ final long[] id = new long[1];
+ ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
+ @Override
+ public void run(IProgressMonitor monitor) throws CoreException {
+ final IMarker bookmark = bookmarksFile.createMarker(IMarker.BOOKMARK);
+ bookmark.setAttribute(IMarker.MESSAGE, message.toString());
+ bookmark.setAttribute(IMarker.LOCATION, location);
+ bookmark.setAttribute(ITmfMarker.MARKER_RANK, rank.toString());
+ bookmark.setAttribute(ITmfMarker.MARKER_TIME, Long.toString(new TmfNanoTimestamp(timestamp).getValue()));
+ bookmark.setAttribute(ITmfMarker.MARKER_COLOR, dialog.getColorValue().toString());
+ id[0] = bookmark.getId();
+ }
+ }, null);
+ fBookmarksMap.put(rank, id[0]);
+ fTable.refresh();
} catch (final CoreException e) {
displayException(e);
}
}
/**
- * Remove a bookmark from this event table.
+ * Add one or more bookmarks to this event table.
*
- * @param bookmark
- * The bookmark to remove
+ * @param bookmarks
+ * The bookmarks to add
+ * @since 2.0
*/
- public void removeBookmark(final IMarker bookmark) {
- for (final Entry<Long, Long> entry : fBookmarksMap.entries()) {
- if (entry.getValue().equals(bookmark.getId())) {
- fBookmarksMap.remove(entry.getKey(), entry.getValue());
- fTable.refresh();
- return;
+ public void addBookmark(final IMarker... bookmarks) {
+ for (IMarker bookmark : bookmarks) {
+ /* try location as an integer for backward compatibility */
+ long rank = bookmark.getAttribute(IMarker.LOCATION, -1);
+ if (rank == -1) {
+ String rankString = bookmark.getAttribute(ITmfMarker.MARKER_RANK, (String) null);
+ if (rankString != null) {
+ try {
+ rank = Long.parseLong(rankString);
+ } catch (NumberFormatException e) {
+ Activator.getDefault().logError("Invalid marker rank", e); //$NON-NLS-1$
+ }
+ }
+ }
+ if (rank != -1) {
+ fBookmarksMap.put(rank, bookmark.getId());
}
}
+ fTable.refresh();
+ }
+
+ /**
+ * Remove one or more bookmarks from this event table.
+ *
+ * @param bookmarks
+ * The bookmarks to remove
+ * @since 2.0
+ */
+ public void removeBookmark(final IMarker... bookmarks) {
+ for (IMarker bookmark : bookmarks) {
+ for (final Entry<Long, Long> entry : fBookmarksMap.entries()) {
+ if (entry.getValue().equals(bookmark.getId())) {
+ fBookmarksMap.remove(entry.getKey(), entry.getValue());
+ break;
+ }
+ }
+ }
+ fTable.refresh();
}
private void toggleBookmark(final Long rank) {
}
try {
fBookmarksMap.clear();
- for (final IMarker bookmark : bookmarksFile.findMarkers(IMarker.BOOKMARK, false, IResource.DEPTH_ZERO)) {
- final int location = bookmark.getAttribute(IMarker.LOCATION, -1);
- if (location != -1) {
- final long rank = location;
- fBookmarksMap.put(rank, bookmark.getId());
- }
- }
- fTable.refresh();
+ IMarker[] bookmarks = bookmarksFile.findMarkers(IMarker.BOOKMARK, false, IResource.DEPTH_ZERO);
+ addBookmark(bookmarks);
} catch (final CoreException e) {
displayException(e);
}
@Override
public void gotoMarker(final IMarker marker) {
- final int rank = marker.getAttribute(IMarker.LOCATION, -1);
+ ITmfTimestamp tsBegin = null;
+ ITmfTimestamp tsEnd = null;
+ /* try location as an integer for backward compatibility */
+ long rank = marker.getAttribute(IMarker.LOCATION, -1);
+ if (rank == -1) {
+ String rankString = marker.getAttribute(ITmfMarker.MARKER_RANK, (String) null);
+ try {
+ rank = Long.parseLong(rankString);
+ } catch (NumberFormatException e) {
+ /* ignored */
+ }
+ }
+ try {
+ String timeString = marker.getAttribute(ITmfMarker.MARKER_TIME, (String) null);
+ long time = Long.parseLong(timeString);
+ tsBegin = new TmfNanoTimestamp(time);
+ String durationString = marker.getAttribute(ITmfMarker.MARKER_DURATION, (String) null);
+ long duration = Long.parseLong(durationString);
+ tsEnd = new TmfNanoTimestamp(time + duration);
+ } catch (NumberFormatException e) {
+ /* ignored */
+ }
+ if (rank == -1 && tsBegin != null) {
+ final ITmfContext context = fTrace.seekEvent(tsBegin);
+ rank = context.getRank();
+ context.dispose();
+ }
if (rank != -1) {
- int index = rank;
+ int index = (int) rank;
if (fTable.getData(Key.FILTER_OBJ) != null) {
// +1 for top filter status row
index = fCache.getFilteredEventIndex(rank) + 1;
fSelectedBeginRank = fSelectedRank;
fTable.setSelection(index + 1); // +1 for header row
updateStatusLine(null);
+ if (tsBegin != null) {
+ if (tsEnd != null) {
+ broadcast(new TmfSelectionRangeUpdatedSignal(TmfEventsTable.this, tsBegin, tsEnd));
+ } else {
+ broadcast(new TmfSelectionRangeUpdatedSignal(TmfEventsTable.this, tsBegin));
+ }
+ }
}
}