| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_vcl.hxx" |
| |
| #include "tools/rc.h" |
| |
| #include "vcl/event.hxx" |
| #include "vcl/decoview.hxx" |
| #include "vcl/spin.h" |
| #include "vcl/spinfld.hxx" |
| |
| #include "controldata.hxx" |
| #include "svdata.hxx" |
| |
| // ======================================================================= |
| |
| void ImplGetSpinbuttonValue( Window *pWin, const Rectangle& rUpperRect, |
| const Rectangle& rLowerRect, |
| sal_Bool bUpperIn, sal_Bool bLowerIn, |
| sal_Bool bUpperEnabled, sal_Bool bLowerEnabled, sal_Bool bHorz, |
| SpinbuttonValue& rValue ) |
| { |
| // convert spinbutton data to a SpinbuttonValue structure for native painting |
| |
| rValue.maUpperRect = rUpperRect; |
| rValue.maLowerRect = rLowerRect; |
| |
| Point aPointerPos = pWin->GetPointerPosPixel(); |
| |
| ControlState nState = CTRL_STATE_ENABLED; |
| if ( bUpperIn ) |
| nState |= CTRL_STATE_PRESSED; |
| if ( !pWin->IsEnabled() || !bUpperEnabled ) |
| nState &= ~CTRL_STATE_ENABLED; |
| if ( pWin->HasFocus() ) |
| nState |= CTRL_STATE_FOCUSED; |
| if( pWin->IsMouseOver() && rUpperRect.IsInside( aPointerPos ) ) |
| nState |= CTRL_STATE_ROLLOVER; |
| rValue.mnUpperState = nState; |
| |
| nState = CTRL_STATE_ENABLED; |
| if ( bLowerIn ) |
| nState |= CTRL_STATE_PRESSED; |
| if ( !pWin->IsEnabled() || !bLowerEnabled ) |
| nState &= ~CTRL_STATE_ENABLED; |
| if ( pWin->HasFocus() ) |
| nState |= CTRL_STATE_FOCUSED; |
| // for overlapping spins: highlight only one |
| if( pWin->IsMouseOver() && rLowerRect.IsInside( aPointerPos ) && |
| !rUpperRect.IsInside( aPointerPos ) ) |
| nState |= CTRL_STATE_ROLLOVER; |
| rValue.mnLowerState = nState; |
| |
| rValue.mnUpperPart = bHorz ? PART_BUTTON_LEFT : PART_BUTTON_UP; |
| rValue.mnLowerPart = bHorz ? PART_BUTTON_RIGHT : PART_BUTTON_DOWN; |
| } |
| |
| |
| sal_Bool ImplDrawNativeSpinfield( Window *pWin, const SpinbuttonValue& rSpinbuttonValue ) |
| { |
| sal_Bool bNativeOK = sal_False; |
| |
| if( pWin->IsNativeControlSupported(CTRL_SPINBOX, PART_ENTIRE_CONTROL) && |
| // there is just no useful native support for spinfields with dropdown |
| !(pWin->GetStyle() & WB_DROPDOWN) ) |
| { |
| if( pWin->IsNativeControlSupported(CTRL_SPINBOX, rSpinbuttonValue.mnUpperPart) && |
| pWin->IsNativeControlSupported(CTRL_SPINBOX, rSpinbuttonValue.mnLowerPart) ) |
| { |
| // only paint the embedded spin buttons, all buttons are painted at once |
| bNativeOK = pWin->DrawNativeControl( CTRL_SPINBOX, PART_ALL_BUTTONS, Rectangle(), CTRL_STATE_ENABLED, |
| rSpinbuttonValue, rtl::OUString() ); |
| } |
| else |
| { |
| // paint the spinbox as a whole, use borderwindow to have proper clipping |
| Window *pBorder = pWin->GetWindow( WINDOW_BORDER ); |
| |
| // to not overwrite everything, set the button region as clipregion to the border window |
| Rectangle aClipRect( rSpinbuttonValue.maLowerRect ); |
| aClipRect.Union( rSpinbuttonValue.maUpperRect ); |
| |
| // convert from screen space to borderwin space |
| aClipRect.SetPos( pBorder->ScreenToOutputPixel(pWin->OutputToScreenPixel(aClipRect.TopLeft())) ); |
| |
| Region oldRgn( pBorder->GetClipRegion() ); |
| pBorder->SetClipRegion( Region( aClipRect ) ); |
| |
| Point aPt; |
| Size aSize( pBorder->GetOutputSizePixel() ); // the size of the border window, i.e., the whole control |
| Rectangle aBound, aContent; |
| Rectangle aNatRgn( aPt, aSize ); |
| if( ! ImplGetSVData()->maNWFData.mbCanDrawWidgetAnySize && |
| pBorder->GetNativeControlRegion( CTRL_SPINBOX, PART_ENTIRE_CONTROL, |
| aNatRgn, 0, rSpinbuttonValue, rtl::OUString(), aBound, aContent) ) |
| { |
| aSize = aContent.GetSize(); |
| } |
| |
| Rectangle aRgn( aPt, aSize ); |
| bNativeOK = pBorder->DrawNativeControl( CTRL_SPINBOX, PART_ENTIRE_CONTROL, aRgn, CTRL_STATE_ENABLED, |
| rSpinbuttonValue, rtl::OUString() ); |
| |
| pBorder->SetClipRegion( oldRgn ); |
| } |
| } |
| return bNativeOK; |
| } |
| |
| sal_Bool ImplDrawNativeSpinbuttons( Window *pWin, const SpinbuttonValue& rSpinbuttonValue ) |
| { |
| sal_Bool bNativeOK = sal_False; |
| |
| if( pWin->IsNativeControlSupported(CTRL_SPINBUTTONS, PART_ENTIRE_CONTROL) ) |
| { |
| // only paint the standalone spin buttons, all buttons are painted at once |
| bNativeOK = pWin->DrawNativeControl( CTRL_SPINBUTTONS, PART_ALL_BUTTONS, Rectangle(), CTRL_STATE_ENABLED, |
| rSpinbuttonValue, rtl::OUString() ); |
| } |
| return bNativeOK; |
| } |
| |
| void ImplDrawSpinButton( OutputDevice* pOutDev, |
| const Rectangle& rUpperRect, |
| const Rectangle& rLowerRect, |
| sal_Bool bUpperIn, sal_Bool bLowerIn, |
| sal_Bool bUpperEnabled, sal_Bool bLowerEnabled, sal_Bool bHorz, sal_Bool bMirrorHorz ) |
| { |
| DecorationView aDecoView( pOutDev ); |
| |
| sal_uInt16 nStyle = BUTTON_DRAW_NOLEFTLIGHTBORDER; |
| sal_uInt16 nSymStyle = 0; |
| |
| SymbolType eType1, eType2; |
| |
| const StyleSettings& rStyleSettings = pOutDev->GetSettings().GetStyleSettings(); |
| if ( rStyleSettings.GetOptions() & STYLE_OPTION_SPINARROW ) |
| { |
| // arrows are only use in OS/2 look |
| if ( bHorz ) |
| { |
| eType1 = bMirrorHorz ? SYMBOL_ARROW_RIGHT : SYMBOL_ARROW_LEFT; |
| eType2 = bMirrorHorz ? SYMBOL_ARROW_LEFT : SYMBOL_ARROW_RIGHT; |
| } |
| else |
| { |
| eType1 = SYMBOL_ARROW_UP; |
| eType2 = SYMBOL_ARROW_DOWN; |
| } |
| } |
| else |
| { |
| if ( bHorz ) |
| { |
| eType1 = bMirrorHorz ? SYMBOL_SPIN_RIGHT : SYMBOL_SPIN_LEFT; |
| eType2 = bMirrorHorz ? SYMBOL_SPIN_LEFT : SYMBOL_SPIN_RIGHT; |
| } |
| else |
| { |
| eType1 = SYMBOL_SPIN_UP; |
| eType2 = SYMBOL_SPIN_DOWN; |
| } |
| } |
| |
| // Oberen/linken Button malen |
| sal_uInt16 nTempStyle = nStyle; |
| if ( bUpperIn ) |
| nTempStyle |= BUTTON_DRAW_PRESSED; |
| |
| sal_Bool bNativeOK = sal_False; |
| Rectangle aUpRect; |
| |
| if( pOutDev->GetOutDevType() == OUTDEV_WINDOW ) |
| { |
| Window *pWin = (Window*) pOutDev; |
| |
| // are we drawing standalone spin buttons or members of a spinfield ? |
| ControlType aControl = CTRL_SPINBUTTONS; |
| switch( pWin->GetType() ) |
| { |
| case WINDOW_EDIT: |
| case WINDOW_MULTILINEEDIT: |
| case WINDOW_PATTERNFIELD: |
| case WINDOW_METRICFIELD: |
| case WINDOW_CURRENCYFIELD: |
| case WINDOW_DATEFIELD: |
| case WINDOW_TIMEFIELD: |
| case WINDOW_LONGCURRENCYFIELD: |
| case WINDOW_NUMERICFIELD: |
| case WINDOW_SPINFIELD: |
| aControl = CTRL_SPINBOX; |
| break; |
| default: |
| aControl = CTRL_SPINBUTTONS; |
| break; |
| } |
| |
| SpinbuttonValue aValue; |
| ImplGetSpinbuttonValue( pWin, rUpperRect, rLowerRect, |
| bUpperIn, bLowerIn, bUpperEnabled, bLowerEnabled, |
| bHorz, aValue ); |
| |
| if( aControl == CTRL_SPINBOX ) |
| bNativeOK = ImplDrawNativeSpinfield( pWin, aValue ); |
| else if( aControl == CTRL_SPINBUTTONS ) |
| bNativeOK = ImplDrawNativeSpinbuttons( pWin, aValue ); |
| } |
| |
| if( !bNativeOK ) |
| aUpRect = aDecoView.DrawButton( rUpperRect, nTempStyle ); |
| |
| // Unteren/rechten Button malen |
| if ( bLowerIn ) |
| nStyle |= BUTTON_DRAW_PRESSED; |
| Rectangle aLowRect; |
| if( !bNativeOK ) |
| aLowRect = aDecoView.DrawButton( rLowerRect, nStyle ); |
| |
| // Zusaetzliche Default-Kante wollen wir auch ausnutzen |
| aUpRect.Left()--; |
| aUpRect.Top()--; |
| aUpRect.Right()++; |
| aUpRect.Bottom()++; |
| aLowRect.Left()--; |
| aLowRect.Top()--; |
| aLowRect.Right()++; |
| aLowRect.Bottom()++; |
| |
| // Wir malen auch in die Kante rein, damit man etwas erkennen kann, |
| // wenn das Rechteck zu klein ist |
| if ( aUpRect.GetHeight() < 4 ) |
| { |
| aUpRect.Right()++; |
| aUpRect.Bottom()++; |
| aLowRect.Right()++; |
| aLowRect.Bottom()++; |
| } |
| |
| // Symbolgroesse berechnen |
| long nTempSize1 = aUpRect.GetWidth(); |
| long nTempSize2 = aLowRect.GetWidth(); |
| if ( Abs( nTempSize1-nTempSize2 ) == 1 ) |
| { |
| if ( nTempSize1 > nTempSize2 ) |
| aUpRect.Left()++; |
| else |
| aLowRect.Left()++; |
| } |
| nTempSize1 = aUpRect.GetHeight(); |
| nTempSize2 = aLowRect.GetHeight(); |
| if ( Abs( nTempSize1-nTempSize2 ) == 1 ) |
| { |
| if ( nTempSize1 > nTempSize2 ) |
| aUpRect.Top()++; |
| else |
| aLowRect.Top()++; |
| } |
| |
| nTempStyle = nSymStyle; |
| if ( !bUpperEnabled ) |
| nTempStyle |= SYMBOL_DRAW_DISABLE; |
| if( !bNativeOK ) |
| aDecoView.DrawSymbol( aUpRect, eType1, rStyleSettings.GetButtonTextColor(), nTempStyle ); |
| |
| if ( !bLowerEnabled ) |
| nSymStyle |= SYMBOL_DRAW_DISABLE; |
| if( !bNativeOK ) |
| aDecoView.DrawSymbol( aLowRect, eType2, rStyleSettings.GetButtonTextColor(), nSymStyle ); |
| } |
| |
| // ======================================================================= |
| |
| void SpinField::ImplInitSpinFieldData() |
| { |
| mpEdit = NULL; |
| mbSpin = sal_False; |
| mbRepeat = sal_False; |
| mbUpperIn = sal_False; |
| mbLowerIn = sal_False; |
| mbInitialUp = sal_False; |
| mbInitialDown = sal_False; |
| mbNoSelect = sal_False; |
| mbInDropDown = sal_False; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void SpinField::ImplInit( Window* pParent, WinBits nWinStyle ) |
| { |
| Edit::ImplInit( pParent, nWinStyle ); |
| |
| if ( nWinStyle & (WB_SPIN|WB_DROPDOWN) ) |
| { |
| mbSpin = sal_True; |
| |
| // Some themes want external spin buttons, therefore the main |
| // spinfield should not overdraw the border between its encapsulated |
| // edit field and the spin buttons |
| if ( (nWinStyle & WB_SPIN) && ImplUseNativeBorder( nWinStyle ) ) |
| { |
| SetBackground(); |
| mpEdit = new Edit( this, WB_NOBORDER ); |
| mpEdit->SetBackground(); |
| } |
| else |
| mpEdit = new Edit( this, WB_NOBORDER ); |
| |
| mpEdit->EnableRTL( sal_False ); |
| mpEdit->SetPosPixel( Point() ); |
| mpEdit->Show(); |
| SetSubEdit( mpEdit ); |
| |
| maRepeatTimer.SetTimeoutHdl( LINK( this, SpinField, ImplTimeout ) ); |
| maRepeatTimer.SetTimeout( GetSettings().GetMouseSettings().GetButtonStartRepeat() ); |
| if ( nWinStyle & WB_REPEAT ) |
| mbRepeat = sal_True; |
| |
| SetCompoundControl( sal_True ); |
| } |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| SpinField::SpinField( WindowType nTyp ) : |
| Edit( nTyp ) |
| { |
| ImplInitSpinFieldData(); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| SpinField::SpinField( Window* pParent, WinBits nWinStyle ) : |
| Edit( WINDOW_SPINFIELD ) |
| { |
| ImplInitSpinFieldData(); |
| ImplInit( pParent, nWinStyle ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| SpinField::SpinField( Window* pParent, const ResId& rResId ) : |
| Edit( WINDOW_SPINFIELD ) |
| { |
| ImplInitSpinFieldData(); |
| rResId.SetRT( RSC_SPINFIELD ); |
| WinBits nStyle = ImplInitRes( rResId ); |
| ImplInit( pParent, nStyle ); |
| ImplLoadRes( rResId ); |
| |
| if ( !(nStyle & WB_HIDE) ) |
| Show(); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| SpinField::~SpinField() |
| { |
| delete mpEdit; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void SpinField::Up() |
| { |
| ImplCallEventListenersAndHandler( VCLEVENT_SPINFIELD_UP, maUpHdlLink, this ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void SpinField::Down() |
| { |
| ImplCallEventListenersAndHandler( VCLEVENT_SPINFIELD_DOWN, maDownHdlLink, this ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void SpinField::First() |
| { |
| ImplCallEventListenersAndHandler( VCLEVENT_SPINFIELD_FIRST, maFirstHdlLink, this ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void SpinField::Last() |
| { |
| ImplCallEventListenersAndHandler( VCLEVENT_SPINFIELD_LAST, maLastHdlLink, this ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void SpinField::MouseButtonDown( const MouseEvent& rMEvt ) |
| { |
| if ( !HasFocus() && ( !mpEdit || !mpEdit->HasFocus() ) ) |
| { |
| mbNoSelect = sal_True; |
| GrabFocus(); |
| } |
| |
| if ( !IsReadOnly() ) |
| { |
| if ( maUpperRect.IsInside( rMEvt.GetPosPixel() ) ) |
| { |
| mbUpperIn = sal_True; |
| mbInitialUp = sal_True; |
| Invalidate( maUpperRect ); |
| } |
| else if ( maLowerRect.IsInside( rMEvt.GetPosPixel() ) ) |
| { |
| mbLowerIn = sal_True; |
| mbInitialDown = sal_True; |
| Invalidate( maLowerRect ); |
| } |
| else if ( maDropDownRect.IsInside( rMEvt.GetPosPixel() ) ) |
| { |
| // Rechts daneben liegt der DropDownButton: |
| mbInDropDown = ShowDropDown( mbInDropDown ? sal_False : sal_True ); |
| Paint( Rectangle( Point(), GetOutputSizePixel() ) ); |
| } |
| |
| if ( mbUpperIn || mbLowerIn ) |
| { |
| Update(); |
| CaptureMouse(); |
| if ( mbRepeat ) |
| maRepeatTimer.Start(); |
| return; |
| } |
| } |
| |
| Edit::MouseButtonDown( rMEvt ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void SpinField::MouseButtonUp( const MouseEvent& rMEvt ) |
| { |
| ReleaseMouse(); |
| mbInitialUp = mbInitialDown = sal_False; |
| maRepeatTimer.Stop(); |
| maRepeatTimer.SetTimeout( GetSettings().GetMouseSettings().GetButtonStartRepeat() ); |
| |
| if ( mbUpperIn ) |
| { |
| mbUpperIn = sal_False; |
| Invalidate( maUpperRect ); |
| Update(); |
| Up(); |
| } |
| else if ( mbLowerIn ) |
| { |
| mbLowerIn = sal_False; |
| Invalidate( maLowerRect ); |
| Update(); |
| Down(); |
| } |
| |
| Edit::MouseButtonUp( rMEvt ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void SpinField::MouseMove( const MouseEvent& rMEvt ) |
| { |
| if ( rMEvt.IsLeft() ) |
| { |
| if ( mbInitialUp ) |
| { |
| sal_Bool bNewUpperIn = maUpperRect.IsInside( rMEvt.GetPosPixel() ); |
| if ( bNewUpperIn != mbUpperIn ) |
| { |
| if ( bNewUpperIn ) |
| { |
| if ( mbRepeat ) |
| maRepeatTimer.Start(); |
| } |
| else |
| maRepeatTimer.Stop(); |
| |
| mbUpperIn = bNewUpperIn; |
| Invalidate( maUpperRect ); |
| Update(); |
| } |
| } |
| else if ( mbInitialDown ) |
| { |
| sal_Bool bNewLowerIn = maLowerRect.IsInside( rMEvt.GetPosPixel() ); |
| if ( bNewLowerIn != mbLowerIn ) |
| { |
| if ( bNewLowerIn ) |
| { |
| if ( mbRepeat ) |
| maRepeatTimer.Start(); |
| } |
| else |
| maRepeatTimer.Stop(); |
| |
| mbLowerIn = bNewLowerIn; |
| Invalidate( maLowerRect ); |
| Update(); |
| } |
| } |
| } |
| |
| Edit::MouseMove( rMEvt ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| long SpinField::Notify( NotifyEvent& rNEvt ) |
| { |
| long nDone = 0; |
| if( rNEvt.GetType() == EVENT_KEYINPUT ) |
| { |
| const KeyEvent& rKEvt = *rNEvt.GetKeyEvent(); |
| if ( !IsReadOnly() ) |
| { |
| sal_uInt16 nMod = rKEvt.GetKeyCode().GetModifier(); |
| switch ( rKEvt.GetKeyCode().GetCode() ) |
| { |
| case KEY_UP: |
| { |
| if ( !nMod ) |
| { |
| Up(); |
| nDone = 1; |
| } |
| } |
| break; |
| case KEY_DOWN: |
| { |
| if ( !nMod ) |
| { |
| Down(); |
| nDone = 1; |
| } |
| else if ( ( nMod == KEY_MOD2 ) && !mbInDropDown && ( GetStyle() & WB_DROPDOWN ) ) |
| { |
| mbInDropDown = ShowDropDown( sal_True ); |
| Paint( Rectangle( Point(), GetOutputSizePixel() ) ); |
| nDone = 1; |
| } |
| } |
| break; |
| case KEY_PAGEUP: |
| { |
| if ( !nMod ) |
| { |
| Last(); |
| nDone = 1; |
| } |
| } |
| break; |
| case KEY_PAGEDOWN: |
| { |
| if ( !nMod ) |
| { |
| First(); |
| nDone = 1; |
| } |
| } |
| break; |
| } |
| } |
| } |
| |
| if ( rNEvt.GetType() == EVENT_COMMAND ) |
| { |
| if ( ( rNEvt.GetCommandEvent()->GetCommand() == COMMAND_WHEEL ) && !IsReadOnly() ) |
| { |
| sal_uInt16 nWheelBehavior( GetSettings().GetMouseSettings().GetWheelBehavior() ); |
| if ( ( nWheelBehavior == MOUSE_WHEEL_ALWAYS ) |
| || ( ( nWheelBehavior == MOUSE_WHEEL_FOCUS_ONLY ) |
| && HasChildPathFocus() |
| ) |
| ) |
| { |
| const CommandWheelData* pData = rNEvt.GetCommandEvent()->GetWheelData(); |
| if ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) |
| { |
| if ( pData->GetDelta() < 0L ) |
| Down(); |
| else |
| Up(); |
| nDone = 1; |
| } |
| } |
| else |
| nDone = 0; // don't eat this event, let the default handling happen (i.e. scroll the context) |
| } |
| } |
| |
| return nDone ? nDone : Edit::Notify( rNEvt ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void SpinField::Command( const CommandEvent& rCEvt ) |
| { |
| Edit::Command( rCEvt ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void SpinField::FillLayoutData() const |
| { |
| if( mbSpin ) |
| { |
| mpControlData->mpLayoutData = new vcl::ControlLayoutData(); |
| AppendLayoutData( *GetSubEdit() ); |
| GetSubEdit()->SetLayoutDataParent( this ); |
| } |
| else |
| Edit::FillLayoutData(); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void SpinField::Paint( const Rectangle& rRect ) |
| { |
| if ( mbSpin ) |
| { |
| sal_Bool bEnable = IsEnabled(); |
| ImplDrawSpinButton( this, maUpperRect, maLowerRect, |
| mbUpperIn, mbLowerIn, bEnable, bEnable ); |
| } |
| |
| if ( GetStyle() & WB_DROPDOWN ) |
| { |
| DecorationView aView( this ); |
| |
| sal_uInt16 nStyle = BUTTON_DRAW_NOLIGHTBORDER; |
| if ( mbInDropDown ) |
| nStyle |= BUTTON_DRAW_PRESSED; |
| Rectangle aInnerRect = aView.DrawButton( maDropDownRect, nStyle ); |
| |
| SymbolType eSymbol = SYMBOL_SPIN_DOWN; |
| if ( GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_SPINUPDOWN ) |
| eSymbol = SYMBOL_SPIN_UPDOWN; |
| |
| nStyle = IsEnabled() ? 0 : SYMBOL_DRAW_DISABLE; |
| aView.DrawSymbol( aInnerRect, eSymbol, GetSettings().GetStyleSettings().GetButtonTextColor(), nStyle ); |
| } |
| |
| Edit::Paint( rRect ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void SpinField::ImplCalcButtonAreas( OutputDevice* pDev, const Size& rOutSz, Rectangle& rDDArea, Rectangle& rSpinUpArea, Rectangle& rSpinDownArea ) |
| { |
| const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings(); |
| |
| Size aSize = rOutSz; |
| Size aDropDownSize; |
| |
| if ( GetStyle() & WB_DROPDOWN ) |
| { |
| long nW = rStyleSettings.GetScrollBarSize(); |
| nW = GetDrawPixel( pDev, nW ); |
| aDropDownSize = Size( CalcZoom( nW ), aSize.Height() ); |
| aSize.Width() -= aDropDownSize.Width(); |
| rDDArea = Rectangle( Point( aSize.Width(), 0 ), aDropDownSize ); |
| rDDArea.Top()--; |
| } |
| else |
| rDDArea.SetEmpty(); |
| |
| // Je nach Hoehe, die groessen Berechnen |
| if ( GetStyle() & WB_SPIN ) |
| { |
| long nBottom1 = aSize.Height()/2; |
| long nBottom2 = aSize.Height()-1; |
| long nTop2 = nBottom1; |
| long nTop1 = 0; |
| if ( !(aSize.Height() & 0x01) ) |
| nBottom1--; |
| |
| sal_Bool bNativeRegionOK = sal_False; |
| Rectangle aContentUp, aContentDown; |
| |
| if ( (pDev->GetOutDevType() == OUTDEV_WINDOW) && |
| // there is just no useful native support for spinfields with dropdown |
| ! (GetStyle() & WB_DROPDOWN) && |
| IsNativeControlSupported(CTRL_SPINBOX, PART_ENTIRE_CONTROL) ) |
| { |
| Window *pWin = (Window*) pDev; |
| Window *pBorder = pWin->GetWindow( WINDOW_BORDER ); |
| |
| // get the system's spin button size |
| ImplControlValue aControlValue; |
| Rectangle aBound; |
| Point aPoint; |
| |
| // use the full extent of the control |
| Rectangle aArea( aPoint, pBorder->GetOutputSizePixel() ); |
| |
| bNativeRegionOK = |
| pWin->GetNativeControlRegion(CTRL_SPINBOX, PART_BUTTON_UP, |
| aArea, 0, aControlValue, rtl::OUString(), aBound, aContentUp) && |
| pWin->GetNativeControlRegion(CTRL_SPINBOX, PART_BUTTON_DOWN, |
| aArea, 0, aControlValue, rtl::OUString(), aBound, aContentDown); |
| |
| if( bNativeRegionOK ) |
| { |
| // convert back from border space to local coordinates |
| aPoint = pBorder->ScreenToOutputPixel( pWin->OutputToScreenPixel( aPoint ) ); |
| aContentUp.Move(-aPoint.X(), -aPoint.Y()); |
| aContentDown.Move(-aPoint.X(), -aPoint.Y()); |
| } |
| } |
| |
| if( bNativeRegionOK ) |
| { |
| rSpinUpArea = aContentUp; |
| rSpinDownArea = aContentDown; |
| } |
| else |
| { |
| aSize.Width() -= CalcZoom( GetDrawPixel( pDev, rStyleSettings.GetSpinSize() ) ); |
| |
| rSpinUpArea = Rectangle( aSize.Width(), nTop1, rOutSz.Width()-aDropDownSize.Width()-1, nBottom1 ); |
| rSpinDownArea = Rectangle( rSpinUpArea.Left(), nTop2, rSpinUpArea.Right(), nBottom2 ); |
| } |
| } |
| else |
| { |
| rSpinUpArea.SetEmpty(); |
| rSpinDownArea.SetEmpty(); |
| } |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void SpinField::Resize() |
| { |
| if ( mbSpin ) |
| { |
| Control::Resize(); |
| Size aSize = GetOutputSizePixel(); |
| bool bSubEditPositioned = false; |
| |
| if ( GetStyle() & (WB_SPIN|WB_DROPDOWN) ) |
| { |
| ImplCalcButtonAreas( this, aSize, maDropDownRect, maUpperRect, maLowerRect ); |
| |
| ImplControlValue aControlValue; |
| Point aPoint; |
| Rectangle aContent, aBound; |
| |
| // use the full extent of the control |
| Window *pBorder = GetWindow( WINDOW_BORDER ); |
| Rectangle aArea( aPoint, pBorder->GetOutputSizePixel() ); |
| |
| // adjust position and size of the edit field |
| if ( GetNativeControlRegion(CTRL_SPINBOX, PART_SUB_EDIT, |
| aArea, 0, aControlValue, rtl::OUString(), aBound, aContent) ) |
| { |
| // convert back from border space to local coordinates |
| aPoint = pBorder->ScreenToOutputPixel( OutputToScreenPixel( aPoint ) ); |
| aContent.Move(-aPoint.X(), -aPoint.Y()); |
| |
| // use the themes drop down size |
| mpEdit->SetPosPixel( aContent.TopLeft() ); |
| bSubEditPositioned = true; |
| aSize = aContent.GetSize(); |
| } |
| else |
| { |
| if ( maUpperRect.IsEmpty() ) |
| { |
| DBG_ASSERT( !maDropDownRect.IsEmpty(), "SpinField::Resize: SPIN && DROPDOWN, but all empty rects?" ); |
| aSize.Width() = maDropDownRect.Left(); |
| } |
| else |
| aSize.Width() = maUpperRect.Left(); |
| } |
| } |
| |
| if( ! bSubEditPositioned ) |
| { |
| // this moves our sub edit if RTL gets switched |
| mpEdit->SetPosPixel( Point() ); |
| } |
| mpEdit->SetSizePixel( aSize ); |
| |
| if ( GetStyle() & WB_SPIN ) |
| Invalidate( Rectangle( maUpperRect.TopLeft(), maLowerRect.BottomRight() ) ); |
| if ( GetStyle() & WB_DROPDOWN ) |
| Invalidate( maDropDownRect ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void SpinField::StateChanged( StateChangedType nType ) |
| { |
| Edit::StateChanged( nType ); |
| |
| if ( nType == STATE_CHANGE_ENABLE ) |
| { |
| if ( mbSpin || ( GetStyle() & WB_DROPDOWN ) ) |
| { |
| mpEdit->Enable( IsEnabled() ); |
| |
| if ( mbSpin ) |
| { |
| Invalidate( maLowerRect ); |
| Invalidate( maUpperRect ); |
| } |
| if ( GetStyle() & WB_DROPDOWN ) |
| Invalidate( maDropDownRect ); |
| } |
| } |
| else if ( nType == STATE_CHANGE_STYLE ) |
| { |
| if ( GetStyle() & WB_REPEAT ) |
| mbRepeat = sal_True; |
| else |
| mbRepeat = sal_False; |
| } |
| else if ( nType == STATE_CHANGE_ZOOM ) |
| { |
| Resize(); |
| if ( mpEdit ) |
| mpEdit->SetZoom( GetZoom() ); |
| Invalidate(); |
| } |
| else if ( nType == STATE_CHANGE_CONTROLFONT ) |
| { |
| if ( mpEdit ) |
| mpEdit->SetControlFont( GetControlFont() ); |
| ImplInitSettings( sal_True, sal_False, sal_False ); |
| Invalidate(); |
| } |
| else if ( nType == STATE_CHANGE_CONTROLFOREGROUND ) |
| { |
| if ( mpEdit ) |
| mpEdit->SetControlForeground( GetControlForeground() ); |
| ImplInitSettings( sal_False, sal_True, sal_False ); |
| Invalidate(); |
| } |
| else if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) |
| { |
| if ( mpEdit ) |
| mpEdit->SetControlBackground( GetControlBackground() ); |
| ImplInitSettings( sal_False, sal_False, sal_True ); |
| Invalidate(); |
| } |
| else if( nType == STATE_CHANGE_MIRRORING ) |
| { |
| if( mpEdit ) |
| mpEdit->StateChanged( STATE_CHANGE_MIRRORING ); |
| Resize(); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void SpinField::DataChanged( const DataChangedEvent& rDCEvt ) |
| { |
| Edit::DataChanged( rDCEvt ); |
| |
| if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && |
| (rDCEvt.GetFlags() & SETTINGS_STYLE) ) |
| { |
| Resize(); |
| Invalidate(); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Rectangle* SpinField::ImplFindPartRect( const Point& rPt ) |
| { |
| if( maUpperRect.IsInside( rPt ) ) |
| return &maUpperRect; |
| else if( maLowerRect.IsInside( rPt ) ) |
| return &maLowerRect; |
| else |
| return NULL; |
| } |
| |
| long SpinField::PreNotify( NotifyEvent& rNEvt ) |
| { |
| long nDone = 0; |
| const MouseEvent* pMouseEvt = NULL; |
| |
| if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL ) |
| { |
| if( !pMouseEvt->GetButtons() && !pMouseEvt->IsSynthetic() && !pMouseEvt->IsModifierChanged() ) |
| { |
| // trigger redraw if mouse over state has changed |
| if( IsNativeControlSupported(CTRL_SPINBOX, PART_ENTIRE_CONTROL) || |
| IsNativeControlSupported(CTRL_SPINBOX, PART_ALL_BUTTONS) ) |
| { |
| Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() ); |
| Rectangle* pLastRect = ImplFindPartRect( GetLastPointerPosPixel() ); |
| if( pRect != pLastRect || (pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow()) ) |
| { |
| // FIXME: this is currently only on aqua |
| // check for other platforms that need similar handling |
| if( ImplGetSVData()->maNWFData.mbNoFocusRects && |
| IsNativeWidgetEnabled() && |
| IsNativeControlSupported( CTRL_EDITBOX, PART_ENTIRE_CONTROL ) ) |
| { |
| ImplInvalidateOutermostBorder( this ); |
| } |
| else |
| { |
| // paint directly |
| Region aRgn( GetActiveClipRegion() ); |
| if( pLastRect ) |
| { |
| SetClipRegion( *pLastRect ); |
| Paint( *pLastRect ); |
| SetClipRegion( aRgn ); |
| } |
| if( pRect ) |
| { |
| SetClipRegion( *pRect ); |
| Paint( *pRect ); |
| SetClipRegion( aRgn ); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| return nDone ? nDone : Edit::PreNotify(rNEvt); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void SpinField::EndDropDown() |
| { |
| mbInDropDown = sal_False; |
| Paint( Rectangle( Point(), GetOutputSizePixel() ) ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool SpinField::ShowDropDown( sal_Bool ) |
| { |
| return sal_False; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Size SpinField::CalcMinimumSize() const |
| { |
| Size aSz = Edit::CalcMinimumSize(); |
| |
| if ( GetStyle() & WB_DROPDOWN ) |
| aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize(); |
| if ( GetStyle() & WB_SPIN ) |
| aSz.Width() += maUpperRect.GetWidth(); |
| |
| return aSz; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Size SpinField::GetOptimalSize(WindowSizeType eType) const |
| { |
| switch (eType) { |
| case WINDOWSIZE_MINIMUM: |
| return CalcMinimumSize(); |
| default: |
| return Edit::GetOptimalSize( eType ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Size SpinField::CalcSize( sal_uInt16 nChars ) const |
| { |
| Size aSz = Edit::CalcSize( nChars ); |
| |
| if ( GetStyle() & WB_DROPDOWN ) |
| aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize(); |
| if ( GetStyle() & WB_SPIN ) |
| aSz.Width() += GetSettings().GetStyleSettings().GetSpinSize(); |
| |
| return aSz; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| IMPL_LINK( SpinField, ImplTimeout, Timer*, pTimer ) |
| { |
| if ( pTimer->GetTimeout() == GetSettings().GetMouseSettings().GetButtonStartRepeat() ) |
| { |
| pTimer->SetTimeout( GetSettings().GetMouseSettings().GetButtonRepeat() ); |
| pTimer->Start(); |
| } |
| else |
| { |
| if ( mbInitialUp ) |
| Up(); |
| else |
| Down(); |
| } |
| return 0; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void SpinField::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags ) |
| { |
| Edit::Draw( pDev, rPos, rSize, nFlags ); |
| |
| WinBits nFieldStyle = GetStyle(); |
| if ( !(nFlags & WINDOW_DRAW_NOCONTROLS ) && ( nFieldStyle & (WB_SPIN|WB_DROPDOWN) ) ) |
| { |
| Point aPos = pDev->LogicToPixel( rPos ); |
| Size aSize = pDev->LogicToPixel( rSize ); |
| OutDevType eOutDevType = pDev->GetOutDevType(); |
| AllSettings aOldSettings = pDev->GetSettings(); |
| |
| pDev->Push(); |
| pDev->SetMapMode(); |
| |
| if ( eOutDevType == OUTDEV_PRINTER ) |
| { |
| StyleSettings aStyleSettings = aOldSettings.GetStyleSettings(); |
| aStyleSettings.SetFaceColor( COL_LIGHTGRAY ); |
| aStyleSettings.SetButtonTextColor( COL_BLACK ); |
| AllSettings aSettings( aOldSettings ); |
| aSettings.SetStyleSettings( aStyleSettings ); |
| pDev->SetSettings( aSettings ); |
| } |
| |
| Rectangle aDD, aUp, aDown; |
| ImplCalcButtonAreas( pDev, aSize, aDD, aUp, aDown ); |
| aDD.Move( aPos.X(), aPos.Y() ); |
| aUp.Move( aPos.X(), aPos.Y() ); |
| aUp.Top()++; |
| aDown.Move( aPos.X(), aPos.Y() ); |
| |
| Color aButtonTextColor; |
| if ( ( nFlags & WINDOW_DRAW_MONO ) || ( eOutDevType == OUTDEV_PRINTER ) ) |
| aButtonTextColor = Color( COL_BLACK ); |
| else |
| aButtonTextColor = GetSettings().GetStyleSettings().GetButtonTextColor(); |
| |
| if ( GetStyle() & WB_DROPDOWN ) |
| { |
| DecorationView aView( pDev ); |
| sal_uInt16 nStyle = BUTTON_DRAW_NOLIGHTBORDER; |
| Rectangle aInnerRect = aView.DrawButton( aDD, nStyle ); |
| SymbolType eSymbol = SYMBOL_SPIN_DOWN; |
| if ( GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_SPINUPDOWN ) |
| eSymbol = SYMBOL_SPIN_UPDOWN; |
| |
| nStyle = ( IsEnabled() || ( nFlags & WINDOW_DRAW_NODISABLE ) ) ? 0 : SYMBOL_DRAW_DISABLE; |
| aView.DrawSymbol( aInnerRect, eSymbol, aButtonTextColor, nStyle ); |
| } |
| |
| if ( GetStyle() & WB_SPIN ) |
| { |
| ImplDrawSpinButton( pDev, aUp, aDown, sal_False, sal_False, sal_True, sal_True ); |
| } |
| |
| pDev->Pop(); |
| pDev->SetSettings( aOldSettings ); |
| } |
| } |