qwt_abstract_slider.cpp 18 KB
Newer Older
pixhawk's avatar
pixhawk committed
1 2 3 4
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
 * Qwt Widget Library
 * Copyright (C) 1997   Josef Wilgen
 * Copyright (C) 2002   Uwe Rathmann
5
 *
pixhawk's avatar
pixhawk committed
6 7 8 9 10
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the Qwt License, Version 1.0
 *****************************************************************************/

#include "qwt_abstract_slider.h"
Bryant's avatar
Bryant committed
11
#include "qwt_abstract_scale_draw.h"
pixhawk's avatar
pixhawk committed
12
#include "qwt_math.h"
Bryant's avatar
Bryant committed
13 14
#include "qwt_scale_map.h"
#include <qevent.h>
pixhawk's avatar
pixhawk committed
15

Bryant's avatar
Bryant committed
16 17
#if QT_VERSION < 0x040601
#define qFabs(x) ::fabs(x)
pixhawk's avatar
pixhawk committed
18 19
#endif

Bryant's avatar
Bryant committed
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
static double qwtAlignToScaleDiv( 
    const QwtAbstractSlider *slider, double value )
{
    const QwtScaleDiv &sd = slider->scaleDiv();

    const int tValue = slider->transform( value );

    if ( tValue == slider->transform( sd.lowerBound() ) )
        return sd.lowerBound();

    if ( tValue == slider->transform( sd.lowerBound() ) )
        return sd.upperBound();

    for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ )
    {
        const QList<double> ticks = sd.ticks( i );
        for ( int j = 0; j < ticks.size(); j++ )
        {
            if ( slider->transform( ticks[ j ] ) == tValue )
                return ticks[ j ];
        }
    }

    return value;
}

pixhawk's avatar
pixhawk committed
46 47 48 49
class QwtAbstractSlider::PrivateData
{
public:
    PrivateData():
Bryant's avatar
Bryant committed
50 51 52 53 54 55 56 57 58 59 60 61 62
        isScrolling( false ),
        isTracking( true ),
        pendingValueChanged( false ),
        readOnly( false ),
        totalSteps( 100 ),
        singleSteps( 1 ),
        pageSteps( 10 ),
        stepAlignment( true ),
        isValid( false ),
        value( 0.0 ),
        wrapping( false ),
        invertedControls( false )
    {
pixhawk's avatar
pixhawk committed
63 64
    }

Bryant's avatar
Bryant committed
65 66 67 68
    bool isScrolling;
    bool isTracking;
    bool pendingValueChanged;

pixhawk's avatar
pixhawk committed
69
    bool readOnly;
Bryant's avatar
Bryant committed
70 71 72 73 74 75 76 77 78 79 80

    uint totalSteps;
    uint singleSteps;
    uint pageSteps;
    bool stepAlignment;

    bool isValid;
    double value;

    bool wrapping;
    bool invertedControls;
pixhawk's avatar
pixhawk committed
81 82
};

83
/*!
Bryant's avatar
Bryant committed
84 85 86 87 88 89 90
  \brief Constructor

  The scale is initialized to [0.0, 100.0], the
  number of steps is set to 100 with 1 and 10 and single
  an page step sizes. Step alignment is enabled.

  The initial value is invalid.
pixhawk's avatar
pixhawk committed
91

Bryant's avatar
Bryant committed
92
  \param parent Parent widget
pixhawk's avatar
pixhawk committed
93
*/
Bryant's avatar
Bryant committed
94 95
QwtAbstractSlider::QwtAbstractSlider( QWidget *parent ):
    QwtAbstractScale( parent )
pixhawk's avatar
pixhawk committed
96 97 98
{
    d_data = new QwtAbstractSlider::PrivateData;

Bryant's avatar
Bryant committed
99 100
    setScale( 0.0, 100.0 );
    setFocusPolicy( Qt::StrongFocus );
pixhawk's avatar
pixhawk committed
101 102 103 104 105 106 107 108
}

//! Destructor
QwtAbstractSlider::~QwtAbstractSlider()
{
    delete d_data;
}

