Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

# qwt_plot_zoomer.cpp

    00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
    00002  * Qwt Widget Library
    00003  * Copyright (C) 1997   Josef Wilgen
    00004  * Copyright (C) 2002   Uwe Rathmann
    00005  *
    00006  * This library is free software; you can redistribute it and/or
    00007  * modify it under the terms of the Qwt License, Version 1.0
    00008  *****************************************************************************/
    00009
    00010 // vim: expandtab
    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         // unzoom if the current depth is below d_maxStackDepth
    00142
    00143         const int zoomOut =
    00144             d_zoomStack.count() - 1 - depth; // -1 for the zoom base
    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(); // remove trailing rects
    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     // we accept only rects
    00581     flags &= ~(PointSelection | PolygonSelection);
    00582     flags |= RectSelection;
    00583
    00584     QwtPlotPicker::setSelectionFlags(flags);
    00585 }
    00586
    00587 // Local Variables:
    00588 // mode: C++
    00589 // c-file-style: "stroustrup"
    00590 // indent-tabs-mode: nil
    00591 // End:
    00592