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