src/qt3support/widgets/q3rangecontrol.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt3Support module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    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 
       
    47 QT_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 
       
   121 Q3RangeControl::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 
       
   140 Q3RangeControl::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 
       
   157 Q3RangeControl::~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 
       
   199 void 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 
       
   221 void 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 
       
   235 void 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 
       
   248 void 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 
       
   261 void 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 
       
   274 void 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 */
       
   304 void 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 */
       
   320 void 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 
       
   343 void 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 
       
   390 void 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 
       
   412 void 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 
       
   427 void 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 
       
   443 void 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 
       
   459 int 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 
       
   483 int 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 
       
   527 int 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 
       
   548 QT_END_NAMESPACE
       
   549 
       
   550 #endif // QT_NO_RANGECONTROL