tmf: Support drag selection in histogram
authorPatrick Tasse <patrick.tasse@gmail.com>
Fri, 8 Nov 2013 17:43:56 +0000 (12:43 -0500)
committerPatrick Tasse <patrick.tasse@gmail.com>
Mon, 25 Nov 2013 20:51:42 +0000 (15:51 -0500)
- Left button drag makes a range selection in both histograms
- Middle button or Ctrl-left button are used to drag the window in full
trace histogram
- Middle-click or Shift-left-click on full trace histogram now centers
the window on the mouse position
- Selection is only propagated when the mouse button is released
- When moving the mouse only redraw instead of refreshing the whole
histogram
- Fix range selection start on Shift-click
- Limit selection range to visible time range
- Draw selection region background corrected when end time is before
start time
- Prevent mouse wheel zoom when dragging in progress

Change-Id: I393e0e72cd2f445be2bd75bb90090f27abc2a2da
Signed-off-by: Patrick Tasse <patrick.tasse@gmail.com>
Reviewed-on: https://git.eclipse.org/r/18308
Tested-by: Hudson CI
Reviewed-by: Bernd Hufmann <bernd.hufmann@ericsson.com>
IP-Clean: Bernd Hufmann <bernd.hufmann@ericsson.com>
Tested-by: Bernd Hufmann <bernd.hufmann@ericsson.com>
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
IP-Clean: Matthew Khouzam <matthew.khouzam@ericsson.com>
Tested-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Tested-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/histogram/FullTraceHistogram.java
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/histogram/Histogram.java
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/histogram/TimeRangeHistogram.java

index 052411bc38f4f42bf18ad25ab2401aa9db31dc88..92007628ca6584afc713d3b301444453b8f871f6 100644 (file)
@@ -16,7 +16,6 @@ package org.eclipse.linuxtools.tmf.ui.views.histogram;
 
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.MouseMoveListener;
 import org.eclipse.swt.events.PaintEvent;
 import org.eclipse.swt.graphics.Color;
 import org.eclipse.swt.graphics.GC;
@@ -32,7 +31,7 @@ import org.eclipse.swt.widgets.Display;
  * @version 1.1
  * @author Francois Chouinard
  */
