ctkDoubleSlider.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. /*=========================================================================
  2. Library: CTK
  3. Copyright (c) Kitware Inc.
  4. All rights reserved.
  5. Distributed under a BSD License. See LICENSE.txt file.
  6. This software is distributed "AS IS" WITHOUT ANY WARRANTY; without even
  7. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the above copyright notice for more information.
  9. =========================================================================*/
  10. // QT includes
  11. #include <QDebug>
  12. #include <QHBoxLayout>
  13. // CTK includes
  14. #include "ctkDoubleSlider.h"
  15. // STD includes
  16. #include <limits>
  17. //-----------------------------------------------------------------------------
  18. class ctkDoubleSliderPrivate: public ctkPrivate<ctkDoubleSlider>
  19. {
  20. public:
  21. ctkDoubleSliderPrivate();
  22. int toInt(double _value)const;
  23. double fromInt(int _value)const;
  24. void init();
  25. void updateOffset(double value);
  26. QSlider* Slider;
  27. double Minimum;
  28. double Maximum;
  29. // we should have a Offset and SliderPositionOffset (and MinimumOffset?)
  30. double Offset;
  31. double SingleStep;
  32. double Value;
  33. };
  34. // --------------------------------------------------------------------------
  35. ctkDoubleSliderPrivate::ctkDoubleSliderPrivate()
  36. {
  37. this->Slider = 0;
  38. this->Minimum = 0.;
  39. this->Maximum = 100.;
  40. this->Offset = 0.;
  41. this->SingleStep = 1.;
  42. this->Value = 0.;
  43. }
  44. // --------------------------------------------------------------------------
  45. void ctkDoubleSliderPrivate::init()
  46. {
  47. CTK_P(ctkDoubleSlider);
  48. this->Slider = new QSlider(p);
  49. QHBoxLayout* l = new QHBoxLayout(p);
  50. l->addWidget(this->Slider);
  51. l->setContentsMargins(0,0,0,0);
  52. this->Minimum = this->Slider->minimum();
  53. this->Maximum = this->Slider->maximum();
  54. this->SingleStep = this->Slider->singleStep();
  55. this->Value = this->Slider->value();
  56. p->connect(this->Slider, SIGNAL(valueChanged(int)), p, SLOT(onValueChanged(int)));
  57. p->connect(this->Slider, SIGNAL(sliderMoved(int)), p, SLOT(onSliderMoved(int)));
  58. p->connect(this->Slider, SIGNAL(sliderPressed()), p, SIGNAL(sliderPressed()));
  59. p->connect(this->Slider, SIGNAL(sliderReleased()), p, SIGNAL(sliderReleased()));
  60. }
  61. // --------------------------------------------------------------------------
  62. int ctkDoubleSliderPrivate::toInt(double doubleValue)const
  63. {
  64. double tmp = doubleValue / this->SingleStep;
  65. static const double minInt = std::numeric_limits<int>::min();
  66. static const double maxInt = std::numeric_limits<int>::max();
  67. #ifndef QT_NO_DEBUG
  68. if (tmp < minInt || tmp > maxInt)
  69. {
  70. qWarning("ctkDoubleSliderPrivate::toInt value out of bounds !");
  71. }
  72. #endif
  73. tmp = qBound(minInt, tmp, maxInt);
  74. int intValue = qRound(tmp);
  75. //qDebug() << __FUNCTION__ << doubleValue << tmp << intValue;
  76. return intValue;
  77. }
  78. // --------------------------------------------------------------------------
  79. double ctkDoubleSliderPrivate::fromInt(int intValue)const
  80. {
  81. double doubleValue = this->SingleStep * (this->Offset + intValue) ;
  82. //qDebug() << __FUNCTION__ << intValue << doubleValue;
  83. return doubleValue;
  84. }
  85. // --------------------------------------------------------------------------
  86. void ctkDoubleSliderPrivate::updateOffset(double value)
  87. {
  88. this->Offset = (value / this->SingleStep) - this->toInt(value);
  89. }
  90. // --------------------------------------------------------------------------
  91. ctkDoubleSlider::ctkDoubleSlider(QWidget* _parent) : Superclass(_parent)
  92. {
  93. CTK_INIT_PRIVATE(ctkDoubleSlider);
  94. ctk_d()->init();
  95. }
  96. // --------------------------------------------------------------------------
  97. ctkDoubleSlider::ctkDoubleSlider(Qt::Orientation _orientation, QWidget* _parent)
  98. : Superclass(_parent)
  99. {
  100. CTK_INIT_PRIVATE(ctkDoubleSlider);
  101. ctk_d()->init();
  102. this->setOrientation(_orientation);
  103. }
  104. // --------------------------------------------------------------------------
  105. ctkDoubleSlider::~ctkDoubleSlider()
  106. {
  107. }
  108. // --------------------------------------------------------------------------
  109. void ctkDoubleSlider::setMinimum(double min)
  110. {
  111. CTK_D(ctkDoubleSlider);
  112. d->Minimum = min;
  113. if (d->Minimum >= d->Value)
  114. {
  115. d->updateOffset(d->Minimum);
  116. }
  117. d->Slider->setMinimum(d->toInt(min));
  118. }
  119. // --------------------------------------------------------------------------
  120. void ctkDoubleSlider::setMaximum(double max)
  121. {
  122. CTK_D(ctkDoubleSlider);
  123. d->Maximum = max;
  124. if (d->Maximum <= d->Value)
  125. {
  126. d->updateOffset(d->Maximum);
  127. }
  128. d->Slider->setMaximum(d->toInt(max));
  129. }
  130. // --------------------------------------------------------------------------
  131. void ctkDoubleSlider::setRange(double min, double max)
  132. {
  133. CTK_D(ctkDoubleSlider);
  134. d->Minimum = min;
  135. d->Maximum = max;
  136. if (d->Minimum >= d->Value)
  137. {
  138. d->updateOffset(d->Minimum);
  139. }
  140. if (d->Maximum <= d->Value)
  141. {
  142. d->updateOffset(d->Maximum);
  143. }
  144. d->Slider->setRange(d->toInt(min), d->toInt(max));
  145. }
  146. // --------------------------------------------------------------------------
  147. double ctkDoubleSlider::minimum()const
  148. {
  149. CTK_D(const ctkDoubleSlider);
  150. return d->Minimum;
  151. }
  152. // --------------------------------------------------------------------------
  153. double ctkDoubleSlider::maximum()const
  154. {
  155. CTK_D(const ctkDoubleSlider);
  156. return d->Maximum;
  157. }
  158. // --------------------------------------------------------------------------
  159. double ctkDoubleSlider::sliderPosition()const
  160. {
  161. CTK_D(const ctkDoubleSlider);
  162. return d->fromInt(d->Slider->sliderPosition());
  163. }
  164. // --------------------------------------------------------------------------
  165. void ctkDoubleSlider::setSliderPosition(double newSliderPosition)
  166. {
  167. CTK_D(ctkDoubleSlider);
  168. d->Slider->setSliderPosition(d->toInt(newSliderPosition));
  169. }
  170. // --------------------------------------------------------------------------
  171. double ctkDoubleSlider::value()const
  172. {
  173. CTK_D(const ctkDoubleSlider);
  174. return d->Value;
  175. }
  176. // --------------------------------------------------------------------------
  177. void ctkDoubleSlider::setValue(double newValue)
  178. {
  179. CTK_D(ctkDoubleSlider);
  180. newValue = qBound(d->Minimum, newValue, d->Maximum);
  181. d->updateOffset(newValue);
  182. int newIntValue = d->toInt(newValue);
  183. if (newIntValue != d->Slider->value())
  184. {
  185. // d->Slider will emit a valueChanged signal that is connected to
  186. // ctkDoubleSlider::onValueChanged
  187. d->Slider->setValue(newIntValue);
  188. }
  189. else
  190. {
  191. double oldValue = d->Value;
  192. d->Value = newValue;
  193. // don't emit a valuechanged signal if the new value is quite
  194. // similar to the old value.
  195. if (qAbs(newValue - oldValue) > (d->SingleStep * 0.000000001))
  196. {
  197. emit this->valueChanged(newValue);
  198. }
  199. }
  200. }
  201. // --------------------------------------------------------------------------
  202. double ctkDoubleSlider::singleStep()const
  203. {
  204. CTK_D(const ctkDoubleSlider);
  205. return d->SingleStep;
  206. }
  207. // --------------------------------------------------------------------------
  208. void ctkDoubleSlider::setSingleStep(double newStep)
  209. {
  210. CTK_D(ctkDoubleSlider);
  211. d->SingleStep = newStep;
  212. // update the new values of the QSlider
  213. double _value = d->Value;
  214. d->updateOffset(_value);
  215. bool oldBlockSignals = this->blockSignals(true);
  216. this->setRange(d->Minimum, d->Maximum);
  217. d->Slider->setValue(d->toInt(_value));
  218. d->Value = _value;
  219. this->blockSignals(oldBlockSignals);
  220. }
  221. // --------------------------------------------------------------------------
  222. double ctkDoubleSlider::tickInterval()const
  223. {
  224. CTK_D(const ctkDoubleSlider);
  225. return d->fromInt(d->Slider->tickInterval());
  226. }
  227. // --------------------------------------------------------------------------
  228. void ctkDoubleSlider::setTickInterval(double newTickInterval)
  229. {
  230. CTK_D(ctkDoubleSlider);
  231. d->Slider->setTickInterval(d->toInt(newTickInterval));
  232. }
  233. // --------------------------------------------------------------------------
  234. bool ctkDoubleSlider::hasTracking()const
  235. {
  236. CTK_D(const ctkDoubleSlider);
  237. return d->Slider->hasTracking();
  238. }
  239. // --------------------------------------------------------------------------
  240. void ctkDoubleSlider::setTracking(bool enable)
  241. {
  242. CTK_D(ctkDoubleSlider);
  243. d->Slider->setTracking(enable);
  244. }
  245. // --------------------------------------------------------------------------
  246. void ctkDoubleSlider::triggerAction( QAbstractSlider::SliderAction action)
  247. {
  248. CTK_D(ctkDoubleSlider);
  249. d->Slider->triggerAction(action);
  250. }
  251. // --------------------------------------------------------------------------
  252. Qt::Orientation ctkDoubleSlider::orientation()const
  253. {
  254. CTK_D(const ctkDoubleSlider);
  255. return d->Slider->orientation();
  256. }
  257. // --------------------------------------------------------------------------
  258. void ctkDoubleSlider::setOrientation(Qt::Orientation newOrientation)
  259. {
  260. CTK_D(ctkDoubleSlider);
  261. d->Slider->setOrientation(newOrientation);
  262. }
  263. // --------------------------------------------------------------------------
  264. void ctkDoubleSlider::onValueChanged(int newValue)
  265. {
  266. CTK_D(ctkDoubleSlider);
  267. double doubleNewValue = d->fromInt(newValue);
  268. /*
  269. qDebug() << "onValueChanged: " << newValue << "->"<< d->fromInt(newValue+d->Offset)
  270. << " old: " << d->Value << "->" << d->toInt(d->Value)
  271. << "offset:" << d->Offset << doubleNewValue;
  272. */
  273. if (d->Value == doubleNewValue)
  274. {
  275. return;
  276. }
  277. d->Value = doubleNewValue;
  278. emit this->valueChanged(d->Value);
  279. }
  280. // --------------------------------------------------------------------------
  281. void ctkDoubleSlider::onSliderMoved(int newPosition)
  282. {
  283. CTK_D(const ctkDoubleSlider);
  284. emit this->sliderMoved(d->fromInt(newPosition));
  285. }