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