Bryant's avatar
Bryant committed
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
/*! 
  Set the value to be valid/invalid

  \param on When true, the value is invalidated

  \sa setValue()
*/
void QwtAbstractSlider::setValid( bool on )
{
    if ( on != d_data->isValid )
    {
        d_data->isValid = on;
        sliderChange();

        Q_EMIT valueChanged( d_data->value );
    }   
}   

//! \return True, when the value is invalid
bool QwtAbstractSlider::isValid() const
{
    return d_data->isValid;
}   

pixhawk's avatar
pixhawk committed
133 134 135 136 137 138
/*!
  En/Disable read only mode

  In read only mode the slider can't be controlled by mouse
  or keyboard.

Bryant's avatar
Bryant committed
139
  \param on Enables in case of true
pixhawk's avatar
pixhawk committed
140
  \sa isReadOnly()
Bryant's avatar
Bryant committed
141 142

  \warning The focus policy is set to Qt::StrongFocus or Qt::NoFocus
pixhawk's avatar
pixhawk committed
143
*/
Bryant's avatar
Bryant committed
144
void QwtAbstractSlider::setReadOnly( bool on )
pixhawk's avatar
pixhawk committed
145
{
Bryant's avatar
Bryant committed
146 147 148 149 150 151 152
    if ( d_data->readOnly != on )
    {
        d_data->readOnly = on;
        setFocusPolicy( on ? Qt::StrongFocus : Qt::NoFocus );

        update();
    }
pixhawk's avatar
pixhawk committed
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
}

/*!
  In read only mode the slider can't be controlled by mouse
  or keyboard.

  \return true if read only
  \sa setReadOnly()
*/
bool QwtAbstractSlider::isReadOnly() const
{
    return d_data->readOnly;
}

/*!
Bryant's avatar
Bryant committed
168
  \brief Enables or disables tracking.
pixhawk's avatar
pixhawk committed
169

Bryant's avatar
Bryant committed
170 171 172 173
  If tracking is enabled, the slider emits the valueChanged() 
  signal while the movable part of the slider is being dragged. 
  If tracking is disabled, the slider emits the valueChanged() signal 
  only when the user releases the slider.
pixhawk's avatar
pixhawk committed
174

Bryant's avatar
Bryant committed
175 176
  Tracking is enabled by default.
  \param on \c true (enable) or \c false (disable) tracking.
pixhawk's avatar
pixhawk committed
177

Bryant's avatar
Bryant committed
178 179 180
  \sa isTracking(), sliderMoved()
*/
void QwtAbstractSlider::setTracking( bool on )
pixhawk's avatar
pixhawk committed
181
{
Bryant's avatar
Bryant committed
182
    d_data->isTracking = on;
pixhawk's avatar
pixhawk committed
183 184 185
}

/*!
Bryant's avatar
Bryant committed
186 187
  \return True, when tracking has been enabled
  \sa setTracking()
pixhawk's avatar
pixhawk committed
188
*/
Bryant's avatar
Bryant committed
189
bool QwtAbstractSlider::isTracking() const
pixhawk's avatar
pixhawk committed
190
{
Bryant's avatar
Bryant committed
191
    return d_data->isTracking;
pixhawk's avatar
pixhawk committed
192 193
}

Bryant's avatar
Bryant committed
194 195 196 197 198
/*!
   Mouse press event handler
   \param event Mouse event
*/
void QwtAbstractSlider::mousePressEvent( QMouseEvent *event )
pixhawk's avatar
pixhawk committed
199
{
Bryant's avatar
Bryant committed
200 201 202
    if ( isReadOnly() )
    {
        event->ignore();
pixhawk's avatar
pixhawk committed
203 204 205
        return;
    }

Bryant's avatar
Bryant committed
206 207
    if ( !d_data->isValid || lowerBound() == upperBound() )
        return;
208

Bryant's avatar
Bryant committed
209
    d_data->isScrolling = isScrollPosition( event->pos() );
210

Bryant's avatar
Bryant committed
211 212 213
    if ( d_data->isScrolling )
    {
        d_data->pendingValueChanged = false;
214

Bryant's avatar
Bryant committed
215
        Q_EMIT sliderPressed();
pixhawk's avatar
pixhawk committed
216 217 218
    }
}

