tmf: Bug 494952: Remove deadlock in Time Chart view
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / widgets / timegraph / TimeGraphViewer.java
index 6cb17d16571fc8dfc31a656e491a2be9f927e8d3..976eafec7bb79eee227e700b0371c688ad2ed8bb 100644 (file)
@@ -42,8 +42,6 @@ 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;
@@ -52,6 +50,7 @@ import org.eclipse.swt.events.MouseWheelListener;
 import org.eclipse.swt.events.SelectionAdapter;
 import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
 import org.eclipse.swt.graphics.RGBA;
 import org.eclipse.swt.graphics.Rectangle;
 import org.eclipse.swt.layout.FillLayout;
@@ -77,10 +76,12 @@ 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;
@@ -92,7 +93,7 @@ import org.eclipse.ui.PlatformUI;
  *
  * @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;
@@ -130,13 +131,14 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
 
     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<>();
@@ -318,7 +320,7 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
      * Sets the tree columns for this time graph combo's filter dialog.
      *
      * @param columnNames the tree column names
-     * @since 2.0
+     * @since 1.2
      */
     public void setFilterColumns(String[] columnNames) {
         getShowFilterDialogAction().getFilterDialog().setColumnNames(columnNames);
@@ -328,7 +330,7 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
      * Sets the tree content provider used by the filter dialog
      *
      * @param contentProvider the tree content provider
-     * @since 2.0
+     * @since 1.2
      */
     public void setFilterContentProvider(ITreeContentProvider contentProvider) {
         getShowFilterDialogAction().getFilterDialog().setContentProvider(contentProvider);
@@ -338,7 +340,7 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
      * Sets the tree label provider used by the filter dialog
      *
      * @param labelProvider the tree label provider
-     * @since 2.0
+     * @since 1.2
      */
     public void setFilterLabelProvider(ITableLabelProvider labelProvider) {
         getShowFilterDialogAction().getFilterDialog().setLabelProvider(labelProvider);
@@ -453,21 +455,18 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
      */
     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();
-                }
+        fDataViewer.addDisposeListener((e) -> {
+            if (fMarkersMenu != null) {
+                fMarkersMenu.dispose();
             }
         });
         GridLayout gl = new GridLayout(2, false);
@@ -499,7 +498,14 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
         fTimeScaleCtrl.addMouseWheelListener(new MouseWheelListener() {
             @Override
             public void mouseScrolled(MouseEvent e) {
-                fTimeGraphCtrl.zoom(e.count > 0);
+                if (e.count == 0) {
+                    return;
+                }
+                if ((e.stateMask & SWT.CTRL) != 0) {
+                    fTimeGraphCtrl.zoom(e.count > 0);
+                } else {
+                    fTimeGraphCtrl.horizontalScroll(e.count > 0);
+                }
             }
         });
 
@@ -512,17 +518,37 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
         fTimeGraphCtrl.addMouseWheelListener(new MouseWheelListener() {
             @Override
             public void mouseScrolled(MouseEvent e) {
-                adjustVerticalScrollBar();
+                if (e.count == 0) {
+                    return;
+                }
+                /*
+                 * On some platforms the mouse scroll event is sent to the
+                 * control that has focus even if it is not under the cursor.
+                 * Handle the event only if not over the time graph control.
+                 */
+                Point ctrlParentCoords = fTimeAlignedComposite.toControl(fTimeGraphCtrl.toDisplay(e.x, e.y));
+                Point scrollBarParentCoords = fDataViewer.toControl(fTimeGraphCtrl.toDisplay(e.x, e.y));
+                if (fTimeGraphCtrl.getBounds().contains(ctrlParentCoords)) {
+                    /* the time graph control handles the event */
+                    adjustVerticalScrollBar();
+                } else if (fTimeScaleCtrl.getBounds().contains(ctrlParentCoords)
+                        || fMarkerAxisCtrl.getBounds().contains(ctrlParentCoords)
+                        || fHorizontalScrollBar.getBounds().contains(scrollBarParentCoords)) {
+                    if ((e.stateMask & SWT.CTRL) != 0) {
+                        fTimeGraphCtrl.zoom(e.count > 0);
+                    } else {
+                        fTimeGraphCtrl.horizontalScroll(e.count > 0);
+                    }
+                } else {
+                    /* over the vertical scroll bar or outside of the viewer */
+                    setTopIndex(getTopIndex() - e.count);
+                }
             }
         });
         fTimeGraphCtrl.addKeyListener(new KeyAdapter() {
             @Override
             public void keyPressed(KeyEvent e) {
-                if ((e.character == '+' || e.character == '=') && ((e.stateMask & SWT.CTRL) == 0)) {
-                    zoomIn();
-                } else if (e.character == '-' && ((e.stateMask & SWT.CTRL) == 0)) {
-                    zoomOut();
-                } else if (e.keyCode == '.') {
+                if (e.keyCode == '.') {
                     boolean extend = (e.stateMask & SWT.SHIFT) != 0;
                     if (extend) {
                         extendToNextMarker();
@@ -541,6 +567,23 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
             }
         });
 
+        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;
+                }
+                if ((e.stateMask & SWT.CTRL) != 0) {
+                    fTimeGraphCtrl.zoom(e.count > 0);
+                } else {
+                    fTimeGraphCtrl.horizontalScroll(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() {
@@ -555,13 +598,16 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
         fHorizontalScrollBar.addListener(SWT.MouseWheel, new Listener() {
             @Override
             public void handleEvent(Event event) {
-                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;
+                if (event.count == 0) {
+                    return;
+                }
+                if ((event.stateMask & SWT.CTRL) != 0) {
+                    fTimeGraphCtrl.zoom(event.count > 0);
+                } else {
+                    fTimeGraphCtrl.horizontalScroll(event.count > 0);
+                }
             }
         });
         fHorizontalScrollBar.addListener(SWT.Selection, new Listener() {
@@ -598,17 +644,20 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
         fDataViewer.update();
         adjustHorizontalScrollBar();
         adjustVerticalScrollBar();
+
+        fDataViewer.addDisposeListener((e) -> {
+            saveOptions();
+            fColorScheme.dispose();
+        });
+
         return fDataViewer;
     }
 
     /**
-     * Dispose the view.
+     * Dispose the time graph viewer.
      */
     public void dispose() {
-        saveOptions();
-        fTimeGraphCtrl.dispose();
         fDataViewer.dispose();
-        fColorScheme.dispose();
     }
 
     /**
@@ -625,6 +674,23 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
         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
      */
@@ -741,6 +807,7 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
         }
         fTimeGraphCtrl.refreshData(traces);
         fTimeScaleCtrl.redraw();
+        fMarkerAxisCtrl.redraw();
         updateMarkerActions();
         adjustVerticalScrollBar();
     }
@@ -813,6 +880,11 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
         }
         fTimeGraphCtrl.redraw();
         fTimeScaleCtrl.redraw();
+        fMarkerAxisCtrl.redraw();
+        /* force update the controls to keep them aligned */
+        fTimeScaleCtrl.update();
+        fMarkerAxisCtrl.update();
+        fTimeGraphCtrl.update();
     }
 
     @Override
@@ -894,6 +966,11 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
         adjustHorizontalScrollBar();
         fTimeGraphCtrl.redraw();
         fTimeScaleCtrl.redraw();
+        fMarkerAxisCtrl.redraw();
+        /* force update the controls to keep them aligned */
+        fTimeScaleCtrl.update();
+        fMarkerAxisCtrl.update();
+        fTimeGraphCtrl.update();
     }
 
     @Override
@@ -902,6 +979,19 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
         fTimeRangeFixed = false;
     }
 
+    /**
+     * @since 2.0
+     */
+    @Override
+    public void resetStartFinishTime(boolean notify) {
+        if (notify) {
+            setStartFinishTimeNotify(fTime0Bound, fTime1Bound);
+        } else {
+            setStartFinishTime(fTime0Bound, fTime1Bound);
+        }
+        fTimeRangeFixed = false;
+    }
+
     @Override
     public void setSelectedTimeNotify(long time, boolean ensureVisible) {
         setSelectedTimeInt(time, ensureVisible, true);
@@ -921,7 +1011,7 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
     }
 
     /**
-     * @since 2.0
+     * @since 1.2
      */
     @Override
     public void setSelectionRangeNotify(long beginTime, long endTime, boolean ensureVisible) {
@@ -929,7 +1019,7 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
     }
 
     /**
-     * @since 2.0
+     * @since 1.2
      */
     @Override
     public void setSelectionRange(long beginTime, long endTime, boolean ensureVisible) {
@@ -955,6 +1045,7 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
 
         fTimeGraphCtrl.redraw();
         fTimeScaleCtrl.redraw();
+        fMarkerAxisCtrl.redraw();
         updateMarkerActions();
 
         if ((time0 != fTime0) || (time1 != fTime1)) {
@@ -1263,11 +1354,29 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
      */
     public void setMarkerCategories(List<String> categories) {
         fMarkerCategories.clear();
-        fMarkerCategories.add(IMarkerEvent.BOOKMARKS);
         if (categories != null) {
             fMarkerCategories.addAll(categories);
         }
-        Collections.sort(fMarkerCategories);
+        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();
+        }
     }
 
     /**
@@ -1715,6 +1824,23 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
         adjustVerticalScrollBar();
     }
 
+    /**
+     * Select an entry and reveal it
+     *
+     * @param entry
+     *            The entry to select
+     * @since 2.0
+     */
+    public void selectAndReveal(@NonNull ITimeGraphEntry entry) {
+        final ITimeGraphEntry parent = entry.getParent();
+        if (parent != null) {
+            fTimeGraphCtrl.setExpandedState(parent, true);
+        }
+        fSelectedEntry = entry;
+        fTimeGraphCtrl.selectItem(entry, false);
+        adjustVerticalScrollBar();
+    }
+
     /**
      * Get the number of expanded (visible) time graph entries. This includes
      * leafs and does not include filtered-out entries.
@@ -2025,7 +2151,7 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
      * Get the show filter dialog action.
      *
      * @return The Action object
-     * @since 2.0
+     * @since 1.2
      */
     public ShowFilterDialogAction getShowFilterDialogAction() {
         if (fShowFilterDialogAction == null) {
@@ -2184,14 +2310,7 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
                         final Action action = new Action(category, IAction.AS_CHECK_BOX) {
                             @Override
                             public void runWithEvent(Event event) {
-                                if (isChecked()) {
-                                    fHiddenMarkerCategories.remove(getText());
-                                } else {
-                                    fHiddenMarkerCategories.add(getText());
-                                }
-                                updateMarkerList();
-                                updateMarkerActions();
-                                getControl().redraw();
+                                setMarkerCategoryVisible(getText(), isChecked());
                             }
                         };
                         action.setChecked(!fHiddenMarkerCategories.contains(category));
@@ -2218,7 +2337,9 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
             if ((marker.getTime() > time ||
                     (marker.getTime() == time && marker.getDuration() > duration))
                     && !fSkippedMarkerCategories.contains(marker.getCategory())) {
-                setSelectionRangeNotify(marker.getTime(), marker.getTime() + marker.getDuration(), true);
+                setSelectionRangeNotify(marker.getTime(), marker.getTime() + marker.getDuration(), false);
+                ensureVisible(marker.getTime());
+                notifyRangeListeners();
                 fTimeGraphCtrl.updateStatusLine();
                 return;
             }
@@ -2241,7 +2362,9 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
             if ((marker.getTime() < time ||
                     (marker.getTime() == time && marker.getDuration() < duration))
                     && !fSkippedMarkerCategories.contains(marker.getCategory())) {
-                setSelectionRangeNotify(marker.getTime(), marker.getTime() + marker.getDuration(), true);
+                setSelectionRangeNotify(marker.getTime(), marker.getTime() + marker.getDuration(), false);
+                ensureVisible(marker.getTime());
+                notifyRangeListeners();
                 fTimeGraphCtrl.updateStatusLine();
                 return;
             }
@@ -2337,7 +2460,8 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
             markers.addAll(fBookmarks);
         }
         Collections.sort(markers, new MarkerComparator());
-        getTimeGraphControl().setMarkers(markers);
+        fTimeGraphCtrl.setMarkers(markers);
+        fMarkerAxisCtrl.setMarkers(markers);
     }
 
     private void adjustHorizontalScrollBar() {
@@ -2432,7 +2556,7 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
      * Returns this viewer's filters.
      *
      * @return an array of viewer filters
-     * @since 2.0
+     * @since 1.2
      */
     public @NonNull ViewerFilter[] getFilters() {
         return fTimeGraphCtrl.getFilters();
@@ -2444,7 +2568,7 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
      *
      * @param filters
      *            an array of viewer filters, or null
-     * @since 2.0
+     * @since 1.2
      */
     public void setFilters(@NonNull ViewerFilter[] filters) {
         fTimeGraphCtrl.setFilters(filters);
This page took 0.031758 seconds and 5 git commands to generate.