tmf: Allow shift key to extend selection in time graph
authorPatrick Tasse <patrick.tasse@gmail.com>
Wed, 6 May 2015 21:02:47 +0000 (17:02 -0400)
committerPatrick Tasse <patrick.tasse@gmail.com>
Mon, 11 May 2015 20:06:46 +0000 (16:06 -0400)
- Extend the selection range when shift key is pressed while pressing
left or right keys.
- Extend the selection range when shift key is pressed while running the
next event, previous event, follow arrow fwd, follow arrow bwd actions.
- Update status line when the above actions modify the selection.
- Make sure the selection end time is visible when modifying the
selection range.
- Show status line when time graph control has focus with mouse outside
of the control bounds, but without displaying the cursor time.
- Highlight the selected state at the selection end time instead of the
selection start time.
- Remove the margin factor that made 'ensure visible' change the time
range when the selection was near the left or right margin.

Change-Id: Iee1dbbbc56e052de1a48bc638355e0c7dc126c2a
Signed-off-by: Patrick Tasse <patrick.tasse@gmail.com>
Reviewed-on: https://git.eclipse.org/r/47381
Reviewed-by: Hudson CI
org.eclipse.tracecompass.tmf.ui.tests/widgetStubs/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/test/stub/views/TsfTraceAnalysisView.java
org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/TimeGraphViewer.java
org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/widgets/TimeGraphControl.java

index 29236d17cbf1a0924b614f480229e569b3713c8b..e7b482e6ba7832f02b4a189c8a67c3a880680d57 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2014 Ericsson
+ * Copyright (c) 2009, 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
@@ -398,7 +398,7 @@ public class TsfTraceAnalysisView extends ViewPart implements
             public void run() {
                 TimeGraphViewer inFocusViewer = getActiveTsfCtrl();
                 if (inFocusViewer != null) {
-                    inFocusViewer.selectNextEvent();
+                    inFocusViewer.selectNextEvent(false);
                 }
             }
         };
@@ -411,7 +411,7 @@ public class TsfTraceAnalysisView extends ViewPart implements
             public void run() {
                 TimeGraphViewer inFocusViewer = getActiveTsfCtrl();
                 if (inFocusViewer != null) {
-                    inFocusViewer.selectPrevEvent();
+                    inFocusViewer.selectPrevEvent(false);
                 }
             }
         };
index b1f3586e34f335ff27de4b1b195e2bc284dbaab3..7e1ec6cc1c1d7016496522df4d8bd05475387032 100644 (file)
@@ -78,7 +78,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
     private static final int MIN_NAME_WIDTH = 6;
     private static final int MAX_NAME_WIDTH = 1000;
     private static final int DEFAULT_HEIGHT = 22;
-    private static final long RECENTERING_MARGIN_FACTOR = 50;
     private static final String HIDE_ARROWS_KEY = "hide.arrows"; //$NON-NLS-1$
     private static final long DEFAULT_FREQUENCY = 1000000000L;
     private static final int H_SCROLLBAR_MAX = Integer.MAX_VALUE - 1;
@@ -782,11 +781,17 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
 
     @Override
     public void setSelectionRangeNotify(long beginTime, long endTime) {
+        long time0 = fTime0;
+        long time1 = fTime1;
         boolean changed = (beginTime != fSelectionBegin || endTime != fSelectionEnd);
         fSelectionBegin = Math.max(fTime0Bound, Math.min(fTime1Bound, beginTime));
         fSelectionEnd = Math.max(fTime0Bound, Math.min(fTime1Bound, endTime));
+        ensureVisible(fSelectionEnd);
         fTimeGraphCtrl.redraw();
         fTimeScaleCtrl.redraw();
+        if ((time0 != fTime0) || (time1 != fTime1)) {
+            notifyRangeListeners();
+        }
         if (changed) {
             notifyTimeListeners();
         }
@@ -804,29 +809,8 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
         long time0 = fTime0;
         long time1 = fTime1;
         if (ensureVisible) {
-            long timeSpace = (fTime1 - fTime0) / RECENTERING_MARGIN_FACTOR;
-            long timeMid = (fTime1 - fTime0) / 2;
-            if (time < fTime0 + timeSpace) {
-                long dt = fTime0 - time + timeMid;
-                fTime0 -= dt;
-                fTime1 -= dt;
-            } else if (time > fTime1 - timeSpace) {
-                long dt = time - fTime1 + timeMid;
-                fTime0 += dt;
-                fTime1 += dt;
-            }
-            if (fTime0 < fTime0Bound) {
-                fTime1 = Math.min(fTime1Bound, fTime1 + (fTime0Bound - fTime0));
-                fTime0 = fTime0Bound;
-            } else if (fTime1 > fTime1Bound) {
-                fTime0 = Math.max(fTime0Bound, fTime0 - (fTime1 - fTime1Bound));
-                fTime1 = fTime1Bound;
-            }
+            ensureVisible(time);
         }
-        if (fTime1 - fTime0 < fMinTimeInterval) {
-            fTime1 = Math.min(fTime1Bound, fTime0 + fMinTimeInterval);
-        }
-        adjustHorizontalScrollBar();
         fTimeGraphCtrl.redraw();
         fTimeScaleCtrl.redraw();
 
@@ -843,6 +827,30 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
         }
     }
 
