source: trunk/src/qt3support/widgets/q3rangecontrol.cpp@ 494

Last change on this file since 494 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 15.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the Qt3Support module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "q3rangecontrol.h"
43#ifndef QT_NO_RANGECONTROL
44#include "qglobal.h"
45#include <limits.h>
46
47QT_BEGIN_NAMESPACE
48
49/*!
50 \class Q3RangeControl
51 \brief The Q3RangeControl class provides an integer value within a range.
52
53 \compat
54
55 Although originally designed for the QScrollBar widget, the
56 Q3RangeControl can also be used in conjunction with other widgets
57 such as QSlider and QSpinBox. Here are the five main concepts in
58 the class:
59
60 \list 1
61
62 \i \e{Current value} The bounded integer that
63 Q3RangeControl maintains. value() returns it, and several
64 functions, including setValue(), set it.
65
66 \i \e{Minimum} The lowest value that value() can ever
67 return. Returned by minValue() and set by setRange() or one of the
68 constructors.
69
70 \i \e{Maximum} The highest value that value() can ever
71 return. Returned by maxValue() and set by setRange() or one of the
72 constructors.
73
74 \i \e{Line step} The smaller of two natural steps that
75 Q3RangeControl provides and typically corresponds to the user
76 pressing an arrow key. The line step is returned by lineStep()
77 and set using setSteps(). The functions addLine() and
78 subtractLine() respectively increment and decrement the current
79 value by lineStep().
80
81 \i \e{Page step} The larger of two natural steps that
82 Q3RangeControl provides and typically corresponds to the user
83 pressing PageUp or PageDown. The page step is returned by
84 pageStep() and set using setSteps(). The functions addPage() and
85 substractPage() respectively increment and decrement the current
86 value by pageStep().
87
88 \endlist
89
90 Unity (1) may be viewed as a third step size. setValue() lets you
91 set the current value to any integer in the allowed range, not
92 just minValue() + \e n * lineStep() for integer values of \e n.
93 Some widgets may allow the user to set any value at all; others
94 may just provide multiples of lineStep() or pageStep().
95
96 Q3RangeControl provides three virtual functions that are well
97 suited for updating the on-screen representation of range controls
98 and emitting signals: valueChange(), rangeChange() and
99 stepChange().
100
101 Q3RangeControl also provides a function called bound() which lets
102 you force arbitrary integers to be within the allowed range of the
103 range control.
104
105 We recommend that all widgets that inherit Q3RangeControl provide
106 at least a signal called valueChanged(); many widgets will want to
107 provide addStep(), addPage(), substractStep() and substractPage()
108 as slots.
109
110 Note that you must use multiple inheritance if you plan to
111 implement a widget using Q3RangeControl because Q3RangeControl is
112 not derived from QWidget.
113*/
114
115
116/*!
117 Constructs a range control with a minimum value of 0, maximum
118 value of 99, line step of 1, page step of 10 and initial value 0.
119*/
120
121Q3RangeControl::Q3RangeControl()
122{
123 minVal = 0;
124 maxVal = 99;
125 line = 1;
126 page = 10;
127 val = 0;
128 prevVal = -1;
129 d = 0;
130}
131
132/*!
133 Constructs a range control whose value can never be smaller than
134 \a minValue or greater than \a maxValue, whose line step size is
135 \a lineStep and page step size is \a pageStep and whose value is
136 initially \a value (which is guaranteed to be in range using
137 bound()).
138*/
139
140Q3RangeControl::Q3RangeControl(int minValue, int maxValue,
141 int lineStep, int pageStep,
142 int value)
143{
144 minVal = minValue;
145 maxVal = maxValue;
146 line = QABS(lineStep);
147 page = QABS(pageStep);
148 prevVal = minVal - 1;
149 val = bound(value);
150 d = 0;
151}
152
153/*!
154 Destroys the range control
155*/
156
157Q3RangeControl::~Q3RangeControl()
158{
159}
160
161
162/*!
163 \fn int Q3RangeControl::value() const
164
165 Returns the current range control value. This is guaranteed to be
166 within the range [minValue(), maxValue()].
167
168 \sa setValue() prevValue()
169*/
170
171/*!
172 \fn int Q3RangeControl::prevValue() const
173
174 Returns the previous value of the range control. "Previous value"
175 means the value before the last change occurred. Setting a new
176 range may affect the value, too, because the value is forced to be
177 inside the specified range. When the range control is initially
178 created, this is the same as value().
179
180 prevValue() can be outside the current legal range if a call to
181 setRange() causes the current value to change. For example, if the
182 range was [0, 1000] and the current value is 500, setRange(0, 400)
183 makes value() return 400 and prevValue() return 500.
184
185 \sa value() setRange()
186*/
187
188/*!
189 Sets the range control's value to \a value and forces it to be
190 within the legal range.
191
192 Calls the virtual valueChange() function if the new value is
193 different from the previous value. The old value can still be
194 retrieved using prevValue().
195
196 \sa value()
197*/
198
199void Q3RangeControl::setValue(int value)
200{
201 directSetValue(value);
202 if (prevVal != val)
203 valueChange();
204}
205
206/*!
207 Sets the range control \a value directly without calling
208 valueChange().
209
210 Forces the new \a value to be within the legal range.
211
212 You will rarely have to call this function. However, if you want
213 to change the range control's value inside the overloaded method
214 valueChange(), setValue() would call the function valueChange()
215 again. To avoid this recursion you must use directSetValue()
216 instead.
217
218 \sa setValue()
219*/
220
221void Q3RangeControl::directSetValue(int value)
222{
223 prevVal = val;
224 val = bound(value);
225}
226
227/*!
228 Equivalent to \c{setValue(value() + pageStep())}.
229
230 If the value is changed, then valueChange() is called.
231
232 \sa subtractPage() addLine() setValue()
233*/
234
235void Q3RangeControl::addPage()
236{
237 setValue(value() + pageStep());
238}
239
240/*!
241 Equivalent to \c{setValue(value() - pageStep())}.
242
243 If the value is changed, then valueChange() is called.
244
245 \sa addPage() subtractLine() setValue()
246*/
247
248void Q3RangeControl::subtractPage()
249{
250 setValue(value() - pageStep());
251}
252
253/*!
254 Equivalent to \c{setValue(value() + lineStep())}.
255
256 If the value is changed, then valueChange() is called.
257
258 \sa subtractLine() addPage() setValue()
259*/
260
261void Q3RangeControl::addLine()
262{
263 setValue(value() + lineStep());
264}
265
266/*!
267 Equivalent to \c{setValue(value() - lineStep())}.
268
269 If the value is changed, then valueChange() is called.
270
271 \sa addLine() subtractPage() setValue()
272*/
273
274void Q3RangeControl::subtractLine()
275{
276 setValue(value() - lineStep());
277}
278
279
280/*!
281 \fn int Q3RangeControl::minValue() const
282
283 Returns the minimum value of the range.
284
285 \sa setMinValue() setRange() maxValue()
286*/
287
288/*!
289 \fn int Q3RangeControl::maxValue() const
290
291 Returns the maximum value of the range.
292
293 \sa setMaxValue() setRange() minValue()
294*/
295
296/*!
297 Sets the minimum value of the range to \a minVal.
298
299 If necessary, the maxValue() is adjusted so that the range remains
300 valid.
301
302 \sa minValue() setMaxValue()
303*/
304void Q3RangeControl::setMinValue(int minVal)
305{
306 int maxVal = maxValue();
307 if (maxVal < minVal)
308 maxVal = minVal;
309 setRange(minVal, maxVal);
310}
311
312/*!
313 Sets the minimum value of the range to \a maxVal.
314
315 If necessary, the minValue() is adjusted so that the range remains
316 valid.
317
318 \sa maxValue() setMinValue()
319*/
320void Q3RangeControl::setMaxValue(int maxVal)
321{
322 int minVal = minValue();
323 if (minVal > maxVal)
324 minVal = maxVal;
325 setRange(minVal, maxVal);
326}
327
328/*!
329 Sets the range control's minimum value to \a minValue and its
330 maximum value to \a maxValue.
331
332 Calls the virtual rangeChange() function if one or both of the new
333 minimum and maximum values are different from the previous
334 setting. Calls the virtual valueChange() function if the current
335 value is adjusted because it was outside the new range.
336
337 If \a maxValue is smaller than \a minValue, \a minValue becomes
338 the only legal value.
339
340 \sa minValue() maxValue()
341*/
342
343void Q3RangeControl::setRange(int minValue, int maxValue)
344{
345 if (minValue > maxValue) {
346 qWarning("Q3RangeControl::setRange: minValue %d > maxValue %d",
347 minValue, maxValue);
348 maxValue = minValue;
349 }
350 if (minValue == minVal && maxValue == maxVal)
351 return;
352 minVal = minValue;
353 maxVal = maxValue;
354 int tmp = bound(val);
355 rangeChange();
356 if (tmp != val) {
357 prevVal = val;
358 val = tmp;
359 valueChange();
360 }
361}
362
363
364/*!
365 \fn int Q3RangeControl::lineStep() const
366
367 Returns the line step.
368
369 \sa setSteps() pageStep()
370*/
371
372/*!
373 \fn int Q3RangeControl::pageStep() const
374
375 Returns the page step.
376
377 \sa setSteps() lineStep()
378*/
379
380/*!
381 Sets the range's line step to \a lineStep and page step to \a
382 pageStep.
383
384 Calls the virtual stepChange() function if the new line step
385 or page step are different from the previous settings.
386
387 \sa lineStep() pageStep() setRange()
388*/
389
390void Q3RangeControl::setSteps(int lineStep, int pageStep)
391{
392 if (lineStep != line || pageStep != page) {
393 line = QABS(lineStep);
394 page = QABS(pageStep);
395 stepChange();
396 }
397}
398
399
400/*!
401 This virtual function is called whenever the range control value
402 changes. You can reimplement it if you want to be notified when
403 the value changes. The default implementation does nothing.
404
405 Note that this method is called after the value has changed. The
406 previous value can be retrieved using prevValue().
407
408 \sa setValue(), addPage(), subtractPage(), addLine(),
409 subtractLine() rangeChange(), stepChange()
410*/
411
412void Q3RangeControl::valueChange()
413{
414}
415
416
417/*!
418 This virtual function is called whenever the range control's range
419 changes. You can reimplement it if you want to be notified when
420 the range changes. The default implementation does nothing.
421
422 Note that this method is called after the range has changed.
423
424 \sa setRange(), valueChange(), stepChange()
425*/
426
427void Q3RangeControl::rangeChange()
428{
429}
430
431
432/*!
433 This virtual function is called whenever the range control's
434 line or page step settings change. You can reimplement it if you
435 want to be notified when the step changes. The default
436 implementation does nothing.
437
438 Note that this method is called after a step setting has changed.
439
440 \sa setSteps(), rangeChange(), valueChange()
441*/
442
443void Q3RangeControl::stepChange()
444{
445}
446
447
448/*!
449 Forces the value \a v to be within the range from minValue() to
450 maxValue() inclusive, and returns the result.
451
452 This function is provided so that you can easily force other
453 numbers than value() into the allowed range. You do not need to
454 call it in order to use Q3RangeControl itself.
455
456 \sa setValue() value() minValue() maxValue()
457*/
458
459int Q3RangeControl::bound(int v) const
460{
461 if (v < minVal)
462 return minVal;
463 if (v > maxVal)
464 return maxVal;
465 return v;
466}
467
468
469/*!
470 Converts \a logical_val to a pixel position. minValue() maps to 0,
471 maxValue() maps to \a span and other values are distributed evenly
472 in-between.
473
474 This function can handle the entire integer range without
475 overflow, providing \a span is \<= 4096.
476
477 Calling this method is useful when actually drawing a range
478 control such as a QScrollBar on-screen.
479
480 \sa valueFromPosition()
481*/
482
483int Q3RangeControl::positionFromValue(int logical_val, int span) const
484{
485 if (span <= 0 || logical_val < minValue() || maxValue() <= minValue())
486 return 0;
487 if (logical_val > maxValue())
488 return span;
489
490 uint range = maxValue() - minValue();
491 uint p = logical_val - minValue();
492
493 if (range > (uint)INT_MAX/4096) {
494 const int scale = 4096*2;
495 return ((p/scale) * span) / (range/scale);
496 // ### the above line is probably not 100% correct
497 // ### but fixing it isn't worth the extreme pain...
498 } else if (range > (uint)span) {
499 return (2*p*span + range) / (2*range);
500 } else {
501 uint div = span / range;
502 uint mod = span % range;
503 return p*div + (2*p*mod + range) / (2*range);
504 }
505 //equiv. to (p*span)/range + 0.5
506 // no overflow because of this implicit assumption:
507 // span <= 4096
508}
509
510
511/*!
512 Converts the pixel position \a pos to a value. 0 maps to
513 minValue(), \a span maps to maxValue() and other values are
514 distributed evenly in-between.
515
516 This function can handle the entire integer range without
517 overflow.
518
519 Calling this method is useful if you actually implemented a range
520 control widget such as QScrollBar and want to handle mouse press
521 events. This function then maps screen coordinates to the logical
522 values.
523
524 \sa positionFromValue()
525*/
526
527int Q3RangeControl::valueFromPosition(int pos, int span) const
528{
529 if (span <= 0 || pos <= 0)
530 return minValue();
531 if (pos >= span)
532 return maxValue();
533
534 uint range = maxValue() - minValue();
535
536 if ((uint)span > range)
537 return minValue() + (2*pos*range + span) / (2*span);
538 else {
539 uint div = range / span;
540 uint mod = range % span;
541 return minValue() + pos*div + (2*pos*mod + span) / (2*span);
542 }
543 // equiv. to minValue() + (pos*range)/span + 0.5
544 // no overflow because of this implicit assumption:
545 // pos <= span < sqrt(INT_MAX+0.0625)+0.25 ~ sqrt(INT_MAX)
546}
547
548QT_END_NAMESPACE
549
550#endif // QT_NO_RANGECONTROL
Note: See TracBrowser for help on using the repository browser.