update credits
[LibreOffice.git] / vcl / source / window / msgbox.cxx
blob28ad89224baa50273d6075d29c512e4f6ff96893
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <tools/rc.h>
23 #include <svids.hrc>
24 #include <svdata.hxx>
25 #include <brdwin.hxx>
26 #include <window.h>
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);
48 if( pResMgr )
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;
62 mpFixedImage = NULL;
63 mbHelpBtn = sal_False;
64 mpCheckBox = NULL;
65 mbCheck = 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;
83 else // WB_DEF_OK
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;
93 else // WB_DEF_NO
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;
106 else
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;
117 else // WB_DEF_RETRY
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 );
156 ImplInitButtons();
158 if ( rTitle.Len() )
159 SetText( rTitle );
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 );
182 ImplInitButtons();
185 // -----------------------------------------------------------------------
187 void MessBox::ImplLoadRes( const ResId& )
189 SetText( ReadStringRes() );
190 SetMessText( ReadStringRes() );
191 SetHelpText( ReadStringRes() );
194 // -----------------------------------------------------------------------
196 MessBox::~MessBox()
198 delete mpVCLMultiLineEdit;
199 delete mpFixedImage;
200 delete mpCheckBox;
203 // -----------------------------------------------------------------------
205 void MessBox::ImplPosControls()
207 if ( !GetHelpId().isEmpty() )
209 if ( !mbHelpBtn )
211 AddButton( BUTTON_HELP, RET_HELP, BUTTONDIALOG_HELPBUTTON, 3 );
212 mbHelpBtn = sal_True;
215 else
217 if ( mbHelpBtn )
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 );
229 Size aImageSize;
230 Size aPageSize;
231 Size aMEditSize;
232 long nTitleWidth;
233 long nButtonSize = ImplGetButtonSize();
234 long nMaxWidth = GetDesktopRectPixel().GetWidth()-8;
235 long nMaxLineWidth;
236 long nWidth;
237 WinBits nWinStyle = WB_LEFT | WB_NOLABEL;
238 sal_uInt16 nTextStyle = TEXT_DRAW_MULTILINE | TEXT_DRAW_TOP | TEXT_DRAW_LEFT;
240 delete mpVCLMultiLineEdit;
241 if ( mpFixedImage )
243 delete mpFixedImage;
244 mpFixedImage = NULL;
246 if ( mpCheckBox )
248 mbCheck = mpCheckBox->IsChecked();
249 delete mpCheckBox;
250 mpCheckBox = NULL;
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 )
262 nMaxWidth = 630;
263 else if ( nMaxWidth < 120 )
264 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 ),
286 aImageSize );
287 mpFixedImage->SetImage( maImage );
288 mpFixedImage->Show();
289 nMaxWidth -= aImageSize.Width()+IMPL_SEP_MSGBOX_IMAGE;
291 else
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 )
301 nWidth = 450;
302 else if ( nMaxLineWidth > 300 )
303 nWidth = nMaxLineWidth+5;
304 else
305 nWidth = 300;
306 if ( nButtonSize > nWidth )
307 nWidth = nButtonSize-(aTextPos.X()-IMPL_DIALOG_OFFSET);
308 if ( nWidth > nMaxWidth )
309 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();
330 else
332 nWinStyle |= WB_TOP;
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 );
389 mpCheckBox->Show();
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 )
407 ImplPosControls();
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 );
424 mbCheck = 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();
503 if( pResMgr )
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.
555 return Image();
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();
592 if( pResMgr )
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: */