ctkDoubleRangeSlider.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 "ctkRangeSlider.h"
00027 #include "ctkDoubleRangeSlider.h"
00028 
00029 
00030 //-----------------------------------------------------------------------------
00031 class ctkDoubleRangeSliderPrivate: public ctkPrivate<ctkDoubleRangeSlider>
00032 {
00033 public:
00034   ctkDoubleRangeSliderPrivate();
00035   
00036   int toInt(double _value)const;
00037   double minFromInt(int _value)const;
00038   double maxFromInt(int _value)const;
00039   void init();
00040   void updateMinOffset(double value);
00041   void updateMaxOffset(double value);
00042 
00043   ctkRangeSlider* Slider;
00044   double Minimum;
00045   double Maximum;
00046   // we should have a MinValueOffset and MinPositionOffset (and MinimumOffset?)
00047   double MinOffset;
00048   // we should have a MaxValueOffset and MaxPositionOffset (and MaximumOffset?)
00049   double MaxOffset;
00050   double SingleStep;
00051   double MinValue;
00052   double MaxValue;
00053 };
00054 
00055 // --------------------------------------------------------------------------
00056 ctkDoubleRangeSliderPrivate::ctkDoubleRangeSliderPrivate()
00057 {
00058   this->Slider = 0;
00059   this->Minimum = 0.;
00060   this->Maximum = 99.;
00061   this->MinOffset = 0.;
00062   this->MaxOffset = 0.;
00063   this->SingleStep = 1.;
00064   this->MinValue = 0.;
00065   this->MaxValue = 99.;
00066 }
00067  
00068 // --------------------------------------------------------------------------
00069 void ctkDoubleRangeSliderPrivate::init()
00070 {
00071   CTK_P(ctkDoubleRangeSlider);
00072   this->Slider = new ctkRangeSlider(p);
00073   QHBoxLayout* l = new QHBoxLayout(p);
00074   l->addWidget(this->Slider);
00075   l->setContentsMargins(0,0,0,0);
00076   
00077   this->Minimum = this->Slider->minimum();
00078   this->Maximum = this->Slider->maximum();
00079   this->MinValue = this->Slider->minimumValue();
00080   this->MaxValue = this->Slider->maximumValue();
00081   this->SingleStep = this->Slider->singleStep();
00082 
00083   p->connect(this->Slider, SIGNAL(minimumValueChanged(int)), p, SLOT(onMinValueChanged(int)));
00084   p->connect(this->Slider, SIGNAL(maximumValueChanged(int)), p, SLOT(onMaxValueChanged(int)));
00085   p->connect(this->Slider, SIGNAL(valuesChanged(int,int)), p, SLOT(onValuesChanged(int,int)));
00086 
00087   p->connect(this->Slider, SIGNAL(minimumPositionChanged(int)), p, SLOT(onMinPosChanged(int)));
00088   p->connect(this->Slider, SIGNAL(maximumPositionChanged(int)), p, SLOT(onMaxPosChanged(int)));
00089   p->connect(this->Slider, SIGNAL(positionsChanged(int,int)), p, SLOT(onPositionsChanged(int,int)));
00090 
00091   p->connect(this->Slider, SIGNAL(sliderPressed()), p, SIGNAL(sliderPressed()));
00092   p->connect(this->Slider, SIGNAL(sliderReleased()), p, SIGNAL(sliderReleased()));
00093 }
00094 
00095 // --------------------------------------------------------------------------
00096 int ctkDoubleRangeSliderPrivate::toInt(double doubleValue)const
00097 {
00098   double tmp = doubleValue / this->SingleStep;
00099   int intValue = qRound(tmp);
00100   return intValue;
00101 }
00102 
00103 // --------------------------------------------------------------------------
00104 double ctkDoubleRangeSliderPrivate::minFromInt(int intValue)const
00105 {
00106   double doubleValue = this->SingleStep * (this->MinOffset + intValue) ;
00107   return doubleValue;
00108 }
00109 
00110 // --------------------------------------------------------------------------
00111 double ctkDoubleRangeSliderPrivate::maxFromInt(int intValue)const
00112 {
00113   double doubleValue = this->SingleStep * (this->MaxOffset + intValue) ;
00114   return doubleValue;
00115 }
00116 
00117 // --------------------------------------------------------------------------
00118 void ctkDoubleRangeSliderPrivate::updateMinOffset(double value)
00119 {
00120   this->MinOffset = (value / this->SingleStep) - this->toInt(value);
00121 }
00122 
00123 // --------------------------------------------------------------------------
00124 void ctkDoubleRangeSliderPrivate::updateMaxOffset(double value)
00125 {
00126   this->MaxOffset = (value / this->SingleStep) - this->toInt(value);
00127 }
00128 
00129 // --------------------------------------------------------------------------
00130 ctkDoubleRangeSlider::ctkDoubleRangeSlider(QWidget* _parent) : Superclass(_parent)
00131 {
00132   CTK_INIT_PRIVATE(ctkDoubleRangeSlider);
00133   ctk_d()->init();
00134 }
00135 
00136 // --------------------------------------------------------------------------
00137 ctkDoubleRangeSlider::ctkDoubleRangeSlider(Qt::Orientation _orientation, QWidget* _parent)
00138   : Superclass(_parent)
00139 {
00140   CTK_INIT_PRIVATE(ctkDoubleRangeSlider);
00141   ctk_d()->init();
00142   this->setOrientation(_orientation);
00143 }
00144 
00145 // --------------------------------------------------------------------------
00146 void ctkDoubleRangeSlider::setMinimum(double min)
00147 {
00148   CTK_D(ctkDoubleRangeSlider);
00149   d->Minimum = min;
00150   if (d->Minimum >= d->MinValue)
00151     {// TBD: use same offset
00152     d->updateMinOffset(d->Minimum);
00153     }
00154   if (d->Minimum >= d->MaxValue)
00155     {// TBD: use same offset
00156     d->updateMaxOffset(d->Minimum);
00157     }
00158   d->Slider->setMinimum(d->toInt(min));
00159 }
00160 
00161 // --------------------------------------------------------------------------
00162 double ctkDoubleRangeSlider::minimum()const
00163 {
00164   CTK_D(const ctkDoubleRangeSlider);
00165   return d->Minimum;
00166 }
00167 
00168 // --------------------------------------------------------------------------
00169 void ctkDoubleRangeSlider::setMaximum(double max)
00170 {
00171   CTK_D(ctkDoubleRangeSlider);
00172   d->Maximum = max;
00173   if (d->Maximum <= d->MinValue)
00174     {// TBD: use same offset
00175     d->updateMinOffset(d->Maximum);
00176     }
00177   if (d->Maximum <= d->MaxValue)
00178     {// TBD: use same offset ?
00179     d->updateMaxOffset(d->Maximum);
00180     }
00181   d->Slider->setMaximum(d->toInt(max));
00182 }
00183 
00184 // --------------------------------------------------------------------------
00185 double ctkDoubleRangeSlider::maximum()const
00186 {
00187   CTK_D(const ctkDoubleRangeSlider);
00188   return d->Maximum;
00189 }
00190 
00191 // --------------------------------------------------------------------------
00192 void ctkDoubleRangeSlider::setRange(double min, double max)
00193 {
00194   CTK_D(ctkDoubleRangeSlider);
00195   d->Minimum = min;
00196   d->Maximum = max;
00197   if (d->Minimum >= d->MinValue)
00198     {// TBD: use same offset
00199     d->updateMinOffset(d->Minimum);
00200     }
00201   if (d->Minimum >= d->MaxValue)
00202     {// TBD: use same offset
00203     d->updateMaxOffset(d->Minimum);
00204     }
00205   if (d->Maximum <= d->MinValue)
00206     {// TBD: use same offset
00207     d->updateMinOffset(d->Maximum);
00208     }
00209   if (d->Maximum <= d->MaxValue)
00210     {// TBD: use same offset ?
00211     d->updateMaxOffset(d->Maximum);
00212     }
00213   d->Slider->setRange(d->toInt(min), d->toInt(max));
00214 }
00215 
00216 // --------------------------------------------------------------------------
00217 double ctkDoubleRangeSlider::minimumPosition()const
00218 {
00219   CTK_D(const ctkDoubleRangeSlider);
00220   return d->minFromInt(d->Slider->minimumPosition());
00221 }
00222 
00223 // --------------------------------------------------------------------------
00224 void ctkDoubleRangeSlider::setMinimumPosition(double minPos)
00225 {
00226   CTK_D(ctkDoubleRangeSlider);
00227   d->Slider->setMinimumPosition(d->toInt(minPos));
00228 }
00229 
00230 // --------------------------------------------------------------------------
00231 double ctkDoubleRangeSlider::maximumPosition()const
00232 {
00233   CTK_D(const ctkDoubleRangeSlider);
00234   return d->maxFromInt(d->Slider->maximumPosition());
00235 }
00236 
00237 // --------------------------------------------------------------------------
00238 void ctkDoubleRangeSlider::setMaximumPosition(double maxPos)
00239 {
00240   CTK_D(ctkDoubleRangeSlider);
00241   d->Slider->setMaximumPosition(d->toInt(maxPos));
00242 }
00243 
00244 // --------------------------------------------------------------------------
00245 void ctkDoubleRangeSlider::setPositions(double minPos, double maxPos)
00246 {
00247   CTK_D(ctkDoubleRangeSlider);
00248   d->Slider->setPositions(d->toInt(minPos), d->toInt(maxPos));
00249 }
00250 
00251 // --------------------------------------------------------------------------
00252 double ctkDoubleRangeSlider::minimumValue()const
00253 {
00254   CTK_D(const ctkDoubleRangeSlider);
00255   return d->MinValue;
00256 }
00257 
00258 // --------------------------------------------------------------------------
00259 void ctkDoubleRangeSlider::setMinimumValue(double newMinValue)
00260 {
00261   CTK_D(ctkDoubleRangeSlider);
00262   newMinValue = qBound(d->Minimum, newMinValue, d->Maximum);
00263   d->updateMinOffset(newMinValue);  
00264   if (newMinValue >= d->MaxValue)
00265     {
00266     d->updateMaxOffset(newMinValue);
00267     }
00268   int newIntValue = d->toInt(newMinValue);
00269   if (newIntValue != d->Slider->minimumValue())
00270     {
00271     // d->Slider will emit a minimumValueChanged signal that is connected to
00272     // ctkDoubleSlider::onValueChanged
00273     d->Slider->setMinimumValue(newIntValue);
00274     }
00275   else
00276     {
00277     double oldValue = d->MinValue;
00278     d->MinValue = newMinValue;
00279     // don't emit a valuechanged signal if the new value is quite 
00280     // similar to the old value.
00281     if (qAbs(newMinValue - oldValue) > (d->SingleStep * 0.000000001))
00282       {
00283       emit this->minimumValueChanged(newMinValue);
00284       }
00285     }
00286 }
00287 
00288 // --------------------------------------------------------------------------
00289 double ctkDoubleRangeSlider::maximumValue()const
00290 {
00291   CTK_D(const ctkDoubleRangeSlider);
00292   return d->MaxValue;
00293 }
00294 
00295 // --------------------------------------------------------------------------
00296 void ctkDoubleRangeSlider::setMaximumValue(double newMaxValue)
00297 {
00298   CTK_D(ctkDoubleRangeSlider);
00299   newMaxValue = qBound(d->Minimum, newMaxValue, d->Maximum);
00300   d->updateMaxOffset(newMaxValue);
00301   if (newMaxValue <= d->MinValue)
00302     {
00303     d->updateMinOffset(newMaxValue);
00304     }
00305   int newIntValue = d->toInt(newMaxValue);
00306   if (newIntValue != d->Slider->maximumValue())
00307     {
00308     // d->Slider will emit a maximumValueChanged signal that is connected to
00309     // ctkDoubleSlider::onValueChanged
00310     d->Slider->setMaximumValue(newIntValue);
00311     }
00312   else
00313     {
00314     double oldValue = d->MaxValue;
00315     d->MaxValue = newMaxValue;
00316     // don't emit a valuechanged signal if the new value is quite 
00317     // similar to the old value.
00318     if (qAbs(newMaxValue - oldValue) > (d->SingleStep * 0.000000001))
00319       {
00320       emit this->maximumValueChanged(newMaxValue);
00321       }
00322     }
00323 }
00324 
00325 // --------------------------------------------------------------------------
00326 void ctkDoubleRangeSlider::setValues(double newMinValue, double newMaxValue)
00327 {
00328   this->setMinimumValue(qMin(newMinValue, newMaxValue));
00329   this->setMaximumValue(qMax(newMinValue, newMaxValue));
00330 }
00331 
00332 // --------------------------------------------------------------------------
00333 double ctkDoubleRangeSlider::singleStep()const
00334 {
00335   CTK_D(const ctkDoubleRangeSlider);
00336   return d->SingleStep;
00337 }
00338 
00339 // --------------------------------------------------------------------------
00340 void ctkDoubleRangeSlider::setSingleStep(double newStep)
00341 {
00342   CTK_D(ctkDoubleRangeSlider);
00343   d->SingleStep = newStep;
00344   // The following can fire A LOT of signals that shouldn't be 
00345   // fired.
00346   bool oldBlockSignals = this->blockSignals(true);
00347   d->updateMinOffset(d->MinValue);
00348   d->updateMaxOffset(d->MaxValue);
00349   // update the new values of the ctkRangeSlider
00350   double _minvalue = d->MinValue;
00351   double _maxvalue = d->MaxValue;
00352   // calling setMinimum or setMaximum can change the values MinimumValue
00353   // and MaximumValue, this is why we re-set them later.  
00354   this->setMinimum(d->Minimum);
00355   this->setMaximum(d->Maximum);
00356   this->setMinimumValue(_minvalue);
00357   this->setMinimumPosition(_minvalue);
00358   this->setMaximumValue(_maxvalue);
00359   this->setMaximumPosition(_maxvalue);
00360   this->blockSignals(oldBlockSignals);
00361 }
00362 
00363 // --------------------------------------------------------------------------
00364 double ctkDoubleRangeSlider::tickInterval()const
00365 {
00366   CTK_D(const ctkDoubleRangeSlider);
00367   return d->minFromInt(d->Slider->tickInterval());
00368 }
00369 
00370 // --------------------------------------------------------------------------
00371 void ctkDoubleRangeSlider::setTickInterval(double newTickInterval)
00372 {
00373   CTK_D(ctkDoubleRangeSlider);
00374   d->Slider->setTickInterval(d->toInt(newTickInterval));
00375 }
00376 
00377 // --------------------------------------------------------------------------
00378 bool ctkDoubleRangeSlider::hasTracking()const
00379 {
00380   CTK_D(const ctkDoubleRangeSlider);
00381   return d->Slider->hasTracking();
00382 }
00383 
00384 // --------------------------------------------------------------------------
00385 void ctkDoubleRangeSlider::setTracking(bool enable)
00386 {
00387   CTK_D(ctkDoubleRangeSlider);
00388   d->Slider->setTracking(enable);
00389 }
00390 
00391 // --------------------------------------------------------------------------
00392 void ctkDoubleRangeSlider::triggerAction( QAbstractSlider::SliderAction action)
00393 {
00394   CTK_D(ctkDoubleRangeSlider);
00395   d->Slider->triggerAction(action);
00396 }
00397 
00398 // --------------------------------------------------------------------------
00399 void ctkDoubleRangeSlider::setOrientation(Qt::Orientation newOrientation)
00400 {
00401   CTK_D(ctkDoubleRangeSlider);
00402   d->Slider->setOrientation(newOrientation);
00403 }
00404 
00405 // --------------------------------------------------------------------------
00406 Qt::Orientation ctkDoubleRangeSlider::orientation()const
00407 {
00408   CTK_D(const ctkDoubleRangeSlider);
00409   return d->Slider->orientation();
00410 }
00411 
00412 // --------------------------------------------------------------------------
00413 void ctkDoubleRangeSlider::onMinValueChanged(int newValue)
00414 {
00415   CTK_D(ctkDoubleRangeSlider);
00416   double doubleNewValue = d->minFromInt(newValue);
00417   if (d->MinValue == doubleNewValue)
00418     {
00419     return;
00420     }
00421   d->MinValue = doubleNewValue;
00422   emit this->minimumValueChanged(d->MinValue);
00423 }
00424 
00425 // --------------------------------------------------------------------------
00426 void ctkDoubleRangeSlider::onMaxValueChanged(int newValue)
00427 {
00428   CTK_D(ctkDoubleRangeSlider);
00429   double doubleNewValue = d->maxFromInt(newValue);
00430   if (d->MaxValue == doubleNewValue)
00431     {
00432     return;
00433     }
00434   d->MaxValue = doubleNewValue;
00435   emit this->maximumValueChanged(d->MaxValue);
00436 }
00437 
00438 // --------------------------------------------------------------------------
00439 void ctkDoubleRangeSlider::onValuesChanged(int min, int max)
00440 {
00441   CTK_D(ctkDoubleRangeSlider);
00442   emit this->valuesChanged(d->minFromInt(min), d->maxFromInt(max));
00443 }
00444 
00445 // --------------------------------------------------------------------------
00446 void ctkDoubleRangeSlider::onMinPosChanged(int newPosition)
00447 {
00448   CTK_D(const ctkDoubleRangeSlider);
00449   emit this->minimumPositionChanged(d->minFromInt(newPosition));
00450 }
00451 
00452 // --------------------------------------------------------------------------
00453 void ctkDoubleRangeSlider::onMaxPosChanged(int newPosition)
00454 {
00455   CTK_D(const ctkDoubleRangeSlider);
00456   emit this->maximumPositionChanged(d->maxFromInt(newPosition));
00457 }
00458 // --------------------------------------------------------------------------
00459 void ctkDoubleRangeSlider::onPositionsChanged(int min, int max)
00460 {
00461   CTK_D(const ctkDoubleRangeSlider);
00462   emit this->positionsChanged(d->minFromInt(min), d->maxFromInt(max));
00463 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines