xref: /trunk/main/vcl/source/window/dialog.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 #include <tools/debug.hxx>
31 
32 #include <tools/rc.h>
33 
34 #include <svdata.hxx>
35 #include <window.h>
36 #include <brdwin.hxx>
37 
38 #include <vcl/svapp.hxx>
39 #include <vcl/event.hxx>
40 #include <vcl/wrkwin.hxx>
41 #include <vcl/button.hxx>
42 #include <vcl/mnemonic.hxx>
43 #include <vcl/dialog.hxx>
44 #include <vcl/decoview.hxx>
45 
46 #ifdef DBG_UTIL
47 #include <vcl/msgbox.hxx>
48 #endif
49 
50 #include <vcl/unowrap.hxx>
51 
52 
53 
54 // =======================================================================
55 
56 #ifdef DBG_UTIL
57 
58 static ByteString ImplGetDialogText( Dialog* pDialog )
59 {
60     ByteString aErrorStr( pDialog->GetText(), RTL_TEXTENCODING_UTF8 );
61     if ( (pDialog->GetType() == WINDOW_MESSBOX) ||
62          (pDialog->GetType() == WINDOW_INFOBOX) ||
63          (pDialog->GetType() == WINDOW_WARNINGBOX) ||
64          (pDialog->GetType() == WINDOW_ERRORBOX) ||
65          (pDialog->GetType() == WINDOW_QUERYBOX) )
66     {
67         aErrorStr += ", ";
68         aErrorStr += ByteString( ((MessBox*)pDialog)->GetMessText(), RTL_TEXTENCODING_UTF8 );
69     }
70     return aErrorStr;
71 }
72 
73 #endif
74 
75 // =======================================================================
76 
77 static sal_Bool ImplIsMnemonicCtrl( Window* pWindow )
78 {
79     if( ! pWindow->GetSettings().GetStyleSettings().GetAutoMnemonic() )
80         return sal_False;
81 
82     if ( (pWindow->GetType() == WINDOW_RADIOBUTTON) ||
83          (pWindow->GetType() == WINDOW_CHECKBOX) ||
84          (pWindow->GetType() == WINDOW_TRISTATEBOX) ||
85          (pWindow->GetType() == WINDOW_PUSHBUTTON) )
86         return sal_True;
87 
88     if ( pWindow->GetType() == WINDOW_FIXEDTEXT )
89     {
90         if ( pWindow->GetStyle() & (WB_INFO | WB_NOLABEL) )
91             return sal_False;
92         Window* pNextWindow = pWindow->GetWindow( WINDOW_NEXT );
93         if ( !pNextWindow )
94             return sal_False;
95         pNextWindow = pNextWindow->GetWindow( WINDOW_CLIENT );
96         if ( !(pNextWindow->GetStyle() & WB_TABSTOP) ||
97              (pNextWindow->GetType() == WINDOW_FIXEDTEXT) ||
98              (pNextWindow->GetType() == WINDOW_GROUPBOX) ||
99              (pNextWindow->GetType() == WINDOW_RADIOBUTTON) ||
100              (pNextWindow->GetType() == WINDOW_CHECKBOX) ||
101              (pNextWindow->GetType() == WINDOW_TRISTATEBOX) ||
102              (pNextWindow->GetType() == WINDOW_PUSHBUTTON) )
103             return sal_False;
104 
105         return sal_True;
106     }
107 
108     return sal_False;
109 }
110 
111 // -----------------------------------------------------------------------
112 
113 void ImplWindowAutoMnemonic( Window* pWindow )
114 {
115     MnemonicGenerator   aMnemonicGenerator;
116     Window*                 pGetChild;
117     Window*                 pChild;
118 
119     // Die schon vergebenen Mnemonics registieren
120     pGetChild = pWindow->GetWindow( WINDOW_FIRSTCHILD );
121     while ( pGetChild )
122     {
123         pChild = pGetChild->ImplGetWindow();
124         aMnemonicGenerator.RegisterMnemonic( pChild->GetText() );
125         pGetChild = pGetChild->GetWindow( WINDOW_NEXT );
126     }
127 
128     // Bei TabPages auch noch die Controls vom Dialog beruecksichtigen
129     if ( pWindow->GetType() == WINDOW_TABPAGE )
130     {
131         Window* pParent = pWindow->GetParent();
132         if ( pParent->GetType() == WINDOW_TABCONTROL )
133             pParent = pParent->GetParent();
134 
135         if ( (pParent->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) == WB_DIALOGCONTROL )
136         {
137             pGetChild = pParent->GetWindow( WINDOW_FIRSTCHILD );
138             while ( pGetChild )
139             {
140                 pChild = pGetChild->ImplGetWindow();
141                 aMnemonicGenerator.RegisterMnemonic( pChild->GetText() );
142                 pGetChild = pGetChild->GetWindow( WINDOW_NEXT );
143             }
144         }
145     }
146 
147     // Die Mnemonics an die Controls vergeben, die noch keinen haben
148     pGetChild = pWindow->GetWindow( WINDOW_FIRSTCHILD );
149     while ( pGetChild )
150     {
151         pChild = pGetChild->ImplGetWindow();
152         if ( ImplIsMnemonicCtrl( pChild ) )
153         {
154             XubString aText = pChild->GetText();
155             if ( aMnemonicGenerator.CreateMnemonic( aText ) )
156                 pChild->SetText( aText );
157         }
158 
159         pGetChild = pGetChild->GetWindow( WINDOW_NEXT );
160     }
161 }
162 
163 // =======================================================================
164 
165 static PushButton* ImplGetDefaultButton( Dialog* pDialog )
166 {
167     Window* pChild = pDialog->GetWindow( WINDOW_FIRSTCHILD );
168     while ( pChild )
169     {
170         if ( pChild->ImplIsPushButton() )
171         {
172             PushButton* pPushButton = (PushButton*)pChild;
173             if ( pPushButton->ImplIsDefButton() )
174                 return pPushButton;
175         }
176 
177         pChild = pChild->GetWindow( WINDOW_NEXT );
178     }
179 
180     return NULL;
181 }
182 
183 // -----------------------------------------------------------------------
184 
185 static PushButton* ImplGetOKButton( Dialog* pDialog )
186 {
187     Window* pChild = pDialog->GetWindow( WINDOW_FIRSTCHILD );
188     while ( pChild )
189     {
190         if ( pChild->GetType() == WINDOW_OKBUTTON )
191             return (PushButton*)pChild;
192 
193         pChild = pChild->GetWindow( WINDOW_NEXT );
194     }
195 
196     return NULL;
197 }
198 
199 // -----------------------------------------------------------------------
200 
201 static PushButton* ImplGetCancelButton( Dialog* pDialog )
202 {
203     Window* pChild = pDialog->GetWindow( WINDOW_FIRSTCHILD );
204     while ( pChild )
205     {
206         if ( pChild->GetType() == WINDOW_CANCELBUTTON )
207             return (PushButton*)pChild;
208 
209         pChild = pChild->GetWindow( WINDOW_NEXT );
210     }
211 
212     return NULL;
213 }
214 
215 // -----------------------------------------------------------------------
216 
217 static void ImplMouseAutoPos( Dialog* pDialog )
218 {
219     sal_uLong nMouseOptions = pDialog->GetSettings().GetMouseSettings().GetOptions();
220     if ( nMouseOptions & MOUSE_OPTION_AUTOCENTERPOS )
221     {
222         Size aSize = pDialog->GetOutputSizePixel();
223         pDialog->SetPointerPosPixel( Point( aSize.Width()/2, aSize.Height()/2 ) );
224     }
225     else if ( nMouseOptions & MOUSE_OPTION_AUTODEFBTNPOS )
226     {
227         Window* pWindow = ImplGetDefaultButton( pDialog );
228         if ( !pWindow )
229             pWindow = ImplGetOKButton( pDialog );
230         if ( !pWindow )
231             pWindow = ImplGetCancelButton( pDialog );
232         if ( !pWindow )
233             pWindow = pDialog;
234         Size aSize = pWindow->GetOutputSizePixel();
235         pWindow->SetPointerPosPixel( Point( aSize.Width()/2, aSize.Height()/2 ) );
236     }
237 }
238 
239 // =======================================================================
240 
241 struct DialogImpl
242 {
243     long    mnResult;
244     bool    mbStartedModal;
245     Link    maEndDialogHdl;
246 
247     DialogImpl() : mnResult( -1 ), mbStartedModal( false ) {}
248 };
249 
250 // =======================================================================
251 
252 void Dialog::ImplInitDialogData()
253 {
254     mpWindowImpl->mbDialog  = sal_True;
255     mpDialogParent          = NULL;
256     mpPrevExecuteDlg        = NULL;
257     mbInExecute             = sal_False;
258     mbOldSaveBack           = sal_False;
259     mbInClose               = sal_False;
260     mbModalMode             = sal_False;
261     mnMousePositioned       = 0;
262     mpDialogImpl            = new DialogImpl;
263 }
264 
265 // -----------------------------------------------------------------------
266 
267 void Dialog::ImplInit( Window* pParent, WinBits nStyle )
268 {
269     sal_uInt16 nSysWinMode = Application::GetSystemWindowMode();
270 
271     if ( !(nStyle & WB_NODIALOGCONTROL) )
272         nStyle |= WB_DIALOGCONTROL;
273     nStyle |= WB_ROLLABLE;
274 
275     // Now, all Dialogs are per default system windows !!!
276     nStyle |= WB_SYSTEMWINDOW;
277 
278 
279     // parent is NULL: get the default Dialog parent
280     if ( !pParent )
281     {
282         pParent = Application::GetDefDialogParent();
283         if ( !pParent && !(nStyle & WB_SYSTEMWINDOW) )
284             pParent = ImplGetSVData()->maWinData.mpAppWin;
285 
286         // If Parent is disabled, then we search for a modal dialog
287         // in this frame
288         if ( pParent && (!pParent->IsInputEnabled() || pParent->IsInModalMode()) )
289         {
290             ImplSVData* pSVData = ImplGetSVData();
291             Dialog*     pExeDlg = pSVData->maWinData.mpLastExecuteDlg;
292             while ( pExeDlg )
293             {
294                 // Nur wenn er sichtbar und enabled ist
295                 if ( pParent->ImplGetFirstOverlapWindow()->IsWindowOrChild( pExeDlg, sal_True ) &&
296                      pExeDlg->IsReallyVisible() &&
297                      pExeDlg->IsEnabled() && pExeDlg->IsInputEnabled() && !pExeDlg->IsInModalMode() )
298                 {
299                     pParent = pExeDlg;
300                     break;
301                 }
302 
303                 pExeDlg = pExeDlg->mpPrevExecuteDlg;
304             }
305         }
306     }
307     // DIALOG_NO_PARENT: explicitly don't have a parent for this Dialog
308     else if( pParent == DIALOG_NO_PARENT )
309         pParent = NULL;
310 
311 /*
312     // Now, all Dialogs are per default system windows !!!
313     if ( pParent && !(nSysWinMode & SYSTEMWINDOW_MODE_NOAUTOMODE) )
314     {
315         if ( !pParent->mpWindowImpl->mpFrameWindow->IsVisible() )
316             pParent = NULL;
317         else
318         {
319             if ( pParent->mpWindowImpl->mpFrameWindow->IsDialog() )
320             {
321                 Size aOutSize = pParent->mpWindowImpl->mpFrameWindow->GetOutputSizePixel();
322                 if ( (aOutSize.Width() < 210) ||(aOutSize.Height() < 160) )
323                     nStyle |= WB_SYSTEMWINDOW;
324             }
325         }
326     }
327 */
328 
329     if ( !pParent || (nStyle & WB_SYSTEMWINDOW) ||
330          (pParent->mpWindowImpl->mpFrameData->mbNeedSysWindow && !(nSysWinMode & SYSTEMWINDOW_MODE_NOAUTOMODE)) ||
331          (nSysWinMode & SYSTEMWINDOW_MODE_DIALOG) )
332     {
333         // create window with a small border ?
334         if ( (nStyle & (WB_BORDER | WB_NOBORDER | WB_MOVEABLE | WB_SIZEABLE | WB_CLOSEABLE)) == WB_BORDER )
335         {
336             ImplBorderWindow* pBorderWin  = new ImplBorderWindow( pParent, nStyle, BORDERWINDOW_STYLE_FRAME );
337             SystemWindow::ImplInit( pBorderWin, nStyle & ~WB_BORDER, NULL );
338             pBorderWin->mpWindowImpl->mpClientWindow = this;
339             pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
340             mpWindowImpl->mpBorderWindow  = pBorderWin;
341             mpWindowImpl->mpRealParent    = pParent;
342         }
343         else
344         {
345             mpWindowImpl->mbFrame         = sal_True;
346             mpWindowImpl->mbOverlapWin    = sal_True;
347             SystemWindow::ImplInit( pParent, (nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_CLOSEABLE | WB_STANDALONE)) | WB_CLOSEABLE, NULL );
348             // Now set all style bits
349             mpWindowImpl->mnStyle = nStyle;
350         }
351     }
352     else
353     {
354         ImplBorderWindow* pBorderWin  = new ImplBorderWindow( pParent, nStyle, BORDERWINDOW_STYLE_OVERLAP | BORDERWINDOW_STYLE_BORDER );
355         SystemWindow::ImplInit( pBorderWin, nStyle & ~WB_BORDER, NULL );
356         pBorderWin->mpWindowImpl->mpClientWindow = this;
357         pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
358         mpWindowImpl->mpBorderWindow  = pBorderWin;
359         mpWindowImpl->mpRealParent    = pParent;
360     }
361 
362     SetActivateMode( ACTIVATE_MODE_GRABFOCUS );
363 
364     ImplInitSettings();
365 }
366 
367 // -----------------------------------------------------------------------
368 
369 void Dialog::ImplInitSettings()
370 {
371     // user override
372     if ( IsControlBackground() )
373         SetBackground( GetControlBackground() );
374     // NWF background
375     else if( IsNativeControlSupported( CTRL_WINDOW_BACKGROUND, PART_BACKGROUND_DIALOG ) )
376     {
377         mpWindowImpl->mnNativeBackground = PART_BACKGROUND_DIALOG;
378         EnableChildTransparentMode( sal_True );
379     }
380     // fallback to settings color
381     else
382         SetBackground( GetSettings().GetStyleSettings().GetDialogColor() );
383 
384 }
385 
386 // -----------------------------------------------------------------------
387 
388 void Dialog::ImplCenterDialog()
389 {
390     Rectangle   aDeskRect = ImplGetFrameWindow()->GetDesktopRectPixel();
391     Point       aDeskPos = aDeskRect.TopLeft();
392     Size        aDeskSize = aDeskRect.GetSize();
393     Size        aWinSize = GetSizePixel();
394     Window *pWindow = this;
395     while ( pWindow->mpWindowImpl->mpBorderWindow )
396         pWindow = pWindow->mpWindowImpl->mpBorderWindow;
397     Point       aWinPos( ((aDeskSize.Width() - aWinSize.Width()) / 2) + aDeskPos.X(),
398                          ((aDeskSize.Height() - aWinSize.Height()) / 2) + aDeskPos.Y() );
399 
400     // Pruefen, ob Dialogbox ausserhalb des Desks liegt
401     if ( (aWinPos.X() + aWinSize.Width()) > (aDeskPos.X()+aDeskSize.Width()) )
402         aWinPos.X() = aDeskPos.X()+aDeskSize.Width() - aWinSize.Width();
403     if ( (aWinPos.Y()+aWinSize.Height()) > (aDeskPos.Y()+aDeskSize.Height()) )
404         aWinPos.Y() = aDeskPos.Y()+aDeskSize.Height() - aWinSize.Height();
405     // Linke Ecke bevorzugen, da Titelbar oben ist
406     if ( aWinPos.X() < aDeskPos.X() )
407         aWinPos.X() = aDeskPos.X();
408     if ( aWinPos.Y() < aDeskPos.Y() )
409         aWinPos.Y() = aDeskPos.Y();
410 
411     //SetPosPixel( aWinPos );
412     SetPosPixel( pWindow->ScreenToOutputPixel( aWinPos ) );
413 }
414 
415 // -----------------------------------------------------------------------
416 
417 Dialog::Dialog( WindowType nType ) :
418     SystemWindow( nType )
419 {
420     ImplInitDialogData();
421 }
422 
423 // -----------------------------------------------------------------------
424 
425 Dialog::Dialog( Window* pParent, WinBits nStyle ) :
426     SystemWindow( WINDOW_DIALOG )
427 {
428     ImplInitDialogData();
429     ImplInit( pParent, nStyle );
430 }
431 
432 // -----------------------------------------------------------------------
433 
434 Dialog::Dialog( Window* pParent, const ResId& rResId ) :
435     SystemWindow( WINDOW_DIALOG )
436 {
437     ImplInitDialogData();
438     rResId.SetRT( RSC_DIALOG );
439     ImplInit( pParent, ImplInitRes( rResId ) );
440     ImplLoadRes( rResId );
441 }
442 
443 // -----------------------------------------------------------------------
444 
445 Dialog::~Dialog()
446 {
447     delete mpDialogImpl;
448     mpDialogImpl = NULL;
449 }
450 
451 // -----------------------------------------------------------------------
452 
453 IMPL_LINK( Dialog, ImplAsyncCloseHdl, void*, EMPTYARG )
454 {
455     Close();
456     return 0;
457 }
458 
459 // -----------------------------------------------------------------------
460 
461 long Dialog::Notify( NotifyEvent& rNEvt )
462 {
463     // Zuerst Basisklasse rufen wegen TabSteuerung
464     long nRet = SystemWindow::Notify( rNEvt );
465     if ( !nRet )
466     {
467         if ( rNEvt.GetType() == EVENT_KEYINPUT )
468         {
469             const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
470             KeyCode         aKeyCode = pKEvt->GetKeyCode();
471             sal_uInt16          nKeyCode = aKeyCode.GetCode();
472 
473             if ( (nKeyCode == KEY_ESCAPE) &&
474                  ((GetStyle() & WB_CLOSEABLE) || ImplGetCancelButton( this ) || ImplGetOKButton( this )) )
475             {
476                 // #i89505# for the benefit of slightly mentally challenged implementations
477                 // like e.g. SfxModelessDialog which destroy themselves inside Close()
478                 // post this Close asynchronous so we can leave our key handler before
479                 // we get destroyed
480                 PostUserEvent( LINK( this, Dialog, ImplAsyncCloseHdl ), this );
481                 return sal_True;
482             }
483         }
484         else if ( rNEvt.GetType() == EVENT_GETFOCUS )
485         {
486             // make sure the dialog is still modal
487             // changing focus between application frames may
488             // have re-enabled input for our parent
489             if( mbInExecute && mbModalMode )
490             {
491                 // do not change modal counter (pSVData->maAppData.mnModalDialog)
492                 SetModalInputMode( sal_False );
493                 SetModalInputMode( sal_True );
494 
495                 // #93022# def-button might have changed after show
496                 if( !mnMousePositioned )
497                 {
498                     mnMousePositioned = 1;
499                     ImplMouseAutoPos( this );
500                 }
501 
502             }
503         }
504     }
505 
506     return nRet;
507 }
508 
509 // -----------------------------------------------------------------------
510 
511 void Dialog::StateChanged( StateChangedType nType )
512 {
513     SystemWindow::StateChanged( nType );
514 
515     if ( nType == STATE_CHANGE_INITSHOW )
516     {
517         if ( GetSettings().GetStyleSettings().GetAutoMnemonic() )
518             ImplWindowAutoMnemonic( this );
519 
520         //if ( IsDefaultPos() && !mpWindowImpl->mbFrame )
521         //    ImplCenterDialog();
522         if ( !HasChildPathFocus() || HasFocus() )
523             GrabFocusToFirstControl();
524         if ( !(GetStyle() & WB_CLOSEABLE) )
525         {
526             if ( ImplGetCancelButton( this ) || ImplGetOKButton( this ) )
527             {
528                 if ( ImplGetBorderWindow() )
529                     ((ImplBorderWindow*)ImplGetBorderWindow())->SetCloser();
530             }
531         }
532 
533         ImplMouseAutoPos( this );
534     }
535     else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
536     {
537         ImplInitSettings();
538         Invalidate();
539     }
540 }
541 
542 // -----------------------------------------------------------------------
543 
544 void Dialog::DataChanged( const DataChangedEvent& rDCEvt )
545 {
546     SystemWindow::DataChanged( rDCEvt );
547 
548     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
549          (rDCEvt.GetFlags() & SETTINGS_STYLE) )
550     {
551         ImplInitSettings();
552         Invalidate();
553     }
554 }
555 
556 // -----------------------------------------------------------------------
557 
558 sal_Bool Dialog::Close()
559 {
560     ImplDelData aDelData;
561     ImplAddDel( &aDelData );
562     ImplCallEventListeners( VCLEVENT_WINDOW_CLOSE );
563     if ( aDelData.IsDelete() )
564         return sal_False;
565     ImplRemoveDel( &aDelData );
566 
567     if ( mpWindowImpl->mxWindowPeer.is() && IsCreatedWithToolkit() && !IsInExecute() )
568         return sal_False;
569 
570     mbInClose = sal_True;
571 
572     if ( !(GetStyle() & WB_CLOSEABLE) )
573     {
574         sal_Bool bRet = sal_True;
575         ImplAddDel( &aDelData );
576         PushButton* pButton = ImplGetCancelButton( this );
577         if ( pButton )
578             pButton->Click();
579         else
580         {
581             pButton = ImplGetOKButton( this );
582             if ( pButton )
583                 pButton->Click();
584             else
585                 bRet = sal_False;
586         }
587         if ( aDelData.IsDelete() )
588             return sal_True;
589         ImplRemoveDel( &aDelData );
590         return bRet;
591     }
592 
593     if ( IsInExecute() )
594     {
595         EndDialog( sal_False );
596         mbInClose = sal_False;
597         return sal_True;
598     }
599     else
600     {
601         mbInClose = sal_False;
602         return SystemWindow::Close();
603     }
604 }
605 
606 // -----------------------------------------------------------------------
607 
608 sal_Bool Dialog::ImplStartExecuteModal()
609 {
610     if ( mbInExecute )
611     {
612 #ifdef DBG_UTIL
613         ByteString aErrorStr( "Dialog::StartExecuteModal() is called in Dialog::StartExecuteModal(): " );
614         aErrorStr += ImplGetDialogText( this );
615         DBG_ERROR( aErrorStr.GetBuffer() );
616 #endif
617         return sal_False;
618     }
619 
620     if ( Application::IsDialogCancelEnabled() )
621     {
622 #ifdef DBG_UTIL
623         ByteString aErrorStr( "Dialog::StartExecuteModal() is called in a none UI application: " );
624         aErrorStr += ImplGetDialogText( this );
625         DBG_ERROR( aErrorStr.GetBuffer() );
626 #endif
627         return sal_False;
628     }
629 
630 #ifdef DBG_UTIL
631     Window* pParent = GetParent();
632     if ( pParent )
633     {
634         pParent = pParent->ImplGetFirstOverlapWindow();
635         DBG_ASSERT( pParent->IsReallyVisible(),
636                     "Dialog::StartExecuteModal() - Parent not visible" );
637         DBG_ASSERT( pParent->IsInputEnabled(),
638                     "Dialog::StartExecuteModal() - Parent input disabled, use another parent to ensure modality!" );
639         DBG_ASSERT( ! pParent->IsInModalMode(),
640                     "Dialog::StartExecuteModal() - Parent already modally disabled, use another parent to ensure modality!" );
641 
642     }
643 #endif
644 
645     ImplSVData* pSVData = ImplGetSVData();
646 
647     // Dialoge, die sich in Execute befinden, miteinander verketten
648     mpPrevExecuteDlg = pSVData->maWinData.mpLastExecuteDlg;
649     pSVData->maWinData.mpLastExecuteDlg = this;
650 
651     // Capture beenden, damit der Dialog bedient werden kann
652     if ( pSVData->maWinData.mpTrackWin )
653         pSVData->maWinData.mpTrackWin->EndTracking( ENDTRACK_CANCEL );
654     if ( pSVData->maWinData.mpCaptureWin )
655         pSVData->maWinData.mpCaptureWin->ReleaseMouse();
656     EnableInput( sal_True, sal_True );
657 
658     if ( GetParent() )
659     {
660         NotifyEvent aNEvt( EVENT_EXECUTEDIALOG, this );
661         GetParent()->Notify( aNEvt );
662     }
663     mbInExecute = sal_True;
664     SetModalInputMode( sal_True );
665     mbOldSaveBack = IsSaveBackgroundEnabled();
666     EnableSaveBackground();
667 
668     // FIXME: no layouting, workaround some clipping issues
669     ImplAdjustNWFSizes();
670 
671     Show();
672 
673     pSVData->maAppData.mnModalMode++;
674     return sal_True;
675 }
676 
677 // -----------------------------------------------------------------------
678 
679 void Dialog::ImplEndExecuteModal()
680 {
681     ImplSVData* pSVData = ImplGetSVData();
682     pSVData->maAppData.mnModalMode--;
683 }
684 
685 // -----------------------------------------------------------------------
686 
687 short Dialog::Execute()
688 {
689     if ( !ImplStartExecuteModal() )
690         return 0;
691 
692     ImplDelData aDelData;
693     ImplAddDel( &aDelData );
694 
695 #ifdef DBG_UTIL
696     ImplDelData aParentDelData;
697     Window* pDialogParent = mpDialogParent;
698     if( pDialogParent )
699         pDialogParent->ImplAddDel( &aParentDelData );
700 #endif
701 
702     // Yield util EndDialog is called or dialog gets destroyed
703     // (the latter should not happen, but better safe than sorry
704     while ( !aDelData.IsDelete() && mbInExecute )
705         Application::Yield();
706 
707     ImplEndExecuteModal();
708 
709 #ifdef DBG_UTIL
710     if( pDialogParent  )
711     {
712         if( ! aParentDelData.IsDelete() )
713             pDialogParent->ImplRemoveDel( &aParentDelData );
714         else
715             DBG_ERROR( "Dialog::Execute() - Parent of dialog destroyed in Execute()" );
716     }
717 #endif
718     if ( !aDelData.IsDelete() )
719         ImplRemoveDel( &aDelData );
720 #ifdef DBG_UTIL
721     else
722     {
723         DBG_ERROR( "Dialog::Execute() - Dialog destroyed in Execute()" );
724     }
725 #endif
726 
727     long nRet = mpDialogImpl->mnResult;
728     mpDialogImpl->mnResult = -1;
729     return (short)nRet;
730 }
731 
732 // -----------------------------------------------------------------------
733 
734 // virtual
735 void Dialog::StartExecuteModal( const Link& rEndDialogHdl )
736 {
737     if ( !ImplStartExecuteModal() )
738         return;
739 
740     mpDialogImpl->maEndDialogHdl = rEndDialogHdl;
741     mpDialogImpl->mbStartedModal = true;
742 }
743 
744 // -----------------------------------------------------------------------
745 
746 sal_Bool Dialog::IsStartedModal() const
747 {
748     return mpDialogImpl->mbStartedModal;
749 }
750 
751 // -----------------------------------------------------------------------
752 
753 void Dialog::EndDialog( long nResult )
754 {
755     if ( mbInExecute )
756     {
757         SetModalInputMode( sal_False );
758 
759         // Dialog aus der Kette der Dialoge die in Execute stehen entfernen
760         ImplSVData* pSVData = ImplGetSVData();
761         Dialog* pExeDlg = pSVData->maWinData.mpLastExecuteDlg;
762         while ( pExeDlg )
763         {
764             if ( pExeDlg == this )
765             {
766                 pSVData->maWinData.mpLastExecuteDlg = mpPrevExecuteDlg;
767                 break;
768             }
769             pExeDlg = pExeDlg->mpPrevExecuteDlg;
770         }
771         // set focus to previous modal dialogue if it is modal for
772         // the same frame parent (or NULL)
773         if( mpPrevExecuteDlg )
774         {
775             Window* pFrameParent = ImplGetFrameWindow()->ImplGetParent();
776             Window* pPrevFrameParent = mpPrevExecuteDlg->ImplGetFrameWindow()->ImplGetParent();
777             if( ( !pFrameParent && !pPrevFrameParent ) ||
778                 ( pFrameParent && pPrevFrameParent && pFrameParent->ImplGetFrame() == pPrevFrameParent->ImplGetFrame() )
779                 )
780             {
781                 mpPrevExecuteDlg->GrabFocus();
782             }
783         }
784         mpPrevExecuteDlg = NULL;
785 
786         Hide();
787         EnableSaveBackground( mbOldSaveBack );
788         if ( GetParent() )
789         {
790             NotifyEvent aNEvt( EVENT_ENDEXECUTEDIALOG, this );
791             GetParent()->Notify( aNEvt );
792         }
793 
794         mpDialogImpl->mnResult = nResult;
795 
796         if ( mpDialogImpl->mbStartedModal )
797         {
798             ImplEndExecuteModal();
799             mpDialogImpl->maEndDialogHdl.Call( this );
800 
801             mpDialogImpl->maEndDialogHdl = Link();
802             mpDialogImpl->mbStartedModal = false;
803             mpDialogImpl->mnResult = -1;
804         }
805         mbInExecute = sal_False;
806     }
807 }
808 
809 // -----------------------------------------------------------------------
810 
811 long Dialog::GetResult() const
812 {
813     return mpDialogImpl->mnResult;
814 }
815 
816 // -----------------------------------------------------------------------
817 
818 void Dialog::EndAllDialogs( Window* pParent )
819 {
820    ImplSVData*  pSVData = ImplGetSVData();
821    Dialog*      pTempModDialog;
822    Dialog*      pModDialog = pSVData->maWinData.mpLastExecuteDlg;
823    while ( pModDialog )
824    {
825      pTempModDialog = pModDialog->mpPrevExecuteDlg;
826      if( !pParent || ( pParent && pParent->IsWindowOrChild( pModDialog, sal_True ) ) )
827      {
828         pModDialog->EndDialog( sal_False );
829         pModDialog->PostUserEvent( Link() );
830      }
831      pModDialog = pTempModDialog;
832    }
833 }
834 
835 // -----------------------------------------------------------------------
836 
837 void Dialog::SetModalInputMode( sal_Bool bModal )
838 {
839     if ( bModal == mbModalMode )
840         return;
841 
842     ImplSVData* pSVData = ImplGetSVData();
843     mbModalMode = bModal;
844     if ( bModal )
845     {
846         pSVData->maAppData.mnModalDialog++;
847 
848         // Diable the prev Modal Dialog, because our dialog must close at first,
849         // before the other dialog can be closed (because the other dialog
850         // is on stack since our dialog returns)
851         if ( mpPrevExecuteDlg && !mpPrevExecuteDlg->IsWindowOrChild( this, sal_True ) )
852             mpPrevExecuteDlg->EnableInput( sal_False, sal_True, sal_True, this );
853 
854         // determine next overlap dialog parent
855         Window* pParent = GetParent();
856         if ( pParent )
857         {
858             // #103716# dialogs should always be modal to the whole frame window
859             // #115933# disable the whole frame hierarchie, useful if our parent
860             // is a modeless dialog
861             mpDialogParent = pParent->mpWindowImpl->mpFrameWindow;
862             mpDialogParent->ImplIncModalCount();
863         }
864 
865     }
866     else
867     {
868         pSVData->maAppData.mnModalDialog--;
869 
870         if ( mpDialogParent )
871         {
872             // #115933# re-enable the whole frame hierarchie again (see above)
873             // note that code in getfocus assures that we do not accidentally enable
874             // windows that were disabled before
875             mpDialogParent->ImplDecModalCount();
876         }
877 
878         // Enable the prev Modal Dialog
879         if ( mpPrevExecuteDlg && !mpPrevExecuteDlg->IsWindowOrChild( this, sal_True ) )
880         {
881             mpPrevExecuteDlg->EnableInput( sal_True, sal_True, sal_True, this );
882             // ensure continued modality of prev dialog
883             // do not change modality counter
884             mpPrevExecuteDlg->SetModalInputMode( sal_False );
885             mpPrevExecuteDlg->SetModalInputMode( sal_True );
886         }
887     }
888 }
889 
890 // -----------------------------------------------------------------------
891 
892 void Dialog::SetModalInputMode( sal_Bool bModal, sal_Bool bSubModalDialogs )
893 {
894     if ( bSubModalDialogs )
895     {
896         Window* pOverlap = ImplGetFirstOverlapWindow();
897         pOverlap = pOverlap->mpWindowImpl->mpFirstOverlap;
898         while ( pOverlap )
899         {
900             if ( pOverlap->IsDialog() )
901                 ((Dialog*)pOverlap)->SetModalInputMode( bModal, sal_True );
902             pOverlap = pOverlap->mpWindowImpl->mpNext;
903         }
904     }
905 
906     SetModalInputMode( bModal );
907 }
908 
909 // -----------------------------------------------------------------------
910 
911 void Dialog::GrabFocusToFirstControl()
912 {
913     Window* pFocusControl;
914 
915     // Wenn Dialog den Focus hat, versuchen wr trotzdem
916     // ein Focus-Control zu finden
917     if ( HasFocus() )
918         pFocusControl = NULL;
919     else
920     {
921         // Wenn schon ein Child-Fenster mal den Focus hatte,
922         // dann dieses bevorzugen
923         pFocusControl = ImplGetFirstOverlapWindow()->mpWindowImpl->mpLastFocusWindow;
924         // Control aus der Dialog-Steuerung suchen
925         if ( pFocusControl )
926             pFocusControl = ImplFindDlgCtrlWindow( pFocusControl );
927     }
928     // Kein Control hatte vorher den Focus, oder das Control
929     // befindet sich nicht in der Tab-Steuerung, dann das erste
930     // Control in der TabSteuerung den Focus geben
931     if ( !pFocusControl ||
932          !(pFocusControl->GetStyle() & WB_TABSTOP) ||
933          !pFocusControl->IsVisible() ||
934          !pFocusControl->IsEnabled() || !pFocusControl->IsInputEnabled() )
935     {
936         sal_uInt16 n = 0;
937         pFocusControl = ImplGetDlgWindow( n, DLGWINDOW_FIRST );
938     }
939     if ( pFocusControl )
940         pFocusControl->ImplControlFocus( GETFOCUS_INIT );
941 }
942 
943 void Dialog::GetDrawWindowBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder, sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
944 {
945     ImplBorderWindow aImplWin( (Window*)this, WB_BORDER|WB_STDWORK, BORDERWINDOW_STYLE_OVERLAP );
946 //  aImplWin.SetText( GetText() );
947 //  aImplWin.SetPosSizePixel( aPos.X(), aPos.Y(), aSize.Width(), aSize.Height() );
948 //  aImplWin.SetDisplayActive( sal_True );
949 //  aImplWin.InitView();
950     aImplWin.GetBorder( rLeftBorder, rTopBorder, rRightBorder, rBottomBorder );
951 }
952 
953 
954 void Dialog::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong )
955 {
956     Point aPos = pDev->LogicToPixel( rPos );
957     Size aSize = pDev->LogicToPixel( rSize );
958 
959     Wallpaper aWallpaper = GetBackground();
960     if ( !aWallpaper.IsBitmap() )
961         ImplInitSettings();
962 
963     pDev->Push();
964     pDev->SetMapMode();
965     pDev->SetLineColor();
966 
967     if ( aWallpaper.IsBitmap() )
968         pDev->DrawBitmapEx( aPos, aSize, aWallpaper.GetBitmap() );
969     else
970     {
971         pDev->SetFillColor( aWallpaper.GetColor() );
972         pDev->DrawRect( Rectangle( aPos, aSize ) );
973     }
974 
975     if (!( GetStyle() & WB_NOBORDER ))
976 	{
977 		ImplBorderWindow aImplWin( this, WB_BORDER|WB_STDWORK, BORDERWINDOW_STYLE_OVERLAP );
978 		aImplWin.SetText( GetText() );
979 		aImplWin.SetPosSizePixel( aPos.X(), aPos.Y(), aSize.Width(), aSize.Height() );
980 		aImplWin.SetDisplayActive( sal_True );
981 		aImplWin.InitView();
982 
983 		aImplWin.Draw( Rectangle( aPos, aSize ), pDev, aPos );
984 	}
985 
986     pDev->Pop();
987 }
988 
989 
990 // =======================================================================
991 
992 ModelessDialog::ModelessDialog( Window* pParent, WinBits nStyle ) :
993     Dialog( WINDOW_MODELESSDIALOG )
994 {
995     ImplInit( pParent, nStyle );
996 }
997 
998 // -----------------------------------------------------------------------
999 
1000 ModelessDialog::ModelessDialog( Window* pParent, const ResId& rResId ) :
1001     Dialog( WINDOW_MODELESSDIALOG )
1002 {
1003     rResId.SetRT( RSC_MODELESSDIALOG );
1004     WinBits nStyle = ImplInitRes( rResId );
1005     ImplInit( pParent, nStyle );
1006     ImplLoadRes( rResId );
1007 
1008     if ( !(nStyle & WB_HIDE) )
1009         Show();
1010 }
1011 
1012 // =======================================================================
1013 
1014 ModalDialog::ModalDialog( Window* pParent, WinBits nStyle ) :
1015     Dialog( WINDOW_MODALDIALOG )
1016 {
1017     ImplInit( pParent, nStyle );
1018 }
1019 
1020 // -----------------------------------------------------------------------
1021 
1022 ModalDialog::ModalDialog( Window* pParent, const ResId& rResId ) :
1023     Dialog( WINDOW_MODALDIALOG )
1024 {
1025     rResId.SetRT( RSC_MODALDIALOG );
1026     ImplInit( pParent, ImplInitRes( rResId ) );
1027     ImplLoadRes( rResId );
1028 }
1029