source: trunk/src/widgets/qspinwidget.cpp@ 174

Last change on this file since 174 was 174, checked in by dmik, 18 years ago

Styles: Implemented the first version of the Warp4 style (contributed by Cornelis Bockemuehl).

  • Property svn:keywords set to Id
File size: 11.9 KB
Line 
1/****************************************************************************
2**
3** Implementation of QSpinWidget class
4**
5** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
6**
7** This file is part of the widgets module of the Qt GUI Toolkit.
8**
9** This file may be distributed under the terms of the Q Public License
10** as defined by Trolltech AS of Norway and appearing in the file
11** LICENSE.QPL included in the packaging of this file.
12**
13** This file may be distributed and/or modified under the terms of the
14** GNU General Public License version 2 as published by the Free Software
15** Foundation and appearing in the file LICENSE.GPL included in the
16** packaging of this file.
17**
18** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
19** licenses may use this file in accordance with the Qt Commercial License
20** Agreement provided with the Software.
21**
22** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
23** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
24**
25** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
26** information about Qt Commercial License Agreements.
27** See http://www.trolltech.com/qpl/ for QPL licensing information.
28** See http://www.trolltech.com/gpl/ for GPL licensing information.
29**
30** Contact info@trolltech.com if any conditions of this licensing are
31** not clear to you.
32**
33**********************************************************************/
34
35#include "qrangecontrol.h"
36
37#ifndef QT_NO_SPINWIDGET
38
39#include "qrect.h"
40#include "qtimer.h"
41#include "qstyle.h"
42#include "qpainter.h"
43
44class QSpinWidgetPrivate
45{
46public:
47 QSpinWidgetPrivate()
48 : upEnabled( TRUE ),
49 downEnabled( TRUE ),
50 theButton( 0 ),
51 buttonDown( 0 ),
52 timerUp( 0 ),
53 bsyms( QSpinWidget::UpDownArrows ),
54 ed ( 0 ) {}
55 uint upEnabled :1;
56 uint downEnabled :1;
57 uint theButton :2;
58 uint buttonDown :2;
59 uint timerUp : 1;
60 QRect up;
61 QRect down;
62 QTimer auRepTimer;
63 QSpinWidget::ButtonSymbols bsyms;
64 QWidget *ed;
65 void startTimer( int msec ) { auRepTimer.start( msec, TRUE ); }
66 void startTimer( bool up, int msec ) { timerUp = up; startTimer( msec ); }
67 void stopTimer() { auRepTimer.stop(); }
68};
69
70/*!
71
72 \class QSpinWidget qspinwidget.h
73 \brief The QSpinWidget class is an internal range control related class.
74
75 \internal
76
77 Constructs an empty range control widget with parent \a parent
78 called \a name.
79
80*/
81
82QSpinWidget::QSpinWidget( QWidget* parent, const char* name )
83 : QWidget( parent, name )
84{
85 d = new QSpinWidgetPrivate();
86 connect( &d->auRepTimer, SIGNAL( timeout() ), this, SLOT( timerDone() ) );
87 setFocusPolicy( StrongFocus );
88
89 arrange();
90 updateDisplay();
91}
92
93
94/*! Destroys the object and frees any allocated resources.
95
96*/
97
98QSpinWidget::~QSpinWidget()
99{
100 delete d;
101}
102
103/*! */
104QWidget * QSpinWidget::editWidget()
105{
106 return d->ed;
107}
108
109/*!
110 Sets the editing widget to \a w.
111*/
112void QSpinWidget::setEditWidget( QWidget * w )
113{
114 if ( w ) {
115 w->reparent( this, QPoint( 0, 0 ) );
116 setFocusProxy( w );
117 }
118 d->ed = w;
119 arrange();
120 updateDisplay();
121}
122
123/*! \reimp
124
125*/
126
127void QSpinWidget::mousePressEvent( QMouseEvent *e )
128{
129 if ( e->button() != LeftButton ) {
130 d->stopTimer();
131 d->buttonDown = 0;
132 d->theButton = 0;
133 repaint( d->down.unite( d->up ), FALSE );
134 return;
135 }
136
137 uint oldButtonDown = d->buttonDown;
138 d->buttonDown = 0;
139
140 // With Warp, the up and down buttons are diagonally separated,
141 // so we are disabling the down button entirely and have to find
142 // out the position of the click within the up button in order
143 // to find out what the user wants!
144 int guiStyle = style().styleHint( QStyle::SH_GUIStyle );
145 if ( guiStyle == QStyle::PMStyle ) {
146 if ( d->up.contains( e->pos() ) ) {
147 QPoint rp = e->pos() - d->up.topLeft();
148 if ( d->up.width() > (rp.x() + rp.y()) ) {
149 if ( d->upEnabled )
150 d->buttonDown = 2;
151 } else {
152 if ( d->downEnabled )
153 d->buttonDown = 1;
154 }
155 }
156 } else {
157 if ( d->down.contains( e->pos() ) && d->downEnabled )
158 d->buttonDown = 1;
159 else if ( d->up.contains( e->pos() ) && d->upEnabled )
160 d->buttonDown = 2;
161 }
162
163 d->theButton = d->buttonDown;
164 if ( oldButtonDown != d->buttonDown ) {
165 if ( !d->buttonDown ) {
166 repaint( d->down.unite( d->up ), FALSE );
167 } else if ( d->buttonDown & 1 ) {
168 // do all with the "up" button in PM style - see note above
169 if ( guiStyle == QStyle::PMStyle )
170 repaint( d->up, FALSE );
171 else
172 repaint( d->down, FALSE );
173 stepDown();
174 if ( guiStyle == QStyle::PMStyle )
175 d->startTimer( TRUE, 300 );
176 else
177 d->startTimer( FALSE, 300 );
178 } else if ( d->buttonDown & 2 ) {
179 repaint( d->up, FALSE );
180 stepUp();
181 d->startTimer( TRUE, 300 );
182 }
183 }
184}
185
186/*!
187
188*/
189
190void QSpinWidget::arrange()
191{
192 d->up = QStyle::visualRect( style().querySubControlMetrics( QStyle::CC_SpinWidget, this,
193 QStyle::SC_SpinWidgetUp ), this );
194 d->down = QStyle::visualRect( style().querySubControlMetrics( QStyle::CC_SpinWidget, this,
195 QStyle::SC_SpinWidgetDown ), this );
196 if ( d->ed ) {
197 QRect r = QStyle::visualRect( style().querySubControlMetrics( QStyle::CC_SpinWidget, this,
198 QStyle::SC_SpinWidgetEditField ), this );
199 d->ed->setGeometry( r );
200 }
201}
202
203/*!
204
205*/
206
207void QSpinWidget::stepUp()
208{
209 emit stepUpPressed();
210}
211
212void QSpinWidget::resizeEvent( QResizeEvent* )
213{
214 arrange();
215}
216
217/*!
218
219*/
220
221void QSpinWidget::stepDown()
222{
223 emit stepDownPressed();
224}
225
226
227void QSpinWidget::timerDone()
228{
229 // we use a double timer to make it possible for users to do
230 // something with 0-timer on valueChanged.
231 QTimer::singleShot( 1, this, SLOT( timerDoneEx() ) );
232}
233
234void QSpinWidget::timerDoneEx()
235{
236 if ( !d->buttonDown )
237 return;
238 if ( d->timerUp )
239 stepUp();
240 else
241 stepDown();
242 d->startTimer( 100 );
243}
244
245
246void QSpinWidget::windowActivationChange( bool oldActive )
247{
248 //was active, but lost focus
249 if ( oldActive && d->buttonDown ) {
250 d->stopTimer();
251 d->buttonDown = 0;
252 d->theButton = 0;
253 }
254 QWidget::windowActivationChange( oldActive );
255}
256
257
258
259/*!
260 The event is passed in \a e.
261*/
262
263void QSpinWidget::mouseReleaseEvent( QMouseEvent *e )
264{
265 if ( e->button() != LeftButton )
266 return;
267
268 uint oldButtonDown = d->theButton;
269 d->theButton = 0;
270 if ( oldButtonDown != d->theButton ) {
271 // do all with the "up" button in PM style -
272 // see note in mousePressEvent
273 int guiStyle = style().styleHint( QStyle::SH_GUIStyle );
274 if ( guiStyle == QStyle::PMStyle )
275 repaint( d->up, FALSE );
276 else if ( oldButtonDown & 1 )
277 repaint( d->down, FALSE );
278 else if ( oldButtonDown & 2 )
279 repaint( d->up, FALSE );
280 }
281 d->stopTimer();
282 d->buttonDown = 0;
283}
284
285
286/*!
287 The event is passed in \a e.
288*/
289
290void QSpinWidget::mouseMoveEvent( QMouseEvent *e )
291{
292 if ( !(e->state() & LeftButton ) )
293 return;
294
295 // do all with the "up" button in PM style -
296 // see note in mousePressEvent
297 int guiStyle = style().styleHint( QStyle::SH_GUIStyle );
298 uint clickButton = 0;
299 if ( guiStyle == QStyle::PMStyle ) {
300 if( d->up.contains( e->pos() ) ) {
301 QPoint rp = e->pos() - d->up.topLeft();
302 if ( d->up.width() > (rp.x() + rp.y()) )
303 clickButton = 2;
304 else
305 clickButton = 1;
306 }
307 } else {
308 if ( d->down.contains(e->pos()) )
309 clickButton = 1;
310 else if ( d->up.contains(e->pos()) )
311 clickButton = 2;
312 }
313
314 uint oldButtonDown = d->theButton;
315 if ( (oldButtonDown & 1) && !(clickButton & 1) ) {
316 //if ( oldButtonDown & 1 && !d->down.contains( e->pos() ) ) {
317 d->stopTimer();
318 d->theButton = 0;
319 if ( guiStyle == QStyle::PMStyle )
320 repaint( d->up, FALSE );
321 else
322 repaint( d->down, FALSE );
323 } else if( (oldButtonDown & 2) && !(clickButton & 2) ) {
324 //} else if ( oldButtonDown & 2 && !d->up.contains( e->pos() ) ) {
325 d->stopTimer();
326 d->theButton = 0;
327 repaint( d->up, FALSE );
328 } else if ( !oldButtonDown && (clickButton & 2) && (d->buttonDown & 2) ) {
329 //} else if ( !oldButtonDown && d->up.contains( e->pos() ) && d->buttonDown & 2 ) {
330 d->startTimer( 500 );
331 d->theButton = 2;
332 repaint( d->up, FALSE );
333 } else if(!oldButtonDown && (clickButton & 1) && (d->buttonDown & 1)) {
334 //} else if ( !oldButtonDown && d->down.contains( e->pos() ) && d->buttonDown & 1 ) {
335 d->startTimer( 500 );
336 d->theButton = 1;
337 if ( guiStyle == QStyle::PMStyle )
338 repaint( d->up, FALSE );
339 else
340 repaint( d->down, FALSE );
341 }
342}
343
344
345/*!
346 The event is passed in \a e.
347*/
348#ifndef QT_NO_WHEELEVENT
349void QSpinWidget::wheelEvent( QWheelEvent *e )
350{
351 e->accept();
352 static float offset = 0;
353 static QSpinWidget* offset_owner = 0;
354 if ( offset_owner != this ) {
355 offset_owner = this;
356 offset = 0;
357 }
358 offset += -e->delta()/120;
359 if ( QABS( offset ) < 1 )
360 return;
361 int ioff = int(offset);
362 int i;
363 for( i=0; i < QABS( ioff ); i++ )
364 offset > 0 ? stepDown() : stepUp();
365 offset -= ioff;
366}
367#endif
368
369/*!
370
371*/
372void QSpinWidget::paintEvent( QPaintEvent * )
373{
374 QPainter p( this );
375
376 QStyle::SFlags flags = QStyle::Style_Default;
377 if (isEnabled())
378 flags |= QStyle::Style_Enabled;
379 if (hasFocus() || focusProxy() && focusProxy()->hasFocus())
380 flags |= QStyle::Style_HasFocus;
381
382 QStyle::SCFlags active;
383 if ( d->theButton & 1 )
384 active = QStyle::SC_SpinWidgetDown;
385 else if ( d->theButton & 2 )
386 active = QStyle::SC_SpinWidgetUp;
387 else
388 active = QStyle::SC_None;
389
390 QRect fr = QStyle::visualRect(
391 style().querySubControlMetrics( QStyle::CC_SpinWidget, this,
392 QStyle::SC_SpinWidgetFrame ), this );
393 style().drawComplexControl( QStyle::CC_SpinWidget, &p, this,
394 fr, colorGroup(),
395 flags,
396 (uint)QStyle::SC_All,
397 active );
398}
399
400
401/*!
402 The previous style is passed in \a old.
403*/
404
405void QSpinWidget::styleChange( QStyle& old )
406{
407 arrange();
408 QWidget::styleChange( old );
409}
410
411/*!
412*/
413
414QRect QSpinWidget::upRect() const
415{
416 return d->up;
417}
418
419/*!
420*/
421
422QRect QSpinWidget::downRect() const
423{
424 return d->down;
425}
426
427/*!
428*/
429
430void QSpinWidget::updateDisplay()
431{
432 if ( !isEnabled() ) {
433 d->upEnabled = FALSE;
434 d->downEnabled = FALSE;
435 }
436 if ( d->theButton & 1 && ( d->downEnabled ) == 0 ) {
437 d->theButton &= ~1;
438 d->buttonDown &= ~1;
439 }
440
441 if ( d->theButton & 2 && ( d->upEnabled ) == 0 ) {
442 d->theButton &= ~2;
443 d->buttonDown &= ~2;
444 }
445 repaint( FALSE );
446}
447
448
449/*!
450 The previous enabled state is passed in \a old.
451*/
452
453void QSpinWidget::enableChanged( bool )
454{
455 d->upEnabled = isEnabled();
456 d->downEnabled = isEnabled();
457 updateDisplay();
458}
459
460
461/*!
462 Sets up-enabled to \a on.
463*/
464
465void QSpinWidget::setUpEnabled( bool on )
466{
467 if ( (bool)d->upEnabled != on ) {
468 d->upEnabled = on;
469 updateDisplay();
470 }
471}
472
473/*!
474*/
475
476bool QSpinWidget::isUpEnabled() const
477{
478 return d->upEnabled;
479}
480
481/*!
482 Sets down-enabled to \a on.
483*/
484
485void QSpinWidget::setDownEnabled( bool on )
486{
487 if ( (bool)d->downEnabled != on ) {
488 d->downEnabled = on;
489 updateDisplay();
490 }
491}
492
493/*!
494*/
495
496bool QSpinWidget::isDownEnabled() const
497{
498 return d->downEnabled;
499}
500
501/*!
502 Sets the button symbol to \a bs.
503*/
504
505void QSpinWidget::setButtonSymbols( ButtonSymbols bs )
506{
507 d->bsyms = bs;
508}
509
510/*!
511*/
512
513QSpinWidget::ButtonSymbols QSpinWidget::buttonSymbols() const
514{
515 return d->bsyms;
516}
517
518#endif
Note: See TracBrowser for help on using the repository browser.