build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / vcl / source / window / msgbox.cxx
blob8248e546457f7ecf0b02c42999a83eddd5730a26
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 .
20 #include <tools/rc.h>
22 #include <svids.hrc>
23 #include <svdata.hxx>
24 #include <brdwin.hxx>
25 #include <window.h>
27 #include <vcl/textrectinfo.hxx>
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>
36 #include <vcl/settings.hxx>
38 static void ImplInitMsgBoxImageList()
40 ImplSVData* pSVData = ImplGetSVData();
41 if ( !pSVData->maWinData.mpMsgBoxImgList )
43 ResMgr* pResMgr = ImplGetResMgr();
44 pSVData->maWinData.mpMsgBoxImgList = new ImageList();
45 if( pResMgr )
47 Color aNonAlphaMask( 0xC0, 0xC0, 0xC0 );
48 pSVData->maWinData.mpMsgBoxImgList->InsertFromHorizontalBitmap
49 ( ResId( SV_RESID_BITMAP_MSGBOX, *pResMgr ), 4, &aNonAlphaMask );
54 void MessBox::ImplInitButtons()
56 WinBits nStyle = GetStyle();
57 ButtonDialogFlags nOKFlags = ButtonDialogFlags::OK;
58 ButtonDialogFlags nCancelFlags = ButtonDialogFlags::Cancel;
59 ButtonDialogFlags nRetryFlags = ButtonDialogFlags::NONE;
60 ButtonDialogFlags nYesFlags = ButtonDialogFlags::NONE;
61 ButtonDialogFlags nNoFlags = ButtonDialogFlags::NONE;
63 if ( nStyle & WB_OK_CANCEL )
65 if ( nStyle & WB_DEF_CANCEL )
66 nCancelFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
67 else // WB_DEF_OK
68 nOKFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
70 AddButton( StandardButtonType::OK, RET_OK, nOKFlags );
71 AddButton( StandardButtonType::Cancel, RET_CANCEL, nCancelFlags );
73 else if ( nStyle & WB_YES_NO )
75 if ( nStyle & WB_DEF_YES )
76 nYesFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
77 else // WB_DEF_NO
78 nNoFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
79 nNoFlags |= ButtonDialogFlags::Cancel;
81 AddButton( StandardButtonType::Yes, RET_YES, nYesFlags );
82 AddButton( StandardButtonType::No, RET_NO, nNoFlags );
84 else if ( nStyle & WB_YES_NO_CANCEL )
86 if ( nStyle & WB_DEF_YES )
87 nYesFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
88 else if ( nStyle & WB_DEF_NO )
89 nNoFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
90 else
91 nCancelFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
93 AddButton( StandardButtonType::Yes, RET_YES, nYesFlags );
94 AddButton( StandardButtonType::No, RET_NO, nNoFlags );
95 AddButton( StandardButtonType::Cancel, RET_CANCEL, nCancelFlags );
97 else if ( nStyle & WB_RETRY_CANCEL )
99 if ( nStyle & WB_DEF_CANCEL )
100 nCancelFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
101 else // WB_DEF_RETRY
102 nRetryFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
104 AddButton( StandardButtonType::Retry, RET_RETRY, nRetryFlags );
105 AddButton( StandardButtonType::Cancel, RET_CANCEL, nCancelFlags );
107 else if ( nStyle & WB_ABORT_RETRY_IGNORE )
109 ButtonDialogFlags nAbortFlags = ButtonDialogFlags::NONE;
110 ButtonDialogFlags nIgnoreFlags = ButtonDialogFlags::NONE;
112 if ( nStyle & WB_DEF_CANCEL )
113 nAbortFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
114 else if ( nStyle & WB_DEF_RETRY )
115 nRetryFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
116 else if ( nStyle & WB_DEF_IGNORE )
117 nIgnoreFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
119 AddButton( StandardButtonType::Abort, RET_CANCEL, nAbortFlags );
120 AddButton( StandardButtonType::Retry, RET_RETRY, nRetryFlags );
121 AddButton( StandardButtonType::Ignore, RET_IGNORE, nIgnoreFlags );
123 else if ( nStyle & WB_OK )
125 nOKFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
127 AddButton( StandardButtonType::OK, RET_OK, nOKFlags );
131 MessBox::MessBox( vcl::Window* pParent, WinBits nStyle,
132 const OUString& rTitle, const OUString& rMessage ) :
133 ButtonDialog( WINDOW_MESSBOX ),
134 mbHelpBtn( false ),
135 mbCheck( false ),
136 maMessText( rMessage )
138 ImplLOKNotifier(pParent);
139 ImplInit( pParent, nStyle | WB_MOVEABLE | WB_HORZ | WB_CENTER );
140 ImplInitButtons();
142 if ( !rTitle.isEmpty() )
143 SetText( rTitle );
146 MessBox::~MessBox()
148 disposeOnce();
151 void MessBox::dispose()
153 mpVCLMultiLineEdit.disposeAndClear();
154 mpFixedImage.disposeAndClear();
155 mpCheckBox.disposeAndClear();
156 ButtonDialog::dispose();
159 void MessBox::ImplPosControls()
161 if ( !GetHelpId().isEmpty() )
163 if ( !mbHelpBtn )
165 AddButton( StandardButtonType::Help, RET_HELP, ButtonDialogFlags::Help, 3 );
166 mbHelpBtn = true;
169 else
171 if ( mbHelpBtn )
173 RemoveButton( RET_HELP );
174 mbHelpBtn = false;
178 TextRectInfo aTextInfo;
179 Rectangle aRect( 0, 0, 30000, 30000 );
180 Rectangle aFormatRect;
181 Point aTextPos( IMPL_DIALOG_OFFSET, IMPL_DIALOG_OFFSET+IMPL_MSGBOX_OFFSET_EXTRA_Y );
182 Size aImageSize;
183 Size aPageSize;
184 Size aMEditSize;
185 long nTitleWidth;
186 long nButtonSize = ImplGetButtonSize();
187 long nMaxWidth = GetDesktopRectPixel().GetWidth()-8;
188 long nMaxLineWidth;
189 long nWidth;
190 WinBits nWinStyle = WB_LEFT | WB_NOLABEL;
191 DrawTextFlags nTextStyle = DrawTextFlags::MultiLine | DrawTextFlags::Top | DrawTextFlags::Left;
193 mpVCLMultiLineEdit.disposeAndClear();
194 mpFixedImage.disposeAndClear();
195 if ( mpCheckBox )
197 mbCheck = mpCheckBox->IsChecked();
198 mpCheckBox.disposeAndClear();
201 // Clean up message text with tabs
202 OUString aMessText(maMessText.replaceAll("\t", " "));
204 //If window too small, we make dialog box be wider
205 if ( mpWindowImpl->mbFrame )
207 nMaxWidth = 630 * GetDPIScaleFactor();
209 else if ( nMaxWidth < 120 )
210 nMaxWidth = 120;
212 nMaxWidth -= mpWindowImpl->mnLeftBorder+mpWindowImpl->mnRightBorder+4;
214 // MessagBox should be at least as wide as to see the title
215 // Extra-Width for Close button, because Close button is set after this call
216 nTitleWidth = CalcTitleWidth();
217 nTitleWidth += mpWindowImpl->mnTopBorder;
219 nMaxWidth -= (IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_X*2);
221 // for an image, get its size, create a suitable control and position it
222 aImageSize = maImage.GetSizePixel();
223 if ( aImageSize.Width() )
225 aImageSize.Width() += 4;
226 aImageSize.Height() += 4;
227 aTextPos.X() += aImageSize.Width()+IMPL_SEP_MSGBOX_IMAGE;
228 mpFixedImage = VclPtr<FixedImage>::Create( this );
229 mpFixedImage->SetPosSizePixel( Point( IMPL_DIALOG_OFFSET-2+IMPL_MSGBOX_OFFSET_EXTRA_X,
230 IMPL_DIALOG_OFFSET-2+IMPL_MSGBOX_OFFSET_EXTRA_Y ),
231 aImageSize );
232 mpFixedImage->SetImage( maImage );
233 mpFixedImage->Show();
234 nMaxWidth -= aImageSize.Width()+IMPL_SEP_MSGBOX_IMAGE;
236 else
237 aTextPos.X() += IMPL_MSGBOX_OFFSET_EXTRA_X;
239 // Determine maximum line length without wordbreak
240 aFormatRect = GetTextRect( aRect, aMessText, nTextStyle, &aTextInfo );
241 nMaxLineWidth = aFormatRect.GetWidth();
242 nTextStyle |= DrawTextFlags::WordBreak;
244 // Determine the width for text formatting
245 if ( nMaxLineWidth > 450 )
246 nWidth = 450;
247 else if ( nMaxLineWidth > 300 )
248 nWidth = nMaxLineWidth+5;
249 else
250 nWidth = 300;
252 nWidth *= GetDPIScaleFactor();
254 if ( nButtonSize > nWidth )
255 nWidth = nButtonSize-(aTextPos.X()-IMPL_DIALOG_OFFSET);
256 if ( nWidth > nMaxWidth )
257 nWidth = nMaxWidth;
259 aRect.Right() = nWidth;
260 aFormatRect = GetTextRect( aRect, aMessText, nTextStyle, &aTextInfo );
261 if ( aTextInfo.GetMaxLineWidth() > nWidth )
263 nWidth = aTextInfo.GetMaxLineWidth()+8;
264 aRect.Right() = nWidth;
265 aFormatRect = GetTextRect( aRect, aMessText, nTextStyle, &aTextInfo );
268 // get Style for VCLMultiLineEdit
269 aMEditSize.Width() = aTextInfo.GetMaxLineWidth()+1;
270 aMEditSize.Height() = aFormatRect.GetHeight();
271 aPageSize.Width() = aImageSize.Width();
272 if ( aMEditSize.Height() < aImageSize.Height() )
274 nWinStyle |= WB_VCENTER;
275 aPageSize.Height() = aImageSize.Height();
276 aMEditSize.Height() = aImageSize.Height();
278 else
280 nWinStyle |= WB_TOP;
281 aPageSize.Height() = aMEditSize.Height();
283 if ( aImageSize.Width() )
284 aPageSize.Width() += IMPL_SEP_MSGBOX_IMAGE;
285 aPageSize.Width() += (IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_X*2);
286 aPageSize.Width() += aMEditSize.Width()+1;
287 aPageSize.Height() += (IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_Y*2);
289 if ( aPageSize.Width() < IMPL_MINSIZE_MSGBOX_WIDTH )
290 aPageSize.Width() = IMPL_MINSIZE_MSGBOX_WIDTH;
291 if ( aPageSize.Width() < nTitleWidth )
292 aPageSize.Width() = nTitleWidth;
294 if ( !maCheckBoxText.isEmpty() )
296 Size aMinCheckboxSize ( aMEditSize );
297 if ( aPageSize.Width() < IMPL_MINSIZE_MSGBOX_WIDTH+80 )
299 aPageSize.Width() = IMPL_MINSIZE_MSGBOX_WIDTH+80;
300 aMinCheckboxSize.Width() += 80;
303 // #104492# auto mnemonics for CJK strings may increase the length, so measure the
304 // checkbox length including a temporary mnemonic, the correct auto mnemonic will be
305 // generated later in the dialog (see init_show)
307 OUString aMnemonicString( maCheckBoxText );
308 if( GetSettings().GetStyleSettings().GetAutoMnemonic() )
310 if( aMnemonicString == GetNonMnemonicString( maCheckBoxText ) )
312 // no mnemonic found -> create one
313 MnemonicGenerator aMnemonicGenerator;
314 aMnemonicString = aMnemonicGenerator.CreateMnemonic( aMnemonicString );
318 mpCheckBox = VclPtr<CheckBox>::Create( this );
319 mpCheckBox->Check( mbCheck );
320 mpCheckBox->SetText( aMnemonicString );
321 mpCheckBox->SetStyle( mpCheckBox->GetStyle() | WB_WORDBREAK );
322 mpCheckBox->SetHelpId( GetHelpId() ); // DR: Check box and dialog have same HID
324 // align checkbox with message text
325 Size aSize = mpCheckBox->CalcMinimumSize( aMinCheckboxSize.Width() );
327 // now set the original non-mnemonic string
328 mpCheckBox->SetText( maCheckBoxText );
330 Point aPos( aTextPos );
331 aPos.Y() += aMEditSize.Height() + (IMPL_DIALOG_OFFSET)+(IMPL_MSGBOX_OFFSET_EXTRA_Y*2);
333 // increase messagebox
334 aPageSize.Height() += aSize.Height() + (IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_Y*2);
336 mpCheckBox->SetPosSizePixel( aPos, aSize );
337 mpCheckBox->Show();
340 mpVCLMultiLineEdit = VclPtr<VclMultiLineEdit>::Create( this, nWinStyle );
341 mpVCLMultiLineEdit->SetText( aMessText );
342 mpVCLMultiLineEdit->SetPosSizePixel( aTextPos, aMEditSize );
343 mpVCLMultiLineEdit->Show();
344 mpVCLMultiLineEdit->SetPaintTransparent(true);
345 mpVCLMultiLineEdit->EnableCursor(false);
346 SetPageSizePixel( aPageSize );
349 void MessBox::StateChanged( StateChangedType nType )
351 if ( nType == StateChangedType::InitShow )
353 ImplPosControls();
355 ButtonDialog::StateChanged( nType );
358 bool MessBox::GetCheckBoxState() const
360 return mpCheckBox ? mpCheckBox->IsChecked() : mbCheck;
363 void MessBox::SetCheckBoxState( bool bCheck )
365 if( mpCheckBox ) mpCheckBox->Check( bCheck );
366 mbCheck = bCheck;
369 Size MessBox::GetOptimalSize() const
371 // FIXME: base me on the font size ?
372 return Size( 250, 100 );
375 InfoBox::InfoBox( vcl::Window* pParent, const OUString& rMessage ) :
376 MessBox( pParent, WB_OK | WB_DEF_OK, OUString(), rMessage )
378 // Default Text is the display title from the application
379 if ( GetText().isEmpty() )
380 SetText( Application::GetDisplayName() );
382 SetImage( InfoBox::GetStandardImage() );
385 InfoBox::InfoBox( vcl::Window* pParent, WinBits nStyle, const OUString& rMessage ) :
386 MessBox( pParent, nStyle, OUString(), rMessage )
388 // Default Text is the display title from the application
389 if ( GetText().isEmpty() )
390 SetText( Application::GetDisplayName() );
392 SetImage( InfoBox::GetStandardImage() );
395 Image InfoBox::GetStandardImage()
397 ImplInitMsgBoxImageList();
398 return ImplGetSVData()->maWinData.mpMsgBoxImgList->GetImage( 4 );
401 WarningBox::WarningBox( vcl::Window* pParent, WinBits nStyle,
402 const OUString& rMessage ) :
403 MessBox( pParent, nStyle, OUString(), rMessage )
405 // Default Text is the display title from the application
406 if ( GetText().isEmpty() )
407 SetText( Application::GetDisplayName() );
409 SetImage( WarningBox::GetStandardImage() );
412 void WarningBox::SetDefaultCheckBoxText()
414 ResMgr* pResMgr = ImplGetResMgr();
415 if( pResMgr )
416 maCheckBoxText = ResId(SV_STDTEXT_DONTWARNAGAIN, *pResMgr).toString();
419 Image WarningBox::GetStandardImage()
421 ImplInitMsgBoxImageList();
422 return ImplGetSVData()->maWinData.mpMsgBoxImgList->GetImage( 3 );
425 ErrorBox::ErrorBox( vcl::Window* pParent, WinBits nStyle,
426 const OUString& rMessage ) :
427 MessBox( pParent, nStyle, OUString(), rMessage )
429 // Default Text is the display title from the application
430 if ( GetText().isEmpty() )
431 SetText( Application::GetDisplayName() );
433 SetImage( ErrorBox::GetStandardImage() );
436 Image ErrorBox::GetStandardImage()
440 ImplInitMsgBoxImageList();
442 catch (const css::uno::Exception &)
444 // During early bootstrap we can have no initialized
445 // ucb and hence no ability to get this image, so nop.
446 return Image();
448 return ImplGetSVData()->maWinData.mpMsgBoxImgList->GetImage( 1 );
451 QueryBox::QueryBox( vcl::Window* pParent, WinBits nStyle, const OUString& rMessage ) :
452 MessBox( pParent, nStyle, OUString(), rMessage )
454 // Default Text is the display title from the application
455 if ( GetText().isEmpty() )
456 SetText( Application::GetDisplayName() );
458 SetImage( QueryBox::GetStandardImage() );
461 void QueryBox::SetDefaultCheckBoxText()
463 ResMgr* pResMgr = ImplGetResMgr();
464 if( pResMgr )
465 maCheckBoxText = ResId(SV_STDTEXT_DONTASKAGAIN, *pResMgr).toString();
468 Image QueryBox::GetStandardImage()
470 ImplInitMsgBoxImageList();
471 return ImplGetSVData()->maWinData.mpMsgBoxImgList->GetImage( 2 );
474 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */