namespace { // helper class to deactivate UpdateMode, if needed, for the life time of an instance class DeactivateUpdateMode
{ public: explicit DeactivateUpdateMode( SfxSplitWindow& rSplitWindow )
: mrSplitWindow( rSplitWindow )
, mbUpdateMode( rSplitWindow.IsUpdateMode() )
{ if ( mbUpdateMode )
{
mrSplitWindow.SetUpdateMode( false );
}
}
void SfxEmptySplitWin_Impl::Actualize()
{
Size aSize( pOwner->GetSizePixel() ); switch ( pOwner->GetAlign() )
{ case WindowAlign::Left: case WindowAlign::Right:
aSize.setWidth( GetFadeInSize() ); break; case WindowAlign::Top: case WindowAlign::Bottom:
aSize.setHeight( GetFadeInSize() ); break;
}
SetSizePixel( aSize );
}
void SfxEmptySplitWin_Impl::FadeIn()
{ if (!bAutoHide )
bAutoHide = IsFadeNoButtonMode();
pOwner->SetFadeIn_Impl( true ); if ( bAutoHide )
{ // Set Timer to close; the caller has to ensure themselves that the // Window is not closed instantly (eg by setting the focus or a modal // mode.
aLastPos = GetPointerPosPixel();
aTimer.Start();
} else
pOwner->SaveConfig_Impl();
}
if ( pEmptyWin )
{ // Set pOwner to NULL, otherwise try to delete pEmptyWin once more. The // window that is just being docked is always deleted from the outside.
pEmptyWin->pOwner = nullptr;
}
pEmptyWin.disposeAndClear();
/* ToinsertSfxDockingWindowsjustpassnoposition.TheSfxSplitWindow searchesthelastmarkedonetothepassedSfxDockingWindoworappendsa newoneattheend.
*/
{ short nLine = -1; // so that the first window cab set nline to 0
sal_uInt16 nPos = 0; bool bNewLine = true; bool bSaveConfig = false;
SfxDock_Impl *pFoundDock=nullptr;
sal_uInt16 nCount = maDockArr.size(); for ( sal_uInt16 n=0; n<nCount; n++ )
{
SfxDock_Impl& rDock = *maDockArr[n]; if ( rDock.bNewLine )
{ // The window opens a new line if ( pFoundDock ) // But after the just inserted window break;
// New line
nPos = 0;
bNewLine = true;
}
if ( rDock.pWin )
{ // Does there exist a window now at this position if ( bNewLine && !pFoundDock )
{ // Not known until now in which real line it is located
sal_uInt16 nL = 0;
[[maybe_unused]] autoconst ok = GetWindowPos( rDock.pWin, nL, nPos );
assert(ok);
nLine = static_cast<short>(nL);
}
if ( !pFoundDock )
{ // The window is located before the inserted one
nPos++;
}
// Line is opened
bNewLine = false; if ( pFoundDock ) break;
}
if ( rDock.nType == pDockWin->GetType() )
{
DBG_ASSERT( !pFoundDock && !rDock.pWin, "Window already exists!");
pFoundDock = &rDock; if ( !bNewLine ) break; else
{ // A new line has been created but no window was found there; // continue searching for a window in this line in-order to set // bNewLine correctly. While doing so nline or nPos are not // to be changed!
nLine++;
}
}
}
if ( !pFoundDock )
{ // Not found, insert at end
pFoundDock = new SfxDock_Impl;
pFoundDock->bHide = true;
maDockArr.push_back( std::unique_ptr<SfxDock_Impl>(pFoundDock) );
pFoundDock->nType = pDockWin->GetType();
nLine++;
nPos = 0;
bNewLine = true;
pFoundDock->bNewLine = bNewLine;
bSaveConfig = true;
}
if ( nLine > nL && GetItemCount( GetItemId( nL ) ) == 1 )
{ // If the last window is removed from its line, then everything slips // one line to the front!
nLine--;
}
RemoveWindow( pDockWin );
InsertWindow( pDockWin, rSize, nLine, nPos, bNewLine );
}
// The window must be inserted before the first window so that it has the // same or a greater position than pDockWin.
sal_uInt16 nCount = maDockArr.size();
sal_uInt16 nLastWindowIdx(0);
// If no window is found, a first window is inserted
sal_uInt16 nInsertPos = 0; for ( sal_uInt16 n=0; n<nCount; n++ )
{
SfxDock_Impl& rD = *maDockArr[n];
if (rD.pWin)
{ // A docked window has been found. If no suitable window behind // the desired insertion point s found, then insertion is done at // the end.
nInsertPos = nCount;
nLastWindowIdx = n;
sal_uInt16 nL=0, nP=0;
GetWindowPos( rD.pWin, nL, nP );
if ( bNewLine || nLine == GetItemCount() )
{ // An existing row should not be inserted, instead a new one // will be created
sal_uInt16 nId = 1; for ( sal_uInt16 n=0; n<GetItemCount(); n++ )
{ if ( GetItemId(n) >= nId )
nId = GetItemId(n)+1;
}
// Create a new nLine:th line
SplitWindowItemFlags nBits = nItemBits; if ( GetAlign() == WindowAlign::Top || GetAlign() == WindowAlign::Bottom )
nBits |= SplitWindowItemFlags::ColSet;
InsertItem( nId, nSetSize, nLine, 0, nBits );
}
// Insert the window at line with the position nline. ItemWindowSize set to // "percentage" share since the SV then does the re-sizing as expected, // "pixel" actually only makes sense if also items with percentage or // relative sizes are present.
nItemBits |= SplitWindowItemFlags::PercentSize;
sal_uInt16 nSet = GetItemId( nLine );
InsertItem( pDockWin->GetType(), pDockWin, nWinSize, nPos, nSet, nItemBits );
// SplitWindows are once created in SFX and when inserting the first // DockingWindows is made visible. if ( GetItemCount() == 1 && GetItemCount( 1 ) == 1 )
{ // The Rearranging in WorkWindow and a Show() on the SplitWindow is // caused by SfxDockingwindow (->SfxWorkWindow::ConfigChild_Impl) if ( !bPinned && !IsFloatingMode() )
{
bPinned = true; bool bFadeIn = ( pEmptyWin->nState & 2 ) != 0;
pEmptyWin->bFadeIn = false;
SetPinned_Impl( false );
pEmptyWin->Actualize();
SAL_INFO("sfx", "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" );
pWorkWin->RegisterChild_Impl( *GetSplitWindow(), eAlign )->nVisible = SfxChildVisibility::VISIBLE; // tdf#113539 FadeIn will call ArrangeChildren_Impl() for us, and avoiding extra calls to that // can make a different to load times because it avoids extra accessibility calcs if ( bFadeIn )
FadeIn(); else
pWorkWin->ArrangeChildren_Impl();
} else
{ bool bFadeIn = ( pEmptyWin->nState & 2 ) != 0;
pEmptyWin->bFadeIn = false;
pEmptyWin->Actualize(); if ( !bPinned || !pEmptyWin->bFadeIn )
{
SAL_INFO("sfx", "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" );
} else
{
SAL_INFO("sfx", "SfxSplitWindow::InsertWindow_Impl - registering real Splitwindow" );
}
pWorkWin->RegisterChild_Impl( *GetSplitWindow(), eAlign )->nVisible = SfxChildVisibility::VISIBLE; // tdf#113539 FadeIn will call ArrangeChildren_Impl() for us, and avoiding extra calls to that // can make a different to load times because it avoids extra accessibility calcs if ( bFadeIn )
FadeIn(); else
pWorkWin->ArrangeChildren_Impl();
}
pWorkWin->ShowChildren_Impl();
}
pDeactivateUpdateMode.reset();
// workaround insufficiency of <SplitWindow> regarding dock layouting: // apply FIXED item size as 'original' item size to improve layouting of undock-dock-cycle of a window
{
std::vector< std::pair< sal_uInt16, tools::Long > > aNewOrgSizes; // get FIXED item sizes
sal_uInt16 nCount = maDockArr.size(); for ( sal_uInt16 n=0; n<nCount; ++n )
{ const SfxDock_Impl& rD = *maDockArr[n]; if ( rD.pWin )
{ const sal_uInt16 nId = rD.nType; const tools::Long nSize = GetItemSize( nId, SplitWindowItemFlags::Fixed );
aNewOrgSizes.emplace_back( nId, nSize );
}
} // apply new item sizes
DeactivateUpdateMode aDeactivateUpdateMode( *this ); for (const std::pair< sal_uInt16, tools::Long > & rNewOrgSize : aNewOrgSizes)
{
SetItemSize( rNewOrgSize.first, rNewOrgSize.second );
}
}
}
// SplitWindows are once created in SFX and is made invisible after // removing the last DockingWindows. if ( GetItemCount( nSet ) == 1 && GetItemCount() == 1 )
{ // The Rearranging in WorkWindow is caused by SfxDockingwindow
Hide();
pEmptyWin->aTimer.Stop();
sal_uInt16 nRealState = pEmptyWin->nState;
FadeOut_Impl();
pEmptyWin->Hide(); #ifdef DBG_UTIL if ( !bPinned || !pEmptyWin->bFadeIn )
{
SAL_INFO("sfx", "SfxSplitWindow::RemoveWindow - releasing empty Splitwindow" );
} else
{
SAL_INFO("sfx", "SfxSplitWindow::RemoveWindow - releasing real Splitwindow" );
} #endif
pWorkWin->ReleaseChild_Impl( *GetSplitWindow() );
pEmptyWin->nState = nRealState;
pWorkWin->ArrangeAutoHideWindows( this );
}
// Remove Windows, and if it was the last of the line, then also remove // the line (line = itemset)
DeactivateUpdateMode aDeactivateUpdateMode( *this );
if ( CursorIsOverRect() || !pTimer )
{ // If the cursor is within the window, display the SplitWindow and set // up the timer for close
pEmptyWin->bAutoHide = true; if ( !IsVisible() )
pEmptyWin->FadeIn();
pEmptyWin->aLastPos = GetPointerPosPixel();
pEmptyWin->aTimer.Start();
} elseif ( pEmptyWin->bAutoHide )
{ if ( GetPointerPosPixel() != pEmptyWin->aLastPos )
{ // The mouse has moved within the running time of the timer, thus // do nothing
pEmptyWin->aLastPos = GetPointerPosPixel();
pEmptyWin->aTimer.Start(); return;
}
// Especially for TF_AUTOSHOW_ON_MOUSEMOVE : // If the window is not visible, there is nothing to do // (user has simply moved the mouse over pEmptyWin) if ( IsVisible() )
{
pEmptyWin->bEndAutoHide = false; if ( !Application::IsInModalMode() &&
!vcl::IsInPopupMenuExecute() &&
!pEmptyWin->bSplit && !HasChildPathFocus( true ) )
{ // While a modal dialog or a popup menu is open or while the // Splitting is done, in any case, do not close. Even as long // as one of the Children has the focus, the window remains // open.
pEmptyWin->bEndAutoHide = true;
}
if ( pEmptyWin->bEndAutoHide )
{ // As far as I am concerned this can be the end of AutoShow // But maybe some other SfxSplitWindow will remain open, // then all others remain open too. if ( !pWorkWin->IsAutoHideMode( this ) )
{
FadeOut_Impl();
pWorkWin->ArrangeAutoHideWindows( this );
} else
{
pEmptyWin->aLastPos = GetPointerPosPixel();
pEmptyWin->aTimer.Start();
}
} else
{
pEmptyWin->aLastPos = GetPointerPosPixel();
pEmptyWin->aTimer.Start();
}
}
}
}
// Also, take the collapsed SplitWindow into account
Point aPos = pEmptyWin->GetParent()->OutputToScreenPixel( pEmptyWin->GetPosPixel() );
Size aSize = pEmptyWin->GetSizePixel();
tools::Rectangle aRect( aPos, aSize );
if ( bVisible )
{
Point aVisPos = GetPosPixel();
Size aVisSize = GetSizePixel();
// Extend with +/- a few pixels, otherwise it is too nervous
aVisPos.AdjustX( -(nPixel) );
aVisPos.AdjustY( -(nPixel) );
aVisSize.AdjustWidth(2 * nPixel );
aVisSize.AdjustHeight(2 * nPixel );
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.