1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
23 #include "vcl/event.hxx"
24 #include "vcl/decoview.hxx"
26 #include "vcl/spinfld.hxx"
28 #include "controldata.hxx"
31 // =======================================================================
35 void ImplGetSpinbuttonValue( Window
*pWin
, const Rectangle
& rUpperRect
,
36 const Rectangle
& rLowerRect
,
37 sal_Bool bUpperIn
, sal_Bool bLowerIn
,
38 sal_Bool bUpperEnabled
, sal_Bool bLowerEnabled
, sal_Bool bHorz
,
39 SpinbuttonValue
& rValue
)
41 // convert spinbutton data to a SpinbuttonValue structure for native painting
43 rValue
.maUpperRect
= rUpperRect
;
44 rValue
.maLowerRect
= rLowerRect
;
46 Point aPointerPos
= pWin
->GetPointerPosPixel();
48 ControlState nState
= CTRL_STATE_ENABLED
;
50 nState
|= CTRL_STATE_PRESSED
;
51 if ( !pWin
->IsEnabled() || !bUpperEnabled
)
52 nState
&= ~CTRL_STATE_ENABLED
;
53 if ( pWin
->HasFocus() )
54 nState
|= CTRL_STATE_FOCUSED
;
55 if( pWin
->IsMouseOver() && rUpperRect
.IsInside( aPointerPos
) )
56 nState
|= CTRL_STATE_ROLLOVER
;
57 rValue
.mnUpperState
= nState
;
59 nState
= CTRL_STATE_ENABLED
;
61 nState
|= CTRL_STATE_PRESSED
;
62 if ( !pWin
->IsEnabled() || !bLowerEnabled
)
63 nState
&= ~CTRL_STATE_ENABLED
;
64 if ( pWin
->HasFocus() )
65 nState
|= CTRL_STATE_FOCUSED
;
66 // for overlapping spins: highlight only one
67 if( pWin
->IsMouseOver() && rLowerRect
.IsInside( aPointerPos
) &&
68 !rUpperRect
.IsInside( aPointerPos
) )
69 nState
|= CTRL_STATE_ROLLOVER
;
70 rValue
.mnLowerState
= nState
;
72 rValue
.mnUpperPart
= bHorz
? PART_BUTTON_LEFT
: PART_BUTTON_UP
;
73 rValue
.mnLowerPart
= bHorz
? PART_BUTTON_RIGHT
: PART_BUTTON_DOWN
;
77 sal_Bool
ImplDrawNativeSpinfield( Window
*pWin
, const SpinbuttonValue
& rSpinbuttonValue
)
79 sal_Bool bNativeOK
= sal_False
;
81 if( pWin
->IsNativeControlSupported(CTRL_SPINBOX
, PART_ENTIRE_CONTROL
) &&
82 // there is just no useful native support for spinfields with dropdown
83 !(pWin
->GetStyle() & WB_DROPDOWN
) )
85 if( pWin
->IsNativeControlSupported(CTRL_SPINBOX
, rSpinbuttonValue
.mnUpperPart
) &&
86 pWin
->IsNativeControlSupported(CTRL_SPINBOX
, rSpinbuttonValue
.mnLowerPart
) )
88 // only paint the embedded spin buttons, all buttons are painted at once
89 bNativeOK
= pWin
->DrawNativeControl( CTRL_SPINBOX
, PART_ALL_BUTTONS
, Rectangle(), CTRL_STATE_ENABLED
,
90 rSpinbuttonValue
, OUString() );
94 // paint the spinbox as a whole, use borderwindow to have proper clipping
95 Window
*pBorder
= pWin
->GetWindow( WINDOW_BORDER
);
97 // to not overwrite everything, set the button region as clipregion to the border window
98 Rectangle
aClipRect( rSpinbuttonValue
.maLowerRect
);
99 aClipRect
.Union( rSpinbuttonValue
.maUpperRect
);
101 // convert from screen space to borderwin space
102 aClipRect
.SetPos( pBorder
->ScreenToOutputPixel(pWin
->OutputToScreenPixel(aClipRect
.TopLeft())) );
104 Region
oldRgn( pBorder
->GetClipRegion() );
105 pBorder
->SetClipRegion( Region( aClipRect
) );
108 Size
aSize( pBorder
->GetOutputSizePixel() ); // the size of the border window, i.e., the whole control
109 Rectangle aBound
, aContent
;
110 Rectangle
aNatRgn( aPt
, aSize
);
111 if( ! ImplGetSVData()->maNWFData
.mbCanDrawWidgetAnySize
&&
112 pBorder
->GetNativeControlRegion( CTRL_SPINBOX
, PART_ENTIRE_CONTROL
,
113 aNatRgn
, 0, rSpinbuttonValue
, OUString(), aBound
, aContent
) )
115 aSize
= aContent
.GetSize();
118 Rectangle
aRgn( aPt
, aSize
);
119 bNativeOK
= pBorder
->DrawNativeControl( CTRL_SPINBOX
, PART_ENTIRE_CONTROL
, aRgn
, CTRL_STATE_ENABLED
,
120 rSpinbuttonValue
, OUString() );
122 pBorder
->SetClipRegion(Region(oldRgn
));
128 sal_Bool
ImplDrawNativeSpinbuttons( Window
*pWin
, const SpinbuttonValue
& rSpinbuttonValue
)
130 sal_Bool bNativeOK
= sal_False
;
132 if( pWin
->IsNativeControlSupported(CTRL_SPINBUTTONS
, PART_ENTIRE_CONTROL
) )
134 // only paint the standalone spin buttons, all buttons are painted at once
135 bNativeOK
= pWin
->DrawNativeControl( CTRL_SPINBUTTONS
, PART_ALL_BUTTONS
, Rectangle(), CTRL_STATE_ENABLED
,
136 rSpinbuttonValue
, OUString() );
143 void ImplDrawSpinButton( OutputDevice
* pOutDev
,
144 const Rectangle
& rUpperRect
,
145 const Rectangle
& rLowerRect
,
146 sal_Bool bUpperIn
, sal_Bool bLowerIn
,
147 sal_Bool bUpperEnabled
, sal_Bool bLowerEnabled
, sal_Bool bHorz
, sal_Bool bMirrorHorz
)
149 DecorationView
aDecoView( pOutDev
);
151 sal_uInt16 nStyle
= BUTTON_DRAW_NOLEFTLIGHTBORDER
;
152 sal_uInt16 nSymStyle
= 0;
154 SymbolType eType1
, eType2
;
156 const StyleSettings
& rStyleSettings
= pOutDev
->GetSettings().GetStyleSettings();
157 if ( rStyleSettings
.GetOptions() & STYLE_OPTION_SPINARROW
)
159 // arrows are only use in OS/2 look
162 eType1
= bMirrorHorz
? SYMBOL_ARROW_RIGHT
: SYMBOL_ARROW_LEFT
;
163 eType2
= bMirrorHorz
? SYMBOL_ARROW_LEFT
: SYMBOL_ARROW_RIGHT
;
167 eType1
= SYMBOL_ARROW_UP
;
168 eType2
= SYMBOL_ARROW_DOWN
;
175 eType1
= bMirrorHorz
? SYMBOL_SPIN_RIGHT
: SYMBOL_SPIN_LEFT
;
176 eType2
= bMirrorHorz
? SYMBOL_SPIN_LEFT
: SYMBOL_SPIN_RIGHT
;
180 eType1
= SYMBOL_SPIN_UP
;
181 eType2
= SYMBOL_SPIN_DOWN
;
185 // draw upper/left Button
186 sal_uInt16 nTempStyle
= nStyle
;
188 nTempStyle
|= BUTTON_DRAW_PRESSED
;
190 sal_Bool bNativeOK
= sal_False
;
193 if( pOutDev
->GetOutDevType() == OUTDEV_WINDOW
)
195 Window
*pWin
= (Window
*) pOutDev
;
197 // are we drawing standalone spin buttons or members of a spinfield ?
198 ControlType aControl
= CTRL_SPINBUTTONS
;
199 switch( pWin
->GetType() )
202 case WINDOW_MULTILINEEDIT
:
203 case WINDOW_PATTERNFIELD
:
204 case WINDOW_METRICFIELD
:
205 case WINDOW_CURRENCYFIELD
:
206 case WINDOW_DATEFIELD
:
207 case WINDOW_TIMEFIELD
:
208 case WINDOW_LONGCURRENCYFIELD
:
209 case WINDOW_NUMERICFIELD
:
210 case WINDOW_SPINFIELD
:
211 aControl
= CTRL_SPINBOX
;
214 aControl
= CTRL_SPINBUTTONS
;
218 SpinbuttonValue aValue
;
219 ImplGetSpinbuttonValue( pWin
, rUpperRect
, rLowerRect
,
220 bUpperIn
, bLowerIn
, bUpperEnabled
, bLowerEnabled
,
223 if( aControl
== CTRL_SPINBOX
)
224 bNativeOK
= ImplDrawNativeSpinfield( pWin
, aValue
);
225 else if( aControl
== CTRL_SPINBUTTONS
)
226 bNativeOK
= ImplDrawNativeSpinbuttons( pWin
, aValue
);
230 aUpRect
= aDecoView
.DrawButton( rUpperRect
, nTempStyle
);
232 // draw lower/right Button
234 nStyle
|= BUTTON_DRAW_PRESSED
;
237 aLowRect
= aDecoView
.DrawButton( rLowerRect
, nStyle
);
239 // make use of additional default edge
249 // draw into the edge, so that something is visible if the rectangle is too small
250 if ( aUpRect
.GetHeight() < 4 )
258 // calculate Symbol size
259 long nTempSize1
= aUpRect
.GetWidth();
260 long nTempSize2
= aLowRect
.GetWidth();
261 if ( std::abs( nTempSize1
-nTempSize2
) == 1 )
263 if ( nTempSize1
> nTempSize2
)
268 nTempSize1
= aUpRect
.GetHeight();
269 nTempSize2
= aLowRect
.GetHeight();
270 if ( std::abs( nTempSize1
-nTempSize2
) == 1 )
272 if ( nTempSize1
> nTempSize2
)
278 nTempStyle
= nSymStyle
;
279 if ( !bUpperEnabled
)
280 nTempStyle
|= SYMBOL_DRAW_DISABLE
;
282 aDecoView
.DrawSymbol( aUpRect
, eType1
, rStyleSettings
.GetButtonTextColor(), nTempStyle
);
284 if ( !bLowerEnabled
)
285 nSymStyle
|= SYMBOL_DRAW_DISABLE
;
287 aDecoView
.DrawSymbol( aLowRect
, eType2
, rStyleSettings
.GetButtonTextColor(), nSymStyle
);
290 // =======================================================================
292 void SpinField::ImplInitSpinFieldData()
296 mbRepeat
= sal_False
;
297 mbUpperIn
= sal_False
;
298 mbLowerIn
= sal_False
;
299 mbInitialUp
= sal_False
;
300 mbInitialDown
= sal_False
;
301 mbNoSelect
= sal_False
;
302 mbInDropDown
= sal_False
;
305 // --------------------------------------------------------------------
307 void SpinField::ImplInit( Window
* pParent
, WinBits nWinStyle
)
309 Edit::ImplInit( pParent
, nWinStyle
);
311 if ( nWinStyle
& (WB_SPIN
|WB_DROPDOWN
) )
315 // Some themes want external spin buttons, therefore the main
316 // spinfield should not overdraw the border between its encapsulated
317 // edit field and the spin buttons
318 if ( (nWinStyle
& WB_SPIN
) && ImplUseNativeBorder( nWinStyle
) )
321 mpEdit
= new Edit( this, WB_NOBORDER
);
322 mpEdit
->SetBackground();
325 mpEdit
= new Edit( this, WB_NOBORDER
);
327 mpEdit
->EnableRTL( sal_False
);
328 mpEdit
->SetPosPixel( Point() );
330 SetSubEdit( mpEdit
);
332 maRepeatTimer
.SetTimeoutHdl( LINK( this, SpinField
, ImplTimeout
) );
333 maRepeatTimer
.SetTimeout( GetSettings().GetMouseSettings().GetButtonStartRepeat() );
334 if ( nWinStyle
& WB_REPEAT
)
337 SetCompoundControl( sal_True
);
341 // --------------------------------------------------------------------
343 SpinField::SpinField( WindowType nTyp
) :
346 ImplInitSpinFieldData();
349 // --------------------------------------------------------------------
351 SpinField::SpinField( Window
* pParent
, WinBits nWinStyle
) :
352 Edit( WINDOW_SPINFIELD
)
354 ImplInitSpinFieldData();
355 ImplInit( pParent
, nWinStyle
);
358 SpinField::SpinField( Window
* pParent
, const ResId
& rResId
) :
359 Edit( WINDOW_SPINFIELD
)
361 ImplInitSpinFieldData();
362 rResId
.SetRT( RSC_SPINFIELD
);
363 WinBits nStyle
= ImplInitRes( rResId
);
364 ImplInit( pParent
, nStyle
);
365 ImplLoadRes( rResId
);
367 if ( !(nStyle
& WB_HIDE
) )
371 // --------------------------------------------------------------------
373 SpinField::~SpinField()
378 // --------------------------------------------------------------------
382 ImplCallEventListenersAndHandler( VCLEVENT_SPINFIELD_UP
, maUpHdlLink
, this );
385 // --------------------------------------------------------------------
387 void SpinField::Down()
389 ImplCallEventListenersAndHandler( VCLEVENT_SPINFIELD_DOWN
, maDownHdlLink
, this );
392 // --------------------------------------------------------------------
394 void SpinField::First()
396 ImplCallEventListenersAndHandler( VCLEVENT_SPINFIELD_FIRST
, maFirstHdlLink
, this );
399 // --------------------------------------------------------------------
401 void SpinField::Last()
403 ImplCallEventListenersAndHandler( VCLEVENT_SPINFIELD_LAST
, maLastHdlLink
, this );
406 // --------------------------------------------------------------------
408 void SpinField::MouseButtonDown( const MouseEvent
& rMEvt
)
410 if ( !HasFocus() && ( !mpEdit
|| !mpEdit
->HasFocus() ) )
412 mbNoSelect
= sal_True
;
418 if ( maUpperRect
.IsInside( rMEvt
.GetPosPixel() ) )
420 mbUpperIn
= sal_True
;
421 mbInitialUp
= sal_True
;
422 Invalidate( maUpperRect
);
424 else if ( maLowerRect
.IsInside( rMEvt
.GetPosPixel() ) )
426 mbLowerIn
= sal_True
;
427 mbInitialDown
= sal_True
;
428 Invalidate( maLowerRect
);
430 else if ( maDropDownRect
.IsInside( rMEvt
.GetPosPixel() ) )
432 // put DropDownButton to the right
433 mbInDropDown
= ShowDropDown( mbInDropDown
? sal_False
: sal_True
);
434 Paint( Rectangle( Point(), GetOutputSizePixel() ) );
437 if ( mbUpperIn
|| mbLowerIn
)
442 maRepeatTimer
.Start();
447 Edit::MouseButtonDown( rMEvt
);
450 // --------------------------------------------------------------------
452 void SpinField::MouseButtonUp( const MouseEvent
& rMEvt
)
455 mbInitialUp
= mbInitialDown
= sal_False
;
456 maRepeatTimer
.Stop();
457 maRepeatTimer
.SetTimeout( GetSettings().GetMouseSettings().GetButtonStartRepeat() );
461 mbUpperIn
= sal_False
;
462 Invalidate( maUpperRect
);
466 else if ( mbLowerIn
)
468 mbLowerIn
= sal_False
;
469 Invalidate( maLowerRect
);
474 Edit::MouseButtonUp( rMEvt
);
477 // --------------------------------------------------------------------
479 void SpinField::MouseMove( const MouseEvent
& rMEvt
)
481 if ( rMEvt
.IsLeft() )
485 sal_Bool bNewUpperIn
= maUpperRect
.IsInside( rMEvt
.GetPosPixel() );
486 if ( bNewUpperIn
!= mbUpperIn
)
491 maRepeatTimer
.Start();
494 maRepeatTimer
.Stop();
496 mbUpperIn
= bNewUpperIn
;
497 Invalidate( maUpperRect
);
501 else if ( mbInitialDown
)
503 sal_Bool bNewLowerIn
= maLowerRect
.IsInside( rMEvt
.GetPosPixel() );
504 if ( bNewLowerIn
!= mbLowerIn
)
509 maRepeatTimer
.Start();
512 maRepeatTimer
.Stop();
514 mbLowerIn
= bNewLowerIn
;
515 Invalidate( maLowerRect
);
521 Edit::MouseMove( rMEvt
);
524 // --------------------------------------------------------------------
526 long SpinField::Notify( NotifyEvent
& rNEvt
)
529 if( rNEvt
.GetType() == EVENT_KEYINPUT
)
531 const KeyEvent
& rKEvt
= *rNEvt
.GetKeyEvent();
534 sal_uInt16 nMod
= rKEvt
.GetKeyCode().GetModifier();
535 switch ( rKEvt
.GetKeyCode().GetCode() )
553 else if ( ( nMod
== KEY_MOD2
) && !mbInDropDown
&& ( GetStyle() & WB_DROPDOWN
) )
555 mbInDropDown
= ShowDropDown( sal_True
);
556 Paint( Rectangle( Point(), GetOutputSizePixel() ) );
583 if ( rNEvt
.GetType() == EVENT_COMMAND
)
585 if ( ( rNEvt
.GetCommandEvent()->GetCommand() == COMMAND_WHEEL
) && !IsReadOnly() )
587 sal_uInt16
nWheelBehavior( GetSettings().GetMouseSettings().GetWheelBehavior() );
588 if ( ( nWheelBehavior
== MOUSE_WHEEL_ALWAYS
)
589 || ( ( nWheelBehavior
== MOUSE_WHEEL_FOCUS_ONLY
)
590 && HasChildPathFocus()
594 const CommandWheelData
* pData
= rNEvt
.GetCommandEvent()->GetWheelData();
595 if ( pData
->GetMode() == COMMAND_WHEEL_SCROLL
)
597 if ( pData
->GetDelta() < 0L )
605 nDone
= 0; // don't eat this event, let the default handling happen (i.e. scroll the context)
609 return nDone
? nDone
: Edit::Notify( rNEvt
);
612 // --------------------------------------------------------------------
614 void SpinField::Command( const CommandEvent
& rCEvt
)
616 Edit::Command( rCEvt
);
619 // --------------------------------------------------------------------
621 void SpinField::FillLayoutData() const
625 mpControlData
->mpLayoutData
= new vcl::ControlLayoutData();
626 AppendLayoutData( *GetSubEdit() );
627 GetSubEdit()->SetLayoutDataParent( this );
630 Edit::FillLayoutData();
633 // --------------------------------------------------------------------
635 void SpinField::Paint( const Rectangle
& rRect
)
639 sal_Bool bEnable
= IsEnabled();
640 ImplDrawSpinButton( this, maUpperRect
, maLowerRect
,
641 mbUpperIn
, mbLowerIn
, bEnable
, bEnable
);
644 if ( GetStyle() & WB_DROPDOWN
)
646 DecorationView
aView( this );
648 sal_uInt16 nStyle
= BUTTON_DRAW_NOLIGHTBORDER
;
650 nStyle
|= BUTTON_DRAW_PRESSED
;
651 Rectangle aInnerRect
= aView
.DrawButton( maDropDownRect
, nStyle
);
653 SymbolType eSymbol
= SYMBOL_SPIN_DOWN
;
654 if ( GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_SPINUPDOWN
)
655 eSymbol
= SYMBOL_SPIN_UPDOWN
;
657 nStyle
= IsEnabled() ? 0 : SYMBOL_DRAW_DISABLE
;
658 aView
.DrawSymbol( aInnerRect
, eSymbol
, GetSettings().GetStyleSettings().GetButtonTextColor(), nStyle
);
661 Edit::Paint( rRect
);
664 // --------------------------------------------------------------------
666 void SpinField::ImplCalcButtonAreas( OutputDevice
* pDev
, const Size
& rOutSz
, Rectangle
& rDDArea
, Rectangle
& rSpinUpArea
, Rectangle
& rSpinDownArea
)
668 const StyleSettings
& rStyleSettings
= pDev
->GetSettings().GetStyleSettings();
673 if ( GetStyle() & WB_DROPDOWN
)
675 long nW
= rStyleSettings
.GetScrollBarSize();
676 nW
= GetDrawPixel( pDev
, nW
);
677 aDropDownSize
= Size( CalcZoom( nW
), aSize
.Height() );
678 aSize
.Width() -= aDropDownSize
.Width();
679 rDDArea
= Rectangle( Point( aSize
.Width(), 0 ), aDropDownSize
);
685 // calcuate sizes according to the height
686 if ( GetStyle() & WB_SPIN
)
688 long nBottom1
= aSize
.Height()/2;
689 long nBottom2
= aSize
.Height()-1;
690 long nTop2
= nBottom1
;
692 if ( !(aSize
.Height() & 0x01) )
695 sal_Bool bNativeRegionOK
= sal_False
;
696 Rectangle aContentUp
, aContentDown
;
698 if ( (pDev
->GetOutDevType() == OUTDEV_WINDOW
) &&
699 // there is just no useful native support for spinfields with dropdown
700 ! (GetStyle() & WB_DROPDOWN
) &&
701 IsNativeControlSupported(CTRL_SPINBOX
, PART_ENTIRE_CONTROL
) )
703 Window
*pWin
= (Window
*) pDev
;
704 Window
*pBorder
= pWin
->GetWindow( WINDOW_BORDER
);
706 // get the system's spin button size
707 ImplControlValue aControlValue
;
711 // use the full extent of the control
712 Rectangle
aArea( aPoint
, pBorder
->GetOutputSizePixel() );
715 pWin
->GetNativeControlRegion(CTRL_SPINBOX
, PART_BUTTON_UP
,
716 aArea
, 0, aControlValue
, OUString(), aBound
, aContentUp
) &&
717 pWin
->GetNativeControlRegion(CTRL_SPINBOX
, PART_BUTTON_DOWN
,
718 aArea
, 0, aControlValue
, OUString(), aBound
, aContentDown
);
720 if( bNativeRegionOK
)
722 // convert back from border space to local coordinates
723 aPoint
= pBorder
->ScreenToOutputPixel( pWin
->OutputToScreenPixel( aPoint
) );
724 aContentUp
.Move(-aPoint
.X(), -aPoint
.Y());
725 aContentDown
.Move(-aPoint
.X(), -aPoint
.Y());
729 if( bNativeRegionOK
)
731 rSpinUpArea
= aContentUp
;
732 rSpinDownArea
= aContentDown
;
736 aSize
.Width() -= CalcZoom( GetDrawPixel( pDev
, rStyleSettings
.GetSpinSize() ) );
738 rSpinUpArea
= Rectangle( aSize
.Width(), nTop1
, rOutSz
.Width()-aDropDownSize
.Width()-1, nBottom1
);
739 rSpinDownArea
= Rectangle( rSpinUpArea
.Left(), nTop2
, rSpinUpArea
.Right(), nBottom2
);
744 rSpinUpArea
.SetEmpty();
745 rSpinDownArea
.SetEmpty();
749 // --------------------------------------------------------------------
751 void SpinField::Resize()
756 Size aSize
= GetOutputSizePixel();
757 bool bSubEditPositioned
= false;
759 if ( GetStyle() & (WB_SPIN
|WB_DROPDOWN
) )
761 ImplCalcButtonAreas( this, aSize
, maDropDownRect
, maUpperRect
, maLowerRect
);
763 ImplControlValue aControlValue
;
765 Rectangle aContent
, aBound
;
767 // use the full extent of the control
768 Window
*pBorder
= GetWindow( WINDOW_BORDER
);
769 Rectangle
aArea( aPoint
, pBorder
->GetOutputSizePixel() );
771 // adjust position and size of the edit field
772 if ( GetNativeControlRegion(CTRL_SPINBOX
, PART_SUB_EDIT
,
773 aArea
, 0, aControlValue
, OUString(), aBound
, aContent
) )
775 // convert back from border space to local coordinates
776 aPoint
= pBorder
->ScreenToOutputPixel( OutputToScreenPixel( aPoint
) );
777 aContent
.Move(-aPoint
.X(), -aPoint
.Y());
779 // use the themes drop down size
780 mpEdit
->SetPosPixel( aContent
.TopLeft() );
781 bSubEditPositioned
= true;
782 aSize
= aContent
.GetSize();
786 if ( maUpperRect
.IsEmpty() )
788 DBG_ASSERT( !maDropDownRect
.IsEmpty(), "SpinField::Resize: SPIN && DROPDOWN, but all empty rects?" );
789 aSize
.Width() = maDropDownRect
.Left();
792 aSize
.Width() = maUpperRect
.Left();
796 if( ! bSubEditPositioned
)
798 // this moves our sub edit if RTL gets switched
799 mpEdit
->SetPosPixel( Point() );
801 mpEdit
->SetSizePixel( aSize
);
803 if ( GetStyle() & WB_SPIN
)
804 Invalidate( Rectangle( maUpperRect
.TopLeft(), maLowerRect
.BottomRight() ) );
805 if ( GetStyle() & WB_DROPDOWN
)
806 Invalidate( maDropDownRect
);
810 // -----------------------------------------------------------------------
812 void SpinField::StateChanged( StateChangedType nType
)
814 Edit::StateChanged( nType
);
816 if ( nType
== STATE_CHANGE_ENABLE
)
818 if ( mbSpin
|| ( GetStyle() & WB_DROPDOWN
) )
820 mpEdit
->Enable( IsEnabled() );
824 Invalidate( maLowerRect
);
825 Invalidate( maUpperRect
);
827 if ( GetStyle() & WB_DROPDOWN
)
828 Invalidate( maDropDownRect
);
831 else if ( nType
== STATE_CHANGE_STYLE
)
833 if ( GetStyle() & WB_REPEAT
)
836 mbRepeat
= sal_False
;
838 else if ( nType
== STATE_CHANGE_ZOOM
)
842 mpEdit
->SetZoom( GetZoom() );
845 else if ( nType
== STATE_CHANGE_CONTROLFONT
)
848 mpEdit
->SetControlFont( GetControlFont() );
849 ImplInitSettings( sal_True
, sal_False
, sal_False
);
852 else if ( nType
== STATE_CHANGE_CONTROLFOREGROUND
)
855 mpEdit
->SetControlForeground( GetControlForeground() );
856 ImplInitSettings( sal_False
, sal_True
, sal_False
);
859 else if ( nType
== STATE_CHANGE_CONTROLBACKGROUND
)
862 mpEdit
->SetControlBackground( GetControlBackground() );
863 ImplInitSettings( sal_False
, sal_False
, sal_True
);
866 else if( nType
== STATE_CHANGE_MIRRORING
)
869 mpEdit
->StateChanged( STATE_CHANGE_MIRRORING
);
874 // -----------------------------------------------------------------------
876 void SpinField::DataChanged( const DataChangedEvent
& rDCEvt
)
878 Edit::DataChanged( rDCEvt
);
880 if ( (rDCEvt
.GetType() == DATACHANGED_SETTINGS
) &&
881 (rDCEvt
.GetFlags() & SETTINGS_STYLE
) )
888 // -----------------------------------------------------------------------
890 Rectangle
* SpinField::ImplFindPartRect( const Point
& rPt
)
892 if( maUpperRect
.IsInside( rPt
) )
894 else if( maLowerRect
.IsInside( rPt
) )
900 long SpinField::PreNotify( NotifyEvent
& rNEvt
)
903 const MouseEvent
* pMouseEvt
= NULL
;
905 if( (rNEvt
.GetType() == EVENT_MOUSEMOVE
) && (pMouseEvt
= rNEvt
.GetMouseEvent()) != NULL
)
907 if( !pMouseEvt
->GetButtons() && !pMouseEvt
->IsSynthetic() && !pMouseEvt
->IsModifierChanged() )
909 // trigger redraw if mouse over state has changed
910 if( IsNativeControlSupported(CTRL_SPINBOX
, PART_ENTIRE_CONTROL
) ||
911 IsNativeControlSupported(CTRL_SPINBOX
, PART_ALL_BUTTONS
) )
913 Rectangle
* pRect
= ImplFindPartRect( GetPointerPosPixel() );
914 Rectangle
* pLastRect
= ImplFindPartRect( GetLastPointerPosPixel() );
915 if( pRect
!= pLastRect
|| (pMouseEvt
->IsLeaveWindow() || pMouseEvt
->IsEnterWindow()) )
917 // FIXME: this is currently only on aqua
918 // check for other platforms that need similar handling
919 if( ImplGetSVData()->maNWFData
.mbNoFocusRects
&&
920 IsNativeWidgetEnabled() &&
921 IsNativeControlSupported( CTRL_EDITBOX
, PART_ENTIRE_CONTROL
) )
923 ImplInvalidateOutermostBorder( this );
928 Region
aRgn( GetActiveClipRegion() );
931 SetClipRegion(Region(*pLastRect
));
933 SetClipRegion( aRgn
);
937 SetClipRegion(Region(*pRect
));
939 SetClipRegion( aRgn
);
947 return nDone
? nDone
: Edit::PreNotify(rNEvt
);
950 // -----------------------------------------------------------------------
952 void SpinField::EndDropDown()
954 mbInDropDown
= sal_False
;
955 Paint( Rectangle( Point(), GetOutputSizePixel() ) );
958 // -----------------------------------------------------------------------
960 sal_Bool
SpinField::ShowDropDown( sal_Bool
)
965 Size
SpinField::CalcMinimumSizeForText(const OUString
&rString
) const
967 Size aSz
= Edit::CalcMinimumSizeForText(rString
);
969 if ( GetStyle() & WB_DROPDOWN
)
970 aSz
.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
971 if ( GetStyle() & WB_SPIN
)
973 ImplControlValue aControlValue
;
974 Rectangle
aArea( Point(), Size(100, aSz
.Height()));
975 Rectangle aEntireBound
, aEntireContent
, aEditBound
, aEditContent
;
977 GetNativeControlRegion(CTRL_SPINBOX
, PART_ENTIRE_CONTROL
,
978 aArea
, 0, aControlValue
, OUString(), aEntireBound
, aEntireContent
) &&
979 GetNativeControlRegion(CTRL_SPINBOX
, PART_SUB_EDIT
,
980 aArea
, 0, aControlValue
, OUString(), aEditBound
, aEditContent
)
983 aSz
.Width() += (aEntireContent
.GetWidth() - aEditContent
.GetWidth());
987 aSz
.Width() += maUpperRect
.GetWidth();
994 Size
SpinField::CalcMinimumSize() const
996 return CalcMinimumSizeForText(GetText());
999 // -----------------------------------------------------------------------
1001 Size
SpinField::GetOptimalSize() const
1003 return CalcMinimumSize();
1006 // -----------------------------------------------------------------------
1008 Size
SpinField::CalcSize( sal_uInt16 nChars
) const
1010 Size aSz
= Edit::CalcSize( nChars
);
1012 if ( GetStyle() & WB_DROPDOWN
)
1013 aSz
.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
1014 if ( GetStyle() & WB_SPIN
)
1015 aSz
.Width() += GetSettings().GetStyleSettings().GetSpinSize();
1020 // --------------------------------------------------------------------
1022 IMPL_LINK( SpinField
, ImplTimeout
, Timer
*, pTimer
)
1024 if ( pTimer
->GetTimeout() == GetSettings().GetMouseSettings().GetButtonStartRepeat() )
1026 pTimer
->SetTimeout( GetSettings().GetMouseSettings().GetButtonRepeat() );
1039 // -----------------------------------------------------------------------
1041 void SpinField::Draw( OutputDevice
* pDev
, const Point
& rPos
, const Size
& rSize
, sal_uLong nFlags
)
1043 Edit::Draw( pDev
, rPos
, rSize
, nFlags
);
1045 WinBits nFieldStyle
= GetStyle();
1046 if ( !(nFlags
& WINDOW_DRAW_NOCONTROLS
) && ( nFieldStyle
& (WB_SPIN
|WB_DROPDOWN
) ) )
1048 Point aPos
= pDev
->LogicToPixel( rPos
);
1049 Size aSize
= pDev
->LogicToPixel( rSize
);
1050 OutDevType eOutDevType
= pDev
->GetOutDevType();
1051 AllSettings aOldSettings
= pDev
->GetSettings();
1056 if ( eOutDevType
== OUTDEV_PRINTER
)
1058 StyleSettings aStyleSettings
= aOldSettings
.GetStyleSettings();
1059 aStyleSettings
.SetFaceColor( COL_LIGHTGRAY
);
1060 aStyleSettings
.SetButtonTextColor( COL_BLACK
);
1061 AllSettings
aSettings( aOldSettings
);
1062 aSettings
.SetStyleSettings( aStyleSettings
);
1063 pDev
->SetSettings( aSettings
);
1066 Rectangle aDD
, aUp
, aDown
;
1067 ImplCalcButtonAreas( pDev
, aSize
, aDD
, aUp
, aDown
);
1068 aDD
.Move( aPos
.X(), aPos
.Y() );
1069 aUp
.Move( aPos
.X(), aPos
.Y() );
1071 aDown
.Move( aPos
.X(), aPos
.Y() );
1073 Color aButtonTextColor
;
1074 if ( ( nFlags
& WINDOW_DRAW_MONO
) || ( eOutDevType
== OUTDEV_PRINTER
) )
1075 aButtonTextColor
= Color( COL_BLACK
);
1077 aButtonTextColor
= GetSettings().GetStyleSettings().GetButtonTextColor();
1079 if ( GetStyle() & WB_DROPDOWN
)
1081 DecorationView
aView( pDev
);
1082 sal_uInt16 nStyle
= BUTTON_DRAW_NOLIGHTBORDER
;
1083 Rectangle aInnerRect
= aView
.DrawButton( aDD
, nStyle
);
1084 SymbolType eSymbol
= SYMBOL_SPIN_DOWN
;
1085 if ( GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_SPINUPDOWN
)
1086 eSymbol
= SYMBOL_SPIN_UPDOWN
;
1088 nStyle
= ( IsEnabled() || ( nFlags
& WINDOW_DRAW_NODISABLE
) ) ? 0 : SYMBOL_DRAW_DISABLE
;
1089 aView
.DrawSymbol( aInnerRect
, eSymbol
, aButtonTextColor
, nStyle
);
1092 if ( GetStyle() & WB_SPIN
)
1094 ImplDrawSpinButton( pDev
, aUp
, aDown
, sal_False
, sal_False
, sal_True
, sal_True
);
1098 pDev
->SetSettings( aOldSettings
);
1102 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */