import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
-
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IMarkerDelta;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ISelectionProvider;
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.swt.SWT;
+import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
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.signal.TmfSelectionRangeUpdatedSignal;
import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
import org.eclipse.tracecompass.tmf.core.signal.TmfTimestampFormatUpdateSignal;
import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentInfo;
import org.eclipse.tracecompass.tmf.ui.views.ITmfTimeAligned;
import org.eclipse.tracecompass.tmf.ui.views.TmfView;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphBookmarkListener;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphContentProvider;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphPresentationProvider2;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphRangeListener;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphSelectionListener;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphTimeListener;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphBookmarkEvent;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphCombo;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphContentProvider;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphTimeEvent;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphViewer;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ILinkEvent;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.IMarkerEvent;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.MarkerEvent;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
import org.eclipse.ui.IActionBars;
* This view contains either a time graph viewer, or a time graph combo which is
* divided between a tree viewer on the left and a time graph viewer on the right.
*/
-public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeAligned {
+public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeAligned, IResourceChangeListener {
/** 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$
+
/**
* Redraw state enum
*/
/** The selected trace */
private ITmfTrace fTrace;
+ /** The selected trace editor file*/
+ private IFile fEditorFile;
+
/** The timegraph entry list */
private List<TimeGraphEntry> fEntryList;
/** The trace to entry list hash map */
private final Map<ITmfTrace, List<TimeGraphEntry>> fEntryListMap = new HashMap<>();
+ /** The trace to filters hash map */
+ private final Map<ITmfTrace, ViewerFilter[]> fFiltersMap = new HashMap<>();
+
/** The trace to build thread hash map */
private final Map<ITmfTrace, BuildThread> fBuildThreadMap = new HashMap<>();
private int fAutoExpandLevel = ALL_LEVELS;
+ /** The list of color resources created by this view */
+ private final List<Color> fColors = new ArrayList<>();
+
// ------------------------------------------------------------------------
// Classes
// ------------------------------------------------------------------------
private interface ITimeGraphWrapper {
- void setTimeGraphProvider(TimeGraphPresentationProvider fPresentation);
+ void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider);
+
+ void setTimeGraphPresentationProvider(TimeGraphPresentationProvider timeGraphPresentationProvider);
TimeGraphViewer getTimeGraphViewer();
- void addSelectionListener(ITimeGraphSelectionListener iTimeGraphSelectionListener);
+ void addSelectionListener(ITimeGraphSelectionListener listener);
ISelectionProvider getSelectionProvider();
Object getInput();
+ void setFilters(ViewerFilter[] filters);
+
+ ViewerFilter[] getFilters();
+
void redraw();
void update();
void setAutoExpandLevel(int level);
+ void setFilterColumns(String[] columnNames);
+
+ void setFilterContentProvider(ITreeContentProvider contentProvider);
+
+ void setFilterLabelProvider(ITableLabelProvider labelProvider);
+
+ IAction getShowFilterDialogAction();
+
void performAlign(int offset, int width);
TmfTimeViewAlignmentInfo getTimeViewAlignmentInfo();
}
@Override
- public void setTimeGraphProvider(TimeGraphPresentationProvider timeGraphProvider) {
- viewer.setTimeGraphProvider(timeGraphProvider);
+ public void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider) {
+ viewer.setTimeGraphContentProvider(timeGraphContentProvider);
+ }
+
+ @Override
+ public void setTimeGraphPresentationProvider(TimeGraphPresentationProvider timeGraphPresentationProvider) {
+ viewer.setTimeGraphProvider(timeGraphPresentationProvider);
}
@Override
return viewer.getInput();
}
+ @Override
+ public void setFilterColumns(String[] columnNames) {
+ viewer.setFilterColumns(columnNames);
+ }
+
+ @Override
+ public void setFilterContentProvider(ITreeContentProvider contentProvider) {
+ viewer.setFilterContentProvider(contentProvider);
+ }
+
+ @Override
+ public void setFilterLabelProvider(ITableLabelProvider labelProvider) {
+ viewer.setFilterLabelProvider(labelProvider);
+ }
+
+ @Override
+ public void setFilters(ViewerFilter[] filters) {
+ viewer.setFilters(filters);
+ }
+
+ @Override
+ public ViewerFilter[] getFilters() {
+ return viewer.getFilters();
+ }
+
+ @Override
+ public IAction getShowFilterDialogAction() {
+ return viewer.getShowFilterDialogAction();
+ }
+
@Override
public void refresh() {
viewer.refresh();
}
@Override
- public void setTimeGraphProvider(TimeGraphPresentationProvider timeGraphProvider) {
- combo.setTimeGraphProvider(timeGraphProvider);
+ public void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider) {
+ combo.setTimeGraphContentProvider(timeGraphContentProvider);
+ }
+
+ @Override
+ public void setTimeGraphPresentationProvider(TimeGraphPresentationProvider timeGraphPresentationProvider) {
+ combo.setTimeGraphProvider(timeGraphPresentationProvider);
}
@Override
return combo.getInput();
}
+ @Override
+ public void setFilterColumns(String[] columnNames) {
+ combo.setFilterColumns(columnNames);
+ }
+
+ @Override
+ public void setFilterContentProvider(ITreeContentProvider contentProvider) {
+ combo.setFilterContentProvider(contentProvider);
+ }
+
+ @Override
+ public void setFilterLabelProvider(ITableLabelProvider labelProvider) {
+ combo.setFilterLabelProvider(labelProvider);
+ }
+
+ @Override
+ public void setFilters(ViewerFilter[] filters) {
+ combo.setFilters(filters);
+ }
+
+ @Override
+ public ViewerFilter[] getFilters() {
+ return combo.getFilters();
+ }
+
+ @Override
+ public IAction getShowFilterDialogAction() {
+ return combo.getShowFilterDialogAction();
+ }
+
@Override
public void refresh() {
combo.refresh();
return combo.getTreeViewer();
}
- IAction getShowFilterAction() {
- return combo.getShowFilterAction();
- }
-
@Override
public void performAlign(int offset, int width) {
combo.performAlign(offset, width);
/**
* Zoom thread
- * @since 2.0
+ * @since 1.1
*/
protected abstract class ZoomThread extends Thread {
private final long fZoomStartTime;
fTimeGraphWrapper.getTimeGraphViewer().setLinks(events);
redraw();
}
+ /* Refresh the markers when zooming */
+ List<IMarkerEvent> markers = getMarkerList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor());
+ if (markers != null) {
+ fTimeGraphWrapper.getTimeGraphViewer().getTimeGraphControl().setMarkers(markers);
+ redraw();
+ }
}
private void zoom(@NonNull TimeGraphEntry entry, @NonNull IProgressMonitor monitor) {
super.createPartControl(parent);
if (fColumns == null || fLabelProvider == null) {
fTimeGraphWrapper = new TimeGraphViewerWrapper(parent, SWT.NONE);
- TimeGraphViewer viewer = fTimeGraphWrapper.getTimeGraphViewer();
- viewer.setTimeGraphContentProvider(fTimeGraphContentProvider);
} else {
TimeGraphComboWrapper wrapper = new TimeGraphComboWrapper(parent, SWT.NONE);
fTimeGraphWrapper = wrapper;
combo.setTreeContentProvider(fTimeGraphContentProvider);
combo.setTreeLabelProvider(fLabelProvider);
combo.setTreeColumns(fColumns);
- combo.setFilterContentProvider(fTimeGraphContentProvider);
- combo.setFilterLabelProvider(fFilterLabelProvider);
- combo.setFilterColumns(fFilterColumns);
- combo.setTimeGraphContentProvider(fTimeGraphContentProvider);
}
+ fTimeGraphWrapper.setTimeGraphContentProvider(fTimeGraphContentProvider);
+ fTimeGraphWrapper.setFilterContentProvider(fTimeGraphContentProvider);
+ fTimeGraphWrapper.setFilterLabelProvider(fFilterLabelProvider);
+ fTimeGraphWrapper.setFilterColumns(fFilterColumns);
- fTimeGraphWrapper.setTimeGraphProvider(fPresentation);
+ fTimeGraphWrapper.setTimeGraphPresentationProvider(fPresentation);
fTimeGraphWrapper.setAutoExpandLevel(fAutoExpandLevel);
fTimeGraphWrapper.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
}
});
+ fTimeGraphWrapper.getTimeGraphViewer().addBookmarkListener(new ITimeGraphBookmarkListener() {
+ @Override
+ public void bookmarkAdded(final TimeGraphBookmarkEvent event) {
+ try {
+ ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
+ @Override
+ public void run(IProgressMonitor monitor) throws CoreException {
+ IMarkerEvent bookmark = event.getBookmark();
+ IMarker marker = fEditorFile.createMarker(IMarker.BOOKMARK);
+ marker.setAttribute(IMarker.MESSAGE, bookmark.getLabel());
+ marker.setAttribute(MARKER_TIME, Long.toString(bookmark.getTime()));
+ if (bookmark.getDuration() > 0) {
+ marker.setAttribute(MARKER_DURATION, Long.toString(bookmark.getDuration()));
+ marker.setAttribute(IMarker.LOCATION,
+ String.format("[%d, %d]", bookmark.getTime(), bookmark.getTime() + bookmark.getDuration())); //$NON-NLS-1$
+ } else {
+ marker.setAttribute(IMarker.LOCATION,
+ String.format("[%d]", bookmark.getTime())); //$NON-NLS-1$
+ }
+ marker.setAttribute(MARKER_COLOR, bookmark.getColor().getRGBA().toString());
+ }
+ }, null);
+ } catch (CoreException e) {
+ Activator.getDefault().logError(e.getMessage());
+ }
+ }
+
+ @Override
+ public void bookmarkRemoved(TimeGraphBookmarkEvent event) {
+ try {
+ IMarkerEvent bookmark = event.getBookmark();
+ 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))) {
+ marker.delete();
+ break;
+ }
+ }
+ } catch (CoreException e) {
+ Activator.getDefault().logError(e.getMessage());
+ }
+ }
+ });
+
fTimeGraphWrapper.getTimeGraphViewer().setTimeFormat(TimeFormat.CALENDAR);
IStatusLineManager statusLineManager = getViewSite().getActionBars().getStatusLineManager();
// make selection available to other views
getSite().setSelectionProvider(fTimeGraphWrapper.getSelectionProvider());
+
+ ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
}
@Override
fTimeGraphWrapper.setFocus();
}
+ @Override
+ public void dispose() {
+ super.dispose();
+ ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
+ }
+
+ /**
+ * @since 2.0
+ */
+ @Override
+ public void resourceChanged(final IResourceChangeEvent event) {
+ for (final IMarkerDelta delta : event.findMarkerDeltas(IMarker.BOOKMARK, false)) {
+ if (delta.getResource().equals(fEditorFile)) {
+ fTimeGraphWrapper.getTimeGraphViewer().setBookmarks(refreshBookmarks(fEditorFile));
+ redraw();
+ return;
+ }
+ }
+ }
+
+ private List<IMarkerEvent> refreshBookmarks(final IFile editorFile) {
+ List<IMarkerEvent> bookmarks = new ArrayList<>();
+ 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);
+ if (label != null && time != null && rgba != null) {
+ Matcher matcher = RGBA_PATTERN.matcher(rgba);
+ if (matcher.matches()) {
+ try {
+ int red = Integer.valueOf(matcher.group(1));
+ int green = Integer.valueOf(matcher.group(2));
+ int blue = Integer.valueOf(matcher.group(3));
+ int alpha = Integer.valueOf(matcher.group(4));
+ Color color = new Color(Display.getDefault(), red, green, blue, alpha);
+ fColors.add(color);
+ bookmarks.add(new MarkerEvent(null, Long.valueOf(time), Long.valueOf(duration), color, label, true));
+ } catch (NumberFormatException e) {
+ Activator.getDefault().logError(e.getMessage());
+ }
+ }
+ }
+ }
+ } catch (CoreException e) {
+ Activator.getDefault().logError(e.getMessage());
+ }
+ return bookmarks;
+ }
+
// ------------------------------------------------------------------------
// Signal handlers
// ------------------------------------------------------------------------
*/
@TmfSignalHandler
public void traceOpened(TmfTraceOpenedSignal signal) {
- fTrace = signal.getTrace();
- loadTrace();
+ loadTrace(signal.getTrace());
}
/**
if (signal.getTrace() == fTrace) {
return;
}
- fTrace = signal.getTrace();
- loadTrace();
+ loadTrace(signal.getTrace());
}
/**
synchronized (fEntryListMap) {
fEntryListMap.remove(signal.getTrace());
}
+ fFiltersMap.remove(signal.getTrace());
if (signal.getTrace() == fTrace) {
fTrace = null;
fStartTime = SWT.DEFAULT;
// Internal
// ------------------------------------------------------------------------
- private void loadTrace() {
+ private void loadTrace(final ITmfTrace trace) {
if (fZoomThread != null) {
fZoomThread.cancel();
fZoomThread = null;
}
+ if (fTrace != null) {
+ /* save the filters of the previous trace */
+ fFiltersMap.put(fTrace, fTimeGraphWrapper.getFilters());
+ }
+ fTrace = trace;
+ fEditorFile = TmfTraceManager.getInstance().getTraceEditorFile(trace);
synchronized (fEntryListMap) {
fEntryList = fEntryListMap.get(fTrace);
if (fEntryList == null) {
return new ArrayList<>();
}
+ /**
+ * Gets the list of markers for a trace in a given time range. Default
+ * implementation returns an empty list.
+ *
+ * @param startTime
+ * Start of the time range
+ * @param endTime
+ * End of the time range
+ * @param resolution
+ * The resolution
+ * @param monitor
+ * The progress monitor object
+ * @return The list of marker events
+ * @since 2.0
+ */
+ protected @Nullable List<IMarkerEvent> getMarkerList(long startTime, long endTime,
+ long resolution, @NonNull IProgressMonitor monitor) {
+ return new ArrayList<>();
+ }
/**
* Refresh the display
}
if (fEntryList != fTimeGraphWrapper.getInput()) {
fTimeGraphWrapper.setInput(fEntryList);
+ /* restore the previously saved filters, if any */
+ fTimeGraphWrapper.setFilters(fFiltersMap.get(fTrace));
fTimeGraphWrapper.getTimeGraphViewer().setLinks(null);
+ fTimeGraphWrapper.getTimeGraphViewer().setBookmarks(refreshBookmarks(fEditorFile));
} else {
fTimeGraphWrapper.refresh();
}
* @param restart
* true if restarting zoom for the same time range
* @return a zoom thread
- * @since 2.0
+ * @since 1.1
*/
protected @Nullable ZoomThread createZoomThread(long startTime, long endTime, long resolution, boolean restart) {
final List<TimeGraphEntry> entryList = fEntryList;
* @param manager the tool bar manager
*/
protected void fillLocalToolBar(IToolBarManager manager) {
- if (fTimeGraphWrapper instanceof TimeGraphComboWrapper) {
- if (fFilterColumns != null && fFilterLabelProvider != null && fFilterColumns.length > 0) {
- manager.add(((TimeGraphComboWrapper) fTimeGraphWrapper).getShowFilterAction());
- }
+ if (fFilterColumns != null && fFilterLabelProvider != null && fFilterColumns.length > 0) {
+ manager.add(fTimeGraphWrapper.getShowFilterDialogAction());
}
manager.add(fTimeGraphWrapper.getTimeGraphViewer().getShowLegendAction());
manager.add(new Separator());
manager.add(fTimeGraphWrapper.getTimeGraphViewer().getResetScaleAction());
manager.add(fTimeGraphWrapper.getTimeGraphViewer().getPreviousEventAction());
manager.add(fTimeGraphWrapper.getTimeGraphViewer().getNextEventAction());
+ manager.add(fTimeGraphWrapper.getTimeGraphViewer().getToggleBookmarkAction());
+ manager.add(fTimeGraphWrapper.getTimeGraphViewer().getPreviousBookmarkAction());
+ manager.add(fTimeGraphWrapper.getTimeGraphViewer().getNextBookmarkAction());
manager.add(fPreviousResourceAction);
manager.add(fNextResourceAction);
manager.add(fTimeGraphWrapper.getTimeGraphViewer().getZoomInAction());