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; // SplitWindow hat dieses Fenster 69 sal_Bool bNewLine; 70 sal_Bool bHide; // SplitWindow hatte dieses Fenster 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 Das SfxEmptySplitWin_Impldow ist ein leeres SplitWindow, das das SfxSplitWindow 83 im AutoHide-Modus ersetzt. Es dient nur als Platzhalter, um MouseMoves 84 zu empfangen und ggf. das eigentlichte SplitWindow einzublenden 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 // Timer zum Schlie\sen aufsetzen; der Aufrufer mu\s selbst sicherstellen, 162 // da\s das Window nicht gleich wieder zu geht ( z.B. durch Setzen des 163 // Focus oder einen modal mode ) 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 Zum Einf"ugen von SfxDockingWindows kann auch keine Position "ubergeben 442 werden. Das SfxSplitWindow sucht dann die zuletzt gemerkte zu dem 443 "ubergebenen SfxDockingWindow heraus oder h"angt es als letztes neu an. 444 445 */ 446 { 447 short nLine = -1; // damit erstes Fenster nLine auf 0 hochsetzen kann 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 // Das Fenster er"offnet eine neue Zeile 460 if ( pFoundDock ) 461 // Aber hinter dem gerade eingef"ugten Fenster 462 break; 463 464 // Neue Zeile 465 nPos = 0; 466 bNewLine = sal_True; 467 } 468 469 if ( pDock->pWin ) 470 { 471 // Es gibt an dieser Stelle gerade ein Fenster 472 if ( bNewLine && !pFoundDock ) 473 { 474 // Bisher ist nicht bekannt, in welcher realen Zeile es liegt 475 GetWindowPos( pDock->pWin, nL, nPos ); 476 nLine = (short) nL; 477 } 478 479 if ( !pFoundDock ) 480 { 481 // Fenster liegt vor dem eingef"ugten 482 nPos++; 483 } 484 485 // Zeile ist schon er"offnet 486 bNewLine = sal_False; 487 if ( pFoundDock ) 488 break; 489 } 490 491 if ( pDock->nType == pDockWin->GetType() ) 492 { 493 DBG_ASSERT( !pFoundDock && !pDock->pWin, "Fenster ist schon vorhanden!"); 494 pFoundDock = pDock; 495 if ( !bNewLine ) 496 break; 497 else 498 { 499 // Es wurde zuletzt eine neue Reihe gestartet, aber noch kein 500 // darin liegendes Fenster gefunden; daher weitersuchen, ob noch 501 // ein Fenster in dieser Zeile folgt, um bNewLine korrekt zu setzen. 502 // Dabei darf aber nLine oder nPos nicht mehr ver"andert werden! 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 Das DockingWindow wird nicht mehr in den internen Daten gespeichert. 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, "Falsche Paramenter!"); 615 if ( bNewLine ) 616 nPos = 0; 617 618 // Das Fenster mu\s vor dem ersten Fenster eingef"ugt werden, das die 619 // gleiche oder eine gr"o\sere Position hat als pDockWin. 620 sal_uInt16 nCount = pDockArr->Count(); 621 622 // Wenn gar kein Fenster gefunden wird, wird als erstes eingef"ugt 623 sal_uInt16 nInsertPos = 0; 624 for ( sal_uInt16 n=0; n<nCount; n++ ) 625 { 626 SfxDock_Impl *pD = (*pDockArr)[n]; 627 628 if (pD->pWin) 629 { 630 // Ein angedocktes Fenster wurde gefunden 631 // Wenn kein geeignetes Fenster hinter der gew"unschten Einf"ugeposition 632 // gefunden wird, wird am Ende eingef"ugt 633 nInsertPos = nCount; 634 sal_uInt16 nL=0, nP=0; 635 GetWindowPos( pD->pWin, nL, nP ); 636 637 if ( (nL == nLine && nP == nPos) || nL > nLine ) 638 { 639 DBG_ASSERT( nL == nLine || bNewLine || nPos > 0, "Falsche Parameter!" ); 640 if ( nL == nLine && nPos == 0 && !bNewLine ) 641 { 642 DBG_ASSERT(pD->bNewLine, "Keine neue Zeile?"); 643 644 // Das Fenster wird auf nPos==0 eingeschoben 645 pD->bNewLine = sal_False; 646 pDock->bNewLine = sal_True; 647 } 648 649 nInsertPos = n; 650 break; 651 } 652 } 653 } 654 655 pDockArr->Insert(pDock, nInsertPos); 656 InsertWindow_Impl( pDock, rSize, nLine, nPos, bNewLine ); 657 SaveConfig_Impl(); 658 } 659 660 //------------------------------------------------------------------------- 661 662 void SfxSplitWindow::InsertWindow_Impl( SfxDock_Impl* pDock, 663 const Size& rSize, 664 sal_uInt16 nLine, sal_uInt16 nPos, sal_Bool bNewLine) 665 666 /* [Beschreibung] 667 668 F"ugt ein DockingWindow ein und veranla\st die Neuberechnung der Gr"o\se 669 des Splitwindows. 670 */ 671 672 { 673 SfxDockingWindow* pDockWin = pDock->pWin; 674 675 sal_uInt16 nItemBits = pDockWin->GetWinBits_Impl(); 676 677 long nWinSize, nSetSize; 678 if ( IsHorizontal() ) 679 { 680 nWinSize = rSize.Width(); 681 nSetSize = rSize.Height(); 682 } 683 else 684 { 685 nSetSize = rSize.Width(); 686 nWinSize = rSize.Height(); 687 } 688 689 pDock->nSize = nWinSize; 690 691 sal_Bool bUpdateMode = IsUpdateMode(); 692 if ( bUpdateMode ) 693 SetUpdateMode( sal_False ); 694 695 if ( bNewLine || nLine == GetItemCount( 0 ) ) 696 { 697 // Es soll nicht in eine vorhandene Zeile eingef"ugt werden, sondern 698 // eine neue erzeugt werden 699 700 sal_uInt16 nId = 1; 701 for ( sal_uInt16 n=0; n<GetItemCount(0); n++ ) 702 { 703 if ( GetItemId(n) >= nId ) 704 nId = GetItemId(n)+1; 705 } 706 707 // Eine neue nLine-te Zeile erzeugen 708 sal_uInt16 nBits = nItemBits; 709 if ( GetAlign() == WINDOWALIGN_TOP || GetAlign() == WINDOWALIGN_BOTTOM ) 710 nBits |= SWIB_COLSET; 711 InsertItem( nId, nSetSize, nLine, 0, nBits ); 712 } 713 714 // In Zeile mit Position nLine das Fenster einf"ugen 715 // ItemWindowSize auf "Prozentual" setzen, da SV dann das Umgr"o\sern 716 // so macht, wie man erwartet; "Pixel" macht eigentlich nur Sinn, wenn 717 // auch Items mit prozentualen oder relativen Gr"o\sen dabei sind. 718 nItemBits |= SWIB_PERCENTSIZE; 719 bLocked = sal_True; 720 sal_uInt16 nSet = GetItemId( nLine ); 721 InsertItem( pDockWin->GetType(), pDockWin, nWinSize, nPos, nSet, nItemBits ); 722 723 // Splitwindows werden im SFX einmal angelegt und beim Einf"ugen des ersten 724 // DockingWindows sichtbar gemacht. 725 if ( GetItemCount( 0 ) == 1 && GetItemCount( 1 ) == 1 ) 726 { 727 // Das Neuarrangieren am WorkWindow und ein Show() auf das SplitWindow 728 // wird vom SfxDockingwindow veranla\st (->SfxWorkWindow::ConfigChild_Impl) 729 if ( !bPinned && !IsFloatingMode() ) 730 { 731 bPinned = sal_True; 732 sal_Bool bFadeIn = ( pEmptyWin->nState & 2 ) != 0; 733 pEmptyWin->bFadeIn = sal_False; 734 SetPinned_Impl( sal_False ); 735 pEmptyWin->Actualize(); 736 DBG_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" ); 737 pWorkWin->RegisterChild_Impl( *GetSplitWindow(), eAlign, sal_True )->nVisible = CHILD_VISIBLE; 738 pWorkWin->ArrangeChilds_Impl(); 739 if ( bFadeIn ) 740 FadeIn(); 741 } 742 else 743 { 744 sal_Bool bFadeIn = ( pEmptyWin->nState & 2 ) != 0; 745 pEmptyWin->bFadeIn = sal_False; 746 pEmptyWin->Actualize(); 747 #ifdef DBG_UTIL 748 if ( !bPinned || !pEmptyWin->bFadeIn ) 749 { 750 DBG_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" ); 751 } 752 else 753 { 754 DBG_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering real Splitwindow" ); 755 } 756 #endif 757 pWorkWin->RegisterChild_Impl( *GetSplitWindow(), eAlign, sal_True )->nVisible = CHILD_VISIBLE; 758 pWorkWin->ArrangeChilds_Impl(); 759 if ( bFadeIn ) 760 FadeIn(); 761 } 762 763 pWorkWin->ShowChilds_Impl(); 764 } 765 766 if ( bUpdateMode ) 767 SetUpdateMode( sal_True ); 768 bLocked = sal_False; 769 } 770 771 //------------------------------------------------------------------------- 772 773 void SfxSplitWindow::RemoveWindow( SfxDockingWindow* pDockWin, sal_Bool bHide ) 774 775 /* [Beschreibung] 776 777 Entfernt ein DockingWindow. Wenn es das letzte war, wird das SplitWindow 778 gehidet. 779 */ 780 { 781 sal_uInt16 nSet = GetSet( pDockWin->GetType() ); 782 783 // Splitwindows werden im SFX einmal angelegt und nach dem Entfernen 784 // des letzten DockingWindows unsichtbar gemacht. 785 if ( GetItemCount( nSet ) == 1 && GetItemCount( 0 ) == 1 ) 786 { 787 // Das Neuarrangieren am WorkWindow wird vom SfxDockingwindow 788 // veranla\st! 789 Hide(); 790 pEmptyWin->aTimer.Stop(); 791 sal_uInt16 nRealState = pEmptyWin->nState; 792 FadeOut_Impl(); 793 pEmptyWin->Hide(); 794 #ifdef DBG_UTIL 795 if ( !bPinned || !pEmptyWin->bFadeIn ) 796 { 797 DBG_TRACE( "SfxSplitWindow::RemoveWindow - releasing empty Splitwindow" ); 798 } 799 else 800 { 801 DBG_TRACE( "SfxSplitWindow::RemoveWindow - releasing real Splitwindow" ); 802 } 803 #endif 804 pWorkWin->ReleaseChild_Impl( *GetSplitWindow() ); 805 pEmptyWin->nState = nRealState; 806 pWorkWin->ArrangeAutoHideWindows( this ); 807 } 808 809 SfxDock_Impl *pDock=0; 810 sal_uInt16 nCount = pDockArr->Count(); 811 for ( sal_uInt16 n=0; n<nCount; n++ ) 812 { 813 pDock = (*pDockArr)[n]; 814 if ( pDock->nType == pDockWin->GetType() ) 815 { 816 pDock->pWin = 0; 817 pDock->bHide = bHide; 818 break; 819 } 820 } 821 822 // Fenster removen, und wenn es das letzte der Zeile war, auch die Zeile 823 // ( Zeile = ItemSet ) 824 sal_Bool bUpdateMode = IsUpdateMode(); 825 if ( bUpdateMode ) 826 SetUpdateMode( sal_False ); 827 bLocked = sal_True; 828 829 RemoveItem( pDockWin->GetType() ); 830 831 if ( nSet && !GetItemCount( nSet ) ) 832 RemoveItem( nSet ); 833 834 if ( bUpdateMode ) 835 SetUpdateMode( sal_True ); 836 bLocked = sal_False; 837 }; 838 839 //------------------------------------------------------------------------- 840 841 sal_Bool SfxSplitWindow::GetWindowPos( const SfxDockingWindow* pWindow, 842 sal_uInt16& rLine, sal_uInt16& rPos ) const 843 /* [Beschreibung] 844 845 Liefert die Id des Itemsets und die des Items f"ur das "ubergebene 846 DockingWindow in der alten Zeilen/Spalten-Bezeichnung zur"uck. 847 */ 848 849 { 850 sal_uInt16 nSet = GetSet ( pWindow->GetType() ); 851 if ( nSet == SPLITWINDOW_ITEM_NOTFOUND ) 852 return sal_False; 853 854 rPos = GetItemPos( pWindow->GetType(), nSet ); 855 rLine = GetItemPos( nSet ); 856 return sal_True; 857 } 858 859 //------------------------------------------------------------------------- 860 861 sal_Bool SfxSplitWindow::GetWindowPos( const Point& rTestPos, 862 sal_uInt16& rLine, sal_uInt16& rPos ) const 863 /* [Beschreibung] 864 865 Liefert die Id des Itemsets und die des Items f"ur das DockingWindow 866 an der "ubergebenen Position in der alten Zeilen/Spalten-Bezeichnung 867 zur"uck. 868 */ 869 870 { 871 sal_uInt16 nId = GetItemId( rTestPos ); 872 if ( nId == 0 ) 873 return sal_False; 874 875 sal_uInt16 nSet = GetSet ( nId ); 876 rPos = GetItemPos( nId, nSet ); 877 rLine = GetItemPos( nSet ); 878 return sal_True; 879 } 880 881 //------------------------------------------------------------------------- 882 883 sal_uInt16 SfxSplitWindow::GetLineCount() const 884 885 /* [Beschreibung] 886 887 Liefert die Zeilenzahl = Zahl der Sub-Itemsets im Root-Set. 888 */ 889 { 890 return GetItemCount( 0 ); 891 } 892 893 //------------------------------------------------------------------------- 894 895 long SfxSplitWindow::GetLineSize( sal_uInt16 nLine ) const 896 897 /* [Beschreibung] 898 899 Liefert die "Zeilenh"ohe" des nLine-ten Itemsets. 900 */ 901 { 902 sal_uInt16 nId = GetItemId( nLine ); 903 return GetItemSize( nId ); 904 } 905 906 //------------------------------------------------------------------------- 907 908 sal_uInt16 SfxSplitWindow::GetWindowCount( sal_uInt16 nLine ) const 909 910 /* [Beschreibung] 911 912 Liefert die 913 */ 914 { 915 sal_uInt16 nId = GetItemId( nLine ); 916 return GetItemCount( nId ); 917 } 918 919 //------------------------------------------------------------------------- 920 921 sal_uInt16 SfxSplitWindow::GetWindowCount() const 922 923 /* [Beschreibung] 924 925 Liefert die Gesamtzahl aller Fenstert 926 */ 927 { 928 return GetItemCount( 0 ); 929 } 930 931 //------------------------------------------------------------------------- 932 933 void SfxSplitWindow::Command( const CommandEvent& rCEvt ) 934 { 935 SplitWindow::Command( rCEvt ); 936 } 937 938 //------------------------------------------------------------------------- 939 940 IMPL_LINK( SfxSplitWindow, TimerHdl, Timer*, pTimer) 941 { 942 if ( pTimer ) 943 pTimer->Stop(); 944 945 if ( CursorIsOverRect( sal_False ) || !pTimer ) 946 { 947 // Wenn der Mauszeiger innerhalb des Fensters liegt, SplitWindow anzeigen 948 // und Timer zum Schlie\sen aufsetzen 949 pEmptyWin->bAutoHide = sal_True; 950 if ( !IsVisible() ) 951 pEmptyWin->FadeIn(); 952 953 pEmptyWin->aLastPos = GetPointerPosPixel(); 954 pEmptyWin->aTimer.Start(); 955 } 956 else if ( pEmptyWin->bAutoHide ) 957 { 958 if ( GetPointerPosPixel() != pEmptyWin->aLastPos ) 959 { 960 // Die Maus wurd innerhalb der Timerlaugzeit bewegt, also erst einmal 961 // nichts tun 962 pEmptyWin->aLastPos = GetPointerPosPixel(); 963 pEmptyWin->aTimer.Start(); 964 return 0L; 965 } 966 967 // Speziell f"ur TF_AUTOSHOW_ON_MOUSEMOVE : 968 // Wenn das Fenster nicht sichtbar ist, gibt es nichts zu tun 969 // (Benutzer ist einfach mit der Maus "uber pEmptyWin gefahren) 970 if ( IsVisible() ) 971 { 972 pEmptyWin->bEndAutoHide = sal_False; 973 if ( !Application::IsInModalMode() && 974 !PopupMenu::IsInExecute() && 975 !pEmptyWin->bSplit && !HasChildPathFocus( sal_True ) ) 976 { 977 // W"ahrend ein modaler Dialog oder ein Popupmenu offen sind 978 // oder w"ahrend des Splittens auf keinen Fall zumachen; auch 979 // solange eines der Children den Focus hat, bleibt das 980 // das Fenster offen 981 pEmptyWin->bEndAutoHide = sal_True; 982 } 983 984 if ( pEmptyWin->bEndAutoHide ) 985 { 986 // Von mir aus kann Schlu\s sein mit AutoShow 987 // Aber vielleicht will noch ein anderes SfxSplitWindow offen bleiben, 988 // dann bleiben auch alle anderen offen 989 if ( !pWorkWin->IsAutoHideMode( this ) ) 990 { 991 FadeOut_Impl(); 992 pWorkWin->ArrangeAutoHideWindows( this ); 993 } 994 else 995 { 996 pEmptyWin->aLastPos = GetPointerPosPixel(); 997 pEmptyWin->aTimer.Start(); 998 } 999 } 1000 else 1001 { 1002 pEmptyWin->aLastPos = GetPointerPosPixel(); 1003 pEmptyWin->aTimer.Start(); 1004 } 1005 } 1006 } 1007 1008 return 0L; 1009 } 1010 1011 //------------------------------------------------------------------------- 1012 1013 sal_Bool SfxSplitWindow::CursorIsOverRect( sal_Bool bForceAdding ) const 1014 { 1015 sal_Bool bVisible = IsVisible(); 1016 1017 // Auch das kollabierte SplitWindow ber"ucksichtigen 1018 Point aPos = pEmptyWin->GetParent()->OutputToScreenPixel( pEmptyWin->GetPosPixel() ); 1019 Size aSize = pEmptyWin->GetSizePixel(); 1020 1021 if ( bForceAdding ) 1022 { 1023 // Um +/- ein paar Pixel erweitern, sonst ist es zu nerv"os 1024 aPos.X() -= nPixel; 1025 aPos.Y() -= nPixel; 1026 aSize.Width() += 2 * nPixel; 1027 aSize.Height() += 2 * nPixel; 1028 } 1029 1030 Rectangle aRect( aPos, aSize ); 1031 1032 if ( bVisible ) 1033 { 1034 Point aVisPos = GetPosPixel(); 1035 Size aVisSize = GetSizePixel(); 1036 1037 // Um +/- ein paar Pixel erweitern, sonst ist es zu nerv"os 1038 aVisPos.X() -= nPixel; 1039 aVisPos.Y() -= nPixel; 1040 aVisSize.Width() += 2 * nPixel; 1041 aVisSize.Height() += 2 * nPixel; 1042 1043 Rectangle aVisRect( aVisPos, aVisSize ); 1044 aRect = aRect.GetUnion( aVisRect ); 1045 } 1046 1047 if ( aRect.IsInside( OutputToScreenPixel( ((Window*)this)->GetPointerPosPixel() ) ) ) 1048 return sal_True; 1049 return sal_False; 1050 } 1051 1052 //------------------------------------------------------------------------- 1053 1054 SplitWindow* SfxSplitWindow::GetSplitWindow() 1055 { 1056 if ( !bPinned || !pEmptyWin->bFadeIn ) 1057 return pEmptyWin; 1058 return this; 1059 } 1060 1061 //------------------------------------------------------------------------- 1062 sal_Bool SfxSplitWindow::IsFadeIn() const 1063 { 1064 return pEmptyWin->bFadeIn; 1065 } 1066 1067 sal_Bool SfxSplitWindow::IsAutoHide( sal_Bool bSelf ) const 1068 { 1069 return bSelf ? pEmptyWin->bAutoHide && !pEmptyWin->bEndAutoHide : pEmptyWin->bAutoHide; 1070 } 1071 1072 //------------------------------------------------------------------------- 1073 1074 void SfxSplitWindow::SetPinned_Impl( sal_Bool bOn ) 1075 { 1076 if ( bPinned == bOn ) 1077 return; 1078 1079 bPinned = bOn; 1080 if ( GetItemCount( 0 ) == 0 ) 1081 return; 1082 1083 if ( !bOn ) 1084 { 1085 pEmptyWin->nState |= 1; 1086 if ( pEmptyWin->bFadeIn ) 1087 { 1088 // Ersatzfenster anmelden 1089 DBG_TRACE( "SfxSplitWindow::SetPinned_Impl - releasing real Splitwindow" ); 1090 pWorkWin->ReleaseChild_Impl( *this ); 1091 Hide(); 1092 pEmptyWin->Actualize(); 1093 DBG_TRACE( "SfxSplitWindow::SetPinned_Impl - registering empty Splitwindow" ); 1094 pWorkWin->RegisterChild_Impl( *pEmptyWin, eAlign, sal_True )->nVisible = CHILD_VISIBLE; 1095 } 1096 1097 Point aPos( GetPosPixel() ); 1098 aPos = GetParent()->OutputToScreenPixel( aPos ); 1099 SetFloatingPos( aPos ); 1100 SetFloatingMode( sal_True ); 1101 GetFloatingWindow()->SetOutputSizePixel( GetOutputSizePixel() ); 1102 1103 if ( pEmptyWin->bFadeIn ) 1104 Show(); 1105 } 1106 else 1107 { 1108 pEmptyWin->nState &= ~1; 1109 SetOutputSizePixel( GetFloatingWindow()->GetOutputSizePixel() ); 1110 SetFloatingMode( sal_False ); 1111 1112 if ( pEmptyWin->bFadeIn ) 1113 { 1114 // Ersatzfenster abmelden 1115 DBG_TRACE( "SfxSplitWindow::SetPinned_Impl - releasing empty Splitwindow" ); 1116 pWorkWin->ReleaseChild_Impl( *pEmptyWin ); 1117 pEmptyWin->Hide(); 1118 DBG_TRACE( "SfxSplitWindow::SetPinned_Impl - registering real Splitwindow" ); 1119 pWorkWin->RegisterChild_Impl( *this, eAlign, sal_True )->nVisible = CHILD_VISIBLE; 1120 } 1121 } 1122 1123 SetAutoHideState( !bPinned ); 1124 pEmptyWin->SetAutoHideState( !bPinned ); 1125 } 1126 1127 //------------------------------------------------------------------------- 1128 1129 void SfxSplitWindow::SetFadeIn_Impl( sal_Bool bOn ) 1130 { 1131 if ( bOn == pEmptyWin->bFadeIn ) 1132 return; 1133 1134 if ( GetItemCount( 0 ) == 0 ) 1135 return; 1136 1137 pEmptyWin->bFadeIn = bOn; 1138 if ( bOn ) 1139 { 1140 pEmptyWin->nState |= 2; 1141 if ( IsFloatingMode() ) 1142 { 1143 // FloatingWindow ist nicht sichtbar, also anzeigen 1144 pWorkWin->ArrangeAutoHideWindows( this ); 1145 Show(); 1146 } 1147 else 1148 { 1149 DBG_TRACE( "SfxSplitWindow::SetFadeIn_Impl - releasing empty Splitwindow" ); 1150 pWorkWin->ReleaseChild_Impl( *pEmptyWin ); 1151 pEmptyWin->Hide(); 1152 DBG_TRACE( "SfxSplitWindow::SetFadeIn_Impl - registering real Splitwindow" ); 1153 pWorkWin->RegisterChild_Impl( *this, eAlign, sal_True )->nVisible = CHILD_VISIBLE; 1154 pWorkWin->ArrangeChilds_Impl(); 1155 pWorkWin->ShowChilds_Impl(); 1156 } 1157 } 1158 else 1159 { 1160 pEmptyWin->bAutoHide = sal_False; 1161 pEmptyWin->nState &= ~2; 1162 if ( !IsFloatingMode() ) 1163 { 1164 // Das Fenster "schwebt" nicht, soll aber ausgeblendet werden, 1165 DBG_TRACE( "SfxSplitWindow::SetFadeIn_Impl - releasing real Splitwindow" ); 1166 pWorkWin->ReleaseChild_Impl( *this ); 1167 Hide(); 1168 pEmptyWin->Actualize(); 1169 DBG_TRACE( "SfxSplitWindow::SetFadeIn_Impl - registering empty Splitwindow" ); 1170 pWorkWin->RegisterChild_Impl( *pEmptyWin, eAlign, sal_True )->nVisible = CHILD_VISIBLE; 1171 pWorkWin->ArrangeChilds_Impl(); 1172 pWorkWin->ShowChilds_Impl(); 1173 pWorkWin->ArrangeAutoHideWindows( this ); 1174 } 1175 else 1176 { 1177 Hide(); 1178 pWorkWin->ArrangeAutoHideWindows( this ); 1179 } 1180 } 1181 } 1182 1183 void SfxSplitWindow::AutoHide() 1184 { 1185 // Wenn dieser Handler am "echten" SplitWindow aufgerufen wird, ist es 1186 // entweder angedockt und soll "schwebend" angezeigt werden oder umgekehrt 1187 if ( !bPinned ) 1188 { 1189 // Es "schwebt", also wieder andocken 1190 SetPinned_Impl( sal_True ); 1191 pWorkWin->ArrangeChilds_Impl(); 1192 } 1193 else 1194 { 1195 // In den "Schwebezustand" bringen 1196 SetPinned_Impl( sal_False ); 1197 pWorkWin->ArrangeChilds_Impl(); 1198 pWorkWin->ArrangeAutoHideWindows( this ); 1199 } 1200 1201 pWorkWin->ShowChilds_Impl(); 1202 SaveConfig_Impl(); 1203 } 1204 1205 void SfxSplitWindow::FadeOut_Impl() 1206 { 1207 if ( pEmptyWin->aTimer.IsActive() ) 1208 { 1209 pEmptyWin->bAutoHide = sal_False; 1210 pEmptyWin->aTimer.Stop(); 1211 } 1212 1213 SetFadeIn_Impl( sal_False ); 1214 Show_Impl(); 1215 } 1216 1217 void SfxSplitWindow::FadeOut() 1218 { 1219 FadeOut_Impl(); 1220 SaveConfig_Impl(); 1221 } 1222 1223 void SfxSplitWindow::FadeIn() 1224 { 1225 SetFadeIn_Impl( sal_True ); 1226 Show_Impl(); 1227 } 1228 1229 void SfxSplitWindow::Show_Impl() 1230 { 1231 sal_uInt16 nCount = pDockArr->Count(); 1232 for ( sal_uInt16 n=0; n<nCount; n++ ) 1233 { 1234 SfxDock_Impl *pDock = (*pDockArr)[n]; 1235 if ( pDock->pWin ) 1236 pDock->pWin->FadeIn( pEmptyWin->bFadeIn ); 1237 } 1238 } 1239 /* 1240 void SfxSplitWindow::Pin_Impl( sal_Bool bPin ) 1241 { 1242 if ( bPinned != bPin ) 1243 AutoHide(); 1244 } 1245 */ 1246 sal_Bool SfxSplitWindow::ActivateNextChild_Impl( sal_Bool bForward ) 1247 { 1248 // Wenn kein pActive, auf erstes bzw. letztes Fenster gehen ( bei !bForward wird erst in der loop dekrementiert ) 1249 sal_uInt16 nCount = pDockArr->Count(); 1250 sal_uInt16 n = bForward ? 0 : nCount; 1251 1252 // Wenn Focus innerhalb, dann ein Fenster vor oder zur"uck, wenn m"oglich 1253 if ( pActive ) 1254 { 1255 // Aktives Fenster ermitteln 1256 for ( n=0; n<nCount; n++ ) 1257 { 1258 SfxDock_Impl *pD = (*pDockArr)[n]; 1259 if ( pD->pWin && pD->pWin->HasChildPathFocus() ) 1260 break; 1261 } 1262 1263 if ( bForward ) 1264 // ein Fenster weiter ( wenn dann n>nCount, wird die Schleife unten gar nicht durchlaufen ) 1265 n++; 1266 } 1267 1268 if ( bForward ) 1269 { 1270 // N"achstes Fenster suchen 1271 for ( sal_uInt16 nNext=n; nNext<nCount; nNext++ ) 1272 { 1273 SfxDock_Impl *pD = (*pDockArr)[nNext]; 1274 if ( pD->pWin ) 1275 { 1276 pD->pWin->GrabFocus(); 1277 return sal_True; 1278 } 1279 } 1280 } 1281 else 1282 { 1283 // Vorheriges Fenster suchen 1284 for ( sal_uInt16 nNext=n; nNext--; ) 1285 { 1286 SfxDock_Impl *pD = (*pDockArr)[nNext]; 1287 if ( pD->pWin ) 1288 { 1289 pD->pWin->GrabFocus(); 1290 return sal_True; 1291 } 1292 } 1293 } 1294 1295 return sal_False; 1296 } 1297 1298 void SfxSplitWindow::SetActiveWindow_Impl( SfxDockingWindow* pWin ) 1299 { 1300 pActive = pWin; 1301 pWorkWin->SetActiveChild_Impl( this ); 1302 } 1303 1304 1305