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/dialoghelper.hxx>
30 #include <vcl/event.hxx>
31 #include <vcl/timer.hxx>
32 #include <vcl/svapp.hxx>
34 #include <splitwin.hxx>
35 #include <workwin.hxx>
36 #include <sfx2/dockwin.hxx>
37 #include <o3tl/string_view.hxx>
44 using namespace ::com::sun::star::uno
;
48 constexpr OUString USERITEM_NAME
= u
"UserItem"_ustr
;
51 // helper class to deactivate UpdateMode, if needed, for the life time of an instance
52 class DeactivateUpdateMode
55 explicit DeactivateUpdateMode( SfxSplitWindow
& rSplitWindow
)
56 : mrSplitWindow( rSplitWindow
)
57 , mbUpdateMode( rSplitWindow
.IsUpdateMode() )
61 mrSplitWindow
.SetUpdateMode( false );
65 ~DeactivateUpdateMode()
69 mrSplitWindow
.SetUpdateMode( true );
74 SfxSplitWindow
& mrSplitWindow
;
75 const bool mbUpdateMode
;
79 class SfxEmptySplitWin_Impl
: public SplitWindow
83 The SfxEmptySplitWin_Impldow is an empty SplitWindow, that replaces the
84 SfxSplitWindow AutoHide mode. It only serves as a placeholder to receive
85 mouse moves and if possible blend in the true SplitWindow display.
87 friend class SfxSplitWindow
;
89 VclPtr
<SfxSplitWindow
> pOwner
;
99 explicit SfxEmptySplitWin_Impl( SfxSplitWindow
*pParent
)
100 : SplitWindow( pParent
->GetParent(), WinBits( WB_BORDER
| WB_3DLOOK
) )
105 , bEndAutoHide( false )
106 , aTimer("sfx2 SfxEmptySplitWin_Impl aTimer")
109 aTimer
.SetInvokeHandler(
110 LINK(pOwner
, SfxSplitWindow
, TimerHdl
) );
111 aTimer
.SetTimeout( 200 );
112 SetAlign( pOwner
->GetAlign() );
114 ShowFadeInHideButton();
117 virtual ~SfxEmptySplitWin_Impl() override
119 virtual void dispose() override
123 SplitWindow::dispose();
126 virtual void FadeIn() override
;
130 void SfxEmptySplitWin_Impl::Actualize()
132 Size
aSize( pOwner
->GetSizePixel() );
133 switch ( pOwner
->GetAlign() )
135 case WindowAlign::Left
:
136 case WindowAlign::Right
:
137 aSize
.setWidth( GetFadeInSize() );
139 case WindowAlign::Top
:
140 case WindowAlign::Bottom
:
141 aSize
.setHeight( GetFadeInSize() );
145 SetSizePixel( aSize
);
148 void SfxEmptySplitWin_Impl::FadeIn()
151 bAutoHide
= IsFadeNoButtonMode();
152 pOwner
->SetFadeIn_Impl( true );
155 // Set Timer to close; the caller has to ensure themselves that the
156 // Window is not closed instantly (eg by setting the focus or a modal
158 aLastPos
= GetPointerPosPixel();
162 pOwner
->SaveConfig_Impl();
166 void SfxSplitWindow::MouseButtonDown( const MouseEvent
& rMEvt
)
168 if ( rMEvt
.GetClicks() != 2 )
169 SplitWindow::MouseButtonDown( rMEvt
);
172 SfxSplitWindow::SfxSplitWindow( vcl::Window
* pParent
, SfxChildAlignment eAl
,
173 SfxWorkWindow
*pW
, bool bWithButtons
)
177 A SfxSplitWindow brings the recursive structure of the SV-SplitWindows to
178 the outside by simulating a table-like structure with rows and columns
179 (maximum recursion depth 2). Furthermore, it ensures the persistence of
180 the arrangement of the SfxDockingWindows.
183 : SplitWindow ( pParent
, WB_BORDER
| WB_SIZEABLE
| WB_3DLOOK
| WB_HIDE
),
196 WindowAlign eTbxAlign
;
199 case SfxChildAlignment::LEFT
:
200 eTbxAlign
= WindowAlign::Left
;
202 case SfxChildAlignment::RIGHT
:
203 eTbxAlign
= WindowAlign::Right
;
205 case SfxChildAlignment::TOP
:
206 eTbxAlign
= WindowAlign::Top
;
208 case SfxChildAlignment::BOTTOM
:
209 eTbxAlign
= WindowAlign::Bottom
;
213 eTbxAlign
= WindowAlign::Top
; // some sort of default...
214 break; // -Wall lots not handled...
217 SetAlign (eTbxAlign
);
218 pEmptyWin
= VclPtr
<SfxEmptySplitWin_Impl
>::Create( this );
221 pEmptyWin
->bFadeIn
= true;
222 pEmptyWin
->nState
= 2;
227 // Read Configuration
228 const OUString aWindowId
{ "SplitWindow" + OUString::number(static_cast<sal_Int32
>(eTbxAlign
)) };
229 SvtViewOptions
aWinOpt( EViewType::Window
, aWindowId
);
231 Any aUserItem
= aWinOpt
.GetUserItem( USERITEM_NAME
);
233 if ( aUserItem
>>= aTemp
)
235 if ( aWinData
.startsWith("V") )
238 pEmptyWin
->nState
= static_cast<sal_uInt16
>(o3tl::toInt32(o3tl::getToken(aWinData
, 1, ',', nIdx
)));
239 if ( pEmptyWin
->nState
& 2 )
240 pEmptyWin
->bFadeIn
= true;
241 bPinned
= true; // always assume pinned - floating mode not used anymore
243 const sal_Int32 nCount
{ o3tl::toInt32(o3tl::getToken(aWinData
, 0, ',', nIdx
)) };
244 for ( sal_Int32 n
=0; n
<nCount
; ++n
)
246 std::unique_ptr
<SfxDock_Impl
> pDock(new SfxDock_Impl
);
247 pDock
->pWin
= nullptr;
248 pDock
->bNewLine
= false;
250 pDock
->nType
= static_cast<sal_uInt16
>(o3tl::toInt32(o3tl::getToken(aWinData
, 0, ',', nIdx
)));
253 // could mean NewLine
254 pDock
->nType
= static_cast<sal_uInt16
>(o3tl::toInt32(o3tl::getToken(aWinData
, 0, ',', nIdx
)));
261 pDock
->bNewLine
= true;
264 maDockArr
.insert(maDockArr
.begin() + n
, std::move(pDock
));
271 pEmptyWin
->bFadeIn
= true;
272 pEmptyWin
->nState
= 2;
277 SfxSplitWindow::~SfxSplitWindow()
282 void SfxSplitWindow::dispose()
288 // Set pOwner to NULL, otherwise try to delete pEmptyWin once more. The
289 // window that is just being docked is always deleted from the outside.
290 pEmptyWin
->pOwner
= nullptr;
292 pEmptyWin
.disposeAndClear();
296 SplitWindow::dispose();
299 void SfxSplitWindow::SaveConfig_Impl()
301 // Save configuration
302 OUStringBuffer aWinData
=
304 + OUString::number(static_cast<sal_Int32
>(VERSION
))
306 + OUString::number(static_cast<sal_Int32
>(pEmptyWin
->nState
))
309 sal_uInt16 nCount
= 0;
310 for ( auto const & rDock
: maDockArr
)
312 if ( rDock
->bHide
|| rDock
->pWin
)
316 aWinData
.append(static_cast<sal_Int32
>(nCount
));
318 for ( auto const & rDock
: maDockArr
)
320 if ( !rDock
->bHide
&& !rDock
->pWin
)
322 if ( rDock
->bNewLine
)
323 aWinData
.append(",0");
324 aWinData
.append("," + OUString::number(static_cast<sal_Int32
>(rDock
->nType
)));
327 const OUString aWindowId
{ "SplitWindow" + OUString::number(static_cast<sal_Int32
>(GetAlign())) };
328 SvtViewOptions
aWinOpt( EViewType::Window
, aWindowId
);
329 aWinOpt
.SetUserItem( USERITEM_NAME
, Any( aWinData
.makeStringAndClear() ) );
333 void SfxSplitWindow::StartSplit()
335 tools::Long nSize
= 0;
336 Size aSize
= GetSizePixel();
340 pEmptyWin
->bFadeIn
= true;
341 pEmptyWin
->bSplit
= true;
344 tools::Rectangle aRect
= pWorkWin
->GetFreeArea( !bPinned
);
345 switch ( GetAlign() )
347 case WindowAlign::Left
:
348 case WindowAlign::Right
:
349 nSize
= aSize
.Width() + aRect
.GetWidth();
351 case WindowAlign::Top
:
352 case WindowAlign::Bottom
:
353 nSize
= aSize
.Height() + aRect
.GetHeight();
357 SetMaxSizePixel( nSize
);
361 void SfxSplitWindow::SplitResize()
365 pWorkWin
->ArrangeChildren_Impl();
366 pWorkWin
->ShowChildren_Impl();
369 pWorkWin
->ArrangeAutoHideWindows( this );
373 void SfxSplitWindow::Split()
376 pEmptyWin
->bSplit
= false;
378 SplitWindow::Split();
380 std::vector
< std::pair
< sal_uInt16
, tools::Long
> > aNewOrgSizes
;
382 sal_uInt16 nCount
= maDockArr
.size();
383 for ( sal_uInt16 n
=0; n
<nCount
; n
++ )
385 const SfxDock_Impl
& rD
= *maDockArr
[n
];
388 const sal_uInt16 nId
= rD
.nType
;
389 const tools::Long nSize
= GetItemSize( nId
, SplitWindowItemFlags::Fixed
);
390 const tools::Long nSetSize
= GetItemSize( GetSet( nId
) );
393 if ( IsHorizontal() )
395 aSize
.setWidth( nSize
);
396 aSize
.setHeight( nSetSize
);
400 aSize
.setWidth( nSetSize
);
401 aSize
.setHeight( nSize
);
404 rD
.pWin
->SetItemSize_Impl( aSize
);
406 aNewOrgSizes
.emplace_back( nId
, nSize
);
410 // workaround insufficiency of <SplitWindow> regarding dock layouting:
411 // apply FIXED item size as 'original' item size to improve layouting of undock-dock-cycle of a window
413 DeactivateUpdateMode
aDeactivateUpdateMode( *this );
414 for (const std::pair
< sal_uInt16
, tools::Long
> & rNewOrgSize
: aNewOrgSizes
)
416 SetItemSize( rNewOrgSize
.first
, rNewOrgSize
.second
);
424 void SfxSplitWindow::InsertWindow( SfxDockingWindow
* pDockWin
, const Size
& rSize
)
427 To insert SfxDockingWindows just pass no position. The SfxSplitWindow
428 searches the last marked one to the passed SfxDockingWindow or appends a
432 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
460 [[maybe_unused
]] auto const ok
= GetWindowPos( rDock
.pWin
, nL
, nPos
);
462 nLine
= static_cast<short>(nL
);
467 // The window is located before the inserted one
477 if ( rDock
.nType
== pDockWin
->GetType() )
479 DBG_ASSERT( !pFoundDock
&& !rDock
.pWin
, "Window already exists!");
485 // A new line has been created but no window was found there;
486 // continue searching for a window in this line in-order to set
487 // bNewLine correctly. While doing so nline or nPos are not
496 // Not found, insert at end
497 pFoundDock
= new SfxDock_Impl
;
498 pFoundDock
->bHide
= true;
499 maDockArr
.push_back( std::unique_ptr
<SfxDock_Impl
>(pFoundDock
) );
500 pFoundDock
->nType
= pDockWin
->GetType();
504 pFoundDock
->bNewLine
= bNewLine
;
508 pFoundDock
->pWin
= pDockWin
;
509 pFoundDock
->bHide
= false;
510 InsertWindow_Impl( pFoundDock
, rSize
, nLine
, nPos
, bNewLine
);
516 void SfxSplitWindow::ReleaseWindow_Impl(SfxDockingWindow
const *pDockWin
, bool bSave
)
518 // The docking window is no longer stored in the internal data.
519 sal_uInt16 nCount
= maDockArr
.size();
520 for ( sal_uInt16 n
=0; n
<nCount
; n
++ )
522 const SfxDock_Impl
& rDock
= *maDockArr
[n
];
523 if ( rDock
.nType
== pDockWin
->GetType() )
525 if ( rDock
.bNewLine
&& n
<nCount
-1 )
526 maDockArr
[n
+1]->bNewLine
= true;
528 // Window has a position, this we forget
529 maDockArr
.erase(maDockArr
.begin() + n
);
539 void SfxSplitWindow::MoveWindow( SfxDockingWindow
* pDockWin
, const Size
& rSize
,
540 sal_uInt16 nLine
, sal_uInt16 nPos
, bool bNewLine
)
544 The docking window is moved within the SplitWindows.
550 [[maybe_unused
]] auto const ok
= GetWindowPos( pDockWin
, nL
, nP
);
553 if ( nLine
> nL
&& GetItemCount( GetItemId( nL
) ) == 1 )
555 // If the last window is removed from its line, then everything slips
556 // one line to the front!
559 RemoveWindow( pDockWin
);
560 InsertWindow( pDockWin
, rSize
, nLine
, nPos
, bNewLine
);
564 void SfxSplitWindow::InsertWindow( SfxDockingWindow
* pDockWin
, const Size
& rSize
,
565 sal_uInt16 nLine
, sal_uInt16 nPos
, bool bNewLine
)
569 The DockingWindow that is pushed on this SplitWindow and shall hold the
570 given position and size.
573 ReleaseWindow_Impl( pDockWin
, false );
574 SfxDock_Impl
*pDock
= new SfxDock_Impl
;
575 pDock
->bHide
= false;
576 pDock
->nType
= pDockWin
->GetType();
577 pDock
->bNewLine
= bNewLine
;
578 pDock
->pWin
= pDockWin
;
580 DBG_ASSERT( nPos
==0 || !bNewLine
, "Wrong Parameter!");
584 // The window must be inserted before the first window so that it has the
585 // same or a greater position than pDockWin.
586 sal_uInt16 nCount
= maDockArr
.size();
587 sal_uInt16
nLastWindowIdx(0);
589 // If no window is found, a first window is inserted
590 sal_uInt16 nInsertPos
= 0;
591 for ( sal_uInt16 n
=0; n
<nCount
; n
++ )
593 SfxDock_Impl
& rD
= *maDockArr
[n
];
597 // A docked window has been found. If no suitable window behind
598 // the desired insertion point s found, then insertion is done at
602 sal_uInt16 nL
=0, nP
=0;
603 GetWindowPos( rD
.pWin
, nL
, nP
);
605 if ( (nL
== nLine
&& nP
== nPos
) || nL
> nLine
)
607 DBG_ASSERT( nL
== nLine
|| bNewLine
|| nPos
> 0, "Wrong Parameter!" );
608 if ( nL
== nLine
&& nPos
== 0 && !bNewLine
)
610 DBG_ASSERT(rD
.bNewLine
, "No new line?");
612 // The position is pushed to nPos==0
614 pDock
->bNewLine
= true;
617 nInsertPos
= n
!= 0 ? nLastWindowIdx
+ 1 : 0; // ignore all non-windows after the last window
622 if (nCount
!= 0 && nInsertPos
== nCount
&& nLastWindowIdx
!= nCount
- 1)
624 nInsertPos
= nLastWindowIdx
+ 1; // ignore all non-windows after the last window
627 maDockArr
.insert(maDockArr
.begin() + nInsertPos
, std::unique_ptr
<SfxDock_Impl
>(pDock
));
628 InsertWindow_Impl( pDock
, rSize
, nLine
, nPos
, bNewLine
);
633 void SfxSplitWindow::InsertWindow_Impl( SfxDock_Impl
const * pDock
,
635 sal_uInt16 nLine
, sal_uInt16 nPos
, bool bNewLine
)
639 Adds a DockingWindow, and causes the recalculation of the size of
644 SfxDockingWindow
* pDockWin
= pDock
->pWin
;
646 SplitWindowItemFlags nItemBits
= SplitWindowItemFlags::NONE
;
648 tools::Long nWinSize
, nSetSize
;
649 if ( IsHorizontal() )
651 nWinSize
= rSize
.Width();
652 nSetSize
= rSize
.Height();
656 nSetSize
= rSize
.Width();
657 nWinSize
= rSize
.Height();
660 std::unique_ptr
<DeactivateUpdateMode
> pDeactivateUpdateMode(new DeactivateUpdateMode( *this ));
662 if ( bNewLine
|| nLine
== GetItemCount() )
664 // An existing row should not be inserted, instead a new one
668 for ( sal_uInt16 n
=0; n
<GetItemCount(); n
++ )
670 if ( GetItemId(n
) >= nId
)
671 nId
= GetItemId(n
)+1;
674 // Create a new nLine:th line
675 SplitWindowItemFlags nBits
= nItemBits
;
676 if ( GetAlign() == WindowAlign::Top
|| GetAlign() == WindowAlign::Bottom
)
677 nBits
|= SplitWindowItemFlags::ColSet
;
678 InsertItem( nId
, nSetSize
, nLine
, 0, nBits
);
681 // Insert the window at line with the position nline. ItemWindowSize set to
682 // "percentage" share since the SV then does the re-sizing as expected,
683 // "pixel" actually only makes sense if also items with percentage or
684 // relative sizes are present.
685 nItemBits
|= SplitWindowItemFlags::PercentSize
;
686 sal_uInt16 nSet
= GetItemId( nLine
);
687 InsertItem( pDockWin
->GetType(), pDockWin
, nWinSize
, nPos
, nSet
, nItemBits
);
689 // SplitWindows are once created in SFX and when inserting the first
690 // DockingWindows is made visible.
691 if ( GetItemCount() == 1 && GetItemCount( 1 ) == 1 )
693 // The Rearranging in WorkWindow and a Show() on the SplitWindow is
694 // caused by SfxDockingwindow (->SfxWorkWindow::ConfigChild_Impl)
695 if ( !bPinned
&& !IsFloatingMode() )
698 bool bFadeIn
= ( pEmptyWin
->nState
& 2 ) != 0;
699 pEmptyWin
->bFadeIn
= false;
700 SetPinned_Impl( false );
701 pEmptyWin
->Actualize();
702 SAL_INFO("sfx", "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" );
703 pWorkWin
->RegisterChild_Impl( *GetSplitWindow(), eAlign
)->nVisible
= SfxChildVisibility::VISIBLE
;
704 // tdf#113539 FadeIn will call ArrangeChildren_Impl() for us, and avoiding extra calls to that
705 // can make a different to load times because it avoids extra accessibility calcs
709 pWorkWin
->ArrangeChildren_Impl();
713 bool bFadeIn
= ( pEmptyWin
->nState
& 2 ) != 0;
714 pEmptyWin
->bFadeIn
= false;
715 pEmptyWin
->Actualize();
716 if ( !bPinned
|| !pEmptyWin
->bFadeIn
)
718 SAL_INFO("sfx", "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" );
722 SAL_INFO("sfx", "SfxSplitWindow::InsertWindow_Impl - registering real Splitwindow" );
724 pWorkWin
->RegisterChild_Impl( *GetSplitWindow(), eAlign
)->nVisible
= SfxChildVisibility::VISIBLE
;
725 // tdf#113539 FadeIn will call ArrangeChildren_Impl() for us, and avoiding extra calls to that
726 // can make a different to load times because it avoids extra accessibility calcs
730 pWorkWin
->ArrangeChildren_Impl();
733 pWorkWin
->ShowChildren_Impl();
736 pDeactivateUpdateMode
.reset();
738 // workaround insufficiency of <SplitWindow> regarding dock layouting:
739 // apply FIXED item size as 'original' item size to improve layouting of undock-dock-cycle of a window
741 std::vector
< std::pair
< sal_uInt16
, tools::Long
> > aNewOrgSizes
;
742 // get FIXED item sizes
743 sal_uInt16 nCount
= maDockArr
.size();
744 for ( sal_uInt16 n
=0; n
<nCount
; ++n
)
746 const SfxDock_Impl
& rD
= *maDockArr
[n
];
749 const sal_uInt16 nId
= rD
.nType
;
750 const tools::Long nSize
= GetItemSize( nId
, SplitWindowItemFlags::Fixed
);
751 aNewOrgSizes
.emplace_back( nId
, nSize
);
754 // apply new item sizes
755 DeactivateUpdateMode
aDeactivateUpdateMode( *this );
756 for (const std::pair
< sal_uInt16
, tools::Long
> & rNewOrgSize
: aNewOrgSizes
)
758 SetItemSize( rNewOrgSize
.first
, rNewOrgSize
.second
);
764 void SfxSplitWindow::RemoveWindow( SfxDockingWindow
const * pDockWin
, bool bHide
)
768 Removes a DockingWindow. If it was the last one, then the SplitWindow is
772 sal_uInt16 nSet
= GetSet( pDockWin
->GetType() );
774 // SplitWindows are once created in SFX and is made invisible after
775 // removing the last DockingWindows.
776 if ( GetItemCount( nSet
) == 1 && GetItemCount() == 1 )
778 // The Rearranging in WorkWindow is caused by SfxDockingwindow
780 pEmptyWin
->aTimer
.Stop();
781 sal_uInt16 nRealState
= pEmptyWin
->nState
;
785 if ( !bPinned
|| !pEmptyWin
->bFadeIn
)
787 SAL_INFO("sfx", "SfxSplitWindow::RemoveWindow - releasing empty Splitwindow" );
791 SAL_INFO("sfx", "SfxSplitWindow::RemoveWindow - releasing real Splitwindow" );
794 pWorkWin
->ReleaseChild_Impl( *GetSplitWindow() );
795 pEmptyWin
->nState
= nRealState
;
796 pWorkWin
->ArrangeAutoHideWindows( this );
799 sal_uInt16 nCount
= maDockArr
.size();
800 for ( sal_uInt16 n
=0; n
<nCount
; n
++ )
802 SfxDock_Impl
& rDock
= *maDockArr
[n
];
803 if ( rDock
.nType
== pDockWin
->GetType() )
805 rDock
.pWin
= nullptr;
811 // Remove Windows, and if it was the last of the line, then also remove
812 // the line (line = itemset)
813 DeactivateUpdateMode
aDeactivateUpdateMode( *this );
815 RemoveItem( pDockWin
->GetType() );
817 if ( nSet
&& !GetItemCount( nSet
) )
822 bool SfxSplitWindow::GetWindowPos( const SfxDockingWindow
* pWindow
,
823 sal_uInt16
& rLine
, sal_uInt16
& rPos
) const
826 Returns the ID of the item sets and items for the DockingWindow in
827 the position passed on the old row / column-name.
831 sal_uInt16 nSet
= GetSet ( pWindow
->GetType() );
832 if ( nSet
== SPLITWINDOW_ITEM_NOTFOUND
)
835 rPos
= GetItemPos( pWindow
->GetType(), nSet
);
836 rLine
= GetItemPos( nSet
);
841 bool SfxSplitWindow::GetWindowPos( const Point
& rTestPos
,
842 sal_uInt16
& rLine
, sal_uInt16
& rPos
) const
845 Returns the ID of the item sets and items for the DockingWindow in
846 the position passed on the old row / column-name.
850 sal_uInt16 nId
= GetItemId( rTestPos
);
854 sal_uInt16 nSet
= GetSet ( nId
);
855 rPos
= GetItemPos( nId
, nSet
);
856 rLine
= GetItemPos( nSet
);
861 sal_uInt16
SfxSplitWindow::GetLineCount() const
865 Returns the number of rows = number of sub-itemsets in the root set.
868 return GetItemCount();
872 tools::Long
SfxSplitWindow::GetLineSize( sal_uInt16 nLine
) const
876 Returns the Row Height of nline itemset.
879 sal_uInt16 nId
= GetItemId( nLine
);
880 return GetItemSize( nId
);
884 sal_uInt16
SfxSplitWindow::GetWindowCount( sal_uInt16 nLine
) const
888 Returns the total number of windows
891 sal_uInt16 nId
= GetItemId( nLine
);
892 return GetItemCount( nId
);
896 sal_uInt16
SfxSplitWindow::GetWindowCount() const
900 Returns the total number of windows
903 return GetItemCount();
907 IMPL_LINK( SfxSplitWindow
, TimerHdl
, Timer
*, pTimer
, void)
912 if ( CursorIsOverRect() || !pTimer
)
914 // If the cursor is within the window, display the SplitWindow and set
915 // up the timer for close
916 pEmptyWin
->bAutoHide
= true;
920 pEmptyWin
->aLastPos
= GetPointerPosPixel();
921 pEmptyWin
->aTimer
.Start();
923 else if ( pEmptyWin
->bAutoHide
)
925 if ( GetPointerPosPixel() != pEmptyWin
->aLastPos
)
927 // The mouse has moved within the running time of the timer, thus
929 pEmptyWin
->aLastPos
= GetPointerPosPixel();
930 pEmptyWin
->aTimer
.Start();
934 // Especially for TF_AUTOSHOW_ON_MOUSEMOVE :
935 // If the window is not visible, there is nothing to do
936 // (user has simply moved the mouse over pEmptyWin)
939 pEmptyWin
->bEndAutoHide
= false;
940 if ( !Application::IsInModalMode() &&
941 !vcl::IsInPopupMenuExecute() &&
942 !pEmptyWin
->bSplit
&& !HasChildPathFocus( true ) )
944 // While a modal dialog or a popup menu is open or while the
945 // Splitting is done, in any case, do not close. Even as long
946 // as one of the Children has the focus, the window remains
948 pEmptyWin
->bEndAutoHide
= true;
951 if ( pEmptyWin
->bEndAutoHide
)
953 // As far as I am concerned this can be the end of AutoShow
954 // But maybe some other SfxSplitWindow will remain open,
955 // then all others remain open too.
956 if ( !pWorkWin
->IsAutoHideMode( this ) )
959 pWorkWin
->ArrangeAutoHideWindows( this );
963 pEmptyWin
->aLastPos
= GetPointerPosPixel();
964 pEmptyWin
->aTimer
.Start();
969 pEmptyWin
->aLastPos
= GetPointerPosPixel();
970 pEmptyWin
->aTimer
.Start();
977 bool SfxSplitWindow::CursorIsOverRect() const
979 bool bVisible
= IsVisible();
981 // Also, take the collapsed SplitWindow into account
982 Point aPos
= pEmptyWin
->GetParent()->OutputToScreenPixel( pEmptyWin
->GetPosPixel() );
983 Size aSize
= pEmptyWin
->GetSizePixel();
985 tools::Rectangle
aRect( aPos
, aSize
);
989 Point aVisPos
= GetPosPixel();
990 Size aVisSize
= GetSizePixel();
992 // Extend with +/- a few pixels, otherwise it is too nervous
993 aVisPos
.AdjustX( -(nPixel
) );
994 aVisPos
.AdjustY( -(nPixel
) );
995 aVisSize
.AdjustWidth(2 * nPixel
);
996 aVisSize
.AdjustHeight(2 * nPixel
);
998 tools::Rectangle
aVisRect( aVisPos
, aVisSize
);
999 aRect
= aRect
.GetUnion( aVisRect
);
1002 return aRect
.Contains( OutputToScreenPixel( static_cast<vcl::Window
*>(const_cast<SfxSplitWindow
*>(this))->GetPointerPosPixel() ) );
1006 SplitWindow
* SfxSplitWindow::GetSplitWindow()
1008 if ( !bPinned
|| !pEmptyWin
->bFadeIn
)
1014 bool SfxSplitWindow::IsFadeIn() const
1016 return pEmptyWin
->bFadeIn
;
1019 bool SfxSplitWindow::IsAutoHide( bool bSelf
) const
1021 return bSelf
? pEmptyWin
->bAutoHide
&& !pEmptyWin
->bEndAutoHide
: pEmptyWin
->bAutoHide
;
1025 void SfxSplitWindow::SetPinned_Impl( bool bOn
)
1027 if ( bPinned
== bOn
)
1031 if ( GetItemCount() == 0 )
1036 pEmptyWin
->nState
|= 1;
1037 if ( pEmptyWin
->bFadeIn
)
1039 // Unregister replacement windows
1040 SAL_INFO("sfx", "SfxSplitWindow::SetPinned_Impl - releasing real Splitwindow" );
1041 pWorkWin
->ReleaseChild_Impl( *this );
1043 pEmptyWin
->Actualize();
1044 SAL_INFO("sfx", "SfxSplitWindow::SetPinned_Impl - registering empty Splitwindow" );
1045 pWorkWin
->RegisterChild_Impl( *pEmptyWin
, eAlign
)->nVisible
= SfxChildVisibility::VISIBLE
;
1048 Point
aPos( GetPosPixel() );
1049 aPos
= GetParent()->OutputToScreenPixel( aPos
);
1050 SetFloatingPos( aPos
);
1051 SetFloatingMode( true );
1052 GetFloatingWindow()->SetOutputSizePixel( GetOutputSizePixel() );
1054 if ( pEmptyWin
->bFadeIn
)
1059 pEmptyWin
->nState
&= ~1;
1060 SetOutputSizePixel( GetFloatingWindow()->GetOutputSizePixel() );
1061 SetFloatingMode(false);
1063 if ( pEmptyWin
->bFadeIn
)
1065 // Unregister replacement windows
1066 SAL_INFO("sfx", "SfxSplitWindow::SetPinned_Impl - releasing empty Splitwindow" );
1067 pWorkWin
->ReleaseChild_Impl( *pEmptyWin
);
1069 SAL_INFO("sfx", "SfxSplitWindow::SetPinned_Impl - registering real Splitwindow" );
1070 pWorkWin
->RegisterChild_Impl( *this, eAlign
)->nVisible
= SfxChildVisibility::VISIBLE
;
1075 void SfxSplitWindow::SetFadeIn_Impl( bool bOn
)
1077 if ( bOn
== pEmptyWin
->bFadeIn
)
1080 if ( GetItemCount() == 0 )
1083 pEmptyWin
->bFadeIn
= bOn
;
1086 pEmptyWin
->nState
|= 2;
1087 if ( IsFloatingMode() )
1089 // FloatingWindow is not visible, thus display it
1090 pWorkWin
->ArrangeAutoHideWindows( this );
1095 SAL_INFO("sfx", "SfxSplitWindow::SetFadeIn_Impl - releasing empty Splitwindow" );
1096 pWorkWin
->ReleaseChild_Impl( *pEmptyWin
);
1098 SAL_INFO("sfx", "SfxSplitWindow::SetFadeIn_Impl - registering real Splitwindow" );
1099 pWorkWin
->RegisterChild_Impl( *this, eAlign
)->nVisible
= SfxChildVisibility::VISIBLE
;
1100 pWorkWin
->ArrangeChildren_Impl();
1101 pWorkWin
->ShowChildren_Impl();
1106 pEmptyWin
->bAutoHide
= false;
1107 pEmptyWin
->nState
&= ~2;
1108 if ( !IsFloatingMode() )
1110 // The window is not "floating", should be hidden
1111 SAL_INFO("sfx", "SfxSplitWindow::SetFadeIn_Impl - releasing real Splitwindow" );
1112 pWorkWin
->ReleaseChild_Impl( *this );
1114 pEmptyWin
->Actualize();
1115 SAL_INFO("sfx", "SfxSplitWindow::SetFadeIn_Impl - registering empty Splitwindow" );
1116 pWorkWin
->RegisterChild_Impl( *pEmptyWin
, eAlign
)->nVisible
= SfxChildVisibility::VISIBLE
;
1117 pWorkWin
->ArrangeChildren_Impl();
1118 pWorkWin
->ShowChildren_Impl();
1119 pWorkWin
->ArrangeAutoHideWindows( this );
1124 pWorkWin
->ArrangeAutoHideWindows( this );
1129 void SfxSplitWindow::FadeOut_Impl()
1131 if ( pEmptyWin
->aTimer
.IsActive() )
1133 pEmptyWin
->bAutoHide
= false;
1134 pEmptyWin
->aTimer
.Stop();
1137 SetFadeIn_Impl( false );
1140 void SfxSplitWindow::FadeOut()
1146 void SfxSplitWindow::FadeIn()
1148 SetFadeIn_Impl( true );
1151 void SfxSplitWindow::SetActiveWindow_Impl( SfxDockingWindow
* pWin
)
1154 pWorkWin
->SetActiveChild_Impl( this );
1158 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */