source: vendor/trolltech/current/src/widgets/qscrollbar.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: 28.3 KB
Line 
1/****************************************************************************
2** $Id: qscrollbar.cpp 2 2005-11-16 15:49:26Z dmik $
3**
4** Implementation of QScrollBar 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 "qscrollbar.h"
39#ifndef QT_NO_SCROLLBAR
40#include "qpainter.h"
41#include "qbitmap.h"
42#include "qapplication.h"
43#include "qtimer.h"
44#include "qstyle.h"
45#ifndef QT_NO_CURSOR
46#include <qcursor.h>
47#endif
48#if defined(QT_ACCESSIBILITY_SUPPORT)
49#include "qaccessible.h"
50#endif
51#include <limits.h>
52
53/*!
54 \class QScrollBar
55 \brief The QScrollBar widget provides a vertical or horizontal scroll bar.
56
57 \ingroup basic
58
59 A scroll bar allows the user to control a value within a
60 program-definable range and gives users a visible indication of
61 the current value of a \link QRangeControl range control \endlink.
62
63 Scroll bars include four separate controls:
64
65 \list
66
67 \i The \e line-up and \e line-down controls are little buttons
68 which the user can use to move one "line" up or down. The meaning
69 of line is configurable. In editors and list boxes it means one
70 line of text; in an image viewer it might mean 20 pixels.
71
72 \i The \e slider is the handle that indicates the current value of
73 the scroll bar, which the user can drag to change the value. This
74 part of the scroll bar is sometimes called the "thumb".
75
76 \i The \e page-up/page-down control is the area on which the
77 slider slides (the scroll bar's background). Clicking here moves
78 the scroll bar towards the click. The meaning of "page" is also
79 configurable: in editors and list boxes it means as many lines as
80 there is space for in the widget.
81
82 \endlist
83
84 QScrollBar has very few of its own functions; it mostly relies on
85 QRangeControl. The most useful functions are setValue() to set the
86 scroll bar directly to some value; addPage(), addLine(),
87 subtractPage(), and subtractLine() to simulate the effects of
88 clicking (useful for accelerator keys); setSteps() to define the
89 values of pageStep() and lineStep(); and setRange() to set the
90 minValue() and maxValue() of the scroll bar. QScrollBar has a
91 convenience constructor with which you can set most of these
92 properties.
93
94 Some GUI styles (for example, the Windows and Motif styles
95 provided with Qt), also use the pageStep() value to calculate the
96 size of the slider.
97
98 In addition to the access functions from QRangeControl, QScrollBar
99 provides a comprehensive set of signals:
100 \table
101 \header \i Signal \i Emitted when
102 \row \i \l valueChanged()
103 \i the scroll bar's value has changed. The tracking()
104 determines whether this signal is emitted during user
105 interaction.
106 \row \i \l sliderPressed()
107 \i the user starts to drag the slider.
108 \row \i \l sliderMoved()
109 \i the user drags the slider.
110 \row \i \l sliderReleased()
111 \i the user releases the slider.
112 \row \i \l nextLine()
113 \i the scroll bar has moved one line down or right. Line is
114 defined in QRangeControl.
115 \row \i \l prevLine()
116 \i the scroll bar has moved one line up or left.
117 \row \i \l nextPage()
118 \i the scroll bar has moved one page down or right.
119 \row \i \l prevPage()
120 \i the scroll bar has moved one page up or left.
121 \endtable
122
123 QScrollBar only provides integer ranges. Note that although
124 QScrollBar handles very large numbers, scroll bars on current
125 screens cannot usefully control ranges above about 100,000 pixels.
126 Beyond that, it becomes difficult for the user to control the
127 scroll bar using either the keyboard or the mouse.
128
129 A scroll bar can be controlled by the keyboard, but it has a
130 default focusPolicy() of \c NoFocus. Use setFocusPolicy() to
131 enable keyboard focus. See keyPressEvent() for a list of key
132 bindings.
133
134 If you need to add scroll bars to an interface, consider using the
135 QScrollView class, which encapsulates the common uses for scroll
136 bars.
137
138 <img src=qscrbar-m.png> <img src=qscrbar-w.png>
139
140 \sa QSlider QSpinBox QScrollView
141 \link guibooks.html#fowler GUI Design Handbook: Scroll Bar\endlink
142*/
143
144
145/*!
146 \fn void QScrollBar::valueChanged( int value )
147
148 This signal is emitted when the scroll bar value has changed, with
149 the new scroll bar \a value as an argument.
150*/
151
152/*!
153 \fn void QScrollBar::sliderPressed()
154
155 This signal is emitted when the user presses the slider with the
156 mouse.
157*/
158
159/*!
160 \fn void QScrollBar::sliderMoved( int value )
161
162 This signal is emitted when the slider is dragged by the user, with
163 the new scroll bar \a value as an argument.
164
165 This signal is emitted even when tracking is turned off.
166
167 \sa tracking() valueChanged() nextLine() prevLine() nextPage()
168 prevPage()
169*/
170
171/*!
172 \fn void QScrollBar::sliderReleased()
173
174 This signal is emitted when the user releases the slider with the
175 mouse.
176*/
177
178/*!
179 \fn void QScrollBar::nextLine()
180
181 This signal is emitted when the scroll bar scrolls one line down
182 or right.
183*/
184
185/*!
186 \fn void QScrollBar::prevLine()
187
188 This signal is emitted when the scroll bar scrolls one line up or
189 left.
190*/
191
192/*!
193 \fn void QScrollBar::nextPage()
194
195 This signal is emitted when the scroll bar scrolls one page down
196 or right.
197*/
198
199/*!
200 \fn void QScrollBar::prevPage()
201
202 This signal is emitted when the scroll bar scrolls one page up or
203 left.
204*/
205
206
207
208static const int thresholdTime = 500;
209static const int repeatTime = 50;
210
211#define HORIZONTAL (orientation() == Horizontal)
212#define VERTICAL !HORIZONTAL
213#define MOTIF_BORDER 2
214#define SLIDER_MIN 9
215
216
217/*!
218 Constructs a vertical scroll bar.
219
220 The \a parent and \a name arguments are sent on to the QWidget
221 constructor.
222
223 The \c minValue defaults to 0, the \c maxValue to 99, with a \c
224 lineStep size of 1 and a \c pageStep size of 10, and an initial
225 \c value of 0.
226*/
227
228QScrollBar::QScrollBar( QWidget *parent, const char *name )
229 : QWidget( parent, name ), orient( Vertical )
230{
231 init();
232}
233
234/*!
235 Constructs a scroll bar.
236
237 The \a orientation must be \c Qt::Vertical or \c Qt::Horizontal.
238
239 The \a parent and \a name arguments are sent on to the QWidget
240 constructor.
241
242 The \c minValue defaults to 0, the \c maxValue to 99, with a \c
243 lineStep size of 1 and a \c pageStep size of 10, and an initial
244 \c value of 0.
245*/
246
247QScrollBar::QScrollBar( Orientation orientation, QWidget *parent,
248 const char *name )
249 : QWidget( parent, name ), orient( orientation )
250{
251 init();
252}
253
254/*!
255 Constructs a scroll bar whose value can never be smaller than \a
256 minValue or greater than \a maxValue, whose line step size is \a
257 lineStep and page step size is \a pageStep and whose value is
258 initially \a value (which is guaranteed to be in range using
259 bound()).
260
261 If \a orientation is \c Vertical the scroll bar is vertical and if
262 it is \c Horizontal the scroll bar is horizontal.
263
264 The \a parent and \a name arguments are sent on to the QWidget
265 constructor.
266*/
267
268QScrollBar::QScrollBar( int minValue, int maxValue, int lineStep, int pageStep,
269 int value, Orientation orientation,
270 QWidget *parent, const char *name )
271 : QWidget( parent, name ),
272 QRangeControl( minValue, maxValue, lineStep, pageStep, value ),
273 orient( orientation )
274{
275 init();
276}
277
278/*!
279 Destructor.
280*/
281QScrollBar::~QScrollBar()
282{
283}
284
285void QScrollBar::init()
286{
287 track = TRUE;
288 sliderPos = 0;
289 pressedControl = QStyle::SC_None;
290 clickedAt = FALSE;
291 setFocusPolicy( NoFocus );
292
293 repeater = 0;
294
295 setBackgroundMode((Qt::BackgroundMode)
296 style().styleHint(QStyle::SH_ScrollBar_BackgroundMode));
297
298 QSizePolicy sp( QSizePolicy::Minimum, QSizePolicy::Fixed );
299 if ( orient == Vertical )
300 sp.transpose();
301 setSizePolicy( sp );
302 clearWState( WState_OwnSizePolicy );
303}
304
305
306/*!
307 \property QScrollBar::orientation
308 \brief the orientation of the scroll bar
309
310 The orientation must be \l Qt::Vertical (the default) or \l
311 Qt::Horizontal.
312*/
313
314void QScrollBar::setOrientation( Orientation orientation )
315{
316 if ( orientation == orient )
317 return;
318 if ( !testWState( WState_OwnSizePolicy ) ) {
319 QSizePolicy sp = sizePolicy();
320 sp.transpose();
321 setSizePolicy( sp );
322 clearWState( WState_OwnSizePolicy );
323 }
324
325 orient = orientation;
326
327 positionSliderFromValue();
328 update();
329 updateGeometry();
330}
331
332/*!
333 \property QScrollBar::tracking
334 \brief whether scroll bar tracking is enabled
335
336 If tracking is enabled (the default), the scroll bar emits the
337 valueChanged() signal while the slider is being dragged. If
338 tracking is disabled, the scroll bar emits the valueChanged()
339 signal only when the user releases the mouse button after moving
340 the slider.
341*/
342
343
344/*!
345 \property QScrollBar::draggingSlider
346 \brief whether the user has clicked the mouse on the slider and is currently dragging it
347*/
348
349bool QScrollBar::draggingSlider() const
350{
351 return pressedControl == QStyle::SC_ScrollBarSlider;
352}
353
354
355/*!
356 Reimplements the virtual function QWidget::setPalette().
357
358 Sets the background color to the mid color for Motif style scroll
359 bars using palette \a p.
360*/
361
362void QScrollBar::setPalette( const QPalette &p )
363{
364 QWidget::setPalette( p );
365 setBackgroundMode((Qt::BackgroundMode)
366 style().styleHint(QStyle::SH_ScrollBar_BackgroundMode));
367}
368
369
370/*! \reimp */
371QSize QScrollBar::sizeHint() const
372{
373 constPolish();
374 int sbextent = style().pixelMetric(QStyle::PM_ScrollBarExtent, this);
375
376 if ( orient == Horizontal ) {
377 return QSize( 30, sbextent );
378 } else {
379 return QSize( sbextent, 30 );
380 }
381}
382
383/*! \fn void QScrollBar::setSizePolicy( QSizePolicy::SizeType, QSizePolicy::SizeType, bool )
384 \reimp
385*/
386
387/*! \reimp */
388void QScrollBar::setSizePolicy( QSizePolicy sp )
389{
390 //## remove 4.0
391 QWidget::setSizePolicy( sp );
392}
393
394/*!
395 \internal
396 Implements the virtual QRangeControl function.
397*/
398
399void QScrollBar::valueChange()
400{
401 int tmp = sliderPos;
402 positionSliderFromValue();
403 if ( tmp != sliderPos && isVisible() )
404 drawControls(QStyle::SC_ScrollBarAddPage |
405 QStyle::SC_ScrollBarSubPage |
406 QStyle::SC_ScrollBarSlider,
407 pressedControl );
408 emit valueChanged(value());
409#if defined(QT_ACCESSIBILITY_SUPPORT)
410 QAccessible::updateAccessibility( this, 0, QAccessible::ValueChanged );
411#endif
412}
413
414/*!
415 \internal
416 Implements the virtual QRangeControl function.
417*/
418
419void QScrollBar::stepChange()
420{
421 rangeChange();
422}
423
424/*!
425 \internal
426 Implements the virtual QRangeControl function.
427*/
428
429void QScrollBar::rangeChange()
430{
431 positionSliderFromValue();
432
433 if ( isVisible() )
434 drawControls(QStyle::SC_ScrollBarAddLine |
435 QStyle::SC_ScrollBarSubLine |
436 QStyle::SC_ScrollBarAddPage |
437 QStyle::SC_ScrollBarSubPage |
438 QStyle::SC_ScrollBarFirst |
439 QStyle::SC_ScrollBarLast |
440 QStyle::SC_ScrollBarSlider,
441 pressedControl );
442}
443
444
445/*!
446 Handles timer events for the scroll bar.
447*/
448
449void QScrollBar::doAutoRepeat()
450{
451 bool sendRepeat = clickedAt;
452#if !defined( QT_NO_CURSOR ) && !defined( QT_NO_STYLE )
453 if(sendRepeat && (pressedControl == QStyle::SC_ScrollBarAddPage ||
454 pressedControl == QStyle::SC_ScrollBarSubPage) &&
455 style().styleHint(QStyle::SH_ScrollBar_StopMouseOverSlider, this) &&
456 style().querySubControl(QStyle::CC_ScrollBar, this,
457 mapFromGlobal(QCursor::pos()) ) == QStyle::SC_ScrollBarSlider)
458 sendRepeat = FALSE;
459#endif
460 if ( sendRepeat ){
461 if ( repeater )
462 repeater->changeInterval( repeatTime );
463 action( (QStyle::SubControl) pressedControl );
464 QApplication::syncX();
465 } else {
466 stopAutoRepeat();
467 }
468}
469
470
471/*!
472 Starts the auto-repeat logic. Some time after this function is
473 called, the auto-repeat starts taking effect and from then on
474 repeats until stopAutoRepeat() is called.
475*/
476
477void QScrollBar::startAutoRepeat()
478{
479 if ( !repeater ) {
480 repeater = new QTimer( this, "auto-repeat timer" );
481 connect( repeater, SIGNAL(timeout()),
482 this, SLOT(doAutoRepeat()) );
483 }
484 repeater->start( thresholdTime, FALSE );
485}
486
487
488/*!
489 Stops the auto-repeat logic.
490*/
491
492void QScrollBar::stopAutoRepeat()
493{
494 delete repeater;
495 repeater = 0;
496}
497
498
499/*!
500 \reimp
501*/
502#ifndef QT_NO_WHEELEVENT
503void QScrollBar::wheelEvent( QWheelEvent *e )
504{
505 static float offset = 0;
506 static QScrollBar* offset_owner = 0;
507 if (offset_owner != this){
508 offset_owner = this;
509 offset = 0;
510 }
511 if ( e->orientation() != orient && !rect().contains(e->pos()) )
512 return;
513 e->accept();
514 int step = QMIN( QApplication::wheelScrollLines()*lineStep(),
515 pageStep() );
516 if ( ( e->state() & ControlButton ) || ( e->state() & ShiftButton ) )
517 step = pageStep();
518 offset += -e->delta()*step/120;
519 if (QABS(offset)<1)
520 return;
521 setValue( value() + int(offset) );
522 offset -= int(offset);
523}
524#endif
525
526/*!
527 \reimp
528*/
529void QScrollBar::keyPressEvent( QKeyEvent *e )
530{
531 // \list
532 // \i Left/Right move a horizontal scrollbar by one line.
533 // \i Up/Down move a vertical scrollbar by one line.
534 // \i PageUp moves up one page.
535 // \i PageDown moves down one page.
536 // \i Home moves to the start (minValue()).
537 // \i End moves to the end (maxValue()).
538 // \endlist
539
540 // Note that unless you call setFocusPolicy(), the default NoFocus
541 // will apply and the user will not be able to use the keyboard to
542 // interact with the scrollbar.
543 switch ( e->key() ) {
544 case Key_Left:
545 if ( orient == Horizontal )
546 subtractLine();
547 break;
548 case Key_Right:
549 if ( orient == Horizontal )
550 addLine();
551 break;
552 case Key_Up:
553 if ( orient == Vertical )
554 subtractLine();
555 break;
556 case Key_Down:
557 if ( orient == Vertical )
558 addLine();
559 break;
560 case Key_PageUp:
561 subtractPage();
562 break;
563 case Key_PageDown:
564 addPage();
565 break;
566 case Key_Home:
567 setValue( minValue() );
568 break;
569 case Key_End:
570 setValue( maxValue() );
571 break;
572 default:
573 e->ignore();
574 break;
575 }
576}
577
578
579/*!
580 \reimp
581*/
582void QScrollBar::resizeEvent( QResizeEvent * )
583{
584 positionSliderFromValue();
585}
586
587
588/*!
589 \reimp
590*/
591void QScrollBar::paintEvent( QPaintEvent * )
592{
593 QPainter p( this );
594 drawControls(QStyle::SC_ScrollBarAddLine |
595 QStyle::SC_ScrollBarSubLine |
596 QStyle::SC_ScrollBarAddPage |
597 QStyle::SC_ScrollBarSubPage |
598 QStyle::SC_ScrollBarFirst |
599 QStyle::SC_ScrollBarLast |
600 QStyle::SC_ScrollBarSlider,
601 pressedControl, &p );
602}
603
604static QCOORD sliderStartPos = 0;
605
606/*!
607 \reimp
608 */
609void QScrollBar::contextMenuEvent( QContextMenuEvent *e )
610{
611 if(clickedAt)
612 e->consume();
613 else
614 e->ignore();
615}
616
617/*!
618 \reimp
619*/
620void QScrollBar::mousePressEvent( QMouseEvent *e )
621{
622 bool midButtonAbsPos =
623 style().styleHint(QStyle::SH_ScrollBar_MiddleClickAbsolutePosition,
624 this);
625
626 if ( !(e->button() == LeftButton ||
627 (midButtonAbsPos && e->button() == MidButton) ) )
628 return;
629
630 if ( maxValue() == minValue() ) // nothing to be done
631 return;
632
633 if ( e->state() & MouseButtonMask ) // another button was already pressed
634 return;
635
636 clickedAt = TRUE;
637 pressedControl = style().querySubControl(QStyle::CC_ScrollBar, this, e->pos() );
638
639 if ( (pressedControl == QStyle::SC_ScrollBarAddPage ||
640 pressedControl == QStyle::SC_ScrollBarSubPage ||
641 pressedControl == QStyle::SC_ScrollBarSlider ) &&
642 ((midButtonAbsPos && e->button() == MidButton) ||
643 style().styleHint(QStyle::SH_ScrollBar_LeftClickAbsolutePosition) && e->button() == LeftButton)) {
644
645 QRect sr = style().querySubControlMetrics(QStyle::CC_ScrollBar, this,
646 QStyle::SC_ScrollBarSlider ),
647 gr = style().querySubControlMetrics(QStyle::CC_ScrollBar, this,
648 QStyle::SC_ScrollBarGroove );
649 int sliderMin, sliderMax, sliderLength;
650 sliderMin = sliderMax = sliderLength = 0;
651 if (HORIZONTAL) {
652 sliderMin = gr.x();
653 sliderMax = sliderMin + gr.width();
654 sliderLength = sr.width();
655 } else {
656 sliderMin = gr.y();
657 sliderMax = sliderMin + gr.height();
658 sliderLength = sr.height();
659 }
660
661 int newSliderPos = (HORIZONTAL ? e->pos().x() : e->pos().y())
662 - sliderLength/2;
663 newSliderPos = QMIN( newSliderPos, sliderMax - sliderLength );
664 newSliderPos = QMAX( newSliderPos, sliderMin );
665 setValue( sliderPosToRangeValue(newSliderPos) );
666 sliderPos = newSliderPos;
667 pressedControl = QStyle::SC_ScrollBarSlider;
668 }
669
670 if ( pressedControl == QStyle::SC_ScrollBarSlider ) {
671 clickOffset = (QCOORD)( (HORIZONTAL ? e->pos().x() : e->pos().y())
672 - sliderPos );
673 slidePrevVal = value();
674 sliderStartPos = sliderPos;
675 drawControls( pressedControl, pressedControl );
676 emit sliderPressed();
677#if defined(QT_ACCESSIBILITY_SUPPORT)
678 QAccessible::updateAccessibility( this, 0, QAccessible::ScrollingStart );
679#endif
680 } else if ( pressedControl != QStyle::SC_None ) {
681 drawControls( pressedControl, pressedControl );
682 action( (QStyle::SubControl) pressedControl );
683 startAutoRepeat();
684 }
685}
686
687
688/*!
689 \reimp
690*/
691void QScrollBar::mouseReleaseEvent( QMouseEvent *e )
692{
693 if ( !clickedAt )
694 return;
695
696 if ( e->stateAfter() & MouseButtonMask ) // some other button is still pressed
697 return;
698
699 QStyle::SubControl tmp = (QStyle::SubControl) pressedControl;
700 clickedAt = FALSE;
701 stopAutoRepeat();
702 mouseMoveEvent( e ); // Might have moved since last mouse move event.
703 pressedControl = QStyle::SC_None;
704
705 if (tmp == QStyle::SC_ScrollBarSlider) {
706 directSetValue( calculateValueFromSlider() );
707 emit sliderReleased();
708 if ( value() != prevValue() ) {
709 emit valueChanged( value() );
710#if defined(QT_ACCESSIBILITY_SUPPORT)
711 QAccessible::updateAccessibility( this, 0, QAccessible::ValueChanged );
712#endif
713 }
714#if defined(QT_ACCESSIBILITY_SUPPORT)
715 QAccessible::updateAccessibility( this, 0, QAccessible::ScrollingEnd );
716#endif
717 }
718 drawControls( tmp, pressedControl );
719 if ( e->button() == MidButton )
720 repaint( FALSE );
721}
722
723
724/*!
725 \reimp
726*/
727void QScrollBar::mouseMoveEvent( QMouseEvent *e )
728{
729 if ( !isVisible() ) {
730 clickedAt = FALSE;
731 return;
732 }
733
734 bool mcab = style().styleHint(QStyle::SH_ScrollBar_MiddleClickAbsolutePosition,
735 this);
736 if ( ! clickedAt || ! (e->state() & LeftButton ||
737 ((e->state() & MidButton) && mcab)))
738 return;
739
740 int newSliderPos;
741 if ( pressedControl == QStyle::SC_ScrollBarSlider ) {
742 QRect gr = style().querySubControlMetrics(QStyle::CC_ScrollBar, this,
743 QStyle::SC_ScrollBarGroove ),
744 sr = style().querySubControlMetrics(QStyle::CC_ScrollBar, this,
745 QStyle::SC_ScrollBarSlider );
746 int sliderMin, sliderMax, sliderLength;
747
748 if (HORIZONTAL) {
749 sliderLength = sr.width();
750 sliderMin = gr.x();
751 sliderMax = gr.right() - sliderLength + 1;
752 } else {
753 sliderLength = sr.height();
754 sliderMin = gr.y();
755 sliderMax = gr.bottom() - sliderLength + 1;
756 }
757
758 QRect r = rect();
759 int m = style().pixelMetric(QStyle::PM_MaximumDragDistance, this);
760 if ( m >= 0 ) {
761 if ( orientation() == Horizontal )
762 r.setRect( r.x() - m, r.y() - 2*m, r.width() + 2*m, r.height() + 4*m );
763 else
764 r.setRect( r.x() - 2*m, r.y() - m, r.width() + 4*m, r.height() + 2*m );
765 if (! r.contains( e->pos()))
766 newSliderPos = sliderStartPos;
767 else
768 newSliderPos = (HORIZONTAL ? e->pos().x() :
769 e->pos().y()) -clickOffset;
770 } else
771 newSliderPos = (HORIZONTAL ? e->pos().x() :
772 e->pos().y()) -clickOffset;
773
774 if ( newSliderPos < sliderMin )
775 newSliderPos = sliderMin;
776 else if ( newSliderPos > sliderMax )
777 newSliderPos = sliderMax;
778 int newVal = sliderPosToRangeValue(newSliderPos);
779 if ( newVal != slidePrevVal )
780 emit sliderMoved( newVal );
781 if ( track && newVal != value() ) {
782 directSetValue( newVal ); // Set directly, painting done below
783 emit valueChanged( value() );
784#if defined(QT_ACCESSIBILITY_SUPPORT)
785 QAccessible::updateAccessibility( this, 0, QAccessible::ValueChanged );
786#endif
787 }
788 slidePrevVal = newVal;
789 sliderPos = (QCOORD)newSliderPos;
790 drawControls( QStyle::SC_ScrollBarAddPage |
791 QStyle::SC_ScrollBarSlider |
792 QStyle::SC_ScrollBarSubPage,
793 pressedControl );
794 } else if (! style().styleHint(QStyle::SH_ScrollBar_ScrollWhenPointerLeavesControl)) {
795 // stop scrolling when the mouse pointer leaves a control
796 // similar to push buttons
797 if ( pressedControl != (uint)style().querySubControl(QStyle::CC_ScrollBar, this, e->pos() ) ) {
798 drawControls( pressedControl, QStyle::SC_None );
799 stopAutoRepeat();
800 } else if ( !repeater ) {
801 drawControls( pressedControl, pressedControl );
802 action( (QStyle::SubControl) pressedControl );
803 startAutoRepeat();
804 }
805 }
806}
807
808
809/*!
810 \fn int QScrollBar::sliderStart() const
811
812 Returns the pixel position where the scroll bar slider starts.
813
814 This is equivalent to sliderRect().y() for vertical scroll bars or
815 sliderRect().x() for horizontal scroll bars.
816*/
817
818/*!
819 Returns the scroll bar slider rectangle.
820
821 \sa sliderStart()
822*/
823
824QRect QScrollBar::sliderRect() const
825{
826 return style().querySubControlMetrics(QStyle::CC_ScrollBar, this,
827 QStyle::SC_ScrollBarSlider );
828}
829
830void QScrollBar::positionSliderFromValue()
831{
832 sliderPos = (QCOORD)rangeValueToSliderPos( value() );
833}
834
835int QScrollBar::calculateValueFromSlider() const
836{
837 return sliderPosToRangeValue( sliderPos );
838}
839
840int QScrollBar::rangeValueToSliderPos( int v ) const
841{
842 QRect gr = style().querySubControlMetrics(QStyle::CC_ScrollBar, this,
843 QStyle::SC_ScrollBarGroove );
844 QRect sr = style().querySubControlMetrics(QStyle::CC_ScrollBar, this,
845 QStyle::SC_ScrollBarSlider );
846 int sliderMin, sliderMax, sliderLength;
847
848 if (HORIZONTAL) {
849 sliderLength = sr.width();
850 sliderMin = gr.x();
851 sliderMax = gr.right() - sliderLength + 1;
852 } else {
853 sliderLength = sr.height();
854 sliderMin = gr.y();
855 sliderMax = gr.bottom() - sliderLength + 1;
856 }
857
858 return positionFromValue( v, sliderMax-sliderMin ) + sliderMin;
859}
860
861int QScrollBar::sliderPosToRangeValue( int pos ) const
862{
863 QRect gr = style().querySubControlMetrics(QStyle::CC_ScrollBar, this,
864 QStyle::SC_ScrollBarGroove );
865 QRect sr = style().querySubControlMetrics(QStyle::CC_ScrollBar, this,
866 QStyle::SC_ScrollBarSlider );
867 int sliderMin, sliderMax, sliderLength;
868
869 if (HORIZONTAL) {
870 sliderLength = sr.width();
871 sliderMin = gr.x();
872 sliderMax = gr.right() - sliderLength + 1;
873 } else {
874 sliderLength = sr.height();
875 sliderMin = gr.y();
876 sliderMax = gr.bottom() - sliderLength + 1;
877 }
878
879 return valueFromPosition( pos - sliderMin, sliderMax - sliderMin );
880}
881
882
883void QScrollBar::action( int control )
884{
885 switch( control ) {
886 case QStyle::SC_ScrollBarAddLine:
887 addLine();
888 emit nextLine();
889 break;
890 case QStyle::SC_ScrollBarSubLine:
891 subtractLine();
892 emit prevLine();
893 break;
894 case QStyle::SC_ScrollBarAddPage:
895 addPage();
896 emit nextPage();
897 break;
898 case QStyle::SC_ScrollBarSubPage:
899 subtractPage();
900 emit prevPage();
901 break;
902 case QStyle::SC_ScrollBarFirst:
903 setValue( minValue() );
904#if defined(QT_ACCESSIBILITY_SUPPORT)
905 QAccessible::updateAccessibility( this, 0, QAccessible::ValueChanged );
906#endif
907 emit valueChanged( minValue() );
908 break;
909 case QStyle::SC_ScrollBarLast:
910 setValue( maxValue() );
911#if defined(QT_ACCESSIBILITY_SUPPORT)
912 QAccessible::updateAccessibility( this, 0, QAccessible::ValueChanged );
913#endif
914 emit valueChanged( maxValue() );
915 break;
916 default:
917 break;
918 }
919}
920
921
922void QScrollBar::drawControls( uint controls, uint activeControl ) const
923{
924 QPainter p ( this );
925 drawControls( controls, activeControl, &p );
926}
927
928
929void QScrollBar::drawControls( uint controls, uint activeControl,
930 QPainter *p ) const
931{
932 if ( !isUpdatesEnabled() )
933 return;
934
935 QStyle::SFlags flags = QStyle::Style_Default;
936 if (isEnabled())
937 flags |= QStyle::Style_Enabled;
938 if (hasFocus())
939 flags |= QStyle::Style_HasFocus;
940 if ( orientation() == Horizontal )
941 flags |= QStyle::Style_Horizontal;
942
943 style().drawComplexControl(QStyle::CC_ScrollBar, p, this, rect(), colorGroup(),
944 flags, (QStyle::SubControl) controls,
945 (QStyle::SubControl) activeControl );
946}
947
948/*!
949 \reimp
950*/
951void QScrollBar::styleChange( QStyle& old )
952{
953 positionSliderFromValue();
954 setBackgroundMode((Qt::BackgroundMode)
955 style().styleHint(QStyle::SH_ScrollBar_BackgroundMode));
956 QWidget::styleChange( old );
957}
958
959/*!
960 \property QScrollBar::minValue
961 \brief the scroll bar's minimum value
962
963 When setting this property, the \l QScrollBar::maxValue is
964 adjusted if necessary to ensure that the range remains valid.
965
966 \sa setRange()
967*/
968int QScrollBar::minValue() const
969{
970 return QRangeControl::minValue();
971}
972
973void QScrollBar::setMinValue( int minVal )
974{
975 QRangeControl::setMinValue( minVal );
976}
977
978/*!
979 \property QScrollBar::maxValue
980 \brief the scroll bar's maximum value
981
982 When setting this property, the \l QScrollBar::minValue is
983 adjusted if necessary to ensure that the range remains valid.
984
985 \sa setRange()
986*/
987int QScrollBar::maxValue() const
988{
989 return QRangeControl::maxValue();
990}
991
992void QScrollBar::setMaxValue( int maxVal )
993{
994 QRangeControl::setMaxValue( maxVal );
995}
996
997/*!
998 \property QScrollBar::lineStep
999 \brief the line step
1000
1001 When setting lineStep, the virtual stepChange() function will be
1002 called if the new line step is different from the previous
1003 setting.
1004
1005 \sa setSteps() QRangeControl::pageStep() setRange()
1006*/
1007
1008int QScrollBar::lineStep() const
1009{
1010 return QRangeControl::lineStep();
1011}
1012
1013/*!
1014 \property QScrollBar::pageStep
1015 \brief the page step
1016
1017 When setting pageStep, the virtual stepChange() function will be
1018 called if the new page step is different from the previous
1019 setting.
1020
1021 \sa QRangeControl::setSteps() setLineStep() setRange()
1022*/
1023
1024int QScrollBar::pageStep() const
1025{
1026 return QRangeControl::pageStep();
1027}
1028
1029void QScrollBar::setLineStep( int i )
1030{
1031 setSteps( i, pageStep() );
1032}
1033
1034void QScrollBar::setPageStep( int i )
1035{
1036 setSteps( lineStep(), i );
1037}
1038
1039/*!
1040 \property QScrollBar::value
1041 \brief the scroll bar's value
1042
1043 \sa QRangeControl::value() prevValue()
1044*/
1045
1046int QScrollBar::value() const
1047{
1048 return QRangeControl::value();
1049}
1050
1051void QScrollBar::setValue( int i )
1052{
1053 QRangeControl::setValue( i );
1054}
1055
1056
1057/*!
1058 This function is called when the scrollbar is hidden.
1059*/
1060void QScrollBar::hideEvent( QHideEvent* )
1061{
1062 pressedControl = QStyle::SC_None;
1063 clickedAt = FALSE;
1064}
1065
1066
1067#undef ADD_LINE_ACTIVE
1068#undef SUB_LINE_ACTIVE
1069#endif
Note: See TracBrowser for help on using the repository browser.