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