00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
#include <math.h>
00013
#include "qwt_plot.h"
00014
#include "qwt_plot_canvas.h"
00015
#include "qwt_plot_zoomer.h"
00016
00040 QwtPlotZoomer::QwtPlotZoomer(
QwtPlotCanvas *canvas,
const char *name):
00041
QwtPlotPicker(canvas, name)
00042 {
00043
if ( canvas )
00044 init();
00045 }
00046
00068 QwtPlotZoomer::QwtPlotZoomer(
int xAxis,
int yAxis,
00069
QwtPlotCanvas *canvas,
const char *name):
00070
QwtPlotPicker(xAxis, yAxis, canvas, name)
00071 {
00072
if ( canvas )
00073 {
00074 init();
00075 }
00076 }
00077
00102 QwtPlotZoomer::QwtPlotZoomer(
int xAxis,
int yAxis,
int selectionFlags,
00103 DisplayMode cursorLabelMode,
QwtPlotCanvas *canvas,
const char *name):
00104
QwtPlotPicker(xAxis, yAxis,canvas, name)
00105 {
00106
if ( canvas )
00107 {
00108 init(selectionFlags, cursorLabelMode);
00109 }
00110 }
00111
00113
void QwtPlotZoomer::init(
int selectionFlags, DisplayMode cursorLabelMode)
00114 {
00115 d_maxStackDepth = -1;
00116
00117
setSelectionFlags(selectionFlags);
00118
setCursorLabelMode(cursorLabelMode);
00119
setRubberBand(RectRubberBand);
00120
00121
setZoomBase(
scaleRect());
00122 }
00123
00135 void QwtPlotZoomer::setMaxStackDepth(
int depth)
00136 {
00137 d_maxStackDepth = depth;
00138
00139
if ( depth >= 0 )
00140 {
00141
00142
00143
const int zoomOut =
00144 d_zoomStack.count() - 1 - depth;
00145
00146
if ( zoomOut > 0 )
00147 {
00148
zoom(-zoomOut);
00149
for ( uint i = d_zoomStack.count() - 1; i > d_zoomRectIndex; i-- )
00150 (
void)d_zoomStack.pop();
00151 }
00152 }
00153 }
00154
00159 int QwtPlotZoomer::maxStackDepth()
const
00160
{
00161
return d_maxStackDepth;
00162 }
00163
00168 const QValueStack<QwtDoubleRect> &
QwtPlotZoomer::zoomStack()
const
00169
{
00170
return d_zoomStack;
00171 }
00172
00177 QValueStack<QwtDoubleRect> &
QwtPlotZoomer::zoomStack()
00178 {
00179
return d_zoomStack;
00180 }
00181
00186 QwtDoubleRect QwtPlotZoomer::zoomBase()
const
00187
{
00188
return d_zoomStack[0];
00189 }
00190
00204 void QwtPlotZoomer::setZoomBase()
00205 {
00206
const QwtPlot *plt =
plot();
00207
if ( !plt )
00208
return;
00209
00210 d_zoomStack.clear();
00211 d_zoomStack.push(
scaleRect());
00212 d_zoomRectIndex = 0;
00213
00214
rescale();
00215 }
00216
00227 void QwtPlotZoomer::setZoomBase(
const QwtDoubleRect &base)
00228 {
00229
const QwtPlot *plt =
plot();
00230
if ( !plt )
00231
return;
00232
00233
const QwtDoubleRect sRect =
scaleRect();
00234
const QwtDoubleRect bRect = base | sRect;
00235
00236 d_zoomStack.clear();
00237 d_zoomStack.push(bRect);
00238 d_zoomRectIndex = 0;
00239
00240
if ( base != sRect )
00241 {
00242 d_zoomStack.push(sRect);
00243 d_zoomRectIndex++;
00244 }
00245
00246
rescale();
00247 }
00248
00254 QwtDoubleRect QwtPlotZoomer::zoomRect()
const
00255
{
00256
return d_zoomStack[d_zoomRectIndex];
00257 }
00258
00262 uint
QwtPlotZoomer::zoomRectIndex()
const
00263
{
00264
return d_zoomRectIndex;
00265 }
00266
00277 void QwtPlotZoomer::zoom(
const QwtDoubleRect &rect)
00278 {
00279
if ( d_maxStackDepth >= 0 && int(d_zoomRectIndex) >= d_maxStackDepth )
00280
return;
00281
00282
const QwtDoubleRect zoomRect = d_zoomStack[0] & rect.
normalize();
00283
if ( zoomRect != d_zoomStack[d_zoomRectIndex] )
00284 {
00285
for ( uint i = d_zoomStack.count() - 1; i > d_zoomRectIndex; i-- )
00286 (
void)d_zoomStack.pop();
00287
00288 d_zoomStack.push(zoomRect);
00289 d_zoomRectIndex++;
00290
00291
rescale();
00292 }
00293 }
00294
00305 void QwtPlotZoomer::zoom(
int offset)
00306 {
00307
if ( offset == 0 )
00308 d_zoomRectIndex = 0;
00309
else
00310 {
00311
int newIndex = d_zoomRectIndex + offset;
00312 newIndex = QMAX(0, newIndex);
00313 newIndex = QMIN(
int(d_zoomStack.count() - 1), newIndex);
00314
00315 d_zoomRectIndex = uint(newIndex);
00316 }
00317
00318
rescale();
00319 }
00320
00327 void QwtPlotZoomer::rescale()
00328 {
00329
QwtPlot *plt =
plot();
00330
if ( !plt )
00331
return;
00332
00333
const QwtDoubleRect &rect = d_zoomStack[d_zoomRectIndex];
00334
if ( rect !=
scaleRect() )
00335 {
00336 plt->
setAxisScale(
xAxis(), rect.
x1(), rect.
x2());
00337 plt->
setAxisScale(
yAxis(), rect.
y1(), rect.
y2());
00338
00339 plt->
replot();
00340 }
00341 }
00342
00350 void QwtPlotZoomer::setAxis(
int xAxis,
int yAxis)
00351 {
00352
if ( xAxis !=
QwtPlotPicker::xAxis() || yAxis !=
QwtPlotPicker::yAxis() )
00353 {
00354
QwtPlotPicker::setAxis(xAxis, yAxis);
00355
setZoomBase(
scaleRect());
00356 }
00357 }
00358
00369 void QwtPlotZoomer::widgetMouseReleaseEvent(QMouseEvent *me)
00370 {
00371
if (
mouseMatch(MouseSelect2, me) )
00372
zoom(0);
00373
else if (
mouseMatch(MouseSelect3, me) )
00374
zoom(-1);
00375
else if (
mouseMatch(MouseSelect6, me) )
00376
zoom(+1);
00377
else
00378
QwtPlotPicker::widgetMouseReleaseEvent(me);
00379 }
00380
00392 void QwtPlotZoomer::widgetKeyPressEvent(QKeyEvent *ke)
00393 {
00394
if ( !
isActive() )
00395 {
00396
if (
keyMatch(KeyUndo, ke) )
00397
zoom(-1);
00398
else if (
keyMatch(KeyRedo, ke) )
00399
zoom(+1);
00400
else if (
keyMatch(KeyHome, ke) )
00401
zoom(0);
00402 }
00403
00404
QwtPlotPicker::widgetKeyPressEvent(ke);
00405 }
00406
00415 void QwtPlotZoomer::moveBy(
double dx,
double dy)
00416 {
00417
const QwtDoubleRect &rect = d_zoomStack[d_zoomRectIndex];
00418
move(rect.
x1() + dx, rect.
y1() + dy);
00419 }
00420
00430 void QwtPlotZoomer::move(
double x,
double y)
00431 {
00432 x = QMAX(x,
zoomBase().x1());
00433 x = QMIN(x,
zoomBase().x2() -
zoomRect().width());
00434
00435 y = QMAX(y,
zoomBase().y1());
00436 y = QMIN(y,
zoomBase().y2() -
zoomRect().height());
00437
00438
if ( x !=
zoomRect().
x1() || y !=
zoomRect().
y1() )
00439 {
00440 d_zoomStack[d_zoomRectIndex].move(x, y);
00441
rescale();
00442 }
00443 }
00444
00456 bool QwtPlotZoomer::accept(QPointArray &pa)
const
00457
{
00458
if ( pa.count() < 2 )
00459
return FALSE;
00460
00461 QRect rect = QRect(pa[0], pa[
int(pa.count() - 1)]).normalize();
00462
00463
const int minSize = 2;
00464
if (rect.width() < minSize && rect.height() < minSize )
00465
return FALSE;
00466
00467
const int minZoomSize = 11;
00468
00469
const QPoint center = rect.center();
00470 rect.setSize(rect.size().expandedTo(QSize(minZoomSize, minZoomSize)));
00471 rect.moveCenter(center);
00472
00473 pa.resize(2);
00474 pa[0] = rect.topLeft();
00475 pa[1] = rect.bottomRight();
00476
00477
return TRUE;
00478 }
00479
00488 QwtDoubleSize QwtPlotZoomer::minZoomSize()
const
00489
{
00490
char f;
00491
int fw, xprecision, yprecision;
00492
00493
plot()->
axisLabelFormat(
xAxis(), f, xprecision, fw);
00494
plot()->
axisLabelFormat(
yAxis(), f, yprecision, fw);
00495
00496
return QwtDoubleSize(
00497 d_zoomStack[0].width() / pow(10.0, xprecision - 1),
00498 d_zoomStack[0].height() / pow(10.0, yprecision - 1)
00499 );
00500 }
00501
00508 void QwtPlotZoomer::begin()
00509 {
00510
if ( d_maxStackDepth >= 0 )
00511 {
00512
if ( d_zoomRectIndex >= uint(d_maxStackDepth) )
00513
return;
00514 }
00515
00516
const QwtDoubleSize minSize =
minZoomSize();
00517
if ( minSize.
isValid() )
00518 {
00519
const QwtDoubleSize sz =
00520 d_zoomStack[d_zoomRectIndex].size() * 0.9999;
00521
00522
if ( minSize.
width() >= sz.
width() &&
00523 minSize.
height() >= sz.
height() )
00524 {
00525
return;
00526 }
00527 }
00528
00529
QwtPlotPicker::begin();
00530 }
00531
00539 bool QwtPlotZoomer::end(
bool ok)
00540 {
00541 ok =
QwtPlotPicker::end(ok);
00542
if (!ok)
00543
return FALSE;
00544
00545
QwtPlot *plot =
QwtPlotZoomer::plot();
00546
if ( !plot )
00547
return FALSE;
00548
00549
const QPointArray &pa =
selection();
00550
if ( pa.count() < 2 )
00551
return FALSE;
00552
00553 QRect rect = QRect(pa[0], pa[
int(pa.count() - 1)]).normalize();
00554
00555
QwtDoubleRect zoomRect =
invTransform(rect).
normalize();
00556
00557
const QwtDoublePoint center = zoomRect.
center();
00558 zoomRect.
setSize(zoomRect.
size().
expandedTo(
minZoomSize()));
00559 zoomRect.
moveCenter(center);
00560
00561
zoom(zoomRect);
00562 emit
zoomed(zoomRect);
00563
00564
return TRUE;
00565 }
00566
00578 void QwtPlotZoomer::setSelectionFlags(
int flags)
00579 {
00580
00581 flags &= ~(PointSelection | PolygonSelection);
00582 flags |= RectSelection;
00583
00584
QwtPlotPicker::setSelectionFlags(flags);
00585 }
00586
00587
00588
00589
00590
00591
00592