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 .
20 #include <com/sun/star/beans/XPropertySet.hpp>
21 #include <com/sun/star/util/PathSettings.hpp>
22 #include <comphelper/processfactory.hxx>
23 #include <osl/file.hxx>
25 #include <tools/debug.hxx>
32 #include <rtl/strbuf.hxx>
33 #include <sal/log.hxx>
35 #include <vcl/builder.hxx>
36 #include <vcl/layout.hxx>
37 #include <vcl/svapp.hxx>
38 #include <vcl/event.hxx>
39 #include <vcl/wrkwin.hxx>
40 #include <vcl/button.hxx>
41 #include <vcl/mnemonic.hxx>
42 #include <vcl/dialog.hxx>
43 #include <vcl/decoview.hxx>
44 #include <vcl/msgbox.hxx>
45 #include <vcl/unowrap.hxx>
49 #include <osl/detail/android-bootstrap.h>
52 // =======================================================================
54 static OString
ImplGetDialogText( Dialog
* pDialog
)
56 OStringBuffer
aErrorStr(OUStringToOString(
57 pDialog
->GetText(), RTL_TEXTENCODING_UTF8
));
58 if ( (pDialog
->GetType() == WINDOW_MESSBOX
) ||
59 (pDialog
->GetType() == WINDOW_INFOBOX
) ||
60 (pDialog
->GetType() == WINDOW_WARNINGBOX
) ||
61 (pDialog
->GetType() == WINDOW_ERRORBOX
) ||
62 (pDialog
->GetType() == WINDOW_QUERYBOX
) )
64 aErrorStr
.append(", ");
65 aErrorStr
.append(OUStringToOString(
66 ((MessBox
*)pDialog
)->GetMessText(), RTL_TEXTENCODING_UTF8
));
68 return aErrorStr
.makeStringAndClear();
71 // =======================================================================
73 static sal_Bool
ImplIsMnemonicCtrl( Window
* pWindow
)
75 if( ! pWindow
->GetSettings().GetStyleSettings().GetAutoMnemonic() )
78 if ( (pWindow
->GetType() == WINDOW_RADIOBUTTON
) ||
79 (pWindow
->GetType() == WINDOW_CHECKBOX
) ||
80 (pWindow
->GetType() == WINDOW_TRISTATEBOX
) ||
81 (pWindow
->GetType() == WINDOW_PUSHBUTTON
) )
84 if ( pWindow
->GetType() == WINDOW_FIXEDTEXT
)
86 if ( pWindow
->GetStyle() & (WB_INFO
| WB_NOLABEL
) )
88 Window
* pNextWindow
= pWindow
->GetWindow( WINDOW_NEXT
);
91 pNextWindow
= pNextWindow
->GetWindow( WINDOW_CLIENT
);
92 if ( !(pNextWindow
->GetStyle() & WB_TABSTOP
) ||
93 (pNextWindow
->GetType() == WINDOW_FIXEDTEXT
) ||
94 (pNextWindow
->GetType() == WINDOW_GROUPBOX
) ||
95 (pNextWindow
->GetType() == WINDOW_RADIOBUTTON
) ||
96 (pNextWindow
->GetType() == WINDOW_CHECKBOX
) ||
97 (pNextWindow
->GetType() == WINDOW_TRISTATEBOX
) ||
98 (pNextWindow
->GetType() == WINDOW_PUSHBUTTON
) )
107 // -----------------------------------------------------------------------
109 // Called by native error dialog popup implementations
110 void ImplHideSplash()
112 ImplSVData
* pSVData
= ImplGetSVData();
113 if( pSVData
->mpIntroWindow
)
114 pSVData
->mpIntroWindow
->Hide();
117 //Get next window after pChild of a pTopLevel window as
118 //if any intermediate layout widgets didn't exist
119 Window
* nextLogicalChildOfParent(Window
*pTopLevel
, Window
*pChild
)
121 Window
*pLastChild
= pChild
;
123 if (isContainerWindow(*pChild
))
124 pChild
= pChild
->GetWindow(WINDOW_FIRSTCHILD
);
126 pChild
= pChild
->GetWindow(WINDOW_NEXT
);
130 Window
*pParent
= pLastChild
->GetParent();
133 if (pParent
== pTopLevel
)
135 pLastChild
= pParent
;
136 pChild
= pParent
->GetWindow(WINDOW_NEXT
);
139 if (pChild
&& isContainerWindow(*pChild
))
140 pChild
= nextLogicalChildOfParent(pTopLevel
, pChild
);
145 Window
* prevLogicalChildOfParent(Window
*pTopLevel
, Window
*pChild
)
147 Window
*pLastChild
= pChild
;
149 if (isContainerWindow(*pChild
))
150 pChild
= pChild
->GetWindow(WINDOW_LASTCHILD
);
152 pChild
= pChild
->GetWindow(WINDOW_PREV
);
156 Window
*pParent
= pLastChild
->GetParent();
159 if (pParent
== pTopLevel
)
161 pLastChild
= pParent
;
162 pChild
= pParent
->GetWindow(WINDOW_PREV
);
165 if (pChild
&& isContainerWindow(*pChild
))
166 pChild
= prevLogicalChildOfParent(pTopLevel
, pChild
);
171 //Get first window of a pTopLevel window as
172 //if any intermediate layout widgets didn't exist
173 Window
* firstLogicalChildOfParent(Window
*pTopLevel
)
175 Window
*pChild
= pTopLevel
->GetWindow(WINDOW_FIRSTCHILD
);
176 if (pChild
&& isContainerWindow(*pChild
))
177 pChild
= nextLogicalChildOfParent(pTopLevel
, pChild
);
181 // -----------------------------------------------------------------------
183 void ImplWindowAutoMnemonic( Window
* pWindow
)
185 MnemonicGenerator aMnemonicGenerator
;
189 // Die schon vergebenen Mnemonics registieren
190 pGetChild
= pWindow
->GetWindow( WINDOW_FIRSTCHILD
);
193 pChild
= pGetChild
->ImplGetWindow();
194 aMnemonicGenerator
.RegisterMnemonic( pChild
->GetText() );
195 pGetChild
= nextLogicalChildOfParent(pWindow
, pGetChild
);
198 // Bei TabPages auch noch die Controls vom Dialog beruecksichtigen
199 if ( pWindow
->GetType() == WINDOW_TABPAGE
)
201 Window
* pParent
= pWindow
->GetParent();
202 if ( pParent
->GetType() == WINDOW_TABCONTROL
)
203 pParent
= pParent
->GetParent();
205 if ( (pParent
->GetStyle() & (WB_DIALOGCONTROL
| WB_NODIALOGCONTROL
)) == WB_DIALOGCONTROL
)
207 pGetChild
= pParent
->GetWindow( WINDOW_FIRSTCHILD
);
210 pChild
= pGetChild
->ImplGetWindow();
211 aMnemonicGenerator
.RegisterMnemonic( pChild
->GetText() );
212 pGetChild
= nextLogicalChildOfParent(pWindow
, pGetChild
);
217 // Die Mnemonics an die Controls vergeben, die noch keinen haben
218 pGetChild
= pWindow
->GetWindow( WINDOW_FIRSTCHILD
);
221 pChild
= pGetChild
->ImplGetWindow();
222 if ( ImplIsMnemonicCtrl( pChild
) )
224 XubString aText
= pChild
->GetText();
225 if ( aMnemonicGenerator
.CreateMnemonic( aText
) )
226 pChild
->SetText( aText
);
229 pGetChild
= nextLogicalChildOfParent(pWindow
, pGetChild
);
233 static VclButtonBox
* getActionArea(Dialog
*pDialog
)
235 VclButtonBox
*pButtonBox
= NULL
;
236 if (pDialog
->isLayoutEnabled())
238 Window
*pBox
= pDialog
->GetWindow(WINDOW_FIRSTCHILD
);
239 Window
*pChild
= pBox
->GetWindow(WINDOW_LASTCHILD
);
242 pButtonBox
= dynamic_cast<VclButtonBox
*>(pChild
);
245 pChild
= pChild
->GetWindow(WINDOW_PREV
);
251 static Window
* getActionAreaButtonList(Dialog
*pDialog
)
253 VclButtonBox
* pButtonBox
= getActionArea(pDialog
);
255 return pButtonBox
->GetWindow(WINDOW_FIRSTCHILD
);
256 return pDialog
->GetWindow(WINDOW_FIRSTCHILD
);
259 // =======================================================================
261 static PushButton
* ImplGetDefaultButton( Dialog
* pDialog
)
263 Window
* pChild
= getActionAreaButtonList(pDialog
);
266 if ( pChild
->ImplIsPushButton() )
268 PushButton
* pPushButton
= (PushButton
*)pChild
;
269 if ( pPushButton
->ImplIsDefButton() )
273 pChild
= pChild
->GetWindow( WINDOW_NEXT
);
279 // -----------------------------------------------------------------------
281 static PushButton
* ImplGetOKButton( Dialog
* pDialog
)
283 Window
* pChild
= getActionAreaButtonList(pDialog
);
286 if ( pChild
->GetType() == WINDOW_OKBUTTON
)
287 return (PushButton
*)pChild
;
289 pChild
= pChild
->GetWindow( WINDOW_NEXT
);
295 // -----------------------------------------------------------------------
297 static PushButton
* ImplGetCancelButton( Dialog
* pDialog
)
299 Window
* pChild
= getActionAreaButtonList(pDialog
);
303 if ( pChild
->GetType() == WINDOW_CANCELBUTTON
)
304 return (PushButton
*)pChild
;
306 pChild
= pChild
->GetWindow( WINDOW_NEXT
);
312 // -----------------------------------------------------------------------
314 static void ImplMouseAutoPos( Dialog
* pDialog
)
316 sal_uLong nMouseOptions
= pDialog
->GetSettings().GetMouseSettings().GetOptions();
317 if ( nMouseOptions
& MOUSE_OPTION_AUTOCENTERPOS
)
319 Size aSize
= pDialog
->GetOutputSizePixel();
320 pDialog
->SetPointerPosPixel( Point( aSize
.Width()/2, aSize
.Height()/2 ) );
322 else if ( nMouseOptions
& MOUSE_OPTION_AUTODEFBTNPOS
)
324 Window
* pWindow
= ImplGetDefaultButton( pDialog
);
326 pWindow
= ImplGetOKButton( pDialog
);
328 pWindow
= ImplGetCancelButton( pDialog
);
331 Size aSize
= pWindow
->GetOutputSizePixel();
332 pWindow
->SetPointerPosPixel( Point( aSize
.Width()/2, aSize
.Height()/2 ) );
336 // =======================================================================
344 DialogImpl() : mnResult( -1 ), mbStartedModal( false ) {}
347 // =======================================================================
349 void Dialog::ImplInitDialogData()
351 mpWindowImpl
->mbDialog
= sal_True
;
352 mpDialogParent
= NULL
;
353 mpPrevExecuteDlg
= NULL
;
354 mbInExecute
= sal_False
;
355 mbOldSaveBack
= sal_False
;
356 mbInClose
= sal_False
;
357 mbModalMode
= sal_False
;
358 mpContentArea
= NULL
;
360 mbIsCalculatingInitialLayoutSize
= false;
361 mnMousePositioned
= 0;
362 mpDialogImpl
= new DialogImpl
;
364 //To-Do, reuse maResizeTimer
365 maLayoutTimer
.SetTimeout(50);
366 maLayoutTimer
.SetTimeoutHdl( LINK( this, Dialog
, ImplHandleLayoutTimerHdl
) );
369 // -----------------------------------------------------------------------
371 void Dialog::ImplInit( Window
* pParent
, WinBits nStyle
)
373 sal_uInt16 nSysWinMode
= Application::GetSystemWindowMode();
375 if ( !(nStyle
& WB_NODIALOGCONTROL
) )
376 nStyle
|= WB_DIALOGCONTROL
;
377 nStyle
|= WB_ROLLABLE
;
379 // Now, all Dialogs are per default system windows !!!
380 nStyle
|= WB_SYSTEMWINDOW
;
383 // parent is NULL: get the default Dialog parent
386 pParent
= Application::GetDefDialogParent();
387 if ( !pParent
&& !(nStyle
& WB_SYSTEMWINDOW
) )
388 pParent
= ImplGetSVData()->maWinData
.mpAppWin
;
390 // If Parent is disabled, then we search for a modal dialog
392 if ( pParent
&& (!pParent
->IsInputEnabled() || pParent
->IsInModalMode()) )
394 ImplSVData
* pSVData
= ImplGetSVData();
395 Dialog
* pExeDlg
= pSVData
->maWinData
.mpLastExecuteDlg
;
398 // Nur wenn er sichtbar und enabled ist
399 if ( pParent
->ImplGetFirstOverlapWindow()->IsWindowOrChild( pExeDlg
, sal_True
) &&
400 pExeDlg
->IsReallyVisible() &&
401 pExeDlg
->IsEnabled() && pExeDlg
->IsInputEnabled() && !pExeDlg
->IsInModalMode() )
407 pExeDlg
= pExeDlg
->mpPrevExecuteDlg
;
411 // DIALOG_NO_PARENT: explicitly don't have a parent for this Dialog
412 else if( pParent
== DIALOG_NO_PARENT
)
416 if ( !pParent
|| (nStyle
& WB_SYSTEMWINDOW
) ||
417 (pParent
->mpWindowImpl
->mpFrameData
->mbNeedSysWindow
&& !(nSysWinMode
& SYSTEMWINDOW_MODE_NOAUTOMODE
)) ||
418 (nSysWinMode
& SYSTEMWINDOW_MODE_DIALOG
) )
420 // create window with a small border ?
421 if ( (nStyle
& (WB_BORDER
| WB_NOBORDER
| WB_MOVEABLE
| WB_SIZEABLE
| WB_CLOSEABLE
)) == WB_BORDER
)
423 ImplBorderWindow
* pBorderWin
= new ImplBorderWindow( pParent
, nStyle
, BORDERWINDOW_STYLE_FRAME
);
424 SystemWindow::ImplInit( pBorderWin
, nStyle
& ~WB_BORDER
, NULL
);
425 pBorderWin
->mpWindowImpl
->mpClientWindow
= this;
426 pBorderWin
->GetBorder( mpWindowImpl
->mnLeftBorder
, mpWindowImpl
->mnTopBorder
, mpWindowImpl
->mnRightBorder
, mpWindowImpl
->mnBottomBorder
);
427 mpWindowImpl
->mpBorderWindow
= pBorderWin
;
428 mpWindowImpl
->mpRealParent
= pParent
;
432 mpWindowImpl
->mbFrame
= sal_True
;
433 mpWindowImpl
->mbOverlapWin
= sal_True
;
434 SystemWindow::ImplInit( pParent
, (nStyle
& (WB_MOVEABLE
| WB_SIZEABLE
| WB_ROLLABLE
| WB_CLOSEABLE
| WB_STANDALONE
)) | WB_CLOSEABLE
, NULL
);
435 // Now set all style bits
436 mpWindowImpl
->mnStyle
= nStyle
;
441 ImplBorderWindow
* pBorderWin
= new ImplBorderWindow( pParent
, nStyle
, BORDERWINDOW_STYLE_OVERLAP
| BORDERWINDOW_STYLE_BORDER
);
442 SystemWindow::ImplInit( pBorderWin
, nStyle
& ~WB_BORDER
, NULL
);
443 pBorderWin
->mpWindowImpl
->mpClientWindow
= this;
444 pBorderWin
->GetBorder( mpWindowImpl
->mnLeftBorder
, mpWindowImpl
->mnTopBorder
, mpWindowImpl
->mnRightBorder
, mpWindowImpl
->mnBottomBorder
);
445 mpWindowImpl
->mpBorderWindow
= pBorderWin
;
446 mpWindowImpl
->mpRealParent
= pParent
;
449 SetActivateMode( ACTIVATE_MODE_GRABFOCUS
);
454 // -----------------------------------------------------------------------
456 void Dialog::ImplInitSettings()
459 if ( IsControlBackground() )
460 SetBackground( GetControlBackground() );
462 else if( IsNativeControlSupported( CTRL_WINDOW_BACKGROUND
, PART_BACKGROUND_DIALOG
) )
464 mpWindowImpl
->mnNativeBackground
= PART_BACKGROUND_DIALOG
;
465 EnableChildTransparentMode( sal_True
);
467 // fallback to settings color
469 SetBackground( GetSettings().GetStyleSettings().GetDialogColor() );
472 // -----------------------------------------------------------------------
474 Dialog::Dialog( WindowType nType
)
475 : SystemWindow( nType
)
476 , mbIsDefferedInit(false)
478 ImplInitDialogData();
481 #define RELPATH_SHARE_LAYER OUString("soffice.cfg")
483 OUString
VclBuilderContainer::getUIRootDir()
485 /*to-do, check if user config has an override before using shared one, etc*/
486 css::uno::Reference
< css::util::XPathSettings
> xPathSettings
= css::util::PathSettings::create(
487 ::comphelper::getProcessComponentContext() );
489 OUString sShareLayer
= xPathSettings
->getBasePathShareLayer();
491 // "UIConfig" is a "multi path" ... use first part only here!
492 sal_Int32 nPos
= sShareLayer
.indexOf(';');
494 sShareLayer
= sShareLayer
.copy(0, nPos
);
496 // Note: May be an user uses URLs without a final slash! Check it ...
497 nPos
= sShareLayer
.lastIndexOf('/');
498 if (nPos
!= sShareLayer
.getLength()-1)
501 sShareLayer
+= RELPATH_SHARE_LAYER
; // folder
503 /*to-do, can we merge all this foo with existing soffice.cfg finding code, etc*/
507 //we can't change sizeable after the fact, so need to defer until we know and then
508 //do the init. Find the real parent stashed in mpDialogParent.
509 void Dialog::doDeferredInit(bool bResizable
)
511 WinBits nBits
= WB_3DLOOK
|WB_CLOSEABLE
|WB_MOVEABLE
;
513 nBits
|= WB_SIZEABLE
;
514 Window
*pParent
= mpDialogParent
;
515 mpDialogParent
= NULL
;
516 ImplInit(pParent
, nBits
);
517 mbIsDefferedInit
= false;
520 Dialog::Dialog(Window
* pParent
, const OString
& rID
, const OUString
& rUIXMLDescription
)
521 : SystemWindow( WINDOW_DIALOG
)
522 , mbIsDefferedInit(true)
524 ImplInitDialogData();
525 mpDialogParent
= pParent
; //will be unset in doDeferredInit
526 m_pUIBuilder
= new VclBuilder(this, getUIRootDir(), rUIXMLDescription
, rID
);
529 Dialog::Dialog(Window
* pParent
, const OString
& rID
, const OUString
& rUIXMLDescription
, WindowType nType
)
530 : SystemWindow( nType
)
531 , mbIsDefferedInit(true)
533 ImplInitDialogData();
534 mpDialogParent
= pParent
; //will be unset in doDeferredInit
535 m_pUIBuilder
= new VclBuilder(this, getUIRootDir(), rUIXMLDescription
, rID
);
539 // -----------------------------------------------------------------------
541 Dialog::Dialog( Window
* pParent
, WinBits nStyle
)
542 : SystemWindow( WINDOW_DIALOG
)
543 , mbIsDefferedInit(false)
545 ImplInitDialogData();
546 ImplInit( pParent
, nStyle
);
549 WinBits
Dialog::init(Window
*pParent
, const ResId
& rResId
)
551 WinBits nStyle
= ImplInitRes( rResId
);
553 ImplInit( pParent
, nStyle
);
554 ImplLoadRes( rResId
);
559 VclButtonBox
* Dialog::get_action_area()
564 void Dialog::set_action_area(VclButtonBox
* pActionArea
)
566 mpActionArea
= pActionArea
;
569 VclBox
* Dialog::get_content_area()
571 return mpContentArea
;
574 void Dialog::set_content_area(VclBox
* pContentArea
)
576 mpContentArea
= pContentArea
;
579 // -----------------------------------------------------------------------
583 maLayoutTimer
.Stop();
588 // -----------------------------------------------------------------------
590 IMPL_LINK_NOARG(Dialog
, ImplAsyncCloseHdl
)
596 // -----------------------------------------------------------------------
598 long Dialog::Notify( NotifyEvent
& rNEvt
)
600 // Zuerst Basisklasse rufen wegen TabSteuerung
601 long nRet
= SystemWindow::Notify( rNEvt
);
604 if ( rNEvt
.GetType() == EVENT_KEYINPUT
)
606 const KeyEvent
* pKEvt
= rNEvt
.GetKeyEvent();
607 KeyCode aKeyCode
= pKEvt
->GetKeyCode();
608 sal_uInt16 nKeyCode
= aKeyCode
.GetCode();
610 if ( (nKeyCode
== KEY_ESCAPE
) &&
611 ((GetStyle() & WB_CLOSEABLE
) || ImplGetCancelButton( this ) || ImplGetOKButton( this )) )
613 // #i89505# for the benefit of slightly mentally challenged implementations
614 // like e.g. SfxModelessDialog which destroy themselves inside Close()
615 // post this Close asynchronous so we can leave our key handler before
617 PostUserEvent( LINK( this, Dialog
, ImplAsyncCloseHdl
), this );
621 else if ( rNEvt
.GetType() == EVENT_GETFOCUS
)
623 // make sure the dialog is still modal
624 // changing focus between application frames may
625 // have re-enabled input for our parent
626 if( mbInExecute
&& mbModalMode
)
628 // do not change modal counter (pSVData->maAppData.mnModalDialog)
629 SetModalInputMode( sal_False
);
630 SetModalInputMode( sal_True
);
632 // #93022# def-button might have changed after show
633 if( !mnMousePositioned
)
635 mnMousePositioned
= 1;
636 ImplMouseAutoPos( this );
646 //What we really want here is something that gives the available width and
647 //height of a users screen, taking away the space taken up the OS
648 //taskbar, menus, etc.
649 Size
bestmaxFrameSizeForScreenSize(const Size
&rScreenSize
)
651 long w
= rScreenSize
.Width();
659 long h
= rScreenSize
.Height();
668 void Dialog::setOptimalLayoutSize()
670 maLayoutTimer
.Stop();
672 //resize dialog to fit requisition on initial show
673 VclBox
*pBox
= static_cast<VclBox
*>(GetWindow(WINDOW_FIRSTCHILD
));
675 const DialogStyle
& rDialogStyle
=
676 GetSettings().GetStyleSettings().GetDialogStyle();
677 pBox
->set_border_width(rDialogStyle
.content_area_border
);
678 pBox
->set_spacing(pBox
->get_spacing() +
679 rDialogStyle
.content_area_spacing
);
681 VclButtonBox
*pActionArea
= getActionArea(this);
684 pActionArea
->set_border_width(rDialogStyle
.action_area_border
);
685 pActionArea
->set_spacing(rDialogStyle
.button_spacing
);
688 Size aSize
= get_preferred_size();
690 Size
aMax(bestmaxFrameSizeForScreenSize(GetDesktopRectPixel().GetSize()));
692 aSize
.Width() = std::min(aMax
.Width(), aSize
.Width());
693 aSize
.Height() = std::min(aMax
.Height(), aSize
.Height());
695 SetMinOutputSizePixel(aSize
);
697 setPosSizeOnContainee(aSize
, *pBox
);
700 // -----------------------------------------------------------------------
702 void Dialog::StateChanged( StateChangedType nType
)
704 SystemWindow::StateChanged( nType
);
706 if ( nType
== STATE_CHANGE_INITSHOW
)
708 if ( GetSettings().GetStyleSettings().GetAutoMnemonic() )
709 ImplWindowAutoMnemonic( this );
711 if (isLayoutEnabled())
713 mbIsCalculatingInitialLayoutSize
= true;
714 setDeferredProperties();
715 setOptimalLayoutSize();
716 mbIsCalculatingInitialLayoutSize
= false;
719 if ( !HasChildPathFocus() || HasFocus() )
720 GrabFocusToFirstControl();
721 if ( !(GetStyle() & WB_CLOSEABLE
) )
723 if ( ImplGetCancelButton( this ) || ImplGetOKButton( this ) )
725 if ( ImplGetBorderWindow() )
726 ((ImplBorderWindow
*)ImplGetBorderWindow())->SetCloser();
730 ImplMouseAutoPos( this );
732 else if ( nType
== STATE_CHANGE_CONTROLBACKGROUND
)
739 // -----------------------------------------------------------------------
741 void Dialog::DataChanged( const DataChangedEvent
& rDCEvt
)
743 SystemWindow::DataChanged( rDCEvt
);
745 if ( (rDCEvt
.GetType() == DATACHANGED_SETTINGS
) &&
746 (rDCEvt
.GetFlags() & SETTINGS_STYLE
) )
753 // -----------------------------------------------------------------------
755 sal_Bool
Dialog::Close()
757 ImplDelData aDelData
;
758 ImplAddDel( &aDelData
);
759 ImplCallEventListeners( VCLEVENT_WINDOW_CLOSE
);
760 if ( aDelData
.IsDead() )
762 ImplRemoveDel( &aDelData
);
764 if ( mpWindowImpl
->mxWindowPeer
.is() && IsCreatedWithToolkit() && !IsInExecute() )
767 mbInClose
= sal_True
;
769 if ( !(GetStyle() & WB_CLOSEABLE
) )
771 sal_Bool bRet
= sal_True
;
772 ImplAddDel( &aDelData
);
773 PushButton
* pButton
= ImplGetCancelButton( this );
778 pButton
= ImplGetOKButton( this );
784 if ( aDelData
.IsDead() )
786 ImplRemoveDel( &aDelData
);
792 EndDialog( sal_False
);
793 mbInClose
= sal_False
;
798 mbInClose
= sal_False
;
799 return SystemWindow::Close();
803 // -----------------------------------------------------------------------
805 sal_Bool
Dialog::ImplStartExecuteModal()
808 // Not sure if the idea is that this will be called on Android or
809 // not? But OK, let's try to have the below code reached on
816 OStringBuffer aErrorStr
;
817 aErrorStr
.append("Dialog::StartExecuteModal() is called in Dialog::StartExecuteModal(): ");
818 aErrorStr
.append(ImplGetDialogText(this));
819 OSL_FAIL(aErrorStr
.getStr());
824 switch ( Application::GetDialogCancelMode() )
826 case Application::DIALOG_CANCEL_OFF
:
828 case Application::DIALOG_CANCEL_SILENT
:
831 "Dialog \"" << ImplGetDialogText(this).getStr()
832 << "\"cancelled in silent mode");
835 assert(false); // this cannot happen
837 case Application::DIALOG_CANCEL_FATAL
:
838 throw Application::DialogCancelledException(
839 ImplGetDialogText(this).getStr());
843 Window
* pParent
= GetParent();
846 pParent
= pParent
->ImplGetFirstOverlapWindow();
847 DBG_ASSERT( pParent
->IsReallyVisible(),
848 "Dialog::StartExecuteModal() - Parent not visible" );
849 DBG_ASSERT( pParent
->IsInputEnabled(),
850 "Dialog::StartExecuteModal() - Parent input disabled, use another parent to ensure modality!" );
851 DBG_ASSERT( ! pParent
->IsInModalMode(),
852 "Dialog::StartExecuteModal() - Parent already modally disabled, use another parent to ensure modality!" );
857 ImplSVData
* pSVData
= ImplGetSVData();
859 // Dialoge, die sich in Execute befinden, miteinander verketten
860 mpPrevExecuteDlg
= pSVData
->maWinData
.mpLastExecuteDlg
;
861 pSVData
->maWinData
.mpLastExecuteDlg
= this;
863 // Capture beenden, damit der Dialog bedient werden kann
864 if ( pSVData
->maWinData
.mpTrackWin
)
865 pSVData
->maWinData
.mpTrackWin
->EndTracking( ENDTRACK_CANCEL
);
866 if ( pSVData
->maWinData
.mpCaptureWin
)
867 pSVData
->maWinData
.mpCaptureWin
->ReleaseMouse();
868 EnableInput( sal_True
, sal_True
);
872 NotifyEvent
aNEvt( EVENT_EXECUTEDIALOG
, this );
873 GetParent()->Notify( aNEvt
);
875 mbInExecute
= sal_True
;
876 SetModalInputMode( sal_True
);
877 mbOldSaveBack
= IsSaveBackgroundEnabled();
878 EnableSaveBackground();
880 // FIXME: no layouting, workaround some clipping issues
881 ImplAdjustNWFSizes();
885 pSVData
->maAppData
.mnModalMode
++;
889 // -----------------------------------------------------------------------
891 void Dialog::ImplEndExecuteModal()
893 ImplSVData
* pSVData
= ImplGetSVData();
894 pSVData
->maAppData
.mnModalMode
--;
897 // -----------------------------------------------------------------------
899 short Dialog::Execute()
901 setDeferredProperties();
903 if ( !ImplStartExecuteModal() )
906 ImplDelData aDelData
;
907 ImplAddDel( &aDelData
);
910 ImplDelData aParentDelData
;
911 Window
* pDialogParent
= mpDialogParent
;
913 pDialogParent
->ImplAddDel( &aParentDelData
);
916 // Yield util EndDialog is called or dialog gets destroyed
917 // (the latter should not happen, but better safe than sorry
918 while ( !aDelData
.IsDead() && mbInExecute
)
919 Application::Yield();
921 ImplEndExecuteModal();
926 if( ! aParentDelData
.IsDead() )
927 pDialogParent
->ImplRemoveDel( &aParentDelData
);
929 OSL_FAIL( "Dialog::Execute() - Parent of dialog destroyed in Execute()" );
932 if ( !aDelData
.IsDead() )
933 ImplRemoveDel( &aDelData
);
937 OSL_FAIL( "Dialog::Execute() - Dialog destroyed in Execute()" );
941 long nRet
= mpDialogImpl
->mnResult
;
942 mpDialogImpl
->mnResult
= -1;
946 // -----------------------------------------------------------------------
949 void Dialog::StartExecuteModal( const Link
& rEndDialogHdl
)
951 if ( !ImplStartExecuteModal() )
954 mpDialogImpl
->maEndDialogHdl
= rEndDialogHdl
;
955 mpDialogImpl
->mbStartedModal
= true;
958 // -----------------------------------------------------------------------
960 void Dialog::EndDialog( long nResult
)
964 SetModalInputMode( sal_False
);
966 // Dialog aus der Kette der Dialoge die in Execute stehen entfernen
967 ImplSVData
* pSVData
= ImplGetSVData();
968 Dialog
* pExeDlg
= pSVData
->maWinData
.mpLastExecuteDlg
;
971 if ( pExeDlg
== this )
973 pSVData
->maWinData
.mpLastExecuteDlg
= mpPrevExecuteDlg
;
976 pExeDlg
= pExeDlg
->mpPrevExecuteDlg
;
978 // set focus to previous modal dialogue if it is modal for
979 // the same frame parent (or NULL)
980 if( mpPrevExecuteDlg
)
982 Window
* pFrameParent
= ImplGetFrameWindow()->ImplGetParent();
983 Window
* pPrevFrameParent
= mpPrevExecuteDlg
->ImplGetFrameWindow()->ImplGetParent();
984 if( ( !pFrameParent
&& !pPrevFrameParent
) ||
985 ( pFrameParent
&& pPrevFrameParent
&& pFrameParent
->ImplGetFrame() == pPrevFrameParent
->ImplGetFrame() )
988 mpPrevExecuteDlg
->GrabFocus();
991 mpPrevExecuteDlg
= NULL
;
994 EnableSaveBackground( mbOldSaveBack
);
997 NotifyEvent
aNEvt( EVENT_ENDEXECUTEDIALOG
, this );
998 GetParent()->Notify( aNEvt
);
1001 mpDialogImpl
->mnResult
= nResult
;
1003 if ( mpDialogImpl
->mbStartedModal
)
1005 ImplEndExecuteModal();
1006 mpDialogImpl
->maEndDialogHdl
.Call( this );
1008 mpDialogImpl
->maEndDialogHdl
= Link();
1009 mpDialogImpl
->mbStartedModal
= false;
1010 mpDialogImpl
->mnResult
= -1;
1012 mbInExecute
= sal_False
;
1016 // -----------------------------------------------------------------------
1018 long Dialog::GetResult() const
1020 return mpDialogImpl
->mnResult
;
1023 // -----------------------------------------------------------------------
1025 void Dialog::EndAllDialogs( Window
* pParent
)
1027 ImplSVData
* pSVData
= ImplGetSVData();
1028 Dialog
* pTempModDialog
;
1029 Dialog
* pModDialog
= pSVData
->maWinData
.mpLastExecuteDlg
;
1030 while ( pModDialog
)
1032 pTempModDialog
= pModDialog
->mpPrevExecuteDlg
;
1033 if( !pParent
|| ( pParent
&& pParent
->IsWindowOrChild( pModDialog
, sal_True
) ) )
1035 pModDialog
->EndDialog( sal_False
);
1036 pModDialog
->PostUserEvent( Link() );
1038 pModDialog
= pTempModDialog
;
1042 // -----------------------------------------------------------------------
1044 void Dialog::SetModalInputMode( sal_Bool bModal
)
1046 if ( bModal
== mbModalMode
)
1049 ImplSVData
* pSVData
= ImplGetSVData();
1050 mbModalMode
= bModal
;
1053 pSVData
->maAppData
.mnModalDialog
++;
1055 // Diable the prev Modal Dialog, because our dialog must close at first,
1056 // before the other dialog can be closed (because the other dialog
1057 // is on stack since our dialog returns)
1058 if ( mpPrevExecuteDlg
&& !mpPrevExecuteDlg
->IsWindowOrChild( this, sal_True
) )
1059 mpPrevExecuteDlg
->EnableInput( sal_False
, sal_True
, sal_True
, this );
1061 // determine next overlap dialog parent
1062 Window
* pParent
= GetParent();
1065 // #103716# dialogs should always be modal to the whole frame window
1066 // #115933# disable the whole frame hierarchie, useful if our parent
1067 // is a modeless dialog
1068 mpDialogParent
= pParent
->mpWindowImpl
->mpFrameWindow
;
1069 mpDialogParent
->ImplIncModalCount();
1075 pSVData
->maAppData
.mnModalDialog
--;
1077 if ( mpDialogParent
)
1079 // #115933# re-enable the whole frame hierarchie again (see above)
1080 // note that code in getfocus assures that we do not accidentally enable
1081 // windows that were disabled before
1082 mpDialogParent
->ImplDecModalCount();
1085 // Enable the prev Modal Dialog
1086 if ( mpPrevExecuteDlg
&& !mpPrevExecuteDlg
->IsWindowOrChild( this, sal_True
) )
1088 mpPrevExecuteDlg
->EnableInput( sal_True
, sal_True
, sal_True
, this );
1089 // ensure continued modality of prev dialog
1090 // do not change modality counter
1091 mpPrevExecuteDlg
->SetModalInputMode( sal_False
);
1092 mpPrevExecuteDlg
->SetModalInputMode( sal_True
);
1097 // -----------------------------------------------------------------------
1099 void Dialog::SetModalInputMode( sal_Bool bModal
, sal_Bool bSubModalDialogs
)
1101 if ( bSubModalDialogs
)
1103 Window
* pOverlap
= ImplGetFirstOverlapWindow();
1104 pOverlap
= pOverlap
->mpWindowImpl
->mpFirstOverlap
;
1107 if ( pOverlap
->IsDialog() )
1108 ((Dialog
*)pOverlap
)->SetModalInputMode( bModal
, sal_True
);
1109 pOverlap
= pOverlap
->mpWindowImpl
->mpNext
;
1113 SetModalInputMode( bModal
);
1116 // -----------------------------------------------------------------------
1118 void Dialog::GrabFocusToFirstControl()
1120 Window
* pFocusControl
;
1122 // Wenn Dialog den Focus hat, versuchen wr trotzdem
1123 // ein Focus-Control zu finden
1125 pFocusControl
= NULL
;
1128 // Wenn schon ein Child-Fenster mal den Focus hatte,
1129 // dann dieses bevorzugen
1130 pFocusControl
= ImplGetFirstOverlapWindow()->mpWindowImpl
->mpLastFocusWindow
;
1131 // Control aus der Dialog-Steuerung suchen
1132 if ( pFocusControl
)
1133 pFocusControl
= ImplFindDlgCtrlWindow( pFocusControl
);
1135 // Kein Control hatte vorher den Focus, oder das Control
1136 // befindet sich nicht in der Tab-Steuerung, dann das erste
1137 // Control in der TabSteuerung den Focus geben
1138 if ( !pFocusControl
||
1139 !(pFocusControl
->GetStyle() & WB_TABSTOP
) ||
1140 !isVisibleInLayout(pFocusControl
) ||
1141 !isEnabledInLayout(pFocusControl
) || !pFocusControl
->IsInputEnabled() )
1144 pFocusControl
= ImplGetDlgWindow( n
, DLGWINDOW_FIRST
);
1146 if ( pFocusControl
)
1147 pFocusControl
->ImplControlFocus( GETFOCUS_INIT
);
1150 void Dialog::GetDrawWindowBorder( sal_Int32
& rLeftBorder
, sal_Int32
& rTopBorder
, sal_Int32
& rRightBorder
, sal_Int32
& rBottomBorder
) const
1152 ImplBorderWindow
aImplWin( (Window
*)this, WB_BORDER
|WB_STDWORK
, BORDERWINDOW_STYLE_OVERLAP
);
1153 // aImplWin.SetText( GetText() );
1154 // aImplWin.SetPosSizePixel( aPos.X(), aPos.Y(), aSize.Width(), aSize.Height() );
1155 // aImplWin.SetDisplayActive( sal_True );
1156 // aImplWin.InitView();
1157 aImplWin
.GetBorder( rLeftBorder
, rTopBorder
, rRightBorder
, rBottomBorder
);
1161 void Dialog::Draw( OutputDevice
* pDev
, const Point
& rPos
, const Size
& rSize
, sal_uLong
)
1163 Point aPos
= pDev
->LogicToPixel( rPos
);
1164 Size aSize
= pDev
->LogicToPixel( rSize
);
1166 Wallpaper aWallpaper
= GetBackground();
1167 if ( !aWallpaper
.IsBitmap() )
1172 pDev
->SetLineColor();
1174 if ( aWallpaper
.IsBitmap() )
1175 pDev
->DrawBitmapEx( aPos
, aSize
, aWallpaper
.GetBitmap() );
1178 pDev
->SetFillColor( aWallpaper
.GetColor() );
1179 pDev
->DrawRect( Rectangle( aPos
, aSize
) );
1182 if (!( GetStyle() & WB_NOBORDER
))
1184 ImplBorderWindow
aImplWin( this, WB_BORDER
|WB_STDWORK
, BORDERWINDOW_STYLE_OVERLAP
);
1185 aImplWin
.SetText( GetText() );
1186 aImplWin
.setPosSizePixel( aPos
.X(), aPos
.Y(), aSize
.Width(), aSize
.Height() );
1187 aImplWin
.SetDisplayActive( sal_True
);
1188 aImplWin
.InitView();
1190 aImplWin
.Draw( Rectangle( aPos
, aSize
), pDev
, aPos
);
1196 bool Dialog::isLayoutEnabled() const
1198 //pre dtor called, and single child is a container => we're layout enabled
1199 return mpDialogImpl
? ::isLayoutEnabled(this) : false;
1202 Size
Dialog::GetOptimalSize() const
1204 if (!isLayoutEnabled())
1205 return SystemWindow::GetOptimalSize();
1207 Size aSize
= VclContainer::getLayoutRequisition(*GetWindow(WINDOW_FIRSTCHILD
));
1209 sal_Int32 nBorderWidth
= get_border_width();
1211 aSize
.Height() += mpWindowImpl
->mnLeftBorder
+ mpWindowImpl
->mnRightBorder
1213 aSize
.Width() += mpWindowImpl
->mnTopBorder
+ mpWindowImpl
->mnBottomBorder
1216 return Window::CalcWindowSize(aSize
);
1219 void Dialog::setPosSizeOnContainee(Size aSize
, VclContainer
&rBox
)
1221 sal_Int32 nBorderWidth
= get_border_width();
1223 aSize
.Width() -= mpWindowImpl
->mnLeftBorder
+ mpWindowImpl
->mnRightBorder
1225 aSize
.Height() -= mpWindowImpl
->mnTopBorder
+ mpWindowImpl
->mnBottomBorder
1228 Point
aPos(mpWindowImpl
->mnLeftBorder
+ nBorderWidth
,
1229 mpWindowImpl
->mnTopBorder
+ nBorderWidth
);
1231 VclContainer::setLayoutAllocation(rBox
, aPos
, aSize
);
1234 IMPL_LINK( Dialog
, ImplHandleLayoutTimerHdl
, void*, EMPTYARG
)
1236 if (!isLayoutEnabled())
1238 SAL_WARN("vcl.layout", "Dialog has become non-layout because extra children have been added directly to it.");
1242 VclBox
*pBox
= static_cast<VclBox
*>(GetWindow(WINDOW_FIRSTCHILD
));
1244 setPosSizeOnContainee(GetSizePixel(), *pBox
);
1248 void Dialog::queue_layout()
1250 if (hasPendingLayout() || isCalculatingInitialLayoutSize())
1254 if (!isLayoutEnabled())
1256 maLayoutTimer
.Start();
1259 void Dialog::Resize()
1264 bool Dialog::set_property(const OString
&rKey
, const OString
&rValue
)
1266 if (rKey
== "border-width")
1267 set_border_width(rValue
.toInt32());
1269 return SystemWindow::set_property(rKey
, rValue
);
1273 void Dialog::SetText(const OUString
& rStr
)
1275 setDeferredProperties();
1276 SystemWindow::SetText(rStr
);
1279 OUString
Dialog::GetText() const
1281 const_cast<Dialog
*>(this)->setDeferredProperties();
1282 return SystemWindow::GetText();
1285 VclBuilderContainer::VclBuilderContainer()
1286 : m_pUIBuilder(NULL
)
1290 VclBuilderContainer::~VclBuilderContainer()
1292 delete m_pUIBuilder
;
1295 // -----------------------------------------------------------------------
1297 ModelessDialog::ModelessDialog( Window
* pParent
, const ResId
& rResId
) :
1298 Dialog( WINDOW_MODELESSDIALOG
)
1300 rResId
.SetRT( RSC_MODELESSDIALOG
);
1302 WinBits nStyle
= init( pParent
, rResId
);
1304 if ( !(nStyle
& WB_HIDE
) )
1308 ModelessDialog::ModelessDialog( Window
* pParent
, const OString
& rID
, const OUString
& rUIXMLDescription
) :
1309 Dialog(pParent
, rID
, rUIXMLDescription
, WINDOW_MODELESSDIALOG
)
1313 // =======================================================================
1315 ModalDialog::ModalDialog( Window
* pParent
, WinBits nStyle
) :
1316 Dialog( WINDOW_MODALDIALOG
)
1318 ImplInit( pParent
, nStyle
);
1321 // -----------------------------------------------------------------------
1323 ModalDialog::ModalDialog( Window
* pParent
, const ResId
& rResId
) :
1324 Dialog( WINDOW_MODALDIALOG
)
1326 rResId
.SetRT( RSC_MODALDIALOG
);
1327 init( pParent
, rResId
);
1330 ModalDialog::ModalDialog( Window
* pParent
, const OString
& rID
, const OUString
& rUIXMLDescription
) :
1331 Dialog(pParent
, rID
, rUIXMLDescription
, WINDOW_MODALDIALOG
)
1335 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */