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 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 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 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 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 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 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 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 243 DialogImpl() : mnResult( -1 ), mbStartedModal( false ) {} 244 }; 245 246 // ======================================================================= 247 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 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 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 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 413 Dialog::Dialog( WindowType nType ) : 414 SystemWindow( nType ) 415 { 416 ImplInitDialogData(); 417 } 418 419 // ----------------------------------------------------------------------- 420 421 Dialog::Dialog( Window* pParent, WinBits nStyle ) : 422 SystemWindow( WINDOW_DIALOG ) 423 { 424 ImplInitDialogData(); 425 ImplInit( pParent, nStyle ); 426 } 427 428 // ----------------------------------------------------------------------- 429 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 441 Dialog::~Dialog() 442 { 443 delete mpDialogImpl; 444 mpDialogImpl = NULL; 445 } 446 447 // ----------------------------------------------------------------------- 448 449 IMPL_LINK( Dialog, ImplAsyncCloseHdl, void*, EMPTYARG ) 450 { 451 Close(); 452 return 0; 453 } 454 455 // ----------------------------------------------------------------------- 456 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 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 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 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 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 675 void Dialog::ImplEndExecuteModal() 676 { 677 ImplSVData* pSVData = ImplGetSVData(); 678 pSVData->maAppData.mnModalMode--; 679 } 680 681 // ----------------------------------------------------------------------- 682 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 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 742 sal_Bool Dialog::IsStartedModal() const 743 { 744 return mpDialogImpl->mbStartedModal; 745 } 746 747 // ----------------------------------------------------------------------- 748 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 807 long Dialog::GetResult() const 808 { 809 return mpDialogImpl->mnResult; 810 } 811 812 // ----------------------------------------------------------------------- 813 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 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 mpPrevExecuteDlg->SetModalInputMode( sal_False ); 881 mpPrevExecuteDlg->SetModalInputMode( sal_True ); 882 } 883 } 884 } 885 886 // ----------------------------------------------------------------------- 887 888 void Dialog::SetModalInputMode( sal_Bool bModal, sal_Bool bSubModalDialogs ) 889 { 890 if ( bSubModalDialogs ) 891 { 892 Window* pOverlap = ImplGetFirstOverlapWindow(); 893 pOverlap = pOverlap->mpWindowImpl->mpFirstOverlap; 894 while ( pOverlap ) 895 { 896 if ( pOverlap->IsDialog() ) 897 ((Dialog*)pOverlap)->SetModalInputMode( bModal, sal_True ); 898 pOverlap = pOverlap->mpWindowImpl->mpNext; 899 } 900 } 901 902 SetModalInputMode( bModal ); 903 } 904 905 // ----------------------------------------------------------------------- 906 907 void Dialog::GrabFocusToFirstControl() 908 { 909 Window* pFocusControl; 910 911 // Wenn Dialog den Focus hat, versuchen wr trotzdem 912 // ein Focus-Control zu finden 913 if ( HasFocus() ) 914 pFocusControl = NULL; 915 else 916 { 917 // Wenn schon ein Child-Fenster mal den Focus hatte, 918 // dann dieses bevorzugen 919 pFocusControl = ImplGetFirstOverlapWindow()->mpWindowImpl->mpLastFocusWindow; 920 // Control aus der Dialog-Steuerung suchen 921 if ( pFocusControl ) 922 pFocusControl = ImplFindDlgCtrlWindow( pFocusControl ); 923 } 924 // Kein Control hatte vorher den Focus, oder das Control 925 // befindet sich nicht in der Tab-Steuerung, dann das erste 926 // Control in der TabSteuerung den Focus geben 927 if ( !pFocusControl || 928 !(pFocusControl->GetStyle() & WB_TABSTOP) || 929 !pFocusControl->IsVisible() || 930 !pFocusControl->IsEnabled() || !pFocusControl->IsInputEnabled() ) 931 { 932 sal_uInt16 n = 0; 933 pFocusControl = ImplGetDlgWindow( n, DLGWINDOW_FIRST ); 934 } 935 if ( pFocusControl ) 936 pFocusControl->ImplControlFocus( GETFOCUS_INIT ); 937 } 938 939 void Dialog::GetDrawWindowBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder, sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const 940 { 941 ImplBorderWindow aImplWin( (Window*)this, WB_BORDER|WB_STDWORK, BORDERWINDOW_STYLE_OVERLAP ); 942 // aImplWin.SetText( GetText() ); 943 // aImplWin.SetPosSizePixel( aPos.X(), aPos.Y(), aSize.Width(), aSize.Height() ); 944 // aImplWin.SetDisplayActive( sal_True ); 945 // aImplWin.InitView(); 946 aImplWin.GetBorder( rLeftBorder, rTopBorder, rRightBorder, rBottomBorder ); 947 } 948 949 950 void Dialog::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong ) 951 { 952 Point aPos = pDev->LogicToPixel( rPos ); 953 Size aSize = pDev->LogicToPixel( rSize ); 954 955 Wallpaper aWallpaper = GetBackground(); 956 if ( !aWallpaper.IsBitmap() ) 957 ImplInitSettings(); 958 959 pDev->Push(); 960 pDev->SetMapMode(); 961 pDev->SetLineColor(); 962 963 if ( aWallpaper.IsBitmap() ) 964 pDev->DrawBitmapEx( aPos, aSize, aWallpaper.GetBitmap() ); 965 else 966 { 967 pDev->SetFillColor( aWallpaper.GetColor() ); 968 pDev->DrawRect( Rectangle( aPos, aSize ) ); 969 } 970 971 if (!( GetStyle() & WB_NOBORDER )) 972 { 973 ImplBorderWindow aImplWin( this, WB_BORDER|WB_STDWORK, BORDERWINDOW_STYLE_OVERLAP ); 974 aImplWin.SetText( GetText() ); 975 aImplWin.SetPosSizePixel( aPos.X(), aPos.Y(), aSize.Width(), aSize.Height() ); 976 aImplWin.SetDisplayActive( sal_True ); 977 aImplWin.InitView(); 978 979 aImplWin.Draw( Rectangle( aPos, aSize ), pDev, aPos ); 980 } 981 982 pDev->Pop(); 983 } 984 985 986 // ======================================================================= 987 988 ModelessDialog::ModelessDialog( Window* pParent, WinBits nStyle ) : 989 Dialog( WINDOW_MODELESSDIALOG ) 990 { 991 ImplInit( pParent, nStyle ); 992 } 993 994 // ----------------------------------------------------------------------- 995 996 ModelessDialog::ModelessDialog( Window* pParent, const ResId& rResId ) : 997 Dialog( WINDOW_MODELESSDIALOG ) 998 { 999 rResId.SetRT( RSC_MODELESSDIALOG ); 1000 WinBits nStyle = ImplInitRes( rResId ); 1001 ImplInit( pParent, nStyle ); 1002 ImplLoadRes( rResId ); 1003 1004 if ( !(nStyle & WB_HIDE) ) 1005 Show(); 1006 } 1007 1008 // ======================================================================= 1009 1010 ModalDialog::ModalDialog( Window* pParent, WinBits nStyle ) : 1011 Dialog( WINDOW_MODALDIALOG ) 1012 { 1013 ImplInit( pParent, nStyle ); 1014 } 1015 1016 // ----------------------------------------------------------------------- 1017 1018 ModalDialog::ModalDialog( Window* pParent, const ResId& rResId ) : 1019 Dialog( WINDOW_MODALDIALOG ) 1020 { 1021 rResId.SetRT( RSC_MODALDIALOG ); 1022 ImplInit( pParent, ImplInitRes( rResId ) ); 1023 ImplLoadRes( rResId ); 1024 } 1025