From 7697e14822a1a7570fab68776310fdddd3af0234 Mon Sep 17 00:00:00 2001 From: Patrick Tasse Date: Tue, 20 Oct 2015 12:51:05 -0400 Subject: [PATCH] tmf: Improve bookmark and marker handling - Support goto marker without rank (with time and duration) in event table. - Update goto marker handling to broadcast time/time range selection. - Execute pending goto marker handling after trace opened signal sent. - Add initial value to AddBookmarkDialog. - Use AddBookmarkDialog in event table. - Improve format of bookmark location string. - Add interface for marker attribute strings. - Fix handling of marker changes when trace is closed or deleted. - Support ADDED resource change delta and consolidate handling of all deltas from the same resource change event. - Add methods to add or remove one or more markers in event table. - Support location attribute as int (backward compatible) or String value in trace package import operation. Change-Id: I64fa20af7c7c3bc7854c92184df2b86d1831f850 Signed-off-by: Patrick Tasse Reviewed-on: https://git.eclipse.org/r/58543 Reviewed-by: Matthew Khouzam Tested-by: Matthew Khouzam Reviewed-by: Hudson CI --- .../META-INF/MANIFEST.MF | 1 + .../tmf/core/resources/ITmfMarker.java | 35 ++++ .../internal/tmf/ui/Messages.java | 7 +- .../tmf/ui/dialogs/AddBookmarkDialog.java | 6 +- .../internal/tmf/ui/messages.properties | 6 +- .../TracePackageImportOperation.java | 7 +- .../tmf/ui/editors/TmfEventsEditor.java | 52 ++++-- .../tmf/ui/viewers/events/TmfEventsTable.java | 173 +++++++++++++----- .../timegraph/AbstractTimeGraphView.java | 48 ++--- .../ui/widgets/timegraph/TimeGraphViewer.java | 2 +- 10 files changed, 244 insertions(+), 93 deletions(-) create mode 100644 tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/resources/ITmfMarker.java diff --git a/tmf/org.eclipse.tracecompass.tmf.core/META-INF/MANIFEST.MF b/tmf/org.eclipse.tracecompass.tmf.core/META-INF/MANIFEST.MF index 821ec1643d..e74a3e9569 100644 --- a/tmf/org.eclipse.tracecompass.tmf.core/META-INF/MANIFEST.MF +++ b/tmf/org.eclipse.tracecompass.tmf.core/META-INF/MANIFEST.MF @@ -44,6 +44,7 @@ Export-Package: org.eclipse.tracecompass.internal.tmf.core;x-friends:="org.eclip org.eclipse.tracecompass.tmf.core.parsers.custom, org.eclipse.tracecompass.tmf.core.project.model, org.eclipse.tracecompass.tmf.core.request, + org.eclipse.tracecompass.tmf.core.resources, org.eclipse.tracecompass.tmf.core.segment, org.eclipse.tracecompass.tmf.core.signal, org.eclipse.tracecompass.tmf.core.statesystem, diff --git a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/resources/ITmfMarker.java b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/resources/ITmfMarker.java new file mode 100644 index 0000000000..2a0bd9bfc0 --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/resources/ITmfMarker.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2015 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Patrick Tasse - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.tracecompass.tmf.core.resources; + +/** + * Interface for TMF-specific marker constants + * + * @noimplement This interface is not intended to be implemented by clients. + * @since 2.0 + */ +public interface ITmfMarker { + + /** Color marker attribute. The format is the output of RGBA.toString(). */ + String MARKER_COLOR = "color"; //$NON-NLS-1$ + + /** Rank marker attribute. The format is the output of Long.toString(). */ + String MARKER_RANK = "rank"; //$NON-NLS-1$ + + /** Time marker attribute. The format is the output of Long.toString(). */ + String MARKER_TIME = "time"; //$NON-NLS-1$ + + /** Duration marker attribute. The format is the output of Long.toString(). */ + String MARKER_DURATION = "duration"; //$NON-NLS-1$ + +} diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/Messages.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/Messages.java index bea7f7ed1b..41b51148b7 100644 --- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/Messages.java +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/Messages.java @@ -39,8 +39,6 @@ public class Messages extends NLS { public static String ManageCustomParsersDialog_TextButtonLabel; public static String TmfEventsTable_AddBookmarkActionText; - public static String TmfEventsTable_AddBookmarkDialogMessage; - public static String TmfEventsTable_AddBookmarkDialogTitle; public static String TmfEventsTable_ApplyPresetFilterMenuName; public static String TmfEventsTable_ClearFiltersActionText; public static String TmfEventsTable_CollapseFilterMenuName; @@ -60,7 +58,6 @@ public class Messages extends NLS { public static String TmfEventsTable_RemoveBookmarkActionText; public static String TmfEventsTable_SearchHint; public static String TmfEventsTable_SearchingJobName; - public static String TmfEventsTable_ShowAll; public static String TmfEventsTable_ShowFilterBarActionText; public static String TmfEventsTable_ShowRawActionText; @@ -70,6 +67,10 @@ public class Messages extends NLS { public static String TmfEventsTable_TimestampColumnHeader; public static String TmfEventsTable_TypeColumnHeader; + public static String TmfMarker_LocationRank; + public static String TmfMarker_LocationTime; + public static String TmfMarker_LocationTimeRange; + public static String TmfTimeFilterDialog_EDIT_PROFILING_OPTIONS; public static String TmfTimeFilterDialog_TRACE_FILTER; public static String TmfTimeFilterDialog_TRACE_FILTER_DESC; diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/dialogs/AddBookmarkDialog.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/dialogs/AddBookmarkDialog.java index bd4a7a045d..8ae8818355 100644 --- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/dialogs/AddBookmarkDialog.java +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/dialogs/AddBookmarkDialog.java @@ -43,9 +43,11 @@ public class AddBookmarkDialog extends MultiLineInputDialog { * * @param parentShell * the parent shell + * @param initialValue + * the initial input value, or null if none (equivalent to the empty string) */ - public AddBookmarkDialog(Shell parentShell) { - super(parentShell, Messages.AddBookmarkDialog_Title, Messages.AddBookmarkDialog_Message, ""); //$NON-NLS-1$ + public AddBookmarkDialog(Shell parentShell, String initialValue) { + super(parentShell, Messages.AddBookmarkDialog_Title, Messages.AddBookmarkDialog_Message, initialValue); } @Override diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/messages.properties b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/messages.properties index ef192f3b50..431558a1e2 100644 --- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/messages.properties +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/messages.properties @@ -32,8 +32,6 @@ ManageCustomParsersDialog_TextButtonLabel=Text # org.eclipse.tracecompass.tmf.ui.viewers.events TmfEventsTable_AddBookmarkActionText=Add Bookmark... -TmfEventsTable_AddBookmarkDialogMessage=Enter Bookmark Description: -TmfEventsTable_AddBookmarkDialogTitle=Add Bookmark TmfEventsTable_ApplyPresetFilterMenuName=Apply Preset Filter... TmfEventsTable_ClearFiltersActionText=Clear Filters TmfEventsTable_CollapseFilterMenuName=Collapse Events @@ -62,6 +60,10 @@ TmfEventsTable_SourceColumnHeader=Source TmfEventsTable_TimestampColumnHeader=Timestamp TmfEventsTable_TypeColumnHeader=Type +TmfMarker_LocationRank=rank {0} +TmfMarker_LocationTime=timestamp [{0}] +TmfMarker_LocationTimeRange=timestamp [{0}, {1}] + # org.eclipse.tracecompass.tmf.ui.viewers.timegraph.dialogs TmfTimeFilterDialog_EDIT_PROFILING_OPTIONS=Edit Profiling Options TmfTimeFilterDialog_TRACE_FILTER=Trace Filter diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/TracePackageImportOperation.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/TracePackageImportOperation.java index 0a9a863a1a..4338082959 100644 --- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/TracePackageImportOperation.java +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/TracePackageImportOperation.java @@ -317,7 +317,12 @@ public class TracePackageImportOperation extends AbstractTracePackageOperation i String key = entry.getKey(); String value = entry.getValue(); if (key.equals(IMarker.LOCATION)) { - createMarker.setAttribute(IMarker.LOCATION, Integer.valueOf(value).intValue()); + try { + /* try location as an integer for backward compatibility */ + createMarker.setAttribute(IMarker.LOCATION, Integer.parseInt(value)); + } catch (NumberFormatException e) { + createMarker.setAttribute(IMarker.LOCATION, value); + } } else { createMarker.setAttribute(key, value); } diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/editors/TmfEventsEditor.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/editors/TmfEventsEditor.java index e96e679e6b..29950f5e26 100644 --- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/editors/TmfEventsEditor.java +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/editors/TmfEventsEditor.java @@ -15,7 +15,9 @@ package org.eclipse.tracecompass.tmf.ui.editors; import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; @@ -239,10 +241,6 @@ public class TmfEventsEditor extends TmfEditor implements ITmfTraceEditor, IReus fEventsTable.addSelectionChangedListener(this); fEventsTable.setTrace(fTrace, true); fEventsTable.refreshBookmarks(fFile); - if (fPendingGotoMarker != null) { - fEventsTable.gotoMarker(fPendingGotoMarker); - fPendingGotoMarker = null; - } /* ensure start time is set */ final ITmfContext context = fTrace.seekEvent(0); @@ -253,6 +251,12 @@ public class TmfEventsEditor extends TmfEditor implements ITmfTraceEditor, IReus if (fTraceSelected) { broadcast(new TmfTraceSelectedSignal(this, fTrace)); } + + /* go to marker after trace opened */ + if (fPendingGotoMarker != null) { + fEventsTable.gotoMarker(fPendingGotoMarker); + fPendingGotoMarker = null; + } } else { fEventsTable = new TmfEventsTable(fParent, 0); fEventsTable.addSelectionChangedListener(this); @@ -444,26 +448,38 @@ public class TmfEventsEditor extends TmfEditor implements ITmfTraceEditor, IReus @Override public void resourceChanged(final IResourceChangeEvent event) { + final Set added = new HashSet<>(); + final Set removed = new HashSet<>(); + boolean deltaFound = false; for (final IMarkerDelta delta : event.findMarkerDeltas(IMarker.BOOKMARK, false)) { if (delta.getResource().equals(fFile)) { if (delta.getKind() == IResourceDelta.REMOVED) { - final IMarker bookmark = delta.getMarker(); - Display.getDefault().asyncExec(new Runnable() { - @Override - public void run() { - fEventsTable.removeBookmark(bookmark); - } - }); - } else if (delta.getKind() == IResourceDelta.CHANGED) { - Display.getDefault().asyncExec(new Runnable() { - @Override - public void run() { - fEventsTable.getTable().refresh(); - } - }); + removed.add(delta.getMarker()); + } else if (delta.getKind() == IResourceDelta.ADDED) { + added.add(delta.getMarker()); } + /* this also covers IResourceDelta.CHANGED */ + deltaFound = true; } } + if (!deltaFound) { + return; + } + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + if (removed.isEmpty() && added.isEmpty()) { + fEventsTable.getTable().refresh(); + } else { + if (!removed.isEmpty()) { + fEventsTable.removeBookmark(Iterables.toArray(removed, IMarker.class)); + } + if (!added.isEmpty()) { + fEventsTable.addBookmark(Iterables.toArray(added, IMarker.class)); + } + } + } + }); } // ------------------------------------------------------------------------ diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/events/TmfEventsTable.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/events/TmfEventsTable.java index 743f291ca7..dcbc7908c8 100644 --- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/events/TmfEventsTable.java +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/events/TmfEventsTable.java @@ -43,6 +43,7 @@ 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; @@ -62,7 +63,6 @@ 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.dialogs.MessageDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.resource.ColorRegistry; @@ -81,6 +81,7 @@ 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.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.custom.StyleRange; @@ -121,7 +122,7 @@ import org.eclipse.tracecompass.internal.tmf.ui.Activator; 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; @@ -138,6 +139,7 @@ import org.eclipse.tracecompass.tmf.core.filter.model.TmfFilterMatchesNode; 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; @@ -145,6 +147,7 @@ import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal; 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; @@ -965,7 +968,7 @@ public class TmfEventsTable extends TmfComponent implements IGotoMarker, IColorS 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)); } } @@ -1159,7 +1162,7 @@ public class TmfEventsTable extends TmfComponent implements IGotoMarker, IColorS 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)); } } @@ -1485,7 +1488,9 @@ public class TmfEventsTable extends TmfComponent implements IGotoMarker, IColorS 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); @@ -2449,6 +2454,22 @@ public class TmfEventsTable extends TmfComponent implements IGotoMarker, IColorS } } + /** + * 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 @@ -2759,29 +2780,39 @@ public class TmfEventsTable extends TmfComponent implements IGotoMarker, IColorS 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); } @@ -2792,19 +2823,50 @@ public class TmfEventsTable extends TmfComponent implements IGotoMarker, IColorS } /** - * 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 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 entry : fBookmarksMap.entries()) { + if (entry.getValue().equals(bookmark.getId())) { + fBookmarksMap.remove(entry.getKey(), entry.getValue()); + break; + } + } + } + fTable.refresh(); } private void toggleBookmark(final Long rank) { @@ -2845,14 +2907,8 @@ public class TmfEventsTable extends TmfComponent implements IGotoMarker, IColorS } 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); } @@ -2860,9 +2916,35 @@ public class TmfEventsTable extends TmfComponent implements IGotoMarker, IColorS @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; @@ -2873,6 +2955,13 @@ public class TmfEventsTable extends TmfComponent implements IGotoMarker, IColorS 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)); + } + } } } diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/AbstractTimeGraphView.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/AbstractTimeGraphView.java index 41145c7aa4..88216e9b4f 100644 --- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/AbstractTimeGraphView.java +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/AbstractTimeGraphView.java @@ -52,6 +52,7 @@ import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; @@ -59,6 +60,7 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.TreeColumn; import org.eclipse.tracecompass.internal.tmf.ui.Activator; +import org.eclipse.tracecompass.tmf.core.resources.ITmfMarker; import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal; import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler; import org.eclipse.tracecompass.tmf.core.signal.TmfTimestampFormatUpdateSignal; @@ -109,15 +111,6 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA /** Constant indicating that all levels of the time graph should be expanded */ protected static final int ALL_LEVELS = AbstractTreeViewer.ALL_LEVELS; - /** Color marker attribute. The format is the output of RGBA.toString(). */ - private static final String MARKER_COLOR = "color"; //$NON-NLS-1$ - - /** Time marker attribute. The format is the output of Long.toString(). */ - private static final String MARKER_TIME = "time"; //$NON-NLS-1$ - - /** Duration marker attribute. The format is the output of Long.toString(). */ - private static final String MARKER_DURATION = "duration"; //$NON-NLS-1$ - private static final Pattern RGBA_PATTERN = Pattern.compile("RGBA \\{(\\d+), (\\d+), (\\d+), (\\d+)\\}"); //$NON-NLS-1$ /** @@ -1074,16 +1067,19 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA IMarkerEvent bookmark = event.getBookmark(); IMarker marker = fEditorFile.createMarker(IMarker.BOOKMARK); marker.setAttribute(IMarker.MESSAGE, bookmark.getLabel()); - marker.setAttribute(MARKER_TIME, Long.toString(bookmark.getTime())); + marker.setAttribute(ITmfMarker.MARKER_TIME, Long.toString(bookmark.getTime())); if (bookmark.getDuration() > 0) { - marker.setAttribute(MARKER_DURATION, Long.toString(bookmark.getDuration())); + marker.setAttribute(ITmfMarker.MARKER_DURATION, Long.toString(bookmark.getDuration())); marker.setAttribute(IMarker.LOCATION, - String.format("[%d, %d]", bookmark.getTime(), bookmark.getTime() + bookmark.getDuration())); //$NON-NLS-1$ + NLS.bind(org.eclipse.tracecompass.internal.tmf.ui.Messages.TmfMarker_LocationTimeRange, + new TmfNanoTimestamp(bookmark.getTime()), + new TmfNanoTimestamp(bookmark.getTime() + bookmark.getDuration()))); } else { marker.setAttribute(IMarker.LOCATION, - String.format("[%d]", bookmark.getTime())); //$NON-NLS-1$ + NLS.bind(org.eclipse.tracecompass.internal.tmf.ui.Messages.TmfMarker_LocationTime, + new TmfNanoTimestamp(bookmark.getTime()))); } - marker.setAttribute(MARKER_COLOR, bookmark.getColor().getRGBA().toString()); + marker.setAttribute(ITmfMarker.MARKER_COLOR, bookmark.getColor().getRGBA().toString()); } }, null); } catch (CoreException e) { @@ -1098,9 +1094,9 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA IMarker[] markers = fEditorFile.findMarkers(IMarker.BOOKMARK, false, IResource.DEPTH_ZERO); for (IMarker marker : markers) { if (bookmark.getLabel().equals(marker.getAttribute(IMarker.MESSAGE)) && - Long.toString(bookmark.getTime()).equals(marker.getAttribute(MARKER_TIME, (String) null)) && - Long.toString(bookmark.getDuration()).equals(marker.getAttribute(MARKER_DURATION, Long.toString(0))) && - bookmark.getColor().getRGBA().toString().equals(marker.getAttribute(MARKER_COLOR))) { + Long.toString(bookmark.getTime()).equals(marker.getAttribute(ITmfMarker.MARKER_TIME, (String) null)) && + Long.toString(bookmark.getDuration()).equals(marker.getAttribute(ITmfMarker.MARKER_DURATION, Long.toString(0))) && + bookmark.getColor().getRGBA().toString().equals(marker.getAttribute(ITmfMarker.MARKER_COLOR))) { marker.delete(); break; } @@ -1158,17 +1154,20 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA private List refreshBookmarks(final IFile editorFile) { List bookmarks = new ArrayList<>(); + for (Color color : fColors) { + color.dispose(); + } + fColors.clear(); + if (editorFile == null || !editorFile.exists()) { + return bookmarks; + } try { - for (Color color : fColors) { - color.dispose(); - } - fColors.clear(); IMarker[] markers = editorFile.findMarkers(IMarker.BOOKMARK, false, IResource.DEPTH_ZERO); for (IMarker marker : markers) { String label = marker.getAttribute(IMarker.MESSAGE, (String) null); - String time = marker.getAttribute(MARKER_TIME, (String) null); - String duration = marker.getAttribute(MARKER_DURATION, Long.toString(0)); - String rgba = marker.getAttribute(MARKER_COLOR, (String) null); + String time = marker.getAttribute(ITmfMarker.MARKER_TIME, (String) null); + String duration = marker.getAttribute(ITmfMarker.MARKER_DURATION, Long.toString(0)); + String rgba = marker.getAttribute(ITmfMarker.MARKER_COLOR, (String) null); if (label != null && time != null && rgba != null) { Matcher matcher = RGBA_PATTERN.matcher(rgba); if (matcher.matches()) { @@ -1243,6 +1242,7 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA fFiltersMap.remove(signal.getTrace()); if (signal.getTrace() == fTrace) { fTrace = null; + fEditorFile = null; fStartTime = SWT.DEFAULT; fEndTime = SWT.DEFAULT; if (fZoomThread != null) { diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/TimeGraphViewer.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/TimeGraphViewer.java index 082bdbd8fc..2b31d7d730 100644 --- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/TimeGraphViewer.java +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/TimeGraphViewer.java @@ -2004,7 +2004,7 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { if (selectedBookmark == null) { final long time = Math.min(fSelectionBegin, fSelectionEnd); final long duration = Math.max(fSelectionBegin, fSelectionEnd) - time; - final AddBookmarkDialog dialog = new AddBookmarkDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell()); + final AddBookmarkDialog dialog = new AddBookmarkDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), null); if (dialog.open() == Window.OK) { final String label = dialog.getValue(); final RGBA rgba = dialog.getColorValue(); -- 2.34.1