GOFIGURE2  0.9.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ctkDoubleSlider.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Library: CTK
4 
5  Copyright (c) Kitware Inc.
6 
7  Licensed under the Apache License, Version 2.0 (the "License");
8  you may not use this file except in compliance with the License.
9  You may obtain a copy of the License at
10 
11  http://www.commontk.org/LICENSE
12 
13  Unless required by applicable law or agreed to in writing, software
14  distributed under the License is distributed on an "AS IS" BASIS,
15  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  See the License for the specific language governing permissions and
17  limitations under the License.
18 
19 =========================================================================*/
20 
21 // QT includes
22 #include <QDebug>
23 #include <QHBoxLayout>
24 
25 // CTK includes
26 #include "ctkDoubleSlider.h"
27 
28 // STD includes
29 #include <limits>
30 
31 //-----------------------------------------------------------------------------
33 {
35 protected:
37 public:
39  int toInt(double _value)const;
40  double fromInt(int _value)const;
41  void init();
42  void updateOffset(double value);
43 
45  double Minimum;
46  double Maximum;
48  // we should have a Offset and SliderPositionOffset (and MinimumOffset?)
49  double Offset;
50  double SingleStep;
51  double Value;
52 };
53 
54 // --------------------------------------------------------------------------
56  :q_ptr(&object)
57 {
58  this->Slider = 0;
59  this->Minimum = 0.;
60  this->Maximum = 100.;
61  this->SettingRange = false;
62  this->Offset = 0.;
63  this->SingleStep = 1.;
64  this->Value = 0.;
65 }
66 
67 // --------------------------------------------------------------------------
69 {
70  Q_Q(ctkDoubleSlider);
71  this->Slider = new QSlider(q);
72  QHBoxLayout* l = new QHBoxLayout(q);
73  l->addWidget(this->Slider);
74  l->setContentsMargins(0,0,0,0);
75 
76  this->Minimum = this->Slider->minimum();
77  this->Maximum = this->Slider->maximum();
78  this->SingleStep = this->Slider->singleStep();
79  this->Value = this->Slider->value();
80 
81  q->connect(this->Slider, SIGNAL(valueChanged(int)), q, SLOT(onValueChanged(int)));
82  q->connect(this->Slider, SIGNAL(sliderMoved(int)), q, SLOT(onSliderMoved(int)));
83  q->connect(this->Slider, SIGNAL(sliderPressed()), q, SIGNAL(sliderPressed()));
84  q->connect(this->Slider, SIGNAL(sliderReleased()), q, SIGNAL(sliderReleased()));
85  q->connect(this->Slider, SIGNAL(rangeChanged(int, int)),
86  q, SLOT(onRangeChanged(int, int)));
87 
88  q->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed,
89  QSizePolicy::Slider));
90 }
91 
92 // --------------------------------------------------------------------------
93 int ctkDoubleSliderPrivate::toInt(double doubleValue)const
94 {
95  double tmp = doubleValue / this->SingleStep;
96  static const double minInt = std::numeric_limits<int>::min();
97  static const double maxInt = std::numeric_limits<int>::max();
98 #ifndef QT_NO_DEBUG
99  if (tmp < minInt || tmp > maxInt)
100  {
101  qWarning("ctkDoubleSliderPrivate::toInt value out of bounds !");
102  }
103 #endif
104  tmp = qBound(minInt, tmp, maxInt);
105  int intValue = qRound(tmp);
106  //qDebug() << __FUNCTION__ << doubleValue << tmp << intValue;
107  return intValue;
108 }
109 
110 // --------------------------------------------------------------------------
111 double ctkDoubleSliderPrivate::fromInt(int intValue)const
112 {
113  double doubleValue = this->SingleStep * (this->Offset + intValue) ;
114  //qDebug() << __FUNCTION__ << intValue << doubleValue;
115  return doubleValue;
116 }
117 
118 // --------------------------------------------------------------------------
120 {
121  this->Offset = (value / this->SingleStep) - this->toInt(value);
122 }
123 
124 // --------------------------------------------------------------------------
126  , d_ptr(new ctkDoubleSliderPrivate(*this))
127 {
128  Q_D(ctkDoubleSlider);
129  d->init();
130 }
131 
132 // --------------------------------------------------------------------------
133 ctkDoubleSlider::ctkDoubleSlider(Qt::Orientation _orientation, QWidget* _parent)
134  : Superclass(_parent)
135  , d_ptr(new ctkDoubleSliderPrivate(*this))
136 {
137  Q_D(ctkDoubleSlider);
138  d->init();
139  this->setOrientation(_orientation);
140 }
141 
142 // --------------------------------------------------------------------------
144 {
145 }
146 
147 // --------------------------------------------------------------------------
149 {
150  Q_D(ctkDoubleSlider);
151  d->Minimum = min;
152  if (d->Minimum >= d->Value)
153  {
154  d->updateOffset(d->Minimum);
155  }
156  d->SettingRange = true;
157  d->Slider->setMinimum(d->toInt(min));
158  d->SettingRange = false;
159  emit this->rangeChanged(d->Minimum, d->Maximum);
160 }
161 
162 // --------------------------------------------------------------------------
164 {
165  Q_D(ctkDoubleSlider);
166  d->Maximum = max;
167  if (d->Maximum <= d->Value)
168  {
169  d->updateOffset(d->Maximum);
170  }
171  d->SettingRange = true;
172  d->Slider->setMaximum(d->toInt(max));
173  d->SettingRange = false;
174  emit this->rangeChanged(d->Minimum, d->Maximum);
175 }
176 
177 // --------------------------------------------------------------------------
178 void ctkDoubleSlider::setRange(double min, double max)
179 {
180  Q_D(ctkDoubleSlider);
181  d->Minimum = min;
182  d->Maximum = max;
183 
184  if (d->Minimum >= d->Value)
185  {
186  d->updateOffset(d->Minimum);
187  }
188  if (d->Maximum <= d->Value)
189  {
190  d->updateOffset(d->Maximum);
191  }
192  d->SettingRange = true;
193  d->Slider->setRange(d->toInt(min), d->toInt(max));
194  d->SettingRange = false;
195  emit this->rangeChanged(d->Minimum, d->Maximum);
196 }
197 
198 // --------------------------------------------------------------------------
199 double ctkDoubleSlider::minimum()const
200 {
201  Q_D(const ctkDoubleSlider);
202  return d->Minimum;
203 }
204 
205 // --------------------------------------------------------------------------
206 double ctkDoubleSlider::maximum()const
207 {
208  Q_D(const ctkDoubleSlider);
209  return d->Maximum;
210 }
211 
212 // --------------------------------------------------------------------------
214 {
215  Q_D(const ctkDoubleSlider);
216  return d->fromInt(d->Slider->sliderPosition());
217 }
218 
219 // --------------------------------------------------------------------------
220 void ctkDoubleSlider::setSliderPosition(double newSliderPosition)
221 {
222  Q_D(ctkDoubleSlider);
223  d->Slider->setSliderPosition(d->toInt(newSliderPosition));
224 }
225 
226 // --------------------------------------------------------------------------
227 double ctkDoubleSlider::value()const
228 {
229  Q_D(const ctkDoubleSlider);
230  return d->Value;
231 }
232 
233 // --------------------------------------------------------------------------
234 void ctkDoubleSlider::setValue(double newValue)
235 {
236  Q_D(ctkDoubleSlider);
237  newValue = qBound(d->Minimum, newValue, d->Maximum);
238  d->updateOffset(newValue);
239  int newIntValue = d->toInt(newValue);
240  if (newIntValue != d->Slider->value())
241  {
242  // d->Slider will emit a valueChanged signal that is connected to
243  // ctkDoubleSlider::onValueChanged
244  d->Slider->setValue(newIntValue);
245  }
246  else
247  {
248  double oldValue = d->Value;
249  d->Value = newValue;
250  // don't emit a valuechanged signal if the new value is quite
251  // similar to the old value.
252  if (qAbs(newValue - oldValue) > (d->SingleStep * 0.000000001))
253  {
254  emit this->valueChanged(newValue);
255  }
256  }
257 }
258 
259 // --------------------------------------------------------------------------
260 double ctkDoubleSlider::singleStep()const
261 {
262  Q_D(const ctkDoubleSlider);
263  return d->SingleStep;
264 }
265 
266 // --------------------------------------------------------------------------
267 void ctkDoubleSlider::setSingleStep(double newStep)
268 {
269  Q_D(ctkDoubleSlider);
270  d->SingleStep = newStep;
271  // update the new values of the QSlider
272  double _value = d->Value;
273  d->updateOffset(_value);
274  bool oldBlockSignals = this->blockSignals(true);
275  this->setRange(d->Minimum, d->Maximum);
276  d->Slider->setValue(d->toInt(_value));
277  d->Value = _value;
278  this->blockSignals(oldBlockSignals);
279 }
280 
281 // --------------------------------------------------------------------------
282 double ctkDoubleSlider::tickInterval()const
283 {
284  Q_D(const ctkDoubleSlider);
285  return d->fromInt(d->Slider->tickInterval());
286 }
287 
288 // --------------------------------------------------------------------------
289 void ctkDoubleSlider::setTickInterval(double newTickInterval)
290 {
291  Q_D(ctkDoubleSlider);
292  d->Slider->setTickInterval(d->toInt(newTickInterval));
293 }
294 
295 // --------------------------------------------------------------------------
297 {
298  Q_D(const ctkDoubleSlider);
299  return d->Slider->hasTracking();
300 }
301 
302 // --------------------------------------------------------------------------
304 {
305  Q_D(ctkDoubleSlider);
306  d->Slider->setTracking(enable);
307 }
308 
309 // --------------------------------------------------------------------------
310 void ctkDoubleSlider::triggerAction( QAbstractSlider::SliderAction action)
311 {
312  Q_D(ctkDoubleSlider);
313  d->Slider->triggerAction(action);
314 }
315 
316 // --------------------------------------------------------------------------
317 Qt::Orientation ctkDoubleSlider::orientation()const
318 {
319  Q_D(const ctkDoubleSlider);
320  return d->Slider->orientation();
321 }
322 
323 // --------------------------------------------------------------------------
324 void ctkDoubleSlider::setOrientation(Qt::Orientation newOrientation)
325 {
326  Q_D(ctkDoubleSlider);
327  d->Slider->setOrientation(newOrientation);
328 }
329 
330 // --------------------------------------------------------------------------
332 {
333  Q_D(ctkDoubleSlider);
334  double doubleNewValue = d->fromInt(newValue);
335 /*
336  qDebug() << "onValueChanged: " << newValue << "->"<< d->fromInt(newValue+d->Offset)
337  << " old: " << d->Value << "->" << d->toInt(d->Value)
338  << "offset:" << d->Offset << doubleNewValue;
339 */
340  if (d->Value == doubleNewValue)
341  {
342  return;
343  }
344  d->Value = doubleNewValue;
345  emit this->valueChanged(d->Value);
346 }
347 
348 // --------------------------------------------------------------------------
349 void ctkDoubleSlider::onSliderMoved(int newPosition)
350 {
351  Q_D(const ctkDoubleSlider);
352  emit this->sliderMoved(d->fromInt(newPosition));
353 }
354 
355 // --------------------------------------------------------------------------
356 void ctkDoubleSlider::onRangeChanged(int min, int max)
357 {
358  Q_D(const ctkDoubleSlider);
359  if (!d->SettingRange)
360  {
361  this->setRange(d->fromInt(min), d->fromInt(max));
362  }
363 }
void onRangeChanged(int min, int max)
ctkDoubleSlider *const q_ptr
void setSliderPosition(double)
void sliderMoved(double position)
void setContentsMargins(int left, int top, int right, int bottom)
double singleStep() const
void triggerAction(QAbstractSlider::SliderAction action)
void onSliderMoved(int position)
ctkDoubleSliderPrivate(ctkDoubleSlider &object)
double tickInterval() const
bool hasTracking() const
void setTickInterval(double ti)
ctkDoubleSlider(QWidget *parent=0)
void setOrientation(Qt::Orientation orientation)
void addWidget(QWidget *widget, int stretch, QFlags< Qt::AlignmentFlag > alignment)
void valueChanged(double value)
double sliderPosition() const
void setValue(double value)
void setSingleStep(double step)
void setMinimum(double min)
double minimum() const
Qt::Orientation orientation() const
bool blockSignals(bool block)
void setRange(double min, double max)
Q_DECLARE_PUBLIC(ctkDoubleSlider)
void onValueChanged(int value)
double fromInt(int _value) const
void updateOffset(double value)
double maximum() const
virtual ~ctkDoubleSlider()
Destructor.
double value() const
void rangeChanged(double min, double max)
void setTracking(bool enable)
void setMaximum(double max)
int toInt(double _value) const