fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / vcl / source / control / button.cxx
blobd223320a9a13f777113c00a97e5f1f585f5b5b99
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <tools/debug.hxx>
22 #include <tools/poly.hxx>
23 #include <tools/rc.h>
25 #include <vcl/image.hxx>
26 #include <vcl/bitmap.hxx>
27 #include <vcl/bitmapex.hxx>
28 #include <vcl/decoview.hxx>
29 #include <vcl/event.hxx>
30 #include <vcl/svapp.hxx>
31 #include <vcl/dialog.hxx>
32 #include <vcl/fixed.hxx>
33 #include <vcl/button.hxx>
34 #include <vcl/salnativewidgets.hxx>
35 #include <vcl/edit.hxx>
36 #include <vcl/layout.hxx>
38 #include <svids.hrc>
39 #include <svdata.hxx>
40 #include <window.h>
41 #include <controldata.hxx>
43 // =======================================================================
45 #define PUSHBUTTON_VIEW_STYLE (WB_3DLOOK | \
46 WB_LEFT | WB_CENTER | WB_RIGHT | \
47 WB_TOP | WB_VCENTER | WB_BOTTOM | \
48 WB_WORDBREAK | WB_NOLABEL | \
49 WB_DEFBUTTON | WB_NOLIGHTBORDER | \
50 WB_RECTSTYLE | WB_SMALLSTYLE | \
51 WB_TOGGLE )
52 #define RADIOBUTTON_VIEW_STYLE (WB_3DLOOK | \
53 WB_LEFT | WB_CENTER | WB_RIGHT | \
54 WB_TOP | WB_VCENTER | WB_BOTTOM | \
55 WB_WORDBREAK | WB_NOLABEL)
56 #define CHECKBOX_VIEW_STYLE (WB_3DLOOK | \
57 WB_LEFT | WB_CENTER | WB_RIGHT | \
58 WB_TOP | WB_VCENTER | WB_BOTTOM | \
59 WB_WORDBREAK | WB_NOLABEL)
61 // =======================================================================
63 class ImplCommonButtonData
65 public:
66 Rectangle maFocusRect;
67 long mnSeparatorX;
68 sal_uInt16 mnButtonState;
69 bool mbSmallSymbol;
71 Image maImage;
72 ImageAlign meImageAlign;
73 SymbolAlign meSymbolAlign;
75 public:
76 ImplCommonButtonData();
77 ~ImplCommonButtonData();
80 // -----------------------------------------------------------------------
81 ImplCommonButtonData::ImplCommonButtonData() : maFocusRect(), mnSeparatorX(0), mnButtonState(0),
82 mbSmallSymbol(false), maImage(), meImageAlign(IMAGEALIGN_TOP), meSymbolAlign(SYMBOLALIGN_LEFT)
86 // -----------------------------------------------------------------------
87 ImplCommonButtonData::~ImplCommonButtonData()
91 // =======================================================================
93 Button::Button( WindowType nType ) :
94 Control( nType )
96 mpButtonData = new ImplCommonButtonData;
99 // -----------------------------------------------------------------------
101 Button::~Button()
103 delete mpButtonData;
106 // -----------------------------------------------------------------------
108 void Button::Click()
110 ImplCallEventListenersAndHandler( VCLEVENT_BUTTON_CLICK, maClickHdl, this );
113 // -----------------------------------------------------------------------
115 OUString Button::GetStandardText( StandardButtonType eButton )
117 static struct
119 sal_uInt32 nResId;
120 const char* pDefText;
121 } aResIdAry[BUTTON_COUNT] =
123 { SV_BUTTONTEXT_OK, "~OK" },
124 { SV_BUTTONTEXT_CANCEL, "~Cancel" },
125 { SV_BUTTONTEXT_YES, "~Yes" },
126 { SV_BUTTONTEXT_NO, "~No" },
127 { SV_BUTTONTEXT_RETRY, "~Retry" },
128 { SV_BUTTONTEXT_HELP, "~Help" },
129 { SV_BUTTONTEXT_CLOSE, "~Close" },
130 { SV_BUTTONTEXT_MORE, "~More" },
131 { SV_BUTTONTEXT_IGNORE, "~Ignore" },
132 { SV_BUTTONTEXT_ABORT, "~Abort" },
133 { SV_BUTTONTEXT_LESS, "~Less" },
134 { SV_BUTTONTEXT_RESET, "R~eset" }
137 ResMgr* pResMgr = ImplGetResMgr();
139 if (!pResMgr)
141 OString aT( aResIdAry[(sal_uInt16)eButton].pDefText );
142 return OStringToOUString(aT, RTL_TEXTENCODING_ASCII_US);
145 sal_uInt32 nResId = aResIdAry[(sal_uInt16)eButton].nResId;
146 #ifdef WNT
147 // http://lists.freedesktop.org/archives/libreoffice/2013-January/044513.html
148 // Under windows we don't want accelerators on ok/cancel but do on other
149 // buttons
150 if (nResId == SV_BUTTONTEXT_OK)
151 nResId = SV_BUTTONTEXT_OK_NOMNEMONIC;
152 else if (nResId == SV_BUTTONTEXT_CANCEL)
153 nResId = SV_BUTTONTEXT_CANCEL_NOMNEMONIC;
154 #endif
155 return ResId(nResId, *pResMgr).toString();
158 // -----------------------------------------------------------------------
160 XubString Button::GetStandardHelpText( StandardButtonType /* eButton */ )
162 XubString aHelpText;
163 return aHelpText;
166 // -----------------------------------------------------------------------
167 sal_Bool Button::SetModeImage( const Image& rImage )
169 if ( rImage != mpButtonData->maImage )
171 mpButtonData->maImage = rImage;
172 StateChanged( STATE_CHANGE_DATA );
173 queue_resize();
175 return sal_True;
178 // -----------------------------------------------------------------------
179 const Image Button::GetModeImage( ) const
181 return mpButtonData->maImage;
184 // -----------------------------------------------------------------------
185 sal_Bool Button::HasImage() const
187 return !!(mpButtonData->maImage);
190 // -----------------------------------------------------------------------
191 void Button::SetImageAlign( ImageAlign eAlign )
193 if ( mpButtonData->meImageAlign != eAlign )
195 mpButtonData->meImageAlign = eAlign;
196 StateChanged( STATE_CHANGE_DATA );
200 // -----------------------------------------------------------------------
201 ImageAlign Button::GetImageAlign() const
203 return mpButtonData->meImageAlign;
206 // -----------------------------------------------------------------------
208 void Button::SetFocusRect( const Rectangle& rFocusRect )
210 ImplSetFocusRect( rFocusRect );
213 // -----------------------------------------------------------------------
215 long Button::ImplGetSeparatorX() const
217 return mpButtonData->mnSeparatorX;
220 void Button::ImplSetSeparatorX( long nX )
222 mpButtonData->mnSeparatorX = nX;
225 // -----------------------------------------------------------------------
227 sal_uInt16 Button::ImplGetTextStyle( OUString& rText, WinBits nWinStyle,
228 sal_uLong nDrawFlags )
230 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
231 sal_uInt16 nTextStyle = FixedText::ImplGetTextStyle( nWinStyle & ~WB_DEFBUTTON );
233 if ( nDrawFlags & WINDOW_DRAW_NOMNEMONIC )
235 if ( nTextStyle & TEXT_DRAW_MNEMONIC )
237 rText = GetNonMnemonicString( rText );
238 nTextStyle &= ~TEXT_DRAW_MNEMONIC;
242 if ( !(nDrawFlags & WINDOW_DRAW_NODISABLE) )
244 if ( !IsEnabled() )
245 nTextStyle |= TEXT_DRAW_DISABLE;
248 if ( (nDrawFlags & WINDOW_DRAW_MONO) ||
249 (rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
250 nTextStyle |= TEXT_DRAW_MONO;
252 return nTextStyle;
255 // -----------------------------------------------------------------------
257 void Button::ImplDrawAlignedImage( OutputDevice* pDev, Point& rPos,
258 Size& rSize, sal_Bool bLayout,
259 sal_uLong nImageSep, sal_uLong nDrawFlags,
260 sal_uInt16 nTextStyle, Rectangle *pSymbolRect,
261 bool bAddImageSep )
263 OUString aText( GetText() );
264 bool bDrawImage = HasImage() && ! ( ImplGetButtonState() & BUTTON_DRAW_NOIMAGE );
265 bool bDrawText = !aText.isEmpty() && ! ( ImplGetButtonState() & BUTTON_DRAW_NOTEXT );
266 bool bHasSymbol = pSymbolRect ? true : false;
268 // No text and no image => nothing to do => return
269 if ( !bDrawImage && !bDrawText && !bHasSymbol )
270 return;
272 WinBits nWinStyle = GetStyle();
273 Rectangle aOutRect( rPos, rSize );
274 MetricVector *pVector = bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : NULL;
275 OUString *pDisplayText = bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : NULL;
276 ImageAlign eImageAlign = mpButtonData->meImageAlign;
277 Size aImageSize = mpButtonData->maImage.GetSizePixel();
279 if ( ( nDrawFlags & WINDOW_DRAW_NOMNEMONIC ) &&
280 ( nTextStyle & TEXT_DRAW_MNEMONIC ) )
282 aText = GetNonMnemonicString( aText );
283 nTextStyle &= ~TEXT_DRAW_MNEMONIC;
286 aImageSize.Width() = CalcZoom( aImageSize.Width() );
287 aImageSize.Height() = CalcZoom( aImageSize.Height() );
289 // Drawing text or symbol only is simple, use style and output rectangle
290 if ( bHasSymbol && !bDrawImage && !bDrawText )
292 *pSymbolRect = aOutRect;
293 return;
295 else if ( bDrawText && !bDrawImage && !bHasSymbol )
297 DrawControlText( *pDev, aOutRect, aText, nTextStyle, pVector, pDisplayText );
299 ImplSetFocusRect( aOutRect );
300 rSize = aOutRect.GetSize();
301 rPos = aOutRect.TopLeft();
303 return;
306 // check for HC mode ( image only! )
307 Image *pImage = &(mpButtonData->maImage);
309 Size aTextSize;
310 Size aSymbolSize;
311 Size aMax;
312 Point aImagePos = rPos;
313 Point aTextPos = rPos;
314 Rectangle aUnion = Rectangle( aImagePos, aImageSize );
315 Rectangle aSymbol;
316 long nSymbolHeight = 0;
318 if ( bDrawText || bHasSymbol )
320 // Get the size of the text output area ( the symbol will be drawn in
321 // this area as well, so the symbol rectangle will be calculated here, too )
323 Rectangle aRect = Rectangle( Point(), rSize );
324 Size aTSSize;
326 if ( bHasSymbol )
328 if ( bDrawText )
330 nSymbolHeight = pDev->GetTextHeight();
331 if ( mpButtonData->mbSmallSymbol )
332 nSymbolHeight = nSymbolHeight * 3 / 4;
334 aSymbol = Rectangle( Point(), Size( nSymbolHeight, nSymbolHeight ) );
335 ImplCalcSymbolRect( aSymbol );
336 aRect.Left() += 3 * nSymbolHeight / 2;
337 aTSSize.Width() = 3 * nSymbolHeight / 2;
339 else
341 aSymbol = Rectangle( Point(), rSize );
342 ImplCalcSymbolRect( aSymbol );
343 aTSSize.Width() = aSymbol.GetWidth();
345 aTSSize.Height() = aSymbol.GetHeight();
346 aSymbolSize = aSymbol.GetSize();
349 if ( bDrawText )
351 if ( ( eImageAlign == IMAGEALIGN_LEFT_TOP ) ||
352 ( eImageAlign == IMAGEALIGN_LEFT ) ||
353 ( eImageAlign == IMAGEALIGN_LEFT_BOTTOM ) ||
354 ( eImageAlign == IMAGEALIGN_RIGHT_TOP ) ||
355 ( eImageAlign == IMAGEALIGN_RIGHT ) ||
356 ( eImageAlign == IMAGEALIGN_RIGHT_BOTTOM ) )
358 aRect.Right() -= ( aImageSize.Width() + nImageSep );
360 else if ( ( eImageAlign == IMAGEALIGN_TOP_LEFT ) ||
361 ( eImageAlign == IMAGEALIGN_TOP ) ||
362 ( eImageAlign == IMAGEALIGN_TOP_RIGHT ) ||
363 ( eImageAlign == IMAGEALIGN_BOTTOM_LEFT ) ||
364 ( eImageAlign == IMAGEALIGN_BOTTOM ) ||
365 ( eImageAlign == IMAGEALIGN_BOTTOM_RIGHT ) )
367 aRect.Bottom() -= ( aImageSize.Height() + nImageSep );
370 aRect = pDev->GetTextRect( aRect, aText, nTextStyle );
371 aTextSize = aRect.GetSize();
373 aTSSize.Width() += aTextSize.Width();
375 if ( aTSSize.Height() < aTextSize.Height() )
376 aTSSize.Height() = aTextSize.Height();
378 if( bAddImageSep && bDrawImage )
380 long nDiff = (aImageSize.Height() - aTextSize.Height()) / 3;
381 if( nDiff > 0 )
382 nImageSep += nDiff;
386 aMax.Width() = aTSSize.Width() > aImageSize.Width() ? aTSSize.Width() : aImageSize.Width();
387 aMax.Height() = aTSSize.Height() > aImageSize.Height() ? aTSSize.Height() : aImageSize.Height();
389 // Now calculate the output area for the image and the text acording to the image align flags
391 if ( ( eImageAlign == IMAGEALIGN_LEFT ) ||
392 ( eImageAlign == IMAGEALIGN_RIGHT ) )
394 aImagePos.Y() = rPos.Y() + ( aMax.Height() - aImageSize.Height() ) / 2;
395 aTextPos.Y() = rPos.Y() + ( aMax.Height() - aTSSize.Height() ) / 2;
397 else if ( ( eImageAlign == IMAGEALIGN_LEFT_BOTTOM ) ||
398 ( eImageAlign == IMAGEALIGN_RIGHT_BOTTOM ) )
400 aImagePos.Y() = rPos.Y() + aMax.Height() - aImageSize.Height();
401 aTextPos.Y() = rPos.Y() + aMax.Height() - aTSSize.Height();
403 else if ( ( eImageAlign == IMAGEALIGN_TOP ) ||
404 ( eImageAlign == IMAGEALIGN_BOTTOM ) )
406 aImagePos.X() = rPos.X() + ( aMax.Width() - aImageSize.Width() ) / 2;
407 aTextPos.X() = rPos.X() + ( aMax.Width() - aTSSize.Width() ) / 2;
409 else if ( ( eImageAlign == IMAGEALIGN_TOP_RIGHT ) ||
410 ( eImageAlign == IMAGEALIGN_BOTTOM_RIGHT ) )
412 aImagePos.X() = rPos.X() + aMax.Width() - aImageSize.Width();
413 aTextPos.X() = rPos.X() + aMax.Width() - aTSSize.Width();
416 if ( ( eImageAlign == IMAGEALIGN_LEFT_TOP ) ||
417 ( eImageAlign == IMAGEALIGN_LEFT ) ||
418 ( eImageAlign == IMAGEALIGN_LEFT_BOTTOM ) )
420 aTextPos.X() = rPos.X() + aImageSize.Width() + nImageSep;
422 else if ( ( eImageAlign == IMAGEALIGN_RIGHT_TOP ) ||
423 ( eImageAlign == IMAGEALIGN_RIGHT ) ||
424 ( eImageAlign == IMAGEALIGN_RIGHT_BOTTOM ) )
426 aImagePos.X() = rPos.X() + aTSSize.Width() + nImageSep;
428 else if ( ( eImageAlign == IMAGEALIGN_TOP_LEFT ) ||
429 ( eImageAlign == IMAGEALIGN_TOP ) ||
430 ( eImageAlign == IMAGEALIGN_TOP_RIGHT ) )
432 aTextPos.Y() = rPos.Y() + aImageSize.Height() + nImageSep;
434 else if ( ( eImageAlign == IMAGEALIGN_BOTTOM_LEFT ) ||
435 ( eImageAlign == IMAGEALIGN_BOTTOM ) ||
436 ( eImageAlign == IMAGEALIGN_BOTTOM_RIGHT ) )
438 aImagePos.Y() = rPos.Y() + aTSSize.Height() + nImageSep;
440 else if ( eImageAlign == IMAGEALIGN_CENTER )
442 aImagePos.X() = rPos.X() + ( aMax.Width() - aImageSize.Width() ) / 2;
443 aImagePos.Y() = rPos.Y() + ( aMax.Height() - aImageSize.Height() ) / 2;
444 aTextPos.X() = rPos.X() + ( aMax.Width() - aTSSize.Width() ) / 2;
445 aTextPos.Y() = rPos.Y() + ( aMax.Height() - aTSSize.Height() ) / 2;
447 aUnion = Rectangle( aImagePos, aImageSize );
448 aUnion.Union( Rectangle( aTextPos, aTSSize ) );
451 // Now place the combination of text and image in the output area of the button
452 // according to the window style (WinBits)
453 long nXOffset = 0;
454 long nYOffset = 0;
456 if ( nWinStyle & WB_CENTER )
458 nXOffset = ( rSize.Width() - aUnion.GetWidth() ) / 2;
460 else if ( nWinStyle & WB_RIGHT )
462 nXOffset = rSize.Width() - aUnion.GetWidth();
465 if ( nWinStyle & WB_VCENTER )
467 nYOffset = ( rSize.Height() - aUnion.GetHeight() ) / 2;
469 else if ( nWinStyle & WB_BOTTOM )
471 nYOffset = rSize.Height() - aUnion.GetHeight();
474 // the top left corner should always be visible, so we don't allow negative offsets
475 if ( nXOffset < 0 ) nXOffset = 0;
476 if ( nYOffset < 0 ) nYOffset = 0;
478 aImagePos.X() += nXOffset;
479 aImagePos.Y() += nYOffset;
480 aTextPos.X() += nXOffset;
481 aTextPos.Y() += nYOffset;
483 // set rPos and rSize to the union
484 rSize = aUnion.GetSize();
485 rPos.X() += nXOffset;
486 rPos.Y() += nYOffset;
488 if ( bHasSymbol )
490 if ( mpButtonData->meSymbolAlign == SYMBOLALIGN_RIGHT )
492 Point aRightPos = Point( aTextPos.X() + aTextSize.Width() + aSymbolSize.Width()/2, aTextPos.Y() );
493 *pSymbolRect = Rectangle( aRightPos, aSymbolSize );
495 else
497 *pSymbolRect = Rectangle( aTextPos, aSymbolSize );
498 aTextPos.X() += ( 3 * nSymbolHeight / 2 );
500 if ( mpButtonData->mbSmallSymbol )
502 nYOffset = (aUnion.GetHeight() - aSymbolSize.Height())/2;
503 pSymbolRect->setY( aTextPos.Y() + nYOffset );
507 sal_uInt16 nStyle = 0;
509 if ( ! ( nDrawFlags & WINDOW_DRAW_NODISABLE ) &&
510 ! IsEnabled() )
511 nStyle |= IMAGE_DRAW_DISABLE;
513 if ( IsZoom() )
514 pDev->DrawImage( aImagePos, aImageSize, *pImage, nStyle );
515 else
516 pDev->DrawImage( aImagePos, *pImage, nStyle );
518 if ( bDrawText )
520 ImplSetFocusRect( Rectangle( aTextPos, aTextSize ) );
521 pDev->DrawText( Rectangle( aTextPos, aTextSize ), aText, nTextStyle, pVector, pDisplayText );
523 else
525 ImplSetFocusRect( Rectangle( aImagePos, aImageSize ) );
529 // -----------------------------------------------------------------------
530 void Button::ImplSetFocusRect( const Rectangle &rFocusRect )
532 Rectangle aFocusRect = rFocusRect;
533 Rectangle aOutputRect = Rectangle( Point(), GetOutputSizePixel() );
535 if ( ! aFocusRect.IsEmpty() )
537 aFocusRect.Left()--;
538 aFocusRect.Top()--;
539 aFocusRect.Right()++;
540 aFocusRect.Bottom()++;
543 if ( aFocusRect.Left() < aOutputRect.Left() ) aFocusRect.Left() = aOutputRect.Left();
544 if ( aFocusRect.Top() < aOutputRect.Top() ) aFocusRect.Top() = aOutputRect.Top();
545 if ( aFocusRect.Right() > aOutputRect.Right() ) aFocusRect.Right() = aOutputRect.Right();
546 if ( aFocusRect.Bottom() > aOutputRect.Bottom() ) aFocusRect.Bottom() = aOutputRect.Bottom();
548 mpButtonData->maFocusRect = aFocusRect;
551 // -----------------------------------------------------------------------
552 const Rectangle& Button::ImplGetFocusRect() const
554 return mpButtonData->maFocusRect;
557 // -----------------------------------------------------------------------
558 sal_uInt16& Button::ImplGetButtonState()
560 return mpButtonData->mnButtonState;
563 // -----------------------------------------------------------------------
564 sal_uInt16 Button::ImplGetButtonState() const
566 return mpButtonData->mnButtonState;
569 // -----------------------------------------------------------------------
570 void Button::ImplSetSymbolAlign( SymbolAlign eAlign )
572 if ( mpButtonData->meSymbolAlign != eAlign )
574 mpButtonData->meSymbolAlign = eAlign;
575 StateChanged( STATE_CHANGE_DATA );
579 // -----------------------------------------------------------------------
580 void Button::SetSmallSymbol(bool bSmall)
582 mpButtonData->mbSmallSymbol = bSmall;
585 // -----------------------------------------------------------------------
586 void Button::EnableImageDisplay( sal_Bool bEnable )
588 if( bEnable )
589 mpButtonData->mnButtonState &= ~BUTTON_DRAW_NOIMAGE;
590 else
591 mpButtonData->mnButtonState |= BUTTON_DRAW_NOIMAGE;
594 // -----------------------------------------------------------------------
595 void Button::EnableTextDisplay( sal_Bool bEnable )
597 if( bEnable )
598 mpButtonData->mnButtonState &= ~BUTTON_DRAW_NOTEXT;
599 else
600 mpButtonData->mnButtonState |= BUTTON_DRAW_NOTEXT;
603 bool Button::IsSmallSymbol () const
605 return mpButtonData->mbSmallSymbol;
608 // =======================================================================
610 void PushButton::ImplInitPushButtonData()
612 mpWindowImpl->mbPushButton = sal_True;
614 meSymbol = SYMBOL_NOSYMBOL;
615 meState = STATE_NOCHECK;
616 meSaveValue = STATE_NOCHECK;
617 mnDDStyle = 0;
618 mbPressed = sal_False;
619 mbInUserDraw = sal_False;
622 // -----------------------------------------------------------------------
624 void PushButton::ImplInit( Window* pParent, WinBits nStyle )
626 nStyle = ImplInitStyle( pParent->GetWindow( WINDOW_LASTCHILD ), nStyle );
627 Button::ImplInit( pParent, nStyle, NULL );
629 if ( nStyle & WB_NOLIGHTBORDER )
630 ImplGetButtonState() |= BUTTON_DRAW_NOLIGHTBORDER;
632 ImplInitSettings( sal_True, sal_True, sal_True );
635 // -----------------------------------------------------------------------
637 WinBits PushButton::ImplInitStyle( const Window* pPrevWindow, WinBits nStyle )
639 if ( !(nStyle & WB_NOTABSTOP) )
640 nStyle |= WB_TABSTOP;
642 // if no alignment is given, default to "vertically centered". This is because since
643 // #i26046#, we respect the vertical alignment flags (previously we didn't completely),
644 // but we of course want to look as before when no vertical alignment is specified
645 if ( ( nStyle & ( WB_TOP | WB_VCENTER | WB_BOTTOM ) ) == 0 )
646 nStyle |= WB_VCENTER;
648 if ( !(nStyle & WB_NOGROUP) &&
649 (!pPrevWindow ||
650 ((pPrevWindow->GetType() != WINDOW_PUSHBUTTON ) &&
651 (pPrevWindow->GetType() != WINDOW_OKBUTTON ) &&
652 (pPrevWindow->GetType() != WINDOW_CANCELBUTTON) &&
653 (pPrevWindow->GetType() != WINDOW_HELPBUTTON )) ) )
654 nStyle |= WB_GROUP;
655 return nStyle;
658 // -----------------------------------------------------------------
660 const Font& PushButton::GetCanonicalFont( const StyleSettings& _rStyle ) const
662 return _rStyle.GetPushButtonFont();
665 // -----------------------------------------------------------------
666 const Color& PushButton::GetCanonicalTextColor( const StyleSettings& _rStyle ) const
668 return _rStyle.GetButtonTextColor();
671 // -----------------------------------------------------------------------
673 void PushButton::ImplInitSettings( sal_Bool bFont,
674 sal_Bool bForeground, sal_Bool bBackground )
676 Button::ImplInitSettings( bFont, bForeground );
678 if ( bBackground )
680 SetBackground();
681 // #i38498#: do not check for GetParent()->IsChildTransparentModeEnabled()
682 // otherwise the formcontrol button will be overdrawn due to PARENTCLIPMODE_NOCLIP
683 // for radio and checkbox this is ok as they shoud appear transparent in documents
684 if ( IsNativeControlSupported( CTRL_PUSHBUTTON, PART_ENTIRE_CONTROL ) ||
685 (GetStyle() & WB_FLATBUTTON) != 0 )
687 EnableChildTransparentMode( sal_True );
688 SetParentClipMode( PARENTCLIPMODE_NOCLIP );
689 SetPaintTransparent( sal_True );
690 mpWindowImpl->mbUseNativeFocus = (GetStyle() & WB_FLATBUTTON)
691 ? false
692 : ImplGetSVData()->maNWFData.mbNoFocusRects;
694 else
696 EnableChildTransparentMode( sal_False );
697 SetParentClipMode( 0 );
698 SetPaintTransparent( sal_False );
703 // -----------------------------------------------------------------------
705 void PushButton::ImplDrawPushButtonFrame( Window* pDev,
706 Rectangle& rRect, sal_uInt16 nStyle )
708 if ( !(pDev->GetStyle() & (WB_RECTSTYLE | WB_SMALLSTYLE)) )
710 StyleSettings aStyleSettings = pDev->GetSettings().GetStyleSettings();
711 if ( pDev->IsControlBackground() )
712 aStyleSettings.Set3DColors( pDev->GetControlBackground() );
715 DecorationView aDecoView( pDev );
716 if ( pDev->IsControlBackground() )
718 AllSettings aSettings = pDev->GetSettings();
719 AllSettings aOldSettings = aSettings;
720 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
721 aStyleSettings.Set3DColors( pDev->GetControlBackground() );
722 aSettings.SetStyleSettings( aStyleSettings );
723 pDev->OutputDevice::SetSettings( aSettings );
724 rRect = aDecoView.DrawButton( rRect, nStyle );
725 pDev->OutputDevice::SetSettings( aOldSettings );
727 else
728 rRect = aDecoView.DrawButton( rRect, nStyle );
731 // -----------------------------------------------------------------------
733 sal_Bool PushButton::ImplHitTestPushButton( Window* pDev,
734 const Point& rPos )
736 Point aTempPoint;
737 Rectangle aTestRect( aTempPoint, pDev->GetOutputSizePixel() );
739 return aTestRect.IsInside( rPos );
742 // -----------------------------------------------------------------------
744 sal_uInt16 PushButton::ImplGetTextStyle( sal_uLong nDrawFlags ) const
746 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
748 sal_uInt16 nTextStyle = TEXT_DRAW_MNEMONIC | TEXT_DRAW_MULTILINE | TEXT_DRAW_ENDELLIPSIS;
750 if ( ( rStyleSettings.GetOptions() & STYLE_OPTION_MONO ) ||
751 ( nDrawFlags & WINDOW_DRAW_MONO ) )
752 nTextStyle |= TEXT_DRAW_MONO;
754 if ( GetStyle() & WB_WORDBREAK )
755 nTextStyle |= TEXT_DRAW_WORDBREAK;
756 if ( GetStyle() & WB_NOLABEL )
757 nTextStyle &= ~TEXT_DRAW_MNEMONIC;
759 if ( GetStyle() & WB_LEFT )
760 nTextStyle |= TEXT_DRAW_LEFT;
761 else if ( GetStyle() & WB_RIGHT )
762 nTextStyle |= TEXT_DRAW_RIGHT;
763 else
764 nTextStyle |= TEXT_DRAW_CENTER;
766 if ( GetStyle() & WB_TOP )
767 nTextStyle |= TEXT_DRAW_TOP;
768 else if ( GetStyle() & WB_BOTTOM )
769 nTextStyle |= TEXT_DRAW_BOTTOM;
770 else
771 nTextStyle |= TEXT_DRAW_VCENTER;
773 if ( ! ( (nDrawFlags & WINDOW_DRAW_NODISABLE) || IsEnabled() ) )
774 nTextStyle |= TEXT_DRAW_DISABLE;
776 return nTextStyle;
779 // -----------------------------------------------------------------------
781 static void ImplDrawBtnDropDownArrow( OutputDevice* pDev,
782 long nX, long nY,
783 Color& rColor, bool bBlack )
785 Color aOldLineColor = pDev->GetLineColor();
786 Color aOldFillColor = pDev->GetFillColor();
788 pDev->SetLineColor();
789 if ( bBlack )
790 pDev->SetFillColor( Color( COL_BLACK ) );
791 else
792 pDev->SetFillColor( rColor );
793 pDev->DrawRect( Rectangle( nX+0, nY+0, nX+6, nY+0 ) );
794 pDev->DrawRect( Rectangle( nX+1, nY+1, nX+5, nY+1 ) );
795 pDev->DrawRect( Rectangle( nX+2, nY+2, nX+4, nY+2 ) );
796 pDev->DrawRect( Rectangle( nX+3, nY+3, nX+3, nY+3 ) );
797 if ( bBlack )
799 pDev->SetFillColor( rColor );
800 pDev->DrawRect( Rectangle( nX+2, nY+1, nX+4, nY+1 ) );
801 pDev->DrawRect( Rectangle( nX+3, nY+2, nX+3, nY+2 ) );
803 pDev->SetLineColor( aOldLineColor );
804 pDev->SetFillColor( aOldFillColor );
807 // -----------------------------------------------------------------------
809 void PushButton::ImplDrawPushButtonContent( OutputDevice* pDev, sal_uLong nDrawFlags,
810 const Rectangle& rRect,
811 bool bLayout,
812 bool bMenuBtnSep
815 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
816 Rectangle aInRect = rRect;
817 Color aColor;
818 OUString aText = PushButton::GetText(); // PushButton:: because of MoreButton
819 sal_uInt16 nTextStyle = ImplGetTextStyle( nDrawFlags );
820 sal_uInt16 nStyle;
822 if( aInRect.Right() < aInRect.Left() || aInRect.Bottom() < aInRect.Top() )
823 aInRect.SetEmpty();
825 pDev->Push( PUSH_CLIPREGION );
826 pDev->IntersectClipRegion( aInRect );
828 if ( nDrawFlags & WINDOW_DRAW_MONO )
829 aColor = Color( COL_BLACK );
830 else if ( IsControlForeground() )
831 aColor = GetControlForeground();
832 else if( nDrawFlags & WINDOW_DRAW_ROLLOVER )
833 aColor = rStyleSettings.GetButtonRolloverTextColor();
834 else
835 aColor = rStyleSettings.GetButtonTextColor();
837 pDev->SetTextColor( aColor );
839 if ( IsEnabled() || (nDrawFlags & WINDOW_DRAW_NODISABLE) )
840 nStyle = 0;
841 else
842 nStyle = SYMBOL_DRAW_DISABLE;
844 Size aSize = rRect.GetSize();
845 Point aPos = rRect.TopLeft();
847 sal_uLong nImageSep = 1 + (pDev->GetTextHeight()-10)/2;
848 if( nImageSep < 1 )
849 nImageSep = 1;
850 if ( mnDDStyle == PUSHBUTTON_DROPDOWN_MENUBUTTON )
852 long nSeparatorX = 0;
853 Rectangle aSymbolRect = aInRect;
854 if ( !aText.isEmpty() && ! (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) )
856 // calculate symbol size
857 long nSymbolSize = pDev->GetTextHeight() / 2 + 1;
859 nSeparatorX = aInRect.Right() - 2*nSymbolSize;
860 aSize.Width() -= 2*nSymbolSize;
862 // center symbol rectangle in the separated area
863 aSymbolRect.Right() -= nSymbolSize/2;
864 aSymbolRect.Left() = aSymbolRect.Right() - nSymbolSize;
866 ImplDrawAlignedImage( pDev, aPos, aSize, bLayout, nImageSep,
867 nDrawFlags, nTextStyle, NULL, true );
869 else
870 ImplCalcSymbolRect( aSymbolRect );
872 if( ! bLayout )
874 long nDistance = (aSymbolRect.GetHeight() > 10) ? 2 : 1;
875 DecorationView aDecoView( pDev );
876 if( bMenuBtnSep && nSeparatorX > 0 )
878 Point aStartPt( nSeparatorX, aSymbolRect.Top()+nDistance );
879 Point aEndPt( nSeparatorX, aSymbolRect.Bottom()-nDistance );
880 aDecoView.DrawSeparator( aStartPt, aEndPt );
882 ImplSetSeparatorX( nSeparatorX );
884 aDecoView.DrawSymbol( aSymbolRect, SYMBOL_SPIN_DOWN, aColor, nStyle );
888 else
890 Rectangle aSymbolRect;
891 ImplDrawAlignedImage( pDev, aPos, aSize, bLayout, nImageSep, nDrawFlags,
892 nTextStyle, IsSymbol() ? &aSymbolRect : NULL, true );
894 if ( IsSymbol() && ! bLayout )
896 DecorationView aDecoView( pDev );
897 aDecoView.DrawSymbol( aSymbolRect, meSymbol, aColor, nStyle );
900 if ( mnDDStyle == PUSHBUTTON_DROPDOWN_TOOLBOX && !bLayout )
902 bool bBlack = false;
903 Color aArrowColor( COL_BLACK );
905 if ( !(nDrawFlags & WINDOW_DRAW_MONO) )
907 if ( !IsEnabled() )
908 aArrowColor = rStyleSettings.GetShadowColor();
909 else
911 aArrowColor = Color( COL_LIGHTGREEN );
912 bBlack = true;
916 ImplDrawBtnDropDownArrow( pDev, aInRect.Right()-6, aInRect.Top()+1,
917 aArrowColor, bBlack );
921 UserDrawEvent aUDEvt( this, aInRect, 0 );
922 UserDraw( aUDEvt );
924 pDev->Pop(); // restore clipregion
927 // -----------------------------------------------------------------------
929 void PushButton::UserDraw( const UserDrawEvent& )
933 // -----------------------------------------------------------------------
935 void PushButton::ImplDrawPushButton( bool bLayout )
937 if( !bLayout )
938 HideFocus();
940 sal_uInt16 nButtonStyle = ImplGetButtonState();
941 Point aPoint;
942 Size aOutSz( GetOutputSizePixel() );
943 Rectangle aRect( aPoint, aOutSz );
944 Rectangle aInRect = aRect;
945 sal_Bool bNativeOK = sal_False;
947 // adjust style if button should be rendered 'pressed'
948 if ( mbPressed )
949 nButtonStyle |= BUTTON_DRAW_PRESSED;
951 // TODO: move this to Window class or make it a member !!!
952 ControlType aCtrlType = 0;
953 switch( GetParent()->GetType() )
955 case WINDOW_LISTBOX:
956 case WINDOW_MULTILISTBOX:
957 case WINDOW_TREELISTBOX:
958 aCtrlType = CTRL_LISTBOX;
959 break;
961 case WINDOW_COMBOBOX:
962 case WINDOW_PATTERNBOX:
963 case WINDOW_NUMERICBOX:
964 case WINDOW_METRICBOX:
965 case WINDOW_CURRENCYBOX:
966 case WINDOW_DATEBOX:
967 case WINDOW_TIMEBOX:
968 case WINDOW_LONGCURRENCYBOX:
969 aCtrlType = CTRL_COMBOBOX;
970 break;
971 default:
972 break;
975 bool bDropDown = ( IsSymbol() && (GetSymbol()==SYMBOL_SPIN_DOWN) && GetText().isEmpty() );
977 if( bDropDown && (aCtrlType == CTRL_COMBOBOX || aCtrlType == CTRL_LISTBOX ) )
979 if( GetParent()->IsNativeControlSupported( aCtrlType, PART_ENTIRE_CONTROL) )
981 // skip painting if the button was already drawn by the theme
982 if( aCtrlType == CTRL_COMBOBOX )
984 Edit* pEdit = static_cast<Edit*>(GetParent());
985 if( pEdit->ImplUseNativeBorder( pEdit->GetStyle() ) )
986 bNativeOK = sal_True;
988 else if( GetParent()->IsNativeControlSupported( aCtrlType, HAS_BACKGROUND_TEXTURE) )
990 bNativeOK = sal_True;
992 if( !bNativeOK && GetParent()->IsNativeControlSupported( aCtrlType, PART_BUTTON_DOWN ) )
994 // let the theme draw it, note we then need support
995 // for CTRL_LISTBOX/PART_BUTTON_DOWN and CTRL_COMBOBOX/PART_BUTTON_DOWN
997 ImplControlValue aControlValue;
998 ControlState nState = 0;
1000 if ( mbPressed ) nState |= CTRL_STATE_PRESSED;
1001 if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED ) nState |= CTRL_STATE_PRESSED;
1002 if ( HasFocus() ) nState |= CTRL_STATE_FOCUSED;
1003 if ( ImplGetButtonState() & BUTTON_DRAW_DEFAULT ) nState |= CTRL_STATE_DEFAULT;
1004 if ( Window::IsEnabled() ) nState |= CTRL_STATE_ENABLED;
1006 if ( IsMouseOver() && aInRect.IsInside( GetPointerPosPixel() ) )
1007 nState |= CTRL_STATE_ROLLOVER;
1009 bNativeOK = DrawNativeControl( aCtrlType, PART_BUTTON_DOWN, aInRect, nState,
1010 aControlValue, OUString() );
1015 if( bNativeOK )
1016 return;
1018 bool bRollOver = (IsMouseOver() && aInRect.IsInside( GetPointerPosPixel() ));
1019 bool bDrawMenuSep = true;
1020 if( (GetStyle() & WB_FLATBUTTON) )
1022 if( ! bRollOver && ! HasFocus() )
1023 bDrawMenuSep = false;
1025 if ( (bNativeOK=IsNativeControlSupported(CTRL_PUSHBUTTON, PART_ENTIRE_CONTROL)) == sal_True )
1027 PushButtonValue aControlValue;
1028 Rectangle aCtrlRegion( aInRect );
1029 ControlState nState = 0;
1031 if ( mbPressed || IsChecked() ) nState |= CTRL_STATE_PRESSED;
1032 if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED ) nState |= CTRL_STATE_PRESSED;
1033 if ( HasFocus() ) nState |= CTRL_STATE_FOCUSED;
1034 if ( ImplGetButtonState() & BUTTON_DRAW_DEFAULT ) nState |= CTRL_STATE_DEFAULT;
1035 if ( Window::IsEnabled() ) nState |= CTRL_STATE_ENABLED;
1037 if ( bRollOver )
1038 nState |= CTRL_STATE_ROLLOVER;
1040 if( GetStyle() & WB_BEVELBUTTON )
1041 aControlValue.mbBevelButton = true;
1043 // draw frame into invisible window to have aInRect modified correctly
1044 // but do not shift the inner rect for pressed buttons (ie remove BUTTON_DRAW_PRESSED)
1045 // this assumes the theme has enough visual cues to signalize the button was pressed
1046 //Window aWin( this );
1047 //ImplDrawPushButtonFrame( &aWin, aInRect, nButtonStyle & ~BUTTON_DRAW_PRESSED );
1049 // looks better this way as symbols were displaced slightly using the above approach
1050 aInRect.Top()+=4;
1051 aInRect.Bottom()-=4;
1052 aInRect.Left()+=4;
1053 aInRect.Right()-=4;
1055 // prepare single line hint (needed on mac to decide between normal push button and
1056 // rectangular bevel button look)
1057 Size aFontSize( Application::GetSettings().GetStyleSettings().GetPushButtonFont().GetSize() );
1058 aFontSize = LogicToPixel( aFontSize, MapMode( MAP_POINT ) );
1059 Size aInRectSize( LogicToPixel( Size( aInRect.GetWidth(), aInRect.GetHeight() ) ) );
1060 aControlValue.mbSingleLine = (aInRectSize.Height() < 2 * aFontSize.Height() );
1062 if( ((nState & CTRL_STATE_ROLLOVER)) || ! (GetStyle() & WB_FLATBUTTON) )
1064 bNativeOK = DrawNativeControl( CTRL_PUSHBUTTON, PART_ENTIRE_CONTROL, aCtrlRegion, nState,
1065 aControlValue, OUString()/*PushButton::GetText()*/ );
1067 else
1069 bNativeOK = true;
1072 // draw content using the same aInRect as non-native VCL would do
1073 ImplDrawPushButtonContent( this,
1074 (nState&CTRL_STATE_ROLLOVER) ? WINDOW_DRAW_ROLLOVER : 0,
1075 aInRect, bLayout, bDrawMenuSep );
1077 if ( HasFocus() )
1078 ShowFocus( ImplGetFocusRect() );
1081 if ( bNativeOK == sal_False )
1083 // draw PushButtonFrame, aInRect has content size afterwards
1084 if( (GetStyle() & WB_FLATBUTTON) )
1086 Rectangle aTempRect( aInRect );
1087 if( ! bLayout && bRollOver )
1088 ImplDrawPushButtonFrame( this, aTempRect, nButtonStyle );
1089 aInRect.Left() += 2;
1090 aInRect.Top() += 2;
1091 aInRect.Right() -= 2;
1092 aInRect.Bottom() -= 2;
1094 else
1096 if( ! bLayout )
1097 ImplDrawPushButtonFrame( this, aInRect, nButtonStyle );
1100 // draw content
1101 ImplDrawPushButtonContent( this, 0, aInRect, bLayout, bDrawMenuSep );
1103 if( ! bLayout && HasFocus() )
1105 ShowFocus( ImplGetFocusRect() );
1110 // -----------------------------------------------------------------------
1112 void PushButton::ImplSetDefButton( sal_Bool bSet )
1114 Size aSize( GetSizePixel() );
1115 Point aPos( GetPosPixel() );
1116 int dLeft(0), dRight(0), dTop(0), dBottom(0);
1117 bool bSetPos = false;
1119 if ( (IsNativeControlSupported(CTRL_PUSHBUTTON, PART_ENTIRE_CONTROL)) == sal_True )
1121 Rectangle aBound, aCont;
1122 Rectangle aCtrlRect( 0, 0, 80, 20 ); // use a constant size to avoid accumulating
1123 // will not work if the theme has dynamic adornment sizes
1124 ImplControlValue aControlValue;
1125 Rectangle aCtrlRegion( aCtrlRect );
1126 ControlState nState = CTRL_STATE_DEFAULT|CTRL_STATE_ENABLED;
1128 // get native size of a 'default' button
1129 // and adjust the VCL button if more space for adornment is required
1130 if( GetNativeControlRegion( CTRL_PUSHBUTTON, PART_ENTIRE_CONTROL, aCtrlRegion,
1131 nState, aControlValue, OUString(),
1132 aBound, aCont ) )
1134 dLeft = aCont.Left() - aBound.Left();
1135 dTop = aCont.Top() - aBound.Top();
1136 dRight = aBound.Right() - aCont.Right();
1137 dBottom = aBound.Bottom() - aCont.Bottom();
1138 bSetPos = dLeft || dTop || dRight || dBottom;
1142 if ( bSet )
1144 if( !(ImplGetButtonState() & BUTTON_DRAW_DEFAULT) && bSetPos )
1146 // adjust pos/size when toggling from non-default to default
1147 aPos.Move(-dLeft, -dTop);
1148 aSize.Width() += dLeft + dRight;
1149 aSize.Height() += dTop + dBottom;
1151 ImplGetButtonState() |= BUTTON_DRAW_DEFAULT;
1153 else
1155 if( (ImplGetButtonState() & BUTTON_DRAW_DEFAULT) && bSetPos )
1157 // adjust pos/size when toggling from default to non-default
1158 aPos.Move(dLeft, dTop);
1159 aSize.Width() -= dLeft + dRight;
1160 aSize.Height() -= dTop + dBottom;
1162 ImplGetButtonState() &= ~BUTTON_DRAW_DEFAULT;
1164 if( bSetPos )
1165 setPosSizePixel( aPos.X(), aPos.Y(), aSize.Width(), aSize.Height(), WINDOW_POSSIZE_ALL );
1167 Invalidate();
1170 // -----------------------------------------------------------------------
1172 sal_Bool PushButton::ImplIsDefButton() const
1174 return (ImplGetButtonState() & BUTTON_DRAW_DEFAULT) != 0;
1177 // -----------------------------------------------------------------------
1179 PushButton::PushButton( WindowType nType ) :
1180 Button( nType )
1182 ImplInitPushButtonData();
1185 // -----------------------------------------------------------------------
1187 PushButton::PushButton( Window* pParent, WinBits nStyle ) :
1188 Button( WINDOW_PUSHBUTTON )
1190 ImplInitPushButtonData();
1191 ImplInit( pParent, nStyle );
1194 // -----------------------------------------------------------------------
1196 PushButton::PushButton( Window* pParent, const ResId& rResId ) :
1197 Button( WINDOW_PUSHBUTTON )
1199 rResId.SetRT( RSC_PUSHBUTTON );
1200 WinBits nStyle = ImplInitRes( rResId );
1201 ImplInitPushButtonData();
1202 ImplInit( pParent, nStyle );
1203 ImplLoadRes( rResId );
1205 if ( !(nStyle & WB_HIDE) )
1206 Show();
1209 // -----------------------------------------------------------------------
1211 PushButton::~PushButton()
1215 // -----------------------------------------------------------------------
1217 void PushButton::MouseButtonDown( const MouseEvent& rMEvt )
1219 if ( rMEvt.IsLeft() &&
1220 ImplHitTestPushButton( this, rMEvt.GetPosPixel() ) )
1222 sal_uInt16 nTrackFlags = 0;
1224 if ( ( GetStyle() & WB_REPEAT ) &&
1225 ! ( GetStyle() & WB_TOGGLE ) )
1226 nTrackFlags |= STARTTRACK_BUTTONREPEAT;
1228 ImplGetButtonState() |= BUTTON_DRAW_PRESSED;
1229 ImplDrawPushButton();
1230 StartTracking( nTrackFlags );
1232 if ( nTrackFlags & STARTTRACK_BUTTONREPEAT )
1233 Click();
1237 // -----------------------------------------------------------------------
1239 void PushButton::Tracking( const TrackingEvent& rTEvt )
1241 if ( rTEvt.IsTrackingEnded() )
1243 if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED )
1245 if ( !(GetStyle() & WB_NOPOINTERFOCUS) && !rTEvt.IsTrackingCanceled() )
1246 GrabFocus();
1248 if ( GetStyle() & WB_TOGGLE )
1250 // Don't toggle, when aborted
1251 if ( !rTEvt.IsTrackingCanceled() )
1253 if ( IsChecked() )
1255 Check( sal_False );
1256 ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
1258 else
1259 Check( sal_True );
1262 else
1263 ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
1265 ImplDrawPushButton();
1267 // do not call Click handler if aborted
1268 if ( !rTEvt.IsTrackingCanceled() )
1270 if ( ! ( ( GetStyle() & WB_REPEAT ) &&
1271 ! ( GetStyle() & WB_TOGGLE ) ) )
1272 Click();
1276 else
1278 if ( ImplHitTestPushButton( this, rTEvt.GetMouseEvent().GetPosPixel() ) )
1280 if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED )
1282 if ( rTEvt.IsTrackingRepeat() && (GetStyle() & WB_REPEAT) &&
1283 ! ( GetStyle() & WB_TOGGLE ) )
1284 Click();
1286 else
1288 ImplGetButtonState() |= BUTTON_DRAW_PRESSED;
1289 ImplDrawPushButton();
1292 else
1294 if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED )
1296 ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
1297 ImplDrawPushButton();
1303 // -----------------------------------------------------------------------
1305 void PushButton::KeyInput( const KeyEvent& rKEvt )
1307 KeyCode aKeyCode = rKEvt.GetKeyCode();
1309 if ( !aKeyCode.GetModifier() &&
1310 ((aKeyCode.GetCode() == KEY_RETURN) || (aKeyCode.GetCode() == KEY_SPACE)) )
1312 if ( !(ImplGetButtonState() & BUTTON_DRAW_PRESSED) )
1314 ImplGetButtonState() |= BUTTON_DRAW_PRESSED;
1315 ImplDrawPushButton();
1318 if ( ( GetStyle() & WB_REPEAT ) &&
1319 ! ( GetStyle() & WB_TOGGLE ) )
1320 Click();
1322 else if ( (ImplGetButtonState() & BUTTON_DRAW_PRESSED) && (aKeyCode.GetCode() == KEY_ESCAPE) )
1324 ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
1325 ImplDrawPushButton();
1327 else
1328 Button::KeyInput( rKEvt );
1331 // -----------------------------------------------------------------------
1333 void PushButton::KeyUp( const KeyEvent& rKEvt )
1335 KeyCode aKeyCode = rKEvt.GetKeyCode();
1337 if ( (ImplGetButtonState() & BUTTON_DRAW_PRESSED) &&
1338 ((aKeyCode.GetCode() == KEY_RETURN) || (aKeyCode.GetCode() == KEY_SPACE)) )
1340 if ( GetStyle() & WB_TOGGLE )
1342 if ( IsChecked() )
1344 Check( sal_False );
1345 ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
1347 else
1348 Check( sal_True );
1350 Toggle();
1352 else
1353 ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
1355 ImplDrawPushButton();
1357 if ( !( ( GetStyle() & WB_REPEAT ) &&
1358 ! ( GetStyle() & WB_TOGGLE ) ) )
1359 Click();
1361 else
1362 Button::KeyUp( rKEvt );
1365 // -----------------------------------------------------------------------
1367 void PushButton::FillLayoutData() const
1369 mpControlData->mpLayoutData = new vcl::ControlLayoutData();
1370 const_cast<PushButton*>(this)->ImplDrawPushButton( true );
1373 // -----------------------------------------------------------------------
1375 void PushButton::Paint( const Rectangle& )
1377 ImplDrawPushButton();
1380 // -----------------------------------------------------------------------
1382 void PushButton::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize,
1383 sal_uLong nFlags )
1385 Point aPos = pDev->LogicToPixel( rPos );
1386 Size aSize = pDev->LogicToPixel( rSize );
1387 Rectangle aRect( aPos, aSize );
1388 Font aFont = GetDrawPixelFont( pDev );
1390 pDev->Push();
1391 pDev->SetMapMode();
1392 pDev->SetFont( aFont );
1393 if ( nFlags & WINDOW_DRAW_MONO )
1395 pDev->SetTextColor( Color( COL_BLACK ) );
1397 else
1399 pDev->SetTextColor( GetTextColor() );
1401 // DecoView uses the FaceColor...
1402 AllSettings aSettings = pDev->GetSettings();
1403 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
1404 if ( IsControlBackground() )
1405 aStyleSettings.SetFaceColor( GetControlBackground() );
1406 else
1407 aStyleSettings.SetFaceColor( GetSettings().GetStyleSettings().GetFaceColor() );
1408 aSettings.SetStyleSettings( aStyleSettings );
1409 pDev->OutputDevice::SetSettings( aSettings );
1411 pDev->SetTextFillColor();
1413 DecorationView aDecoView( pDev );
1414 sal_uInt16 nButtonStyle = 0;
1415 if ( nFlags & WINDOW_DRAW_MONO )
1416 nButtonStyle |= BUTTON_DRAW_MONO;
1417 if ( IsChecked() )
1418 nButtonStyle |= BUTTON_DRAW_CHECKED;
1419 aRect = aDecoView.DrawButton( aRect, nButtonStyle );
1421 ImplDrawPushButtonContent( pDev, nFlags, aRect, false, true );
1422 pDev->Pop();
1425 // -----------------------------------------------------------------------
1427 void PushButton::Resize()
1429 Control::Resize();
1430 Invalidate();
1433 // -----------------------------------------------------------------------
1435 void PushButton::GetFocus()
1437 ShowFocus( ImplGetFocusRect() );
1438 SetInputContext( InputContext( GetFont() ) );
1439 Button::GetFocus();
1442 // -----------------------------------------------------------------------
1444 void PushButton::LoseFocus()
1446 EndSelection();
1447 HideFocus();
1448 Button::LoseFocus();
1451 // -----------------------------------------------------------------------
1453 void PushButton::StateChanged( StateChangedType nType )
1455 Button::StateChanged( nType );
1457 if ( (nType == STATE_CHANGE_ENABLE) ||
1458 (nType == STATE_CHANGE_TEXT) ||
1459 (nType == STATE_CHANGE_IMAGE) ||
1460 (nType == STATE_CHANGE_DATA) ||
1461 (nType == STATE_CHANGE_STATE) ||
1462 (nType == STATE_CHANGE_UPDATEMODE) )
1464 if ( IsReallyVisible() && IsUpdateMode() )
1465 Invalidate();
1467 else if ( nType == STATE_CHANGE_STYLE )
1469 SetStyle( ImplInitStyle( GetWindow( WINDOW_PREV ), GetStyle() ) );
1471 bool bIsDefButton = ( GetStyle() & WB_DEFBUTTON ) != 0;
1472 bool bWasDefButton = ( GetPrevStyle() & WB_DEFBUTTON ) != 0;
1473 if ( bIsDefButton != bWasDefButton )
1474 ImplSetDefButton( bIsDefButton );
1476 if ( IsReallyVisible() && IsUpdateMode() )
1478 if ( (GetPrevStyle() & PUSHBUTTON_VIEW_STYLE) !=
1479 (GetStyle() & PUSHBUTTON_VIEW_STYLE) )
1480 Invalidate();
1483 else if ( (nType == STATE_CHANGE_ZOOM) ||
1484 (nType == STATE_CHANGE_CONTROLFONT) )
1486 ImplInitSettings( sal_True, sal_False, sal_False );
1487 Invalidate();
1489 else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
1491 ImplInitSettings( sal_False, sal_True, sal_False );
1492 Invalidate();
1494 else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
1496 ImplInitSettings( sal_False, sal_False, sal_True );
1497 Invalidate();
1501 // -----------------------------------------------------------------------
1503 void PushButton::DataChanged( const DataChangedEvent& rDCEvt )
1505 Button::DataChanged( rDCEvt );
1507 if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
1508 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
1509 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
1510 (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
1512 ImplInitSettings( sal_True, sal_True, sal_True );
1513 Invalidate();
1517 // -----------------------------------------------------------------------
1519 long PushButton::PreNotify( NotifyEvent& rNEvt )
1521 long nDone = 0;
1522 const MouseEvent* pMouseEvt = NULL;
1524 if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL )
1526 if( pMouseEvt->IsEnterWindow() || pMouseEvt->IsLeaveWindow() )
1528 // trigger redraw as mouse over state has changed
1530 // TODO: move this to Window class or make it a member !!!
1531 ControlType aCtrlType = 0;
1532 switch( GetParent()->GetType() )
1534 case WINDOW_LISTBOX:
1535 case WINDOW_MULTILISTBOX:
1536 case WINDOW_TREELISTBOX:
1537 aCtrlType = CTRL_LISTBOX;
1538 break;
1540 case WINDOW_COMBOBOX:
1541 case WINDOW_PATTERNBOX:
1542 case WINDOW_NUMERICBOX:
1543 case WINDOW_METRICBOX:
1544 case WINDOW_CURRENCYBOX:
1545 case WINDOW_DATEBOX:
1546 case WINDOW_TIMEBOX:
1547 case WINDOW_LONGCURRENCYBOX:
1548 aCtrlType = CTRL_COMBOBOX;
1549 break;
1550 default:
1551 break;
1554 bool bDropDown = ( IsSymbol() && (GetSymbol()==SYMBOL_SPIN_DOWN) && GetText().isEmpty() );
1556 if( bDropDown && GetParent()->IsNativeControlSupported( aCtrlType, PART_ENTIRE_CONTROL) &&
1557 !GetParent()->IsNativeControlSupported( aCtrlType, PART_BUTTON_DOWN) )
1559 Window *pBorder = GetParent()->GetWindow( WINDOW_BORDER );
1560 if(aCtrlType == CTRL_COMBOBOX)
1562 // only paint the button part to avoid flickering of the combobox text
1563 Point aPt;
1564 Rectangle aClipRect( aPt, GetOutputSizePixel() );
1565 aClipRect.SetPos(pBorder->ScreenToOutputPixel(OutputToScreenPixel(aClipRect.TopLeft())));
1566 pBorder->Invalidate( aClipRect );
1568 else
1570 pBorder->Invalidate( INVALIDATE_NOERASE );
1571 pBorder->Update();
1574 else if( (GetStyle() & WB_FLATBUTTON) ||
1575 IsNativeControlSupported(CTRL_PUSHBUTTON, PART_ENTIRE_CONTROL) )
1577 Invalidate();
1582 return nDone ? nDone : Button::PreNotify(rNEvt);
1585 // -----------------------------------------------------------------------
1587 void PushButton::Toggle()
1589 ImplCallEventListenersAndHandler( VCLEVENT_PUSHBUTTON_TOGGLE, maToggleHdl, this );
1592 // -----------------------------------------------------------------------
1594 void PushButton::SetSymbol( SymbolType eSymbol )
1596 if ( meSymbol != eSymbol )
1598 meSymbol = eSymbol;
1599 StateChanged( STATE_CHANGE_DATA );
1603 // -----------------------------------------------------------------------
1604 void PushButton::SetSymbolAlign( SymbolAlign eAlign )
1606 ImplSetSymbolAlign( eAlign );
1609 // -----------------------------------------------------------------------
1611 void PushButton::SetDropDown( sal_uInt16 nStyle )
1613 if ( mnDDStyle != nStyle )
1615 mnDDStyle = nStyle;
1616 StateChanged( STATE_CHANGE_DATA );
1620 // -----------------------------------------------------------------------
1622 void PushButton::SetState( TriState eState )
1624 if ( meState != eState )
1626 meState = eState;
1627 if ( meState == STATE_NOCHECK )
1628 ImplGetButtonState() &= ~(BUTTON_DRAW_CHECKED | BUTTON_DRAW_DONTKNOW);
1629 else if ( meState == STATE_CHECK )
1631 ImplGetButtonState() &= ~BUTTON_DRAW_DONTKNOW;
1632 ImplGetButtonState() |= BUTTON_DRAW_CHECKED;
1634 else // STATE_DONTKNOW
1636 ImplGetButtonState() &= ~BUTTON_DRAW_CHECKED;
1637 ImplGetButtonState() |= BUTTON_DRAW_DONTKNOW;
1640 StateChanged( STATE_CHANGE_STATE );
1641 Toggle();
1645 // -----------------------------------------------------------------------
1647 void PushButton::SetPressed( sal_Bool bPressed )
1649 if ( mbPressed != bPressed )
1651 mbPressed = bPressed;
1652 StateChanged( STATE_CHANGE_DATA );
1656 // -----------------------------------------------------------------------
1658 void PushButton::EndSelection()
1660 EndTracking( ENDTRACK_CANCEL );
1661 if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED )
1663 ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
1664 if ( !mbPressed )
1665 ImplDrawPushButton();
1669 // -----------------------------------------------------------------------
1671 Size PushButton::CalcMinimumSize( long nMaxWidth ) const
1673 Size aSize;
1675 if ( IsSymbol() )
1677 if ( IsSmallSymbol ())
1678 aSize = Size( 16, 12 );
1679 else
1680 aSize = Size( 26, 24 );
1681 if( mnDDStyle == PUSHBUTTON_DROPDOWN_MENUBUTTON )
1682 aSize.Width() += 4;
1684 else if ( IsImage() && ! (ImplGetButtonState() & BUTTON_DRAW_NOIMAGE) )
1685 aSize = GetModeImage().GetSizePixel();
1686 if ( !PushButton::GetText().isEmpty() && ! (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) )
1688 sal_uLong nDrawFlags = 0;
1689 Size textSize = GetTextRect( Rectangle( Point(), Size( nMaxWidth ? nMaxWidth : 0x7fffffff, 0x7fffffff ) ),
1690 PushButton::GetText(), ImplGetTextStyle( nDrawFlags ) ).GetSize();
1691 aSize.Width() += int( textSize.Width () * 1.15 );
1692 aSize.Height() = std::max( aSize.Height(), long( textSize.Height() * 1.15 ) );
1695 // cf. ImplDrawPushButton ...
1696 if( (GetStyle() & WB_SMALLSTYLE) == 0 )
1698 aSize.Width() += 12;
1699 aSize.Height() += 12;
1702 return CalcWindowSize( aSize );
1705 Size PushButton::GetOptimalSize() const
1707 return CalcMinimumSize();
1710 bool PushButton::set_property(const OString &rKey, const OString &rValue)
1712 if (rKey == "has-default")
1714 WinBits nBits = GetStyle();
1715 nBits &= ~(WB_DEFBUTTON);
1716 if (toBool(rValue))
1717 nBits |= WB_DEFBUTTON;
1718 SetStyle(nBits);
1720 else
1721 return Control::set_property(rKey, rValue);
1722 return true;
1726 // =======================================================================
1728 void OKButton::ImplInit( Window* pParent, WinBits nStyle )
1730 PushButton::ImplInit( pParent, nStyle );
1732 SetText( Button::GetStandardText( BUTTON_OK ) );
1733 SetHelpText( Button::GetStandardHelpText( BUTTON_OK ) );
1736 // -----------------------------------------------------------------------
1738 OKButton::OKButton( Window* pParent, WinBits nStyle ) :
1739 PushButton( WINDOW_OKBUTTON )
1741 ImplInit( pParent, nStyle );
1744 // -----------------------------------------------------------------------
1746 OKButton::OKButton( Window* pParent, const ResId& rResId ) :
1747 PushButton( WINDOW_OKBUTTON )
1749 rResId.SetRT( RSC_OKBUTTON );
1750 WinBits nStyle = ImplInitRes( rResId );
1751 ImplInit( pParent, nStyle );
1752 ImplLoadRes( rResId );
1754 if ( !(nStyle & WB_HIDE) )
1755 Show();
1758 // -----------------------------------------------------------------------
1760 void OKButton::Click()
1762 // close parent if no link set
1763 if ( !GetClickHdl() )
1765 Window* pParent = getNonLayoutParent(this);
1766 if ( pParent->IsSystemWindow() )
1768 if ( pParent->IsDialog() )
1770 if ( ((Dialog*)pParent)->IsInExecute() )
1771 ((Dialog*)pParent)->EndDialog( sal_True );
1772 // prevent recursive calls
1773 else if ( !((Dialog*)pParent)->IsInClose() )
1775 if ( pParent->GetStyle() & WB_CLOSEABLE )
1776 ((Dialog*)pParent)->Close();
1779 else
1781 if ( pParent->GetStyle() & WB_CLOSEABLE )
1782 ((SystemWindow*)pParent)->Close();
1786 else
1788 PushButton::Click();
1792 // =======================================================================
1794 void CancelButton::ImplInit( Window* pParent, WinBits nStyle )
1796 PushButton::ImplInit( pParent, nStyle );
1798 SetText( Button::GetStandardText( BUTTON_CANCEL ) );
1799 SetHelpText( Button::GetStandardHelpText( BUTTON_CANCEL ) );
1802 // -----------------------------------------------------------------------
1804 CancelButton::CancelButton( Window* pParent, WinBits nStyle ) :
1805 PushButton( WINDOW_CANCELBUTTON )
1807 ImplInit( pParent, nStyle );
1810 // -----------------------------------------------------------------------
1812 CancelButton::CancelButton( Window* pParent, const ResId& rResId ) :
1813 PushButton( WINDOW_CANCELBUTTON )
1815 rResId.SetRT( RSC_CANCELBUTTON );
1816 WinBits nStyle = ImplInitRes( rResId );
1817 ImplInit( pParent, nStyle );
1818 ImplLoadRes( rResId );
1820 if ( !(nStyle & WB_HIDE) )
1821 Show();
1824 // -----------------------------------------------------------------------
1826 void CancelButton::Click()
1828 // close parent if link not set
1829 if ( !GetClickHdl() )
1831 Window* pParent = getNonLayoutParent(this);
1832 if ( pParent->IsSystemWindow() )
1834 if ( pParent->IsDialog() )
1836 if ( ((Dialog*)pParent)->IsInExecute() )
1837 ((Dialog*)pParent)->EndDialog( sal_False );
1838 // prevent recursive calls
1839 else if ( !((Dialog*)pParent)->IsInClose() )
1841 if ( pParent->GetStyle() & WB_CLOSEABLE )
1842 ((Dialog*)pParent)->Close();
1845 else
1847 if ( pParent->GetStyle() & WB_CLOSEABLE )
1848 ((SystemWindow*)pParent)->Close();
1852 else
1854 PushButton::Click();
1858 CloseButton::CloseButton( Window* pParent, WinBits nStyle )
1859 : CancelButton(pParent, nStyle)
1861 SetText( Button::GetStandardText( BUTTON_CLOSE ) );
1862 SetHelpText( Button::GetStandardHelpText( BUTTON_CLOSE ) );
1865 // =======================================================================
1867 void HelpButton::ImplInit( Window* pParent, WinBits nStyle )
1869 PushButton::ImplInit( pParent, nStyle | WB_NOPOINTERFOCUS );
1871 SetText( Button::GetStandardText( BUTTON_HELP ) );
1872 SetHelpText( Button::GetStandardHelpText( BUTTON_HELP ) );
1875 // -----------------------------------------------------------------------
1877 HelpButton::HelpButton( Window* pParent, WinBits nStyle ) :
1878 PushButton( WINDOW_HELPBUTTON )
1880 ImplInit( pParent, nStyle );
1883 // -----------------------------------------------------------------------
1885 HelpButton::HelpButton( Window* pParent, const ResId& rResId ) :
1886 PushButton( WINDOW_HELPBUTTON )
1888 rResId.SetRT( RSC_HELPBUTTON );
1889 WinBits nStyle = ImplInitRes( rResId );
1890 ImplInit( pParent, nStyle );
1891 ImplLoadRes( rResId );
1893 if ( !(nStyle & WB_HIDE) )
1894 Show();
1897 // -----------------------------------------------------------------------
1899 void HelpButton::Click()
1901 // trigger help if no link set
1902 if ( !GetClickHdl() )
1904 Window* pFocusWin = Application::GetFocusWindow();
1905 if ( !pFocusWin )
1906 pFocusWin = this;
1908 HelpEvent aEvt( pFocusWin->GetPointerPosPixel(), HELPMODE_CONTEXT );
1909 pFocusWin->RequestHelp( aEvt );
1911 PushButton::Click();
1914 // =======================================================================
1916 void RadioButton::ImplInitRadioButtonData()
1918 mbChecked = sal_False;
1919 mbSaveValue = sal_False;
1920 mbRadioCheck = sal_True;
1921 mbStateChanged = sal_False;
1924 // -----------------------------------------------------------------------
1926 void RadioButton::ImplInit( Window* pParent, WinBits nStyle )
1928 nStyle = ImplInitStyle( pParent->GetWindow( WINDOW_LASTCHILD ), nStyle );
1929 Button::ImplInit( pParent, nStyle, NULL );
1931 ImplInitSettings( sal_True, sal_True, sal_True );
1934 // -----------------------------------------------------------------------
1936 WinBits RadioButton::ImplInitStyle( const Window* pPrevWindow, WinBits nStyle )
1938 if ( !(nStyle & WB_NOGROUP) &&
1939 (!pPrevWindow || (pPrevWindow->GetType() != WINDOW_RADIOBUTTON)) )
1940 nStyle |= WB_GROUP;
1941 if ( !(nStyle & WB_NOTABSTOP) )
1943 if ( IsChecked() )
1944 nStyle |= WB_TABSTOP;
1945 else
1946 nStyle &= ~WB_TABSTOP;
1948 return nStyle;
1951 // -----------------------------------------------------------------
1953 const Font& RadioButton::GetCanonicalFont( const StyleSettings& _rStyle ) const
1955 return _rStyle.GetRadioCheckFont();
1958 // -----------------------------------------------------------------
1959 const Color& RadioButton::GetCanonicalTextColor( const StyleSettings& _rStyle ) const
1961 return _rStyle.GetRadioCheckTextColor();
1964 // -----------------------------------------------------------------------
1966 void RadioButton::ImplInitSettings( sal_Bool bFont,
1967 sal_Bool bForeground, sal_Bool bBackground )
1969 Button::ImplInitSettings( bFont, bForeground );
1971 if ( bBackground )
1973 Window* pParent = GetParent();
1974 if ( !IsControlBackground() &&
1975 (pParent->IsChildTransparentModeEnabled() || IsNativeControlSupported( CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL ) ) )
1977 EnableChildTransparentMode( sal_True );
1978 SetParentClipMode( PARENTCLIPMODE_NOCLIP );
1979 SetPaintTransparent( sal_True );
1980 SetBackground();
1981 if( IsNativeControlSupported( CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL ) )
1982 mpWindowImpl->mbUseNativeFocus = ImplGetSVData()->maNWFData.mbNoFocusRects;
1984 else
1986 EnableChildTransparentMode( sal_False );
1987 SetParentClipMode( 0 );
1988 SetPaintTransparent( sal_False );
1990 if ( IsControlBackground() )
1991 SetBackground( GetControlBackground() );
1992 else
1993 SetBackground( pParent->GetBackground() );
1998 void RadioButton::DrawRadioButtonState( )
2000 ImplDrawRadioButtonState( );
2003 // -----------------------------------------------------------------------
2005 void RadioButton::ImplInvalidateOrDrawRadioButtonState()
2007 if( ImplGetSVData()->maNWFData.mbCheckBoxNeedsErase )
2009 if ( IsNativeControlSupported(CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL) )
2011 Invalidate();
2012 Update();
2013 return;
2016 ImplDrawRadioButtonState();
2019 void RadioButton::ImplDrawRadioButtonState()
2021 sal_Bool bNativeOK = sal_False;
2023 // no native drawing for image radio buttons
2024 if ( !maImage && (bNativeOK=IsNativeControlSupported(CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL)) == sal_True )
2026 ImplControlValue aControlValue( mbChecked ? BUTTONVALUE_ON : BUTTONVALUE_OFF );
2027 Rectangle aCtrlRect( maStateRect.TopLeft(), maStateRect.GetSize() );
2028 ControlState nState = 0;
2030 if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED ) nState |= CTRL_STATE_PRESSED;
2031 if ( HasFocus() ) nState |= CTRL_STATE_FOCUSED;
2032 if ( ImplGetButtonState() & BUTTON_DRAW_DEFAULT ) nState |= CTRL_STATE_DEFAULT;
2033 if ( IsEnabled() ) nState |= CTRL_STATE_ENABLED;
2035 if ( IsMouseOver() && maMouseRect.IsInside( GetPointerPosPixel() ) )
2036 nState |= CTRL_STATE_ROLLOVER;
2038 bNativeOK = DrawNativeControl( CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL, aCtrlRect, nState,
2039 aControlValue,OUString() );
2043 if ( bNativeOK == sal_False )
2045 // kein Image-RadioButton
2046 if ( !maImage )
2048 sal_uInt16 nStyle = ImplGetButtonState();
2049 if ( !IsEnabled() )
2050 nStyle |= BUTTON_DRAW_DISABLED;
2051 if ( mbChecked )
2052 nStyle |= BUTTON_DRAW_CHECKED;
2053 Image aImage = GetRadioImage( GetSettings(), nStyle );
2054 if ( IsZoom() )
2055 DrawImage( maStateRect.TopLeft(), maStateRect.GetSize(), aImage );
2056 else
2057 DrawImage( maStateRect.TopLeft(), aImage );
2059 else
2061 HideFocus();
2063 DecorationView aDecoView( this );
2064 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
2065 Rectangle aImageRect = maStateRect;
2066 Size aImageSize = maImage.GetSizePixel();
2067 sal_Bool bEnabled = IsEnabled();
2068 sal_uInt16 nButtonStyle = FRAME_DRAW_DOUBLEIN;
2070 aImageSize.Width() = CalcZoom( aImageSize.Width() );
2071 aImageSize.Height() = CalcZoom( aImageSize.Height() );
2073 // display border and selection status
2074 aImageRect = aDecoView.DrawFrame( aImageRect, nButtonStyle );
2075 if ( (ImplGetButtonState() & BUTTON_DRAW_PRESSED) || !bEnabled )
2076 SetFillColor( rStyleSettings.GetFaceColor() );
2077 else
2078 SetFillColor( rStyleSettings.GetFieldColor() );
2079 SetLineColor();
2080 DrawRect( aImageRect );
2082 // display image
2083 nButtonStyle = 0;
2084 if ( !bEnabled )
2085 nButtonStyle |= IMAGE_DRAW_DISABLE;
2087 Image *pImage = &maImage;
2089 Point aImagePos( aImageRect.TopLeft() );
2090 aImagePos.X() += (aImageRect.GetWidth()-aImageSize.Width())/2;
2091 aImagePos.Y() += (aImageRect.GetHeight()-aImageSize.Height())/2;
2092 if ( IsZoom() )
2093 DrawImage( aImagePos, aImageSize, *pImage, nButtonStyle );
2094 else
2095 DrawImage( aImagePos, *pImage, nButtonStyle );
2097 aImageRect.Left()++;
2098 aImageRect.Top()++;
2099 aImageRect.Right()--;
2100 aImageRect.Bottom()--;
2102 ImplSetFocusRect( aImageRect );
2104 if ( mbChecked )
2106 SetLineColor( rStyleSettings.GetHighlightColor() );
2107 SetFillColor();
2108 if ( (aImageSize.Width() >= 20) || (aImageSize.Height() >= 20) )
2110 aImageRect.Left()++;
2111 aImageRect.Top()++;
2112 aImageRect.Right()--;
2113 aImageRect.Bottom()--;
2115 DrawRect( aImageRect );
2116 aImageRect.Left()++;
2117 aImageRect.Top()++;
2118 aImageRect.Right()--;
2119 aImageRect.Bottom()--;
2120 DrawRect( aImageRect );
2123 if ( HasFocus() )
2124 ShowFocus( ImplGetFocusRect() );
2129 // -----------------------------------------------------------------------
2131 void RadioButton::ImplDraw( OutputDevice* pDev, sal_uLong nDrawFlags,
2132 const Point& rPos, const Size& rSize,
2133 const Size& rImageSize, Rectangle& rStateRect,
2134 Rectangle& rMouseRect, bool bLayout )
2136 WinBits nWinStyle = GetStyle();
2137 OUString aText( GetText() );
2138 MetricVector* pVector = bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : NULL;
2139 OUString* pDisplayText = bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : NULL;
2141 pDev->Push( PUSH_CLIPREGION );
2142 pDev->IntersectClipRegion( Rectangle( rPos, rSize ) );
2144 // no image radio button
2145 if ( !maImage )
2147 if ( ( !aText.isEmpty() && ! (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) ) ||
2148 ( HasImage() && ! (ImplGetButtonState() & BUTTON_DRAW_NOIMAGE) ) )
2150 sal_uInt16 nTextStyle = Button::ImplGetTextStyle( aText, nWinStyle, nDrawFlags );
2152 const long nImageSep = GetDrawPixel( pDev, ImplGetImageToTextDistance() );
2153 Size aSize( rSize );
2154 Point aPos( rPos );
2155 aPos.X() += rImageSize.Width() + nImageSep;
2156 aSize.Width() -= rImageSize.Width() + nImageSep;
2158 // if the text rect height is smaller than the height of the image
2159 // then for single lines the default should be centered text
2160 if( (nWinStyle & (WB_TOP|WB_VCENTER|WB_BOTTOM)) == 0 &&
2161 (rImageSize.Height() > rSize.Height() || ! (nWinStyle & WB_WORDBREAK) ) )
2163 nTextStyle &= ~(TEXT_DRAW_TOP|TEXT_DRAW_BOTTOM);
2164 nTextStyle |= TEXT_DRAW_VCENTER;
2165 aSize.Height() = rImageSize.Height();
2168 ImplDrawAlignedImage( pDev, aPos, aSize, bLayout, 1,
2169 nDrawFlags, nTextStyle, NULL );
2171 rMouseRect = Rectangle( aPos, aSize );
2172 rMouseRect.Left() = rPos.X();
2174 rStateRect.Left() = rPos.X();
2175 rStateRect.Top() = rMouseRect.Top();
2177 if ( aSize.Height() > rImageSize.Height() )
2178 rStateRect.Top() += ( aSize.Height() - rImageSize.Height() ) / 2;
2179 else
2181 rStateRect.Top() -= ( rImageSize.Height() - aSize.Height() ) / 2;
2182 if( rStateRect.Top() < 0 )
2183 rStateRect.Top() = 0;
2186 rStateRect.Right() = rStateRect.Left() + rImageSize.Width()-1;
2187 rStateRect.Bottom() = rStateRect.Top() + rImageSize.Height()-1;
2189 if ( rStateRect.Bottom() > rMouseRect.Bottom() )
2190 rMouseRect.Bottom() = rStateRect.Bottom();
2192 else
2194 if ( mbLegacyNoTextAlign && ( nWinStyle & WB_CENTER ) )
2195 rStateRect.Left() = rPos.X()+((rSize.Width()-rImageSize.Width())/2);
2196 else if ( mbLegacyNoTextAlign && ( nWinStyle & WB_RIGHT ) )
2197 rStateRect.Left() = rPos.X()+rSize.Width()-rImageSize.Width(); //-1;
2198 else
2199 rStateRect.Left() = rPos.X(); //+1;
2200 if ( nWinStyle & WB_VCENTER )
2201 rStateRect.Top() = rPos.Y()+((rSize.Height()-rImageSize.Height())/2);
2202 else if ( nWinStyle & WB_BOTTOM )
2203 rStateRect.Top() = rPos.Y()+rSize.Height()-rImageSize.Height(); //-1;
2204 else
2205 rStateRect.Top() = rPos.Y(); //+1;
2206 rStateRect.Right() = rStateRect.Left()+rImageSize.Width()-1;
2207 rStateRect.Bottom() = rStateRect.Top()+rImageSize.Height()-1;
2208 rMouseRect = rStateRect;
2210 ImplSetFocusRect( rStateRect );
2212 /* and above -1 because CalcSize() does not include focus-rectangle since images would be even
2213 positioned higher in writer
2214 rFocusRect = rStateRect;
2215 rFocusRect.Left()--;
2216 rFocusRect.Top()--;
2217 rFocusRect.Right()++;
2218 rFocusRect.Bottom()++;
2222 else
2224 bool bTopImage = (nWinStyle & WB_TOP) != 0;
2225 Size aImageSize = maImage.GetSizePixel();
2226 Rectangle aImageRect( rPos, rSize );
2227 long nTextHeight = pDev->GetTextHeight();
2228 long nTextWidth = pDev->GetCtrlTextWidth( aText );
2230 // calculate position and sizes
2231 if ( !aText.isEmpty() && ! (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) )
2233 Size aTmpSize( (aImageSize.Width()+8), (aImageSize.Height()+8) );
2234 if ( bTopImage )
2236 aImageRect.Left() = (rSize.Width()-aTmpSize.Width())/2;
2237 aImageRect.Top() = (rSize.Height()-(aTmpSize.Height()+nTextHeight+6))/2;
2239 else
2240 aImageRect.Top() = (rSize.Height()-aTmpSize.Height())/2;
2242 aImageRect.Right() = aImageRect.Left()+aTmpSize.Width();
2243 aImageRect.Bottom() = aImageRect.Top()+aTmpSize.Height();
2245 // display text
2246 Point aTxtPos = rPos;
2247 if ( bTopImage )
2249 aTxtPos.X() += (rSize.Width()-nTextWidth)/2;
2250 aTxtPos.Y() += aImageRect.Bottom()+6;
2252 else
2254 aTxtPos.X() += aImageRect.Right()+8;
2255 aTxtPos.Y() += (rSize.Height()-nTextHeight)/2;
2257 pDev->DrawCtrlText( aTxtPos, aText, 0, STRING_LEN, TEXT_DRAW_MNEMONIC, pVector, pDisplayText );
2260 rMouseRect = aImageRect;
2261 rStateRect = aImageRect;
2264 pDev->Pop();
2267 // -----------------------------------------------------------------------
2269 void RadioButton::ImplDrawRadioButton( bool bLayout )
2271 if( !bLayout )
2272 HideFocus();
2274 Size aImageSize;
2275 if ( !maImage )
2276 aImageSize = ImplGetRadioImageSize();
2277 else
2278 aImageSize = maImage.GetSizePixel();
2279 aImageSize.Width() = CalcZoom( aImageSize.Width() );
2280 aImageSize.Height() = CalcZoom( aImageSize.Height() );
2282 // Draw control text
2283 ImplDraw( this, 0, Point(), GetOutputSizePixel(),
2284 aImageSize, maStateRect, maMouseRect, bLayout );
2286 if( !bLayout || (IsNativeControlSupported(CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL)==sal_True) )
2288 if ( !maImage && HasFocus() )
2289 ShowFocus( ImplGetFocusRect() );
2291 ImplDrawRadioButtonState();
2295 void RadioButton::group(RadioButton &rOther)
2297 if (&rOther == this)
2298 return;
2300 if (!m_xGroup)
2302 m_xGroup.reset(new std::vector<RadioButton*>);
2303 m_xGroup->push_back(this);
2306 std::vector<RadioButton*>::iterator aFind = std::find(m_xGroup->begin(), m_xGroup->end(), &rOther);
2307 if (aFind == m_xGroup->end())
2309 m_xGroup->push_back(&rOther);
2311 if (rOther.m_xGroup)
2313 std::vector< RadioButton* > aOthers(rOther.GetRadioButtonGroup(false));
2314 //make all members of the group share the same button group
2315 for (std::vector<RadioButton*>::iterator aI = aOthers.begin(), aEnd = aOthers.end(); aI != aEnd; ++aI)
2317 aFind = std::find(m_xGroup->begin(), m_xGroup->end(), *aI);
2318 if (aFind == m_xGroup->end())
2319 m_xGroup->push_back(*aI);
2323 //make all members of the group share the same button group
2324 for (std::vector<RadioButton*>::iterator aI = m_xGroup->begin(), aEnd = m_xGroup->end();
2325 aI != aEnd; ++aI)
2327 RadioButton* pButton = *aI;
2328 pButton->m_xGroup = m_xGroup;
2332 //if this one is checked, uncheck all the others
2333 if (mbChecked)
2334 ImplUncheckAllOther();
2337 // .-----------------------------------------------------------------------
2339 std::vector< RadioButton* > RadioButton::GetRadioButtonGroup(bool bIncludeThis) const
2341 if (m_xGroup)
2343 if (bIncludeThis)
2344 return *m_xGroup;
2345 std::vector< RadioButton* > aGroup;
2346 for (std::vector<RadioButton*>::iterator aI = m_xGroup->begin(), aEnd = m_xGroup->end(); aI != aEnd; ++aI)
2348 RadioButton *pRadioButton = *aI;
2349 if (pRadioButton == this)
2350 continue;
2351 aGroup.push_back(pRadioButton);
2353 return aGroup;
2356 //old-school
2357 SAL_WARN("vcl.control", "No new-style group set on radiobutton, using old-style digging around");
2359 // go back to first in group;
2360 Window* pFirst = const_cast<RadioButton*>(this);
2361 while( ( pFirst->GetStyle() & WB_GROUP ) == 0 )
2363 Window* pWindow = pFirst->GetWindow( WINDOW_PREV );
2364 if( pWindow )
2365 pFirst = pWindow;
2366 else
2367 break;
2369 std::vector< RadioButton* > aGroup;
2370 // insert radiobuttons up to next group
2373 if( pFirst->GetType() == WINDOW_RADIOBUTTON )
2375 if( pFirst != this || bIncludeThis )
2376 aGroup.push_back( static_cast<RadioButton*>(pFirst) );
2378 pFirst = pFirst->GetWindow( WINDOW_NEXT );
2379 } while( pFirst && ( ( pFirst->GetStyle() & WB_GROUP ) == 0 ) );
2381 return aGroup;
2384 // -----------------------------------------------------------------------
2386 void RadioButton::ImplUncheckAllOther()
2388 mpWindowImpl->mnStyle |= WB_TABSTOP;
2390 std::vector<RadioButton*> aGroup(GetRadioButtonGroup(false));
2391 // iterate over radio button group and checked buttons
2392 for (std::vector<RadioButton*>::iterator aI = aGroup.begin(), aEnd = aGroup.end(); aI != aEnd; ++aI)
2394 RadioButton *pWindow = *aI;
2395 if ( pWindow->IsChecked() )
2397 ImplDelData aDelData;
2398 pWindow->ImplAddDel( &aDelData );
2399 pWindow->SetState( sal_False );
2400 if ( aDelData.IsDead() )
2401 return;
2402 pWindow->ImplRemoveDel( &aDelData );
2405 // not inside if clause to always remove wrongly set WB_TABSTOPS
2406 pWindow->mpWindowImpl->mnStyle &= ~WB_TABSTOP;
2410 // -----------------------------------------------------------------------
2412 void RadioButton::ImplCallClick( sal_Bool bGrabFocus, sal_uInt16 nFocusFlags )
2414 mbStateChanged = !mbChecked;
2415 mbChecked = sal_True;
2416 mpWindowImpl->mnStyle |= WB_TABSTOP;
2417 ImplInvalidateOrDrawRadioButtonState();
2418 ImplDelData aDelData;
2419 ImplAddDel( &aDelData );
2420 if ( mbRadioCheck )
2421 ImplUncheckAllOther();
2422 if ( aDelData.IsDead() )
2423 return;
2424 if ( bGrabFocus )
2425 ImplGrabFocus( nFocusFlags );
2426 if ( aDelData.IsDead() )
2427 return;
2428 if ( mbStateChanged )
2429 Toggle();
2430 if ( aDelData.IsDead() )
2431 return;
2432 Click();
2433 if ( aDelData.IsDead() )
2434 return;
2435 ImplRemoveDel( &aDelData );
2436 mbStateChanged = sal_False;
2439 // -----------------------------------------------------------------------
2441 RadioButton::RadioButton( Window* pParent, WinBits nStyle ) :
2442 Button( WINDOW_RADIOBUTTON ), mbLegacyNoTextAlign( false )
2444 ImplInitRadioButtonData();
2445 ImplInit( pParent, nStyle );
2448 // -----------------------------------------------------------------------
2450 RadioButton::RadioButton( Window* pParent, const ResId& rResId ) :
2451 Button( WINDOW_RADIOBUTTON ), mbLegacyNoTextAlign( false )
2453 rResId.SetRT( RSC_RADIOBUTTON );
2454 WinBits nStyle = ImplInitRes( rResId );
2455 ImplInitRadioButtonData();
2456 ImplInit( pParent, nStyle );
2457 ImplLoadRes( rResId );
2459 if ( !(nStyle & WB_HIDE) )
2460 Show();
2463 // -----------------------------------------------------------------------
2465 void RadioButton::ImplLoadRes( const ResId& rResId )
2467 Button::ImplLoadRes( rResId );
2469 //anderer Wert als Default ?
2470 sal_uInt16 nChecked = ReadShortRes();
2471 if ( nChecked )
2472 SetState( sal_True );
2475 // -----------------------------------------------------------------------
2477 RadioButton::~RadioButton()
2479 if (m_xGroup)
2481 m_xGroup->erase(std::remove(m_xGroup->begin(), m_xGroup->end(), this),
2482 m_xGroup->end());
2486 // -----------------------------------------------------------------------
2488 void RadioButton::MouseButtonDown( const MouseEvent& rMEvt )
2490 if ( rMEvt.IsLeft() && maMouseRect.IsInside( rMEvt.GetPosPixel() ) )
2492 ImplGetButtonState() |= BUTTON_DRAW_PRESSED;
2493 ImplInvalidateOrDrawRadioButtonState();
2494 StartTracking();
2495 return;
2498 Button::MouseButtonDown( rMEvt );
2501 // -----------------------------------------------------------------------
2503 void RadioButton::Tracking( const TrackingEvent& rTEvt )
2505 if ( rTEvt.IsTrackingEnded() )
2507 if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED )
2509 if ( !(GetStyle() & WB_NOPOINTERFOCUS) && !rTEvt.IsTrackingCanceled() )
2510 GrabFocus();
2512 ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
2514 // do not call click handler if aborted
2515 if ( !rTEvt.IsTrackingCanceled() )
2516 ImplCallClick();
2517 else
2518 ImplInvalidateOrDrawRadioButtonState();
2521 else
2523 if ( maMouseRect.IsInside( rTEvt.GetMouseEvent().GetPosPixel() ) )
2525 if ( !(ImplGetButtonState() & BUTTON_DRAW_PRESSED) )
2527 ImplGetButtonState() |= BUTTON_DRAW_PRESSED;
2528 ImplInvalidateOrDrawRadioButtonState();
2531 else
2533 if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED )
2535 ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
2536 ImplInvalidateOrDrawRadioButtonState();
2542 // -----------------------------------------------------------------------
2544 void RadioButton::KeyInput( const KeyEvent& rKEvt )
2546 KeyCode aKeyCode = rKEvt.GetKeyCode();
2548 if ( !aKeyCode.GetModifier() && (aKeyCode.GetCode() == KEY_SPACE) )
2550 if ( !(ImplGetButtonState() & BUTTON_DRAW_PRESSED) )
2552 ImplGetButtonState() |= BUTTON_DRAW_PRESSED;
2553 ImplInvalidateOrDrawRadioButtonState();
2556 else if ( (ImplGetButtonState() & BUTTON_DRAW_PRESSED) && (aKeyCode.GetCode() == KEY_ESCAPE) )
2558 ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
2559 ImplInvalidateOrDrawRadioButtonState();
2561 else
2562 Button::KeyInput( rKEvt );
2565 // -----------------------------------------------------------------------
2567 void RadioButton::KeyUp( const KeyEvent& rKEvt )
2569 KeyCode aKeyCode = rKEvt.GetKeyCode();
2571 if ( (ImplGetButtonState() & BUTTON_DRAW_PRESSED) && (aKeyCode.GetCode() == KEY_SPACE) )
2573 ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
2574 ImplCallClick();
2576 else
2577 Button::KeyUp( rKEvt );
2580 // -----------------------------------------------------------------------
2582 void RadioButton::FillLayoutData() const
2584 mpControlData->mpLayoutData = new vcl::ControlLayoutData();
2585 const_cast<RadioButton*>(this)->ImplDrawRadioButton( true );
2588 // -----------------------------------------------------------------------
2590 void RadioButton::Paint( const Rectangle& )
2592 ImplDrawRadioButton();
2595 // -----------------------------------------------------------------------
2597 void RadioButton::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize,
2598 sal_uLong nFlags )
2600 if ( !maImage )
2602 MapMode aResMapMode( MAP_100TH_MM );
2603 Point aPos = pDev->LogicToPixel( rPos );
2604 Size aSize = pDev->LogicToPixel( rSize );
2605 Size aImageSize = pDev->LogicToPixel( Size( 300, 300 ), aResMapMode );
2606 Size aBrd1Size = pDev->LogicToPixel( Size( 20, 20 ), aResMapMode );
2607 Size aBrd2Size = pDev->LogicToPixel( Size( 60, 60 ), aResMapMode );
2608 Font aFont = GetDrawPixelFont( pDev );
2609 Rectangle aStateRect;
2610 Rectangle aMouseRect;
2612 aImageSize.Width() = CalcZoom( aImageSize.Width() );
2613 aImageSize.Height() = CalcZoom( aImageSize.Height() );
2614 aBrd1Size.Width() = CalcZoom( aBrd1Size.Width() );
2615 aBrd1Size.Height() = CalcZoom( aBrd1Size.Height() );
2616 aBrd2Size.Width() = CalcZoom( aBrd2Size.Width() );
2617 aBrd2Size.Height() = CalcZoom( aBrd2Size.Height() );
2619 if ( !aBrd1Size.Width() )
2620 aBrd1Size.Width() = 1;
2621 if ( !aBrd1Size.Height() )
2622 aBrd1Size.Height() = 1;
2623 if ( !aBrd2Size.Width() )
2624 aBrd2Size.Width() = 1;
2625 if ( !aBrd2Size.Height() )
2626 aBrd2Size.Height() = 1;
2628 pDev->Push();
2629 pDev->SetMapMode();
2630 pDev->SetFont( aFont );
2631 if ( nFlags & WINDOW_DRAW_MONO )
2632 pDev->SetTextColor( Color( COL_BLACK ) );
2633 else
2634 pDev->SetTextColor( GetTextColor() );
2635 pDev->SetTextFillColor();
2637 ImplDraw( pDev, nFlags, aPos, aSize,
2638 aImageSize, aStateRect, aMouseRect );
2640 Point aCenterPos = aStateRect.Center();
2641 long nRadX = aImageSize.Width()/2;
2642 long nRadY = aImageSize.Height()/2;
2644 pDev->SetLineColor();
2645 pDev->SetFillColor( Color( COL_BLACK ) );
2646 pDev->DrawPolygon( Polygon( aCenterPos, nRadX, nRadY ) );
2647 nRadX -= aBrd1Size.Width();
2648 nRadY -= aBrd1Size.Height();
2649 pDev->SetFillColor( Color( COL_WHITE ) );
2650 pDev->DrawPolygon( Polygon( aCenterPos, nRadX, nRadY ) );
2651 if ( mbChecked )
2653 nRadX -= aBrd1Size.Width();
2654 nRadY -= aBrd1Size.Height();
2655 if ( !nRadX )
2656 nRadX = 1;
2657 if ( !nRadY )
2658 nRadY = 1;
2659 pDev->SetFillColor( Color( COL_BLACK ) );
2660 pDev->DrawPolygon( Polygon( aCenterPos, nRadX, nRadY ) );
2663 pDev->Pop();
2665 else
2667 OSL_FAIL( "RadioButton::Draw() - not implemented for RadioButton with Image" );
2671 // -----------------------------------------------------------------------
2673 void RadioButton::Resize()
2675 Control::Resize();
2676 Invalidate();
2679 // -----------------------------------------------------------------------
2681 void RadioButton::GetFocus()
2683 ShowFocus( ImplGetFocusRect() );
2684 SetInputContext( InputContext( GetFont() ) );
2685 Button::GetFocus();
2688 // -----------------------------------------------------------------------
2690 void RadioButton::LoseFocus()
2692 if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED )
2694 ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
2695 ImplInvalidateOrDrawRadioButtonState();
2698 HideFocus();
2699 Button::LoseFocus();
2702 // -----------------------------------------------------------------------
2704 void RadioButton::StateChanged( StateChangedType nType )
2706 Button::StateChanged( nType );
2708 if ( nType == STATE_CHANGE_STATE )
2710 if ( IsReallyVisible() && IsUpdateMode() )
2711 Invalidate( maStateRect );
2713 else if ( (nType == STATE_CHANGE_ENABLE) ||
2714 (nType == STATE_CHANGE_TEXT) ||
2715 (nType == STATE_CHANGE_IMAGE) ||
2716 (nType == STATE_CHANGE_DATA) ||
2717 (nType == STATE_CHANGE_UPDATEMODE) )
2719 if ( IsUpdateMode() )
2720 Invalidate();
2722 else if ( nType == STATE_CHANGE_STYLE )
2724 SetStyle( ImplInitStyle( GetWindow( WINDOW_PREV ), GetStyle() ) );
2726 if ( (GetPrevStyle() & RADIOBUTTON_VIEW_STYLE) !=
2727 (GetStyle() & RADIOBUTTON_VIEW_STYLE) )
2729 if ( IsUpdateMode() )
2730 Invalidate();
2733 else if ( (nType == STATE_CHANGE_ZOOM) ||
2734 (nType == STATE_CHANGE_CONTROLFONT) )
2736 ImplInitSettings( sal_True, sal_False, sal_False );
2737 Invalidate();
2739 else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
2741 ImplInitSettings( sal_False, sal_True, sal_False );
2742 Invalidate();
2744 else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
2746 ImplInitSettings( sal_False, sal_False, sal_True );
2747 Invalidate();
2751 // -----------------------------------------------------------------------
2753 void RadioButton::DataChanged( const DataChangedEvent& rDCEvt )
2755 Button::DataChanged( rDCEvt );
2757 if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
2758 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
2759 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
2760 (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
2762 ImplInitSettings( sal_True, sal_True, sal_True );
2763 Invalidate();
2767 // -----------------------------------------------------------------------
2769 long RadioButton::PreNotify( NotifyEvent& rNEvt )
2771 long nDone = 0;
2772 const MouseEvent* pMouseEvt = NULL;
2774 if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL )
2776 if( !pMouseEvt->GetButtons() && !pMouseEvt->IsSynthetic() && !pMouseEvt->IsModifierChanged() )
2778 // trigger redraw if mouse over state has changed
2779 if( IsNativeControlSupported(CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL) )
2781 if( ( maMouseRect.IsInside( GetPointerPosPixel()) &&
2782 !maMouseRect.IsInside( GetLastPointerPosPixel()) ) ||
2783 ( maMouseRect.IsInside( GetLastPointerPosPixel()) &&
2784 !maMouseRect.IsInside( GetPointerPosPixel()) ) ||
2785 pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow() )
2787 Invalidate( maStateRect );
2793 return nDone ? nDone : Button::PreNotify(rNEvt);
2796 // -----------------------------------------------------------------------
2798 void RadioButton::Toggle()
2800 ImplCallEventListenersAndHandler( VCLEVENT_RADIOBUTTON_TOGGLE, maToggleHdl, this );
2803 // -----------------------------------------------------------------------
2805 sal_Bool RadioButton::SetModeRadioImage( const Image& rImage )
2807 if ( rImage != maImage )
2809 maImage = rImage;
2810 StateChanged( STATE_CHANGE_DATA );
2811 queue_resize();
2813 return sal_True;
2816 // -----------------------------------------------------------------------
2818 const Image& RadioButton::GetModeRadioImage( ) const
2820 return maImage;
2823 // -----------------------------------------------------------------------
2825 void RadioButton::SetState( sal_Bool bCheck )
2827 // TabStop-Flag richtig mitfuehren
2828 if ( bCheck )
2829 mpWindowImpl->mnStyle |= WB_TABSTOP;
2830 else
2831 mpWindowImpl->mnStyle &= ~WB_TABSTOP;
2833 if ( mbChecked != bCheck )
2835 mbChecked = bCheck;
2836 StateChanged( STATE_CHANGE_STATE );
2837 Toggle();
2841 bool RadioButton::set_property(const OString &rKey, const OString &rValue)
2843 if (rKey == "active")
2844 SetState(toBool(rValue));
2845 else
2846 return Window::set_property(rKey, rValue);
2847 return true;
2850 // -----------------------------------------------------------------------
2852 void RadioButton::Check( sal_Bool bCheck )
2854 // TabStop-Flag richtig mitfuehren
2855 if ( bCheck )
2856 mpWindowImpl->mnStyle |= WB_TABSTOP;
2857 else
2858 mpWindowImpl->mnStyle &= ~WB_TABSTOP;
2860 if ( mbChecked != bCheck )
2862 mbChecked = bCheck;
2863 ImplDelData aDelData;
2864 ImplAddDel( &aDelData );
2865 StateChanged( STATE_CHANGE_STATE );
2866 if ( aDelData.IsDead() )
2867 return;
2868 if ( bCheck && mbRadioCheck )
2869 ImplUncheckAllOther();
2870 if ( aDelData.IsDead() )
2871 return;
2872 Toggle();
2873 ImplRemoveDel( &aDelData );
2877 // -----------------------------------------------------------------------
2879 long RadioButton::ImplGetImageToTextDistance() const
2881 // 4 pixels, but take zoom into account, so the text doesn't "jump" relative to surrounding elements,
2882 // which might have been aligned with the text of the check box
2883 return CalcZoom( 4 );
2886 // -----------------------------------------------------------------------
2888 Size RadioButton::ImplGetRadioImageSize() const
2890 Size aSize;
2891 // why are IsNativeControlSupported and GetNativeControlRegion not const ?
2892 RadioButton* pThis = const_cast<RadioButton*>(this);
2893 bool bDefaultSize = true;
2894 if( pThis->IsNativeControlSupported( CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL ) )
2896 ImplControlValue aControlValue;
2897 // #i45896# workaround gcc3.3 temporary problem
2898 Rectangle aCtrlRegion( Point( 0, 0 ), GetSizePixel() );
2899 ControlState nState = CTRL_STATE_DEFAULT|CTRL_STATE_ENABLED;
2900 Rectangle aBoundingRgn, aContentRgn;
2902 // get native size of a radio button
2903 if( pThis->GetNativeControlRegion( CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL, aCtrlRegion,
2904 nState, aControlValue, OUString(),
2905 aBoundingRgn, aContentRgn ) )
2907 aSize = aContentRgn.GetSize();
2908 bDefaultSize = false;
2911 if( bDefaultSize )
2912 aSize = GetRadioImage( GetSettings(), 0 ).GetSizePixel();
2913 return aSize;
2916 static void LoadThemedImageList (const StyleSettings &rStyleSettings,
2917 ImageList *pList, const ResId &rResId,
2918 sal_uInt16 nImages)
2920 Color aColorAry1[6];
2921 Color aColorAry2[6];
2922 aColorAry1[0] = Color( 0xC0, 0xC0, 0xC0 );
2923 aColorAry1[1] = Color( 0xFF, 0xFF, 0x00 );
2924 aColorAry1[2] = Color( 0xFF, 0xFF, 0xFF );
2925 aColorAry1[3] = Color( 0x80, 0x80, 0x80 );
2926 aColorAry1[4] = Color( 0x00, 0x00, 0x00 );
2927 aColorAry1[5] = Color( 0x00, 0xFF, 0x00 );
2928 aColorAry2[0] = rStyleSettings.GetFaceColor();
2929 aColorAry2[1] = rStyleSettings.GetWindowColor();
2930 aColorAry2[2] = rStyleSettings.GetLightColor();
2931 aColorAry2[3] = rStyleSettings.GetShadowColor();
2932 aColorAry2[4] = rStyleSettings.GetDarkShadowColor();
2933 aColorAry2[5] = rStyleSettings.GetWindowTextColor();
2935 Color aMaskColor(0x00, 0x00, 0xFF );
2936 DBG_ASSERT( sizeof(aColorAry1) == sizeof(aColorAry2), "aColorAry1 must match aColorAry2" );
2937 // FIXME: do we want the mask for the checkbox ?
2938 pList->InsertFromHorizontalBitmap (rResId, nImages, &aMaskColor,
2939 aColorAry1, aColorAry2, sizeof(aColorAry1) / sizeof(Color));
2942 Image RadioButton::GetRadioImage( const AllSettings& rSettings, sal_uInt16 nFlags )
2944 ImplSVData* pSVData = ImplGetSVData();
2945 const StyleSettings& rStyleSettings = rSettings.GetStyleSettings();
2946 sal_uInt16 nStyle = 0;
2948 if ( rStyleSettings.GetOptions() & STYLE_OPTION_MONO )
2949 nStyle = STYLE_RADIOBUTTON_MONO;
2951 if ( !pSVData->maCtrlData.mpRadioImgList ||
2952 (pSVData->maCtrlData.mnRadioStyle != nStyle) ||
2953 (pSVData->maCtrlData.mnLastRadioFColor != rStyleSettings.GetFaceColor().GetColor()) ||
2954 (pSVData->maCtrlData.mnLastRadioWColor != rStyleSettings.GetWindowColor().GetColor()) ||
2955 (pSVData->maCtrlData.mnLastRadioLColor != rStyleSettings.GetLightColor().GetColor()) )
2957 if ( pSVData->maCtrlData.mpRadioImgList )
2958 delete pSVData->maCtrlData.mpRadioImgList;
2960 pSVData->maCtrlData.mnLastRadioFColor = rStyleSettings.GetFaceColor().GetColor();
2961 pSVData->maCtrlData.mnLastRadioWColor = rStyleSettings.GetWindowColor().GetColor();
2962 pSVData->maCtrlData.mnLastRadioLColor = rStyleSettings.GetLightColor().GetColor();
2964 ResMgr* pResMgr = ImplGetResMgr();
2965 pSVData->maCtrlData.mpRadioImgList = new ImageList();
2966 if( pResMgr )
2967 LoadThemedImageList( rStyleSettings,
2968 pSVData->maCtrlData.mpRadioImgList,
2969 ResId( SV_RESID_BITMAP_RADIO+nStyle, *pResMgr ), 6
2971 pSVData->maCtrlData.mnRadioStyle = nStyle;
2974 sal_uInt16 nId;
2975 if ( nFlags & BUTTON_DRAW_DISABLED )
2977 if ( nFlags & BUTTON_DRAW_CHECKED )
2978 nId = 6;
2979 else
2980 nId = 5;
2982 else if ( nFlags & BUTTON_DRAW_PRESSED )
2984 if ( nFlags & BUTTON_DRAW_CHECKED )
2985 nId = 4;
2986 else
2987 nId = 3;
2989 else
2991 if ( nFlags & BUTTON_DRAW_CHECKED )
2992 nId = 2;
2993 else
2994 nId = 1;
2996 return pSVData->maCtrlData.mpRadioImgList->GetImage( nId );
2999 // -----------------------------------------------------------------------
3001 void RadioButton::ImplSetMinimumNWFSize()
3003 Push( PUSH_MAPMODE );
3004 SetMapMode( MAP_PIXEL );
3006 ImplControlValue aControlValue;
3007 Size aCurSize( GetSizePixel() );
3008 Rectangle aCtrlRegion( Point( 0, 0 ), aCurSize );
3009 Rectangle aBoundingRgn, aContentRgn;
3011 // get native size of a radiobutton
3012 if( GetNativeControlRegion( CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL, aCtrlRegion,
3013 CTRL_STATE_DEFAULT|CTRL_STATE_ENABLED, aControlValue, OUString(),
3014 aBoundingRgn, aContentRgn ) )
3016 Size aSize = aContentRgn.GetSize();
3018 if( aSize.Height() > aCurSize.Height() )
3020 aCurSize.Height() = aSize.Height();
3021 SetSizePixel( aCurSize );
3025 Pop();
3028 // -----------------------------------------------------------------------
3030 Size RadioButton::CalcMinimumSize( long nMaxWidth ) const
3032 Size aSize;
3033 if ( !maImage )
3034 aSize = ImplGetRadioImageSize();
3035 else
3036 aSize = maImage.GetSizePixel();
3038 nMaxWidth -= aSize.Width();
3040 OUString aText = GetText();
3041 if ( !aText.isEmpty() && ! (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) )
3043 // subtract what will be added later
3044 nMaxWidth-=2;
3045 nMaxWidth -= ImplGetImageToTextDistance();
3047 Size aTextSize = GetTextRect( Rectangle( Point(), Size( nMaxWidth > 0 ? nMaxWidth : 0x7fffffff, 0x7fffffff ) ),
3048 aText, FixedText::ImplGetTextStyle( GetStyle() ) ).GetSize();
3049 aSize.Width()+=2; // for focus rect
3050 aSize.Width() += ImplGetImageToTextDistance();
3051 aSize.Width() += aTextSize.Width();
3052 if ( aSize.Height() < aTextSize.Height() )
3053 aSize.Height() = aTextSize.Height();
3055 // else if ( !maImage )
3056 // {
3057 /* da ansonsten im Writer die Control zu weit oben haengen
3058 aSize.Width() += 2;
3059 aSize.Height() += 2;
3061 // }
3063 return CalcWindowSize( aSize );
3066 // -----------------------------------------------------------------------
3068 Size RadioButton::GetOptimalSize() const
3070 return CalcMinimumSize();
3073 // =======================================================================
3075 void CheckBox::ImplInitCheckBoxData()
3077 meState = STATE_NOCHECK;
3078 meSaveValue = STATE_NOCHECK;
3079 mbTriState = sal_False;
3082 // -----------------------------------------------------------------------
3084 void CheckBox::ImplInit( Window* pParent, WinBits nStyle )
3086 nStyle = ImplInitStyle( pParent->GetWindow( WINDOW_LASTCHILD ), nStyle );
3087 Button::ImplInit( pParent, nStyle, NULL );
3089 ImplInitSettings( sal_True, sal_True, sal_True );
3092 // -----------------------------------------------------------------------
3094 WinBits CheckBox::ImplInitStyle( const Window* pPrevWindow, WinBits nStyle )
3096 if ( !(nStyle & WB_NOTABSTOP) )
3097 nStyle |= WB_TABSTOP;
3098 if ( !(nStyle & WB_NOGROUP) &&
3099 (!pPrevWindow || (pPrevWindow->GetType() != WINDOW_CHECKBOX)) )
3100 nStyle |= WB_GROUP;
3101 return nStyle;
3104 // -----------------------------------------------------------------
3106 const Font& CheckBox::GetCanonicalFont( const StyleSettings& _rStyle ) const
3108 return _rStyle.GetRadioCheckFont();
3111 // -----------------------------------------------------------------
3112 const Color& CheckBox::GetCanonicalTextColor( const StyleSettings& _rStyle ) const
3114 return _rStyle.GetRadioCheckTextColor();
3117 // -----------------------------------------------------------------------
3119 void CheckBox::ImplInitSettings( sal_Bool bFont,
3120 sal_Bool bForeground, sal_Bool bBackground )
3122 Button::ImplInitSettings( bFont, bForeground );
3124 if ( bBackground )
3126 Window* pParent = GetParent();
3127 if ( !IsControlBackground() &&
3128 (pParent->IsChildTransparentModeEnabled() || IsNativeControlSupported( CTRL_CHECKBOX, PART_ENTIRE_CONTROL ) ) )
3130 EnableChildTransparentMode( sal_True );
3131 SetParentClipMode( PARENTCLIPMODE_NOCLIP );
3132 SetPaintTransparent( sal_True );
3133 SetBackground();
3134 if( IsNativeControlSupported( CTRL_CHECKBOX, PART_ENTIRE_CONTROL ) )
3135 ImplGetWindowImpl()->mbUseNativeFocus = ImplGetSVData()->maNWFData.mbNoFocusRects;
3137 else
3139 EnableChildTransparentMode( sal_False );
3140 SetParentClipMode( 0 );
3141 SetPaintTransparent( sal_False );
3143 if ( IsControlBackground() )
3144 SetBackground( GetControlBackground() );
3145 else
3146 SetBackground( pParent->GetBackground() );
3151 // -----------------------------------------------------------------------
3153 void CheckBox::ImplLoadRes( const ResId& rResId )
3155 Button::ImplLoadRes( rResId );
3157 if ( rResId.GetRT() != RSC_TRISTATEBOX )
3159 sal_uInt16 nChecked = ReadShortRes();
3160 //anderer Wert als Default ?
3161 if( nChecked )
3162 Check( sal_True );
3166 // -----------------------------------------------------------------------
3168 void CheckBox::ImplInvalidateOrDrawCheckBoxState()
3170 if( ImplGetSVData()->maNWFData.mbCheckBoxNeedsErase )
3172 if ( IsNativeControlSupported(CTRL_CHECKBOX, PART_ENTIRE_CONTROL) )
3174 Invalidate();
3175 Update();
3176 return;
3179 ImplDrawCheckBoxState();
3182 void CheckBox::ImplDrawCheckBoxState()
3184 bool bNativeOK = sal_True;
3186 if ( (bNativeOK=IsNativeControlSupported(CTRL_CHECKBOX, PART_ENTIRE_CONTROL)) == sal_True )
3188 ImplControlValue aControlValue( meState == STATE_CHECK ? BUTTONVALUE_ON : BUTTONVALUE_OFF );
3189 Rectangle aCtrlRegion( maStateRect );
3190 ControlState nState = 0;
3192 if ( HasFocus() ) nState |= CTRL_STATE_FOCUSED;
3193 if ( ImplGetButtonState() & BUTTON_DRAW_DEFAULT ) nState |= CTRL_STATE_DEFAULT;
3194 if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED ) nState |= CTRL_STATE_PRESSED;
3195 if ( IsEnabled() ) nState |= CTRL_STATE_ENABLED;
3197 if ( meState == STATE_CHECK )
3198 aControlValue.setTristateVal( BUTTONVALUE_ON );
3199 else if ( meState == STATE_DONTKNOW )
3200 aControlValue.setTristateVal( BUTTONVALUE_MIXED );
3202 if ( IsMouseOver() && maMouseRect.IsInside( GetPointerPosPixel() ) )
3203 nState |= CTRL_STATE_ROLLOVER;
3205 bNativeOK = DrawNativeControl( CTRL_CHECKBOX, PART_ENTIRE_CONTROL, aCtrlRegion, nState,
3206 aControlValue, OUString() );
3209 if ( bNativeOK == sal_False )
3211 sal_uInt16 nStyle = ImplGetButtonState();
3212 if ( !IsEnabled() )
3213 nStyle |= BUTTON_DRAW_DISABLED;
3214 if ( meState == STATE_DONTKNOW )
3215 nStyle |= BUTTON_DRAW_DONTKNOW;
3216 else if ( meState == STATE_CHECK )
3217 nStyle |= BUTTON_DRAW_CHECKED;
3218 Image aImage = GetCheckImage( GetSettings(), nStyle );
3219 if ( IsZoom() )
3220 DrawImage( maStateRect.TopLeft(), maStateRect.GetSize(), aImage );
3221 else
3222 DrawImage( maStateRect.TopLeft(), aImage );
3226 // -----------------------------------------------------------------------
3228 void CheckBox::ImplDraw( OutputDevice* pDev, sal_uLong nDrawFlags,
3229 const Point& rPos, const Size& rSize,
3230 const Size& rImageSize, Rectangle& rStateRect,
3231 Rectangle& rMouseRect, bool bLayout )
3233 WinBits nWinStyle = GetStyle();
3234 OUString aText( GetText() );
3236 pDev->Push( PUSH_CLIPREGION | PUSH_LINECOLOR );
3237 pDev->IntersectClipRegion( Rectangle( rPos, rSize ) );
3239 long nLineY = rPos.Y() + (rSize.Height()-1)/2;
3240 if ( ( !aText.isEmpty() && ! (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) ) ||
3241 ( HasImage() && ! (ImplGetButtonState() & BUTTON_DRAW_NOIMAGE) ) )
3243 sal_uInt16 nTextStyle = Button::ImplGetTextStyle( aText, nWinStyle, nDrawFlags );
3245 const long nImageSep = GetDrawPixel( pDev, ImplGetImageToTextDistance() );
3246 Size aSize( rSize );
3247 Point aPos( rPos );
3248 aPos.X() += rImageSize.Width() + nImageSep;
3249 aSize.Width() -= rImageSize.Width() + nImageSep;
3251 // if the text rect height is smaller than the height of the image
3252 // then for single lines the default should be centered text
3253 if( (nWinStyle & (WB_TOP|WB_VCENTER|WB_BOTTOM)) == 0 &&
3254 (rImageSize.Height() > rSize.Height() || ! (nWinStyle & WB_WORDBREAK) ) )
3256 nTextStyle &= ~(TEXT_DRAW_TOP|TEXT_DRAW_BOTTOM);
3257 nTextStyle |= TEXT_DRAW_VCENTER;
3258 aSize.Height() = rImageSize.Height();
3261 ImplDrawAlignedImage( pDev, aPos, aSize, bLayout, 1,
3262 nDrawFlags, nTextStyle, NULL );
3263 nLineY = aPos.Y() + aSize.Height()/2;
3265 rMouseRect = Rectangle( aPos, aSize );
3266 rMouseRect.Left() = rPos.X();
3267 rStateRect.Left() = rPos.X();
3268 rStateRect.Top() = rMouseRect.Top();
3270 if ( aSize.Height() > rImageSize.Height() )
3271 rStateRect.Top() += ( aSize.Height() - rImageSize.Height() ) / 2;
3272 else
3274 rStateRect.Top() -= ( rImageSize.Height() - aSize.Height() ) / 2;
3275 if( rStateRect.Top() < 0 )
3276 rStateRect.Top() = 0;
3279 rStateRect.Right() = rStateRect.Left()+rImageSize.Width()-1;
3280 rStateRect.Bottom() = rStateRect.Top()+rImageSize.Height()-1;
3281 if ( rStateRect.Bottom() > rMouseRect.Bottom() )
3282 rMouseRect.Bottom() = rStateRect.Bottom();
3284 else
3286 if ( mbLegacyNoTextAlign && ( nWinStyle & WB_CENTER ) )
3287 rStateRect.Left() = rPos.X()+((rSize.Width()-rImageSize.Width())/2);
3288 else if ( mbLegacyNoTextAlign && ( nWinStyle & WB_RIGHT ) )
3289 rStateRect.Left() = rPos.X()+rSize.Width()-rImageSize.Width();
3290 else
3291 rStateRect.Left() = rPos.X();
3292 if ( nWinStyle & WB_VCENTER )
3293 rStateRect.Top() = rPos.Y()+((rSize.Height()-rImageSize.Height())/2);
3294 else if ( nWinStyle & WB_BOTTOM )
3295 rStateRect.Top() = rPos.Y()+rSize.Height()-rImageSize.Height();
3296 else
3297 rStateRect.Top() = rPos.Y();
3298 rStateRect.Right() = rStateRect.Left()+rImageSize.Width()-1;
3299 rStateRect.Bottom() = rStateRect.Top()+rImageSize.Height()-1;
3300 // provide space for focusrect
3301 // note: this assumes that the control's size was adjusted
3302 // accordingly in Get/LoseFocus, so the onscreen position won't change
3303 if( HasFocus() )
3304 rStateRect.Move( 1, 1 );
3305 rMouseRect = rStateRect;
3307 ImplSetFocusRect( rStateRect );
3310 const int nLineSpace = 4;
3311 if( (GetStyle() & WB_CBLINESTYLE) != 0 &&
3312 rMouseRect.Right()-1-nLineSpace < rPos.X()+rSize.Width() )
3314 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
3315 if ( rStyleSettings.GetOptions() & STYLE_OPTION_MONO )
3316 SetLineColor( Color( COL_BLACK ) );
3317 else
3318 SetLineColor( rStyleSettings.GetShadowColor() );
3319 long nLineX = rMouseRect.Right()+nLineSpace;
3320 DrawLine( Point( nLineX, nLineY ), Point( rPos.X() + rSize.Width()-1, nLineY ) );
3321 if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
3323 SetLineColor( rStyleSettings.GetLightColor() );
3324 DrawLine( Point( nLineX, nLineY+1 ), Point( rPos.X() + rSize.Width()-1, nLineY+1 ) );
3328 pDev->Pop();
3331 // -----------------------------------------------------------------------
3333 void CheckBox::ImplDrawCheckBox( bool bLayout )
3335 Size aImageSize = ImplGetCheckImageSize();
3336 aImageSize.Width() = CalcZoom( aImageSize.Width() );
3337 aImageSize.Height() = CalcZoom( aImageSize.Height() );
3339 if( !bLayout )
3340 HideFocus();
3342 ImplDraw( this, 0, Point(), GetOutputSizePixel(), aImageSize,
3343 maStateRect, maMouseRect, bLayout );
3345 if( !bLayout )
3347 ImplDrawCheckBoxState();
3348 if ( HasFocus() )
3349 ShowFocus( ImplGetFocusRect() );
3353 // -----------------------------------------------------------------------
3355 void CheckBox::ImplCheck()
3357 TriState eNewState;
3358 if ( meState == STATE_NOCHECK )
3359 eNewState = STATE_CHECK;
3360 else if ( !mbTriState )
3361 eNewState = STATE_NOCHECK;
3362 else if ( meState == STATE_CHECK )
3363 eNewState = STATE_DONTKNOW;
3364 else
3365 eNewState = STATE_NOCHECK;
3366 meState = eNewState;
3368 ImplDelData aDelData;
3369 ImplAddDel( &aDelData );
3370 if( (GetStyle() & WB_EARLYTOGGLE) )
3371 Toggle();
3372 ImplInvalidateOrDrawCheckBoxState();
3373 if( ! (GetStyle() & WB_EARLYTOGGLE) )
3374 Toggle();
3375 if ( aDelData.IsDead() )
3376 return;
3377 ImplRemoveDel( &aDelData );
3378 Click();
3381 // -----------------------------------------------------------------------
3383 CheckBox::CheckBox( Window* pParent, WinBits nStyle ) :
3384 Button( WINDOW_CHECKBOX ), mbLegacyNoTextAlign( false )
3386 ImplInitCheckBoxData();
3387 ImplInit( pParent, nStyle );
3390 // -----------------------------------------------------------------------
3392 CheckBox::CheckBox( Window* pParent, const ResId& rResId ) :
3393 Button( WINDOW_CHECKBOX ), mbLegacyNoTextAlign( false )
3395 rResId.SetRT( RSC_CHECKBOX );
3396 WinBits nStyle = ImplInitRes( rResId );
3397 ImplInitCheckBoxData();
3398 ImplInit( pParent, nStyle );
3399 ImplLoadRes( rResId );
3401 if ( !(nStyle & WB_HIDE) )
3402 Show();
3405 // -----------------------------------------------------------------------
3407 void CheckBox::MouseButtonDown( const MouseEvent& rMEvt )
3409 if ( rMEvt.IsLeft() && maMouseRect.IsInside( rMEvt.GetPosPixel() ) )
3411 ImplGetButtonState() |= BUTTON_DRAW_PRESSED;
3412 ImplInvalidateOrDrawCheckBoxState();
3413 StartTracking();
3414 return;
3417 Button::MouseButtonDown( rMEvt );
3420 // -----------------------------------------------------------------------
3422 void CheckBox::Tracking( const TrackingEvent& rTEvt )
3424 if ( rTEvt.IsTrackingEnded() )
3426 if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED )
3428 if ( !(GetStyle() & WB_NOPOINTERFOCUS) && !rTEvt.IsTrackingCanceled() )
3429 GrabFocus();
3431 ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
3433 // do not call click handler if aborted
3434 if ( !rTEvt.IsTrackingCanceled() )
3435 ImplCheck();
3436 else
3437 ImplInvalidateOrDrawCheckBoxState();
3440 else
3442 if ( maMouseRect.IsInside( rTEvt.GetMouseEvent().GetPosPixel() ) )
3444 if ( !(ImplGetButtonState() & BUTTON_DRAW_PRESSED) )
3446 ImplGetButtonState() |= BUTTON_DRAW_PRESSED;
3447 ImplInvalidateOrDrawCheckBoxState();
3450 else
3452 if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED )
3454 ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
3455 ImplInvalidateOrDrawCheckBoxState();
3461 // -----------------------------------------------------------------------
3463 void CheckBox::KeyInput( const KeyEvent& rKEvt )
3465 KeyCode aKeyCode = rKEvt.GetKeyCode();
3467 if ( !aKeyCode.GetModifier() && (aKeyCode.GetCode() == KEY_SPACE) )
3469 if ( !(ImplGetButtonState() & BUTTON_DRAW_PRESSED) )
3471 ImplGetButtonState() |= BUTTON_DRAW_PRESSED;
3472 ImplInvalidateOrDrawCheckBoxState();
3475 else if ( (ImplGetButtonState() & BUTTON_DRAW_PRESSED) && (aKeyCode.GetCode() == KEY_ESCAPE) )
3477 ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
3478 ImplInvalidateOrDrawCheckBoxState();
3480 else
3481 Button::KeyInput( rKEvt );
3484 // -----------------------------------------------------------------------
3486 void CheckBox::KeyUp( const KeyEvent& rKEvt )
3488 KeyCode aKeyCode = rKEvt.GetKeyCode();
3490 if ( (ImplGetButtonState() & BUTTON_DRAW_PRESSED) && (aKeyCode.GetCode() == KEY_SPACE) )
3492 ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
3493 ImplCheck();
3495 else
3496 Button::KeyUp( rKEvt );
3499 // -----------------------------------------------------------------------
3501 void CheckBox::FillLayoutData() const
3503 mpControlData->mpLayoutData = new vcl::ControlLayoutData();
3504 const_cast<CheckBox*>(this)->ImplDrawCheckBox( true );
3507 // -----------------------------------------------------------------------
3509 void CheckBox::Paint( const Rectangle& )
3511 ImplDrawCheckBox();
3514 // -----------------------------------------------------------------------
3516 void CheckBox::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize,
3517 sal_uLong nFlags )
3519 MapMode aResMapMode( MAP_100TH_MM );
3520 Point aPos = pDev->LogicToPixel( rPos );
3521 Size aSize = pDev->LogicToPixel( rSize );
3522 Size aImageSize = pDev->LogicToPixel( Size( 300, 300 ), aResMapMode );
3523 Size aBrd1Size = pDev->LogicToPixel( Size( 20, 20 ), aResMapMode );
3524 Size aBrd2Size = pDev->LogicToPixel( Size( 30, 30 ), aResMapMode );
3525 long nCheckWidth = pDev->LogicToPixel( Size( 20, 20 ), aResMapMode ).Width();
3526 Font aFont = GetDrawPixelFont( pDev );
3527 Rectangle aStateRect;
3528 Rectangle aMouseRect;
3530 aImageSize.Width() = CalcZoom( aImageSize.Width() );
3531 aImageSize.Height() = CalcZoom( aImageSize.Height() );
3532 aBrd1Size.Width() = CalcZoom( aBrd1Size.Width() );
3533 aBrd1Size.Height() = CalcZoom( aBrd1Size.Height() );
3534 aBrd2Size.Width() = CalcZoom( aBrd2Size.Width() );
3535 aBrd2Size.Height() = CalcZoom( aBrd2Size.Height() );
3537 if ( !aBrd1Size.Width() )
3538 aBrd1Size.Width() = 1;
3539 if ( !aBrd1Size.Height() )
3540 aBrd1Size.Height() = 1;
3541 if ( !aBrd2Size.Width() )
3542 aBrd2Size.Width() = 1;
3543 if ( !aBrd2Size.Height() )
3544 aBrd2Size.Height() = 1;
3545 if ( !nCheckWidth )
3546 nCheckWidth = 1;
3548 pDev->Push();
3549 pDev->SetMapMode();
3550 pDev->SetFont( aFont );
3551 if ( nFlags & WINDOW_DRAW_MONO )
3552 pDev->SetTextColor( Color( COL_BLACK ) );
3553 else
3554 pDev->SetTextColor( GetTextColor() );
3555 pDev->SetTextFillColor();
3557 ImplDraw( pDev, nFlags, aPos, aSize,
3558 aImageSize, aStateRect, aMouseRect, false );
3560 pDev->SetLineColor();
3561 pDev->SetFillColor( Color( COL_BLACK ) );
3562 pDev->DrawRect( aStateRect );
3563 aStateRect.Left() += aBrd1Size.Width();
3564 aStateRect.Top() += aBrd1Size.Height();
3565 aStateRect.Right() -= aBrd1Size.Width();
3566 aStateRect.Bottom() -= aBrd1Size.Height();
3567 if ( meState == STATE_DONTKNOW )
3568 pDev->SetFillColor( Color( COL_LIGHTGRAY ) );
3569 else
3570 pDev->SetFillColor( Color( COL_WHITE ) );
3571 pDev->DrawRect( aStateRect );
3573 if ( meState == STATE_CHECK )
3575 aStateRect.Left() += aBrd2Size.Width();
3576 aStateRect.Top() += aBrd2Size.Height();
3577 aStateRect.Right() -= aBrd2Size.Width();
3578 aStateRect.Bottom() -= aBrd2Size.Height();
3579 Point aPos11( aStateRect.TopLeft() );
3580 Point aPos12( aStateRect.BottomRight() );
3581 Point aPos21( aStateRect.TopRight() );
3582 Point aPos22( aStateRect.BottomLeft() );
3583 Point aTempPos11( aPos11 );
3584 Point aTempPos12( aPos12 );
3585 Point aTempPos21( aPos21 );
3586 Point aTempPos22( aPos22 );
3587 pDev->SetLineColor( Color( COL_BLACK ) );
3588 long nDX = 0;
3589 for ( long i = 0; i < nCheckWidth; i++ )
3591 if ( !(i % 2) )
3593 aTempPos11.X() = aPos11.X()+nDX;
3594 aTempPos12.X() = aPos12.X()+nDX;
3595 aTempPos21.X() = aPos21.X()+nDX;
3596 aTempPos22.X() = aPos22.X()+nDX;
3598 else
3600 nDX++;
3601 aTempPos11.X() = aPos11.X()-nDX;
3602 aTempPos12.X() = aPos12.X()-nDX;
3603 aTempPos21.X() = aPos21.X()-nDX;
3604 aTempPos22.X() = aPos22.X()-nDX;
3606 pDev->DrawLine( aTempPos11, aTempPos12 );
3607 pDev->DrawLine( aTempPos21, aTempPos22 );
3611 pDev->Pop();
3614 // -----------------------------------------------------------------------
3616 void CheckBox::Resize()
3618 Control::Resize();
3619 Invalidate();
3622 // -----------------------------------------------------------------------
3624 void CheckBox::GetFocus()
3626 if ( GetText().isEmpty() || (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) )
3628 // increase button size to have space for focus rect
3629 // checkboxes without text will draw focusrect around the check
3630 // See CheckBox::ImplDraw()
3631 Point aPos( GetPosPixel() );
3632 Size aSize( GetSizePixel() );
3633 aPos.Move(-1,-1);
3634 aSize.Height() += 2;
3635 aSize.Width() += 2;
3636 setPosSizePixel( aPos.X(), aPos.Y(), aSize.Width(), aSize.Height(), WINDOW_POSSIZE_ALL );
3637 ImplDrawCheckBox();
3639 else
3640 ShowFocus( ImplGetFocusRect() );
3642 SetInputContext( InputContext( GetFont() ) );
3643 Button::GetFocus();
3646 // -----------------------------------------------------------------------
3648 void CheckBox::LoseFocus()
3650 if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED )
3652 ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
3653 ImplInvalidateOrDrawCheckBoxState();
3656 HideFocus();
3657 Button::LoseFocus();
3659 if ( GetText().isEmpty() || (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) )
3661 // decrease button size again (see GetFocus())
3662 // checkboxes without text will draw focusrect around the check
3663 Point aPos( GetPosPixel() );
3664 Size aSize( GetSizePixel() );
3665 aPos.Move(1,1);
3666 aSize.Height() -= 2;
3667 aSize.Width() -= 2;
3668 setPosSizePixel( aPos.X(), aPos.Y(), aSize.Width(), aSize.Height(), WINDOW_POSSIZE_ALL );
3669 ImplDrawCheckBox();
3673 // -----------------------------------------------------------------------
3675 void CheckBox::StateChanged( StateChangedType nType )
3677 Button::StateChanged( nType );
3679 if ( nType == STATE_CHANGE_STATE )
3681 if ( IsReallyVisible() && IsUpdateMode() )
3682 Invalidate( maStateRect );
3684 else if ( (nType == STATE_CHANGE_ENABLE) ||
3685 (nType == STATE_CHANGE_TEXT) ||
3686 (nType == STATE_CHANGE_IMAGE) ||
3687 (nType == STATE_CHANGE_DATA) ||
3688 (nType == STATE_CHANGE_UPDATEMODE) )
3690 if ( IsUpdateMode() )
3691 Invalidate();
3693 else if ( nType == STATE_CHANGE_STYLE )
3695 SetStyle( ImplInitStyle( GetWindow( WINDOW_PREV ), GetStyle() ) );
3697 if ( (GetPrevStyle() & CHECKBOX_VIEW_STYLE) !=
3698 (GetStyle() & CHECKBOX_VIEW_STYLE) )
3700 if ( IsUpdateMode() )
3701 Invalidate();
3704 else if ( (nType == STATE_CHANGE_ZOOM) ||
3705 (nType == STATE_CHANGE_CONTROLFONT) )
3707 ImplInitSettings( sal_True, sal_False, sal_False );
3708 Invalidate();
3710 else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
3712 ImplInitSettings( sal_False, sal_True, sal_False );
3713 Invalidate();
3715 else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
3717 ImplInitSettings( sal_False, sal_False, sal_True );
3718 Invalidate();
3722 // -----------------------------------------------------------------------
3724 void CheckBox::DataChanged( const DataChangedEvent& rDCEvt )
3726 Button::DataChanged( rDCEvt );
3728 if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
3729 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
3730 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
3731 (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
3733 ImplInitSettings( sal_True, sal_True, sal_True );
3734 Invalidate();
3738 // -----------------------------------------------------------------------
3740 long CheckBox::PreNotify( NotifyEvent& rNEvt )
3742 long nDone = 0;
3743 const MouseEvent* pMouseEvt = NULL;
3745 if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL )
3747 if( !pMouseEvt->GetButtons() && !pMouseEvt->IsSynthetic() && !pMouseEvt->IsModifierChanged() )
3749 // trigger redraw if mouse over state has changed
3750 if( IsNativeControlSupported(CTRL_CHECKBOX, PART_ENTIRE_CONTROL) )
3752 if( ( maMouseRect.IsInside( GetPointerPosPixel()) &&
3753 !maMouseRect.IsInside( GetLastPointerPosPixel()) ) ||
3754 ( maMouseRect.IsInside( GetLastPointerPosPixel()) &&
3755 !maMouseRect.IsInside( GetPointerPosPixel()) ) ||
3756 pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow() )
3758 Invalidate( maStateRect );
3764 return nDone ? nDone : Button::PreNotify(rNEvt);
3767 // -----------------------------------------------------------------------
3769 void CheckBox::Toggle()
3771 ImplCallEventListenersAndHandler( VCLEVENT_CHECKBOX_TOGGLE, maToggleHdl, this );
3774 // -----------------------------------------------------------------------
3776 void CheckBox::SetState( TriState eState )
3778 if ( !mbTriState && (eState == STATE_DONTKNOW) )
3779 eState = STATE_NOCHECK;
3781 if ( meState != eState )
3783 meState = eState;
3784 StateChanged( STATE_CHANGE_STATE );
3785 Toggle();
3789 bool CheckBox::set_property(const OString &rKey, const OString &rValue)
3791 if (rKey == "active")
3792 SetState(toBool(rValue) ? STATE_CHECK : STATE_NOCHECK);
3793 else
3794 return Window::set_property(rKey, rValue);
3795 return true;
3798 // -----------------------------------------------------------------------
3800 void CheckBox::EnableTriState( sal_Bool bTriState )
3802 if ( mbTriState != bTriState )
3804 mbTriState = bTriState;
3806 if ( !bTriState && (meState == STATE_DONTKNOW) )
3807 SetState( STATE_NOCHECK );
3811 // -----------------------------------------------------------------------
3813 long CheckBox::ImplGetImageToTextDistance() const
3815 // 4 pixels, but take zoom into account, so the text doesn't "jump" relative to surrounding elements,
3816 // which might have been aligned with the text of the check box
3817 return CalcZoom( 4 );
3820 // -----------------------------------------------------------------------
3822 Size CheckBox::ImplGetCheckImageSize() const
3824 Size aSize;
3825 // why are IsNativeControlSupported and GetNativeControlRegion not const ?
3826 CheckBox* pThis = const_cast<CheckBox*>(this);
3827 bool bDefaultSize = true;
3828 if( pThis->IsNativeControlSupported( CTRL_CHECKBOX, PART_ENTIRE_CONTROL ) )
3830 ImplControlValue aControlValue;
3831 // #i45896# workaround gcc3.3 temporary problem
3832 Rectangle aCtrlRegion( Point( 0, 0 ), GetSizePixel() );
3833 ControlState nState = CTRL_STATE_DEFAULT|CTRL_STATE_ENABLED;
3834 Rectangle aBoundingRgn, aContentRgn;
3836 // get native size of a check box
3837 if( pThis->GetNativeControlRegion( CTRL_CHECKBOX, PART_ENTIRE_CONTROL, aCtrlRegion,
3838 nState, aControlValue, OUString(),
3839 aBoundingRgn, aContentRgn ) )
3841 aSize = aContentRgn.GetSize();
3842 bDefaultSize = false;
3845 if( bDefaultSize )
3846 aSize = GetCheckImage( GetSettings(), 0 ).GetSizePixel();
3847 return aSize;
3850 Image CheckBox::GetCheckImage( const AllSettings& rSettings, sal_uInt16 nFlags )
3852 ImplSVData* pSVData = ImplGetSVData();
3853 const StyleSettings& rStyleSettings = rSettings.GetStyleSettings();
3854 sal_uInt16 nStyle = 0;
3856 if ( rStyleSettings.GetOptions() & STYLE_OPTION_MONO )
3857 nStyle = STYLE_CHECKBOX_MONO;
3859 if ( !pSVData->maCtrlData.mpCheckImgList ||
3860 (pSVData->maCtrlData.mnCheckStyle != nStyle) ||
3861 (pSVData->maCtrlData.mnLastCheckFColor != rStyleSettings.GetFaceColor().GetColor()) ||
3862 (pSVData->maCtrlData.mnLastCheckWColor != rStyleSettings.GetWindowColor().GetColor()) ||
3863 (pSVData->maCtrlData.mnLastCheckLColor != rStyleSettings.GetLightColor().GetColor()) )
3865 if ( pSVData->maCtrlData.mpCheckImgList )
3866 delete pSVData->maCtrlData.mpCheckImgList;
3868 pSVData->maCtrlData.mnLastCheckFColor = rStyleSettings.GetFaceColor().GetColor();
3869 pSVData->maCtrlData.mnLastCheckWColor = rStyleSettings.GetWindowColor().GetColor();
3870 pSVData->maCtrlData.mnLastCheckLColor = rStyleSettings.GetLightColor().GetColor();
3872 ResMgr* pResMgr = ImplGetResMgr();
3873 pSVData->maCtrlData.mpCheckImgList = new ImageList();
3874 if( pResMgr )
3875 LoadThemedImageList( rStyleSettings,
3876 pSVData->maCtrlData.mpCheckImgList,
3877 ResId( SV_RESID_BITMAP_CHECK+nStyle, *pResMgr ), 9 );
3878 pSVData->maCtrlData.mnCheckStyle = nStyle;
3881 sal_uInt16 nId;
3882 if ( nFlags & BUTTON_DRAW_DISABLED )
3884 if ( nFlags & BUTTON_DRAW_DONTKNOW )
3885 nId = 9;
3886 else if ( nFlags & BUTTON_DRAW_CHECKED )
3887 nId = 6;
3888 else
3889 nId = 5;
3891 else if ( nFlags & BUTTON_DRAW_PRESSED )
3893 if ( nFlags & BUTTON_DRAW_DONTKNOW )
3894 nId = 8;
3895 else if ( nFlags & BUTTON_DRAW_CHECKED )
3896 nId = 4;
3897 else
3898 nId = 3;
3900 else
3902 if ( nFlags & BUTTON_DRAW_DONTKNOW )
3903 nId = 7;
3904 else if ( nFlags & BUTTON_DRAW_CHECKED )
3905 nId = 2;
3906 else
3907 nId = 1;
3909 return pSVData->maCtrlData.mpCheckImgList->GetImage( nId );
3912 // -----------------------------------------------------------------------
3914 void CheckBox::ImplSetMinimumNWFSize()
3916 Push( PUSH_MAPMODE );
3917 SetMapMode( MAP_PIXEL );
3919 ImplControlValue aControlValue;
3920 Size aCurSize( GetSizePixel() );
3921 Rectangle aCtrlRegion( Point( 0, 0 ), aCurSize );
3922 Rectangle aBoundingRgn, aContentRgn;
3924 // get native size of a radiobutton
3925 if( GetNativeControlRegion( CTRL_CHECKBOX, PART_ENTIRE_CONTROL, aCtrlRegion,
3926 CTRL_STATE_DEFAULT|CTRL_STATE_ENABLED, aControlValue, OUString(),
3927 aBoundingRgn, aContentRgn ) )
3929 Size aSize = aContentRgn.GetSize();
3931 if( aSize.Height() > aCurSize.Height() )
3933 aCurSize.Height() = aSize.Height();
3934 SetSizePixel( aCurSize );
3938 Pop();
3941 // -----------------------------------------------------------------------
3943 Size CheckBox::CalcMinimumSize( long nMaxWidth ) const
3945 Size aSize = ImplGetCheckImageSize();
3946 nMaxWidth -= aSize.Width();
3948 OUString aText = GetText();
3949 if ( !aText.isEmpty() && ! (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) )
3951 // subtract what will be added later
3952 nMaxWidth-=2;
3953 nMaxWidth -= ImplGetImageToTextDistance();
3955 Size aTextSize = GetTextRect( Rectangle( Point(), Size( nMaxWidth > 0 ? nMaxWidth : 0x7fffffff, 0x7fffffff ) ),
3956 aText, FixedText::ImplGetTextStyle( GetStyle() ) ).GetSize();
3957 aSize.Width()+=2; // for focus rect
3958 aSize.Width() += ImplGetImageToTextDistance();
3959 aSize.Width() += aTextSize.Width();
3960 if ( aSize.Height() < aTextSize.Height() )
3961 aSize.Height() = aTextSize.Height();
3963 else
3965 // is this still correct ? since the checkbox now
3966 // shows a focus rect it should be 2 pixels wider and longer
3967 /* da ansonsten im Writer die Control zu weit oben haengen
3968 aSize.Width() += 2;
3969 aSize.Height() += 2;
3973 return CalcWindowSize( aSize );
3976 // -----------------------------------------------------------------------
3978 Size CheckBox::GetOptimalSize() const
3980 return CalcMinimumSize();
3983 // =======================================================================
3985 ImageButton::ImageButton( Window* pParent, WinBits nStyle ) :
3986 PushButton( pParent, nStyle )
3988 ImplInitStyle();
3991 // -----------------------------------------------------------------------
3993 ImageButton::ImageButton( Window* pParent, const ResId& rResId ) :
3994 PushButton( pParent, rResId.SetRT( RSC_IMAGEBUTTON ) )
3996 sal_uLong nObjMask = ReadLongRes();
3998 if ( RSC_IMAGEBUTTON_IMAGE & nObjMask )
4000 SetModeImage( Image( ResId( (RSHEADER_TYPE*)GetClassRes(), *rResId.GetResMgr() ) ) );
4001 IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
4004 if ( RSC_IMAGEBUTTON_SYMBOL & nObjMask )
4005 SetSymbol( (SymbolType)ReadLongRes() );
4007 if ( RSC_IMAGEBUTTON_STATE & nObjMask )
4008 SetState( (TriState)ReadLongRes() );
4010 ImplInitStyle();
4013 // -----------------------------------------------------------------------
4015 ImageButton::~ImageButton()
4019 // -----------------------------------------------------------------------
4020 void ImageButton::ImplInitStyle()
4022 WinBits nStyle = GetStyle();
4024 if ( ! ( nStyle & ( WB_RIGHT | WB_LEFT ) ) )
4025 nStyle |= WB_CENTER;
4027 if ( ! ( nStyle & ( WB_TOP | WB_BOTTOM ) ) )
4028 nStyle |= WB_VCENTER;
4030 SetStyle( nStyle );
4033 // =======================================================================
4035 ImageRadioButton::ImageRadioButton( Window* pParent, WinBits nStyle ) :
4036 RadioButton( pParent, nStyle )
4040 // -----------------------------------------------------------------------
4042 ImageRadioButton::ImageRadioButton( Window* pParent, const ResId& rResId ) :
4043 RadioButton( pParent, rResId.SetRT( RSC_IMAGERADIOBUTTON ) )
4045 sal_uLong nObjMask = ReadLongRes();
4047 if ( RSC_IMAGERADIOBUTTON_IMAGE & nObjMask )
4049 SetModeRadioImage( Image( ResId( (RSHEADER_TYPE*)GetClassRes(), *rResId.GetResMgr() ) ) );
4050 IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
4054 // -----------------------------------------------------------------------
4056 ImageRadioButton::~ImageRadioButton()
4060 // =======================================================================
4062 TriStateBox::TriStateBox( Window* pParent, WinBits nStyle ) :
4063 CheckBox( pParent, nStyle )
4065 EnableTriState( sal_True );
4068 // -----------------------------------------------------------------------
4070 TriStateBox::TriStateBox( Window* pParent, const ResId& rResId ) :
4071 CheckBox( pParent, rResId.SetRT( RSC_TRISTATEBOX ) )
4073 EnableTriState( sal_True );
4075 sal_uLong nTriState = ReadLongRes();
4076 sal_uInt16 bDisableTriState = ReadShortRes();
4077 //anderer Wert als Default ?
4078 if ( (TriState)nTriState != STATE_NOCHECK )
4079 SetState( (TriState)nTriState );
4080 if ( bDisableTriState )
4081 EnableTriState( sal_False );
4084 // -----------------------------------------------------------------------
4086 TriStateBox::~TriStateBox()
4090 // =======================================================================
4092 DisclosureButton::DisclosureButton( Window* pParent, WinBits nStyle ) :
4093 CheckBox( pParent, nStyle )
4097 DisclosureButton::DisclosureButton( Window* pParent, const ResId& rResId ) :
4098 CheckBox( pParent, rResId.SetRT( RSC_CHECKBOX ) )
4102 // -----------------------------------------------------------------------
4104 void DisclosureButton::ImplDrawCheckBoxState()
4106 /* HACK: DisclosureButton is currently assuming, that the disclosure sign
4107 will fit into the rectangle occupied by a normal checkbox on all themes.
4108 If this does not hold true for some theme, ImplGetCheckImageSize
4109 would have to be overloaded for DisclosureButton; also GetNativeControlRegion
4110 for CTRL_LISTNODE would have to be implemented and taken into account
4113 Rectangle aStateRect( GetStateRect() );
4115 ImplControlValue aControlValue( GetState() == STATE_CHECK ? BUTTONVALUE_ON : BUTTONVALUE_OFF );
4116 Rectangle aCtrlRegion( aStateRect );
4117 ControlState nState = 0;
4119 if ( HasFocus() ) nState |= CTRL_STATE_FOCUSED;
4120 if ( ImplGetButtonState() & BUTTON_DRAW_DEFAULT ) nState |= CTRL_STATE_DEFAULT;
4121 if ( Window::IsEnabled() ) nState |= CTRL_STATE_ENABLED;
4122 if ( IsMouseOver() && GetMouseRect().IsInside( GetPointerPosPixel() ) )
4123 nState |= CTRL_STATE_ROLLOVER;
4125 if( ! DrawNativeControl( CTRL_LISTNODE, PART_ENTIRE_CONTROL, aCtrlRegion, nState,
4126 aControlValue, OUString() ) )
4128 ImplSVCtrlData& rCtrlData( ImplGetSVData()->maCtrlData );
4129 if( ! rCtrlData.mpDisclosurePlus )
4130 rCtrlData.mpDisclosurePlus = new Image( BitmapEx( VclResId( SV_DISCLOSURE_PLUS ) ) );
4131 if( ! rCtrlData.mpDisclosureMinus )
4132 rCtrlData.mpDisclosureMinus = new Image( BitmapEx( VclResId( SV_DISCLOSURE_MINUS ) ) );
4134 Image* pImg = NULL;
4135 pImg = IsChecked() ? rCtrlData.mpDisclosureMinus : rCtrlData.mpDisclosurePlus;
4137 DBG_ASSERT( pImg, "no disclosure image" );
4138 if( ! pImg )
4139 return;
4141 sal_uInt16 nStyle = 0;
4142 if( ! IsEnabled() )
4143 nStyle |= IMAGE_DRAW_DISABLE;
4145 Size aSize( aStateRect.GetSize() );
4146 Size aImgSize( pImg->GetSizePixel() );
4147 Point aOff( (aSize.Width() - aImgSize.Width())/2,
4148 (aSize.Height() - aImgSize.Height())/2 );
4149 aOff += aStateRect.TopLeft();
4150 DrawImage( aOff, *pImg, nStyle );
4154 // -----------------------------------------------------------------------
4156 void DisclosureButton::KeyInput( const KeyEvent& rKEvt )
4158 KeyCode aKeyCode = rKEvt.GetKeyCode();
4160 if( !aKeyCode.GetModifier() &&
4161 ( ( aKeyCode.GetCode() == KEY_ADD ) ||
4162 ( aKeyCode.GetCode() == KEY_SUBTRACT ) )
4165 Check( aKeyCode.GetCode() == KEY_ADD );
4167 else
4168 CheckBox::KeyInput( rKEvt );
4171 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */