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: spinfld.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"
35 #include "vcl/event.hxx"
36 #include "vcl/decoview.hxx"
38 #include "vcl/spinfld.hxx"
39 #include "vcl/controllayout.hxx"
40 #include "vcl/svdata.hxx"
42 // =======================================================================
44 void ImplGetSpinbuttonValue( Window
*pWin
, const Rectangle
& rUpperRect
,
45 const Rectangle
& rLowerRect
,
46 BOOL bUpperIn
, BOOL bLowerIn
,
47 BOOL bUpperEnabled
, BOOL bLowerEnabled
, BOOL bHorz
,
48 SpinbuttonValue
& rValue
)
50 // convert spinbutton data to a SpinbuttonValue structure for native painting
52 rValue
.maUpperRect
= rUpperRect
;
53 rValue
.maLowerRect
= rLowerRect
;
55 Point aPointerPos
= pWin
->GetPointerPosPixel();
57 ControlState nState
= CTRL_STATE_ENABLED
;
59 nState
|= CTRL_STATE_PRESSED
;
60 if ( !pWin
->IsEnabled() || !bUpperEnabled
)
61 nState
&= ~CTRL_STATE_ENABLED
;
62 if ( pWin
->HasFocus() )
63 nState
|= CTRL_STATE_FOCUSED
;
64 if( pWin
->IsMouseOver() && rUpperRect
.IsInside( aPointerPos
) )
65 nState
|= CTRL_STATE_ROLLOVER
;
66 rValue
.mnUpperState
= nState
;
68 nState
= CTRL_STATE_ENABLED
;
70 nState
|= CTRL_STATE_PRESSED
;
71 if ( !pWin
->IsEnabled() || !bLowerEnabled
)
72 nState
&= ~CTRL_STATE_ENABLED
;
73 if ( pWin
->HasFocus() )
74 nState
|= CTRL_STATE_FOCUSED
;
75 // for overlapping spins: highlight only one
76 if( pWin
->IsMouseOver() && rLowerRect
.IsInside( aPointerPos
) &&
77 !rUpperRect
.IsInside( aPointerPos
) )
78 nState
|= CTRL_STATE_ROLLOVER
;
79 rValue
.mnLowerState
= nState
;
81 rValue
.mnUpperPart
= bHorz
? PART_BUTTON_LEFT
: PART_BUTTON_UP
;
82 rValue
.mnLowerPart
= bHorz
? PART_BUTTON_RIGHT
: PART_BUTTON_DOWN
;
86 BOOL
ImplDrawNativeSpinfield( Window
*pWin
, const SpinbuttonValue
& rSpinbuttonValue
)
88 BOOL bNativeOK
= FALSE
;
90 if( pWin
->IsNativeControlSupported(CTRL_SPINBOX
, PART_ENTIRE_CONTROL
) &&
91 // there is just no useful native support for spinfields with dropdown
92 !(pWin
->GetStyle() & WB_DROPDOWN
) )
94 ImplControlValue aControlValue
;
95 aControlValue
.setOptionalVal( (void*) &rSpinbuttonValue
);
97 if( pWin
->IsNativeControlSupported(CTRL_SPINBOX
, rSpinbuttonValue
.mnUpperPart
) &&
98 pWin
->IsNativeControlSupported(CTRL_SPINBOX
, rSpinbuttonValue
.mnLowerPart
) )
100 // only paint the embedded spin buttons, all buttons are painted at once
101 bNativeOK
= pWin
->DrawNativeControl( CTRL_SPINBOX
, PART_ALL_BUTTONS
, Region(), CTRL_STATE_ENABLED
,
102 aControlValue
, rtl::OUString() );
106 // paint the spinbox as a whole, use borderwindow to have proper clipping
107 Window
*pBorder
= pWin
->GetWindow( WINDOW_BORDER
);
109 // to not overwrite everything, set the button region as clipregion to the border window
110 Rectangle
aClipRect( rSpinbuttonValue
.maLowerRect
);
111 aClipRect
.Union( rSpinbuttonValue
.maUpperRect
);
113 // convert from screen space to borderwin space
114 aClipRect
.SetPos( pBorder
->ScreenToOutputPixel(pWin
->OutputToScreenPixel(aClipRect
.TopLeft())) );
116 Region
oldRgn( pBorder
->GetClipRegion() );
117 pBorder
->SetClipRegion( Region( aClipRect
) );
120 Size
aSize( pBorder
->GetOutputSizePixel() ); // the size of the border window, i.e., the whole control
121 Region aBound
, aContent
;
122 Region
aNatRgn( Rectangle( aPt
, aSize
) );
123 if( pBorder
->GetNativeControlRegion(CTRL_SPINBOX
, PART_ENTIRE_CONTROL
,
124 aNatRgn
, 0, aControlValue
, rtl::OUString(), aBound
, aContent
) )
126 aSize
= aContent
.GetBoundRect().GetSize();
129 Region
aRgn( Rectangle( aPt
, aSize
) );
130 bNativeOK
= pBorder
->DrawNativeControl( CTRL_SPINBOX
, PART_ENTIRE_CONTROL
, aRgn
, CTRL_STATE_ENABLED
,
131 aControlValue
, rtl::OUString() );
133 pBorder
->SetClipRegion( oldRgn
);
139 BOOL
ImplDrawNativeSpinbuttons( Window
*pWin
, const SpinbuttonValue
& rSpinbuttonValue
)
141 BOOL bNativeOK
= FALSE
;
143 if( pWin
->IsNativeControlSupported(CTRL_SPINBUTTONS
, PART_ENTIRE_CONTROL
) )
145 ImplControlValue aControlValue
;
146 aControlValue
.setOptionalVal( (void*) &rSpinbuttonValue
);
148 // only paint the standalone spin buttons, all buttons are painted at once
149 bNativeOK
= pWin
->DrawNativeControl( CTRL_SPINBUTTONS
, PART_ALL_BUTTONS
, Region(), CTRL_STATE_ENABLED
,
150 aControlValue
, rtl::OUString() );
155 void ImplDrawSpinButton( OutputDevice
* pOutDev
,
156 const Rectangle
& rUpperRect
,
157 const Rectangle
& rLowerRect
,
158 BOOL bUpperIn
, BOOL bLowerIn
,
159 BOOL bUpperEnabled
, BOOL bLowerEnabled
, BOOL bHorz
, BOOL bMirrorHorz
)
161 DecorationView
aDecoView( pOutDev
);
163 USHORT nStyle
= BUTTON_DRAW_NOLEFTLIGHTBORDER
;
164 USHORT nSymStyle
= 0;
166 SymbolType eType1
, eType2
;
168 const StyleSettings
& rStyleSettings
= pOutDev
->GetSettings().GetStyleSettings();
169 if ( rStyleSettings
.GetOptions() & STYLE_OPTION_SPINARROW
)
171 // arrows are only use in OS/2 look
174 eType1
= bMirrorHorz
? SYMBOL_ARROW_RIGHT
: SYMBOL_ARROW_LEFT
;
175 eType2
= bMirrorHorz
? SYMBOL_ARROW_LEFT
: SYMBOL_ARROW_RIGHT
;
179 eType1
= SYMBOL_ARROW_UP
;
180 eType2
= SYMBOL_ARROW_DOWN
;
187 eType1
= bMirrorHorz
? SYMBOL_SPIN_RIGHT
: SYMBOL_SPIN_LEFT
;
188 eType2
= bMirrorHorz
? SYMBOL_SPIN_LEFT
: SYMBOL_SPIN_RIGHT
;
192 eType1
= SYMBOL_SPIN_UP
;
193 eType2
= SYMBOL_SPIN_DOWN
;
197 // Oberen/linken Button malen
198 USHORT nTempStyle
= nStyle
;
200 nTempStyle
|= BUTTON_DRAW_PRESSED
;
202 BOOL bNativeOK
= FALSE
;
205 if( pOutDev
->GetOutDevType() == OUTDEV_WINDOW
)
207 Window
*pWin
= (Window
*) pOutDev
;
209 // are we drawing standalone spin buttons or members of a spinfield ?
210 ControlType aControl
= CTRL_SPINBUTTONS
;
211 switch( pWin
->GetType() )
214 case WINDOW_MULTILINEEDIT
:
215 case WINDOW_PATTERNFIELD
:
216 case WINDOW_METRICFIELD
:
217 case WINDOW_CURRENCYFIELD
:
218 case WINDOW_DATEFIELD
:
219 case WINDOW_TIMEFIELD
:
220 case WINDOW_LONGCURRENCYFIELD
:
221 case WINDOW_NUMERICFIELD
:
222 case WINDOW_SPINFIELD
:
223 aControl
= CTRL_SPINBOX
;
226 aControl
= CTRL_SPINBUTTONS
;
230 SpinbuttonValue aValue
;
231 ImplGetSpinbuttonValue( pWin
, rUpperRect
, rLowerRect
,
232 bUpperIn
, bLowerIn
, bUpperEnabled
, bLowerEnabled
,
235 if( aControl
== CTRL_SPINBOX
)
236 bNativeOK
= ImplDrawNativeSpinfield( pWin
, aValue
);
237 else if( aControl
== CTRL_SPINBUTTONS
)
238 bNativeOK
= ImplDrawNativeSpinbuttons( pWin
, aValue
);
242 aUpRect
= aDecoView
.DrawButton( rUpperRect
, nTempStyle
);
244 // Unteren/rechten Button malen
246 nStyle
|= BUTTON_DRAW_PRESSED
;
249 aLowRect
= aDecoView
.DrawButton( rLowerRect
, nStyle
);
251 // Zusaetzliche Default-Kante wollen wir auch ausnutzen
261 // Wir malen auch in die Kante rein, damit man etwas erkennen kann,
262 // wenn das Rechteck zu klein ist
263 if ( aUpRect
.GetHeight() < 4 )
271 // Symbolgroesse berechnen
272 long nTempSize1
= aUpRect
.GetWidth();
273 long nTempSize2
= aLowRect
.GetWidth();
274 if ( Abs( nTempSize1
-nTempSize2
) == 1 )
276 if ( nTempSize1
> nTempSize2
)
281 nTempSize1
= aUpRect
.GetHeight();
282 nTempSize2
= aLowRect
.GetHeight();
283 if ( Abs( nTempSize1
-nTempSize2
) == 1 )
285 if ( nTempSize1
> nTempSize2
)
291 nTempStyle
= nSymStyle
;
292 if ( !bUpperEnabled
)
293 nTempStyle
|= SYMBOL_DRAW_DISABLE
;
295 aDecoView
.DrawSymbol( aUpRect
, eType1
, rStyleSettings
.GetButtonTextColor(), nTempStyle
);
297 if ( !bLowerEnabled
)
298 nSymStyle
|= SYMBOL_DRAW_DISABLE
;
300 aDecoView
.DrawSymbol( aLowRect
, eType2
, rStyleSettings
.GetButtonTextColor(), nSymStyle
);
303 // =======================================================================
305 void SpinField::ImplInitSpinFieldData()
313 mbInitialDown
= FALSE
;
315 mbInDropDown
= FALSE
;
318 // --------------------------------------------------------------------
320 void SpinField::ImplInit( Window
* pParent
, WinBits nWinStyle
)
322 Edit::ImplInit( pParent
, nWinStyle
);
324 if ( nWinStyle
& (WB_SPIN
|WB_DROPDOWN
) )
328 // Some themes want external spin buttons, therefore the main
329 // spinfield should not overdraw the border between its encapsulated
330 // edit field and the spin buttons
331 if ( (nWinStyle
& WB_SPIN
) && ImplUseNativeBorder( nWinStyle
) )
334 mpEdit
= new Edit( this, WB_NOBORDER
);
335 mpEdit
->SetBackground();
338 mpEdit
= new Edit( this, WB_NOBORDER
);
340 mpEdit
->EnableRTL( FALSE
);
341 mpEdit
->SetPosPixel( Point() );
343 SetSubEdit( mpEdit
);
345 maRepeatTimer
.SetTimeoutHdl( LINK( this, SpinField
, ImplTimeout
) );
346 maRepeatTimer
.SetTimeout( GetSettings().GetMouseSettings().GetButtonStartRepeat() );
347 if ( nWinStyle
& WB_REPEAT
)
350 SetCompoundControl( TRUE
);
354 // --------------------------------------------------------------------
356 SpinField::SpinField( WindowType nTyp
) :
359 ImplInitSpinFieldData();
362 // --------------------------------------------------------------------
364 SpinField::SpinField( Window
* pParent
, WinBits nWinStyle
) :
365 Edit( WINDOW_SPINFIELD
)
367 ImplInitSpinFieldData();
368 ImplInit( pParent
, nWinStyle
);
371 // --------------------------------------------------------------------
373 SpinField::SpinField( Window
* pParent
, const ResId
& rResId
) :
374 Edit( WINDOW_SPINFIELD
)
376 ImplInitSpinFieldData();
377 rResId
.SetRT( RSC_SPINFIELD
);
378 WinBits nStyle
= ImplInitRes( rResId
);
379 ImplInit( pParent
, nStyle
);
380 ImplLoadRes( rResId
);
382 if ( !(nStyle
& WB_HIDE
) )
386 // --------------------------------------------------------------------
388 SpinField::~SpinField()
393 // --------------------------------------------------------------------
397 ImplCallEventListenersAndHandler( VCLEVENT_SPINFIELD_UP
, maUpHdlLink
, this );
400 // --------------------------------------------------------------------
402 void SpinField::Down()
404 ImplCallEventListenersAndHandler( VCLEVENT_SPINFIELD_DOWN
, maDownHdlLink
, this );
407 // --------------------------------------------------------------------
409 void SpinField::First()
411 ImplCallEventListenersAndHandler( VCLEVENT_SPINFIELD_FIRST
, maFirstHdlLink
, this );
414 // --------------------------------------------------------------------
416 void SpinField::Last()
418 ImplCallEventListenersAndHandler( VCLEVENT_SPINFIELD_LAST
, maLastHdlLink
, this );
421 // --------------------------------------------------------------------
423 void SpinField::MouseButtonDown( const MouseEvent
& rMEvt
)
425 if ( !HasFocus() && ( !mpEdit
|| !mpEdit
->HasFocus() ) )
433 if ( maUpperRect
.IsInside( rMEvt
.GetPosPixel() ) )
437 Invalidate( maUpperRect
);
439 else if ( maLowerRect
.IsInside( rMEvt
.GetPosPixel() ) )
442 mbInitialDown
= TRUE
;
443 Invalidate( maLowerRect
);
445 else if ( maDropDownRect
.IsInside( rMEvt
.GetPosPixel() ) )
447 // Rechts daneben liegt der DropDownButton:
448 mbInDropDown
= ShowDropDown( mbInDropDown
? FALSE
: TRUE
);
449 Paint( Rectangle( Point(), GetOutputSizePixel() ) );
452 if ( mbUpperIn
|| mbLowerIn
)
457 maRepeatTimer
.Start();
462 Edit::MouseButtonDown( rMEvt
);
465 // --------------------------------------------------------------------
467 void SpinField::MouseButtonUp( const MouseEvent
& rMEvt
)
470 mbInitialUp
= mbInitialDown
= FALSE
;
471 maRepeatTimer
.Stop();
472 maRepeatTimer
.SetTimeout( GetSettings().GetMouseSettings().GetButtonStartRepeat() );
477 Invalidate( maUpperRect
);
481 else if ( mbLowerIn
)
484 Invalidate( maLowerRect
);
489 Edit::MouseButtonUp( rMEvt
);
492 // --------------------------------------------------------------------
494 void SpinField::MouseMove( const MouseEvent
& rMEvt
)
496 if ( rMEvt
.IsLeft() )
500 BOOL bNewUpperIn
= maUpperRect
.IsInside( rMEvt
.GetPosPixel() );
501 if ( bNewUpperIn
!= mbUpperIn
)
506 maRepeatTimer
.Start();
509 maRepeatTimer
.Stop();
511 mbUpperIn
= bNewUpperIn
;
512 Invalidate( maUpperRect
);
516 else if ( mbInitialDown
)
518 BOOL bNewLowerIn
= maLowerRect
.IsInside( rMEvt
.GetPosPixel() );
519 if ( bNewLowerIn
!= mbLowerIn
)
524 maRepeatTimer
.Start();
527 maRepeatTimer
.Stop();
529 mbLowerIn
= bNewLowerIn
;
530 Invalidate( maLowerRect
);
536 Edit::MouseMove( rMEvt
);
539 // --------------------------------------------------------------------
541 long SpinField::Notify( NotifyEvent
& rNEvt
)
544 if( rNEvt
.GetType() == EVENT_KEYINPUT
)
546 const KeyEvent
& rKEvt
= *rNEvt
.GetKeyEvent();
549 USHORT nMod
= rKEvt
.GetKeyCode().GetModifier();
550 switch ( rKEvt
.GetKeyCode().GetCode() )
568 else if ( ( nMod
== KEY_MOD2
) && !mbInDropDown
&& ( GetStyle() & WB_DROPDOWN
) )
570 mbInDropDown
= ShowDropDown( TRUE
);
571 Paint( Rectangle( Point(), GetOutputSizePixel() ) );
598 if ( rNEvt
.GetType() == EVENT_COMMAND
)
600 if ( ( rNEvt
.GetCommandEvent()->GetCommand() == COMMAND_WHEEL
) && !IsReadOnly() )
602 USHORT
nWheelBehavior( GetSettings().GetMouseSettings().GetWheelBehavior() );
603 if ( ( nWheelBehavior
== MOUSE_WHEEL_ALWAYS
)
604 || ( ( nWheelBehavior
== MOUSE_WHEEL_FOCUS_ONLY
)
605 && HasChildPathFocus()
609 const CommandWheelData
* pData
= rNEvt
.GetCommandEvent()->GetWheelData();
610 if ( pData
->GetMode() == COMMAND_WHEEL_SCROLL
)
612 if ( pData
->GetDelta() < 0L )
620 nDone
= 0; // don't eat this event, let the default handling happen (i.e. scroll the context)
624 return nDone
? nDone
: Edit::Notify( rNEvt
);
627 // --------------------------------------------------------------------
629 void SpinField::Command( const CommandEvent
& rCEvt
)
631 Edit::Command( rCEvt
);
634 // --------------------------------------------------------------------
636 void SpinField::FillLayoutData() const
640 mpLayoutData
= new vcl::ControlLayoutData();
641 AppendLayoutData( *GetSubEdit() );
642 GetSubEdit()->SetLayoutDataParent( this );
645 Edit::FillLayoutData();
648 // --------------------------------------------------------------------
650 void SpinField::Paint( const Rectangle
& rRect
)
654 BOOL bEnable
= IsEnabled();
655 ImplDrawSpinButton( this, maUpperRect
, maLowerRect
,
656 mbUpperIn
, mbLowerIn
, bEnable
, bEnable
);
659 if ( GetStyle() & WB_DROPDOWN
)
661 DecorationView
aView( this );
663 USHORT nStyle
= BUTTON_DRAW_NOLIGHTBORDER
;
665 nStyle
|= BUTTON_DRAW_PRESSED
;
666 Rectangle aInnerRect
= aView
.DrawButton( maDropDownRect
, nStyle
);
668 SymbolType eSymbol
= SYMBOL_SPIN_DOWN
;
669 if ( GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_SPINUPDOWN
)
670 eSymbol
= SYMBOL_SPIN_UPDOWN
;
672 nStyle
= IsEnabled() ? 0 : SYMBOL_DRAW_DISABLE
;
673 aView
.DrawSymbol( aInnerRect
, eSymbol
, GetSettings().GetStyleSettings().GetButtonTextColor(), nStyle
);
676 Edit::Paint( rRect
);
679 // --------------------------------------------------------------------
681 void SpinField::ImplCalcButtonAreas( OutputDevice
* pDev
, const Size
& rOutSz
, Rectangle
& rDDArea
, Rectangle
& rSpinUpArea
, Rectangle
& rSpinDownArea
)
683 const StyleSettings
& rStyleSettings
= pDev
->GetSettings().GetStyleSettings();
688 if ( GetStyle() & WB_DROPDOWN
)
690 long nW
= rStyleSettings
.GetScrollBarSize();
691 nW
= GetDrawPixel( pDev
, nW
);
692 aDropDownSize
= Size( CalcZoom( nW
), aSize
.Height() );
693 aSize
.Width() -= aDropDownSize
.Width();
694 rDDArea
= Rectangle( Point( aSize
.Width(), 0 ), aDropDownSize
);
700 // Je nach Hoehe, die groessen Berechnen
701 if ( GetStyle() & WB_SPIN
)
703 long nBottom1
= aSize
.Height()/2;
704 long nBottom2
= aSize
.Height()-1;
705 long nTop2
= nBottom1
;
707 if ( !(aSize
.Height() & 0x01) )
710 BOOL bNativeRegionOK
= FALSE
;
711 Region aContentUp
, aContentDown
;
713 if ( (pDev
->GetOutDevType() == OUTDEV_WINDOW
) &&
714 // there is just no useful native support for spinfields with dropdown
715 ! (GetStyle() & WB_DROPDOWN
) &&
716 IsNativeControlSupported(CTRL_SPINBOX
, PART_ENTIRE_CONTROL
) )
718 Window
*pWin
= (Window
*) pDev
;
719 Window
*pBorder
= pWin
->GetWindow( WINDOW_BORDER
);
721 // get the system's spin button size
722 ImplControlValue aControlValue
;
726 // use the full extent of the control
727 Region
aArea( Rectangle( aPoint
, pBorder
->GetOutputSizePixel() ) );
730 pWin
->GetNativeControlRegion(CTRL_SPINBOX
, PART_BUTTON_UP
,
731 aArea
, 0, aControlValue
, rtl::OUString(), aBound
, aContentUp
) &&
732 pWin
->GetNativeControlRegion(CTRL_SPINBOX
, PART_BUTTON_DOWN
,
733 aArea
, 0, aControlValue
, rtl::OUString(), aBound
, aContentDown
);
735 if( bNativeRegionOK
)
737 // convert back from border space to local coordinates
738 aPoint
= pBorder
->ScreenToOutputPixel( pWin
->OutputToScreenPixel( aPoint
) );
739 aContentUp
.Move(-aPoint
.X(), -aPoint
.Y());
740 aContentDown
.Move(-aPoint
.X(), -aPoint
.Y());
744 if( bNativeRegionOK
)
746 rSpinUpArea
= aContentUp
.GetBoundRect();
747 rSpinDownArea
= aContentDown
.GetBoundRect();
751 aSize
.Width() -= CalcZoom( GetDrawPixel( pDev
, rStyleSettings
.GetSpinSize() ) );
753 rSpinUpArea
= Rectangle( aSize
.Width(), nTop1
, rOutSz
.Width()-aDropDownSize
.Width()-1, nBottom1
);
754 rSpinDownArea
= Rectangle( rSpinUpArea
.Left(), nTop2
, rSpinUpArea
.Right(), nBottom2
);
759 rSpinUpArea
.SetEmpty();
760 rSpinDownArea
.SetEmpty();
764 // --------------------------------------------------------------------
766 void SpinField::Resize()
771 Size aSize
= GetOutputSizePixel();
772 bool bSubEditPositioned
= false;
774 if ( GetStyle() & (WB_SPIN
|WB_DROPDOWN
) )
776 ImplCalcButtonAreas( this, aSize
, maDropDownRect
, maUpperRect
, maLowerRect
);
778 ImplControlValue aControlValue
;
780 Region aContent
, aBound
;
782 // use the full extent of the control
783 Window
*pBorder
= GetWindow( WINDOW_BORDER
);
784 Region
aArea( Rectangle(aPoint
, pBorder
->GetOutputSizePixel()) );
786 // adjust position and size of the edit field
787 if ( GetNativeControlRegion(CTRL_SPINBOX
, PART_SUB_EDIT
,
788 aArea
, 0, aControlValue
, rtl::OUString(), aBound
, aContent
) )
790 // convert back from border space to local coordinates
791 aPoint
= pBorder
->ScreenToOutputPixel( OutputToScreenPixel( aPoint
) );
792 aContent
.Move(-aPoint
.X(), -aPoint
.Y());
794 // use the themes drop down size
795 Rectangle aContentRect
= aContent
.GetBoundRect();
796 mpEdit
->SetPosPixel( aContentRect
.TopLeft() );
797 bSubEditPositioned
= true;
798 aSize
= aContentRect
.GetSize();
802 if ( maUpperRect
.IsEmpty() )
804 DBG_ASSERT( !maDropDownRect
.IsEmpty(), "SpinField::Resize: SPIN && DROPDOWN, but all empty rects?" );
805 aSize
.Width() = maDropDownRect
.Left();
808 aSize
.Width() = maUpperRect
.Left();
812 if( ! bSubEditPositioned
)
814 // this moves our sub edit if RTL gets switched
815 mpEdit
->SetPosPixel( Point() );
817 mpEdit
->SetSizePixel( aSize
);
819 if ( GetStyle() & WB_SPIN
)
820 Invalidate( Rectangle( maUpperRect
.TopLeft(), maLowerRect
.BottomRight() ) );
821 if ( GetStyle() & WB_DROPDOWN
)
822 Invalidate( maDropDownRect
);
826 // -----------------------------------------------------------------------
828 void SpinField::StateChanged( StateChangedType nType
)
830 Edit::StateChanged( nType
);
832 if ( nType
== STATE_CHANGE_ENABLE
)
834 if ( mbSpin
|| ( GetStyle() & WB_DROPDOWN
) )
836 mpEdit
->Enable( IsEnabled() );
840 Invalidate( maLowerRect
);
841 Invalidate( maUpperRect
);
843 if ( GetStyle() & WB_DROPDOWN
)
844 Invalidate( maDropDownRect
);
847 else if ( nType
== STATE_CHANGE_STYLE
)
849 if ( GetStyle() & WB_REPEAT
)
854 else if ( nType
== STATE_CHANGE_ZOOM
)
858 mpEdit
->SetZoom( GetZoom() );
861 else if ( nType
== STATE_CHANGE_CONTROLFONT
)
864 mpEdit
->SetControlFont( GetControlFont() );
865 ImplInitSettings( TRUE
, FALSE
, FALSE
);
868 else if ( nType
== STATE_CHANGE_CONTROLFOREGROUND
)
871 mpEdit
->SetControlForeground( GetControlForeground() );
872 ImplInitSettings( FALSE
, TRUE
, FALSE
);
875 else if ( nType
== STATE_CHANGE_CONTROLBACKGROUND
)
878 mpEdit
->SetControlBackground( GetControlBackground() );
879 ImplInitSettings( FALSE
, FALSE
, TRUE
);
882 else if( nType
== STATE_CHANGE_MIRRORING
)
885 mpEdit
->StateChanged( STATE_CHANGE_MIRRORING
);
890 // -----------------------------------------------------------------------
892 void SpinField::DataChanged( const DataChangedEvent
& rDCEvt
)
894 Edit::DataChanged( rDCEvt
);
896 if ( (rDCEvt
.GetType() == DATACHANGED_SETTINGS
) &&
897 (rDCEvt
.GetFlags() & SETTINGS_STYLE
) )
904 // -----------------------------------------------------------------------
906 Rectangle
* SpinField::ImplFindPartRect( const Point
& rPt
)
908 if( maUpperRect
.IsInside( rPt
) )
910 else if( maLowerRect
.IsInside( rPt
) )
916 long SpinField::PreNotify( NotifyEvent
& rNEvt
)
919 const MouseEvent
* pMouseEvt
= NULL
;
921 if( (rNEvt
.GetType() == EVENT_MOUSEMOVE
) && (pMouseEvt
= rNEvt
.GetMouseEvent()) != NULL
)
923 if( !pMouseEvt
->GetButtons() && !pMouseEvt
->IsSynthetic() && !pMouseEvt
->IsModifierChanged() )
925 // trigger redraw if mouse over state has changed
926 if( IsNativeControlSupported(CTRL_SPINBOX
, PART_ENTIRE_CONTROL
) ||
927 IsNativeControlSupported(CTRL_SPINBOX
, PART_ALL_BUTTONS
) )
929 Rectangle
* pRect
= ImplFindPartRect( GetPointerPosPixel() );
930 Rectangle
* pLastRect
= ImplFindPartRect( GetLastPointerPosPixel() );
931 if( pRect
!= pLastRect
|| (pMouseEvt
->IsLeaveWindow() || pMouseEvt
->IsEnterWindow()) )
933 // FIXME: this is currently only on aqua
934 // check for other platforms that need similar handling
935 if( ImplGetSVData()->maNWFData
.mbNoFocusRects
&&
936 IsNativeWidgetEnabled() &&
937 IsNativeControlSupported( CTRL_EDITBOX
, PART_ENTIRE_CONTROL
) )
939 ImplInvalidateOutermostBorder( this );
944 Region
aRgn( GetActiveClipRegion() );
947 SetClipRegion( *pLastRect
);
949 SetClipRegion( aRgn
);
953 SetClipRegion( *pRect
);
955 SetClipRegion( aRgn
);
963 return nDone
? nDone
: Edit::PreNotify(rNEvt
);
966 // -----------------------------------------------------------------------
968 void SpinField::EndDropDown()
970 mbInDropDown
= FALSE
;
971 Paint( Rectangle( Point(), GetOutputSizePixel() ) );
974 // -----------------------------------------------------------------------
976 BOOL
SpinField::ShowDropDown( BOOL
)
981 // -----------------------------------------------------------------------
983 Size
SpinField::CalcMinimumSize() const
985 Size aSz
= Edit::CalcMinimumSize();
987 if ( GetStyle() & WB_DROPDOWN
)
988 aSz
.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
989 if ( GetStyle() & WB_SPIN
)
990 aSz
.Width() += maUpperRect
.GetWidth();
995 // -----------------------------------------------------------------------
997 Size
SpinField::GetOptimalSize(WindowSizeType eType
) const
1000 case WINDOWSIZE_MINIMUM
:
1001 return CalcMinimumSize();
1003 return Edit::GetOptimalSize( eType
);
1007 // -----------------------------------------------------------------------
1009 Size
SpinField::CalcSize( USHORT nChars
) const
1011 Size aSz
= Edit::CalcSize( nChars
);
1013 if ( GetStyle() & WB_DROPDOWN
)
1014 aSz
.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
1015 if ( GetStyle() & WB_SPIN
)
1016 aSz
.Width() += GetSettings().GetStyleSettings().GetSpinSize();
1021 // --------------------------------------------------------------------
1023 IMPL_LINK( SpinField
, ImplTimeout
, Timer
*, pTimer
)
1025 if ( pTimer
->GetTimeout() == GetSettings().GetMouseSettings().GetButtonStartRepeat() )
1027 pTimer
->SetTimeout( GetSettings().GetMouseSettings().GetButtonRepeat() );
1040 // -----------------------------------------------------------------------
1042 void SpinField::Draw( OutputDevice
* pDev
, const Point
& rPos
, const Size
& rSize
, ULONG nFlags
)
1044 Edit::Draw( pDev
, rPos
, rSize
, nFlags
);
1046 WinBits nFieldStyle
= GetStyle();
1047 if ( !(nFlags
& WINDOW_DRAW_NOCONTROLS
) && ( nFieldStyle
& (WB_SPIN
|WB_DROPDOWN
) ) )
1049 Point aPos
= pDev
->LogicToPixel( rPos
);
1050 Size aSize
= pDev
->LogicToPixel( rSize
);
1051 OutDevType eOutDevType
= pDev
->GetOutDevType();
1052 AllSettings aOldSettings
= pDev
->GetSettings();
1057 if ( eOutDevType
== OUTDEV_PRINTER
)
1059 StyleSettings aStyleSettings
= aOldSettings
.GetStyleSettings();
1060 aStyleSettings
.SetFaceColor( COL_LIGHTGRAY
);
1061 aStyleSettings
.SetButtonTextColor( COL_BLACK
);
1062 AllSettings
aSettings( aOldSettings
);
1063 aSettings
.SetStyleSettings( aStyleSettings
);
1064 pDev
->SetSettings( aSettings
);
1067 Rectangle aDD
, aUp
, aDown
;
1068 ImplCalcButtonAreas( pDev
, aSize
, aDD
, aUp
, aDown
);
1069 aDD
.Move( aPos
.X(), aPos
.Y() );
1070 aUp
.Move( aPos
.X(), aPos
.Y() );
1072 aDown
.Move( aPos
.X(), aPos
.Y() );
1074 Color aButtonTextColor
;
1075 if ( ( nFlags
& WINDOW_DRAW_MONO
) || ( eOutDevType
== OUTDEV_PRINTER
) )
1076 aButtonTextColor
= Color( COL_BLACK
);
1078 aButtonTextColor
= GetSettings().GetStyleSettings().GetButtonTextColor();
1080 if ( GetStyle() & WB_DROPDOWN
)
1082 DecorationView
aView( pDev
);
1083 USHORT nStyle
= BUTTON_DRAW_NOLIGHTBORDER
;
1084 Rectangle aInnerRect
= aView
.DrawButton( aDD
, nStyle
);
1085 SymbolType eSymbol
= SYMBOL_SPIN_DOWN
;
1086 if ( GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_SPINUPDOWN
)
1087 eSymbol
= SYMBOL_SPIN_UPDOWN
;
1089 nStyle
= ( IsEnabled() || ( nFlags
& WINDOW_DRAW_NODISABLE
) ) ? 0 : SYMBOL_DRAW_DISABLE
;
1090 aView
.DrawSymbol( aInnerRect
, eSymbol
, aButtonTextColor
, nStyle
);
1093 if ( GetStyle() & WB_SPIN
)
1095 ImplDrawSpinButton( pDev
, aUp
, aDown
, FALSE
, FALSE
, TRUE
, TRUE
);
1099 pDev
->SetSettings( aOldSettings
);