/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
// Help to make changes to the alignment compatible!
LayoutManagerListener::LayoutManagerListener(
SfxWorkWindow* pWrkWin ) :
m_bHasFrame( false ),
m_pWrkWin( pWrkWin )
{
}
static sal_uInt16 TbxMatch( sal_uInt16 nPos )
{ switch ( nPos )
{ case SFX_OBJECTBAR_APPLICATION : return 0; case SFX_OBJECTBAR_OPTIONS: return 1; case SFX_OBJECTBAR_MACRO: return 2; case SFX_OBJECTBAR_OBJECT: return 3; case SFX_OBJECTBAR_TOOLS: return 4; case SFX_OBJECTBAR_FULLSCREEN: case SFX_OBJECTBAR_COMMONTASK: case SFX_OBJECTBAR_RECORDING: return nPos+1; default: return nPos;
}
}
static sal_uInt16 ChildAlignValue(SfxChildAlignment eAlign)
{
sal_uInt16 ret = 17;
switch (eAlign)
{ case SfxChildAlignment::HIGHESTTOP:
ret = 1; break; case SfxChildAlignment::LOWESTBOTTOM:
ret = 2; break; case SfxChildAlignment::FIRSTLEFT:
ret = 3; break; case SfxChildAlignment::LASTRIGHT:
ret = 4; break; case SfxChildAlignment::LEFT:
ret = 5; break; case SfxChildAlignment::RIGHT:
ret = 6; break; case SfxChildAlignment::FIRSTRIGHT:
ret = 7; break; case SfxChildAlignment::LASTLEFT:
ret = 8; break; case SfxChildAlignment::TOP:
ret = 9; break; case SfxChildAlignment::BOTTOM:
ret = 10; break; case SfxChildAlignment::TOOLBOXTOP:
ret = 11; break; case SfxChildAlignment::TOOLBOXBOTTOM:
ret = 12; break; case SfxChildAlignment::LOWESTTOP:
ret = 13; break; case SfxChildAlignment::HIGHESTBOTTOM:
ret = 14; break; case SfxChildAlignment::TOOLBOXLEFT:
ret = 15; break; case SfxChildAlignment::TOOLBOXRIGHT:
ret = 16; break; case SfxChildAlignment::NOALIGNMENT: break; // -Wall not handled...
}
return ret;
}
void SfxWorkWindow::Sort_Impl()
{
aSortedList.clear(); for (size_t i = 0; i < aChildren.size(); ++i)
{
SfxChild_Impl *pCli = aChildren[i].get(); if (pCli)
{
decltype(aSortedList)::size_type k; for (k=0; k<aSortedList.size(); k++) if (ChildAlignValue( aChildren[aSortedList[k]]->eAlign ) >
ChildAlignValue(pCli->eAlign)) break;
aSortedList.insert( aSortedList.begin() + k, i );
}
}
// For the ObjectBars an integral place in the Childlist is reserved, // so that they always come in a defined order. for (int i=0; i<SFX_OBJECTBAR_MAX; ++i)
aChildren.push_back( nullptr );
// create and initialize layout manager listener
Reference< css::frame::XFrame > xFrame = GetFrameInterface();
m_xLayoutManagerListener = new LayoutManagerListener( this );
m_xLayoutManagerListener->setFrame( xFrame );
// The required split windows (one for each side) can be created for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX; n++ )
{ // The SplitWindows excludes direct ChildWindows of the WorkWindows // and receives the docked window.
// Helper method to release the child lists. Should the destructor not be // called after this, instead work continues, then space for the object bars // and split windows has to be reserved in the same way as in the constructor // of SfxWorkWindow.
void SfxWorkWindow::DeleteControllers_Impl()
{
// Lock SplitWindows (which means suppressing the Resize-Reaction of the // DockingWindows) for (size_t n=0; n<SFX_SPLITWINDOWS_MAX; n++ )
{
VclPtr<SfxSplitWindow> const &p = pSplit[n]; if (p->GetWindowCount())
p->Lock();
}
// If the child window is a direct child window and not in a // SplitWindow, cancel it at the workwindow. // After TH a cancellation on the SplitWindow is not necessary // since this window is also destroyed (see below). if (pCW->pCli)
{ if (pChild->GetController())
ReleaseChild_Impl(*pChild->GetController()); else
ReleaseChild_Impl(*pChild->GetWindow());
}
// ATTENTION: The array itself is cleared after this loop!! // Therefore we have to set every array entry to zero as it could be // accessed by calling pChild->Destroy(). // Window::NotifyAllChildren() calls SfxWorkWindow::DataChanged_Impl for // 8-bit displays (WM_QUERYPALETTECHANGED message due to focus change)!!
}
if ( xLayoutManager.is() )
{
xLayoutManager->reset();
// Delete StatusBar
ResetStatusBar_Impl();
// Delete ObjectBars (this is done last, so that aChildren does not // receive dead Pointers) for (SfxObjectBar_Impl & i : aObjBarList)
{ // Not every position must be occupied
ToolbarId eId = i.eId; if (eId != ToolbarId::None)
i.eId = ToolbarId::None;
}
}
// ObjectBars are all released at once, since they occupy a // fixed contiguous area in the array pChild
aChildren.clear();
bSorted = false;
aClientArea = GetTopRect_Impl(); if ( aClientArea.IsEmpty() ) return;
SvBorder aBorder; if ( nChildren && IsVisible_Impl() )
aBorder = Arrange_Impl(); // If the current application document contains an IPClient, then the // object through SetTopToolFramePixel has to be assigned the available // space. The object will then point to its UITools and sets the app border // (-> SfxInPlaceEnv_Impl:: ArrangeChildren_Impl ()). Otherwise the // app border is set here directly to possibly overwrite the Border that // was set by an object from another document. The object does not set // the SetAppBorder when it removes its UI tools so that no-dithering // ObjectBar arises. // (->SfxInPlaceEnv_Impl::ArrangeChildren_Impl())
void SfxWorkWindow::FlushPendingChildSizes()
{ // tdf#116865, if any windows are being resized, i.e. their // resize timer is active, then calling GetSizePixel on // them forces the timer to fire and sets the final // size to which they are getting resized towards. for (size_t i = 0; i < aChildren.size(); ++i)
{
SfxChild_Impl *pCli = aChildren[i].get(); if (!pCli || !pCli->pWin) continue;
(void)pCli->pWin->GetSizePixel();
}
}
SvBorder SfxWorkWindow::Arrange_Impl()
/* [Description]
This method organizes all visible child windows so that the docked window sorted in order from the outside to the inside are placed after one another. If a visible window does not fit anymore into the free ClientArea, it is set to "not visible".
*/
{ //tdf#116865 trigger pending sizing timers now so we arrange //with the final size of the client area. // //Otherwise calling GetSizePixel in the following loop will trigger the //timers, causing reentry into Arrange_Impl again where the inner //Arrange_Impl arranges with the final size, and then returns to this outer //Arrange_Impl which would rearrange with the old client area size
FlushPendingChildSizes();
aClientArea = GetTopRect_Impl();
aUpperClientArea = aClientArea;
SvBorder aBorder; if ( !nChildren ) return aBorder;
if (!bSorted)
Sort_Impl();
Point aPos;
Size aSize;
tools::Rectangle aTmp( aClientArea );
for (sal_uInt16 n : aSortedList)
{
SfxChild_Impl* pCli = aChildren[n].get(); if ( !pCli->pWin ) continue;
// First, we assume that there is room for the window.
pCli->nVisible |= SfxChildVisibility::FITS_IN;
// Skip invisible windows if (pCli->nVisible != SfxChildVisibility::VISIBLE) continue;
for (std::unique_ptr<SfxChild_Impl>& pCli : aChildren)
{ if (!pCli) continue;
SfxChildWin_Impl* pCW = nullptr; if (pCli->pWin || pCli->xController)
{ // We have to find the SfxChildWin_Impl to retrieve the // SFX_CHILDWIN flags that can influence visibility. for (const std::unique_ptr<SfxChildWin_Impl>& pCWin : aChildWins)
{
SfxChild_Impl* pChild = pCWin->pCli; if ( pChild == pCli.get() )
{
pCW = pCWin.get(); break;
}
}
bool bVisible( !bInvisible ); if ( pCW )
{ // Check flag SFX_CHILDWIN_NEVERHIDE that forces us to show // the child window even in situations where no child window is // visible.
SfxChildWindowFlags nFlags = pCW->aInfo.nFlags;
bVisible = !bInvisible || ( nFlags & SfxChildWindowFlags::NEVERHIDE );
}
if ( SfxChildVisibility::VISIBLE == (pCli->nVisible & SfxChildVisibility::VISIBLE) && bVisible )
{ if (pCli->xController)
{ if (!pCli->xController->getDialog()->get_visible())
{ auto xController = pCli->xController;
weld::DialogController::runAsync(xController,
[=](sal_Int32 nResult){ if (nResult == nCloseResponseToJustHide) return;
xController->Close();
});
}
} else
{
ShowFlags nFlags = pCli->bSetFocus ? ShowFlags::NONE : ShowFlags::NoFocusChange | ShowFlags::NoActivate;
pCli->pWin->Show(true, nFlags);
}
pCli->bSetFocus = false;
} else
{ if (pCli->xController)
{ if (pCli->xController->getDialog()->get_visible())
pCli->xController->response(RET_CLOSE);
} else
pCli->pWin->Hide();
}
}
}
}
void SfxWorkWindow::HideChildren_Impl()
{ for ( sal_uInt16 nPos = aChildren.size(); nPos > 0; --nPos )
{
SfxChild_Impl *pChild = aChildren[nPos-1].get(); if (!pChild) continue; if (pChild->xController)
pChild->xController->response(RET_CLOSE); elseif (pChild->pWin)
pChild->pWin->Hide();
}
}
void SfxWorkWindow::ResetObjectBars_Impl()
{ for ( auto & n: aObjBarList )
n.bDestroy = true;
for ( auto & n: aChildWins )
n->nId = 0;
}
void SfxWorkWindow::SetObjectBar_Impl(sal_uInt16 nPos, SfxVisibilityFlags nFlags, ToolbarId eId)
{
DBG_ASSERT( nPos < SFX_OBJECTBAR_MAX, "object bar position overflow" );
void SfxWorkWindow::UpdateObjectBars_Impl2()
{ if (comphelper::IsFuzzing()) return;
// Lock SplitWindows (which means suppressing the Resize-Reaction of the // DockingWindows) for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX; n++ )
{
VclPtr<SfxSplitWindow> const & p = pSplit[n]; if (p->GetWindowCount())
p->Lock();
}
// Unlock the SplitWindows again for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX; n++ )
{
VclPtr<SfxSplitWindow> const & p = pSplit[n]; if (p->GetWindowCount())
p->Lock(false);
}
}
void SfxWorkWindow::UpdateChildWindows_Impl()
{ // tdf#100870, tdf#101320: don't use range-based for loop when // container is modified for ( size_t n=0; n<aChildWins.size(); n++ )
{ // any current or in the context available Childwindows
SfxChildWin_Impl *pCW = aChildWins[n].get();
SfxChildWindow *pChildWin = pCW->pWin; bool bCreate = false; if ( pCW->nId && (pCW->aInfo.nFlags & SfxChildWindowFlags::ALWAYSAVAILABLE || IsVisible_Impl( pCW->nVisibility ) ) )
{ // In the context is an appropriate ChildWindow allowed; // it is also turned on? if ( pChildWin == nullptr && pCW->bCreate )
{ // Internal docking is only used for embedding into another // container. We force the floating state of all floatable // child windows. if ( !bInternalDockingAllowed )
{ // Special case for all non-floatable child windows. We have // to prevent the creation here!
bCreate = !( pCW->aInfo.nFlags & SfxChildWindowFlags::FORCEDOCK );
} elseif ( !IsDockingAllowed() || bIsFullScreen ) // || !bInternalDocking )
{ // In Presentation mode or FullScreen only FloatingWindows
SfxChildAlignment eAlign; if ( pCW->aInfo.GetExtraData_Impl( &eAlign ) )
bCreate = ( eAlign == SfxChildAlignment::NOALIGNMENT );
} else
bCreate = true;
if (pCW->aInfo.nFlags & SfxChildWindowFlags::NEVERCLONE)
pCW->bCreate = bCreate = false; // Don't create and remember that we haven't created.
// Currently, no window here, but it is enabled; windows // Create window and if possible theContext if ( bCreate )
CreateChildWin_Impl( pCW, false );
if ( !bAllChildrenVisible && pCW->pCli )
pCW->pCli->nVisible &= ~SfxChildVisibility::ACTIVE;
} elseif ( pChildWin )
{ // Window already exists, it should also be visible? if ( ( !bIsFullScreen || pChildWin->GetAlignment() == SfxChildAlignment::NOALIGNMENT ) && bAllChildrenVisible )
{ // Update Mode is compatible; definitely enable it
bCreate = true; if ( pCW->pCli )
{ // The window is a direct Child if ((IsDockingAllowed() && bInternalDockingAllowed)
|| pCW->pCli->eAlign == SfxChildAlignment::NOALIGNMENT)
pCW->pCli->nVisible |= SfxChildVisibility::NOT_HIDDEN;
} else
{ if ( pCW->bCreate && IsDockingAllowed() && bInternalDockingAllowed ) // The window ia within a SplitWindow static_cast<SfxDockingWindow*>(pChildWin->GetWindow())->Reappear_Impl();
}
}
}
}
SfxChildWindow *pChildWin = SfxChildWindow::CreateChildWindow( pCW->nId, pWorkWin, &GetBindings(), pCW->aInfo).release(); if (!pChildWin) return;
if ( bSetFocus )
bSetFocus = pChildWin->WantsFocus();
pChildWin->SetWorkWindow_Impl( this );
// At least the extra string is changed during the evaluation, // also get it anewed
SfxChildWinInfo aInfo = pChildWin->GetInfo();
pCW->aInfo.aExtraString = aInfo.aExtraString;
pCW->aInfo.bVisible = aInfo.bVisible;
pCW->aInfo.nFlags |= aInfo.nFlags;
// The creation was successful
GetBindings().Invalidate(pCW->nId);
// make childwin keyboard accessible
pWorkWin->GetSystemWindow()->GetTaskPaneList()->AddWindow( pChildWin->GetWindow() );
pCW->pWin = pChildWin;
if ( pChildWin->GetAlignment() == SfxChildAlignment::NOALIGNMENT || pChildWin->GetWindow()->GetParent() == pWorkWin)
{ // The window is not docked or docked outside of one split windows // and must therefore be registered explicitly as a Child if (pChildWin->GetController())
pCW->pCli = RegisterChild_Impl(pChildWin->GetController(), pChildWin->GetAlignment()); else
pCW->pCli = RegisterChild_Impl(*(pChildWin->GetWindow()), pChildWin->GetAlignment());
pCW->pCli->nVisible = SfxChildVisibility::VISIBLE; if ( pChildWin->GetAlignment() != SfxChildAlignment::NOALIGNMENT && bIsFullScreen )
pCW->pCli->nVisible ^= SfxChildVisibility::ACTIVE;
pCW->pCli->bSetFocus = bSetFocus;
} else
{ // A docked window which parent is not a WorkingWindow, must lie // in a SplitWindow and thus not be explicitly registered. // This happens already in the initialization of SfxDockingWindows!
}
// Save the information in the INI file
SaveStatus_Impl(pChildWin, pCW->aInfo);
}
// Save the information in the INI file
SfxChildWindowFlags nFlags = pCW->aInfo.nFlags;
pCW->aInfo = pChildWin->GetInfo();
pCW->aInfo.nFlags |= nFlags;
SaveStatus_Impl(pChildWin, pCW->aInfo);
pChildWin->Hide();
if ( pCW->pCli )
{ // Child window is a direct child window and must therefore unregister // itself from the WorkWindow
pCW->pCli = nullptr; if (pChildWin->GetController())
ReleaseChild_Impl(*pChildWin->GetController()); else
ReleaseChild_Impl(*pChildWin->GetWindow());
} else
{ // ChildWindow is within a SplitWindow and unregister itself in // the destructor.
}
Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
aValue >>= xLayoutManager;
// No status bar, if no ID is required or when in FullScreenView or // if disabled if (aStatBar.eId != StatusBarId::None && IsDockingAllowed() && bInternalDockingAllowed && bShowStatusBar &&
!bIsFullScreen)
{ // Id has changed, thus create a suitable Statusbarmanager, this takes // over the current status bar; if ( xLayoutManager.is() )
xLayoutManager->requestElement( g_aStatusBarResName );
} else
{ // Destroy the current StatusBar // The Manager only creates the Status bar, does not destroy it. if ( xLayoutManager.is() )
xLayoutManager->destroyElement( g_aStatusBarResName );
}
}
// configure DockingWindow inside a SplitWindow if ( eConfig == SfxDockingConfig::TOGGLEFLOATMODE)
{ // DockingWindow was dragged into a SplitWindow
pCW->pCli = nullptr;
ReleaseChild_Impl(*pDockWin);
}
// The current affected window is included in the calculation of // the inner rectangle! for (sal_uInt16 i : aSortedList)
{
SfxChild_Impl* pCli = aChildren[i].get();
if ( pCli && pCli->nVisible == SfxChildVisibility::VISIBLE && pCli->pWin )
{ switch ( pCli->eAlign )
{ case SfxChildAlignment::TOP: // Object-Toolboxes come always last
aInnerRect.AdjustTop(pCli->aSize.Height() ); break;
case SfxChildAlignment::HIGHESTTOP: // Always performed first
aInnerRect.AdjustTop(pCli->aSize.Height() ); break;
case SfxChildAlignment::LOWESTTOP: // Is only counted if it is the current window if ( i == nPos )
aInnerRect.AdjustTop(pCli->aSize.Height() ); break;
case SfxChildAlignment::BOTTOM: // Object-Toolboxes come always last
aInnerRect.AdjustBottom( -(pCli->aSize.Height()) ); break;
case SfxChildAlignment::LOWESTBOTTOM: // Always performed first
aInnerRect.AdjustBottom( -(pCli->aSize.Height()) ); break;
case SfxChildAlignment::HIGHESTBOTTOM: // Is only counted if it is the current window if ( i == nPos )
aInnerRect.AdjustBottom( -(pCli->aSize.Height()) ); break;
case SfxChildAlignment::LEFT: // Toolboxes come always last
aInnerRect.AdjustLeft(pCli->aSize.Width() ); break;
case SfxChildAlignment::FIRSTLEFT: // Always performed first
aInnerRect.AdjustLeft(pCli->aSize.Width() ); break;
case SfxChildAlignment::LASTLEFT: // Is only counted if it is the current window if (i == nPos)
aInnerRect.AdjustLeft(pCli->aSize.Width() ); break;
case SfxChildAlignment::RIGHT: // Toolboxes come always last
aInnerRect.AdjustRight( -(pCli->aSize.Width()) ); break;
case SfxChildAlignment::FIRSTRIGHT: // Is only counted if it is the current window if (i == nPos)
aInnerRect.AdjustRight( -(pCli->aSize.Width()) ); break;
case SfxChildAlignment::LASTRIGHT: // Always performed first
aInnerRect.AdjustRight( -(pCli->aSize.Width()) ); break;
if ( !pCW )
{ // If new, then initialize, add this here depending on the flag or // the Parent
pCW = new SfxChildWin_Impl( lId );
pCW->nId = nId;
InitializeChild_Impl( pCW );
aChildWins.push_back( std::unique_ptr<SfxChildWin_Impl>(pCW) );
}
void SfxWorkWindow::ToggleChildWindow_Impl(sal_uInt16 nId, bool bSetFocus)
{ if (SfxChildWin_Impl* pCW = Get_ById(aChildWins, nId))
{ // The Window is already known
SfxChildWindow *pChild = pCW->pWin;
bool bCreationAllowed( true ); if ( !bInternalDockingAllowed )
{ // Special case for all non-floatable child windows. We have // to prevent the creation here!
bCreationAllowed = !( pCW->aInfo.nFlags & SfxChildWindowFlags::FORCEDOCK );
}
if ( bCreationAllowed )
{ if ( pCW->bCreate )
{ if ( pChild )
{ if ( pChild->QueryClose() )
{
pCW->bCreate = false; // The Window should be switched off
pChild->SetVisible_Impl( false );
RemoveChildWin_Impl( pCW );
}
} else
{ // no actual Window exists, yet => just remember the "switched off" state
pCW->bCreate = false;
}
} else
{
pCW->bCreate = true; if ( pChild )
{
ShowChildWindow_Impl( nId, true, bSetFocus );
} else
{ // create actual Window
CreateChildWin_Impl( pCW, bSetFocus ); if ( !pCW->pWin ) // no success
pCW->bCreate = false;
}
}
}
ArrangeChildren_Impl();
ShowChildren_Impl();
if ( pCW->bCreate && bCreationAllowed )
{ if ( !pCW->pCli )
{
SfxDockingWindow *pDock = static_cast<SfxDockingWindow*>( pCW->pWin->GetWindow() ); if ( pDock->IsAutoHide_Impl() )
pDock->AutoShow_Impl();
}
}
return;
}
#ifdef DBG_UTIL if (Get_BySaveId(aChildWins, nId))
{
OSL_FAIL("The ChildWindow is not in context!");
} else
{
OSL_FAIL("The ChildWindow is not registered!");
} #endif
}
if ( !pCW )
{ // If new, then initialize, add this here depending on the flag or // the Parent
pCW = new SfxChildWin_Impl( nId );
pCW->bEnable = false;
pCW->nId = 0;
pCW->nVisibility = SfxVisibilityFlags::Invisible;
InitializeChild_Impl( pCW );
aChildWins.push_back( std::unique_ptr<SfxChildWin_Impl>(pCW) );
}
if ( !pCW )
{ // If new, then initialize, add this here depending on the flag or // the Parent
pCW = new SfxChildWin_Impl( nId );
InitializeChild_Impl( pCW );
aChildWins.push_back( std::unique_ptr<SfxChildWin_Impl>(pCW) );
}
if ( pCW->bCreate != bOn )
ToggleChildWindow_Impl(nId,bSetFocus);
}
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.