Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/sfx2/source/appl/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 76 kB image not shown  

Quelle  workwin.cxx   Sprache: C

 
/* -*- 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/configuration.hxx>
#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/configmgr.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;
    OUString pName;
};

}

constexpr ResIdToResName pToolBarResToName[] =
{
    { ToolbarId::FullScreenToolbox,       u"fullscreenbar"_ustr        },
    { ToolbarId::EnvToolbox,              u"standardbar"_ustr,         },
    { ToolbarId::SvxTbx_Form_Navigation,  u"formsnavigationbar"_ustr   },
    { ToolbarId::SvxTbx_Form_Filter,      u"formsfilterbar"_ustr       },
    { ToolbarId::SvxTbx_Text_Control_Attributes, u"formtextobjectbar"_ustr    },
    { ToolbarId::SvxTbx_Controls,         u"formcontrols"_ustr         },
    { ToolbarId::SvxTbx_FormDesign,       u"formdesign"_ustr           },
    { ToolbarId::Math_Toolbox,            u"toolbar"_ustr              },      //math
    { ToolbarId::Text_Toolbox_Sc,         u"textobjectbar"_ustr        },      //calc
    { ToolbarId::Draw_Objectbar,          u"drawobjectbar"_ustr        },
    { ToolbarId::Graphic_Objectbar,       u"graphicobjectbar"_ustr     },
    { ToolbarId::Objectbar_Format,        u"formatobjectbar"_ustr      },
    { ToolbarId::Objectbar_Preview,       u"previewbar"_ustr           },
    { ToolbarId::Objectbar_Tools,         u"toolbar"_ustr              },      //calc
    { ToolbarId::Bezier_Toolbox_Sd,       u"bezierobjectbar"_ustr      },      //draw/impress
    { ToolbarId::Gluepoints_Toolbox,      u"gluepointsobjectbar"_ustr  },
    { ToolbarId::Draw_Graf_Toolbox,       u"graphicobjectbar"_ustr     },
    { ToolbarId::Draw_Obj_Toolbox,        u"drawingobjectbar"_ustr     },      //impress
    { ToolbarId::Draw_Text_Toolbox_Sd,    u"textobjectbar"_ustr        },      //impress
    { ToolbarId::Draw_Toolbox_Sd,         u"toolbar"_ustr              },      //impress
    { ToolbarId::Draw_Options_Toolbox,    u"optionsbar"_ustr           },
    { ToolbarId::Draw_CommonTask_Toolbox, u"commontaskbar"_ustr        },
    { ToolbarId::Graphic_Obj_Toolbox,     u"drawingobjectbar"_ustr     },      //draw
    { ToolbarId::Outline_Toolbox,         u"outlinetoolbar"_ustr       },      //impress
    { ToolbarId::Slide_Toolbox,           u"slideviewtoolbar"_ustr     },
    { ToolbarId::Slide_Obj_Toolbox,       u"slideviewobjectbar"_ustr   },
    { ToolbarId::Bezier_Toolbox_Sw,       u"bezierobjectbar"_ustr      },
    { ToolbarId::Draw_Toolbox_Sw,         u"drawingobjectbar"_ustr     },
    { ToolbarId::Draw_Text_Toolbox_Sw,    u"drawtextobjectbar"_ustr    },
    { ToolbarId::Frame_Toolbox,           u"frameobjectbar"_ustr       },
    { ToolbarId::Grafik_Toolbox,          u"graphicobjectbar"_ustr     },
    { ToolbarId::Num_Toolbox,             u"numobjectbar"_ustr         },
    { ToolbarId::Ole_Toolbox,             u"oleobjectbar"_ustr         },
    { ToolbarId::Table_Toolbox,           u"tableobjectbar"_ustr       },
    { ToolbarId::Text_Toolbox_Sw,         u"textobjectbar"_ustr        },
    { ToolbarId::PView_Toolbox,           u"previewobjectbar"_ustr     },      //writer
    { ToolbarId::Webtools_Toolbox,        u"toolbar"_ustr              },      //web
    { ToolbarId::Webtext_Toolbox,         u"textobjectbar"_ustr        },
    { ToolbarId::Tools_Toolbox,           u"toolbar"_ustr              },      //writer
    { ToolbarId::Webframe_Toolbox,        u"frameobjectbar"_ustr       },      //web
    { ToolbarId::Webgraphic_Toolbox,      u"graphicobjectbar"_ustr     },
    { ToolbarId::Webole_Toolbox,          u"oleobjectbar"_ustr         },
    { ToolbarId::Basicide_Objectbar,      u"macrobar"_ustr             },
    { ToolbarId::Svx_Fontwork_Bar,        u"fontworkobjectbar"_ustr    },      //global
    { ToolbarId::Svx_Extrusion_Bar,       u"extrusionobjectbar"_ustr   },
    { ToolbarId::FormLayer_Toolbox,       u"formsobjectbar"_ustr       },
    { ToolbarId::Module_Toolbox,          u"viewerbar"_ustr            },      //writer (plugin)
    { ToolbarId::Objectbar_App,           u"viewerbar"_ustr            },      //calc   (plugin)
    { ToolbarId::Draw_Viewer_Toolbox,     u"viewerbar"_ustr            },      //impress(plugin)
    { ToolbarId::Draw_Media_Toolbox,      u"mediaobjectbar"_ustr       },      //draw/impress
    { ToolbarId::Media_Objectbar,         u"mediaobjectbar"_ustr       },      //calc
    { ToolbarId::Media_Toolbox,           u"mediaobjectbar"_ustr       },      //writer
    { ToolbarId::None,                    u""_ustr                     }
};

// Sort the Children according their alignment
// The order corresponds to the enum SfxChildAlignment (->CHILDWIN.HXX).

constexpr OUString g_aLayoutManagerPropName = u"LayoutManager"_ustr;

// 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 >&&nbsp;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( u"LockCount"_ustr );
            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( 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 OUString g_aStatusBarResName( u"private:resource/statusbar/statusbar"_ustr );
constexpr OUString g_aTbxTypeName( u"private:resource/toolbar/"_ustr );
constexpr OUString g_aProgressBarResName( u"private:resource/progressbar/progressbar"_ustr );

// 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();
    m_xLayoutManagerListener = new LayoutManagerListener( this );
    m_xLayoutManagerListener->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 );
        pSplit[n] = VclPtr<SfxSplitWindow>::Create(pWorkWin, eAlign, thistrue );
    }

    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 = pObjShell->GetMedium()->GetItemSet().GetItem(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()
{
    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();
    }

    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 bForceDestroyToolbars =
        comphelper::LibreOfficeKit::isActive() ? false : sfx2::SfxNotebookBar::IsActive(true);
    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 || bForceDestroyToolbars)
        {
            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;
        }
    }
}

namespace
{
template <sal_uInt16 SfxChildWin_Impl::*Member>
SfxChildWin_Impl* Get_Impl(const std::vector<std::unique_ptr<SfxChildWin_Impl>>& rChildWins,
                           sal_uInt16 nId)
{
    for (auto& pChildWin : rChildWins)
        if (pChildWin.get()->*Member == nId)
            return pChildWin.get();
    return nullptr;
}
auto Get_ById = Get_Impl<&SfxChildWin_Impl::nId>;
auto Get_BySaveId = Get_Impl<&SfxChildWin_Impl::nSaveId>;
}

void SfxWorkWindow::SetChildWindowVisible_Impl( sal_uInt32 lId, bool bEnabled, SfxVisibilityFlags nMode )
{
    sal_uInt16 nId = static_cast<sal_uInt16>( lId & 0xFFFF );

    SfxChildWin_Impl* pCW = Get_BySaveId(aChildWins, nId);

    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)
{
    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
}


bool SfxWorkWindow::HasChildWindow_Impl(sal_uInt16 nId)
{
    if (const SfxChildWin_Impl* pCW = Get_BySaveId(aChildWins, nId))
        return ( pCW->pWin && pCW->bCreate );

    return false;
}

bool SfxWorkWindow::IsFloating( sal_uInt16 nId )
{
    SfxChildWin_Impl* pCW = Get_BySaveId(aChildWins, nId);

    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)
{
    if (SfxChildWin_Impl* pCW = Get_BySaveId(aChildWins, nId))
    {
        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 = Get_BySaveId(aChildWins, nId);

    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);
}


void SfxWorkWindow::ShowChildWindow_Impl(sal_uInt16 nId, bool bVisible, bool bSetFocus)
{
    if (SfxChildWin_Impl* pCW = Get_ById(aChildWins, nId))
    {
        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 )
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=92 H=94 G=92

¤ Dauer der Verarbeitung: 0.22 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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.