You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
650 lines
16 KiB
650 lines
16 KiB
15 years ago
|
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
|
||
|
* Qwt Widget Library
|
||
|
* Copyright (C) 1997 Josef Wilgen
|
||
|
* Copyright (C) 2002 Uwe Rathmann
|
||
|
*
|
||
|
* This library is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the Qwt License, Version 1.0
|
||
|
*****************************************************************************/
|
||
|
|
||
|
// vim: expandtab
|
||
|
|
||
|
#include <math.h>
|
||
|
#include "qwt_plot.h"
|
||
|
#include "qwt_plot_canvas.h"
|
||
|
#include "qwt_plot_zoomer.h"
|
||
|
#include "qwt_scale_div.h"
|
||
|
#if QT_VERSION < 0x040000
|
||
|
typedef QValueStack<QwtDoubleRect> QwtZoomStack;
|
||
|
#else
|
||
|
typedef QStack<QwtDoubleRect> QwtZoomStack;
|
||
|
#endif
|
||
|
|
||
|
class QwtPlotZoomer::PrivateData
|
||
|
{
|
||
|
public:
|
||
|
uint zoomRectIndex;
|
||
|
QwtZoomStack zoomStack;
|
||
|
|
||
|
int maxStackDepth;
|
||
|
};
|
||
|
|
||
|
/*!
|
||
|
\brief Create a zoomer for a plot canvas.
|
||
|
|
||
|
The zoomer is set to those x- and y-axis of the parent plot of the
|
||
|
canvas that are enabled. If both or no x-axis are enabled, the picker
|
||
|
is set to QwtPlot::xBottom. If both or no y-axis are
|
||
|
enabled, it is set to QwtPlot::yLeft.
|
||
|
|
||
14 years ago
|
The selectionFlags() are set to
|
||
15 years ago
|
QwtPicker::RectSelection & QwtPicker::ClickSelection, the
|
||
|
tracker mode to QwtPicker::ActiveOnly.
|
||
|
|
||
|
\param canvas Plot canvas to observe, also the parent object
|
||
|
\param doReplot Call replot for the attached plot before initializing
|
||
14 years ago
|
the zoomer with its scales. This might be necessary,
|
||
15 years ago
|
when the plot is in a state with pending scale changes.
|
||
|
|
||
|
\sa QwtPlot::autoReplot(), QwtPlot::replot(), setZoomBase()
|
||
|
*/
|
||
|
QwtPlotZoomer::QwtPlotZoomer(QwtPlotCanvas *canvas, bool doReplot):
|
||
|
QwtPlotPicker(canvas)
|
||
|
{
|
||
|
if ( canvas )
|
||
|
init(RectSelection & ClickSelection, ActiveOnly, doReplot);
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\brief Create a zoomer for a plot canvas.
|
||
|
|
||
14 years ago
|
The selectionFlags() are set to
|
||
15 years ago
|
QwtPicker::RectSelection & QwtPicker::ClickSelection, the
|
||
14 years ago
|
tracker mode to QwtPicker::ActiveOnly.
|
||
15 years ago
|
|
||
|
\param xAxis X axis of the zoomer
|
||
|
\param yAxis Y axis of the zoomer
|
||
|
\param canvas Plot canvas to observe, also the parent object
|
||
|
\param doReplot Call replot for the attached plot before initializing
|
||
14 years ago
|
the zoomer with its scales. This might be necessary,
|
||
15 years ago
|
when the plot is in a state with pending scale changes.
|
||
|
|
||
|
\sa QwtPlot::autoReplot(), QwtPlot::replot(), setZoomBase()
|
||
|
*/
|
||
|
|
||
|
QwtPlotZoomer::QwtPlotZoomer(int xAxis, int yAxis,
|
||
14 years ago
|
QwtPlotCanvas *canvas, bool doReplot):
|
||
15 years ago
|
QwtPlotPicker(xAxis, yAxis, canvas)
|
||
|
{
|
||
|
if ( canvas )
|
||
|
init(RectSelection & ClickSelection, ActiveOnly, doReplot);
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
Create a zoomer for a plot canvas.
|
||
|
|
||
|
\param xAxis X axis of the zoomer
|
||
|
\param yAxis Y axis of the zoomer
|
||
|
\param selectionFlags Or'd value of QwtPicker::RectSelectionType and
|
||
14 years ago
|
QwtPicker::SelectionMode.
|
||
15 years ago
|
QwtPicker::RectSelection will be auto added.
|
||
|
\param trackerMode Tracker mode
|
||
|
\param canvas Plot canvas to observe, also the parent object
|
||
|
\param doReplot Call replot for the attached plot before initializing
|
||
14 years ago
|
the zoomer with its scales. This might be necessary,
|
||
15 years ago
|
when the plot is in a state with pending scale changes.
|
||
|
|
||
|
\sa QwtPicker, QwtPicker::setSelectionFlags(), QwtPicker::setRubberBand(),
|
||
|
QwtPicker::setTrackerMode
|
||
|
|
||
|
\sa QwtPlot::autoReplot(), QwtPlot::replot(), setZoomBase()
|
||
|
*/
|
||
|
|
||
|
QwtPlotZoomer::QwtPlotZoomer(int xAxis, int yAxis, int selectionFlags,
|
||
14 years ago
|
DisplayMode trackerMode, QwtPlotCanvas *canvas, bool doReplot):
|
||
15 years ago
|
QwtPlotPicker(xAxis, yAxis, canvas)
|
||
|
{
|
||
|
if ( canvas )
|
||
|
init(selectionFlags, trackerMode, doReplot);
|
||
|
}
|
||
|
|
||
|
//! Init the zoomer, used by the constructors
|
||
14 years ago
|
void QwtPlotZoomer::init(int selectionFlags,
|
||
|
DisplayMode trackerMode, bool doReplot)
|
||
15 years ago
|
{
|
||
|
d_data = new PrivateData;
|
||
|
|
||
|
d_data->maxStackDepth = -1;
|
||
|
|
||
|
setSelectionFlags(selectionFlags);
|
||
|
setTrackerMode(trackerMode);
|
||
|
setRubberBand(RectRubberBand);
|
||
|
|
||
|
if ( doReplot && plot() )
|
||
|
plot()->replot();
|
||
|
|
||
|
setZoomBase(scaleRect());
|
||
|
}
|
||
|
|
||
|
QwtPlotZoomer::~QwtPlotZoomer()
|
||
|
{
|
||
|
delete d_data;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\brief Limit the number of recursive zoom operations to depth.
|
||
|
|
||
|
A value of -1 set the depth to unlimited, 0 disables zooming.
|
||
|
If the current zoom rectangle is below depth, the plot is unzoomed.
|
||
|
|
||
|
\param depth Maximum for the stack depth
|
||
|
\sa maxStackDepth()
|
||
|
\note depth doesn't include the zoom base, so zoomStack().count() might be
|
||
|
maxStackDepth() + 1.
|
||
|
*/
|
||
|
void QwtPlotZoomer::setMaxStackDepth(int depth)
|
||
|
{
|
||
|
d_data->maxStackDepth = depth;
|
||
|
|
||
14 years ago
|
if ( depth >= 0 ) {
|
||
15 years ago
|
// unzoom if the current depth is below d_data->maxStackDepth
|
||
|
|
||
14 years ago
|
const int zoomOut =
|
||
15 years ago
|
int(d_data->zoomStack.count()) - 1 - depth; // -1 for the zoom base
|
||
|
|
||
14 years ago
|
if ( zoomOut > 0 ) {
|
||
15 years ago
|
zoom(-zoomOut);
|
||
14 years ago
|
for ( int i = int(d_data->zoomStack.count()) - 1;
|
||
|
i > int(d_data->zoomRectIndex); i-- ) {
|
||
15 years ago
|
(void)d_data->zoomStack.pop(); // remove trailing rects
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\return Maximal depth of the zoom stack.
|
||
|
\sa setMaxStackDepth()
|
||
|
*/
|
||
|
int QwtPlotZoomer::maxStackDepth() const
|
||
|
{
|
||
|
return d_data->maxStackDepth;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
Return the zoom stack. zoomStack()[0] is the zoom base,
|
||
|
zoomStack()[1] the first zoomed rectangle.
|
||
|
|
||
|
\sa setZoomStack(), zoomRectIndex()
|
||
|
*/
|
||
|
const QwtZoomStack &QwtPlotZoomer::zoomStack() const
|
||
|
{
|
||
|
return d_data->zoomStack;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\return Initial rectangle of the zoomer
|
||
|
\sa setZoomBase(), zoomRect()
|
||
|
*/
|
||
|
QwtDoubleRect QwtPlotZoomer::zoomBase() const
|
||
|
{
|
||
|
return d_data->zoomStack[0];
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
Reinitialized the zoom stack with scaleRect() as base.
|
||
|
|
||
|
\param doReplot Call replot for the attached plot before initializing
|
||
14 years ago
|
the zoomer with its scales. This might be necessary,
|
||
15 years ago
|
when the plot is in a state with pending scale changes.
|
||
|
|
||
|
\sa zoomBase(), scaleRect() QwtPlot::autoReplot(), QwtPlot::replot().
|
||
|
*/
|
||
|
void QwtPlotZoomer::setZoomBase(bool doReplot)
|
||
|
{
|
||
|
QwtPlot *plt = plot();
|
||
|
if ( plt == NULL )
|
||
|
return;
|
||
|
|
||
|
if ( doReplot )
|
||
|
plt->replot();
|
||
|
|
||
|
d_data->zoomStack.clear();
|
||
|
d_data->zoomStack.push(scaleRect());
|
||
|
d_data->zoomRectIndex = 0;
|
||
|
|
||
|
rescale();
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\brief Set the initial size of the zoomer.
|
||
|
|
||
|
base is united with the current scaleRect() and the zoom stack is
|
||
|
reinitalized with it as zoom base. plot is zoomed to scaleRect().
|
||
14 years ago
|
|
||
15 years ago
|
\param base Zoom base
|
||
14 years ago
|
|
||
15 years ago
|
\sa zoomBase(), scaleRect()
|
||
|
*/
|
||
|
void QwtPlotZoomer::setZoomBase(const QwtDoubleRect &base)
|
||
|
{
|
||
|
const QwtPlot *plt = plot();
|
||
|
if ( !plt )
|
||
|
return;
|
||
|
|
||
|
const QwtDoubleRect sRect = scaleRect();
|
||
|
const QwtDoubleRect bRect = base | sRect;
|
||
|
|
||
|
d_data->zoomStack.clear();
|
||
|
d_data->zoomStack.push(bRect);
|
||
|
d_data->zoomRectIndex = 0;
|
||
|
|
||
14 years ago
|
if ( base != sRect ) {
|
||
15 years ago
|
d_data->zoomStack.push(sRect);
|
||
|
d_data->zoomRectIndex++;
|
||
|
}
|
||
|
|
||
|
rescale();
|
||
|
}
|
||
|
|
||
14 years ago
|
/*!
|
||
|
Rectangle at the current position on the zoom stack.
|
||
15 years ago
|
|
||
|
\sa zoomRectIndex(), scaleRect().
|
||
|
*/
|
||
|
QwtDoubleRect QwtPlotZoomer::zoomRect() const
|
||
|
{
|
||
|
return d_data->zoomStack[d_data->zoomRectIndex];
|
||
|
}
|
||
|
|
||
14 years ago
|
/*!
|
||
15 years ago
|
\return Index of current position of zoom stack.
|
||
|
*/
|
||
|
uint QwtPlotZoomer::zoomRectIndex() const
|
||
|
{
|
||
|
return d_data->zoomRectIndex;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\brief Zoom in
|
||
|
|
||
|
Clears all rectangles above the current position of the
|
||
14 years ago
|
zoom stack and pushs the intersection of zoomRect() and
|
||
15 years ago
|
the normalized rect on it.
|
||
|
|
||
|
\note If the maximal stack depth is reached, zoom is ignored.
|
||
|
\note The zoomed signal is emitted.
|
||
|
*/
|
||
|
|
||
|
void QwtPlotZoomer::zoom(const QwtDoubleRect &rect)
|
||
14 years ago
|
{
|
||
|
if ( d_data->maxStackDepth >= 0 &&
|
||
|
int(d_data->zoomRectIndex) >= d_data->maxStackDepth ) {
|
||
15 years ago
|
return;
|
||
|
}
|
||
|
|
||
|
const QwtDoubleRect zoomRect = d_data->zoomStack[0] & rect.normalized();
|
||
14 years ago
|
if ( zoomRect != d_data->zoomStack[d_data->zoomRectIndex] ) {
|
||
|
for ( uint i = int(d_data->zoomStack.count()) - 1;
|
||
|
i > d_data->zoomRectIndex; i-- ) {
|
||
15 years ago
|
(void)d_data->zoomStack.pop();
|
||
|
}
|
||
|
|
||
|
d_data->zoomStack.push(zoomRect);
|
||
|
d_data->zoomRectIndex++;
|
||
|
|
||
|
rescale();
|
||
|
|
||
|
emit zoomed(zoomRect);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\brief Zoom in or out
|
||
|
|
||
|
Activate a rectangle on the zoom stack with an offset relative
|
||
|
to the current position. Negative values of offest will zoom out,
|
||
|
positive zoom in. A value of 0 zooms out to the zoom base.
|
||
|
|
||
|
\param offset Offset relative to the current position of the zoom stack.
|
||
|
\note The zoomed signal is emitted.
|
||
|
\sa zoomRectIndex()
|
||
|
*/
|
||
|
void QwtPlotZoomer::zoom(int offset)
|
||
|
{
|
||
|
if ( offset == 0 )
|
||
|
d_data->zoomRectIndex = 0;
|
||
14 years ago
|
else {
|
||
15 years ago
|
int newIndex = d_data->zoomRectIndex + offset;
|
||
|
newIndex = qwtMax(0, newIndex);
|
||
|
newIndex = qwtMin(int(d_data->zoomStack.count()) - 1, newIndex);
|
||
|
|
||
|
d_data->zoomRectIndex = uint(newIndex);
|
||
|
}
|
||
|
|
||
|
rescale();
|
||
|
|
||
|
emit zoomed(zoomRect());
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\brief Assign a zoom stack
|
||
|
|
||
|
In combination with other types of navigation it might be useful to
|
||
|
modify to manipulate the complete zoom stack.
|
||
|
|
||
|
\param zoomStack New zoom stack
|
||
|
\param zoomRectIndex Index of the current position of zoom stack.
|
||
|
In case of -1 the current position is at the top
|
||
|
of the stack.
|
||
|
|
||
|
\note The zoomed signal might be emitted.
|
||
|
\sa zoomStack(), zoomRectIndex()
|
||
|
*/
|
||
|
void QwtPlotZoomer::setZoomStack(
|
||
|
const QwtZoomStack &zoomStack, int zoomRectIndex)
|
||
|
{
|
||
|
if ( zoomStack.isEmpty() )
|
||
|
return;
|
||
|
|
||
|
if ( d_data->maxStackDepth >= 0 &&
|
||
14 years ago
|
int(zoomStack.count()) > d_data->maxStackDepth ) {
|
||
15 years ago
|
return;
|
||
|
}
|
||
|
|
||
|
if ( zoomRectIndex < 0 || zoomRectIndex > int(zoomStack.count()) )
|
||
|
zoomRectIndex = zoomStack.count() - 1;
|
||
|
|
||
|
const bool doRescale = zoomStack[zoomRectIndex] != zoomRect();
|
||
|
|
||
|
d_data->zoomStack = zoomStack;
|
||
|
d_data->zoomRectIndex = uint(zoomRectIndex);
|
||
|
|
||
14 years ago
|
if ( doRescale ) {
|
||
15 years ago
|
rescale();
|
||
|
emit zoomed(zoomRect());
|
||
|
}
|
||
|
}
|
||
|
|
||
14 years ago
|
/*!
|
||
15 years ago
|
Adjust the observed plot to zoomRect()
|
||
|
|
||
|
\note Initiates QwtPlot::replot
|
||
|
*/
|
||
|
|
||
|
void QwtPlotZoomer::rescale()
|
||
|
{
|
||
|
QwtPlot *plt = plot();
|
||
|
if ( !plt )
|
||
|
return;
|
||
|
|
||
|
const QwtDoubleRect &rect = d_data->zoomStack[d_data->zoomRectIndex];
|
||
14 years ago
|
if ( rect != scaleRect() ) {
|
||
15 years ago
|
const bool doReplot = plt->autoReplot();
|
||
|
plt->setAutoReplot(false);
|
||
|
|
||
|
double x1 = rect.left();
|
||
|
double x2 = rect.right();
|
||
14 years ago
|
if ( plt->axisScaleDiv(xAxis())->lBound() >
|
||
|
plt->axisScaleDiv(xAxis())->hBound() ) {
|
||
15 years ago
|
qSwap(x1, x2);
|
||
|
}
|
||
|
|
||
|
plt->setAxisScale(xAxis(), x1, x2);
|
||
|
|
||
|
double y1 = rect.top();
|
||
|
double y2 = rect.bottom();
|
||
14 years ago
|
if ( plt->axisScaleDiv(yAxis())->lBound() >
|
||
|
plt->axisScaleDiv(yAxis())->hBound() ) {
|
||
15 years ago
|
qSwap(y1, y2);
|
||
|
}
|
||
|
plt->setAxisScale(yAxis(), y1, y2);
|
||
|
|
||
|
plt->setAutoReplot(doReplot);
|
||
|
|
||
|
plt->replot();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
Reinitialize the axes, and set the zoom base to their scales.
|
||
|
|
||
14 years ago
|
\param xAxis X axis
|
||
15 years ago
|
\param yAxis Y axis
|
||
|
*/
|
||
|
|
||
|
void QwtPlotZoomer::setAxis(int xAxis, int yAxis)
|
||
|
{
|
||
14 years ago
|
if ( xAxis != QwtPlotPicker::xAxis() || yAxis != QwtPlotPicker::yAxis() ) {
|
||
15 years ago
|
QwtPlotPicker::setAxis(xAxis, yAxis);
|
||
|
setZoomBase(scaleRect());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
Qt::MidButton zooms out one position on the zoom stack,
|
||
|
Qt::RightButton to the zoom base.
|
||
|
|
||
|
Changes the current position on the stack, but doesn't pop
|
||
|
any rectangle.
|
||
|
|
||
|
\note The mouse events can be changed, using
|
||
|
QwtEventPattern::setMousePattern: 2, 1
|
||
|
*/
|
||
|
void QwtPlotZoomer::widgetMouseReleaseEvent(QMouseEvent *me)
|
||
|
{
|
||
|
if ( mouseMatch(MouseSelect2, me) )
|
||
|
zoom(0);
|
||
|
else if ( mouseMatch(MouseSelect3, me) )
|
||
|
zoom(-1);
|
||
|
else if ( mouseMatch(MouseSelect6, me) )
|
||
|
zoom(+1);
|
||
14 years ago
|
else
|
||
15 years ago
|
QwtPlotPicker::widgetMouseReleaseEvent(me);
|
||
|
}
|
||
|
|
||
|
/*!
|
||
14 years ago
|
Qt::Key_Plus zooms out, Qt::Key_Minus zooms in one position on the
|
||
15 years ago
|
zoom stack, Qt::Key_Escape zooms out to the zoom base.
|
||
|
|
||
|
Changes the current position on the stack, but doesn't pop
|
||
|
any rectangle.
|
||
|
|
||
|
\note The keys codes can be changed, using
|
||
|
QwtEventPattern::setKeyPattern: 3, 4, 5
|
||
|
*/
|
||
|
|
||
|
void QwtPlotZoomer::widgetKeyPressEvent(QKeyEvent *ke)
|
||
|
{
|
||
14 years ago
|
if ( !isActive() ) {
|
||
15 years ago
|
if ( keyMatch(KeyUndo, ke) )
|
||
|
zoom(-1);
|
||
|
else if ( keyMatch(KeyRedo, ke) )
|
||
|
zoom(+1);
|
||
|
else if ( keyMatch(KeyHome, ke) )
|
||
|
zoom(0);
|
||
|
}
|
||
|
|
||
|
QwtPlotPicker::widgetKeyPressEvent(ke);
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
Move the current zoom rectangle.
|
||
|
|
||
|
\param dx X offset
|
||
|
\param dy Y offset
|
||
|
|
||
|
\note The changed rectangle is limited by the zoom base
|
||
|
*/
|
||
|
void QwtPlotZoomer::moveBy(double dx, double dy)
|
||
|
{
|
||
|
const QwtDoubleRect &rect = d_data->zoomStack[d_data->zoomRectIndex];
|
||
|
move(rect.left() + dx, rect.top() + dy);
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
Move the the current zoom rectangle.
|
||
|
|
||
|
\param x X value
|
||
|
\param y Y value
|
||
|
|
||
|
\sa QwtDoubleRect::move
|
||
|
\note The changed rectangle is limited by the zoom base
|
||
|
*/
|
||
|
void QwtPlotZoomer::move(double x, double y)
|
||
|
{
|
||
|
if ( x < zoomBase().left() )
|
||
|
x = zoomBase().left();
|
||
|
if ( x > zoomBase().right() - zoomRect().width() )
|
||
|
x = zoomBase().right() - zoomRect().width();
|
||
|
|
||
|
if ( y < zoomBase().top() )
|
||
|
y = zoomBase().top();
|
||
|
if ( y > zoomBase().bottom() - zoomRect().height() )
|
||
|
y = zoomBase().bottom() - zoomRect().height();
|
||
|
|
||
14 years ago
|
if ( x != zoomRect().left() || y != zoomRect().top() ) {
|
||
15 years ago
|
d_data->zoomStack[d_data->zoomRectIndex].moveTo(x, y);
|
||
|
rescale();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\brief Check and correct a selected rectangle
|
||
|
|
||
|
Reject rectangles with a hight or width < 2, otherwise
|
||
|
expand the selected rectangle to a minimum size of 11x11
|
||
|
and accept it.
|
||
14 years ago
|
|
||
15 years ago
|
\return true If rect is accepted, or has been changed
|
||
14 years ago
|
to a accepted rectangle.
|
||
15 years ago
|
*/
|
||
|
|
||
|
bool QwtPlotZoomer::accept(QwtPolygon &pa) const
|
||
|
{
|
||
|
if ( pa.count() < 2 )
|
||
|
return false;
|
||
|
|
||
|
QRect rect = QRect(pa[0], pa[int(pa.count()) - 1]);
|
||
|
#if QT_VERSION < 0x040000
|
||
|
rect = rect.normalize();
|
||
|
#else
|
||
|
rect = rect.normalized();
|
||
|
#endif
|
||
|
|
||
|
const int minSize = 2;
|
||
|
if (rect.width() < minSize && rect.height() < minSize )
|
||
14 years ago
|
return false;
|
||
15 years ago
|
|
||
|
const int minZoomSize = 11;
|
||
|
|
||
|
const QPoint center = rect.center();
|
||
|
rect.setSize(rect.size().expandedTo(QSize(minZoomSize, minZoomSize)));
|
||
|
rect.moveCenter(center);
|
||
|
|
||
|
pa.resize(2);
|
||
|
pa[0] = rect.topLeft();
|
||
|
pa[1] = rect.bottomRight();
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\brief Limit zooming by a minimum rectangle
|
||
|
|
||
|
\return zoomBase().width() / 10e4, zoomBase().height() / 10e4
|
||
|
*/
|
||
|
QwtDoubleSize QwtPlotZoomer::minZoomSize() const
|
||
|
{
|
||
|
return QwtDoubleSize(
|
||
14 years ago
|
d_data->zoomStack[0].width() / 10e4,
|
||
|
d_data->zoomStack[0].height() / 10e4
|
||
|
);
|
||
15 years ago
|
}
|
||
|
|
||
14 years ago
|
/*!
|
||
15 years ago
|
Rejects selections, when the stack depth is too deep, or
|
||
|
the zoomed rectangle is minZoomSize().
|
||
|
|
||
|
\sa minZoomSize(), maxStackDepth()
|
||
|
*/
|
||
|
void QwtPlotZoomer::begin()
|
||
|
{
|
||
14 years ago
|
if ( d_data->maxStackDepth >= 0 ) {
|
||
15 years ago
|
if ( d_data->zoomRectIndex >= uint(d_data->maxStackDepth) )
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const QwtDoubleSize minSize = minZoomSize();
|
||
14 years ago
|
if ( minSize.isValid() ) {
|
||
|
const QwtDoubleSize sz =
|
||
15 years ago
|
d_data->zoomStack[d_data->zoomRectIndex].size() * 0.9999;
|
||
|
|
||
|
if ( minSize.width() >= sz.width() &&
|
||
14 years ago
|
minSize.height() >= sz.height() ) {
|
||
15 years ago
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
QwtPlotPicker::begin();
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
Expand the selected rectangle to minZoomSize() and zoom in
|
||
|
if accepted.
|
||
|
|
||
|
\sa QwtPlotZoomer::accept()a, QwtPlotZoomer::minZoomSize()
|
||
|
*/
|
||
|
bool QwtPlotZoomer::end(bool ok)
|
||
|
{
|
||
|
ok = QwtPlotPicker::end(ok);
|
||
|
if (!ok)
|
||
|
return false;
|
||
|
|
||
|
QwtPlot *plot = QwtPlotZoomer::plot();
|
||
|
if ( !plot )
|
||
|
return false;
|
||
|
|
||
|
const QwtPolygon &pa = selection();
|
||
|
if ( pa.count() < 2 )
|
||
|
return false;
|
||
|
|
||
|
QRect rect = QRect(pa[0], pa[int(pa.count() - 1)]);
|
||
|
#if QT_VERSION < 0x040000
|
||
|
rect = rect.normalize();
|
||
|
#else
|
||
|
rect = rect.normalized();
|
||
|
#endif
|
||
|
|
||
|
|
||
|
QwtDoubleRect zoomRect = invTransform(rect).normalized();
|
||
|
|
||
|
const QwtDoublePoint center = zoomRect.center();
|
||
|
zoomRect.setSize(zoomRect.size().expandedTo(minZoomSize()));
|
||
|
zoomRect.moveCenter(center);
|
||
|
|
||
|
zoom(zoomRect);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
Set the selection flags
|
||
14 years ago
|
|
||
15 years ago
|
\param flags Or'd value of QwtPicker::RectSelectionType and
|
||
14 years ago
|
QwtPicker::SelectionMode. The default value is
|
||
15 years ago
|
QwtPicker::RectSelection & QwtPicker::ClickSelection.
|
||
|
|
||
|
\sa selectionFlags(), SelectionType, RectSelectionType, SelectionMode
|
||
|
\note QwtPicker::RectSelection will be auto added.
|
||
|
*/
|
||
|
|
||
|
void QwtPlotZoomer::setSelectionFlags(int flags)
|
||
|
{
|
||
|
// we accept only rects
|
||
|
flags &= ~(PointSelection | PolygonSelection);
|
||
|
flags |= RectSelection;
|
||
|
|
||
|
QwtPlotPicker::setSelectionFlags(flags);
|
||
|
}
|