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