blob: 1de231f6ac6740ff3dd7f12731fd767b232b6075 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 2014 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Francois Chouinard - Initial API and implementation
* Bernd Hufmann - Changed to updated histogram data model
* Patrick Tasse - Update for mouse wheel zoom
*******************************************************************************/
package org.eclipse.tracecompass.tmf.ui.views.histogram;
import java.util.Objects;
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;
/**
* A histogram widget that displays the event distribution of a whole trace.
* <p>
* It also features a selected range window that can be dragged and zoomed.
*
* @version 1.1
* @author Francois Chouinard
*/
public class FullTraceHistogram extends Histogram {
// ------------------------------------------------------------------------
// Attributes
// ------------------------------------------------------------------------
private final HistogramZoom fZoom;
private long fRangeStartTime = 0L;
private long fRangeDuration;
// ------------------------------------------------------------------------
// Construction
// ------------------------------------------------------------------------
/**
* Full Constructor
*
* @param view A reference to the parent histogram view
* @param parent A reference to the parent composite
*/
public FullTraceHistogram(HistogramView view, Composite parent) {
super(view, parent);
fZoom = new HistogramZoom(this, getStartTime(), getTimeLimit());
}
@Override
public void dispose() {
super.dispose();
}
// ------------------------------------------------------------------------
// Operations
// ------------------------------------------------------------------------
@Override
public void clear() {
fRangeStartTime = 0L;
fRangeDuration = 0L;
if (fZoom != null) {
fZoom.setFullRange(0L, 0L);
fZoom.setNewRange(0L, 0L);
}
super.clear();
}
/**
* Sets the time range of the full histogram.
*
* @param startTime A start time
* @param endTime A end time
*/
public void setFullRange(long startTime, long endTime) {
fZoom.setFullRange(startTime, endTime);
fZoom.setNewRange(fRangeStartTime, fRangeDuration);
}
/**
* Sets the selected time range.
*
* @param startTime The histogram start time
* @param duration The histogram duration
*/
public void setTimeRange(long startTime, long duration) {
fRangeStartTime = startTime;
fRangeDuration = duration;
fZoom.setNewRange(fRangeStartTime, fRangeDuration);
fDataModel.complete();
}
// ------------------------------------------------------------------------
// MouseListener
// ------------------------------------------------------------------------
private int fStartDelta;
private boolean fMouseMoved;
@Override
public void mouseDown(MouseEvent event) {
if (fScaledData != null && fDragState == DRAG_NONE && fDataModel.getStartTime() < fDataModel.getEndTime()) {
if (event.button == 2 || (event.button == 1 && (event.stateMask & SWT.MODIFIER_MASK) == SWT.CTRL)) {
fDragState = DRAG_RANGE;
fDragButton = event.button;
int center = (int) (((fRangeStartTime + fRangeDuration / 2) - fScaledData.fFirstBucketTime) / fScaledData.fBucketDuration);
fStartDelta = center - 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);
}
@Override
public void mouseUp(MouseEvent event) {
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;
} 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);
}
// ------------------------------------------------------------------------
// MouseMoveListener
// ------------------------------------------------------------------------
@Override
public void mouseMove(MouseEvent event) {
if (fDragState == DRAG_RANGE) {
int center = event.x + fStartDelta;
long newStart = getTimestamp(center) - fRangeDuration / 2;
fRangeStartTime = Math.max(getStartTime(), Math.min(getEndTime() - fRangeDuration, newStart));
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);
}
// ------------------------------------------------------------------------
// PaintListener
// ------------------------------------------------------------------------
@Override
public void paintControl(PaintEvent event) {
super.paintControl(event);
Image image = Objects.requireNonNull((Image) fCanvas.getData(IMAGE_KEY));
Image rangeRectangleImage = new Image(image.getDevice(), image, SWT.IMAGE_COPY);
GC rangeWindowGC = new GC(rangeRectangleImage);
if ((fScaledData != null) && (fRangeDuration != 0 || fDragState == DRAG_ZOOM)) {
drawTimeRangeWindow(rangeWindowGC, fRangeStartTime, fRangeDuration);
}
// Draws the buffer image onto the canvas.
event.gc.drawImage(rangeRectangleImage, 0, 0);
rangeWindowGC.dispose();
rangeRectangleImage.dispose();
}
/**
* Get the histogram zoom
* @return the histogram zoom
*/
public HistogramZoom getZoom() {
return fZoom;
}
}