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