-public class FullTraceHistogram extends Histogram implements MouseMoveListener {
+public class FullTraceHistogram extends Histogram {
 
     // ------------------------------------------------------------------------
     // Constants
@@ -64,7 +63,6 @@ public class FullTraceHistogram extends Histogram implements MouseMoveListener {
         super(view, parent);
         fZoom = new HistogramZoom(this, getStartTime(), getTimeLimit());
         addMouseWheelListener(fZoom);
-        fCanvas.addMouseMoveListener(this);
     }
 
     @Override
@@ -111,48 +109,49 @@ public class FullTraceHistogram extends Histogram implements MouseMoveListener {
         fDataModel.complete();
     }
 
-    @Override
-    public void updateTimeRange(long startTime, long endTime) {
-        ((HistogramView) fParentView).updateTimeRange(startTime, endTime);
-    }
-
     // ------------------------------------------------------------------------
     // MouseListener
     // ------------------------------------------------------------------------
 
-    private boolean fMouseDown;
     private int fStartPosition;
+    private boolean fMouseMoved;
 
     @Override
     public void mouseDown(MouseEvent event) {
-        fMouseDown = true;
-        fStartPosition = event.x;
+        if ((event.button == 2 || (event.button == 1 && (event.stateMask & SWT.MODIFIER_MASK) == SWT.CTRL)) &&
+                fDragState == DRAG_NONE && fDataModel.getNbEvents() != 0) {
+            fDragState = DRAG_RANGE;
+            fDragButton = event.button;
+            fStartPosition = event.x;
+            fMouseMoved = false;
+            return;
+        }
+        super.mouseDown(event);
     }
 
     @Override
     public void mouseUp(MouseEvent event) {
-        if (fMouseDown) {
-            fMouseDown = false;
-            // Check if mouse click without move; if so, just set the current event time
-            if (event.x == fStartPosition) {
-                super.mouseDown(event);
-                return;
+        if (fDragState == DRAG_RANGE && event.button == fDragButton) {
+            fDragState = DRAG_NONE;
+            fDragButton = 0;
+            if (!fMouseMoved) {
+                // if single click without move, center on the click
+                long startTime = getTimestamp(event.x) - fRangeDuration / 2;
+                fRangeStartTime = Math.max(getStartTime(), Math.min(getEndTime() - fRangeDuration, startTime));
             }
-
             ((HistogramView) fParentView).updateTimeRange(fRangeStartTime, fRangeStartTime + fRangeDuration);
-
+            return;
         }
+        super.mouseUp(event);
     }
 
-
     // ------------------------------------------------------------------------
     // MouseMoveListener
     // ------------------------------------------------------------------------
 
     @Override
     public void mouseMove(MouseEvent event) {
-
-        if (fMouseDown) {
+        if (fDragState == DRAG_RANGE) {
             int nbBuckets = event.x - fStartPosition;
             long delta = nbBuckets * fScaledData.fBucketDuration;
             long newStart = fZoom.getStartTime() + delta;
@@ -165,8 +164,11 @@ public class FullTraceHistogram extends Histogram implements MouseMoveListener {
                 newStart = newEnd - fZoom.getDuration();
             }
             fRangeStartTime = newStart;
-            fDataModel.complete();
+            fCanvas.redraw();
+            fMouseMoved = true;
+            return;
         }
+        super.mouseMove(event);
     }
 
     // ------------------------------------------------------------------------
index d2690bef07ba0d53a2f6136651b3653198999b56..afe31ff57eade0a22e95dc7bcee4cda3ec281ead 100644 (file)
@@ -32,6 +32,7 @@ import org.eclipse.swt.events.KeyEvent;
 import org.eclipse.swt.events.KeyListener;
 import org.eclipse.swt.events.MouseEvent;
 import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.MouseMoveListener;
 import org.eclipse.swt.events.MouseTrackListener;
 import org.eclipse.swt.events.MouseWheelListener;
 import org.eclipse.swt.events.PaintEvent;
@@ -87,7 +88,7 @@ import org.eclipse.swt.widgets.Text;
  * @version 1.1
  * @author Francois Chouinard
  */
-public abstract class Histogram implements ControlListener, PaintListener, KeyListener, MouseListener, MouseTrackListener, IHistogramModelListener {
+public abstract class Histogram implements ControlListener, PaintListener, KeyListener, MouseListener, MouseMoveListener, MouseTrackListener, IHistogramModelListener {
 
     // ------------------------------------------------------------------------
     // Constants
@@ -102,6 +103,23 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
     private final Color fLostEventColor = new Color(Display.getCurrent(), 208, 62, 120);
     private final Color fFillColor = Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
 
+    // Drag states
+    /**
+     * No drag in progress
+     * @since 2.2
+     */
+    protected final int DRAG_NONE = 0;
+    /**
+     * Drag the selection
+     * @since 2.2
+     */
+    protected final int DRAG_SELECTION = 1;
+    /**
+     * Drag the time range
+     * @since 2.2
+     */
+    protected final int DRAG_RANGE = 2;
+
     // ------------------------------------------------------------------------
     // Attributes
     // ------------------------------------------------------------------------
@@ -150,6 +168,21 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
      */
     private long fSelectionEnd = 0L;
 
+    /**
+     * The drag state
+     * @see #DRAG_NONE
+     * @see #DRAG_SELECTION
+     * @see #DRAG_RANGE
+     * @since 2.2
+     */
+    protected int fDragState = DRAG_NONE;
+
+    /**
+     * The button that started a mouse drag, or 0 if no drag in progress
+     * @since 2.2
+     */
+    protected int fDragButton = 0;
+
     // ------------------------------------------------------------------------
     // Construction
     // ------------------------------------------------------------------------
@@ -173,6 +206,7 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
         fCanvas.addKeyListener(this);
         fCanvas.addMouseListener(this);
         fCanvas.addMouseTrackListener(this);
+        fCanvas.addMouseMoveListener(this);
 
         TmfSignalManager.register(this);
     }
@@ -353,7 +387,11 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
      * @param startTime A start time
      * @param endTime A end time.
      */
-    public abstract void updateTimeRange(long startTime, long endTime);
+    public void updateTimeRange(long startTime, long endTime) {
+        if (fDragState == DRAG_NONE) {
+            ((HistogramView) fParentView).updateTimeRange(startTime, endTime);
+        }
+    }
 
     /**
      * Clear the histogram and reset the data
@@ -547,8 +585,6 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
     // ------------------------------------------------------------------------
 
     private void updateSelectionTime() {
-        fSelectionBegin = Math.min(fSelectionBegin, fDataModel.getEndTime());
-        fSelectionEnd = Math.min(fSelectionEnd, fDataModel.getEndTime());
         ((HistogramView) fParentView).updateSelectionTime(fSelectionBegin, fSelectionEnd);
     }
 
@@ -639,14 +675,6 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
                 }
             }
 
-            // Add a dashed line as a delimiter
-            int delimiterIndex = (int) ((getDataModel().getEndTime() - scaledData.getFirstBucketTime()) / scaledData.fBucketDuration) + 1;
-            drawDelimiter(imageGC, fLastEventColor, height, delimiterIndex);
-
-            // Fill the area to the right of delimiter with background color
-            imageGC.setBackground(fFillColor);
-            imageGC.fillRectangle(delimiterIndex + 1, 0, width - (delimiterIndex + 1), height);
-
             // Draw the selection bars
             int alpha = imageGC.getAlpha();
             imageGC.setAlpha(100);
@@ -660,10 +688,23 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
             if (endBucket >= 0 && endBucket < limit && endBucket != beginBucket) {
                 imageGC.drawLine(endBucket, 0, endBucket, height);
             }
-            if (endBucket - beginBucket > 1) {
-                imageGC.fillRectangle(beginBucket + 1, 0, endBucket - beginBucket - 1, height);
+            if (Math.abs(endBucket - beginBucket) > 1) {
+                if (endBucket > beginBucket) {
+                    imageGC.fillRectangle(beginBucket + 1, 0, endBucket - beginBucket - 1, height);
+                } else {
+                    imageGC.fillRectangle(endBucket + 1, 0, beginBucket - endBucket - 1, height);
+                }
             }
             imageGC.setAlpha(alpha);
+
+            // Add a dashed line as a delimiter
+            int delimiterIndex = (int) ((getDataModel().getEndTime() - scaledData.getFirstBucketTime()) / scaledData.fBucketDuration) + 1;
+            drawDelimiter(imageGC, fLastEventColor, height, delimiterIndex);
+
+            // Fill the area to the right of delimiter with background color
+            imageGC.setBackground(fFillColor);
+            imageGC.fillRectangle(delimiterIndex + 1, 0, width - (delimiterIndex + 1), height);
+
         } catch (final Exception e) {
             // Do nothing
         }
@@ -702,35 +743,49 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
 
     @Override
     public void mouseDown(final MouseEvent event) {
-        if (fDataModel.getNbEvents() > 0 && fScaledData.fLastBucket >= event.x) {
-            if ((event.stateMask & SWT.MODIFIER_MASK) == 0) {
-                fScaledData.fSelectionBeginBucket = event.x;
-                fScaledData.fSelectionEndBucket = event.x;
-                fSelectionBegin = getTimestamp(event.x);
-                fSelectionEnd = fSelectionBegin;
-            } else if ((event.stateMask & SWT.MODIFIER_MASK) == SWT.SHIFT) {
-                if (fSelectionBegin == fSelectionEnd) {
-                    if (event.x < fScaledData.fSelectionBeginBucket) {
-                        fScaledData.fSelectionBeginBucket = event.x;
-                        fSelectionBegin = getTimestamp(event.x);
-                    } else {
-                        fScaledData.fSelectionEndBucket = event.x;
-                        fSelectionEnd = getTimestamp(event.x);
-                    }
-                } else if (Math.abs(event.x - fScaledData.fSelectionBeginBucket) <= Math.abs(event.x - fScaledData.fSelectionEndBucket)) {
-                    fScaledData.fSelectionBeginBucket = event.x;
-                    fSelectionBegin = getTimestamp(event.x);
-                } else {
-                    fScaledData.fSelectionEndBucket = event.x;
-                    fSelectionEnd = getTimestamp(event.x);
+        if (event.button == 1 && fDragState == DRAG_NONE && fDataModel.getNbEvents() != 0) {
+            fDragState = DRAG_SELECTION;
+            fDragButton = event.button;
+            if ((event.stateMask & SWT.MODIFIER_MASK) == SWT.SHIFT) {
+                if (Math.abs(event.x - fScaledData.fSelectionBeginBucket) < Math.abs(event.x - fScaledData.fSelectionEndBucket)) {
+                    fScaledData.fSelectionBeginBucket = fScaledData.fSelectionEndBucket;
+                    fSelectionBegin = fSelectionEnd;
                 }
+                fSelectionEnd = Math.min(getTimestamp(event.x), getEndTime());
+                fScaledData.fSelectionEndBucket = (int) ((fSelectionEnd - fScaledData.fFirstBucketTime) / fScaledData.fBucketDuration);
+            } else {
+                fSelectionBegin = Math.min(getTimestamp(event.x), getEndTime());
+                fScaledData.fSelectionBeginBucket = (int) ((fSelectionBegin - fScaledData.fFirstBucketTime) / fScaledData.fBucketDuration);
+                fSelectionEnd = fSelectionBegin;
+                fScaledData.fSelectionEndBucket = fScaledData.fSelectionBeginBucket;
             }
-            updateSelectionTime();
+            fCanvas.redraw();
         }
     }
 
     @Override
     public void mouseUp(final MouseEvent event) {
+        if (fDragState == DRAG_SELECTION && event.button == fDragButton) {
+            fDragState = DRAG_NONE;
+            fDragButton = 0;
+            updateSelectionTime();
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // MouseMoveListener
+    // ------------------------------------------------------------------------
+
+    /**
+     * @since 2.2
+     */
+    @Override
+    public void mouseMove(MouseEvent event) {
+        if (fDragState == DRAG_SELECTION && fDataModel.getNbEvents() > 0) {
+            fSelectionEnd = Math.max(getStartTime(), Math.min(getEndTime(), getTimestamp(event.x)));
+            fScaledData.fSelectionEndBucket = (int) ((fSelectionEnd - fScaledData.fFirstBucketTime) / fScaledData.fBucketDuration);
+            fCanvas.redraw();
+        }
     }
 
     // ------------------------------------------------------------------------
index 58b784c934e511cbd0328576b39e6e9aa1dcaf26..4a14b25e67b4a20c41350c035a78de94cb8f58fc 100644 (file)
@@ -54,11 +54,6 @@ public class TimeRangeHistogram extends Histogram {
     // Operations
     // ------------------------------------------------------------------------
 
-    @Override
-    public void updateTimeRange(long startTime, long endTime) {
-        ((HistogramView) fParentView).updateTimeRange(startTime, endTime);
-    }
-
     @Override
     public synchronized void clear() {
         if (fZoom != null) {
This page took 0.031266 seconds and 5 git commands to generate.