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