summaryrefslogtreecommitdiffstats
path: root/sfx2/source/appl/workwin.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sfx2/source/appl/workwin.cxx')
-rw-r--r--sfx2/source/appl/workwin.cxx2430
1 files changed, 2430 insertions, 0 deletions
diff --git a/sfx2/source/appl/workwin.cxx b/sfx2/source/appl/workwin.cxx
new file mode 100644
index 000000000..4874db7ee
--- /dev/null
+++ b/sfx2/source/appl/workwin.cxx
@@ -0,0 +1,2430 @@
+/* -*- 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 .
+ */
+
+#include <config_features.h>
+#include <config_feature_desktop.h>
+#include <comphelper/lok.hxx>
+#include <comphelper/processfactory.hxx>
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/objface.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/app.hxx>
+#include <workwin.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/module.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/dockwin.hxx>
+#include <sfx2/viewsh.hxx>
+#include <splitwin.hxx>
+#include <sfx2/sfxsids.hrc>
+#include <sfx2/toolbarids.hxx>
+#include <vcl/taskpanelist.hxx>
+#include <vcl/svapp.hxx>
+#include <svl/eitem.hxx>
+#include <tools/svborder.hxx>
+#include <tools/debug.hxx>
+#include <unotools/moduleoptions.hxx>
+#include <com/sun/star/ui/XUIElement.hpp>
+#include <com/sun/star/frame/LayoutManagerEvents.hpp>
+#include <com/sun/star/frame/ModuleManager.hpp>
+#include <com/sun/star/frame/XLayoutManager.hpp>
+#include <com/sun/star/frame/XLayoutManagerEventBroadcaster.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <type_traits>
+#include <unordered_map>
+#include <sfx2/notebookbar/SfxNotebookBar.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+namespace {
+
+struct ResIdToResName
+{
+ ToolbarId eId;
+ const char* pName;
+};
+
+}
+
+const ResIdToResName pToolBarResToName[] =
+{
+ { ToolbarId::FullScreenToolbox, "fullscreenbar" },
+ { ToolbarId::EnvToolbox, "standardbar", },
+ { ToolbarId::SvxTbx_Form_Navigation, "formsnavigationbar" },
+ { ToolbarId::SvxTbx_Form_Filter, "formsfilterbar" },
+ { ToolbarId::SvxTbx_Text_Control_Attributes, "formtextobjectbar" },
+ { ToolbarId::SvxTbx_Controls, "formcontrols" },
+ { ToolbarId::SvxTbx_FormDesign, "formdesign" },
+ { ToolbarId::Math_Toolbox, "toolbar" }, //math
+ { ToolbarId::Text_Toolbox_Sc, "textobjectbar" }, //calc
+ { ToolbarId::Draw_Objectbar, "drawobjectbar" },
+ { ToolbarId::Graphic_Objectbar, "graphicobjectbar" },
+ { ToolbarId::Objectbar_Format, "formatobjectbar" },
+ { ToolbarId::Objectbar_Preview, "previewbar" },
+ { ToolbarId::Objectbar_Tools, "toolbar" }, //calc
+ { ToolbarId::Bezier_Toolbox_Sd, "bezierobjectbar" }, //draw/impress
+ { ToolbarId::Gluepoints_Toolbox, "gluepointsobjectbar" },
+ { ToolbarId::Draw_Graf_Toolbox, "graphicobjectbar" },
+ { ToolbarId::Draw_Obj_Toolbox, "drawingobjectbar" }, //impress
+ { ToolbarId::Draw_Text_Toolbox_Sd, "textobjectbar" }, //impress
+ { ToolbarId::Draw_Toolbox_Sd, "toolbar" }, //impress
+ { ToolbarId::Draw_Options_Toolbox, "optionsbar" },
+ { ToolbarId::Draw_CommonTask_Toolbox, "commontaskbar" },
+ { ToolbarId::Graphic_Obj_Toolbox, "drawingobjectbar" }, //draw
+ { ToolbarId::Outline_Toolbox, "outlinetoolbar" }, //impress
+ { ToolbarId::Slide_Toolbox, "slideviewtoolbar" },
+ { ToolbarId::Slide_Obj_Toolbox, "slideviewobjectbar" },
+ { ToolbarId::Bezier_Toolbox_Sw, "bezierobjectbar" },
+ { ToolbarId::Draw_Toolbox_Sw, "drawingobjectbar" },
+ { ToolbarId::Draw_Text_Toolbox_Sw, "drawtextobjectbar" },
+ { ToolbarId::Frame_Toolbox, "frameobjectbar" },
+ { ToolbarId::Grafik_Toolbox, "graphicobjectbar" },
+ { ToolbarId::Num_Toolbox, "numobjectbar" },
+ { ToolbarId::Ole_Toolbox, "oleobjectbar" },
+ { ToolbarId::Table_Toolbox, "tableobjectbar" },
+ { ToolbarId::Text_Toolbox_Sw, "textobjectbar" },
+ { ToolbarId::PView_Toolbox, "previewobjectbar" }, //writer
+ { ToolbarId::Webtools_Toolbox, "toolbar" }, //web
+ { ToolbarId::Webtext_Toolbox, "textobjectbar" },
+ { ToolbarId::Tools_Toolbox, "toolbar" }, //writer
+ { ToolbarId::Webframe_Toolbox, "frameobjectbar" }, //web
+ { ToolbarId::Webgraphic_Toolbox, "graphicobjectbar" },
+ { ToolbarId::Webole_Toolbox, "oleobjectbar" },
+ { ToolbarId::Basicide_Objectbar, "macrobar" },
+ { ToolbarId::Svx_Fontwork_Bar, "fontworkobjectbar" }, //global
+ { ToolbarId::Svx_Extrusion_Bar, "extrusionobjectbar" },
+ { ToolbarId::FormLayer_Toolbox, "formsobjectbar" },
+ { ToolbarId::Module_Toolbox, "viewerbar" }, //writer (plugin)
+ { ToolbarId::Objectbar_App, "viewerbar" }, //calc (plugin)
+ { ToolbarId::Draw_Viewer_Toolbox, "viewerbar" }, //impress(plugin)
+ { ToolbarId::Draw_Media_Toolbox, "mediaobjectbar" }, //draw/impress
+ { ToolbarId::Media_Objectbar, "mediaobjectbar" }, //calc
+ { ToolbarId::Media_Toolbox, "mediaobjectbar" }, //writer
+ { ToolbarId::None, "" }
+};
+
+// Sort the Children according their alignment
+// The order corresponds to the enum SfxChildAlignment (->CHILDWIN.HXX).
+
+constexpr OUStringLiteral g_aLayoutManagerPropName = u"LayoutManager";
+
+// Help to make changes to the alignment compatible!
+LayoutManagerListener::LayoutManagerListener(
+ SfxWorkWindow* pWrkWin ) :
+ m_bHasFrame( false ),
+ m_pWrkWin( pWrkWin )
+{
+}
+
+LayoutManagerListener::~LayoutManagerListener()
+{
+}
+
+void LayoutManagerListener::setFrame( const css::uno::Reference< css::frame::XFrame >& xFrame )
+{
+ SolarMutexGuard aGuard;
+ if ( !m_pWrkWin || m_bHasFrame )
+ return;
+
+ m_xFrame = xFrame;
+ m_bHasFrame = true;
+
+ if ( !xFrame.is() )
+ return;
+
+ css::uno::Reference< css::beans::XPropertySet > xPropSet( xFrame, UNO_QUERY );
+ css::uno::Reference< css::frame::XLayoutManagerEventBroadcaster > xLayoutManager;
+ if ( !xPropSet.is() )
+ return;
+
+ try
+ {
+ Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
+ aValue >>= xLayoutManager;
+
+ if ( xLayoutManager.is() )
+ xLayoutManager->addLayoutManagerEventListener(
+ css::uno::Reference< css::frame::XLayoutManagerListener >(this) );
+
+ xPropSet.set( xLayoutManager, UNO_QUERY );
+ if ( xPropSet.is() )
+ {
+ aValue = xPropSet->getPropertyValue( "LockCount" );
+ aValue >>= m_pWrkWin->m_nLock;
+ }
+ }
+ catch ( css::lang::DisposedException& )
+ {
+ }
+ catch ( const css::uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch ( css::uno::Exception& )
+ {
+ }
+}
+
+
+// XComponent
+
+void SAL_CALL LayoutManagerListener::addEventListener(
+ const css::uno::Reference< css::lang::XEventListener >& )
+{
+ // do nothing, only internal class
+}
+
+void SAL_CALL LayoutManagerListener::removeEventListener(
+ const css::uno::Reference< css::lang::XEventListener >& )
+{
+ // do nothing, only internal class
+}
+
+void SAL_CALL LayoutManagerListener::dispose()
+{
+ SolarMutexGuard aGuard;
+
+ // reset member
+ m_pWrkWin = nullptr;
+
+ css::uno::Reference< css::frame::XFrame > xFrame( m_xFrame.get(), css::uno::UNO_QUERY );
+ if ( !xFrame.is() )
+ return;
+
+ m_xFrame.clear();
+ m_bHasFrame = false;
+
+ css::uno::Reference< css::beans::XPropertySet > xPropSet( xFrame, css::uno::UNO_QUERY );
+ css::uno::Reference< css::frame::XLayoutManagerEventBroadcaster > xLayoutManager;
+ if ( !xPropSet.is() )
+ return;
+
+ try
+ {
+ css::uno::Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
+ aValue >>= xLayoutManager;
+
+ // remove as listener from layout manager
+ if ( xLayoutManager.is() )
+ xLayoutManager->removeLayoutManagerEventListener(
+ css::uno::Reference< css::frame::XLayoutManagerListener >(this) );
+ }
+ catch ( css::lang::DisposedException& )
+ {
+ }
+ catch ( const css::uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch ( css::uno::Exception& )
+ {
+ }
+}
+
+
+// XEventListener
+
+void SAL_CALL LayoutManagerListener::disposing(
+ const css::lang::EventObject& )
+{
+ SolarMutexGuard aGuard;
+ m_pWrkWin = nullptr;
+ m_bHasFrame = false;
+ m_xFrame.clear();
+}
+
+
+// XLayoutManagerEventListener
+
+void SAL_CALL LayoutManagerListener::layoutEvent(
+ const css::lang::EventObject&,
+ ::sal_Int16 eLayoutEvent,
+ const css::uno::Any& )
+{
+ SolarMutexGuard aGuard;
+ if ( !m_pWrkWin )
+ return;
+
+ if ( eLayoutEvent == css::frame::LayoutManagerEvents::VISIBLE )
+ {
+ m_pWrkWin->MakeVisible_Impl( true );
+ m_pWrkWin->ShowChildren_Impl();
+ m_pWrkWin->ArrangeChildren_Impl();
+ }
+ else if ( eLayoutEvent == css::frame::LayoutManagerEvents::INVISIBLE )
+ {
+ m_pWrkWin->MakeVisible_Impl( false );
+ m_pWrkWin->HideChildren_Impl();
+ m_pWrkWin->ArrangeChildren_Impl();
+ }
+ else if ( eLayoutEvent == css::frame::LayoutManagerEvents::LOCK )
+ {
+ m_pWrkWin->Lock_Impl( true );
+ }
+ else if ( eLayoutEvent == css::frame::LayoutManagerEvents::UNLOCK )
+ {
+ m_pWrkWin->Lock_Impl( false );
+ }
+}
+
+namespace
+{
+ struct ToolbarIdHash
+ {
+ size_t operator()(ToolbarId t) const
+ {
+ typedef std::underlying_type<ToolbarId>::type underlying_type;
+ return std::hash<underlying_type>()(static_cast<underlying_type>(t));
+ }
+ };
+
+ class FilledToolBarResIdToResourceURLMap
+ {
+ private:
+ typedef std::unordered_map<ToolbarId, OUString, ToolbarIdHash> ToolBarResIdToResourceURLMap;
+ ToolBarResIdToResourceURLMap m_aResIdToResourceURLMap;
+ public:
+ FilledToolBarResIdToResourceURLMap()
+ {
+ sal_Int32 nIndex( 0 );
+ while (pToolBarResToName[nIndex].eId != ToolbarId::None)
+ {
+ OUString aResourceURL( OUString::createFromAscii( pToolBarResToName[nIndex].pName ));
+ m_aResIdToResourceURLMap.emplace(pToolBarResToName[nIndex].eId, aResourceURL);
+ ++nIndex;
+ }
+ }
+
+ OUString findURL(ToolbarId eId) const
+ {
+ ToolBarResIdToResourceURLMap::const_iterator aIter = m_aResIdToResourceURLMap.find(eId);
+ if ( aIter != m_aResIdToResourceURLMap.end() )
+ return aIter->second;
+ return OUString();
+ }
+ };
+}
+
+static OUString GetResourceURLFromToolbarId(ToolbarId eId)
+{
+ static FilledToolBarResIdToResourceURLMap theFilledToolBarResIdToResourceURLMap;
+ return theFilledToolBarResIdToResourceURLMap.findURL(eId);
+}
+
+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 );
+ }
+ }
+
+ bSorted = true;
+}
+
+constexpr OUStringLiteral g_aStatusBarResName( u"private:resource/statusbar/statusbar" );
+constexpr OUStringLiteral g_aTbxTypeName( u"private:resource/toolbar/" );
+constexpr OUStringLiteral g_aProgressBarResName( u"private:resource/progressbar/progressbar" );
+
+// constructor for workwin of a Frame
+
+SfxWorkWindow::SfxWorkWindow( vcl::Window *pWin, SfxFrame *pFrm, SfxFrame* pMaster ) :
+ pBindings(&pFrm->GetCurrentViewFrame()->GetBindings()),
+ pWorkWin (pWin),
+ pActiveChild( nullptr ),
+ nUpdateMode(SfxVisibilityFlags::Standard),
+ nChildren( 0 ),
+ nOrigMode( SfxVisibilityFlags::Invisible ),
+ bSorted( true ),
+ bDockingAllowed(true),
+ bInternalDockingAllowed(true),
+ bAllChildrenVisible(true),
+#if !defined(ANDROID) || HAVE_FEATURE_ANDROID_LOK
+ bIsFullScreen( false ),
+#else // Fennec-based Android Viewer
+ bIsFullScreen( true ),
+#endif
+#if HAVE_FEATURE_DESKTOP
+ bShowStatusBar( true ),
+#else
+ bShowStatusBar( sal_False ),
+#endif
+ m_nLock( 0 ),
+ pMasterFrame( pMaster ),
+ pFrame( pFrm )
+{
+ DBG_ASSERT (pBindings, "No Bindings!");
+
+ pBindings->SetWorkWindow_Impl( std::unique_ptr<SfxWorkWindow>(this) );
+
+ // 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();
+ rtl::Reference<LayoutManagerListener> pLayoutManagerListener = new LayoutManagerListener( this );
+ m_xLayoutManagerListener = pLayoutManagerListener;
+ pLayoutManagerListener->setFrame( xFrame );
+
+ SfxShell* pConfigShell = pFrm->GetCurrentViewFrame();
+ if ( pConfigShell && pConfigShell->GetObjectShell() )
+ {
+ bShowStatusBar = ( !pConfigShell->GetObjectShell()->IsInPlaceActive() );
+ bDockingAllowed = true;
+ bInternalDockingAllowed = true;
+ }
+
+ // 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.
+
+ SfxChildAlignment eAlign =
+ ( n == SFX_SPLITWINDOWS_LEFT ? SfxChildAlignment::LEFT :
+ n == SFX_SPLITWINDOWS_RIGHT ? SfxChildAlignment::RIGHT :
+ n == SFX_SPLITWINDOWS_TOP ? SfxChildAlignment::TOP :
+ SfxChildAlignment::BOTTOM );
+ VclPtr<SfxSplitWindow> pSplitWin = VclPtr<SfxSplitWindow>::Create(pWorkWin, eAlign, this, true );
+ pSplit[n] = pSplitWin;
+ }
+
+ nOrigMode = SfxVisibilityFlags::Standard;
+ nUpdateMode = SfxVisibilityFlags::Standard;
+}
+
+
+// Destructor
+
+SfxWorkWindow::~SfxWorkWindow()
+{
+
+ // Delete SplitWindows
+ for (VclPtr<SfxSplitWindow> & p : pSplit)
+ {
+ if (p->GetWindowCount())
+ ReleaseChild_Impl(*p);
+ p.disposeAndClear();
+ }
+
+ // Delete help structure for Child-Windows
+ DBG_ASSERT( aChildren.empty(), "dangling children" );
+
+ if ( m_xLayoutManagerListener.is() )
+ m_xLayoutManagerListener->dispose();
+}
+
+void SfxWorkWindow::Lock_Impl( bool bLock )
+{
+ if ( bLock )
+ m_nLock++;
+ else
+ --m_nLock;
+ if ( m_nLock<0 )
+ {
+ OSL_FAIL("Lock count underflow!");
+ assert(m_nLock >= 0);
+ m_nLock = 0;
+ }
+
+ if ( !m_nLock )
+ ArrangeChildren_Impl();
+}
+
+
+// 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();
+ }
+
+ // Delete Child-Windows
+ while(!aChildWins.empty())
+ {
+ std::unique_ptr<SfxChildWin_Impl> pCW = std::move(*aChildWins.begin());
+ aChildWins.erase(aChildWins.begin());
+ SfxChildWindow *pChild = pCW->pWin;
+ if (pChild)
+ {
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ vcl::Window* pWindow = pChild->GetWindow();
+ if (pWindow)
+ {
+ pWindow->ReleaseLOKNotifier();
+ }
+ }
+ pChild->Hide();
+
+ // 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());
+ }
+
+ pCW->pWin = nullptr;
+ pWorkWin->GetSystemWindow()->GetTaskPaneList()->RemoveWindow( pChild->GetWindow() );
+ pChild->Destroy();
+ }
+
+ // 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)!!
+ }
+
+ Reference< css::frame::XFrame > xFrame = GetFrameInterface();
+ Reference< css::beans::XPropertySet > xPropSet( xFrame, UNO_QUERY );
+ Reference< css::frame::XLayoutManager > xLayoutManager;
+ if ( xPropSet.is() )
+ {
+ try
+ {
+ Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
+ aValue >>= xLayoutManager;
+ }
+ catch ( Exception& )
+ {
+ }
+ }
+
+ 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;
+
+ nChildren = 0;
+}
+
+
+// for placing the child window.
+
+void SfxWorkWindow::ArrangeChildren_Impl( bool bForce )
+{
+ if ( pFrame->IsClosing_Impl() || ( m_nLock && !bForce ))
+ return;
+
+ SfxInPlaceClient *pClient = nullptr;
+ SfxViewFrame *pF = pFrame->GetCurrentViewFrame();
+ if ( pF && pF->GetViewShell() )
+ pClient = pF->GetViewShell()->GetIPClient();
+
+ if ( pClient )
+ return;
+
+ 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())
+
+ pMasterFrame->SetToolSpaceBorderPixel_Impl( aBorder );
+
+ ArrangeAutoHideWindows( nullptr );
+}
+
+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;
+
+ if ( pCli->bResize )
+ aSize = pCli->aSize;
+ else
+ aSize = pCli->pWin->GetSizePixel();
+
+ SvBorder aTemp = aBorder;
+ bool bAllowHiding = true;
+ switch ( pCli->eAlign )
+ {
+ case SfxChildAlignment::HIGHESTTOP:
+ case SfxChildAlignment::TOP:
+ case SfxChildAlignment::TOOLBOXTOP:
+ case SfxChildAlignment::LOWESTTOP:
+ aSize.setWidth( aTmp.GetWidth() );
+ if ( pCli->pWin->GetType() == WindowType::SPLITWINDOW )
+ aSize = static_cast<SplitWindow *>(pCli->pWin.get())->CalcLayoutSizePixel( aSize );
+ bAllowHiding = false;
+ aBorder.Top() += aSize.Height();
+ aPos = aTmp.TopLeft();
+ aTmp.AdjustTop(aSize.Height() );
+ if ( pCli->eAlign == SfxChildAlignment::HIGHESTTOP )
+ aUpperClientArea.AdjustTop(aSize.Height() );
+ break;
+
+ case SfxChildAlignment::LOWESTBOTTOM:
+ case SfxChildAlignment::BOTTOM:
+ case SfxChildAlignment::TOOLBOXBOTTOM:
+ case SfxChildAlignment::HIGHESTBOTTOM:
+ aSize.setWidth( aTmp.GetWidth() );
+ if ( pCli->pWin->GetType() == WindowType::SPLITWINDOW )
+ aSize = static_cast<SplitWindow *>(pCli->pWin.get())->CalcLayoutSizePixel( aSize );
+ aBorder.Bottom() += aSize.Height();
+ aPos = aTmp.BottomLeft();
+ aPos.AdjustY( -(aSize.Height()-1) );
+ aTmp.AdjustBottom( -(aSize.Height()) );
+ if ( pCli->eAlign == SfxChildAlignment::LOWESTBOTTOM )
+ aUpperClientArea.AdjustBottom( -(aSize.Height()) );
+ break;
+
+ case SfxChildAlignment::FIRSTLEFT:
+ case SfxChildAlignment::LEFT:
+ case SfxChildAlignment::LASTLEFT:
+ case SfxChildAlignment::TOOLBOXLEFT:
+ aSize.setHeight( aTmp.GetHeight() );
+ if ( pCli->pWin->GetType() == WindowType::SPLITWINDOW )
+ aSize = static_cast<SplitWindow *>(pCli->pWin.get())->CalcLayoutSizePixel( aSize );
+ bAllowHiding = false;
+ aBorder.Left() += aSize.Width();
+ aPos = aTmp.TopLeft();
+ aTmp.AdjustLeft(aSize.Width() );
+ if ( pCli->eAlign != SfxChildAlignment::TOOLBOXLEFT )
+ aUpperClientArea.AdjustLeft(aSize.Width() );
+ break;
+
+ case SfxChildAlignment::FIRSTRIGHT:
+ case SfxChildAlignment::RIGHT:
+ case SfxChildAlignment::LASTRIGHT:
+ case SfxChildAlignment::TOOLBOXRIGHT:
+ aSize.setHeight( aTmp.GetHeight() );
+ if ( pCli->pWin->GetType() == WindowType::SPLITWINDOW )
+ aSize = static_cast<SplitWindow *>(pCli->pWin.get())->CalcLayoutSizePixel( aSize );
+ aBorder.Right() += aSize.Width();
+ aPos = aTmp.TopRight();
+ aPos.AdjustX( -(aSize.Width()-1) );
+ aTmp.AdjustRight( -(aSize.Width()) );
+ if ( pCli->eAlign != SfxChildAlignment::TOOLBOXRIGHT )
+ aUpperClientArea.AdjustRight( -(aSize.Width()) );
+ break;
+
+ default:
+ pCli->aSize = pCli->pWin->GetSizePixel();
+ pCli->bResize = false;
+ continue;
+ }
+
+ pCli->pWin->SetPosSizePixel( aPos, aSize );
+ pCli->bResize = false;
+ pCli->aSize = aSize;
+ if( bAllowHiding && !RequestTopToolSpacePixel_Impl( aBorder ) )
+ {
+ pCli->nVisible ^= SfxChildVisibility::FITS_IN;
+ aBorder = aTemp;
+ }
+ }
+
+ if ( aClientArea.GetWidth() >= aBorder.Left() + aBorder.Right() )
+ {
+ aClientArea.AdjustLeft(aBorder.Left() );
+ aClientArea.AdjustRight( -(aBorder.Right()) );
+ }
+ else
+ {
+ aBorder.Left() = aClientArea.Left();
+ aBorder.Right() = aClientArea.Right();
+ aClientArea.SetRight( aTmp.Left() );
+ aClientArea.SetLeft( aTmp.Left() );
+ }
+
+ if ( aClientArea.GetHeight() >= aBorder.Top() + aBorder.Bottom() )
+ {
+ aClientArea.AdjustTop(aBorder.Top() );
+ aClientArea.AdjustBottom( -(aBorder.Bottom()) );
+ }
+ else
+ {
+ aBorder.Top() = aClientArea.Top();
+ aBorder.Bottom() = aClientArea.Bottom();
+ aClientArea.SetTop(aTmp.Top());
+ aClientArea.SetBottom(aTmp.Top());
+ }
+
+ return IsDockingAllowed() ? aBorder : SvBorder();
+}
+
+bool SfxWorkWindow::PrepareClose_Impl()
+{
+ for (const std::unique_ptr<SfxChildWin_Impl> &pCW : aChildWins)
+ {
+ SfxChildWindow *pChild = pCW->pWin;
+ if ( pChild && !pChild->QueryClose() )
+ return false;
+ }
+
+ return true;
+}
+
+SfxChild_Impl* SfxWorkWindow::RegisterChild_Impl( vcl::Window& rWindow,
+ SfxChildAlignment eAlign )
+{
+ DBG_ASSERT( aChildren.size() < 255, "too many children" );
+ DBG_ASSERT( SfxChildAlignValid(eAlign), "invalid align" );
+ DBG_ASSERT( !FindChild_Impl(&rWindow), "child registered more than once" );
+
+
+ if ( rWindow.GetParent() != pWorkWin )
+ rWindow.SetParent( pWorkWin );
+
+ auto pChild = std::make_unique<SfxChild_Impl>(rWindow, rWindow.GetSizePixel(),
+ eAlign, rWindow.IsVisible());
+
+ aChildren.push_back(std::move(pChild));
+ bSorted = false;
+ nChildren++;
+ return aChildren.back().get();
+}
+
+SfxChild_Impl* SfxWorkWindow::RegisterChild_Impl(std::shared_ptr<SfxDialogController>& rController,
+ SfxChildAlignment eAlign )
+{
+ DBG_ASSERT( aChildren.size() < 255, "too many children" );
+ DBG_ASSERT( SfxChildAlignValid(eAlign), "invalid align" );
+
+ auto pChild = std::make_unique<SfxChild_Impl>(rController, eAlign);
+
+ aChildren.push_back(std::move(pChild));
+ bSorted = false;
+ nChildren++;
+ return aChildren.back().get();
+}
+
+void SfxWorkWindow::ReleaseChild_Impl( vcl::Window& rWindow )
+{
+
+ SfxChild_Impl *pChild = nullptr;
+ decltype(aChildren)::size_type nPos;
+ for ( nPos = 0; nPos < aChildren.size(); ++nPos )
+ {
+ pChild = aChildren[nPos].get();
+ if ( pChild && pChild->pWin == &rWindow )
+ {
+ bSorted = false;
+ nChildren--;
+ aChildren.erase(aChildren.begin() + nPos);
+ return;
+ }
+ }
+ OSL_FAIL( "releasing unregistered child" );
+}
+
+void SfxWorkWindow::ReleaseChild_Impl(const SfxDialogController& rController)
+{
+
+ SfxChild_Impl *pChild = nullptr;
+ decltype(aChildren)::size_type nPos;
+ for ( nPos = 0; nPos < aChildren.size(); ++nPos )
+ {
+ pChild = aChildren[nPos].get();
+ if (pChild && pChild->xController.get() == &rController)
+ {
+ bSorted = false;
+ nChildren--;
+ aChildren.erase(aChildren.begin() + nPos);
+ return;
+ }
+ }
+ OSL_FAIL( "releasing unregistered child" );
+}
+
+SfxChild_Impl* SfxWorkWindow::FindChild_Impl( const vcl::Window* rWindow ) const
+{
+
+ sal_uInt16 nCount = aChildren.size();
+ for ( sal_uInt16 nPos = 0; nPos < nCount; ++nPos )
+ {
+ SfxChild_Impl *pChild = aChildren[nPos].get();
+ if ( pChild && pChild->pWin == rWindow )
+ return pChild;
+ }
+
+ return nullptr;
+}
+
+void SfxWorkWindow::ShowChildren_Impl()
+{
+ bool bInvisible = ( !IsVisible_Impl() || ( !pWorkWin->IsReallyVisible() && !pWorkWin->IsReallyShown() ));
+
+ 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);
+ else if (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" );
+
+ SfxObjectBar_Impl aObjBar;
+ aObjBar.eId = eId;
+ aObjBar.nMode = nFlags;
+
+ for (SfxObjectBar_Impl & rBar : aObjBarList)
+ {
+ if ( rBar.eId == aObjBar.eId )
+ {
+ rBar = aObjBar;
+ return;
+ }
+ }
+
+ aObjBarList.push_back( aObjBar );
+}
+
+bool SfxWorkWindow::IsVisible_Impl( SfxVisibilityFlags nMode ) const
+{
+ switch( nUpdateMode )
+ {
+ case SfxVisibilityFlags::Standard:
+ return true;
+ case SfxVisibilityFlags::Invisible:
+ return false;
+ case SfxVisibilityFlags::Client:
+ case SfxVisibilityFlags::Server:
+ return bool(nMode & nUpdateMode);
+ default:
+ return (nMode & nOrigMode ) ||
+ nOrigMode == SfxVisibilityFlags::Standard;
+ }
+}
+
+void SfxWorkWindow::UpdateObjectBars_Impl()
+{
+ if ( pFrame->IsClosing_Impl() )
+ return;
+
+ UpdateObjectBars_Impl2();
+
+ {
+ ArrangeChildren_Impl( false );
+
+ ShowChildren_Impl();
+ }
+
+ ShowChildren_Impl();
+}
+
+Reference< css::task::XStatusIndicator > SfxWorkWindow::GetStatusIndicator()
+{
+ Reference< css::beans::XPropertySet > xPropSet( GetFrameInterface(), UNO_QUERY );
+ Reference< css::frame::XLayoutManager > xLayoutManager;
+ Reference< css::task::XStatusIndicator > xStatusIndicator;
+
+ if ( xPropSet.is() )
+ {
+ Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
+ aValue >>= xLayoutManager;
+ if ( xLayoutManager.is() )
+ {
+ xLayoutManager->createElement( g_aProgressBarResName );
+ xLayoutManager->showElement( g_aProgressBarResName );
+
+ Reference< css::ui::XUIElement > xProgressBar =
+ xLayoutManager->getElement( g_aProgressBarResName );
+ if ( xProgressBar.is() )
+ {
+ xStatusIndicator.set( xProgressBar->getRealInterface(), UNO_QUERY );
+ }
+ }
+ }
+
+ return xStatusIndicator;
+}
+
+
+bool SfxWorkWindow::IsPluginMode( SfxObjectShell const * pObjShell )
+{
+ if ( pObjShell && pObjShell->GetMedium() )
+ {
+ const SfxBoolItem* pViewOnlyItem = SfxItemSet::GetItem<SfxBoolItem>(pObjShell->GetMedium()->GetItemSet(), SID_VIEWONLY, false);
+ if ( pViewOnlyItem && pViewOnlyItem->GetValue() )
+ return true;
+ }
+
+ return false;
+}
+
+
+css::uno::Reference< css::frame::XFrame > SfxWorkWindow::GetFrameInterface()
+{
+ css::uno::Reference< css::frame::XFrame > xFrame;
+
+ SfxDispatcher* pDispatcher( GetBindings().GetDispatcher() );
+ if ( pDispatcher )
+ {
+ SfxViewFrame* pViewFrame = pDispatcher->GetFrame();
+ if ( pViewFrame )
+ xFrame = pViewFrame->GetFrame().GetFrameInterface();
+ }
+
+ return xFrame;
+}
+
+
+void SfxWorkWindow::UpdateObjectBars_Impl2()
+{
+ // 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();
+ }
+
+ Reference< css::beans::XPropertySet > xPropSet( GetFrameInterface(), UNO_QUERY );
+ Reference< css::frame::XLayoutManager > xLayoutManager;
+
+ if ( xPropSet.is() )
+ {
+ Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
+ aValue >>= xLayoutManager;
+ }
+
+ if ( !xLayoutManager.is() )
+ return;
+
+ bool bPluginMode( false );
+ SfxDispatcher* pDispatcher( GetBindings().GetDispatcher() );
+
+ if ( pDispatcher )
+ {
+ SfxViewFrame* pViewFrame = pDispatcher->GetFrame();
+ if ( pViewFrame )
+ bPluginMode = IsPluginMode( pViewFrame->GetObjectShell() );
+ }
+
+ // Iterate over all Toolboxes
+ xLayoutManager->lock();
+ const bool isNotebookBarActive = sfx2::SfxNotebookBar::IsActive();
+ for ( auto const & n: aObjBarList )
+ {
+ ToolbarId eId = n.eId;
+ bool bDestroy = n.bDestroy;
+
+ // Determine the valid mode for the ToolBox
+ SfxVisibilityFlags nTbxMode = n.nMode;
+ bool bFullScreenTbx( nTbxMode & SfxVisibilityFlags::FullScreen );
+ nTbxMode &= ~SfxVisibilityFlags::FullScreen;
+ nTbxMode &= ~SfxVisibilityFlags::Viewer;
+
+ // Is a ToolBox required in this context ?
+ bool bModesMatching = (nUpdateMode != SfxVisibilityFlags::Invisible) && ((nTbxMode & nUpdateMode) == nUpdateMode);
+ if ( bDestroy || isNotebookBarActive)
+ {
+ OUString aTbxId = g_aTbxTypeName + GetResourceURLFromToolbarId(eId);
+ xLayoutManager->destroyElement( aTbxId );
+ }
+ else if ( eId != ToolbarId::None && ( ( bModesMatching && !bIsFullScreen ) ||
+ ( bIsFullScreen && bFullScreenTbx ) ) )
+ {
+ OUString aTbxId = g_aTbxTypeName + GetResourceURLFromToolbarId(eId);
+ if ( !IsDockingAllowed() && !xLayoutManager->isElementFloating( aTbxId ))
+ xLayoutManager->destroyElement( aTbxId );
+ else
+ {
+ xLayoutManager->requestElement( aTbxId );
+ if ( bPluginMode )
+ xLayoutManager->lockWindow( aTbxId );
+ }
+ }
+ else if ( eId != ToolbarId::None )
+ {
+ // Delete the Toolbox at this Position if possible
+ OUString aTbxId = g_aTbxTypeName + GetResourceURLFromToolbarId(eId);
+ xLayoutManager->destroyElement( aTbxId );
+ }
+ }
+
+ UpdateStatusBar_Impl();
+
+ // unlocking automatically forces Layout
+ xLayoutManager->unlock();
+
+ UpdateChildWindows_Impl();
+
+ // 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 );
+ }
+ else if ( !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;
+ }
+ else if ( 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();
+ }
+ }
+ }
+ }
+
+ if ( pChildWin && !bCreate )
+ {
+ if ( !pChildWin->QueryClose() || pChildWin->IsHideNotDelete() || Application::IsUICaptured() )
+ {
+ if ( pCW->pCli )
+ {
+ if ( pCW->pCli->nVisible & SfxChildVisibility::NOT_HIDDEN )
+ pCW->pCli->nVisible ^= SfxChildVisibility::NOT_HIDDEN;
+ }
+ else
+ static_cast<SfxDockingWindow*>(pChildWin->GetWindow())->Disappear_Impl();
+ }
+ else
+ RemoveChildWin_Impl( pCW );
+ }
+ }
+}
+
+void SfxWorkWindow::CreateChildWin_Impl( SfxChildWin_Impl *pCW, bool bSetFocus )
+{
+ pCW->aInfo.bVisible = true;
+
+ 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);
+
+ sal_uInt16 nPos = pChildWin->GetPosition();
+ if (nPos != CHILDWIN_NOPOS)
+ {
+ DBG_ASSERT(nPos < SFX_OBJECTBAR_MAX, "Illegal objectbar position!");
+ if ( aChildren[TbxMatch(nPos)] )// &&
+ {
+ // ChildWindow replaces ObjectBar
+ aChildren[TbxMatch(nPos)]->nVisible ^= SfxChildVisibility::NOT_HIDDEN;
+ }
+ }
+
+ // 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);
+}
+
+void SfxWorkWindow::RemoveChildWin_Impl( SfxChildWin_Impl *pCW )
+{
+ sal_uInt16 nId = pCW->nSaveId;
+ SfxChildWindow *pChildWin = pCW->pWin;
+
+ // 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.
+ }
+
+ pWorkWin->GetSystemWindow()->GetTaskPaneList()->RemoveWindow( pChildWin->GetWindow() );
+ pCW->pWin = nullptr;
+ pChildWin->Destroy();
+
+ GetBindings().Invalidate( nId );
+}
+
+void SfxWorkWindow::ResetStatusBar_Impl()
+{
+ aStatBar.eId = StatusBarId::None;
+}
+
+void SfxWorkWindow::SetStatusBar_Impl(StatusBarId eId)
+{
+ if (eId != StatusBarId::None && bShowStatusBar && IsVisible_Impl())
+ aStatBar.eId = eId;
+}
+
+void SfxWorkWindow::UpdateStatusBar_Impl()
+{
+ Reference< css::beans::XPropertySet > xPropSet( GetFrameInterface(), UNO_QUERY );
+ Reference< css::frame::XLayoutManager > xLayoutManager;
+
+ 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 );
+ }
+}
+
+void SfxWorkWindow::MakeVisible_Impl( bool bVis )
+{
+ if ( bVis )
+ nOrigMode = SfxVisibilityFlags::Standard;
+ else
+ nOrigMode = SfxVisibilityFlags::Invisible;
+
+ if ( nOrigMode != nUpdateMode)
+ nUpdateMode = nOrigMode;
+}
+
+bool SfxWorkWindow::IsVisible_Impl() const
+{
+ return nOrigMode != SfxVisibilityFlags::Invisible;
+}
+
+
+void SfxWorkWindow::HidePopups_Impl(bool bHide, sal_uInt16 nId )
+{
+ if (comphelper::LibreOfficeKit::isActive() && bHide)
+ return;
+
+ for (const std::unique_ptr<SfxChildWin_Impl>& i : aChildWins)
+ {
+ SfxChildWindow *pCW = i->pWin;
+ if (pCW && pCW->GetAlignment() == SfxChildAlignment::NOALIGNMENT && pCW->GetType() != nId)
+ {
+ vcl::Window *pWin = pCW->GetWindow();
+ SfxChild_Impl *pChild = FindChild_Impl(pWin);
+ if (!pChild)
+ {
+ SAL_WARN("sfx.appl", "missing SfxChild_Impl child!");
+ continue;
+ }
+ if (bHide)
+ {
+ pChild->nVisible &= ~SfxChildVisibility::ACTIVE;
+ pCW->Hide();
+ }
+ else if ( !comphelper::LibreOfficeKit::isActive() ||
+ SfxChildVisibility::ACTIVE != (pChild->nVisible & SfxChildVisibility::ACTIVE) )
+ {
+ pChild->nVisible |= SfxChildVisibility::ACTIVE;
+ if ( SfxChildVisibility::VISIBLE == (pChild->nVisible & SfxChildVisibility::VISIBLE) )
+ pCW->Show( ShowFlags::NoFocusChange | ShowFlags::NoActivate );
+ }
+ }
+ }
+}
+
+
+void SfxWorkWindow::ConfigChild_Impl(SfxChildIdentifier eChild,
+ SfxDockingConfig eConfig, sal_uInt16 nId)
+{
+ SfxDockingWindow* pDockWin=nullptr;
+ sal_uInt16 nPos = USHRT_MAX;
+ vcl::Window *pWin=nullptr;
+ SfxChildWin_Impl *pCW = nullptr;
+
+ // configure direct childwindow
+ for (const std::unique_ptr<SfxChildWin_Impl>& i : aChildWins)
+ {
+ pCW = i.get();
+ SfxChildWindow *pChild = pCW->pWin;
+ if ( pChild && (pChild->GetType() == nId ))
+ {
+ if (SfxDockingWindow* pSfxDockingWindow = dynamic_cast<SfxDockingWindow*>(pChild->GetWindow()))
+ {
+ // it's a DockingWindow
+ pDockWin = pSfxDockingWindow;
+ }
+ else
+ {
+ // FloatingWindow or ModelessDialog
+ pWin = pChild->GetWindow();
+ }
+ break;
+ }
+ }
+
+ if ( pDockWin )
+ {
+ if ( eChild == SfxChildIdentifier::DOCKINGWINDOW || pDockWin->GetAlignment() == SfxChildAlignment::NOALIGNMENT )
+ {
+ if ( eChild == SfxChildIdentifier::SPLITWINDOW && eConfig == SfxDockingConfig::TOGGLEFLOATMODE)
+ {
+ // DockingWindow was dragged out of a SplitWindow
+ pCW->pCli = RegisterChild_Impl(*pDockWin, pDockWin->GetAlignment());
+ pCW->pCli->nVisible = SfxChildVisibility::VISIBLE;
+ }
+
+ pWin = pDockWin;
+ }
+ else
+ {
+ SfxSplitWindow *pSplitWin = GetSplitWindow_Impl(pDockWin->GetAlignment());
+
+ // configure DockingWindow inside a SplitWindow
+ if ( eConfig == SfxDockingConfig::TOGGLEFLOATMODE)
+ {
+ // DockingWindow was dragged into a SplitWindow
+ pCW->pCli = nullptr;
+ ReleaseChild_Impl(*pDockWin);
+ }
+
+ pWin = pSplitWin->GetSplitWindow();
+ if ( pSplitWin->GetWindowCount() == 1 )
+ static_cast<SplitWindow*>(pWin)->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
+ }
+ }
+
+ DBG_ASSERT( pCW, "Unknown window!" );
+
+ if ( !bSorted )
+ // windows may have been registered and released without an update until now
+ Sort_Impl();
+
+ decltype(aSortedList)::size_type n;
+ for ( n=0; n<aSortedList.size(); ++n )
+ {
+ SfxChild_Impl *pChild = aChildren[aSortedList[n]].get();
+ if ( pChild && pChild->pWin == pWin )
+ break;
+ }
+
+ if ( n < aSortedList.size() )
+ // sometimes called while toggling float mode
+ nPos = aSortedList[n];
+
+ switch ( eConfig )
+ {
+ case SfxDockingConfig::SETDOCKINGRECTS :
+ {
+ if (nPos == USHRT_MAX || !pDockWin)
+ return;
+
+ tools::Rectangle aOuterRect( GetTopRect_Impl() );
+ aOuterRect.SetPos( pWorkWin->OutputToScreenPixel( aOuterRect.TopLeft() ));
+ tools::Rectangle aInnerRect( aOuterRect );
+
+ // 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;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ pDockWin->SetDockingRects(aOuterRect, aInnerRect);
+ break;
+ }
+
+ case SfxDockingConfig::ALIGNDOCKINGWINDOW :
+ case SfxDockingConfig::TOGGLEFLOATMODE:
+ {
+ if ( nPos == USHRT_MAX && !pCW )
+ return;
+
+ SfxChildAlignment eAlign = SfxChildAlignment::NOALIGNMENT;
+ SfxChild_Impl *pCli = ( nPos != USHRT_MAX ) ? aChildren[nPos].get() : nullptr;
+ if ( pCli && pDockWin )
+ {
+ eAlign = pDockWin->GetAlignment();
+ if ( eChild == SfxChildIdentifier::DOCKINGWINDOW || eAlign == SfxChildAlignment::NOALIGNMENT)
+ {
+ // configuration inside the SplitWindow, no change for the SplitWindows' configuration
+ pCli->bResize = true;
+ pCli->aSize = pDockWin->GetSizePixel();
+ }
+ }
+
+ if ( pCli )
+ {
+ if( pCli->eAlign != eAlign )
+ {
+ bSorted = false;
+ pCli->eAlign = eAlign;
+ }
+
+ ArrangeChildren_Impl();
+ ShowChildren_Impl();
+ }
+
+ if ( pCW && pCW->pWin )
+ {
+ // store changed configuration
+ SfxChildWindowFlags nFlags = pCW->aInfo.nFlags;
+ pCW->aInfo = pCW->pWin->GetInfo();
+ pCW->aInfo.nFlags |= nFlags;
+ SaveStatus_Impl( pCW->pWin, pCW->aInfo);
+ }
+
+ break;
+ }
+ }
+}
+
+
+void SfxWorkWindow::SetChildWindowVisible_Impl( sal_uInt32 lId, bool bEnabled, SfxVisibilityFlags nMode )
+{
+ sal_uInt16 nId = static_cast<sal_uInt16>( lId & 0xFFFF );
+
+ SfxChildWin_Impl *pCW=nullptr;
+
+ if ( !pCW )
+ {
+ // If no Parent or the Parent us still unknown, then search here
+ sal_uInt16 nCount = aChildWins.size();
+ for (sal_uInt16 n=0; n<nCount; n++)
+ if (aChildWins[n]->nSaveId == nId)
+ {
+ pCW = aChildWins[n].get();
+ 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) );
+ }
+
+ pCW->nId = nId;
+ pCW->nVisibility = nMode;
+ pCW->bEnable = bEnabled;
+}
+
+
+// The on/off status of a ChildWindow is switched
+
+void SfxWorkWindow::ToggleChildWindow_Impl(sal_uInt16 nId, bool bSetFocus)
+{
+ sal_uInt16 nCount = aChildWins.size();
+ sal_uInt16 n;
+ for (n=0; n<nCount; n++)
+ if (aChildWins[n]->nId == nId)
+ break;
+
+ if ( n<nCount )
+ {
+ // The Window is already known
+ SfxChildWin_Impl *pCW = aChildWins[n].get();
+ 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
+ nCount = aChildWins.size();
+ for (n=0; n<nCount; n++)
+ if (aChildWins[n]->nSaveId == nId)
+ break;
+
+ if ( n < nCount )
+ {
+ OSL_FAIL("The ChildWindow is not in context!");
+ }
+ else
+ {
+ OSL_FAIL("The ChildWindow is not registered!");
+ }
+#endif
+}
+
+
+bool SfxWorkWindow::HasChildWindow_Impl(sal_uInt16 nId)
+{
+ sal_uInt16 nCount = aChildWins.size();
+ sal_uInt16 n;
+ for (n=0; n<nCount; n++)
+ if (aChildWins[n]->nSaveId == nId)
+ break;
+
+ if (n<nCount)
+ {
+ SfxChildWin_Impl *pCW = aChildWins[n].get();
+ SfxChildWindow *pChild = pCW->pWin;
+ return ( pChild && pCW->bCreate );
+ }
+
+ return false;
+}
+
+bool SfxWorkWindow::IsFloating( sal_uInt16 nId )
+{
+ SfxChildWin_Impl *pCW=nullptr;
+
+ if ( !pCW )
+ {
+ // If no Parent or the Parent us still unknown, then search here
+ sal_uInt16 nCount = aChildWins.size();
+ for (sal_uInt16 n=0; n<nCount; n++)
+ if (aChildWins[n]->nSaveId == nId)
+ {
+ pCW = aChildWins[n].get();
+ break;
+ }
+ }
+
+ 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) );
+ }
+
+ SfxChildAlignment eAlign;
+ if ( pCW->aInfo.GetExtraData_Impl( &eAlign ) )
+ return( eAlign == SfxChildAlignment::NOALIGNMENT );
+ else
+ return true;
+}
+
+
+bool SfxWorkWindow::KnowsChildWindow_Impl(sal_uInt16 nId)
+{
+ SfxChildWin_Impl *pCW=nullptr;
+ sal_uInt16 nCount = aChildWins.size();
+ sal_uInt16 n;
+ for (n=0; n<nCount; n++)
+ {
+ pCW = aChildWins[n].get();
+ if ( pCW->nSaveId == nId)
+ break;
+ }
+
+ if (n<nCount)
+ {
+ if ( !(pCW->aInfo.nFlags & SfxChildWindowFlags::ALWAYSAVAILABLE) && !IsVisible_Impl( pCW->nVisibility ) )
+ return false;
+ return pCW->bEnable;
+ }
+ else
+ return false;
+}
+
+
+void SfxWorkWindow::SetChildWindow_Impl(sal_uInt16 nId, bool bOn, bool bSetFocus)
+{
+ SfxChildWin_Impl *pCW=nullptr;
+ SfxWorkWindow *pWork = nullptr;
+
+ if ( !pCW )
+ {
+ // If no Parent or the Parent us still unknown, then search here
+ sal_uInt16 nCount = aChildWins.size();
+ for (sal_uInt16 n=0; n<nCount; n++)
+ if (aChildWins[n]->nSaveId == nId)
+ {
+ pCW = aChildWins[n].get();
+ pWork = this;
+ break;
+ }
+ }
+
+ if ( !pCW )
+ {
+ // If new, then initialize, add this here depending on the flag or
+ // the Parent
+ pCW = new SfxChildWin_Impl( nId );
+ InitializeChild_Impl( pCW );
+ if ( !pWork || pCW->aInfo.nFlags & SfxChildWindowFlags::TASK )
+ pWork = this;
+ pWork->aChildWins.push_back( std::unique_ptr<SfxChildWin_Impl>(pCW) );
+ }
+
+ if ( pCW->bCreate != bOn )
+ pWork->ToggleChildWindow_Impl(nId,bSetFocus);
+}
+
+
+void SfxWorkWindow::ShowChildWindow_Impl(sal_uInt16 nId, bool bVisible, bool bSetFocus)
+{
+ sal_uInt16 nCount = aChildWins.size();
+ SfxChildWin_Impl* pCW=nullptr;
+ sal_uInt16 n;
+ for (n=0; n<nCount; n++)
+ {
+ pCW = aChildWins[n].get();
+ if (pCW->nId == nId)
+ break;
+ }
+
+ if ( n<nCount )
+ {
+ SfxChildWindow *pChildWin = pCW->pWin;
+ if ( pChildWin )
+ {
+ if ( bVisible )
+ {
+ if ( pCW->pCli )
+ {
+ pCW->pCli->bSetFocus = bSetFocus;
+ pCW->pCli->nVisible = SfxChildVisibility::VISIBLE;
+ pChildWin->Show( bSetFocus && pChildWin->WantsFocus() ? ShowFlags::NONE : ShowFlags::NoFocusChange | ShowFlags::NoActivate );
+ }
+ else
+ static_cast<SfxDockingWindow*>(pChildWin->GetWindow())->Reappear_Impl();
+
+ }
+ else
+ {
+ if ( pCW->pCli )
+ {
+ pCW->pCli->nVisible = SfxChildVisibility::VISIBLE ^ SfxChildVisibility::NOT_HIDDEN;
+ pCW->pWin->Hide();
+ }
+ else
+ static_cast<SfxDockingWindow*>(pChildWin->GetWindow())->Disappear_Impl();
+
+ }
+
+ ArrangeChildren_Impl();
+ ShowChildren_Impl();
+ }
+ else if ( bVisible )
+ {
+ SetChildWindow_Impl( nId, true, bSetFocus );
+ pChildWin = pCW->pWin;
+ }
+
+ if ( pChildWin )
+ {
+ pChildWin->SetVisible_Impl( bVisible );
+ SfxChildWindowFlags nFlags = pCW->aInfo.nFlags;
+ pCW->aInfo = pChildWin->GetInfo();
+ pCW->aInfo.nFlags |= nFlags;
+ if ( !pCW->bCreate )
+ SaveStatus_Impl( pChildWin, pCW->aInfo );
+ }
+
+ return;
+ }
+
+#ifdef DBG_UTIL
+ nCount = aChildWins.size();
+ for (n=0; n<nCount; n++)
+ if (aChildWins[n]->nSaveId == nId)
+ break;
+
+ if ( n<nCount )
+ {
+ OSL_FAIL("The ChildWindow is not in context!");
+ }
+ else
+ {
+ OSL_FAIL("The ChildWindow is not registered");
+ }
+#endif
+}
+
+
+SfxChildWindow* SfxWorkWindow::GetChildWindow_Impl(sal_uInt16 nId)
+{
+ sal_uInt16 nCount = aChildWins.size();
+ sal_uInt16 n;
+ for (n=0; n<nCount; n++)
+ if (aChildWins[n]->nSaveId == nId)
+ break;
+
+ if (n<nCount)
+ return aChildWins[n]->pWin;
+ return nullptr;
+}
+
+
+void SfxWorkWindow::ResetChildWindows_Impl()
+{
+ for (std::unique_ptr<SfxChildWin_Impl>& pChildWin : aChildWins)
+ {
+ pChildWin->nId = 0;
+ pChildWin->bEnable = false;
+ }
+}
+
+// returns the size of the area (client area) of the
+// parent windows, in which the ChildWindow can be fitted.
+
+tools::Rectangle SfxWorkWindow::GetTopRect_Impl() const
+{
+ return pMasterFrame->GetTopOuterRectPixel_Impl();
+}
+
+
+// Virtual method to find out if there is room for a ChildWindow in the
+// client area of the parent.
+
+bool SfxWorkWindow::RequestTopToolSpacePixel_Impl( SvBorder aBorder )
+{
+ return !(!IsDockingAllowed() ||
+ aClientArea.GetWidth() < aBorder.Left() + aBorder.Right() ||
+ aClientArea.GetHeight() < aBorder.Top() + aBorder.Bottom());
+}
+
+void SfxWorkWindow::SaveStatus_Impl(SfxChildWindow *pChild, const SfxChildWinInfo &rInfo)
+{
+ // The Status of the Presentation mode is not saved
+ if ( IsDockingAllowed() && bInternalDockingAllowed )
+ pChild->SaveStatus(rInfo);
+}
+
+void SfxWorkWindow::InitializeChild_Impl(SfxChildWin_Impl *pCW)
+{
+ SfxDispatcher *pDisp = pBindings->GetDispatcher_Impl();
+ SfxViewFrame *pViewFrame = pDisp ? pDisp->GetFrame() :nullptr;
+ SfxModule *pMod = pViewFrame ? SfxModule::GetActiveModule(pViewFrame) :nullptr;
+
+ OUString sModule;
+ if (pViewFrame)
+ {
+ try
+ {
+ uno::Reference< frame::XModuleManager2 > xModuleManager(
+ frame::ModuleManager::create(::comphelper::getProcessComponentContext()));
+ sModule = xModuleManager->identify(pViewFrame->GetFrame().GetFrameInterface());
+ SvtModuleOptions::EFactory eFac = SvtModuleOptions::ClassifyFactoryByServiceName(sModule);
+ sModule = SvtModuleOptions::GetFactoryShortName(eFac);
+ }
+ catch (...)
+ {
+ }
+ }
+
+ SfxChildWinFactory* pFact=nullptr;
+ SfxApplication *pApp = SfxGetpApp();
+ {
+ pFact = pApp->GetChildWinFactoryById(pCW->nSaveId);
+ if ( pFact )
+ {
+ pCW->aInfo = pFact->aInfo;
+ pCW->aInfo.aModule = sModule;
+ SfxChildWindow::InitializeChildWinFactory_Impl(
+ pCW->nSaveId, pCW->aInfo);
+ pCW->bCreate = pCW->aInfo.bVisible;
+ SfxChildWindowFlags nFlags = pFact->aInfo.nFlags;
+ if ( nFlags & SfxChildWindowFlags::TASK )
+ pCW->aInfo.nFlags |= SfxChildWindowFlags::TASK;
+ if ( nFlags & SfxChildWindowFlags::CANTGETFOCUS )
+ pCW->aInfo.nFlags |= SfxChildWindowFlags::CANTGETFOCUS;
+ if ( nFlags & SfxChildWindowFlags::FORCEDOCK )
+ pCW->aInfo.nFlags |= SfxChildWindowFlags::FORCEDOCK;
+ pFact->aInfo = pCW->aInfo;
+ return;
+ }
+ }
+
+ if ( !pMod )
+ return;
+
+ pFact = pMod->GetChildWinFactoryById(pCW->nSaveId);
+ if ( !pFact )
+ return;
+
+ pCW->aInfo = pFact->aInfo;
+ pCW->aInfo.aModule = sModule;
+ SfxChildWindow::InitializeChildWinFactory_Impl(
+ pCW->nSaveId, pCW->aInfo);
+ pCW->bCreate = pCW->aInfo.bVisible;
+ SfxChildWindowFlags nFlags = pFact->aInfo.nFlags;
+ if ( nFlags & SfxChildWindowFlags::TASK )
+ pCW->aInfo.nFlags |= SfxChildWindowFlags::TASK;
+ if ( nFlags & SfxChildWindowFlags::CANTGETFOCUS )
+ pCW->aInfo.nFlags |= SfxChildWindowFlags::CANTGETFOCUS;
+ if ( nFlags & SfxChildWindowFlags::FORCEDOCK )
+ pCW->aInfo.nFlags |= SfxChildWindowFlags::FORCEDOCK;
+ if ( nFlags & SfxChildWindowFlags::ALWAYSAVAILABLE )
+ pCW->aInfo.nFlags |= SfxChildWindowFlags::ALWAYSAVAILABLE;
+ pFact->aInfo = pCW->aInfo;
+}
+
+SfxSplitWindow* SfxWorkWindow::GetSplitWindow_Impl( SfxChildAlignment eAlign )
+{
+ switch ( eAlign )
+ {
+ case SfxChildAlignment::TOP:
+ return pSplit[2];
+
+ case SfxChildAlignment::BOTTOM:
+ return pSplit[3];
+
+ case SfxChildAlignment::LEFT:
+ return pSplit[0];
+
+ case SfxChildAlignment::RIGHT:
+ return pSplit[1];
+
+ default:
+ return nullptr;
+ }
+}
+
+void SfxWorkWindow::MakeChildrenVisible_Impl( bool bVis )
+{
+ bAllChildrenVisible = bVis;
+ if ( bVis )
+ {
+ if ( !bSorted )
+ Sort_Impl();
+ for (sal_uInt16 n : aSortedList)
+ {
+ SfxChild_Impl* pCli = aChildren[n].get();
+ if ( (pCli->eAlign == SfxChildAlignment::NOALIGNMENT) || (IsDockingAllowed() && bInternalDockingAllowed) )
+ pCli->nVisible |= SfxChildVisibility::ACTIVE;
+ }
+ }
+ else
+ {
+ if ( !bSorted )
+ Sort_Impl();
+ for (sal_uInt16 n : aSortedList)
+ {
+ SfxChild_Impl* pCli = aChildren[n].get();
+ pCli->nVisible &= ~SfxChildVisibility::ACTIVE;
+ }
+ }
+}
+
+bool SfxWorkWindow::IsAutoHideMode( const SfxSplitWindow *pSplitWin )
+{
+ for (const VclPtr<SfxSplitWindow> & pWin : pSplit)
+ {
+ if ( pWin.get() != pSplitWin && pWin->IsAutoHide( true ) )
+ return true;
+ }
+ return false;
+}
+
+
+void SfxWorkWindow::EndAutoShow_Impl( Point aPos )
+{
+ for (VclPtr<SfxSplitWindow> & p : pSplit)
+ {
+ if ( p && p->IsAutoHide(false) )
+ {
+ Point aLocalPos = p->ScreenToOutputPixel( aPos );
+ tools::Rectangle aRect( Point(), p->GetSizePixel() );
+ if ( !aRect.Contains( aLocalPos ) )
+ p->FadeOut();
+ }
+ }
+}
+
+void SfxWorkWindow::ArrangeAutoHideWindows( SfxSplitWindow *pActSplitWin )
+{
+ if ( m_nLock )
+ return;
+
+ tools::Rectangle aArea( aUpperClientArea );
+ for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX; n++ )
+ {
+ // Either dummy window or window in the auto-show-mode are processed
+ // (not pinned, FadeIn).
+ // Only the abandoned window may be invisible, because perhaps its
+ // size is just being calculated before it is displayed.
+ VclPtr<SfxSplitWindow> const & pSplitWin = pSplit[n];
+ bool bDummyWindow = !pSplitWin->IsFadeIn();
+ vcl::Window *pDummy = pSplitWin->GetSplitWindow();
+ vcl::Window *pWin = bDummyWindow ? pDummy : pSplitWin;
+ if ( (pSplitWin->IsPinned() && !bDummyWindow) || (!pWin->IsVisible() && pActSplitWin != pSplitWin) )
+ continue;
+
+ // Width and position of the dummy window as a starting point
+ Size aSize = pDummy->GetSizePixel();
+ Point aPos = pDummy->GetPosPixel();
+
+ switch ( n )
+ {
+ case 0 :
+ {
+ // Left SplitWindow
+ // Get the width of the Window yourself, if no DummyWindow
+ if ( !bDummyWindow )
+ aSize.setWidth( pSplitWin->GetSizePixel().Width() );
+
+ // If a Window is visible to the left, then the free region
+ // starts to the right from it, for example at the Client area
+ tools::Long nLeft = aPos.X() + aSize.Width();
+ if ( nLeft > aArea.Left() )
+ aArea.SetLeft( nLeft );
+ break;
+ }
+ case 1 :
+ {
+ // Right SplitWindow
+ // Position to correct the difference of the widths
+ aPos.AdjustX(aSize.Width() );
+
+ // Get the width of the Window yourself, if no DummyWindow
+ if ( !bDummyWindow )
+ aSize.setWidth( pSplitWin->GetSizePixel().Width() );
+
+ aPos.AdjustX( -(aSize.Width()) );
+
+ // If already a window is opened at the left side, then the
+ // right is not allowed to overlap this one.
+ if ( aPos.X() < aArea.Left() )
+ {
+ aPos.setX( aArea.Left() );
+ aSize.setWidth( aArea.GetWidth() );
+ }
+
+ // If a Window is visible to the right, then the free region
+ // starts to the left from it, for example at the Client area
+ tools::Long nRight = aPos.X();
+ if ( !aArea.IsWidthEmpty() && nRight < aArea.Right() )
+ aArea.SetRight( nRight );
+ break;
+ }
+ case 2 :
+ {
+ // Top SplitWindow
+ // Get the height of the Window yourself, if no DummyWindow
+ if ( !bDummyWindow )
+ aSize.setHeight( pSplitWin->GetSizePixel().Height() );
+
+
+ // Adjust width with regard to if a Window is already open
+ // to the left or right
+ aPos.setX( aArea.Left() );
+ aSize.setWidth( aArea.GetWidth() );
+
+ // If a Window is visible at the top, then the free region
+ // starts beneath it, for example at the Client area
+ tools::Long nTop = aPos.Y() + aSize.Height();
+ if ( nTop > aArea.Top() )
+ aArea.SetTop( nTop );
+ break;
+ }
+ case 3 :
+ {
+ // The bottom SplitWindow
+ // Position to correct the difference of the heights
+ aPos.AdjustY(aSize.Height() );
+
+ // Get the height of the Window yourself, if no DummyWindow
+ if ( !bDummyWindow )
+ aSize.setHeight( pSplitWin->GetSizePixel().Height() );
+
+ aPos.AdjustY( -(aSize.Height()) );
+
+ // Adjust width with regard to if a Window is already open
+ // to the left or right.
+ aPos.setX( aArea.Left() );
+ aSize.setWidth( aArea.GetWidth() );
+
+ // If already a window is opened at the top, then the
+ // bottom one is not allowed to overlap this one.
+ if ( aPos.Y() < aArea.Top() )
+ {
+ aPos.setY( aArea.Top() );
+ aSize.setHeight( aArea.GetHeight() );
+ }
+
+ break;
+ }
+ }
+
+ if ( !bDummyWindow )
+ // the FadeIn-Window is a Floating window, which coordinates are
+ // set in Screen coordinates.
+ pSplitWin->SetPosSizePixel( pWorkWin->OutputToScreenPixel(aPos), aSize );
+ else
+ // the docked DummyWindow
+ pDummy->SetPosSizePixel( aPos, aSize );
+ }
+}
+
+tools::Rectangle SfxWorkWindow::GetFreeArea( bool bAutoHide ) const
+{
+ if ( bAutoHide )
+ {
+ tools::Rectangle aArea( aClientArea );
+ for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX; n++ )
+ {
+ if ( pSplit[n]->IsPinned() || !pSplit[n]->IsVisible() )
+ continue;
+
+ Size aSize = pSplit[n]->GetSizePixel();
+ switch ( n )
+ {
+ case 0 :
+ aArea.AdjustLeft(aSize.Width() );
+ break;
+ case 1 :
+ aArea.AdjustRight( -(aSize.Width()) );
+ break;
+ case 2 :
+ aArea.AdjustTop(aSize.Height() );
+ break;
+ case 3 :
+ aArea.AdjustBottom( -(aSize.Height()) );
+ break;
+ }
+ }
+
+ return aArea;
+ }
+ else
+ return aClientArea;
+}
+
+void SfxWorkWindow::SetActiveChild_Impl( vcl::Window *pChild )
+{
+ pActiveChild = pChild;
+}
+
+void SfxWorkWindow::DataChanged_Impl()
+{
+ ArrangeChildren_Impl();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */