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
;
49 #define USERITEM_NAME OUString("UserItem")
52 // helper class to deactivate UpdateMode, if needed, for the life time of an instance
53 class DeactivateUpdateMode
56 explicit DeactivateUpdateMode( SfxSplitWindow
& rSplitWindow
)
57 : mrSplitWindow( rSplitWindow
)
58 , mbUpdateMode( rSplitWindow
.IsUpdateMode() )
62 mrSplitWindow
.SetUpdateMode( false );
66 ~DeactivateUpdateMode()
70 mrSplitWindow
.SetUpdateMode( true );
75 SfxSplitWindow
& mrSplitWindow
;
76 const bool mbUpdateMode
;
80 class SfxEmptySplitWin_Impl
: public SplitWindow
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
;
100 SfxEmptySplitWin_Impl( SfxSplitWindow
*pParent
)
101 : SplitWindow( pParent
->GetParent(), WinBits( WB_BORDER
| WB_3DLOOK
) )
106 , bEndAutoHide( false )
109 aTimer
.SetTimeoutHdl(
110 LINK(pOwner
, SfxSplitWindow
, TimerHdl
) );
111 aTimer
.SetTimeout( 200 );
112 SetAlign( pOwner
->GetAlign() );
114 ShowAutoHideButton( pOwner
->IsAutoHideButtonVisible() );
115 ShowFadeInHideButton( true );
118 virtual ~SfxEmptySplitWin_Impl()
120 virtual void dispose() SAL_OVERRIDE
124 SplitWindow::dispose();
127 virtual void MouseMove( const MouseEvent
& ) SAL_OVERRIDE
;
128 virtual void AutoHide() SAL_OVERRIDE
;
129 virtual void FadeIn() SAL_OVERRIDE
;
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();
142 case WINDOWALIGN_TOP
:
143 case WINDOWALIGN_BOTTOM
:
144 aSize
.Height() = GetFadeInSize();
148 SetSizePixel( aSize
);
151 void SfxEmptySplitWin_Impl::AutoHide()
153 pOwner
->SetPinned_Impl( !pOwner
->bPinned
);
154 pOwner
->SaveConfig_Impl();
159 void SfxEmptySplitWin_Impl::FadeIn()
162 bAutoHide
= IsFadeNoButtonMode();
163 pOwner
->SetFadeIn_Impl( true );
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
169 aLastPos
= GetPointerPosPixel();
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
)
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
),
205 pDockArr( new SfxDockArr_Impl
),
213 ShowAutoHideButton( false ); // no autohide button (pin) anymore
214 ShowFadeOutButton( true );
218 WindowAlign eTbxAlign
;
221 case SfxChildAlignment::LEFT
:
222 eTbxAlign
= WINDOWALIGN_LEFT
;
224 case SfxChildAlignment::RIGHT
:
225 eTbxAlign
= WINDOWALIGN_RIGHT
;
227 case SfxChildAlignment::TOP
:
228 eTbxAlign
= WINDOWALIGN_TOP
;
230 case SfxChildAlignment::BOTTOM
:
231 eTbxAlign
= WINDOWALIGN_BOTTOM
;
235 eTbxAlign
= WINDOWALIGN_TOP
; // some sort of default...
236 break; // -Wall lots not handled..
239 SetAlign (eTbxAlign
);
240 pEmptyWin
= VclPtr
<SfxEmptySplitWin_Impl
>::Create( this );
243 pEmptyWin
->bFadeIn
= true;
244 pEmptyWin
->nState
= 2;
249 // Read Configuration
250 OUString
aWindowId("SplitWindow");
251 aWindowId
+= OUString::number( (sal_Int32
) eTbxAlign
);
252 SvtViewOptions
aWinOpt( E_WINDOW
, aWindowId
);
254 Any aUserItem
= aWinOpt
.GetUserItem( USERITEM_NAME
);
256 if ( aUserItem
>>= 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
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
;
271 pDock
->bNewLine
= false;
273 pDock
->nType
= (sal_uInt16
) aWinData
.getToken(i
++, ',').toInt32();
276 // could mean NewLine
277 pDock
->nType
= (sal_uInt16
) aWinData
.getToken(i
++, ',').toInt32();
285 pDock
->bNewLine
= true;
288 pDockArr
->insert(pDockArr
->begin() + n
, pDock
);
295 pEmptyWin
->bFadeIn
= true;
296 pEmptyWin
->nState
= 2;
299 SetAutoHideState( !bPinned
);
300 pEmptyWin
->SetAutoHideState( !bPinned
);
305 SfxSplitWindow::~SfxSplitWindow()
310 void SfxSplitWindow::dispose()
312 if ( !pWorkWin
->GetParent_Impl() )
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();
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;
340 for ( n
=0; n
<pDockArr
->size(); n
++ )
342 const SfxDock_Impl
& rDock
= (*pDockArr
)[n
];
343 if ( rDock
.bHide
|| rDock
.pWin
)
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
)
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()
371 Size aSize
= GetSizePixel();
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();
386 case WINDOWALIGN_TOP
:
387 case WINDOWALIGN_BOTTOM
:
388 nSize
= aSize
.Height() + aRect
.GetHeight();
392 SetMaxSizePixel( nSize
);
397 void SfxSplitWindow::SplitResize()
401 pWorkWin
->ArrangeChildren_Impl();
402 pWorkWin
->ShowChildren_Impl();
405 pWorkWin
->ArrangeAutoHideWindows( this );
410 void SfxSplitWindow::Split()
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
];
425 const sal_uInt16 nId
= rD
.nType
;
426 const long nSize
= GetItemSize( nId
, SWIB_FIXED
);
427 const long nSetSize
= GetItemSize( GetSet( nId
) );
430 if ( IsHorizontal() )
432 aSize
.Width() = nSize
;
433 aSize
.Height() = nSetSize
;
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
);
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
470 short nLine
= -1; // so that the first window cab set nline to 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
484 // But after the just inserted window
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
);
504 // The window is located before the inserted one
514 if ( rDock
.nType
== pDockWin
->GetType() )
516 DBG_ASSERT( !pFoundDock
&& !rDock
.pWin
, "Window already exists!");
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
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();
541 pFoundDock
->bNewLine
= bNewLine
;
545 pFoundDock
->pWin
= pDockWin
;
546 pFoundDock
->bHide
= false;
547 InsertWindow_Impl( pFoundDock
, rSize
, nLine
, nPos
, bNewLine
);
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
);
578 void SfxSplitWindow::MoveWindow( SfxDockingWindow
* pDockWin
, const Size
& rSize
,
579 sal_uInt16 nLine
, sal_uInt16 nPos
, bool bNewLine
)
583 The docking window is moved within the SplitWindows.
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!
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
)
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!");
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
];
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
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
652 pDock
->bNewLine
= true;
655 nInsertPos
= n
!= 0 ? nLastWindowIdx
+ 1 : 0; // ignore all non-windows after the last window
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
);
672 void SfxSplitWindow::InsertWindow_Impl( SfxDock_Impl
* pDock
,
674 sal_uInt16 nLine
, sal_uInt16 nPos
, bool bNewLine
)
678 Adds a DockingWindow, and causes the recalculation of the size of
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();
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
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
;
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() )
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();
752 bool bFadeIn
= ( pEmptyWin
->nState
& 2 ) != 0;
753 pEmptyWin
->bFadeIn
= false;
754 pEmptyWin
->Actualize();
756 if ( !bPinned
|| !pEmptyWin
->bFadeIn
)
758 OSL_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" );
762 OSL_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering real Splitwindow" );
765 pWorkWin
->RegisterChild_Impl( *GetSplitWindow(), eAlign
, true )->nVisible
= SfxChildVisibility::VISIBLE
;
766 pWorkWin
->ArrangeChildren_Impl();
771 pWorkWin
->ShowChildren_Impl();
774 delete pDeactivateUpdateMode
;
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
];
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
)
808 Removes a DockingWindow. If it was the last one, then the SplitWindow is
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
820 pEmptyWin
->aTimer
.Stop();
821 sal_uInt16 nRealState
= pEmptyWin
->nState
;
825 if ( !bPinned
|| !pEmptyWin
->bFadeIn
)
827 OSL_TRACE( "SfxSplitWindow::RemoveWindow - releasing empty Splitwindow" );
831 OSL_TRACE( "SfxSplitWindow::RemoveWindow - releasing real Splitwindow" );
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() )
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 );
856 RemoveItem( pDockWin
->GetType() );
858 if ( nSet
&& !GetItemCount( nSet
) )
861 delete pDeactivateUpdateMode
;
867 bool SfxSplitWindow::GetWindowPos( const SfxDockingWindow
* pWindow
,
868 sal_uInt16
& rLine
, sal_uInt16
& rPos
) const
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
)
880 rPos
= GetItemPos( pWindow
->GetType(), nSet
);
881 rLine
= GetItemPos( nSet
);
887 bool SfxSplitWindow::GetWindowPos( const Point
& rTestPos
,
888 sal_uInt16
& rLine
, sal_uInt16
& rPos
) const
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
);
900 sal_uInt16 nSet
= GetSet ( nId
);
901 rPos
= GetItemPos( nId
, nSet
);
902 rLine
= GetItemPos( nSet
);
908 sal_uInt16
SfxSplitWindow::GetLineCount() const
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
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
937 Returns the total number of windows
940 sal_uInt16 nId
= GetItemId( nLine
);
941 return GetItemCount( nId
);
946 sal_uInt16
SfxSplitWindow::GetWindowCount() const
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)
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;
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
987 pEmptyWin
->aLastPos
= GetPointerPosPixel();
988 pEmptyWin
->aTimer
.Start();
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)
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
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 ) )
1017 pWorkWin
->ArrangeAutoHideWindows( this );
1021 pEmptyWin
->aLastPos
= GetPointerPosPixel();
1022 pEmptyWin
->aTimer
.Start();
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();
1046 // Extend with +/- a few pixels, otherwise it is too nervous
1049 aSize
.Width() += 2 * nPixel
;
1050 aSize
.Height() += 2 * nPixel
;
1053 Rectangle
aRect( aPos
, aSize
);
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() ) ) )
1077 SplitWindow
* SfxSplitWindow::GetSplitWindow()
1079 if ( !bPinned
|| !pEmptyWin
->bFadeIn
)
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
)
1103 if ( GetItemCount( 0 ) == 0 )
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 );
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
)
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
);
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
)
1157 if ( GetItemCount( 0 ) == 0 )
1160 pEmptyWin
->bFadeIn
= bOn
;
1163 pEmptyWin
->nState
|= 2;
1164 if ( IsFloatingMode() )
1166 // FloatingWindow is not visible, thus display it
1167 pWorkWin
->ArrangeAutoHideWindows( this );
1172 OSL_TRACE( "SfxSplitWindow::SetFadeIn_Impl - releasing empty Splitwindow" );
1173 pWorkWin
->ReleaseChild_Impl( *pEmptyWin
);
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();
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 );
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 );
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
1212 // It "floats", thus dock it again
1213 SetPinned_Impl( true );
1214 pWorkWin
->ArrangeChildren_Impl();
1219 SetPinned_Impl( false );
1220 pWorkWin
->ArrangeChildren_Impl();
1221 pWorkWin
->ArrangeAutoHideWindows( this );
1224 pWorkWin
->ShowChildren_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()
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
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() )
1270 // up window counter (then when n>nCount, the loop below is
1277 // Search for next window
1278 for ( sal_uInt16 nNext
=n
; nNext
<nCount
; nNext
++ )
1280 const SfxDock_Impl
& rD
= (*pDockArr
)[nNext
];
1283 rD
.pWin
->GrabFocus();
1290 // Search for previous window
1291 for ( sal_uInt16 nNext
=n
; nNext
--; )
1293 const SfxDock_Impl
& rD
= (*pDockArr
)[nNext
];
1296 rD
.pWin
->GrabFocus();
1305 void SfxSplitWindow::SetActiveWindow_Impl( SfxDockingWindow
* pWin
)
1308 pWorkWin
->SetActiveChild_Impl( this );
1312 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */