Version 3.6.0.2, tag libreoffice-3.6.0.2
[LibreOffice.git] / vcl / source / window / msgbox.cxx
blob6863d2e815076adbe0ff8ae40f3634f8b4cad6dc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <tools/rc.h>
32 #include <svids.hrc>
33 #include <svdata.hxx>
34 #include <brdwin.hxx>
35 #include <window.h>
37 #include <vcl/metric.hxx>
38 #include <vcl/svapp.hxx>
39 #include <vcl/wrkwin.hxx>
40 #include <vcl/fixed.hxx>
41 #include <vcl/sound.hxx>
42 #include <vcl/msgbox.hxx>
43 #include <vcl/button.hxx>
44 #include <vcl/mnemonic.hxx>
48 // =======================================================================
50 static void ImplInitMsgBoxImageList()
52 ImplSVData* pSVData = ImplGetSVData();
53 if ( !pSVData->maWinData.mpMsgBoxImgList )
55 ResMgr* pResMgr = ImplGetResMgr();
56 pSVData->maWinData.mpMsgBoxImgList = new ImageList(4);
57 if( pResMgr )
59 Color aNonAlphaMask( 0xC0, 0xC0, 0xC0 );
60 pSVData->maWinData.mpMsgBoxImgList->InsertFromHorizontalBitmap
61 ( ResId( SV_RESID_BITMAP_MSGBOX, *pResMgr ), 4, &aNonAlphaMask );
66 // =======================================================================
68 void MessBox::ImplInitMessBoxData()
70 mpFixedText = NULL;
71 mpFixedImage = NULL;
72 mnSoundType = 0;
73 mbHelpBtn = sal_False;
74 mpCheckBox = NULL;
75 mbCheck = sal_False;
78 // -----------------------------------------------------------------------
80 void MessBox::ImplInitButtons()
82 WinBits nStyle = GetStyle();
83 sal_uInt16 nOKFlags = BUTTONDIALOG_OKBUTTON;
84 sal_uInt16 nCancelFlags = BUTTONDIALOG_CANCELBUTTON;
85 sal_uInt16 nRetryFlags = 0;
86 sal_uInt16 nYesFlags = 0;
87 sal_uInt16 nNoFlags = 0;
89 if ( nStyle & WB_OK_CANCEL )
91 if ( nStyle & WB_DEF_CANCEL )
92 nCancelFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
93 else // WB_DEF_OK
94 nOKFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
96 AddButton( BUTTON_OK, BUTTONID_OK, nOKFlags );
97 AddButton( BUTTON_CANCEL, BUTTONID_CANCEL, nCancelFlags );
99 else if ( nStyle & WB_YES_NO )
101 if ( nStyle & WB_DEF_YES )
102 nYesFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
103 else // WB_DEF_NO
104 nNoFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
105 nNoFlags |= BUTTONDIALOG_CANCELBUTTON;
107 AddButton( BUTTON_YES, BUTTONID_YES, nYesFlags );
108 AddButton( BUTTON_NO, BUTTONID_NO, nNoFlags );
110 else if ( nStyle & WB_YES_NO_CANCEL )
112 if ( nStyle & WB_DEF_YES )
113 nYesFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
114 else if ( nStyle & WB_DEF_NO )
115 nNoFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
116 else
117 nCancelFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
119 AddButton( BUTTON_YES, BUTTONID_YES, nYesFlags );
120 AddButton( BUTTON_NO, BUTTONID_NO, nNoFlags );
121 AddButton( BUTTON_CANCEL, BUTTONID_CANCEL, nCancelFlags );
123 else if ( nStyle & WB_RETRY_CANCEL )
125 if ( nStyle & WB_DEF_CANCEL )
126 nCancelFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
127 else // WB_DEF_RETRY
128 nRetryFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
130 AddButton( BUTTON_RETRY, BUTTONID_RETRY, nRetryFlags );
131 AddButton( BUTTON_CANCEL, BUTTONID_CANCEL, nCancelFlags );
133 else if ( nStyle & WB_ABORT_RETRY_IGNORE )
135 sal_uInt16 nAbortFlags = 0;
136 sal_uInt16 nIgnoreFlags = 0;
138 if ( nStyle & WB_DEF_CANCEL )
139 nAbortFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
140 else if ( nStyle & WB_DEF_RETRY )
141 nRetryFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
142 else if ( nStyle & WB_DEF_IGNORE )
143 nIgnoreFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
145 AddButton( BUTTON_ABORT, BUTTONID_CANCEL, nAbortFlags );
146 AddButton( BUTTON_RETRY, BUTTONID_RETRY, nRetryFlags );
147 AddButton( BUTTON_IGNORE, BUTTONID_IGNORE, nIgnoreFlags );
149 else if ( nStyle & WB_OK )
151 nOKFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
153 AddButton( BUTTON_OK, BUTTONID_OK, nOKFlags );
157 // -----------------------------------------------------------------------
159 MessBox::MessBox( Window* pParent, WinBits nStyle,
160 const XubString& rTitle, const XubString& rMessage ) :
161 ButtonDialog( WINDOW_MESSBOX ),
162 maMessText( rMessage )
164 ImplInitMessBoxData();
165 ImplInit( pParent, nStyle | WB_MOVEABLE | WB_HORZ | WB_CENTER );
166 ImplInitButtons();
168 if ( rTitle.Len() )
169 SetText( rTitle );
172 // -----------------------------------------------------------------------
174 MessBox::MessBox( Window* pParent, const ResId& rResId ) :
175 ButtonDialog( WINDOW_MESSBOX )
177 ImplInitMessBoxData();
179 GetRes( rResId.SetRT( RSC_MESSBOX ) );
180 sal_uInt16 nHiButtons = ReadShortRes();
181 sal_uInt16 nLoButtons = ReadShortRes();
182 sal_uInt16 nHiDefButton = ReadShortRes();
183 sal_uInt16 nLoDefButton = ReadShortRes();
184 rtl::OString aHelpId( ReadByteStringRes() );
185 /* sal_uInt16 bSysModal = */ ReadShortRes();
186 SetHelpId( aHelpId );
187 WinBits nBits = (((sal_uLong)nHiButtons << 16) + nLoButtons) |
188 (((sal_uLong)nHiDefButton << 16) + nLoDefButton);
189 ImplInit( pParent, nBits | WB_MOVEABLE | WB_HORZ | WB_CENTER );
191 ImplLoadRes( rResId );
192 ImplInitButtons();
195 // -----------------------------------------------------------------------
197 void MessBox::ImplLoadRes( const ResId& )
199 SetText( ReadStringRes() );
200 SetMessText( ReadStringRes() );
201 SetHelpText( ReadStringRes() );
204 // -----------------------------------------------------------------------
206 MessBox::~MessBox()
208 delete mpFixedText;
209 delete mpFixedImage;
210 delete mpCheckBox;
213 // -----------------------------------------------------------------------
215 void MessBox::ImplPosControls()
217 if ( !GetHelpId().isEmpty() )
219 if ( !mbHelpBtn )
221 AddButton( BUTTON_HELP, BUTTONID_HELP, BUTTONDIALOG_HELPBUTTON, 3 );
222 mbHelpBtn = sal_True;
225 else
227 if ( mbHelpBtn )
229 RemoveButton( BUTTONID_HELP );
230 mbHelpBtn = sal_False;
234 XubString aMessText( maMessText );
235 TextRectInfo aTextInfo;
236 Rectangle aRect( 0, 0, 30000, 30000 );
237 Rectangle aFormatRect;
238 Point aTextPos( IMPL_DIALOG_OFFSET, IMPL_DIALOG_OFFSET+IMPL_MSGBOX_OFFSET_EXTRA_Y );
239 Size aImageSize;
240 Size aPageSize;
241 Size aFixedSize;
242 long nTitleWidth;
243 long nButtonSize = ImplGetButtonSize();
244 long nMaxWidth = GetDesktopRectPixel().GetWidth()-8;
245 long nMaxLineWidth;
246 long nWidth;
247 WinBits nWinStyle = WB_LEFT | WB_WORDBREAK | WB_NOLABEL | WB_INFO;
248 sal_uInt16 nTextStyle = TEXT_DRAW_MULTILINE | TEXT_DRAW_TOP | TEXT_DRAW_LEFT;
250 delete mpFixedText;
251 if ( mpFixedImage )
253 delete mpFixedImage;
254 mpFixedImage = NULL;
256 if ( mpCheckBox )
258 mbCheck = mpCheckBox->IsChecked();
259 delete mpCheckBox;
260 mpCheckBox = NULL;
264 // Message-Text um Tabs bereinigen
265 XubString aTabStr( RTL_CONSTASCII_USTRINGPARAM( " " ) );
266 sal_uInt16 nIndex = 0;
267 while ( nIndex != STRING_NOTFOUND )
268 nIndex = aMessText.SearchAndReplace( '\t', aTabStr, nIndex );
270 // Wenn Fenster zu schmall, machen wir Dialog auch breiter
271 if ( mpWindowImpl->mbFrame )
272 nMaxWidth = 630;
273 else if ( nMaxWidth < 120 )
274 nMaxWidth = 120;
276 nMaxWidth -= mpWindowImpl->mnLeftBorder+mpWindowImpl->mnRightBorder+4;
278 // MessageBox sollte min. so breit sein, das auch Title sichtbar ist
279 // Extra-Width for Closer, because Closer is set after this call
280 nTitleWidth = CalcTitleWidth();
281 nTitleWidth += mpWindowImpl->mnTopBorder;
283 nMaxWidth -= (IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_X*2);
285 // Wenn wir ein Image haben, dann deren Groesse ermitteln und das
286 // entsprechende Control anlegen und positionieren
287 aImageSize = maImage.GetSizePixel();
288 if ( aImageSize.Width() )
290 aImageSize.Width() += 4;
291 aImageSize.Height() += 4;
292 aTextPos.X() += aImageSize.Width()+IMPL_SEP_MSGBOX_IMAGE;
293 mpFixedImage = new FixedImage( this );
294 mpFixedImage->SetPosSizePixel( Point( IMPL_DIALOG_OFFSET-2+IMPL_MSGBOX_OFFSET_EXTRA_X,
295 IMPL_DIALOG_OFFSET-2+IMPL_MSGBOX_OFFSET_EXTRA_Y ),
296 aImageSize );
297 mpFixedImage->SetImage( maImage );
298 mpFixedImage->Show();
299 nMaxWidth -= aImageSize.Width()+IMPL_SEP_MSGBOX_IMAGE;
301 else
302 aTextPos.X() += IMPL_MSGBOX_OFFSET_EXTRA_X;
304 // Maximale Zeilenlaenge ohne Wordbreak ermitteln
305 aFormatRect = GetTextRect( aRect, aMessText, nTextStyle, &aTextInfo );
306 nMaxLineWidth = aFormatRect.GetWidth();
307 nTextStyle |= TEXT_DRAW_WORDBREAK;
309 // Breite fuer Textformatierung ermitteln
310 if ( nMaxLineWidth > 450 )
311 nWidth = 450;
312 else if ( nMaxLineWidth > 300 )
313 nWidth = nMaxLineWidth+5;
314 else
315 nWidth = 300;
316 if ( nButtonSize > nWidth )
317 nWidth = nButtonSize-(aTextPos.X()-IMPL_DIALOG_OFFSET);
318 if ( nWidth > nMaxWidth )
319 nWidth = nMaxWidth;
321 aRect.Right() = nWidth;
322 aFormatRect = GetTextRect( aRect, aMessText, nTextStyle, &aTextInfo );
323 if ( aTextInfo.GetMaxLineWidth() > nWidth )
325 nWidth = aTextInfo.GetMaxLineWidth()+8;
326 aRect.Right() = nWidth;
327 aFormatRect = GetTextRect( aRect, aMessText, nTextStyle, &aTextInfo );
330 // Style fuer FixedText ermitteln
331 aPageSize.Width() = aImageSize.Width();
332 aFixedSize.Width() = aTextInfo.GetMaxLineWidth()+1;
333 aFixedSize.Height() = aFormatRect.GetHeight();
334 if ( aFixedSize.Height() < aImageSize.Height() )
336 nWinStyle |= WB_VCENTER;
337 aPageSize.Height() = aImageSize.Height();
338 aFixedSize.Height() = aImageSize.Height();
340 else
342 nWinStyle |= WB_TOP;
343 aPageSize.Height() = aFixedSize.Height();
345 if ( aImageSize.Width() )
346 aPageSize.Width() += IMPL_SEP_MSGBOX_IMAGE;
347 aPageSize.Width() += (IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_X*2);
348 aPageSize.Width() += aFixedSize.Width()+1;
349 aPageSize.Height() += (IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_Y*2);
351 if ( aPageSize.Width() < IMPL_MINSIZE_MSGBOX_WIDTH )
352 aPageSize.Width() = IMPL_MINSIZE_MSGBOX_WIDTH;
353 if ( aPageSize.Width() < nTitleWidth )
354 aPageSize.Width() = nTitleWidth;
356 if ( maCheckBoxText.Len() )
358 Size aMinCheckboxSize ( aFixedSize );
359 if ( aPageSize.Width() < IMPL_MINSIZE_MSGBOX_WIDTH+80 )
361 aPageSize.Width() = IMPL_MINSIZE_MSGBOX_WIDTH+80;
362 aMinCheckboxSize.Width() += 80;
365 // #104492# auto mnemonics for CJK strings may increase the length, so measure the
366 // checkbox length including a temporary mnemonic, the correct auto mnemonic will be
367 // generated later in the dialog (see init_show)
369 String aMnemonicString( maCheckBoxText );
370 if( GetSettings().GetStyleSettings().GetAutoMnemonic() )
372 if( aMnemonicString == GetNonMnemonicString( maCheckBoxText ) )
374 // no mnemonic found -> create one
375 MnemonicGenerator aMnemonicGenerator;
376 aMnemonicGenerator.CreateMnemonic( aMnemonicString );
380 mpCheckBox = new CheckBox( this );
381 mpCheckBox->Check( mbCheck );
382 mpCheckBox->SetText( aMnemonicString );
383 mpCheckBox->SetStyle( mpCheckBox->GetStyle() | WB_WORDBREAK );
384 mpCheckBox->SetHelpId( GetHelpId() ); // DR: Check box and dialog have same HID
386 // align checkbox with message text
387 Size aSize = mpCheckBox->CalcMinimumSize( aMinCheckboxSize.Width() );
389 // now set the original non-mnemonic string
390 mpCheckBox->SetText( maCheckBoxText );
392 Point aPos( aTextPos );
393 aPos.Y() += aFixedSize.Height() + (IMPL_DIALOG_OFFSET)+(IMPL_MSGBOX_OFFSET_EXTRA_Y*2);
395 // increase messagebox
396 aPageSize.Height() += aSize.Height() + (IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_Y*2);
398 mpCheckBox->SetPosSizePixel( aPos, aSize );
399 mpCheckBox->Show();
402 mpFixedText = new FixedText( this, nWinStyle );
403 if( mpFixedText->GetStyle() & WB_EXTRAOFFSET ) // TODO: use CalcMinimumSize() instead
404 aFixedSize.Width() += 2;
405 mpFixedText->SetPosSizePixel( aTextPos, aFixedSize );
406 mpFixedText->SetText( aMessText );
407 mpFixedText->Show();
408 SetPageSizePixel( aPageSize );
411 // -----------------------------------------------------------------------
413 void MessBox::StateChanged( StateChangedType nType )
415 if ( nType == STATE_CHANGE_INITSHOW )
417 ImplPosControls();
418 if ( mnSoundType )
419 Sound::Beep( (SoundType)(mnSoundType-1), this );
421 ButtonDialog::StateChanged( nType );
424 // -----------------------------------------------------------------------
426 sal_Bool MessBox::GetCheckBoxState() const
428 return mpCheckBox ? mpCheckBox->IsChecked() : mbCheck;
431 // -----------------------------------------------------------------------
433 void MessBox::SetCheckBoxState( sal_Bool bCheck )
435 if( mpCheckBox ) mpCheckBox->Check( bCheck );
436 mbCheck = bCheck;
439 // -----------------------------------------------------------------------
441 Size MessBox::GetOptimalSize(WindowSizeType eType) const
443 switch( eType ) {
444 case WINDOWSIZE_MINIMUM:
445 // FIXME: base me on the font size ?
446 return Size( 250, 100 );
447 default:
448 return Window::GetOptimalSize( eType );
452 // ============================================================================
454 void InfoBox::ImplInitInfoBoxData()
456 // Default Text is the display title from the application
457 if ( !GetText().Len() )
458 SetText( Application::GetDisplayName() );
460 SetImage( InfoBox::GetStandardImage() );
461 mnSoundType = ((sal_uInt16)SOUND_INFO)+1;
464 // -----------------------------------------------------------------------
466 InfoBox::InfoBox( Window* pParent, const XubString& rMessage ) :
467 MessBox( pParent, WB_OK | WB_DEF_OK, ImplGetSVEmptyStr(), rMessage )
469 ImplInitInfoBoxData();
472 // -----------------------------------------------------------------------
474 InfoBox::InfoBox( Window* pParent, const ResId & rResId ) :
475 MessBox( pParent, rResId.SetRT( RSC_INFOBOX ) )
477 ImplInitInfoBoxData();
480 // -----------------------------------------------------------------------
482 Image InfoBox::GetStandardImage()
484 ImplInitMsgBoxImageList();
485 return ImplGetSVData()->maWinData.mpMsgBoxImgList->GetImage( 4 );
488 // ============================================================================
490 void WarningBox::ImplInitWarningBoxData()
492 // Default Text is the display title from the application
493 if ( !GetText().Len() )
494 SetText( Application::GetDisplayName() );
496 SetImage( WarningBox::GetStandardImage() );
497 mnSoundType = ((sal_uInt16)SOUND_WARNING)+1;
500 // -----------------------------------------------------------------------
502 WarningBox::WarningBox( Window* pParent, WinBits nStyle,
503 const XubString& rMessage ) :
504 MessBox( pParent, nStyle, ImplGetSVEmptyStr(), rMessage )
506 ImplInitWarningBoxData();
509 // -----------------------------------------------------------------------
511 WarningBox::WarningBox( Window* pParent, const ResId& rResId ) :
512 MessBox( pParent, rResId.SetRT( RSC_WARNINGBOX ) )
514 ImplInitWarningBoxData();
517 // -----------------------------------------------------------------------
519 void WarningBox::SetDefaultCheckBoxText()
521 ResMgr* pResMgr = ImplGetResMgr();
522 if( pResMgr )
523 maCheckBoxText = ResId(SV_STDTEXT_DONTWARNAGAIN, *pResMgr).toString();
526 // -----------------------------------------------------------------------
528 Image WarningBox::GetStandardImage()
530 ImplInitMsgBoxImageList();
531 return ImplGetSVData()->maWinData.mpMsgBoxImgList->GetImage( 3 );
534 // ============================================================================
536 void ErrorBox::ImplInitErrorBoxData()
538 // Default Text is the display title from the application
539 if ( !GetText().Len() )
540 SetText( Application::GetDisplayName() );
542 SetImage( ErrorBox::GetStandardImage() );
543 mnSoundType = ((sal_uInt16)SOUND_ERROR)+1;
546 // -----------------------------------------------------------------------
548 ErrorBox::ErrorBox( Window* pParent, WinBits nStyle,
549 const XubString& rMessage ) :
550 MessBox( pParent, nStyle, ImplGetSVEmptyStr(), rMessage )
552 ImplInitErrorBoxData();
555 // -----------------------------------------------------------------------
557 ErrorBox::ErrorBox( Window* pParent, const ResId& rResId ) :
558 MessBox( pParent, rResId.SetRT( RSC_ERRORBOX ) )
560 ImplInitErrorBoxData();
563 // -----------------------------------------------------------------------
565 Image ErrorBox::GetStandardImage()
569 ImplInitMsgBoxImageList();
571 catch (const ::com::sun::star::uno::Exception &)
573 // During early bootstrap we can have no initialized
574 // ucb and hence no ability to get this image, so nop.
575 return Image();
577 return ImplGetSVData()->maWinData.mpMsgBoxImgList->GetImage( 1 );
580 // ============================================================================
582 void QueryBox::ImplInitQueryBoxData()
584 // Default Text is the display title from the application
585 if ( !GetText().Len() )
586 SetText( Application::GetDisplayName() );
588 SetImage( QueryBox::GetStandardImage() );
589 mnSoundType = ((sal_uInt16)SOUND_QUERY)+1;
592 // -----------------------------------------------------------------------
594 QueryBox::QueryBox( Window* pParent, WinBits nStyle, const XubString& rMessage ) :
595 MessBox( pParent, nStyle, ImplGetSVEmptyStr(), rMessage )
597 ImplInitQueryBoxData();
600 // -----------------------------------------------------------------------
602 QueryBox::QueryBox( Window* pParent, const ResId& rResId ) :
603 MessBox( pParent, rResId.SetRT( RSC_QUERYBOX ) )
605 ImplInitQueryBoxData();
608 // -----------------------------------------------------------------------
610 void QueryBox::SetDefaultCheckBoxText()
612 ResMgr* pResMgr = ImplGetResMgr();
613 if( pResMgr )
614 maCheckBoxText = ResId(SV_STDTEXT_DONTASKAGAIN, *pResMgr).toString();
617 // -----------------------------------------------------------------------
619 Image QueryBox::GetStandardImage()
621 ImplInitMsgBoxImageList();
622 return ImplGetSVData()->maWinData.mpMsgBoxImgList->GetImage( 2 );
625 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */