+ /**
+ * 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(), false);
+ ensureVisible(marker.getTime());
+ notifyRangeListeners();
+ 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(), false);
+ ensureVisible(marker.getTime());
+ notifyRangeListeners();
+ 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);
+ }
+