# qwt_double_range.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 #include "qwt_double_range.h"
    00011 #include "qwt_math.h"
    00012
    00013 static double MinRelStep = 1.0e-10;
    00014 static double DefaultRelStep = 1.0e-2;
    00015 static double MinEps = 1.0e-10;
    00016
    00021 QwtDoubleRange::QwtDoubleRange():
    00022     d_minValue(0.0),
    00023     d_maxValue(0.0),
    00024     d_step(1.0),
    00025     d_pageSize(1),
    00026     d_isValid(false),
    00027     d_value(0.0),
    00028     d_exactValue(0.0),
    00029     d_exactPrevValue(0.0),
    00030     d_prevValue(0.0),
    00031     d_periodic(false)
    00032 {
    00033 }
    00034
    00036 QwtDoubleRange::~QwtDoubleRange()
    00037 {
    00038 }
    00039
    00041 void QwtDoubleRange::setValid(bool isValid)
    00042 {
    00043     if ( isValid != d_isValid )
    00044     {
    00045         d_isValid = isValid;
    00046         valueChange();
    00047     }
    00048 }
    00049
    00051 bool QwtDoubleRange::isValid() const
    00052 {
    00053     return d_isValid;
    00054 }
    00055
    00064 void QwtDoubleRange::setNewValue(double x, bool align)
    00065 {
    00066     double vmin,vmax;
    00067
    00068     d_prevValue = d_value;
    00069
    00070     vmin = qwtMin(d_minValue, d_maxValue);
    00071     vmax = qwtMax(d_minValue, d_maxValue);
    00072
    00073     //
    00074     // Range check
    00075     //
    00076     if (x < vmin)
    00077     {
    00078         if ((d_periodic) && (vmin != vmax))
    00079            d_value = x + ceil( (vmin - x) / (vmax - vmin ) )
    00080               * (vmax - vmin);
    00081         else
    00082            d_value = vmin;
    00083     }
    00084     else if (x > vmax)
    00085     {
    00086         if ((d_periodic) && (vmin != vmax))
    00087            d_value = x - ceil( ( x - vmax) / (vmax - vmin ))
    00088               * (vmax - vmin);
    00089         else
    00090            d_value = vmax;
    00091     }
    00092     else
    00093        d_value = x;
    00094
    00095     d_exactPrevValue = d_exactValue;
    00096     d_exactValue = d_value;
    00097
    00098     // align to grid
    00099     if (align)
    00100     {
    00101         if (d_step != 0.0)
    00102            d_value = d_minValue +
    00103              qRound((d_value - d_minValue) / d_step) * d_step;
    00104         else
    00105            d_value = d_minValue;
    00106
    00107         // correct rounding error at the border
    00108         if (fabs(d_value - d_maxValue) < MinEps * qwtAbs(d_step))
    00109            d_value = d_maxValue;
    00110
    00111         // correct rounding error if value = 0
    00112         if (fabs(d_value) < MinEps * qwtAbs(d_step))
    00113            d_value = 0.0;
    00114     }
    00115
    00116     if (!d_isValid || d_prevValue != d_value)
    00117     {
    00118         d_isValid = true;
    00119         valueChange();
    00120     }
    00121 }
    00122
    00132 void QwtDoubleRange::fitValue(double x)
    00133 {
    00134     setNewValue(x, true);
    00135 }
    00136
    00137
    00147 void QwtDoubleRange::setValue(double x)
    00148 {
    00149     setNewValue(x, false);
    00150 }
    00151
    00169 void QwtDoubleRange::setRange(double vmin, double vmax, double vstep, int pageSize)
    00170 {
    00171     bool rchg = ((d_maxValue != vmax) || (d_minValue != vmin));
    00172
    00173     if (rchg)
    00174     {
    00175         d_minValue = vmin;
    00176         d_maxValue = vmax;
    00177     }
    00178
    00179     //
    00180     // look if the step width has an acceptable
    00181     // value or otherwise change it.
    00182     //
    00183     setStep(vstep);
    00184
    00185     //
    00186     // limit page size
    00187     //
    00188     d_pageSize = qwtLim(pageSize,0,
    00189         int(qwtAbs((d_maxValue - d_minValue) / d_step)));
    00190
    00191     //
    00192     // If the value lies out of the range, it
    00193     // will be changed. Note that it will not be adjusted to
    00194     // the new step width.
    00195     setNewValue(d_value, false);
    00196
    00197     // call notifier after the step width has been
    00198     // adjusted.
    00199     if (rchg)
    00200        rangeChange();
    00201 }
    00202
    00208 void QwtDoubleRange::setStep(double vstep)
    00209 {
    00210     double intv = d_maxValue - d_minValue;
    00211
    00212     double newStep;
    00213     if (vstep == 0.0)
    00214        newStep = intv * DefaultRelStep;
    00215     else
    00216     {
    00217         if ((intv > 0) && (vstep < 0) || (intv < 0) && (vstep > 0))
    00218            newStep = -vstep;
    00219         else
    00220            newStep = vstep;
    00221
    00222         if ( fabs(newStep) < fabs(MinRelStep * intv) )
    00223            newStep = MinRelStep * intv;
    00224     }
    00225
    00226     if (newStep != d_step)
    00227     {
    00228         d_step = newStep;
    00229         stepChange();
    00230     }
    00231 }
    00232
    00233
    00248 void QwtDoubleRange::setPeriodic(bool tf)
    00249 {
    00250     d_periodic = tf;
    00251 }
    00252
    00259 void QwtDoubleRange::incValue(int nSteps)
    00260 {
    00261     if ( isValid() )
    00262         setNewValue(d_value + double(nSteps) * d_step, true);
    00263 }
    00264
    00271 void QwtDoubleRange::incPages(int nPages)
    00272 {
    00273     if ( isValid() )
    00274         setNewValue(d_value + double(nPages) * double(d_pageSize) * d_step, true);
    00275 }
    00276
    00283 void QwtDoubleRange::valueChange()
    00284 {
    00285 }
    00286
    00287
    00294 void QwtDoubleRange::rangeChange()
    00295 {
    00296 }
    00297
    00298
    00305 void QwtDoubleRange::stepChange()
    00306 {
    00307 }
    00308
    00313 double QwtDoubleRange::step() const
    00314 {
    00315     return qwtAbs(d_step);
    00316 }
    00317
    00326 double QwtDoubleRange::maxValue() const
    00327 {
    00328     return d_maxValue;
    00329 }
    00330
    00339 double QwtDoubleRange::minValue() const
    00340 {
    00341     return d_minValue;
    00342 }
    00343
    00348 bool QwtDoubleRange::periodic() const
    00349 {
    00350     return d_periodic;
    00351 }
    00352
    00354 int QwtDoubleRange::pageSize() const
    00355 {
    00356     return d_pageSize;
    00357 }
    00358
    00360 double QwtDoubleRange::value() const
    00361 {
    00362     return d_value;
    00363 }
    00364
    00374 double QwtDoubleRange::exactValue() const
    00375 {
    00376     return d_exactValue;
    00377 }
    00378
    00380 double QwtDoubleRange::exactPrevValue() const
    00381 {
    00382     return d_exactPrevValue;
    00383 }
    00384
    00386 double QwtDoubleRange::prevValue() const
    00387 {
    00388     return d_prevValue;
    00389 }