Bryant's avatar
Bryant committed
219 220 221 222 223
/*!
   Mouse Move Event handler
   \param event Mouse event
*/
void QwtAbstractSlider::mouseMoveEvent( QMouseEvent *event )
pixhawk's avatar
pixhawk committed
224
{
Bryant's avatar
Bryant committed
225 226 227
    if ( isReadOnly() )
    {
        event->ignore();
pixhawk's avatar
pixhawk committed
228 229 230
        return;
    }

Bryant's avatar
Bryant committed
231 232 233 234 235 236
    if ( d_data->isValid && d_data->isScrolling )
    {
        double value = scrolledTo( event->pos() );
        if ( value != d_data->value )
        {
            value = boundedValue( value );
pixhawk's avatar
pixhawk committed
237

Bryant's avatar
Bryant committed
238 239 240 241 242 243 244 245
            if ( d_data->stepAlignment )
            {
                value = alignedValue( value );
            }
            else
            {
                value = qwtAlignToScaleDiv( this, value );
            }
pixhawk's avatar
pixhawk committed
246

Bryant's avatar
Bryant committed
247 248 249
            if ( value != d_data->value )
            {
                d_data->value = value;
pixhawk's avatar
pixhawk committed
250

Bryant's avatar
Bryant committed
251
                sliderChange();
252

Bryant's avatar
Bryant committed
253
                Q_EMIT sliderMoved( d_data->value );
254

Bryant's avatar
Bryant committed
255 256 257 258 259 260
                if ( d_data->isTracking )
                    Q_EMIT valueChanged( d_data->value );
                else
                    d_data->pendingValueChanged = true;
            }
        }
pixhawk's avatar
pixhawk committed
261 262 263 264
    }
}

/*!
Bryant's avatar
Bryant committed
265 266
   Mouse Release Event handler
   \param event Mouse event
pixhawk's avatar
pixhawk committed
267
*/
Bryant's avatar
Bryant committed
268
void QwtAbstractSlider::mouseReleaseEvent( QMouseEvent *event )
pixhawk's avatar
pixhawk committed
269
{
Bryant's avatar
Bryant committed
270 271 272 273 274
    if ( isReadOnly() )
    {
        event->ignore();
        return;
    }
pixhawk's avatar
pixhawk committed
275

Bryant's avatar
Bryant committed
276 277 278
    if ( d_data->isScrolling && d_data->isValid )
    {
        d_data->isScrolling = false;
pixhawk's avatar
pixhawk committed
279

Bryant's avatar
Bryant committed
280 281
        if ( d_data->pendingValueChanged )
            Q_EMIT valueChanged( d_data->value );
pixhawk's avatar
pixhawk committed
282

Bryant's avatar
Bryant committed
283 284
        Q_EMIT sliderReleased();
    }
pixhawk's avatar
pixhawk committed
285 286
}

287
/*!
Bryant's avatar
Bryant committed
288 289 290 291 292 293 294 295 296 297
   Wheel Event handler

   In/decreases the value by s number of steps. The direction 
   depends on the invertedControls() property.

   When the control or shift modifier is pressed the wheel delta
   ( divided by 120 ) is mapped to an increment according to
   pageSteps(). Otherwise it is mapped to singleSteps().

   \param event Wheel event
pixhawk's avatar
pixhawk committed
298
*/
Bryant's avatar
Bryant committed
299
void QwtAbstractSlider::wheelEvent( QWheelEvent *event )
pixhawk's avatar
pixhawk committed
300
{
Bryant's avatar
Bryant committed
301 302 303
    if ( isReadOnly() )
    {
        event->ignore();
pixhawk's avatar
pixhawk committed
304 305 306
        return;
    }

Bryant's avatar
Bryant committed
307
    if ( !d_data->isValid || d_data->isScrolling )
pixhawk's avatar
pixhawk committed
308 309
        return;

Bryant's avatar
Bryant committed
310
    int numSteps = 0;
pixhawk's avatar
pixhawk committed
311

Bryant's avatar
Bryant committed
312 313 314 315 316 317 318 319 320 321 322 323
    if ( ( event->modifiers() & Qt::ControlModifier) ||
        ( event->modifiers() & Qt::ShiftModifier ) )
    {
        // one page regardless of delta
        numSteps = d_data->pageSteps;
        if ( event->delta() < 0 )
            numSteps = -numSteps;
    }
    else
    {
        const int numTurns = ( event->delta() / 120 );
        numSteps = numTurns * d_data->singleSteps;
pixhawk's avatar
pixhawk committed
324 325
    }

Bryant's avatar
Bryant committed
326 327
    if ( d_data->invertedControls )
        numSteps = -numSteps;
pixhawk's avatar
pixhawk committed
328

Bryant's avatar
Bryant committed
329 330 331 332 333
    const double value = incrementedValue( d_data->value, numSteps );
    if ( value != d_data->value )
    {
        d_data->value = value;
        sliderChange();
pixhawk's avatar
pixhawk committed
334

Bryant's avatar
Bryant committed
335 336
        Q_EMIT sliderMoved( d_data->value );
        Q_EMIT valueChanged( d_data->value );
pixhawk's avatar
pixhawk committed
337 338 339 340 341 342
    }
}

