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 #include "qwt_scale_div.h"
00017 #if QT_VERSION < 0x040000
00018 typedef QValueStack<QwtDoubleRect> QwtZoomStack;
00019 #else
00020 typedef QStack<QwtDoubleRect> QwtZoomStack;
00021 #endif
00022
00023 class QwtPlotZoomer::PrivateData
00024 {
00025 public:
00026 uint zoomRectIndex;
00027 QwtZoomStack zoomStack;
00028
00029 int maxStackDepth;
00030 };
00031
00051 QwtPlotZoomer::QwtPlotZoomer(QwtPlotCanvas *canvas, bool doReplot):
00052 QwtPlotPicker(canvas)
00053 {
00054 if ( canvas )
00055 init(RectSelection & ClickSelection, ActiveOnly, doReplot);
00056 }
00057
00075 QwtPlotZoomer::QwtPlotZoomer(int xAxis, int yAxis,
00076 QwtPlotCanvas *canvas, bool doReplot):
00077 QwtPlotPicker(xAxis, yAxis, canvas)
00078 {
00079 if ( canvas )
00080 init(RectSelection & ClickSelection, ActiveOnly, doReplot);
00081 }
00082
00103 QwtPlotZoomer::QwtPlotZoomer(int xAxis, int yAxis, int selectionFlags,
00104 DisplayMode trackerMode, QwtPlotCanvas *canvas, bool doReplot):
00105 QwtPlotPicker(xAxis, yAxis, canvas)
00106 {
00107 if ( canvas )
00108 init(selectionFlags, trackerMode, doReplot);
00109 }
00110
00112 void QwtPlotZoomer::init(int selectionFlags,
00113 DisplayMode trackerMode, bool doReplot)
00114 {
00115 d_data = new PrivateData;
00116
00117 d_data->maxStackDepth = -1;
00118
00119 setSelectionFlags(selectionFlags);
00120 setTrackerMode(trackerMode);
00121 setRubberBand(RectRubberBand);
00122
00123 if ( doReplot && plot() )
00124 plot()->replot();
00125
00126 setZoomBase(scaleRect());
00127 }
00128
00129 QwtPlotZoomer::~QwtPlotZoomer()
00130 {
00131 delete d_data;
00132 }
00133
00145 void QwtPlotZoomer::setMaxStackDepth(int depth)
00146 {
00147 d_data->maxStackDepth = depth;
00148
00149 if ( depth >= 0 )
00150 {
00151
00152
00153 const int zoomOut =
00154 int(d_data->zoomStack.count()) - 1 - depth;
00155
00156 if ( zoomOut > 0 )
00157 {
00158 zoom(-zoomOut);
00159 for ( int i = int(d_data->zoomStack.count()) - 1;
00160 i > int(d_data->zoomRectIndex); i-- )
00161 {
00162 (void)d_data->zoomStack.pop();
00163 }
00164 }
00165 }
00166 }
00167
00172 int QwtPlotZoomer::maxStackDepth() const
00173 {
00174 return d_data->maxStackDepth;
00175 }
00176
00181 const QwtZoomStack &QwtPlotZoomer::zoomStack() const
00182 {
00183 return d_data->zoomStack;
00184 }
00185
00190 QwtDoubleRect QwtPlotZoomer::zoomBase() const
00191 {
00192 return d_data->zoomStack[0];
00193 }
00194
00208 void QwtPlotZoomer::setZoomBase()
00209 {
00210 const QwtPlot *plt = plot();
00211 if ( !plt )
00212 return;
00213
00214 d_data->zoomStack.clear();
00215 d_data->zoomStack.push(scaleRect());
00216 d_data->zoomRectIndex = 0;
00217
00218 rescale();
00219 }
00220
00231 void QwtPlotZoomer::setZoomBase(const QwtDoubleRect &base)
00232 {
00233 const QwtPlot *plt = plot();
00234 if ( !plt )
00235 return;
00236
00237 const QwtDoubleRect sRect = scaleRect();
00238 const QwtDoubleRect bRect = base | sRect;
00239
00240 d_data->zoomStack.clear();
00241 d_data->zoomStack.push(bRect);
00242 d_data->zoomRectIndex = 0;
00243
00244 if ( base != sRect )
00245 {
00246 d_data->zoomStack.push(sRect);
00247 d_data->zoomRectIndex++;
00248 }
00249
00250 rescale();
00251 }
00252
00258 QwtDoubleRect QwtPlotZoomer::zoomRect() const
00259 {
00260 return d_data->zoomStack[d_data->zoomRectIndex];
00261 }
00262
00266 uint QwtPlotZoomer::zoomRectIndex() const
00267 {
00268 return d_data->zoomRectIndex;
00269 }
00270
00282 void QwtPlotZoomer::zoom(const QwtDoubleRect &rect)
00283 {
00284 if ( d_data->maxStackDepth >= 0 &&
00285 int(d_data->zoomRectIndex) >= d_data->maxStackDepth )
00286 {
00287 return;
00288 }
00289
00290 const QwtDoubleRect zoomRect = d_data->zoomStack[0] & rect.normalized();
00291 if ( zoomRect != d_data->zoomStack[d_data->zoomRectIndex] )
00292 {
00293 for ( uint i = int(d_data->zoomStack.count()) - 1;
00294 i > d_data->zoomRectIndex; i-- )
00295 {
00296 (void)d_data->zoomStack.pop();
00297 }
00298
00299 d_data->zoomStack.push(zoomRect);
00300 d_data->zoomRectIndex++;
00301
00302 rescale();
00303
00304 emit zoomed(zoomRect);
00305 }
00306 }
00307
00319 void QwtPlotZoomer::zoom(int offset)
00320 {
00321 if ( offset == 0 )
00322 d_data->zoomRectIndex = 0;
00323 else
00324 {
00325 int newIndex = d_data->zoomRectIndex + offset;
00326 newIndex = qwtMax(0, newIndex);
00327 newIndex = qwtMin(int(d_data->zoomStack.count()) - 1, newIndex);
00328
00329 d_data->zoomRectIndex = uint(newIndex);
00330 }
00331
00332 rescale();
00333
00334 emit zoomed(zoomRect());
00335 }
00336
00343 void QwtPlotZoomer::rescale()
00344 {
00345 QwtPlot *plt = plot();
00346 if ( !plt )
00347 return;
00348
00349 const QwtDoubleRect &rect = d_data->zoomStack[d_data->zoomRectIndex];
00350 if ( rect != scaleRect() )
00351 {
00352 const bool doReplot = plt->autoReplot();
00353 plt->setAutoReplot(false);
00354
00355 double x1 = rect.left();
00356 double x2 = rect.right();
00357 if ( plt->axisScaleDiv(xAxis())->lBound() >
00358 plt->axisScaleDiv(xAxis())->hBound() )
00359 {
00360 qSwap(x1, x2);
00361 }
00362
00363 plt->setAxisScale(xAxis(), x1, x2);
00364
00365 double y1 = rect.top();
00366 double y2 = rect.bottom();
00367 if ( plt->axisScaleDiv(yAxis())->lBound() >
00368 plt->axisScaleDiv(yAxis())->hBound() )
00369 {
00370 qSwap(y1, y2);
00371 }
00372 plt->setAxisScale(yAxis(), y1, y2);
00373
00374 plt->setAutoReplot(doReplot);
00375
00376 plt->replot();
00377 }
00378 }
00379
00387 void QwtPlotZoomer::setAxis(int xAxis, int yAxis)
00388 {
00389 if ( xAxis != QwtPlotPicker::xAxis() || yAxis != QwtPlotPicker::yAxis() )
00390 {
00391 QwtPlotPicker::setAxis(xAxis, yAxis);
00392 setZoomBase(scaleRect());
00393 }
00394 }
00395
00406 void QwtPlotZoomer::widgetMouseReleaseEvent(QMouseEvent *me)
00407 {
00408 if ( mouseMatch(MouseSelect2, me) )
00409 zoom(0);
00410 else if ( mouseMatch(MouseSelect3, me) )
00411 zoom(-1);
00412 else if ( mouseMatch(MouseSelect6, me) )
00413 zoom(+1);
00414 else
00415 QwtPlotPicker::widgetMouseReleaseEvent(me);
00416 }
00417
00429 void QwtPlotZoomer::widgetKeyPressEvent(QKeyEvent *ke)
00430 {
00431 if ( !isActive() )
00432 {
00433 if ( keyMatch(KeyUndo, ke) )
00434 zoom(-1);
00435 else if ( keyMatch(KeyRedo, ke) )
00436 zoom(+1);
00437 else if ( keyMatch(KeyHome, ke) )
00438 zoom(0);
00439 }
00440
00441 QwtPlotPicker::widgetKeyPressEvent(ke);
00442 }
00443
00452 void QwtPlotZoomer::moveBy(double dx, double dy)
00453 {
00454 const QwtDoubleRect &rect = d_data->zoomStack[d_data->zoomRectIndex];
00455 move(rect.left() + dx, rect.top() + dy);
00456 }
00457
00467 void QwtPlotZoomer::move(double x, double y)
00468 {
00469 if ( x < zoomBase().left() )
00470 x = zoomBase().left();
00471 if ( x > zoomBase().right() - zoomRect().width() )
00472 x = zoomBase().right() - zoomRect().width();
00473
00474 if ( y < zoomBase().top() )
00475 y = zoomBase().top();
00476 if ( y > zoomBase().bottom() - zoomRect().height() )
00477 y = zoomBase().bottom() - zoomRect().height();
00478
00479 if ( x != zoomRect().left() || y != zoomRect().top() )
00480 {
00481 d_data->zoomStack[d_data->zoomRectIndex].moveTo(x, y);
00482 rescale();
00483 }
00484 }
00485
00497 bool QwtPlotZoomer::accept(QwtPolygon &pa) const
00498 {
00499 if ( pa.count() < 2 )
00500 return false;
00501
00502 QRect rect = QRect(pa[0], pa[int(pa.count()) - 1]);
00503 #if QT_VERSION < 0x040000
00504 rect = rect.normalize();
00505 #else
00506 rect = rect.normalized();
00507 #endif
00508
00509 const int minSize = 2;
00510 if (rect.width() < minSize && rect.height() < minSize )
00511 return false;
00512
00513 const int minZoomSize = 11;
00514
00515 const QPoint center = rect.center();
00516 rect.setSize(rect.size().expandedTo(QSize(minZoomSize, minZoomSize)));
00517 rect.moveCenter(center);
00518
00519 pa.resize(2);
00520 pa[0] = rect.topLeft();
00521 pa[1] = rect.bottomRight();
00522
00523 return true;
00524 }
00525
00531 QwtDoubleSize QwtPlotZoomer::minZoomSize() const
00532 {
00533 return QwtDoubleSize(
00534 d_data->zoomStack[0].width() / 10e4,
00535 d_data->zoomStack[0].height() / 10e4
00536 );
00537 }
00538
00545 void QwtPlotZoomer::begin()
00546 {
00547 if ( d_data->maxStackDepth >= 0 )
00548 {
00549 if ( d_data->zoomRectIndex >= uint(d_data->maxStackDepth) )
00550 return;
00551 }
00552
00553 const QwtDoubleSize minSize = minZoomSize();
00554 if ( minSize.isValid() )
00555 {
00556 const QwtDoubleSize sz =
00557 d_data->zoomStack[d_data->zoomRectIndex].size() * 0.9999;
00558
00559 if ( minSize.width() >= sz.width() &&
00560 minSize.height() >= sz.height() )
00561 {
00562 return;
00563 }
00564 }
00565
00566 QwtPlotPicker::begin();
00567 }
00568
00575 bool QwtPlotZoomer::end(bool ok)
00576 {
00577 ok = QwtPlotPicker::end(ok);
00578 if (!ok)
00579 return false;
00580
00581 QwtPlot *plot = QwtPlotZoomer::plot();
00582 if ( !plot )
00583 return false;
00584
00585 const QwtPolygon &pa = selection();
00586 if ( pa.count() < 2 )
00587 return false;
00588
00589 QRect rect = QRect(pa[0], pa[int(pa.count() - 1)]);
00590 #if QT_VERSION < 0x040000
00591 rect = rect.normalize();
00592 #else
00593 rect = rect.normalized();
00594 #endif
00595
00596
00597 QwtDoubleRect zoomRect = invTransform(rect).normalized();
00598
00599 const QwtDoublePoint center = zoomRect.center();
00600 zoomRect.setSize(zoomRect.size().expandedTo(minZoomSize()));
00601 zoomRect.moveCenter(center);
00602
00603 zoom(zoomRect);
00604
00605 return true;
00606 }
00607
00619 void QwtPlotZoomer::setSelectionFlags(int flags)
00620 {
00621
00622 flags &= ~(PointSelection | PolygonSelection);
00623 flags |= RectSelection;
00624
00625 QwtPlotPicker::setSelectionFlags(flags);
00626 }