~l3on/ubuntu/oneiric/qwt/fix-921430

« back to all changes in this revision

Viewing changes to qwt-5.0.2/src/qwt_abstract_slider.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Fathi Boudra
  • Date: 2007-10-05 15:20:41 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20071005152041-qmybqh4fj9jejyo2
Tags: 5.0.2-2
* Handle nostrip build option. (Closes: #437877)
* Build libqwt5-doc package in binary-indep target. (Closes: #443110)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
 
2
 * Qwt Widget Library
 
3
 * Copyright (C) 1997   Josef Wilgen
 
4
 * Copyright (C) 2002   Uwe Rathmann
 
5
 * 
 
6
 * This library is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the Qwt License, Version 1.0
 
8
 *****************************************************************************/
 
9
 
 
10
#include <qevent.h>
 
11
#include <qdatetime.h>
 
12
#include "qwt_abstract_slider.h"
 
13
#include "qwt_math.h"
 
14
 
 
15
#ifndef WHEEL_DELTA
 
16
#define WHEEL_DELTA 120
 
17
#endif
 
18
 
 
19
class QwtAbstractSlider::PrivateData
 
20
{
 
21
public:
 
22
    PrivateData():
 
23
        scrollMode(ScrNone),
 
24
        mouseOffset(0.0),
 
25
        tracking(true),
 
26
        tmrID(0),
 
27
        updTime(150),
 
28
        mass(0.0),
 
29
        readOnly(false)
 
30
    {
 
31
    }
 
32
 
 
33
    int scrollMode;
 
34
    double mouseOffset;
 
35
    int direction;
 
36
    int tracking;
 
37
 
 
38
    int tmrID;
 
39
    int updTime;
 
40
    int timerTick;
 
41
    QTime time;
 
42
    double speed;
 
43
    double mass;
 
44
    Qt::Orientation orientation;
 
45
    bool readOnly;
 
46
};
 
47
 
 
48
/*! 
 
49
   \brief Constructor
 
50
 
 
51
   \param orientation Orientation
 
52
   \param parent Parent widget
 
53
*/
 
54
QwtAbstractSlider::QwtAbstractSlider(
 
55
        Qt::Orientation orientation, QWidget *parent): 
 
56
    QWidget(parent, NULL)
 
57
{
 
58
    d_data = new QwtAbstractSlider::PrivateData;
 
59
    d_data->orientation = orientation;
 
60
 
 
61
#if QT_VERSION >= 0x040000
 
62
    using namespace Qt;
 
63
#endif
 
64
    setFocusPolicy(TabFocus);
 
65
}
 
66
 
 
67
//! Destructor
 
68
QwtAbstractSlider::~QwtAbstractSlider()
 
69
{
 
70
    if(d_data->tmrID) 
 
71
        killTimer(d_data->tmrID);
 
72
 
 
73
    delete d_data;
 
74
}
 
75
 
 
76
/*!
 
77
  En/Disable read only mode
 
78
 
 
79
  In read only mode the slider can't be controlled by mouse
 
80
  or keyboard.
 
81
 
 
82
  \param readOnly Enables in case of true
 
83
  \sa isReadOnly()
 
84
*/
 
85
void QwtAbstractSlider::setReadOnly(bool readOnly)
 
86
{
 
87
    d_data->readOnly = readOnly;
 
88
    update();
 
89
}
 
90
 
 
91
/*!
 
92
  In read only mode the slider can't be controlled by mouse
 
93
  or keyboard.
 
94
 
 
95
  \return true if read only
 
96
  \sa setReadOnly()
 
97
*/
 
98
bool QwtAbstractSlider::isReadOnly() const
 
99
{
 
100
    return d_data->readOnly;
 
101
}
 
102
 
 
103
/*!
 
104
  \brief Set the orientation.
 
105
  \param o Orientation. Allowed values are
 
106
           Qt::Horizontal and Qt::Vertical.
 
107
*/
 
108
void QwtAbstractSlider::setOrientation(Qt::Orientation o)
 
109
{
 
110
    d_data->orientation = o;
 
111
}
 
112
 
 
113
/*! 
 
114
  \return Orientation
 
115
  \sa setOrientation()
 
116
*/
 
117
Qt::Orientation QwtAbstractSlider::orientation() const
 
118
{
 
119
    return d_data->orientation;
 
120
}
 
121
 
 
122
//! Stop updating if automatic scrolling is active
 
123
 
 
124
void QwtAbstractSlider::stopMoving() 
 
125
{
 
126
    if(d_data->tmrID)
 
127
    {
 
128
        killTimer(d_data->tmrID);
 
129
        d_data->tmrID = 0;
 
130
    }
 
131
}
 
132
 
 
133
/*!
 
134
  \brief Specify the update interval for automatic scrolling
 
135
  \param t update interval in milliseconds
 
136
  \sa getScrollMode()
 
137
*/
 
138
void QwtAbstractSlider::setUpdateTime(int t) 
 
139
{
 
140
    if (t < 50) 
 
141
        t = 50;
 
142
    d_data->updTime = t;
 
143
}
 
144
 
 
145
 
 
146
//! Mouse press event handler
 
147
void QwtAbstractSlider::mousePressEvent(QMouseEvent *e) 
 
148
{
 
149
    if ( isReadOnly() )
 
150
    {
 
151
        e->ignore();
 
152
        return;
 
153
    }
 
154
    if ( !isValid() )
 
155
        return;
 
156
 
 
157
    const QPoint &p = e->pos();
 
158
 
 
159
    d_data->timerTick = 0;
 
160
 
 
161
    getScrollMode(p, d_data->scrollMode, d_data->direction);
 
162
    stopMoving();
 
163
    
 
164
    switch(d_data->scrollMode)
 
165
    {
 
166
        case ScrPage:
 
167
        case ScrTimer:
 
168
            d_data->mouseOffset = 0;
 
169
            d_data->tmrID = startTimer(qwtMax(250, 2 * d_data->updTime));
 
170
            break;
 
171
        
 
172
        case ScrMouse:
 
173
            d_data->time.start();
 
174
            d_data->speed = 0;
 
175
            d_data->mouseOffset = getValue(p) - value();
 
176
            emit sliderPressed();
 
177
            break;
 
178
        
 
179
        default:
 
180
            d_data->mouseOffset = 0;
 
181
            d_data->direction = 0;
 
182
            break;
 
183
    }
 
184
}
 
185
 
 
186
 
 
187
//! Emits a valueChanged() signal if necessary
 
188
void QwtAbstractSlider::buttonReleased()
 
189
{
 
190
    if ((!d_data->tracking) || (value() != prevValue()))
 
191
        emit valueChanged(value());
 
192
}
 
193
 
 
194
 
 
195
//! Mouse Release Event handler
 
196
void QwtAbstractSlider::mouseReleaseEvent(QMouseEvent *e)
 
197
{
 
198
    if ( isReadOnly() )
 
199
    {
 
200
        e->ignore();
 
201
        return;
 
202
    }
 
203
    if ( !isValid() )
 
204
        return;
 
205
 
 
206
    const double inc = step();
 
207
    
 
208
    switch(d_data->scrollMode) 
 
209
    {
 
210
        case ScrMouse:
 
211
        {
 
212
            setPosition(e->pos());
 
213
            d_data->direction = 0;
 
214
            d_data->mouseOffset = 0;
 
215
            if (d_data->mass > 0.0) 
 
216
            {
 
217
                const int ms = d_data->time.elapsed();
 
218
                if ((fabs(d_data->speed) >  0.0) && (ms < 50))
 
219
                    d_data->tmrID = startTimer(d_data->updTime);
 
220
            }
 
221
            else
 
222
            {
 
223
                d_data->scrollMode = ScrNone;
 
224
                buttonReleased();
 
225
            }
 
226
            emit sliderReleased();
 
227
            
 
228
            break;
 
229
        }
 
230
 
 
231
        case ScrDirect:
 
232
        {
 
233
            setPosition(e->pos());
 
234
            d_data->direction = 0;
 
235
            d_data->mouseOffset = 0;
 
236
            d_data->scrollMode = ScrNone;
 
237
            buttonReleased();
 
238
            break;
 
239
        }
 
240
 
 
241
        case ScrPage:
 
242
        {
 
243
            stopMoving();
 
244
            if (!d_data->timerTick)
 
245
                QwtDoubleRange::incPages(d_data->direction);
 
246
            d_data->timerTick = 0;
 
247
            buttonReleased();
 
248
            d_data->scrollMode = ScrNone;
 
249
            break;
 
250
        }
 
251
 
 
252
        case ScrTimer:
 
253
        {
 
254
            stopMoving();
 
255
            if (!d_data->timerTick)
 
256
                QwtDoubleRange::fitValue(value() + double(d_data->direction) * inc);
 
257
            d_data->timerTick = 0;
 
258
            buttonReleased();
 
259
            d_data->scrollMode = ScrNone;
 
260
            break;
 
261
        }
 
262
 
 
263
        default:
 
264
        {
 
265
            d_data->scrollMode = ScrNone;
 
266
            buttonReleased();
 
267
        }
 
268
    }
 
269
}
 
270
 
 
271
 
 
272
/*!
 
273
  Move the slider to a specified point, adjust the value
 
274
  and emit signals if necessary.
 
275
*/
 
276
void QwtAbstractSlider::setPosition(const QPoint &p) 
 
277
{
 
278
    QwtDoubleRange::fitValue(getValue(p) - d_data->mouseOffset);
 
279
}
 
280
 
 
281
 
 
282
/*!
 
283
  \brief Enables or disables tracking.
 
284
 
 
285
  If tracking is enabled, the slider emits a
 
286
  valueChanged() signal whenever its value
 
287
  changes (the default behaviour). If tracking
 
288
  is disabled, the value changed() signal will only
 
289
  be emitted if:<ul>
 
290
  <li>the user releases the mouse
 
291
      button and the value has changed or
 
292
  <li>at the end of automatic scrolling.</ul>
 
293
  Tracking is enabled by default.
 
294
  \param enable \c true (enable) or \c false (disable) tracking.
 
295
*/
 
296
void QwtAbstractSlider::setTracking(bool enable)
 
297
{
 
298
    d_data->tracking = enable;
 
299
}
 
300
 
 
301
/*! 
 
302
   Mouse Move Event handler
 
303
   \param e Mouse event
 
304
*/
 
305
void QwtAbstractSlider::mouseMoveEvent(QMouseEvent *e)
 
306
{
 
307
    if ( isReadOnly() )
 
308
    {
 
309
        e->ignore();
 
310
        return;
 
311
    }
 
312
 
 
313
    if ( !isValid() )
 
314
        return;
 
315
 
 
316
    if (d_data->scrollMode == ScrMouse )
 
317
    {
 
318
        setPosition(e->pos());
 
319
        if (d_data->mass > 0.0) 
 
320
        {
 
321
            double ms = double(d_data->time.elapsed());
 
322
            if (ms < 1.0) 
 
323
                ms = 1.0;
 
324
            d_data->speed = (exactValue() - exactPrevValue()) / ms;
 
325
            d_data->time.start();
 
326
        }
 
327
        if (value() != prevValue())
 
328
            emit sliderMoved(value());
 
329
    }
 
330
}
 
331
 
 
332
/*! 
 
333
   Wheel Event handler
 
334
   \param e Whell event
 
335
*/
 
336
void QwtAbstractSlider::wheelEvent(QWheelEvent *e)
 
337
{
 
338
    if ( isReadOnly() )
 
339
    {
 
340
        e->ignore();
 
341
        return;
 
342
    }
 
343
 
 
344
    if ( !isValid() )
 
345
        return;
 
346
 
 
347
    int mode = ScrNone, direction = 0;
 
348
 
 
349
    // Give derived classes a chance to say ScrNone
 
350
    getScrollMode(e->pos(), mode, direction);
 
351
    if ( mode != ScrNone )
 
352
    {
 
353
        const int inc = e->delta() / WHEEL_DELTA;
 
354
        QwtDoubleRange::incPages(inc);
 
355
        if (value() != prevValue())
 
356
            emit sliderMoved(value());
 
357
    }
 
358
}
 
359
 
 
360
/*!
 
361
  Handles key events
 
362
 
 
363
  - Key_Down, KeyLeft\n
 
364
    Decrement by 1
 
365
  - Key_Up, Key_Right\n
 
366
    Increment by 1
 
367
 
 
368
  \param e Key event
 
369
  \sa isReadOnly()
 
370
*/
 
371
void QwtAbstractSlider::keyPressEvent(QKeyEvent *e)
 
372
{
 
373
    if ( isReadOnly() )
 
374
    {
 
375
        e->ignore();
 
376
        return;
 
377
    }
 
378
 
 
379
    if ( !isValid() )
 
380
        return;
 
381
 
 
382
    int increment = 0;
 
383
    switch ( e->key() ) 
 
384
    {
 
385
        case Qt::Key_Down:
 
386
            if ( orientation() == Qt::Vertical )
 
387
                increment = -1;
 
388
            break;
 
389
        case Qt::Key_Up:
 
390
            if ( orientation() == Qt::Vertical )
 
391
                increment = 1;
 
392
            break;
 
393
        case Qt::Key_Left:
 
394
            if ( orientation() == Qt::Horizontal )
 
395
                increment = -1;
 
396
            break;
 
397
        case Qt::Key_Right:
 
398
            if ( orientation() == Qt::Horizontal )
 
399
                increment = 1;
 
400
            break;
 
401
        default:;
 
402
            e->ignore();
 
403
    }
 
404
 
 
405
    if ( increment != 0 )
 
406
    {
 
407
        QwtDoubleRange::incValue(increment);
 
408
        if (value() != prevValue())
 
409
            emit sliderMoved(value());
 
410
    }
 
411
}
 
412
 
 
413
/*! 
 
414
   Qt timer event
 
415
   \param e Timer event
 
416
*/
 
417
void QwtAbstractSlider::timerEvent(QTimerEvent *)
 
418
{
 
419
    const double inc = step();
 
420
 
 
421
    switch (d_data->scrollMode)
 
422
    {
 
423
        case ScrMouse:
 
424
        {
 
425
            if (d_data->mass > 0.0)
 
426
            {
 
427
                d_data->speed *= exp( - double(d_data->updTime) * 0.001 / d_data->mass );
 
428
                const double newval = 
 
429
                    exactValue() + d_data->speed * double(d_data->updTime);
 
430
                QwtDoubleRange::fitValue(newval);
 
431
                // stop if d_data->speed < one step per second
 
432
                if (fabs(d_data->speed) < 0.001 * fabs(step()))
 
433
                {
 
434
                    d_data->speed = 0;
 
435
                    stopMoving();
 
436
                    buttonReleased();
 
437
                }
 
438
 
 
439
            }
 
440
            else
 
441
               stopMoving();
 
442
            break;
 
443
        }
 
444
 
 
445
        case ScrPage:
 
446
        {
 
447
            QwtDoubleRange::incPages(d_data->direction);
 
448
            if (!d_data->timerTick) 
 
449
            {
 
450
                killTimer(d_data->tmrID);
 
451
                d_data->tmrID = startTimer(d_data->updTime);
 
452
            }
 
453
            break;
 
454
        }
 
455
        case ScrTimer:
 
456
        {
 
457
            QwtDoubleRange::fitValue(value() +  double(d_data->direction) * inc);
 
458
            if (!d_data->timerTick) 
 
459
            {
 
460
                killTimer(d_data->tmrID);
 
461
                d_data->tmrID = startTimer(d_data->updTime);
 
462
            }
 
463
            break;
 
464
        }
 
465
        default:
 
466
        {
 
467
            stopMoving();
 
468
            break;
 
469
        }
 
470
    }
 
471
 
 
472
    d_data->timerTick = 1;
 
473
}
 
474
 
 
475
 
 
476
/*!
 
477
  Notify change of value
 
478
 
 
479
  This function can be reimplemented by derived classes
 
480
  in order to keep track of changes, i.e. repaint the widget.
 
481
  The default implementation emits a valueChanged() signal
 
482
  if tracking is enabled.
 
483
*/
 
484
void QwtAbstractSlider::valueChange() 
 
485
{
 
486
    if (d_data->tracking)
 
487
       emit valueChanged(value());  
 
488
}
 
489
 
 
490
/*!
 
491
  \brief Set the slider's mass for flywheel effect.
 
492
 
 
493
  If the slider's mass is greater then 0, it will continue
 
494
  to move after the mouse button has been released. Its speed
 
495
  decreases with time at a rate depending on the slider's mass.
 
496
  A large mass means that it will continue to move for a
 
497
  long time.
 
498
 
 
499
  Derived widgets may overload this function to make it public.
 
500
 
 
501
  \param val New mass in kg
 
502
 
 
503
  \bug If the mass is smaller than 1g, it is set to zero.
 
504
       The maximal mass is limited to 100kg.
 
505
  \sa mass()
 
506
*/
 
507
void QwtAbstractSlider::setMass(double val)
 
508
{
 
509
    if (val < 0.001)
 
510
       d_data->mass = 0.0;
 
511
    else if (val > 100.0)
 
512
       d_data->mass = 100.0;
 
513
    else
 
514
       d_data->mass = val;
 
515
}
 
516
 
 
517
/*!
 
518
    \return mass
 
519
    \sa setMass()
 
520
*/
 
521
double QwtAbstractSlider::mass() const
 
522
{   
 
523
    return d_data->mass; 
 
524
}
 
525
 
 
526
 
 
527
/*!
 
528
  \brief Move the slider to a specified value
 
529
 
 
530
  This function can be used to move the slider to a value
 
531
  which is not an integer multiple of the step size.
 
532
  \param val new value
 
533
  \sa fitValue()
 
534
*/
 
535
void QwtAbstractSlider::setValue(double val)
 
536
{
 
537
    if (d_data->scrollMode == ScrMouse) 
 
538
        stopMoving();
 
539
    QwtDoubleRange::setValue(val);
 
540
}
 
541
 
 
542
 
 
543
/*!
 
544
  \brief Set the slider's value to the nearest integer multiple
 
545
         of the step size.
 
546
 
 
547
   \param valeu Value
 
548
   \sa setValue(), incValue()
 
549
*/
 
550
void QwtAbstractSlider::fitValue(double value)
 
551
{
 
552
    if (d_data->scrollMode == ScrMouse) 
 
553
        stopMoving();
 
554
    QwtDoubleRange::fitValue(value);
 
555
}
 
556
 
 
557
/*!
 
558
  \brief Increment the value by a specified number of steps
 
559
  \param steps number of steps
 
560
  \sa setValue()
 
561
*/
 
562
void QwtAbstractSlider::incValue(int steps)
 
563
{
 
564
    if (d_data->scrollMode == ScrMouse) 
 
565
        stopMoving();
 
566
    QwtDoubleRange::incValue(steps);
 
567
}
 
568
 
 
569
void QwtAbstractSlider::setMouseOffset(double offset)
 
570
{
 
571
    d_data->mouseOffset = offset;
 
572
 
573
 
 
574
double QwtAbstractSlider::mouseOffset() const
 
575
{
 
576
    return d_data->mouseOffset;
 
577
}
 
578
 
 
579
int QwtAbstractSlider::scrollMode() const
 
580
{
 
581
    return d_data->scrollMode;
 
582
}