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 .
24 #include <unotools/viewoptions.hxx>
25 #include <rtl/ustrbuf.hxx>
26 #include <sal/log.hxx>
27 #include <tools/debug.hxx>
29 #include <vcl/event.hxx>
30 #include <vcl/menu.hxx>
31 #include <vcl/timer.hxx>
32 #include <vcl/svapp.hxx>
34 #include <splitwin.hxx>
35 #include <workwin.hxx>
36 #include <sfx2/dockwin.hxx>
42 using namespace ::com::sun::star::uno
;
46 constexpr OUStringLiteral USERITEM_NAME
= u
"UserItem";
49 // helper class to deactivate UpdateMode, if needed, for the life time of an instance
50 class DeactivateUpdateMode
53 explicit DeactivateUpdateMode( SfxSplitWindow
& rSplitWindow
)
54 : mrSplitWindow( rSplitWindow
)
55 , mbUpdateMode( rSplitWindow
.IsUpdateMode() )
59 mrSplitWindow
.SetUpdateMode( false );
63 ~DeactivateUpdateMode()
67 mrSplitWindow
.SetUpdateMode( true );
72 SfxSplitWindow
& mrSplitWindow
;
73 const bool mbUpdateMode
;
77 class SfxEmptySplitWin_Impl
: public SplitWindow
81 The SfxEmptySplitWin_Impldow is an empty SplitWindow, that replaces the
82 SfxSplitWindow AutoHide mode. It only serves as a placeholder to receive
83 mouse moves and if possible blend in the true SplitWindow display.
85 friend class SfxSplitWindow
;
87 VclPtr
<SfxSplitWindow
> pOwner
;
97 explicit SfxEmptySplitWin_Impl( SfxSplitWindow
*pParent
)
98 : SplitWindow( pParent
->GetParent(), WinBits( WB_BORDER
| WB_3DLOOK
) )
103 , bEndAutoHide( false )
104 , aTimer("sfx2 SfxEmptySplitWin_Impl aTimer")
107 aTimer
.SetInvokeHandler(
108 LINK(pOwner
, SfxSplitWindow
, TimerHdl
) );
109 aTimer
.SetTimeout( 200 );
110 SetAlign( pOwner
->GetAlign() );
112 ShowFadeInHideButton();
115 virtual ~SfxEmptySplitWin_Impl() override
117 virtual void dispose() override
121 SplitWindow::dispose();
124 virtual void FadeIn() override
;
128 void SfxEmptySplitWin_Impl::Actualize()
130 Size
aSize( pOwner
->GetSizePixel() );
131 switch ( pOwner
->GetAlign() )
133 case WindowAlign::Left
:
134 case WindowAlign::Right
:
135 aSize
.setWidth( GetFadeInSize() );
137 case WindowAlign::Top
:
138 case WindowAlign::Bottom
:
139 aSize
.setHeight( GetFadeInSize() );
143 SetSizePixel( aSize
);
146 void SfxEmptySplitWin_Impl::FadeIn()
149 bAutoHide
= IsFadeNoButtonMode();
150 pOwner
->SetFadeIn_Impl( true );
153 // Set Timer to close; the caller has to ensure themselves that the
154 // Window is not closed instantly (eg by setting the focus or a modal
156 aLastPos
= GetPointerPosPixel();
160 pOwner
->SaveConfig_Impl();
164 void SfxSplitWindow::MouseButtonDown( const MouseEvent
& rMEvt
)
166 if ( rMEvt
.GetClicks() != 2 )
167 SplitWindow::MouseButtonDown( rMEvt
);
170 SfxSplitWindow::SfxSplitWindow( vcl::Window
* pParent
, SfxChildAlignment eAl
,
171 SfxWorkWindow
*pW
, bool bWithButtons
)
175 A SfxSplitWindow brings the recursive structure of the SV-SplitWindows to
176 the outside by simulating a table-like structure with rows and columns
177 (maximum recursion depth 2). Furthermore, it ensures the persistence of
178 the arrangement of the SfxDockingWindows.
181 : SplitWindow ( pParent
, WB_BORDER
| WB_SIZEABLE
| WB_3DLOOK
| WB_HIDE
),
194 WindowAlign eTbxAlign
;
197 case SfxChildAlignment::LEFT
:
198 eTbxAlign
= WindowAlign::Left
;
200 case SfxChildAlignment::RIGHT
:
201 eTbxAlign
= WindowAlign::Right
;
203 case SfxChildAlignment::TOP
:
204 eTbxAlign
= WindowAlign::Top
;
206 case SfxChildAlignment::BOTTOM
:
207 eTbxAlign
= WindowAlign::Bottom
;
211 eTbxAlign
= WindowAlign::Top
; // some sort of default...
212 break; // -Wall lots not handled...
215 SetAlign (eTbxAlign
);
216 pEmptyWin
= VclPtr
<SfxEmptySplitWin_Impl
>::Create( this );
219 pEmptyWin
->bFadeIn
= true;
220 pEmptyWin
->nState
= 2;
225 // Read Configuration
226 const OUString aWindowId
{ "SplitWindow" + OUString::number(static_cast<sal_Int32
>(eTbxAlign
)) };
227 SvtViewOptions
aWinOpt( EViewType::Window
, aWindowId
);
229 Any aUserItem
= aWinOpt
.GetUserItem( USERITEM_NAME
);
231 if ( aUserItem
>>= aTemp
)
233 if ( aWinData
.startsWith("V") )
236 pEmptyWin
->nState
= static_cast<sal_uInt16
>(aWinData
.getToken( 1, ',', nIdx
).toInt32());
237 if ( pEmptyWin
->nState
& 2 )
238 pEmptyWin
->bFadeIn
= true;
239 bPinned
= true; // always assume pinned - floating mode not used anymore
241 const sal_Int32 nCount
{ aWinData
.getToken(0, ',', nIdx
).toInt32() };
242 for ( sal_Int32 n
=0; n
<nCount
; ++n
)
244 std::unique_ptr
<SfxDock_Impl
> pDock(new SfxDock_Impl
);
245 pDock
->pWin
= nullptr;
246 pDock
->bNewLine
= false;
248 pDock
->nType
= static_cast<sal_uInt16
>(aWinData
.getToken(0, ',', nIdx
).toInt32());
251 // could mean NewLine
252 pDock
->nType
= static_cast<sal_uInt16
>(aWinData
.getToken(0, ',', nIdx
).toInt32());
259 pDock
->bNewLine
= true;
262 maDockArr
.insert(maDockArr
.begin() + n
, std::move(pDock
));
269 pEmptyWin
->bFadeIn
= true;
270 pEmptyWin
->nState
= 2;
275 SfxSplitWindow::~SfxSplitWindow()
280 void SfxSplitWindow::dispose()
286 // Set pOwner to NULL, otherwise try to delete pEmptyWin once more. The
287 // window that is just being docked is always deleted from the outside.
288 pEmptyWin
->pOwner
= nullptr;
290 pEmptyWin
.disposeAndClear();
294 SplitWindow::dispose();
297 void SfxSplitWindow::SaveConfig_Impl()
299 // Save configuration
300 OUStringBuffer aWinData
;
301 aWinData
.append('V');
302 aWinData
.append(static_cast<sal_Int32
>(VERSION
));
303 aWinData
.append(',');
304 aWinData
.append(static_cast<sal_Int32
>(pEmptyWin
->nState
));
305 aWinData
.append(',');
307 sal_uInt16 nCount
= 0;
308 for ( auto const & rDock
: maDockArr
)
310 if ( rDock
->bHide
|| rDock
->pWin
)
314 aWinData
.append(static_cast<sal_Int32
>(nCount
));
316 for ( auto const & rDock
: maDockArr
)
318 if ( !rDock
->bHide
&& !rDock
->pWin
)
320 if ( rDock
->bNewLine
)
321 aWinData
.append(",0");
322 aWinData
.append(',');
323 aWinData
.append(static_cast<sal_Int32
>(rDock
->nType
));
326 const OUString aWindowId
{ "SplitWindow" + OUString::number(static_cast<sal_Int32
>(GetAlign())) };
327 SvtViewOptions
aWinOpt( EViewType::Window
, aWindowId
);
328 aWinOpt
.SetUserItem( USERITEM_NAME
, makeAny( aWinData
.makeStringAndClear() ) );
332 void SfxSplitWindow::StartSplit()
334 tools::Long nSize
= 0;
335 Size aSize
= GetSizePixel();
339 pEmptyWin
->bFadeIn
= true;
340 pEmptyWin
->bSplit
= true;
343 tools::Rectangle aRect
= pWorkWin
->GetFreeArea( !bPinned
);
344 switch ( GetAlign() )
346 case WindowAlign::Left
:
347 case WindowAlign::Right
:
348 nSize
= aSize
.Width() + aRect
.GetWidth();
350 case WindowAlign::Top
:
351 case WindowAlign::Bottom
:
352 nSize
= aSize
.Height() + aRect
.GetHeight();
356 SetMaxSizePixel( nSize
);
360 void SfxSplitWindow::SplitResize()
364 pWorkWin
->ArrangeChildren_Impl();
365 pWorkWin
->ShowChildren_Impl();
368 pWorkWin
->ArrangeAutoHideWindows( this );
372 void SfxSplitWindow::Split()
375 pEmptyWin
->bSplit
= false;
377 SplitWindow::Split();
379 std::vector
< std::pair
< sal_uInt16
, tools::Long
> > aNewOrgSizes
;
381 sal_uInt16 nCount
= maDockArr
.size();
382 for ( sal_uInt16 n
=0; n
<nCount
; n
++ )
384 const SfxDock_Impl
& rD
= *maDockArr
[n
];
387 const sal_uInt16 nId
= rD
.nType
;
388 const tools::Long nSize
= GetItemSize( nId
, SplitWindowItemFlags::Fixed
);
389 const tools::Long nSetSize
= GetItemSize( GetSet( nId
) );
392 if ( IsHorizontal() )
394 aSize
.setWidth( nSize
);
395 aSize
.setHeight( nSetSize
);
399 aSize
.setWidth( nSetSize
);
400 aSize
.setHeight( nSize
);
403 rD
.pWin
->SetItemSize_Impl( aSize
);
405 aNewOrgSizes
.emplace_back( nId
, nSize
);
409 // workaround insufficiency of <SplitWindow> regarding dock layouting:
410 // apply FIXED item size as 'original' item size to improve layouting of undock-dock-cycle of a window
412 DeactivateUpdateMode
aDeactivateUpdateMode( *this );
413 for (const std::pair
< sal_uInt16
, tools::Long
> & rNewOrgSize
: aNewOrgSizes
)
415 SetItemSize( rNewOrgSize
.first
, rNewOrgSize
.second
);
423 void SfxSplitWindow::InsertWindow( SfxDockingWindow
* pDockWin
, const Size
& rSize
)
426 To insert SfxDockingWindows just pass no position. The SfxSplitWindow
427 searches the last marked one to the passed SfxDockingWindow or appends a
431 short nLine
= -1; // so that the first window cab set nline to 0
434 bool bNewLine
= true;
435 bool bSaveConfig
= false;
436 SfxDock_Impl
*pFoundDock
=nullptr;
437 sal_uInt16 nCount
= maDockArr
.size();
438 for ( sal_uInt16 n
=0; n
<nCount
; n
++ )
440 SfxDock_Impl
& rDock
= *maDockArr
[n
];
441 if ( rDock
.bNewLine
)
443 // The window opens a new line
445 // But after the just inserted window
455 // Does there exist a window now at this position
456 if ( bNewLine
&& !pFoundDock
)
458 // Not known until now in which real line it is located
459 GetWindowPos( rDock
.pWin
, nL
, nPos
);
460 nLine
= static_cast<short>(nL
);
465 // The window is located before the inserted one
475 if ( rDock
.nType
== pDockWin
->GetType() )
477 DBG_ASSERT( !pFoundDock
&& !rDock
.pWin
, "Window already exists!");
483 // A new line has been created but no window was found there;
484 // continue searching for a window in this line in-order to set
485 // bNewLine correctly. While doing so nline or nPos are not
494 // Not found, insert at end
495 pFoundDock
= new SfxDock_Impl
;
496 pFoundDock
->bHide
= true;
497 maDockArr
.push_back( std::unique_ptr
<SfxDock_Impl
>(pFoundDock
) );
498 pFoundDock
->nType
= pDockWin
->GetType();
502 pFoundDock
->bNewLine
= bNewLine
;
506 pFoundDock
->pWin
= pDockWin
;
507 pFoundDock
->bHide
= false;
508 InsertWindow_Impl( pFoundDock
, rSize
, nLine
, nPos
, bNewLine
);
514 void SfxSplitWindow::ReleaseWindow_Impl(SfxDockingWindow
const *pDockWin
, bool bSave
)
516 // The docking window is no longer stored in the internal data.
517 sal_uInt16 nCount
= maDockArr
.size();
518 for ( sal_uInt16 n
=0; n
<nCount
; n
++ )
520 const SfxDock_Impl
& rDock
= *maDockArr
[n
];
521 if ( rDock
.nType
== pDockWin
->GetType() )
523 if ( rDock
.bNewLine
&& n
<nCount
-1 )
524 maDockArr
[n
+1]->bNewLine
= true;
526 // Window has a position, this we forget
527 maDockArr
.erase(maDockArr
.begin() + n
);
537 void SfxSplitWindow::MoveWindow( SfxDockingWindow
* pDockWin
, const Size
& rSize
,
538 sal_uInt16 nLine
, sal_uInt16 nPos
, bool bNewLine
)
542 The docking window is moved within the SplitWindows.
547 GetWindowPos( pDockWin
, nL
, nP
);
549 if ( nLine
> nL
&& GetItemCount( GetItemId( nL
) ) == 1 )
551 // If the last window is removed from its line, then everything slips
552 // one line to the front!
555 RemoveWindow( pDockWin
);
556 InsertWindow( pDockWin
, rSize
, nLine
, nPos
, bNewLine
);
560 void SfxSplitWindow::InsertWindow( SfxDockingWindow
* pDockWin
, const Size
& rSize
,
561 sal_uInt16 nLine
, sal_uInt16 nPos
, bool bNewLine
)
565 The DockingWindow that is pushed on this SplitWindow and shall hold the
566 given position and size.
569 ReleaseWindow_Impl( pDockWin
, false );
570 SfxDock_Impl
*pDock
= new SfxDock_Impl
;
571 pDock
->bHide
= false;
572 pDock
->nType
= pDockWin
->GetType();
573 pDock
->bNewLine
= bNewLine
;
574 pDock
->pWin
= pDockWin
;
576 DBG_ASSERT( nPos
==0 || !bNewLine
, "Wrong Parameter!");
580 // The window must be inserted before the first window so that it has the
581 // same or a greater position than pDockWin.
582 sal_uInt16 nCount
= maDockArr
.size();
583 sal_uInt16
nLastWindowIdx(0);
585 // If no window is found, a first window is inserted
586 sal_uInt16 nInsertPos
= 0;
587 for ( sal_uInt16 n
=0; n
<nCount
; n
++ )
589 SfxDock_Impl
& rD
= *maDockArr
[n
];
593 // A docked window has been found. If no suitable window behind
594 // the desired insertion point s found, then insertion is done at
598 sal_uInt16 nL
=0, nP
=0;
599 GetWindowPos( rD
.pWin
, nL
, nP
);
601 if ( (nL
== nLine
&& nP
== nPos
) || nL
> nLine
)
603 DBG_ASSERT( nL
== nLine
|| bNewLine
|| nPos
> 0, "Wrong Parameter!" );
604 if ( nL
== nLine
&& nPos
== 0 && !bNewLine
)
606 DBG_ASSERT(rD
.bNewLine
, "No new line?");
608 // The position is pushed to nPos==0
610 pDock
->bNewLine
= true;
613 nInsertPos
= n
!= 0 ? nLastWindowIdx
+ 1 : 0; // ignore all non-windows after the last window
618 if (nCount
!= 0 && nInsertPos
== nCount
&& nLastWindowIdx
!= nCount
- 1)
620 nInsertPos
= nLastWindowIdx
+ 1; // ignore all non-windows after the last window
623 maDockArr
.insert(maDockArr
.begin() + nInsertPos
, std::unique_ptr
<SfxDock_Impl
>(pDock
));
624 InsertWindow_Impl( pDock
, rSize
, nLine
, nPos
, bNewLine
);
629 void SfxSplitWindow::InsertWindow_Impl( SfxDock_Impl
const * pDock
,
631 sal_uInt16 nLine
, sal_uInt16 nPos
, bool bNewLine
)
635 Adds a DockingWindow, and causes the recalculation of the size of
640 SfxDockingWindow
* pDockWin
= pDock
->pWin
;
642 SplitWindowItemFlags nItemBits
= SplitWindowItemFlags::NONE
;
644 tools::Long nWinSize
, nSetSize
;
645 if ( IsHorizontal() )
647 nWinSize
= rSize
.Width();
648 nSetSize
= rSize
.Height();
652 nSetSize
= rSize
.Width();
653 nWinSize
= rSize
.Height();
656 std::unique_ptr
<DeactivateUpdateMode
> pDeactivateUpdateMode(new DeactivateUpdateMode( *this ));
658 if ( bNewLine
|| nLine
== GetItemCount() )
660 // An existing row should not be inserted, instead a new one
664 for ( sal_uInt16 n
=0; n
<GetItemCount(); n
++ )
666 if ( GetItemId(n
) >= nId
)
667 nId
= GetItemId(n
)+1;
670 // Create a new nLine:th line
671 SplitWindowItemFlags nBits
= nItemBits
;
672 if ( GetAlign() == WindowAlign::Top
|| GetAlign() == WindowAlign::Bottom
)
673 nBits
|= SplitWindowItemFlags::ColSet
;
674 InsertItem( nId
, nSetSize
, nLine
, 0, nBits
);
677 // Insert the window at line with the position nline. ItemWindowSize set to
678 // "percentage" share since the SV then does the re-sizing as expected,
679 // "pixel" actually only makes sense if also items with percentage or
680 // relative sizes are present.
681 nItemBits
|= SplitWindowItemFlags::PercentSize
;
682 sal_uInt16 nSet
= GetItemId( nLine
);
683 InsertItem( pDockWin
->GetType(), pDockWin
, nWinSize
, nPos
, nSet
, nItemBits
);
685 // SplitWindows are once created in SFX and when inserting the first
686 // DockingWindows is made visible.
687 if ( GetItemCount() == 1 && GetItemCount( 1 ) == 1 )
689 // The Rearranging in WorkWindow and a Show() on the SplitWindow is
690 // caused by SfxDockingwindow (->SfxWorkWindow::ConfigChild_Impl)
691 if ( !bPinned
&& !IsFloatingMode() )
694 bool bFadeIn
= ( pEmptyWin
->nState
& 2 ) != 0;
695 pEmptyWin
->bFadeIn
= false;
696 SetPinned_Impl( false );
697 pEmptyWin
->Actualize();
698 SAL_INFO("sfx", "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" );
699 pWorkWin
->RegisterChild_Impl( *GetSplitWindow(), eAlign
)->nVisible
= SfxChildVisibility::VISIBLE
;
700 // tdf#113539 FadeIn will call ArrangeChildren_Impl() for us, and avoiding extra calls to that
701 // can make a different to load times because it avoids extra accessibility calcs
705 pWorkWin
->ArrangeChildren_Impl();
709 bool bFadeIn
= ( pEmptyWin
->nState
& 2 ) != 0;
710 pEmptyWin
->bFadeIn
= false;
711 pEmptyWin
->Actualize();
712 if ( !bPinned
|| !pEmptyWin
->bFadeIn
)
714 SAL_INFO("sfx", "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" );
718 SAL_INFO("sfx", "SfxSplitWindow::InsertWindow_Impl - registering real Splitwindow" );
720 pWorkWin
->RegisterChild_Impl( *GetSplitWindow(), eAlign
)->nVisible
= SfxChildVisibility::VISIBLE
;
721 // tdf#113539 FadeIn will call ArrangeChildren_Impl() for us, and avoiding extra calls to that
722 // can make a different to load times because it avoids extra accessibility calcs
726 pWorkWin
->ArrangeChildren_Impl();
729 pWorkWin
->ShowChildren_Impl();
732 pDeactivateUpdateMode
.reset();
734 // workaround insufficiency of <SplitWindow> regarding dock layouting:
735 // apply FIXED item size as 'original' item size to improve layouting of undock-dock-cycle of a window
737 std::vector
< std::pair
< sal_uInt16
, tools::Long
> > aNewOrgSizes
;
738 // get FIXED item sizes
739 sal_uInt16 nCount
= maDockArr
.size();
740 for ( sal_uInt16 n
=0; n
<nCount
; ++n
)
742 const SfxDock_Impl
& rD
= *maDockArr
[n
];
745 const sal_uInt16 nId
= rD
.nType
;
746 const tools::Long nSize
= GetItemSize( nId
, SplitWindowItemFlags::Fixed
);
747 aNewOrgSizes
.emplace_back( nId
, nSize
);
750 // apply new item sizes
751 DeactivateUpdateMode
aDeactivateUpdateMode( *this );
752 for (const std::pair
< sal_uInt16
, tools::Long
> & rNewOrgSize
: aNewOrgSizes
)
754 SetItemSize( rNewOrgSize
.first
, rNewOrgSize
.second
);
760 void SfxSplitWindow::RemoveWindow( SfxDockingWindow
const * pDockWin
, bool bHide
)
764 Removes a DockingWindow. If it was the last one, then the SplitWindow is
768 sal_uInt16 nSet
= GetSet( pDockWin
->GetType() );
770 // SplitWindows are once created in SFX and is made invisible after
771 // removing the last DockingWindows.
772 if ( GetItemCount( nSet
) == 1 && GetItemCount() == 1 )
774 // The Rearranging in WorkWindow is caused by SfxDockingwindow
776 pEmptyWin
->aTimer
.Stop();
777 sal_uInt16 nRealState
= pEmptyWin
->nState
;
781 if ( !bPinned
|| !pEmptyWin
->bFadeIn
)
783 SAL_INFO("sfx", "SfxSplitWindow::RemoveWindow - releasing empty Splitwindow" );
787 SAL_INFO("sfx", "SfxSplitWindow::RemoveWindow - releasing real Splitwindow" );
790 pWorkWin
->ReleaseChild_Impl( *GetSplitWindow() );
791 pEmptyWin
->nState
= nRealState
;
792 pWorkWin
->ArrangeAutoHideWindows( this );
795 sal_uInt16 nCount
= maDockArr
.size();
796 for ( sal_uInt16 n
=0; n
<nCount
; n
++ )
798 SfxDock_Impl
& rDock
= *maDockArr
[n
];
799 if ( rDock
.nType
== pDockWin
->GetType() )
801 rDock
.pWin
= nullptr;
807 // Remove Windows, and if it was the last of the line, then also remove
808 // the line (line = itemset)
809 DeactivateUpdateMode
aDeactivateUpdateMode( *this );
811 RemoveItem( pDockWin
->GetType() );
813 if ( nSet
&& !GetItemCount( nSet
) )
818 bool SfxSplitWindow::GetWindowPos( const SfxDockingWindow
* pWindow
,
819 sal_uInt16
& rLine
, sal_uInt16
& rPos
) const
822 Returns the ID of the item sets and items for the DockingWindow in
823 the position passed on the old row / column-name.
827 sal_uInt16 nSet
= GetSet ( pWindow
->GetType() );
828 if ( nSet
== SPLITWINDOW_ITEM_NOTFOUND
)
831 rPos
= GetItemPos( pWindow
->GetType(), nSet
);
832 rLine
= GetItemPos( nSet
);
837 bool SfxSplitWindow::GetWindowPos( const Point
& rTestPos
,
838 sal_uInt16
& rLine
, sal_uInt16
& rPos
) const
841 Returns the ID of the item sets and items for the DockingWindow in
842 the position passed on the old row / column-name.
846 sal_uInt16 nId
= GetItemId( rTestPos
);
850 sal_uInt16 nSet
= GetSet ( nId
);
851 rPos
= GetItemPos( nId
, nSet
);
852 rLine
= GetItemPos( nSet
);
857 sal_uInt16
SfxSplitWindow::GetLineCount() const
861 Returns the number of rows = number of sub-itemsets in the root set.
864 return GetItemCount();
868 tools::Long
SfxSplitWindow::GetLineSize( sal_uInt16 nLine
) const
872 Returns the Row Height of nline itemset.
875 sal_uInt16 nId
= GetItemId( nLine
);
876 return GetItemSize( nId
);
880 sal_uInt16
SfxSplitWindow::GetWindowCount( sal_uInt16 nLine
) const
884 Returns the total number of windows
887 sal_uInt16 nId
= GetItemId( nLine
);
888 return GetItemCount( nId
);
892 sal_uInt16
SfxSplitWindow::GetWindowCount() const
896 Returns the total number of windows
899 return GetItemCount();
903 IMPL_LINK( SfxSplitWindow
, TimerHdl
, Timer
*, pTimer
, void)
908 if ( CursorIsOverRect() || !pTimer
)
910 // If the cursor is within the window, display the SplitWindow and set
911 // up the timer for close
912 pEmptyWin
->bAutoHide
= true;
916 pEmptyWin
->aLastPos
= GetPointerPosPixel();
917 pEmptyWin
->aTimer
.Start();
919 else if ( pEmptyWin
->bAutoHide
)
921 if ( GetPointerPosPixel() != pEmptyWin
->aLastPos
)
923 // The mouse has moved within the running time of the timer, thus
925 pEmptyWin
->aLastPos
= GetPointerPosPixel();
926 pEmptyWin
->aTimer
.Start();
930 // Especially for TF_AUTOSHOW_ON_MOUSEMOVE :
931 // If the window is not visible, there is nothing to do
932 // (user has simply moved the mouse over pEmptyWin)
935 pEmptyWin
->bEndAutoHide
= false;
936 if ( !Application::IsInModalMode() &&
937 !PopupMenu::IsInExecute() &&
938 !pEmptyWin
->bSplit
&& !HasChildPathFocus( true ) )
940 // While a modal dialog or a popup menu is open or while the
941 // Splitting is done, in any case, do not close. Even as long
942 // as one of the Children has the focus, the window remains
944 pEmptyWin
->bEndAutoHide
= true;
947 if ( pEmptyWin
->bEndAutoHide
)
949 // As far as I am concerned this can be the end of AutoShow
950 // But maybe some other SfxSplitWindow will remain open,
951 // then all others remain open too.
952 if ( !pWorkWin
->IsAutoHideMode( this ) )
955 pWorkWin
->ArrangeAutoHideWindows( this );
959 pEmptyWin
->aLastPos
= GetPointerPosPixel();
960 pEmptyWin
->aTimer
.Start();
965 pEmptyWin
->aLastPos
= GetPointerPosPixel();
966 pEmptyWin
->aTimer
.Start();
973 bool SfxSplitWindow::CursorIsOverRect() const
975 bool bVisible
= IsVisible();
977 // Also, take the collapsed SplitWindow into account
978 Point aPos
= pEmptyWin
->GetParent()->OutputToScreenPixel( pEmptyWin
->GetPosPixel() );
979 Size aSize
= pEmptyWin
->GetSizePixel();
981 tools::Rectangle
aRect( aPos
, aSize
);
985 Point aVisPos
= GetPosPixel();
986 Size aVisSize
= GetSizePixel();
988 // Extend with +/- a few pixels, otherwise it is too nervous
989 aVisPos
.AdjustX( -(nPixel
) );
990 aVisPos
.AdjustY( -(nPixel
) );
991 aVisSize
.AdjustWidth(2 * nPixel
);
992 aVisSize
.AdjustHeight(2 * nPixel
);
994 tools::Rectangle
aVisRect( aVisPos
, aVisSize
);
995 aRect
= aRect
.GetUnion( aVisRect
);
998 return aRect
.Contains( OutputToScreenPixel( static_cast<vcl::Window
*>(const_cast<SfxSplitWindow
*>(this))->GetPointerPosPixel() ) );
1002 SplitWindow
* SfxSplitWindow::GetSplitWindow()
1004 if ( !bPinned
|| !pEmptyWin
->bFadeIn
)
1010 bool SfxSplitWindow::IsFadeIn() const
1012 return pEmptyWin
->bFadeIn
;
1015 bool SfxSplitWindow::IsAutoHide( bool bSelf
) const
1017 return bSelf
? pEmptyWin
->bAutoHide
&& !pEmptyWin
->bEndAutoHide
: pEmptyWin
->bAutoHide
;
1021 void SfxSplitWindow::SetPinned_Impl( bool bOn
)
1023 if ( bPinned
== bOn
)
1027 if ( GetItemCount() == 0 )
1032 pEmptyWin
->nState
|= 1;
1033 if ( pEmptyWin
->bFadeIn
)
1035 // Unregister replacement windows
1036 SAL_INFO("sfx", "SfxSplitWindow::SetPinned_Impl - releasing real Splitwindow" );
1037 pWorkWin
->ReleaseChild_Impl( *this );
1039 pEmptyWin
->Actualize();
1040 SAL_INFO("sfx", "SfxSplitWindow::SetPinned_Impl - registering empty Splitwindow" );
1041 pWorkWin
->RegisterChild_Impl( *pEmptyWin
, eAlign
)->nVisible
= SfxChildVisibility::VISIBLE
;
1044 Point
aPos( GetPosPixel() );
1045 aPos
= GetParent()->OutputToScreenPixel( aPos
);
1046 SetFloatingPos( aPos
);
1047 SetFloatingMode( true );
1048 GetFloatingWindow()->SetOutputSizePixel( GetOutputSizePixel() );
1050 if ( pEmptyWin
->bFadeIn
)
1055 pEmptyWin
->nState
&= ~1;
1056 SetOutputSizePixel( GetFloatingWindow()->GetOutputSizePixel() );
1057 SetFloatingMode(false);
1059 if ( pEmptyWin
->bFadeIn
)
1061 // Unregister replacement windows
1062 SAL_INFO("sfx", "SfxSplitWindow::SetPinned_Impl - releasing empty Splitwindow" );
1063 pWorkWin
->ReleaseChild_Impl( *pEmptyWin
);
1065 SAL_INFO("sfx", "SfxSplitWindow::SetPinned_Impl - registering real Splitwindow" );
1066 pWorkWin
->RegisterChild_Impl( *this, eAlign
)->nVisible
= SfxChildVisibility::VISIBLE
;
1071 void SfxSplitWindow::SetFadeIn_Impl( bool bOn
)
1073 if ( bOn
== pEmptyWin
->bFadeIn
)
1076 if ( GetItemCount() == 0 )
1079 pEmptyWin
->bFadeIn
= bOn
;
1082 pEmptyWin
->nState
|= 2;
1083 if ( IsFloatingMode() )
1085 // FloatingWindow is not visible, thus display it
1086 pWorkWin
->ArrangeAutoHideWindows( this );
1091 SAL_INFO("sfx", "SfxSplitWindow::SetFadeIn_Impl - releasing empty Splitwindow" );
1092 pWorkWin
->ReleaseChild_Impl( *pEmptyWin
);
1094 SAL_INFO("sfx", "SfxSplitWindow::SetFadeIn_Impl - registering real Splitwindow" );
1095 pWorkWin
->RegisterChild_Impl( *this, eAlign
)->nVisible
= SfxChildVisibility::VISIBLE
;
1096 pWorkWin
->ArrangeChildren_Impl();
1097 pWorkWin
->ShowChildren_Impl();
1102 pEmptyWin
->bAutoHide
= false;
1103 pEmptyWin
->nState
&= ~2;
1104 if ( !IsFloatingMode() )
1106 // The window is not "floating", should be hidden
1107 SAL_INFO("sfx", "SfxSplitWindow::SetFadeIn_Impl - releasing real Splitwindow" );
1108 pWorkWin
->ReleaseChild_Impl( *this );
1110 pEmptyWin
->Actualize();
1111 SAL_INFO("sfx", "SfxSplitWindow::SetFadeIn_Impl - registering empty Splitwindow" );
1112 pWorkWin
->RegisterChild_Impl( *pEmptyWin
, eAlign
)->nVisible
= SfxChildVisibility::VISIBLE
;
1113 pWorkWin
->ArrangeChildren_Impl();
1114 pWorkWin
->ShowChildren_Impl();
1115 pWorkWin
->ArrangeAutoHideWindows( this );
1120 pWorkWin
->ArrangeAutoHideWindows( this );
1125 void SfxSplitWindow::FadeOut_Impl()
1127 if ( pEmptyWin
->aTimer
.IsActive() )
1129 pEmptyWin
->bAutoHide
= false;
1130 pEmptyWin
->aTimer
.Stop();
1133 SetFadeIn_Impl( false );
1136 void SfxSplitWindow::FadeOut()
1142 void SfxSplitWindow::FadeIn()
1144 SetFadeIn_Impl( true );
1147 void SfxSplitWindow::SetActiveWindow_Impl( SfxDockingWindow
* pWin
)
1150 pWorkWin
->SetActiveChild_Impl( this );
1154 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */