ctkDoubleRangeSlider.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  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 "ctkRangeSlider.h"
  15. #include "ctkDoubleRangeSlider.h"
  16. //-----------------------------------------------------------------------------
  17. class ctkDoubleRangeSliderPrivate: public ctkPrivate<ctkDoubleRangeSlider>
  18. {
  19. public:
  20. ctkDoubleRangeSliderPrivate();
  21. int toInt(double _value)const;
  22. double minFromInt(int _value)const;
  23. double maxFromInt(int _value)const;
  24. void init();
  25. void updateMinOffset(double value);
  26. void updateMaxOffset(double value);
  27. ctkRangeSlider* Slider;
  28. double Minimum;
  29. double Maximum;
  30. // we should have a MinValueOffset and MinPositionOffset (and MinimumOffset?)
  31. double MinOffset;
  32. // we should have a MaxValueOffset and MaxPositionOffset (and MaximumOffset?)
  33. double MaxOffset;
  34. double SingleStep;
  35. double MinValue;
  36. double MaxValue;
  37. };
  38. // --------------------------------------------------------------------------
  39. ctkDoubleRangeSliderPrivate::ctkDoubleRangeSliderPrivate()
  40. {
  41. this->Slider = 0;
  42. this->Minimum = 0.;
  43. this->Maximum = 99.;
  44. this->MinOffset = 0.;
  45. this->MaxOffset = 0.;
  46. this->SingleStep = 1.;
  47. this->MinValue = 0.;
  48. this->MaxValue = 99.;
  49. }
  50. // --------------------------------------------------------------------------
  51. void ctkDoubleRangeSliderPrivate::init()
  52. {
  53. CTK_P(ctkDoubleRangeSlider);
  54. this->Slider = new ctkRangeSlider(p);
  55. QHBoxLayout* l = new QHBoxLayout(p);
  56. l->addWidget(this->Slider);
  57. l->setContentsMargins(0,0,0,0);
  58. this->Minimum = this->Slider->minimum();
  59. this->Maximum = this->Slider->maximum();
  60. this->MinValue = this->Slider->minimumValue();
  61. this->MaxValue = this->Slider->maximumValue();
  62. this->SingleStep = this->Slider->singleStep();
  63. p->connect(this->Slider, SIGNAL(minimumValueChanged(int)), p, SLOT(onMinValueChanged(int)));
  64. p->connect(this->Slider, SIGNAL(maximumValueChanged(int)), p, SLOT(onMaxValueChanged(int)));
  65. p->connect(this->Slider, SIGNAL(valuesChanged(int,int)), p, SLOT(onValuesChanged(int,int)));
  66. p->connect(this->Slider, SIGNAL(minimumPositionChanged(int)), p, SLOT(onMinPosChanged(int)));
  67. p->connect(this->Slider, SIGNAL(maximumPositionChanged(int)), p, SLOT(onMaxPosChanged(int)));
  68. p->connect(this->Slider, SIGNAL(positionsChanged(int,int)), p, SLOT(onPositionsChanged(int,int)));
  69. p->connect(this->Slider, SIGNAL(sliderPressed()), p, SIGNAL(sliderPressed()));
  70. p->connect(this->Slider, SIGNAL(sliderReleased()), p, SIGNAL(sliderReleased()));
  71. }
  72. // --------------------------------------------------------------------------
  73. int ctkDoubleRangeSliderPrivate::toInt(double doubleValue)const
  74. {
  75. double tmp = doubleValue / this->SingleStep;
  76. int intValue = qRound(tmp);
  77. return intValue;
  78. }
  79. // --------------------------------------------------------------------------
  80. double ctkDoubleRangeSliderPrivate::minFromInt(int intValue)const
  81. {
  82. double doubleValue = this->SingleStep * (this->MinOffset + intValue) ;
  83. return doubleValue;
  84. }
  85. // --------------------------------------------------------------------------
  86. double ctkDoubleRangeSliderPrivate::maxFromInt(int intValue)const
  87. {
  88. double doubleValue = this->SingleStep * (this->MaxOffset + intValue) ;
  89. return doubleValue;
  90. }
  91. // --------------------------------------------------------------------------
  92. void ctkDoubleRangeSliderPrivate::updateMinOffset(double value)
  93. {
  94. this->MinOffset = (value / this->SingleStep) - this->toInt(value);
  95. }
  96. // --------------------------------------------------------------------------
  97. void ctkDoubleRangeSliderPrivate::updateMaxOffset(double value)
  98. {
  99. this->MaxOffset = (value / this->SingleStep) - this->toInt(value);
  100. }
  101. // --------------------------------------------------------------------------
  102. ctkDoubleRangeSlider::ctkDoubleRangeSlider(QWidget* _parent) : Superclass(_parent)
  103. {
  104. CTK_INIT_PRIVATE(ctkDoubleRangeSlider);
  105. ctk_d()->init();
  106. }
  107. // --------------------------------------------------------------------------
  108. ctkDoubleRangeSlider::ctkDoubleRangeSlider(Qt::Orientation _orientation, QWidget* _parent)
  109. : Superclass(_parent)
  110. {
  111. CTK_INIT_PRIVATE(ctkDoubleRangeSlider);
  112. ctk_d()->init();
  113. this->setOrientation(_orientation);
  114. }
  115. // --------------------------------------------------------------------------
  116. void ctkDoubleRangeSlider::setMinimum(double min)
  117. {
  118. CTK_D(ctkDoubleRangeSlider);
  119. d->Minimum = min;
  120. if (d->Minimum >= d->MinValue)
  121. {// TBD: use same offset
  122. d->updateMinOffset(d->Minimum);
  123. }
  124. if (d->Minimum >= d->MaxValue)
  125. {// TBD: use same offset
  126. d->updateMaxOffset(d->Minimum);
  127. }
  128. d->Slider->setMinimum(d->toInt(min));
  129. }
  130. // --------------------------------------------------------------------------
  131. double ctkDoubleRangeSlider::minimum()const
  132. {
  133. CTK_D(const ctkDoubleRangeSlider);
  134. return d->Minimum;
  135. }
  136. // --------------------------------------------------------------------------
  137. void ctkDoubleRangeSlider::setMaximum(double max)
  138. {
  139. CTK_D(ctkDoubleRangeSlider);
  140. d->Maximum = max;
  141. if (d->Maximum <= d->MinValue)
  142. {// TBD: use same offset
  143. d->updateMinOffset(d->Maximum);
  144. }
  145. if (d->Maximum <= d->MaxValue)
  146. {// TBD: use same offset ?
  147. d->updateMaxOffset(d->Maximum);
  148. }
  149. d->Slider->setMaximum(d->toInt(max));
  150. }
  151. // --------------------------------------------------------------------------
  152. double ctkDoubleRangeSlider::maximum()const
  153. {
  154. CTK_D(const ctkDoubleRangeSlider);
  155. return d->Maximum;
  156. }
  157. // --------------------------------------------------------------------------
  158. void ctkDoubleRangeSlider::setRange(double min, double max)
  159. {
  160. CTK_D(ctkDoubleRangeSlider);
  161. d->Minimum = min;
  162. d->Maximum = max;
  163. if (d->Minimum >= d->MinValue)
  164. {// TBD: use same offset
  165. d->updateMinOffset(d->Minimum);
  166. }
  167. if (d->Minimum >= d->MaxValue)
  168. {// TBD: use same offset
  169. d->updateMaxOffset(d->Minimum);
  170. }
  171. if (d->Maximum <= d->MinValue)
  172. {// TBD: use same offset
  173. d->updateMinOffset(d->Maximum);
  174. }
  175. if (d->Maximum <= d->MaxValue)
  176. {// TBD: use same offset ?
  177. d->updateMaxOffset(d->Maximum);
  178. }
  179. d->Slider->setRange(d->toInt(min), d->toInt(max));
  180. }
  181. // --------------------------------------------------------------------------
  182. double ctkDoubleRangeSlider::minimumPosition()const
  183. {
  184. CTK_D(const ctkDoubleRangeSlider);
  185. return d->minFromInt(d->Slider->minimumPosition());
  186. }
  187. // --------------------------------------------------------------------------
  188. void ctkDoubleRangeSlider::setMinimumPosition(double minPos)
  189. {
  190. CTK_D(ctkDoubleRangeSlider);
  191. d->Slider->setMinimumPosition(d->toInt(minPos));
  192. }
  193. // --------------------------------------------------------------------------
  194. double ctkDoubleRangeSlider::maximumPosition()const
  195. {
  196. CTK_D(const ctkDoubleRangeSlider);
  197. return d->maxFromInt(d->Slider->maximumPosition());
  198. }
  199. // --------------------------------------------------------------------------
  200. void ctkDoubleRangeSlider::setMaximumPosition(double maxPos)
  201. {
  202. CTK_D(ctkDoubleRangeSlider);
  203. d->Slider->setMaximumPosition(d->toInt(maxPos));
  204. }
  205. // --------------------------------------------------------------------------
  206. void ctkDoubleRangeSlider::setPositions(double minPos, double maxPos)
  207. {
  208. CTK_D(ctkDoubleRangeSlider);
  209. d->Slider->setPositions(d->toInt(minPos), d->toInt(maxPos));
  210. }
  211. // --------------------------------------------------------------------------
  212. double ctkDoubleRangeSlider::minimumValue()const
  213. {
  214. CTK_D(const ctkDoubleRangeSlider);
  215. return d->MinValue;
  216. }
  217. // --------------------------------------------------------------------------
  218. void ctkDoubleRangeSlider::setMinimumValue(double newMinValue)
  219. {
  220. CTK_D(ctkDoubleRangeSlider);
  221. newMinValue = qBound(d->Minimum, newMinValue, d->Maximum);
  222. d->updateMinOffset(newMinValue);
  223. if (newMinValue >= d->MaxValue)
  224. {
  225. d->updateMaxOffset(newMinValue);
  226. }
  227. int newIntValue = d->toInt(newMinValue);
  228. if (newIntValue != d->Slider->minimumValue())
  229. {
  230. // d->Slider will emit a minimumValueChanged signal that is connected to
  231. // ctkDoubleSlider::onValueChanged
  232. d->Slider->setMinimumValue(newIntValue);
  233. }
  234. else
  235. {
  236. double oldValue = d->MinValue;
  237. d->MinValue = newMinValue;
  238. // don't emit a valuechanged signal if the new value is quite
  239. // similar to the old value.
  240. if (qAbs(newMinValue - oldValue) > (d->SingleStep * 0.000000001))
  241. {
  242. emit this->minimumValueChanged(newMinValue);
  243. }
  244. }
  245. }
  246. // --------------------------------------------------------------------------
  247. double ctkDoubleRangeSlider::maximumValue()const
  248. {
  249. CTK_D(const ctkDoubleRangeSlider);
  250. return d->MaxValue;
  251. }
  252. // --------------------------------------------------------------------------
  253. void ctkDoubleRangeSlider::setMaximumValue(double newMaxValue)
  254. {
  255. CTK_D(ctkDoubleRangeSlider);
  256. newMaxValue = qBound(d->Minimum, newMaxValue, d->Maximum);
  257. d->updateMaxOffset(newMaxValue);
  258. if (newMaxValue <= d->MinValue)
  259. {
  260. d->updateMinOffset(newMaxValue);
  261. }
  262. int newIntValue = d->toInt(newMaxValue);
  263. if (newIntValue != d->Slider->maximumValue())
  264. {
  265. // d->Slider will emit a maximumValueChanged signal that is connected to
  266. // ctkDoubleSlider::onValueChanged
  267. d->Slider->setMaximumValue(newIntValue);
  268. }
  269. else
  270. {
  271. double oldValue = d->MaxValue;
  272. d->MaxValue = newMaxValue;
  273. // don't emit a valuechanged signal if the new value is quite
  274. // similar to the old value.
  275. if (qAbs(newMaxValue - oldValue) > (d->SingleStep * 0.000000001))
  276. {
  277. emit this->maximumValueChanged(newMaxValue);
  278. }
  279. }
  280. }
  281. // --------------------------------------------------------------------------
  282. void ctkDoubleRangeSlider::setValues(double newMinValue, double newMaxValue)
  283. {
  284. this->setMinimumValue(qMin(newMinValue, newMaxValue));
  285. this->setMaximumValue(qMax(newMinValue, newMaxValue));
  286. }
  287. // --------------------------------------------------------------------------
  288. double ctkDoubleRangeSlider::singleStep()const
  289. {
  290. CTK_D(const ctkDoubleRangeSlider);
  291. return d->SingleStep;
  292. }
  293. // --------------------------------------------------------------------------
  294. void ctkDoubleRangeSlider::setSingleStep(double newStep)
  295. {
  296. CTK_D(ctkDoubleRangeSlider);
  297. d->SingleStep = newStep;
  298. d->updateMinOffset(d->MinValue);
  299. d->updateMaxOffset(d->MaxValue);
  300. // update the new values of the ctkRangeSlider
  301. double _minvalue = d->MinValue;
  302. double _maxvalue = d->MaxValue;
  303. this->setMinimum(d->Minimum);
  304. this->setMaximum(d->Maximum);
  305. this->setMinimumValue(_minvalue);
  306. this->setMinimumPosition(_minvalue);
  307. this->setMaximumValue(_maxvalue);
  308. this->setMaximumPosition(_maxvalue);
  309. }
  310. // --------------------------------------------------------------------------
  311. double ctkDoubleRangeSlider::tickInterval()const
  312. {
  313. CTK_D(const ctkDoubleRangeSlider);
  314. return d->minFromInt(d->Slider->tickInterval());
  315. }
  316. // --------------------------------------------------------------------------
  317. void ctkDoubleRangeSlider::setTickInterval(double newTickInterval)
  318. {
  319. CTK_D(ctkDoubleRangeSlider);
  320. d->Slider->setTickInterval(d->toInt(newTickInterval));
  321. }
  322. // --------------------------------------------------------------------------
  323. bool ctkDoubleRangeSlider::hasTracking()const
  324. {
  325. CTK_D(const ctkDoubleRangeSlider);
  326. return d->Slider->hasTracking();
  327. }
  328. // --------------------------------------------------------------------------
  329. void ctkDoubleRangeSlider::setTracking(bool enable)
  330. {
  331. CTK_D(ctkDoubleRangeSlider);
  332. d->Slider->setTracking(enable);
  333. }
  334. // --------------------------------------------------------------------------
  335. void ctkDoubleRangeSlider::triggerAction( QAbstractSlider::SliderAction action)
  336. {
  337. CTK_D(ctkDoubleRangeSlider);
  338. d->Slider->triggerAction(action);
  339. }
  340. // --------------------------------------------------------------------------
  341. void ctkDoubleRangeSlider::setOrientation(Qt::Orientation newOrientation)
  342. {
  343. CTK_D(ctkDoubleRangeSlider);
  344. d->Slider->setOrientation(newOrientation);
  345. }
  346. // --------------------------------------------------------------------------
  347. Qt::Orientation ctkDoubleRangeSlider::orientation()const
  348. {
  349. CTK_D(const ctkDoubleRangeSlider);
  350. return d->Slider->orientation();
  351. }
  352. // --------------------------------------------------------------------------
  353. void ctkDoubleRangeSlider::onMinValueChanged(int newValue)
  354. {
  355. CTK_D(ctkDoubleRangeSlider);
  356. double doubleNewValue = d->minFromInt(newValue);
  357. if (d->MinValue == doubleNewValue)
  358. {
  359. return;
  360. }
  361. d->MinValue = doubleNewValue;
  362. emit this->minimumValueChanged(d->MinValue);
  363. }
  364. // --------------------------------------------------------------------------
  365. void ctkDoubleRangeSlider::onMaxValueChanged(int newValue)
  366. {
  367. CTK_D(ctkDoubleRangeSlider);
  368. double doubleNewValue = d->maxFromInt(newValue);
  369. if (d->MaxValue == doubleNewValue)
  370. {
  371. return;
  372. }
  373. d->MaxValue = doubleNewValue;
  374. emit this->maximumValueChanged(d->MaxValue);
  375. }
  376. // --------------------------------------------------------------------------
  377. void ctkDoubleRangeSlider::onValuesChanged(int min, int max)
  378. {
  379. CTK_D(ctkDoubleRangeSlider);
  380. emit this->valuesChanged(d->minFromInt(min), d->maxFromInt(max));
  381. }
  382. // --------------------------------------------------------------------------
  383. void ctkDoubleRangeSlider::onMinPosChanged(int newPosition)
  384. {
  385. CTK_D(const ctkDoubleRangeSlider);
  386. emit this->minimumPositionChanged(d->minFromInt(newPosition));
  387. }
  388. // --------------------------------------------------------------------------
  389. void ctkDoubleRangeSlider::onMaxPosChanged(int newPosition)
  390. {
  391. CTK_D(const ctkDoubleRangeSlider);
  392. emit this->maximumPositionChanged(d->maxFromInt(newPosition));
  393. }
  394. // --------------------------------------------------------------------------
  395. void ctkDoubleRangeSlider::onPositionsChanged(int min, int max)
  396. {
  397. CTK_D(const ctkDoubleRangeSlider);
  398. emit this->positionsChanged(d->minFromInt(min), d->maxFromInt(max));
  399. }