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
00054 QwtPlotZoomer::QwtPlotZoomer(QwtPlotCanvas *canvas):
00055 QwtPlotPicker(canvas)
00056 {
00057 if ( canvas )
00058 init();
00059 }
00060
00081 QwtPlotZoomer::QwtPlotZoomer(int xAxis, int yAxis,
00082 QwtPlotCanvas *canvas):
00083 QwtPlotPicker(xAxis, yAxis, canvas)
00084 {
00085 if ( canvas )
00086 {
00087 init();
00088 }
00089 }
00090
00114 QwtPlotZoomer::QwtPlotZoomer(int xAxis, int yAxis, int selectionFlags,
00115 DisplayMode trackerMode, QwtPlotCanvas *canvas):
00116 QwtPlotPicker(xAxis, yAxis,canvas)
00117 {
00118 if ( canvas )
00119 {
00120 init(selectionFlags, trackerMode);
00121 }
00122 }
00123
00125 void QwtPlotZoomer::init(int selectionFlags, DisplayMode trackerMode)
00126 {
00127 d_data = new PrivateData;
00128
00129 d_data->maxStackDepth = -1;
00130
00131 setSelectionFlags(selectionFlags);
00132 setTrackerMode(trackerMode);
00133 setRubberBand(RectRubberBand);
00134
00135 setZoomBase(scaleRect());
00136 }
00137
00138 QwtPlotZoomer::~QwtPlotZoomer()
00139 {
00140 delete d_data;
00141 }
00142
00154 void QwtPlotZoomer::setMaxStackDepth(int depth)
00155 {
00156 d_data->maxStackDepth = depth;
00157
00158 if ( depth >= 0 )
00159 {
00160
00161
00162 const int zoomOut =
00163 int(d_data->zoomStack.count()) - 1 - depth;
00164
00165 if ( zoomOut > 0 )
00166 {
00167 zoom(-zoomOut);
00168 for ( int i = int(d_data->zoomStack.count()) - 1;
00169 i > int(d_data->zoomRectIndex); i-- )
00170 {
00171 (void)d_data->zoomStack.pop();
00172 }
00173 }
00174 }
00175 }
00176
00181 int QwtPlotZoomer::maxStackDepth() const
00182 {
00183 return d_data->maxStackDepth;
00184 }
00185
00190 const QwtZoomStack &QwtPlotZoomer::zoomStack() const
00191 {
00192 return d_data->zoomStack;
00193 }
00194
00199 QwtDoubleRect QwtPlotZoomer::zoomBase() const
00200 {
00201 return d_data->zoomStack[0];
00202 }
00203
00217 void QwtPlotZoomer::setZoomBase()
00218 {
00219 const QwtPlot *plt = plot();
00220 if ( !plt )
00221 return;
00222
00223 d_data->zoomStack.clear();
00224 d_data->zoomStack.push(scaleRect());
00225 d_data->zoomRectIndex = 0;
00226
00227 rescale();
00228 }
00229
00240 void QwtPlotZoomer::setZoomBase(const QwtDoubleRect &base)
00241 {
00242 const QwtPlot *plt = plot();
00243 if ( !plt )
00244 return;
00245
00246 const QwtDoubleRect sRect = scaleRect();
00247 const QwtDoubleRect bRect = base | sRect;
00248
00249 d_data->zoomStack.clear();
00250 d_data->zoomStack.push(bRect);
00251 d_data->zoomRectIndex = 0;
00252
00253 if ( base != sRect )
00254 {
00255 d_data->zoomStack.push(sRect);
00256 d_data->zoomRectIndex++;
00257 }
00258
00259 rescale();
00260 }
00261
00267 QwtDoubleRect QwtPlotZoomer::zoomRect() const
00268 {
00269 return d_data->zoomStack[d_data->zoomRectIndex];
00270 }
00271
00275 uint QwtPlotZoomer::zoomRectIndex() const
00276 {
00277 return d_data->zoomRectIndex;
00278 }
00279
00290 void QwtPlotZoomer::zoom(const QwtDoubleRect &rect)
00291 {
00292 if ( d_data->maxStackDepth >= 0 &&
00293 int(d_data->zoomRectIndex) >= d_data->maxStackDepth )
00294 {
00295 return;
00296 }
00297
00298 const QwtDoubleRect zoomRect = d_data->zoomStack[0] & rect.normalized();
00299 if ( zoomRect != d_data->zoomStack[d_data->zoomRectIndex] )
00300 {
00301 for ( uint i = int(d_data->zoomStack.count()) - 1;
00302 i > d_data->zoomRectIndex; i-- )
00303 {
00304 (void)d_data->zoomStack.pop();
00305 }
00306
00307 d_data->zoomStack.push(zoomRect);
00308 d_data->zoomRectIndex++;
00309
00310 rescale();
00311 }
00312 }
00313
00324 void QwtPlotZoomer::zoom(int offset)
00325 {
00326 if ( offset == 0 )
00327 d_data->zoomRectIndex = 0;
00328 else
00329 {
00330 int newIndex = d_data->zoomRectIndex + offset;
00331 newIndex = qwtMax(0, newIndex);
00332 newIndex = qwtMin(int(d_data->zoomStack.count()) - 1, newIndex);
00333
00334 d_data->zoomRectIndex = uint(newIndex);
00335 }
00336
00337 rescale();
00338 }
00339
00346 void QwtPlotZoomer::rescale()
00347 {
00348 QwtPlot *plt = plot();
00349 if ( !plt )
00350 return;
00351
00352 const QwtDoubleRect &rect = d_data->zoomStack[d_data->zoomRectIndex];
00353 if ( rect != scaleRect() )
00354 {
00355 const bool doReplot = plt->autoReplot();
00356 plt->setAutoReplot(false);
00357
00358 double x1 = rect.left();
00359 double x2 = rect.right();
00360 if ( plt->axisScaleDiv(xAxis())->lBound() >
00361 plt->axisScaleDiv(xAxis())->hBound() )
00362 {
00363 qSwap(x1, x2);
00364 }
00365
00366 plt->setAxisScale(xAxis(), x1, x2);
00367
00368 double y1 = rect.top();
00369 double y2 = rect.bottom();
00370 if ( plt->axisScaleDiv(yAxis())->lBound() >
00371 plt->axisScaleDiv(yAxis())->hBound() )
00372 {
00373 qSwap(y1, y2);
00374 }
00375 plt->setAxisScale(yAxis(), y1, y2);
00376
00377 plt->setAutoReplot(doReplot);
00378
00379 plt->replot();
00380 }
00381 }
00382
00390 void QwtPlotZoomer::setAxis(int xAxis, int yAxis)
00391 {
00392 if ( xAxis != QwtPlotPicker::xAxis() || yAxis != QwtPlotPicker::yAxis() )
00393 {
00394 QwtPlotPicker::setAxis(xAxis, yAxis);
00395 setZoomBase(scaleRect());
00396 }
00397 }
00398
00409 void QwtPlotZoomer::widgetMouseReleaseEvent(QMouseEvent *me)
00410 {
00411 if ( mouseMatch(MouseSelect2, me) )
00412 zoom(0);
00413 else if ( mouseMatch(MouseSelect3, me) )
00414 zoom(-1);
00415 else if ( mouseMatch(MouseSelect6, me) )
00416 zoom(+1);
00417 else
00418 QwtPlotPicker::widgetMouseReleaseEvent(me);
00419 }
00420
00432 void QwtPlotZoomer::widgetKeyPressEvent(QKeyEvent *ke)
00433 {
00434 if ( !isActive() )
00435 {
00436 if ( keyMatch(KeyUndo, ke) )
00437 zoom(-1);
00438 else if ( keyMatch(KeyRedo, ke) )
00439 zoom(+1);
00440 else if ( keyMatch(KeyHome, ke) )
00441 zoom(0);
00442 }
00443
00444 QwtPlotPicker::widgetKeyPressEvent(ke);
00445 }
00446
00455 void QwtPlotZoomer::moveBy(double dx, double dy)
00456 {
00457 const QwtDoubleRect &rect = d_data->zoomStack[d_data->zoomRectIndex];
00458 move(rect.left() + dx, rect.top() + dy);
00459 }
00460
00470 void QwtPlotZoomer::move(double x, double y)
00471 {
00472 x = qwtMax(x, zoomBase().left());
00473 x = qwtMin(x, zoomBase().right() - zoomRect().width());
00474
00475 y = qwtMax(y, zoomBase().top());
00476 y = qwtMin(y, zoomBase().bottom() - zoomRect().height());
00477
00478 if ( x != zoomRect().left() || y != zoomRect().top() )
00479 {
00480 d_data->zoomStack[d_data->zoomRectIndex].moveTo(x, y);
00481 rescale();
00482 }
00483 }
00484
00496 bool QwtPlotZoomer::accept(SelectedPoints &pa) const
00497 {
00498 if ( pa.count() < 2 )
00499 return false;
00500
00501 QRect rect = QRect(pa[0], pa[int(pa.count()) - 1]);
00502 #if QT_VERSION < 0x040000
00503 rect = rect.normalize();
00504 #else
00505 rect = rect.normalized();
00506 #endif
00507
00508 const int minSize = 2;
00509 if (rect.width() < minSize && rect.height() < minSize )
00510 return false;
00511
00512 const int minZoomSize = 11;
00513
00514 const QPoint center = rect.center();
00515 rect.setSize(rect.size().expandedTo(QSize(minZoomSize, minZoomSize)));
00516 rect.moveCenter(center);
00517
00518 pa.resize(2);
00519 pa[0] = rect.topLeft();
00520 pa[1] = rect.bottomRight();
00521
00522 return true;
00523 }
00524
00530 QwtDoubleSize QwtPlotZoomer::minZoomSize() const
00531 {
00532 return QwtDoubleSize(
00533 d_data->zoomStack[0].width() / 10e4,
00534 d_data->zoomStack[0].height() / 10e4
00535 );
00536 }
00537
00544 void QwtPlotZoomer::begin()
00545 {
00546 if ( d_data->maxStackDepth >= 0 )
00547 {
00548 if ( d_data->zoomRectIndex >= uint(d_data->maxStackDepth) )
00549 return;
00550 }
00551
00552 const QwtDoubleSize minSize = minZoomSize();
00553 if ( minSize.isValid() )
00554 {
00555 const QwtDoubleSize sz =
00556 d_data->zoomStack[d_data->zoomRectIndex].size() * 0.9999;
00557
00558 if ( minSize.width() >= sz.width() &&
00559 minSize.height() >= sz.height() )
00560 {
00561 return;
00562 }
00563 }
00564
00565 QwtPlotPicker::begin();
00566 }
00567
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 SelectedPoints &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 emit zoomed(zoomRect);
00605
00606 return true;
00607 }
00608
00620 void QwtPlotZoomer::setSelectionFlags(int flags)
00621 {
00622
00623 flags &= ~(PointSelection | PolygonSelection);
00624 flags |= RectSelection;
00625
00626 QwtPlotPicker::setSelectionFlags(flags);
00627 }