1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: spinbtn.cxx,v $
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>
35 #include <vcl/event.hxx>
36 #include <vcl/spin.hxx>
38 // =======================================================================
40 void SpinButton::ImplInit( Window
* pParent
, WinBits nStyle
)
45 mbInitialDown
= FALSE
;
52 maRepeatTimer
.SetTimeout( GetSettings().GetMouseSettings().GetButtonStartRepeat() );
53 maRepeatTimer
.SetTimeoutHdl( LINK( this, SpinButton
, ImplTimeout
) );
55 mbRepeat
= 0 != ( nStyle
& WB_REPEAT
);
57 if ( nStyle
& WB_HSCROLL
)
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
);
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() );
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()
148 Size
aSize( GetOutputSizePixel() );
150 Rectangle
aRect( aTmpPoint
, aSize
);
153 maLowerRect
= Rectangle( 0, 0, aSize
.Width()/2, aSize
.Height()-1 );
154 maUpperRect
= Rectangle( maLowerRect
.TopRight(), aRect
.BottomRight() );
158 maUpperRect
= Rectangle( 0, 0, aSize
.Width()-1, aSize
.Height()/2 );
159 maLowerRect
= Rectangle( maUpperRect
.BottomLeft(), aRect
.BottomRight() );
162 ImplCalcFocusRect( ImplIsUpperEnabled() || !ImplIsLowerEnabled() );
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
);
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() );
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
;
194 aLowerRect
= Rectangle( 0, 0, aSize
.Width()/2, aSize
.Height()-1 );
195 aUpperRect
= Rectangle( aLowerRect
.TopRight(), aRect
.BottomRight() );
199 aUpperRect
= Rectangle( 0, 0, aSize
.Width()-1, aSize
.Height()/2 );
200 aLowerRect
= Rectangle( aUpperRect
.BottomLeft(), aRect
.BottomRight() );
206 ImplDrawSpinButton( pDev
, aUpperRect
, aLowerRect
, FALSE
, FALSE
,
207 IsEnabled() && ImplIsUpperEnabled(),
208 IsEnabled() && ImplIsLowerEnabled(), mbHorz
, TRUE
);
213 void SpinButton::Paint( const Rectangle
& )
217 BOOL bEnable
= IsEnabled();
218 ImplDrawSpinButton( this, maUpperRect
, maLowerRect
, mbUpperIn
, mbLowerIn
,
219 bEnable
&& ImplIsUpperEnabled(),
220 bEnable
&& ImplIsLowerEnabled(), mbHorz
, TRUE
);
223 ShowFocus( maFocusRect
);
226 // -----------------------------------------------------------------------
228 void SpinButton::MouseButtonDown( const MouseEvent
& rMEvt
)
230 if ( maUpperRect
.IsInside( rMEvt
.GetPosPixel() ) && ( ImplIsUpperEnabled() ) )
234 Invalidate( maUpperRect
);
236 else if ( maLowerRect
.IsInside( rMEvt
.GetPosPixel() ) && ( ImplIsLowerEnabled() ) )
239 mbInitialDown
= TRUE
;
240 Invalidate( maLowerRect
);
243 if ( mbUpperIn
|| mbLowerIn
)
248 maRepeatTimer
.Start();
252 // -----------------------------------------------------------------------
254 void SpinButton::MouseButtonUp( const MouseEvent
& )
259 maRepeatTimer
.Stop();
260 maRepeatTimer
.SetTimeout(GetSettings().GetMouseSettings().GetButtonStartRepeat() );
266 Invalidate( maUpperRect
);
270 else if ( mbLowerIn
)
273 Invalidate( maLowerRect
);
278 mbInitialUp
= mbInitialDown
= FALSE
;
281 // -----------------------------------------------------------------------
283 void SpinButton::MouseMove( const MouseEvent
& rMEvt
)
285 if ( !rMEvt
.IsLeft() || (!mbInitialUp
&& !mbInitialDown
) )
288 if ( !maUpperRect
.IsInside( rMEvt
.GetPosPixel() ) &&
289 mbUpperIn
&& mbInitialUp
)
292 maRepeatTimer
.Stop();
293 Invalidate( maUpperRect
);
296 else if ( !maLowerRect
.IsInside( rMEvt
.GetPosPixel() ) &&
297 mbLowerIn
& mbInitialDown
)
300 maRepeatTimer
.Stop();
301 Invalidate( maLowerRect
);
304 else if ( maUpperRect
.IsInside( rMEvt
.GetPosPixel() ) &&
305 !mbUpperIn
&& mbInitialUp
)
309 maRepeatTimer
.Start();
310 Invalidate( maUpperRect
);
313 else if ( maLowerRect
.IsInside( rMEvt
.GetPosPixel() ) &&
314 !mbLowerIn
&& mbInitialDown
)
318 maRepeatTimer
.Start();
319 Invalidate( maLowerRect
);
324 // -----------------------------------------------------------------------
326 void SpinButton::KeyInput( const KeyEvent
& rKEvt
)
328 KeyCode aCode
= rKEvt
.GetKeyCode();
330 if ( !rKEvt
.GetKeyCode().GetModifier() )
332 switch ( rKEvt
.GetKeyCode().GetCode() )
337 BOOL bUp
= KEY_RIGHT
== rKEvt
.GetKeyCode().GetCode();
338 if ( mbHorz
&& !ImplMoveFocus( bUp
) )
346 BOOL bUp
= KEY_UP
== rKEvt
.GetKeyCode().GetCode();
347 if ( !mbHorz
&& !ImplMoveFocus( KEY_UP
== rKEvt
.GetKeyCode().GetCode() ) )
353 mbUpperIsFocused
? Up() : Down();
357 Control::KeyInput( rKEvt
);
362 Control::KeyInput( rKEvt
);
365 // -----------------------------------------------------------------------
367 void SpinButton::StateChanged( StateChangedType nType
)
371 case STATE_CHANGE_DATA
:
372 case STATE_CHANGE_ENABLE
:
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
)
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
)
421 Range aRange
= rRange
;
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
)
450 if ( nValue
< mnMinRange
)
453 if ( mnValue
!= nValue
)
456 StateChanged( STATE_CHANGE_DATA
);
460 // -----------------------------------------------------------------------
462 void SpinButton::GetFocus()
464 ShowFocus( maFocusRect
);
468 // -----------------------------------------------------------------------
470 void SpinButton::LoseFocus()
473 Control::LoseFocus();
476 // -----------------------------------------------------------------------
478 BOOL
SpinButton::ImplMoveFocus( BOOL _bUpper
)
480 if ( _bUpper
== mbUpperIsFocused
)
484 ImplCalcFocusRect( _bUpper
);
486 ShowFocus( maFocusRect
);
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
) )
509 else if( maLowerRect
.IsInside( rPt
) )
515 long SpinButton::PreNotify( NotifyEvent
& rNEvt
)
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() );
535 SetClipRegion( *pLastRect
);
537 SetClipRegion( aRgn
);
541 SetClipRegion( *pRect
);
543 SetClipRegion( aRgn
);
550 return nDone
? nDone
: Control::PreNotify(rNEvt
);
553 // -----------------------------------------------------------------------