Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <tools/debug.hxx>
21 : #include <tools/lineend.hxx>
22 : #include <tools/poly.hxx>
23 : #include <tools/rc.h>
24 :
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/settings.hxx>
32 : #include <vcl/dialog.hxx>
33 : #include <vcl/fixed.hxx>
34 : #include <vcl/button.hxx>
35 : #include <vcl/salnativewidgets.hxx>
36 : #include <vcl/edit.hxx>
37 : #include <vcl/layout.hxx>
38 :
39 : #include <svids.hrc>
40 : #include <svdata.hxx>
41 : #include <window.h>
42 : #include <controldata.hxx>
43 :
44 : #define PUSHBUTTON_VIEW_STYLE (WB_3DLOOK | \
45 : WB_LEFT | WB_CENTER | WB_RIGHT | \
46 : WB_TOP | WB_VCENTER | WB_BOTTOM | \
47 : WB_WORDBREAK | WB_NOLABEL | \
48 : WB_DEFBUTTON | WB_NOLIGHTBORDER | \
49 : WB_RECTSTYLE | WB_SMALLSTYLE | \
50 : WB_TOGGLE )
51 : #define RADIOBUTTON_VIEW_STYLE (WB_3DLOOK | \
52 : WB_LEFT | WB_CENTER | WB_RIGHT | \
53 : WB_TOP | WB_VCENTER | WB_BOTTOM | \
54 : WB_WORDBREAK | WB_NOLABEL)
55 : #define CHECKBOX_VIEW_STYLE (WB_3DLOOK | \
56 : WB_LEFT | WB_CENTER | WB_RIGHT | \
57 : WB_TOP | WB_VCENTER | WB_BOTTOM | \
58 : WB_WORDBREAK | WB_NOLABEL)
59 :
60 : class ImplCommonButtonData
61 : {
62 : public:
63 : Rectangle maFocusRect;
64 : long mnSeparatorX;
65 : sal_uInt16 mnButtonState;
66 : bool mbSmallSymbol;
67 :
68 : Image maImage;
69 : ImageAlign meImageAlign;
70 : SymbolAlign meSymbolAlign;
71 :
72 : public:
73 : ImplCommonButtonData();
74 : ~ImplCommonButtonData();
75 : };
76 :
77 0 : ImplCommonButtonData::ImplCommonButtonData() : maFocusRect(), mnSeparatorX(0), mnButtonState(0),
78 0 : mbSmallSymbol(false), maImage(), meImageAlign(IMAGEALIGN_TOP), meSymbolAlign(SYMBOLALIGN_LEFT)
79 : {
80 0 : }
81 :
82 0 : ImplCommonButtonData::~ImplCommonButtonData()
83 : {
84 0 : }
85 :
86 0 : Button::Button( WindowType nType ) :
87 0 : Control( nType )
88 : {
89 0 : mpButtonData = new ImplCommonButtonData;
90 0 : }
91 :
92 0 : Button::~Button()
93 : {
94 0 : delete mpButtonData;
95 0 : }
96 :
97 0 : void Button::Click()
98 : {
99 0 : ImplCallEventListenersAndHandler( VCLEVENT_BUTTON_CLICK, maClickHdl, this );
100 0 : }
101 :
102 0 : OUString Button::GetStandardText( StandardButtonType eButton )
103 : {
104 : static struct
105 : {
106 : sal_uInt32 nResId;
107 : const char* pDefText;
108 : } aResIdAry[BUTTON_COUNT] =
109 : {
110 : { SV_BUTTONTEXT_OK, "~OK" },
111 : { SV_BUTTONTEXT_CANCEL, "~Cancel" },
112 : { SV_BUTTONTEXT_YES, "~Yes" },
113 : { SV_BUTTONTEXT_NO, "~No" },
114 : { SV_BUTTONTEXT_RETRY, "~Retry" },
115 : { SV_BUTTONTEXT_HELP, "~Help" },
116 : { SV_BUTTONTEXT_CLOSE, "~Close" },
117 : { SV_BUTTONTEXT_MORE, "~More" },
118 : { SV_BUTTONTEXT_IGNORE, "~Ignore" },
119 : { SV_BUTTONTEXT_ABORT, "~Abort" },
120 : { SV_BUTTONTEXT_LESS, "~Less" },
121 : { SV_BUTTONTEXT_RESET, "R~eset" }
122 : };
123 :
124 0 : ResMgr* pResMgr = ImplGetResMgr();
125 :
126 0 : if (!pResMgr)
127 : {
128 0 : OString aT( aResIdAry[(sal_uInt16)eButton].pDefText );
129 0 : return OStringToOUString(aT, RTL_TEXTENCODING_ASCII_US);
130 : }
131 :
132 0 : sal_uInt32 nResId = aResIdAry[(sal_uInt16)eButton].nResId;
133 : #ifdef WNT
134 : // http://lists.freedesktop.org/archives/libreoffice/2013-January/044513.html
135 : // Under windows we don't want accelerators on ok/cancel but do on other
136 : // buttons
137 : if (nResId == SV_BUTTONTEXT_OK)
138 : nResId = SV_BUTTONTEXT_OK_NOMNEMONIC;
139 : else if (nResId == SV_BUTTONTEXT_CANCEL)
140 : nResId = SV_BUTTONTEXT_CANCEL_NOMNEMONIC;
141 : #endif
142 0 : return ResId(nResId, *pResMgr).toString();
143 : }
144 :
145 0 : bool Button::SetModeImage( const Image& rImage )
146 : {
147 0 : if ( rImage != mpButtonData->maImage )
148 : {
149 0 : mpButtonData->maImage = rImage;
150 0 : StateChanged( STATE_CHANGE_DATA );
151 0 : queue_resize();
152 : }
153 0 : return true;
154 : }
155 :
156 0 : const Image Button::GetModeImage( ) const
157 : {
158 0 : return mpButtonData->maImage;
159 : }
160 :
161 0 : bool Button::HasImage() const
162 : {
163 0 : return !!(mpButtonData->maImage);
164 : }
165 :
166 0 : void Button::SetImageAlign( ImageAlign eAlign )
167 : {
168 0 : if ( mpButtonData->meImageAlign != eAlign )
169 : {
170 0 : mpButtonData->meImageAlign = eAlign;
171 0 : StateChanged( STATE_CHANGE_DATA );
172 : }
173 0 : }
174 :
175 0 : ImageAlign Button::GetImageAlign() const
176 : {
177 0 : return mpButtonData->meImageAlign;
178 : }
179 :
180 0 : void Button::SetFocusRect( const Rectangle& rFocusRect )
181 : {
182 0 : ImplSetFocusRect( rFocusRect );
183 0 : }
184 :
185 0 : long Button::ImplGetSeparatorX() const
186 : {
187 0 : return mpButtonData->mnSeparatorX;
188 : }
189 :
190 0 : void Button::ImplSetSeparatorX( long nX )
191 : {
192 0 : mpButtonData->mnSeparatorX = nX;
193 0 : }
194 :
195 0 : sal_uInt16 Button::ImplGetTextStyle( OUString& rText, WinBits nWinStyle,
196 : sal_uLong nDrawFlags )
197 : {
198 0 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
199 0 : sal_uInt16 nTextStyle = FixedText::ImplGetTextStyle( nWinStyle & ~WB_DEFBUTTON );
200 :
201 0 : if ( nDrawFlags & WINDOW_DRAW_NOMNEMONIC )
202 : {
203 0 : if ( nTextStyle & TEXT_DRAW_MNEMONIC )
204 : {
205 0 : rText = GetNonMnemonicString( rText );
206 0 : nTextStyle &= ~TEXT_DRAW_MNEMONIC;
207 : }
208 : }
209 :
210 0 : if ( !(nDrawFlags & WINDOW_DRAW_NODISABLE) )
211 : {
212 0 : if ( !IsEnabled() )
213 0 : nTextStyle |= TEXT_DRAW_DISABLE;
214 : }
215 :
216 0 : if ( (nDrawFlags & WINDOW_DRAW_MONO) ||
217 0 : (rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
218 0 : nTextStyle |= TEXT_DRAW_MONO;
219 :
220 0 : return nTextStyle;
221 : }
222 :
223 0 : void Button::ImplDrawAlignedImage( OutputDevice* pDev, Point& rPos,
224 : Size& rSize, bool bLayout,
225 : sal_uLong nImageSep, sal_uLong nDrawFlags,
226 : sal_uInt16 nTextStyle, Rectangle *pSymbolRect,
227 : bool bAddImageSep )
228 : {
229 0 : OUString aText( GetText() );
230 0 : bool bDrawImage = HasImage() && ! ( ImplGetButtonState() & BUTTON_DRAW_NOIMAGE );
231 0 : bool bDrawText = !aText.isEmpty() && ! ( ImplGetButtonState() & BUTTON_DRAW_NOTEXT );
232 0 : bool bHasSymbol = pSymbolRect ? true : false;
233 :
234 : // No text and no image => nothing to do => return
235 0 : if ( !bDrawImage && !bDrawText && !bHasSymbol )
236 0 : return;
237 :
238 0 : WinBits nWinStyle = GetStyle();
239 0 : Rectangle aOutRect( rPos, rSize );
240 0 : MetricVector *pVector = bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : NULL;
241 0 : OUString *pDisplayText = bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : NULL;
242 0 : ImageAlign eImageAlign = mpButtonData->meImageAlign;
243 0 : Size aImageSize = mpButtonData->maImage.GetSizePixel();
244 :
245 0 : if ( ( nDrawFlags & WINDOW_DRAW_NOMNEMONIC ) &&
246 0 : ( nTextStyle & TEXT_DRAW_MNEMONIC ) )
247 : {
248 0 : aText = GetNonMnemonicString( aText );
249 0 : nTextStyle &= ~TEXT_DRAW_MNEMONIC;
250 : }
251 :
252 0 : aImageSize.Width() = CalcZoom( aImageSize.Width() );
253 0 : aImageSize.Height() = CalcZoom( aImageSize.Height() );
254 :
255 : // Drawing text or symbol only is simple, use style and output rectangle
256 0 : if ( bHasSymbol && !bDrawImage && !bDrawText )
257 : {
258 0 : *pSymbolRect = aOutRect;
259 0 : return;
260 : }
261 0 : else if ( bDrawText && !bDrawImage && !bHasSymbol )
262 : {
263 0 : DrawControlText( *pDev, aOutRect, aText, nTextStyle, pVector, pDisplayText );
264 :
265 0 : ImplSetFocusRect( aOutRect );
266 0 : rSize = aOutRect.GetSize();
267 0 : rPos = aOutRect.TopLeft();
268 :
269 0 : return;
270 : }
271 :
272 : // check for HC mode ( image only! )
273 0 : Image *pImage = &(mpButtonData->maImage);
274 :
275 0 : Size aTextSize;
276 0 : Size aSymbolSize;
277 0 : Size aMax;
278 0 : Point aImagePos = rPos;
279 0 : Point aTextPos = rPos;
280 0 : Rectangle aUnion = Rectangle( aImagePos, aImageSize );
281 0 : Rectangle aSymbol;
282 0 : long nSymbolHeight = 0;
283 :
284 0 : if ( bDrawText || bHasSymbol )
285 : {
286 : // Get the size of the text output area ( the symbol will be drawn in
287 : // this area as well, so the symbol rectangle will be calculated here, too )
288 :
289 0 : Rectangle aRect = Rectangle( Point(), rSize );
290 0 : Size aTSSize;
291 :
292 0 : if ( bHasSymbol )
293 : {
294 0 : if ( bDrawText )
295 : {
296 0 : nSymbolHeight = pDev->GetTextHeight();
297 0 : if ( mpButtonData->mbSmallSymbol )
298 0 : nSymbolHeight = nSymbolHeight * 3 / 4;
299 :
300 0 : aSymbol = Rectangle( Point(), Size( nSymbolHeight, nSymbolHeight ) );
301 0 : ImplCalcSymbolRect( aSymbol );
302 0 : aRect.Left() += 3 * nSymbolHeight / 2;
303 0 : aTSSize.Width() = 3 * nSymbolHeight / 2;
304 : }
305 : else
306 : {
307 0 : aSymbol = Rectangle( Point(), rSize );
308 0 : ImplCalcSymbolRect( aSymbol );
309 0 : aTSSize.Width() = aSymbol.GetWidth();
310 : }
311 0 : aTSSize.Height() = aSymbol.GetHeight();
312 0 : aSymbolSize = aSymbol.GetSize();
313 : }
314 :
315 0 : if ( bDrawText )
316 : {
317 0 : if ( ( eImageAlign == IMAGEALIGN_LEFT_TOP ) ||
318 0 : ( eImageAlign == IMAGEALIGN_LEFT ) ||
319 0 : ( eImageAlign == IMAGEALIGN_LEFT_BOTTOM ) ||
320 0 : ( eImageAlign == IMAGEALIGN_RIGHT_TOP ) ||
321 0 : ( eImageAlign == IMAGEALIGN_RIGHT ) ||
322 : ( eImageAlign == IMAGEALIGN_RIGHT_BOTTOM ) )
323 : {
324 0 : aRect.Right() -= ( aImageSize.Width() + nImageSep );
325 : }
326 0 : else if ( ( eImageAlign == IMAGEALIGN_TOP_LEFT ) ||
327 0 : ( eImageAlign == IMAGEALIGN_TOP ) ||
328 0 : ( eImageAlign == IMAGEALIGN_TOP_RIGHT ) ||
329 0 : ( eImageAlign == IMAGEALIGN_BOTTOM_LEFT ) ||
330 0 : ( eImageAlign == IMAGEALIGN_BOTTOM ) ||
331 : ( eImageAlign == IMAGEALIGN_BOTTOM_RIGHT ) )
332 : {
333 0 : aRect.Bottom() -= ( aImageSize.Height() + nImageSep );
334 : }
335 :
336 0 : aRect = pDev->GetTextRect( aRect, aText, nTextStyle );
337 0 : aTextSize = aRect.GetSize();
338 :
339 0 : aTSSize.Width() += aTextSize.Width();
340 :
341 0 : if ( aTSSize.Height() < aTextSize.Height() )
342 0 : aTSSize.Height() = aTextSize.Height();
343 :
344 0 : if( bAddImageSep && bDrawImage )
345 : {
346 0 : long nDiff = (aImageSize.Height() - aTextSize.Height()) / 3;
347 0 : if( nDiff > 0 )
348 0 : nImageSep += nDiff;
349 : }
350 : }
351 :
352 0 : aMax.Width() = aTSSize.Width() > aImageSize.Width() ? aTSSize.Width() : aImageSize.Width();
353 0 : aMax.Height() = aTSSize.Height() > aImageSize.Height() ? aTSSize.Height() : aImageSize.Height();
354 :
355 : // Now calculate the output area for the image and the text acording to the image align flags
356 :
357 0 : if ( ( eImageAlign == IMAGEALIGN_LEFT ) ||
358 : ( eImageAlign == IMAGEALIGN_RIGHT ) )
359 : {
360 0 : aImagePos.Y() = rPos.Y() + ( aMax.Height() - aImageSize.Height() ) / 2;
361 0 : aTextPos.Y() = rPos.Y() + ( aMax.Height() - aTSSize.Height() ) / 2;
362 : }
363 0 : else if ( ( eImageAlign == IMAGEALIGN_LEFT_BOTTOM ) ||
364 : ( eImageAlign == IMAGEALIGN_RIGHT_BOTTOM ) )
365 : {
366 0 : aImagePos.Y() = rPos.Y() + aMax.Height() - aImageSize.Height();
367 0 : aTextPos.Y() = rPos.Y() + aMax.Height() - aTSSize.Height();
368 : }
369 0 : else if ( ( eImageAlign == IMAGEALIGN_TOP ) ||
370 : ( eImageAlign == IMAGEALIGN_BOTTOM ) )
371 : {
372 0 : aImagePos.X() = rPos.X() + ( aMax.Width() - aImageSize.Width() ) / 2;
373 0 : aTextPos.X() = rPos.X() + ( aMax.Width() - aTSSize.Width() ) / 2;
374 : }
375 0 : else if ( ( eImageAlign == IMAGEALIGN_TOP_RIGHT ) ||
376 : ( eImageAlign == IMAGEALIGN_BOTTOM_RIGHT ) )
377 : {
378 0 : aImagePos.X() = rPos.X() + aMax.Width() - aImageSize.Width();
379 0 : aTextPos.X() = rPos.X() + aMax.Width() - aTSSize.Width();
380 : }
381 :
382 0 : if ( ( eImageAlign == IMAGEALIGN_LEFT_TOP ) ||
383 0 : ( eImageAlign == IMAGEALIGN_LEFT ) ||
384 : ( eImageAlign == IMAGEALIGN_LEFT_BOTTOM ) )
385 : {
386 0 : aTextPos.X() = rPos.X() + aImageSize.Width() + nImageSep;
387 : }
388 0 : else if ( ( eImageAlign == IMAGEALIGN_RIGHT_TOP ) ||
389 0 : ( eImageAlign == IMAGEALIGN_RIGHT ) ||
390 : ( eImageAlign == IMAGEALIGN_RIGHT_BOTTOM ) )
391 : {
392 0 : aImagePos.X() = rPos.X() + aTSSize.Width() + nImageSep;
393 : }
394 0 : else if ( ( eImageAlign == IMAGEALIGN_TOP_LEFT ) ||
395 0 : ( eImageAlign == IMAGEALIGN_TOP ) ||
396 : ( eImageAlign == IMAGEALIGN_TOP_RIGHT ) )
397 : {
398 0 : aTextPos.Y() = rPos.Y() + aImageSize.Height() + nImageSep;
399 : }
400 0 : else if ( ( eImageAlign == IMAGEALIGN_BOTTOM_LEFT ) ||
401 0 : ( eImageAlign == IMAGEALIGN_BOTTOM ) ||
402 : ( eImageAlign == IMAGEALIGN_BOTTOM_RIGHT ) )
403 : {
404 0 : aImagePos.Y() = rPos.Y() + aTSSize.Height() + nImageSep;
405 : }
406 0 : else if ( eImageAlign == IMAGEALIGN_CENTER )
407 : {
408 0 : aImagePos.X() = rPos.X() + ( aMax.Width() - aImageSize.Width() ) / 2;
409 0 : aImagePos.Y() = rPos.Y() + ( aMax.Height() - aImageSize.Height() ) / 2;
410 0 : aTextPos.X() = rPos.X() + ( aMax.Width() - aTSSize.Width() ) / 2;
411 0 : aTextPos.Y() = rPos.Y() + ( aMax.Height() - aTSSize.Height() ) / 2;
412 : }
413 0 : aUnion = Rectangle( aImagePos, aImageSize );
414 0 : aUnion.Union( Rectangle( aTextPos, aTSSize ) );
415 : }
416 :
417 : // Now place the combination of text and image in the output area of the button
418 : // according to the window style (WinBits)
419 0 : long nXOffset = 0;
420 0 : long nYOffset = 0;
421 :
422 0 : if ( nWinStyle & WB_CENTER )
423 : {
424 0 : nXOffset = ( rSize.Width() - aUnion.GetWidth() ) / 2;
425 : }
426 0 : else if ( nWinStyle & WB_RIGHT )
427 : {
428 0 : nXOffset = rSize.Width() - aUnion.GetWidth();
429 : }
430 :
431 0 : if ( nWinStyle & WB_VCENTER )
432 : {
433 0 : nYOffset = ( rSize.Height() - aUnion.GetHeight() ) / 2;
434 : }
435 0 : else if ( nWinStyle & WB_BOTTOM )
436 : {
437 0 : nYOffset = rSize.Height() - aUnion.GetHeight();
438 : }
439 :
440 : // the top left corner should always be visible, so we don't allow negative offsets
441 0 : if ( nXOffset < 0 ) nXOffset = 0;
442 0 : if ( nYOffset < 0 ) nYOffset = 0;
443 :
444 0 : aImagePos.X() += nXOffset;
445 0 : aImagePos.Y() += nYOffset;
446 0 : aTextPos.X() += nXOffset;
447 0 : aTextPos.Y() += nYOffset;
448 :
449 : // set rPos and rSize to the union
450 0 : rSize = aUnion.GetSize();
451 0 : rPos.X() += nXOffset;
452 0 : rPos.Y() += nYOffset;
453 :
454 0 : if ( bHasSymbol )
455 : {
456 0 : if ( mpButtonData->meSymbolAlign == SYMBOLALIGN_RIGHT )
457 : {
458 0 : Point aRightPos = Point( aTextPos.X() + aTextSize.Width() + aSymbolSize.Width()/2, aTextPos.Y() );
459 0 : *pSymbolRect = Rectangle( aRightPos, aSymbolSize );
460 : }
461 : else
462 : {
463 0 : *pSymbolRect = Rectangle( aTextPos, aSymbolSize );
464 0 : aTextPos.X() += ( 3 * nSymbolHeight / 2 );
465 : }
466 0 : if ( mpButtonData->mbSmallSymbol )
467 : {
468 0 : nYOffset = (aUnion.GetHeight() - aSymbolSize.Height())/2;
469 0 : pSymbolRect->setY( aTextPos.Y() + nYOffset );
470 : }
471 : }
472 :
473 0 : sal_uInt16 nStyle = 0;
474 :
475 0 : if ( ! ( nDrawFlags & WINDOW_DRAW_NODISABLE ) &&
476 0 : ! IsEnabled() )
477 0 : nStyle |= IMAGE_DRAW_DISABLE;
478 :
479 0 : if ( IsZoom() )
480 0 : pDev->DrawImage( aImagePos, aImageSize, *pImage, nStyle );
481 : else
482 0 : pDev->DrawImage( aImagePos, *pImage, nStyle );
483 :
484 0 : if ( bDrawText )
485 : {
486 0 : ImplSetFocusRect( Rectangle( aTextPos, aTextSize ) );
487 0 : pDev->DrawText( Rectangle( aTextPos, aTextSize ), aText, nTextStyle, pVector, pDisplayText );
488 : }
489 : else
490 : {
491 0 : ImplSetFocusRect( Rectangle( aImagePos, aImageSize ) );
492 0 : }
493 : }
494 :
495 0 : void Button::ImplSetFocusRect( const Rectangle &rFocusRect )
496 : {
497 0 : Rectangle aFocusRect = rFocusRect;
498 0 : Rectangle aOutputRect = Rectangle( Point(), GetOutputSizePixel() );
499 :
500 0 : if ( ! aFocusRect.IsEmpty() )
501 : {
502 0 : aFocusRect.Left()--;
503 0 : aFocusRect.Top()--;
504 0 : aFocusRect.Right()++;
505 0 : aFocusRect.Bottom()++;
506 : }
507 :
508 0 : if ( aFocusRect.Left() < aOutputRect.Left() ) aFocusRect.Left() = aOutputRect.Left();
509 0 : if ( aFocusRect.Top() < aOutputRect.Top() ) aFocusRect.Top() = aOutputRect.Top();
510 0 : if ( aFocusRect.Right() > aOutputRect.Right() ) aFocusRect.Right() = aOutputRect.Right();
511 0 : if ( aFocusRect.Bottom() > aOutputRect.Bottom() ) aFocusRect.Bottom() = aOutputRect.Bottom();
512 :
513 0 : mpButtonData->maFocusRect = aFocusRect;
514 0 : }
515 :
516 0 : const Rectangle& Button::ImplGetFocusRect() const
517 : {
518 0 : return mpButtonData->maFocusRect;
519 : }
520 :
521 0 : sal_uInt16& Button::ImplGetButtonState()
522 : {
523 0 : return mpButtonData->mnButtonState;
524 : }
525 :
526 0 : sal_uInt16 Button::ImplGetButtonState() const
527 : {
528 0 : return mpButtonData->mnButtonState;
529 : }
530 :
531 0 : void Button::ImplSetSymbolAlign( SymbolAlign eAlign )
532 : {
533 0 : if ( mpButtonData->meSymbolAlign != eAlign )
534 : {
535 0 : mpButtonData->meSymbolAlign = eAlign;
536 0 : StateChanged( STATE_CHANGE_DATA );
537 : }
538 0 : }
539 :
540 0 : void Button::SetSmallSymbol(bool bSmall)
541 : {
542 0 : mpButtonData->mbSmallSymbol = bSmall;
543 0 : }
544 :
545 0 : void Button::EnableImageDisplay( bool bEnable )
546 : {
547 0 : if( bEnable )
548 0 : mpButtonData->mnButtonState &= ~BUTTON_DRAW_NOIMAGE;
549 : else
550 0 : mpButtonData->mnButtonState |= BUTTON_DRAW_NOIMAGE;
551 0 : }
552 :
553 0 : void Button::EnableTextDisplay( bool bEnable )
554 : {
555 0 : if( bEnable )
556 0 : mpButtonData->mnButtonState &= ~BUTTON_DRAW_NOTEXT;
557 : else
558 0 : mpButtonData->mnButtonState |= BUTTON_DRAW_NOTEXT;
559 0 : }
560 :
561 0 : bool Button::IsSmallSymbol () const
562 : {
563 0 : return mpButtonData->mbSmallSymbol;
564 : }
565 :
566 0 : bool Button::set_property(const OString &rKey, const OString &rValue)
567 : {
568 0 : if (rKey == "image-position")
569 : {
570 0 : ImageAlign eAlign = IMAGEALIGN_LEFT;
571 0 : if (rValue == "left")
572 0 : eAlign = IMAGEALIGN_LEFT;
573 0 : else if (rValue == "right")
574 0 : eAlign = IMAGEALIGN_RIGHT;
575 0 : else if (rValue == "top")
576 0 : eAlign = IMAGEALIGN_TOP;
577 0 : else if (rValue == "bottom")
578 0 : eAlign = IMAGEALIGN_BOTTOM;
579 0 : SetImageAlign(eAlign);
580 : }
581 : else
582 0 : return Control::set_property(rKey, rValue);
583 0 : return true;
584 : }
585 :
586 0 : void PushButton::ImplInitPushButtonData()
587 : {
588 0 : mpWindowImpl->mbPushButton = true;
589 :
590 0 : meSymbol = SYMBOL_NOSYMBOL;
591 0 : meState = TRISTATE_FALSE;
592 0 : meSaveValue = TRISTATE_FALSE;
593 0 : mnDDStyle = 0;
594 0 : mbPressed = false;
595 0 : mbInUserDraw = false;
596 0 : }
597 :
598 : namespace
599 : {
600 0 : Window* getPreviousSibling(Window *pParent)
601 : {
602 0 : return pParent ? pParent->GetWindow(WINDOW_LASTCHILD) : NULL;
603 : }
604 : }
605 :
606 0 : void PushButton::ImplInit( Window* pParent, WinBits nStyle )
607 : {
608 0 : nStyle = ImplInitStyle(getPreviousSibling(pParent), nStyle);
609 0 : Button::ImplInit( pParent, nStyle, NULL );
610 :
611 0 : if ( nStyle & WB_NOLIGHTBORDER )
612 0 : ImplGetButtonState() |= BUTTON_DRAW_NOLIGHTBORDER;
613 :
614 0 : ImplInitSettings( true, true, true );
615 0 : }
616 :
617 0 : WinBits PushButton::ImplInitStyle( const Window* pPrevWindow, WinBits nStyle )
618 : {
619 0 : if ( !(nStyle & WB_NOTABSTOP) )
620 0 : nStyle |= WB_TABSTOP;
621 :
622 : // if no alignment is given, default to "vertically centered". This is because since
623 : // #i26046#, we respect the vertical alignment flags (previously we didn't completely),
624 : // but we of course want to look as before when no vertical alignment is specified
625 0 : if ( ( nStyle & ( WB_TOP | WB_VCENTER | WB_BOTTOM ) ) == 0 )
626 0 : nStyle |= WB_VCENTER;
627 :
628 0 : if ( !(nStyle & WB_NOGROUP) &&
629 0 : (!pPrevWindow ||
630 0 : ((pPrevWindow->GetType() != WINDOW_PUSHBUTTON ) &&
631 0 : (pPrevWindow->GetType() != WINDOW_OKBUTTON ) &&
632 0 : (pPrevWindow->GetType() != WINDOW_CANCELBUTTON) &&
633 0 : (pPrevWindow->GetType() != WINDOW_HELPBUTTON )) ) )
634 0 : nStyle |= WB_GROUP;
635 0 : return nStyle;
636 : }
637 :
638 0 : const Font& PushButton::GetCanonicalFont( const StyleSettings& _rStyle ) const
639 : {
640 0 : return _rStyle.GetPushButtonFont();
641 : }
642 :
643 0 : const Color& PushButton::GetCanonicalTextColor( const StyleSettings& _rStyle ) const
644 : {
645 0 : return _rStyle.GetButtonTextColor();
646 : }
647 :
648 0 : void PushButton::ImplInitSettings( bool bFont,
649 : bool bForeground, bool bBackground )
650 : {
651 0 : Button::ImplInitSettings( bFont, bForeground );
652 :
653 0 : if ( bBackground )
654 : {
655 0 : SetBackground();
656 : // #i38498#: do not check for GetParent()->IsChildTransparentModeEnabled()
657 : // otherwise the formcontrol button will be overdrawn due to PARENTCLIPMODE_NOCLIP
658 : // for radio and checkbox this is ok as they shoud appear transparent in documents
659 0 : if ( IsNativeControlSupported( CTRL_PUSHBUTTON, PART_ENTIRE_CONTROL ) ||
660 0 : (GetStyle() & WB_FLATBUTTON) != 0 )
661 : {
662 0 : EnableChildTransparentMode( true );
663 0 : SetParentClipMode( PARENTCLIPMODE_NOCLIP );
664 0 : SetPaintTransparent( true );
665 0 : mpWindowImpl->mbUseNativeFocus = (GetStyle() & WB_FLATBUTTON)
666 : ? false
667 0 : : ImplGetSVData()->maNWFData.mbNoFocusRects;
668 : }
669 : else
670 : {
671 0 : EnableChildTransparentMode( false );
672 0 : SetParentClipMode( 0 );
673 0 : SetPaintTransparent( false );
674 : }
675 : }
676 0 : }
677 :
678 0 : void PushButton::ImplDrawPushButtonFrame( Window* pDev,
679 : Rectangle& rRect, sal_uInt16 nStyle )
680 : {
681 0 : if ( !(pDev->GetStyle() & (WB_RECTSTYLE | WB_SMALLSTYLE)) )
682 : {
683 0 : StyleSettings aStyleSettings = pDev->GetSettings().GetStyleSettings();
684 0 : if ( pDev->IsControlBackground() )
685 0 : aStyleSettings.Set3DColors( pDev->GetControlBackground() );
686 : }
687 :
688 0 : DecorationView aDecoView( pDev );
689 0 : if ( pDev->IsControlBackground() )
690 : {
691 0 : AllSettings aSettings = pDev->GetSettings();
692 0 : AllSettings aOldSettings = aSettings;
693 0 : StyleSettings aStyleSettings = aSettings.GetStyleSettings();
694 0 : aStyleSettings.Set3DColors( pDev->GetControlBackground() );
695 0 : aSettings.SetStyleSettings( aStyleSettings );
696 0 : pDev->OutputDevice::SetSettings( aSettings );
697 0 : rRect = aDecoView.DrawButton( rRect, nStyle );
698 0 : pDev->OutputDevice::SetSettings( aOldSettings );
699 : }
700 : else
701 0 : rRect = aDecoView.DrawButton( rRect, nStyle );
702 0 : }
703 :
704 0 : bool PushButton::ImplHitTestPushButton( Window* pDev,
705 : const Point& rPos )
706 : {
707 0 : Point aTempPoint;
708 0 : Rectangle aTestRect( aTempPoint, pDev->GetOutputSizePixel() );
709 :
710 0 : return aTestRect.IsInside( rPos );
711 : }
712 :
713 0 : sal_uInt16 PushButton::ImplGetTextStyle( sal_uLong nDrawFlags ) const
714 : {
715 0 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
716 :
717 0 : sal_uInt16 nTextStyle = TEXT_DRAW_MNEMONIC | TEXT_DRAW_MULTILINE | TEXT_DRAW_ENDELLIPSIS;
718 :
719 0 : if ( ( rStyleSettings.GetOptions() & STYLE_OPTION_MONO ) ||
720 0 : ( nDrawFlags & WINDOW_DRAW_MONO ) )
721 0 : nTextStyle |= TEXT_DRAW_MONO;
722 :
723 0 : if ( GetStyle() & WB_WORDBREAK )
724 0 : nTextStyle |= TEXT_DRAW_WORDBREAK;
725 0 : if ( GetStyle() & WB_NOLABEL )
726 0 : nTextStyle &= ~TEXT_DRAW_MNEMONIC;
727 :
728 0 : if ( GetStyle() & WB_LEFT )
729 0 : nTextStyle |= TEXT_DRAW_LEFT;
730 0 : else if ( GetStyle() & WB_RIGHT )
731 0 : nTextStyle |= TEXT_DRAW_RIGHT;
732 : else
733 0 : nTextStyle |= TEXT_DRAW_CENTER;
734 :
735 0 : if ( GetStyle() & WB_TOP )
736 0 : nTextStyle |= TEXT_DRAW_TOP;
737 0 : else if ( GetStyle() & WB_BOTTOM )
738 0 : nTextStyle |= TEXT_DRAW_BOTTOM;
739 : else
740 0 : nTextStyle |= TEXT_DRAW_VCENTER;
741 :
742 0 : if ( ! ( (nDrawFlags & WINDOW_DRAW_NODISABLE) || IsEnabled() ) )
743 0 : nTextStyle |= TEXT_DRAW_DISABLE;
744 :
745 0 : return nTextStyle;
746 : }
747 :
748 0 : static void ImplDrawBtnDropDownArrow( OutputDevice* pDev,
749 : long nX, long nY,
750 : Color& rColor, bool bBlack )
751 : {
752 0 : Color aOldLineColor = pDev->GetLineColor();
753 0 : Color aOldFillColor = pDev->GetFillColor();
754 :
755 0 : pDev->SetLineColor();
756 0 : if ( bBlack )
757 0 : pDev->SetFillColor( Color( COL_BLACK ) );
758 : else
759 0 : pDev->SetFillColor( rColor );
760 0 : pDev->DrawRect( Rectangle( nX+0, nY+0, nX+6, nY+0 ) );
761 0 : pDev->DrawRect( Rectangle( nX+1, nY+1, nX+5, nY+1 ) );
762 0 : pDev->DrawRect( Rectangle( nX+2, nY+2, nX+4, nY+2 ) );
763 0 : pDev->DrawRect( Rectangle( nX+3, nY+3, nX+3, nY+3 ) );
764 0 : if ( bBlack )
765 : {
766 0 : pDev->SetFillColor( rColor );
767 0 : pDev->DrawRect( Rectangle( nX+2, nY+1, nX+4, nY+1 ) );
768 0 : pDev->DrawRect( Rectangle( nX+3, nY+2, nX+3, nY+2 ) );
769 : }
770 0 : pDev->SetLineColor( aOldLineColor );
771 0 : pDev->SetFillColor( aOldFillColor );
772 0 : }
773 :
774 0 : void PushButton::ImplDrawPushButtonContent( OutputDevice* pDev, sal_uLong nDrawFlags,
775 : const Rectangle& rRect,
776 : bool bLayout,
777 : bool bMenuBtnSep
778 : )
779 : {
780 0 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
781 0 : Rectangle aInRect = rRect;
782 0 : Color aColor;
783 0 : OUString aText = PushButton::GetText(); // PushButton:: because of MoreButton
784 0 : sal_uInt16 nTextStyle = ImplGetTextStyle( nDrawFlags );
785 : sal_uInt16 nStyle;
786 :
787 0 : if( aInRect.Right() < aInRect.Left() || aInRect.Bottom() < aInRect.Top() )
788 0 : aInRect.SetEmpty();
789 :
790 0 : pDev->Push( PUSH_CLIPREGION );
791 0 : pDev->IntersectClipRegion( aInRect );
792 :
793 0 : if ( nDrawFlags & WINDOW_DRAW_MONO )
794 0 : aColor = Color( COL_BLACK );
795 0 : else if( (nDrawFlags & WINDOW_DRAW_ROLLOVER) && IsNativeControlSupported(CTRL_PUSHBUTTON, PART_ENTIRE_CONTROL) )
796 0 : aColor = rStyleSettings.GetButtonRolloverTextColor();
797 0 : else if ( IsControlForeground() )
798 0 : aColor = GetControlForeground();
799 0 : else if( nDrawFlags & WINDOW_DRAW_ROLLOVER )
800 0 : aColor = rStyleSettings.GetButtonRolloverTextColor();
801 : else
802 0 : aColor = rStyleSettings.GetButtonTextColor();
803 :
804 0 : pDev->SetTextColor( aColor );
805 :
806 0 : if ( IsEnabled() || (nDrawFlags & WINDOW_DRAW_NODISABLE) )
807 0 : nStyle = 0;
808 : else
809 0 : nStyle = SYMBOL_DRAW_DISABLE;
810 :
811 0 : Size aSize = rRect.GetSize();
812 0 : Point aPos = rRect.TopLeft();
813 :
814 0 : sal_uLong nImageSep = 1 + (pDev->GetTextHeight()-10)/2;
815 0 : if( nImageSep < 1 )
816 0 : nImageSep = 1;
817 0 : if ( mnDDStyle == PUSHBUTTON_DROPDOWN_MENUBUTTON )
818 : {
819 0 : long nSeparatorX = 0;
820 0 : Rectangle aSymbolRect = aInRect;
821 0 : if ( !aText.isEmpty() && ! (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) )
822 : {
823 : // calculate symbol size
824 0 : long nSymbolSize = pDev->GetTextHeight() / 2 + 1;
825 :
826 0 : nSeparatorX = aInRect.Right() - 2*nSymbolSize;
827 0 : aSize.Width() -= 2*nSymbolSize;
828 :
829 : // center symbol rectangle in the separated area
830 0 : aSymbolRect.Right() -= nSymbolSize/2;
831 0 : aSymbolRect.Left() = aSymbolRect.Right() - nSymbolSize;
832 :
833 : ImplDrawAlignedImage( pDev, aPos, aSize, bLayout, nImageSep,
834 0 : nDrawFlags, nTextStyle, NULL, true );
835 : }
836 : else
837 0 : ImplCalcSymbolRect( aSymbolRect );
838 :
839 0 : if( ! bLayout )
840 : {
841 0 : long nDistance = (aSymbolRect.GetHeight() > 10) ? 2 : 1;
842 0 : DecorationView aDecoView( pDev );
843 0 : if( bMenuBtnSep && nSeparatorX > 0 )
844 : {
845 0 : Point aStartPt( nSeparatorX, aSymbolRect.Top()+nDistance );
846 0 : Point aEndPt( nSeparatorX, aSymbolRect.Bottom()-nDistance );
847 0 : aDecoView.DrawSeparator( aStartPt, aEndPt );
848 : }
849 0 : ImplSetSeparatorX( nSeparatorX );
850 :
851 0 : aDecoView.DrawSymbol( aSymbolRect, SYMBOL_SPIN_DOWN, aColor, nStyle );
852 : }
853 :
854 : }
855 : else
856 : {
857 0 : Rectangle aSymbolRect;
858 : ImplDrawAlignedImage( pDev, aPos, aSize, bLayout, nImageSep, nDrawFlags,
859 0 : nTextStyle, IsSymbol() ? &aSymbolRect : NULL, true );
860 :
861 0 : if ( IsSymbol() && ! bLayout )
862 : {
863 0 : DecorationView aDecoView( pDev );
864 0 : aDecoView.DrawSymbol( aSymbolRect, meSymbol, aColor, nStyle );
865 : }
866 :
867 0 : if ( mnDDStyle == PUSHBUTTON_DROPDOWN_TOOLBOX && !bLayout )
868 : {
869 0 : bool bBlack = false;
870 0 : Color aArrowColor( COL_BLACK );
871 :
872 0 : if ( !(nDrawFlags & WINDOW_DRAW_MONO) )
873 : {
874 0 : if ( !IsEnabled() )
875 0 : aArrowColor = rStyleSettings.GetShadowColor();
876 : else
877 : {
878 0 : aArrowColor = Color( COL_LIGHTGREEN );
879 0 : bBlack = true;
880 : }
881 : }
882 :
883 0 : ImplDrawBtnDropDownArrow( pDev, aInRect.Right()-6, aInRect.Top()+1,
884 0 : aArrowColor, bBlack );
885 : }
886 : }
887 :
888 0 : UserDrawEvent aUDEvt( this, aInRect, 0 );
889 0 : UserDraw( aUDEvt );
890 :
891 0 : pDev->Pop(); // restore clipregion
892 0 : }
893 :
894 0 : void PushButton::UserDraw( const UserDrawEvent& )
895 : {
896 0 : }
897 :
898 0 : void PushButton::ImplDrawPushButton( bool bLayout )
899 : {
900 0 : if( !bLayout )
901 0 : HideFocus();
902 :
903 0 : sal_uInt16 nButtonStyle = ImplGetButtonState();
904 0 : Point aPoint;
905 0 : Size aOutSz( GetOutputSizePixel() );
906 0 : Rectangle aRect( aPoint, aOutSz );
907 0 : Rectangle aInRect = aRect;
908 0 : bool bNativeOK = false;
909 :
910 : // adjust style if button should be rendered 'pressed'
911 0 : if ( mbPressed )
912 0 : nButtonStyle |= BUTTON_DRAW_PRESSED;
913 :
914 : // TODO: move this to Window class or make it a member !!!
915 0 : ControlType aCtrlType = 0;
916 0 : switch( GetParent()->GetType() )
917 : {
918 : case WINDOW_LISTBOX:
919 : case WINDOW_MULTILISTBOX:
920 : case WINDOW_TREELISTBOX:
921 0 : aCtrlType = CTRL_LISTBOX;
922 0 : break;
923 :
924 : case WINDOW_COMBOBOX:
925 : case WINDOW_PATTERNBOX:
926 : case WINDOW_NUMERICBOX:
927 : case WINDOW_METRICBOX:
928 : case WINDOW_CURRENCYBOX:
929 : case WINDOW_DATEBOX:
930 : case WINDOW_TIMEBOX:
931 : case WINDOW_LONGCURRENCYBOX:
932 0 : aCtrlType = CTRL_COMBOBOX;
933 0 : break;
934 : default:
935 0 : break;
936 : }
937 :
938 0 : bool bDropDown = ( IsSymbol() && (GetSymbol()==SYMBOL_SPIN_DOWN) && GetText().isEmpty() );
939 :
940 0 : if( bDropDown && (aCtrlType == CTRL_COMBOBOX || aCtrlType == CTRL_LISTBOX ) )
941 : {
942 0 : if( GetParent()->IsNativeControlSupported( aCtrlType, PART_ENTIRE_CONTROL) )
943 : {
944 : // skip painting if the button was already drawn by the theme
945 0 : if( aCtrlType == CTRL_COMBOBOX )
946 : {
947 0 : Edit* pEdit = static_cast<Edit*>(GetParent());
948 0 : if( pEdit->ImplUseNativeBorder( pEdit->GetStyle() ) )
949 0 : bNativeOK = true;
950 : }
951 0 : else if( GetParent()->IsNativeControlSupported( aCtrlType, HAS_BACKGROUND_TEXTURE) )
952 : {
953 0 : bNativeOK = true;
954 : }
955 0 : if( !bNativeOK && GetParent()->IsNativeControlSupported( aCtrlType, PART_BUTTON_DOWN ) )
956 : {
957 : // let the theme draw it, note we then need support
958 : // for CTRL_LISTBOX/PART_BUTTON_DOWN and CTRL_COMBOBOX/PART_BUTTON_DOWN
959 :
960 0 : ImplControlValue aControlValue;
961 0 : ControlState nState = 0;
962 :
963 0 : if ( mbPressed ) nState |= CTRL_STATE_PRESSED;
964 0 : if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED ) nState |= CTRL_STATE_PRESSED;
965 0 : if ( HasFocus() ) nState |= CTRL_STATE_FOCUSED;
966 0 : if ( ImplGetButtonState() & BUTTON_DRAW_DEFAULT ) nState |= CTRL_STATE_DEFAULT;
967 0 : if ( Window::IsEnabled() ) nState |= CTRL_STATE_ENABLED;
968 :
969 0 : if ( IsMouseOver() && aInRect.IsInside( GetPointerPosPixel() ) )
970 0 : nState |= CTRL_STATE_ROLLOVER;
971 :
972 : bNativeOK = DrawNativeControl( aCtrlType, PART_BUTTON_DOWN, aInRect, nState,
973 0 : aControlValue, OUString() );
974 : }
975 : }
976 : }
977 :
978 0 : if( bNativeOK )
979 0 : return;
980 :
981 0 : bool bRollOver = (IsMouseOver() && aInRect.IsInside( GetPointerPosPixel() ));
982 0 : bool bDrawMenuSep = true;
983 0 : if( (GetStyle() & WB_FLATBUTTON) )
984 : {
985 0 : if( ! bRollOver && ! HasFocus() )
986 0 : bDrawMenuSep = false;
987 : }
988 0 : if ( (bNativeOK=IsNativeControlSupported(CTRL_PUSHBUTTON, PART_ENTIRE_CONTROL)) )
989 : {
990 0 : PushButtonValue aControlValue;
991 0 : Rectangle aCtrlRegion( aInRect );
992 0 : ControlState nState = 0;
993 :
994 0 : if ( mbPressed || IsChecked() ) nState |= CTRL_STATE_PRESSED;
995 0 : if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED ) nState |= CTRL_STATE_PRESSED;
996 0 : if ( HasFocus() ) nState |= CTRL_STATE_FOCUSED;
997 0 : if ( ImplGetButtonState() & BUTTON_DRAW_DEFAULT ) nState |= CTRL_STATE_DEFAULT;
998 0 : if ( Window::IsEnabled() ) nState |= CTRL_STATE_ENABLED;
999 :
1000 0 : if ( bRollOver )
1001 0 : nState |= CTRL_STATE_ROLLOVER;
1002 :
1003 0 : if( GetStyle() & WB_BEVELBUTTON )
1004 0 : aControlValue.mbBevelButton = true;
1005 :
1006 : // draw frame into invisible window to have aInRect modified correctly
1007 : // but do not shift the inner rect for pressed buttons (ie remove BUTTON_DRAW_PRESSED)
1008 : // this assumes the theme has enough visual cues to signalize the button was pressed
1009 : //Window aWin( this );
1010 : //ImplDrawPushButtonFrame( &aWin, aInRect, nButtonStyle & ~BUTTON_DRAW_PRESSED );
1011 :
1012 : // looks better this way as symbols were displaced slightly using the above approach
1013 0 : aInRect.Top()+=4;
1014 0 : aInRect.Bottom()-=4;
1015 0 : aInRect.Left()+=4;
1016 0 : aInRect.Right()-=4;
1017 :
1018 : // prepare single line hint (needed on mac to decide between normal push button and
1019 : // rectangular bevel button look)
1020 0 : Size aFontSize( Application::GetSettings().GetStyleSettings().GetPushButtonFont().GetSize() );
1021 0 : aFontSize = LogicToPixel( aFontSize, MapMode( MAP_POINT ) );
1022 0 : Size aInRectSize( LogicToPixel( Size( aInRect.GetWidth(), aInRect.GetHeight() ) ) );
1023 0 : aControlValue.mbSingleLine = (aInRectSize.Height() < 2 * aFontSize.Height() );
1024 :
1025 0 : if( ((nState & CTRL_STATE_ROLLOVER)) || ! (GetStyle() & WB_FLATBUTTON) )
1026 : {
1027 : bNativeOK = DrawNativeControl( CTRL_PUSHBUTTON, PART_ENTIRE_CONTROL, aCtrlRegion, nState,
1028 0 : aControlValue, OUString()/*PushButton::GetText()*/ );
1029 : }
1030 : else
1031 : {
1032 0 : bNativeOK = true;
1033 : }
1034 :
1035 : // draw content using the same aInRect as non-native VCL would do
1036 : ImplDrawPushButtonContent( this,
1037 0 : (nState&CTRL_STATE_ROLLOVER) ? WINDOW_DRAW_ROLLOVER : 0,
1038 0 : aInRect, bLayout, bDrawMenuSep );
1039 :
1040 0 : if ( HasFocus() )
1041 0 : ShowFocus( ImplGetFocusRect() );
1042 : }
1043 :
1044 0 : if ( !bNativeOK )
1045 : {
1046 : // draw PushButtonFrame, aInRect has content size afterwards
1047 0 : if( (GetStyle() & WB_FLATBUTTON) )
1048 : {
1049 0 : Rectangle aTempRect( aInRect );
1050 0 : if( ! bLayout && bRollOver )
1051 0 : ImplDrawPushButtonFrame( this, aTempRect, nButtonStyle );
1052 0 : aInRect.Left() += 2;
1053 0 : aInRect.Top() += 2;
1054 0 : aInRect.Right() -= 2;
1055 0 : aInRect.Bottom() -= 2;
1056 : }
1057 : else
1058 : {
1059 0 : if( ! bLayout )
1060 0 : ImplDrawPushButtonFrame( this, aInRect, nButtonStyle );
1061 : }
1062 :
1063 : // draw content
1064 0 : ImplDrawPushButtonContent( this, 0, aInRect, bLayout, bDrawMenuSep );
1065 :
1066 0 : if( ! bLayout && HasFocus() )
1067 : {
1068 0 : ShowFocus( ImplGetFocusRect() );
1069 : }
1070 : }
1071 : }
1072 :
1073 0 : void PushButton::ImplSetDefButton( bool bSet )
1074 : {
1075 0 : Size aSize( GetSizePixel() );
1076 0 : Point aPos( GetPosPixel() );
1077 0 : int dLeft(0), dRight(0), dTop(0), dBottom(0);
1078 0 : bool bSetPos = false;
1079 :
1080 0 : if ( IsNativeControlSupported(CTRL_PUSHBUTTON, PART_ENTIRE_CONTROL) )
1081 : {
1082 0 : Rectangle aBound, aCont;
1083 0 : Rectangle aCtrlRect( 0, 0, 80, 20 ); // use a constant size to avoid accumulating
1084 : // will not work if the theme has dynamic adornment sizes
1085 0 : ImplControlValue aControlValue;
1086 0 : Rectangle aCtrlRegion( aCtrlRect );
1087 0 : ControlState nState = CTRL_STATE_DEFAULT|CTRL_STATE_ENABLED;
1088 :
1089 : // get native size of a 'default' button
1090 : // and adjust the VCL button if more space for adornment is required
1091 0 : if( GetNativeControlRegion( CTRL_PUSHBUTTON, PART_ENTIRE_CONTROL, aCtrlRegion,
1092 : nState, aControlValue, OUString(),
1093 0 : aBound, aCont ) )
1094 : {
1095 0 : dLeft = aCont.Left() - aBound.Left();
1096 0 : dTop = aCont.Top() - aBound.Top();
1097 0 : dRight = aBound.Right() - aCont.Right();
1098 0 : dBottom = aBound.Bottom() - aCont.Bottom();
1099 0 : bSetPos = dLeft || dTop || dRight || dBottom;
1100 0 : }
1101 : }
1102 :
1103 0 : if ( bSet )
1104 : {
1105 0 : if( !(ImplGetButtonState() & BUTTON_DRAW_DEFAULT) && bSetPos )
1106 : {
1107 : // adjust pos/size when toggling from non-default to default
1108 0 : aPos.Move(-dLeft, -dTop);
1109 0 : aSize.Width() += dLeft + dRight;
1110 0 : aSize.Height() += dTop + dBottom;
1111 : }
1112 0 : ImplGetButtonState() |= BUTTON_DRAW_DEFAULT;
1113 : }
1114 : else
1115 : {
1116 0 : if( (ImplGetButtonState() & BUTTON_DRAW_DEFAULT) && bSetPos )
1117 : {
1118 : // adjust pos/size when toggling from default to non-default
1119 0 : aPos.Move(dLeft, dTop);
1120 0 : aSize.Width() -= dLeft + dRight;
1121 0 : aSize.Height() -= dTop + dBottom;
1122 : }
1123 0 : ImplGetButtonState() &= ~BUTTON_DRAW_DEFAULT;
1124 : }
1125 0 : if( bSetPos )
1126 0 : setPosSizePixel( aPos.X(), aPos.Y(), aSize.Width(), aSize.Height(), WINDOW_POSSIZE_ALL );
1127 :
1128 0 : Invalidate();
1129 0 : }
1130 :
1131 0 : bool PushButton::ImplIsDefButton() const
1132 : {
1133 0 : return (ImplGetButtonState() & BUTTON_DRAW_DEFAULT) != 0;
1134 : }
1135 :
1136 0 : PushButton::PushButton( WindowType nType ) :
1137 0 : Button( nType )
1138 : {
1139 0 : ImplInitPushButtonData();
1140 0 : }
1141 :
1142 0 : PushButton::PushButton( Window* pParent, WinBits nStyle ) :
1143 0 : Button( WINDOW_PUSHBUTTON )
1144 : {
1145 0 : ImplInitPushButtonData();
1146 0 : ImplInit( pParent, nStyle );
1147 0 : }
1148 :
1149 0 : PushButton::PushButton( Window* pParent, const ResId& rResId ) :
1150 0 : Button( WINDOW_PUSHBUTTON )
1151 : {
1152 0 : rResId.SetRT( RSC_PUSHBUTTON );
1153 0 : WinBits nStyle = ImplInitRes( rResId );
1154 0 : ImplInitPushButtonData();
1155 0 : ImplInit( pParent, nStyle );
1156 0 : ImplLoadRes( rResId );
1157 :
1158 0 : if ( !(nStyle & WB_HIDE) )
1159 0 : Show();
1160 0 : }
1161 :
1162 0 : PushButton::~PushButton()
1163 : {
1164 0 : }
1165 :
1166 0 : void PushButton::MouseButtonDown( const MouseEvent& rMEvt )
1167 : {
1168 0 : if ( rMEvt.IsLeft() &&
1169 0 : ImplHitTestPushButton( this, rMEvt.GetPosPixel() ) )
1170 : {
1171 0 : sal_uInt16 nTrackFlags = 0;
1172 :
1173 0 : if ( ( GetStyle() & WB_REPEAT ) &&
1174 0 : ! ( GetStyle() & WB_TOGGLE ) )
1175 0 : nTrackFlags |= STARTTRACK_BUTTONREPEAT;
1176 :
1177 0 : ImplGetButtonState() |= BUTTON_DRAW_PRESSED;
1178 0 : ImplDrawPushButton();
1179 0 : StartTracking( nTrackFlags );
1180 :
1181 0 : if ( nTrackFlags & STARTTRACK_BUTTONREPEAT )
1182 0 : Click();
1183 : }
1184 0 : }
1185 :
1186 0 : void PushButton::Tracking( const TrackingEvent& rTEvt )
1187 : {
1188 0 : if ( rTEvt.IsTrackingEnded() )
1189 : {
1190 0 : if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED )
1191 : {
1192 0 : if ( !(GetStyle() & WB_NOPOINTERFOCUS) && !rTEvt.IsTrackingCanceled() )
1193 0 : GrabFocus();
1194 :
1195 0 : if ( GetStyle() & WB_TOGGLE )
1196 : {
1197 : // Don't toggle, when aborted
1198 0 : if ( !rTEvt.IsTrackingCanceled() )
1199 : {
1200 0 : if ( IsChecked() )
1201 : {
1202 0 : Check( false );
1203 0 : ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
1204 : }
1205 : else
1206 0 : Check( true );
1207 : }
1208 : }
1209 : else
1210 0 : ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
1211 :
1212 0 : ImplDrawPushButton();
1213 :
1214 : // do not call Click handler if aborted
1215 0 : if ( !rTEvt.IsTrackingCanceled() )
1216 : {
1217 0 : if ( ! ( ( GetStyle() & WB_REPEAT ) &&
1218 0 : ! ( GetStyle() & WB_TOGGLE ) ) )
1219 0 : Click();
1220 : }
1221 : }
1222 : }
1223 : else
1224 : {
1225 0 : if ( ImplHitTestPushButton( this, rTEvt.GetMouseEvent().GetPosPixel() ) )
1226 : {
1227 0 : if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED )
1228 : {
1229 0 : if ( rTEvt.IsTrackingRepeat() && (GetStyle() & WB_REPEAT) &&
1230 0 : ! ( GetStyle() & WB_TOGGLE ) )
1231 0 : Click();
1232 : }
1233 : else
1234 : {
1235 0 : ImplGetButtonState() |= BUTTON_DRAW_PRESSED;
1236 0 : ImplDrawPushButton();
1237 : }
1238 : }
1239 : else
1240 : {
1241 0 : if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED )
1242 : {
1243 0 : ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
1244 0 : ImplDrawPushButton();
1245 : }
1246 : }
1247 : }
1248 0 : }
1249 :
1250 0 : void PushButton::KeyInput( const KeyEvent& rKEvt )
1251 : {
1252 0 : KeyCode aKeyCode = rKEvt.GetKeyCode();
1253 :
1254 0 : if ( !aKeyCode.GetModifier() &&
1255 0 : ((aKeyCode.GetCode() == KEY_RETURN) || (aKeyCode.GetCode() == KEY_SPACE)) )
1256 : {
1257 0 : if ( !(ImplGetButtonState() & BUTTON_DRAW_PRESSED) )
1258 : {
1259 0 : ImplGetButtonState() |= BUTTON_DRAW_PRESSED;
1260 0 : ImplDrawPushButton();
1261 : }
1262 :
1263 0 : if ( ( GetStyle() & WB_REPEAT ) &&
1264 0 : ! ( GetStyle() & WB_TOGGLE ) )
1265 0 : Click();
1266 : }
1267 0 : else if ( (ImplGetButtonState() & BUTTON_DRAW_PRESSED) && (aKeyCode.GetCode() == KEY_ESCAPE) )
1268 : {
1269 0 : ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
1270 0 : ImplDrawPushButton();
1271 : }
1272 : else
1273 0 : Button::KeyInput( rKEvt );
1274 0 : }
1275 :
1276 0 : void PushButton::KeyUp( const KeyEvent& rKEvt )
1277 : {
1278 0 : KeyCode aKeyCode = rKEvt.GetKeyCode();
1279 :
1280 0 : if ( (ImplGetButtonState() & BUTTON_DRAW_PRESSED) &&
1281 0 : ((aKeyCode.GetCode() == KEY_RETURN) || (aKeyCode.GetCode() == KEY_SPACE)) )
1282 : {
1283 0 : if ( GetStyle() & WB_TOGGLE )
1284 : {
1285 0 : if ( IsChecked() )
1286 : {
1287 0 : Check( false );
1288 0 : ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
1289 : }
1290 : else
1291 0 : Check( true );
1292 :
1293 0 : Toggle();
1294 : }
1295 : else
1296 0 : ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
1297 :
1298 0 : ImplDrawPushButton();
1299 :
1300 0 : if ( !( ( GetStyle() & WB_REPEAT ) &&
1301 0 : ! ( GetStyle() & WB_TOGGLE ) ) )
1302 0 : Click();
1303 : }
1304 : else
1305 0 : Button::KeyUp( rKEvt );
1306 0 : }
1307 :
1308 0 : void PushButton::FillLayoutData() const
1309 : {
1310 0 : mpControlData->mpLayoutData = new vcl::ControlLayoutData();
1311 0 : const_cast<PushButton*>(this)->ImplDrawPushButton( true );
1312 0 : }
1313 :
1314 0 : void PushButton::Paint( const Rectangle& )
1315 : {
1316 0 : ImplDrawPushButton();
1317 0 : }
1318 :
1319 0 : void PushButton::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize,
1320 : sal_uLong nFlags )
1321 : {
1322 0 : Point aPos = pDev->LogicToPixel( rPos );
1323 0 : Size aSize = pDev->LogicToPixel( rSize );
1324 0 : Rectangle aRect( aPos, aSize );
1325 0 : Font aFont = GetDrawPixelFont( pDev );
1326 :
1327 0 : pDev->Push();
1328 0 : pDev->SetMapMode();
1329 0 : pDev->SetFont( aFont );
1330 0 : if ( nFlags & WINDOW_DRAW_MONO )
1331 : {
1332 0 : pDev->SetTextColor( Color( COL_BLACK ) );
1333 : }
1334 : else
1335 : {
1336 0 : pDev->SetTextColor( GetTextColor() );
1337 :
1338 : // DecoView uses the FaceColor...
1339 0 : AllSettings aSettings = pDev->GetSettings();
1340 0 : StyleSettings aStyleSettings = aSettings.GetStyleSettings();
1341 0 : if ( IsControlBackground() )
1342 0 : aStyleSettings.SetFaceColor( GetControlBackground() );
1343 : else
1344 0 : aStyleSettings.SetFaceColor( GetSettings().GetStyleSettings().GetFaceColor() );
1345 0 : aSettings.SetStyleSettings( aStyleSettings );
1346 0 : pDev->OutputDevice::SetSettings( aSettings );
1347 : }
1348 0 : pDev->SetTextFillColor();
1349 :
1350 0 : DecorationView aDecoView( pDev );
1351 0 : sal_uInt16 nButtonStyle = 0;
1352 0 : if ( nFlags & WINDOW_DRAW_MONO )
1353 0 : nButtonStyle |= BUTTON_DRAW_MONO;
1354 0 : if ( IsChecked() )
1355 0 : nButtonStyle |= BUTTON_DRAW_CHECKED;
1356 0 : aRect = aDecoView.DrawButton( aRect, nButtonStyle );
1357 :
1358 0 : ImplDrawPushButtonContent( pDev, nFlags, aRect, false, true );
1359 0 : pDev->Pop();
1360 0 : }
1361 :
1362 0 : void PushButton::Resize()
1363 : {
1364 0 : Control::Resize();
1365 0 : Invalidate();
1366 0 : }
1367 :
1368 0 : void PushButton::GetFocus()
1369 : {
1370 0 : ShowFocus( ImplGetFocusRect() );
1371 0 : SetInputContext( InputContext( GetFont() ) );
1372 0 : Button::GetFocus();
1373 0 : }
1374 :
1375 0 : void PushButton::LoseFocus()
1376 : {
1377 0 : EndSelection();
1378 0 : HideFocus();
1379 0 : Button::LoseFocus();
1380 0 : }
1381 :
1382 0 : void PushButton::StateChanged( StateChangedType nType )
1383 : {
1384 0 : Button::StateChanged( nType );
1385 :
1386 0 : if ( (nType == STATE_CHANGE_ENABLE) ||
1387 0 : (nType == STATE_CHANGE_TEXT) ||
1388 0 : (nType == STATE_CHANGE_IMAGE) ||
1389 0 : (nType == STATE_CHANGE_DATA) ||
1390 0 : (nType == STATE_CHANGE_STATE) ||
1391 : (nType == STATE_CHANGE_UPDATEMODE) )
1392 : {
1393 0 : if ( IsReallyVisible() && IsUpdateMode() )
1394 0 : Invalidate();
1395 : }
1396 0 : else if ( nType == STATE_CHANGE_STYLE )
1397 : {
1398 0 : SetStyle( ImplInitStyle( GetWindow( WINDOW_PREV ), GetStyle() ) );
1399 :
1400 0 : bool bIsDefButton = ( GetStyle() & WB_DEFBUTTON ) != 0;
1401 0 : bool bWasDefButton = ( GetPrevStyle() & WB_DEFBUTTON ) != 0;
1402 0 : if ( bIsDefButton != bWasDefButton )
1403 0 : ImplSetDefButton( bIsDefButton );
1404 :
1405 0 : if ( IsReallyVisible() && IsUpdateMode() )
1406 : {
1407 0 : if ( (GetPrevStyle() & PUSHBUTTON_VIEW_STYLE) !=
1408 0 : (GetStyle() & PUSHBUTTON_VIEW_STYLE) )
1409 0 : Invalidate();
1410 : }
1411 : }
1412 0 : else if ( (nType == STATE_CHANGE_ZOOM) ||
1413 : (nType == STATE_CHANGE_CONTROLFONT) )
1414 : {
1415 0 : ImplInitSettings( true, false, false );
1416 0 : Invalidate();
1417 : }
1418 0 : else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
1419 : {
1420 0 : ImplInitSettings( false, true, false );
1421 0 : Invalidate();
1422 : }
1423 0 : else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
1424 : {
1425 0 : ImplInitSettings( false, false, true );
1426 0 : Invalidate();
1427 : }
1428 0 : }
1429 :
1430 0 : void PushButton::DataChanged( const DataChangedEvent& rDCEvt )
1431 : {
1432 0 : Button::DataChanged( rDCEvt );
1433 :
1434 0 : if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
1435 0 : (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
1436 0 : ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
1437 0 : (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
1438 : {
1439 0 : ImplInitSettings( true, true, true );
1440 0 : Invalidate();
1441 : }
1442 0 : }
1443 :
1444 0 : bool PushButton::PreNotify( NotifyEvent& rNEvt )
1445 : {
1446 0 : const MouseEvent* pMouseEvt = NULL;
1447 :
1448 0 : if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL )
1449 : {
1450 0 : if( pMouseEvt->IsEnterWindow() || pMouseEvt->IsLeaveWindow() )
1451 : {
1452 : // trigger redraw as mouse over state has changed
1453 :
1454 : // TODO: move this to Window class or make it a member !!!
1455 0 : ControlType aCtrlType = 0;
1456 0 : switch( GetParent()->GetType() )
1457 : {
1458 : case WINDOW_LISTBOX:
1459 : case WINDOW_MULTILISTBOX:
1460 : case WINDOW_TREELISTBOX:
1461 0 : aCtrlType = CTRL_LISTBOX;
1462 0 : break;
1463 :
1464 : case WINDOW_COMBOBOX:
1465 : case WINDOW_PATTERNBOX:
1466 : case WINDOW_NUMERICBOX:
1467 : case WINDOW_METRICBOX:
1468 : case WINDOW_CURRENCYBOX:
1469 : case WINDOW_DATEBOX:
1470 : case WINDOW_TIMEBOX:
1471 : case WINDOW_LONGCURRENCYBOX:
1472 0 : aCtrlType = CTRL_COMBOBOX;
1473 0 : break;
1474 : default:
1475 0 : break;
1476 : }
1477 :
1478 0 : bool bDropDown = ( IsSymbol() && (GetSymbol()==SYMBOL_SPIN_DOWN) && GetText().isEmpty() );
1479 :
1480 0 : if( bDropDown && GetParent()->IsNativeControlSupported( aCtrlType, PART_ENTIRE_CONTROL) &&
1481 0 : !GetParent()->IsNativeControlSupported( aCtrlType, PART_BUTTON_DOWN) )
1482 : {
1483 0 : Window *pBorder = GetParent()->GetWindow( WINDOW_BORDER );
1484 0 : if(aCtrlType == CTRL_COMBOBOX)
1485 : {
1486 : // only paint the button part to avoid flickering of the combobox text
1487 0 : Point aPt;
1488 0 : Rectangle aClipRect( aPt, GetOutputSizePixel() );
1489 0 : aClipRect.SetPos(pBorder->ScreenToOutputPixel(OutputToScreenPixel(aClipRect.TopLeft())));
1490 0 : pBorder->Invalidate( aClipRect );
1491 : }
1492 : else
1493 : {
1494 0 : pBorder->Invalidate( INVALIDATE_NOERASE );
1495 0 : pBorder->Update();
1496 : }
1497 : }
1498 0 : else if( (GetStyle() & WB_FLATBUTTON) ||
1499 0 : IsNativeControlSupported(CTRL_PUSHBUTTON, PART_ENTIRE_CONTROL) )
1500 : {
1501 0 : Invalidate();
1502 : }
1503 : }
1504 : }
1505 :
1506 0 : return Button::PreNotify(rNEvt);
1507 : }
1508 :
1509 0 : void PushButton::Toggle()
1510 : {
1511 0 : ImplCallEventListenersAndHandler( VCLEVENT_PUSHBUTTON_TOGGLE, maToggleHdl, this );
1512 0 : }
1513 :
1514 0 : void PushButton::SetSymbol( SymbolType eSymbol )
1515 : {
1516 0 : if ( meSymbol != eSymbol )
1517 : {
1518 0 : meSymbol = eSymbol;
1519 0 : StateChanged( STATE_CHANGE_DATA );
1520 : }
1521 0 : }
1522 :
1523 0 : void PushButton::SetSymbolAlign( SymbolAlign eAlign )
1524 : {
1525 0 : ImplSetSymbolAlign( eAlign );
1526 0 : }
1527 :
1528 0 : void PushButton::SetDropDown( sal_uInt16 nStyle )
1529 : {
1530 0 : if ( mnDDStyle != nStyle )
1531 : {
1532 0 : mnDDStyle = nStyle;
1533 0 : StateChanged( STATE_CHANGE_DATA );
1534 : }
1535 0 : }
1536 :
1537 0 : void PushButton::SetState( TriState eState )
1538 : {
1539 0 : if ( meState != eState )
1540 : {
1541 0 : meState = eState;
1542 0 : if ( meState == TRISTATE_FALSE )
1543 0 : ImplGetButtonState() &= ~(BUTTON_DRAW_CHECKED | BUTTON_DRAW_DONTKNOW);
1544 0 : else if ( meState == TRISTATE_TRUE )
1545 : {
1546 0 : ImplGetButtonState() &= ~BUTTON_DRAW_DONTKNOW;
1547 0 : ImplGetButtonState() |= BUTTON_DRAW_CHECKED;
1548 : }
1549 : else // TRISTATE_INDET
1550 : {
1551 0 : ImplGetButtonState() &= ~BUTTON_DRAW_CHECKED;
1552 0 : ImplGetButtonState() |= BUTTON_DRAW_DONTKNOW;
1553 : }
1554 :
1555 0 : StateChanged( STATE_CHANGE_STATE );
1556 0 : Toggle();
1557 : }
1558 0 : }
1559 :
1560 0 : void PushButton::SetPressed( bool bPressed )
1561 : {
1562 0 : if ( mbPressed != bPressed )
1563 : {
1564 0 : mbPressed = bPressed;
1565 0 : StateChanged( STATE_CHANGE_DATA );
1566 : }
1567 0 : }
1568 :
1569 0 : void PushButton::EndSelection()
1570 : {
1571 0 : EndTracking( ENDTRACK_CANCEL );
1572 0 : if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED )
1573 : {
1574 0 : ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
1575 0 : if ( !mbPressed )
1576 0 : ImplDrawPushButton();
1577 : }
1578 0 : }
1579 :
1580 0 : Size PushButton::CalcMinimumSize( long nMaxWidth ) const
1581 : {
1582 0 : Size aSize;
1583 :
1584 0 : if ( IsSymbol() )
1585 : {
1586 0 : if ( IsSmallSymbol ())
1587 0 : aSize = Size( 16, 12 );
1588 : else
1589 0 : aSize = Size( 26, 24 );
1590 : }
1591 0 : else if ( IsImage() && ! (ImplGetButtonState() & BUTTON_DRAW_NOIMAGE) )
1592 0 : aSize = GetModeImage().GetSizePixel();
1593 0 : if( mnDDStyle == PUSHBUTTON_DROPDOWN_MENUBUTTON )
1594 : {
1595 0 : long nSymbolSize = GetTextHeight() / 2 + 1;
1596 0 : aSize.Width() += 2*nSymbolSize;
1597 : }
1598 0 : if ( !PushButton::GetText().isEmpty() && ! (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) )
1599 : {
1600 0 : sal_uLong nDrawFlags = 0;
1601 : Size textSize = GetTextRect( Rectangle( Point(), Size( nMaxWidth ? nMaxWidth : 0x7fffffff, 0x7fffffff ) ),
1602 0 : PushButton::GetText(), ImplGetTextStyle( nDrawFlags ) ).GetSize();
1603 0 : aSize.Width() += textSize.Width();
1604 0 : aSize.Height() = std::max( aSize.Height(), long( textSize.Height() * 1.15 ) );
1605 : }
1606 :
1607 : // cf. ImplDrawPushButton ...
1608 0 : if( (GetStyle() & WB_SMALLSTYLE) == 0 )
1609 : {
1610 0 : aSize.Width() += 24;
1611 0 : aSize.Height() += 12;
1612 : }
1613 :
1614 0 : return CalcWindowSize( aSize );
1615 : }
1616 :
1617 0 : Size PushButton::GetOptimalSize() const
1618 : {
1619 0 : return CalcMinimumSize();
1620 : }
1621 :
1622 0 : bool PushButton::set_property(const OString &rKey, const OString &rValue)
1623 : {
1624 0 : if (rKey == "has-default")
1625 : {
1626 0 : WinBits nBits = GetStyle();
1627 0 : nBits &= ~(WB_DEFBUTTON);
1628 0 : if (toBool(rValue))
1629 0 : nBits |= WB_DEFBUTTON;
1630 0 : SetStyle(nBits);
1631 : }
1632 : else
1633 0 : return Button::set_property(rKey, rValue);
1634 0 : return true;
1635 : }
1636 :
1637 0 : void OKButton::ImplInit( Window* pParent, WinBits nStyle )
1638 : {
1639 0 : PushButton::ImplInit( pParent, nStyle );
1640 :
1641 0 : SetText( Button::GetStandardText( BUTTON_OK ) );
1642 0 : }
1643 :
1644 0 : OKButton::OKButton( Window* pParent, WinBits nStyle ) :
1645 0 : PushButton( WINDOW_OKBUTTON )
1646 : {
1647 0 : ImplInit( pParent, nStyle );
1648 0 : }
1649 :
1650 0 : OKButton::OKButton( Window* pParent, const ResId& rResId ) :
1651 0 : PushButton( WINDOW_OKBUTTON )
1652 : {
1653 0 : rResId.SetRT( RSC_OKBUTTON );
1654 0 : WinBits nStyle = ImplInitRes( rResId );
1655 0 : ImplInit( pParent, nStyle );
1656 0 : ImplLoadRes( rResId );
1657 :
1658 0 : if ( !(nStyle & WB_HIDE) )
1659 0 : Show();
1660 0 : }
1661 :
1662 0 : void OKButton::Click()
1663 : {
1664 : // close parent if no link set
1665 0 : if ( !GetClickHdl() )
1666 : {
1667 0 : Window* pParent = getNonLayoutParent(this);
1668 0 : if ( pParent->IsSystemWindow() )
1669 : {
1670 0 : if ( pParent->IsDialog() )
1671 : {
1672 0 : if ( ((Dialog*)pParent)->IsInExecute() )
1673 0 : ((Dialog*)pParent)->EndDialog( RET_OK );
1674 : // prevent recursive calls
1675 0 : else if ( !((Dialog*)pParent)->IsInClose() )
1676 : {
1677 0 : if ( pParent->GetStyle() & WB_CLOSEABLE )
1678 0 : ((Dialog*)pParent)->Close();
1679 : }
1680 : }
1681 : else
1682 : {
1683 0 : if ( pParent->GetStyle() & WB_CLOSEABLE )
1684 0 : ((SystemWindow*)pParent)->Close();
1685 : }
1686 : }
1687 : }
1688 : else
1689 : {
1690 0 : PushButton::Click();
1691 : }
1692 0 : }
1693 :
1694 0 : void CancelButton::ImplInit( Window* pParent, WinBits nStyle )
1695 : {
1696 0 : PushButton::ImplInit( pParent, nStyle );
1697 :
1698 0 : SetText( Button::GetStandardText( BUTTON_CANCEL ) );
1699 0 : }
1700 :
1701 0 : CancelButton::CancelButton( Window* pParent, WinBits nStyle ) :
1702 0 : PushButton( WINDOW_CANCELBUTTON )
1703 : {
1704 0 : ImplInit( pParent, nStyle );
1705 0 : }
1706 :
1707 0 : CancelButton::CancelButton( Window* pParent, const ResId& rResId ) :
1708 0 : PushButton( WINDOW_CANCELBUTTON )
1709 : {
1710 0 : rResId.SetRT( RSC_CANCELBUTTON );
1711 0 : WinBits nStyle = ImplInitRes( rResId );
1712 0 : ImplInit( pParent, nStyle );
1713 0 : ImplLoadRes( rResId );
1714 :
1715 0 : if ( !(nStyle & WB_HIDE) )
1716 0 : Show();
1717 0 : }
1718 :
1719 0 : void CancelButton::Click()
1720 : {
1721 : // close parent if link not set
1722 0 : if ( !GetClickHdl() )
1723 : {
1724 0 : Window* pParent = getNonLayoutParent(this);
1725 0 : if ( pParent->IsSystemWindow() )
1726 : {
1727 0 : if ( pParent->IsDialog() )
1728 : {
1729 0 : if ( ((Dialog*)pParent)->IsInExecute() )
1730 0 : ((Dialog*)pParent)->EndDialog( RET_CANCEL );
1731 : // prevent recursive calls
1732 0 : else if ( !((Dialog*)pParent)->IsInClose() )
1733 : {
1734 0 : if ( pParent->GetStyle() & WB_CLOSEABLE )
1735 0 : ((Dialog*)pParent)->Close();
1736 : }
1737 : }
1738 : else
1739 : {
1740 0 : if ( pParent->GetStyle() & WB_CLOSEABLE )
1741 0 : ((SystemWindow*)pParent)->Close();
1742 : }
1743 : }
1744 : }
1745 : else
1746 : {
1747 0 : PushButton::Click();
1748 : }
1749 0 : }
1750 :
1751 0 : CloseButton::CloseButton( Window* pParent, WinBits nStyle )
1752 0 : : CancelButton(pParent, nStyle)
1753 : {
1754 0 : SetText( Button::GetStandardText( BUTTON_CLOSE ) );
1755 0 : }
1756 :
1757 0 : void HelpButton::ImplInit( Window* pParent, WinBits nStyle )
1758 : {
1759 0 : PushButton::ImplInit( pParent, nStyle | WB_NOPOINTERFOCUS );
1760 :
1761 0 : SetText( Button::GetStandardText( BUTTON_HELP ) );
1762 0 : }
1763 :
1764 0 : HelpButton::HelpButton( Window* pParent, WinBits nStyle ) :
1765 0 : PushButton( WINDOW_HELPBUTTON )
1766 : {
1767 0 : ImplInit( pParent, nStyle );
1768 0 : }
1769 :
1770 0 : HelpButton::HelpButton( Window* pParent, const ResId& rResId ) :
1771 0 : PushButton( WINDOW_HELPBUTTON )
1772 : {
1773 0 : rResId.SetRT( RSC_HELPBUTTON );
1774 0 : WinBits nStyle = ImplInitRes( rResId );
1775 0 : ImplInit( pParent, nStyle );
1776 0 : ImplLoadRes( rResId );
1777 :
1778 0 : if ( !(nStyle & WB_HIDE) )
1779 0 : Show();
1780 0 : }
1781 :
1782 0 : void HelpButton::Click()
1783 : {
1784 : // trigger help if no link set
1785 0 : if ( !GetClickHdl() )
1786 : {
1787 0 : Window* pFocusWin = Application::GetFocusWindow();
1788 0 : if ( !pFocusWin )
1789 0 : pFocusWin = this;
1790 :
1791 0 : HelpEvent aEvt( pFocusWin->GetPointerPosPixel(), HELPMODE_CONTEXT );
1792 0 : pFocusWin->RequestHelp( aEvt );
1793 : }
1794 0 : PushButton::Click();
1795 0 : }
1796 :
1797 0 : void RadioButton::ImplInitRadioButtonData()
1798 : {
1799 0 : mbChecked = false;
1800 0 : mbSaveValue = false;
1801 0 : mbRadioCheck = true;
1802 0 : mbStateChanged = false;
1803 0 : }
1804 :
1805 0 : void RadioButton::ImplInit( Window* pParent, WinBits nStyle )
1806 : {
1807 0 : nStyle = ImplInitStyle(getPreviousSibling(pParent), nStyle);
1808 0 : Button::ImplInit( pParent, nStyle, NULL );
1809 :
1810 0 : ImplInitSettings( true, true, true );
1811 0 : }
1812 :
1813 0 : WinBits RadioButton::ImplInitStyle( const Window* pPrevWindow, WinBits nStyle )
1814 : {
1815 0 : if ( !(nStyle & WB_NOGROUP) &&
1816 0 : (!pPrevWindow || (pPrevWindow->GetType() != WINDOW_RADIOBUTTON)) )
1817 0 : nStyle |= WB_GROUP;
1818 0 : if ( !(nStyle & WB_NOTABSTOP) )
1819 : {
1820 0 : if ( IsChecked() )
1821 0 : nStyle |= WB_TABSTOP;
1822 : else
1823 0 : nStyle &= ~WB_TABSTOP;
1824 : }
1825 0 : return nStyle;
1826 : }
1827 :
1828 0 : const Font& RadioButton::GetCanonicalFont( const StyleSettings& _rStyle ) const
1829 : {
1830 0 : return _rStyle.GetRadioCheckFont();
1831 : }
1832 :
1833 0 : const Color& RadioButton::GetCanonicalTextColor( const StyleSettings& _rStyle ) const
1834 : {
1835 0 : return _rStyle.GetRadioCheckTextColor();
1836 : }
1837 :
1838 0 : void RadioButton::ImplInitSettings( bool bFont,
1839 : bool bForeground, bool bBackground )
1840 : {
1841 0 : Button::ImplInitSettings( bFont, bForeground );
1842 :
1843 0 : if ( bBackground )
1844 : {
1845 0 : Window* pParent = GetParent();
1846 0 : if ( !IsControlBackground() &&
1847 0 : (pParent->IsChildTransparentModeEnabled() || IsNativeControlSupported( CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL ) ) )
1848 : {
1849 0 : EnableChildTransparentMode( true );
1850 0 : SetParentClipMode( PARENTCLIPMODE_NOCLIP );
1851 0 : SetPaintTransparent( true );
1852 0 : SetBackground();
1853 0 : if( IsNativeControlSupported( CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL ) )
1854 0 : mpWindowImpl->mbUseNativeFocus = ImplGetSVData()->maNWFData.mbNoFocusRects;
1855 : }
1856 : else
1857 : {
1858 0 : EnableChildTransparentMode( false );
1859 0 : SetParentClipMode( 0 );
1860 0 : SetPaintTransparent( false );
1861 :
1862 0 : if ( IsControlBackground() )
1863 0 : SetBackground( GetControlBackground() );
1864 : else
1865 0 : SetBackground( pParent->GetBackground() );
1866 : }
1867 : }
1868 0 : }
1869 :
1870 0 : void RadioButton::DrawRadioButtonState( )
1871 : {
1872 0 : ImplDrawRadioButtonState( );
1873 0 : }
1874 :
1875 0 : void RadioButton::ImplInvalidateOrDrawRadioButtonState()
1876 : {
1877 0 : if( ImplGetSVData()->maNWFData.mbCheckBoxNeedsErase )
1878 : {
1879 0 : if ( IsNativeControlSupported(CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL) )
1880 : {
1881 0 : Invalidate();
1882 0 : Update();
1883 0 : return;
1884 : }
1885 : }
1886 0 : ImplDrawRadioButtonState();
1887 : }
1888 :
1889 0 : void RadioButton::ImplDrawRadioButtonState()
1890 : {
1891 0 : bool bNativeOK = false;
1892 :
1893 : // no native drawing for image radio buttons
1894 0 : if ( !maImage && (bNativeOK=IsNativeControlSupported(CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL)) )
1895 : {
1896 0 : ImplControlValue aControlValue( mbChecked ? BUTTONVALUE_ON : BUTTONVALUE_OFF );
1897 0 : Rectangle aCtrlRect( maStateRect.TopLeft(), maStateRect.GetSize() );
1898 0 : ControlState nState = 0;
1899 :
1900 0 : if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED ) nState |= CTRL_STATE_PRESSED;
1901 0 : if ( HasFocus() ) nState |= CTRL_STATE_FOCUSED;
1902 0 : if ( ImplGetButtonState() & BUTTON_DRAW_DEFAULT ) nState |= CTRL_STATE_DEFAULT;
1903 0 : if ( IsEnabled() ) nState |= CTRL_STATE_ENABLED;
1904 :
1905 0 : if ( IsMouseOver() && maMouseRect.IsInside( GetPointerPosPixel() ) )
1906 0 : nState |= CTRL_STATE_ROLLOVER;
1907 :
1908 : bNativeOK = DrawNativeControl( CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL, aCtrlRect, nState,
1909 0 : aControlValue,OUString() );
1910 :
1911 : }
1912 :
1913 0 : if ( !bNativeOK )
1914 : {
1915 : // kein Image-RadioButton
1916 0 : if ( !maImage )
1917 : {
1918 0 : sal_uInt16 nStyle = ImplGetButtonState();
1919 0 : if ( !IsEnabled() )
1920 0 : nStyle |= BUTTON_DRAW_DISABLED;
1921 0 : if ( mbChecked )
1922 0 : nStyle |= BUTTON_DRAW_CHECKED;
1923 0 : Image aImage = GetRadioImage( GetSettings(), nStyle );
1924 0 : if ( IsZoom() )
1925 0 : DrawImage( maStateRect.TopLeft(), maStateRect.GetSize(), aImage );
1926 : else
1927 0 : DrawImage( maStateRect.TopLeft(), aImage );
1928 : }
1929 : else
1930 : {
1931 0 : HideFocus();
1932 :
1933 0 : DecorationView aDecoView( this );
1934 0 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1935 0 : Rectangle aImageRect = maStateRect;
1936 0 : Size aImageSize = maImage.GetSizePixel();
1937 0 : bool bEnabled = IsEnabled();
1938 0 : sal_uInt16 nButtonStyle = FRAME_DRAW_DOUBLEIN;
1939 :
1940 0 : aImageSize.Width() = CalcZoom( aImageSize.Width() );
1941 0 : aImageSize.Height() = CalcZoom( aImageSize.Height() );
1942 :
1943 : // display border and selection status
1944 0 : aImageRect = aDecoView.DrawFrame( aImageRect, nButtonStyle );
1945 0 : if ( (ImplGetButtonState() & BUTTON_DRAW_PRESSED) || !bEnabled )
1946 0 : SetFillColor( rStyleSettings.GetFaceColor() );
1947 : else
1948 0 : SetFillColor( rStyleSettings.GetFieldColor() );
1949 0 : SetLineColor();
1950 0 : DrawRect( aImageRect );
1951 :
1952 : // display image
1953 0 : nButtonStyle = 0;
1954 0 : if ( !bEnabled )
1955 0 : nButtonStyle |= IMAGE_DRAW_DISABLE;
1956 :
1957 0 : Image *pImage = &maImage;
1958 :
1959 0 : Point aImagePos( aImageRect.TopLeft() );
1960 0 : aImagePos.X() += (aImageRect.GetWidth()-aImageSize.Width())/2;
1961 0 : aImagePos.Y() += (aImageRect.GetHeight()-aImageSize.Height())/2;
1962 0 : if ( IsZoom() )
1963 0 : DrawImage( aImagePos, aImageSize, *pImage, nButtonStyle );
1964 : else
1965 0 : DrawImage( aImagePos, *pImage, nButtonStyle );
1966 :
1967 0 : aImageRect.Left()++;
1968 0 : aImageRect.Top()++;
1969 0 : aImageRect.Right()--;
1970 0 : aImageRect.Bottom()--;
1971 :
1972 0 : ImplSetFocusRect( aImageRect );
1973 :
1974 0 : if ( mbChecked )
1975 : {
1976 0 : SetLineColor( rStyleSettings.GetHighlightColor() );
1977 0 : SetFillColor();
1978 0 : if ( (aImageSize.Width() >= 20) || (aImageSize.Height() >= 20) )
1979 : {
1980 0 : aImageRect.Left()++;
1981 0 : aImageRect.Top()++;
1982 0 : aImageRect.Right()--;
1983 0 : aImageRect.Bottom()--;
1984 : }
1985 0 : DrawRect( aImageRect );
1986 0 : aImageRect.Left()++;
1987 0 : aImageRect.Top()++;
1988 0 : aImageRect.Right()--;
1989 0 : aImageRect.Bottom()--;
1990 0 : DrawRect( aImageRect );
1991 : }
1992 :
1993 0 : if ( HasFocus() )
1994 0 : ShowFocus( ImplGetFocusRect() );
1995 : }
1996 : }
1997 0 : }
1998 :
1999 0 : void RadioButton::ImplDraw( OutputDevice* pDev, sal_uLong nDrawFlags,
2000 : const Point& rPos, const Size& rSize,
2001 : const Size& rImageSize, Rectangle& rStateRect,
2002 : Rectangle& rMouseRect, bool bLayout )
2003 : {
2004 0 : WinBits nWinStyle = GetStyle();
2005 0 : OUString aText( GetText() );
2006 0 : MetricVector* pVector = bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : NULL;
2007 0 : OUString* pDisplayText = bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : NULL;
2008 :
2009 0 : pDev->Push( PUSH_CLIPREGION );
2010 0 : pDev->IntersectClipRegion( Rectangle( rPos, rSize ) );
2011 :
2012 : // no image radio button
2013 0 : if ( !maImage )
2014 : {
2015 0 : if ( ( !aText.isEmpty() && ! (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) ) ||
2016 0 : ( HasImage() && ! (ImplGetButtonState() & BUTTON_DRAW_NOIMAGE) ) )
2017 : {
2018 0 : sal_uInt16 nTextStyle = Button::ImplGetTextStyle( aText, nWinStyle, nDrawFlags );
2019 :
2020 0 : const long nImageSep = GetDrawPixel( pDev, ImplGetImageToTextDistance() );
2021 0 : Size aSize( rSize );
2022 0 : Point aPos( rPos );
2023 0 : aPos.X() += rImageSize.Width() + nImageSep;
2024 0 : aSize.Width() -= rImageSize.Width() + nImageSep;
2025 :
2026 : // if the text rect height is smaller than the height of the image
2027 : // then for single lines the default should be centered text
2028 0 : if( (nWinStyle & (WB_TOP|WB_VCENTER|WB_BOTTOM)) == 0 &&
2029 0 : (rImageSize.Height() > rSize.Height() || ! (nWinStyle & WB_WORDBREAK) ) )
2030 : {
2031 0 : nTextStyle &= ~(TEXT_DRAW_TOP|TEXT_DRAW_BOTTOM);
2032 0 : nTextStyle |= TEXT_DRAW_VCENTER;
2033 0 : aSize.Height() = rImageSize.Height();
2034 : }
2035 :
2036 : ImplDrawAlignedImage( pDev, aPos, aSize, bLayout, 1,
2037 0 : nDrawFlags, nTextStyle, NULL );
2038 :
2039 0 : rMouseRect = Rectangle( aPos, aSize );
2040 0 : rMouseRect.Left() = rPos.X();
2041 :
2042 0 : rStateRect.Left() = rPos.X();
2043 0 : rStateRect.Top() = rMouseRect.Top();
2044 :
2045 0 : if ( aSize.Height() > rImageSize.Height() )
2046 0 : rStateRect.Top() += ( aSize.Height() - rImageSize.Height() ) / 2;
2047 : else
2048 : {
2049 0 : rStateRect.Top() -= ( rImageSize.Height() - aSize.Height() ) / 2;
2050 0 : if( rStateRect.Top() < 0 )
2051 0 : rStateRect.Top() = 0;
2052 : }
2053 :
2054 0 : rStateRect.Right() = rStateRect.Left() + rImageSize.Width()-1;
2055 0 : rStateRect.Bottom() = rStateRect.Top() + rImageSize.Height()-1;
2056 :
2057 0 : if ( rStateRect.Bottom() > rMouseRect.Bottom() )
2058 0 : rMouseRect.Bottom() = rStateRect.Bottom();
2059 : }
2060 : else
2061 : {
2062 0 : if ( mbLegacyNoTextAlign && ( nWinStyle & WB_CENTER ) )
2063 0 : rStateRect.Left() = rPos.X()+((rSize.Width()-rImageSize.Width())/2);
2064 0 : else if ( mbLegacyNoTextAlign && ( nWinStyle & WB_RIGHT ) )
2065 0 : rStateRect.Left() = rPos.X()+rSize.Width()-rImageSize.Width(); //-1;
2066 : else
2067 0 : rStateRect.Left() = rPos.X(); //+1;
2068 0 : if ( nWinStyle & WB_VCENTER )
2069 0 : rStateRect.Top() = rPos.Y()+((rSize.Height()-rImageSize.Height())/2);
2070 0 : else if ( nWinStyle & WB_BOTTOM )
2071 0 : rStateRect.Top() = rPos.Y()+rSize.Height()-rImageSize.Height(); //-1;
2072 : else
2073 0 : rStateRect.Top() = rPos.Y(); //+1;
2074 0 : rStateRect.Right() = rStateRect.Left()+rImageSize.Width()-1;
2075 0 : rStateRect.Bottom() = rStateRect.Top()+rImageSize.Height()-1;
2076 0 : rMouseRect = rStateRect;
2077 :
2078 0 : ImplSetFocusRect( rStateRect );
2079 :
2080 : /* and above -1 because CalcSize() does not include focus-rectangle since images would be even
2081 : positioned higher in writer
2082 : rFocusRect = rStateRect;
2083 : rFocusRect.Left()--;
2084 : rFocusRect.Top()--;
2085 : rFocusRect.Right()++;
2086 : rFocusRect.Bottom()++;
2087 : */
2088 : }
2089 : }
2090 : else
2091 : {
2092 0 : bool bTopImage = (nWinStyle & WB_TOP) != 0;
2093 0 : Size aImageSize = maImage.GetSizePixel();
2094 0 : Rectangle aImageRect( rPos, rSize );
2095 0 : long nTextHeight = pDev->GetTextHeight();
2096 0 : long nTextWidth = pDev->GetCtrlTextWidth( aText );
2097 :
2098 : // calculate position and sizes
2099 0 : if ( !aText.isEmpty() && ! (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) )
2100 : {
2101 0 : Size aTmpSize( (aImageSize.Width()+8), (aImageSize.Height()+8) );
2102 0 : if ( bTopImage )
2103 : {
2104 0 : aImageRect.Left() = (rSize.Width()-aTmpSize.Width())/2;
2105 0 : aImageRect.Top() = (rSize.Height()-(aTmpSize.Height()+nTextHeight+6))/2;
2106 : }
2107 : else
2108 0 : aImageRect.Top() = (rSize.Height()-aTmpSize.Height())/2;
2109 :
2110 0 : aImageRect.Right() = aImageRect.Left()+aTmpSize.Width();
2111 0 : aImageRect.Bottom() = aImageRect.Top()+aTmpSize.Height();
2112 :
2113 : // display text
2114 0 : Point aTxtPos = rPos;
2115 0 : if ( bTopImage )
2116 : {
2117 0 : aTxtPos.X() += (rSize.Width()-nTextWidth)/2;
2118 0 : aTxtPos.Y() += aImageRect.Bottom()+6;
2119 : }
2120 : else
2121 : {
2122 0 : aTxtPos.X() += aImageRect.Right()+8;
2123 0 : aTxtPos.Y() += (rSize.Height()-nTextHeight)/2;
2124 : }
2125 0 : pDev->DrawCtrlText( aTxtPos, aText, 0, aText.getLength(), TEXT_DRAW_MNEMONIC, pVector, pDisplayText );
2126 : }
2127 :
2128 0 : rMouseRect = aImageRect;
2129 0 : rStateRect = aImageRect;
2130 : }
2131 :
2132 0 : pDev->Pop();
2133 0 : }
2134 :
2135 0 : void RadioButton::ImplDrawRadioButton( bool bLayout )
2136 : {
2137 0 : if( !bLayout )
2138 0 : HideFocus();
2139 :
2140 0 : Size aImageSize;
2141 0 : if ( !maImage )
2142 0 : aImageSize = ImplGetRadioImageSize();
2143 : else
2144 0 : aImageSize = maImage.GetSizePixel();
2145 0 : aImageSize.Width() = CalcZoom( aImageSize.Width() );
2146 0 : aImageSize.Height() = CalcZoom( aImageSize.Height() );
2147 :
2148 : // Draw control text
2149 0 : ImplDraw( this, 0, Point(), GetOutputSizePixel(),
2150 0 : aImageSize, maStateRect, maMouseRect, bLayout );
2151 :
2152 0 : if( !bLayout || IsNativeControlSupported(CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL) )
2153 : {
2154 0 : if ( !maImage && HasFocus() )
2155 0 : ShowFocus( ImplGetFocusRect() );
2156 :
2157 0 : ImplDrawRadioButtonState();
2158 : }
2159 0 : }
2160 :
2161 0 : void RadioButton::group(RadioButton &rOther)
2162 : {
2163 0 : if (&rOther == this)
2164 0 : return;
2165 :
2166 0 : if (!m_xGroup)
2167 : {
2168 0 : m_xGroup.reset(new std::vector<RadioButton*>);
2169 0 : m_xGroup->push_back(this);
2170 : }
2171 :
2172 0 : std::vector<RadioButton*>::iterator aFind = std::find(m_xGroup->begin(), m_xGroup->end(), &rOther);
2173 0 : if (aFind == m_xGroup->end())
2174 : {
2175 0 : m_xGroup->push_back(&rOther);
2176 :
2177 0 : if (rOther.m_xGroup)
2178 : {
2179 0 : std::vector< RadioButton* > aOthers(rOther.GetRadioButtonGroup(false));
2180 : //make all members of the group share the same button group
2181 0 : for (std::vector<RadioButton*>::iterator aI = aOthers.begin(), aEnd = aOthers.end(); aI != aEnd; ++aI)
2182 : {
2183 0 : aFind = std::find(m_xGroup->begin(), m_xGroup->end(), *aI);
2184 0 : if (aFind == m_xGroup->end())
2185 0 : m_xGroup->push_back(*aI);
2186 0 : }
2187 : }
2188 :
2189 : //make all members of the group share the same button group
2190 0 : for (std::vector<RadioButton*>::iterator aI = m_xGroup->begin(), aEnd = m_xGroup->end();
2191 : aI != aEnd; ++aI)
2192 : {
2193 0 : RadioButton* pButton = *aI;
2194 0 : pButton->m_xGroup = m_xGroup;
2195 : }
2196 : }
2197 :
2198 : //if this one is checked, uncheck all the others
2199 0 : if (mbChecked)
2200 0 : ImplUncheckAllOther();
2201 : }
2202 :
2203 0 : std::vector< RadioButton* > RadioButton::GetRadioButtonGroup(bool bIncludeThis) const
2204 : {
2205 0 : if (m_xGroup)
2206 : {
2207 0 : if (bIncludeThis)
2208 0 : return *m_xGroup;
2209 0 : std::vector< RadioButton* > aGroup;
2210 0 : for (std::vector<RadioButton*>::iterator aI = m_xGroup->begin(), aEnd = m_xGroup->end(); aI != aEnd; ++aI)
2211 : {
2212 0 : RadioButton *pRadioButton = *aI;
2213 0 : if (pRadioButton == this)
2214 0 : continue;
2215 0 : aGroup.push_back(pRadioButton);
2216 : }
2217 0 : return aGroup;
2218 : }
2219 :
2220 : //old-school
2221 : SAL_WARN("vcl.control", "No new-style group set on radiobutton <" << GetHelpId() << "> using old-style digging around");
2222 :
2223 : // go back to first in group;
2224 0 : Window* pFirst = const_cast<RadioButton*>(this);
2225 0 : while( ( pFirst->GetStyle() & WB_GROUP ) == 0 )
2226 : {
2227 0 : Window* pWindow = pFirst->GetWindow( WINDOW_PREV );
2228 0 : if( pWindow )
2229 0 : pFirst = pWindow;
2230 : else
2231 0 : break;
2232 : }
2233 0 : std::vector< RadioButton* > aGroup;
2234 : // insert radiobuttons up to next group
2235 0 : do
2236 : {
2237 0 : if( pFirst->GetType() == WINDOW_RADIOBUTTON )
2238 : {
2239 0 : if( pFirst != this || bIncludeThis )
2240 0 : aGroup.push_back( static_cast<RadioButton*>(pFirst) );
2241 : }
2242 0 : pFirst = pFirst->GetWindow( WINDOW_NEXT );
2243 0 : } while( pFirst && ( ( pFirst->GetStyle() & WB_GROUP ) == 0 ) );
2244 :
2245 0 : return aGroup;
2246 : }
2247 :
2248 0 : void RadioButton::ImplUncheckAllOther()
2249 : {
2250 0 : mpWindowImpl->mnStyle |= WB_TABSTOP;
2251 :
2252 0 : std::vector<RadioButton*> aGroup(GetRadioButtonGroup(false));
2253 : // iterate over radio button group and checked buttons
2254 0 : for (std::vector<RadioButton*>::iterator aI = aGroup.begin(), aEnd = aGroup.end(); aI != aEnd; ++aI)
2255 : {
2256 0 : RadioButton *pWindow = *aI;
2257 0 : if ( pWindow->IsChecked() )
2258 : {
2259 0 : ImplDelData aDelData;
2260 0 : pWindow->ImplAddDel( &aDelData );
2261 0 : pWindow->SetState( false );
2262 0 : if ( aDelData.IsDead() )
2263 0 : return;
2264 0 : pWindow->ImplRemoveDel( &aDelData );
2265 : }
2266 :
2267 : // not inside if clause to always remove wrongly set WB_TABSTOPS
2268 0 : pWindow->mpWindowImpl->mnStyle &= ~WB_TABSTOP;
2269 0 : }
2270 : }
2271 :
2272 0 : void RadioButton::ImplCallClick( bool bGrabFocus, sal_uInt16 nFocusFlags )
2273 : {
2274 0 : mbStateChanged = !mbChecked;
2275 0 : mbChecked = true;
2276 0 : mpWindowImpl->mnStyle |= WB_TABSTOP;
2277 0 : ImplInvalidateOrDrawRadioButtonState();
2278 0 : ImplDelData aDelData;
2279 0 : ImplAddDel( &aDelData );
2280 0 : if ( mbRadioCheck )
2281 0 : ImplUncheckAllOther();
2282 0 : if ( aDelData.IsDead() )
2283 0 : return;
2284 0 : if ( bGrabFocus )
2285 0 : ImplGrabFocus( nFocusFlags );
2286 0 : if ( aDelData.IsDead() )
2287 0 : return;
2288 0 : if ( mbStateChanged )
2289 0 : Toggle();
2290 0 : if ( aDelData.IsDead() )
2291 0 : return;
2292 0 : Click();
2293 0 : if ( aDelData.IsDead() )
2294 0 : return;
2295 0 : ImplRemoveDel( &aDelData );
2296 0 : mbStateChanged = false;
2297 : }
2298 :
2299 0 : RadioButton::RadioButton( Window* pParent, WinBits nStyle ) :
2300 0 : Button( WINDOW_RADIOBUTTON ), mbLegacyNoTextAlign( false )
2301 : {
2302 0 : ImplInitRadioButtonData();
2303 0 : ImplInit( pParent, nStyle );
2304 0 : }
2305 :
2306 0 : RadioButton::RadioButton( Window* pParent, const ResId& rResId ) :
2307 0 : Button( WINDOW_RADIOBUTTON ), mbLegacyNoTextAlign( false )
2308 : {
2309 0 : rResId.SetRT( RSC_RADIOBUTTON );
2310 0 : WinBits nStyle = ImplInitRes( rResId );
2311 0 : ImplInitRadioButtonData();
2312 0 : ImplInit( pParent, nStyle );
2313 0 : ImplLoadRes( rResId );
2314 :
2315 0 : if ( !(nStyle & WB_HIDE) )
2316 0 : Show();
2317 0 : }
2318 :
2319 0 : void RadioButton::ImplLoadRes( const ResId& rResId )
2320 : {
2321 0 : Button::ImplLoadRes( rResId );
2322 :
2323 : //anderer Wert als Default ?
2324 0 : sal_uInt16 nChecked = ReadShortRes();
2325 0 : if ( nChecked )
2326 0 : SetState( true );
2327 0 : }
2328 :
2329 0 : RadioButton::~RadioButton()
2330 : {
2331 0 : if (m_xGroup)
2332 : {
2333 : m_xGroup->erase(std::remove(m_xGroup->begin(), m_xGroup->end(), this),
2334 0 : m_xGroup->end());
2335 : }
2336 0 : }
2337 :
2338 0 : void RadioButton::MouseButtonDown( const MouseEvent& rMEvt )
2339 : {
2340 0 : if ( rMEvt.IsLeft() && maMouseRect.IsInside( rMEvt.GetPosPixel() ) )
2341 : {
2342 0 : ImplGetButtonState() |= BUTTON_DRAW_PRESSED;
2343 0 : ImplInvalidateOrDrawRadioButtonState();
2344 0 : StartTracking();
2345 0 : return;
2346 : }
2347 :
2348 0 : Button::MouseButtonDown( rMEvt );
2349 : }
2350 :
2351 0 : void RadioButton::Tracking( const TrackingEvent& rTEvt )
2352 : {
2353 0 : if ( rTEvt.IsTrackingEnded() )
2354 : {
2355 0 : if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED )
2356 : {
2357 0 : if ( !(GetStyle() & WB_NOPOINTERFOCUS) && !rTEvt.IsTrackingCanceled() )
2358 0 : GrabFocus();
2359 :
2360 0 : ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
2361 :
2362 : // do not call click handler if aborted
2363 0 : if ( !rTEvt.IsTrackingCanceled() )
2364 0 : ImplCallClick();
2365 : else
2366 0 : ImplInvalidateOrDrawRadioButtonState();
2367 : }
2368 : }
2369 : else
2370 : {
2371 0 : if ( maMouseRect.IsInside( rTEvt.GetMouseEvent().GetPosPixel() ) )
2372 : {
2373 0 : if ( !(ImplGetButtonState() & BUTTON_DRAW_PRESSED) )
2374 : {
2375 0 : ImplGetButtonState() |= BUTTON_DRAW_PRESSED;
2376 0 : ImplInvalidateOrDrawRadioButtonState();
2377 : }
2378 : }
2379 : else
2380 : {
2381 0 : if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED )
2382 : {
2383 0 : ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
2384 0 : ImplInvalidateOrDrawRadioButtonState();
2385 : }
2386 : }
2387 : }
2388 0 : }
2389 :
2390 0 : void RadioButton::KeyInput( const KeyEvent& rKEvt )
2391 : {
2392 0 : KeyCode aKeyCode = rKEvt.GetKeyCode();
2393 :
2394 0 : if ( !aKeyCode.GetModifier() && (aKeyCode.GetCode() == KEY_SPACE) )
2395 : {
2396 0 : if ( !(ImplGetButtonState() & BUTTON_DRAW_PRESSED) )
2397 : {
2398 0 : ImplGetButtonState() |= BUTTON_DRAW_PRESSED;
2399 0 : ImplInvalidateOrDrawRadioButtonState();
2400 : }
2401 : }
2402 0 : else if ( (ImplGetButtonState() & BUTTON_DRAW_PRESSED) && (aKeyCode.GetCode() == KEY_ESCAPE) )
2403 : {
2404 0 : ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
2405 0 : ImplInvalidateOrDrawRadioButtonState();
2406 : }
2407 : else
2408 0 : Button::KeyInput( rKEvt );
2409 0 : }
2410 :
2411 0 : void RadioButton::KeyUp( const KeyEvent& rKEvt )
2412 : {
2413 0 : KeyCode aKeyCode = rKEvt.GetKeyCode();
2414 :
2415 0 : if ( (ImplGetButtonState() & BUTTON_DRAW_PRESSED) && (aKeyCode.GetCode() == KEY_SPACE) )
2416 : {
2417 0 : ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
2418 0 : ImplCallClick();
2419 : }
2420 : else
2421 0 : Button::KeyUp( rKEvt );
2422 0 : }
2423 :
2424 0 : void RadioButton::FillLayoutData() const
2425 : {
2426 0 : mpControlData->mpLayoutData = new vcl::ControlLayoutData();
2427 0 : const_cast<RadioButton*>(this)->ImplDrawRadioButton( true );
2428 0 : }
2429 :
2430 0 : void RadioButton::Paint( const Rectangle& )
2431 : {
2432 0 : ImplDrawRadioButton();
2433 0 : }
2434 :
2435 0 : void RadioButton::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize,
2436 : sal_uLong nFlags )
2437 : {
2438 0 : if ( !maImage )
2439 : {
2440 0 : MapMode aResMapMode( MAP_100TH_MM );
2441 0 : Point aPos = pDev->LogicToPixel( rPos );
2442 0 : Size aSize = pDev->LogicToPixel( rSize );
2443 0 : Size aImageSize = pDev->LogicToPixel( Size( 300, 300 ), aResMapMode );
2444 0 : Size aBrd1Size = pDev->LogicToPixel( Size( 20, 20 ), aResMapMode );
2445 0 : Size aBrd2Size = pDev->LogicToPixel( Size( 60, 60 ), aResMapMode );
2446 0 : Font aFont = GetDrawPixelFont( pDev );
2447 0 : Rectangle aStateRect;
2448 0 : Rectangle aMouseRect;
2449 :
2450 0 : aImageSize.Width() = CalcZoom( aImageSize.Width() );
2451 0 : aImageSize.Height() = CalcZoom( aImageSize.Height() );
2452 0 : aBrd1Size.Width() = CalcZoom( aBrd1Size.Width() );
2453 0 : aBrd1Size.Height() = CalcZoom( aBrd1Size.Height() );
2454 0 : aBrd2Size.Width() = CalcZoom( aBrd2Size.Width() );
2455 0 : aBrd2Size.Height() = CalcZoom( aBrd2Size.Height() );
2456 :
2457 0 : if ( !aBrd1Size.Width() )
2458 0 : aBrd1Size.Width() = 1;
2459 0 : if ( !aBrd1Size.Height() )
2460 0 : aBrd1Size.Height() = 1;
2461 0 : if ( !aBrd2Size.Width() )
2462 0 : aBrd2Size.Width() = 1;
2463 0 : if ( !aBrd2Size.Height() )
2464 0 : aBrd2Size.Height() = 1;
2465 :
2466 0 : pDev->Push();
2467 0 : pDev->SetMapMode();
2468 0 : pDev->SetFont( aFont );
2469 0 : if ( nFlags & WINDOW_DRAW_MONO )
2470 0 : pDev->SetTextColor( Color( COL_BLACK ) );
2471 : else
2472 0 : pDev->SetTextColor( GetTextColor() );
2473 0 : pDev->SetTextFillColor();
2474 :
2475 : ImplDraw( pDev, nFlags, aPos, aSize,
2476 0 : aImageSize, aStateRect, aMouseRect );
2477 :
2478 0 : Point aCenterPos = aStateRect.Center();
2479 0 : long nRadX = aImageSize.Width()/2;
2480 0 : long nRadY = aImageSize.Height()/2;
2481 :
2482 0 : pDev->SetLineColor();
2483 0 : pDev->SetFillColor( Color( COL_BLACK ) );
2484 0 : pDev->DrawPolygon( Polygon( aCenterPos, nRadX, nRadY ) );
2485 0 : nRadX -= aBrd1Size.Width();
2486 0 : nRadY -= aBrd1Size.Height();
2487 0 : pDev->SetFillColor( Color( COL_WHITE ) );
2488 0 : pDev->DrawPolygon( Polygon( aCenterPos, nRadX, nRadY ) );
2489 0 : if ( mbChecked )
2490 : {
2491 0 : nRadX -= aBrd1Size.Width();
2492 0 : nRadY -= aBrd1Size.Height();
2493 0 : if ( !nRadX )
2494 0 : nRadX = 1;
2495 0 : if ( !nRadY )
2496 0 : nRadY = 1;
2497 0 : pDev->SetFillColor( Color( COL_BLACK ) );
2498 0 : pDev->DrawPolygon( Polygon( aCenterPos, nRadX, nRadY ) );
2499 : }
2500 :
2501 0 : pDev->Pop();
2502 : }
2503 : else
2504 : {
2505 : OSL_FAIL( "RadioButton::Draw() - not implemented for RadioButton with Image" );
2506 : }
2507 0 : }
2508 :
2509 0 : void RadioButton::Resize()
2510 : {
2511 0 : Control::Resize();
2512 0 : Invalidate();
2513 0 : }
2514 :
2515 0 : void RadioButton::GetFocus()
2516 : {
2517 0 : ShowFocus( ImplGetFocusRect() );
2518 0 : SetInputContext( InputContext( GetFont() ) );
2519 0 : Button::GetFocus();
2520 0 : }
2521 :
2522 0 : void RadioButton::LoseFocus()
2523 : {
2524 0 : if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED )
2525 : {
2526 0 : ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
2527 0 : ImplInvalidateOrDrawRadioButtonState();
2528 : }
2529 :
2530 0 : HideFocus();
2531 0 : Button::LoseFocus();
2532 0 : }
2533 :
2534 0 : void RadioButton::StateChanged( StateChangedType nType )
2535 : {
2536 0 : Button::StateChanged( nType );
2537 :
2538 0 : if ( nType == STATE_CHANGE_STATE )
2539 : {
2540 0 : if ( IsReallyVisible() && IsUpdateMode() )
2541 0 : Invalidate( maStateRect );
2542 : }
2543 0 : else if ( (nType == STATE_CHANGE_ENABLE) ||
2544 0 : (nType == STATE_CHANGE_TEXT) ||
2545 0 : (nType == STATE_CHANGE_IMAGE) ||
2546 0 : (nType == STATE_CHANGE_DATA) ||
2547 : (nType == STATE_CHANGE_UPDATEMODE) )
2548 : {
2549 0 : if ( IsUpdateMode() )
2550 0 : Invalidate();
2551 : }
2552 0 : else if ( nType == STATE_CHANGE_STYLE )
2553 : {
2554 0 : SetStyle( ImplInitStyle( GetWindow( WINDOW_PREV ), GetStyle() ) );
2555 :
2556 0 : if ( (GetPrevStyle() & RADIOBUTTON_VIEW_STYLE) !=
2557 0 : (GetStyle() & RADIOBUTTON_VIEW_STYLE) )
2558 : {
2559 0 : if ( IsUpdateMode() )
2560 0 : Invalidate();
2561 : }
2562 : }
2563 0 : else if ( (nType == STATE_CHANGE_ZOOM) ||
2564 : (nType == STATE_CHANGE_CONTROLFONT) )
2565 : {
2566 0 : ImplInitSettings( true, false, false );
2567 0 : Invalidate();
2568 : }
2569 0 : else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
2570 : {
2571 0 : ImplInitSettings( false, true, false );
2572 0 : Invalidate();
2573 : }
2574 0 : else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
2575 : {
2576 0 : ImplInitSettings( false, false, true );
2577 0 : Invalidate();
2578 : }
2579 0 : }
2580 :
2581 0 : void RadioButton::DataChanged( const DataChangedEvent& rDCEvt )
2582 : {
2583 0 : Button::DataChanged( rDCEvt );
2584 :
2585 0 : if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
2586 0 : (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
2587 0 : ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
2588 0 : (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
2589 : {
2590 0 : ImplInitSettings( true, true, true );
2591 0 : Invalidate();
2592 : }
2593 0 : }
2594 :
2595 0 : bool RadioButton::PreNotify( NotifyEvent& rNEvt )
2596 : {
2597 0 : const MouseEvent* pMouseEvt = NULL;
2598 :
2599 0 : if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL )
2600 : {
2601 0 : if( !pMouseEvt->GetButtons() && !pMouseEvt->IsSynthetic() && !pMouseEvt->IsModifierChanged() )
2602 : {
2603 : // trigger redraw if mouse over state has changed
2604 0 : if( IsNativeControlSupported(CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL) )
2605 : {
2606 0 : if( ( maMouseRect.IsInside( GetPointerPosPixel()) &&
2607 0 : !maMouseRect.IsInside( GetLastPointerPosPixel()) ) ||
2608 0 : ( maMouseRect.IsInside( GetLastPointerPosPixel()) &&
2609 0 : !maMouseRect.IsInside( GetPointerPosPixel()) ) ||
2610 0 : pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow() )
2611 : {
2612 0 : Invalidate( maStateRect );
2613 : }
2614 : }
2615 : }
2616 : }
2617 :
2618 0 : return Button::PreNotify(rNEvt);
2619 : }
2620 :
2621 0 : void RadioButton::Toggle()
2622 : {
2623 0 : ImplCallEventListenersAndHandler( VCLEVENT_RADIOBUTTON_TOGGLE, maToggleHdl, this );
2624 0 : }
2625 :
2626 0 : bool RadioButton::SetModeRadioImage( const Image& rImage )
2627 : {
2628 0 : if ( rImage != maImage )
2629 : {
2630 0 : maImage = rImage;
2631 0 : StateChanged( STATE_CHANGE_DATA );
2632 0 : queue_resize();
2633 : }
2634 0 : return true;
2635 : }
2636 :
2637 0 : const Image& RadioButton::GetModeRadioImage( ) const
2638 : {
2639 0 : return maImage;
2640 : }
2641 :
2642 0 : void RadioButton::SetState( bool bCheck )
2643 : {
2644 : // TabStop-Flag richtig mitfuehren
2645 0 : if ( bCheck )
2646 0 : mpWindowImpl->mnStyle |= WB_TABSTOP;
2647 : else
2648 0 : mpWindowImpl->mnStyle &= ~WB_TABSTOP;
2649 :
2650 0 : if ( mbChecked != bCheck )
2651 : {
2652 0 : mbChecked = bCheck;
2653 0 : StateChanged( STATE_CHANGE_STATE );
2654 0 : Toggle();
2655 : }
2656 0 : }
2657 :
2658 0 : bool RadioButton::set_property(const OString &rKey, const OString &rValue)
2659 : {
2660 0 : if (rKey == "active")
2661 0 : SetState(toBool(rValue));
2662 0 : else if (rKey == "image-position")
2663 : {
2664 0 : WinBits nBits = GetStyle();
2665 0 : if (rValue == "left")
2666 : {
2667 0 : nBits &= ~(WB_CENTER | WB_RIGHT);
2668 0 : nBits |= WB_LEFT;
2669 : }
2670 0 : else if (rValue == "right")
2671 : {
2672 0 : nBits &= ~(WB_CENTER | WB_LEFT);
2673 0 : nBits |= WB_RIGHT;
2674 : }
2675 0 : else if (rValue == "top")
2676 : {
2677 0 : nBits &= ~(WB_VCENTER | WB_BOTTOM);
2678 0 : nBits |= WB_TOP;
2679 : }
2680 0 : else if (rValue == "bottom")
2681 : {
2682 0 : nBits &= ~(WB_VCENTER | WB_TOP);
2683 0 : nBits |= WB_BOTTOM;
2684 : }
2685 : //Its rather mad to have to set these bits when there is the other
2686 : //image align. Looks like e.g. the radiobuttons etc weren't converted
2687 : //over to image align fully.
2688 0 : SetStyle(nBits);
2689 : //Deliberate to set the sane ImageAlign property
2690 0 : return Button::set_property(rKey, rValue);
2691 : }
2692 : else
2693 0 : return Button::set_property(rKey, rValue);
2694 0 : return true;
2695 : }
2696 :
2697 0 : void RadioButton::Check( bool bCheck )
2698 : {
2699 : // TabStop-Flag richtig mitfuehren
2700 0 : if ( bCheck )
2701 0 : mpWindowImpl->mnStyle |= WB_TABSTOP;
2702 : else
2703 0 : mpWindowImpl->mnStyle &= ~WB_TABSTOP;
2704 :
2705 0 : if ( mbChecked != bCheck )
2706 : {
2707 0 : mbChecked = bCheck;
2708 0 : ImplDelData aDelData;
2709 0 : ImplAddDel( &aDelData );
2710 0 : StateChanged( STATE_CHANGE_STATE );
2711 0 : if ( aDelData.IsDead() )
2712 0 : return;
2713 0 : if ( bCheck && mbRadioCheck )
2714 0 : ImplUncheckAllOther();
2715 0 : if ( aDelData.IsDead() )
2716 0 : return;
2717 0 : Toggle();
2718 0 : ImplRemoveDel( &aDelData );
2719 : }
2720 : }
2721 :
2722 0 : long RadioButton::ImplGetImageToTextDistance() const
2723 : {
2724 : // 4 pixels, but take zoom into account, so the text doesn't "jump" relative to surrounding elements,
2725 : // which might have been aligned with the text of the check box
2726 0 : return CalcZoom( 4 );
2727 : }
2728 :
2729 0 : Size RadioButton::ImplGetRadioImageSize() const
2730 : {
2731 0 : Size aSize;
2732 0 : bool bDefaultSize = true;
2733 0 : if( IsNativeControlSupported( CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL ) )
2734 : {
2735 0 : ImplControlValue aControlValue;
2736 : // #i45896# workaround gcc3.3 temporary problem
2737 0 : Rectangle aCtrlRegion( Point( 0, 0 ), GetSizePixel() );
2738 0 : ControlState nState = CTRL_STATE_DEFAULT|CTRL_STATE_ENABLED;
2739 0 : Rectangle aBoundingRgn, aContentRgn;
2740 :
2741 : // get native size of a radio button
2742 0 : if( GetNativeControlRegion( CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL, aCtrlRegion,
2743 : nState, aControlValue, OUString(),
2744 0 : aBoundingRgn, aContentRgn ) )
2745 : {
2746 0 : aSize = aContentRgn.GetSize();
2747 0 : bDefaultSize = false;
2748 0 : }
2749 : }
2750 0 : if( bDefaultSize )
2751 0 : aSize = GetRadioImage( GetSettings(), 0 ).GetSizePixel();
2752 0 : return aSize;
2753 : }
2754 :
2755 0 : static void LoadThemedImageList (const StyleSettings &rStyleSettings,
2756 : ImageList *pList, const ResId &rResId,
2757 : sal_uInt16 nImages)
2758 : {
2759 0 : Color aColorAry1[6];
2760 0 : Color aColorAry2[6];
2761 0 : aColorAry1[0] = Color( 0xC0, 0xC0, 0xC0 );
2762 0 : aColorAry1[1] = Color( 0xFF, 0xFF, 0x00 );
2763 0 : aColorAry1[2] = Color( 0xFF, 0xFF, 0xFF );
2764 0 : aColorAry1[3] = Color( 0x80, 0x80, 0x80 );
2765 0 : aColorAry1[4] = Color( 0x00, 0x00, 0x00 );
2766 0 : aColorAry1[5] = Color( 0x00, 0xFF, 0x00 );
2767 0 : aColorAry2[0] = rStyleSettings.GetFaceColor();
2768 0 : aColorAry2[1] = rStyleSettings.GetWindowColor();
2769 0 : aColorAry2[2] = rStyleSettings.GetLightColor();
2770 0 : aColorAry2[3] = rStyleSettings.GetShadowColor();
2771 0 : aColorAry2[4] = rStyleSettings.GetDarkShadowColor();
2772 0 : aColorAry2[5] = rStyleSettings.GetWindowTextColor();
2773 :
2774 0 : Color aMaskColor(0x00, 0x00, 0xFF );
2775 : DBG_ASSERT( sizeof(aColorAry1) == sizeof(aColorAry2), "aColorAry1 must match aColorAry2" );
2776 : // FIXME: do we want the mask for the checkbox ?
2777 : pList->InsertFromHorizontalBitmap (rResId, nImages, &aMaskColor,
2778 0 : aColorAry1, aColorAry2, sizeof(aColorAry1) / sizeof(Color));
2779 0 : }
2780 :
2781 0 : Image RadioButton::GetRadioImage( const AllSettings& rSettings, sal_uInt16 nFlags )
2782 : {
2783 0 : ImplSVData* pSVData = ImplGetSVData();
2784 0 : const StyleSettings& rStyleSettings = rSettings.GetStyleSettings();
2785 0 : sal_uInt16 nStyle = 0;
2786 :
2787 0 : if ( rStyleSettings.GetOptions() & STYLE_OPTION_MONO )
2788 0 : nStyle = STYLE_RADIOBUTTON_MONO;
2789 :
2790 0 : if ( !pSVData->maCtrlData.mpRadioImgList ||
2791 0 : (pSVData->maCtrlData.mnRadioStyle != nStyle) ||
2792 0 : (pSVData->maCtrlData.mnLastRadioFColor != rStyleSettings.GetFaceColor().GetColor()) ||
2793 0 : (pSVData->maCtrlData.mnLastRadioWColor != rStyleSettings.GetWindowColor().GetColor()) ||
2794 0 : (pSVData->maCtrlData.mnLastRadioLColor != rStyleSettings.GetLightColor().GetColor()) )
2795 : {
2796 0 : if ( pSVData->maCtrlData.mpRadioImgList )
2797 0 : delete pSVData->maCtrlData.mpRadioImgList;
2798 :
2799 0 : pSVData->maCtrlData.mnLastRadioFColor = rStyleSettings.GetFaceColor().GetColor();
2800 0 : pSVData->maCtrlData.mnLastRadioWColor = rStyleSettings.GetWindowColor().GetColor();
2801 0 : pSVData->maCtrlData.mnLastRadioLColor = rStyleSettings.GetLightColor().GetColor();
2802 :
2803 0 : ResMgr* pResMgr = ImplGetResMgr();
2804 0 : pSVData->maCtrlData.mpRadioImgList = new ImageList();
2805 0 : if( pResMgr )
2806 : LoadThemedImageList( rStyleSettings,
2807 : pSVData->maCtrlData.mpRadioImgList,
2808 : ResId( SV_RESID_BITMAP_RADIO+nStyle, *pResMgr ), 6
2809 0 : );
2810 0 : pSVData->maCtrlData.mnRadioStyle = nStyle;
2811 : }
2812 :
2813 : sal_uInt16 nId;
2814 0 : if ( nFlags & BUTTON_DRAW_DISABLED )
2815 : {
2816 0 : if ( nFlags & BUTTON_DRAW_CHECKED )
2817 0 : nId = 6;
2818 : else
2819 0 : nId = 5;
2820 : }
2821 0 : else if ( nFlags & BUTTON_DRAW_PRESSED )
2822 : {
2823 0 : if ( nFlags & BUTTON_DRAW_CHECKED )
2824 0 : nId = 4;
2825 : else
2826 0 : nId = 3;
2827 : }
2828 : else
2829 : {
2830 0 : if ( nFlags & BUTTON_DRAW_CHECKED )
2831 0 : nId = 2;
2832 : else
2833 0 : nId = 1;
2834 : }
2835 0 : return pSVData->maCtrlData.mpRadioImgList->GetImage( nId );
2836 : }
2837 :
2838 0 : void RadioButton::ImplSetMinimumNWFSize()
2839 : {
2840 0 : Push( PUSH_MAPMODE );
2841 0 : SetMapMode( MAP_PIXEL );
2842 :
2843 0 : ImplControlValue aControlValue;
2844 0 : Size aCurSize( GetSizePixel() );
2845 0 : Rectangle aCtrlRegion( Point( 0, 0 ), aCurSize );
2846 0 : Rectangle aBoundingRgn, aContentRgn;
2847 :
2848 : // get native size of a radiobutton
2849 0 : if( GetNativeControlRegion( CTRL_RADIOBUTTON, PART_ENTIRE_CONTROL, aCtrlRegion,
2850 : CTRL_STATE_DEFAULT|CTRL_STATE_ENABLED, aControlValue, OUString(),
2851 0 : aBoundingRgn, aContentRgn ) )
2852 : {
2853 0 : Size aSize = aContentRgn.GetSize();
2854 :
2855 0 : if( aSize.Height() > aCurSize.Height() )
2856 : {
2857 0 : aCurSize.Height() = aSize.Height();
2858 0 : SetSizePixel( aCurSize );
2859 : }
2860 : }
2861 :
2862 0 : Pop();
2863 0 : }
2864 :
2865 0 : Size RadioButton::CalcMinimumSize( long nMaxWidth ) const
2866 : {
2867 0 : Size aSize;
2868 0 : if ( !maImage )
2869 0 : aSize = ImplGetRadioImageSize();
2870 : else
2871 : {
2872 0 : aSize = maImage.GetSizePixel();
2873 0 : aSize.Width() += 8;
2874 0 : aSize.Height() += 8;
2875 : }
2876 :
2877 0 : OUString aText = GetText();
2878 0 : if ( !aText.isEmpty() && ! (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) )
2879 : {
2880 0 : bool bTopImage = (GetStyle() & WB_TOP) != 0;
2881 :
2882 0 : if (!bTopImage)
2883 : {
2884 0 : nMaxWidth -= aSize.Width();
2885 0 : nMaxWidth -= ImplGetImageToTextDistance();
2886 : }
2887 :
2888 : // subtract what will be added later
2889 0 : nMaxWidth-=2;
2890 :
2891 : Size aTextSize = GetTextRect( Rectangle( Point(), Size( nMaxWidth > 0 ? nMaxWidth : 0x7fffffff, 0x7fffffff ) ),
2892 0 : aText, FixedText::ImplGetTextStyle( GetStyle() ) ).GetSize();
2893 :
2894 0 : aSize.Width()+=2; // for focus rect
2895 :
2896 0 : if (!bTopImage)
2897 : {
2898 0 : aSize.Width() += ImplGetImageToTextDistance();
2899 0 : aSize.Width() += aTextSize.Width();
2900 0 : if ( aSize.Height() < aTextSize.Height() )
2901 0 : aSize.Height() = aTextSize.Height();
2902 : }
2903 : else
2904 : {
2905 0 : aSize.Height() += 6;
2906 0 : aSize.Height() += GetTextHeight();
2907 0 : if ( aSize.Width() < aTextSize.Width() )
2908 0 : aSize.Width() = aTextSize.Width();
2909 : }
2910 : }
2911 :
2912 0 : return CalcWindowSize( aSize );
2913 : }
2914 :
2915 0 : Size RadioButton::GetOptimalSize() const
2916 : {
2917 0 : return CalcMinimumSize();
2918 : }
2919 :
2920 0 : void CheckBox::ImplInitCheckBoxData()
2921 : {
2922 0 : meState = TRISTATE_FALSE;
2923 0 : meSaveValue = TRISTATE_FALSE;
2924 0 : mbTriState = false;
2925 0 : }
2926 :
2927 0 : void CheckBox::ImplInit( Window* pParent, WinBits nStyle )
2928 : {
2929 0 : nStyle = ImplInitStyle(getPreviousSibling(pParent), nStyle);
2930 0 : Button::ImplInit( pParent, nStyle, NULL );
2931 :
2932 0 : ImplInitSettings( true, true, true );
2933 0 : }
2934 :
2935 0 : WinBits CheckBox::ImplInitStyle( const Window* pPrevWindow, WinBits nStyle )
2936 : {
2937 0 : if ( !(nStyle & WB_NOTABSTOP) )
2938 0 : nStyle |= WB_TABSTOP;
2939 0 : if ( !(nStyle & WB_NOGROUP) &&
2940 0 : (!pPrevWindow || (pPrevWindow->GetType() != WINDOW_CHECKBOX)) )
2941 0 : nStyle |= WB_GROUP;
2942 0 : return nStyle;
2943 : }
2944 :
2945 0 : const Font& CheckBox::GetCanonicalFont( const StyleSettings& _rStyle ) const
2946 : {
2947 0 : return _rStyle.GetRadioCheckFont();
2948 : }
2949 :
2950 0 : const Color& CheckBox::GetCanonicalTextColor( const StyleSettings& _rStyle ) const
2951 : {
2952 0 : return _rStyle.GetRadioCheckTextColor();
2953 : }
2954 :
2955 0 : void CheckBox::ImplInitSettings( bool bFont,
2956 : bool bForeground, bool bBackground )
2957 : {
2958 0 : Button::ImplInitSettings( bFont, bForeground );
2959 :
2960 0 : if ( bBackground )
2961 : {
2962 0 : Window* pParent = GetParent();
2963 0 : if ( !IsControlBackground() &&
2964 0 : (pParent->IsChildTransparentModeEnabled() || IsNativeControlSupported( CTRL_CHECKBOX, PART_ENTIRE_CONTROL ) ) )
2965 : {
2966 0 : EnableChildTransparentMode( true );
2967 0 : SetParentClipMode( PARENTCLIPMODE_NOCLIP );
2968 0 : SetPaintTransparent( true );
2969 0 : SetBackground();
2970 0 : if( IsNativeControlSupported( CTRL_CHECKBOX, PART_ENTIRE_CONTROL ) )
2971 0 : ImplGetWindowImpl()->mbUseNativeFocus = ImplGetSVData()->maNWFData.mbNoFocusRects;
2972 : }
2973 : else
2974 : {
2975 0 : EnableChildTransparentMode( false );
2976 0 : SetParentClipMode( 0 );
2977 0 : SetPaintTransparent( false );
2978 :
2979 0 : if ( IsControlBackground() )
2980 0 : SetBackground( GetControlBackground() );
2981 : else
2982 0 : SetBackground( pParent->GetBackground() );
2983 : }
2984 : }
2985 0 : }
2986 :
2987 0 : void CheckBox::ImplLoadRes( const ResId& rResId )
2988 : {
2989 0 : Button::ImplLoadRes( rResId );
2990 :
2991 0 : if ( rResId.GetRT() != RSC_TRISTATEBOX )
2992 : {
2993 0 : sal_uInt16 nChecked = ReadShortRes();
2994 : //anderer Wert als Default ?
2995 0 : if( nChecked )
2996 0 : Check( true );
2997 : }
2998 0 : }
2999 :
3000 0 : void CheckBox::ImplInvalidateOrDrawCheckBoxState()
3001 : {
3002 0 : if( ImplGetSVData()->maNWFData.mbCheckBoxNeedsErase )
3003 : {
3004 0 : if ( IsNativeControlSupported(CTRL_CHECKBOX, PART_ENTIRE_CONTROL) )
3005 : {
3006 0 : Invalidate();
3007 0 : Update();
3008 0 : return;
3009 : }
3010 : }
3011 0 : ImplDrawCheckBoxState();
3012 : }
3013 :
3014 0 : void CheckBox::ImplDrawCheckBoxState()
3015 : {
3016 0 : bool bNativeOK = true;
3017 :
3018 0 : if ( (bNativeOK=IsNativeControlSupported(CTRL_CHECKBOX, PART_ENTIRE_CONTROL)) )
3019 : {
3020 0 : ImplControlValue aControlValue( meState == TRISTATE_TRUE ? BUTTONVALUE_ON : BUTTONVALUE_OFF );
3021 0 : Rectangle aCtrlRegion( maStateRect );
3022 0 : ControlState nState = 0;
3023 :
3024 0 : if ( HasFocus() ) nState |= CTRL_STATE_FOCUSED;
3025 0 : if ( ImplGetButtonState() & BUTTON_DRAW_DEFAULT ) nState |= CTRL_STATE_DEFAULT;
3026 0 : if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED ) nState |= CTRL_STATE_PRESSED;
3027 0 : if ( IsEnabled() ) nState |= CTRL_STATE_ENABLED;
3028 :
3029 0 : if ( meState == TRISTATE_TRUE )
3030 0 : aControlValue.setTristateVal( BUTTONVALUE_ON );
3031 0 : else if ( meState == TRISTATE_INDET )
3032 0 : aControlValue.setTristateVal( BUTTONVALUE_MIXED );
3033 :
3034 0 : if ( IsMouseOver() && maMouseRect.IsInside( GetPointerPosPixel() ) )
3035 0 : nState |= CTRL_STATE_ROLLOVER;
3036 :
3037 : bNativeOK = DrawNativeControl( CTRL_CHECKBOX, PART_ENTIRE_CONTROL, aCtrlRegion, nState,
3038 0 : aControlValue, OUString() );
3039 : }
3040 :
3041 0 : if ( !bNativeOK )
3042 : {
3043 0 : sal_uInt16 nStyle = ImplGetButtonState();
3044 0 : if ( !IsEnabled() )
3045 0 : nStyle |= BUTTON_DRAW_DISABLED;
3046 0 : if ( meState == TRISTATE_INDET )
3047 0 : nStyle |= BUTTON_DRAW_DONTKNOW;
3048 0 : else if ( meState == TRISTATE_TRUE )
3049 0 : nStyle |= BUTTON_DRAW_CHECKED;
3050 0 : Image aImage = GetCheckImage( GetSettings(), nStyle );
3051 0 : if ( IsZoom() )
3052 0 : DrawImage( maStateRect.TopLeft(), maStateRect.GetSize(), aImage );
3053 : else
3054 0 : DrawImage( maStateRect.TopLeft(), aImage );
3055 : }
3056 0 : }
3057 :
3058 0 : void CheckBox::ImplDraw( OutputDevice* pDev, sal_uLong nDrawFlags,
3059 : const Point& rPos, const Size& rSize,
3060 : const Size& rImageSize, Rectangle& rStateRect,
3061 : Rectangle& rMouseRect, bool bLayout )
3062 : {
3063 0 : WinBits nWinStyle = GetStyle();
3064 0 : OUString aText( GetText() );
3065 :
3066 0 : pDev->Push( PUSH_CLIPREGION | PUSH_LINECOLOR );
3067 0 : pDev->IntersectClipRegion( Rectangle( rPos, rSize ) );
3068 :
3069 0 : long nLineY = rPos.Y() + (rSize.Height()-1)/2;
3070 0 : if ( ( !aText.isEmpty() && ! (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) ) ||
3071 0 : ( HasImage() && ! (ImplGetButtonState() & BUTTON_DRAW_NOIMAGE) ) )
3072 : {
3073 0 : sal_uInt16 nTextStyle = Button::ImplGetTextStyle( aText, nWinStyle, nDrawFlags );
3074 :
3075 0 : const long nImageSep = GetDrawPixel( pDev, ImplGetImageToTextDistance() );
3076 0 : Size aSize( rSize );
3077 0 : Point aPos( rPos );
3078 0 : aPos.X() += rImageSize.Width() + nImageSep;
3079 0 : aSize.Width() -= rImageSize.Width() + nImageSep;
3080 :
3081 : // if the text rect height is smaller than the height of the image
3082 : // then for single lines the default should be centered text
3083 0 : if( (nWinStyle & (WB_TOP|WB_VCENTER|WB_BOTTOM)) == 0 &&
3084 0 : (rImageSize.Height() > rSize.Height() || ! (nWinStyle & WB_WORDBREAK) ) )
3085 : {
3086 0 : nTextStyle &= ~(TEXT_DRAW_TOP|TEXT_DRAW_BOTTOM);
3087 0 : nTextStyle |= TEXT_DRAW_VCENTER;
3088 0 : aSize.Height() = rImageSize.Height();
3089 : }
3090 :
3091 : ImplDrawAlignedImage( pDev, aPos, aSize, bLayout, 1,
3092 0 : nDrawFlags, nTextStyle, NULL );
3093 0 : nLineY = aPos.Y() + aSize.Height()/2;
3094 :
3095 0 : rMouseRect = Rectangle( aPos, aSize );
3096 0 : rMouseRect.Left() = rPos.X();
3097 0 : rStateRect.Left() = rPos.X();
3098 0 : rStateRect.Top() = rMouseRect.Top();
3099 :
3100 0 : if ( aSize.Height() > rImageSize.Height() )
3101 0 : rStateRect.Top() += ( aSize.Height() - rImageSize.Height() ) / 2;
3102 : else
3103 : {
3104 0 : rStateRect.Top() -= ( rImageSize.Height() - aSize.Height() ) / 2;
3105 0 : if( rStateRect.Top() < 0 )
3106 0 : rStateRect.Top() = 0;
3107 : }
3108 :
3109 0 : rStateRect.Right() = rStateRect.Left()+rImageSize.Width()-1;
3110 0 : rStateRect.Bottom() = rStateRect.Top()+rImageSize.Height()-1;
3111 0 : if ( rStateRect.Bottom() > rMouseRect.Bottom() )
3112 0 : rMouseRect.Bottom() = rStateRect.Bottom();
3113 : }
3114 : else
3115 : {
3116 0 : if ( mbLegacyNoTextAlign && ( nWinStyle & WB_CENTER ) )
3117 0 : rStateRect.Left() = rPos.X()+((rSize.Width()-rImageSize.Width())/2);
3118 0 : else if ( mbLegacyNoTextAlign && ( nWinStyle & WB_RIGHT ) )
3119 0 : rStateRect.Left() = rPos.X()+rSize.Width()-rImageSize.Width();
3120 : else
3121 0 : rStateRect.Left() = rPos.X();
3122 0 : if ( nWinStyle & WB_VCENTER )
3123 0 : rStateRect.Top() = rPos.Y()+((rSize.Height()-rImageSize.Height())/2);
3124 0 : else if ( nWinStyle & WB_BOTTOM )
3125 0 : rStateRect.Top() = rPos.Y()+rSize.Height()-rImageSize.Height();
3126 : else
3127 0 : rStateRect.Top() = rPos.Y();
3128 0 : rStateRect.Right() = rStateRect.Left()+rImageSize.Width()-1;
3129 0 : rStateRect.Bottom() = rStateRect.Top()+rImageSize.Height()-1;
3130 : // provide space for focusrect
3131 : // note: this assumes that the control's size was adjusted
3132 : // accordingly in Get/LoseFocus, so the onscreen position won't change
3133 0 : if( HasFocus() )
3134 0 : rStateRect.Move( 1, 1 );
3135 0 : rMouseRect = rStateRect;
3136 :
3137 0 : ImplSetFocusRect( rStateRect );
3138 : }
3139 :
3140 0 : const int nLineSpace = 4;
3141 0 : if( (GetStyle() & WB_CBLINESTYLE) != 0 &&
3142 0 : rMouseRect.Right()-1-nLineSpace < rPos.X()+rSize.Width() )
3143 : {
3144 0 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
3145 0 : if ( rStyleSettings.GetOptions() & STYLE_OPTION_MONO )
3146 0 : SetLineColor( Color( COL_BLACK ) );
3147 : else
3148 0 : SetLineColor( rStyleSettings.GetShadowColor() );
3149 0 : long nLineX = rMouseRect.Right()+nLineSpace;
3150 0 : DrawLine( Point( nLineX, nLineY ), Point( rPos.X() + rSize.Width()-1, nLineY ) );
3151 0 : if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
3152 : {
3153 0 : SetLineColor( rStyleSettings.GetLightColor() );
3154 0 : DrawLine( Point( nLineX, nLineY+1 ), Point( rPos.X() + rSize.Width()-1, nLineY+1 ) );
3155 : }
3156 : }
3157 :
3158 0 : pDev->Pop();
3159 0 : }
3160 :
3161 0 : void CheckBox::ImplDrawCheckBox( bool bLayout )
3162 : {
3163 0 : Size aImageSize = ImplGetCheckImageSize();
3164 0 : aImageSize.Width() = CalcZoom( aImageSize.Width() );
3165 0 : aImageSize.Height() = CalcZoom( aImageSize.Height() );
3166 :
3167 0 : if( !bLayout )
3168 0 : HideFocus();
3169 :
3170 0 : ImplDraw( this, 0, Point(), GetOutputSizePixel(), aImageSize,
3171 0 : maStateRect, maMouseRect, bLayout );
3172 :
3173 0 : if( !bLayout )
3174 : {
3175 0 : ImplDrawCheckBoxState();
3176 0 : if ( HasFocus() )
3177 0 : ShowFocus( ImplGetFocusRect() );
3178 : }
3179 0 : }
3180 :
3181 0 : void CheckBox::ImplCheck()
3182 : {
3183 : TriState eNewState;
3184 0 : if ( meState == TRISTATE_FALSE )
3185 0 : eNewState = TRISTATE_TRUE;
3186 0 : else if ( !mbTriState )
3187 0 : eNewState = TRISTATE_FALSE;
3188 0 : else if ( meState == TRISTATE_TRUE )
3189 0 : eNewState = TRISTATE_INDET;
3190 : else
3191 0 : eNewState = TRISTATE_FALSE;
3192 0 : meState = eNewState;
3193 :
3194 0 : ImplDelData aDelData;
3195 0 : ImplAddDel( &aDelData );
3196 0 : if( (GetStyle() & WB_EARLYTOGGLE) )
3197 0 : Toggle();
3198 0 : ImplInvalidateOrDrawCheckBoxState();
3199 0 : if( ! (GetStyle() & WB_EARLYTOGGLE) )
3200 0 : Toggle();
3201 0 : if ( aDelData.IsDead() )
3202 0 : return;
3203 0 : ImplRemoveDel( &aDelData );
3204 0 : Click();
3205 : }
3206 :
3207 0 : CheckBox::CheckBox( Window* pParent, WinBits nStyle ) :
3208 0 : Button( WINDOW_CHECKBOX ), mbLegacyNoTextAlign( false )
3209 : {
3210 0 : ImplInitCheckBoxData();
3211 0 : ImplInit( pParent, nStyle );
3212 0 : }
3213 :
3214 0 : CheckBox::CheckBox( Window* pParent, const ResId& rResId ) :
3215 0 : Button( WINDOW_CHECKBOX ), mbLegacyNoTextAlign( false )
3216 : {
3217 0 : rResId.SetRT( RSC_CHECKBOX );
3218 0 : WinBits nStyle = ImplInitRes( rResId );
3219 0 : ImplInitCheckBoxData();
3220 0 : ImplInit( pParent, nStyle );
3221 0 : ImplLoadRes( rResId );
3222 :
3223 0 : if ( !(nStyle & WB_HIDE) )
3224 0 : Show();
3225 0 : }
3226 :
3227 0 : void CheckBox::MouseButtonDown( const MouseEvent& rMEvt )
3228 : {
3229 0 : if ( rMEvt.IsLeft() && maMouseRect.IsInside( rMEvt.GetPosPixel() ) )
3230 : {
3231 0 : ImplGetButtonState() |= BUTTON_DRAW_PRESSED;
3232 0 : ImplInvalidateOrDrawCheckBoxState();
3233 0 : StartTracking();
3234 0 : return;
3235 : }
3236 :
3237 0 : Button::MouseButtonDown( rMEvt );
3238 : }
3239 :
3240 0 : void CheckBox::Tracking( const TrackingEvent& rTEvt )
3241 : {
3242 0 : if ( rTEvt.IsTrackingEnded() )
3243 : {
3244 0 : if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED )
3245 : {
3246 0 : if ( !(GetStyle() & WB_NOPOINTERFOCUS) && !rTEvt.IsTrackingCanceled() )
3247 0 : GrabFocus();
3248 :
3249 0 : ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
3250 :
3251 : // do not call click handler if aborted
3252 0 : if ( !rTEvt.IsTrackingCanceled() )
3253 0 : ImplCheck();
3254 : else
3255 0 : ImplInvalidateOrDrawCheckBoxState();
3256 : }
3257 : }
3258 : else
3259 : {
3260 0 : if ( maMouseRect.IsInside( rTEvt.GetMouseEvent().GetPosPixel() ) )
3261 : {
3262 0 : if ( !(ImplGetButtonState() & BUTTON_DRAW_PRESSED) )
3263 : {
3264 0 : ImplGetButtonState() |= BUTTON_DRAW_PRESSED;
3265 0 : ImplInvalidateOrDrawCheckBoxState();
3266 : }
3267 : }
3268 : else
3269 : {
3270 0 : if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED )
3271 : {
3272 0 : ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
3273 0 : ImplInvalidateOrDrawCheckBoxState();
3274 : }
3275 : }
3276 : }
3277 0 : }
3278 :
3279 0 : void CheckBox::KeyInput( const KeyEvent& rKEvt )
3280 : {
3281 0 : KeyCode aKeyCode = rKEvt.GetKeyCode();
3282 :
3283 0 : if ( !aKeyCode.GetModifier() && (aKeyCode.GetCode() == KEY_SPACE) )
3284 : {
3285 0 : if ( !(ImplGetButtonState() & BUTTON_DRAW_PRESSED) )
3286 : {
3287 0 : ImplGetButtonState() |= BUTTON_DRAW_PRESSED;
3288 0 : ImplInvalidateOrDrawCheckBoxState();
3289 : }
3290 : }
3291 0 : else if ( (ImplGetButtonState() & BUTTON_DRAW_PRESSED) && (aKeyCode.GetCode() == KEY_ESCAPE) )
3292 : {
3293 0 : ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
3294 0 : ImplInvalidateOrDrawCheckBoxState();
3295 : }
3296 : else
3297 0 : Button::KeyInput( rKEvt );
3298 0 : }
3299 :
3300 0 : void CheckBox::KeyUp( const KeyEvent& rKEvt )
3301 : {
3302 0 : KeyCode aKeyCode = rKEvt.GetKeyCode();
3303 :
3304 0 : if ( (ImplGetButtonState() & BUTTON_DRAW_PRESSED) && (aKeyCode.GetCode() == KEY_SPACE) )
3305 : {
3306 0 : ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
3307 0 : ImplCheck();
3308 : }
3309 : else
3310 0 : Button::KeyUp( rKEvt );
3311 0 : }
3312 :
3313 0 : void CheckBox::FillLayoutData() const
3314 : {
3315 0 : mpControlData->mpLayoutData = new vcl::ControlLayoutData();
3316 0 : const_cast<CheckBox*>(this)->ImplDrawCheckBox( true );
3317 0 : }
3318 :
3319 0 : void CheckBox::Paint( const Rectangle& )
3320 : {
3321 0 : ImplDrawCheckBox();
3322 0 : }
3323 :
3324 0 : void CheckBox::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize,
3325 : sal_uLong nFlags )
3326 : {
3327 0 : MapMode aResMapMode( MAP_100TH_MM );
3328 0 : Point aPos = pDev->LogicToPixel( rPos );
3329 0 : Size aSize = pDev->LogicToPixel( rSize );
3330 0 : Size aImageSize = pDev->LogicToPixel( Size( 300, 300 ), aResMapMode );
3331 0 : Size aBrd1Size = pDev->LogicToPixel( Size( 20, 20 ), aResMapMode );
3332 0 : Size aBrd2Size = pDev->LogicToPixel( Size( 30, 30 ), aResMapMode );
3333 0 : long nCheckWidth = pDev->LogicToPixel( Size( 20, 20 ), aResMapMode ).Width();
3334 0 : Font aFont = GetDrawPixelFont( pDev );
3335 0 : Rectangle aStateRect;
3336 0 : Rectangle aMouseRect;
3337 :
3338 0 : aImageSize.Width() = CalcZoom( aImageSize.Width() );
3339 0 : aImageSize.Height() = CalcZoom( aImageSize.Height() );
3340 0 : aBrd1Size.Width() = CalcZoom( aBrd1Size.Width() );
3341 0 : aBrd1Size.Height() = CalcZoom( aBrd1Size.Height() );
3342 0 : aBrd2Size.Width() = CalcZoom( aBrd2Size.Width() );
3343 0 : aBrd2Size.Height() = CalcZoom( aBrd2Size.Height() );
3344 :
3345 0 : if ( !aBrd1Size.Width() )
3346 0 : aBrd1Size.Width() = 1;
3347 0 : if ( !aBrd1Size.Height() )
3348 0 : aBrd1Size.Height() = 1;
3349 0 : if ( !aBrd2Size.Width() )
3350 0 : aBrd2Size.Width() = 1;
3351 0 : if ( !aBrd2Size.Height() )
3352 0 : aBrd2Size.Height() = 1;
3353 0 : if ( !nCheckWidth )
3354 0 : nCheckWidth = 1;
3355 :
3356 0 : pDev->Push();
3357 0 : pDev->SetMapMode();
3358 0 : pDev->SetFont( aFont );
3359 0 : if ( nFlags & WINDOW_DRAW_MONO )
3360 0 : pDev->SetTextColor( Color( COL_BLACK ) );
3361 : else
3362 0 : pDev->SetTextColor( GetTextColor() );
3363 0 : pDev->SetTextFillColor();
3364 :
3365 : ImplDraw( pDev, nFlags, aPos, aSize,
3366 0 : aImageSize, aStateRect, aMouseRect, false );
3367 :
3368 0 : pDev->SetLineColor();
3369 0 : pDev->SetFillColor( Color( COL_BLACK ) );
3370 0 : pDev->DrawRect( aStateRect );
3371 0 : aStateRect.Left() += aBrd1Size.Width();
3372 0 : aStateRect.Top() += aBrd1Size.Height();
3373 0 : aStateRect.Right() -= aBrd1Size.Width();
3374 0 : aStateRect.Bottom() -= aBrd1Size.Height();
3375 0 : if ( meState == TRISTATE_INDET )
3376 0 : pDev->SetFillColor( Color( COL_LIGHTGRAY ) );
3377 : else
3378 0 : pDev->SetFillColor( Color( COL_WHITE ) );
3379 0 : pDev->DrawRect( aStateRect );
3380 :
3381 0 : if ( meState == TRISTATE_TRUE )
3382 : {
3383 0 : aStateRect.Left() += aBrd2Size.Width();
3384 0 : aStateRect.Top() += aBrd2Size.Height();
3385 0 : aStateRect.Right() -= aBrd2Size.Width();
3386 0 : aStateRect.Bottom() -= aBrd2Size.Height();
3387 0 : Point aPos11( aStateRect.TopLeft() );
3388 0 : Point aPos12( aStateRect.BottomRight() );
3389 0 : Point aPos21( aStateRect.TopRight() );
3390 0 : Point aPos22( aStateRect.BottomLeft() );
3391 0 : Point aTempPos11( aPos11 );
3392 0 : Point aTempPos12( aPos12 );
3393 0 : Point aTempPos21( aPos21 );
3394 0 : Point aTempPos22( aPos22 );
3395 0 : pDev->SetLineColor( Color( COL_BLACK ) );
3396 0 : long nDX = 0;
3397 0 : for ( long i = 0; i < nCheckWidth; i++ )
3398 : {
3399 0 : if ( !(i % 2) )
3400 : {
3401 0 : aTempPos11.X() = aPos11.X()+nDX;
3402 0 : aTempPos12.X() = aPos12.X()+nDX;
3403 0 : aTempPos21.X() = aPos21.X()+nDX;
3404 0 : aTempPos22.X() = aPos22.X()+nDX;
3405 : }
3406 : else
3407 : {
3408 0 : nDX++;
3409 0 : aTempPos11.X() = aPos11.X()-nDX;
3410 0 : aTempPos12.X() = aPos12.X()-nDX;
3411 0 : aTempPos21.X() = aPos21.X()-nDX;
3412 0 : aTempPos22.X() = aPos22.X()-nDX;
3413 : }
3414 0 : pDev->DrawLine( aTempPos11, aTempPos12 );
3415 0 : pDev->DrawLine( aTempPos21, aTempPos22 );
3416 : }
3417 : }
3418 :
3419 0 : pDev->Pop();
3420 0 : }
3421 :
3422 0 : void CheckBox::Resize()
3423 : {
3424 0 : Control::Resize();
3425 0 : Invalidate();
3426 0 : }
3427 :
3428 0 : void CheckBox::GetFocus()
3429 : {
3430 0 : if ( GetText().isEmpty() || (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) )
3431 : {
3432 : // increase button size to have space for focus rect
3433 : // checkboxes without text will draw focusrect around the check
3434 : // See CheckBox::ImplDraw()
3435 0 : Point aPos( GetPosPixel() );
3436 0 : Size aSize( GetSizePixel() );
3437 0 : aPos.Move(-1,-1);
3438 0 : aSize.Height() += 2;
3439 0 : aSize.Width() += 2;
3440 0 : setPosSizePixel( aPos.X(), aPos.Y(), aSize.Width(), aSize.Height(), WINDOW_POSSIZE_ALL );
3441 0 : ImplDrawCheckBox();
3442 : }
3443 : else
3444 0 : ShowFocus( ImplGetFocusRect() );
3445 :
3446 0 : SetInputContext( InputContext( GetFont() ) );
3447 0 : Button::GetFocus();
3448 0 : }
3449 :
3450 0 : void CheckBox::LoseFocus()
3451 : {
3452 0 : if ( ImplGetButtonState() & BUTTON_DRAW_PRESSED )
3453 : {
3454 0 : ImplGetButtonState() &= ~BUTTON_DRAW_PRESSED;
3455 0 : ImplInvalidateOrDrawCheckBoxState();
3456 : }
3457 :
3458 0 : HideFocus();
3459 0 : Button::LoseFocus();
3460 :
3461 0 : if ( GetText().isEmpty() || (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) )
3462 : {
3463 : // decrease button size again (see GetFocus())
3464 : // checkboxes without text will draw focusrect around the check
3465 0 : Point aPos( GetPosPixel() );
3466 0 : Size aSize( GetSizePixel() );
3467 0 : aPos.Move(1,1);
3468 0 : aSize.Height() -= 2;
3469 0 : aSize.Width() -= 2;
3470 0 : setPosSizePixel( aPos.X(), aPos.Y(), aSize.Width(), aSize.Height(), WINDOW_POSSIZE_ALL );
3471 0 : ImplDrawCheckBox();
3472 : }
3473 0 : }
3474 :
3475 0 : void CheckBox::StateChanged( StateChangedType nType )
3476 : {
3477 0 : Button::StateChanged( nType );
3478 :
3479 0 : if ( nType == STATE_CHANGE_STATE )
3480 : {
3481 0 : if ( IsReallyVisible() && IsUpdateMode() )
3482 0 : Invalidate( maStateRect );
3483 : }
3484 0 : else if ( (nType == STATE_CHANGE_ENABLE) ||
3485 0 : (nType == STATE_CHANGE_TEXT) ||
3486 0 : (nType == STATE_CHANGE_IMAGE) ||
3487 0 : (nType == STATE_CHANGE_DATA) ||
3488 : (nType == STATE_CHANGE_UPDATEMODE) )
3489 : {
3490 0 : if ( IsUpdateMode() )
3491 0 : Invalidate();
3492 : }
3493 0 : else if ( nType == STATE_CHANGE_STYLE )
3494 : {
3495 0 : SetStyle( ImplInitStyle( GetWindow( WINDOW_PREV ), GetStyle() ) );
3496 :
3497 0 : if ( (GetPrevStyle() & CHECKBOX_VIEW_STYLE) !=
3498 0 : (GetStyle() & CHECKBOX_VIEW_STYLE) )
3499 : {
3500 0 : if ( IsUpdateMode() )
3501 0 : Invalidate();
3502 : }
3503 : }
3504 0 : else if ( (nType == STATE_CHANGE_ZOOM) ||
3505 : (nType == STATE_CHANGE_CONTROLFONT) )
3506 : {
3507 0 : ImplInitSettings( true, false, false );
3508 0 : Invalidate();
3509 : }
3510 0 : else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
3511 : {
3512 0 : ImplInitSettings( false, true, false );
3513 0 : Invalidate();
3514 : }
3515 0 : else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
3516 : {
3517 0 : ImplInitSettings( false, false, true );
3518 0 : Invalidate();
3519 : }
3520 0 : }
3521 :
3522 0 : void CheckBox::DataChanged( const DataChangedEvent& rDCEvt )
3523 : {
3524 0 : Button::DataChanged( rDCEvt );
3525 :
3526 0 : if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
3527 0 : (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
3528 0 : ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
3529 0 : (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
3530 : {
3531 0 : ImplInitSettings( true, true, true );
3532 0 : Invalidate();
3533 : }
3534 0 : }
3535 :
3536 0 : bool CheckBox::PreNotify( NotifyEvent& rNEvt )
3537 : {
3538 0 : const MouseEvent* pMouseEvt = NULL;
3539 :
3540 0 : if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL )
3541 : {
3542 0 : if( !pMouseEvt->GetButtons() && !pMouseEvt->IsSynthetic() && !pMouseEvt->IsModifierChanged() )
3543 : {
3544 : // trigger redraw if mouse over state has changed
3545 0 : if( IsNativeControlSupported(CTRL_CHECKBOX, PART_ENTIRE_CONTROL) )
3546 : {
3547 0 : if( ( maMouseRect.IsInside( GetPointerPosPixel()) &&
3548 0 : !maMouseRect.IsInside( GetLastPointerPosPixel()) ) ||
3549 0 : ( maMouseRect.IsInside( GetLastPointerPosPixel()) &&
3550 0 : !maMouseRect.IsInside( GetPointerPosPixel()) ) ||
3551 0 : pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow() )
3552 : {
3553 0 : Invalidate( maStateRect );
3554 : }
3555 : }
3556 : }
3557 : }
3558 :
3559 0 : return Button::PreNotify(rNEvt);
3560 : }
3561 :
3562 0 : void CheckBox::Toggle()
3563 : {
3564 0 : ImplCallEventListenersAndHandler( VCLEVENT_CHECKBOX_TOGGLE, maToggleHdl, this );
3565 0 : }
3566 :
3567 0 : void CheckBox::SetState( TriState eState )
3568 : {
3569 0 : if ( !mbTriState && (eState == TRISTATE_INDET) )
3570 0 : eState = TRISTATE_FALSE;
3571 :
3572 0 : if ( meState != eState )
3573 : {
3574 0 : meState = eState;
3575 0 : StateChanged( STATE_CHANGE_STATE );
3576 0 : Toggle();
3577 : }
3578 0 : }
3579 :
3580 0 : bool CheckBox::set_property(const OString &rKey, const OString &rValue)
3581 : {
3582 0 : if (rKey == "active")
3583 0 : SetState(toBool(rValue) ? TRISTATE_TRUE : TRISTATE_FALSE);
3584 : else
3585 0 : return Button::set_property(rKey, rValue);
3586 0 : return true;
3587 : }
3588 :
3589 0 : void CheckBox::EnableTriState( bool bTriState )
3590 : {
3591 0 : if ( mbTriState != bTriState )
3592 : {
3593 0 : mbTriState = bTriState;
3594 :
3595 0 : if ( !bTriState && (meState == TRISTATE_INDET) )
3596 0 : SetState( TRISTATE_FALSE );
3597 : }
3598 0 : }
3599 :
3600 0 : long CheckBox::ImplGetImageToTextDistance() const
3601 : {
3602 : // 4 pixels, but take zoom into account, so the text doesn't "jump" relative to surrounding elements,
3603 : // which might have been aligned with the text of the check box
3604 0 : return CalcZoom( 4 );
3605 : }
3606 :
3607 0 : Size CheckBox::ImplGetCheckImageSize() const
3608 : {
3609 0 : Size aSize;
3610 0 : bool bDefaultSize = true;
3611 0 : if( IsNativeControlSupported( CTRL_CHECKBOX, PART_ENTIRE_CONTROL ) )
3612 : {
3613 0 : ImplControlValue aControlValue;
3614 : // #i45896# workaround gcc3.3 temporary problem
3615 0 : Rectangle aCtrlRegion( Point( 0, 0 ), GetSizePixel() );
3616 0 : ControlState nState = CTRL_STATE_DEFAULT|CTRL_STATE_ENABLED;
3617 0 : Rectangle aBoundingRgn, aContentRgn;
3618 :
3619 : // get native size of a check box
3620 0 : if( GetNativeControlRegion( CTRL_CHECKBOX, PART_ENTIRE_CONTROL, aCtrlRegion,
3621 : nState, aControlValue, OUString(),
3622 0 : aBoundingRgn, aContentRgn ) )
3623 : {
3624 0 : aSize = aContentRgn.GetSize();
3625 0 : bDefaultSize = false;
3626 0 : }
3627 : }
3628 0 : if( bDefaultSize )
3629 0 : aSize = GetCheckImage( GetSettings(), 0 ).GetSizePixel();
3630 0 : return aSize;
3631 : }
3632 :
3633 0 : Image CheckBox::GetCheckImage( const AllSettings& rSettings, sal_uInt16 nFlags )
3634 : {
3635 0 : ImplSVData* pSVData = ImplGetSVData();
3636 0 : const StyleSettings& rStyleSettings = rSettings.GetStyleSettings();
3637 0 : sal_uInt16 nStyle = 0;
3638 :
3639 0 : if ( rStyleSettings.GetOptions() & STYLE_OPTION_MONO )
3640 0 : nStyle = STYLE_CHECKBOX_MONO;
3641 :
3642 0 : if ( !pSVData->maCtrlData.mpCheckImgList ||
3643 0 : (pSVData->maCtrlData.mnCheckStyle != nStyle) ||
3644 0 : (pSVData->maCtrlData.mnLastCheckFColor != rStyleSettings.GetFaceColor().GetColor()) ||
3645 0 : (pSVData->maCtrlData.mnLastCheckWColor != rStyleSettings.GetWindowColor().GetColor()) ||
3646 0 : (pSVData->maCtrlData.mnLastCheckLColor != rStyleSettings.GetLightColor().GetColor()) )
3647 : {
3648 0 : if ( pSVData->maCtrlData.mpCheckImgList )
3649 0 : delete pSVData->maCtrlData.mpCheckImgList;
3650 :
3651 0 : pSVData->maCtrlData.mnLastCheckFColor = rStyleSettings.GetFaceColor().GetColor();
3652 0 : pSVData->maCtrlData.mnLastCheckWColor = rStyleSettings.GetWindowColor().GetColor();
3653 0 : pSVData->maCtrlData.mnLastCheckLColor = rStyleSettings.GetLightColor().GetColor();
3654 :
3655 0 : ResMgr* pResMgr = ImplGetResMgr();
3656 0 : pSVData->maCtrlData.mpCheckImgList = new ImageList();
3657 0 : if( pResMgr )
3658 : LoadThemedImageList( rStyleSettings,
3659 : pSVData->maCtrlData.mpCheckImgList,
3660 0 : ResId( SV_RESID_BITMAP_CHECK+nStyle, *pResMgr ), 9 );
3661 0 : pSVData->maCtrlData.mnCheckStyle = nStyle;
3662 : }
3663 :
3664 : sal_uInt16 nId;
3665 0 : if ( nFlags & BUTTON_DRAW_DISABLED )
3666 : {
3667 0 : if ( nFlags & BUTTON_DRAW_DONTKNOW )
3668 0 : nId = 9;
3669 0 : else if ( nFlags & BUTTON_DRAW_CHECKED )
3670 0 : nId = 6;
3671 : else
3672 0 : nId = 5;
3673 : }
3674 0 : else if ( nFlags & BUTTON_DRAW_PRESSED )
3675 : {
3676 0 : if ( nFlags & BUTTON_DRAW_DONTKNOW )
3677 0 : nId = 8;
3678 0 : else if ( nFlags & BUTTON_DRAW_CHECKED )
3679 0 : nId = 4;
3680 : else
3681 0 : nId = 3;
3682 : }
3683 : else
3684 : {
3685 0 : if ( nFlags & BUTTON_DRAW_DONTKNOW )
3686 0 : nId = 7;
3687 0 : else if ( nFlags & BUTTON_DRAW_CHECKED )
3688 0 : nId = 2;
3689 : else
3690 0 : nId = 1;
3691 : }
3692 0 : return pSVData->maCtrlData.mpCheckImgList->GetImage( nId );
3693 : }
3694 :
3695 0 : void CheckBox::ImplSetMinimumNWFSize()
3696 : {
3697 0 : Push( PUSH_MAPMODE );
3698 0 : SetMapMode( MAP_PIXEL );
3699 :
3700 0 : ImplControlValue aControlValue;
3701 0 : Size aCurSize( GetSizePixel() );
3702 0 : Rectangle aCtrlRegion( Point( 0, 0 ), aCurSize );
3703 0 : Rectangle aBoundingRgn, aContentRgn;
3704 :
3705 : // get native size of a radiobutton
3706 0 : if( GetNativeControlRegion( CTRL_CHECKBOX, PART_ENTIRE_CONTROL, aCtrlRegion,
3707 : CTRL_STATE_DEFAULT|CTRL_STATE_ENABLED, aControlValue, OUString(),
3708 0 : aBoundingRgn, aContentRgn ) )
3709 : {
3710 0 : Size aSize = aContentRgn.GetSize();
3711 :
3712 0 : if( aSize.Height() > aCurSize.Height() )
3713 : {
3714 0 : aCurSize.Height() = aSize.Height();
3715 0 : SetSizePixel( aCurSize );
3716 : }
3717 : }
3718 :
3719 0 : Pop();
3720 0 : }
3721 :
3722 0 : Size CheckBox::CalcMinimumSize( long nMaxWidth ) const
3723 : {
3724 0 : Size aSize = ImplGetCheckImageSize();
3725 0 : nMaxWidth -= aSize.Width();
3726 :
3727 0 : OUString aText = GetText();
3728 0 : if ( !aText.isEmpty() && ! (ImplGetButtonState() & BUTTON_DRAW_NOTEXT) )
3729 : {
3730 : // subtract what will be added later
3731 0 : nMaxWidth-=2;
3732 0 : nMaxWidth -= ImplGetImageToTextDistance();
3733 :
3734 : Size aTextSize = GetTextRect( Rectangle( Point(), Size( nMaxWidth > 0 ? nMaxWidth : 0x7fffffff, 0x7fffffff ) ),
3735 0 : aText, FixedText::ImplGetTextStyle( GetStyle() ) ).GetSize();
3736 0 : aSize.Width()+=2; // for focus rect
3737 0 : aSize.Width() += ImplGetImageToTextDistance();
3738 0 : aSize.Width() += aTextSize.Width();
3739 0 : if ( aSize.Height() < aTextSize.Height() )
3740 0 : aSize.Height() = aTextSize.Height();
3741 : }
3742 : else
3743 : {
3744 : // is this still correct ? since the checkbox now
3745 : // shows a focus rect it should be 2 pixels wider and longer
3746 : /* da ansonsten im Writer die Control zu weit oben haengen
3747 : aSize.Width() += 2;
3748 : aSize.Height() += 2;
3749 : */
3750 : }
3751 :
3752 0 : return CalcWindowSize( aSize );
3753 : }
3754 :
3755 0 : Size CheckBox::GetOptimalSize() const
3756 : {
3757 0 : return CalcMinimumSize();
3758 : }
3759 :
3760 0 : ImageButton::ImageButton( Window* pParent, WinBits nStyle ) :
3761 0 : PushButton( pParent, nStyle )
3762 : {
3763 0 : ImplInitStyle();
3764 0 : }
3765 :
3766 0 : ImageButton::ImageButton( Window* pParent, const ResId& rResId ) :
3767 0 : PushButton( pParent, rResId.SetRT( RSC_IMAGEBUTTON ) )
3768 : {
3769 0 : sal_uLong nObjMask = ReadLongRes();
3770 :
3771 0 : if ( RSC_IMAGEBUTTON_IMAGE & nObjMask )
3772 : {
3773 0 : SetModeImage( Image( ResId( (RSHEADER_TYPE*)GetClassRes(), *rResId.GetResMgr() ) ) );
3774 0 : IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
3775 : }
3776 :
3777 0 : if ( RSC_IMAGEBUTTON_SYMBOL & nObjMask )
3778 0 : SetSymbol( (SymbolType)ReadLongRes() );
3779 :
3780 0 : if ( RSC_IMAGEBUTTON_STATE & nObjMask )
3781 0 : SetState( (TriState)ReadLongRes() );
3782 :
3783 0 : ImplInitStyle();
3784 0 : }
3785 :
3786 0 : ImageButton::~ImageButton()
3787 : {
3788 0 : }
3789 :
3790 0 : void ImageButton::ImplInitStyle()
3791 : {
3792 0 : WinBits nStyle = GetStyle();
3793 :
3794 0 : if ( ! ( nStyle & ( WB_RIGHT | WB_LEFT ) ) )
3795 0 : nStyle |= WB_CENTER;
3796 :
3797 0 : if ( ! ( nStyle & ( WB_TOP | WB_BOTTOM ) ) )
3798 0 : nStyle |= WB_VCENTER;
3799 :
3800 0 : SetStyle( nStyle );
3801 0 : }
3802 :
3803 0 : ImageRadioButton::ImageRadioButton( Window* pParent, WinBits nStyle ) :
3804 0 : RadioButton( pParent, nStyle )
3805 : {
3806 0 : }
3807 :
3808 0 : ImageRadioButton::~ImageRadioButton()
3809 : {
3810 0 : }
3811 :
3812 0 : TriStateBox::TriStateBox( Window* pParent, WinBits nStyle ) :
3813 0 : CheckBox( pParent, nStyle )
3814 : {
3815 0 : EnableTriState( true );
3816 0 : }
3817 :
3818 0 : TriStateBox::~TriStateBox()
3819 : {
3820 0 : }
3821 :
3822 0 : DisclosureButton::DisclosureButton( Window* pParent, WinBits nStyle ) :
3823 0 : CheckBox( pParent, nStyle )
3824 : {
3825 0 : }
3826 :
3827 0 : void DisclosureButton::ImplDrawCheckBoxState()
3828 : {
3829 : /* HACK: DisclosureButton is currently assuming, that the disclosure sign
3830 : will fit into the rectangle occupied by a normal checkbox on all themes.
3831 : If this does not hold true for some theme, ImplGetCheckImageSize
3832 : would have to be overloaded for DisclosureButton; also GetNativeControlRegion
3833 : for CTRL_LISTNODE would have to be implemented and taken into account
3834 : */
3835 :
3836 0 : Rectangle aStateRect( GetStateRect() );
3837 :
3838 0 : ImplControlValue aControlValue( GetState() == TRISTATE_TRUE ? BUTTONVALUE_ON : BUTTONVALUE_OFF );
3839 0 : Rectangle aCtrlRegion( aStateRect );
3840 0 : ControlState nState = 0;
3841 :
3842 0 : if ( HasFocus() ) nState |= CTRL_STATE_FOCUSED;
3843 0 : if ( ImplGetButtonState() & BUTTON_DRAW_DEFAULT ) nState |= CTRL_STATE_DEFAULT;
3844 0 : if ( Window::IsEnabled() ) nState |= CTRL_STATE_ENABLED;
3845 0 : if ( IsMouseOver() && GetMouseRect().IsInside( GetPointerPosPixel() ) )
3846 0 : nState |= CTRL_STATE_ROLLOVER;
3847 :
3848 0 : if( ! DrawNativeControl( CTRL_LISTNODE, PART_ENTIRE_CONTROL, aCtrlRegion, nState,
3849 0 : aControlValue, OUString() ) )
3850 : {
3851 0 : ImplSVCtrlData& rCtrlData( ImplGetSVData()->maCtrlData );
3852 0 : if( ! rCtrlData.mpDisclosurePlus )
3853 0 : rCtrlData.mpDisclosurePlus = new Image( BitmapEx( VclResId( SV_DISCLOSURE_PLUS ) ) );
3854 0 : if( ! rCtrlData.mpDisclosureMinus )
3855 0 : rCtrlData.mpDisclosureMinus = new Image( BitmapEx( VclResId( SV_DISCLOSURE_MINUS ) ) );
3856 :
3857 0 : Image* pImg = NULL;
3858 0 : pImg = IsChecked() ? rCtrlData.mpDisclosureMinus : rCtrlData.mpDisclosurePlus;
3859 :
3860 : DBG_ASSERT( pImg, "no disclosure image" );
3861 0 : if( ! pImg )
3862 0 : return;
3863 :
3864 0 : sal_uInt16 nStyle = 0;
3865 0 : if( ! IsEnabled() )
3866 0 : nStyle |= IMAGE_DRAW_DISABLE;
3867 :
3868 0 : Size aSize( aStateRect.GetSize() );
3869 0 : Size aImgSize( pImg->GetSizePixel() );
3870 0 : Point aOff( (aSize.Width() - aImgSize.Width())/2,
3871 0 : (aSize.Height() - aImgSize.Height())/2 );
3872 0 : aOff += aStateRect.TopLeft();
3873 0 : DrawImage( aOff, *pImg, nStyle );
3874 0 : }
3875 : }
3876 :
3877 0 : void DisclosureButton::KeyInput( const KeyEvent& rKEvt )
3878 : {
3879 0 : KeyCode aKeyCode = rKEvt.GetKeyCode();
3880 :
3881 0 : if( !aKeyCode.GetModifier() &&
3882 0 : ( ( aKeyCode.GetCode() == KEY_ADD ) ||
3883 0 : ( aKeyCode.GetCode() == KEY_SUBTRACT ) )
3884 : )
3885 : {
3886 0 : Check( aKeyCode.GetCode() == KEY_ADD );
3887 : }
3888 : else
3889 0 : CheckBox::KeyInput( rKEvt );
3890 3 : }
3891 :
3892 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|