/*****************************************************************************
- * Copyright (c) 2007, 2015 Intel Corporation, Ericsson, others
+ * Copyright (c) 2007, 2016 Intel Corporation, Ericsson, others
* 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
package org.eclipse.tracecompass.tmf.ui.widgets.timegraph;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
+import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuCreator;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MenuDetectListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.RGBA;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Slider;
import org.eclipse.tracecompass.internal.tmf.ui.Activator;
import org.eclipse.tracecompass.internal.tmf.ui.ITmfImageConstants;
import org.eclipse.tracecompass.internal.tmf.ui.Messages;
+import org.eclipse.tracecompass.internal.tmf.ui.dialogs.AddBookmarkDialog;
import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentInfo;
import org.eclipse.tracecompass.tmf.ui.views.ITmfTimeAligned;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.dialogs.ShowFilterDialogAction;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.dialogs.TimeGraphLegend;
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.widgets.IMarkerAxisListener;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.ITimeDataProvider;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeDataProviderCyclesConverter;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphColorScheme;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphControl;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphMarkerAxis;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphScale;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphTooltipHandler;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
+import org.eclipse.ui.PlatformUI;
/**
* Generic time graph viewer implementation
*
* @author Patrick Tasse, and others
*/
-public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
+public class TimeGraphViewer implements ITimeDataProvider, IMarkerAxisListener, SelectionListener {
/** Constant indicating that all levels of the time graph should be expanded */
public static final int ALL_LEVELS = AbstractTreeViewer.ALL_LEVELS;
private static final long DEFAULT_FREQUENCY = 1000000000L;
private static final int H_SCROLLBAR_MAX = Integer.MAX_VALUE - 1;
+ private static final ImageDescriptor ADD_BOOKMARK = Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_ADD_BOOKMARK);
+ private static final ImageDescriptor NEXT_BOOKMARK = Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_NEXT_BOOKMARK);
+ private static final ImageDescriptor PREVIOUS_BOOKMARK = Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_PREVIOUS_BOOKMARK);
+ private static final ImageDescriptor REMOVE_BOOKMARK = Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_REMOVE_BOOKMARK);
+
private long fMinTimeInterval;
private ITimeGraphEntry fSelectedEntry;
private long fBeginTime = SWT.DEFAULT; // The user-specified bounds start time
private TimeGraphControl fTimeGraphCtrl;
private TimeGraphScale fTimeScaleCtrl;
+ private TimeGraphMarkerAxis fMarkerAxisCtrl;
private Slider fHorizontalScrollBar;
private Slider fVerticalScrollBar;
- private TimeGraphColorScheme fColorScheme;
+ private @NonNull TimeGraphColorScheme fColorScheme = new TimeGraphColorScheme();
private Object fInputElement;
private ITimeGraphContentProvider fTimeGraphContentProvider;
private ITimeGraphPresentationProvider fTimeGraphProvider;
- private ITimeDataProvider fTimeDataProvider = this;
+ private @NonNull ITimeDataProvider fTimeDataProvider = this;
private TimeGraphTooltipHandler fToolTipHandler;
private List<ITimeGraphSelectionListener> fSelectionListeners = new ArrayList<>();
private List<ITimeGraphTimeListener> fTimeListeners = new ArrayList<>();
private List<ITimeGraphRangeListener> fRangeListeners = new ArrayList<>();
+ private List<ITimeGraphBookmarkListener> fBookmarkListeners = new ArrayList<>();
// Time format, using Epoch reference, Relative time format(default),
// Number, or Cycles
private Action fHideArrowsAction;
private Action fFollowArrowFwdAction;
private Action fFollowArrowBwdAction;
+ private ShowFilterDialogAction fShowFilterDialogAction;
+ private Action fToggleBookmarkAction;
+ private Action fNextMarkerAction;
+ private Action fPreviousMarkerAction;
+ private MenuManager fMarkersMenu;
+
+ /** The list of bookmarks */
+ private final List<IMarkerEvent> fBookmarks = new ArrayList<>();
+
+ /** The list of marker categories */
+ private final List<String> fMarkerCategories = new ArrayList<>();
+
+ /** The set of hidden marker categories */
+ private final Set<String> fHiddenMarkerCategories = new HashSet<>();
+
+ /** The set of skipped marker categories */
+ private final Set<String> fSkippedMarkerCategories = new HashSet<>();
+
+ /** The list of markers */
+ private final List<IMarkerEvent> fMarkers = new ArrayList<>();
private ListenerNotifier fListenerNotifier;
}
}
+ private final static class MarkerComparator implements Comparator<IMarkerEvent> {
+ @Override
+ public int compare(IMarkerEvent o1, IMarkerEvent o2) {
+ int res = Long.compare(o1.getTime(), o2.getTime());
+ if (res != 0) {
+ return res;
+ }
+ return Long.compare(o1.getDuration(), o2.getDuration());
+ }
+ }
+
/**
* Standard constructor.
* <p>
fToolTipHandler.activateHoverHelp(fTimeGraphCtrl);
}
+ /**
+ * Sets the tree columns for this time graph combo's filter dialog.
+ *
+ * @param columnNames the tree column names
+ * @since 2.0
+ */
+ public void setFilterColumns(String[] columnNames) {
+ getShowFilterDialogAction().getFilterDialog().setColumnNames(columnNames);
+ }
+
+ /**
+ * Sets the tree content provider used by the filter dialog
+ *
+ * @param contentProvider the tree content provider
+ * @since 2.0
+ */
+ public void setFilterContentProvider(ITreeContentProvider contentProvider) {
+ getShowFilterDialogAction().getFilterDialog().setContentProvider(contentProvider);
+ }
+
+ /**
+ * Sets the tree label provider used by the filter dialog
+ *
+ * @param labelProvider the tree label provider
+ * @since 2.0
+ */
+ public void setFilterLabelProvider(ITableLabelProvider labelProvider) {
+ getShowFilterDialogAction().getFilterDialog().setLabelProvider(labelProvider);
+ }
+
/**
* Sets or clears the input for this time graph viewer.
*
setTopIndex(0);
fSelectionBegin = SWT.DEFAULT;
fSelectionEnd = SWT.DEFAULT;
+ updateMarkerActions();
fSelectedEntry = null;
refreshAllData(input);
}
*/
protected Control createDataViewer(Composite parent, int style) {
loadOptions();
- fColorScheme = new TimeGraphColorScheme();
fDataViewer = new Composite(parent, style) {
@Override
public void redraw() {
fTimeScaleCtrl.redraw();
fTimeGraphCtrl.redraw();
+ fMarkerAxisCtrl.redraw();
super.redraw();
}
};
+ fDataViewer.addDisposeListener(new DisposeListener() {
+ @Override
+ public void widgetDisposed(DisposeEvent e) {
+ if (fMarkersMenu != null) {
+ fMarkersMenu.dispose();
+ }
+ }
+ });
GridLayout gl = new GridLayout(2, false);
gl.marginHeight = fBorderWidth;
gl.marginWidth = 0;
fTimeScaleCtrl.addMouseWheelListener(new MouseWheelListener() {
@Override
public void mouseScrolled(MouseEvent e) {
+ if (e.count == 0) {
+ return;
+ }
fTimeGraphCtrl.zoom(e.count > 0);
}
});
fTimeGraphCtrl.addMouseWheelListener(new MouseWheelListener() {
@Override
public void mouseScrolled(MouseEvent e) {
+ if (e.count == 0) {
+ return;
+ }
adjustVerticalScrollBar();
}
});
fTimeGraphCtrl.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
- if (e.character == '+') {
+ if ((e.character == '+' || e.character == '=') && ((e.stateMask & SWT.CTRL) == 0)) {
zoomIn();
- } else if (e.character == '-') {
+ } else if (e.character == '-' && ((e.stateMask & SWT.CTRL) == 0)) {
zoomOut();
+ } else if (e.keyCode == '.') {
+ boolean extend = (e.stateMask & SWT.SHIFT) != 0;
+ if (extend) {
+ extendToNextMarker();
+ } else {
+ selectNextMarker();
+ }
+ } else if (e.keyCode == ',') {
+ boolean extend = (e.stateMask & SWT.SHIFT) != 0;
+ if (extend) {
+ extendToPrevMarker();
+ } else {
+ selectPrevMarker();
+ }
}
adjustVerticalScrollBar();
}
});
+ fMarkerAxisCtrl = createTimeGraphMarkerAxis(fTimeAlignedComposite, fColorScheme, this);
+ fMarkerAxisCtrl.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false));
+ fMarkerAxisCtrl.addMarkerAxisListener(this);
+ fMarkerAxisCtrl.addMouseWheelListener(new MouseWheelListener() {
+ @Override
+ public void mouseScrolled(MouseEvent e) {
+ if (e.count == 0) {
+ return;
+ }
+ fTimeGraphCtrl.zoom(e.count > 0);
+ }
+ });
+
fVerticalScrollBar = new Slider(fDataViewer, SWT.VERTICAL | SWT.NO_FOCUS);
fVerticalScrollBar.setLayoutData(new GridData(SWT.DEFAULT, SWT.FILL, false, true, 1, 1));
fVerticalScrollBar.addSelectionListener(new SelectionAdapter() {
fHorizontalScrollBar.addListener(SWT.MouseWheel, new Listener() {
@Override
public void handleEvent(Event event) {
+ // don't handle the immediately following SWT.Selection event
+ event.doit = false;
+ if (event.count == 0) {
+ return;
+ }
if ((event.stateMask & SWT.MODIFIER_MASK) == SWT.CTRL) {
getTimeGraphControl().zoom(event.count > 0);
} else {
getTimeGraphControl().horizontalScroll(event.count > 0);
}
- // don't handle the immediately following SWT.Selection event
- event.doit = false;
}
});
fHorizontalScrollBar.addListener(SWT.Selection, new Listener() {
return new TimeGraphControl(parent, colors);
}
+ /**
+ * Create a new time graph marker axis.
+ *
+ * @param parent
+ * The parent composite object
+ * @param colorScheme
+ * The color scheme to use
+ * @param timeProvider
+ * The time data provider
+ * @return The new TimeGraphMarkerAxis
+ * @since 2.0
+ */
+ protected TimeGraphMarkerAxis createTimeGraphMarkerAxis(Composite parent,
+ @NonNull TimeGraphColorScheme colorScheme, @NonNull ITimeDataProvider timeProvider) {
+ return new TimeGraphMarkerAxis(parent, colorScheme, timeProvider);
+ }
+
/**
* Resize the controls
*/
}
fTimeGraphCtrl.refreshData(traces);
fTimeScaleCtrl.redraw();
+ fMarkerAxisCtrl.redraw();
+ updateMarkerActions();
adjustVerticalScrollBar();
}
}
fTimeGraphCtrl.redraw();
fTimeScaleCtrl.redraw();
+ fMarkerAxisCtrl.redraw();
+ /* force update the controls to keep them aligned */
+ fTimeScaleCtrl.update();
+ fMarkerAxisCtrl.update();
+ fTimeGraphCtrl.update();
}
@Override
adjustHorizontalScrollBar();
fTimeGraphCtrl.redraw();
fTimeScaleCtrl.redraw();
+ fMarkerAxisCtrl.redraw();
+ /* force update the controls to keep them aligned */
+ fTimeScaleCtrl.update();
+ fMarkerAxisCtrl.update();
+ fTimeGraphCtrl.update();
}
@Override
setSelectedTimeInt(time, ensureVisible, false);
}
+ private void setSelectedTimeInt(long time, boolean ensureVisible, boolean doNotify) {
+ setSelectionRangeInt(time, time, ensureVisible, doNotify);
+ }
+
+ /**
+ * @since 2.0
+ */
@Override
- public void setSelectionRangeNotify(long beginTime, long endTime) {
- long time0 = fTime0;
- long time1 = fTime1;
- long selectionBegin = fSelectionBegin;
- long selectionEnd = fSelectionEnd;
- fSelectionBegin = Math.max(fTime0Bound, Math.min(fTime1Bound, beginTime));
- fSelectionEnd = Math.max(fTime0Bound, Math.min(fTime1Bound, endTime));
- boolean changed = (selectionBegin != fSelectionBegin || selectionEnd != fSelectionEnd);
- ensureVisible(fSelectionEnd);
- fTimeGraphCtrl.redraw();
- fTimeScaleCtrl.redraw();
- if ((time0 != fTime0) || (time1 != fTime1)) {
- notifyRangeListeners();
- }
- if (changed) {
- notifyTimeListeners();
- }
+ public void setSelectionRangeNotify(long beginTime, long endTime, boolean ensureVisible) {
+ setSelectionRangeInt(beginTime, endTime, ensureVisible, true);
}
+ /**
+ * @since 2.0
+ */
@Override
- public void setSelectionRange(long beginTime, long endTime) {
+ public void setSelectionRange(long beginTime, long endTime, boolean ensureVisible) {
/* if there is a pending time selection, ignore this one */
if (fListenerNotifier != null && fListenerNotifier.hasTimeSelected()) {
return;
}
- fSelectionBegin = Math.max(fTime0Bound, Math.min(fTime1Bound, beginTime));
- fSelectionEnd = Math.max(fTime0Bound, Math.min(fTime1Bound, endTime));
- fTimeGraphCtrl.redraw();
- fTimeScaleCtrl.redraw();
+ setSelectionRangeInt(beginTime, endTime, ensureVisible, false);
}
- private void setSelectedTimeInt(long time, boolean ensureVisible, boolean doNotify) {
- long selection = Math.max(fTime0Bound, Math.min(fTime1Bound, time));
+ private void setSelectionRangeInt(long beginTime, long endTime, boolean ensureVisible, boolean doNotify) {
long time0 = fTime0;
long time1 = fTime1;
+ long selectionBegin = fSelectionBegin;
+ long selectionEnd = fSelectionEnd;
+ fSelectionBegin = Math.max(fTime0Bound, Math.min(fTime1Bound, beginTime));
+ fSelectionEnd = Math.max(fTime0Bound, Math.min(fTime1Bound, endTime));
+ boolean changed = (selectionBegin != fSelectionBegin || selectionEnd != fSelectionEnd);
+
if (ensureVisible) {
- ensureVisible(selection);
+ ensureVisible(selectionBegin != fSelectionBegin ? fSelectionBegin : fSelectionEnd);
}
+
fTimeGraphCtrl.redraw();
fTimeScaleCtrl.redraw();
-
- boolean notifySelectedTime = (selection != fSelectionBegin || selection != fSelectionEnd);
- fSelectionBegin = selection;
- fSelectionEnd = selection;
+ fMarkerAxisCtrl.redraw();
+ updateMarkerActions();
if ((time0 != fTime0) || (time1 != fTime1)) {
notifyRangeListeners();
}
- if (doNotify && notifySelectedTime) {
+ if (doNotify && changed) {
notifyTimeListeners();
}
}
}
}
+ /**
+ * Add a bookmark listener
+ *
+ * @param listener
+ * The listener to add
+ * @since 2.0
+ */
+ public void addBookmarkListener(ITimeGraphBookmarkListener listener) {
+ fBookmarkListeners.add(listener);
+ }
+
+ /**
+ * Remove a bookmark listener
+ *
+ * @param listener
+ * The listener to remove
+ * @since 2.0
+ */
+ public void removeBookmarkListener(ITimeGraphBookmarkListener listener) {
+ fBookmarkListeners.remove(listener);
+ }
+
+ private void fireBookmarkAdded(IMarkerEvent bookmark) {
+ TimeGraphBookmarkEvent event = new TimeGraphBookmarkEvent(this, bookmark);
+
+ for (ITimeGraphBookmarkListener listener : fBookmarkListeners) {
+ listener.bookmarkAdded(event);
+ }
+ }
+
+ private void fireBookmarkRemoved(IMarkerEvent bookmark) {
+ TimeGraphBookmarkEvent event = new TimeGraphBookmarkEvent(this, bookmark);
+
+ for (ITimeGraphBookmarkListener listener : fBookmarkListeners) {
+ listener.bookmarkRemoved(event);
+ }
+ }
+
+ /**
+ * Set the bookmarks list.
+ *
+ * @param bookmarks
+ * The bookmarks list, or null
+ * @since 2.0
+ */
+ public void setBookmarks(List<IMarkerEvent> bookmarks) {
+ fBookmarks.clear();
+ if (bookmarks != null) {
+ fBookmarks.addAll(bookmarks);
+ }
+ updateMarkerList();
+ updateMarkerActions();
+ }
+
+ /**
+ * Get the bookmarks list.
+ *
+ * @return The bookmarks list
+ * @since 2.0
+ */
+ public List<IMarkerEvent> getBookmarks() {
+ return Collections.unmodifiableList(fBookmarks);
+ }
+
+ /**
+ * Set the list of marker categories.
+ *
+ * @param categories
+ * The list of marker categories, or null
+ * @since 2.0
+ */
+ public void setMarkerCategories(List<String> categories) {
+ fMarkerCategories.clear();
+ if (categories != null) {
+ fMarkerCategories.addAll(categories);
+ }
+ fMarkerCategories.add(IMarkerEvent.BOOKMARKS);
+ fMarkerAxisCtrl.setMarkerCategories(fMarkerCategories);
+ }
+
+ /**
+ * @since 2.0
+ */
+ @Override
+ public void setMarkerCategoryVisible(String category, boolean visible) {
+ boolean changed = false;
+ if (visible) {
+ changed = fHiddenMarkerCategories.remove(category);
+ } else {
+ changed = fHiddenMarkerCategories.add(category);
+ }
+ if (changed) {
+ updateMarkerList();
+ updateMarkerActions();
+ getControl().redraw();
+ }
+ }
+
+ /**
+ * Set the markers list.
+ *
+ * @param markers
+ * The markers list, or null
+ * @since 2.0
+ */
+ public void setMarkers(List<IMarkerEvent> markers) {
+ fMarkers.clear();
+ if (markers != null) {
+ fMarkers.addAll(markers);
+ }
+ updateMarkerList();
+ updateMarkerActions();
+ }
+
+ /**
+ * Get the markers list.
+ *
+ * @return The markers list, or null
+ * @since 2.0
+ */
+ public List<IMarkerEvent> getMarkers() {
+ return Collections.unmodifiableList(fMarkers);
+ }
+
/**
* Callback to set a selected event in the view
*
* @param entry
* The entry
* @return true if the entry is expanded, false if collapsed
- * @since 2.0
+ * @since 1.1
*/
public boolean getExpandedState(ITimeGraphEntry entry) {
return fTimeGraphCtrl.getExpandedState(entry);
return fFollowArrowBwdAction;
}
+ /**
+ * Get the show filter dialog action.
+ *
+ * @return The Action object
+ * @since 2.0
+ */
+ public ShowFilterDialogAction getShowFilterDialogAction() {
+ if (fShowFilterDialogAction == null) {
+ fShowFilterDialogAction = new ShowFilterDialogAction(this);
+ }
+ return fShowFilterDialogAction;
+ }
+
+ /**
+ * Get the toggle bookmark action.
+ *
+ * @return The Action object
+ * @since 2.0
+ */
+ public Action getToggleBookmarkAction() {
+ if (fToggleBookmarkAction == null) {
+ fToggleBookmarkAction = new Action() {
+ @Override
+ public void runWithEvent(Event event) {
+ IMarkerEvent selectedBookmark = getBookmarkAtSelection();
+ 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(), null);
+ if (dialog.open() == Window.OK) {
+ final String label = dialog.getValue();
+ final RGBA rgba = dialog.getColorValue();
+ IMarkerEvent bookmark = new MarkerEvent(null, time, duration, IMarkerEvent.BOOKMARKS, rgba, label, true);
+ fBookmarks.add(bookmark);
+ updateMarkerList();
+ updateMarkerActions();
+ getControl().redraw();
+ fireBookmarkAdded(bookmark);
+ }
+ } else {
+ fBookmarks.remove(selectedBookmark);
+ updateMarkerList();
+ updateMarkerActions();
+ getControl().redraw();
+ fireBookmarkRemoved(selectedBookmark);
+ }
+ }
+ };
+ fToggleBookmarkAction.setText(Messages.TmfTimeGraphViewer_BookmarkActionAddText);
+ fToggleBookmarkAction.setToolTipText(Messages.TmfTimeGraphViewer_BookmarkActionAddText);
+ fToggleBookmarkAction.setImageDescriptor(ADD_BOOKMARK);
+ }
+ return fToggleBookmarkAction;
+ }
+
+ /**
+ * Get the next marker action.
+ *
+ * @return The Action object
+ * @since 2.0
+ */
+ public Action getNextMarkerAction() {
+ if (fNextMarkerAction == null) {
+ fNextMarkerAction = new Action(Messages.TmfTimeGraphViewer_NextMarkerActionText, IAction.AS_DROP_DOWN_MENU) {
+ @Override
+ public void runWithEvent(Event event) {
+ boolean extend = (event.stateMask & SWT.SHIFT) != 0;
+ if (extend) {
+ extendToNextMarker();
+ } else {
+ selectNextMarker();
+ }
+ }
+ };
+ fNextMarkerAction.setToolTipText(Messages.TmfTimeGraphViewer_NextMarkerActionText);
+ fNextMarkerAction.setImageDescriptor(NEXT_BOOKMARK);
+ fNextMarkerAction.setMenuCreator(new IMenuCreator () {
+ Menu menu = null;
+ @Override
+ public void dispose() {
+ if (menu != null) {
+ menu.dispose();
+ menu = null;
+ }
+ }
+
+ @Override
+ public Menu getMenu(Control parent) {
+ if (menu != null) {
+ menu.dispose();
+ }
+ menu = new Menu(parent);
+ for (String category : fMarkerCategories) {
+ final Action action = new Action(category, IAction.AS_CHECK_BOX) {
+ @Override
+ public void runWithEvent(Event event) {
+ if (isChecked()) {
+ fSkippedMarkerCategories.remove(getText());
+ } else {
+ fSkippedMarkerCategories.add(getText());
+ }
+ updateMarkerActions();
+ }
+ };
+ action.setEnabled(!fHiddenMarkerCategories.contains(category));
+ action.setChecked(action.isEnabled() && !fSkippedMarkerCategories.contains(category));
+ new ActionContributionItem(action).fill(menu, -1);
+ }
+ return menu;
+ }
+
+ @Override
+ public Menu getMenu(Menu parent) {
+ return null;
+ }
+ });
+ }
+ return fNextMarkerAction;
+ }
+
+ /**
+ * Get the previous marker action.
+ *
+ * @return The Action object
+ * @since 2.0
+ */
+ public Action getPreviousMarkerAction() {
+ if (fPreviousMarkerAction == null) {
+ fPreviousMarkerAction = new Action() {
+ @Override
+ public void runWithEvent(Event event) {
+ boolean extend = (event.stateMask & SWT.SHIFT) != 0;
+ if (extend) {
+ extendToPrevMarker();
+ } else {
+ selectPrevMarker();
+ }
+ }
+ };
+ fPreviousMarkerAction.setText(Messages.TmfTimeGraphViewer_PreviousMarkerActionText);
+ fPreviousMarkerAction.setToolTipText(Messages.TmfTimeGraphViewer_PreviousMarkerActionText);
+ fPreviousMarkerAction.setImageDescriptor(PREVIOUS_BOOKMARK);
+ }
+ return fPreviousMarkerAction;
+ }
+
+ /**
+ * Get the show markers menu.
+ *
+ * @return The menu manager object
+ * @since 2.0
+ */
+ public MenuManager getMarkersMenu() {
+ if (fMarkersMenu == null) {
+ fMarkersMenu = new MenuManager(Messages.TmfTimeGraphViewer_ShowMarkersMenuText);
+ fMarkersMenu.setRemoveAllWhenShown(true);
+ fMarkersMenu.addMenuListener(new IMenuListener() {
+ @Override
+ public void menuAboutToShow(IMenuManager manager) {
+ for (String category : fMarkerCategories) {
+ final Action action = new Action(category, IAction.AS_CHECK_BOX) {
+ @Override
+ public void runWithEvent(Event event) {
+ setMarkerCategoryVisible(getText(), isChecked());
+ }
+ };
+ action.setChecked(!fHiddenMarkerCategories.contains(category));
+ manager.add(action);
+ }
+ }
+ });
+ }
+ return fMarkersMenu;
+ }
+
+ /**
+ * Select the next marker that begins at or after the current selection
+ * begin time. Markers that begin at the same time are ordered by end time.
+ */
+ private void selectNextMarker() {
+ List<IMarkerEvent> markers = getTimeGraphControl().getMarkers();
+ if (markers == null) {
+ return;
+ }
+ for (IMarkerEvent marker : markers) {
+ final long time = Math.min(fSelectionBegin, fSelectionEnd);
+ final long duration = Math.max(fSelectionBegin, fSelectionEnd) - time;
+ if ((marker.getTime() > time ||
+ (marker.getTime() == time && marker.getDuration() > duration))
+ && !fSkippedMarkerCategories.contains(marker.getCategory())) {
+ setSelectionRangeNotify(marker.getTime(), marker.getTime() + marker.getDuration(), true);
+ fTimeGraphCtrl.updateStatusLine();
+ return;
+ }
+ }
+ }
+
+ /**
+ * Select the previous marker that begins at or before the current selection
+ * begin time. Markers that begin at the same time are ordered by end time.
+ */
+ private void selectPrevMarker() {
+ List<IMarkerEvent> markers = getTimeGraphControl().getMarkers();
+ if (markers == null) {
+ return;
+ }
+ final long time = Math.min(fSelectionBegin, fSelectionEnd);
+ final long duration = Math.max(fSelectionBegin, fSelectionEnd) - time;
+ for (int i = markers.size() - 1; i >= 0; i--) {
+ IMarkerEvent marker = markers.get(i);
+ if ((marker.getTime() < time ||
+ (marker.getTime() == time && marker.getDuration() < duration))
+ && !fSkippedMarkerCategories.contains(marker.getCategory())) {
+ setSelectionRangeNotify(marker.getTime(), marker.getTime() + marker.getDuration(), true);
+ fTimeGraphCtrl.updateStatusLine();
+ return;
+ }
+ }
+ }
+
+ /**
+ * Extend the selection to the closest next marker end time.
+ */
+ private void extendToNextMarker() {
+ List<IMarkerEvent> markers = getTimeGraphControl().getMarkers();
+ if (markers == null) {
+ return;
+ }
+ IMarkerEvent nextMarker = null;
+ for (IMarkerEvent marker : markers) {
+ if (marker.getTime() + marker.getDuration() > fSelectionEnd
+ && !fSkippedMarkerCategories.contains(marker.getCategory())
+ && (nextMarker == null || marker.getTime() + marker.getDuration() < nextMarker.getTime() + nextMarker.getDuration())) {
+ nextMarker = marker;
+ }
+ }
+ if (nextMarker != null) {
+ setSelectionRangeNotify(fSelectionBegin, nextMarker.getTime() + nextMarker.getDuration(), true);
+ fTimeGraphCtrl.updateStatusLine();
+ }
+ }
+
+ /**
+ * Extend the selection to the closest previous marker start time.
+ */
+ private void extendToPrevMarker() {
+ List<IMarkerEvent> markers = getTimeGraphControl().getMarkers();
+ if (markers == null) {
+ return;
+ }
+ for (int i = markers.size() - 1; i >= 0; i--) {
+ IMarkerEvent marker = markers.get(i);
+ if (marker.getTime() < fSelectionEnd
+ && !fSkippedMarkerCategories.contains(marker.getCategory())) {
+ setSelectionRangeNotify(fSelectionBegin, marker.getTime(), true);
+ fTimeGraphCtrl.updateStatusLine();
+ return;
+ }
+ }
+ }
+
+ private IMarkerEvent getBookmarkAtSelection() {
+ final long time = Math.min(fSelectionBegin, fSelectionEnd);
+ final long duration = Math.max(fSelectionBegin, fSelectionEnd) - time;
+ for (IMarkerEvent bookmark : fBookmarks) {
+ if (bookmark.getTime() == time && bookmark.getDuration() == duration) {
+ return bookmark;
+ }
+ }
+ return null;
+ }
+
+ private void updateMarkerActions() {
+ boolean enabled = fTime0Bound != SWT.DEFAULT || fTime1Bound != SWT.DEFAULT;
+ if (fToggleBookmarkAction != null) {
+ if (getBookmarkAtSelection() != null) {
+ fToggleBookmarkAction.setText(Messages.TmfTimeGraphViewer_BookmarkActionRemoveText);
+ fToggleBookmarkAction.setToolTipText(Messages.TmfTimeGraphViewer_BookmarkActionRemoveText);
+ fToggleBookmarkAction.setImageDescriptor(REMOVE_BOOKMARK);
+ } else {
+ fToggleBookmarkAction.setText(Messages.TmfTimeGraphViewer_BookmarkActionAddText);
+ fToggleBookmarkAction.setToolTipText(Messages.TmfTimeGraphViewer_BookmarkActionAddText);
+ fToggleBookmarkAction.setImageDescriptor(ADD_BOOKMARK);
+ }
+ fToggleBookmarkAction.setEnabled(enabled);
+ }
+ List<IMarkerEvent> markers = getTimeGraphControl().getMarkers();
+ if (markers == null) {
+ markers = Collections.emptyList();
+ }
+ if (fPreviousMarkerAction != null) {
+ fPreviousMarkerAction.setEnabled(enabled && !markers.isEmpty());
+ }
+ if (fNextMarkerAction != null) {
+ fNextMarkerAction.setEnabled(enabled && !markers.isEmpty());
+ }
+ }
+
+ private void updateMarkerList() {
+ List<IMarkerEvent> markers = new ArrayList<>();
+ for (IMarkerEvent marker : fMarkers) {
+ if (!fHiddenMarkerCategories.contains(marker.getCategory())) {
+ markers.add(marker);
+ }
+ }
+ if (!fHiddenMarkerCategories.contains(IMarkerEvent.BOOKMARKS)) {
+ markers.addAll(fBookmarks);
+ }
+ Collections.sort(markers, new MarkerComparator());
+ fTimeGraphCtrl.setMarkers(markers);
+ fMarkerAxisCtrl.setMarkers(markers);
+ }
+
private void adjustHorizontalScrollBar() {
long time0 = getTime0();
long time1 = getTime1();
* @param filter
* The filter object to be attached to the view
*/
- public void addFilter(ViewerFilter filter) {
+ public void addFilter(@NonNull ViewerFilter filter) {
fTimeGraphCtrl.addFilter(filter);
refresh();
}
* @param filter
* The filter object to be attached to the view
*/
- public void removeFilter(ViewerFilter filter) {
+ public void removeFilter(@NonNull ViewerFilter filter) {
fTimeGraphCtrl.removeFilter(filter);
refresh();
}
+ /**
+ * Returns this viewer's filters.
+ *
+ * @return an array of viewer filters
+ * @since 2.0
+ */
+ public @NonNull ViewerFilter[] getFilters() {
+ return fTimeGraphCtrl.getFilters();
+ }
+
+ /**
+ * Sets the filters, replacing any previous filters, and triggers
+ * refiltering of the elements.
+ *
+ * @param filters
+ * an array of viewer filters, or null
+ * @since 2.0
+ */
+ public void setFilters(@NonNull ViewerFilter[] filters) {
+ fTimeGraphCtrl.setFilters(filters);
+ refresh();
+ }
+
/**
* Return the time alignment information
*