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 ************************************************************************/
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);
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()
73 mbHelpBtn
= 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
;
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
;
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
;
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
;
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
);
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
);
195 // -----------------------------------------------------------------------
197 void MessBox::ImplLoadRes( const ResId
& )
199 SetText( ReadStringRes() );
200 SetMessText( ReadStringRes() );
201 SetHelpText( ReadStringRes() );
204 // -----------------------------------------------------------------------
213 // -----------------------------------------------------------------------
215 void MessBox::ImplPosControls()
217 if ( !GetHelpId().isEmpty() )
221 AddButton( BUTTON_HELP
, BUTTONID_HELP
, BUTTONDIALOG_HELPBUTTON
, 3 );
222 mbHelpBtn
= sal_True
;
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
);
243 long nButtonSize
= ImplGetButtonSize();
244 long nMaxWidth
= GetDesktopRectPixel().GetWidth()-8;
247 WinBits nWinStyle
= WB_LEFT
| WB_WORDBREAK
| WB_NOLABEL
| WB_INFO
;
248 sal_uInt16 nTextStyle
= TEXT_DRAW_MULTILINE
| TEXT_DRAW_TOP
| TEXT_DRAW_LEFT
;
258 mbCheck
= mpCheckBox
->IsChecked();
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
)
273 else if ( 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
),
297 mpFixedImage
->SetImage( maImage
);
298 mpFixedImage
->Show();
299 nMaxWidth
-= aImageSize
.Width()+IMPL_SEP_MSGBOX_IMAGE
;
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 )
312 else if ( nMaxLineWidth
> 300 )
313 nWidth
= nMaxLineWidth
+5;
316 if ( nButtonSize
> nWidth
)
317 nWidth
= nButtonSize
-(aTextPos
.X()-IMPL_DIALOG_OFFSET
);
318 if ( 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();
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
);
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
);
408 SetPageSizePixel( aPageSize
);
411 // -----------------------------------------------------------------------
413 void MessBox::StateChanged( StateChangedType nType
)
415 if ( nType
== STATE_CHANGE_INITSHOW
)
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
);
439 // -----------------------------------------------------------------------
441 Size
MessBox::GetOptimalSize(WindowSizeType eType
) const
444 case WINDOWSIZE_MINIMUM
:
445 // FIXME: base me on the font size ?
446 return Size( 250, 100 );
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();
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.
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();
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: */