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