/*!
  Handles key events

Bryant's avatar
Bryant committed
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362
  QwtAbstractSlider handles the following keys:

  - Qt::Key_Left\n
    Add/Subtract singleSteps() in direction to lowerBound();
  - Qt::Key_Right\n
    Add/Subtract singleSteps() in direction to upperBound();
  - Qt::Key_Down\n
    Subtract singleSteps(), when invertedControls() is false
  - Qt::Key_Up\n
    Add singleSteps(), when invertedControls() is false
  - Qt::Key_PageDown\n
    Subtract pageSteps(), when invertedControls() is false
  - Qt::Key_PageUp\n
    Add pageSteps(), when invertedControls() is false
  - Qt::Key_Home\n
    Set the value to the minimum()
  - Qt::Key_End\n
    Set the value to the maximum()

  \param event Key event
pixhawk's avatar
pixhawk committed
363 364
  \sa isReadOnly()
*/
Bryant's avatar
Bryant committed
365
void QwtAbstractSlider::keyPressEvent( QKeyEvent *event )
pixhawk's avatar
pixhawk committed
366
{
Bryant's avatar
Bryant committed
367 368 369
    if ( isReadOnly() )
    {
        event->ignore();
pixhawk's avatar
pixhawk committed
370 371 372
        return;
    }

Bryant's avatar
Bryant committed
373
    if ( !d_data->isValid || d_data->isScrolling )
pixhawk's avatar
pixhawk committed
374 375
        return;

Bryant's avatar
Bryant committed
376 377
    int numSteps = 0;
    double value = d_data->value;
pixhawk's avatar
pixhawk committed
378

Bryant's avatar
Bryant committed
379 380 381 382 383 384 385
    switch ( event->key() )
    {
        case Qt::Key_Left:
        {
            numSteps = -static_cast<int>( d_data->singleSteps );
            if ( isInverted() )
                numSteps = -numSteps;
pixhawk's avatar
pixhawk committed
386

Bryant's avatar
Bryant committed
387 388 389 390 391 392 393
            break;
        }
        case Qt::Key_Right:
        {
            numSteps = d_data->singleSteps;
            if ( isInverted() )
                numSteps = -numSteps;
pixhawk's avatar
pixhawk committed
394

Bryant's avatar
Bryant committed
395 396 397 398 399 400 401 402 403 404 405 406 407 408
            break;
        }
        case Qt::Key_Down:
        {
            numSteps = -static_cast<int>( d_data->singleSteps );
            if ( d_data->invertedControls )
                numSteps = -numSteps;
            break;
        }
        case Qt::Key_Up:
        {
            numSteps = d_data->singleSteps;
            if ( d_data->invertedControls )
                numSteps = -numSteps;
409

Bryant's avatar
Bryant committed
410
            break;
411
        }
Bryant's avatar
Bryant committed
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438
        case Qt::Key_PageUp:
        {
            numSteps = d_data->pageSteps;
            if ( d_data->invertedControls )
                numSteps = -numSteps;
            break;
        }
        case Qt::Key_PageDown:
        {
            numSteps = -static_cast<int>( d_data->pageSteps );
            if ( d_data->invertedControls )
                numSteps = -numSteps;
            break;
        }
        case Qt::Key_Home:
        {
            value = minimum();
            break;
        }
        case Qt::Key_End:
        {
            value = maximum();
            break;
        }
        default:;
        {
            event->ignore();
pixhawk's avatar
pixhawk committed
439
        }
440
    }
Bryant's avatar
Bryant committed
441 442 443 444

    if ( numSteps != 0 )
    {
        value = incrementedValue( d_data->value, numSteps );
445
    }
Bryant's avatar
Bryant committed
446 447 448 449 450 451 452 453

    if ( value != d_data->value )
    {
        d_data->value = value;
        sliderChange();

        Q_EMIT sliderMoved( d_data->value );
        Q_EMIT valueChanged( d_data->value );
pixhawk's avatar
pixhawk committed
454
    }
Bryant's avatar
Bryant committed
455
}
pixhawk's avatar
pixhawk committed
456

