1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
28 #include <vcl/metric.hxx>
29 #include <vcl/svapp.hxx>
30 #include <vcl/wrkwin.hxx>
31 #include <vcl/fixed.hxx>
32 #include <vcl/vclmedit.hxx>
33 #include <vcl/msgbox.hxx>
34 #include <vcl/button.hxx>
35 #include <vcl/mnemonic.hxx>
39 // =======================================================================
41 static void ImplInitMsgBoxImageList()
43 ImplSVData
* pSVData
= ImplGetSVData();
44 if ( !pSVData
->maWinData
.mpMsgBoxImgList
)
46 ResMgr
* pResMgr
= ImplGetResMgr();
47 pSVData
->maWinData
.mpMsgBoxImgList
= new ImageList(4);
50 Color
aNonAlphaMask( 0xC0, 0xC0, 0xC0 );
51 pSVData
->maWinData
.mpMsgBoxImgList
->InsertFromHorizontalBitmap
52 ( ResId( SV_RESID_BITMAP_MSGBOX
, *pResMgr
), 4, &aNonAlphaMask
);
57 // =======================================================================
59 void MessBox::ImplInitMessBoxData()
61 mpVCLMultiLineEdit
= NULL
;
63 mbHelpBtn
= sal_False
;
68 // -----------------------------------------------------------------------
70 void MessBox::ImplInitButtons()
72 WinBits nStyle
= GetStyle();
73 sal_uInt16 nOKFlags
= BUTTONDIALOG_OKBUTTON
;
74 sal_uInt16 nCancelFlags
= BUTTONDIALOG_CANCELBUTTON
;
75 sal_uInt16 nRetryFlags
= 0;
76 sal_uInt16 nYesFlags
= 0;
77 sal_uInt16 nNoFlags
= 0;
79 if ( nStyle
& WB_OK_CANCEL
)
81 if ( nStyle
& WB_DEF_CANCEL
)
82 nCancelFlags
|= BUTTONDIALOG_DEFBUTTON
| BUTTONDIALOG_FOCUSBUTTON
;
84 nOKFlags
|= BUTTONDIALOG_DEFBUTTON
| BUTTONDIALOG_FOCUSBUTTON
;
86 AddButton( BUTTON_OK
, RET_OK
, nOKFlags
);
87 AddButton( BUTTON_CANCEL
, RET_CANCEL
, nCancelFlags
);
89 else if ( nStyle
& WB_YES_NO
)
91 if ( nStyle
& WB_DEF_YES
)
92 nYesFlags
|= BUTTONDIALOG_DEFBUTTON
| BUTTONDIALOG_FOCUSBUTTON
;
94 nNoFlags
|= BUTTONDIALOG_DEFBUTTON
| BUTTONDIALOG_FOCUSBUTTON
;
95 nNoFlags
|= BUTTONDIALOG_CANCELBUTTON
;
97 AddButton( BUTTON_YES
, RET_YES
, nYesFlags
);
98 AddButton( BUTTON_NO
, RET_NO
, nNoFlags
);
100 else if ( nStyle
& WB_YES_NO_CANCEL
)
102 if ( nStyle
& WB_DEF_YES
)
103 nYesFlags
|= BUTTONDIALOG_DEFBUTTON
| BUTTONDIALOG_FOCUSBUTTON
;
104 else if ( nStyle
& WB_DEF_NO
)
105 nNoFlags
|= BUTTONDIALOG_DEFBUTTON
| BUTTONDIALOG_FOCUSBUTTON
;
107 nCancelFlags
|= BUTTONDIALOG_DEFBUTTON
| BUTTONDIALOG_FOCUSBUTTON
;
109 AddButton( BUTTON_YES
, RET_YES
, nYesFlags
);
110 AddButton( BUTTON_NO
, RET_NO
, nNoFlags
);
111 AddButton( BUTTON_CANCEL
, RET_CANCEL
, nCancelFlags
);
113 else if ( nStyle
& WB_RETRY_CANCEL
)
115 if ( nStyle
& WB_DEF_CANCEL
)
116 nCancelFlags
|= BUTTONDIALOG_DEFBUTTON
| BUTTONDIALOG_FOCUSBUTTON
;
118 nRetryFlags
|= BUTTONDIALOG_DEFBUTTON
| BUTTONDIALOG_FOCUSBUTTON
;
120 AddButton( BUTTON_RETRY
, RET_RETRY
, nRetryFlags
);
121 AddButton( BUTTON_CANCEL
, RET_CANCEL
, nCancelFlags
);
123 else if ( nStyle
& WB_ABORT_RETRY_IGNORE
)
125 sal_uInt16 nAbortFlags
= 0;
126 sal_uInt16 nIgnoreFlags
= 0;
128 if ( nStyle
& WB_DEF_CANCEL
)
129 nAbortFlags
|= BUTTONDIALOG_DEFBUTTON
| BUTTONDIALOG_FOCUSBUTTON
;
130 else if ( nStyle
& WB_DEF_RETRY
)
131 nRetryFlags
|= BUTTONDIALOG_DEFBUTTON
| BUTTONDIALOG_FOCUSBUTTON
;
132 else if ( nStyle
& WB_DEF_IGNORE
)
133 nIgnoreFlags
|= BUTTONDIALOG_DEFBUTTON
| BUTTONDIALOG_FOCUSBUTTON
;
135 AddButton( BUTTON_ABORT
, RET_CANCEL
, nAbortFlags
);
136 AddButton( BUTTON_RETRY
, RET_RETRY
, nRetryFlags
);
137 AddButton( BUTTON_IGNORE
, RET_IGNORE
, nIgnoreFlags
);
139 else if ( nStyle
& WB_OK
)
141 nOKFlags
|= BUTTONDIALOG_DEFBUTTON
| BUTTONDIALOG_FOCUSBUTTON
;
143 AddButton( BUTTON_OK
, RET_OK
, nOKFlags
);
147 // -----------------------------------------------------------------------
149 MessBox::MessBox( Window
* pParent
, WinBits nStyle
,
150 const XubString
& rTitle
, const XubString
& rMessage
) :
151 ButtonDialog( WINDOW_MESSBOX
),
152 maMessText( rMessage
)
154 ImplInitMessBoxData();
155 ImplInit( pParent
, nStyle
| WB_MOVEABLE
| WB_HORZ
| WB_CENTER
);
162 // -----------------------------------------------------------------------
164 MessBox::MessBox( Window
* pParent
, const ResId
& rResId
) :
165 ButtonDialog( WINDOW_MESSBOX
)
167 ImplInitMessBoxData();
169 GetRes( rResId
.SetRT( RSC_MESSBOX
) );
170 sal_uInt16 nHiButtons
= ReadShortRes();
171 sal_uInt16 nLoButtons
= ReadShortRes();
172 sal_uInt16 nHiDefButton
= ReadShortRes();
173 sal_uInt16 nLoDefButton
= ReadShortRes();
174 OString
aHelpId( ReadByteStringRes() );
175 /* sal_uInt16 bSysModal = */ ReadShortRes();
176 SetHelpId( aHelpId
);
177 WinBits nBits
= (((sal_uLong
)nHiButtons
<< 16) + nLoButtons
) |
178 (((sal_uLong
)nHiDefButton
<< 16) + nLoDefButton
);
179 ImplInit( pParent
, nBits
| WB_MOVEABLE
| WB_HORZ
| WB_CENTER
);
181 ImplLoadRes( rResId
);
185 // -----------------------------------------------------------------------
187 void MessBox::ImplLoadRes( const ResId
& )
189 SetText( ReadStringRes() );
190 SetMessText( ReadStringRes() );
191 SetHelpText( ReadStringRes() );
194 // -----------------------------------------------------------------------
198 delete mpVCLMultiLineEdit
;
203 // -----------------------------------------------------------------------
205 void MessBox::ImplPosControls()
207 if ( !GetHelpId().isEmpty() )
211 AddButton( BUTTON_HELP
, RET_HELP
, BUTTONDIALOG_HELPBUTTON
, 3 );
212 mbHelpBtn
= sal_True
;
219 RemoveButton( RET_HELP
);
220 mbHelpBtn
= sal_False
;
224 XubString
aMessText( maMessText
);
225 TextRectInfo aTextInfo
;
226 Rectangle
aRect( 0, 0, 30000, 30000 );
227 Rectangle aFormatRect
;
228 Point
aTextPos( IMPL_DIALOG_OFFSET
, IMPL_DIALOG_OFFSET
+IMPL_MSGBOX_OFFSET_EXTRA_Y
);
233 long nButtonSize
= ImplGetButtonSize();
234 long nMaxWidth
= GetDesktopRectPixel().GetWidth()-8;
237 WinBits nWinStyle
= WB_LEFT
| WB_NOLABEL
;
238 sal_uInt16 nTextStyle
= TEXT_DRAW_MULTILINE
| TEXT_DRAW_TOP
| TEXT_DRAW_LEFT
;
240 delete mpVCLMultiLineEdit
;
248 mbCheck
= mpCheckBox
->IsChecked();
254 // Message-Text um Tabs bereinigen
255 OUString
aTabStr(" ");
256 sal_uInt16 nIndex
= 0;
257 while ( nIndex
!= STRING_NOTFOUND
)
258 nIndex
= aMessText
.SearchAndReplace( OUString('\t'), aTabStr
, nIndex
);
260 // Wenn Fenster zu schmall, machen wir Dialog auch breiter
261 if ( mpWindowImpl
->mbFrame
)
263 else if ( nMaxWidth
< 120 )
266 nMaxWidth
-= mpWindowImpl
->mnLeftBorder
+mpWindowImpl
->mnRightBorder
+4;
268 // MessageBox sollte min. so breit sein, das auch Title sichtbar ist
269 // Extra-Width for Closer, because Closer is set after this call
270 nTitleWidth
= CalcTitleWidth();
271 nTitleWidth
+= mpWindowImpl
->mnTopBorder
;
273 nMaxWidth
-= (IMPL_DIALOG_OFFSET
*2)+(IMPL_MSGBOX_OFFSET_EXTRA_X
*2);
275 // Wenn wir ein Image haben, dann deren Groesse ermitteln und das
276 // entsprechende Control anlegen und positionieren
277 aImageSize
= maImage
.GetSizePixel();
278 if ( aImageSize
.Width() )
280 aImageSize
.Width() += 4;
281 aImageSize
.Height() += 4;
282 aTextPos
.X() += aImageSize
.Width()+IMPL_SEP_MSGBOX_IMAGE
;
283 mpFixedImage
= new FixedImage( this );
284 mpFixedImage
->SetPosSizePixel( Point( IMPL_DIALOG_OFFSET
-2+IMPL_MSGBOX_OFFSET_EXTRA_X
,
285 IMPL_DIALOG_OFFSET
-2+IMPL_MSGBOX_OFFSET_EXTRA_Y
),
287 mpFixedImage
->SetImage( maImage
);
288 mpFixedImage
->Show();
289 nMaxWidth
-= aImageSize
.Width()+IMPL_SEP_MSGBOX_IMAGE
;
292 aTextPos
.X() += IMPL_MSGBOX_OFFSET_EXTRA_X
;
294 // Maximale Zeilenlaenge ohne Wordbreak ermitteln
295 aFormatRect
= GetTextRect( aRect
, aMessText
, nTextStyle
, &aTextInfo
);
296 nMaxLineWidth
= aFormatRect
.GetWidth();
297 nTextStyle
|= TEXT_DRAW_WORDBREAK
;
299 // Breite fuer Textformatierung ermitteln
300 if ( nMaxLineWidth
> 450 )
302 else if ( nMaxLineWidth
> 300 )
303 nWidth
= nMaxLineWidth
+5;
306 if ( nButtonSize
> nWidth
)
307 nWidth
= nButtonSize
-(aTextPos
.X()-IMPL_DIALOG_OFFSET
);
308 if ( nWidth
> nMaxWidth
)
311 aRect
.Right() = nWidth
;
312 aFormatRect
= GetTextRect( aRect
, aMessText
, nTextStyle
, &aTextInfo
);
313 if ( aTextInfo
.GetMaxLineWidth() > nWidth
)
315 nWidth
= aTextInfo
.GetMaxLineWidth()+8;
316 aRect
.Right() = nWidth
;
317 aFormatRect
= GetTextRect( aRect
, aMessText
, nTextStyle
, &aTextInfo
);
320 // Style fuer VCLMultiLineEdit ermitteln
321 aMEditSize
.Width() = aTextInfo
.GetMaxLineWidth()+1;
322 aMEditSize
.Height() = aFormatRect
.GetHeight();
323 aPageSize
.Width() = aImageSize
.Width();
324 if ( aMEditSize
.Height() < aImageSize
.Height() )
326 nWinStyle
|= WB_VCENTER
;
327 aPageSize
.Height() = aImageSize
.Height();
328 aMEditSize
.Height() = aImageSize
.Height();
333 aPageSize
.Height() = aMEditSize
.Height();
335 if ( aImageSize
.Width() )
336 aPageSize
.Width() += IMPL_SEP_MSGBOX_IMAGE
;
337 aPageSize
.Width() += (IMPL_DIALOG_OFFSET
*2)+(IMPL_MSGBOX_OFFSET_EXTRA_X
*2);
338 aPageSize
.Width() += aMEditSize
.Width()+1;
339 aPageSize
.Height() += (IMPL_DIALOG_OFFSET
*2)+(IMPL_MSGBOX_OFFSET_EXTRA_Y
*2);
341 if ( aPageSize
.Width() < IMPL_MINSIZE_MSGBOX_WIDTH
)
342 aPageSize
.Width() = IMPL_MINSIZE_MSGBOX_WIDTH
;
343 if ( aPageSize
.Width() < nTitleWidth
)
344 aPageSize
.Width() = nTitleWidth
;
346 if ( maCheckBoxText
.Len() )
348 Size
aMinCheckboxSize ( aMEditSize
);
349 if ( aPageSize
.Width() < IMPL_MINSIZE_MSGBOX_WIDTH
+80 )
351 aPageSize
.Width() = IMPL_MINSIZE_MSGBOX_WIDTH
+80;
352 aMinCheckboxSize
.Width() += 80;
355 // #104492# auto mnemonics for CJK strings may increase the length, so measure the
356 // checkbox length including a temporary mnemonic, the correct auto mnemonic will be
357 // generated later in the dialog (see init_show)
359 String
aMnemonicString( maCheckBoxText
);
360 if( GetSettings().GetStyleSettings().GetAutoMnemonic() )
362 if( aMnemonicString
== GetNonMnemonicString( maCheckBoxText
) )
364 // no mnemonic found -> create one
365 MnemonicGenerator aMnemonicGenerator
;
366 aMnemonicGenerator
.CreateMnemonic( aMnemonicString
);
370 mpCheckBox
= new CheckBox( this );
371 mpCheckBox
->Check( mbCheck
);
372 mpCheckBox
->SetText( aMnemonicString
);
373 mpCheckBox
->SetStyle( mpCheckBox
->GetStyle() | WB_WORDBREAK
);
374 mpCheckBox
->SetHelpId( GetHelpId() ); // DR: Check box and dialog have same HID
376 // align checkbox with message text
377 Size aSize
= mpCheckBox
->CalcMinimumSize( aMinCheckboxSize
.Width() );
379 // now set the original non-mnemonic string
380 mpCheckBox
->SetText( maCheckBoxText
);
382 Point
aPos( aTextPos
);
383 aPos
.Y() += aMEditSize
.Height() + (IMPL_DIALOG_OFFSET
)+(IMPL_MSGBOX_OFFSET_EXTRA_Y
*2);
385 // increase messagebox
386 aPageSize
.Height() += aSize
.Height() + (IMPL_DIALOG_OFFSET
*2)+(IMPL_MSGBOX_OFFSET_EXTRA_Y
*2);
388 mpCheckBox
->SetPosSizePixel( aPos
, aSize
);
392 mpVCLMultiLineEdit
= new VclMultiLineEdit( this, nWinStyle
);
393 mpVCLMultiLineEdit
->SetText( aMessText
);
394 mpVCLMultiLineEdit
->SetPosSizePixel( aTextPos
, aMEditSize
);
395 mpVCLMultiLineEdit
->Show();
396 mpVCLMultiLineEdit
->SetPaintTransparent(sal_True
);
397 mpVCLMultiLineEdit
->EnableCursor(sal_False
);
398 SetPageSizePixel( aPageSize
);
401 // -----------------------------------------------------------------------
403 void MessBox::StateChanged( StateChangedType nType
)
405 if ( nType
== STATE_CHANGE_INITSHOW
)
409 ButtonDialog::StateChanged( nType
);
412 // -----------------------------------------------------------------------
414 sal_Bool
MessBox::GetCheckBoxState() const
416 return mpCheckBox
? mpCheckBox
->IsChecked() : mbCheck
;
419 // -----------------------------------------------------------------------
421 void MessBox::SetCheckBoxState( sal_Bool bCheck
)
423 if( mpCheckBox
) mpCheckBox
->Check( bCheck
);
427 // -----------------------------------------------------------------------
429 Size
MessBox::GetOptimalSize() const
431 // FIXME: base me on the font size ?
432 return Size( 250, 100 );
435 // ============================================================================
437 void InfoBox::ImplInitInfoBoxData()
439 // Default Text is the display title from the application
440 if ( GetText().isEmpty() )
441 SetText( Application::GetDisplayName() );
443 SetImage( InfoBox::GetStandardImage() );
446 // -----------------------------------------------------------------------
448 InfoBox::InfoBox( Window
* pParent
, const OUString
& rMessage
) :
449 MessBox( pParent
, WB_OK
| WB_DEF_OK
, ImplGetSVEmptyStr(), rMessage
)
451 ImplInitInfoBoxData();
454 // -----------------------------------------------------------------------
456 InfoBox::InfoBox( Window
* pParent
, const ResId
& rResId
) :
457 MessBox( pParent
, rResId
.SetRT( RSC_INFOBOX
) )
459 ImplInitInfoBoxData();
462 // -----------------------------------------------------------------------
464 Image
InfoBox::GetStandardImage()
466 ImplInitMsgBoxImageList();
467 return ImplGetSVData()->maWinData
.mpMsgBoxImgList
->GetImage( 4 );
470 // ============================================================================
472 void WarningBox::ImplInitWarningBoxData()
474 // Default Text is the display title from the application
475 if ( GetText().isEmpty() )
476 SetText( Application::GetDisplayName() );
478 SetImage( WarningBox::GetStandardImage() );
481 // -----------------------------------------------------------------------
483 WarningBox::WarningBox( Window
* pParent
, WinBits nStyle
,
484 const XubString
& rMessage
) :
485 MessBox( pParent
, nStyle
, ImplGetSVEmptyStr(), rMessage
)
487 ImplInitWarningBoxData();
490 // -----------------------------------------------------------------------
492 WarningBox::WarningBox( Window
* pParent
, const ResId
& rResId
) :
493 MessBox( pParent
, rResId
.SetRT( RSC_WARNINGBOX
) )
495 ImplInitWarningBoxData();
498 // -----------------------------------------------------------------------
500 void WarningBox::SetDefaultCheckBoxText()
502 ResMgr
* pResMgr
= ImplGetResMgr();
504 maCheckBoxText
= ResId(SV_STDTEXT_DONTWARNAGAIN
, *pResMgr
).toString();
507 // -----------------------------------------------------------------------
509 Image
WarningBox::GetStandardImage()
511 ImplInitMsgBoxImageList();
512 return ImplGetSVData()->maWinData
.mpMsgBoxImgList
->GetImage( 3 );
515 // ============================================================================
517 void ErrorBox::ImplInitErrorBoxData()
519 // Default Text is the display title from the application
520 if ( GetText().isEmpty() )
521 SetText( Application::GetDisplayName() );
523 SetImage( ErrorBox::GetStandardImage() );
526 // -----------------------------------------------------------------------
528 ErrorBox::ErrorBox( Window
* pParent
, WinBits nStyle
,
529 const XubString
& rMessage
) :
530 MessBox( pParent
, nStyle
, ImplGetSVEmptyStr(), rMessage
)
532 ImplInitErrorBoxData();
535 // -----------------------------------------------------------------------
537 ErrorBox::ErrorBox( Window
* pParent
, const ResId
& rResId
) :
538 MessBox( pParent
, rResId
.SetRT( RSC_ERRORBOX
) )
540 ImplInitErrorBoxData();
543 // -----------------------------------------------------------------------
545 Image
ErrorBox::GetStandardImage()
549 ImplInitMsgBoxImageList();
551 catch (const ::com::sun::star::uno::Exception
&)
553 // During early bootstrap we can have no initialized
554 // ucb and hence no ability to get this image, so nop.
557 return ImplGetSVData()->maWinData
.mpMsgBoxImgList
->GetImage( 1 );
560 // ============================================================================
562 void QueryBox::ImplInitQueryBoxData()
564 // Default Text is the display title from the application
565 if ( GetText().isEmpty() )
566 SetText( Application::GetDisplayName() );
568 SetImage( QueryBox::GetStandardImage() );
571 // -----------------------------------------------------------------------
573 QueryBox::QueryBox( Window
* pParent
, WinBits nStyle
, const XubString
& rMessage
) :
574 MessBox( pParent
, nStyle
, ImplGetSVEmptyStr(), rMessage
)
576 ImplInitQueryBoxData();
579 // -----------------------------------------------------------------------
581 QueryBox::QueryBox( Window
* pParent
, const ResId
& rResId
) :
582 MessBox( pParent
, rResId
.SetRT( RSC_QUERYBOX
) )
584 ImplInitQueryBoxData();
587 // -----------------------------------------------------------------------
589 void QueryBox::SetDefaultCheckBoxText()
591 ResMgr
* pResMgr
= ImplGetResMgr();
593 maCheckBoxText
= ResId(SV_STDTEXT_DONTASKAGAIN
, *pResMgr
).toString();
596 // -----------------------------------------------------------------------
598 Image
QueryBox::GetStandardImage()
600 ImplInitMsgBoxImageList();
601 return ImplGetSVData()->maWinData
.mpMsgBoxImgList
->GetImage( 2 );
604 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */