summaryrefslogtreecommitdiff
path: root/vcl/source/window/dialog.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/window/dialog.cxx')
-rw-r--r--vcl/source/window/dialog.cxx1028
1 files changed, 1028 insertions, 0 deletions
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
new file mode 100644
index 000000000000..3b5585d3bc63
--- /dev/null
+++ b/vcl/source/window/dialog.cxx
@@ -0,0 +1,1028 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+#include <tools/debug.hxx>
+
+#ifndef _SV_RC_H
+#include <tools/rc.h>
+#endif
+#include <vcl/svdata.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.h>
+#include <vcl/event.hxx>
+#include <vcl/brdwin.hxx>
+#include <vcl/wrkwin.hxx>
+#include <vcl/button.hxx>
+#include <vcl/mnemonic.hxx>
+#include <vcl/dialog.hxx>
+#include <vcl/decoview.hxx>
+
+#ifdef DBG_UTIL
+#include <vcl/msgbox.hxx>
+#endif
+
+#include <vcl/unowrap.hxx>
+
+
+
+// =======================================================================
+
+#ifdef DBG_UTIL
+
+static ByteString ImplGetDialogText( Dialog* pDialog )
+{
+ ByteString aErrorStr( pDialog->GetText(), RTL_TEXTENCODING_UTF8 );
+ if ( (pDialog->GetType() == WINDOW_MESSBOX) ||
+ (pDialog->GetType() == WINDOW_INFOBOX) ||
+ (pDialog->GetType() == WINDOW_WARNINGBOX) ||
+ (pDialog->GetType() == WINDOW_ERRORBOX) ||
+ (pDialog->GetType() == WINDOW_QUERYBOX) )
+ {
+ aErrorStr += ", ";
+ aErrorStr += ByteString( ((MessBox*)pDialog)->GetMessText(), RTL_TEXTENCODING_UTF8 );
+ }
+ return aErrorStr;
+}
+
+#endif
+
+// =======================================================================
+
+static BOOL ImplIsMnemonicCtrl( Window* pWindow )
+{
+ if( ! pWindow->GetSettings().GetStyleSettings().GetAutoMnemonic() )
+ return FALSE;
+
+ if ( (pWindow->GetType() == WINDOW_RADIOBUTTON) ||
+ (pWindow->GetType() == WINDOW_CHECKBOX) ||
+ (pWindow->GetType() == WINDOW_TRISTATEBOX) ||
+ (pWindow->GetType() == WINDOW_PUSHBUTTON) )
+ return TRUE;
+
+ if ( pWindow->GetType() == WINDOW_FIXEDTEXT )
+ {
+ if ( pWindow->GetStyle() & (WB_INFO | WB_NOLABEL) )
+ return FALSE;
+ Window* pNextWindow = pWindow->GetWindow( WINDOW_NEXT );
+ if ( !pNextWindow )
+ return FALSE;
+ pNextWindow = pNextWindow->GetWindow( WINDOW_CLIENT );
+ if ( !(pNextWindow->GetStyle() & WB_TABSTOP) ||
+ (pNextWindow->GetType() == WINDOW_FIXEDTEXT) ||
+ (pNextWindow->GetType() == WINDOW_GROUPBOX) ||
+ (pNextWindow->GetType() == WINDOW_RADIOBUTTON) ||
+ (pNextWindow->GetType() == WINDOW_CHECKBOX) ||
+ (pNextWindow->GetType() == WINDOW_TRISTATEBOX) ||
+ (pNextWindow->GetType() == WINDOW_PUSHBUTTON) )
+ return FALSE;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplWindowAutoMnemonic( Window* pWindow )
+{
+ MnemonicGenerator aMnemonicGenerator;
+ Window* pGetChild;
+ Window* pChild;
+
+ // Die schon vergebenen Mnemonics registieren
+ pGetChild = pWindow->GetWindow( WINDOW_FIRSTCHILD );
+ while ( pGetChild )
+ {
+ pChild = pGetChild->ImplGetWindow();
+ aMnemonicGenerator.RegisterMnemonic( pChild->GetText() );
+ pGetChild = pGetChild->GetWindow( WINDOW_NEXT );
+ }
+
+ // Bei TabPages auch noch die Controls vom Dialog beruecksichtigen
+ if ( pWindow->GetType() == WINDOW_TABPAGE )
+ {
+ Window* pParent = pWindow->GetParent();
+ if ( pParent->GetType() == WINDOW_TABCONTROL )
+ pParent = pParent->GetParent();
+
+ if ( (pParent->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) == WB_DIALOGCONTROL )
+ {
+ pGetChild = pParent->GetWindow( WINDOW_FIRSTCHILD );
+ while ( pGetChild )
+ {
+ pChild = pGetChild->ImplGetWindow();
+ aMnemonicGenerator.RegisterMnemonic( pChild->GetText() );
+ pGetChild = pGetChild->GetWindow( WINDOW_NEXT );
+ }
+ }
+ }
+
+ // Die Mnemonics an die Controls vergeben, die noch keinen haben
+ pGetChild = pWindow->GetWindow( WINDOW_FIRSTCHILD );
+ while ( pGetChild )
+ {
+ pChild = pGetChild->ImplGetWindow();
+ if ( ImplIsMnemonicCtrl( pChild ) )
+ {
+ XubString aText = pChild->GetText();
+ if ( aMnemonicGenerator.CreateMnemonic( aText ) )
+ pChild->SetText( aText );
+ }
+
+ pGetChild = pGetChild->GetWindow( WINDOW_NEXT );
+ }
+}
+
+// =======================================================================
+
+static PushButton* ImplGetDefaultButton( Dialog* pDialog )
+{
+ Window* pChild = pDialog->GetWindow( WINDOW_FIRSTCHILD );
+ while ( pChild )
+ {
+ if ( pChild->ImplIsPushButton() )
+ {
+ PushButton* pPushButton = (PushButton*)pChild;
+ if ( pPushButton->ImplIsDefButton() )
+ return pPushButton;
+ }
+
+ pChild = pChild->GetWindow( WINDOW_NEXT );
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+static PushButton* ImplGetOKButton( Dialog* pDialog )
+{
+ Window* pChild = pDialog->GetWindow( WINDOW_FIRSTCHILD );
+ while ( pChild )
+ {
+ if ( pChild->GetType() == WINDOW_OKBUTTON )
+ return (PushButton*)pChild;
+
+ pChild = pChild->GetWindow( WINDOW_NEXT );
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+static PushButton* ImplGetCancelButton( Dialog* pDialog )
+{
+ Window* pChild = pDialog->GetWindow( WINDOW_FIRSTCHILD );
+ while ( pChild )
+ {
+ if ( pChild->GetType() == WINDOW_CANCELBUTTON )
+ return (PushButton*)pChild;
+
+ pChild = pChild->GetWindow( WINDOW_NEXT );
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplMouseAutoPos( Dialog* pDialog )
+{
+ ULONG nMouseOptions = pDialog->GetSettings().GetMouseSettings().GetOptions();
+ if ( nMouseOptions & MOUSE_OPTION_AUTOCENTERPOS )
+ {
+ Size aSize = pDialog->GetOutputSizePixel();
+ pDialog->SetPointerPosPixel( Point( aSize.Width()/2, aSize.Height()/2 ) );
+ }
+ else if ( nMouseOptions & MOUSE_OPTION_AUTODEFBTNPOS )
+ {
+ Window* pWindow = ImplGetDefaultButton( pDialog );
+ if ( !pWindow )
+ pWindow = ImplGetOKButton( pDialog );
+ if ( !pWindow )
+ pWindow = ImplGetCancelButton( pDialog );
+ if ( !pWindow )
+ pWindow = pDialog;
+ Size aSize = pWindow->GetOutputSizePixel();
+ pWindow->SetPointerPosPixel( Point( aSize.Width()/2, aSize.Height()/2 ) );
+ }
+}
+
+// =======================================================================
+
+struct DialogImpl
+{
+ long mnResult;
+ bool mbStartedModal;
+ Link maEndDialogHdl;
+
+ DialogImpl() : mnResult( -1 ), mbStartedModal( false ) {}
+};
+
+// =======================================================================
+
+void Dialog::ImplInitDialogData()
+{
+ mpWindowImpl->mbDialog = TRUE;
+ mpDialogParent = NULL;
+ mpPrevExecuteDlg = NULL;
+ mbInExecute = FALSE;
+ mbOldSaveBack = FALSE;
+ mbInClose = FALSE;
+ mbModalMode = FALSE;
+ mnMousePositioned = 0;
+ mpDialogImpl = new DialogImpl;
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::ImplInit( Window* pParent, WinBits nStyle )
+{
+ USHORT nSysWinMode = Application::GetSystemWindowMode();
+
+ if ( !(nStyle & WB_NODIALOGCONTROL) )
+ nStyle |= WB_DIALOGCONTROL;
+ nStyle |= WB_ROLLABLE;
+
+ // Now, all Dialogs are per default system windows !!!
+ nStyle |= WB_SYSTEMWINDOW;
+
+
+ // parent is NULL: get the default Dialog parent
+ if ( !pParent )
+ {
+ pParent = Application::GetDefDialogParent();
+ if ( !pParent && !(nStyle & WB_SYSTEMWINDOW) )
+ pParent = ImplGetSVData()->maWinData.mpAppWin;
+
+ // If Parent is disabled, then we search for a modal dialog
+ // in this frame
+ if ( pParent && (!pParent->IsInputEnabled() || pParent->IsInModalMode()) )
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+ Dialog* pExeDlg = pSVData->maWinData.mpLastExecuteDlg;
+ while ( pExeDlg )
+ {
+ // Nur wenn er sichtbar und enabled ist
+ if ( pParent->ImplGetFirstOverlapWindow()->IsWindowOrChild( pExeDlg, TRUE ) &&
+ pExeDlg->IsReallyVisible() &&
+ pExeDlg->IsEnabled() && pExeDlg->IsInputEnabled() && !pExeDlg->IsInModalMode() )
+ {
+ pParent = pExeDlg;
+ break;
+ }
+
+ pExeDlg = pExeDlg->mpPrevExecuteDlg;
+ }
+ }
+ }
+ // DIALOG_NO_PARENT: explicitly don't have a parent for this Dialog
+ else if( pParent == DIALOG_NO_PARENT )
+ pParent = NULL;
+
+/*
+ // Now, all Dialogs are per default system windows !!!
+ if ( pParent && !(nSysWinMode & SYSTEMWINDOW_MODE_NOAUTOMODE) )
+ {
+ if ( !pParent->mpWindowImpl->mpFrameWindow->IsVisible() )
+ pParent = NULL;
+ else
+ {
+ if ( pParent->mpWindowImpl->mpFrameWindow->IsDialog() )
+ {
+ Size aOutSize = pParent->mpWindowImpl->mpFrameWindow->GetOutputSizePixel();
+ if ( (aOutSize.Width() < 210) ||(aOutSize.Height() < 160) )
+ nStyle |= WB_SYSTEMWINDOW;
+ }
+ }
+ }
+*/
+
+ if ( !pParent || (nStyle & WB_SYSTEMWINDOW) ||
+ (pParent->mpWindowImpl->mpFrameData->mbNeedSysWindow && !(nSysWinMode & SYSTEMWINDOW_MODE_NOAUTOMODE)) ||
+ (nSysWinMode & SYSTEMWINDOW_MODE_DIALOG) )
+ {
+ // create window with a small border ?
+ if ( (nStyle & (WB_BORDER | WB_NOBORDER | WB_MOVEABLE | WB_SIZEABLE | WB_CLOSEABLE)) == WB_BORDER )
+ {
+ ImplBorderWindow* pBorderWin = new ImplBorderWindow( pParent, nStyle, BORDERWINDOW_STYLE_FRAME );
+ SystemWindow::ImplInit( pBorderWin, nStyle & ~WB_BORDER, NULL );
+ pBorderWin->mpWindowImpl->mpClientWindow = this;
+ pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
+ mpWindowImpl->mpBorderWindow = pBorderWin;
+ mpWindowImpl->mpRealParent = pParent;
+ }
+ else
+ {
+ mpWindowImpl->mbFrame = TRUE;
+ mpWindowImpl->mbOverlapWin = TRUE;
+ SystemWindow::ImplInit( pParent, (nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_CLOSEABLE | WB_STANDALONE)) | WB_CLOSEABLE, NULL );
+ // Now set all style bits
+ mpWindowImpl->mnStyle = nStyle;
+ }
+ }
+ else
+ {
+ ImplBorderWindow* pBorderWin = new ImplBorderWindow( pParent, nStyle, BORDERWINDOW_STYLE_OVERLAP | BORDERWINDOW_STYLE_BORDER );
+ SystemWindow::ImplInit( pBorderWin, nStyle & ~WB_BORDER, NULL );
+ pBorderWin->mpWindowImpl->mpClientWindow = this;
+ pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
+ mpWindowImpl->mpBorderWindow = pBorderWin;
+ mpWindowImpl->mpRealParent = pParent;
+ }
+
+ SetActivateMode( ACTIVATE_MODE_GRABFOCUS );
+
+ ImplInitSettings();
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::ImplInitSettings()
+{
+ // user override
+ if ( IsControlBackground() )
+ SetBackground( GetControlBackground() );
+ // NWF background
+ else if( IsNativeControlSupported( CTRL_WINDOW_BACKGROUND, PART_BACKGROUND_DIALOG ) )
+ {
+ mpWindowImpl->mnNativeBackground = PART_BACKGROUND_DIALOG;
+ EnableChildTransparentMode( TRUE );
+ }
+ // fallback to settings color
+ else
+ SetBackground( GetSettings().GetStyleSettings().GetDialogColor() );
+
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::ImplCenterDialog()
+{
+ Rectangle aDeskRect = ImplGetFrameWindow()->GetDesktopRectPixel();
+ Point aDeskPos = aDeskRect.TopLeft();
+ Size aDeskSize = aDeskRect.GetSize();
+ Size aWinSize = GetSizePixel();
+ Window *pWindow = this;
+ while ( pWindow->mpWindowImpl->mpBorderWindow )
+ pWindow = pWindow->mpWindowImpl->mpBorderWindow;
+ Point aWinPos( ((aDeskSize.Width() - aWinSize.Width()) / 2) + aDeskPos.X(),
+ ((aDeskSize.Height() - aWinSize.Height()) / 2) + aDeskPos.Y() );
+
+ // Pruefen, ob Dialogbox ausserhalb des Desks liegt
+ if ( (aWinPos.X() + aWinSize.Width()) > (aDeskPos.X()+aDeskSize.Width()) )
+ aWinPos.X() = aDeskPos.X()+aDeskSize.Width() - aWinSize.Width();
+ if ( (aWinPos.Y()+aWinSize.Height()) > (aDeskPos.Y()+aDeskSize.Height()) )
+ aWinPos.Y() = aDeskPos.Y()+aDeskSize.Height() - aWinSize.Height();
+ // Linke Ecke bevorzugen, da Titelbar oben ist
+ if ( aWinPos.X() < aDeskPos.X() )
+ aWinPos.X() = aDeskPos.X();
+ if ( aWinPos.Y() < aDeskPos.Y() )
+ aWinPos.Y() = aDeskPos.Y();
+
+ //SetPosPixel( aWinPos );
+ SetPosPixel( pWindow->ScreenToOutputPixel( aWinPos ) );
+}
+
+// -----------------------------------------------------------------------
+
+Dialog::Dialog( WindowType nType ) :
+ SystemWindow( nType )
+{
+ ImplInitDialogData();
+}
+
+// -----------------------------------------------------------------------
+
+Dialog::Dialog( Window* pParent, WinBits nStyle ) :
+ SystemWindow( WINDOW_DIALOG )
+{
+ ImplInitDialogData();
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+Dialog::Dialog( Window* pParent, const ResId& rResId ) :
+ SystemWindow( WINDOW_DIALOG )
+{
+ ImplInitDialogData();
+ rResId.SetRT( RSC_DIALOG );
+ ImplInit( pParent, ImplInitRes( rResId ) );
+ ImplLoadRes( rResId );
+}
+
+// -----------------------------------------------------------------------
+
+Dialog::~Dialog()
+{
+ delete mpDialogImpl;
+ mpDialogImpl = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( Dialog, ImplAsyncCloseHdl, void*, EMPTYARG )
+{
+ Close();
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+long Dialog::Notify( NotifyEvent& rNEvt )
+{
+ // Zuerst Basisklasse rufen wegen TabSteuerung
+ long nRet = SystemWindow::Notify( rNEvt );
+ if ( !nRet )
+ {
+ if ( rNEvt.GetType() == EVENT_KEYINPUT )
+ {
+ const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
+ KeyCode aKeyCode = pKEvt->GetKeyCode();
+ USHORT nKeyCode = aKeyCode.GetCode();
+
+ if ( (nKeyCode == KEY_ESCAPE) &&
+ ((GetStyle() & WB_CLOSEABLE) || ImplGetCancelButton( this ) || ImplGetOKButton( this )) )
+ {
+ // #i89505# for the benefit of slightly mentally challenged implementations
+ // like e.g. SfxModelessDialog which destroy themselves inside Close()
+ // post this Close asynchronous so we can leave our key handler before
+ // we get destroyed
+ PostUserEvent( LINK( this, Dialog, ImplAsyncCloseHdl ), this );
+ return TRUE;
+ }
+ }
+ else if ( rNEvt.GetType() == EVENT_GETFOCUS )
+ {
+ // make sure the dialog is still modal
+ // changing focus between application frames may
+ // have re-enabled input for our parent
+ if( mbInExecute && mbModalMode )
+ {
+ // do not change modal counter (pSVData->maAppData.mnModalDialog)
+ SetModalInputMode( FALSE );
+ SetModalInputMode( TRUE );
+
+ // #93022# def-button might have changed after show
+ if( !mnMousePositioned )
+ {
+ mnMousePositioned = 1;
+ ImplMouseAutoPos( this );
+ }
+
+ }
+ }
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::StateChanged( StateChangedType nType )
+{
+ SystemWindow::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_INITSHOW )
+ {
+ if ( GetSettings().GetStyleSettings().GetAutoMnemonic() )
+ ImplWindowAutoMnemonic( this );
+
+ //if ( IsDefaultPos() && !mpWindowImpl->mbFrame )
+ // ImplCenterDialog();
+ if ( !HasChildPathFocus() || HasFocus() )
+ GrabFocusToFirstControl();
+ if ( !(GetStyle() & WB_CLOSEABLE) )
+ {
+ if ( ImplGetCancelButton( this ) || ImplGetOKButton( this ) )
+ {
+ if ( ImplGetBorderWindow() )
+ ((ImplBorderWindow*)ImplGetBorderWindow())->SetCloser();
+ }
+ }
+
+ ImplMouseAutoPos( this );
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ SystemWindow::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Dialog::Close()
+{
+ ImplDelData aDelData;
+ ImplAddDel( &aDelData );
+ ImplCallEventListeners( VCLEVENT_WINDOW_CLOSE );
+ if ( aDelData.IsDelete() )
+ return FALSE;
+ ImplRemoveDel( &aDelData );
+
+ if ( mpWindowImpl->mxWindowPeer.is() && IsCreatedWithToolkit() && !IsInExecute() )
+ return FALSE;
+
+ mbInClose = TRUE;
+
+ if ( !(GetStyle() & WB_CLOSEABLE) )
+ {
+ BOOL bRet = TRUE;
+ ImplAddDel( &aDelData );
+ PushButton* pButton = ImplGetCancelButton( this );
+ if ( pButton )
+ pButton->Click();
+ else
+ {
+ pButton = ImplGetOKButton( this );
+ if ( pButton )
+ pButton->Click();
+ else
+ bRet = FALSE;
+ }
+ if ( aDelData.IsDelete() )
+ return TRUE;
+ ImplRemoveDel( &aDelData );
+ return bRet;
+ }
+
+ if ( IsInExecute() )
+ {
+ EndDialog( FALSE );
+ mbInClose = FALSE;
+ return TRUE;
+ }
+ else
+ {
+ mbInClose = FALSE;
+ return SystemWindow::Close();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Dialog::ImplStartExecuteModal()
+{
+ if ( mbInExecute )
+ {
+#ifdef DBG_UTIL
+ ByteString aErrorStr( "Dialog::StartExecuteModal() is called in Dialog::StartExecuteModal(): " );
+ aErrorStr += ImplGetDialogText( this );
+ DBG_ERROR( aErrorStr.GetBuffer() );
+#endif
+ return FALSE;
+ }
+
+ if ( Application::IsDialogCancelEnabled() )
+ {
+#ifdef DBG_UTIL
+ ByteString aErrorStr( "Dialog::StartExecuteModal() is called in a none UI application: " );
+ aErrorStr += ImplGetDialogText( this );
+ DBG_ERROR( aErrorStr.GetBuffer() );
+#endif
+ return FALSE;
+ }
+
+#ifdef DBG_UTIL
+ Window* pParent = GetParent();
+ if ( pParent )
+ {
+ pParent = pParent->ImplGetFirstOverlapWindow();
+ DBG_ASSERT( pParent->IsReallyVisible(),
+ "Dialog::StartExecuteModal() - Parent not visible" );
+ DBG_ASSERT( pParent->IsInputEnabled(),
+ "Dialog::StartExecuteModal() - Parent input disabled, use another parent to ensure modality!" );
+ DBG_ASSERT( ! pParent->IsInModalMode(),
+ "Dialog::StartExecuteModal() - Parent already modally disabled, use another parent to ensure modality!" );
+
+ }
+#endif
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Dialoge, die sich in Execute befinden, miteinander verketten
+ mpPrevExecuteDlg = pSVData->maWinData.mpLastExecuteDlg;
+ pSVData->maWinData.mpLastExecuteDlg = this;
+
+ // Capture beenden, damit der Dialog bedient werden kann
+ if ( pSVData->maWinData.mpTrackWin )
+ pSVData->maWinData.mpTrackWin->EndTracking( ENDTRACK_CANCEL );
+ if ( pSVData->maWinData.mpCaptureWin )
+ pSVData->maWinData.mpCaptureWin->ReleaseMouse();
+ EnableInput( TRUE, TRUE );
+
+ if ( GetParent() )
+ {
+ NotifyEvent aNEvt( EVENT_EXECUTEDIALOG, this );
+ GetParent()->Notify( aNEvt );
+ }
+ mbInExecute = TRUE;
+ SetModalInputMode( TRUE );
+ mbOldSaveBack = IsSaveBackgroundEnabled();
+ EnableSaveBackground();
+
+ // FIXME: no layouting, workaround some clipping issues
+ ImplAdjustNWFSizes();
+
+ Show();
+
+ pSVData->maAppData.mnModalMode++;
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::ImplEndExecuteModal()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ pSVData->maAppData.mnModalMode--;
+}
+
+// -----------------------------------------------------------------------
+
+short Dialog::Execute()
+{
+ if ( !ImplStartExecuteModal() )
+ return 0;
+
+ ImplDelData aDelData;
+ ImplAddDel( &aDelData );
+
+#ifdef DBG_UTIL
+ ImplDelData aParentDelData;
+ Window* pDialogParent = mpDialogParent;
+ if( pDialogParent )
+ pDialogParent->ImplAddDel( &aParentDelData );
+#endif
+
+ // Yield util EndDialog is called or dialog gets destroyed
+ // (the latter should not happen, but better safe than sorry
+ while ( !aDelData.IsDelete() && mbInExecute )
+ Application::Yield();
+
+ ImplEndExecuteModal();
+
+#ifdef DBG_UTIL
+ if( pDialogParent )
+ {
+ if( ! aParentDelData.IsDelete() )
+ pDialogParent->ImplRemoveDel( &aParentDelData );
+ else
+ DBG_ERROR( "Dialog::Execute() - Parent of dialog destroyed in Execute()" );
+ }
+#endif
+ if ( !aDelData.IsDelete() )
+ ImplRemoveDel( &aDelData );
+#ifdef DBG_UTIL
+ else
+ {
+ DBG_ERROR( "Dialog::Execute() - Dialog destroyed in Execute()" );
+ }
+#endif
+
+ long nRet = mpDialogImpl->mnResult;
+ mpDialogImpl->mnResult = -1;
+ return (short)nRet;
+}
+
+// -----------------------------------------------------------------------
+
+// virtual
+void Dialog::StartExecuteModal( const Link& rEndDialogHdl )
+{
+ if ( !ImplStartExecuteModal() )
+ return;
+
+ mpDialogImpl->maEndDialogHdl = rEndDialogHdl;
+ mpDialogImpl->mbStartedModal = true;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Dialog::IsStartedModal() const
+{
+ return mpDialogImpl->mbStartedModal;
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::EndDialog( long nResult )
+{
+ if ( mbInExecute )
+ {
+ SetModalInputMode( FALSE );
+
+ // Dialog aus der Kette der Dialoge die in Execute stehen entfernen
+ ImplSVData* pSVData = ImplGetSVData();
+ Dialog* pExeDlg = pSVData->maWinData.mpLastExecuteDlg;
+ while ( pExeDlg )
+ {
+ if ( pExeDlg == this )
+ {
+ pSVData->maWinData.mpLastExecuteDlg = mpPrevExecuteDlg;
+ break;
+ }
+ pExeDlg = pExeDlg->mpPrevExecuteDlg;
+ }
+ // set focus to previous modal dialogue if it is modal for
+ // the same frame parent (or NULL)
+ if( mpPrevExecuteDlg )
+ {
+ Window* pFrameParent = ImplGetFrameWindow()->ImplGetParent();
+ Window* pPrevFrameParent = mpPrevExecuteDlg->ImplGetFrameWindow()->ImplGetParent();
+ if( ( !pFrameParent && !pPrevFrameParent ) ||
+ ( pFrameParent && pPrevFrameParent && pFrameParent->ImplGetFrame() == pPrevFrameParent->ImplGetFrame() )
+ )
+ {
+ mpPrevExecuteDlg->GrabFocus();
+ }
+ }
+ mpPrevExecuteDlg = NULL;
+
+ Hide();
+ EnableSaveBackground( mbOldSaveBack );
+ if ( GetParent() )
+ {
+ NotifyEvent aNEvt( EVENT_ENDEXECUTEDIALOG, this );
+ GetParent()->Notify( aNEvt );
+ }
+
+ mpDialogImpl->mnResult = nResult;
+
+ if ( mpDialogImpl->mbStartedModal )
+ {
+ ImplEndExecuteModal();
+ mpDialogImpl->maEndDialogHdl.Call( this );
+
+ mpDialogImpl->maEndDialogHdl = Link();
+ mpDialogImpl->mbStartedModal = false;
+ mpDialogImpl->mnResult = -1;
+ }
+ mbInExecute = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long Dialog::GetResult() const
+{
+ return mpDialogImpl->mnResult;
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::EndAllDialogs( Window* pParent )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ Dialog* pTempModDialog;
+ Dialog* pModDialog = pSVData->maWinData.mpLastExecuteDlg;
+ while ( pModDialog )
+ {
+ pTempModDialog = pModDialog->mpPrevExecuteDlg;
+ if( !pParent || ( pParent && pParent->IsWindowOrChild( pModDialog, TRUE ) ) )
+ {
+ pModDialog->EndDialog( FALSE );
+ pModDialog->PostUserEvent( Link() );
+ }
+ pModDialog = pTempModDialog;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::SetModalInputMode( BOOL bModal )
+{
+ if ( bModal == mbModalMode )
+ return;
+
+ ImplSVData* pSVData = ImplGetSVData();
+ mbModalMode = bModal;
+ if ( bModal )
+ {
+ pSVData->maAppData.mnModalDialog++;
+
+ // Diable the prev Modal Dialog, because our dialog must close at first,
+ // before the other dialog can be closed (because the other dialog
+ // is on stack since our dialog returns)
+ if ( mpPrevExecuteDlg && !mpPrevExecuteDlg->IsWindowOrChild( this, TRUE ) )
+ mpPrevExecuteDlg->EnableInput( FALSE, TRUE, TRUE, this );
+
+ // determine next overlap dialog parent
+ Window* pParent = GetParent();
+ if ( pParent )
+ {
+ // #103716# dialogs should always be modal to the whole frame window
+ // #115933# disable the whole frame hierarchie, useful if our parent
+ // is a modeless dialog
+ mpDialogParent = pParent->mpWindowImpl->mpFrameWindow;
+ mpDialogParent->ImplIncModalCount();
+ }
+
+ }
+ else
+ {
+ pSVData->maAppData.mnModalDialog--;
+
+ if ( mpDialogParent )
+ {
+ // #115933# re-enable the whole frame hierarchie again (see above)
+ // note that code in getfocus assures that we do not accidentally enable
+ // windows that were disabled before
+ mpDialogParent->ImplDecModalCount();
+ }
+
+ // Enable the prev Modal Dialog
+ if ( mpPrevExecuteDlg && !mpPrevExecuteDlg->IsWindowOrChild( this, TRUE ) )
+ {
+ mpPrevExecuteDlg->EnableInput( TRUE, TRUE, TRUE, this );
+ // ensure continued modality of prev dialog
+ // do not change modality counter
+ mpPrevExecuteDlg->SetModalInputMode( FALSE );
+ mpPrevExecuteDlg->SetModalInputMode( TRUE );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::SetModalInputMode( BOOL bModal, BOOL bSubModalDialogs )
+{
+ if ( bSubModalDialogs )
+ {
+ Window* pOverlap = ImplGetFirstOverlapWindow();
+ pOverlap = pOverlap->mpWindowImpl->mpFirstOverlap;
+ while ( pOverlap )
+ {
+ if ( pOverlap->IsDialog() )
+ ((Dialog*)pOverlap)->SetModalInputMode( bModal, TRUE );
+ pOverlap = pOverlap->mpWindowImpl->mpNext;
+ }
+ }
+
+ SetModalInputMode( bModal );
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::GrabFocusToFirstControl()
+{
+ Window* pFocusControl;
+
+ // Wenn Dialog den Focus hat, versuchen wr trotzdem
+ // ein Focus-Control zu finden
+ if ( HasFocus() )
+ pFocusControl = NULL;
+ else
+ {
+ // Wenn schon ein Child-Fenster mal den Focus hatte,
+ // dann dieses bevorzugen
+ pFocusControl = ImplGetFirstOverlapWindow()->mpWindowImpl->mpLastFocusWindow;
+ // Control aus der Dialog-Steuerung suchen
+ if ( pFocusControl )
+ pFocusControl = ImplFindDlgCtrlWindow( pFocusControl );
+ }
+ // Kein Control hatte vorher den Focus, oder das Control
+ // befindet sich nicht in der Tab-Steuerung, dann das erste
+ // Control in der TabSteuerung den Focus geben
+ if ( !pFocusControl ||
+ !(pFocusControl->GetStyle() & WB_TABSTOP) ||
+ !pFocusControl->IsVisible() ||
+ !pFocusControl->IsEnabled() || !pFocusControl->IsInputEnabled() )
+ {
+ USHORT n = 0;
+ pFocusControl = ImplGetDlgWindow( n, DLGWINDOW_FIRST );
+ }
+ if ( pFocusControl )
+ pFocusControl->ImplControlFocus( GETFOCUS_INIT );
+}
+
+void Dialog::GetDrawWindowBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder, sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
+{
+ ImplBorderWindow aImplWin( (Window*)this, WB_BORDER|WB_STDWORK, BORDERWINDOW_STYLE_OVERLAP );
+// aImplWin.SetText( GetText() );
+// aImplWin.SetPosSizePixel( aPos.X(), aPos.Y(), aSize.Width(), aSize.Height() );
+// aImplWin.SetDisplayActive( TRUE );
+// aImplWin.InitView();
+ aImplWin.GetBorder( rLeftBorder, rTopBorder, rRightBorder, rBottomBorder );
+}
+
+
+void Dialog::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, ULONG )
+{
+ Point aPos = pDev->LogicToPixel( rPos );
+ Size aSize = pDev->LogicToPixel( rSize );
+
+ Wallpaper aWallpaper = GetBackground();
+ if ( !aWallpaper.IsBitmap() )
+ ImplInitSettings();
+
+ pDev->Push();
+ pDev->SetMapMode();
+ pDev->SetLineColor();
+
+ if ( aWallpaper.IsBitmap() )
+ pDev->DrawBitmapEx( aPos, aSize, aWallpaper.GetBitmap() );
+ else
+ {
+ pDev->SetFillColor( aWallpaper.GetColor() );
+ pDev->DrawRect( Rectangle( aPos, aSize ) );
+ }
+
+ if (!( GetStyle() & WB_NOBORDER ))
+ {
+ ImplBorderWindow aImplWin( this, WB_BORDER|WB_STDWORK, BORDERWINDOW_STYLE_OVERLAP );
+ aImplWin.SetText( GetText() );
+ aImplWin.SetPosSizePixel( aPos.X(), aPos.Y(), aSize.Width(), aSize.Height() );
+ aImplWin.SetDisplayActive( TRUE );
+ aImplWin.InitView();
+
+ aImplWin.Draw( Rectangle( aPos, aSize ), pDev, aPos );
+ }
+
+ pDev->Pop();
+}
+
+
+// =======================================================================
+
+ModelessDialog::ModelessDialog( Window* pParent, WinBits nStyle ) :
+ Dialog( WINDOW_MODELESSDIALOG )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+ModelessDialog::ModelessDialog( Window* pParent, const ResId& rResId ) :
+ Dialog( WINDOW_MODELESSDIALOG )
+{
+ rResId.SetRT( RSC_MODELESSDIALOG );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// =======================================================================
+
+ModalDialog::ModalDialog( Window* pParent, WinBits nStyle ) :
+ Dialog( WINDOW_MODALDIALOG )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+ModalDialog::ModalDialog( Window* pParent, const ResId& rResId ) :
+ Dialog( WINDOW_MODALDIALOG )
+{
+ rResId.SetRT( RSC_MODALDIALOG );
+ ImplInit( pParent, ImplInitRes( rResId ) );
+ ImplLoadRes( rResId );
+}