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 #if QT_VERSION < 0x040000
00017 typedef QValueStack<QwtDoubleRect> QwtZoomStack;
00018 #else
00019 typedef QStack<QwtDoubleRect> QwtZoomStack;
00020 #endif
00021
00022
00023 class QwtPlotZoomer::PrivateData
00024 {
00025 public:
00026 uint zoomRectIndex;
00027 QwtZoomStack zoomStack;
00028
00029 int maxStackDepth;
00030 };
00031
00055 QwtPlotZoomer::QwtPlotZoomer(QwtPlotCanvas *canvas):
00056 QwtPlotPicker(canvas)
00057 {
00058 if ( canvas )
00059 init();
00060 }
00061
00083 QwtPlotZoomer::QwtPlotZoomer(int xAxis, int yAxis,
00084 QwtPlotCanvas *canvas):
00085 QwtPlotPicker(xAxis, yAxis, canvas)
00086 {
00087 if ( canvas )
00088 {
00089 init();
00090 }
00091 }
00092
00116 QwtPlotZoomer::QwtPlotZoomer(int xAxis, int yAxis, int selectionFlags,
00117 DisplayMode trackerMode, QwtPlotCanvas *canvas):
00118 QwtPlotPicker(xAxis, yAxis,canvas)
00119 {
00120 if ( canvas )
00121 {
00122 init(selectionFlags, trackerMode);
00123 }
00124 }
00125
00127 void QwtPlotZoomer::init(int selectionFlags, DisplayMode trackerMode)
00128 {
00129 d_data = new PrivateData;
00130
00131 d_data->maxStackDepth = -1;
00132
00133 setSelectionFlags(selectionFlags);
00134 setTrackerMode(trackerMode);
00135 setRubberBand(RectRubberBand);
00136
00137 setZoomBase(scaleRect());
00138 }
00139
00140 QwtPlotZoomer::~QwtPlotZoomer()
00141 {
00142 delete d_data;
00143 }
00144
00156 void QwtPlotZoomer::setMaxStackDepth(int depth)
00157 {
00158 d_data->maxStackDepth = depth;
00159
00160 if ( depth >= 0 )
00161 {
00162
00163
00164 const int zoomOut =
00165 int(d_data->zoomStack.count()) - 1 - depth;
00166
00167 if ( zoomOut > 0 )
00168 {
00169 zoom(-zoomOut);
00170 for ( int i = int(d_data->zoomStack.count()) - 1;
00171 i > int(d_data->zoomRectIndex); i-- )
00172 {
00173 (void)d_data->zoomStack.pop();
00174 }
00175 }
00176 }
00177 }
00178
00183 int QwtPlotZoomer::maxStackDepth() const
00184 {
00185 return d_data->maxStackDepth;
00186 }
00187
00192 const QwtZoomStack &QwtPlotZoomer::zoomStack() const
00193 {
00194 return d_data->zoomStack;
00195 }
00196
00201 QwtZoomStack &QwtPlotZoomer::zoomStack()
00202 {
00203 return d_data->zoomStack;
00204 }
00205
00210 QwtDoubleRect QwtPlotZoomer::zoomBase() const
00211 {
00212 return d_data->zoomStack[0];
00213 }
00214
00228 void QwtPlotZoomer::setZoomBase()
00229 {
00230 const QwtPlot *plt = plot();
00231 if ( !plt )
00232 return;
00233
00234 d_data->zoomStack.clear();
00235 d_data->zoomStack.push(scaleRect());
00236 d_data->zoomRectIndex = 0;
00237
00238 rescale();
00239 }
00240
00251 void QwtPlotZoomer::setZoomBase(const QwtDoubleRect &base)
00252 {
00253 const QwtPlot *plt = plot();
00254 if ( !plt )
00255 return;
00256
00257 const QwtDoubleRect sRect = scaleRect();
00258 const QwtDoubleRect bRect = base | sRect;
00259
00260 d_data->zoomStack.clear();
00261 d_data->zoomStack.push(bRect);
00262 d_data->zoomRectIndex = 0;
00263
00264 if ( base != sRect )
00265 {
00266 d_data->zoomStack.push(sRect);
00267 d_data->zoomRectIndex++;
00268 }
00269
00270 rescale();
00271 }
00272
00278 QwtDoubleRect QwtPlotZoomer::zoomRect() const
00279 {
00280 return d_data->zoomStack[d_data->zoomRectIndex];
00281 }
00282
00286 uint QwtPlotZoomer::zoomRectIndex() const
00287 {
00288 return d_data->zoomRectIndex;
00289 }
00290
00301 void QwtPlotZoomer::zoom(const QwtDoubleRect &rect)
00302 {
00303 if ( d_data->maxStackDepth >= 0 && int(d_data->zoomRectIndex) >= d_data->maxStackDepth )
00304 return;
00305
00306 const QwtDoubleRect zoomRect = d_data->zoomStack[0] & rect.normalized();
00307 if ( zoomRect != d_data->zoomStack[d_data->zoomRectIndex] )
00308 {
00309 for ( uint i = int(d_data->zoomStack.count()) - 1; i > d_data->zoomRectIndex; i-- )
00310 (void)d_data->zoomStack.pop();
00311
00312 d_data->zoomStack.push(zoomRect);
00313 d_data->zoomRectIndex++;
00314
00315 rescale();
00316 }
00317 }
00318
00329 void QwtPlotZoomer::zoom(int offset)
00330 {
00331 if ( offset == 0 )
00332 d_data->zoomRectIndex = 0;
00333 else
00334 {
00335 int newIndex = d_data->zoomRectIndex + offset;
00336 newIndex = qwtMax(0, newIndex);
00337 newIndex = qwtMin(int(d_data->zoomStack.count()) - 1, newIndex);
00338
00339 d_data->zoomRectIndex = uint(newIndex);
00340 }
00341
00342 rescale();
00343 }
00344
00351 void QwtPlotZoomer::rescale()
00352 {
00353 QwtPlot *plt = plot();
00354 if ( !plt )
00355 return;
00356
00357 const QwtDoubleRect &rect = d_data->zoomStack[d_data->zoomRectIndex];
00358 if ( rect != scaleRect() )
00359 {
00360 const bool doReplot = plt->autoReplot();
00361 plt->setAutoReplot(false);
00362
00363 plt->setAxisScale(xAxis(), rect.left(), rect.right());
00364 plt->setAxisScale(yAxis(), rect.top(), rect.bottom());
00365
00366 plt->setAutoReplot(doReplot);
00367
00368 plt->replot();
00369 }
00370 }
00371
00379 void QwtPlotZoomer::setAxis(int xAxis, int yAxis)
00380 {
00381 if ( xAxis != QwtPlotPicker::xAxis() || yAxis != QwtPlotPicker::yAxis() )
00382 {
00383 QwtPlotPicker::setAxis(xAxis, yAxis);
00384 setZoomBase(scaleRect());
00385 }
00386 }
00387
00398 void QwtPlotZoomer::widgetMouseReleaseEvent(QMouseEvent *me)
00399 {
00400 if ( mouseMatch(MouseSelect2, me) )
00401 zoom(0);
00402 else if ( mouseMatch(MouseSelect3, me) )
00403 zoom(-1);
00404 else if ( mouseMatch(MouseSelect6, me) )
00405 zoom(+1);
00406 else
00407 QwtPlotPicker::widgetMouseReleaseEvent(me);
00408 }
00409
00421 void QwtPlotZoomer::widgetKeyPressEvent(QKeyEvent *ke)
00422 {
00423 if ( !isActive() )
00424 {
00425 if ( keyMatch(KeyUndo, ke) )
00426 zoom(-1);
00427 else if ( keyMatch(KeyRedo, ke) )
00428 zoom(+1);
00429 else if ( keyMatch(KeyHome, ke) )
00430 zoom(0);
00431 }
00432
00433 QwtPlotPicker::widgetKeyPressEvent(ke);
00434 }
00435
00444 void QwtPlotZoomer::moveBy(double dx, double dy)
00445 {
00446 const QwtDoubleRect &rect = d_data->zoomStack[d_data->zoomRectIndex];
00447 move(rect.left() + dx, rect.top() + dy);
00448 }
00449
00459 void QwtPlotZoomer::move(double x, double y)
00460 {
00461 x = qwtMax(x, zoomBase().left());
00462 x = qwtMin(x, zoomBase().right() - zoomRect().width());
00463
00464 y = qwtMax(y, zoomBase().top());
00465 y = qwtMin(y, zoomBase().bottom() - zoomRect().height());
00466
00467 if ( x != zoomRect().left() || y != zoomRect().top() )
00468 {
00469 d_data->zoomStack[d_data->zoomRectIndex].moveTo(x, y);
00470 rescale();
00471 }
00472 }
00473
00485 bool QwtPlotZoomer::accept(SelectedPoints &pa) const
00486 {
00487 if ( pa.count() < 2 )
00488 return false;
00489
00490 QRect rect = QRect(pa[0], pa[int(pa.count()) - 1]);
00491 #if QT_VERSION < 0x040000
00492 rect = rect.normalize();
00493 #else
00494 rect = rect.normalized();
00495 #endif
00496
00497 const int minSize = 2;
00498 if (rect.width() < minSize && rect.height() < minSize )
00499 return false;
00500
00501 const int minZoomSize = 11;
00502
00503 const QPoint center = rect.center();
00504 rect.setSize(rect.size().expandedTo(QSize(minZoomSize, minZoomSize)));
00505 rect.moveCenter(center);
00506
00507 pa.resize(2);
00508 pa[0] = rect.topLeft();
00509 pa[1] = rect.bottomRight();
00510
00511 return true;
00512 }
00513
00522 QwtDoubleSize QwtPlotZoomer::minZoomSize() const
00523 {
00524 char f;
00525 int fw, xprecision, yprecision;
00526
00527 plot()->axisLabelFormat(xAxis(), f, xprecision, fw);
00528 plot()->axisLabelFormat(yAxis(), f, yprecision, fw);
00529
00530 return QwtDoubleSize(
00531 d_data->zoomStack[0].width() / pow(10.0, xprecision - 1),
00532 d_data->zoomStack[0].height() / pow(10.0, yprecision - 1)
00533 );
00534 }
00535
00542 void QwtPlotZoomer::begin()
00543 {
00544 if ( d_data->maxStackDepth >= 0 )
00545 {
00546 if ( d_data->zoomRectIndex >= uint(d_data->maxStackDepth) )
00547 return;
00548 }
00549
00550 const QwtDoubleSize minSize = minZoomSize();
00551 if ( minSize.isValid() )
00552 {
00553 const QwtDoubleSize sz =
00554 d_data->zoomStack[d_data->zoomRectIndex].size() * 0.9999;
00555
00556 if ( minSize.width() >= sz.width() &&
00557 minSize.height() >= sz.height() )
00558 {
00559 return;
00560 }
00561 }
00562
00563 QwtPlotPicker::begin();
00564 }
00565
00573 bool QwtPlotZoomer::end(bool ok)
00574 {
00575 ok = QwtPlotPicker::end(ok);
00576 if (!ok)
00577 return false;
00578
00579 QwtPlot *plot = QwtPlotZoomer::plot();
00580 if ( !plot )
00581 return false;
00582
00583 const SelectedPoints &pa = selection();
00584 if ( pa.count() < 2 )
00585 return false;
00586
00587 QRect rect = QRect(pa[0], pa[int(pa.count() - 1)]);
00588 #if QT_VERSION < 0x040000
00589 rect = rect.normalize();
00590 #else
00591 rect = rect.normalized();
00592 #endif
00593
00594
00595 QwtDoubleRect zoomRect = invTransform(rect).normalized();
00596
00597 const QwtDoublePoint center = zoomRect.center();
00598 zoomRect.setSize(zoomRect.size().expandedTo(minZoomSize()));
00599 zoomRect.moveCenter(center);
00600
00601 zoom(zoomRect);
00602 emit zoomed(zoomRect);
00603
00604 return true;
00605 }
00606
00618 void QwtPlotZoomer::setSelectionFlags(int flags)
00619 {
00620
00621 flags &= ~(PointSelection | PolygonSelection);
00622 flags |= RectSelection;
00623
00624 QwtPlotPicker::setSelectionFlags(flags);
00625 }