# qwt_plot_magnifier.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 <qevent.h>
    00014 #include "qwt_plot.h"
    00015 #include "qwt_plot_canvas.h"
    00016 #include "qwt_scale_div.h"
    00017 #include "qwt_plot_magnifier.h"
    00018
    00019 class QwtPlotMagnifier::PrivateData
    00020 {
    00021 public:
    00022     PrivateData():
    00023         isEnabled(false),
    00024         wheelFactor(0.9),
    00025         wheelButtonState(Qt::NoButton),
    00026         mouseFactor(0.95),
    00027         mouseButton(Qt::RightButton),
    00028         mouseButtonState(Qt::NoButton),
    00029         keyFactor(0.9),
    00030         zoomInKey(Qt::Key_Plus),
    00031         zoomOutKey(Qt::Key_Minus),
    00032 #if QT_VERSION < 0x040000
    00033         zoomInKeyButtonState(Qt::NoButton),
    00034         zoomOutKeyButtonState(Qt::NoButton),
    00035 #else
    00036         zoomInKeyButtonState(Qt::NoModifier),
    00037         zoomOutKeyButtonState(Qt::NoModifier),
    00038 #endif
    00039         mousePressed(false)
    00040     {
    00041         for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
    00042             isAxisEnabled[axis] = true;
    00043     }
    00044
    00045     bool isEnabled;
    00046
    00047     double wheelFactor;
    00048     int wheelButtonState;
    00049
    00050     double mouseFactor;
    00051     int mouseButton;
    00052     int mouseButtonState;
    00053
    00054     double keyFactor;
    00055     int zoomInKey;
    00056     int zoomOutKey;
    00057     int zoomInKeyButtonState;
    00058     int zoomOutKeyButtonState;
    00059
    00060     bool isAxisEnabled[QwtPlot::axisCnt];
    00061
    00062     bool mousePressed;
    00063     bool hasMouseTracking;
    00064     QPoint mousePos;
    00065 };
    00066
    00067 QwtPlotMagnifier::QwtPlotMagnifier(QwtPlotCanvas *canvas):
    00068     QObject(canvas)
    00069 {
    00070     d_data = new PrivateData();
    00071     setEnabled(true);
    00072 }
    00073
    00074 QwtPlotMagnifier::~QwtPlotMagnifier()
    00075 {
    00076     delete d_data;
    00077 }
    00078
    00079 void QwtPlotMagnifier::setEnabled(bool on)
    00080 {
    00081     if ( d_data->isEnabled != on )
    00082     {
    00083         d_data->isEnabled = on;
    00084
    00085         QObject *o = parent();
    00086         if ( o )
    00087         {
    00088             if ( d_data->isEnabled )
    00089                 o->installEventFilter(this);
    00090             else
    00091                 o->removeEventFilter(this);
    00092         }
    00093     }
    00094 }
    00095
    00096 bool QwtPlotMagnifier::isEnabled() const
    00097 {
    00098     return d_data->isEnabled;
    00099 }
    00100
    00101 void QwtPlotMagnifier::setWheelFactor(double factor)
    00102 {
    00103     d_data->wheelFactor = factor;
    00104 }
    00105
    00106 double QwtPlotMagnifier::wheelFactor() const
    00107 {
    00108     return d_data->wheelFactor;
    00109 }
    00110
    00111 void QwtPlotMagnifier::setWheelButtonState(int buttonState)
    00112 {
    00113     d_data->wheelButtonState = buttonState;
    00114 }
    00115
    00116 int QwtPlotMagnifier::wheelButtonState() const
    00117 {
    00118     return d_data->wheelButtonState;
    00119 }
    00120
    00121 void QwtPlotMagnifier::setMouseFactor(double factor)
    00122 {
    00123     d_data->mouseFactor = factor;
    00124 }
    00125
    00126 double QwtPlotMagnifier::mouseFactor() const
    00127 {
    00128     return d_data->mouseFactor;
    00129 }
    00130
    00131 void QwtPlotMagnifier::setMouseButton(int button, int buttonState)
    00132 {
    00133     d_data->mouseButton = button;
    00134     d_data->mouseButtonState = buttonState;
    00135 }
    00136
    00137 void QwtPlotMagnifier::getMouseButton(
    00138     int &button, int &buttonState) const
    00139 {
    00140     button = d_data->mouseButton;
    00141     buttonState = d_data->mouseButtonState;
    00142 }
    00143
    00144 void QwtPlotMagnifier::setKeyFactor(double factor)
    00145 {
    00146     d_data->keyFactor = factor;
    00147 }
    00148
    00149 double QwtPlotMagnifier::keyFactor() const
    00150 {
    00151     return d_data->keyFactor;
    00152 }
    00153
    00154 void QwtPlotMagnifier::setZoomInKey(int key, int buttonState)
    00155 {
    00156     d_data->zoomInKey = key;
    00157     d_data->zoomInKeyButtonState = buttonState;
    00158 }
    00159
    00160 void QwtPlotMagnifier::getZoomInKey(int &key, int &buttonState)
    00161 {
    00162     key = d_data->zoomInKey;
    00163     buttonState = d_data->zoomInKeyButtonState;
    00164 }
    00165
    00166 void QwtPlotMagnifier::setZoomOutKey(int key, int buttonState)
    00167 {
    00168     d_data->zoomOutKey = key;
    00169     d_data->zoomOutKeyButtonState = buttonState;
    00170 }
    00171
    00172 void QwtPlotMagnifier::getZoomOutKey(int &key, int &buttonState)
    00173 {
    00174     key = d_data->zoomOutKey;
    00175     buttonState = d_data->zoomOutKeyButtonState;
    00176 }
    00177
    00178 void QwtPlotMagnifier::setAxisEnabled(int axis, bool on)
    00179 {
    00180     if ( axis >= 0 && axis < QwtPlot::axisCnt )
    00181         d_data->isAxisEnabled[axis] = on;
    00182 }
    00183
    00184 bool QwtPlotMagnifier::isAxisEnabled(int axis) const
    00185 {
    00186     if ( axis >= 0 && axis < QwtPlot::axisCnt )
    00187         return d_data->isAxisEnabled[axis];
    00188
    00189     return true;
    00190 }
    00191
    00193 QwtPlotCanvas *QwtPlotMagnifier::canvas()
    00194 {
    00195     QObject *w = parent();
    00196     if ( w && w->inherits("QwtPlotCanvas") )
    00197         return (QwtPlotCanvas *)w;
    00198
    00199     return NULL;
    00200 }
    00201
    00203 const QwtPlotCanvas *QwtPlotMagnifier::canvas() const
    00204 {
    00205     return ((QwtPlotMagnifier *)this)->canvas();
    00206 }
    00207
    00209 QwtPlot *QwtPlotMagnifier::plot()
    00210 {
    00211     QObject *w = canvas();
    00212     if ( w )
    00213     {
    00214         w = w->parent();
    00215         if ( w && w->inherits("QwtPlot") )
    00216             return (QwtPlot *)w;
    00217     }
    00218
    00219     return NULL;
    00220 }
    00221
    00223 const QwtPlot *QwtPlotMagnifier::plot() const
    00224 {
    00225     return ((QwtPlotMagnifier *)this)->plot();
    00226 }
    00227
    00228 bool QwtPlotMagnifier::eventFilter(QObject *o, QEvent *e)
    00229 {
    00230     if ( o && o == parent() )
    00231     {
    00232         switch(e->type() )
    00233         {
    00234             case QEvent::MouseButtonPress:
    00235             {
    00236                 widgetMousePressEvent((QMouseEvent *)e);
    00237                 break;
    00238             }
    00239             case QEvent::MouseMove:
    00240             {
    00241                 widgetMouseMoveEvent((QMouseEvent *)e);
    00242                 break;
    00243             }
    00244             case QEvent::MouseButtonRelease:
    00245             {
    00246                 widgetMouseReleaseEvent((QMouseEvent *)e);
    00247                 break;
    00248             }
    00249             case QEvent::Wheel:
    00250             {
    00251                 widgetWheelEvent((QWheelEvent *)e);
    00252                 break;
    00253             }
    00254             case QEvent::KeyPress:
    00255             {
    00256                 widgetKeyPressEvent((QKeyEvent *)e);
    00257                 break;
    00258             }
    00259             case QEvent::KeyRelease:
    00260             {
    00261                 widgetKeyReleaseEvent((QKeyEvent *)e);
    00262                 break;
    00263             }
    00264             default:;
    00265         }
    00266     }
    00267     return QObject::eventFilter(o, e);
    00268 }
    00269
    00270 void QwtPlotMagnifier::widgetMousePressEvent(QMouseEvent *me)
    00271 {
    00272     if ( me->button() != d_data->mouseButton )
    00273         return;
    00274
    00275 #if QT_VERSION < 0x040000
    00276     if ( (me->state() & Qt::KeyButtonMask) !=
    00277         (d_data->mouseButtonState & Qt::KeyButtonMask) )
    00278 #else
    00279     if ( (me->modifiers() & Qt::KeyboardModifierMask) !=
    00280         (int)(d_data->mouseButtonState & Qt::KeyboardModifierMask) )
    00281 #endif
    00282     {
    00283         return;
    00284     }
    00285
    00286     d_data->hasMouseTracking = canvas()->hasMouseTracking();
    00287     canvas()->setMouseTracking(true);
    00288     d_data->mousePos = me->pos();
    00289     d_data->mousePressed = true;
    00290 }
    00291
    00292 void QwtPlotMagnifier::widgetMouseReleaseEvent(QMouseEvent *)
    00293 {
    00294     if ( d_data->mousePressed )
    00295     {
    00296         d_data->mousePressed = false;
    00297         canvas()->setMouseTracking(d_data->hasMouseTracking);
    00298     }
    00299 }
    00300
    00301 void QwtPlotMagnifier::widgetMouseMoveEvent(QMouseEvent *me)
    00302 {
    00303     if ( !d_data->mousePressed )
    00304         return;
    00305
    00306     const int dy = me->pos().y() - d_data->mousePos.y();
    00307     if ( dy != 0 )
    00308     {
    00309         double f = d_data->mouseFactor;
    00310         if ( dy < 0 )
    00311             f = 1 / f;
    00312
    00313         rescale(f);
    00314     }
    00315
    00316     d_data->mousePos = me->pos();
    00317 }
    00318
    00319 void QwtPlotMagnifier::widgetWheelEvent(QWheelEvent *we)
    00320 {
    00321 #if QT_VERSION < 0x040000
    00322     if ( (we->state() & Qt::KeyButtonMask) !=
    00323         (d_data->wheelButtonState & Qt::KeyButtonMask) )
    00324 #else
    00325     if ( (we->modifiers() & Qt::KeyboardModifierMask) !=
    00326         (int)(d_data->wheelButtonState & Qt::KeyboardModifierMask) )
    00327 #endif
    00328     {
    00329         return;
    00330     }
    00331
    00332     if ( d_data->wheelFactor != 0.0 )
    00333     {
    00334        /*
    00335            A positive delta indicates that the wheel was
    00336            rotated forwards away from the user; a negative
    00337            value indicates that the wheel was rotated
    00338            backwards toward the user.
    00339            Most mouse types work in steps of 15 degrees,
    00340            in which case the delta value is a multiple
    00341            of 120 (== 15 * 8).
    00342         */
    00343         double f = ::pow(d_data->wheelFactor,
    00344             qwtAbs(we->delta() / 120));
    00345         if ( we->delta() > 0 )
    00346             f = 1 / f;
    00347
    00348         rescale(f);
    00349     }
    00350 }
    00351
    00352 void QwtPlotMagnifier::widgetKeyPressEvent(QKeyEvent *ke)
    00353 {
    00354     const int key = ke->key();
    00355 #if QT_VERSION < 0x040000
    00356     const int state = ke->state();
    00357 #else
    00358     const int state = ke->modifiers();
    00359 #endif
    00360
    00361     if ( key == d_data->zoomInKey &&
    00362         state == d_data->zoomInKeyButtonState )
    00363     {
    00364         rescale(d_data->keyFactor);
    00365     }
    00366     else if ( key == d_data->zoomOutKey &&
    00367         state == d_data->zoomOutKeyButtonState )
    00368     {
    00369         rescale(1.0 / d_data->keyFactor);
    00370     }
    00371 }
    00372
    00373 void QwtPlotMagnifier::widgetKeyReleaseEvent(QKeyEvent *)
    00374 {
    00375 }
    00376
    00377 void QwtPlotMagnifier::rescale(double factor)
    00378 {
    00379     if ( factor == 1.0 || factor == 0.0 )
    00380         return;
    00381
    00382     bool doReplot = false;
    00383     QwtPlot* plt = plot();
    00384
    00385     const bool autoReplot = plt->autoReplot();
    00386     plt->setAutoReplot(false);
    00387
    00388     for ( int axisId = 0; axisId < QwtPlot::axisCnt; axisId++ )
    00389     {
    00390         const QwtScaleDiv *scaleDiv = plt->axisScaleDiv(axisId);
    00391         if ( isAxisEnabled(axisId) && scaleDiv->isValid() )
    00392         {
    00393             const double center =
    00394                 scaleDiv->lBound() + scaleDiv->range() / 2;
    00395             const double width_2 = scaleDiv->range() / 2 * factor;
    00396
    00397             plt->setAxisScale(axisId, center - width_2, center + width_2);
    00398             doReplot = true;
    00399         }
    00400     }
    00401
    00402     plt->setAutoReplot(autoReplot);
    00403
    00404     if ( doReplot )
    00405         plt->replot();
    00406 }