diff options
Diffstat (limited to 'vcl/source/control/button.cxx')
-rw-r--r-- | vcl/source/control/button.cxx | 4534 |
1 files changed, 4534 insertions, 0 deletions
diff --git a/vcl/source/control/button.cxx b/vcl/source/control/button.cxx new file mode 100644 index 000000000000..db7649a90258 --- /dev/null +++ b/vcl/source/control/button.cxx @@ -0,0 +1,4534 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_vcl.hxx" + +#include <tools/debug.hxx> + +#ifndef _SV_SVIDS_HRC +#include <vcl/svids.hrc> +#endif +#include <vcl/svdata.hxx> +#ifndef _SV_IAMGE_HXX +#include <vcl/image.hxx> +#endif +#include <vcl/bitmap.hxx> +#include <vcl/bitmapex.hxx> +#include <vcl/decoview.hxx> +#include <vcl/event.hxx> +#include <vcl/svapp.hxx> +#include <vcl/dialog.hxx> +#include <vcl/fixed.hxx> +#include <tools/poly.hxx> +#include <vcl/button.hxx> +#include <vcl/window.h> +#include <vcl/controldata.hxx> +#ifndef _SV_NATIVEWIDGET_HXX +#include <vcl/salnativewidgets.hxx> +#endif +#include <vcl/edit.hxx> + +#ifndef _SV_RC_H +#include <tools/rc.h> +#endif + + + +// ======================================================================= + +#define PUSHBUTTON_VIEW_STYLE (WB_3DLOOK | \ + WB_LEFT | WB_CENTER | WB_RIGHT | \ + WB_TOP | WB_VCENTER | WB_BOTTOM | \ + WB_WORDBREAK | WB_NOLABEL | \ + WB_DEFBUTTON | WB_NOLIGHTBORDER | \ + WB_RECTSTYLE | WB_SMALLSTYLE | \ + WB_TOGGLE ) +#define RADIOBUTTON_VIEW_STYLE (WB_3DLOOK | \ + WB_LEFT | WB_CENTER | WB_RIGHT | \ + WB_TOP | WB_VCENTER | WB_BOTTOM | \ + WB_WORDBREAK | WB_NOLABEL) +#define CHECKBOX_VIEW_STYLE (WB_3DLOOK | \ + WB_LEFT | WB_CENTER | WB_RIGHT | \ + WB_TOP | WB_VCENTER | WB_BOTTOM | \ + WB_WORDBREAK | WB_NOLABEL) + +// ======================================================================= + +class ImplCommonButtonData +{ +public: + Rectangle maFocusRect; + Rectangle maSymbolRect; + USHORT mnButtonState; + BOOL mbSmallSymbol; + + Image maImage; + Image maImageHC; + BitmapEx* mpBitmapEx; + BitmapEx* mpBitmapExHC; + ImageAlign meImageAlign; + SymbolAlign meSymbolAlign; + +public: + ImplCommonButtonData(); + ~ImplCommonButtonData(); +}; + +// ----------------------------------------------------------------------- +ImplCommonButtonData::ImplCommonButtonData() +{ + mnButtonState = 0; + mbSmallSymbol = FALSE; + + mpBitmapEx = NULL; + mpBitmapExHC = NULL; + meImageAlign = IMAGEALIGN_TOP; + meSymbolAlign = SYMBOLALIGN_LEFT; +} + +// ----------------------------------------------------------------------- +ImplCommonButtonData::~ImplCommonButtonData() +{ + delete mpBitmapEx; + delete mpBitmapExHC; +} + +// ======================================================================= + +Button::Button( WindowType nType ) : + Control( nType ) +{ + mpButtonData = new ImplCommonButtonData; +} + +// ----------------------------------------------------------------------- + +Button::Button( Window* pParent, WinBits nStyle ) : + Control( WINDOW_BUTTON ) +{ + mpButtonData = new ImplCommonButtonData; + ImplInit( pParent, nStyle, NULL ); +} + +// ----------------------------------------------------------------------- + +Button::Button( Window* pParent, const ResId& rResId ) : + Control( WINDOW_BUTTON ) +{ + rResId.SetRT( RSC_BUTTON ); + mpButtonData = new ImplCommonButtonData; + WinBits nStyle = ImplInitRes( rResId ); + ImplInit( pParent, nStyle, NULL ); + ImplLoadRes( rResId ); + + if ( !(nStyle & WB_HIDE) ) + Show(); +} + +// ----------------------------------------------------------------------- + +Button::~Button() +{ + delete mpButtonData; +} + +// ----------------------------------------------------------------------- + +void Button::Click() +{ + ImplCallEventListenersAndHandler( VCLEVENT_BUTTON_CLICK, maClickHdl, this ); +} + +// ----------------------------------------------------------------------- + +XubString Button::GetStandardText( StandardButtonType eButton ) +{ + static struct + { + sal_uInt32 nResId; + const char* pDefText; + } aResIdAry[BUTTON_COUNT] = + { + { SV_BUTTONTEXT_OK, "~OK" }, + { SV_BUTTONTEXT_CANCEL, "~Cancel" }, + { SV_BUTTONTEXT_YES, "~Yes" }, + { SV_BUTTONTEXT_NO, "~No" }, + { SV_BUTTONTEXT_RETRY, "~Retry" }, + { SV_BUTTONTEXT_HELP, "~Help" }, + { SV_BUTTONTEXT_CLOSE, "~Close" }, + { SV_BUTTONTEXT_MORE, "~More" }, + { SV_BUTTONTEXT_IGNORE, "~Ignore" }, + { SV_BUTTONTEXT_ABORT, "~Abort" }, + { SV_BUTTONTEXT_LESS, "~Less" } + }; + + String aText; + ResMgr* pResMgr = ImplGetResMgr(); + if( pResMgr ) + { + ResId aResId( aResIdAry[(USHORT)eButton].nResId, *pResMgr ); + aText = String( aResId ); + } + else + { + ByteString aT( aResIdAry[(USHORT)eButton].pDefText ); + aText = String( aT, RTL_TEXTENCODING_ASCII_US ); + } + return aText; +} + +// ----------------------------------------------------------------------- + +XubString Button::GetStandardHelpText( StandardButtonType /* eButton */ ) +{ + XubString aHelpText; + return aHelpText; +} +// ----------------------------------------------------------------------- +BOOL Button::SetModeImage( const Image& rImage, BmpColorMode eMode ) +{ + if( eMode == BMP_COLOR_NORMAL ) + { + if ( rImage != mpButtonData->maImage ) + { + delete mpButtonData->mpBitmapEx; + + mpButtonData->mpBitmapEx = NULL; + mpButtonData->maImage = rImage; + + StateChanged( STATE_CHANGE_DATA ); + } + } + else if( eMode == BMP_COLOR_HIGHCONTRAST ) + { + if( rImage != mpButtonData->maImageHC ) + { + delete mpButtonData->mpBitmapExHC; + + mpButtonData->mpBitmapExHC = NULL; + mpButtonData->maImageHC = rImage; + + StateChanged( STATE_CHANGE_DATA ); + } + } + else + return FALSE; + + return TRUE; +} + +// ----------------------------------------------------------------------- +const Image Button::GetModeImage( BmpColorMode eMode ) const +{ + if( eMode == BMP_COLOR_NORMAL ) + { + return mpButtonData->maImage; + } + else if( eMode == BMP_COLOR_HIGHCONTRAST ) + { + return mpButtonData->maImageHC; + } + else + return Image(); +} + +// ----------------------------------------------------------------------- +BOOL Button::HasImage() const +{ + return !!(mpButtonData->maImage); +} + +// ----------------------------------------------------------------------- +void Button::SetImageAlign( ImageAlign eAlign ) +{ + if ( mpButtonData->meImageAlign != eAlign ) + { + mpButtonData->meImageAlign = eAlign; + StateChanged( STATE_CHANGE_DATA ); + } +} + +// ----------------------------------------------------------------------- +ImageAlign Button::GetImageAlign() const +{ + return mpButtonData->meImageAlign; +} + +// ----------------------------------------------------------------------- +BOOL Button::SetModeBitmap( const BitmapEx& rBitmap, BmpColorMode eMode ) +{ + if ( SetModeImage( rBitmap, eMode ) ) + { + if( eMode == BMP_COLOR_NORMAL ) + { + if ( !mpButtonData->mpBitmapEx ) + mpButtonData->mpBitmapEx = new BitmapEx( rBitmap ); + } + else if ( eMode == BMP_COLOR_HIGHCONTRAST ) + { + if ( !mpButtonData->mpBitmapExHC ) + mpButtonData->mpBitmapExHC = new BitmapEx( rBitmap ); + } + else + return FALSE; + + return TRUE; + } + return FALSE; +} + +// ----------------------------------------------------------------------- +BitmapEx Button::GetModeBitmap( BmpColorMode eMode ) const +{ + BitmapEx aBmp; + + if ( eMode == BMP_COLOR_NORMAL ) + { + if ( mpButtonData->mpBitmapEx ) + aBmp = *( mpButtonData->mpBitmapEx ); + } + else if ( eMode == BMP_COLOR_HIGHCONTRAST ) + { + if ( mpButtonData->mpBitmapExHC ) + aBmp = *( mpButtonData->mpBitmapExHC ); + } + + return aBmp; +} + +// ----------------------------------------------------------------------- +void Button::SetFocusRect( const Rectangle& rFocusRect ) +{ + ImplSetFocusRect( rFocusRect ); +} + +// ----------------------------------------------------------------------- +const Rectangle& Button::GetFocusRect() const +{ + return ImplGetFocusRect(); +} + +// ----------------------------------------------------------------------- + +const Rectangle& Button::ImplGetSymbolRect() const +{ + return mpButtonData->maSymbolRect; +} + +void Button::ImplSetSymbolRect( const Rectangle& i_rRect ) +{ + mpButtonData->maSymbolRect = i_rRect; +} + +// ----------------------------------------------------------------------- + +USHORT Button::ImplGetTextStyle( XubString& rText, WinBits nWinStyle, + ULONG nDrawFlags ) +{ + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + USHORT nTextStyle = FixedText::ImplGetTextStyle( nWinStyle & ~WB_DEFBUTTON ); + + if ( nDrawFlags & WINDOW_DRAW_NOMNEMONIC ) + { + if ( nTextStyle & TEXT_DRAW_MNEMONIC ) + { + rText = GetNonMnemonicString( rText ); + nTextStyle &= ~TEXT_DRAW_MNEMONIC; + } + } + + if ( !(nDrawFlags & WINDOW_DRAW_NODISABLE) ) + { + if ( !IsEnabled() ) + nTextStyle |= TEXT_DRAW_DISABLE; + } + + if ( (nDrawFlags & WINDOW_DRAW_MONO) || + (rStyleSettings.GetOptions() & STYLE_OPTION_MONO) ) + nTextStyle |= TEXT_DRAW_MONO; + + return nTextStyle; +} + +// ----------------------------------------------------------------------- + +void Button::ImplDrawAlignedImage( OutputDevice* pDev, Point& rPos, + Size& rSize, BOOL bLayout, + ULONG nImageSep, ULONG nDrawFlags, + USHORT nTextStyle, Rectangle *pSymbolRect, + bool bAddImageSep ) +{ + XubString aText( GetText() ); + BOOL bDrawImage = HasImage() && ! ( ImplGetButtonState() & BUTTON_DRAW_NOIMAGE ); + BOOL bDrawText = aText.Len() && ! ( ImplGetButtonState() & BUTTON_DRAW_NOTEXT ); + BOOL bHasSymbol = pSymbolRect ? TRUE : FALSE; + + // No text and no image => nothing to do => return + if ( !bDrawImage && !bDrawText && !bHasSymbol ) + return; + + WinBits nWinStyle = GetStyle(); + Rectangle aOutRect( rPos, rSize ); + MetricVector *pVector = bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : NULL; + String *pDisplayText = bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : NULL; + ImageAlign eImageAlign = mpButtonData->meImageAlign; + Size aImageSize = mpButtonData->maImage.GetSizePixel(); + + if ( ( nDrawFlags & WINDOW_DRAW_NOMNEMONIC ) && + ( nTextStyle & TEXT_DRAW_MNEMONIC ) ) + { + aText = GetNonMnemonicString( aText ); + nTextStyle &= ~TEXT_DRAW_MNEMONIC; + } + + aImageSize.Width() = CalcZoom( aImageSize.Width() ); + aImageSize.Height() = CalcZoom( aImageSize.Height() ); + + // Drawing text or symbol only is simple, use style and output rectangle + if ( bHasSymbol && !bDrawImage && !bDrawText ) + { + *pSymbolRect = aOutRect; + return; + } + else if ( bDrawText && !bDrawImage && !bHasSymbol ) + { + DrawControlText( *pDev, aOutRect, aText, nTextStyle, pVector, pDisplayText ); + + ImplSetFocusRect( aOutRect ); + rSize = aOutRect.GetSize(); + rPos = aOutRect.TopLeft(); + + return; + } + + // check for HC mode ( image only! ) + Image *pImage = &(mpButtonData->maImage); + BitmapEx *pBitmapEx = mpButtonData->mpBitmapEx; + + if( !!(mpButtonData->maImageHC) ) + { + if( GetSettings().GetStyleSettings().GetHighContrastMode() ) + { + pImage = &(mpButtonData->maImageHC); + pBitmapEx = mpButtonData->mpBitmapExHC; + } + } + + if ( pBitmapEx && ( pDev->GetOutDevType() == OUTDEV_PRINTER ) ) + { + // Die Groesse richtet sich nach dem Bildschirm, soll auf + // dem Drucker genau so aussehen... + MapMode aMap100thMM( MAP_100TH_MM ); + aImageSize = PixelToLogic( aImageSize, aMap100thMM ); + aImageSize = pDev->LogicToPixel( aImageSize, aMap100thMM ); + } + + Size aTextSize; + Size aSymbolSize; + Size aMax; + Point aImagePos = rPos; + Point aTextPos = rPos; + Rectangle aUnion = Rectangle( aImagePos, aImageSize ); + Rectangle aSymbol; + long nSymbolHeight = 0; + + if ( bDrawText || bHasSymbol ) + { + // Get the size of the text output area ( the symbol will be drawn in + // this area as well, so the symbol rectangle will be calculated here, too ) + + Rectangle aRect = Rectangle( Point(), rSize ); + Size aTSSize; + + if ( bHasSymbol ) + { + if ( bDrawText ) + { + nSymbolHeight = pDev->GetTextHeight(); + if ( mpButtonData->mbSmallSymbol ) + nSymbolHeight = nSymbolHeight * 3 / 4; + + aSymbol = Rectangle( Point(), Size( nSymbolHeight, nSymbolHeight ) ); + ImplCalcSymbolRect( aSymbol ); + aRect.Left() += 3 * nSymbolHeight / 2; + aTSSize.Width() = 3 * nSymbolHeight / 2; + } + else + { + aSymbol = Rectangle( Point(), rSize ); + ImplCalcSymbolRect( aSymbol ); + aTSSize.Width() = aSymbol.GetWidth(); + } + aTSSize.Height() = aSymbol.GetHeight(); + aSymbolSize = aSymbol.GetSize(); + } + + if ( bDrawText ) + { + if ( ( eImageAlign == IMAGEALIGN_LEFT_TOP ) || + ( eImageAlign == IMAGEALIGN_LEFT ) || + ( eImageAlign == IMAGEALIGN_LEFT_BOTTOM ) || + ( eImageAlign == IMAGEALIGN_RIGHT_TOP ) || + ( eImageAlign == IMAGEALIGN_RIGHT ) || + ( eImageAlign == IMAGEALIGN_RIGHT_BOTTOM ) ) + { + aRect.Right() -= ( aImageSize.Width() + nImageSep ); + } + else if ( ( eImageAlign == IMAGEALIGN_TOP_LEFT ) || + ( eImageAlign == IMAGEALIGN_TOP ) || + ( eImageAlign == IMAGEALIGN_TOP_RIGHT ) || + ( eImageAlign == IMAGEALIGN_BOTTOM_LEFT ) || + ( eImageAlign == IMAGEALIGN_BOTTOM ) || + ( eImageAlign == IMAGEALIGN_BOTTOM_RIGHT ) ) + { + aRect.Bottom() -= ( aImageSize.Height() + nImageSep ); + } + + aRect = pDev->GetTextRect( aRect, aText, nTextStyle ); + aTextSize = aRect.GetSize(); + + aTSSize.Width() += aTextSize.Width(); + + if ( aTSSize.Height() < aTextSize.Height() ) + aTSSize.Height() = aTextSize.Height(); + + if( bAddImageSep && bDrawImage ) + { + long nDiff = (aImageSize.Height() - aTextSize.Height()) / 3; + if( nDiff > 0 ) + nImageSep += nDiff; + } + } + + aMax.Width() = aTSSize.Width() > aImageSize.Width() ? aTSSize.Width() : aImageSize.Width(); + aMax.Height() = aTSSize.Height() > aImageSize.Height() ? aTSSize.Height() : aImageSize.Height(); + + // Now calculate the output area for the image and the text acording to the image align flags + + if ( ( eImageAlign == IMAGEALIGN_LEFT ) || + ( eImageAlign == IMAGEALIGN_RIGHT ) ) + { + aImagePos.Y() = rPos.Y() + ( aMax.Height() - aImageSize.Height() ) / 2; + aTextPos.Y() = rPos.Y() + ( aMax.Height() - aTSSize.Height() ) / 2; + } + else if ( ( eImageAlign == IMAGEALIGN_LEFT_BOTTOM ) || + ( eImageAlign == IMAGEALIGN_RIGHT_BOTTOM ) ) + { + aImagePos.Y() = rPos.Y() + aMax.Height() - aImageSize.Height(); + aTextPos.Y() = rPos.Y() + aMax.Height() - aTSSize.Height(); + } + else if ( ( eImageAlign == IMAGEALIGN_TOP ) || + ( eImageAlign == IMAGEALIGN_BOTTOM ) ) + { + aImagePos.X() = rPos.X() + ( aMax.Width() - aImageSize.Width() ) / 2; + aTextPos.X() = rPos.X() + ( aMax.Width() - aTSSize.Width() ) / 2; + } + else if ( ( eImageAlign == IMAGEALIGN_TOP_RIGHT ) || + ( eImageAlign == IMAGEALIGN_BOTTOM_RIGHT ) ) + { + aImagePos.X() = rPos.X() + aMax.Width() - aImageSize.Width(); + aTextPos.X() = rPos.X() + aMax.Width() - aTSSize.Width(); + } + + if ( ( eImageAlign == IMAGEALIGN_LEFT_TOP ) || + ( eImageAlign == IMAGEALIGN_LEFT ) || + ( eImageAlign == IMAGEALIGN_LEFT_BOTTOM ) ) + { + aTextPos.X() = rPos.X() + aImageSize.Width() + nImageSep; + } + else if ( ( eImageAlign == IMAGEALIGN_RIGHT_TOP ) || + ( eImageAlign == IMAGEALIGN_RIGHT ) || + ( eImageAlign == IMAGEALIGN_RIGHT_BOTTOM ) ) + { + aImagePos.X() = rPos.X() + aTSSize.Width() + nImageSep; + } + else if ( ( eImageAlign == IMAGEALIGN_TOP_LEFT ) || + ( eImageAlign == IMAGEALIGN_TOP ) || + ( eImageAlign == IMAGEALIGN_TOP_RIGHT ) ) + { + aTextPos.Y() = rPos.Y() + aImageSize.Height() + nImageSep; + } + else if ( ( eImageAlign == IMAGEALIGN_BOTTOM_LEFT ) || + ( eImageAlign == IMAGEALIGN_BOTTOM ) || + ( eImageAlign == IMAGEALIGN_BOTTOM_RIGHT ) ) + { + aImagePos.Y() = rPos.Y() + aTSSize.Height() + nImageSep; + } + else if ( eImageAlign == IMAGEALIGN_CENTER ) + { + aImagePos.X() = rPos.X() + ( aMax.Width() - aImageSize.Width() ) / 2; + aImagePos.Y() = rPos.Y() + ( aMax.Height() - aImageSize.Height() ) / 2; + aTextPos.X() = rPos.X() + ( aMax.Width() - aTSSize.Width() ) / 2; + aTextPos.Y() = rPos.Y() + ( aMax.Height() - aTSSize.Height() ) / 2; + } + aUnion = Rectangle( aImagePos, aImageSize ); + aUnion.Union( Rectangle( aTextPos, aTSSize ) ); + } + + // Now place the combination of text and image in the output area of the button + // according to the window style (WinBits) + long nXOffset = 0; + long nYOffset = 0; + + if ( nWinStyle & WB_CENTER ) + { + nXOffset = ( rSize.Width() - aUnion.GetWidth() ) / 2; + } + else if ( nWinStyle & WB_RIGHT ) + { + nXOffset = rSize.Width() - aUnion.GetWidth(); + } + + if ( nWinStyle & WB_VCENTER ) + { + nYOffset = ( rSize.Height() - aUnion.GetHeight() ) / 2; + } + else if ( nWinStyle & WB_BOTTOM ) + { + nYOffset = rSize.Height() - aUnion.GetHeight(); + } + + // the top left corner should always be visible, so we don't allow negative offsets + if ( nXOffset < 0 ) nXOffset = 0; + if ( nYOffset < 0 ) nYOffset = 0; + + aImagePos.X() += nXOffset; + aImagePos.Y() += nYOffset; + aTextPos.X() += nXOffset; + aTextPos.Y() += nYOffset; + + // set rPos and rSize to the union + rSize = aUnion.GetSize(); + rPos.X() += nXOffset; + rPos.Y() += nYOffset; + + if ( bHasSymbol ) + { + if ( mpButtonData->meSymbolAlign == SYMBOLALIGN_RIGHT ) + { + Point aRightPos = Point( aTextPos.X() + aTextSize.Width() + aSymbolSize.Width()/2, aTextPos.Y() ); + *pSymbolRect = Rectangle( aRightPos, aSymbolSize ); + } + else + { + *pSymbolRect = Rectangle( aTextPos, aSymbolSize ); + aTextPos.X() += ( 3 * nSymbolHeight / 2 ); + } + if ( mpButtonData->mbSmallSymbol ) + { + nYOffset = (aUnion.GetHeight() - aSymbolSize.Height())/2; + pSymbolRect->setY( aTextPos.Y() + nYOffset ); + } + } + + USHORT nStyle = 0; + + if ( ! ( nDrawFlags & WINDOW_DRAW_NODISABLE ) && + ! IsEnabled() ) + nStyle |= IMAGE_DRAW_DISABLE; + + if ( pBitmapEx && ( pDev->GetOutDevType() == OUTDEV_PRINTER ) ) + { + // Fuer die BitmapEx ueberlegt sich KA noch, wie man die disablete + // Darstellung hinbekommt... + pBitmapEx->Draw( pDev, aImagePos, aImageSize /*, nStyle*/ ); + } + else + { + if ( IsZoom() ) + pDev->DrawImage( aImagePos, aImageSize, *pImage, nStyle ); + else + pDev->DrawImage( aImagePos, *pImage, nStyle ); + } + + if ( bDrawText ) + { + ImplSetFocusRect( Rectangle( aTextPos, aTextSize ) ); + pDev->DrawText( Rectangle( aTextPos, aTextSize ), aText, nTextStyle, pVector, pDisplayText ); + } + else + { + ImplSetFocusRect( Rectangle( aImagePos, aImageSize ) ); + } +} + +// ----------------------------------------------------------------------- +void Button::ImplSetFocusRect( const Rectangle &rFocusRect ) +{ + Rectangle aFocusRect = rFocusRect; + Rectangle aOutputRect = Rectangle( Point(), GetOutputSizePixel() ); + + if ( ! aFocusRect.IsEmpty() ) + { + aFocusRect.Left()--; + aFocusRect.Top()--; + aFocusRect.Right()++; + aFocusRect.Bottom()++; + } + + if ( aFocusRect.Left() < aOutputRect.Left() ) aFocusRect.Left() = aOutputRect.Left(); + if ( aFocusRect.Top() < aOutputRect.Top() ) aFocusRect.Top() = aOutputRect.Top(); + if ( aFocusRect.Right() > aOutputRect.Right() ) aFocusRect.Right() = aOutputRect.Right(); + if ( aFocusRect.Bottom() > aOutputRect.Bottom() ) aFocusRect.Bottom() = aOutputRect.Bottom(); + + mpButtonData->maFocusRect = aFocusRect; +} + +// ----------------------------------------------------------------------- +const Rectangle& Button::ImplGetFocusRect() const +{ + return mpButtonData->maFocusRect; +} + +// ----------------------------------------------------------------------- +USHORT& Button::ImplGetButtonState() +{ + return mpButtonData->mnButtonState; +} + +// ----------------------------------------------------------------------- +USHORT Button::ImplGetButtonState() const +{ + return mpButtonData->mnButtonState; +} + +// ----------------------------------------------------------------------- +void Button::ImplSetSymbolAlign( SymbolAlign eAlign ) +{ + if ( mpButtonData->meSymbolAlign != eAlign ) + { + mpButtonData->meSymbolAlign = eAlign; + StateChanged( STATE_CHANGE_DATA ); + } +} + +// ----------------------------------------------------------------------- +SymbolAlign Button::ImplGetSymbolAlign() const +{ + return mpButtonData->meSymbolAlign; +} +// ----------------------------------------------------------------------- +void Button::ImplSetSmallSymbol( BOOL bSmall ) +{ + mpButtonData->mbSmallSymbol = bSmall; +} + +// ----------------------------------------------------------------------- +void Button::EnableImageDisplay( BOOL bEnable ) +{ + if( bEnable ) + mpButtonData->mnButtonState &= ~BUTTON_DRAW_NOIMAGE; + else + mpButtonData->mnButtonState |= BUTTON_DRAW_NOIMAGE; +} + +// ----------------------------------------------------------------------- +BOOL Button::IsImageDisplayEnabled() +{ + return (mpButtonData->mnButtonState & BUTTON_DRAW_NOIMAGE) == 0; +} + +// ----------------------------------------------------------------------- +void Button::EnableTextDisplay( BOOL bEnable ) +{ + if( bEnable ) + mpButtonData->mnButtonState &= ~BUTTON_DRAW_NOTEXT; + else + mpButtonData->mnButtonState |= BUTTON_DRAW_NOTEXT; +} + +// ----------------------------------------------------------------------- +BOOL Button::IsTextDisplayEnabled() +{ + return (mpButtonData->mnButtonState & BUTTON_DRAW_NOTEXT) == 0; +} + +// ----------------------------------------------------------------------- +void Button::DataChanged( const DataChangedEvent& rDCEvt ) +{ + Control::DataChanged( rDCEvt ); + + // The flag SETTINGS_IN_UPDATE_SETTINGS is set when the settings changed due to a + // Application::SettingsChanged event. In this scenario we want to keep the style settings + // of our radio buttons and our check boxes. + if ( ( rDCEvt.GetType() == DATACHANGED_SETTINGS ) && + ( rDCEvt.GetFlags() & SETTINGS_IN_UPDATE_SETTINGS ) ) + + { + const AllSettings* pOldSettings = rDCEvt.GetOldSettings(); + if ( pOldSettings ) + { + BOOL bResetStyleSettings = FALSE; + AllSettings aAllSettings = GetSettings(); + StyleSettings aStyleSetting = aAllSettings.GetStyleSettings(); + + USHORT nCheckBoxStyle = aStyleSetting.GetCheckBoxStyle(); + if ( nCheckBoxStyle != pOldSettings->GetStyleSettings().GetCheckBoxStyle() ) + { + aStyleSetting.SetCheckBoxStyle( pOldSettings->GetStyleSettings().GetCheckBoxStyle() ); + bResetStyleSettings = TRUE; + } + + USHORT nRadioButtonStyle = aStyleSetting.GetRadioButtonStyle(); + if ( nRadioButtonStyle != pOldSettings->GetStyleSettings().GetRadioButtonStyle() ) + { + aStyleSetting.SetRadioButtonStyle( pOldSettings->GetStyleSettings().GetRadioButtonStyle() ); + bResetStyleSettings = TRUE; + } + + if ( bResetStyleSettings ) + { + aAllSettings.SetStyleSettings( pOldSettings->GetStyleSettings() ); + SetSettings( aAllSettings ); + } + } + } +} + +void Button::SetSmallSymbol (bool small) +{ + ImplSetSmallSymbol (small); +} + +bool Button::IsSmallSymbol () const +{ + return mpButtonData->mbSmallSymbol; +} + +// ======================================================================= + +void PushButton::ImplInitPushButtonData() +{ + mpWindowImpl->mbPushButton = TRUE; + + meSymbol = SYMBOL_NOSYMBOL; + meState = STATE_NOCHECK; + meSaveValue = STATE_NOCHECK; + mnDDStyle = 0; + mbPressed = FALSE; + mbInUserDraw = FALSE; +} + +// ----------------------------------------------------------------------- + +void PushButton::ImplInit( Window* pParent, WinBits nStyle ) +{ + nStyle = ImplInitStyle( pParent->GetWindow( WINDOW_LASTCHILD ), nStyle ); + Button::ImplInit( pParent, nStyle, NULL ); + + if ( nStyle & WB_NOLIGHTBORDER ) + ImplGetButtonState() |= BUTTON_DRAW_NOLIGHTBORDER; + + ImplInitSettings( TRUE, TRUE, TRUE ); +} + +// ----------------------------------------------------------------------- + +WinBits PushButton::ImplInitStyle( const Window* pPrevWindow, WinBits nStyle ) +{ + if ( !(nStyle & WB_NOTABSTOP) ) + nStyle |= WB_TABSTOP; + + // if no alignment is given, default to "vertically centered". This is because since + // #i26046#, we respect the vertical alignment flags (previously we didn't completely), + // but we of course want to look as before when no vertical alignment is specified + if ( ( nStyle & ( WB_TOP | WB_VCENTER | WB_BOTTOM ) ) == 0 ) + nStyle |= WB_VCENTER; + + if ( !(nStyle & WB_NOGROUP) && + (!pPrevWindow || + ((pPrevWindow->GetType() != WINDOW_PUSHBUTTON) && + (pPrevWindow->GetType() != WINDOW_OKBUTTON) && + (pPrevWindow->GetType() != WINDOW_CANCELBUTTON) && + (pPrevWindow->GetType() != WINDOW_HELPBUTTON)) ) ) + nStyle |= WB_GROUP; + return nStyle; +} + +// ----------------------------------------------------------------- + +const Font& PushButton::GetCanonicalFont( const StyleSettings& _rStyle ) const +{ + return _rStyle.GetPushButtonFont(); +} + +// ----------------------------------------------------------------- +const Color& PushButton::GetCanonicalTextColor( const StyleSettings& _rStyle ) const +{ + return _rStyle.GetButtonTextColor(); +} + +// ----------------------------------------------------------------------- + +void PushButton::ImplInitSettings( BOOL bFont, + BOOL bForeground, BOOL bBackground ) +{ + Button::ImplInitSettings( bFont, bForeground ); + + if ( bBackground ) + { + SetBackground(); + // #i38498#: do not check for GetParent()->IsChildTransparentModeEnabled() + // otherwise the formcontrol button will be overdrawn due to PARENTCLIPMODE_NOCLIP + // for radio and checkbox this is ok as they shoud appear transparent in documents + if ( IsNativeControlSupported( CTRL_PUSHBUTTON, PART_ENTIRE_CONTROL ) || + (GetStyle() & WB_FLATBUTTON) != 0 ) + { + EnableChildTransparentMode( TRUE ); + SetParentClipMode( PARENTCLIPMODE_NOCLIP ); + SetPaintTransparent( TRUE ); + mpWindowImpl->mbUseNativeFocus = (GetStyle() & WB_FLATBUTTON) + ? false + : ImplGetSVData()->maNWFData.mbNoFocusRects; + } + else + { + EnableChildTransparentMode( FALSE ); + SetParentClipMode( 0 ); + SetPaintTransparent( FALSE ); + } + } +} + +// ----------------------------------------------------------------------- + +void PushButton::ImplDrawPushButtonFrame( Window* pDev, + Rectangle& rRect, USHORT nStyle ) +{ + if ( !(pDev->GetStyle() & (WB_RECTSTYLE | WB_SMALLSTYLE)) ) + { + StyleSettings aStyleSettings = pDev->GetSettings().GetStyleSettings(); + if ( pDev->IsControlBackground() ) + aStyleSettings.Set3DColors( pDev->GetControlBackground() ); + + USHORT nPushButtonSysStyle = aStyleSettings.GetPushButtonStyle() & STYLE_PUSHBUTTON_STYLE; + if ( nPushButtonSysStyle == STYLE_PUSHBUTTON_MAC ) + { + pDev->SetLineColor(); + pDev->SetFillColor( aStyleSettings.GetFaceColor() ); + pDev->DrawRect( rRect ); + + if ( (aStyleSettings.GetOptions() & STYLE_OPTION_MONO) || + (pDev->GetOutDevType() == OUTDEV_PRINTER) ) + nStyle |= BUTTON_DRAW_MONO; + + if ( nStyle & BUTTON_DRAW_DEFAULT ) + { + if ( nStyle & BUTTON_DRAW_MONO ) + pDev->SetLineColor( Color( COL_BLACK ) ); + else + pDev->SetLineColor( aStyleSettings.GetDarkShadowColor() ); + + pDev->DrawLine( Point( rRect.Left()+3, rRect.Top() ), + Point( rRect.Right()-3, rRect.Top() ) ); + pDev->DrawLine( Point( rRect.Left()+3, rRect.Bottom() ), + Point( rRect.Right()-3, rRect.Bottom() ) ); + pDev->DrawLine( Point( rRect.Left(), rRect.Top()+3 ), + Point( rRect.Left(), rRect.Bottom()-3 ) ); + pDev->DrawLine( Point( rRect.Right(), rRect.Top()+3 ), + Point( rRect.Right(), rRect.Bottom()-3 ) ); + pDev->DrawPixel( Point( rRect.Left()+2, rRect.Top()+1 ) ); + pDev->DrawPixel( Point( rRect.Left()+1, rRect.Top()+2 ) ); + pDev->DrawPixel( Point( rRect.Right()-2, rRect.Top()+1 ) ); + pDev->DrawPixel( Point( rRect.Right()-1, rRect.Top()+2 ) ); + pDev->DrawPixel( Point( rRect.Left()+2, rRect.Bottom()-1 ) ); + pDev->DrawPixel( Point( rRect.Left()+1, rRect.Bottom()-2 ) ); + pDev->DrawPixel( Point( rRect.Right()-2, rRect.Bottom()-1 ) ); + pDev->DrawPixel( Point( rRect.Right()-1, rRect.Bottom()-2 ) ); + + if ( nStyle & BUTTON_DRAW_MONO ) + pDev->SetLineColor( Color( COL_BLACK ) ); + else + pDev->SetLineColor( aStyleSettings.GetShadowColor() ); + pDev->DrawLine( Point( rRect.Left()+3, rRect.Bottom()-1 ), + Point( rRect.Right()-3, rRect.Bottom()-1 ) ); + pDev->DrawLine( Point( rRect.Right()-1, rRect.Top()+3 ), + Point( rRect.Right()-1, rRect.Bottom()-3 ) ); + pDev->DrawPixel( Point( rRect.Right()-3, rRect.Bottom()-2 ) ); + pDev->DrawPixel( Point( rRect.Right()-2, rRect.Bottom()-2 ) ); + pDev->DrawPixel( Point( rRect.Right()-2, rRect.Bottom()-3 ) ); + } + + rRect.Left() += 2; + rRect.Top() += 2; + rRect.Right() -= 2; + rRect.Bottom() -= 2; + + if ( nStyle & BUTTON_DRAW_MONO ) + pDev->SetLineColor( Color( COL_BLACK ) ); + else + pDev->SetLineColor( aStyleSettings.GetDarkShadowColor() ); + + pDev->DrawLine( Point( rRect.Left()+2, rRect.Top() ), + Point( rRect.Right()-2, rRect.Top() ) ); + pDev->DrawLine( Point( rRect.Left()+2, rRect.Bottom() ), + Point( rRect.Right()-2, rRect.Bottom() ) ); + pDev->DrawLine( Point( rRect.Left(), rRect.Top()+2 ), + Point( rRect.Left(), rRect.Bottom()-2 ) ); + pDev->DrawLine( Point( rRect.Right(), rRect.Top()+2 ), + Point( rRect.Right(), rRect.Bottom()-2 ) ); + pDev->DrawPixel( Point( rRect.Left()+1, rRect.Top()+1 ) ); + pDev->DrawPixel( Point( rRect.Right()-1, rRect.Top()+1 ) ); + pDev->DrawPixel( Point( rRect.Left()+1, rRect.Bottom()-1 ) ); + pDev->DrawPixel( Point( rRect.Right()-1, rRect.Bottom()-1 ) ); + + pDev->SetLineColor(); + if ( nStyle & BUTTON_DRAW_CHECKED ) + pDev->SetFillColor( aStyleSettings.GetCheckedColor() ); + else + pDev->SetFillColor( aStyleSettings.GetFaceColor() ); + pDev->DrawRect( Rectangle( rRect.Left()+2, rRect.Top()+2, rRect.Right()-2, rRect.Bottom()-2 ) ); + + if ( !(nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED)) ) + { + if ( nStyle & BUTTON_DRAW_MONO ) + pDev->SetLineColor( Color( COL_BLACK ) ); + else + pDev->SetLineColor( aStyleSettings.GetShadowColor() ); + pDev->DrawLine( Point( rRect.Left()+2, rRect.Bottom()-1 ), + Point( rRect.Right()-2, rRect.Bottom()-1 ) ); + pDev->DrawLine( Point( rRect.Right()-1, rRect.Top()+2 ), + Point( rRect.Right()-1, rRect.Bottom()-2 ) ); + pDev->DrawPixel( Point( rRect.Right()-2, rRect.Bottom()-2 ) ); + pDev->SetLineColor( aStyleSettings.GetLightColor() ); + } + else + pDev->SetLineColor( aStyleSettings.GetShadowColor() ); + + if ( !(nStyle & BUTTON_DRAW_MONO) ) + { + pDev->DrawLine( Point( rRect.Left()+2, rRect.Top()+1 ), + Point( rRect.Right()-2, rRect.Top()+1 ) ); + pDev->DrawLine( Point( rRect.Left()+1, rRect.Top()+2 ), + Point( rRect.Left()+1, rRect.Bottom()-2 ) ); + pDev->DrawPixel( Point( rRect.Top()+2, rRect.Right()+2 ) ); + } + + rRect.Left() += 2; + rRect.Top() += 2; + rRect.Right() -= 2; + rRect.Bottom() -= 2; + + if ( nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED) ) + { + rRect.Left()++; + rRect.Top()++; + rRect.Right()++; + rRect.Bottom()++; + } + + return; + } + } + + DecorationView aDecoView( pDev ); + if ( pDev->IsControlBackground() ) + { + AllSettings aSettings = pDev->GetSettings(); + AllSettings aOldSettings = aSettings; + StyleSettings aStyleSettings = aSettings.GetStyleSettings(); + aStyleSettings.Set3DColors( pDev->GetControlBackground() ); + aSettings.SetStyleSettings( aStyleSettings ); + pDev->OutputDevice::SetSettings( aSettings ); + rRect = aDecoView.DrawButton( rRect, nStyle ); + pDev->OutputDevice::SetSettings( aOldSettings ); + } + else + rRect = aDecoView.DrawButton( rRect, nStyle ); +} + +// ----------------------------------------------------------------------- + +BOOL PushButton::ImplHitTestPushButton( Window* pDev, + const Point& rPos ) +{ + Point aTempPoint; + Rectangle aTestRect( aTempPoint, pDev->GetOutputSizePixel() ); + + if ( !(pDev->GetStyle() & (WB_RECTSTYLE | WB_SMALLSTYLE)) ) + { + const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings(); + + USHORT nPushButtonSysStyle = rStyleSettings.GetPushButtonStyle() & STYLE_PUSHBUTTON_STYLE; + if ( nPushButtonSysStyle == STYLE_PUSHBUTTON_MAC ) + { + aTestRect.Left() += 2; + aTestRect.Top() += 2; + aTestRect.Right() -= 2; + aTestRect.Bottom() -= 2; + } + } + + return aTestRect.IsInside( rPos ); +} + +// ----------------------------------------------------------------------- + +USHORT PushButton::ImplGetTextStyle( ULONG nDrawFlags ) const +{ + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + + USHORT nTextStyle = TEXT_DRAW_MNEMONIC | TEXT_DRAW_MULTILINE | TEXT_DRAW_ENDELLIPSIS; + + if ( ( rStyleSettings.GetOptions() & STYLE_OPTION_MONO ) || + ( nDrawFlags & WINDOW_DRAW_MONO ) ) + nTextStyle |= TEXT_DRAW_MONO; + + if ( GetStyle() & WB_WORDBREAK ) + nTextStyle |= TEXT_DRAW_WORDBREAK; + if ( GetStyle() & WB_NOLABEL ) + nTextStyle &= ~TEXT_DRAW_MNEMONIC; + + if ( GetStyle() & WB_LEFT ) + nTextStyle |= TEXT_DRAW_LEFT; + else if ( GetStyle() & WB_RIGHT ) + nTextStyle |= TEXT_DRAW_RIGHT; + else + nTextStyle |= TEXT_DRAW_CENTER; + + if ( GetStyle() & WB_TOP ) + nTextStyle |= TEXT_DRAW_TOP; + else if ( GetStyle() & WB_BOTTOM ) + nTextStyle |= TEXT_DRAW_BOTTOM; + else + nTextStyle |= TEXT_DRAW_VCENTER; + + if ( ! ( (nDrawFlags & WINDOW_DRAW_NODISABLE) || IsEnabled() ) ) + nTextStyle |= TEXT_DRAW_DISABLE; + + return nTextStyle; +} + +// ----------------------------------------------------------------------- + +static void ImplDrawBtnDropDownArrow( OutputDevice* pDev, + long nX, long nY, + Color& rColor, BOOL bBlack ) +{ + Color aOldLineColor = pDev->GetLineColor(); + Color aOldFillColor = pDev->GetFillColor(); + + pDev->SetLineColor(); + if ( bBlack ) + pDev->SetFillColor( Color( COL_BLACK ) ); + else + pDev->SetFillColor( rColor ); + pDev->DrawRect( Rectangle( nX+0, nY+0, nX+6, nY+0 ) ); + pDev->DrawRect( Rectangle( nX+1, nY+1, nX+5, nY+1 ) ); + pDev->DrawRect( Rectangle( nX+2, nY+2, nX+4, nY+2 ) ); + pDev->DrawRect( Rectangle( nX+3, nY+3, nX+3, nY+3 ) ); + if ( bBlack ) + { + pDev->SetFillColor( rColor ); + pDev->DrawRect( Rectangle( nX+2, nY+1, nX+4, nY+1 ) ); + pDev->DrawRect( Rectangle( nX+3, nY+2, nX+3, nY+2 ) ); + } + pDev->SetLineColor( aOldLineColor ); + pDev->SetFillColor( aOldFillColor ); +} + +// ----------------------------------------------------------------------- + +void PushButton::ImplDrawPushButtonContent( OutputDevice* pDev, ULONG nDrawFlags, + const Rectangle& rRect, + bool bLayout, + bool bMenuBtnSep + ) +{ + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + Rectangle aInRect = rRect; + Color aColor; + XubString aText = PushButton::GetText(); // PushButton:: wegen MoreButton + USHORT nTextStyle = ImplGetTextStyle( nDrawFlags ); + USHORT nStyle; + + if( aInRect.nRight < aInRect.nLeft || aInRect.nBottom < aInRect.nTop ) + aInRect.SetEmpty(); + + pDev->Push( PUSH_CLIPREGION ); + pDev->IntersectClipRegion( aInRect ); + + if ( nDrawFlags & WINDOW_DRAW_MONO ) + aColor = Color( COL_BLACK ); + else if ( IsControlForeground() ) + aColor = GetControlForeground(); + else if( nDrawFlags & WINDOW_DRAW_ROLLOVER ) + aColor = rStyleSettings.GetButtonRolloverTextColor(); + else + aColor = rStyleSettings.GetButtonTextColor(); + + pDev->SetTextColor( aColor ); + + if ( IsEnabled() || (nDrawFlags & WINDOW_DRAW_NODISABLE) ) + nStyle = 0; + else + nStyle = SYMBOL_DRAW_DISABLE; + + Size aSize = rRect.GetSize(); + Point aPos = rRect.TopLeft(); + + ULONG nImageSep = 1 + (pDev->GetTextHeight()-10)/2; + if( nImageSep < 1 ) + nImageSep = 1; + if ( mnDDStyle == PUSHBUTTON_DROPDOWN_MENUBUTTON ) + { + if ( aText.Len() && ! (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) ) + { + // calc Symbol- and Textrect + long nSymbolSize = pDev->GetTextHeight() / 2 + 1; + aInRect.Right() -= 5; + aInRect.Left() = aInRect.Right() - nSymbolSize; + aSize.Width() -= ( 5 + nSymbolSize ); + + ImplDrawAlignedImage( pDev, aPos, aSize, bLayout, nImageSep, + nDrawFlags, nTextStyle, NULL, true ); + } + else + ImplCalcSymbolRect( aInRect ); + + if( ! bLayout ) + { + long nDistance = (aInRect.GetHeight() > 10) ? 2 : 1; + DecorationView aDecoView( pDev ); + if( bMenuBtnSep ) + { + long nX = aInRect.Left() - 2*nDistance;; + Point aStartPt( nX, aInRect.Top()+nDistance ); + Point aEndPt( nX, aInRect.Bottom()-nDistance ); + aDecoView.DrawSeparator( aStartPt, aEndPt ); + } + aDecoView.DrawSymbol( aInRect, SYMBOL_SPIN_DOWN, aColor, nStyle ); + aInRect.Left() -= 2*nDistance; + ImplSetSymbolRect( aInRect ); + } + } + else + { + Rectangle aSymbolRect; + // FIXME: (GetStyle() & WB_FLATBUTTON) != 0 is preliminary + // in the next major this should be replaced by "true" + ImplDrawAlignedImage( pDev, aPos, aSize, bLayout, nImageSep, nDrawFlags, + nTextStyle, IsSymbol() ? &aSymbolRect : NULL, true ); + + if ( IsSymbol() && ! bLayout ) + { + DecorationView aDecoView( pDev ); + aDecoView.DrawSymbol( aSymbolRect, meSymbol, aColor, nStyle ); + ImplSetSymbolRect( aSymbolRect ); + } + + if ( mnDDStyle == PUSHBUTTON_DROPDOWN_TOOLBOX && !bLayout ) + { + BOOL bBlack = FALSE; + Color aArrowColor( COL_BLACK ); + + if ( !(nDrawFlags & WINDOW_DRAW_MONO) ) + { + if ( !IsEnabled() ) + aArrowColor = rStyleSettings.GetShadowColor(); + else + { + aArrowColor = Color( COL_LIGHTGREEN ); + bBlack = TRUE; + } + } + + ImplDrawBtnDropDownArrow( pDev, aInRect.Right()-6, aInRect.Top()+1, + aArrowColor, bBlack ); + } + } + + UserDrawEvent aUDEvt( this, aInRect, 0 ); + UserDraw( aUDEvt ); + + pDev->Pop(); // restore clipregion +} + +// ----------------------------------------------------------------------- + +void PushButton::UserDraw( const UserDrawEvent& ) +{ +} + +// ----------------------------------------------------------------------- + +void PushButton::ImplDrawPushButton( bool bLayout ) +{ + if( !bLayout ) + HideFocus(); + + USHORT nButtonStyle = ImplGetButtonState(); + Point aPoint; + Size aOutSz( GetOutputSizePixel() ); + Rectangle aRect( aPoint, aOutSz ); + Rectangle aInRect = aRect; + Rectangle aTextRect; + BOOL bNativeOK = FALSE; + + // adjust style if button should be rendered 'pressed' + if ( mbPressed ) + nButtonStyle |= BUTTON_DRAW_PRESSED; + + // TODO: move this to Window class or make it a member !!! + ControlType aCtrlType = 0; + switch( GetParent()->GetType() ) + { + case WINDOW_LISTBOX: + case WINDOW_MULTILISTBOX: + case WINDOW_TREELISTBOX: + aCtrlType = CTRL_LISTBOX; + break; + + case WINDOW_COMBOBOX: + case WINDOW_PATTERNBOX: + case WINDOW_NUMERICBOX: + case WINDOW_METRICBOX: + case WINDOW_CURRENCYBOX: + case WINDOW_DATEBOX: + case WINDOW_TIMEBOX: + case WINDOW_LONGCURRENCYBOX: + aCtrlType = CTRL_COMBOBOX; + break; + default: + break; + } + + BOOL bDropDown = ( IsSymbol() && (GetSymbol()==SYMBOL_SPIN_DOWN) && !GetText().Len() ); + + if( bDropDown && (aCtrlType == CTRL_COMBOBOX || aCtrlType == CTRL_LISTBOX ) ) + { + if( GetParent()->IsNativeControlSupported( aCtrlType, PART_ENTIRE_CONTROL) ) + { + // skip painting if the button was already drawn by the theme + if( aCtrlType == CTRL_COMBOBOX ) + { + Edit* pEdit = static_cast<Edit*>(GetParent()); + if( pEdit->ImplUseNativeBorder( pEdit->GetStyle() ) ) + bNativeOK = TRUE; + } + else if( GetParent()->IsNativeControlSupported( aCtrlType, HAS_BACKGROUND_TEXTURE) ) + { + bNativeOK = TRUE; + } + if( !bNativeOK && GetParent()->IsNativeControlSupported( aCtrlType, PART_BUTTON_DOWN ) ) + { + // let the theme draw it, note we then need support + // for CTRL_LISTBOX/PART_BUTTON_DOWN and CTRL_COMBOBOX/PART_BUTTON_DOWN + + ImplControlValue aControlValue; + ControlState nState = 0; + + if ( mbPressed ) nState |= CTRL_STATE_PRESSED; + if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED ) nState |= CTRL_STATE_PRESSED; + if ( HasFocus() ) nState |= CTRL_STATE_FOCUSED; + if ( ImplGetButtonState() & BUTTON_DRAW_DEFAULT ) nState |= CTRL_STATE_DEFAULT; + if ( Window::IsEnabled() ) nState |= CTRL_STATE_ENABLED; + + if ( IsMouseOver() && aInRect.IsInside( GetPointerPosPixel() ) ) + nState |= CTRL_STATE_ROLLOVER; + + bNativeOK = DrawNativeControl( aCtrlType, PART_BUTTON_DOWN, aInRect, nState, + aControlValue, rtl::OUString() ); + } + } + } + + if( bNativeOK ) + return; + + bool bRollOver = (IsMouseOver() && aInRect.IsInside( GetPointerPosPixel() )); + bool bDrawMenuSep = true; + if( (GetStyle() & WB_FLATBUTTON) ) + { + if( ! bRollOver && ! HasFocus() ) + bDrawMenuSep = false; + } + if ( (bNativeOK=IsNativeControlSupported(CTRL_PUSHBUTTON, PART_ENTIRE_CONTROL)) == TRUE ) + { + PushButtonValue aControlValue; + Rectangle aCtrlRegion( aInRect ); + ControlState nState = 0; + + if ( mbPressed || IsChecked() ) nState |= CTRL_STATE_PRESSED; + if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED ) nState |= CTRL_STATE_PRESSED; + if ( HasFocus() ) nState |= CTRL_STATE_FOCUSED; + if ( ImplGetButtonState() & BUTTON_DRAW_DEFAULT ) nState |= CTRL_STATE_DEFAULT; + if ( Window::IsEnabled() ) nState |= CTRL_STATE_ENABLED; + + if ( bRollOver ) + nState |= CTRL_STATE_ROLLOVER; + + if( GetStyle() & WB_BEVELBUTTON ) + aControlValue.mbBevelButton = true; + + // draw frame into invisible window to have aInRect modified correctly + // but do not shift the inner rect for pressed buttons (ie remove BUTTON_DRAW_PRESSED) + // this assumes the theme has enough visual cues to signalize the button was pressed + //Window aWin( this ); + //ImplDrawPushButtonFrame( &aWin, aInRect, nButtonStyle & ~BUTTON_DRAW_PRESSED ); + + // looks better this way as symbols were displaced slightly using the above approach + aInRect.Top()+=4; + aInRect.Bottom()-=4; + aInRect.Left()+=4; + aInRect.Right()-=4; + + // prepare single line hint (needed on mac to decide between normal push button and + // rectangular bevel button look) + Size aFontSize( Application::GetSettings().GetStyleSettings().GetPushButtonFont().GetSize() ); + aFontSize = LogicToPixel( aFontSize, MapMode( MAP_POINT ) ); + Size aInRectSize( LogicToPixel( Size( aInRect.GetWidth(), aInRect.GetHeight() ) ) ); + aControlValue.mbSingleLine = (aInRectSize.Height() < 2 * aFontSize.Height() ); + + if( ((nState & CTRL_STATE_ROLLOVER)) || ! (GetStyle() & WB_FLATBUTTON) ) + { + bNativeOK = DrawNativeControl( CTRL_PUSHBUTTON, PART_ENTIRE_CONTROL, aCtrlRegion, nState, + aControlValue, rtl::OUString()/*PushButton::GetText()*/ ); + } + else + { + bNativeOK = true; + } + + // draw content using the same aInRect as non-native VCL would do + ImplDrawPushButtonContent( this, + (nState&CTRL_STATE_ROLLOVER) ? WINDOW_DRAW_ROLLOVER : 0, + aInRect, bLayout, bDrawMenuSep ); + + if ( HasFocus() ) + ShowFocus( ImplGetFocusRect() ); + } + + if ( bNativeOK == FALSE ) + { + // draw PushButtonFrame, aInRect has content size afterwards + if( (GetStyle() & WB_FLATBUTTON) ) + { + Rectangle aTempRect( aInRect ); + if( ! bLayout && bRollOver ) + ImplDrawPushButtonFrame( this, aTempRect, nButtonStyle ); + aInRect.Left() += 2; + aInRect.Top() += 2; + aInRect.Right() -= 2; + aInRect.Bottom() -= 2; + } + else + { + if( ! bLayout ) + ImplDrawPushButtonFrame( this, aInRect, nButtonStyle ); + } + + // draw content + ImplDrawPushButtonContent( this, 0, aInRect, bLayout, bDrawMenuSep ); + + if( ! bLayout && HasFocus() ) + { + ShowFocus( ImplGetFocusRect() ); + } + } +} + +// ----------------------------------------------------------------------- + +void PushButton::ImplSetDefButton( BOOL bSet ) +{ + Size aSize( GetSizePixel() ); + Point aPos( GetPosPixel() ); + int dLeft(0), dRight(0), dTop(0), dBottom(0); + BOOL bSetPos = FALSE; + + if ( (IsNativeControlSupported(CTRL_PUSHBUTTON, PART_ENTIRE_CONTROL)) == TRUE ) + { + Rectangle aBound, aCont; + Rectangle aCtrlRect( 0, 0, 80, 20 ); // use a constant size to avoid accumulating + // will not work if the theme has dynamic adornment sizes + ImplControlValue aControlValue; + Rectangle aCtrlRegion( aCtrlRect ); + ControlState nState = CTRL_STATE_DEFAULT|CTRL_STATE_ENABLED; + + // get native size of a 'default' button + // and adjust the VCL button if more space for adornment is required + if( GetNativeControlRegion( CTRL_PUSHBUTTON, PART_ENTIRE_CONTROL, aCtrlRegion, + nState, aControlValue, rtl::OUString(), + aBound, aCont ) ) + { + dLeft = aCont.Left() - aBound.Left(); + dTop = aCont.Top() - aBound.Top(); + dRight = aBound.Right() - aCont.Right(); + dBottom = aBound.Bottom() - aCont.Bottom(); + bSetPos = dLeft || dTop || dRight || dBottom; + } + } + + if ( bSet ) + { + if( !(ImplGetButtonState() & BUTTON_DRAW_DEFAULT) && bSetPos ) + { + // adjust pos/size when toggling from non-default to default + aPos.Move(-dLeft, -dTop); + aSize.Width() += dLeft + dRight; + aSize.Height() += dTop + dBottom; + } + ImplGetButtonState() |= BUTTON_DRAW_DEFAULT; + } + else + { + if( (ImplGetButtonState() & BUTTON_DRAW_DEFAULT) && bSetPos ) + { + // adjust pos/size when toggling from default to non-default + aPos.Move(dLeft, dTop); + aSize.Width() -= dLeft + dRight; + aSize.Height() -= dTop + dBottom; + } + ImplGetButtonState() &= ~BUTTON_DRAW_DEFAULT; + } + if( bSetPos ) + SetPosSizePixel( aPos.X(), aPos.Y(), aSize.Width(), aSize.Height(), WINDOW_POSSIZE_ALL ); + + Invalidate(); +} + +// ----------------------------------------------------------------------- + +BOOL PushButton::ImplIsDefButton() const +{ + return (ImplGetButtonState() & BUTTON_DRAW_DEFAULT) != 0; +} + +// ----------------------------------------------------------------------- + +PushButton::PushButton( WindowType nType ) : + Button( nType ) +{ + ImplInitPushButtonData(); +} + +// ----------------------------------------------------------------------- + +PushButton::PushButton( Window* pParent, WinBits nStyle ) : + Button( WINDOW_PUSHBUTTON ) +{ + ImplInitPushButtonData(); + ImplInit( pParent, nStyle ); +} + +// ----------------------------------------------------------------------- + +PushButton::PushButton( Window* pParent, const ResId& rResId ) : + Button( WINDOW_PUSHBUTTON ) +{ + ImplInitPushButtonData(); + rResId.SetRT( RSC_PUSHBUTTON ); + WinBits nStyle = ImplInitRes( rResId ); + ImplInit( pParent, nStyle ); + ImplLoadRes( rResId ); + + if ( !(nStyle & WB_HIDE) ) + Show(); +} + +// ----------------------------------------------------------------------- + +PushButton::~PushButton() +{ +} + +// ----------------------------------------------------------------------- + +void PushButton::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if ( rMEvt.IsLeft() && + ImplHitTestPushButton( this, rMEvt.GetPosPixel() ) ) + { + USHORT nTrackFlags = 0; + + if ( ( GetStyle() & WB_REPEAT ) && + ! ( GetStyle() & WB_TOGGLE ) ) + nTrackFlags |= STARTTRACK_BUTTONREPEAT; + + ImplGetButtonState() |= BUTTON_DRAW_PRESSED; + ImplDrawPushButton(); + StartTracking( nTrackFlags ); + + if ( nTrackFlags & STARTTRACK_BUTTONREPEAT ) + Click(); + } +} + +// ----------------------------------------------------------------------- + +void PushButton::Tracking( const TrackingEvent& rTEvt ) +{ + if ( rTEvt.IsTrackingEnded() ) + { + if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED ) + { + if ( !(GetStyle() & WB_NOPOINTERFOCUS) && !rTEvt.IsTrackingCanceled() ) + GrabFocus(); + + if ( GetStyle() & WB_TOGGLE ) + { + // Don't toggle, when aborted + if ( !rTEvt.IsTrackingCanceled() ) + { + if ( IsChecked() ) + { + Check( FALSE ); + ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED; + } + else + Check( TRUE ); + } + } + else + ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED; + + ImplDrawPushButton(); + + // Bei Abbruch kein Click-Handler rufen + if ( !rTEvt.IsTrackingCanceled() ) + { + if ( ! ( ( GetStyle() & WB_REPEAT ) && + ! ( GetStyle() & WB_TOGGLE ) ) ) + Click(); + } + } + } + else + { + if ( ImplHitTestPushButton( this, rTEvt.GetMouseEvent().GetPosPixel() ) ) + { + if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED ) + { + if ( rTEvt.IsTrackingRepeat() && (GetStyle() & WB_REPEAT) && + ! ( GetStyle() & WB_TOGGLE ) ) + Click(); + } + else + { + ImplGetButtonState() |= BUTTON_DRAW_PRESSED; + ImplDrawPushButton(); + } + } + else + { + if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED ) + { + ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED; + ImplDrawPushButton(); + } + } + } +} + +// ----------------------------------------------------------------------- + +void PushButton::KeyInput( const KeyEvent& rKEvt ) +{ + KeyCode aKeyCode = rKEvt.GetKeyCode(); + + if ( !aKeyCode.GetModifier() && + ((aKeyCode.GetCode() == KEY_RETURN) || (aKeyCode.GetCode() == KEY_SPACE)) ) + { + if ( !(ImplGetButtonState() & BUTTON_DRAW_PRESSED) ) + { + ImplGetButtonState() |= BUTTON_DRAW_PRESSED; + ImplDrawPushButton(); + } + + if ( ( GetStyle() & WB_REPEAT ) && + ! ( GetStyle() & WB_TOGGLE ) ) + Click(); + } + else if ( (ImplGetButtonState() & BUTTON_DRAW_PRESSED) && (aKeyCode.GetCode() == KEY_ESCAPE) ) + { + ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED; + ImplDrawPushButton(); + } + else + Button::KeyInput( rKEvt ); +} + +// ----------------------------------------------------------------------- + +void PushButton::KeyUp( const KeyEvent& rKEvt ) +{ + KeyCode aKeyCode = rKEvt.GetKeyCode(); + + if ( (ImplGetButtonState() & BUTTON_DRAW_PRESSED) && + ((aKeyCode.GetCode() == KEY_RETURN) || (aKeyCode.GetCode() == KEY_SPACE)) ) + { + if ( GetStyle() & WB_TOGGLE ) + { + if ( IsChecked() ) + { + Check( FALSE ); + ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED; + } + else + Check( TRUE ); + + Toggle(); + } + else + ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED; + + ImplDrawPushButton(); + + if ( !( ( GetStyle() & WB_REPEAT ) && + ! ( GetStyle() & WB_TOGGLE ) ) ) + Click(); + } + else + Button::KeyUp( rKEvt ); +} + +// ----------------------------------------------------------------------- + +void PushButton::FillLayoutData() const +{ + mpControlData->mpLayoutData = new vcl::ControlLayoutData(); + const_cast<PushButton*>(this)->ImplDrawPushButton( true ); +} + +// ----------------------------------------------------------------------- + +void PushButton::Paint( const Rectangle& ) +{ + ImplDrawPushButton(); +} + +// ----------------------------------------------------------------------- + +void PushButton::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, + ULONG nFlags ) +{ + Point aPos = pDev->LogicToPixel( rPos ); + Size aSize = pDev->LogicToPixel( rSize ); + Rectangle aRect( aPos, aSize ); + Rectangle aTextRect; + Font aFont = GetDrawPixelFont( pDev ); + + pDev->Push(); + pDev->SetMapMode(); + pDev->SetFont( aFont ); + if ( nFlags & WINDOW_DRAW_MONO ) + { + pDev->SetTextColor( Color( COL_BLACK ) ); + } + else + { + pDev->SetTextColor( GetTextColor() ); + + // DecoView uses the FaceColor... + AllSettings aSettings = pDev->GetSettings(); + StyleSettings aStyleSettings = aSettings.GetStyleSettings(); + if ( IsControlBackground() ) + aStyleSettings.SetFaceColor( GetControlBackground() ); + else + aStyleSettings.SetFaceColor( GetSettings().GetStyleSettings().GetFaceColor() ); + aSettings.SetStyleSettings( aStyleSettings ); + pDev->SetSettings( aSettings ); + } + pDev->SetTextFillColor(); + + DecorationView aDecoView( pDev ); + USHORT nButtonStyle = 0; + if ( nFlags & WINDOW_DRAW_MONO ) + nButtonStyle |= BUTTON_DRAW_MONO; + if ( IsChecked() ) + nButtonStyle |= BUTTON_DRAW_CHECKED; + aRect = aDecoView.DrawButton( aRect, nButtonStyle ); + + ImplDrawPushButtonContent( pDev, nFlags, aRect, false, true ); + pDev->Pop(); +} + +// ----------------------------------------------------------------------- + +void PushButton::Resize() +{ + Control::Resize(); + Invalidate(); +} + +// ----------------------------------------------------------------------- + +void PushButton::GetFocus() +{ + ShowFocus( ImplGetFocusRect() ); + SetInputContext( InputContext( GetFont() ) ); + Button::GetFocus(); +} + +// ----------------------------------------------------------------------- + +void PushButton::LoseFocus() +{ + EndSelection(); + HideFocus(); + Button::LoseFocus(); +} + +// ----------------------------------------------------------------------- + +void PushButton::StateChanged( StateChangedType nType ) +{ + Button::StateChanged( nType ); + + if ( (nType == STATE_CHANGE_ENABLE) || + (nType == STATE_CHANGE_TEXT) || + (nType == STATE_CHANGE_IMAGE) || + (nType == STATE_CHANGE_DATA) || + (nType == STATE_CHANGE_STATE) || + (nType == STATE_CHANGE_UPDATEMODE) ) + { + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate(); + } + else if ( nType == STATE_CHANGE_STYLE ) + { + SetStyle( ImplInitStyle( GetWindow( WINDOW_PREV ), GetStyle() ) ); + + bool bIsDefButton = ( GetStyle() & WB_DEFBUTTON ) != 0; + bool bWasDefButton = ( GetPrevStyle() & WB_DEFBUTTON ) != 0; + if ( bIsDefButton != bWasDefButton ) + ImplSetDefButton( bIsDefButton ); + + if ( IsReallyVisible() && IsUpdateMode() ) + { + if ( (GetPrevStyle() & PUSHBUTTON_VIEW_STYLE) != + (GetStyle() & PUSHBUTTON_VIEW_STYLE) ) + Invalidate(); + } + } + else if ( (nType == STATE_CHANGE_ZOOM) || + (nType == STATE_CHANGE_CONTROLFONT) ) + { + ImplInitSettings( TRUE, FALSE, FALSE ); + Invalidate(); + } + else if ( nType == STATE_CHANGE_CONTROLFOREGROUND ) + { + ImplInitSettings( FALSE, TRUE, FALSE ); + Invalidate(); + } + else if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) + { + ImplInitSettings( FALSE, FALSE, TRUE ); + Invalidate(); + } +} + +// ----------------------------------------------------------------------- + +void PushButton::DataChanged( const DataChangedEvent& rDCEvt ) +{ + Button::DataChanged( rDCEvt ); + + if ( (rDCEvt.GetType() == DATACHANGED_FONTS) || + (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) || + ((rDCEvt.GetType() == DATACHANGED_SETTINGS) && + (rDCEvt.GetFlags() & SETTINGS_STYLE)) ) + { + ImplInitSettings( TRUE, TRUE, TRUE ); + Invalidate(); + } +} + +// ----------------------------------------------------------------------- + +long PushButton::PreNotify( NotifyEvent& rNEvt ) +{ + long nDone = 0; + const MouseEvent* pMouseEvt = NULL; + + if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL ) + { + if( pMouseEvt->IsEnterWindow() || pMouseEvt->IsLeaveWindow() ) + { + // trigger redraw as mouse over state has changed + + // TODO: move this to Window class or make it a member !!! + ControlType aCtrlType = 0; + switch( GetParent()->GetType() ) + { + case WINDOW_LISTBOX: + case WINDOW_MULTILISTBOX: + case WINDOW_TREELISTBOX: + aCtrlType = CTRL_LISTBOX; + break; + + case WINDOW_COMBOBOX: + case WINDOW_PATTERNBOX: + case WINDOW_NUMERICBOX: + case WINDOW_METRICBOX: + case WINDOW_CURRENCYBOX: + case WINDOW_DATEBOX: + case WINDOW_TIMEBOX: + case WINDOW_LONGCURRENCYBOX: + aCtrlType = CTRL_COMBOBOX; + break; + default: + break; + } + + BOOL bDropDown = ( IsSymbol() && (GetSymbol()==SYMBOL_SPIN_DOWN) && !GetText().Len() ); + + if( bDropDown && GetParent()->IsNativeControlSupported( aCtrlType, PART_ENTIRE_CONTROL) && + !GetParent()->IsNativeControlSupported( aCtrlType, PART_BUTTON_DOWN) ) + { + Window *pBorder = GetParent()->GetWindow( WINDOW_BORDER ); + if(aCtrlType == CTRL_COMBOBOX) + { + // only paint the button part to avoid flickering of the combobox text + Point aPt; + Rectangle aClipRect( aPt, GetOutputSizePixel() ); + aClipRect.SetPos(pBorder->ScreenToOutputPixel(OutputToScreenPixel(aClipRect.TopLeft()))); + pBorder->Invalidate( aClipRect ); + } + else + { + pBorder->Invalidate( INVALIDATE_NOERASE ); + pBorder->Update(); + } + } + else if( (GetStyle() & WB_FLATBUTTON) || + IsNativeControlSupported(CTRL_PUSHBUTTON, PART_ENTIRE_CONTROL) ) + { + Invalidate(); + } + } + } + + return nDone ? nDone : Button::PreNotify(rNEvt); +} + +// ----------------------------------------------------------------------- + +void PushButton::Toggle() +{ + ImplCallEventListenersAndHandler( VCLEVENT_PUSHBUTTON_TOGGLE, maToggleHdl, this ); +} + +// ----------------------------------------------------------------------- + +void PushButton::SetSymbol( SymbolType eSymbol ) +{ + if ( meSymbol != eSymbol ) + { + meSymbol = eSymbol; + StateChanged( STATE_CHANGE_DATA ); + } +} + +// ----------------------------------------------------------------------- +void PushButton::SetSymbolAlign( SymbolAlign eAlign ) +{ + ImplSetSymbolAlign( eAlign ); +} + +// ----------------------------------------------------------------------- +SymbolAlign PushButton::GetSymbolAlign() const +{ + return ImplGetSymbolAlign(); +} + +// ----------------------------------------------------------------------- + +void PushButton::SetDropDown( USHORT nStyle ) +{ + if ( mnDDStyle != nStyle ) + { + mnDDStyle = nStyle; + StateChanged( STATE_CHANGE_DATA ); + } +} + +// ----------------------------------------------------------------------- + +void PushButton::SetState( TriState eState ) +{ + if ( meState != eState ) + { + meState = eState; + if ( meState == STATE_NOCHECK ) + ImplGetButtonState() &= ~(BUTTON_DRAW_CHECKED | BUTTON_DRAW_DONTKNOW); + else if ( meState == STATE_CHECK ) + { + ImplGetButtonState() &= ~BUTTON_DRAW_DONTKNOW; + ImplGetButtonState() |= BUTTON_DRAW_CHECKED; + } + else // STATE_DONTKNOW + { + ImplGetButtonState() &= ~BUTTON_DRAW_CHECKED; + ImplGetButtonState() |= BUTTON_DRAW_DONTKNOW; + } + + StateChanged( STATE_CHANGE_STATE ); + Toggle(); + } +} + +// ----------------------------------------------------------------------- + +void PushButton::SetPressed( BOOL bPressed ) +{ + if ( mbPressed != bPressed ) + { + mbPressed = bPressed; + StateChanged( STATE_CHANGE_DATA ); + } +} + +// ----------------------------------------------------------------------- + +void PushButton::EndSelection() +{ + EndTracking( ENDTRACK_CANCEL ); + if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED ) + { + ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED; + if ( !mbPressed ) + ImplDrawPushButton(); + } +} + +// ----------------------------------------------------------------------- + +Size PushButton::CalcMinimumSize( long nMaxWidth ) const +{ + Size aSize; + + if ( IsSymbol() ) + { + if ( IsSmallSymbol ()) + aSize = Size( 16, 12 ); + else + aSize = Size( 26, 24 ); + if( mnDDStyle == PUSHBUTTON_DROPDOWN_MENUBUTTON ) + aSize.Width() += 4; + } + else if ( IsImage() && ! (ImplGetButtonState() & BUTTON_DRAW_NOIMAGE) ) + aSize = GetModeImage().GetSizePixel(); + if ( PushButton::GetText().Len() && ! (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) ) + { + ULONG nDrawFlags = 0; + Size textSize = GetTextRect( Rectangle( Point(), Size( nMaxWidth ? nMaxWidth : 0x7fffffff, 0x7fffffff ) ), + PushButton::GetText(), ImplGetTextStyle( nDrawFlags ) ).GetSize(); + aSize.Width() += int( textSize.Width () * 1.15 ); + aSize.Height() = std::max( aSize.Height(), long( textSize.Height() * 1.15 ) ); + } + + // cf. ImplDrawPushButton ... + if( (GetStyle() & WB_SMALLSTYLE) == 0 ) + { + aSize.Width() += 8; + aSize.Height() += 8; + } + + return CalcWindowSize( aSize ); +} + +Size PushButton::GetOptimalSize(WindowSizeType eType) const +{ + switch (eType) { + case WINDOWSIZE_MINIMUM: { + return CalcMinimumSize(); + } + default: + return Button::GetOptimalSize( eType ); + } +} + +// ======================================================================= + +void OKButton::ImplInit( Window* pParent, WinBits nStyle ) +{ + PushButton::ImplInit( pParent, nStyle ); + + SetText( Button::GetStandardText( BUTTON_OK ) ); + SetHelpText( Button::GetStandardHelpText( BUTTON_OK ) ); +} + +// ----------------------------------------------------------------------- + +OKButton::OKButton( Window* pParent, WinBits nStyle ) : + PushButton( WINDOW_OKBUTTON ) +{ + ImplInit( pParent, nStyle ); +} + +// ----------------------------------------------------------------------- + +OKButton::OKButton( Window* pParent, const ResId& rResId ) : + PushButton( WINDOW_OKBUTTON ) +{ + rResId.SetRT( RSC_OKBUTTON ); + WinBits nStyle = ImplInitRes( rResId ); + ImplInit( pParent, nStyle ); + ImplLoadRes( rResId ); + + if ( !(nStyle & WB_HIDE) ) + Show(); +} + +// ----------------------------------------------------------------------- + +void OKButton::Click() +{ + // Ist kein Link gesetzt, dann schliesse Parent + if ( !GetClickHdl() ) + { + Window* pParent = GetParent(); + if ( pParent->IsSystemWindow() ) + { + if ( pParent->IsDialog() ) + { + if ( ((Dialog*)pParent)->IsInExecute() ) + ((Dialog*)pParent)->EndDialog( TRUE ); + // gegen rekursive Aufrufe schuetzen + else if ( !((Dialog*)pParent)->IsInClose() ) + { + if ( pParent->GetStyle() & WB_CLOSEABLE ) + ((Dialog*)pParent)->Close(); + } + } + else + { + if ( pParent->GetStyle() & WB_CLOSEABLE ) + ((SystemWindow*)pParent)->Close(); + } + } + } + else + { + PushButton::Click(); + } +} + +// ======================================================================= + +void CancelButton::ImplInit( Window* pParent, WinBits nStyle ) +{ + PushButton::ImplInit( pParent, nStyle ); + + SetText( Button::GetStandardText( BUTTON_CANCEL ) ); + SetHelpText( Button::GetStandardHelpText( BUTTON_CANCEL ) ); +} + +// ----------------------------------------------------------------------- + +CancelButton::CancelButton( Window* pParent, WinBits nStyle ) : + PushButton( WINDOW_CANCELBUTTON ) +{ + ImplInit( pParent, nStyle ); +} + +// ----------------------------------------------------------------------- + +CancelButton::CancelButton( Window* pParent, const ResId& rResId ) : + PushButton( WINDOW_CANCELBUTTON ) +{ + rResId.SetRT( RSC_CANCELBUTTON ); + WinBits nStyle = ImplInitRes( rResId ); + ImplInit( pParent, nStyle ); + ImplLoadRes( rResId ); + + if ( !(nStyle & WB_HIDE) ) + Show(); +} + +// ----------------------------------------------------------------------- + +void CancelButton::Click() +{ + // Ist kein Link gesetzt, dann schliesse Parent + if ( !GetClickHdl() ) + { + Window* pParent = GetParent(); + if ( pParent->IsSystemWindow() ) + { + if ( pParent->IsDialog() ) + { + if ( ((Dialog*)pParent)->IsInExecute() ) + ((Dialog*)pParent)->EndDialog( FALSE ); + // gegen rekursive Aufrufe schuetzen + else if ( !((Dialog*)pParent)->IsInClose() ) + { + if ( pParent->GetStyle() & WB_CLOSEABLE ) + ((Dialog*)pParent)->Close(); + } + } + else + { + if ( pParent->GetStyle() & WB_CLOSEABLE ) + ((SystemWindow*)pParent)->Close(); + } + } + } + else + { + PushButton::Click(); + } +} + +// ======================================================================= + +void HelpButton::ImplInit( Window* pParent, WinBits nStyle ) +{ + PushButton::ImplInit( pParent, nStyle | WB_NOPOINTERFOCUS ); + + SetText( Button::GetStandardText( BUTTON_HELP ) ); + SetHelpText( Button::GetStandardHelpText( BUTTON_HELP ) ); +} + +// ----------------------------------------------------------------------- + +HelpButton::HelpButton( Window* pParent, WinBits nStyle ) : + PushButton( WINDOW_HELPBUTTON ) +{ + ImplInit( pParent, nStyle ); +} + +// ----------------------------------------------------------------------- + +HelpButton::HelpButton( Window* pParent, const ResId& rResId ) : + PushButton( WINDOW_HELPBUTTON ) +{ + rResId.SetRT( RSC_HELPBUTTON ); + WinBits nStyle = ImplInitRes( rResId ); + ImplInit( pParent, nStyle ); + ImplLoadRes( rResId ); + + if ( !(nStyle & WB_HIDE) ) + Show(); +} + +// ----------------------------------------------------------------------- + +void HelpButton::Click() +{ + // Ist kein Link gesetzt, loese Hilfe aus + if ( !GetClickHdl() ) + { + Window* pFocusWin = Application::GetFocusWindow(); + if ( !pFocusWin ) + pFocusWin = this; + + HelpEvent aEvt( pFocusWin->GetPointerPosPixel(), HELPMODE_CONTEXT ); + pFocusWin->RequestHelp( aEvt ); + } + PushButton::Click(); +} + +// ======================================================================= + +void RadioButton::ImplInitRadioButtonData() +{ + mbChecked = FALSE; + mbSaveValue = FALSE; + mbRadioCheck = TRUE; + mbStateChanged = FALSE; +} + +// ----------------------------------------------------------------------- + +void RadioButton::ImplInit( Window* pParent, WinBits nStyle ) +{ + nStyle = ImplInitStyle( pParent->GetWindow( WINDOW_LASTCHILD ), nStyle ); + Button::ImplInit( pParent, nStyle, NULL ); + + ImplInitSettings( TRUE, TRUE, TRUE ); +} + +// ----------------------------------------------------------------------- + +WinBits RadioButton::ImplInitStyle( const Window* pPrevWindow, WinBits nStyle ) +{ + if ( !(nStyle & WB_NOGROUP) && + (!pPrevWindow || (pPrevWindow->GetType() != WINDOW_RADIOBUTTON)) ) + nStyle |= WB_GROUP; + if ( !(nStyle & WB_NOTABSTOP) ) + { + if ( IsChecked() ) + nStyle |= WB_TABSTOP; + else + nStyle &= ~WB_TABSTOP; + } + return nStyle; +} + +// ----------------------------------------------------------------- + +const Font& RadioButton::GetCanonicalFont( const StyleSettings& _rStyle ) const +{ + return _rStyle.GetRadioCheckFont(); +} + +// ----------------------------------------------------------------- +const Color& RadioButton::GetCanonicalTextColor( const StyleSettings& _rStyle ) const +{ + return _rStyle.GetRadioCheckTextColor(); +} + +// ----------------------------------------------------------------------- + +void RadioButton::ImplInitSettings( BOOL bFont, + BOOL bForeground, BOOL bBackground ) +{ + Button::ImplInitSettings( bFont, bForeground ); + + if ( bBackground ) + { + Window* pParent = GetParent(); + if ( !IsControlBackground() && + (pParent->IsChildTransparentModeEnabled() || IsNativeControlSupported( CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL ) ) ) + { + EnableChildTransparentMode( TRUE ); + SetParentClipMode( PARENTCLIPMODE_NOCLIP ); + SetPaintTransparent( TRUE ); + SetBackground(); + if( IsNativeControlSupported( CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL ) ) + mpWindowImpl->mbUseNativeFocus = ImplGetSVData()->maNWFData.mbNoFocusRects; + } + else + { + EnableChildTransparentMode( FALSE ); + SetParentClipMode( 0 ); + SetPaintTransparent( FALSE ); + + if ( IsControlBackground() ) + SetBackground( GetControlBackground() ); + else + SetBackground( pParent->GetBackground() ); + } + } +} + +//--------------------------------------------------------------------- +//--- 12.03.2003 18:46:14 --------------------------------------------- + +void RadioButton::DrawRadioButtonState( ) +{ + ImplDrawRadioButtonState( ); +} + +// ----------------------------------------------------------------------- + +void RadioButton::ImplInvalidateOrDrawRadioButtonState() +{ + if( ImplGetSVData()->maNWFData.mbCheckBoxNeedsErase ) + { + if ( IsNativeControlSupported(CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL) ) + { + Invalidate(); + Update(); + return; + } + } + ImplDrawRadioButtonState(); +} + +void RadioButton::ImplDrawRadioButtonState() +{ + USHORT nButtonStyle = 0; + BOOL bNativeOK = FALSE; + + // no native drawing for image radio buttons + if ( !maImage && (bNativeOK=IsNativeControlSupported(CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL)) == TRUE ) + { + ImplControlValue aControlValue( mbChecked ? BUTTONVALUE_ON : BUTTONVALUE_OFF ); + Rectangle aCtrlRect( maStateRect.TopLeft(), maStateRect.GetSize() ); + ControlState nState = 0; + + if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED ) nState |= CTRL_STATE_PRESSED; + if ( HasFocus() ) nState |= CTRL_STATE_FOCUSED; + if ( ImplGetButtonState() & BUTTON_DRAW_DEFAULT ) nState |= CTRL_STATE_DEFAULT; + if ( IsEnabled() ) nState |= CTRL_STATE_ENABLED; + + if ( IsMouseOver() && maMouseRect.IsInside( GetPointerPosPixel() ) ) + nState |= CTRL_STATE_ROLLOVER; + + bNativeOK = DrawNativeControl( CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL, aCtrlRect, nState, + aControlValue,rtl::OUString() ); + + } + +if ( bNativeOK == FALSE ) +{ + // kein Image-RadioButton + if ( !maImage ) + { + USHORT nStyle = ImplGetButtonState(); + if ( !IsEnabled() ) + nStyle |= BUTTON_DRAW_DISABLED; + if ( mbChecked ) + nStyle |= BUTTON_DRAW_CHECKED; + Image aImage = GetRadioImage( GetSettings(), nStyle ); + if ( IsZoom() ) + DrawImage( maStateRect.TopLeft(), maStateRect.GetSize(), aImage ); + else + DrawImage( maStateRect.TopLeft(), aImage ); + } + else + { + HideFocus(); + + DecorationView aDecoView( this ); + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + Rectangle aImageRect = maStateRect; + Size aImageSize = maImage.GetSizePixel(); + BOOL bEnabled = IsEnabled(); + + aImageSize.Width() = CalcZoom( aImageSize.Width() ); + aImageSize.Height() = CalcZoom( aImageSize.Height() ); + + // Border und Selektionsstatus ausgeben + nButtonStyle = FRAME_DRAW_DOUBLEIN; + aImageRect = aDecoView.DrawFrame( aImageRect, nButtonStyle ); + if ( (ImplGetButtonState() & BUTTON_DRAW_PRESSED) || !bEnabled ) + SetFillColor( rStyleSettings.GetFaceColor() ); + else + SetFillColor( rStyleSettings.GetFieldColor() ); + SetLineColor(); + DrawRect( aImageRect ); + + // Image ausgeben + nButtonStyle = 0; + if ( !bEnabled ) + nButtonStyle |= IMAGE_DRAW_DISABLE; + + // check for HC mode + Image *pImage = &maImage; + if( !!maImageHC ) + { + if( rStyleSettings.GetHighContrastMode() ) + pImage = &maImageHC; + } + + Point aImagePos( aImageRect.TopLeft() ); + aImagePos.X() += (aImageRect.GetWidth()-aImageSize.Width())/2; + aImagePos.Y() += (aImageRect.GetHeight()-aImageSize.Height())/2; + if ( IsZoom() ) + DrawImage( aImagePos, aImageSize, *pImage, nButtonStyle ); + else + DrawImage( aImagePos, *pImage, nButtonStyle ); + + aImageRect.Left()++; + aImageRect.Top()++; + aImageRect.Right()--; + aImageRect.Bottom()--; + + ImplSetFocusRect( aImageRect ); + + if ( mbChecked ) + { + SetLineColor( rStyleSettings.GetHighlightColor() ); + SetFillColor(); + if ( (aImageSize.Width() >= 20) || (aImageSize.Height() >= 20) ) + { + aImageRect.Left()++; + aImageRect.Top()++; + aImageRect.Right()--; + aImageRect.Bottom()--; + } + DrawRect( aImageRect ); + aImageRect.Left()++; + aImageRect.Top()++; + aImageRect.Right()--; + aImageRect.Bottom()--; + DrawRect( aImageRect ); + } + + if ( HasFocus() ) + ShowFocus( ImplGetFocusRect() ); + } +} +} + +// ----------------------------------------------------------------------- + +void RadioButton::ImplDraw( OutputDevice* pDev, ULONG nDrawFlags, + const Point& rPos, const Size& rSize, + const Size& rImageSize, Rectangle& rStateRect, + Rectangle& rMouseRect, bool bLayout ) +{ + WinBits nWinStyle = GetStyle(); + XubString aText( GetText() ); + Rectangle aRect( rPos, rSize ); + MetricVector* pVector = bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : NULL; + String* pDisplayText = bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : NULL; + + pDev->Push( PUSH_CLIPREGION ); + pDev->IntersectClipRegion( Rectangle( rPos, rSize ) ); + + // kein Image-RadioButton + if ( !maImage ) + { + if ( ( aText.Len() && ! (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) ) || + ( HasImage() && ! (ImplGetButtonState() & BUTTON_DRAW_NOIMAGE) ) ) + { + USHORT nTextStyle = Button::ImplGetTextStyle( aText, nWinStyle, nDrawFlags ); + + const long nImageSep = GetDrawPixel( pDev, ImplGetImageToTextDistance() ); + Size aSize( rSize ); + Point aPos( rPos ); + aPos.X() += rImageSize.Width() + nImageSep; + aSize.Width() -= rImageSize.Width() + nImageSep; + + // if the text rect height is smaller than the height of the image + // then for single lines the default should be centered text + if( (nWinStyle & (WB_TOP|WB_VCENTER|WB_BOTTOM)) == 0 && + (rImageSize.Height() > rSize.Height() || ! (nWinStyle & WB_WORDBREAK) ) ) + { + nTextStyle &= ~(TEXT_DRAW_TOP|TEXT_DRAW_BOTTOM); + nTextStyle |= TEXT_DRAW_VCENTER; + aSize.Height() = rImageSize.Height(); + } + + ImplDrawAlignedImage( pDev, aPos, aSize, bLayout, 1, + nDrawFlags, nTextStyle, NULL ); + + rMouseRect = Rectangle( aPos, aSize ); + rMouseRect.Left() = rPos.X(); + + rStateRect.Left() = rPos.X(); + rStateRect.Top() = rMouseRect.Top(); + + if ( aSize.Height() > rImageSize.Height() ) + rStateRect.Top() += ( aSize.Height() - rImageSize.Height() ) / 2; + else + { + rStateRect.Top() -= ( rImageSize.Height() - aSize.Height() ) / 2; + if( rStateRect.Top() < 0 ) + rStateRect.Top() = 0; + } + + rStateRect.Right() = rStateRect.Left() + rImageSize.Width()-1; + rStateRect.Bottom() = rStateRect.Top() + rImageSize.Height()-1; + + if ( rStateRect.Bottom() > rMouseRect.Bottom() ) + rMouseRect.Bottom() = rStateRect.Bottom(); + } + else + { + if ( nWinStyle & WB_CENTER ) + rStateRect.Left() = rPos.X()+((rSize.Width()-rImageSize.Width())/2); + else if ( nWinStyle & WB_RIGHT ) + rStateRect.Left() = rPos.X()+rSize.Width()-rImageSize.Width(); //-1; + else + rStateRect.Left() = rPos.X(); //+1; + if ( nWinStyle & WB_VCENTER ) + rStateRect.Top() = rPos.Y()+((rSize.Height()-rImageSize.Height())/2); + else if ( nWinStyle & WB_BOTTOM ) + rStateRect.Top() = rPos.Y()+rSize.Height()-rImageSize.Height(); //-1; + else + rStateRect.Top() = rPos.Y(); //+1; + rStateRect.Right() = rStateRect.Left()+rImageSize.Width()-1; + rStateRect.Bottom() = rStateRect.Top()+rImageSize.Height()-1; + rMouseRect = rStateRect; + + ImplSetFocusRect( rStateRect ); + +/* und oben -1, da CalcSize() auch Focus-Rechteck nicht mit einrechnet, +da im Writer ansonsten die Images noch weiter oben haengen + rFocusRect = rStateRect; + rFocusRect.Left()--; + rFocusRect.Top()--; + rFocusRect.Right()++; + rFocusRect.Bottom()++; +*/ + } + } + else + { + BOOL bTopImage = (nWinStyle & WB_TOP) != 0; + Size aImageSize = maImage.GetSizePixel(); + Rectangle aImageRect( rPos, rSize ); + long nTextHeight = pDev->GetTextHeight(); + long nTextWidth = pDev->GetCtrlTextWidth( aText ); + + // Positionen und Groessen berechnen + if ( aText.Len() && ! (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) ) + { + Size aTmpSize( (aImageSize.Width()+8), (aImageSize.Height()+8) ); + if ( bTopImage ) + { + aImageRect.Left() = (rSize.Width()-aTmpSize.Width())/2; + aImageRect.Top() = (rSize.Height()-(aTmpSize.Height()+nTextHeight+6))/2; + } + else + aImageRect.Top() = (rSize.Height()-aTmpSize.Height())/2; + + aImageRect.Right() = aImageRect.Left()+aTmpSize.Width(); + aImageRect.Bottom() = aImageRect.Top()+aTmpSize.Height(); + + // Text ausgeben + Point aTxtPos = rPos; + if ( bTopImage ) + { + aTxtPos.X() += (rSize.Width()-nTextWidth)/2; + aTxtPos.Y() += aImageRect.Bottom()+6; + } + else + { + aTxtPos.X() += aImageRect.Right()+8; + aTxtPos.Y() += (rSize.Height()-nTextHeight)/2; + } + pDev->DrawCtrlText( aTxtPos, aText, 0, STRING_LEN, TEXT_DRAW_MNEMONIC, pVector, pDisplayText ); + } + + rMouseRect = aImageRect; + rStateRect = aImageRect; + } + + pDev->Pop(); +} + +// ----------------------------------------------------------------------- + +void RadioButton::ImplDrawRadioButton( bool bLayout ) +{ + if( !bLayout ) + HideFocus(); + + Size aImageSize; + if ( !maImage ) + aImageSize = ImplGetRadioImageSize(); + else + aImageSize = maImage.GetSizePixel(); + aImageSize.Width() = CalcZoom( aImageSize.Width() ); + aImageSize.Height() = CalcZoom( aImageSize.Height() ); + + // Draw control text + ImplDraw( this, 0, Point(), GetOutputSizePixel(), + aImageSize, maStateRect, maMouseRect, bLayout ); + + if( !bLayout || (IsNativeControlSupported(CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL)==TRUE) ) + { + if ( !maImage && HasFocus() ) + ShowFocus( ImplGetFocusRect() ); + + ImplDrawRadioButtonState(); + } +} + +// ----------------------------------------------------------------------- + +void RadioButton::GetRadioButtonGroup( std::vector< RadioButton* >& io_rGroup, bool bIncludeThis ) const +{ + // empty the list + io_rGroup.clear(); + + // go back to first in group; + Window* pFirst = const_cast<RadioButton*>(this); + while( ( pFirst->GetStyle() & WB_GROUP ) == 0 ) + { + Window* pWindow = pFirst->GetWindow( WINDOW_PREV ); + if( pWindow ) + pFirst = pWindow; + else + break; + } + // insert radiobuttons up to next group + do + { + if( pFirst->GetType() == WINDOW_RADIOBUTTON ) + { + if( pFirst != this || bIncludeThis ) + io_rGroup.push_back( static_cast<RadioButton*>(pFirst) ); + } + pFirst = pFirst->GetWindow( WINDOW_NEXT ); + } while( pFirst && ( ( pFirst->GetStyle() & WB_GROUP ) == 0 ) ); +} + +// ----------------------------------------------------------------------- + +void RadioButton::ImplUncheckAllOther() +{ + mpWindowImpl->mnStyle |= WB_TABSTOP; + + // Gruppe mit RadioButtons durchgehen und die gecheckten Buttons + Window* pWindow; + WinBits nStyle; + if ( !(GetStyle() & WB_GROUP) ) + { + pWindow = GetWindow( WINDOW_PREV ); + while ( pWindow ) + { + nStyle = pWindow->GetStyle(); + + if ( pWindow->GetType() == WINDOW_RADIOBUTTON ) + { + if ( ((RadioButton*)pWindow)->IsChecked() ) + { + ImplDelData aDelData; + pWindow->ImplAddDel( &aDelData ); + ((RadioButton*)pWindow)->SetState( FALSE ); + if ( aDelData.IsDelete() ) + return; + pWindow->ImplRemoveDel( &aDelData ); + } + // Um falsch gesetzt WB_TABSTOPS immer zu entfernen, nicht + // innerhalb der if-Abfrage + pWindow->mpWindowImpl->mnStyle &= ~WB_TABSTOP; + } + + if ( nStyle & WB_GROUP ) + break; + + pWindow = pWindow->GetWindow( WINDOW_PREV ); + } + } + + pWindow = GetWindow( WINDOW_NEXT ); + while ( pWindow ) + { + nStyle = pWindow->GetStyle(); + + if ( nStyle & WB_GROUP ) + break; + + if ( pWindow->GetType() == WINDOW_RADIOBUTTON ) + { + if ( ((RadioButton*)pWindow)->IsChecked() ) + { + ImplDelData aDelData; + pWindow->ImplAddDel( &aDelData ); + ((RadioButton*)pWindow)->SetState( FALSE ); + if ( aDelData.IsDelete() ) + return; + pWindow->ImplRemoveDel( &aDelData ); + } + // Um falsch gesetzt WB_TABSTOPS immer zu entfernen, nicht + // innerhalb der if-Abfrage + pWindow->mpWindowImpl->mnStyle &= ~WB_TABSTOP; + } + + pWindow = pWindow->GetWindow( WINDOW_NEXT ); + } +} + +// ----------------------------------------------------------------------- + +void RadioButton::ImplCallClick( BOOL bGrabFocus, USHORT nFocusFlags ) +{ + mbStateChanged = !mbChecked; + mbChecked = TRUE; + mpWindowImpl->mnStyle |= WB_TABSTOP; + ImplInvalidateOrDrawRadioButtonState(); + ImplDelData aDelData; + ImplAddDel( &aDelData ); + if ( mbRadioCheck ) + ImplUncheckAllOther(); + if ( aDelData.IsDelete() ) + return; + if ( bGrabFocus ) + ImplGrabFocus( nFocusFlags ); + if ( aDelData.IsDelete() ) + return; + if ( mbStateChanged ) + Toggle(); + if ( aDelData.IsDelete() ) + return; + Click(); + if ( aDelData.IsDelete() ) + return; + ImplRemoveDel( &aDelData ); + mbStateChanged = FALSE; +} + +// ----------------------------------------------------------------------- + +RadioButton::RadioButton( Window* pParent, WinBits nStyle ) : + Button( WINDOW_RADIOBUTTON ) +{ + ImplInitRadioButtonData(); + ImplInit( pParent, nStyle ); +} + +// ----------------------------------------------------------------------- + +RadioButton::RadioButton( Window* pParent, const ResId& rResId ) : + Button( WINDOW_RADIOBUTTON ) +{ + ImplInitRadioButtonData(); + rResId.SetRT( RSC_RADIOBUTTON ); + WinBits nStyle = ImplInitRes( rResId ); + ImplInit( pParent, nStyle ); + ImplLoadRes( rResId ); + + if ( !(nStyle & WB_HIDE) ) + Show(); +} + +// ----------------------------------------------------------------------- + +void RadioButton::ImplLoadRes( const ResId& rResId ) +{ + Button::ImplLoadRes( rResId ); + + //anderer Wert als Default ? + USHORT nChecked = ReadShortRes(); + if ( nChecked ) + SetState( TRUE ); +} + +// ----------------------------------------------------------------------- + +RadioButton::~RadioButton() +{ +} + +// ----------------------------------------------------------------------- + +void RadioButton::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if ( rMEvt.IsLeft() && maMouseRect.IsInside( rMEvt.GetPosPixel() ) ) + { + ImplGetButtonState() |= BUTTON_DRAW_PRESSED; + ImplInvalidateOrDrawRadioButtonState(); + StartTracking(); + return; + } + + Button::MouseButtonDown( rMEvt ); +} + +// ----------------------------------------------------------------------- + +void RadioButton::Tracking( const TrackingEvent& rTEvt ) +{ + if ( rTEvt.IsTrackingEnded() ) + { + if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED ) + { + if ( !(GetStyle() & WB_NOPOINTERFOCUS) && !rTEvt.IsTrackingCanceled() ) + GrabFocus(); + + ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED; + + // Bei Abbruch kein Click-Handler rufen + if ( !rTEvt.IsTrackingCanceled() ) + ImplCallClick(); + else + ImplInvalidateOrDrawRadioButtonState(); + } + } + else + { + if ( maMouseRect.IsInside( rTEvt.GetMouseEvent().GetPosPixel() ) ) + { + if ( !(ImplGetButtonState() & BUTTON_DRAW_PRESSED) ) + { + ImplGetButtonState() |= BUTTON_DRAW_PRESSED; + ImplInvalidateOrDrawRadioButtonState(); + } + } + else + { + if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED ) + { + ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED; + ImplInvalidateOrDrawRadioButtonState(); + } + } + } +} + +// ----------------------------------------------------------------------- + +void RadioButton::KeyInput( const KeyEvent& rKEvt ) +{ + KeyCode aKeyCode = rKEvt.GetKeyCode(); + + if ( !aKeyCode.GetModifier() && (aKeyCode.GetCode() == KEY_SPACE) ) + { + if ( !(ImplGetButtonState() & BUTTON_DRAW_PRESSED) ) + { + ImplGetButtonState() |= BUTTON_DRAW_PRESSED; + ImplInvalidateOrDrawRadioButtonState(); + } + } + else if ( (ImplGetButtonState() & BUTTON_DRAW_PRESSED) && (aKeyCode.GetCode() == KEY_ESCAPE) ) + { + ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED; + ImplInvalidateOrDrawRadioButtonState(); + } + else + Button::KeyInput( rKEvt ); +} + +// ----------------------------------------------------------------------- + +void RadioButton::KeyUp( const KeyEvent& rKEvt ) +{ + KeyCode aKeyCode = rKEvt.GetKeyCode(); + + if ( (ImplGetButtonState() & BUTTON_DRAW_PRESSED) && (aKeyCode.GetCode() == KEY_SPACE) ) + { + ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED; + ImplCallClick(); + } + else + Button::KeyUp( rKEvt ); +} + +// ----------------------------------------------------------------------- + +void RadioButton::FillLayoutData() const +{ + mpControlData->mpLayoutData = new vcl::ControlLayoutData(); + const_cast<RadioButton*>(this)->ImplDrawRadioButton( true ); +} + +// ----------------------------------------------------------------------- + +void RadioButton::Paint( const Rectangle& ) +{ + ImplDrawRadioButton(); +} + +// ----------------------------------------------------------------------- + +void RadioButton::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, + ULONG nFlags ) +{ + if ( !maImage ) + { + MapMode aResMapMode( MAP_100TH_MM ); + Point aPos = pDev->LogicToPixel( rPos ); + Size aSize = pDev->LogicToPixel( rSize ); + Size aImageSize = pDev->LogicToPixel( Size( 300, 300 ), aResMapMode ); + Size aBrd1Size = pDev->LogicToPixel( Size( 20, 20 ), aResMapMode ); + Size aBrd2Size = pDev->LogicToPixel( Size( 60, 60 ), aResMapMode ); + Font aFont = GetDrawPixelFont( pDev ); + Rectangle aStateRect; + Rectangle aMouseRect; + Rectangle aFocusRect; + + aImageSize.Width() = CalcZoom( aImageSize.Width() ); + aImageSize.Height() = CalcZoom( aImageSize.Height() ); + aBrd1Size.Width() = CalcZoom( aBrd1Size.Width() ); + aBrd1Size.Height() = CalcZoom( aBrd1Size.Height() ); + aBrd2Size.Width() = CalcZoom( aBrd2Size.Width() ); + aBrd2Size.Height() = CalcZoom( aBrd2Size.Height() ); + + if ( !aBrd1Size.Width() ) + aBrd1Size.Width() = 1; + if ( !aBrd1Size.Height() ) + aBrd1Size.Height() = 1; + if ( !aBrd2Size.Width() ) + aBrd2Size.Width() = 1; + if ( !aBrd2Size.Height() ) + aBrd2Size.Height() = 1; + + pDev->Push(); + pDev->SetMapMode(); + pDev->SetFont( aFont ); + if ( nFlags & WINDOW_DRAW_MONO ) + pDev->SetTextColor( Color( COL_BLACK ) ); + else + pDev->SetTextColor( GetTextColor() ); + pDev->SetTextFillColor(); + + ImplDraw( pDev, nFlags, aPos, aSize, + aImageSize, aStateRect, aMouseRect ); + + Point aCenterPos = aStateRect.Center(); + long nRadX = aImageSize.Width()/2; + long nRadY = aImageSize.Height()/2; + + pDev->SetLineColor(); + pDev->SetFillColor( Color( COL_BLACK ) ); + pDev->DrawPolygon( Polygon( aCenterPos, nRadX, nRadY ) ); + nRadX -= aBrd1Size.Width(); + nRadY -= aBrd1Size.Height(); + pDev->SetFillColor( Color( COL_WHITE ) ); + pDev->DrawPolygon( Polygon( aCenterPos, nRadX, nRadY ) ); + if ( mbChecked ) + { + nRadX -= aBrd1Size.Width(); + nRadY -= aBrd1Size.Height(); + if ( !nRadX ) + nRadX = 1; + if ( !nRadY ) + nRadY = 1; + pDev->SetFillColor( Color( COL_BLACK ) ); + pDev->DrawPolygon( Polygon( aCenterPos, nRadX, nRadY ) ); + } + + pDev->Pop(); + } + else + { + DBG_ERROR( "RadioButton::Draw() - not implemented for RadioButton with Image" ); + } +} + +// ----------------------------------------------------------------------- + +void RadioButton::Resize() +{ + Control::Resize(); + Invalidate(); +} + +// ----------------------------------------------------------------------- + +void RadioButton::GetFocus() +{ + ShowFocus( ImplGetFocusRect() ); + SetInputContext( InputContext( GetFont() ) ); + Button::GetFocus(); +} + +// ----------------------------------------------------------------------- + +void RadioButton::LoseFocus() +{ + if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED ) + { + ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED; + ImplInvalidateOrDrawRadioButtonState(); + } + + HideFocus(); + Button::LoseFocus(); +} + +// ----------------------------------------------------------------------- + +void RadioButton::StateChanged( StateChangedType nType ) +{ + Button::StateChanged( nType ); + + if ( nType == STATE_CHANGE_STATE ) + { + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate( maStateRect ); + } + else if ( (nType == STATE_CHANGE_ENABLE) || + (nType == STATE_CHANGE_TEXT) || + (nType == STATE_CHANGE_IMAGE) || + (nType == STATE_CHANGE_DATA) || + (nType == STATE_CHANGE_UPDATEMODE) ) + { + if ( IsUpdateMode() ) + Invalidate(); + } + else if ( nType == STATE_CHANGE_STYLE ) + { + SetStyle( ImplInitStyle( GetWindow( WINDOW_PREV ), GetStyle() ) ); + + if ( (GetPrevStyle() & RADIOBUTTON_VIEW_STYLE) != + (GetStyle() & RADIOBUTTON_VIEW_STYLE) ) + { + if ( IsUpdateMode() ) + Invalidate(); + } + } + else if ( (nType == STATE_CHANGE_ZOOM) || + (nType == STATE_CHANGE_CONTROLFONT) ) + { + ImplInitSettings( TRUE, FALSE, FALSE ); + Invalidate(); + } + else if ( nType == STATE_CHANGE_CONTROLFOREGROUND ) + { + ImplInitSettings( FALSE, TRUE, FALSE ); + Invalidate(); + } + else if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) + { + ImplInitSettings( FALSE, FALSE, TRUE ); + Invalidate(); + } +} + +// ----------------------------------------------------------------------- + +void RadioButton::DataChanged( const DataChangedEvent& rDCEvt ) +{ + Button::DataChanged( rDCEvt ); + + if ( (rDCEvt.GetType() == DATACHANGED_FONTS) || + (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) || + ((rDCEvt.GetType() == DATACHANGED_SETTINGS) && + (rDCEvt.GetFlags() & SETTINGS_STYLE)) ) + { + ImplInitSettings( TRUE, TRUE, TRUE ); + Invalidate(); + } +} + +// ----------------------------------------------------------------------- + +long RadioButton::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_RADIOBUTTON, PART_ENTIRE_CONTROL) ) + { + if( ( maMouseRect.IsInside( GetPointerPosPixel()) && + !maMouseRect.IsInside( GetLastPointerPosPixel()) ) || + ( maMouseRect.IsInside( GetLastPointerPosPixel()) && + !maMouseRect.IsInside( GetPointerPosPixel()) ) || + pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow() ) + { + Invalidate( maStateRect ); + } + } + } + } + + return nDone ? nDone : Button::PreNotify(rNEvt); +} + +// ----------------------------------------------------------------------- + +void RadioButton::Toggle() +{ + ImplCallEventListenersAndHandler( VCLEVENT_RADIOBUTTON_TOGGLE, maToggleHdl, this ); +} + +// ----------------------------------------------------------------------- + +BOOL RadioButton::SetModeRadioImage( const Image& rImage, BmpColorMode eMode ) +{ + if( eMode == BMP_COLOR_NORMAL ) +{ + if ( rImage != maImage ) + { + maImage = rImage; + StateChanged( STATE_CHANGE_DATA ); + } +} + else if( eMode == BMP_COLOR_HIGHCONTRAST ) + { + if( maImageHC != rImage ) + { + maImageHC = rImage; + StateChanged( STATE_CHANGE_DATA ); + } + } + else + return FALSE; + + return TRUE; +} + +// ----------------------------------------------------------------------- + +const Image& RadioButton::GetModeRadioImage( BmpColorMode eMode ) const +{ + if( eMode == BMP_COLOR_HIGHCONTRAST ) + return maImageHC; + else + return maImage; +} + +// ----------------------------------------------------------------------- + +void RadioButton::SetState( BOOL bCheck ) +{ + // TabStop-Flag richtig mitfuehren + if ( bCheck ) + mpWindowImpl->mnStyle |= WB_TABSTOP; + else + mpWindowImpl->mnStyle &= ~WB_TABSTOP; + + if ( mbChecked != bCheck ) + { + mbChecked = bCheck; + StateChanged( STATE_CHANGE_STATE ); + Toggle(); + } +} + +// ----------------------------------------------------------------------- + +void RadioButton::Check( BOOL bCheck ) +{ + // TabStop-Flag richtig mitfuehren + if ( bCheck ) + mpWindowImpl->mnStyle |= WB_TABSTOP; + else + mpWindowImpl->mnStyle &= ~WB_TABSTOP; + + if ( mbChecked != bCheck ) + { + mbChecked = bCheck; + ImplDelData aDelData; + ImplAddDel( &aDelData ); + StateChanged( STATE_CHANGE_STATE ); + if ( aDelData.IsDelete() ) + return; + if ( bCheck && mbRadioCheck ) + ImplUncheckAllOther(); + if ( aDelData.IsDelete() ) + return; + Toggle(); + ImplRemoveDel( &aDelData ); + } +} + +// ----------------------------------------------------------------------- + +long RadioButton::ImplGetImageToTextDistance() const +{ + // 4 pixels, but take zoom into account, so the text doesn't "jump" relative to surrounding elements, + // which might have been aligned with the text of the check box + return CalcZoom( 4 ); +} + +// ----------------------------------------------------------------------- + +Size RadioButton::ImplGetRadioImageSize() const +{ + Size aSize; + // why are IsNativeControlSupported and GetNativeControlRegion not const ? + RadioButton* pThis = const_cast<RadioButton*>(this); + bool bDefaultSize = true; + if( pThis->IsNativeControlSupported( CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL ) ) + { + ImplControlValue aControlValue; + // #i45896# workaround gcc3.3 temporary problem + Rectangle aCtrlRegion( Point( 0, 0 ), GetSizePixel() ); + ControlState nState = CTRL_STATE_DEFAULT|CTRL_STATE_ENABLED; + Rectangle aBoundingRgn, aContentRgn; + + // get native size of a radio button + if( pThis->GetNativeControlRegion( CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL, aCtrlRegion, + nState, aControlValue, rtl::OUString(), + aBoundingRgn, aContentRgn ) ) + { + aSize = aContentRgn.GetSize(); + bDefaultSize = false; + } + } + if( bDefaultSize ) + aSize = GetRadioImage( GetSettings(), 0 ).GetSizePixel(); + return aSize; +} + +static void LoadThemedImageList (const StyleSettings &rStyleSettings, + ImageList *pList, const ResId &rResId, + USHORT nImages) +{ + Color aColorAry1[6]; + Color aColorAry2[6]; + aColorAry1[0] = Color( 0xC0, 0xC0, 0xC0 ); + aColorAry1[1] = Color( 0xFF, 0xFF, 0x00 ); + aColorAry1[2] = Color( 0xFF, 0xFF, 0xFF ); + aColorAry1[3] = Color( 0x80, 0x80, 0x80 ); + aColorAry1[4] = Color( 0x00, 0x00, 0x00 ); + aColorAry1[5] = Color( 0x00, 0xFF, 0x00 ); + aColorAry2[0] = rStyleSettings.GetFaceColor(); + aColorAry2[1] = rStyleSettings.GetWindowColor(); + aColorAry2[2] = rStyleSettings.GetLightColor(); + aColorAry2[3] = rStyleSettings.GetShadowColor(); + aColorAry2[4] = rStyleSettings.GetDarkShadowColor(); + aColorAry2[5] = rStyleSettings.GetWindowTextColor(); + + Color aMaskColor(0x00, 0x00, 0xFF ); + DBG_ASSERT( sizeof(aColorAry1) == sizeof(aColorAry2), "aColorAry1 must match aColorAry2" ); + // FIXME: do we want the mask for the checkbox ? + pList->InsertFromHorizontalBitmap (rResId, nImages, &aMaskColor, + aColorAry1, aColorAry2, sizeof(aColorAry1) / sizeof(Color)); +} + +Image RadioButton::GetRadioImage( const AllSettings& rSettings, USHORT nFlags ) +{ + ImplSVData* pSVData = ImplGetSVData(); + const StyleSettings& rStyleSettings = rSettings.GetStyleSettings(); + USHORT nStyle = rStyleSettings.GetRadioButtonStyle() & STYLE_RADIOBUTTON_STYLE; + + if ( rStyleSettings.GetOptions() & STYLE_OPTION_MONO ) + nStyle = STYLE_RADIOBUTTON_MONO; + + if ( !pSVData->maCtrlData.mpRadioImgList || + (pSVData->maCtrlData.mnRadioStyle != nStyle) || + (pSVData->maCtrlData.mnLastRadioFColor != rStyleSettings.GetFaceColor().GetColor()) || + (pSVData->maCtrlData.mnLastRadioWColor != rStyleSettings.GetWindowColor().GetColor()) || + (pSVData->maCtrlData.mnLastRadioLColor != rStyleSettings.GetLightColor().GetColor()) ) + { + if ( pSVData->maCtrlData.mpRadioImgList ) + delete pSVData->maCtrlData.mpRadioImgList; + + pSVData->maCtrlData.mnLastRadioFColor = rStyleSettings.GetFaceColor().GetColor(); + pSVData->maCtrlData.mnLastRadioWColor = rStyleSettings.GetWindowColor().GetColor(); + pSVData->maCtrlData.mnLastRadioLColor = rStyleSettings.GetLightColor().GetColor(); + + Color pColorAry1[6]; + Color pColorAry2[6]; + pColorAry1[0] = Color( 0xC0, 0xC0, 0xC0 ); + pColorAry1[1] = Color( 0xFF, 0xFF, 0x00 ); + pColorAry1[2] = Color( 0xFF, 0xFF, 0xFF ); + pColorAry1[3] = Color( 0x80, 0x80, 0x80 ); + pColorAry1[4] = Color( 0x00, 0x00, 0x00 ); + pColorAry1[5] = Color( 0x00, 0xFF, 0x00 ); + pColorAry2[0] = rStyleSettings.GetFaceColor(); + pColorAry2[1] = rStyleSettings.GetWindowColor(); + pColorAry2[2] = rStyleSettings.GetLightColor(); + pColorAry2[3] = rStyleSettings.GetShadowColor(); + pColorAry2[4] = rStyleSettings.GetDarkShadowColor(); + pColorAry2[5] = rStyleSettings.GetWindowTextColor(); + + ResMgr* pResMgr = ImplGetResMgr(); + pSVData->maCtrlData.mpRadioImgList = new ImageList(); + if( pResMgr ) + LoadThemedImageList( rStyleSettings, + pSVData->maCtrlData.mpRadioImgList, + ResId( SV_RESID_BITMAP_RADIO+nStyle, *pResMgr ), 6 ); + pSVData->maCtrlData.mnRadioStyle = nStyle; + } + + USHORT nId; + if ( nFlags & BUTTON_DRAW_DISABLED ) + { + if ( nFlags & BUTTON_DRAW_CHECKED ) + nId = 6; + else + nId = 5; + } + else if ( nFlags & BUTTON_DRAW_PRESSED ) + { + if ( nFlags & BUTTON_DRAW_CHECKED ) + nId = 4; + else + nId = 3; + } + else + { + if ( nFlags & BUTTON_DRAW_CHECKED ) + nId = 2; + else + nId = 1; + } + return pSVData->maCtrlData.mpRadioImgList->GetImage( nId ); +} + +// ----------------------------------------------------------------------- + +void RadioButton::ImplSetMinimumNWFSize() +{ + Push( PUSH_MAPMODE ); + SetMapMode( MAP_PIXEL ); + + ImplControlValue aControlValue; + Size aCurSize( GetSizePixel() ); + Rectangle aCtrlRegion( Point( 0, 0 ), aCurSize ); + Rectangle aBoundingRgn, aContentRgn; + + // get native size of a radiobutton + if( GetNativeControlRegion( CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL, aCtrlRegion, + CTRL_STATE_DEFAULT|CTRL_STATE_ENABLED, aControlValue, rtl::OUString(), + aBoundingRgn, aContentRgn ) ) + { + Size aSize = aContentRgn.GetSize(); + + if( aSize.Height() > aCurSize.Height() ) + { + aCurSize.Height() = aSize.Height(); + SetSizePixel( aCurSize ); + } + } + + Pop(); +} + +// ----------------------------------------------------------------------- + +Size RadioButton::CalcMinimumSize( long nMaxWidth ) const +{ + Size aSize; + if ( !maImage ) + aSize = ImplGetRadioImageSize(); + else + aSize = maImage.GetSizePixel(); + + nMaxWidth -= aSize.Width(); + + XubString aText = GetText(); + if ( aText.Len() && ! (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) ) + { + // subtract what will be added later + nMaxWidth-=2; + nMaxWidth -= ImplGetImageToTextDistance(); + + Size aTextSize = GetTextRect( Rectangle( Point(), Size( nMaxWidth > 0 ? nMaxWidth : 0x7fffffff, 0x7fffffff ) ), + aText, FixedText::ImplGetTextStyle( GetStyle() ) ).GetSize(); + aSize.Width()+=2; // for focus rect + aSize.Width() += ImplGetImageToTextDistance(); + aSize.Width() += aTextSize.Width(); + if ( aSize.Height() < aTextSize.Height() ) + aSize.Height() = aTextSize.Height(); + } + else if ( !maImage ) + { +/* da ansonsten im Writer die Control zu weit oben haengen + aSize.Width() += 2; + aSize.Height() += 2; +*/ + } + + return CalcWindowSize( aSize ); +} + +// ----------------------------------------------------------------------- + +Size RadioButton::GetOptimalSize(WindowSizeType eType) const +{ + switch (eType) { + case WINDOWSIZE_MINIMUM: + return CalcMinimumSize(); + default: + return Button::GetOptimalSize( eType ); + } +} + +// ======================================================================= + +void CheckBox::ImplInitCheckBoxData() +{ + meState = STATE_NOCHECK; + meSaveValue = STATE_NOCHECK; + mbTriState = FALSE; +} + +// ----------------------------------------------------------------------- + +void CheckBox::ImplInit( Window* pParent, WinBits nStyle ) +{ + nStyle = ImplInitStyle( pParent->GetWindow( WINDOW_LASTCHILD ), nStyle ); + Button::ImplInit( pParent, nStyle, NULL ); + + ImplInitSettings( TRUE, TRUE, TRUE ); +} + +// ----------------------------------------------------------------------- + +WinBits CheckBox::ImplInitStyle( const Window* pPrevWindow, WinBits nStyle ) +{ + if ( !(nStyle & WB_NOTABSTOP) ) + nStyle |= WB_TABSTOP; + if ( !(nStyle & WB_NOGROUP) && + (!pPrevWindow || (pPrevWindow->GetType() != WINDOW_CHECKBOX)) ) + nStyle |= WB_GROUP; + return nStyle; +} + +// ----------------------------------------------------------------- + +const Font& CheckBox::GetCanonicalFont( const StyleSettings& _rStyle ) const +{ + return _rStyle.GetRadioCheckFont(); +} + +// ----------------------------------------------------------------- +const Color& CheckBox::GetCanonicalTextColor( const StyleSettings& _rStyle ) const +{ + return _rStyle.GetRadioCheckTextColor(); +} + +// ----------------------------------------------------------------------- + +void CheckBox::ImplInitSettings( BOOL bFont, + BOOL bForeground, BOOL bBackground ) +{ + Button::ImplInitSettings( bFont, bForeground ); + + if ( bBackground ) + { + Window* pParent = GetParent(); + if ( !IsControlBackground() && + (pParent->IsChildTransparentModeEnabled() || IsNativeControlSupported( CTRL_CHECKBOX, PART_ENTIRE_CONTROL ) ) ) + { + EnableChildTransparentMode( TRUE ); + SetParentClipMode( PARENTCLIPMODE_NOCLIP ); + SetPaintTransparent( TRUE ); + SetBackground(); + if( IsNativeControlSupported( CTRL_CHECKBOX, PART_ENTIRE_CONTROL ) ) + ImplGetWindowImpl()->mbUseNativeFocus = ImplGetSVData()->maNWFData.mbNoFocusRects; + } + else + { + EnableChildTransparentMode( FALSE ); + SetParentClipMode( 0 ); + SetPaintTransparent( FALSE ); + + if ( IsControlBackground() ) + SetBackground( GetControlBackground() ); + else + SetBackground( pParent->GetBackground() ); + } + } +} + +// ----------------------------------------------------------------------- + +void CheckBox::ImplLoadRes( const ResId& rResId ) +{ + Button::ImplLoadRes( rResId ); + + if ( rResId.GetRT() != RSC_TRISTATEBOX ) + { + USHORT nChecked = ReadShortRes(); + //anderer Wert als Default ? + if( nChecked ) + Check( TRUE ); + } +} + +// ----------------------------------------------------------------------- + +void CheckBox::ImplInvalidateOrDrawCheckBoxState() +{ + if( ImplGetSVData()->maNWFData.mbCheckBoxNeedsErase ) + { + if ( IsNativeControlSupported(CTRL_CHECKBOX, PART_ENTIRE_CONTROL) ) + { + Invalidate(); + Update(); + return; + } + } + ImplDrawCheckBoxState(); +} + +void CheckBox::ImplDrawCheckBoxState() +{ + bool bNativeOK = TRUE; + + if ( (bNativeOK=IsNativeControlSupported(CTRL_CHECKBOX, PART_ENTIRE_CONTROL)) == TRUE ) + { + ImplControlValue aControlValue( meState == STATE_CHECK ? BUTTONVALUE_ON : BUTTONVALUE_OFF ); + Rectangle aCtrlRegion( maStateRect ); + ControlState nState = 0; + + if ( HasFocus() ) nState |= CTRL_STATE_FOCUSED; + if ( ImplGetButtonState() & BUTTON_DRAW_DEFAULT ) nState |= CTRL_STATE_DEFAULT; + if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED ) nState |= CTRL_STATE_PRESSED; + if ( IsEnabled() ) nState |= CTRL_STATE_ENABLED; + + if ( meState == STATE_CHECK ) + aControlValue.setTristateVal( BUTTONVALUE_ON ); + else if ( meState == STATE_DONTKNOW ) + aControlValue.setTristateVal( BUTTONVALUE_MIXED ); + + if ( IsMouseOver() && maMouseRect.IsInside( GetPointerPosPixel() ) ) + nState |= CTRL_STATE_ROLLOVER; + + bNativeOK = DrawNativeControl( CTRL_CHECKBOX, PART_ENTIRE_CONTROL, aCtrlRegion, nState, + aControlValue, rtl::OUString() ); + } + + if ( bNativeOK == FALSE ) + { + USHORT nStyle = ImplGetButtonState(); + if ( !IsEnabled() ) + nStyle |= BUTTON_DRAW_DISABLED; + if ( meState == STATE_DONTKNOW ) + nStyle |= BUTTON_DRAW_DONTKNOW; + else if ( meState == STATE_CHECK ) + nStyle |= BUTTON_DRAW_CHECKED; + Image aImage = GetCheckImage( GetSettings(), nStyle ); + if ( IsZoom() ) + DrawImage( maStateRect.TopLeft(), maStateRect.GetSize(), aImage ); + else + DrawImage( maStateRect.TopLeft(), aImage ); + } +} + +// ----------------------------------------------------------------------- + +void CheckBox::ImplDraw( OutputDevice* pDev, ULONG nDrawFlags, + const Point& rPos, const Size& rSize, + const Size& rImageSize, Rectangle& rStateRect, + Rectangle& rMouseRect, bool bLayout ) +{ + WinBits nWinStyle = GetStyle(); + XubString aText( GetText() ); + + pDev->Push( PUSH_CLIPREGION | PUSH_LINECOLOR ); + pDev->IntersectClipRegion( Rectangle( rPos, rSize ) ); + + long nLineY = rPos.Y() + (rSize.Height()-1)/2; + if ( ( aText.Len() && ! (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) ) || + ( HasImage() && ! (ImplGetButtonState() & BUTTON_DRAW_NOIMAGE) ) ) + { + USHORT nTextStyle = Button::ImplGetTextStyle( aText, nWinStyle, nDrawFlags ); + + const long nImageSep = GetDrawPixel( pDev, ImplGetImageToTextDistance() ); + Size aSize( rSize ); + Point aPos( rPos ); + aPos.X() += rImageSize.Width() + nImageSep; + aSize.Width() -= rImageSize.Width() + nImageSep; + + // if the text rect height is smaller than the height of the image + // then for single lines the default should be centered text + if( (nWinStyle & (WB_TOP|WB_VCENTER|WB_BOTTOM)) == 0 && + (rImageSize.Height() > rSize.Height() || ! (nWinStyle & WB_WORDBREAK) ) ) + { + nTextStyle &= ~(TEXT_DRAW_TOP|TEXT_DRAW_BOTTOM); + nTextStyle |= TEXT_DRAW_VCENTER; + aSize.Height() = rImageSize.Height(); + } + + ImplDrawAlignedImage( pDev, aPos, aSize, bLayout, 1, + nDrawFlags, nTextStyle, NULL ); + nLineY = aPos.Y() + aSize.Height()/2; + + rMouseRect = Rectangle( aPos, aSize ); + rMouseRect.Left() = rPos.X(); + rStateRect.Left() = rPos.X(); + rStateRect.Top() = rMouseRect.Top(); + + if ( aSize.Height() > rImageSize.Height() ) + rStateRect.Top() += ( aSize.Height() - rImageSize.Height() ) / 2; + else + { + rStateRect.Top() -= ( rImageSize.Height() - aSize.Height() ) / 2; + if( rStateRect.Top() < 0 ) + rStateRect.Top() = 0; + } + + rStateRect.Right() = rStateRect.Left()+rImageSize.Width()-1; + rStateRect.Bottom() = rStateRect.Top()+rImageSize.Height()-1; + if ( rStateRect.Bottom() > rMouseRect.Bottom() ) + rMouseRect.Bottom() = rStateRect.Bottom(); + } + else + { + if ( nWinStyle & WB_CENTER ) + rStateRect.Left() = rPos.X()+((rSize.Width()-rImageSize.Width())/2); + else if ( nWinStyle & WB_RIGHT ) + rStateRect.Left() = rPos.X()+rSize.Width()-rImageSize.Width(); + else + rStateRect.Left() = rPos.X(); + if ( nWinStyle & WB_VCENTER ) + rStateRect.Top() = rPos.Y()+((rSize.Height()-rImageSize.Height())/2); + else if ( nWinStyle & WB_BOTTOM ) + rStateRect.Top() = rPos.Y()+rSize.Height()-rImageSize.Height(); + else + rStateRect.Top() = rPos.Y(); + rStateRect.Right() = rStateRect.Left()+rImageSize.Width()-1; + rStateRect.Bottom() = rStateRect.Top()+rImageSize.Height()-1; + // provide space for focusrect + // note: this assumes that the control's size was adjusted + // accordingly in Get/LoseFocus, so the onscreen position won't change + if( HasFocus() ) + rStateRect.Move( 1, 1 ); + rMouseRect = rStateRect; + + ImplSetFocusRect( rStateRect ); + } + + const int nLineSpace = 4; + if( (GetStyle() & WB_CBLINESTYLE) != 0 && + rMouseRect.Right()-1-nLineSpace < rPos.X()+rSize.Width() ) + { + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + if ( rStyleSettings.GetOptions() & STYLE_OPTION_MONO ) + SetLineColor( Color( COL_BLACK ) ); + else + SetLineColor( rStyleSettings.GetShadowColor() ); + long nLineX = rMouseRect.Right()+nLineSpace; + DrawLine( Point( nLineX, nLineY ), Point( rPos.X() + rSize.Width()-1, nLineY ) ); + if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) ) + { + SetLineColor( rStyleSettings.GetLightColor() ); + DrawLine( Point( nLineX, nLineY+1 ), Point( rPos.X() + rSize.Width()-1, nLineY+1 ) ); + } + } + + pDev->Pop(); +} + +// ----------------------------------------------------------------------- + +void CheckBox::ImplDrawCheckBox( bool bLayout ) +{ + Size aImageSize = ImplGetCheckImageSize(); + aImageSize.Width() = CalcZoom( aImageSize.Width() ); + aImageSize.Height() = CalcZoom( aImageSize.Height() ); + + if( !bLayout ) + HideFocus(); + + ImplDraw( this, 0, Point(), GetOutputSizePixel(), aImageSize, + maStateRect, maMouseRect, bLayout ); + + if( !bLayout ) + { + ImplDrawCheckBoxState(); + if ( HasFocus() ) + ShowFocus( ImplGetFocusRect() ); + } +} + +// ----------------------------------------------------------------------- + +void CheckBox::ImplCheck() +{ + TriState eNewState; + if ( meState == STATE_NOCHECK ) + eNewState = STATE_CHECK; + else if ( !mbTriState ) + eNewState = STATE_NOCHECK; + else if ( meState == STATE_CHECK ) + eNewState = STATE_DONTKNOW; + else + eNewState = STATE_NOCHECK; + meState = eNewState; + + ImplDelData aDelData; + ImplAddDel( &aDelData ); + if( (GetStyle() & WB_EARLYTOGGLE) ) + Toggle(); + ImplInvalidateOrDrawCheckBoxState(); + if( ! (GetStyle() & WB_EARLYTOGGLE) ) + Toggle(); + if ( aDelData.IsDelete() ) + return; + ImplRemoveDel( &aDelData ); + Click(); +} + +// ----------------------------------------------------------------------- + +CheckBox::CheckBox( Window* pParent, WinBits nStyle ) : + Button( WINDOW_CHECKBOX ) +{ + ImplInitCheckBoxData(); + ImplInit( pParent, nStyle ); +} + +// ----------------------------------------------------------------------- + +CheckBox::CheckBox( Window* pParent, const ResId& rResId ) : + Button( WINDOW_CHECKBOX ) +{ + ImplInitCheckBoxData(); + rResId.SetRT( RSC_CHECKBOX ); + WinBits nStyle = ImplInitRes( rResId ); + ImplInit( pParent, nStyle ); + ImplLoadRes( rResId ); + + if ( !(nStyle & WB_HIDE) ) + Show(); +} + +// ----------------------------------------------------------------------- + +void CheckBox::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if ( rMEvt.IsLeft() && maMouseRect.IsInside( rMEvt.GetPosPixel() ) ) + { + ImplGetButtonState() |= BUTTON_DRAW_PRESSED; + ImplInvalidateOrDrawCheckBoxState(); + StartTracking(); + return; + } + + Button::MouseButtonDown( rMEvt ); +} + +// ----------------------------------------------------------------------- + +void CheckBox::Tracking( const TrackingEvent& rTEvt ) +{ + if ( rTEvt.IsTrackingEnded() ) + { + if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED ) + { + if ( !(GetStyle() & WB_NOPOINTERFOCUS) && !rTEvt.IsTrackingCanceled() ) + GrabFocus(); + + ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED; + + // Bei Abbruch kein Click-Handler rufen + if ( !rTEvt.IsTrackingCanceled() ) + ImplCheck(); + else + ImplInvalidateOrDrawCheckBoxState(); + } + } + else + { + if ( maMouseRect.IsInside( rTEvt.GetMouseEvent().GetPosPixel() ) ) + { + if ( !(ImplGetButtonState() & BUTTON_DRAW_PRESSED) ) + { + ImplGetButtonState() |= BUTTON_DRAW_PRESSED; + ImplInvalidateOrDrawCheckBoxState(); + } + } + else + { + if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED ) + { + ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED; + ImplInvalidateOrDrawCheckBoxState(); + } + } + } +} + +// ----------------------------------------------------------------------- + +void CheckBox::KeyInput( const KeyEvent& rKEvt ) +{ + KeyCode aKeyCode = rKEvt.GetKeyCode(); + + if ( !aKeyCode.GetModifier() && (aKeyCode.GetCode() == KEY_SPACE) ) + { + if ( !(ImplGetButtonState() & BUTTON_DRAW_PRESSED) ) + { + ImplGetButtonState() |= BUTTON_DRAW_PRESSED; + ImplInvalidateOrDrawCheckBoxState(); + } + } + else if ( (ImplGetButtonState() & BUTTON_DRAW_PRESSED) && (aKeyCode.GetCode() == KEY_ESCAPE) ) + { + ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED; + ImplInvalidateOrDrawCheckBoxState(); + } + else + Button::KeyInput( rKEvt ); +} + +// ----------------------------------------------------------------------- + +void CheckBox::KeyUp( const KeyEvent& rKEvt ) +{ + KeyCode aKeyCode = rKEvt.GetKeyCode(); + + if ( (ImplGetButtonState() & BUTTON_DRAW_PRESSED) && (aKeyCode.GetCode() == KEY_SPACE) ) + { + ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED; + ImplCheck(); + } + else + Button::KeyUp( rKEvt ); +} + +// ----------------------------------------------------------------------- + +void CheckBox::FillLayoutData() const +{ + mpControlData->mpLayoutData = new vcl::ControlLayoutData(); + const_cast<CheckBox*>(this)->ImplDrawCheckBox( true ); +} + +// ----------------------------------------------------------------------- + +void CheckBox::Paint( const Rectangle& ) +{ + ImplDrawCheckBox(); +} + +// ----------------------------------------------------------------------- + +void CheckBox::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, + ULONG nFlags ) +{ + MapMode aResMapMode( MAP_100TH_MM ); + Point aPos = pDev->LogicToPixel( rPos ); + Size aSize = pDev->LogicToPixel( rSize ); + Size aImageSize = pDev->LogicToPixel( Size( 300, 300 ), aResMapMode ); + Size aBrd1Size = pDev->LogicToPixel( Size( 20, 20 ), aResMapMode ); + Size aBrd2Size = pDev->LogicToPixel( Size( 30, 30 ), aResMapMode ); + long nCheckWidth = pDev->LogicToPixel( Size( 20, 20 ), aResMapMode ).Width(); + Font aFont = GetDrawPixelFont( pDev ); + Rectangle aStateRect; + Rectangle aMouseRect; + + aImageSize.Width() = CalcZoom( aImageSize.Width() ); + aImageSize.Height() = CalcZoom( aImageSize.Height() ); + aBrd1Size.Width() = CalcZoom( aBrd1Size.Width() ); + aBrd1Size.Height() = CalcZoom( aBrd1Size.Height() ); + aBrd2Size.Width() = CalcZoom( aBrd2Size.Width() ); + aBrd2Size.Height() = CalcZoom( aBrd2Size.Height() ); + + if ( !aBrd1Size.Width() ) + aBrd1Size.Width() = 1; + if ( !aBrd1Size.Height() ) + aBrd1Size.Height() = 1; + if ( !aBrd2Size.Width() ) + aBrd2Size.Width() = 1; + if ( !aBrd2Size.Height() ) + aBrd2Size.Height() = 1; + if ( !nCheckWidth ) + nCheckWidth = 1; + + pDev->Push(); + pDev->SetMapMode(); + pDev->SetFont( aFont ); + if ( nFlags & WINDOW_DRAW_MONO ) + pDev->SetTextColor( Color( COL_BLACK ) ); + else + pDev->SetTextColor( GetTextColor() ); + pDev->SetTextFillColor(); + + ImplDraw( pDev, nFlags, aPos, aSize, + aImageSize, aStateRect, aMouseRect, false ); + + pDev->SetLineColor(); + pDev->SetFillColor( Color( COL_BLACK ) ); + pDev->DrawRect( aStateRect ); + aStateRect.Left() += aBrd1Size.Width(); + aStateRect.Top() += aBrd1Size.Height(); + aStateRect.Right() -= aBrd1Size.Width(); + aStateRect.Bottom() -= aBrd1Size.Height(); + if ( meState == STATE_DONTKNOW ) + pDev->SetFillColor( Color( COL_LIGHTGRAY ) ); + else + pDev->SetFillColor( Color( COL_WHITE ) ); + pDev->DrawRect( aStateRect ); + + if ( meState == STATE_CHECK ) + { + aStateRect.Left() += aBrd2Size.Width(); + aStateRect.Top() += aBrd2Size.Height(); + aStateRect.Right() -= aBrd2Size.Width(); + aStateRect.Bottom() -= aBrd2Size.Height(); + Point aPos11( aStateRect.TopLeft() ); + Point aPos12( aStateRect.BottomRight() ); + Point aPos21( aStateRect.TopRight() ); + Point aPos22( aStateRect.BottomLeft() ); + Point aTempPos11( aPos11 ); + Point aTempPos12( aPos12 ); + Point aTempPos21( aPos21 ); + Point aTempPos22( aPos22 ); + pDev->SetLineColor( Color( COL_BLACK ) ); + long nDX = 0; + for ( long i = 0; i < nCheckWidth; i++ ) + { + if ( !(i % 2) ) + { + aTempPos11.X() = aPos11.X()+nDX; + aTempPos12.X() = aPos12.X()+nDX; + aTempPos21.X() = aPos21.X()+nDX; + aTempPos22.X() = aPos22.X()+nDX; + } + else + { + nDX++; + aTempPos11.X() = aPos11.X()-nDX; + aTempPos12.X() = aPos12.X()-nDX; + aTempPos21.X() = aPos21.X()-nDX; + aTempPos22.X() = aPos22.X()-nDX; + } + pDev->DrawLine( aTempPos11, aTempPos12 ); + pDev->DrawLine( aTempPos21, aTempPos22 ); + } + } + + pDev->Pop(); +} + +// ----------------------------------------------------------------------- + +void CheckBox::Resize() +{ + Control::Resize(); + Invalidate(); +} + +// ----------------------------------------------------------------------- + +void CheckBox::GetFocus() +{ + if ( !GetText().Len() || (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) ) + { + // increase button size to have space for focus rect + // checkboxes without text will draw focusrect around the check + // See CheckBox::ImplDraw() + Point aPos( GetPosPixel() ); + Size aSize( GetSizePixel() ); + aPos.Move(-1,-1); + aSize.Height() += 2; + aSize.Width() += 2; + SetPosSizePixel( aPos.X(), aPos.Y(), aSize.Width(), aSize.Height(), WINDOW_POSSIZE_ALL ); + ImplDrawCheckBox(); + } + else + ShowFocus( ImplGetFocusRect() ); + + SetInputContext( InputContext( GetFont() ) ); + Button::GetFocus(); +} + +// ----------------------------------------------------------------------- + +void CheckBox::LoseFocus() +{ + if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED ) + { + ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED; + ImplInvalidateOrDrawCheckBoxState(); + } + + HideFocus(); + Button::LoseFocus(); + + if ( !GetText().Len() || (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) ) + { + // decrease button size again (see GetFocus()) + // checkboxes without text will draw focusrect around the check + Point aPos( GetPosPixel() ); + Size aSize( GetSizePixel() ); + aPos.Move(1,1); + aSize.Height() -= 2; + aSize.Width() -= 2; + SetPosSizePixel( aPos.X(), aPos.Y(), aSize.Width(), aSize.Height(), WINDOW_POSSIZE_ALL ); + ImplDrawCheckBox(); + } +} + +// ----------------------------------------------------------------------- + +void CheckBox::StateChanged( StateChangedType nType ) +{ + Button::StateChanged( nType ); + + if ( nType == STATE_CHANGE_STATE ) + { + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate( maStateRect ); + } + else if ( (nType == STATE_CHANGE_ENABLE) || + (nType == STATE_CHANGE_TEXT) || + (nType == STATE_CHANGE_IMAGE) || + (nType == STATE_CHANGE_DATA) || + (nType == STATE_CHANGE_UPDATEMODE) ) + { + if ( IsUpdateMode() ) + Invalidate(); + } + else if ( nType == STATE_CHANGE_STYLE ) + { + SetStyle( ImplInitStyle( GetWindow( WINDOW_PREV ), GetStyle() ) ); + + if ( (GetPrevStyle() & CHECKBOX_VIEW_STYLE) != + (GetStyle() & CHECKBOX_VIEW_STYLE) ) + { + if ( IsUpdateMode() ) + Invalidate(); + } + } + else if ( (nType == STATE_CHANGE_ZOOM) || + (nType == STATE_CHANGE_CONTROLFONT) ) + { + ImplInitSettings( TRUE, FALSE, FALSE ); + Invalidate(); + } + else if ( nType == STATE_CHANGE_CONTROLFOREGROUND ) + { + ImplInitSettings( FALSE, TRUE, FALSE ); + Invalidate(); + } + else if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) + { + ImplInitSettings( FALSE, FALSE, TRUE ); + Invalidate(); + } +} + +// ----------------------------------------------------------------------- + +void CheckBox::DataChanged( const DataChangedEvent& rDCEvt ) +{ + Button::DataChanged( rDCEvt ); + + if ( (rDCEvt.GetType() == DATACHANGED_FONTS) || + (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) || + ((rDCEvt.GetType() == DATACHANGED_SETTINGS) && + (rDCEvt.GetFlags() & SETTINGS_STYLE)) ) + { + ImplInitSettings( TRUE, TRUE, TRUE ); + Invalidate(); + } +} + +// ----------------------------------------------------------------------- + +long CheckBox::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_CHECKBOX, PART_ENTIRE_CONTROL) ) + { + if( ( maMouseRect.IsInside( GetPointerPosPixel()) && + !maMouseRect.IsInside( GetLastPointerPosPixel()) ) || + ( maMouseRect.IsInside( GetLastPointerPosPixel()) && + !maMouseRect.IsInside( GetPointerPosPixel()) ) || + pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow() ) + { + Invalidate( maStateRect ); + } + } + } + } + + return nDone ? nDone : Button::PreNotify(rNEvt); +} + +// ----------------------------------------------------------------------- + +void CheckBox::Toggle() +{ + ImplCallEventListenersAndHandler( VCLEVENT_CHECKBOX_TOGGLE, maToggleHdl, this ); +} + +// ----------------------------------------------------------------------- + +void CheckBox::SetState( TriState eState ) +{ + if ( !mbTriState && (eState == STATE_DONTKNOW) ) + eState = STATE_NOCHECK; + + if ( meState != eState ) + { + meState = eState; + StateChanged( STATE_CHANGE_STATE ); + Toggle(); + } +} + +// ----------------------------------------------------------------------- + +void CheckBox::EnableTriState( BOOL bTriState ) +{ + if ( mbTriState != bTriState ) + { + mbTriState = bTriState; + + if ( !bTriState && (meState == STATE_DONTKNOW) ) + SetState( STATE_NOCHECK ); + } +} + +// ----------------------------------------------------------------------- + +long CheckBox::ImplGetImageToTextDistance() const +{ + // 4 pixels, but take zoom into account, so the text doesn't "jump" relative to surrounding elements, + // which might have been aligned with the text of the check box + return CalcZoom( 4 ); +} + +// ----------------------------------------------------------------------- + +Size CheckBox::ImplGetCheckImageSize() const +{ + Size aSize; + // why are IsNativeControlSupported and GetNativeControlRegion not const ? + CheckBox* pThis = const_cast<CheckBox*>(this); + bool bDefaultSize = true; + if( pThis->IsNativeControlSupported( CTRL_CHECKBOX, PART_ENTIRE_CONTROL ) ) + { + ImplControlValue aControlValue; + // #i45896# workaround gcc3.3 temporary problem + Rectangle aCtrlRegion( Point( 0, 0 ), GetSizePixel() ); + ControlState nState = CTRL_STATE_DEFAULT|CTRL_STATE_ENABLED; + Rectangle aBoundingRgn, aContentRgn; + + // get native size of a check box + if( pThis->GetNativeControlRegion( CTRL_CHECKBOX, PART_ENTIRE_CONTROL, aCtrlRegion, + nState, aControlValue, rtl::OUString(), + aBoundingRgn, aContentRgn ) ) + { + aSize = aContentRgn.GetSize(); + bDefaultSize = false; + } + } + if( bDefaultSize ) + aSize = GetCheckImage( GetSettings(), 0 ).GetSizePixel(); + return aSize; +} + +Image CheckBox::GetCheckImage( const AllSettings& rSettings, USHORT nFlags ) +{ + ImplSVData* pSVData = ImplGetSVData(); + const StyleSettings& rStyleSettings = rSettings.GetStyleSettings(); + USHORT nStyle = rStyleSettings.GetCheckBoxStyle() & STYLE_CHECKBOX_STYLE; + + if ( rStyleSettings.GetOptions() & STYLE_OPTION_MONO ) + nStyle = STYLE_CHECKBOX_MONO; + + if ( !pSVData->maCtrlData.mpCheckImgList || + (pSVData->maCtrlData.mnCheckStyle != nStyle) || + (pSVData->maCtrlData.mnLastCheckFColor != rStyleSettings.GetFaceColor().GetColor()) || + (pSVData->maCtrlData.mnLastCheckWColor != rStyleSettings.GetWindowColor().GetColor()) || + (pSVData->maCtrlData.mnLastCheckLColor != rStyleSettings.GetLightColor().GetColor()) ) + { + if ( pSVData->maCtrlData.mpCheckImgList ) + delete pSVData->maCtrlData.mpCheckImgList; + + pSVData->maCtrlData.mnLastCheckFColor = rStyleSettings.GetFaceColor().GetColor(); + pSVData->maCtrlData.mnLastCheckWColor = rStyleSettings.GetWindowColor().GetColor(); + pSVData->maCtrlData.mnLastCheckLColor = rStyleSettings.GetLightColor().GetColor(); + + ResMgr* pResMgr = ImplGetResMgr(); + pSVData->maCtrlData.mpCheckImgList = new ImageList(); + if( pResMgr ) + LoadThemedImageList( rStyleSettings, + pSVData->maCtrlData.mpCheckImgList, + ResId( SV_RESID_BITMAP_CHECK+nStyle, *pResMgr ), 9 ); + pSVData->maCtrlData.mnCheckStyle = nStyle; + } + + USHORT nId; + if ( nFlags & BUTTON_DRAW_DISABLED ) + { + if ( nFlags & BUTTON_DRAW_DONTKNOW ) + nId = 9; + else if ( nFlags & BUTTON_DRAW_CHECKED ) + nId = 6; + else + nId = 5; + } + else if ( nFlags & BUTTON_DRAW_PRESSED ) + { + if ( nFlags & BUTTON_DRAW_DONTKNOW ) + nId = 8; + else if ( nFlags & BUTTON_DRAW_CHECKED ) + nId = 4; + else + nId = 3; + } + else + { + if ( nFlags & BUTTON_DRAW_DONTKNOW ) + nId = 7; + else if ( nFlags & BUTTON_DRAW_CHECKED ) + nId = 2; + else + nId = 1; + } + return pSVData->maCtrlData.mpCheckImgList->GetImage( nId ); +} + +// ----------------------------------------------------------------------- + +void CheckBox::ImplSetMinimumNWFSize() +{ + Push( PUSH_MAPMODE ); + SetMapMode( MAP_PIXEL ); + + ImplControlValue aControlValue; + Size aCurSize( GetSizePixel() ); + Rectangle aCtrlRegion( Point( 0, 0 ), aCurSize ); + Rectangle aBoundingRgn, aContentRgn; + + // get native size of a radiobutton + if( GetNativeControlRegion( CTRL_CHECKBOX, PART_ENTIRE_CONTROL, aCtrlRegion, + CTRL_STATE_DEFAULT|CTRL_STATE_ENABLED, aControlValue, rtl::OUString(), + aBoundingRgn, aContentRgn ) ) + { + Size aSize = aContentRgn.GetSize(); + + if( aSize.Height() > aCurSize.Height() ) + { + aCurSize.Height() = aSize.Height(); + SetSizePixel( aCurSize ); + } + } + + Pop(); +} + +// ----------------------------------------------------------------------- + +Size CheckBox::CalcMinimumSize( long nMaxWidth ) const +{ + Size aSize = ImplGetCheckImageSize(); + nMaxWidth -= aSize.Width(); + + XubString aText = GetText(); + if ( aText.Len() && ! (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) ) + { + // subtract what will be added later + nMaxWidth-=2; + nMaxWidth -= ImplGetImageToTextDistance(); + + Size aTextSize = GetTextRect( Rectangle( Point(), Size( nMaxWidth > 0 ? nMaxWidth : 0x7fffffff, 0x7fffffff ) ), + aText, FixedText::ImplGetTextStyle( GetStyle() ) ).GetSize(); + aSize.Width()+=2; // for focus rect + aSize.Width() += ImplGetImageToTextDistance(); + aSize.Width() += aTextSize.Width(); + if ( aSize.Height() < aTextSize.Height() ) + aSize.Height() = aTextSize.Height(); + } + else + { + // is this still correct ? since the checkbox now + // shows a focus rect it should be 2 pixels wider and longer +/* da ansonsten im Writer die Control zu weit oben haengen + aSize.Width() += 2; + aSize.Height() += 2; +*/ + } + + return CalcWindowSize( aSize ); +} + +// ----------------------------------------------------------------------- + +Size CheckBox::GetOptimalSize(WindowSizeType eType) const +{ + switch (eType) { + case WINDOWSIZE_MINIMUM: + return CalcMinimumSize(); + default: + return Button::GetOptimalSize( eType ); + } +} + +// ======================================================================= + +ImageButton::ImageButton( WindowType nType ) : + PushButton( nType ) +{ + ImplInitStyle(); +} + +// ----------------------------------------------------------------------- + +ImageButton::ImageButton( Window* pParent, WinBits nStyle ) : + PushButton( pParent, nStyle ) +{ + ImplInitStyle(); +} + +// ----------------------------------------------------------------------- + +ImageButton::ImageButton( Window* pParent, const ResId& rResId ) : + PushButton( pParent, rResId.SetRT( RSC_IMAGEBUTTON ) ) +{ + ULONG nObjMask = ReadLongRes(); + + if ( RSC_IMAGEBUTTON_IMAGE & nObjMask ) + { + SetModeImage( Image( ResId( (RSHEADER_TYPE*)GetClassRes(), *rResId.GetResMgr() ) ) ); + IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) ); + } + + if ( RSC_IMAGEBUTTON_SYMBOL & nObjMask ) + SetSymbol( (SymbolType)ReadLongRes() ); + + if ( RSC_IMAGEBUTTON_STATE & nObjMask ) + SetState( (TriState)ReadLongRes() ); + + ImplInitStyle(); +} + +// ----------------------------------------------------------------------- + +ImageButton::~ImageButton() +{ +} + +// ----------------------------------------------------------------------- +void ImageButton::ImplInitStyle() +{ + WinBits nStyle = GetStyle(); + + if ( ! ( nStyle & ( WB_RIGHT | WB_LEFT ) ) ) + nStyle |= WB_CENTER; + + if ( ! ( nStyle & ( WB_TOP | WB_BOTTOM ) ) ) + nStyle |= WB_VCENTER; + + SetStyle( nStyle ); +} + +// ======================================================================= + +ImageRadioButton::ImageRadioButton( Window* pParent, WinBits nStyle ) : + RadioButton( pParent, nStyle ) +{ +} + +// ----------------------------------------------------------------------- + +ImageRadioButton::ImageRadioButton( Window* pParent, const ResId& rResId ) : + RadioButton( pParent, rResId.SetRT( RSC_IMAGERADIOBUTTON ) ) +{ + ULONG nObjMask = ReadLongRes(); + + if ( RSC_IMAGERADIOBUTTON_IMAGE & nObjMask ) + { + SetModeRadioImage( Image( ResId( (RSHEADER_TYPE*)GetClassRes(), *rResId.GetResMgr() ) ) ); + IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) ); + } +} + +// ----------------------------------------------------------------------- + +ImageRadioButton::~ImageRadioButton() +{ +} + +// ======================================================================= + +TriStateBox::TriStateBox( Window* pParent, WinBits nStyle ) : + CheckBox( pParent, nStyle ) +{ + EnableTriState( TRUE ); +} + +// ----------------------------------------------------------------------- + +TriStateBox::TriStateBox( Window* pParent, const ResId& rResId ) : + CheckBox( pParent, rResId.SetRT( RSC_TRISTATEBOX ) ) +{ + EnableTriState( TRUE ); + + ULONG nTriState = ReadLongRes(); + USHORT bDisableTriState = ReadShortRes(); + //anderer Wert als Default ? + if ( (TriState)nTriState != STATE_NOCHECK ) + SetState( (TriState)nTriState ); + if ( bDisableTriState ) + EnableTriState( FALSE ); +} + +// ----------------------------------------------------------------------- + +TriStateBox::~TriStateBox() +{ +} + +// ======================================================================= + +DisclosureButton::DisclosureButton( Window* pParent, WinBits ) : + CheckBox( pParent, WB_NOBORDER ) +{ +} + +// ----------------------------------------------------------------------- + +DisclosureButton::DisclosureButton( Window* pParent, const ResId& rResId ) : + CheckBox( pParent, rResId.SetRT( RSC_CHECKBOX ) ) +{ +} + +// ----------------------------------------------------------------------- + +void DisclosureButton::ImplDrawCheckBoxState() +{ + /* HACK: DisclosureButton is currently assuming, that the disclosure sign + will fit into the rectangle occupied by a normal checkbox on all themes. + If this does not hold true for some theme, ImplGetCheckImageSize + would have to be overloaded for DisclosureButton; also GetNativeControlRegion + for CTRL_LISTNODE would have to be implemented and taken into account + */ + + Rectangle aStateRect( GetStateRect() ); + + ImplControlValue aControlValue( GetState() == STATE_CHECK ? BUTTONVALUE_ON : BUTTONVALUE_OFF ); + Rectangle aCtrlRegion( aStateRect ); + ControlState nState = 0; + + if ( HasFocus() ) nState |= CTRL_STATE_FOCUSED; + if ( ImplGetButtonState() & BUTTON_DRAW_DEFAULT ) nState |= CTRL_STATE_DEFAULT; + if ( Window::IsEnabled() ) nState |= CTRL_STATE_ENABLED; + if ( IsMouseOver() && GetMouseRect().IsInside( GetPointerPosPixel() ) ) + nState |= CTRL_STATE_ROLLOVER; + + if( ! DrawNativeControl( CTRL_LISTNODE, PART_ENTIRE_CONTROL, aCtrlRegion, nState, + aControlValue, rtl::OUString() ) ) + { + ImplSVCtrlData& rCtrlData( ImplGetSVData()->maCtrlData ); + if( ! rCtrlData.mpDisclosurePlus ) + rCtrlData.mpDisclosurePlus = new Image( BitmapEx( VclResId( SV_DISCLOSURE_PLUS ) ) ); + if( ! rCtrlData.mpDisclosurePlusHC ) + rCtrlData.mpDisclosurePlusHC = new Image( BitmapEx( VclResId( SV_DISCLOSURE_PLUS_HC ) ) ); + if( ! rCtrlData.mpDisclosureMinus ) + rCtrlData.mpDisclosureMinus = new Image( BitmapEx( VclResId( SV_DISCLOSURE_MINUS ) ) ); + if( ! rCtrlData.mpDisclosureMinusHC ) + rCtrlData.mpDisclosureMinusHC = new Image( BitmapEx( VclResId( SV_DISCLOSURE_MINUS_HC ) ) ); + + Image* pImg = NULL; + if( GetSettings().GetStyleSettings().GetHighContrastMode() ) + pImg = IsChecked() ? rCtrlData.mpDisclosureMinusHC : rCtrlData.mpDisclosurePlusHC; + else + pImg = IsChecked() ? rCtrlData.mpDisclosureMinus : rCtrlData.mpDisclosurePlus; + + DBG_ASSERT( pImg, "no disclosure image" ); + if( ! pImg ) + return; + + USHORT nStyle = 0; + if( ! IsEnabled() ) + nStyle |= IMAGE_DRAW_DISABLE; + + Size aSize( aStateRect.GetSize() ); + Size aImgSize( pImg->GetSizePixel() ); + Point aOff( (aSize.Width() - aImgSize.Width())/2, + (aSize.Height() - aImgSize.Height())/2 ); + aOff += aStateRect.TopLeft(); + DrawImage( aOff, *pImg, nStyle ); + } +} + +// ----------------------------------------------------------------------- + +void DisclosureButton::KeyInput( const KeyEvent& rKEvt ) +{ + KeyCode aKeyCode = rKEvt.GetKeyCode(); + + if( !aKeyCode.GetModifier() && + ( ( aKeyCode.GetCode() == KEY_ADD ) || + ( aKeyCode.GetCode() == KEY_SUBTRACT ) ) + ) + { + Check( aKeyCode.GetCode() == KEY_ADD ); + } + else + Button::KeyInput( rKEvt ); +} + + |