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_sfx2.hxx" 30 31 #ifdef SOLARIS 32 // HACK: prevent conflict between STLPORT and Workshop headers on Solaris 8 33 #include <ctime> 34 #endif 35 36 #include <string> // HACK: prevent conflict between STLPORT and Workshop headers 37 38 #ifndef _WRKWIN_HXX //autogen 39 #include <vcl/wrkwin.hxx> 40 #endif 41 #include <unotools/viewoptions.hxx> 42 #ifndef GCC 43 #endif 44 45 #include <vcl/timer.hxx> 46 47 #include "splitwin.hxx" 48 #include "workwin.hxx" 49 #include <sfx2/dockwin.hxx> 50 #include <sfx2/app.hxx> 51 #include "dialog.hrc" 52 #include "sfx2/sfxresid.hxx" 53 #include <sfx2/mnumgr.hxx> 54 #include "virtmenu.hxx" 55 #include <sfx2/msgpool.hxx> 56 #include <sfx2/viewfrm.hxx> 57 58 using namespace ::com::sun::star::uno; 59 using namespace ::rtl; 60 61 #define VERSION 1 62 #define nPixel 30L 63 #define USERITEM_NAME OUString::createFromAscii( "UserItem" ) 64 65 struct SfxDock_Impl 66 { 67 sal_uInt16 nType; 68 SfxDockingWindow* pWin; // This window has SplitWindow 69 sal_Bool bNewLine; 70 sal_Bool bHide; // SplitWindow had this window 71 long nSize; 72 }; 73 74 typedef SfxDock_Impl* SfxDockPtr; 75 SV_DECL_PTRARR_DEL( SfxDockArr_Impl, SfxDockPtr, 4, 4) 76 SV_IMPL_PTRARR( SfxDockArr_Impl, SfxDockPtr); 77 78 class SfxEmptySplitWin_Impl : public SplitWindow 79 { 80 /* [Beschreibung] 81 82 SfxEmptySplitWin_Impldow is an empty split window replacing the SfxSplitWindow 83 in AutoHide mode. It works as a placeholder to receive mouse MouseMoves. 84 the actual light split window display 85 */ 86 friend class SfxSplitWindow; 87 88 SfxSplitWindow* pOwner; 89 sal_Bool bFadeIn; 90 sal_Bool bAutoHide; 91 sal_Bool bSplit; 92 sal_Bool bEndAutoHide; 93 Timer aTimer; 94 Point aLastPos; 95 sal_uInt16 nState; 96 97 SfxEmptySplitWin_Impl( SfxSplitWindow *pParent ) 98 : SplitWindow( pParent->GetParent(), WinBits( WB_BORDER | WB_3DLOOK ) ) 99 , pOwner( pParent ) 100 , bFadeIn( sal_False ) 101 , bAutoHide( sal_False ) 102 , bSplit( sal_False ) 103 , bEndAutoHide( sal_False ) 104 , nState( 1 ) 105 { 106 aTimer.SetTimeoutHdl( 107 LINK(pOwner, SfxSplitWindow, TimerHdl ) ); 108 aTimer.SetTimeout( 200 ); 109 // EnableDrop( sal_True ); 110 SetAlign( pOwner->GetAlign() ); 111 Actualize(); 112 ShowAutoHideButton( pOwner->IsAutoHideButtonVisible() ); 113 ShowFadeInHideButton( sal_True ); 114 } 115 116 ~SfxEmptySplitWin_Impl() 117 { 118 aTimer.Stop(); 119 } 120 121 virtual void MouseMove( const MouseEvent& ); 122 virtual void AutoHide(); 123 virtual void FadeIn(); 124 void Actualize(); 125 }; 126 127 void SfxEmptySplitWin_Impl::Actualize() 128 { 129 Size aSize( pOwner->GetSizePixel() ); 130 switch ( pOwner->GetAlign() ) 131 { 132 case WINDOWALIGN_LEFT: 133 case WINDOWALIGN_RIGHT: 134 aSize.Width() = GetFadeInSize(); 135 break; 136 case WINDOWALIGN_TOP: 137 case WINDOWALIGN_BOTTOM: 138 aSize.Height() = GetFadeInSize(); 139 break; 140 } 141 142 SetSizePixel( aSize ); 143 } 144 145 void SfxEmptySplitWin_Impl::AutoHide() 146 { 147 pOwner->SetPinned_Impl( !pOwner->bPinned ); 148 pOwner->SaveConfig_Impl(); 149 bAutoHide = sal_True; 150 FadeIn(); 151 } 152 153 void SfxEmptySplitWin_Impl::FadeIn() 154 { 155 if (!bAutoHide ) 156 bAutoHide = IsFadeNoButtonMode(); 157 pOwner->SetFadeIn_Impl( sal_True ); 158 pOwner->Show_Impl(); 159 if ( bAutoHide ) 160 { 161 // Put timer to close; the caller must make sure it is, 162 // that the window does not stay or leave ( z.B. by setting the 163 // Focus mode or modal ) 164 aLastPos = GetPointerPosPixel(); 165 aTimer.Start(); 166 } 167 else 168 pOwner->SaveConfig_Impl(); 169 } 170 171 //------------------------------------------------------------------------- 172 173 void SfxSplitWindow::MouseButtonDown( const MouseEvent& rMEvt ) 174 { 175 if ( rMEvt.GetClicks() != 2 ) 176 SplitWindow::MouseButtonDown( rMEvt ); 177 } 178 179 void SfxEmptySplitWin_Impl::MouseMove( const MouseEvent& rMEvt ) 180 { 181 SplitWindow::MouseMove( rMEvt ); 182 } 183 184 //------------------------------------------------------------------------- 185 186 SfxSplitWindow::SfxSplitWindow( Window* pParent, SfxChildAlignment eAl, 187 SfxWorkWindow *pW, sal_Bool bWithButtons, WinBits nBits ) 188 189 /* [Beschreibung] 190 191 Ein SfxSplitWindow verbirgt die rekursive Struktur des SV-Splitwindows 192 nach au\sen, indem es einen tabellenartigen Aufbau mit Zeilen und Spalten 193 ( also maximale Rekursionstiefe 2 ) simuliert. 194 Au\erdem sichert es die Persistenz der Anordnung der SfxDockingWindows. 195 */ 196 197 : SplitWindow ( pParent, nBits | WB_HIDE ), 198 eAlign(eAl), 199 pWorkWin(pW), 200 pDockArr( new SfxDockArr_Impl ), 201 bLocked(sal_False), 202 bPinned(sal_True), 203 pEmptyWin(NULL), 204 pActive(NULL) 205 { 206 if ( bWithButtons ) 207 { 208 ShowAutoHideButton( sal_False ); // no autohide button (pin) anymore 209 ShowFadeOutButton( sal_True ); 210 } 211 212 // SV-Alignment setzen 213 WindowAlign eTbxAlign; 214 switch ( eAlign ) 215 { 216 case SFX_ALIGN_LEFT: 217 eTbxAlign = WINDOWALIGN_LEFT; 218 break; 219 case SFX_ALIGN_RIGHT: 220 eTbxAlign = WINDOWALIGN_RIGHT; 221 break; 222 case SFX_ALIGN_TOP: 223 eTbxAlign = WINDOWALIGN_TOP; 224 break; 225 case SFX_ALIGN_BOTTOM: 226 eTbxAlign = WINDOWALIGN_BOTTOM; 227 bPinned = sal_True; 228 break; 229 default: 230 eTbxAlign = WINDOWALIGN_TOP; // some sort of default... 231 break; // -Wall lots not handled.. 232 } 233 234 SetAlign (eTbxAlign); 235 pEmptyWin = new SfxEmptySplitWin_Impl( this ); 236 if ( bPinned ) 237 { 238 pEmptyWin->bFadeIn = sal_True; 239 pEmptyWin->nState = 2; 240 } 241 242 if ( bWithButtons ) 243 { 244 // Konfiguration einlesen 245 String aWindowId = String::CreateFromAscii("SplitWindow"); 246 aWindowId += String::CreateFromInt32( (sal_Int32) eTbxAlign ); 247 SvtViewOptions aWinOpt( E_WINDOW, aWindowId ); 248 String aWinData; 249 Any aUserItem = aWinOpt.GetUserItem( USERITEM_NAME ); 250 OUString aTemp; 251 if ( aUserItem >>= aTemp ) 252 aWinData = String( aTemp ); 253 if ( aWinData.Len() && aWinData.GetChar( (sal_uInt16) 0 ) == 'V' ) 254 { 255 pEmptyWin->nState = (sal_uInt16) aWinData.GetToken( 1, ',' ).ToInt32(); 256 if ( pEmptyWin->nState & 2 ) 257 pEmptyWin->bFadeIn = sal_True; 258 //bPinned = !( pEmptyWin->nState & 1 ); 259 bPinned = sal_True; // always assume pinned - floating mode not used anymore 260 261 sal_uInt16 i=2; 262 sal_uInt16 nCount = (sal_uInt16) aWinData.GetToken(i++, ',').ToInt32(); 263 for ( sal_uInt16 n=0; n<nCount; n++ ) 264 { 265 SfxDock_Impl *pDock = new SfxDock_Impl; 266 pDock->pWin = 0; 267 pDock->bNewLine = sal_False; 268 pDock->bHide = sal_True; 269 pDock->nType = (sal_uInt16) aWinData.GetToken(i++, ',').ToInt32(); 270 if ( !pDock->nType ) 271 { 272 // K"onnte NewLine bedeuten 273 pDock->nType = (sal_uInt16) aWinData.GetToken(i++, ',').ToInt32(); 274 if ( !pDock->nType ) 275 { 276 // Lesefehler 277 delete pDock; 278 break; 279 } 280 else 281 pDock->bNewLine = sal_True; 282 } 283 284 pDockArr->Insert(pDock,n); 285 } 286 } 287 } 288 else 289 { 290 bPinned = sal_True; 291 pEmptyWin->bFadeIn = sal_True; 292 pEmptyWin->nState = 2; 293 } 294 295 SetAutoHideState( !bPinned ); 296 pEmptyWin->SetAutoHideState( !bPinned ); 297 } 298 299 //------------------------------------------------------------------------- 300 301 SfxSplitWindow::~SfxSplitWindow() 302 { 303 if ( !pWorkWin->GetParent_Impl() ) 304 SaveConfig_Impl(); 305 306 if ( pEmptyWin ) 307 { 308 // pOwner auf NULL setzen, sonst versucht pEmptyWin, nochmal zu 309 // l"oschen; es wird n"amlich von au\sen immer das Fenster deleted, 310 // das gerade angedockt ist 311 pEmptyWin->pOwner = NULL; 312 delete pEmptyWin; 313 } 314 315 delete pDockArr; 316 } 317 318 void SfxSplitWindow::SaveConfig_Impl() 319 { 320 // Konfiguration abspeichern 321 String aWinData('V'); 322 aWinData += String::CreateFromInt32( VERSION ); 323 aWinData += ','; 324 aWinData += String::CreateFromInt32( pEmptyWin->nState ); 325 aWinData += ','; 326 327 sal_uInt16 nCount = 0; 328 sal_uInt16 n; 329 for ( n=0; n<pDockArr->Count(); n++ ) 330 { 331 SfxDock_Impl *pDock = (*pDockArr)[n]; 332 if ( pDock->bHide || pDock->pWin ) 333 nCount++; 334 } 335 336 aWinData += String::CreateFromInt32( nCount ); 337 338 for ( n=0; n<pDockArr->Count(); n++ ) 339 { 340 SfxDock_Impl *pDock = (*pDockArr)[n]; 341 if ( !pDock->bHide && !pDock->pWin ) 342 continue; 343 if ( pDock->bNewLine ) 344 aWinData += DEFINE_CONST_UNICODE(",0"); 345 aWinData += ','; 346 aWinData += String::CreateFromInt32( pDock->nType); 347 } 348 349 String aWindowId = String::CreateFromAscii("SplitWindow"); 350 aWindowId += String::CreateFromInt32( (sal_Int32) GetAlign() ); 351 SvtViewOptions aWinOpt( E_WINDOW, aWindowId ); 352 aWinOpt.SetUserItem( USERITEM_NAME, makeAny( OUString( aWinData ) ) ); 353 } 354 355 //------------------------------------------------------------------------- 356 357 void SfxSplitWindow::StartSplit() 358 { 359 long nSize = 0; 360 Size aSize = GetSizePixel(); 361 362 if ( pEmptyWin ) 363 { 364 pEmptyWin->bFadeIn = sal_True; 365 pEmptyWin->bSplit = sal_True; 366 } 367 368 Rectangle aRect = pWorkWin->GetFreeArea( !bPinned ); 369 switch ( GetAlign() ) 370 { 371 case WINDOWALIGN_LEFT: 372 case WINDOWALIGN_RIGHT: 373 nSize = aSize.Width() + aRect.GetWidth(); 374 break; 375 case WINDOWALIGN_TOP: 376 case WINDOWALIGN_BOTTOM: 377 nSize = aSize.Height() + aRect.GetHeight(); 378 break; 379 } 380 381 SetMaxSizePixel( nSize ); 382 } 383 384 //------------------------------------------------------------------------- 385 386 void SfxSplitWindow::SplitResize() 387 { 388 if ( bPinned ) 389 { 390 pWorkWin->ArrangeChilds_Impl(); 391 pWorkWin->ShowChilds_Impl(); 392 } 393 else 394 pWorkWin->ArrangeAutoHideWindows( this ); 395 } 396 397 //------------------------------------------------------------------------- 398 399 void SfxSplitWindow::Split() 400 { 401 if ( pEmptyWin ) 402 pEmptyWin->bSplit = sal_False; 403 404 SplitWindow::Split(); 405 406 sal_uInt16 nCount = pDockArr->Count(); 407 for ( sal_uInt16 n=0; n<nCount; n++ ) 408 { 409 SfxDock_Impl *pD = (*pDockArr)[n]; 410 if ( pD->pWin ) 411 { 412 sal_uInt16 nId = pD->nType; 413 long nSize = GetItemSize( nId, SWIB_FIXED ); 414 long nSetSize = GetItemSize( GetSet( nId ) ); 415 Size aSize; 416 417 if ( IsHorizontal() ) 418 { 419 aSize.Width() = nSize; 420 aSize.Height() = nSetSize; 421 } 422 else 423 { 424 aSize.Width() = nSetSize; 425 aSize.Height() = nSize; 426 } 427 428 pD->pWin->SetItemSize_Impl( aSize ); 429 } 430 } 431 432 SaveConfig_Impl(); 433 } 434 435 //------------------------------------------------------------------------- 436 437 void SfxSplitWindow::InsertWindow( SfxDockingWindow* pDockWin, const Size& rSize) 438 439 /* [Beschreibung] 440 441 To insert SfxDockingWindows with no position can also be transfered. 442 The SfxSplitWindow then searches out the noted recently transfered 443 to the newly SfxDockingWindow or it depends on the last. 444 445 */ 446 { 447 short nLine = -1; // so first window can be set to 0 nLine high 448 sal_uInt16 nL; 449 sal_uInt16 nPos = 0; 450 sal_Bool bNewLine = sal_True; 451 sal_Bool bSaveConfig = sal_False; 452 SfxDock_Impl *pFoundDock=0; 453 sal_uInt16 nCount = pDockArr->Count(); 454 for ( sal_uInt16 n=0; n<nCount; n++ ) 455 { 456 SfxDock_Impl *pDock = (*pDockArr)[n]; 457 if ( pDock->bNewLine ) 458 { 459 // The window opens a new line 460 if ( pFoundDock ) 461 // But behind the window just inserted 462 break; 463 464 // new line 465 nPos = 0; 466 bNewLine = sal_True; 467 } 468 469 if ( pDock->pWin ) 470 { 471 // It is at this point just a window 472 if ( bNewLine && !pFoundDock ) 473 { 474 // It is not known, in which real line is the one 475 GetWindowPos( pDock->pWin, nL, nPos ); 476 nLine = (short) nL; 477 } 478 479 if ( !pFoundDock ) 480 { 481 // before the window is attached 482 nPos++; 483 } 484 485 // Line is now open 486 bNewLine = sal_False; 487 if ( pFoundDock ) 488 break; 489 } 490 491 if ( pDock->nType == pDockWin->GetType() ) 492 { 493 DBG_ASSERT( !pFoundDock && !pDock->pWin, "Window is already available!"); 494 pFoundDock = pDock; 495 if ( !bNewLine ) 496 break; 497 else 498 { 499 // It was most recently a new series started, but not found a 500 // window above it, so keep looking if nochein window follows 501 // this line to bNewLine to set correctly. But it must be nLine 502 // or nPos shouldn't be changed. 503 nLine++; 504 } 505 } 506 } 507 508 if ( !pFoundDock ) 509 { 510 // Nicht gefunden, am Ende einf"ugen 511 pFoundDock = new SfxDock_Impl; 512 pFoundDock->bHide = sal_True; 513 pDockArr->Insert( pFoundDock, nCount ); 514 pFoundDock->nType = pDockWin->GetType(); 515 nLine++; 516 nPos = 0; 517 bNewLine = sal_True; 518 pFoundDock->bNewLine = bNewLine; 519 bSaveConfig = sal_True; 520 } 521 522 pFoundDock->pWin = pDockWin; 523 pFoundDock->bHide = sal_False; 524 InsertWindow_Impl( pFoundDock, rSize, nLine, nPos, bNewLine ); 525 if ( bSaveConfig ) 526 SaveConfig_Impl(); 527 } 528 529 //------------------------------------------------------------------------- 530 531 void SfxSplitWindow::ReleaseWindow_Impl(SfxDockingWindow *pDockWin, sal_Bool bSave) 532 533 /* [Beschreibung] 534 535 The DockinWindow is no longer stored in the internal data. 536 */ 537 538 { 539 SfxDock_Impl *pDock=0; 540 sal_uInt16 nCount = pDockArr->Count(); 541 sal_Bool bFound = sal_False; 542 for ( sal_uInt16 n=0; n<nCount; n++ ) 543 { 544 pDock = (*pDockArr)[n]; 545 if ( pDock->nType == pDockWin->GetType() ) 546 { 547 if ( pDock->bNewLine && n<nCount-1 ) 548 (*pDockArr)[n+1]->bNewLine = sal_True; 549 550 // Fenster hat schon eine Position, die vergessen wir 551 bFound = sal_True; 552 pDockArr->Remove(n); 553 break; 554 } 555 } 556 557 if ( bFound ) 558 delete pDock; 559 560 if ( bSave ) 561 SaveConfig_Impl(); 562 } 563 564 //------------------------------------------------------------------------- 565 566 void SfxSplitWindow::MoveWindow( SfxDockingWindow* pDockWin, const Size& rSize, 567 sal_uInt16 nLine, sal_uInt16 nPos, sal_Bool bNewLine) 568 569 /* [Beschreibung] 570 571 Das DockingWindow wird innerhalb des Splitwindows verschoben. 572 573 */ 574 575 { 576 sal_uInt16 nL, nP; 577 GetWindowPos( pDockWin, nL, nP ); 578 579 if ( nLine > nL && GetItemCount( GetItemId( nL, 0 ) ) == 1 ) 580 { 581 // Wenn das letzte Fenster aus seiner Zeile entfernt wird, rutscht 582 // alles eine Zeile nach vorne! 583 nLine--; 584 } 585 /* 586 else if ( nLine == nL && nPos > nP ) 587 { 588 nPos--; 589 } 590 */ 591 RemoveWindow( pDockWin ); 592 InsertWindow( pDockWin, rSize, nLine, nPos, bNewLine ); 593 } 594 595 //------------------------------------------------------------------------- 596 597 void SfxSplitWindow::InsertWindow( SfxDockingWindow* pDockWin, const Size& rSize, 598 sal_uInt16 nLine, sal_uInt16 nPos, sal_Bool bNewLine) 599 600 /* [Beschreibung] 601 602 Das DockingWindow wird in dieses Splitwindow geschoben und soll die 603 "ubergebene Position und Gr"o\se haben. 604 605 */ 606 { 607 ReleaseWindow_Impl( pDockWin, sal_False ); 608 SfxDock_Impl *pDock = new SfxDock_Impl; 609 pDock->bHide = sal_False; 610 pDock->nType = pDockWin->GetType(); 611 pDock->bNewLine = bNewLine; 612 pDock->pWin = pDockWin; 613 614 DBG_ASSERT( nPos==0 || !bNewLine, "Wrong Parameter!"); 615 if ( bNewLine ) 616 nPos = 0; 617 618 // The window introduced before the first window are suffices that the 619 // body or a greater position as the pDockWin. 620 sal_uInt16 nCount = pDockArr->Count(); 621 sal_uInt16 nLastWindowIdx(0); 622 623 // If window not found, is inserted as the first 624 sal_uInt16 nInsertPos = 0; 625 for ( sal_uInt16 n=0; n<nCount; n++ ) 626 { 627 SfxDock_Impl *pD = (*pDockArr)[n]; 628 629 if (pD->pWin) 630 { 631 // Ein angedocktes Fenster wurde gefunden 632 // Wenn kein geeignetes Fenster hinter der gew"unschten Einf"ugeposition 633 // gefunden wird, wird am Ende eingef"ugt 634 nInsertPos = nCount; 635 nLastWindowIdx = n; 636 sal_uInt16 nL=0, nP=0; 637 GetWindowPos( pD->pWin, nL, nP ); 638 639 if ( (nL == nLine && nP == nPos) || nL > nLine ) 640 { 641 DBG_ASSERT( nL == nLine || bNewLine || nPos > 0, "Wrong Parameter!" ); 642 if ( nL == nLine && nPos == 0 && !bNewLine ) 643 { 644 DBG_ASSERT(pD->bNewLine, "No new line?"); 645 646 // Das Fenster wird auf nPos==0 eingeschoben 647 pD->bNewLine = sal_False; 648 pDock->bNewLine = sal_True; 649 } 650 651 nInsertPos = n != 0 ? nLastWindowIdx + 1 : 0; // ignore all non-windows after the last window 652 break; 653 } 654 } 655 } 656 if (nInsertPos == nCount && nLastWindowIdx != nCount - 1) 657 { 658 nInsertPos = nLastWindowIdx + 1; // ignore all non-windows after the last window 659 } 660 661 pDockArr->Insert(pDock, nInsertPos); 662 InsertWindow_Impl( pDock, rSize, nLine, nPos, bNewLine ); 663 SaveConfig_Impl(); 664 } 665 666 //------------------------------------------------------------------------- 667 668 void SfxSplitWindow::InsertWindow_Impl( SfxDock_Impl* pDock, 669 const Size& rSize, 670 sal_uInt16 nLine, sal_uInt16 nPos, sal_Bool bNewLine) 671 672 /* [Beschreibung] 673 674 F"ugt ein DockingWindow ein und veranla\st die Neuberechnung der Gr"o\se 675 des Splitwindows. 676 */ 677 678 { 679 SfxDockingWindow* pDockWin = pDock->pWin; 680 681 sal_uInt16 nItemBits = pDockWin->GetWinBits_Impl(); 682 683 long nWinSize, nSetSize; 684 if ( IsHorizontal() ) 685 { 686 nWinSize = rSize.Width(); 687 nSetSize = rSize.Height(); 688 } 689 else 690 { 691 nSetSize = rSize.Width(); 692 nWinSize = rSize.Height(); 693 } 694 695 pDock->nSize = nWinSize; 696 697 sal_Bool bUpdateMode = IsUpdateMode(); 698 if ( bUpdateMode ) 699 SetUpdateMode( sal_False ); 700 701 if ( bNewLine || nLine == GetItemCount( 0 ) ) 702 { 703 // Es soll nicht in eine vorhandene Zeile eingef"ugt werden, sondern 704 // eine neue erzeugt werden 705 706 sal_uInt16 nId = 1; 707 for ( sal_uInt16 n=0; n<GetItemCount(0); n++ ) 708 { 709 if ( GetItemId(n) >= nId ) 710 nId = GetItemId(n)+1; 711 } 712 713 // Eine neue nLine-te Zeile erzeugen 714 sal_uInt16 nBits = nItemBits; 715 if ( GetAlign() == WINDOWALIGN_TOP || GetAlign() == WINDOWALIGN_BOTTOM ) 716 nBits |= SWIB_COLSET; 717 InsertItem( nId, nSetSize, nLine, 0, nBits ); 718 } 719 720 // In Zeile mit Position nLine das Fenster einf"ugen 721 // ItemWindowSize auf "Prozentual" setzen, da SV dann das Umgr"o\sern 722 // so macht, wie man erwartet; "Pixel" macht eigentlich nur Sinn, wenn 723 // auch Items mit prozentualen oder relativen Gr"o\sen dabei sind. 724 nItemBits |= SWIB_PERCENTSIZE; 725 bLocked = sal_True; 726 sal_uInt16 nSet = GetItemId( nLine ); 727 InsertItem( pDockWin->GetType(), pDockWin, nWinSize, nPos, nSet, nItemBits ); 728 729 // Splitwindows werden im SFX einmal angelegt und beim Einf"ugen des ersten 730 // DockingWindows sichtbar gemacht. 731 if ( GetItemCount( 0 ) == 1 && GetItemCount( 1 ) == 1 ) 732 { 733 // Das Neuarrangieren am WorkWindow und ein Show() auf das SplitWindow 734 // wird vom SfxDockingwindow veranla\st (->SfxWorkWindow::ConfigChild_Impl) 735 if ( !bPinned && !IsFloatingMode() ) 736 { 737 bPinned = sal_True; 738 sal_Bool bFadeIn = ( pEmptyWin->nState & 2 ) != 0; 739 pEmptyWin->bFadeIn = sal_False; 740 SetPinned_Impl( sal_False ); 741 pEmptyWin->Actualize(); 742 DBG_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" ); 743 pWorkWin->RegisterChild_Impl( *GetSplitWindow(), eAlign, sal_True )->nVisible = CHILD_VISIBLE; 744 pWorkWin->ArrangeChilds_Impl(); 745 if ( bFadeIn ) 746 FadeIn(); 747 } 748 else 749 { 750 sal_Bool bFadeIn = ( pEmptyWin->nState & 2 ) != 0; 751 pEmptyWin->bFadeIn = sal_False; 752 pEmptyWin->Actualize(); 753 #ifdef DBG_UTIL 754 if ( !bPinned || !pEmptyWin->bFadeIn ) 755 { 756 DBG_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" ); 757 } 758 else 759 { 760 DBG_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering real Splitwindow" ); 761 } 762 #endif 763 pWorkWin->RegisterChild_Impl( *GetSplitWindow(), eAlign, sal_True )->nVisible = CHILD_VISIBLE; 764 pWorkWin->ArrangeChilds_Impl(); 765 if ( bFadeIn ) 766 FadeIn(); 767 } 768 769 pWorkWin->ShowChilds_Impl(); 770 } 771 772 if ( bUpdateMode ) 773 SetUpdateMode( sal_True ); 774 bLocked = sal_False; 775 } 776 777 //------------------------------------------------------------------------- 778 779 void SfxSplitWindow::RemoveWindow( SfxDockingWindow* pDockWin, sal_Bool bHide ) 780 781 /* [Beschreibung] 782 783 Entfernt ein DockingWindow. Wenn es das letzte war, wird das SplitWindow 784 gehidet. 785 */ 786 { 787 sal_uInt16 nSet = GetSet( pDockWin->GetType() ); 788 789 // Splitwindows werden im SFX einmal angelegt und nach dem Entfernen 790 // des letzten DockingWindows unsichtbar gemacht. 791 if ( GetItemCount( nSet ) == 1 && GetItemCount( 0 ) == 1 ) 792 { 793 // Das Neuarrangieren am WorkWindow wird vom SfxDockingwindow 794 // veranla\st! 795 Hide(); 796 pEmptyWin->aTimer.Stop(); 797 sal_uInt16 nRealState = pEmptyWin->nState; 798 FadeOut_Impl(); 799 pEmptyWin->Hide(); 800 #ifdef DBG_UTIL 801 if ( !bPinned || !pEmptyWin->bFadeIn ) 802 { 803 DBG_TRACE( "SfxSplitWindow::RemoveWindow - releasing empty Splitwindow" ); 804 } 805 else 806 { 807 DBG_TRACE( "SfxSplitWindow::RemoveWindow - releasing real Splitwindow" ); 808 } 809 #endif 810 pWorkWin->ReleaseChild_Impl( *GetSplitWindow() ); 811 pEmptyWin->nState = nRealState; 812 pWorkWin->ArrangeAutoHideWindows( this ); 813 } 814 815 SfxDock_Impl *pDock=0; 816 sal_uInt16 nCount = pDockArr->Count(); 817 for ( sal_uInt16 n=0; n<nCount; n++ ) 818 { 819 pDock = (*pDockArr)[n]; 820 if ( pDock->nType == pDockWin->GetType() ) 821 { 822 pDock->pWin = 0; 823 pDock->bHide = bHide; 824 break; 825 } 826 } 827 828 // Fenster removen, und wenn es das letzte der Zeile war, auch die Zeile 829 // ( Zeile = ItemSet ) 830 sal_Bool bUpdateMode = IsUpdateMode(); 831 if ( bUpdateMode ) 832 SetUpdateMode( sal_False ); 833 bLocked = sal_True; 834 835 RemoveItem( pDockWin->GetType() ); 836 837 if ( nSet && !GetItemCount( nSet ) ) 838 RemoveItem( nSet ); 839 840 if ( bUpdateMode ) 841 SetUpdateMode( sal_True ); 842 bLocked = sal_False; 843 }; 844 845 //------------------------------------------------------------------------- 846 847 sal_Bool SfxSplitWindow::GetWindowPos( const SfxDockingWindow* pWindow, 848 sal_uInt16& rLine, sal_uInt16& rPos ) const 849 /* [Beschreibung] 850 851 Liefert die Id des Itemsets und die des Items f"ur das "ubergebene 852 DockingWindow in der alten Zeilen/Spalten-Bezeichnung zur"uck. 853 */ 854 855 { 856 sal_uInt16 nSet = GetSet ( pWindow->GetType() ); 857 if ( nSet == SPLITWINDOW_ITEM_NOTFOUND ) 858 return sal_False; 859 860 rPos = GetItemPos( pWindow->GetType(), nSet ); 861 rLine = GetItemPos( nSet ); 862 return sal_True; 863 } 864 865 //------------------------------------------------------------------------- 866 867 sal_Bool SfxSplitWindow::GetWindowPos( const Point& rTestPos, 868 sal_uInt16& rLine, sal_uInt16& rPos ) const 869 /* [Beschreibung] 870 871 Liefert die Id des Itemsets und die des Items f"ur das DockingWindow 872 an der "ubergebenen Position in der alten Zeilen/Spalten-Bezeichnung 873 zur"uck. 874 */ 875 876 { 877 sal_uInt16 nId = GetItemId( rTestPos ); 878 if ( nId == 0 ) 879 return sal_False; 880 881 sal_uInt16 nSet = GetSet ( nId ); 882 rPos = GetItemPos( nId, nSet ); 883 rLine = GetItemPos( nSet ); 884 return sal_True; 885 } 886 887 //------------------------------------------------------------------------- 888 889 sal_uInt16 SfxSplitWindow::GetLineCount() const 890 891 /* [Beschreibung] 892 893 Liefert die Zeilenzahl = Zahl der Sub-Itemsets im Root-Set. 894 */ 895 { 896 return GetItemCount( 0 ); 897 } 898 899 //------------------------------------------------------------------------- 900 901 long SfxSplitWindow::GetLineSize( sal_uInt16 nLine ) const 902 903 /* [Beschreibung] 904 905 Liefert die "Zeilenh"ohe" des nLine-ten Itemsets. 906 */ 907 { 908 sal_uInt16 nId = GetItemId( nLine ); 909 return GetItemSize( nId ); 910 } 911 912 //------------------------------------------------------------------------- 913 914 sal_uInt16 SfxSplitWindow::GetWindowCount( sal_uInt16 nLine ) const 915 916 /* [Beschreibung] 917 918 Liefert die 919 */ 920 { 921 sal_uInt16 nId = GetItemId( nLine ); 922 return GetItemCount( nId ); 923 } 924 925 //------------------------------------------------------------------------- 926 927 sal_uInt16 SfxSplitWindow::GetWindowCount() const 928 929 /* [Beschreibung] 930 931 Liefert die Gesamtzahl aller Fenstert 932 */ 933 { 934 return GetItemCount( 0 ); 935 } 936 937 //------------------------------------------------------------------------- 938 939 void SfxSplitWindow::Command( const CommandEvent& rCEvt ) 940 { 941 SplitWindow::Command( rCEvt ); 942 } 943 944 //------------------------------------------------------------------------- 945 946 IMPL_LINK( SfxSplitWindow, TimerHdl, Timer*, pTimer) 947 { 948 if ( pTimer ) 949 pTimer->Stop(); 950 951 if ( CursorIsOverRect( sal_False ) || !pTimer ) 952 { 953 // Wenn der Mauszeiger innerhalb des Fensters liegt, SplitWindow anzeigen 954 // und Timer zum Schlie\sen aufsetzen 955 pEmptyWin->bAutoHide = sal_True; 956 if ( !IsVisible() ) 957 pEmptyWin->FadeIn(); 958 959 pEmptyWin->aLastPos = GetPointerPosPixel(); 960 pEmptyWin->aTimer.Start(); 961 } 962 else if ( pEmptyWin->bAutoHide ) 963 { 964 if ( GetPointerPosPixel() != pEmptyWin->aLastPos ) 965 { 966 // Die Maus wurd innerhalb der Timerlaugzeit bewegt, also erst einmal 967 // nichts tun 968 pEmptyWin->aLastPos = GetPointerPosPixel(); 969 pEmptyWin->aTimer.Start(); 970 return 0L; 971 } 972 973 // Speziell f"ur TF_AUTOSHOW_ON_MOUSEMOVE : 974 // Wenn das Fenster nicht sichtbar ist, gibt es nichts zu tun 975 // (Benutzer ist einfach mit der Maus "uber pEmptyWin gefahren) 976 if ( IsVisible() ) 977 { 978 pEmptyWin->bEndAutoHide = sal_False; 979 if ( !Application::IsInModalMode() && 980 !PopupMenu::IsInExecute() && 981 !pEmptyWin->bSplit && !HasChildPathFocus( sal_True ) ) 982 { 983 // W"ahrend ein modaler Dialog oder ein Popupmenu offen sind 984 // oder w"ahrend des Splittens auf keinen Fall zumachen; auch 985 // solange eines der Children den Focus hat, bleibt das 986 // das Fenster offen 987 pEmptyWin->bEndAutoHide = sal_True; 988 } 989 990 if ( pEmptyWin->bEndAutoHide ) 991 { 992 // Von mir aus kann Schlu\s sein mit AutoShow 993 // Aber vielleicht will noch ein anderes SfxSplitWindow offen bleiben, 994 // dann bleiben auch alle anderen offen 995 if ( !pWorkWin->IsAutoHideMode( this ) ) 996 { 997 FadeOut_Impl(); 998 pWorkWin->ArrangeAutoHideWindows( this ); 999 } 1000 else 1001 { 1002 pEmptyWin->aLastPos = GetPointerPosPixel(); 1003 pEmptyWin->aTimer.Start(); 1004 } 1005 } 1006 else 1007 { 1008 pEmptyWin->aLastPos = GetPointerPosPixel(); 1009 pEmptyWin->aTimer.Start(); 1010 } 1011 } 1012 } 1013 1014 return 0L; 1015 } 1016 1017 //------------------------------------------------------------------------- 1018 1019 sal_Bool SfxSplitWindow::CursorIsOverRect( sal_Bool bForceAdding ) const 1020 { 1021 sal_Bool bVisible = IsVisible(); 1022 1023 // Auch das kollabierte SplitWindow ber"ucksichtigen 1024 Point aPos = pEmptyWin->GetParent()->OutputToScreenPixel( pEmptyWin->GetPosPixel() ); 1025 Size aSize = pEmptyWin->GetSizePixel(); 1026 1027 if ( bForceAdding ) 1028 { 1029 // Um +/- ein paar Pixel erweitern, sonst ist es zu nerv"os 1030 aPos.X() -= nPixel; 1031 aPos.Y() -= nPixel; 1032 aSize.Width() += 2 * nPixel; 1033 aSize.Height() += 2 * nPixel; 1034 } 1035 1036 Rectangle aRect( aPos, aSize ); 1037 1038 if ( bVisible ) 1039 { 1040 Point aVisPos = GetPosPixel(); 1041 Size aVisSize = GetSizePixel(); 1042 1043 // Um +/- ein paar Pixel erweitern, sonst ist es zu nerv"os 1044 aVisPos.X() -= nPixel; 1045 aVisPos.Y() -= nPixel; 1046 aVisSize.Width() += 2 * nPixel; 1047 aVisSize.Height() += 2 * nPixel; 1048 1049 Rectangle aVisRect( aVisPos, aVisSize ); 1050 aRect = aRect.GetUnion( aVisRect ); 1051 } 1052 1053 if ( aRect.IsInside( OutputToScreenPixel( ((Window*)this)->GetPointerPosPixel() ) ) ) 1054 return sal_True; 1055 return sal_False; 1056 } 1057 1058 //------------------------------------------------------------------------- 1059 1060 SplitWindow* SfxSplitWindow::GetSplitWindow() 1061 { 1062 if ( !bPinned || !pEmptyWin->bFadeIn ) 1063 return pEmptyWin; 1064 return this; 1065 } 1066 1067 //------------------------------------------------------------------------- 1068 sal_Bool SfxSplitWindow::IsFadeIn() const 1069 { 1070 return pEmptyWin->bFadeIn; 1071 } 1072 1073 sal_Bool SfxSplitWindow::IsAutoHide( sal_Bool bSelf ) const 1074 { 1075 return bSelf ? pEmptyWin->bAutoHide && !pEmptyWin->bEndAutoHide : pEmptyWin->bAutoHide; 1076 } 1077 1078 //------------------------------------------------------------------------- 1079 1080 void SfxSplitWindow::SetPinned_Impl( sal_Bool bOn ) 1081 { 1082 if ( bPinned == bOn ) 1083 return; 1084 1085 bPinned = bOn; 1086 if ( GetItemCount( 0 ) == 0 ) 1087 return; 1088 1089 if ( !bOn ) 1090 { 1091 pEmptyWin->nState |= 1; 1092 if ( pEmptyWin->bFadeIn ) 1093 { 1094 // Ersatzfenster anmelden 1095 DBG_TRACE( "SfxSplitWindow::SetPinned_Impl - releasing real Splitwindow" ); 1096 pWorkWin->ReleaseChild_Impl( *this ); 1097 Hide(); 1098 pEmptyWin->Actualize(); 1099 DBG_TRACE( "SfxSplitWindow::SetPinned_Impl - registering empty Splitwindow" ); 1100 pWorkWin->RegisterChild_Impl( *pEmptyWin, eAlign, sal_True )->nVisible = CHILD_VISIBLE; 1101 } 1102 1103 Point aPos( GetPosPixel() ); 1104 aPos = GetParent()->OutputToScreenPixel( aPos ); 1105 SetFloatingPos( aPos ); 1106 SetFloatingMode( sal_True ); 1107 GetFloatingWindow()->SetOutputSizePixel( GetOutputSizePixel() ); 1108 1109 if ( pEmptyWin->bFadeIn ) 1110 Show(); 1111 } 1112 else 1113 { 1114 pEmptyWin->nState &= ~1; 1115 SetOutputSizePixel( GetFloatingWindow()->GetOutputSizePixel() ); 1116 SetFloatingMode( sal_False ); 1117 1118 if ( pEmptyWin->bFadeIn ) 1119 { 1120 // Ersatzfenster abmelden 1121 DBG_TRACE( "SfxSplitWindow::SetPinned_Impl - releasing empty Splitwindow" ); 1122 pWorkWin->ReleaseChild_Impl( *pEmptyWin ); 1123 pEmptyWin->Hide(); 1124 DBG_TRACE( "SfxSplitWindow::SetPinned_Impl - registering real Splitwindow" ); 1125 pWorkWin->RegisterChild_Impl( *this, eAlign, sal_True )->nVisible = CHILD_VISIBLE; 1126 } 1127 } 1128 1129 SetAutoHideState( !bPinned ); 1130 pEmptyWin->SetAutoHideState( !bPinned ); 1131 } 1132 1133 //------------------------------------------------------------------------- 1134 1135 void SfxSplitWindow::SetFadeIn_Impl( sal_Bool bOn ) 1136 { 1137 if ( bOn == pEmptyWin->bFadeIn ) 1138 return; 1139 1140 if ( GetItemCount( 0 ) == 0 ) 1141 return; 1142 1143 pEmptyWin->bFadeIn = bOn; 1144 if ( bOn ) 1145 { 1146 pEmptyWin->nState |= 2; 1147 if ( IsFloatingMode() ) 1148 { 1149 // FloatingWindow ist nicht sichtbar, also anzeigen 1150 pWorkWin->ArrangeAutoHideWindows( this ); 1151 Show(); 1152 } 1153 else 1154 { 1155 DBG_TRACE( "SfxSplitWindow::SetFadeIn_Impl - releasing empty Splitwindow" ); 1156 pWorkWin->ReleaseChild_Impl( *pEmptyWin ); 1157 pEmptyWin->Hide(); 1158 DBG_TRACE( "SfxSplitWindow::SetFadeIn_Impl - registering real Splitwindow" ); 1159 pWorkWin->RegisterChild_Impl( *this, eAlign, sal_True )->nVisible = CHILD_VISIBLE; 1160 pWorkWin->ArrangeChilds_Impl(); 1161 pWorkWin->ShowChilds_Impl(); 1162 } 1163 } 1164 else 1165 { 1166 pEmptyWin->bAutoHide = sal_False; 1167 pEmptyWin->nState &= ~2; 1168 if ( !IsFloatingMode() ) 1169 { 1170 // Das Fenster "schwebt" nicht, soll aber ausgeblendet werden, 1171 DBG_TRACE( "SfxSplitWindow::SetFadeIn_Impl - releasing real Splitwindow" ); 1172 pWorkWin->ReleaseChild_Impl( *this ); 1173 Hide(); 1174 pEmptyWin->Actualize(); 1175 DBG_TRACE( "SfxSplitWindow::SetFadeIn_Impl - registering empty Splitwindow" ); 1176 pWorkWin->RegisterChild_Impl( *pEmptyWin, eAlign, sal_True )->nVisible = CHILD_VISIBLE; 1177 pWorkWin->ArrangeChilds_Impl(); 1178 pWorkWin->ShowChilds_Impl(); 1179 pWorkWin->ArrangeAutoHideWindows( this ); 1180 } 1181 else 1182 { 1183 Hide(); 1184 pWorkWin->ArrangeAutoHideWindows( this ); 1185 } 1186 } 1187 } 1188 1189 void SfxSplitWindow::AutoHide() 1190 { 1191 // Wenn dieser Handler am "echten" SplitWindow aufgerufen wird, ist es 1192 // entweder angedockt und soll "schwebend" angezeigt werden oder umgekehrt 1193 if ( !bPinned ) 1194 { 1195 // Es "schwebt", also wieder andocken 1196 SetPinned_Impl( sal_True ); 1197 pWorkWin->ArrangeChilds_Impl(); 1198 } 1199 else 1200 { 1201 // In den "Schwebezustand" bringen 1202 SetPinned_Impl( sal_False ); 1203 pWorkWin->ArrangeChilds_Impl(); 1204 pWorkWin->ArrangeAutoHideWindows( this ); 1205 } 1206 1207 pWorkWin->ShowChilds_Impl(); 1208 SaveConfig_Impl(); 1209 } 1210 1211 void SfxSplitWindow::FadeOut_Impl() 1212 { 1213 if ( pEmptyWin->aTimer.IsActive() ) 1214 { 1215 pEmptyWin->bAutoHide = sal_False; 1216 pEmptyWin->aTimer.Stop(); 1217 } 1218 1219 SetFadeIn_Impl( sal_False ); 1220 Show_Impl(); 1221 } 1222 1223 void SfxSplitWindow::FadeOut() 1224 { 1225 FadeOut_Impl(); 1226 SaveConfig_Impl(); 1227 } 1228 1229 void SfxSplitWindow::FadeIn() 1230 { 1231 SetFadeIn_Impl( sal_True ); 1232 Show_Impl(); 1233 } 1234 1235 void SfxSplitWindow::Show_Impl() 1236 { 1237 sal_uInt16 nCount = pDockArr->Count(); 1238 for ( sal_uInt16 n=0; n<nCount; n++ ) 1239 { 1240 SfxDock_Impl *pDock = (*pDockArr)[n]; 1241 if ( pDock->pWin ) 1242 pDock->pWin->FadeIn( pEmptyWin->bFadeIn ); 1243 } 1244 } 1245 /* 1246 void SfxSplitWindow::Pin_Impl( sal_Bool bPin ) 1247 { 1248 if ( bPinned != bPin ) 1249 AutoHide(); 1250 } 1251 */ 1252 sal_Bool SfxSplitWindow::ActivateNextChild_Impl( sal_Bool bForward ) 1253 { 1254 // Wenn kein pActive, auf erstes bzw. letztes Fenster gehen ( bei !bForward wird erst in der loop dekrementiert ) 1255 sal_uInt16 nCount = pDockArr->Count(); 1256 sal_uInt16 n = bForward ? 0 : nCount; 1257 1258 // Wenn Focus innerhalb, dann ein Fenster vor oder zur"uck, wenn m"oglich 1259 if ( pActive ) 1260 { 1261 // Aktives Fenster ermitteln 1262 for ( n=0; n<nCount; n++ ) 1263 { 1264 SfxDock_Impl *pD = (*pDockArr)[n]; 1265 if ( pD->pWin && pD->pWin->HasChildPathFocus() ) 1266 break; 1267 } 1268 1269 if ( bForward ) 1270 // ein Fenster weiter ( wenn dann n>nCount, wird die Schleife unten gar nicht durchlaufen ) 1271 n++; 1272 } 1273 1274 if ( bForward ) 1275 { 1276 // N"achstes Fenster suchen 1277 for ( sal_uInt16 nNext=n; nNext<nCount; nNext++ ) 1278 { 1279 SfxDock_Impl *pD = (*pDockArr)[nNext]; 1280 if ( pD->pWin ) 1281 { 1282 pD->pWin->GrabFocus(); 1283 return sal_True; 1284 } 1285 } 1286 } 1287 else 1288 { 1289 // Vorheriges Fenster suchen 1290 for ( sal_uInt16 nNext=n; nNext--; ) 1291 { 1292 SfxDock_Impl *pD = (*pDockArr)[nNext]; 1293 if ( pD->pWin ) 1294 { 1295 pD->pWin->GrabFocus(); 1296 return sal_True; 1297 } 1298 } 1299 } 1300 1301 return sal_False; 1302 } 1303 1304 void SfxSplitWindow::SetActiveWindow_Impl( SfxDockingWindow* pWin ) 1305 { 1306 pActive = pWin; 1307 pWorkWin->SetActiveChild_Impl( this ); 1308 } 1309 1310 1311