source: vendor/trolltech/current/src/widgets/qrangecontrol.cpp

Last change on this file was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

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