update dev300-m58
[ooovba.git] / vcl / source / control / spinbtn.cxx
blob89833d88682fde96ae258dbcea6eebf71bb4e409
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: spinbtn.cxx,v $
10 * $Revision: 1.13 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
33 #include <tools/rcid.h>
34 #include <vcl/spin.h>
35 #include <vcl/event.hxx>
36 #include <vcl/spin.hxx>
38 // =======================================================================
40 void SpinButton::ImplInit( Window* pParent, WinBits nStyle )
42 mbUpperIn = FALSE;
43 mbLowerIn = FALSE;
44 mbInitialUp = FALSE;
45 mbInitialDown = FALSE;
47 mnMinRange = 0;
48 mnMaxRange = 100;
49 mnValue = 0;
50 mnValueStep = 1;
52 maRepeatTimer.SetTimeout( GetSettings().GetMouseSettings().GetButtonStartRepeat() );
53 maRepeatTimer.SetTimeoutHdl( LINK( this, SpinButton, ImplTimeout ) );
55 mbRepeat = 0 != ( nStyle & WB_REPEAT );
57 if ( nStyle & WB_HSCROLL )
58 mbHorz = TRUE;
59 else
60 mbHorz = FALSE;
62 Control::ImplInit( pParent, nStyle, NULL );
65 // -----------------------------------------------------------------------
67 SpinButton::SpinButton( Window* pParent, WinBits nStyle )
68 :Control( WINDOW_SPINBUTTON )
69 ,mbUpperIsFocused( FALSE )
71 ImplInit( pParent, nStyle );
74 // -----------------------------------------------------------------------
76 SpinButton::SpinButton( Window* pParent, const ResId& rResId )
77 :Control( WINDOW_SPINBUTTON )
78 ,mbUpperIsFocused( FALSE )
80 rResId.SetRT( RSC_SPINBUTTON );
81 ImplInit( pParent, ImplInitRes( rResId ) );
82 ImplLoadRes( rResId );
83 Resize();
86 // -----------------------------------------------------------------------
88 SpinButton::~SpinButton()
92 // -----------------------------------------------------------------------
94 IMPL_LINK( SpinButton, ImplTimeout, Timer*, pTimer )
96 if ( pTimer->GetTimeout() == GetSettings().GetMouseSettings().GetButtonStartRepeat() )
98 pTimer->SetTimeout( GetSettings().GetMouseSettings().GetButtonRepeat() );
99 pTimer->Start();
101 else
103 if ( mbInitialUp )
104 Up();
105 else
106 Down();
109 return 0;
112 // -----------------------------------------------------------------------
114 void SpinButton::Up()
116 if ( ImplIsUpperEnabled() )
118 mnValue += mnValueStep;
119 StateChanged( STATE_CHANGE_DATA );
121 ImplMoveFocus( TRUE );
124 ImplCallEventListenersAndHandler( VCLEVENT_SPINBUTTON_UP, maUpHdlLink, this );
127 // -----------------------------------------------------------------------
129 void SpinButton::Down()
131 if ( ImplIsLowerEnabled() )
133 mnValue -= mnValueStep;
134 StateChanged( STATE_CHANGE_DATA );
136 ImplMoveFocus( FALSE );
139 ImplCallEventListenersAndHandler( VCLEVENT_SPINBUTTON_DOWN, maDownHdlLink, this );
142 // -----------------------------------------------------------------------
144 void SpinButton::Resize()
146 Control::Resize();
148 Size aSize( GetOutputSizePixel() );
149 Point aTmpPoint;
150 Rectangle aRect( aTmpPoint, aSize );
151 if ( mbHorz )
153 maLowerRect = Rectangle( 0, 0, aSize.Width()/2, aSize.Height()-1 );
154 maUpperRect = Rectangle( maLowerRect.TopRight(), aRect.BottomRight() );
156 else
158 maUpperRect = Rectangle( 0, 0, aSize.Width()-1, aSize.Height()/2 );
159 maLowerRect = Rectangle( maUpperRect.BottomLeft(), aRect.BottomRight() );
162 ImplCalcFocusRect( ImplIsUpperEnabled() || !ImplIsLowerEnabled() );
164 Invalidate();
167 // -----------------------------------------------------------------------
169 void SpinButton::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, ULONG nFlags )
171 Point aPos = pDev->LogicToPixel( rPos );
172 Size aSize = pDev->LogicToPixel( rSize );
174 pDev->Push();
175 pDev->SetMapMode();
176 if ( !(nFlags & WINDOW_DRAW_MONO) )
178 // DecoView uses the FaceColor...
179 AllSettings aSettings = pDev->GetSettings();
180 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
181 if ( IsControlBackground() )
182 aStyleSettings.SetFaceColor( GetControlBackground() );
183 else
184 aStyleSettings.SetFaceColor( GetSettings().GetStyleSettings().GetFaceColor() );
186 aSettings.SetStyleSettings( aStyleSettings );
187 pDev->SetSettings( aSettings );
190 Rectangle aRect( Point( 0, 0 ), aSize );
191 Rectangle aLowerRect, aUpperRect;
192 if ( mbHorz )
194 aLowerRect = Rectangle( 0, 0, aSize.Width()/2, aSize.Height()-1 );
195 aUpperRect = Rectangle( aLowerRect.TopRight(), aRect.BottomRight() );
197 else
199 aUpperRect = Rectangle( 0, 0, aSize.Width()-1, aSize.Height()/2 );
200 aLowerRect = Rectangle( aUpperRect.BottomLeft(), aRect.BottomRight() );
203 aUpperRect += aPos;
204 aLowerRect += aPos;
206 ImplDrawSpinButton( pDev, aUpperRect, aLowerRect, FALSE, FALSE,
207 IsEnabled() && ImplIsUpperEnabled(),
208 IsEnabled() && ImplIsLowerEnabled(), mbHorz, TRUE );
209 pDev->Pop();
213 void SpinButton::Paint( const Rectangle& )
215 HideFocus();
217 BOOL bEnable = IsEnabled();
218 ImplDrawSpinButton( this, maUpperRect, maLowerRect, mbUpperIn, mbLowerIn,
219 bEnable && ImplIsUpperEnabled(),
220 bEnable && ImplIsLowerEnabled(), mbHorz, TRUE );
222 if ( HasFocus() )
223 ShowFocus( maFocusRect );
226 // -----------------------------------------------------------------------
228 void SpinButton::MouseButtonDown( const MouseEvent& rMEvt )
230 if ( maUpperRect.IsInside( rMEvt.GetPosPixel() ) && ( ImplIsUpperEnabled() ) )
232 mbUpperIn = TRUE;
233 mbInitialUp = TRUE;
234 Invalidate( maUpperRect );
236 else if ( maLowerRect.IsInside( rMEvt.GetPosPixel() ) && ( ImplIsLowerEnabled() ) )
238 mbLowerIn = TRUE;
239 mbInitialDown = TRUE;
240 Invalidate( maLowerRect );
243 if ( mbUpperIn || mbLowerIn )
245 Update();
246 CaptureMouse();
247 if ( mbRepeat )
248 maRepeatTimer.Start();
252 // -----------------------------------------------------------------------
254 void SpinButton::MouseButtonUp( const MouseEvent& )
256 ReleaseMouse();
257 if ( mbRepeat )
259 maRepeatTimer.Stop();
260 maRepeatTimer.SetTimeout(GetSettings().GetMouseSettings().GetButtonStartRepeat() );
263 if ( mbUpperIn )
265 mbUpperIn = FALSE;
266 Invalidate( maUpperRect );
267 Update();
268 Up();
270 else if ( mbLowerIn )
272 mbLowerIn = FALSE;
273 Invalidate( maLowerRect );
274 Update();
275 Down();
278 mbInitialUp = mbInitialDown = FALSE;
281 // -----------------------------------------------------------------------
283 void SpinButton::MouseMove( const MouseEvent& rMEvt )
285 if ( !rMEvt.IsLeft() || (!mbInitialUp && !mbInitialDown) )
286 return;
288 if ( !maUpperRect.IsInside( rMEvt.GetPosPixel() ) &&
289 mbUpperIn && mbInitialUp )
291 mbUpperIn = FALSE;
292 maRepeatTimer.Stop();
293 Invalidate( maUpperRect );
294 Update();
296 else if ( !maLowerRect.IsInside( rMEvt.GetPosPixel() ) &&
297 mbLowerIn & mbInitialDown )
299 mbLowerIn = FALSE;
300 maRepeatTimer.Stop();
301 Invalidate( maLowerRect );
302 Update();
304 else if ( maUpperRect.IsInside( rMEvt.GetPosPixel() ) &&
305 !mbUpperIn && mbInitialUp )
307 mbUpperIn = TRUE;
308 if ( mbRepeat )
309 maRepeatTimer.Start();
310 Invalidate( maUpperRect );
311 Update();
313 else if ( maLowerRect.IsInside( rMEvt.GetPosPixel() ) &&
314 !mbLowerIn && mbInitialDown )
316 mbLowerIn = TRUE;
317 if ( mbRepeat )
318 maRepeatTimer.Start();
319 Invalidate( maLowerRect );
320 Update();
324 // -----------------------------------------------------------------------
326 void SpinButton::KeyInput( const KeyEvent& rKEvt )
328 KeyCode aCode = rKEvt.GetKeyCode();
330 if ( !rKEvt.GetKeyCode().GetModifier() )
332 switch ( rKEvt.GetKeyCode().GetCode() )
334 case KEY_LEFT:
335 case KEY_RIGHT:
337 BOOL bUp = KEY_RIGHT == rKEvt.GetKeyCode().GetCode();
338 if ( mbHorz && !ImplMoveFocus( bUp ) )
339 bUp ? Up() : Down();
341 break;
343 case KEY_UP:
344 case KEY_DOWN:
346 BOOL bUp = KEY_UP == rKEvt.GetKeyCode().GetCode();
347 if ( !mbHorz && !ImplMoveFocus( KEY_UP == rKEvt.GetKeyCode().GetCode() ) )
348 bUp ? Up() : Down();
350 break;
352 case KEY_SPACE:
353 mbUpperIsFocused ? Up() : Down();
354 break;
356 default:
357 Control::KeyInput( rKEvt );
358 break;
361 else
362 Control::KeyInput( rKEvt );
365 // -----------------------------------------------------------------------
367 void SpinButton::StateChanged( StateChangedType nType )
369 switch ( nType )
371 case STATE_CHANGE_DATA:
372 case STATE_CHANGE_ENABLE:
373 Invalidate();
374 break;
376 case STATE_CHANGE_STYLE:
378 BOOL bNewRepeat = 0 != ( GetStyle() & WB_REPEAT );
379 if ( bNewRepeat != mbRepeat )
381 if ( maRepeatTimer.IsActive() )
383 maRepeatTimer.Stop();
384 maRepeatTimer.SetTimeout( GetSettings().GetMouseSettings().GetButtonStartRepeat() );
386 mbRepeat = bNewRepeat;
389 BOOL bNewHorz = 0 != ( GetStyle() & WB_HSCROLL );
390 if ( bNewHorz != mbHorz )
392 mbHorz = bNewHorz;
393 Resize();
396 break;
399 Control::StateChanged( nType );
402 // -----------------------------------------------------------------------
404 void SpinButton::SetRangeMin( long nNewRange )
406 SetRange( Range( nNewRange, GetRangeMax() ) );
409 // -----------------------------------------------------------------------
411 void SpinButton::SetRangeMax( long nNewRange )
413 SetRange( Range( GetRangeMin(), nNewRange ) );
416 // -----------------------------------------------------------------------
418 void SpinButton::SetRange( const Range& rRange )
420 // adjust rage
421 Range aRange = rRange;
422 aRange.Justify();
423 long nNewMinRange = aRange.Min();
424 long nNewMaxRange = aRange.Max();
426 // do something only if old and new range differ
427 if ( (mnMinRange != nNewMinRange) ||
428 (mnMaxRange != nNewMaxRange) )
430 mnMinRange = nNewMinRange;
431 mnMaxRange = nNewMaxRange;
433 // adjust value to new range, if necessary
434 if ( mnValue > mnMaxRange )
435 mnValue = mnMaxRange;
436 if ( mnValue < mnMinRange )
437 mnValue = mnMinRange;
439 StateChanged( STATE_CHANGE_DATA );
443 // -----------------------------------------------------------------------
445 void SpinButton::SetValue( long nValue )
447 // adjust, if necessary
448 if ( nValue > mnMaxRange )
449 nValue = mnMaxRange;
450 if ( nValue < mnMinRange )
451 nValue = mnMinRange;
453 if ( mnValue != nValue )
455 mnValue = nValue;
456 StateChanged( STATE_CHANGE_DATA );
460 // -----------------------------------------------------------------------
462 void SpinButton::GetFocus()
464 ShowFocus( maFocusRect );
465 Control::GetFocus();
468 // -----------------------------------------------------------------------
470 void SpinButton::LoseFocus()
472 HideFocus();
473 Control::LoseFocus();
476 // -----------------------------------------------------------------------
478 BOOL SpinButton::ImplMoveFocus( BOOL _bUpper )
480 if ( _bUpper == mbUpperIsFocused )
481 return FALSE;
483 HideFocus();
484 ImplCalcFocusRect( _bUpper );
485 if ( HasFocus() )
486 ShowFocus( maFocusRect );
487 return TRUE;
490 // -----------------------------------------------------------------------
492 void SpinButton::ImplCalcFocusRect( BOOL _bUpper )
494 maFocusRect = _bUpper ? maUpperRect : maLowerRect;
495 // inflate by some pixels
496 maFocusRect.Left() += 2;
497 maFocusRect.Top() += 2;
498 maFocusRect.Right() -= 2;
499 maFocusRect.Bottom() -= 2;
500 mbUpperIsFocused = _bUpper;
503 // -----------------------------------------------------------------------
505 Rectangle* SpinButton::ImplFindPartRect( const Point& rPt )
507 if( maUpperRect.IsInside( rPt ) )
508 return &maUpperRect;
509 else if( maLowerRect.IsInside( rPt ) )
510 return &maLowerRect;
511 else
512 return NULL;
515 long SpinButton::PreNotify( NotifyEvent& rNEvt )
517 long nDone = 0;
518 const MouseEvent* pMouseEvt = NULL;
520 if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL )
522 if( !pMouseEvt->GetButtons() && !pMouseEvt->IsSynthetic() && !pMouseEvt->IsModifierChanged() )
524 // trigger redraw if mouse over state has changed
525 if( IsNativeControlSupported(CTRL_SPINBOX, PART_ENTIRE_CONTROL) ||
526 IsNativeControlSupported(CTRL_SPINBOX, PART_ALL_BUTTONS) )
528 Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() );
529 Rectangle* pLastRect = ImplFindPartRect( GetLastPointerPosPixel() );
530 if( pRect != pLastRect || (pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow()) )
532 Region aRgn( GetActiveClipRegion() );
533 if( pLastRect )
535 SetClipRegion( *pLastRect );
536 Paint( *pLastRect );
537 SetClipRegion( aRgn );
539 if( pRect )
541 SetClipRegion( *pRect );
542 Paint( *pRect );
543 SetClipRegion( aRgn );
550 return nDone ? nDone : Control::PreNotify(rNEvt);
553 // -----------------------------------------------------------------------