bump product version to 5.0.4.1
[LibreOffice.git] / sfx2 / source / dialog / splitwin.cxx
blobfb56c2891897ecde396e295f23ce5fcce0c96f4f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #ifdef SOLARIS
21 #include <ctime>
22 #endif
24 #include <string>
26 #include <vcl/wrkwin.hxx>
27 #include <unotools/viewoptions.hxx>
29 #include <vcl/timer.hxx>
31 #include "splitwin.hxx"
32 #include "workwin.hxx"
33 #include <sfx2/dockwin.hxx>
34 #include <sfx2/app.hxx>
35 #include "dialog.hrc"
36 #include <sfx2/sfxresid.hxx>
37 #include <sfx2/mnumgr.hxx>
38 #include "virtmenu.hxx"
39 #include <sfx2/msgpool.hxx>
40 #include <sfx2/viewfrm.hxx>
42 #include <vector>
43 #include <utility>
45 using namespace ::com::sun::star::uno;
47 #define VERSION 1
48 #define nPixel 30L
49 #define USERITEM_NAME OUString("UserItem")
51 namespace {
52 // helper class to deactivate UpdateMode, if needed, for the life time of an instance
53 class DeactivateUpdateMode
55 public:
56 explicit DeactivateUpdateMode( SfxSplitWindow& rSplitWindow )
57 : mrSplitWindow( rSplitWindow )
58 , mbUpdateMode( rSplitWindow.IsUpdateMode() )
60 if ( mbUpdateMode )
62 mrSplitWindow.SetUpdateMode( false );
66 ~DeactivateUpdateMode()
68 if ( mbUpdateMode )
70 mrSplitWindow.SetUpdateMode( true );
74 private:
75 SfxSplitWindow& mrSplitWindow;
76 const bool mbUpdateMode;
80 class SfxEmptySplitWin_Impl : public SplitWindow
82 /* [Description]
84 The SfxEmptySplitWin_Impldow is an empty SplitWindow, that replaces the
85 SfxSplitWindow AutoHide mode. It only serves as a placeholder to receive
86 mouse moves and if possible blend in the true SplitWindow display.
88 friend class SfxSplitWindow;
90 VclPtr<SfxSplitWindow> pOwner;
91 bool bFadeIn;
92 bool bAutoHide;
93 bool bSplit;
94 bool bEndAutoHide;
95 Timer aTimer;
96 Point aLastPos;
97 sal_uInt16 nState;
99 public:
100 SfxEmptySplitWin_Impl( SfxSplitWindow *pParent )
101 : SplitWindow( pParent->GetParent(), WinBits( WB_BORDER | WB_3DLOOK ) )
102 , pOwner( pParent )
103 , bFadeIn( false )
104 , bAutoHide( false )
105 , bSplit( false )
106 , bEndAutoHide( false )
107 , nState( 1 )
109 aTimer.SetTimeoutHdl(
110 LINK(pOwner, SfxSplitWindow, TimerHdl ) );
111 aTimer.SetTimeout( 200 );
112 SetAlign( pOwner->GetAlign() );
113 Actualize();
114 ShowAutoHideButton( pOwner->IsAutoHideButtonVisible() );
115 ShowFadeInHideButton( true );
118 virtual ~SfxEmptySplitWin_Impl()
119 { disposeOnce(); }
120 virtual void dispose() SAL_OVERRIDE
122 aTimer.Stop();
123 pOwner.clear();
124 SplitWindow::dispose();
127 virtual void MouseMove( const MouseEvent& ) SAL_OVERRIDE;
128 virtual void AutoHide() SAL_OVERRIDE;
129 virtual void FadeIn() SAL_OVERRIDE;
130 void Actualize();
133 void SfxEmptySplitWin_Impl::Actualize()
135 Size aSize( pOwner->GetSizePixel() );
136 switch ( pOwner->GetAlign() )
138 case WINDOWALIGN_LEFT:
139 case WINDOWALIGN_RIGHT:
140 aSize.Width() = GetFadeInSize();
141 break;
142 case WINDOWALIGN_TOP:
143 case WINDOWALIGN_BOTTOM:
144 aSize.Height() = GetFadeInSize();
145 break;
148 SetSizePixel( aSize );
151 void SfxEmptySplitWin_Impl::AutoHide()
153 pOwner->SetPinned_Impl( !pOwner->bPinned );
154 pOwner->SaveConfig_Impl();
155 bAutoHide = true;
156 FadeIn();
159 void SfxEmptySplitWin_Impl::FadeIn()
161 if (!bAutoHide )
162 bAutoHide = IsFadeNoButtonMode();
163 pOwner->SetFadeIn_Impl( true );
164 if ( bAutoHide )
166 // Set Timer to close; the caller has to ensure themselves that the
167 // Window is not closed instantly (eg by setting the focus or a modal
168 // mode.
169 aLastPos = GetPointerPosPixel();
170 aTimer.Start();
172 else
173 pOwner->SaveConfig_Impl();
178 void SfxSplitWindow::MouseButtonDown( const MouseEvent& rMEvt )
180 if ( rMEvt.GetClicks() != 2 )
181 SplitWindow::MouseButtonDown( rMEvt );
184 void SfxEmptySplitWin_Impl::MouseMove( const MouseEvent& rMEvt )
186 SplitWindow::MouseMove( rMEvt );
191 SfxSplitWindow::SfxSplitWindow( vcl::Window* pParent, SfxChildAlignment eAl,
192 SfxWorkWindow *pW, bool bWithButtons, WinBits nBits )
194 /* [Description]
196 A SfxSplitWindow brings the recursive structure of the SV-SplitWindows to
197 the outside by simulating a table-like structure with rows and columns
198 (maximum recursion depth 2). Furthermore, it ensures the persistence of
199 the arrangement of the SfxDockingWindows.
202 : SplitWindow ( pParent, nBits | WB_HIDE ),
203 eAlign(eAl),
204 pWorkWin(pW),
205 pDockArr( new SfxDockArr_Impl ),
206 bLocked(false),
207 bPinned(true),
208 pEmptyWin(NULL),
209 pActive(NULL)
211 if ( bWithButtons )
213 ShowAutoHideButton( false ); // no autohide button (pin) anymore
214 ShowFadeOutButton( true );
217 // Set SV-Alignment
218 WindowAlign eTbxAlign;
219 switch ( eAlign )
221 case SfxChildAlignment::LEFT:
222 eTbxAlign = WINDOWALIGN_LEFT;
223 break;
224 case SfxChildAlignment::RIGHT:
225 eTbxAlign = WINDOWALIGN_RIGHT;
226 break;
227 case SfxChildAlignment::TOP:
228 eTbxAlign = WINDOWALIGN_TOP;
229 break;
230 case SfxChildAlignment::BOTTOM:
231 eTbxAlign = WINDOWALIGN_BOTTOM;
232 bPinned = true;
233 break;
234 default:
235 eTbxAlign = WINDOWALIGN_TOP; // some sort of default...
236 break; // -Wall lots not handled..
239 SetAlign (eTbxAlign);
240 pEmptyWin = VclPtr<SfxEmptySplitWin_Impl>::Create( this );
241 if ( bPinned )
243 pEmptyWin->bFadeIn = true;
244 pEmptyWin->nState = 2;
247 if ( bWithButtons )
249 // Read Configuration
250 OUString aWindowId("SplitWindow");
251 aWindowId += OUString::number( (sal_Int32) eTbxAlign );
252 SvtViewOptions aWinOpt( E_WINDOW, aWindowId );
253 OUString aWinData;
254 Any aUserItem = aWinOpt.GetUserItem( USERITEM_NAME );
255 OUString aTemp;
256 if ( aUserItem >>= aTemp )
257 aWinData = aTemp;
258 if ( aWinData.startsWith("V") )
260 pEmptyWin->nState = (sal_uInt16) aWinData.getToken( 1, ',' ).toInt32();
261 if ( pEmptyWin->nState & 2 )
262 pEmptyWin->bFadeIn = true;
263 bPinned = true; // always assume pinned - floating mode not used anymore
265 sal_uInt16 i=2;
266 sal_uInt16 nCount = (sal_uInt16) aWinData.getToken(i++, ',').toInt32();
267 for ( sal_uInt16 n=0; n<nCount; n++ )
269 SfxDock_Impl *pDock = new SfxDock_Impl;
270 pDock->pWin = 0;
271 pDock->bNewLine = false;
272 pDock->bHide = true;
273 pDock->nType = (sal_uInt16) aWinData.getToken(i++, ',').toInt32();
274 if ( !pDock->nType )
276 // could mean NewLine
277 pDock->nType = (sal_uInt16) aWinData.getToken(i++, ',').toInt32();
278 if ( !pDock->nType )
280 // Read error
281 delete pDock;
282 break;
284 else
285 pDock->bNewLine = true;
288 pDockArr->insert(pDockArr->begin() + n, pDock);
292 else
294 bPinned = true;
295 pEmptyWin->bFadeIn = true;
296 pEmptyWin->nState = 2;
299 SetAutoHideState( !bPinned );
300 pEmptyWin->SetAutoHideState( !bPinned );
305 SfxSplitWindow::~SfxSplitWindow()
307 disposeOnce();
310 void SfxSplitWindow::dispose()
312 if ( !pWorkWin->GetParent_Impl() )
313 SaveConfig_Impl();
315 if ( pEmptyWin )
317 // Set pOwner to NULL, otherwise try to delete pEmptyWin once more. The
318 // window that is just being docked is always deleted from the outside.
319 pEmptyWin->pOwner = NULL;
321 pEmptyWin.disposeAndClear();
323 delete pDockArr;
324 pActive.clear();
325 SplitWindow::dispose();
328 void SfxSplitWindow::SaveConfig_Impl()
330 // Save configuration
331 OUStringBuffer aWinData;
332 aWinData.append('V');
333 aWinData.append(static_cast<sal_Int32>(VERSION));
334 aWinData.append(',');
335 aWinData.append(static_cast<sal_Int32>(pEmptyWin->nState));
336 aWinData.append(',');
338 sal_uInt16 nCount = 0;
339 sal_uInt16 n;
340 for ( n=0; n<pDockArr->size(); n++ )
342 const SfxDock_Impl& rDock = (*pDockArr)[n];
343 if ( rDock.bHide || rDock.pWin )
344 nCount++;
347 aWinData.append(static_cast<sal_Int32>(nCount));
349 for ( n=0; n<pDockArr->size(); n++ )
351 const SfxDock_Impl& rDock = (*pDockArr)[n];
352 if ( !rDock.bHide && !rDock.pWin )
353 continue;
354 if ( rDock.bNewLine )
355 aWinData.append(",0");
356 aWinData.append(',');
357 aWinData.append(static_cast<sal_Int32>(rDock.nType));
360 OUString aWindowId("SplitWindow");
361 aWindowId += OUString::number( (sal_Int32) GetAlign() );
362 SvtViewOptions aWinOpt( E_WINDOW, aWindowId );
363 aWinOpt.SetUserItem( USERITEM_NAME, makeAny( aWinData.makeStringAndClear() ) );
368 void SfxSplitWindow::StartSplit()
370 long nSize = 0;
371 Size aSize = GetSizePixel();
373 if ( pEmptyWin )
375 pEmptyWin->bFadeIn = true;
376 pEmptyWin->bSplit = true;
379 Rectangle aRect = pWorkWin->GetFreeArea( !bPinned );
380 switch ( GetAlign() )
382 case WINDOWALIGN_LEFT:
383 case WINDOWALIGN_RIGHT:
384 nSize = aSize.Width() + aRect.GetWidth();
385 break;
386 case WINDOWALIGN_TOP:
387 case WINDOWALIGN_BOTTOM:
388 nSize = aSize.Height() + aRect.GetHeight();
389 break;
392 SetMaxSizePixel( nSize );
397 void SfxSplitWindow::SplitResize()
399 if ( bPinned )
401 pWorkWin->ArrangeChildren_Impl();
402 pWorkWin->ShowChildren_Impl();
404 else
405 pWorkWin->ArrangeAutoHideWindows( this );
410 void SfxSplitWindow::Split()
412 if ( pEmptyWin )
413 pEmptyWin->bSplit = false;
415 SplitWindow::Split();
417 std::vector< std::pair< sal_uInt16, long > > aNewOrgSizes;
419 sal_uInt16 nCount = pDockArr->size();
420 for ( sal_uInt16 n=0; n<nCount; n++ )
422 const SfxDock_Impl& rD = (*pDockArr)[n];
423 if ( rD.pWin )
425 const sal_uInt16 nId = rD.nType;
426 const long nSize = GetItemSize( nId, SWIB_FIXED );
427 const long nSetSize = GetItemSize( GetSet( nId ) );
428 Size aSize;
430 if ( IsHorizontal() )
432 aSize.Width() = nSize;
433 aSize.Height() = nSetSize;
435 else
437 aSize.Width() = nSetSize;
438 aSize.Height() = nSize;
441 rD.pWin->SetItemSize_Impl( aSize );
443 aNewOrgSizes.push_back( std::pair< sal_uInt16, long >( nId, nSize ) );
447 // workaround insuffiency of <SplitWindow> regarding dock layouting:
448 // apply FIXED item size as 'original' item size to improve layouting of undock-dock-cycle of a window
450 DeactivateUpdateMode aDeactivateUpdateMode( *this );
451 for ( sal_uInt16 i = 0; i < aNewOrgSizes.size(); ++i )
453 SetItemSize( aNewOrgSizes[i].first, aNewOrgSizes[i].second );
457 SaveConfig_Impl();
462 void SfxSplitWindow::InsertWindow( SfxDockingWindow* pDockWin, const Size& rSize)
465 To insert SfxDockingWindows just pass no position. The SfxSplitWindow
466 searches the last marked one to the passed SfxDockingWindow or appends a
467 new one at the end.
470 short nLine = -1; // so that the first window cab set nline to 0
471 sal_uInt16 nL;
472 sal_uInt16 nPos = 0;
473 bool bNewLine = true;
474 bool bSaveConfig = false;
475 SfxDock_Impl *pFoundDock=0;
476 sal_uInt16 nCount = pDockArr->size();
477 for ( sal_uInt16 n=0; n<nCount; n++ )
479 SfxDock_Impl& rDock = (*pDockArr)[n];
480 if ( rDock.bNewLine )
482 // The window opens a new line
483 if ( pFoundDock )
484 // But after the just inserted window
485 break;
487 // New line
488 nPos = 0;
489 bNewLine = true;
492 if ( rDock.pWin )
494 // Does there exist a window now at this position
495 if ( bNewLine && !pFoundDock )
497 // Not known until now in which real line it is located
498 GetWindowPos( rDock.pWin, nL, nPos );
499 nLine = (short) nL;
502 if ( !pFoundDock )
504 // The window is located before the inserted one
505 nPos++;
508 // Line is opened
509 bNewLine = false;
510 if ( pFoundDock )
511 break;
514 if ( rDock.nType == pDockWin->GetType() )
516 DBG_ASSERT( !pFoundDock && !rDock.pWin, "Window already exists!");
517 pFoundDock = &rDock;
518 if ( !bNewLine )
519 break;
520 else
522 // A new line has been created but no window was found there;
523 // continue searching for a window in this line in-order to set
524 // bNewLine correctly. While doing so nline or nPos are not
525 // to be changed!
526 nLine++;
531 if ( !pFoundDock )
533 // Not found, insert at end
534 pFoundDock = new SfxDock_Impl;
535 pFoundDock->bHide = true;
536 pDockArr->push_back( pFoundDock );
537 pFoundDock->nType = pDockWin->GetType();
538 nLine++;
539 nPos = 0;
540 bNewLine = true;
541 pFoundDock->bNewLine = bNewLine;
542 bSaveConfig = true;
545 pFoundDock->pWin = pDockWin;
546 pFoundDock->bHide = false;
547 InsertWindow_Impl( pFoundDock, rSize, nLine, nPos, bNewLine );
548 if ( bSaveConfig )
549 SaveConfig_Impl();
554 void SfxSplitWindow::ReleaseWindow_Impl(SfxDockingWindow *pDockWin, bool bSave)
556 // The docking window is no longer stored in the internal data.
557 sal_uInt16 nCount = pDockArr->size();
558 for ( sal_uInt16 n=0; n<nCount; n++ )
560 const SfxDock_Impl& rDock = (*pDockArr)[n];
561 if ( rDock.nType == pDockWin->GetType() )
563 if ( rDock.bNewLine && n<nCount-1 )
564 (*pDockArr)[n+1].bNewLine = true;
566 // Window has a position, this we forget
567 pDockArr->erase(pDockArr->begin() + n);
568 break;
572 if ( bSave )
573 SaveConfig_Impl();
578 void SfxSplitWindow::MoveWindow( SfxDockingWindow* pDockWin, const Size& rSize,
579 sal_uInt16 nLine, sal_uInt16 nPos, bool bNewLine)
581 /* [Description]
583 The docking window is moved within the SplitWindows.
587 sal_uInt16 nL, nP;
588 GetWindowPos( pDockWin, nL, nP );
590 if ( nLine > nL && GetItemCount( GetItemId( nL, 0 ) ) == 1 )
592 // If the last window is removed from its line, then everything slips
593 // one line to the front!
594 nLine--;
596 RemoveWindow( pDockWin );
597 InsertWindow( pDockWin, rSize, nLine, nPos, bNewLine );
602 void SfxSplitWindow::InsertWindow( SfxDockingWindow* pDockWin, const Size& rSize,
603 sal_uInt16 nLine, sal_uInt16 nPos, bool bNewLine)
605 /* [Description]
607 The DockingWindow that is pushed on this SplitWindow and shall hold the
608 given position and size.
611 ReleaseWindow_Impl( pDockWin, false );
612 SfxDock_Impl *pDock = new SfxDock_Impl;
613 pDock->bHide = false;
614 pDock->nType = pDockWin->GetType();
615 pDock->bNewLine = bNewLine;
616 pDock->pWin = pDockWin;
618 DBG_ASSERT( nPos==0 || !bNewLine, "Wrong Paramenter!");
619 if ( bNewLine )
620 nPos = 0;
622 // The window must be inserted before the first window so that it has the
623 // same or a greater position than pDockWin.
624 sal_uInt16 nCount = pDockArr->size();
625 sal_uInt16 nLastWindowIdx(0);
627 // If no window is found, a first window is inserted
628 sal_uInt16 nInsertPos = 0;
629 for ( sal_uInt16 n=0; n<nCount; n++ )
631 SfxDock_Impl& rD = (*pDockArr)[n];
633 if (rD.pWin)
635 // A docked window has been found. If no suitable window behind the
636 // the desired insertion point s found, then insertion is done at
637 // the end.
638 nInsertPos = nCount;
639 nLastWindowIdx = n;
640 sal_uInt16 nL=0, nP=0;
641 GetWindowPos( rD.pWin, nL, nP );
643 if ( (nL == nLine && nP == nPos) || nL > nLine )
645 DBG_ASSERT( nL == nLine || bNewLine || nPos > 0, "Wrong Parameter!" );
646 if ( nL == nLine && nPos == 0 && !bNewLine )
648 DBG_ASSERT(rD.bNewLine, "No new line?");
650 // The posption is pushed to nPos==0
651 rD.bNewLine = false;
652 pDock->bNewLine = true;
655 nInsertPos = n != 0 ? nLastWindowIdx + 1 : 0; // ignore all non-windows after the last window
656 break;
660 if (nCount != 0 && nInsertPos == nCount && nLastWindowIdx != nCount - 1)
662 nInsertPos = nLastWindowIdx + 1; // ignore all non-windows after the last window
665 pDockArr->insert(pDockArr->begin() + nInsertPos, pDock);
666 InsertWindow_Impl( pDock, rSize, nLine, nPos, bNewLine );
667 SaveConfig_Impl();
672 void SfxSplitWindow::InsertWindow_Impl( SfxDock_Impl* pDock,
673 const Size& rSize,
674 sal_uInt16 nLine, sal_uInt16 nPos, bool bNewLine)
676 /* [Description]
678 Adds a DockingWindow, and causes the recalculation of the size of
679 the SplitWindows.
683 SfxDockingWindow* pDockWin = pDock->pWin;
685 sal_uInt16 nItemBits = pDockWin->GetWinBits_Impl();
687 long nWinSize, nSetSize;
688 if ( IsHorizontal() )
690 nWinSize = rSize.Width();
691 nSetSize = rSize.Height();
693 else
695 nSetSize = rSize.Width();
696 nWinSize = rSize.Height();
699 pDock->nSize = nWinSize;
701 DeactivateUpdateMode* pDeactivateUpdateMode = new DeactivateUpdateMode( *this );
703 if ( bNewLine || nLine == GetItemCount( 0 ) )
705 // An existing row should not be inserted, instead a new one
706 // will be created
708 sal_uInt16 nId = 1;
709 for ( sal_uInt16 n=0; n<GetItemCount(0); n++ )
711 if ( GetItemId(n) >= nId )
712 nId = GetItemId(n)+1;
715 // Create a new nLine:th line
716 sal_uInt16 nBits = nItemBits;
717 if ( GetAlign() == WINDOWALIGN_TOP || GetAlign() == WINDOWALIGN_BOTTOM )
718 nBits |= SWIB_COLSET;
719 InsertItem( nId, nSetSize, nLine, 0, nBits );
722 // Insert the window at line with the position nline. ItemWindowSize set to
723 // "percentage" share since the SV then does the re-sizing as expected,
724 // "pixel" actually only makes sense if also items with percentage or
725 // relative sizes are present.
726 nItemBits |= SWIB_PERCENTSIZE;
727 bLocked = true;
728 sal_uInt16 nSet = GetItemId( nLine );
729 InsertItem( pDockWin->GetType(), pDockWin, nWinSize, nPos, nSet, nItemBits );
731 // SplitWindows are once created in SFX and when inserting the first
732 // DockingWindows is made visible.
733 if ( GetItemCount( 0 ) == 1 && GetItemCount( 1 ) == 1 )
735 // The Rearranging in WorkWindow and a Show() on the SplitWindow is
736 // caues by SfxDockingwindow (->SfxWorkWindow::ConfigChild_Impl)
737 if ( !bPinned && !IsFloatingMode() )
739 bPinned = true;
740 bool bFadeIn = ( pEmptyWin->nState & 2 ) != 0;
741 pEmptyWin->bFadeIn = false;
742 SetPinned_Impl( false );
743 pEmptyWin->Actualize();
744 OSL_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" );
745 pWorkWin->RegisterChild_Impl( *GetSplitWindow(), eAlign, true )->nVisible = SfxChildVisibility::VISIBLE;
746 pWorkWin->ArrangeChildren_Impl();
747 if ( bFadeIn )
748 FadeIn();
750 else
752 bool bFadeIn = ( pEmptyWin->nState & 2 ) != 0;
753 pEmptyWin->bFadeIn = false;
754 pEmptyWin->Actualize();
755 #ifdef DBG_UTIL
756 if ( !bPinned || !pEmptyWin->bFadeIn )
758 OSL_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" );
760 else
762 OSL_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering real Splitwindow" );
764 #endif
765 pWorkWin->RegisterChild_Impl( *GetSplitWindow(), eAlign, true )->nVisible = SfxChildVisibility::VISIBLE;
766 pWorkWin->ArrangeChildren_Impl();
767 if ( bFadeIn )
768 FadeIn();
771 pWorkWin->ShowChildren_Impl();
774 delete pDeactivateUpdateMode;
775 bLocked = false;
777 // workaround insuffiency of <SplitWindow> regarding dock layouting:
778 // apply FIXED item size as 'original' item size to improve layouting of undock-dock-cycle of a window
780 std::vector< std::pair< sal_uInt16, long > > aNewOrgSizes;
781 // get FIXED item sizes
782 sal_uInt16 nCount = pDockArr->size();
783 for ( sal_uInt16 n=0; n<nCount; ++n )
785 const SfxDock_Impl& rD = (*pDockArr)[n];
786 if ( rD.pWin )
788 const sal_uInt16 nId = rD.nType;
789 const long nSize = GetItemSize( nId, SWIB_FIXED );
790 aNewOrgSizes.push_back( std::pair< sal_uInt16, long >( nId, nSize ) );
793 // apply new item sizes
794 DeactivateUpdateMode aDeactivateUpdateMode( *this );
795 for ( sal_uInt16 i = 0; i < aNewOrgSizes.size(); ++i )
797 SetItemSize( aNewOrgSizes[i].first, aNewOrgSizes[i].second );
804 void SfxSplitWindow::RemoveWindow( SfxDockingWindow* pDockWin, bool bHide )
806 /* [Description]
808 Removes a DockingWindow. If it was the last one, then the SplitWindow is
809 being hidden.
812 sal_uInt16 nSet = GetSet( pDockWin->GetType() );
814 // SplitWindows are once created in SFX and is made invisible after
815 // removing the last DockingWindows.
816 if ( GetItemCount( nSet ) == 1 && GetItemCount( 0 ) == 1 )
818 // The Rearranging in WorkWindow is caues by SfxDockingwindow
819 Hide();
820 pEmptyWin->aTimer.Stop();
821 sal_uInt16 nRealState = pEmptyWin->nState;
822 FadeOut_Impl();
823 pEmptyWin->Hide();
824 #ifdef DBG_UTIL
825 if ( !bPinned || !pEmptyWin->bFadeIn )
827 OSL_TRACE( "SfxSplitWindow::RemoveWindow - releasing empty Splitwindow" );
829 else
831 OSL_TRACE( "SfxSplitWindow::RemoveWindow - releasing real Splitwindow" );
833 #endif
834 pWorkWin->ReleaseChild_Impl( *GetSplitWindow() );
835 pEmptyWin->nState = nRealState;
836 pWorkWin->ArrangeAutoHideWindows( this );
839 sal_uInt16 nCount = pDockArr->size();
840 for ( sal_uInt16 n=0; n<nCount; n++ )
842 SfxDock_Impl& rDock = (*pDockArr)[n];
843 if ( rDock.nType == pDockWin->GetType() )
845 rDock.pWin = 0;
846 rDock.bHide = bHide;
847 break;
851 // Remove Windows, and if it was the last of the line, then also remove
852 // the line (line = itemset)
853 DeactivateUpdateMode* pDeactivateUpdateMode = new DeactivateUpdateMode( *this );
854 bLocked = true;
856 RemoveItem( pDockWin->GetType() );
858 if ( nSet && !GetItemCount( nSet ) )
859 RemoveItem( nSet );
861 delete pDeactivateUpdateMode;
862 bLocked = false;
867 bool SfxSplitWindow::GetWindowPos( const SfxDockingWindow* pWindow,
868 sal_uInt16& rLine, sal_uInt16& rPos ) const
869 /* [Description]
871 Returns the ID of the item sets and items for the DockingWindow in
872 the position passed on the old row / column-name.
876 sal_uInt16 nSet = GetSet ( pWindow->GetType() );
877 if ( nSet == SPLITWINDOW_ITEM_NOTFOUND )
878 return false;
880 rPos = GetItemPos( pWindow->GetType(), nSet );
881 rLine = GetItemPos( nSet );
882 return true;
887 bool SfxSplitWindow::GetWindowPos( const Point& rTestPos,
888 sal_uInt16& rLine, sal_uInt16& rPos ) const
889 /* [Description]
891 Returns the ID of the item sets and items for the DockingWindow in
892 the position passed on the old row / column-name.
896 sal_uInt16 nId = GetItemId( rTestPos );
897 if ( nId == 0 )
898 return false;
900 sal_uInt16 nSet = GetSet ( nId );
901 rPos = GetItemPos( nId, nSet );
902 rLine = GetItemPos( nSet );
903 return true;
908 sal_uInt16 SfxSplitWindow::GetLineCount() const
910 /* [Description]
912 Returns the number of rows = number of sub-itemsets in the root set.
915 return GetItemCount( 0 );
920 long SfxSplitWindow::GetLineSize( sal_uInt16 nLine ) const
922 /* [Description]
924 Returns the Row Height of nline itemset.
927 sal_uInt16 nId = GetItemId( nLine );
928 return GetItemSize( nId );
933 sal_uInt16 SfxSplitWindow::GetWindowCount( sal_uInt16 nLine ) const
935 /* [Description]
937 Returns the total number of windows
940 sal_uInt16 nId = GetItemId( nLine );
941 return GetItemCount( nId );
946 sal_uInt16 SfxSplitWindow::GetWindowCount() const
948 /* [Description]
950 Returns the total number of windows
953 return GetItemCount( 0 );
958 void SfxSplitWindow::Command( const CommandEvent& rCEvt )
960 SplitWindow::Command( rCEvt );
965 IMPL_LINK_TYPED( SfxSplitWindow, TimerHdl, Timer*, pTimer, void)
967 if ( pTimer )
968 pTimer->Stop();
970 if ( CursorIsOverRect( false ) || !pTimer )
972 // If the cursor is within the window, display the SplitWindow and set
973 // up the timer for close
974 pEmptyWin->bAutoHide = true;
975 if ( !IsVisible() )
976 pEmptyWin->FadeIn();
978 pEmptyWin->aLastPos = GetPointerPosPixel();
979 pEmptyWin->aTimer.Start();
981 else if ( pEmptyWin->bAutoHide )
983 if ( GetPointerPosPixel() != pEmptyWin->aLastPos )
985 // The mouse has moved within the running time of the timer, thus
986 // do nothing
987 pEmptyWin->aLastPos = GetPointerPosPixel();
988 pEmptyWin->aTimer.Start();
989 return;
992 // Especially for TF_AUTOSHOW_ON_MOUSEMOVE :
993 // If the window is not visible, there is nothing to do
994 // (user has simply moved the mouse over pEmptyWin)
995 if ( IsVisible() )
997 pEmptyWin->bEndAutoHide = false;
998 if ( !Application::IsInModalMode() &&
999 !PopupMenu::IsInExecute() &&
1000 !pEmptyWin->bSplit && !HasChildPathFocus( true ) )
1002 // While a modal dialog or a popup menu is open or while the
1003 // Splitting is done, in any case, do not close. Even as long
1004 // as one of the Children has the focus, the window remains
1005 // open.
1006 pEmptyWin->bEndAutoHide = true;
1009 if ( pEmptyWin->bEndAutoHide )
1011 // As far as I am concered this can be the end of AutoShow
1012 // But maybe some other SfxSplitWindow will remain open,
1013 // then all others remain open too.
1014 if ( !pWorkWin->IsAutoHideMode( this ) )
1016 FadeOut_Impl();
1017 pWorkWin->ArrangeAutoHideWindows( this );
1019 else
1021 pEmptyWin->aLastPos = GetPointerPosPixel();
1022 pEmptyWin->aTimer.Start();
1025 else
1027 pEmptyWin->aLastPos = GetPointerPosPixel();
1028 pEmptyWin->aTimer.Start();
1036 bool SfxSplitWindow::CursorIsOverRect( bool bForceAdding ) const
1038 bool bVisible = IsVisible();
1040 // Also, take the collapsed SplitWindow into account
1041 Point aPos = pEmptyWin->GetParent()->OutputToScreenPixel( pEmptyWin->GetPosPixel() );
1042 Size aSize = pEmptyWin->GetSizePixel();
1044 if ( bForceAdding )
1046 // Extend with +/- a few pixels, otherwise it is too nervous
1047 aPos.X() -= nPixel;
1048 aPos.Y() -= nPixel;
1049 aSize.Width() += 2 * nPixel;
1050 aSize.Height() += 2 * nPixel;
1053 Rectangle aRect( aPos, aSize );
1055 if ( bVisible )
1057 Point aVisPos = GetPosPixel();
1058 Size aVisSize = GetSizePixel();
1060 // Extend with +/- a few pixels, otherwise it is too nervous
1061 aVisPos.X() -= nPixel;
1062 aVisPos.Y() -= nPixel;
1063 aVisSize.Width() += 2 * nPixel;
1064 aVisSize.Height() += 2 * nPixel;
1066 Rectangle aVisRect( aVisPos, aVisSize );
1067 aRect = aRect.GetUnion( aVisRect );
1070 if ( aRect.IsInside( OutputToScreenPixel( ((vcl::Window*)this)->GetPointerPosPixel() ) ) )
1071 return true;
1072 return false;
1077 SplitWindow* SfxSplitWindow::GetSplitWindow()
1079 if ( !bPinned || !pEmptyWin->bFadeIn )
1080 return pEmptyWin;
1081 return this;
1085 bool SfxSplitWindow::IsFadeIn() const
1087 return pEmptyWin->bFadeIn;
1090 bool SfxSplitWindow::IsAutoHide( bool bSelf ) const
1092 return bSelf ? pEmptyWin->bAutoHide && !pEmptyWin->bEndAutoHide : pEmptyWin->bAutoHide;
1097 void SfxSplitWindow::SetPinned_Impl( bool bOn )
1099 if ( bPinned == bOn )
1100 return;
1102 bPinned = bOn;
1103 if ( GetItemCount( 0 ) == 0 )
1104 return;
1106 if ( !bOn )
1108 pEmptyWin->nState |= 1;
1109 if ( pEmptyWin->bFadeIn )
1111 // Unregister replacement windows
1112 OSL_TRACE( "SfxSplitWindow::SetPinned_Impl - releasing real Splitwindow" );
1113 pWorkWin->ReleaseChild_Impl( *this );
1114 Hide();
1115 pEmptyWin->Actualize();
1116 OSL_TRACE( "SfxSplitWindow::SetPinned_Impl - registering empty Splitwindow" );
1117 pWorkWin->RegisterChild_Impl( *pEmptyWin, eAlign, true )->nVisible = SfxChildVisibility::VISIBLE;
1120 Point aPos( GetPosPixel() );
1121 aPos = GetParent()->OutputToScreenPixel( aPos );
1122 SetFloatingPos( aPos );
1123 SetFloatingMode( true );
1124 GetFloatingWindow()->SetOutputSizePixel( GetOutputSizePixel() );
1126 if ( pEmptyWin->bFadeIn )
1127 Show();
1129 else
1131 pEmptyWin->nState &= ~1;
1132 SetOutputSizePixel( GetFloatingWindow()->GetOutputSizePixel() );
1133 SetFloatingMode( false );
1135 if ( pEmptyWin->bFadeIn )
1137 // Unregister replacement windows
1138 OSL_TRACE( "SfxSplitWindow::SetPinned_Impl - releasing empty Splitwindow" );
1139 pWorkWin->ReleaseChild_Impl( *pEmptyWin );
1140 pEmptyWin->Hide();
1141 OSL_TRACE( "SfxSplitWindow::SetPinned_Impl - registering real Splitwindow" );
1142 pWorkWin->RegisterChild_Impl( *this, eAlign, true )->nVisible = SfxChildVisibility::VISIBLE;
1146 SetAutoHideState( !bPinned );
1147 pEmptyWin->SetAutoHideState( !bPinned );
1152 void SfxSplitWindow::SetFadeIn_Impl( bool bOn )
1154 if ( bOn == pEmptyWin->bFadeIn )
1155 return;
1157 if ( GetItemCount( 0 ) == 0 )
1158 return;
1160 pEmptyWin->bFadeIn = bOn;
1161 if ( bOn )
1163 pEmptyWin->nState |= 2;
1164 if ( IsFloatingMode() )
1166 // FloatingWindow is not visible, thus display it
1167 pWorkWin->ArrangeAutoHideWindows( this );
1168 Show();
1170 else
1172 OSL_TRACE( "SfxSplitWindow::SetFadeIn_Impl - releasing empty Splitwindow" );
1173 pWorkWin->ReleaseChild_Impl( *pEmptyWin );
1174 pEmptyWin->Hide();
1175 OSL_TRACE( "SfxSplitWindow::SetFadeIn_Impl - registering real Splitwindow" );
1176 pWorkWin->RegisterChild_Impl( *this, eAlign, true )->nVisible = SfxChildVisibility::VISIBLE;
1177 pWorkWin->ArrangeChildren_Impl();
1178 pWorkWin->ShowChildren_Impl();
1181 else
1183 pEmptyWin->bAutoHide = false;
1184 pEmptyWin->nState &= ~2;
1185 if ( !IsFloatingMode() )
1187 // The window is not "floating", should be hidden
1188 OSL_TRACE( "SfxSplitWindow::SetFadeIn_Impl - releasing real Splitwindow" );
1189 pWorkWin->ReleaseChild_Impl( *this );
1190 Hide();
1191 pEmptyWin->Actualize();
1192 OSL_TRACE( "SfxSplitWindow::SetFadeIn_Impl - registering empty Splitwindow" );
1193 pWorkWin->RegisterChild_Impl( *pEmptyWin, eAlign, true )->nVisible = SfxChildVisibility::VISIBLE;
1194 pWorkWin->ArrangeChildren_Impl();
1195 pWorkWin->ShowChildren_Impl();
1196 pWorkWin->ArrangeAutoHideWindows( this );
1198 else
1200 Hide();
1201 pWorkWin->ArrangeAutoHideWindows( this );
1206 void SfxSplitWindow::AutoHide()
1208 // If this handler is called in the "real" SplitWindow, it is
1209 // either docked and should be displayed as floating, or vice versa
1210 if ( !bPinned )
1212 // It "floats", thus dock it again
1213 SetPinned_Impl( true );
1214 pWorkWin->ArrangeChildren_Impl();
1216 else
1218 // In "limbo"
1219 SetPinned_Impl( false );
1220 pWorkWin->ArrangeChildren_Impl();
1221 pWorkWin->ArrangeAutoHideWindows( this );
1224 pWorkWin->ShowChildren_Impl();
1225 SaveConfig_Impl();
1228 void SfxSplitWindow::FadeOut_Impl()
1230 if ( pEmptyWin->aTimer.IsActive() )
1232 pEmptyWin->bAutoHide = false;
1233 pEmptyWin->aTimer.Stop();
1236 SetFadeIn_Impl( false );
1239 void SfxSplitWindow::FadeOut()
1241 FadeOut_Impl();
1242 SaveConfig_Impl();
1245 void SfxSplitWindow::FadeIn()
1247 SetFadeIn_Impl( true );
1250 bool SfxSplitWindow::ActivateNextChild_Impl( bool bForward )
1252 // If no pActive, go to first and last window (!bForward is first
1253 // decremented in the loop)
1254 sal_uInt16 nCount = pDockArr->size();
1255 sal_uInt16 n = bForward ? 0 : nCount;
1257 // if Focus is within, then move to a window forward or backwards
1258 // if possible
1259 if ( pActive )
1261 // Determine the active window
1262 for ( n=0; n<nCount; n++ )
1264 const SfxDock_Impl& rD = (*pDockArr)[n];
1265 if ( rD.pWin && rD.pWin->HasChildPathFocus() )
1266 break;
1269 if ( bForward )
1270 // up window counter (then when n>nCount, the loop below is
1271 // not entered)
1272 n++;
1275 if ( bForward )
1277 // Search for next window
1278 for ( sal_uInt16 nNext=n; nNext<nCount; nNext++ )
1280 const SfxDock_Impl& rD = (*pDockArr)[nNext];
1281 if ( rD.pWin )
1283 rD.pWin->GrabFocus();
1284 return true;
1288 else
1290 // Search for previous window
1291 for ( sal_uInt16 nNext=n; nNext--; )
1293 const SfxDock_Impl& rD = (*pDockArr)[nNext];
1294 if ( rD.pWin )
1296 rD.pWin->GrabFocus();
1297 return true;
1302 return false;
1305 void SfxSplitWindow::SetActiveWindow_Impl( SfxDockingWindow* pWin )
1307 pActive = pWin;
1308 pWorkWin->SetActiveChild_Impl( this );
1312 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */