ctkDoubleSlider.cpp

Go to the documentation of this file.
00001 /*=========================================================================
00002 
00003   Library:   CTK
00004  
00005   Copyright (c) 2010  Kitware Inc.
00006 
00007   Licensed under the Apache License, Version 2.0 (the "License");
00008   you may not use this file except in compliance with the License.
00009   You may obtain a copy of the License at
00010 
00011       http://www.commontk.org/LICENSE
00012 
00013   Unless required by applicable law or agreed to in writing, software
00014   distributed under the License is distributed on an "AS IS" BASIS,
00015   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016   See the License for the specific language governing permissions and
00017   limitations under the License.
00018  
00019 =========================================================================*/
00020 
00021 // QT includes
00022 #include <QDebug>
00023 #include <QHBoxLayout>
00024 
00025 // CTK includes
00026 #include "ctkDoubleSlider.h"
00027 
00028 // STD includes
00029 #include <limits>
00030 
00031 //-----------------------------------------------------------------------------
00032 class ctkDoubleSliderPrivate: public ctkPrivate<ctkDoubleSlider>
00033 {
00034   public:
00035   ctkDoubleSliderPrivate();
00036   int toInt(double _value)const;
00037   double fromInt(int _value)const;
00038   void init();
00039   void updateOffset(double value);
00040 
00041   QSlider*    Slider;
00042   double      Minimum;
00043   double      Maximum;
00044   // we should have a Offset and SliderPositionOffset (and MinimumOffset?)
00045   double      Offset;
00046   double      SingleStep;
00047   double      Value;
00048 };
00049 
00050 // --------------------------------------------------------------------------
00051 ctkDoubleSliderPrivate::ctkDoubleSliderPrivate()
00052 {
00053   this->Slider = 0;
00054   this->Minimum = 0.;
00055   this->Maximum = 100.;
00056   this->Offset = 0.;
00057   this->SingleStep = 1.;
00058   this->Value = 0.;
00059 }
00060 
00061 // --------------------------------------------------------------------------
00062 void ctkDoubleSliderPrivate::init()
00063 {
00064   CTK_P(ctkDoubleSlider);
00065   this->Slider = new QSlider(p);
00066   QHBoxLayout* l = new QHBoxLayout(p);
00067   l->addWidget(this->Slider);
00068   l->setContentsMargins(0,0,0,0);
00069   
00070   this->Minimum = this->Slider->minimum();
00071   this->Maximum = this->Slider->maximum();
00072   this->SingleStep = this->Slider->singleStep();
00073   this->Value = this->Slider->value();
00074 
00075   p->connect(this->Slider, SIGNAL(valueChanged(int)), p, SLOT(onValueChanged(int)));
00076   p->connect(this->Slider, SIGNAL(sliderMoved(int)), p, SLOT(onSliderMoved(int)));
00077   p->connect(this->Slider, SIGNAL(sliderPressed()), p, SIGNAL(sliderPressed()));
00078   p->connect(this->Slider, SIGNAL(sliderReleased()), p, SIGNAL(sliderReleased()));
00079 }
00080   
00081 // --------------------------------------------------------------------------
00082 int ctkDoubleSliderPrivate::toInt(double doubleValue)const
00083 {
00084   double tmp = doubleValue / this->SingleStep;
00085   static const double minInt = std::numeric_limits<int>::min();
00086   static const double maxInt = std::numeric_limits<int>::max();
00087 #ifndef QT_NO_DEBUG
00088   if (tmp < minInt || tmp > maxInt)
00089     {
00090     qWarning("ctkDoubleSliderPrivate::toInt value out of bounds !");
00091     }
00092 #endif
00093   tmp = qBound(minInt, tmp, maxInt);
00094   int intValue = qRound(tmp);
00095   //qDebug() << __FUNCTION__ << doubleValue << tmp << intValue;
00096   return intValue;
00097 }
00098 
00099 // --------------------------------------------------------------------------
00100 double ctkDoubleSliderPrivate::fromInt(int intValue)const
00101 {
00102   double doubleValue = this->SingleStep * (this->Offset + intValue) ;
00103   //qDebug() << __FUNCTION__ << intValue << doubleValue;
00104   return doubleValue;
00105 }
00106 
00107 // --------------------------------------------------------------------------
00108 void ctkDoubleSliderPrivate::updateOffset(double value)
00109 {
00110   this->Offset = (value / this->SingleStep) - this->toInt(value);
00111 }
00112 
00113 // --------------------------------------------------------------------------
00114 ctkDoubleSlider::ctkDoubleSlider(QWidget* _parent) : Superclass(_parent)
00115 {
00116   CTK_INIT_PRIVATE(ctkDoubleSlider);
00117   ctk_d()->init();
00118 }
00119 
00120 // --------------------------------------------------------------------------
00121 ctkDoubleSlider::ctkDoubleSlider(Qt::Orientation _orientation, QWidget* _parent)
00122   : Superclass(_parent)
00123 {
00124   CTK_INIT_PRIVATE(ctkDoubleSlider);
00125   ctk_d()->init();
00126   this->setOrientation(_orientation);
00127 }
00128 
00129 // --------------------------------------------------------------------------
00130 ctkDoubleSlider::~ctkDoubleSlider()
00131 {
00132 }
00133 
00134 // --------------------------------------------------------------------------
00135 void ctkDoubleSlider::setMinimum(double min)
00136 {
00137   CTK_D(ctkDoubleSlider);
00138   d->Minimum = min;
00139   if (d->Minimum >= d->Value)
00140     {
00141     d->updateOffset(d->Minimum);
00142     }
00143   d->Slider->setMinimum(d->toInt(min));
00144 }
00145 
00146 // --------------------------------------------------------------------------
00147 void ctkDoubleSlider::setMaximum(double max)
00148 {
00149   CTK_D(ctkDoubleSlider);
00150   d->Maximum = max;
00151   if (d->Maximum <= d->Value)
00152     {
00153     d->updateOffset(d->Maximum);
00154     }
00155   d->Slider->setMaximum(d->toInt(max));
00156 }
00157 
00158 // --------------------------------------------------------------------------
00159 void ctkDoubleSlider::setRange(double min, double max)
00160 {
00161   CTK_D(ctkDoubleSlider);
00162   d->Minimum = min;
00163   d->Maximum = max;
00164   
00165   if (d->Minimum >= d->Value)
00166     {
00167     d->updateOffset(d->Minimum);
00168     }
00169   if (d->Maximum <= d->Value)
00170     {
00171     d->updateOffset(d->Maximum);
00172     }
00173   
00174   d->Slider->setRange(d->toInt(min), d->toInt(max));
00175 }
00176 
00177 // --------------------------------------------------------------------------
00178 double ctkDoubleSlider::minimum()const
00179 {
00180   CTK_D(const ctkDoubleSlider);
00181   return d->Minimum;
00182 }
00183 
00184 // --------------------------------------------------------------------------
00185 double ctkDoubleSlider::maximum()const
00186 {
00187   CTK_D(const ctkDoubleSlider);
00188   return d->Maximum;
00189 }
00190 
00191 // --------------------------------------------------------------------------
00192 double ctkDoubleSlider::sliderPosition()const
00193 {
00194   CTK_D(const ctkDoubleSlider);
00195   return d->fromInt(d->Slider->sliderPosition());
00196 }
00197 
00198 // --------------------------------------------------------------------------
00199 void ctkDoubleSlider::setSliderPosition(double newSliderPosition)
00200 {
00201   CTK_D(ctkDoubleSlider);
00202   d->Slider->setSliderPosition(d->toInt(newSliderPosition));
00203 }
00204 
00205 // --------------------------------------------------------------------------
00206 double ctkDoubleSlider::value()const
00207 {
00208   CTK_D(const ctkDoubleSlider);
00209   return d->Value;
00210 }
00211 
00212 // --------------------------------------------------------------------------
00213 void ctkDoubleSlider::setValue(double newValue)
00214 {
00215   CTK_D(ctkDoubleSlider);
00216   newValue = qBound(d->Minimum, newValue, d->Maximum);
00217   d->updateOffset(newValue);
00218   int newIntValue = d->toInt(newValue);
00219   if (newIntValue != d->Slider->value())
00220     {
00221     // d->Slider will emit a valueChanged signal that is connected to
00222     // ctkDoubleSlider::onValueChanged
00223     d->Slider->setValue(newIntValue);
00224     }
00225   else
00226     {
00227     double oldValue = d->Value;
00228     d->Value = newValue;
00229     // don't emit a valuechanged signal if the new value is quite 
00230     // similar to the old value.
00231     if (qAbs(newValue - oldValue) > (d->SingleStep * 0.000000001))
00232       {
00233       emit this->valueChanged(newValue);
00234       }
00235     }
00236 }
00237 
00238 // --------------------------------------------------------------------------
00239 double ctkDoubleSlider::singleStep()const
00240 {
00241   CTK_D(const ctkDoubleSlider);
00242   return d->SingleStep;
00243 }
00244 
00245 // --------------------------------------------------------------------------
00246 void ctkDoubleSlider::setSingleStep(double newStep)
00247 {
00248   CTK_D(ctkDoubleSlider);
00249   d->SingleStep = newStep;
00250   // update the new values of the QSlider
00251   double _value = d->Value;
00252   d->updateOffset(_value);
00253   bool oldBlockSignals = this->blockSignals(true);
00254   this->setRange(d->Minimum, d->Maximum);
00255   d->Slider->setValue(d->toInt(_value));
00256   d->Value = _value;
00257   this->blockSignals(oldBlockSignals);
00258 }
00259 
00260 // --------------------------------------------------------------------------
00261 double ctkDoubleSlider::tickInterval()const
00262 {
00263   CTK_D(const ctkDoubleSlider);
00264   return d->fromInt(d->Slider->tickInterval());
00265 }
00266 
00267 // --------------------------------------------------------------------------
00268 void ctkDoubleSlider::setTickInterval(double newTickInterval)
00269 {
00270   CTK_D(ctkDoubleSlider);
00271   d->Slider->setTickInterval(d->toInt(newTickInterval));
00272 }
00273 
00274 // --------------------------------------------------------------------------
00275 bool ctkDoubleSlider::hasTracking()const
00276 {
00277   CTK_D(const ctkDoubleSlider);
00278   return d->Slider->hasTracking();
00279 }
00280 
00281 // --------------------------------------------------------------------------
00282 void ctkDoubleSlider::setTracking(bool enable)
00283 {
00284   CTK_D(ctkDoubleSlider);
00285   d->Slider->setTracking(enable);
00286 }
00287 
00288 // --------------------------------------------------------------------------
00289 void ctkDoubleSlider::triggerAction( QAbstractSlider::SliderAction action)
00290 {
00291   CTK_D(ctkDoubleSlider);
00292   d->Slider->triggerAction(action);
00293 }
00294 
00295 // --------------------------------------------------------------------------
00296 Qt::Orientation ctkDoubleSlider::orientation()const
00297 {
00298   CTK_D(const ctkDoubleSlider);
00299   return d->Slider->orientation();
00300 }
00301 
00302 // --------------------------------------------------------------------------
00303 void ctkDoubleSlider::setOrientation(Qt::Orientation newOrientation)
00304 {
00305   CTK_D(ctkDoubleSlider);
00306   d->Slider->setOrientation(newOrientation);
00307 }
00308 
00309 // --------------------------------------------------------------------------
00310 void ctkDoubleSlider::onValueChanged(int newValue)
00311 {
00312   CTK_D(ctkDoubleSlider);
00313   double doubleNewValue = d->fromInt(newValue);
00314 /*
00315   qDebug() << "onValueChanged: " << newValue << "->"<< d->fromInt(newValue+d->Offset) 
00316            << " old: " << d->Value << "->" << d->toInt(d->Value) 
00317            << "offset:" << d->Offset << doubleNewValue;
00318 */
00319   if (d->Value == doubleNewValue)
00320     {
00321     return;
00322     }
00323   d->Value = doubleNewValue;
00324   emit this->valueChanged(d->Value);
00325 }
00326 
00327 // --------------------------------------------------------------------------
00328 void ctkDoubleSlider::onSliderMoved(int newPosition)
00329 {
00330   CTK_D(const ctkDoubleSlider);
00331   emit this->sliderMoved(d->fromInt(newPosition));
00332 }
00333 
00334 
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines