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 

Generated on Sun Nov 21 11:12:44 2004 for Qwt User's Guide by doxygen 1.3.5