Bryant's avatar
Bryant committed
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471
/*!
  \brief Set the number of steps

  The range of the slider is divided into a number of steps from
  which the value increments according to user inputs depend. 

  The default setting is 100.

  \param stepCount Number of steps

  \sa totalSteps(), setSingleSteps(), setPageSteps()
 */
void QwtAbstractSlider::setTotalSteps( uint stepCount )
{
    d_data->totalSteps = stepCount;
pixhawk's avatar
pixhawk committed
472 473
}

Bryant's avatar
Bryant committed
474 475 476 477 478 479 480 481
/*!
  \return Number of steps
  \sa setTotalSteps(), singleSteps(), pageSteps()
 */
uint QwtAbstractSlider::totalSteps() const
{
    return d_data->totalSteps;
}
pixhawk's avatar
pixhawk committed
482 483

/*!
Bryant's avatar
Bryant committed
484
  \brief Set the number of steps for a single increment
pixhawk's avatar
pixhawk committed
485

Bryant's avatar
Bryant committed
486 487 488 489 490 491 492 493 494
  The range of the slider is divided into a number of steps from
  which the value increments according to user inputs depend. 

  \param stepCount Number of steps

  \sa singleSteps(), setTotalSteps(), setPageSteps()
 */

void QwtAbstractSlider::setSingleSteps( uint stepCount )
pixhawk's avatar
pixhawk committed
495
{
Bryant's avatar
Bryant committed
496 497
    d_data->singleSteps = stepCount;
}   
pixhawk's avatar
pixhawk committed
498 499

/*!
Bryant's avatar
Bryant committed
500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522
  \return Number of steps
  \sa setSingleSteps(), totalSteps(), pageSteps()
 */
uint QwtAbstractSlider::singleSteps() const
{
    return d_data->singleSteps;
}   

/*! 
  \brief Set the number of steps for a page increment
    
  The range of the slider is divided into a number of steps from
  which the value increments according to user inputs depend. 

  \param stepCount Number of steps

  \sa pageSteps(), setTotalSteps(), setSingleSteps()
 */

void QwtAbstractSlider::setPageSteps( uint stepCount )
{
    d_data->pageSteps = stepCount;
}
pixhawk's avatar
pixhawk committed
523

Bryant's avatar
Bryant committed
524 525 526 527 528 529 530 531
/*!
  \return Number of steps
  \sa setPageSteps(), totalSteps(), singleSteps()
 */
uint QwtAbstractSlider::pageSteps() const
{
    return d_data->pageSteps;
}
pixhawk's avatar
pixhawk committed
532

Bryant's avatar
Bryant committed
533 534
/*!
  \brief Enable step alignment
pixhawk's avatar
pixhawk committed
535

Bryant's avatar
Bryant committed
536 537
  When step alignment is enabled values resulting from slider
  movements are aligned to the step size.
pixhawk's avatar
pixhawk committed
538

Bryant's avatar
Bryant committed
539 540
  \param on Enable step alignment when true
  \sa stepAlignment()
pixhawk's avatar
pixhawk committed
541
*/
Bryant's avatar
Bryant committed
542 543 544 545 546 547 548 549 550 551 552 553 554
void QwtAbstractSlider::setStepAlignment( bool on )
{   
    if ( on != d_data->stepAlignment )
    {
        d_data->stepAlignment = on;
    }
}   
    
/*!
  \return True, when step alignment is enabled
  \sa setStepAlignment()
 */
