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