From 79d60771ba15494d81fa09a11b17a075505a63ff Mon Sep 17 00:00:00 2001 From: Patrick Tasse Date: Tue, 12 Nov 2013 13:51:37 -0500 Subject: [PATCH] tmf: Support drag zoom in histogram - Right button drag is used to select a new zoom window in both histograms - Shift-right button drag or click is used to modify the zoom window in full range histogram - Zoom is cancelled if the selected range duration is zero - New time range is propagated when the mouse button is released - Move draw time range window method to base class Change-Id: If46c1edd5c8f67a1b48ebc2ebbe2527613ba927c Signed-off-by: Patrick Tasse Reviewed-on: https://git.eclipse.org/r/18310 Tested-by: Hudson CI Reviewed-by: Matthew Khouzam IP-Clean: Matthew Khouzam Tested-by: Matthew Khouzam Reviewed-by: Etienne Bergeron Tested-by: Marc-Andre Laperle --- .../views/histogram/FullTraceHistogram.java | 96 +++++++++---------- .../tmf/ui/views/histogram/Histogram.java | 53 ++++++++++ .../views/histogram/TimeRangeHistogram.java | 72 ++++++++++++-- 3 files changed, 161 insertions(+), 60 deletions(-) diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/histogram/FullTraceHistogram.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/histogram/FullTraceHistogram.java index 92007628ca..12d7a29a5c 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/histogram/FullTraceHistogram.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/histogram/FullTraceHistogram.java @@ -17,11 +17,9 @@ package org.eclipse.linuxtools.tmf.ui.views.histogram; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.PaintEvent; -import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; /** * A histogram widget that displays the event distribution of a whole trace. @@ -33,13 +31,6 @@ import org.eclipse.swt.widgets.Display; */ public class FullTraceHistogram extends Histogram { - // ------------------------------------------------------------------------ - // Constants - // ------------------------------------------------------------------------ - - // Histogram colors - private final Color fTimeRangeColor = new Color(Display.getCurrent(), 255, 128, 0); - // ------------------------------------------------------------------------ // Attributes // ------------------------------------------------------------------------ @@ -67,7 +58,6 @@ public class FullTraceHistogram extends Histogram { @Override public void dispose() { - fTimeRangeColor.dispose(); super.dispose(); } @@ -118,13 +108,28 @@ public class FullTraceHistogram extends Histogram { @Override public void mouseDown(MouseEvent event) { - 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; + if (fDragState == DRAG_NONE && fDataModel.getNbEvents() != 0) { + if (event.button == 2 || (event.button == 1 && (event.stateMask & SWT.MODIFIER_MASK) == SWT.CTRL)) { + fDragState = DRAG_RANGE; + fDragButton = event.button; + fStartPosition = event.x; + fMouseMoved = false; + return; + } else if (event.button == 3) { + fDragState = DRAG_ZOOM; + fDragButton = event.button; + long time = Math.min(getTimestamp(event.x), getEndTime()); + if ((event.stateMask & SWT.MODIFIER_MASK) == SWT.SHIFT) { + if (time < fRangeStartTime + fRangeDuration / 2) { + fRangeStartTime = fRangeStartTime + fRangeDuration; + } + } else { + fRangeStartTime = time; + } + fRangeDuration = time - fRangeStartTime; + fCanvas.redraw(); + return; + } } super.mouseDown(event); } @@ -141,6 +146,21 @@ public class FullTraceHistogram extends Histogram { } ((HistogramView) fParentView).updateTimeRange(fRangeStartTime, fRangeStartTime + fRangeDuration); return; + } else if (fDragState == DRAG_ZOOM && event.button == fDragButton) { + fDragState = DRAG_NONE; + fDragButton = 0; + if (fRangeDuration < 0) { + fRangeStartTime = fRangeStartTime + fRangeDuration; + fRangeDuration = -fRangeDuration; + } + if (fRangeDuration > 0) { + ((HistogramView) fParentView).updateTimeRange(fRangeStartTime, fRangeStartTime + fRangeDuration); + } else { + fRangeStartTime = fZoom.getStartTime(); + fRangeDuration = fZoom.getDuration(); + fCanvas.redraw(); + } + return; } super.mouseUp(event); } @@ -167,6 +187,11 @@ public class FullTraceHistogram extends Histogram { fCanvas.redraw(); fMouseMoved = true; return; + } else if (fDragState == DRAG_ZOOM) { + long endTime = Math.max(getStartTime(), Math.min(getEndTime(), getTimestamp(event.x))); + fRangeDuration = endTime - fRangeStartTime; + fCanvas.redraw(); + return; } super.mouseMove(event); } @@ -185,8 +210,8 @@ public class FullTraceHistogram extends Histogram { Image rangeRectangleImage = new Image(image.getDevice(), image, SWT.IMAGE_COPY); GC rangeWindowGC = new GC(rangeRectangleImage); - if ((fScaledData != null) && (fRangeStartTime != 0)) { - drawTimeRangeWindow(rangeWindowGC); + if ((fScaledData != null) && (fRangeDuration != 0 || fDragState == DRAG_ZOOM)) { + drawTimeRangeWindow(rangeWindowGC, fRangeStartTime, fRangeDuration); } // Draws the buffer image onto the canvas. @@ -196,39 +221,6 @@ public class FullTraceHistogram extends Histogram { rangeRectangleImage.dispose(); } - private void drawTimeRangeWindow(GC imageGC) { - - // Map times to histogram coordinates - long bucketSpan = Math.max(fScaledData.fBucketDuration, 1); - int rangeWidth = (int) (fRangeDuration / bucketSpan); - - int left = (int) ((fRangeStartTime - fDataModel.getFirstBucketTime()) / bucketSpan); - int right = left + rangeWidth; - int center = (left + right) / 2; - int height = fCanvas.getSize().y; - - // Draw the selection window - imageGC.setForeground(fTimeRangeColor); - imageGC.setLineWidth(1); - imageGC.setLineStyle(SWT.LINE_SOLID); - imageGC.drawRoundRectangle(left, 0, rangeWidth, height - 1, 15, 15); - - // Fill the selection window - imageGC.setBackground(fTimeRangeColor); - imageGC.setAlpha(35); - imageGC.fillRoundRectangle(left + 1, 1, rangeWidth - 1, height - 2, 15, 15); - imageGC.setAlpha(255); - - // Draw the cross hair - imageGC.setForeground(fTimeRangeColor); - imageGC.setLineWidth(1); - imageGC.setLineStyle(SWT.LINE_SOLID); - - int chHalfWidth = ((rangeWidth < 60) ? (rangeWidth * 2) / 3 : 40) / 2; - imageGC.drawLine(center - chHalfWidth, height / 2, center + chHalfWidth, height / 2); - imageGC.drawLine(center, (height / 2) - chHalfWidth, center, (height / 2) + chHalfWidth); - } - /** * Get the histogram zoom * @return the histogram zoom diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/histogram/Histogram.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/histogram/Histogram.java index d31491bfb1..341d7052ca 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/histogram/Histogram.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/histogram/Histogram.java @@ -102,6 +102,7 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi private final Color fHistoBarColor = new Color(Display.getDefault(), 74, 112, 139); private final Color fLostEventColor = new Color(Display.getCurrent(), 208, 62, 120); private final Color fFillColor = Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND); + private final Color fTimeRangeColor = new Color(Display.getCurrent(), 255, 128, 0); // Drag states /** @@ -119,6 +120,11 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi * @since 2.2 */ protected final int DRAG_RANGE = 2; + /** + * Drag the zoom range + * @since 2.2 + */ + protected final int DRAG_ZOOM = 3; // ------------------------------------------------------------------------ // Attributes @@ -173,6 +179,7 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi * @see #DRAG_NONE * @see #DRAG_SELECTION * @see #DRAG_RANGE + * @see #DRAG_ZOOM * @since 2.2 */ protected int fDragState = DRAG_NONE; @@ -224,6 +231,7 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi fHistoBarColor.dispose(); fLastEventColor.dispose(); + fTimeRangeColor.dispose(); fDataModel.removeHistogramListener(this); } @@ -737,6 +745,51 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi imageGC.fillRectangle(index, 3 * dash, 1, height - 3 * dash); } + /** + * Draw a time range window + * + * @param imageGC + * the GC + * @param rangeStartTime + * the range start time + * @param rangeDuration + * the range duration + * @since 2.2 + */ + protected void drawTimeRangeWindow(GC imageGC, long rangeStartTime, long rangeDuration) { + + // Map times to histogram coordinates + long bucketSpan = Math.max(fScaledData.fBucketDuration, 1); + long startTime = Math.min(rangeStartTime, rangeStartTime + rangeDuration); + int rangeWidth = (int) (Math.abs(rangeDuration) / bucketSpan); + + int left = (int) ((startTime - fDataModel.getFirstBucketTime()) / bucketSpan); + int right = left + rangeWidth; + int center = (left + right) / 2; + int height = fCanvas.getSize().y; + + // Draw the selection window + imageGC.setForeground(fTimeRangeColor); + imageGC.setLineWidth(1); + imageGC.setLineStyle(SWT.LINE_SOLID); + imageGC.drawRoundRectangle(left, 0, rangeWidth, height - 1, 15, 15); + + // Fill the selection window + imageGC.setBackground(fTimeRangeColor); + imageGC.setAlpha(35); + imageGC.fillRoundRectangle(left + 1, 1, rangeWidth - 1, height - 2, 15, 15); + imageGC.setAlpha(255); + + // Draw the cross hair + imageGC.setForeground(fTimeRangeColor); + imageGC.setLineWidth(1); + imageGC.setLineStyle(SWT.LINE_SOLID); + + int chHalfWidth = ((rangeWidth < 60) ? (rangeWidth * 2) / 3 : 40) / 2; + imageGC.drawLine(center - chHalfWidth, height / 2, center + chHalfWidth, height / 2); + imageGC.drawLine(center, (height / 2) - chHalfWidth, center, (height / 2) + chHalfWidth); + } + // ------------------------------------------------------------------------ // KeyListener // ------------------------------------------------------------------------ diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/histogram/TimeRangeHistogram.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/histogram/TimeRangeHistogram.java index ea162ce79f..e5d5b22b4c 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/histogram/TimeRangeHistogram.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/histogram/TimeRangeHistogram.java @@ -17,6 +17,9 @@ package org.eclipse.linuxtools.tmf.ui.views.histogram; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; /** @@ -111,14 +114,22 @@ public class TimeRangeHistogram extends Histogram { @Override public void mouseDown(MouseEvent event) { - 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; - fMaxOffset = (int) ((fRangeStartTime - fFullRangeStartTime) / fScaledData.fBucketDuration); - fMinOffset = (int) ((fRangeStartTime + fRangeDuration - fFullRangeEndTime) / fScaledData.fBucketDuration); - return; + if (fDragState == DRAG_NONE && fDataModel.getNbEvents() != 0) { + if (event.button == 2 || (event.button == 1 && (event.stateMask & SWT.MODIFIER_MASK) == SWT.CTRL)) { + fDragState = DRAG_RANGE; + fDragButton = event.button; + fStartPosition = event.x; + fMaxOffset = (int) ((fRangeStartTime - fFullRangeStartTime) / fScaledData.fBucketDuration); + fMinOffset = (int) ((fRangeStartTime + fRangeDuration - fFullRangeEndTime) / fScaledData.fBucketDuration); + return; + } else if (event.button == 3) { + fDragState = DRAG_ZOOM; + fDragButton = event.button; + fRangeStartTime = Math.min(getTimestamp(event.x), getEndTime()); + fRangeDuration = 0; + fCanvas.redraw(); + return; + } } super.mouseDown(event); } @@ -137,6 +148,21 @@ public class TimeRangeHistogram extends Histogram { setOffset(0); } return; + } else if (fDragState == DRAG_ZOOM && event.button == fDragButton) { + fDragState = DRAG_NONE; + fDragButton = 0; + if (fRangeDuration < 0) { + fRangeStartTime = fRangeStartTime + fRangeDuration; + fRangeDuration = -fRangeDuration; + } + if (fRangeDuration > 0) { + ((HistogramView) fParentView).updateTimeRange(fRangeStartTime, fRangeStartTime + fRangeDuration); + } else { + fRangeStartTime = fZoom.getStartTime(); + fRangeDuration = fZoom.getDuration(); + fCanvas.redraw(); + } + return; } super.mouseUp(event); } @@ -152,8 +178,38 @@ public class TimeRangeHistogram extends Histogram { setOffset(offset); fCanvas.redraw(); return; + } else if (fDragState == DRAG_ZOOM) { + long endTime = Math.max(getStartTime(), Math.min(getEndTime(), getTimestamp(event.x))); + fRangeDuration = endTime - fRangeStartTime; + fCanvas.redraw(); + return; } super.mouseMove(event); } + // ------------------------------------------------------------------------ + // PaintListener + // ------------------------------------------------------------------------ + + @Override + public void paintControl(PaintEvent event) { + super.paintControl(event); + + if (fDragState == DRAG_ZOOM) { + Image image = (Image) fCanvas.getData(IMAGE_KEY); + assert image != null; + + Image rangeRectangleImage = new Image(image.getDevice(), image, SWT.IMAGE_COPY); + GC rangeWindowGC = new GC(rangeRectangleImage); + + drawTimeRangeWindow(rangeWindowGC, fRangeStartTime, fRangeDuration); + + // Draws the buffer image onto the canvas. + event.gc.drawImage(rangeRectangleImage, 0, 0); + + rangeWindowGC.dispose(); + rangeRectangleImage.dispose(); + } + } + } -- 2.34.1