+    private void ensureVisible(long time) {
+        long timeMid = (fTime1 - fTime0) / 2;
+        if (time < fTime0) {
+            long dt = fTime0 - time + timeMid;
+            fTime0 -= dt;
+            fTime1 -= dt;
+        } else if (time > fTime1) {
+            long dt = time - fTime1 + timeMid;
+            fTime0 += dt;
+            fTime1 += dt;
+        }
+        if (fTime0 < fTime0Bound) {
+            fTime1 = Math.min(fTime1Bound, fTime1 + (fTime0Bound - fTime0));
+            fTime0 = fTime0Bound;
+        } else if (fTime1 > fTime1Bound) {
+            fTime0 = Math.max(fTime0Bound, fTime0 - (fTime1 - fTime1Bound));
+            fTime1 = fTime1Bound;
+        }
+        if (fTime1 - fTime0 < fMinTimeInterval) {
+            fTime1 = Math.min(fTime1Bound, fTime0 + fMinTimeInterval);
+        }
+        adjustHorizontalScrollBar();
+    }
+
     @Override
     public void widgetDefaultSelected(SelectionEvent e) {
         if (fSelectedEntry != getSelection()) {
@@ -861,17 +869,25 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
 
     /**
      * Callback for when the next event is selected
+     *
+     * @param extend
+     *            true to extend selection range, false for single selection
+     * @since 1.0
      */
-    public void selectNextEvent() {
-        fTimeGraphCtrl.selectNextEvent();
+    public void selectNextEvent(boolean extend) {
+        fTimeGraphCtrl.selectNextEvent(extend);
         adjustVerticalScrollBar();
     }
 
     /**
      * Callback for when the previous event is selected
+     *
+     * @param extend
+     *            true to extend selection range, false for single selection
+     * @since 1.0
      */
-    public void selectPrevEvent() {
-        fTimeGraphCtrl.selectPrevEvent();
+    public void selectPrevEvent(boolean extend) {
+        fTimeGraphCtrl.selectPrevEvent(extend);
         adjustVerticalScrollBar();
     }
 
@@ -1534,8 +1550,9 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
         if (fNextEventAction == null) {
             fNextEventAction = new Action() {
                 @Override
-                public void run() {
-                    selectNextEvent();
+                public void runWithEvent(Event event) {
+                    boolean extend = (event.stateMask & SWT.SHIFT) != 0;
+                    selectNextEvent(extend);
                 }
             };
 
@@ -1556,8 +1573,9 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
         if (fPrevEventAction == null) {
             fPrevEventAction = new Action() {
                 @Override
-                public void run() {
-                    selectPrevEvent();
+                public void runWithEvent(Event event) {
+                    boolean extend = (event.stateMask & SWT.SHIFT) != 0;
+                    selectPrevEvent(extend);
                 }
             };
 
@@ -1705,8 +1723,9 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
         if (fFollowArrowFwdAction == null) {
             fFollowArrowFwdAction = new Action() {
                 @Override
-                public void run() {
-                    fTimeGraphCtrl.followArrowFwd();
+                public void runWithEvent(Event event) {
+                    boolean extend = (event.stateMask & SWT.SHIFT) != 0;
+                    fTimeGraphCtrl.followArrowFwd(extend);
                     adjustVerticalScrollBar();
                 }
             };
@@ -1729,8 +1748,9 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
         if (fFollowArrowBwdAction == null) {
             fFollowArrowBwdAction = new Action() {
                 @Override
-                public void run() {
-                    fTimeGraphCtrl.followArrowBwd();
+                public void runWithEvent(Event event) {
+                    boolean extend = (event.stateMask & SWT.SHIFT) != 0;
+                    fTimeGraphCtrl.followArrowBwd(extend);
                     adjustVerticalScrollBar();
                 }
             };
index cafddf64ad2280704b56007363a01bf4075edd65..f7ea5e3fc55f2c1c4af58393e577c91147e4a477 100644 (file)
@@ -111,6 +111,7 @@ public class TimeGraphControl extends TimeGraphBaseControl
     private static final int ARROW_HOVER_MAX_DIST = 5;
 
     private static final int NO_STATUS = -1;
+    private static final int STATUS_WITHOUT_CURSOR_TIME = -2;
 
     /** Resource manager */
     private LocalResourceManager fResourceManager = new LocalResourceManager(JFaceResources.getResources());
@@ -721,8 +722,11 @@ public class TimeGraphControl extends TimeGraphBaseControl
      *
      * @param n
      *            1 for next event, -1 for previous event
+     * @param extend
+     *            true to extend selection range, false for single selection
+     * @since 1.0
      */
-    public void selectEvent(int n) {
+    public void selectEvent(int n, boolean extend) {
         if (null == fTimeProvider) {
             return;
         }
@@ -730,15 +734,15 @@ public class TimeGraphControl extends TimeGraphBaseControl
         if (trace == null) {
             return;
         }
-        long selectedTime = fTimeProvider.getSelectionBegin();
+        long selectedTime = fTimeProvider.getSelectionEnd();
         long endTime = fTimeProvider.getMaxTime();
         ITimeEvent nextEvent;
-        if (-1 == n && selectedTime > endTime) {
+        if (n == -1 && selectedTime > endTime) {
             nextEvent = Utils.findEvent(trace, selectedTime, 0);
         } else {
             nextEvent = Utils.findEvent(trace, selectedTime, n);
         }
-        if (null == nextEvent && -1 == n) {
+        if (null == nextEvent && n == -1) {
             nextEvent = Utils.getFirstEvent(trace);
         }
         if (null != nextEvent) {
@@ -756,28 +760,45 @@ public class TimeGraphControl extends TimeGraphBaseControl
                 // for previous event go to its end time unless we were already there
                 nextTime = nextEvent.getTime() + nextEvent.getDuration();
             }
-            fTimeProvider.setSelectedTimeNotify(nextTime, true);
+            if (extend) {
+                fTimeProvider.setSelectionRangeNotify(fTimeProvider.getSelectionBegin(), nextTime);
+            } else {
+                fTimeProvider.setSelectedTimeNotify(nextTime, true);
+            }
             fireSelectionChanged();
-        } else if (1 == n) {
-            fTimeProvider.setSelectedTimeNotify(endTime, true);
+        } else if (n == 1) {
+            if (extend) {
+                fTimeProvider.setSelectionRangeNotify(fTimeProvider.getSelectionBegin(), endTime);
+            } else {
+                fTimeProvider.setSelectedTimeNotify(endTime, true);
+            }
             fireSelectionChanged();
         }
+        updateStatusLine(STATUS_WITHOUT_CURSOR_TIME);
     }
 
     /**
      * Select the next event
+     *
+     * @param extend
+     *            true to extend selection range, false for single selection
+     * @since 1.0
      */
-    public void selectNextEvent() {
-        selectEvent(1);
+    public void selectNextEvent(boolean extend) {
+        selectEvent(1, extend);
         // Notify if visible time window has been adjusted
         fTimeProvider.setStartFinishTimeNotify(fTimeProvider.getTime0(), fTimeProvider.getTime1());
     }
 
     /**
      * Select the previous event
+     *
+     * @param extend
+     *            true to extend selection range, false for single selection
+     * @since 1.0
      */
-    public void selectPrevEvent() {
-        selectEvent(-1);
+    public void selectPrevEvent(boolean extend) {
+        selectEvent(-1, extend);
         // Notify if visible time window has been adjusted
         fTimeProvider.setStartFinishTimeNotify(fTimeProvider.getTime0(), fTimeProvider.getTime1());
     }
@@ -919,50 +940,68 @@ public class TimeGraphControl extends TimeGraphBaseControl
 
     /**
      * Follow the arrow forward
+     *
+     * @param extend
+     *            true to extend selection range, false for single selection
+     * @since 1.0
      */
-    public void followArrowFwd() {
+    public void followArrowFwd(boolean extend) {
         ITimeGraphEntry trace = getSelectedTrace();
         if (trace == null) {
             return;
         }
-        long selectedTime = fTimeProvider.getSelectionBegin();
+        long selectedTime = fTimeProvider.getSelectionEnd();
         for (ILinkEvent link : fItemData.fLinks) {
             if (link.getEntry() == trace && link.getTime() == selectedTime) {
                 selectItem(link.getDestinationEntry(), false);
                 if (link.getDuration() != 0) {
-                    fTimeProvider.setSelectedTimeNotify(link.getTime() + link.getDuration(), true);
+                    if (extend) {
+                        fTimeProvider.setSelectionRangeNotify(fTimeProvider.getSelectionBegin(), link.getTime() + link.getDuration());
+                    } else {
+                        fTimeProvider.setSelectedTimeNotify(link.getTime() + link.getDuration(), true);
+                    }
                     // Notify if visible time window has been adjusted
                     fTimeProvider.setStartFinishTimeNotify(fTimeProvider.getTime0(), fTimeProvider.getTime1());
                 }
                 fireSelectionChanged();
+                updateStatusLine(STATUS_WITHOUT_CURSOR_TIME);
                 return;
             }
         }
-        selectNextEvent();
+        selectNextEvent(extend);
     }
 
     /**
      * Follow the arrow backward
+     *
+     * @param extend
+     *            true to extend selection range, false for single selection
+     * @since 1.0
      */
-    public void followArrowBwd() {
+    public void followArrowBwd(boolean extend) {
         ITimeGraphEntry trace = getSelectedTrace();
         if (trace == null) {
             return;
         }
-        long selectedTime = fTimeProvider.getSelectionBegin();
+        long selectedTime = fTimeProvider.getSelectionEnd();
         for (ILinkEvent link : fItemData.fLinks) {
             if (link.getDestinationEntry() == trace && link.getTime() + link.getDuration() == selectedTime) {
                 selectItem(link.getEntry(), false);
                 if (link.getDuration() != 0) {
-                    fTimeProvider.setSelectedTimeNotify(link.getTime(), true);
+                    if (extend) {
+                        fTimeProvider.setSelectionRangeNotify(fTimeProvider.getSelectionBegin(), link.getTime());
+                    } else {
+                        fTimeProvider.setSelectedTimeNotify(link.getTime(), true);
+                    }
                     // Notify if visible time window has been adjusted
                     fTimeProvider.setStartFinishTimeNotify(fTimeProvider.getTime0(), fTimeProvider.getTime1());
                 }
                 fireSelectionChanged();
+                updateStatusLine(STATUS_WITHOUT_CURSOR_TIME);
                 return;
             }
         }
-        selectPrevEvent();
+        selectPrevEvent(extend);
     }
 
     /**
@@ -1373,7 +1412,7 @@ public class TimeGraphControl extends TimeGraphBaseControl
         ITimeGraphEntry entry = item.fEntry;
         long time0 = timeProvider.getTime0();
         long time1 = timeProvider.getTime1();
-        long selectedTime = fTimeProvider.getSelectionBegin();
+        long selectedTime = fTimeProvider.getSelectionEnd();
 
         Rectangle nameRect = getNameRect(bounds, i, nameSpace);
         if (nameRect.y >= bounds.y + bounds.height) {
@@ -1807,10 +1846,12 @@ public class TimeGraphControl extends TimeGraphBaseControl
             } else if (idx > 0) {
                 idx--;
             }
-        } else if (SWT.ARROW_LEFT == e.keyCode) {
-            selectPrevEvent();
-        } else if (SWT.ARROW_RIGHT == e.keyCode) {
-            selectNextEvent();
+        } else if (SWT.ARROW_LEFT == e.keyCode && fDragState == DRAG_NONE) {
+            boolean extend = (e.stateMask & SWT.SHIFT) != 0;
+            selectPrevEvent(extend);
+        } else if (SWT.ARROW_RIGHT == e.keyCode && fDragState == DRAG_NONE) {
+            boolean extend = (e.stateMask & SWT.SHIFT) != 0;
+            selectNextEvent(extend);
         } else if (SWT.PAGE_DOWN == e.keyCode) {
             int page = countPerPage();
             idx = getSelectedIndex();
@@ -1860,7 +1901,7 @@ public class TimeGraphControl extends TimeGraphBaseControl
     public void focusGained(FocusEvent e) {
         fIsInFocus = true;
         redraw();
-        updateStatusLine(NO_STATUS);
+        updateStatusLine(STATUS_WITHOUT_CURSOR_TIME);
     }
 
     @Override
@@ -1937,30 +1978,35 @@ public class TimeGraphControl extends TimeGraphBaseControl
         TimeFormat tf = tdp.getTimeFormat();
         Resolution res = Resolution.NANOSEC;
         StringBuilder message = new StringBuilder();
-        if (x >= 0 && fDragState == DRAG_NONE) {
-            long time = getTimeAtX(x);
-            if (time >= 0) {
-                if (tdp instanceof ITimeDataProviderConverter) {
-                    time = ((ITimeDataProviderConverter) tdp).convertTime(time);
-                }
-                long selectionBegin = tdp.getSelectionBegin();
-                long selectionEnd = tdp.getSelectionEnd();
-                message.append(NLS.bind("T: {0}{1}     T1: {2}{3}", //$NON-NLS-1$
-                        new Object[] {
-                                tf == TimeFormat.CALENDAR ? Utils.formatDate(time) + ' ' : "", //$NON-NLS-1$
-                                Utils.formatTime(time, tf, res),
-                                tf == TimeFormat.CALENDAR ? Utils.formatDate(selectionBegin) + ' ' : "", //$NON-NLS-1$
-                                Utils.formatTime(selectionBegin, tf, res)
-                        }));
-                if (selectionBegin != selectionEnd) {
-                    message.append(NLS.bind("     T2: {0}{1}     \u0394: {2}", //$NON-NLS-1$
+        if ((x >= 0 || x == STATUS_WITHOUT_CURSOR_TIME) && fDragState == DRAG_NONE) {
+            if (x != STATUS_WITHOUT_CURSOR_TIME) {
+                long time = getTimeAtX(x);
+                if (time >= 0) {
+                    if (tdp instanceof ITimeDataProviderConverter) {
+                        time = ((ITimeDataProviderConverter) tdp).convertTime(time);
+                    }
+                    message.append(NLS.bind("T: {0}{1}     ", //$NON-NLS-1$
                             new Object[] {
-                                    tf == TimeFormat.CALENDAR ? Utils.formatDate(selectionEnd) + ' ' : "", //$NON-NLS-1$
-                                    Utils.formatTime(selectionEnd, tf, res),
-                                    Utils.formatDelta(selectionEnd - selectionBegin, tf, res)
+                                    tf == TimeFormat.CALENDAR ? Utils.formatDate(time) + ' ' : "", //$NON-NLS-1$
+                                    Utils.formatTime(time, tf, res)
                             }));
                 }
             }
+            long selectionBegin = tdp.getSelectionBegin();
+            long selectionEnd = tdp.getSelectionEnd();
+            message.append(NLS.bind("T1: {0}{1}", //$NON-NLS-1$
+                    new Object[] {
+                            tf == TimeFormat.CALENDAR ? Utils.formatDate(selectionBegin) + ' ' : "", //$NON-NLS-1$
+                            Utils.formatTime(selectionBegin, tf, res)
+                    }));
+            if (selectionBegin != selectionEnd) {
+                message.append(NLS.bind("     T2: {0}{1}     \u0394: {2}", //$NON-NLS-1$
+                        new Object[] {
+                                tf == TimeFormat.CALENDAR ? Utils.formatDate(selectionEnd) + ' ' : "", //$NON-NLS-1$
+                                Utils.formatTime(selectionEnd, tf, res),
+                                Utils.formatDelta(selectionEnd - selectionBegin, tf, res)
+                        }));
+            }
         } else if (fDragState == DRAG_SELECTION || fDragState == DRAG_ZOOM) {
             long time0 = fDragBeginMarker ? getTimeAtX(fDragX0) : fDragTime0;
             long time = fDragBeginMarker ? fDragTime0 : getTimeAtX(fDragX);
@@ -2219,7 +2265,7 @@ public class TimeGraphControl extends TimeGraphBaseControl
             fMouseOverSplitLine = false;
             redraw();
         }
-        updateStatusLine(NO_STATUS);
+        updateStatusLine(STATUS_WITHOUT_CURSOR_TIME);
     }
 
     @Override
This page took 0.033469 seconds and 5 git commands to generate.