1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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>
36 #include "sfx2/sfxresid.hxx"
37 #include <sfx2/mnumgr.hxx>
38 #include "virtmenu.hxx"
39 #include <sfx2/msgpool.hxx>
40 #include <sfx2/viewfrm.hxx>
45 using namespace ::com::sun::star::uno
;
46 using namespace ::rtl
;
50 #define USERITEM_NAME OUString("UserItem")
53 // helper class to deactivate UpdateMode, if needed, for the life time of an instance
54 class DeactivateUpdateMode
57 explicit DeactivateUpdateMode( SfxSplitWindow
& rSplitWindow
)
58 : mrSplitWindow( rSplitWindow
)
59 , mbUpdateMode( rSplitWindow
.IsUpdateMode() )
63 mrSplitWindow
.SetUpdateMode( sal_False
);
67 ~DeactivateUpdateMode( void )
71 mrSplitWindow
.SetUpdateMode( sal_True
);
76 SfxSplitWindow
& mrSplitWindow
;
77 const sal_Bool mbUpdateMode
;
84 SfxDockingWindow
* pWin
; // SplitWindow has this window
86 sal_Bool bHide
; // SplitWindow had this window
90 class SfxDockArr_Impl
: public std::vector
<SfxDock_Impl
*>
95 for(const_iterator it
= begin(); it
!= end(); ++it
)
101 class SfxEmptySplitWin_Impl
: public SplitWindow
105 The SfxEmptySplitWin_Impldow is an empty SplitWindow, that replaces the
106 SfxSplitWindow AutoHide mode. It only serves as a placeholder to receive
107 mouse moves and if possible blend in the true SplitWindow display.
109 friend class SfxSplitWindow
;
111 SfxSplitWindow
* pOwner
;
115 sal_Bool bEndAutoHide
;
120 SfxEmptySplitWin_Impl( SfxSplitWindow
*pParent
)
121 : SplitWindow( pParent
->GetParent(), WinBits( WB_BORDER
| WB_3DLOOK
) )
123 , bFadeIn( sal_False
)
124 , bAutoHide( sal_False
)
125 , bSplit( sal_False
)
126 , bEndAutoHide( sal_False
)
129 aTimer
.SetTimeoutHdl(
130 LINK(pOwner
, SfxSplitWindow
, TimerHdl
) );
131 aTimer
.SetTimeout( 200 );
132 SetAlign( pOwner
->GetAlign() );
134 ShowAutoHideButton( pOwner
->IsAutoHideButtonVisible() );
135 ShowFadeInHideButton( sal_True
);
138 ~SfxEmptySplitWin_Impl()
143 virtual void MouseMove( const MouseEvent
& );
144 virtual void AutoHide();
145 virtual void FadeIn();
149 void SfxEmptySplitWin_Impl::Actualize()
151 Size
aSize( pOwner
->GetSizePixel() );
152 switch ( pOwner
->GetAlign() )
154 case WINDOWALIGN_LEFT
:
155 case WINDOWALIGN_RIGHT
:
156 aSize
.Width() = GetFadeInSize();
158 case WINDOWALIGN_TOP
:
159 case WINDOWALIGN_BOTTOM
:
160 aSize
.Height() = GetFadeInSize();
164 SetSizePixel( aSize
);
167 void SfxEmptySplitWin_Impl::AutoHide()
169 pOwner
->SetPinned_Impl( !pOwner
->bPinned
);
170 pOwner
->SaveConfig_Impl();
171 bAutoHide
= sal_True
;
175 void SfxEmptySplitWin_Impl::FadeIn()
178 bAutoHide
= IsFadeNoButtonMode();
179 pOwner
->SetFadeIn_Impl( sal_True
);
183 // Set Timer to close; the caller has to ensure themselves that the
184 // Window is not closed instantly (eg by setting the focus or a modal
186 aLastPos
= GetPointerPosPixel();
190 pOwner
->SaveConfig_Impl();
193 //-------------------------------------------------------------------------
195 void SfxSplitWindow::MouseButtonDown( const MouseEvent
& rMEvt
)
197 if ( rMEvt
.GetClicks() != 2 )
198 SplitWindow::MouseButtonDown( rMEvt
);
201 void SfxEmptySplitWin_Impl::MouseMove( const MouseEvent
& rMEvt
)
203 SplitWindow::MouseMove( rMEvt
);
206 //-------------------------------------------------------------------------
208 SfxSplitWindow::SfxSplitWindow( Window
* pParent
, SfxChildAlignment eAl
,
209 SfxWorkWindow
*pW
, sal_Bool bWithButtons
, WinBits nBits
)
213 A SfxSplitWindow brings the recursive structure of the SV-SplitWindows to
214 the outside by simulating a table-like structure with rows and columns
215 (maximum recursion depth 2). Furthermore, it ensures the persistence of
216 the arrangement of the SfxDockingWindows.
219 : SplitWindow ( pParent
, nBits
| WB_HIDE
),
222 pDockArr( new SfxDockArr_Impl
),
230 ShowAutoHideButton( sal_False
); // no autohide button (pin) anymore
231 ShowFadeOutButton( sal_True
);
235 WindowAlign eTbxAlign
;
239 eTbxAlign
= WINDOWALIGN_LEFT
;
241 case SFX_ALIGN_RIGHT
:
242 eTbxAlign
= WINDOWALIGN_RIGHT
;
245 eTbxAlign
= WINDOWALIGN_TOP
;
247 case SFX_ALIGN_BOTTOM
:
248 eTbxAlign
= WINDOWALIGN_BOTTOM
;
252 eTbxAlign
= WINDOWALIGN_TOP
; // some sort of default...
253 break; // -Wall lots not handled..
256 SetAlign (eTbxAlign
);
257 pEmptyWin
= new SfxEmptySplitWin_Impl( this );
260 pEmptyWin
->bFadeIn
= sal_True
;
261 pEmptyWin
->nState
= 2;
266 // Read Configuration
267 String aWindowId
= OUString("SplitWindow");
268 aWindowId
+= OUString::number( (sal_Int32
) eTbxAlign
);
269 SvtViewOptions
aWinOpt( E_WINDOW
, aWindowId
);
271 Any aUserItem
= aWinOpt
.GetUserItem( USERITEM_NAME
);
273 if ( aUserItem
>>= aTemp
)
274 aWinData
= String( aTemp
);
275 if ( aWinData
.Len() && aWinData
.GetChar( (sal_uInt16
) 0 ) == 'V' )
277 pEmptyWin
->nState
= (sal_uInt16
) aWinData
.GetToken( 1, ',' ).ToInt32();
278 if ( pEmptyWin
->nState
& 2 )
279 pEmptyWin
->bFadeIn
= sal_True
;
280 bPinned
= sal_True
; // always assume pinned - floating mode not used anymore
283 sal_uInt16 nCount
= (sal_uInt16
) aWinData
.GetToken(i
++, ',').ToInt32();
284 for ( sal_uInt16 n
=0; n
<nCount
; n
++ )
286 SfxDock_Impl
*pDock
= new SfxDock_Impl
;
288 pDock
->bNewLine
= sal_False
;
289 pDock
->bHide
= sal_True
;
290 pDock
->nType
= (sal_uInt16
) aWinData
.GetToken(i
++, ',').ToInt32();
293 // could mean NewLine
294 pDock
->nType
= (sal_uInt16
) aWinData
.GetToken(i
++, ',').ToInt32();
302 pDock
->bNewLine
= sal_True
;
305 pDockArr
->insert(pDockArr
->begin() + n
, pDock
);
312 pEmptyWin
->bFadeIn
= sal_True
;
313 pEmptyWin
->nState
= 2;
316 SetAutoHideState( !bPinned
);
317 pEmptyWin
->SetAutoHideState( !bPinned
);
320 //-------------------------------------------------------------------------
322 SfxSplitWindow::~SfxSplitWindow()
324 if ( !pWorkWin
->GetParent_Impl() )
329 // Set pOwner to NULL, otherwise try to delete pEmptyWin once more. The
330 // window that is just beeing docked is always deleted from the outside.
331 pEmptyWin
->pOwner
= NULL
;
338 void SfxSplitWindow::SaveConfig_Impl()
340 // Save configuration
341 OUStringBuffer aWinData
;
342 aWinData
.append('V');
343 aWinData
.append(static_cast<sal_Int32
>(VERSION
));
344 aWinData
.append(',');
345 aWinData
.append(static_cast<sal_Int32
>(pEmptyWin
->nState
));
346 aWinData
.append(',');
348 sal_uInt16 nCount
= 0;
350 for ( n
=0; n
<pDockArr
->size(); n
++ )
352 SfxDock_Impl
*pDock
= (*pDockArr
)[n
];
353 if ( pDock
->bHide
|| pDock
->pWin
)
357 aWinData
.append(static_cast<sal_Int32
>(nCount
));
359 for ( n
=0; n
<pDockArr
->size(); n
++ )
361 SfxDock_Impl
*pDock
= (*pDockArr
)[n
];
362 if ( !pDock
->bHide
&& !pDock
->pWin
)
364 if ( pDock
->bNewLine
)
365 aWinData
.append(",0");
366 aWinData
.append(',');
367 aWinData
.append(static_cast<sal_Int32
>(pDock
->nType
));
370 String aWindowId
= OUString("SplitWindow");
371 aWindowId
+= OUString::number( (sal_Int32
) GetAlign() );
372 SvtViewOptions
aWinOpt( E_WINDOW
, aWindowId
);
373 aWinOpt
.SetUserItem( USERITEM_NAME
, makeAny( aWinData
.makeStringAndClear() ) );
376 //-------------------------------------------------------------------------
378 void SfxSplitWindow::StartSplit()
381 Size aSize
= GetSizePixel();
385 pEmptyWin
->bFadeIn
= sal_True
;
386 pEmptyWin
->bSplit
= sal_True
;
389 Rectangle aRect
= pWorkWin
->GetFreeArea( !bPinned
);
390 switch ( GetAlign() )
392 case WINDOWALIGN_LEFT
:
393 case WINDOWALIGN_RIGHT
:
394 nSize
= aSize
.Width() + aRect
.GetWidth();
396 case WINDOWALIGN_TOP
:
397 case WINDOWALIGN_BOTTOM
:
398 nSize
= aSize
.Height() + aRect
.GetHeight();
402 SetMaxSizePixel( nSize
);
405 //-------------------------------------------------------------------------
407 void SfxSplitWindow::SplitResize()
411 pWorkWin
->ArrangeChildren_Impl();
412 pWorkWin
->ShowChildren_Impl();
415 pWorkWin
->ArrangeAutoHideWindows( this );
418 //-------------------------------------------------------------------------
420 void SfxSplitWindow::Split()
423 pEmptyWin
->bSplit
= sal_False
;
425 SplitWindow::Split();
427 std::vector
< std::pair
< sal_uInt16
, long > > aNewOrgSizes
;
429 sal_uInt16 nCount
= pDockArr
->size();
430 for ( sal_uInt16 n
=0; n
<nCount
; n
++ )
432 SfxDock_Impl
*pD
= (*pDockArr
)[n
];
435 const sal_uInt16 nId
= pD
->nType
;
436 const long nSize
= GetItemSize( nId
, SWIB_FIXED
);
437 const long nSetSize
= GetItemSize( GetSet( nId
) );
440 if ( IsHorizontal() )
442 aSize
.Width() = nSize
;
443 aSize
.Height() = nSetSize
;
447 aSize
.Width() = nSetSize
;
448 aSize
.Height() = nSize
;
451 pD
->pWin
->SetItemSize_Impl( aSize
);
453 aNewOrgSizes
.push_back( std::pair
< sal_uInt16
, long >( nId
, nSize
) );
457 // workaround insuffiency of <SplitWindow> regarding dock layouting:
458 // apply FIXED item size as 'original' item size to improve layouting of undock-dock-cycle of a window
460 DeactivateUpdateMode
aDeactivateUpdateMode( *this );
461 for ( sal_uInt16 i
= 0; i
< aNewOrgSizes
.size(); ++i
)
463 SetItemSize( aNewOrgSizes
[i
].first
, aNewOrgSizes
[i
].second
);
470 //-------------------------------------------------------------------------
472 void SfxSplitWindow::InsertWindow( SfxDockingWindow
* pDockWin
, const Size
& rSize
)
475 To insert SfxDockingWindows just pass no position. The SfxSplitWindow
476 searches the last marked one to the passed SfxDockingWindow or appends a
480 short nLine
= -1; // so that the first window cab set nline to 0
483 sal_Bool bNewLine
= sal_True
;
484 sal_Bool bSaveConfig
= sal_False
;
485 SfxDock_Impl
*pFoundDock
=0;
486 sal_uInt16 nCount
= pDockArr
->size();
487 for ( sal_uInt16 n
=0; n
<nCount
; n
++ )
489 SfxDock_Impl
*pDock
= (*pDockArr
)[n
];
490 if ( pDock
->bNewLine
)
492 // The window opens a new line
494 // But after the just inserted window
504 // Does there exist a window now at this position
505 if ( bNewLine
&& !pFoundDock
)
507 // Not known until now in which real line it is located
508 GetWindowPos( pDock
->pWin
, nL
, nPos
);
514 // The window is located before the inserted one
519 bNewLine
= sal_False
;
524 if ( pDock
->nType
== pDockWin
->GetType() )
526 DBG_ASSERT( !pFoundDock
&& !pDock
->pWin
, "Window already exists!");
532 // A new line has been created but no window was found there;
533 // continue searching for a window in this line in-order to set
534 // bNewLine correctly. While doing so nline or nPos are not
543 // Not found, insert at end
544 pFoundDock
= new SfxDock_Impl
;
545 pFoundDock
->bHide
= sal_True
;
546 pDockArr
->push_back( pFoundDock
);
547 pFoundDock
->nType
= pDockWin
->GetType();
551 pFoundDock
->bNewLine
= bNewLine
;
552 bSaveConfig
= sal_True
;
555 pFoundDock
->pWin
= pDockWin
;
556 pFoundDock
->bHide
= sal_False
;
557 InsertWindow_Impl( pFoundDock
, rSize
, nLine
, nPos
, bNewLine
);
562 //-------------------------------------------------------------------------
564 void SfxSplitWindow::ReleaseWindow_Impl(SfxDockingWindow
*pDockWin
, sal_Bool bSave
)
566 // The docking window is no longer stored in the internal data.
567 SfxDock_Impl
*pDock
=0;
568 sal_uInt16 nCount
= pDockArr
->size();
569 sal_Bool bFound
= sal_False
;
570 for ( sal_uInt16 n
=0; n
<nCount
; n
++ )
572 pDock
= (*pDockArr
)[n
];
573 if ( pDock
->nType
== pDockWin
->GetType() )
575 if ( pDock
->bNewLine
&& n
<nCount
-1 )
576 (*pDockArr
)[n
+1]->bNewLine
= sal_True
;
578 // Window has a position, this we forget
580 pDockArr
->erase(pDockArr
->begin() + n
);
592 //-------------------------------------------------------------------------
594 void SfxSplitWindow::MoveWindow( SfxDockingWindow
* pDockWin
, const Size
& rSize
,
595 sal_uInt16 nLine
, sal_uInt16 nPos
, sal_Bool bNewLine
)
599 The docking window is moved within the SplitWindows.
604 GetWindowPos( pDockWin
, nL
, nP
);
606 if ( nLine
> nL
&& GetItemCount( GetItemId( nL
, 0 ) ) == 1 )
608 // If the last window is removed from its line, then everything slips
609 // one line to the front!
612 RemoveWindow( pDockWin
);
613 InsertWindow( pDockWin
, rSize
, nLine
, nPos
, bNewLine
);
616 //-------------------------------------------------------------------------
618 void SfxSplitWindow::InsertWindow( SfxDockingWindow
* pDockWin
, const Size
& rSize
,
619 sal_uInt16 nLine
, sal_uInt16 nPos
, sal_Bool bNewLine
)
623 The DockingWindow that is pushed on this SplitWindow and shall hold the
624 given position and size.
627 ReleaseWindow_Impl( pDockWin
, sal_False
);
628 SfxDock_Impl
*pDock
= new SfxDock_Impl
;
629 pDock
->bHide
= sal_False
;
630 pDock
->nType
= pDockWin
->GetType();
631 pDock
->bNewLine
= bNewLine
;
632 pDock
->pWin
= pDockWin
;
634 DBG_ASSERT( nPos
==0 || !bNewLine
, "Wrong Paramenter!");
638 // The window must be inserted before the first window so that it has the
639 // same or a greater position than pDockWin.
640 sal_uInt16 nCount
= pDockArr
->size();
641 sal_uInt16
nLastWindowIdx(0);
643 // If no window is found, a first window is inserted
644 sal_uInt16 nInsertPos
= 0;
645 for ( sal_uInt16 n
=0; n
<nCount
; n
++ )
647 SfxDock_Impl
*pD
= (*pDockArr
)[n
];
651 // A docked window has been found. If no suitable window behind the
652 // the desired insertion point s found, then insertion is done at
656 sal_uInt16 nL
=0, nP
=0;
657 GetWindowPos( pD
->pWin
, nL
, nP
);
659 if ( (nL
== nLine
&& nP
== nPos
) || nL
> nLine
)
661 DBG_ASSERT( nL
== nLine
|| bNewLine
|| nPos
> 0, "Wrong Parameter!" );
662 if ( nL
== nLine
&& nPos
== 0 && !bNewLine
)
664 DBG_ASSERT(pD
->bNewLine
, "No new line?");
666 // The posption is pushed to nPos==0
667 pD
->bNewLine
= sal_False
;
668 pDock
->bNewLine
= sal_True
;
671 nInsertPos
= n
!= 0 ? nLastWindowIdx
+ 1 : 0; // ignore all non-windows after the last window
676 if (nCount
!= 0 && nInsertPos
== nCount
&& nLastWindowIdx
!= nCount
- 1)
678 nInsertPos
= nLastWindowIdx
+ 1; // ignore all non-windows after the last window
681 pDockArr
->insert(pDockArr
->begin() + nInsertPos
, pDock
);
682 InsertWindow_Impl( pDock
, rSize
, nLine
, nPos
, bNewLine
);
686 //-------------------------------------------------------------------------
688 void SfxSplitWindow::InsertWindow_Impl( SfxDock_Impl
* pDock
,
690 sal_uInt16 nLine
, sal_uInt16 nPos
, sal_Bool bNewLine
)
694 Adds a DockingWindow, and causes the recalculation of the size of
699 SfxDockingWindow
* pDockWin
= pDock
->pWin
;
701 sal_uInt16 nItemBits
= pDockWin
->GetWinBits_Impl();
703 long nWinSize
, nSetSize
;
704 if ( IsHorizontal() )
706 nWinSize
= rSize
.Width();
707 nSetSize
= rSize
.Height();
711 nSetSize
= rSize
.Width();
712 nWinSize
= rSize
.Height();
715 pDock
->nSize
= nWinSize
;
717 DeactivateUpdateMode
* pDeactivateUpdateMode
= new DeactivateUpdateMode( *this );
719 if ( bNewLine
|| nLine
== GetItemCount( 0 ) )
721 // An existing row should not be inserted, instead a new one
725 for ( sal_uInt16 n
=0; n
<GetItemCount(0); n
++ )
727 if ( GetItemId(n
) >= nId
)
728 nId
= GetItemId(n
)+1;
731 // Create a new nLine:th line
732 sal_uInt16 nBits
= nItemBits
;
733 if ( GetAlign() == WINDOWALIGN_TOP
|| GetAlign() == WINDOWALIGN_BOTTOM
)
734 nBits
|= SWIB_COLSET
;
735 InsertItem( nId
, nSetSize
, nLine
, 0, nBits
);
738 // Insert the window at line with the position nline. ItemWindowSize set to
739 // "percentage" share since the SV then does the re-sizing as expected,
740 // "pixel" actually only makes sense if also items with percentage or
741 // relative sizes are present.
742 nItemBits
|= SWIB_PERCENTSIZE
;
744 sal_uInt16 nSet
= GetItemId( nLine
);
745 InsertItem( pDockWin
->GetType(), pDockWin
, nWinSize
, nPos
, nSet
, nItemBits
);
747 // SplitWindows are once created in SFX and when inserting the first
748 // DockingWindows is made visable.
749 if ( GetItemCount( 0 ) == 1 && GetItemCount( 1 ) == 1 )
751 // The Rearranging in WorkWindow and a Show() on the SplitWindow is
752 // caues by SfxDockingwindow (->SfxWorkWindow::ConfigChild_Impl)
753 if ( !bPinned
&& !IsFloatingMode() )
756 sal_Bool bFadeIn
= ( pEmptyWin
->nState
& 2 ) != 0;
757 pEmptyWin
->bFadeIn
= sal_False
;
758 SetPinned_Impl( sal_False
);
759 pEmptyWin
->Actualize();
760 OSL_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" );
761 pWorkWin
->RegisterChild_Impl( *GetSplitWindow(), eAlign
, sal_True
)->nVisible
= CHILD_VISIBLE
;
762 pWorkWin
->ArrangeChildren_Impl();
768 sal_Bool bFadeIn
= ( pEmptyWin
->nState
& 2 ) != 0;
769 pEmptyWin
->bFadeIn
= sal_False
;
770 pEmptyWin
->Actualize();
772 if ( !bPinned
|| !pEmptyWin
->bFadeIn
)
774 OSL_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" );
778 OSL_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering real Splitwindow" );
781 pWorkWin
->RegisterChild_Impl( *GetSplitWindow(), eAlign
, sal_True
)->nVisible
= CHILD_VISIBLE
;
782 pWorkWin
->ArrangeChildren_Impl();
787 pWorkWin
->ShowChildren_Impl();
790 delete pDeactivateUpdateMode
;
793 // workaround insuffiency of <SplitWindow> regarding dock layouting:
794 // apply FIXED item size as 'original' item size to improve layouting of undock-dock-cycle of a window
796 std::vector
< std::pair
< sal_uInt16
, long > > aNewOrgSizes
;
797 // get FIXED item sizes
798 sal_uInt16 nCount
= pDockArr
->size();
799 for ( sal_uInt16 n
=0; n
<nCount
; ++n
)
801 SfxDock_Impl
*pD
= (*pDockArr
)[n
];
804 const sal_uInt16 nId
= pD
->nType
;
805 const long nSize
= GetItemSize( nId
, SWIB_FIXED
);
806 aNewOrgSizes
.push_back( std::pair
< sal_uInt16
, long >( nId
, nSize
) );
809 // apply new item sizes
810 DeactivateUpdateMode
aDeactivateUpdateMode( *this );
811 for ( sal_uInt16 i
= 0; i
< aNewOrgSizes
.size(); ++i
)
813 SetItemSize( aNewOrgSizes
[i
].first
, aNewOrgSizes
[i
].second
);
818 //-------------------------------------------------------------------------
820 void SfxSplitWindow::RemoveWindow( SfxDockingWindow
* pDockWin
, sal_Bool bHide
)
824 Removes a DockingWindow. If it was the last one, then the SplitWindow is
828 sal_uInt16 nSet
= GetSet( pDockWin
->GetType() );
830 // SplitWindows are once created in SFX and is made invisible after
831 // removing the last DockingWindows.
832 if ( GetItemCount( nSet
) == 1 && GetItemCount( 0 ) == 1 )
834 // The Rearranging in WorkWindow is caues by SfxDockingwindow
836 pEmptyWin
->aTimer
.Stop();
837 sal_uInt16 nRealState
= pEmptyWin
->nState
;
841 if ( !bPinned
|| !pEmptyWin
->bFadeIn
)
843 OSL_TRACE( "SfxSplitWindow::RemoveWindow - releasing empty Splitwindow" );
847 OSL_TRACE( "SfxSplitWindow::RemoveWindow - releasing real Splitwindow" );
850 pWorkWin
->ReleaseChild_Impl( *GetSplitWindow() );
851 pEmptyWin
->nState
= nRealState
;
852 pWorkWin
->ArrangeAutoHideWindows( this );
855 SfxDock_Impl
*pDock
=0;
856 sal_uInt16 nCount
= pDockArr
->size();
857 for ( sal_uInt16 n
=0; n
<nCount
; n
++ )
859 pDock
= (*pDockArr
)[n
];
860 if ( pDock
->nType
== pDockWin
->GetType() )
863 pDock
->bHide
= bHide
;
868 // Remove Windows, and if it was the last of the line, then also remove
869 // the line (line = itemset)
870 DeactivateUpdateMode
* pDeactivateUpdateMode
= new DeactivateUpdateMode( *this );
873 RemoveItem( pDockWin
->GetType() );
875 if ( nSet
&& !GetItemCount( nSet
) )
878 delete pDeactivateUpdateMode
;
882 //-------------------------------------------------------------------------
884 sal_Bool
SfxSplitWindow::GetWindowPos( const SfxDockingWindow
* pWindow
,
885 sal_uInt16
& rLine
, sal_uInt16
& rPos
) const
888 Returns the ID of the item sets and items for the DockingWindow in
889 the position passed on the old row / column-name.
893 sal_uInt16 nSet
= GetSet ( pWindow
->GetType() );
894 if ( nSet
== SPLITWINDOW_ITEM_NOTFOUND
)
897 rPos
= GetItemPos( pWindow
->GetType(), nSet
);
898 rLine
= GetItemPos( nSet
);
902 //-------------------------------------------------------------------------
904 sal_Bool
SfxSplitWindow::GetWindowPos( const Point
& rTestPos
,
905 sal_uInt16
& rLine
, sal_uInt16
& rPos
) const
908 Returns the ID of the item sets and items for the DockingWindow in
909 the position passed on the old row / column-name.
913 sal_uInt16 nId
= GetItemId( rTestPos
);
917 sal_uInt16 nSet
= GetSet ( nId
);
918 rPos
= GetItemPos( nId
, nSet
);
919 rLine
= GetItemPos( nSet
);
923 //-------------------------------------------------------------------------
925 sal_uInt16
SfxSplitWindow::GetLineCount() const
929 Returns the number of rows = number of sub-itemsets in the root set.
932 return GetItemCount( 0 );
935 //-------------------------------------------------------------------------
937 long SfxSplitWindow::GetLineSize( sal_uInt16 nLine
) const
941 Returns the Row Height of nline itemset.
944 sal_uInt16 nId
= GetItemId( nLine
);
945 return GetItemSize( nId
);
948 //-------------------------------------------------------------------------
950 sal_uInt16
SfxSplitWindow::GetWindowCount( sal_uInt16 nLine
) const
954 Returns the total number of windows
957 sal_uInt16 nId
= GetItemId( nLine
);
958 return GetItemCount( nId
);
961 //-------------------------------------------------------------------------
963 sal_uInt16
SfxSplitWindow::GetWindowCount() const
967 Returns the total number of windows
970 return GetItemCount( 0 );
973 //-------------------------------------------------------------------------
975 void SfxSplitWindow::Command( const CommandEvent
& rCEvt
)
977 SplitWindow::Command( rCEvt
);
980 //-------------------------------------------------------------------------
982 IMPL_LINK( SfxSplitWindow
, TimerHdl
, Timer
*, pTimer
)
987 if ( CursorIsOverRect( sal_False
) || !pTimer
)
989 // If the cursor is within the window, display the SplitWindow and set
990 // up the timer for close
991 pEmptyWin
->bAutoHide
= sal_True
;
995 pEmptyWin
->aLastPos
= GetPointerPosPixel();
996 pEmptyWin
->aTimer
.Start();
998 else if ( pEmptyWin
->bAutoHide
)
1000 if ( GetPointerPosPixel() != pEmptyWin
->aLastPos
)
1002 // The mouse has moved within the running time of the timer, thus
1004 pEmptyWin
->aLastPos
= GetPointerPosPixel();
1005 pEmptyWin
->aTimer
.Start();
1009 // Especially for TF_AUTOSHOW_ON_MOUSEMOVE :
1010 // If the window is not visible, there is nothing to do
1011 // (user has simply moved the mouse over pEmptyWin)
1014 pEmptyWin
->bEndAutoHide
= sal_False
;
1015 if ( !Application::IsInModalMode() &&
1016 !PopupMenu::IsInExecute() &&
1017 !pEmptyWin
->bSplit
&& !HasChildPathFocus( sal_True
) )
1019 // While a modal dialog or a popup menu is open or while the
1020 // Splitting is done, in any case, do not close. Even as long
1021 // as one of the Children has the focus, the window remains
1023 pEmptyWin
->bEndAutoHide
= sal_True
;
1026 if ( pEmptyWin
->bEndAutoHide
)
1028 // As far as I am concered this can be the end of AutoShow
1029 // But maybe some other SfxSplitWindow will remain open,
1030 // then all others remain open too.
1031 if ( !pWorkWin
->IsAutoHideMode( this ) )
1034 pWorkWin
->ArrangeAutoHideWindows( this );
1038 pEmptyWin
->aLastPos
= GetPointerPosPixel();
1039 pEmptyWin
->aTimer
.Start();
1044 pEmptyWin
->aLastPos
= GetPointerPosPixel();
1045 pEmptyWin
->aTimer
.Start();
1053 //-------------------------------------------------------------------------
1055 sal_Bool
SfxSplitWindow::CursorIsOverRect( sal_Bool bForceAdding
) const
1057 sal_Bool bVisible
= IsVisible();
1059 // Also, take the collapsed SplitWindow into account
1060 Point aPos
= pEmptyWin
->GetParent()->OutputToScreenPixel( pEmptyWin
->GetPosPixel() );
1061 Size aSize
= pEmptyWin
->GetSizePixel();
1065 // Extend with +/- a few pixels, otherwise it is too nervous
1068 aSize
.Width() += 2 * nPixel
;
1069 aSize
.Height() += 2 * nPixel
;
1072 Rectangle
aRect( aPos
, aSize
);
1076 Point aVisPos
= GetPosPixel();
1077 Size aVisSize
= GetSizePixel();
1079 // Extend with +/- a few pixels, otherwise it is too nervous
1080 aVisPos
.X() -= nPixel
;
1081 aVisPos
.Y() -= nPixel
;
1082 aVisSize
.Width() += 2 * nPixel
;
1083 aVisSize
.Height() += 2 * nPixel
;
1085 Rectangle
aVisRect( aVisPos
, aVisSize
);
1086 aRect
= aRect
.GetUnion( aVisRect
);
1089 if ( aRect
.IsInside( OutputToScreenPixel( ((Window
*)this)->GetPointerPosPixel() ) ) )
1094 //-------------------------------------------------------------------------
1096 SplitWindow
* SfxSplitWindow::GetSplitWindow()
1098 if ( !bPinned
|| !pEmptyWin
->bFadeIn
)
1103 //-------------------------------------------------------------------------
1104 sal_Bool
SfxSplitWindow::IsFadeIn() const
1106 return pEmptyWin
->bFadeIn
;
1109 sal_Bool
SfxSplitWindow::IsAutoHide( sal_Bool bSelf
) const
1111 return bSelf
? pEmptyWin
->bAutoHide
&& !pEmptyWin
->bEndAutoHide
: pEmptyWin
->bAutoHide
;
1114 //-------------------------------------------------------------------------
1116 void SfxSplitWindow::SetPinned_Impl( sal_Bool bOn
)
1118 if ( bPinned
== bOn
)
1122 if ( GetItemCount( 0 ) == 0 )
1127 pEmptyWin
->nState
|= 1;
1128 if ( pEmptyWin
->bFadeIn
)
1130 // Unregister replacement windows
1131 OSL_TRACE( "SfxSplitWindow::SetPinned_Impl - releasing real Splitwindow" );
1132 pWorkWin
->ReleaseChild_Impl( *this );
1134 pEmptyWin
->Actualize();
1135 OSL_TRACE( "SfxSplitWindow::SetPinned_Impl - registering empty Splitwindow" );
1136 pWorkWin
->RegisterChild_Impl( *pEmptyWin
, eAlign
, sal_True
)->nVisible
= CHILD_VISIBLE
;
1139 Point
aPos( GetPosPixel() );
1140 aPos
= GetParent()->OutputToScreenPixel( aPos
);
1141 SetFloatingPos( aPos
);
1142 SetFloatingMode( sal_True
);
1143 GetFloatingWindow()->SetOutputSizePixel( GetOutputSizePixel() );
1145 if ( pEmptyWin
->bFadeIn
)
1150 pEmptyWin
->nState
&= ~1;
1151 SetOutputSizePixel( GetFloatingWindow()->GetOutputSizePixel() );
1152 SetFloatingMode( sal_False
);
1154 if ( pEmptyWin
->bFadeIn
)
1156 // Unregister replacement windows
1157 OSL_TRACE( "SfxSplitWindow::SetPinned_Impl - releasing empty Splitwindow" );
1158 pWorkWin
->ReleaseChild_Impl( *pEmptyWin
);
1160 OSL_TRACE( "SfxSplitWindow::SetPinned_Impl - registering real Splitwindow" );
1161 pWorkWin
->RegisterChild_Impl( *this, eAlign
, sal_True
)->nVisible
= CHILD_VISIBLE
;
1165 SetAutoHideState( !bPinned
);
1166 pEmptyWin
->SetAutoHideState( !bPinned
);
1169 //-------------------------------------------------------------------------
1171 void SfxSplitWindow::SetFadeIn_Impl( sal_Bool bOn
)
1173 if ( bOn
== pEmptyWin
->bFadeIn
)
1176 if ( GetItemCount( 0 ) == 0 )
1179 pEmptyWin
->bFadeIn
= bOn
;
1182 pEmptyWin
->nState
|= 2;
1183 if ( IsFloatingMode() )
1185 // FloatingWindow is not visable, thus display it
1186 pWorkWin
->ArrangeAutoHideWindows( this );
1191 OSL_TRACE( "SfxSplitWindow::SetFadeIn_Impl - releasing empty Splitwindow" );
1192 pWorkWin
->ReleaseChild_Impl( *pEmptyWin
);
1194 OSL_TRACE( "SfxSplitWindow::SetFadeIn_Impl - registering real Splitwindow" );
1195 pWorkWin
->RegisterChild_Impl( *this, eAlign
, sal_True
)->nVisible
= CHILD_VISIBLE
;
1196 pWorkWin
->ArrangeChildren_Impl();
1197 pWorkWin
->ShowChildren_Impl();
1202 pEmptyWin
->bAutoHide
= sal_False
;
1203 pEmptyWin
->nState
&= ~2;
1204 if ( !IsFloatingMode() )
1206 // The window is not "floating", should be hidden
1207 OSL_TRACE( "SfxSplitWindow::SetFadeIn_Impl - releasing real Splitwindow" );
1208 pWorkWin
->ReleaseChild_Impl( *this );
1210 pEmptyWin
->Actualize();
1211 OSL_TRACE( "SfxSplitWindow::SetFadeIn_Impl - registering empty Splitwindow" );
1212 pWorkWin
->RegisterChild_Impl( *pEmptyWin
, eAlign
, sal_True
)->nVisible
= CHILD_VISIBLE
;
1213 pWorkWin
->ArrangeChildren_Impl();
1214 pWorkWin
->ShowChildren_Impl();
1215 pWorkWin
->ArrangeAutoHideWindows( this );
1220 pWorkWin
->ArrangeAutoHideWindows( this );
1225 void SfxSplitWindow::AutoHide()
1227 // If this handler is called in the "real" SplitWindow, it is
1228 // either docked and should be displayed as floating, or vice versa
1231 // It "floats", thus dock it again
1232 SetPinned_Impl( sal_True
);
1233 pWorkWin
->ArrangeChildren_Impl();
1238 SetPinned_Impl( sal_False
);
1239 pWorkWin
->ArrangeChildren_Impl();
1240 pWorkWin
->ArrangeAutoHideWindows( this );
1243 pWorkWin
->ShowChildren_Impl();
1247 void SfxSplitWindow::FadeOut_Impl()
1249 if ( pEmptyWin
->aTimer
.IsActive() )
1251 pEmptyWin
->bAutoHide
= sal_False
;
1252 pEmptyWin
->aTimer
.Stop();
1255 SetFadeIn_Impl( sal_False
);
1259 void SfxSplitWindow::FadeOut()
1265 void SfxSplitWindow::FadeIn()
1267 SetFadeIn_Impl( sal_True
);
1271 void SfxSplitWindow::Show_Impl()
1273 sal_uInt16 nCount
= pDockArr
->size();
1274 for ( sal_uInt16 n
=0; n
<nCount
; n
++ )
1276 SfxDock_Impl
*pDock
= (*pDockArr
)[n
];
1278 pDock
->pWin
->FadeIn( pEmptyWin
->bFadeIn
);
1282 sal_Bool
SfxSplitWindow::ActivateNextChild_Impl( sal_Bool bForward
)
1284 // If no pActive, go to first and last window (!bForward is first
1285 // decremented in the loop)
1286 sal_uInt16 nCount
= pDockArr
->size();
1287 sal_uInt16 n
= bForward
? 0 : nCount
;
1289 // if Focus is within, then move to a window forward or backwards
1293 // Determine the active window
1294 for ( n
=0; n
<nCount
; n
++ )
1296 SfxDock_Impl
*pD
= (*pDockArr
)[n
];
1297 if ( pD
->pWin
&& pD
->pWin
->HasChildPathFocus() )
1302 // up window counter (then when n>nCount, the loop below is
1309 // Search for next window
1310 for ( sal_uInt16 nNext
=n
; nNext
<nCount
; nNext
++ )
1312 SfxDock_Impl
*pD
= (*pDockArr
)[nNext
];
1315 pD
->pWin
->GrabFocus();
1322 // Search for previous window
1323 for ( sal_uInt16 nNext
=n
; nNext
--; )
1325 SfxDock_Impl
*pD
= (*pDockArr
)[nNext
];
1328 pD
->pWin
->GrabFocus();
1337 void SfxSplitWindow::SetActiveWindow_Impl( SfxDockingWindow
* pWin
)
1340 pWorkWin
->SetActiveChild_Impl( this );
1344 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */