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