bool QwtAbstractSlider::stepAlignment() const
pixhawk's avatar
pixhawk committed
555
{
Bryant's avatar
Bryant committed
556
    return d_data->stepAlignment;
pixhawk's avatar
pixhawk committed
557 558 559
}

/*!
Bryant's avatar
Bryant committed
560 561 562 563
  Set the slider to the specified value

  \param value New value
  \sa setValid(), sliderChange(), valueChanged()
pixhawk's avatar
pixhawk committed
564
*/
Bryant's avatar
Bryant committed
565
void QwtAbstractSlider::setValue( double value )
566
{
Bryant's avatar
Bryant committed
567 568 569 570 571 572 573 574 575 576 577 578
    value = qBound( minimum(), value, maximum() );

    const bool changed = ( d_data->value != value ) || !d_data->isValid;

    d_data->value = value;
    d_data->isValid = true;

    if ( changed )
    {
        sliderChange();
        Q_EMIT valueChanged( d_data->value );
    }
pixhawk's avatar
pixhawk committed
579 580
}

Bryant's avatar
Bryant committed
581 582 583 584 585
//! Returns the current value.
double QwtAbstractSlider::value() const
{
    return d_data->value;
}
pixhawk's avatar
pixhawk committed
586 587

/*!
Bryant's avatar
Bryant committed
588 589
  If wrapping is true stepping up from upperBound() value will 
  take you to the minimum() value and vice versa. 
pixhawk's avatar
pixhawk committed
590

Bryant's avatar
Bryant committed
591 592
  \param on En/Disable wrapping
  \sa wrapping()
pixhawk's avatar
pixhawk committed
593
*/
Bryant's avatar
Bryant committed
594 595 596 597 598 599 600 601 602 603
void QwtAbstractSlider::setWrapping( bool on )
{
    d_data->wrapping = on;
}   

/*!
  \return True, when wrapping is set
  \sa setWrapping()
 */ 
bool QwtAbstractSlider::wrapping() const
pixhawk's avatar
pixhawk committed
604
{
Bryant's avatar
Bryant committed
605
    return d_data->wrapping;
pixhawk's avatar
pixhawk committed
606 607
}

Bryant's avatar
Bryant committed
608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635
/*!
  Invert wheel and key events

  Usually scrolling the mouse wheel "up" and using keys like page 
  up will increase the slider's value towards its maximum. 
  When invertedControls() is enabled the value is scrolled
  towards its minimum.

  Inverting the controls might be f.e. useful for a vertical slider
  with an inverted scale ( decreasing from top to bottom ).

  \param on Invert controls, when true

  \sa invertedControls(), keyEvent(), wheelEvent()
 */
void QwtAbstractSlider::setInvertedControls( bool on )
{
    d_data->invertedControls = on;
}

/*!
 \return True, when the controls are inverted
 \sa setInvertedControls()
 */
bool QwtAbstractSlider::invertedControls() const
{
    return d_data->invertedControls;
}
pixhawk's avatar
pixhawk committed
636 637

/*!
Bryant's avatar
Bryant committed
638
  Increment the slider
pixhawk's avatar
pixhawk committed
639

Bryant's avatar
Bryant committed
640 641 642 643 644 645
  The step size depends on the number of totalSteps()

  \param stepCount Number of steps
  \sa setTotalSteps(), incrementedValue()
 */
void QwtAbstractSlider::incrementValue( int stepCount )
pixhawk's avatar
pixhawk committed
646
{
Bryant's avatar
Bryant committed
647 648 649 650 651 652 653 654
    const double value = incrementedValue( 
        d_data->value, stepCount );

    if ( value != d_data->value )
    {
        d_data->value = value;
        sliderChange();
    }
pixhawk's avatar
pixhawk committed
655 656 657
}

/*!
Bryant's avatar
Bryant committed
658 659 660 661 662 663 664 665 666
  Increment a value 

  \param value Value 
  \param stepCount Number of steps

  \return Incremented value
 */
double QwtAbstractSlider::incrementedValue( 
    double value, int stepCount ) const
