1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
32 #include "vcl/event.hxx"
33 #include "vcl/decoview.hxx"
35 #include "vcl/spinfld.hxx"
36 #include "vcl/controldata.hxx"
37 #include "vcl/svdata.hxx"
39 // =======================================================================
41 void ImplGetSpinbuttonValue( Window
*pWin
, const Rectangle
& rUpperRect
,
42 const Rectangle
& rLowerRect
,
43 BOOL bUpperIn
, BOOL bLowerIn
,
44 BOOL bUpperEnabled
, BOOL bLowerEnabled
, BOOL bHorz
,
45 SpinbuttonValue
& rValue
)
47 // convert spinbutton data to a SpinbuttonValue structure for native painting
49 rValue
.maUpperRect
= rUpperRect
;
50 rValue
.maLowerRect
= rLowerRect
;
52 Point aPointerPos
= pWin
->GetPointerPosPixel();
54 ControlState nState
= CTRL_STATE_ENABLED
;
56 nState
|= CTRL_STATE_PRESSED
;
57 if ( !pWin
->IsEnabled() || !bUpperEnabled
)
58 nState
&= ~CTRL_STATE_ENABLED
;
59 if ( pWin
->HasFocus() )
60 nState
|= CTRL_STATE_FOCUSED
;
61 if( pWin
->IsMouseOver() && rUpperRect
.IsInside( aPointerPos
) )
62 nState
|= CTRL_STATE_ROLLOVER
;
63 rValue
.mnUpperState
= nState
;
65 nState
= CTRL_STATE_ENABLED
;
67 nState
|= CTRL_STATE_PRESSED
;
68 if ( !pWin
->IsEnabled() || !bLowerEnabled
)
69 nState
&= ~CTRL_STATE_ENABLED
;
70 if ( pWin
->HasFocus() )
71 nState
|= CTRL_STATE_FOCUSED
;
72 // for overlapping spins: highlight only one
73 if( pWin
->IsMouseOver() && rLowerRect
.IsInside( aPointerPos
) &&
74 !rUpperRect
.IsInside( aPointerPos
) )
75 nState
|= CTRL_STATE_ROLLOVER
;
76 rValue
.mnLowerState
= nState
;
78 rValue
.mnUpperPart
= bHorz
? PART_BUTTON_LEFT
: PART_BUTTON_UP
;
79 rValue
.mnLowerPart
= bHorz
? PART_BUTTON_RIGHT
: PART_BUTTON_DOWN
;
83 BOOL
ImplDrawNativeSpinfield( Window
*pWin
, const SpinbuttonValue
& rSpinbuttonValue
)
85 BOOL bNativeOK
= FALSE
;
87 if( pWin
->IsNativeControlSupported(CTRL_SPINBOX
, PART_ENTIRE_CONTROL
) &&
88 // there is just no useful native support for spinfields with dropdown
89 !(pWin
->GetStyle() & WB_DROPDOWN
) )
91 if( pWin
->IsNativeControlSupported(CTRL_SPINBOX
, rSpinbuttonValue
.mnUpperPart
) &&
92 pWin
->IsNativeControlSupported(CTRL_SPINBOX
, rSpinbuttonValue
.mnLowerPart
) )
94 // only paint the embedded spin buttons, all buttons are painted at once
95 bNativeOK
= pWin
->DrawNativeControl( CTRL_SPINBOX
, PART_ALL_BUTTONS
, Rectangle(), CTRL_STATE_ENABLED
,
96 rSpinbuttonValue
, rtl::OUString() );
100 // paint the spinbox as a whole, use borderwindow to have proper clipping
101 Window
*pBorder
= pWin
->GetWindow( WINDOW_BORDER
);
103 // to not overwrite everything, set the button region as clipregion to the border window
104 Rectangle
aClipRect( rSpinbuttonValue
.maLowerRect
);
105 aClipRect
.Union( rSpinbuttonValue
.maUpperRect
);
107 // convert from screen space to borderwin space
108 aClipRect
.SetPos( pBorder
->ScreenToOutputPixel(pWin
->OutputToScreenPixel(aClipRect
.TopLeft())) );
110 Region
oldRgn( pBorder
->GetClipRegion() );
111 pBorder
->SetClipRegion( Region( aClipRect
) );
114 Size
aSize( pBorder
->GetOutputSizePixel() ); // the size of the border window, i.e., the whole control
115 Rectangle aBound
, aContent
;
116 Rectangle
aNatRgn( aPt
, aSize
);
117 if( ! ImplGetSVData()->maNWFData
.mbCanDrawWidgetAnySize
&&
118 pBorder
->GetNativeControlRegion( CTRL_SPINBOX
, PART_ENTIRE_CONTROL
,
119 aNatRgn
, 0, rSpinbuttonValue
, rtl::OUString(), aBound
, aContent
) )
121 aSize
= aContent
.GetSize();
124 Rectangle
aRgn( aPt
, aSize
);
125 bNativeOK
= pBorder
->DrawNativeControl( CTRL_SPINBOX
, PART_ENTIRE_CONTROL
, aRgn
, CTRL_STATE_ENABLED
,
126 rSpinbuttonValue
, rtl::OUString() );
128 pBorder
->SetClipRegion( oldRgn
);
134 BOOL
ImplDrawNativeSpinbuttons( Window
*pWin
, const SpinbuttonValue
& rSpinbuttonValue
)
136 BOOL bNativeOK
= FALSE
;
138 if( pWin
->IsNativeControlSupported(CTRL_SPINBUTTONS
, PART_ENTIRE_CONTROL
) )
140 // only paint the standalone spin buttons, all buttons are painted at once
141 bNativeOK
= pWin
->DrawNativeControl( CTRL_SPINBUTTONS
, PART_ALL_BUTTONS
, Rectangle(), CTRL_STATE_ENABLED
,
142 rSpinbuttonValue
, rtl::OUString() );
147 void ImplDrawSpinButton( OutputDevice
* pOutDev
,
148 const Rectangle
& rUpperRect
,
149 const Rectangle
& rLowerRect
,
150 BOOL bUpperIn
, BOOL bLowerIn
,
151 BOOL bUpperEnabled
, BOOL bLowerEnabled
, BOOL bHorz
, BOOL bMirrorHorz
)
153 DecorationView
aDecoView( pOutDev
);
155 USHORT nStyle
= BUTTON_DRAW_NOLEFTLIGHTBORDER
;
156 USHORT nSymStyle
= 0;
158 SymbolType eType1
, eType2
;
160 const StyleSettings
& rStyleSettings
= pOutDev
->GetSettings().GetStyleSettings();
161 if ( rStyleSettings
.GetOptions() & STYLE_OPTION_SPINARROW
)
163 // arrows are only use in OS/2 look
166 eType1
= bMirrorHorz
? SYMBOL_ARROW_RIGHT
: SYMBOL_ARROW_LEFT
;
167 eType2
= bMirrorHorz
? SYMBOL_ARROW_LEFT
: SYMBOL_ARROW_RIGHT
;
171 eType1
= SYMBOL_ARROW_UP
;
172 eType2
= SYMBOL_ARROW_DOWN
;
179 eType1
= bMirrorHorz
? SYMBOL_SPIN_RIGHT
: SYMBOL_SPIN_LEFT
;
180 eType2
= bMirrorHorz
? SYMBOL_SPIN_LEFT
: SYMBOL_SPIN_RIGHT
;
184 eType1
= SYMBOL_SPIN_UP
;
185 eType2
= SYMBOL_SPIN_DOWN
;
189 // Oberen/linken Button malen
190 USHORT nTempStyle
= nStyle
;
192 nTempStyle
|= BUTTON_DRAW_PRESSED
;
194 BOOL bNativeOK
= FALSE
;
197 if( pOutDev
->GetOutDevType() == OUTDEV_WINDOW
)
199 Window
*pWin
= (Window
*) pOutDev
;
201 // are we drawing standalone spin buttons or members of a spinfield ?
202 ControlType aControl
= CTRL_SPINBUTTONS
;
203 switch( pWin
->GetType() )
206 case WINDOW_MULTILINEEDIT
:
207 case WINDOW_PATTERNFIELD
:
208 case WINDOW_METRICFIELD
:
209 case WINDOW_CURRENCYFIELD
:
210 case WINDOW_DATEFIELD
:
211 case WINDOW_TIMEFIELD
:
212 case WINDOW_LONGCURRENCYFIELD
:
213 case WINDOW_NUMERICFIELD
:
214 case WINDOW_SPINFIELD
:
215 aControl
= CTRL_SPINBOX
;
218 aControl
= CTRL_SPINBUTTONS
;
222 SpinbuttonValue aValue
;
223 ImplGetSpinbuttonValue( pWin
, rUpperRect
, rLowerRect
,
224 bUpperIn
, bLowerIn
, bUpperEnabled
, bLowerEnabled
,
227 if( aControl
== CTRL_SPINBOX
)
228 bNativeOK
= ImplDrawNativeSpinfield( pWin
, aValue
);
229 else if( aControl
== CTRL_SPINBUTTONS
)
230 bNativeOK
= ImplDrawNativeSpinbuttons( pWin
, aValue
);
234 aUpRect
= aDecoView
.DrawButton( rUpperRect
, nTempStyle
);
236 // Unteren/rechten Button malen
238 nStyle
|= BUTTON_DRAW_PRESSED
;
241 aLowRect
= aDecoView
.DrawButton( rLowerRect
, nStyle
);
243 // Zusaetzliche Default-Kante wollen wir auch ausnutzen
253 // Wir malen auch in die Kante rein, damit man etwas erkennen kann,
254 // wenn das Rechteck zu klein ist
255 if ( aUpRect
.GetHeight() < 4 )
263 // Symbolgroesse berechnen
264 long nTempSize1
= aUpRect
.GetWidth();
265 long nTempSize2
= aLowRect
.GetWidth();
266 if ( Abs( nTempSize1
-nTempSize2
) == 1 )
268 if ( nTempSize1
> nTempSize2
)
273 nTempSize1
= aUpRect
.GetHeight();
274 nTempSize2
= aLowRect
.GetHeight();
275 if ( Abs( nTempSize1
-nTempSize2
) == 1 )
277 if ( nTempSize1
> nTempSize2
)
283 nTempStyle
= nSymStyle
;
284 if ( !bUpperEnabled
)
285 nTempStyle
|= SYMBOL_DRAW_DISABLE
;
287 aDecoView
.DrawSymbol( aUpRect
, eType1
, rStyleSettings
.GetButtonTextColor(), nTempStyle
);
289 if ( !bLowerEnabled
)
290 nSymStyle
|= SYMBOL_DRAW_DISABLE
;
292 aDecoView
.DrawSymbol( aLowRect
, eType2
, rStyleSettings
.GetButtonTextColor(), nSymStyle
);
295 // =======================================================================
297 void SpinField::ImplInitSpinFieldData()
305 mbInitialDown
= FALSE
;
307 mbInDropDown
= FALSE
;
310 // --------------------------------------------------------------------
312 void SpinField::ImplInit( Window
* pParent
, WinBits nWinStyle
)
314 Edit::ImplInit( pParent
, nWinStyle
);
316 if ( nWinStyle
& (WB_SPIN
|WB_DROPDOWN
) )
320 // Some themes want external spin buttons, therefore the main
321 // spinfield should not overdraw the border between its encapsulated
322 // edit field and the spin buttons
323 if ( (nWinStyle
& WB_SPIN
) && ImplUseNativeBorder( nWinStyle
) )
326 mpEdit
= new Edit( this, WB_NOBORDER
);
327 mpEdit
->SetBackground();
330 mpEdit
= new Edit( this, WB_NOBORDER
);
332 mpEdit
->EnableRTL( FALSE
);
333 mpEdit
->SetPosPixel( Point() );
335 SetSubEdit( mpEdit
);
337 maRepeatTimer
.SetTimeoutHdl( LINK( this, SpinField
, ImplTimeout
) );
338 maRepeatTimer
.SetTimeout( GetSettings().GetMouseSettings().GetButtonStartRepeat() );
339 if ( nWinStyle
& WB_REPEAT
)
342 SetCompoundControl( TRUE
);
346 // --------------------------------------------------------------------
348 SpinField::SpinField( WindowType nTyp
) :
351 ImplInitSpinFieldData();
354 // --------------------------------------------------------------------
356 SpinField::SpinField( Window
* pParent
, WinBits nWinStyle
) :
357 Edit( WINDOW_SPINFIELD
)
359 ImplInitSpinFieldData();
360 ImplInit( pParent
, nWinStyle
);
363 // --------------------------------------------------------------------
365 SpinField::SpinField( Window
* pParent
, const ResId
& rResId
) :
366 Edit( WINDOW_SPINFIELD
)
368 ImplInitSpinFieldData();
369 rResId
.SetRT( RSC_SPINFIELD
);
370 WinBits nStyle
= ImplInitRes( rResId
);
371 ImplInit( pParent
, nStyle
);
372 ImplLoadRes( rResId
);
374 if ( !(nStyle
& WB_HIDE
) )
378 // --------------------------------------------------------------------
380 SpinField::~SpinField()
385 // --------------------------------------------------------------------
389 ImplCallEventListenersAndHandler( VCLEVENT_SPINFIELD_UP
, maUpHdlLink
, this );
392 // --------------------------------------------------------------------
394 void SpinField::Down()
396 ImplCallEventListenersAndHandler( VCLEVENT_SPINFIELD_DOWN
, maDownHdlLink
, this );
399 // --------------------------------------------------------------------
401 void SpinField::First()
403 ImplCallEventListenersAndHandler( VCLEVENT_SPINFIELD_FIRST
, maFirstHdlLink
, this );
406 // --------------------------------------------------------------------
408 void SpinField::Last()
410 ImplCallEventListenersAndHandler( VCLEVENT_SPINFIELD_LAST
, maLastHdlLink
, this );
413 // --------------------------------------------------------------------
415 void SpinField::MouseButtonDown( const MouseEvent
& rMEvt
)
417 if ( !HasFocus() && ( !mpEdit
|| !mpEdit
->HasFocus() ) )
425 if ( maUpperRect
.IsInside( rMEvt
.GetPosPixel() ) )
429 Invalidate( maUpperRect
);
431 else if ( maLowerRect
.IsInside( rMEvt
.GetPosPixel() ) )
434 mbInitialDown
= TRUE
;
435 Invalidate( maLowerRect
);
437 else if ( maDropDownRect
.IsInside( rMEvt
.GetPosPixel() ) )
439 // Rechts daneben liegt der DropDownButton:
440 mbInDropDown
= ShowDropDown( mbInDropDown
? FALSE
: TRUE
);
441 Paint( Rectangle( Point(), GetOutputSizePixel() ) );
444 if ( mbUpperIn
|| mbLowerIn
)
449 maRepeatTimer
.Start();
454 Edit::MouseButtonDown( rMEvt
);
457 // --------------------------------------------------------------------
459 void SpinField::MouseButtonUp( const MouseEvent
& rMEvt
)
462 mbInitialUp
= mbInitialDown
= FALSE
;
463 maRepeatTimer
.Stop();
464 maRepeatTimer
.SetTimeout( GetSettings().GetMouseSettings().GetButtonStartRepeat() );
469 Invalidate( maUpperRect
);
473 else if ( mbLowerIn
)
476 Invalidate( maLowerRect
);
481 Edit::MouseButtonUp( rMEvt
);
484 // --------------------------------------------------------------------
486 void SpinField::MouseMove( const MouseEvent
& rMEvt
)
488 if ( rMEvt
.IsLeft() )
492 BOOL bNewUpperIn
= maUpperRect
.IsInside( rMEvt
.GetPosPixel() );
493 if ( bNewUpperIn
!= mbUpperIn
)
498 maRepeatTimer
.Start();
501 maRepeatTimer
.Stop();
503 mbUpperIn
= bNewUpperIn
;
504 Invalidate( maUpperRect
);
508 else if ( mbInitialDown
)
510 BOOL bNewLowerIn
= maLowerRect
.IsInside( rMEvt
.GetPosPixel() );
511 if ( bNewLowerIn
!= mbLowerIn
)
516 maRepeatTimer
.Start();
519 maRepeatTimer
.Stop();
521 mbLowerIn
= bNewLowerIn
;
522 Invalidate( maLowerRect
);
528 Edit::MouseMove( rMEvt
);
531 // --------------------------------------------------------------------
533 long SpinField::Notify( NotifyEvent
& rNEvt
)
536 if( rNEvt
.GetType() == EVENT_KEYINPUT
)
538 const KeyEvent
& rKEvt
= *rNEvt
.GetKeyEvent();
541 USHORT nMod
= rKEvt
.GetKeyCode().GetModifier();
542 switch ( rKEvt
.GetKeyCode().GetCode() )
560 else if ( ( nMod
== KEY_MOD2
) && !mbInDropDown
&& ( GetStyle() & WB_DROPDOWN
) )
562 mbInDropDown
= ShowDropDown( TRUE
);
563 Paint( Rectangle( Point(), GetOutputSizePixel() ) );
590 if ( rNEvt
.GetType() == EVENT_COMMAND
)
592 if ( ( rNEvt
.GetCommandEvent()->GetCommand() == COMMAND_WHEEL
) && !IsReadOnly() )
594 USHORT
nWheelBehavior( GetSettings().GetMouseSettings().GetWheelBehavior() );
595 if ( ( nWheelBehavior
== MOUSE_WHEEL_ALWAYS
)
596 || ( ( nWheelBehavior
== MOUSE_WHEEL_FOCUS_ONLY
)
597 && HasChildPathFocus()
601 const CommandWheelData
* pData
= rNEvt
.GetCommandEvent()->GetWheelData();
602 if ( pData
->GetMode() == COMMAND_WHEEL_SCROLL
)
604 if ( pData
->GetDelta() < 0L )
612 nDone
= 0; // don't eat this event, let the default handling happen (i.e. scroll the context)
616 return nDone
? nDone
: Edit::Notify( rNEvt
);
619 // --------------------------------------------------------------------
621 void SpinField::Command( const CommandEvent
& rCEvt
)
623 Edit::Command( rCEvt
);
626 // --------------------------------------------------------------------
628 void SpinField::FillLayoutData() const
632 mpControlData
->mpLayoutData
= new vcl::ControlLayoutData();
633 AppendLayoutData( *GetSubEdit() );
634 GetSubEdit()->SetLayoutDataParent( this );
637 Edit::FillLayoutData();
640 // --------------------------------------------------------------------
642 void SpinField::Paint( const Rectangle
& rRect
)
646 BOOL bEnable
= IsEnabled();
647 ImplDrawSpinButton( this, maUpperRect
, maLowerRect
,
648 mbUpperIn
, mbLowerIn
, bEnable
, bEnable
);
651 if ( GetStyle() & WB_DROPDOWN
)
653 DecorationView
aView( this );
655 USHORT nStyle
= BUTTON_DRAW_NOLIGHTBORDER
;
657 nStyle
|= BUTTON_DRAW_PRESSED
;
658 Rectangle aInnerRect
= aView
.DrawButton( maDropDownRect
, nStyle
);
660 SymbolType eSymbol
= SYMBOL_SPIN_DOWN
;
661 if ( GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_SPINUPDOWN
)
662 eSymbol
= SYMBOL_SPIN_UPDOWN
;
664 nStyle
= IsEnabled() ? 0 : SYMBOL_DRAW_DISABLE
;
665 aView
.DrawSymbol( aInnerRect
, eSymbol
, GetSettings().GetStyleSettings().GetButtonTextColor(), nStyle
);
668 Edit::Paint( rRect
);
671 // --------------------------------------------------------------------
673 void SpinField::ImplCalcButtonAreas( OutputDevice
* pDev
, const Size
& rOutSz
, Rectangle
& rDDArea
, Rectangle
& rSpinUpArea
, Rectangle
& rSpinDownArea
)
675 const StyleSettings
& rStyleSettings
= pDev
->GetSettings().GetStyleSettings();
680 if ( GetStyle() & WB_DROPDOWN
)
682 long nW
= rStyleSettings
.GetScrollBarSize();
683 nW
= GetDrawPixel( pDev
, nW
);
684 aDropDownSize
= Size( CalcZoom( nW
), aSize
.Height() );
685 aSize
.Width() -= aDropDownSize
.Width();
686 rDDArea
= Rectangle( Point( aSize
.Width(), 0 ), aDropDownSize
);
692 // Je nach Hoehe, die groessen Berechnen
693 if ( GetStyle() & WB_SPIN
)
695 long nBottom1
= aSize
.Height()/2;
696 long nBottom2
= aSize
.Height()-1;
697 long nTop2
= nBottom1
;
699 if ( !(aSize
.Height() & 0x01) )
702 BOOL bNativeRegionOK
= FALSE
;
703 Rectangle aContentUp
, aContentDown
;
705 if ( (pDev
->GetOutDevType() == OUTDEV_WINDOW
) &&
706 // there is just no useful native support for spinfields with dropdown
707 ! (GetStyle() & WB_DROPDOWN
) &&
708 IsNativeControlSupported(CTRL_SPINBOX
, PART_ENTIRE_CONTROL
) )
710 Window
*pWin
= (Window
*) pDev
;
711 Window
*pBorder
= pWin
->GetWindow( WINDOW_BORDER
);
713 // get the system's spin button size
714 ImplControlValue aControlValue
;
718 // use the full extent of the control
719 Rectangle
aArea( aPoint
, pBorder
->GetOutputSizePixel() );
722 pWin
->GetNativeControlRegion(CTRL_SPINBOX
, PART_BUTTON_UP
,
723 aArea
, 0, aControlValue
, rtl::OUString(), aBound
, aContentUp
) &&
724 pWin
->GetNativeControlRegion(CTRL_SPINBOX
, PART_BUTTON_DOWN
,
725 aArea
, 0, aControlValue
, rtl::OUString(), aBound
, aContentDown
);
727 if( bNativeRegionOK
)
729 // convert back from border space to local coordinates
730 aPoint
= pBorder
->ScreenToOutputPixel( pWin
->OutputToScreenPixel( aPoint
) );
731 aContentUp
.Move(-aPoint
.X(), -aPoint
.Y());
732 aContentDown
.Move(-aPoint
.X(), -aPoint
.Y());
736 if( bNativeRegionOK
)
738 rSpinUpArea
= aContentUp
;
739 rSpinDownArea
= aContentDown
;
743 aSize
.Width() -= CalcZoom( GetDrawPixel( pDev
, rStyleSettings
.GetSpinSize() ) );
745 rSpinUpArea
= Rectangle( aSize
.Width(), nTop1
, rOutSz
.Width()-aDropDownSize
.Width()-1, nBottom1
);
746 rSpinDownArea
= Rectangle( rSpinUpArea
.Left(), nTop2
, rSpinUpArea
.Right(), nBottom2
);
751 rSpinUpArea
.SetEmpty();
752 rSpinDownArea
.SetEmpty();
756 // --------------------------------------------------------------------
758 void SpinField::Resize()
763 Size aSize
= GetOutputSizePixel();
764 bool bSubEditPositioned
= false;
766 if ( GetStyle() & (WB_SPIN
|WB_DROPDOWN
) )
768 ImplCalcButtonAreas( this, aSize
, maDropDownRect
, maUpperRect
, maLowerRect
);
770 ImplControlValue aControlValue
;
772 Rectangle aContent
, aBound
;
774 // use the full extent of the control
775 Window
*pBorder
= GetWindow( WINDOW_BORDER
);
776 Rectangle
aArea( aPoint
, pBorder
->GetOutputSizePixel() );
778 // adjust position and size of the edit field
779 if ( GetNativeControlRegion(CTRL_SPINBOX
, PART_SUB_EDIT
,
780 aArea
, 0, aControlValue
, rtl::OUString(), aBound
, aContent
) )
782 // convert back from border space to local coordinates
783 aPoint
= pBorder
->ScreenToOutputPixel( OutputToScreenPixel( aPoint
) );
784 aContent
.Move(-aPoint
.X(), -aPoint
.Y());
786 // use the themes drop down size
787 mpEdit
->SetPosPixel( aContent
.TopLeft() );
788 bSubEditPositioned
= true;
789 aSize
= aContent
.GetSize();
793 if ( maUpperRect
.IsEmpty() )
795 DBG_ASSERT( !maDropDownRect
.IsEmpty(), "SpinField::Resize: SPIN && DROPDOWN, but all empty rects?" );
796 aSize
.Width() = maDropDownRect
.Left();
799 aSize
.Width() = maUpperRect
.Left();
803 if( ! bSubEditPositioned
)
805 // this moves our sub edit if RTL gets switched
806 mpEdit
->SetPosPixel( Point() );
808 mpEdit
->SetSizePixel( aSize
);
810 if ( GetStyle() & WB_SPIN
)
811 Invalidate( Rectangle( maUpperRect
.TopLeft(), maLowerRect
.BottomRight() ) );
812 if ( GetStyle() & WB_DROPDOWN
)
813 Invalidate( maDropDownRect
);
817 // -----------------------------------------------------------------------
819 void SpinField::StateChanged( StateChangedType nType
)
821 Edit::StateChanged( nType
);
823 if ( nType
== STATE_CHANGE_ENABLE
)
825 if ( mbSpin
|| ( GetStyle() & WB_DROPDOWN
) )
827 mpEdit
->Enable( IsEnabled() );
831 Invalidate( maLowerRect
);
832 Invalidate( maUpperRect
);
834 if ( GetStyle() & WB_DROPDOWN
)
835 Invalidate( maDropDownRect
);
838 else if ( nType
== STATE_CHANGE_STYLE
)
840 if ( GetStyle() & WB_REPEAT
)
845 else if ( nType
== STATE_CHANGE_ZOOM
)
849 mpEdit
->SetZoom( GetZoom() );
852 else if ( nType
== STATE_CHANGE_CONTROLFONT
)
855 mpEdit
->SetControlFont( GetControlFont() );
856 ImplInitSettings( TRUE
, FALSE
, FALSE
);
859 else if ( nType
== STATE_CHANGE_CONTROLFOREGROUND
)
862 mpEdit
->SetControlForeground( GetControlForeground() );
863 ImplInitSettings( FALSE
, TRUE
, FALSE
);
866 else if ( nType
== STATE_CHANGE_CONTROLBACKGROUND
)
869 mpEdit
->SetControlBackground( GetControlBackground() );
870 ImplInitSettings( FALSE
, FALSE
, TRUE
);
873 else if( nType
== STATE_CHANGE_MIRRORING
)
876 mpEdit
->StateChanged( STATE_CHANGE_MIRRORING
);
881 // -----------------------------------------------------------------------
883 void SpinField::DataChanged( const DataChangedEvent
& rDCEvt
)
885 Edit::DataChanged( rDCEvt
);
887 if ( (rDCEvt
.GetType() == DATACHANGED_SETTINGS
) &&
888 (rDCEvt
.GetFlags() & SETTINGS_STYLE
) )
895 // -----------------------------------------------------------------------
897 Rectangle
* SpinField::ImplFindPartRect( const Point
& rPt
)
899 if( maUpperRect
.IsInside( rPt
) )
901 else if( maLowerRect
.IsInside( rPt
) )
907 long SpinField::PreNotify( NotifyEvent
& rNEvt
)
910 const MouseEvent
* pMouseEvt
= NULL
;
912 if( (rNEvt
.GetType() == EVENT_MOUSEMOVE
) && (pMouseEvt
= rNEvt
.GetMouseEvent()) != NULL
)
914 if( !pMouseEvt
->GetButtons() && !pMouseEvt
->IsSynthetic() && !pMouseEvt
->IsModifierChanged() )
916 // trigger redraw if mouse over state has changed
917 if( IsNativeControlSupported(CTRL_SPINBOX
, PART_ENTIRE_CONTROL
) ||
918 IsNativeControlSupported(CTRL_SPINBOX
, PART_ALL_BUTTONS
) )
920 Rectangle
* pRect
= ImplFindPartRect( GetPointerPosPixel() );
921 Rectangle
* pLastRect
= ImplFindPartRect( GetLastPointerPosPixel() );
922 if( pRect
!= pLastRect
|| (pMouseEvt
->IsLeaveWindow() || pMouseEvt
->IsEnterWindow()) )
924 // FIXME: this is currently only on aqua
925 // check for other platforms that need similar handling
926 if( ImplGetSVData()->maNWFData
.mbNoFocusRects
&&
927 IsNativeWidgetEnabled() &&
928 IsNativeControlSupported( CTRL_EDITBOX
, PART_ENTIRE_CONTROL
) )
930 ImplInvalidateOutermostBorder( this );
935 Region
aRgn( GetActiveClipRegion() );
938 SetClipRegion( *pLastRect
);
940 SetClipRegion( aRgn
);
944 SetClipRegion( *pRect
);
946 SetClipRegion( aRgn
);
954 return nDone
? nDone
: Edit::PreNotify(rNEvt
);
957 // -----------------------------------------------------------------------
959 void SpinField::EndDropDown()
961 mbInDropDown
= FALSE
;
962 Paint( Rectangle( Point(), GetOutputSizePixel() ) );
965 // -----------------------------------------------------------------------
967 BOOL
SpinField::ShowDropDown( BOOL
)
972 // -----------------------------------------------------------------------
974 Size
SpinField::CalcMinimumSize() const
976 Size aSz
= Edit::CalcMinimumSize();
978 if ( GetStyle() & WB_DROPDOWN
)
979 aSz
.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
980 if ( GetStyle() & WB_SPIN
)
981 aSz
.Width() += maUpperRect
.GetWidth();
986 // -----------------------------------------------------------------------
988 Size
SpinField::GetOptimalSize(WindowSizeType eType
) const
991 case WINDOWSIZE_MINIMUM
:
992 return CalcMinimumSize();
994 return Edit::GetOptimalSize( eType
);
998 // -----------------------------------------------------------------------
1000 Size
SpinField::CalcSize( USHORT nChars
) const
1002 Size aSz
= Edit::CalcSize( nChars
);
1004 if ( GetStyle() & WB_DROPDOWN
)
1005 aSz
.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
1006 if ( GetStyle() & WB_SPIN
)
1007 aSz
.Width() += GetSettings().GetStyleSettings().GetSpinSize();
1012 // --------------------------------------------------------------------
1014 IMPL_LINK( SpinField
, ImplTimeout
, Timer
*, pTimer
)
1016 if ( pTimer
->GetTimeout() == GetSettings().GetMouseSettings().GetButtonStartRepeat() )
1018 pTimer
->SetTimeout( GetSettings().GetMouseSettings().GetButtonRepeat() );
1031 // -----------------------------------------------------------------------
1033 void SpinField::Draw( OutputDevice
* pDev
, const Point
& rPos
, const Size
& rSize
, ULONG nFlags
)
1035 Edit::Draw( pDev
, rPos
, rSize
, nFlags
);
1037 WinBits nFieldStyle
= GetStyle();
1038 if ( !(nFlags
& WINDOW_DRAW_NOCONTROLS
) && ( nFieldStyle
& (WB_SPIN
|WB_DROPDOWN
) ) )
1040 Point aPos
= pDev
->LogicToPixel( rPos
);
1041 Size aSize
= pDev
->LogicToPixel( rSize
);
1042 OutDevType eOutDevType
= pDev
->GetOutDevType();
1043 AllSettings aOldSettings
= pDev
->GetSettings();
1048 if ( eOutDevType
== OUTDEV_PRINTER
)
1050 StyleSettings aStyleSettings
= aOldSettings
.GetStyleSettings();
1051 aStyleSettings
.SetFaceColor( COL_LIGHTGRAY
);
1052 aStyleSettings
.SetButtonTextColor( COL_BLACK
);
1053 AllSettings
aSettings( aOldSettings
);
1054 aSettings
.SetStyleSettings( aStyleSettings
);
1055 pDev
->SetSettings( aSettings
);
1058 Rectangle aDD
, aUp
, aDown
;
1059 ImplCalcButtonAreas( pDev
, aSize
, aDD
, aUp
, aDown
);
1060 aDD
.Move( aPos
.X(), aPos
.Y() );
1061 aUp
.Move( aPos
.X(), aPos
.Y() );
1063 aDown
.Move( aPos
.X(), aPos
.Y() );
1065 Color aButtonTextColor
;
1066 if ( ( nFlags
& WINDOW_DRAW_MONO
) || ( eOutDevType
== OUTDEV_PRINTER
) )
1067 aButtonTextColor
= Color( COL_BLACK
);
1069 aButtonTextColor
= GetSettings().GetStyleSettings().GetButtonTextColor();
1071 if ( GetStyle() & WB_DROPDOWN
)
1073 DecorationView
aView( pDev
);
1074 USHORT nStyle
= BUTTON_DRAW_NOLIGHTBORDER
;
1075 Rectangle aInnerRect
= aView
.DrawButton( aDD
, nStyle
);
1076 SymbolType eSymbol
= SYMBOL_SPIN_DOWN
;
1077 if ( GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_SPINUPDOWN
)
1078 eSymbol
= SYMBOL_SPIN_UPDOWN
;
1080 nStyle
= ( IsEnabled() || ( nFlags
& WINDOW_DRAW_NODISABLE
) ) ? 0 : SYMBOL_DRAW_DISABLE
;
1081 aView
.DrawSymbol( aInnerRect
, eSymbol
, aButtonTextColor
, nStyle
);
1084 if ( GetStyle() & WB_SPIN
)
1086 ImplDrawSpinButton( pDev
, aUp
, aDown
, FALSE
, FALSE
, TRUE
, TRUE
);
1090 pDev
->SetSettings( aOldSettings
);