pixhawk's avatar
pixhawk committed
667
{
Bryant's avatar
Bryant committed
668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744
    if ( d_data->totalSteps == 0 )
        return value;

    const QwtTransform *transformation =
        scaleMap().transformation();

    if ( transformation == NULL )
    {
        const double range = maximum() - minimum();
        value += stepCount * range / d_data->totalSteps;
    }
    else
    {
        QwtScaleMap map = scaleMap();
        map.setPaintInterval( 0, d_data->totalSteps );

        // we need equidant steps according to
        // paint device coordinates
        const double range = transformation->transform( maximum() ) 
            - transformation->transform( minimum() );

        const double stepSize = range / d_data->totalSteps;

        double v = transformation->transform( value );

        v = qRound( v / stepSize ) * stepSize; 
        v += stepCount * range / d_data->totalSteps;

        value = transformation->invTransform( v );
    }

    value = boundedValue( value );

    if ( d_data->stepAlignment )
        value = alignedValue( value );

    return value;
}

double QwtAbstractSlider::boundedValue( double value ) const
{
    const double vmin = minimum();
    const double vmax = maximum();

    if ( d_data->wrapping && vmin != vmax )
    {
        const int fullCircle = 360 * 16;

        const double pd = scaleMap().pDist();
        if ( int( pd / fullCircle ) * fullCircle == pd )
        {
            // full circle scales: min and max are the same
            const double range = vmax - vmin;

            if ( value < vmin )
            {
                value += ::ceil( ( vmin - value ) / range ) * range;
            }
            else if ( value > vmax )
            {
                value -= ::ceil( ( value - vmax ) / range ) * range;
            }
        }
        else
        {
            if ( value < vmin )
                value = vmax;
            else if ( value > vmax )
                value = vmin;
        }
    }
    else
    {
        value = qBound( vmin, value, vmax );
    }

    return value;
pixhawk's avatar
pixhawk committed
745 746
}

Bryant's avatar
Bryant committed
747
double QwtAbstractSlider::alignedValue( double value ) const
pixhawk's avatar
pixhawk committed
748
{
Bryant's avatar
Bryant committed
749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795
    if ( d_data->totalSteps == 0 )
        return value;

    double stepSize;

    if ( scaleMap().transformation() == NULL )
    {
        stepSize = ( maximum() - minimum() ) / d_data->totalSteps;
        if ( stepSize > 0.0 )
        {
            value = lowerBound() + 
                qRound( ( value - lowerBound() ) / stepSize ) * stepSize;
        }
    }
    else
    {
        stepSize = ( scaleMap().p2() - scaleMap().p1() ) / d_data->totalSteps;

        if ( stepSize > 0.0 )
        {
            double v = scaleMap().transform( value );

            v = scaleMap().p1() +
                qRound( ( v - scaleMap().p1() ) / stepSize ) * stepSize;

            value = scaleMap().invTransform( v );
        }
    }

    if ( qAbs( stepSize ) > 1e-12 )
    {
        if ( qFuzzyCompare( value + 1.0, 1.0 ) )
        {
            // correct rounding error if value = 0
            value = 0.0;
        }
        else
        {
            // correct rounding error at the border
            if ( qFuzzyCompare( value, upperBound() ) )
                value = upperBound();
            else if ( qFuzzyCompare( value, lowerBound() ) )
                value = lowerBound();
        }
    }

    return value;
796
}
pixhawk's avatar
pixhawk committed
797

Bryant's avatar
Bryant committed
798 799 800 801
/*!
  Update the slider according to modifications of the scale
 */
void QwtAbstractSlider::scaleChange()
pixhawk's avatar
pixhawk committed
802
{
Bryant's avatar
Bryant committed
803 804 805 806 807 808 809 810 811 812 813 814 815
    const double value = qBound( minimum(), d_data->value, maximum() );

    const bool changed = ( value != d_data->value );
    if ( changed )
    {
        d_data->value = value;
    }

    if ( d_data->isValid || changed )
        Q_EMIT valueChanged( d_data->value );

    updateGeometry();
    update();
pixhawk's avatar
pixhawk committed
816 817
}

Bryant's avatar
Bryant committed
818 819
//! Calling update()
void QwtAbstractSlider::sliderChange()
pixhawk's avatar
pixhawk committed
820
{
Bryant's avatar
Bryant committed
821
    update();
pixhawk's avatar
pixhawk committed
822
}