tdf#125040 Make single mode toolbar context aware

This patch modifies the "Standard (Single Mode)" toolbar
to have an optional context-aware section, given that a
corresponding singlemode-<context-name>.xml files exist.
This is a lot like the "Contextual Single" NB, except
that it's implemented with regular toolbars, so docking/
customization/extensions/uno api etc. are all working.

In addition, the "Single Toolbar" mode was modified to
not show any other contextual toolbar. (But of course the
single mode toolbar itself is perfectly usable outside of
this mode.)

Change-Id: Id746d9df59340a81962a8689b132941deea54b6c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135591
Tested-by: Jenkins
Reviewed-by: Maxim Monastirsky <momonasmon@gmail.com>
diff --git a/framework/inc/uielement/toolbarmanager.hxx b/framework/inc/uielement/toolbarmanager.hxx
index 1cfddd9..746b40e 100644
--- a/framework/inc/uielement/toolbarmanager.hxx
+++ b/framework/inc/uielement/toolbarmanager.hxx
@@ -94,6 +94,7 @@ public:
    virtual void ConnectCallbacks(ToolBarManager* pManager) = 0;
    virtual void SetMenuType(ToolBoxMenuType eType) = 0;
    virtual void MergeToolbar(ToolBoxItemId & rItemId,
                              sal_uInt16 nFirstItem,
                              const OUString& rModuleIdentifier,
                              CommandToInfoMap& rCommandMap,
                              MergeToolbarInstruction& rInstruction) = 0;
@@ -144,7 +145,9 @@ class ToolBarManager final : public ToolbarManager_Base

        void CheckAndUpdateImages();
        void RequestImages();
        void FillToolbar( const css::uno::Reference< css::container::XIndexAccess >& rToolBarData );
        void FillToolbar( const css::uno::Reference< css::container::XIndexAccess >& rToolBarData,
                          const css::uno::Reference< css::container::XIndexAccess >& rContextData,
                          const OUString& rContextToolbarName );
        void FillAddonToolbar( const css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > >& rAddonToolbar );
        void FillOverflowToolbar( ToolBox const * pParent );
        void notifyRegisteredControllers( const OUString& aUIElementName, const OUString& aCommand );
@@ -193,6 +196,9 @@ class ToolBarManager final : public ToolbarManager_Base

    private:
        void Init();
        void FillToolbarFromContainer(const css::uno::Reference< css::container::XIndexAccess >& rItemContainer,
                                      const OUString& rResourceName, ToolBoxItemId& nId, ToolBoxItemId& nAddonId);
        void ToggleButton(const OUString& rResourceName, std::u16string_view rCommand);
        void AddCustomizeMenuItems(ToolBox const * pToolBar);
        void InitImageManager();
        void RemoveControllers();
@@ -219,12 +225,14 @@ class ToolBarManager final : public ToolbarManager_Base
             m_bUpdateControllers : 1;

        sal_Int16 m_eSymbolSize;
        sal_uInt16 m_nContextMinPos;

        std::unique_ptr<ToolBarManagerImpl>                          m_pImpl;
        VclPtr<ToolBox>                                              m_pToolBar;

        OUString                                                     m_aModuleIdentifier;
        OUString                                                     m_aResourceName;
        OUString                                                     m_aContextResourceName;

        css::uno::Reference< css::util::XURLTransformer >            m_xURLTransformer;
        css::uno::Reference< css::frame::XFrame >                    m_xFrame;
diff --git a/framework/inc/uielement/toolbarmerger.hxx b/framework/inc/uielement/toolbarmerger.hxx
index 837507b..b84ca20 100644
--- a/framework/inc/uielement/toolbarmerger.hxx
+++ b/framework/inc/uielement/toolbarmerger.hxx
@@ -75,7 +75,7 @@ class ToolBarMerger
                                                   OUString& rControlType,
                                                   sal_uInt16& rWidth );

        static ReferenceToolbarPathInfo FindReferencePoint( const ToolBox* pToolbar,
        static ReferenceToolbarPathInfo FindReferencePoint( const ToolBox* pToolbar, sal_uInt16 nFirstItem,
                                                            std::u16string_view rReferencePoint );

        static bool       ProcessMergeOperation( ToolBox*                  pToolbar,
diff --git a/framework/inc/uielement/toolbarwrapper.hxx b/framework/inc/uielement/toolbarwrapper.hxx
index da90455..a1bfbd0 100644
--- a/framework/inc/uielement/toolbarwrapper.hxx
+++ b/framework/inc/uielement/toolbarwrapper.hxx
@@ -23,6 +23,7 @@

#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/ui/XUIFunctionListener.hpp>
#include <com/sun/star/ui/XContextChangeEventListener.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>

#include <memory>
@@ -37,19 +38,14 @@ namespace weld
namespace framework
{

class ToolBarManager;
class ToolBarWrapper final : public css::ui::XUIFunctionListener,
                       public UIConfigElementWrapperBase
class ToolBarWrapper final : public cppu::ImplInheritanceHelper<UIConfigElementWrapperBase,
                                                                css::ui::XUIFunctionListener,
                                                                css::ui::XContextChangeEventListener>
{
    public:
        ToolBarWrapper( const css::uno::Reference< css::uno::XComponentContext >& xContext );
        virtual ~ToolBarWrapper() override;

        // XInterface
        virtual void SAL_CALL acquire() noexcept override;
        virtual void SAL_CALL release() noexcept override;
        virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;

        // XComponent
        virtual void SAL_CALL dispose() override;

@@ -68,6 +64,9 @@ class ToolBarWrapper final : public css::ui::XUIFunctionListener,
        // XUIFunctionListener
        virtual void SAL_CALL functionExecute( const OUString& aUIElementName, const OUString& aCommand ) override;

        // XContextChangeEventListener
        virtual void SAL_CALL notifyContextChangeEvent( const css::ui::ContextChangeEventObject& aEvent ) override;

        // XEventListener
        using cppu::OPropertySetHelper::disposing;
        virtual void SAL_CALL disposing( const css::lang::EventObject& aEvent ) override;
@@ -78,6 +77,7 @@ class ToolBarWrapper final : public css::ui::XUIFunctionListener,

        css::uno::Reference< css::lang::XComponent >            m_xToolBarManager;
        css::uno::Reference< css::uno::XComponentContext >      m_xContext;
        css::uno::Reference< css::ui::XUIElement >              m_xSubElement;

        std::unique_ptr<weld::Builder>                          m_xBuilder;
        std::unique_ptr<weld::Container>                        m_xTopLevel;
diff --git a/framework/source/uielement/toolbarmanager.cxx b/framework/source/uielement/toolbarmanager.cxx
index 4d56884..e9de797 100644
--- a/framework/source/uielement/toolbarmanager.cxx
+++ b/framework/source/uielement/toolbarmanager.cxx
@@ -333,12 +333,12 @@ public:
        m_pToolBar->SetMenuType( eType );
    }

    virtual void MergeToolbar(ToolBoxItemId & rItemId,
    virtual void MergeToolbar(ToolBoxItemId & rItemId, sal_uInt16 nFirstItem,
                              const OUString& rModuleIdentifier,
                              CommandToInfoMap& rCommandMap,
                              MergeToolbarInstruction& rInstruction) override
    {
        ReferenceToolbarPathInfo aRefPoint = ToolBarMerger::FindReferencePoint( m_pToolBar, rInstruction.aMergePoint );
        ReferenceToolbarPathInfo aRefPoint = ToolBarMerger::FindReferencePoint( m_pToolBar, nFirstItem, rInstruction.aMergePoint );

        // convert the sequence< sequence< propertyvalue > > structure to
        // something we can better handle. A vector with item data
@@ -522,6 +522,7 @@ public:
    virtual void SetMenuType(ToolBoxMenuType /*eType*/) override {}

    virtual void MergeToolbar(ToolBoxItemId & /*rItemId*/,
                              sal_uInt16 /*nFirstItem*/,
                              const OUString& /*rModuleIdentifier*/,
                              CommandToInfoMap& /*rCommandMap*/,
                              MergeToolbarInstruction& /*rInstruction*/) override {}
@@ -572,6 +573,7 @@ ToolBarManager::ToolBarManager( const Reference< XComponentContext >& rxContext,
    m_bFrameActionRegistered( false ),
    m_bUpdateControllers( false ),
    m_eSymbolSize(SvtMiscOptions().GetCurrentSymbolsSize()),
    m_nContextMinPos(0),
    m_pImpl( new VclToolBarManager( pToolBar ) ),
    m_pToolBar( pToolBar ),
    m_aResourceName(std::move( aResourceName )),
@@ -592,6 +594,7 @@ ToolBarManager::ToolBarManager( const Reference< XComponentContext >& rxContext,
    m_bFrameActionRegistered( false ),
    m_bUpdateControllers( false ),
    m_eSymbolSize( SvtMiscOptions().GetCurrentSymbolsSize() ),
    m_nContextMinPos(0),
    m_pImpl( new WeldToolBarManager( pToolBar, pBuilder ) ),
    m_pToolBar( nullptr ),
    m_aResourceName(std::move( aResourceName )),
@@ -1332,7 +1335,9 @@ void ToolBarManager::InitImageManager()
    }
}

void ToolBarManager::FillToolbar( const Reference< XIndexAccess >& rItemContainer )
void ToolBarManager::FillToolbar( const Reference< XIndexAccess >& rItemContainer,
                                  const Reference< XIndexAccess >& rContextData,
                                  const OUString& rContextToolbarName )
{
    OString aTbxName = OUStringToOString( m_aResourceName, RTL_TEXTENCODING_ASCII_US );
    SAL_INFO( "fwk.uielement", "framework (cd100003) ::ToolBarManager::FillToolbar " << aTbxName );
@@ -1351,7 +1356,54 @@ void ToolBarManager::FillToolbar( const Reference< XIndexAccess >& rItemContaine
    m_aControllerMap.clear();
    m_aCommandMap.clear();

    ToolBoxItemId nId( 1 );
    ToolBoxItemId nId(1), nAddonId(1000);
    FillToolbarFromContainer( rItemContainer, m_aResourceName, nId, nAddonId );
    m_aContextResourceName = rContextToolbarName;
    if ( rContextData.is() )
    {
        m_pImpl->InsertSeparator();
        FillToolbarFromContainer( rContextData, m_aContextResourceName, nId, nAddonId );
    }

    // Request images for all toolbar items. Must be done before CreateControllers as
    // some controllers need access to the image.
    RequestImages();

    // Create controllers after we set the images. There are controllers which needs
    // an image at the toolbar at creation time!
    CreateControllers();

    // Notify controllers that they are now correctly initialized and can start listening
    // toolbars that will open in popup mode will be updated immediately to avoid flickering
    if( m_pImpl->WillUsePopupMode() )
        UpdateControllers();
    else if ( m_pImpl->IsReallyVisible() )
    {
        m_aAsyncUpdateControllersTimer.Start();
    }

    // Try to retrieve UIName from the container property set and set it as the title
    // if it is not empty.
    Reference< XPropertySet > xPropSet( rItemContainer, UNO_QUERY );
    if ( !xPropSet.is() )
        return;

    try
    {
        OUString aUIName;
        xPropSet->getPropertyValue("UIName") >>= aUIName;
        if ( !aUIName.isEmpty() )
            m_pImpl->SetName( aUIName );
    }
    catch (const Exception&)
    {
    }
}

void ToolBarManager::FillToolbarFromContainer( const Reference< XIndexAccess >& rItemContainer,
                                               const OUString& rResourceName, ToolBoxItemId& nId, ToolBoxItemId& nAddonId )
{
    m_nContextMinPos = m_pImpl->GetItemCount();
    CommandInfo aCmdInfo;
    for ( sal_Int32 n = 0; n < rItemContainer->getCount(); n++ )
    {
@@ -1447,12 +1499,10 @@ void ToolBarManager::FillToolbar( const Reference< XIndexAccess >& rItemContaine

    // Support add-on toolbar merging here. Working directly on the toolbar object is much
    // simpler and faster.
    constexpr sal_uInt16 TOOLBAR_ITEM_STARTID = 1000;

    MergeToolbarInstructionContainer aMergeInstructionContainer;

    // Retrieve the toolbar name from the resource name
    OUString aToolbarName( m_aResourceName );
    OUString aToolbarName( rResourceName );
    sal_Int32 nIndex = aToolbarName.lastIndexOf( '/' );
    if (( nIndex > 0 ) && ( nIndex < aToolbarName.getLength() ))
        aToolbarName = aToolbarName.copy( nIndex+1 );
@@ -1461,51 +1511,16 @@ void ToolBarManager::FillToolbar( const Reference< XIndexAccess >& rItemContaine

    if ( !aMergeInstructionContainer.empty() )
    {
        ToolBoxItemId nItemId( TOOLBAR_ITEM_STARTID );
        const sal_uInt32 nCount = aMergeInstructionContainer.size();
        for ( sal_uInt32 i=0; i < nCount; i++ )
        {
            MergeToolbarInstruction& rInstruction = aMergeInstructionContainer[i];
            if ( ToolBarMerger::IsCorrectContext( rInstruction.aMergeContext, m_aModuleIdentifier ))
            {
                m_pImpl->MergeToolbar(nItemId, m_aModuleIdentifier, m_aCommandMap, rInstruction);
                m_pImpl->MergeToolbar(nAddonId, m_nContextMinPos, m_aModuleIdentifier, m_aCommandMap, rInstruction);
            }
        }
    }

    // Request images for all toolbar items. Must be done before CreateControllers as
    // some controllers need access to the image.
    RequestImages();

    // Create controllers after we set the images. There are controllers which needs
    // an image at the toolbar at creation time!
    CreateControllers();

    // Notify controllers that they are now correctly initialized and can start listening
    // toolbars that will open in popup mode will be updated immediately to avoid flickering
    if( m_pImpl->WillUsePopupMode() )
        UpdateControllers();
    else if ( m_pImpl->IsReallyVisible() )
    {
        m_aAsyncUpdateControllersTimer.Start();
    }

    // Try to retrieve UIName from the container property set and set it as the title
    // if it is not empty.
    Reference< XPropertySet > xPropSet( rItemContainer, UNO_QUERY );
    if ( !xPropSet.is() )
        return;

    try
    {
        OUString aUIName;
        xPropSet->getPropertyValue("UIName") >>= aUIName;
        if ( !aUIName.isEmpty() )
            m_pImpl->SetName( aUIName );
    }
    catch (const Exception&)
    {
    }
}

void ToolBarManager::FillAddonToolbar( const Sequence< Sequence< PropertyValue > >& rAddonToolbar )
@@ -1991,6 +2006,66 @@ void ToolBarManager::AddCustomizeMenuItems(ToolBox const * pToolBar)
        pMenu->RemoveDisabledEntries();
}

void ToolBarManager::ToggleButton( const OUString& rResourceName, std::u16string_view rCommand )
{
    Reference< XLayoutManager > xLayoutManager = getLayoutManagerFromFrame( m_xFrame );
    if ( !xLayoutManager.is() )
        return;

    Reference< XUIElementSettings > xUIElementSettings( xLayoutManager->getElement( rResourceName ), UNO_QUERY );
    if ( !xUIElementSettings.is() )
        return;

    Reference< XIndexContainer > xItemContainer( xUIElementSettings->getSettings( true ), UNO_QUERY );
    sal_Int32 nCount = xItemContainer->getCount();
    for ( sal_Int32 i = 0; i < nCount; i++ )
    {
        Sequence< PropertyValue > aProp;
        sal_Int32 nVisibleIndex( -1 );
        OUString aCommandURL;
        bool bVisible( false );

        if ( xItemContainer->getByIndex( i ) >>= aProp )
        {
            for ( sal_Int32 j = 0; j < aProp.getLength(); j++ )
            {
                if ( aProp[j].Name == ITEM_DESCRIPTOR_COMMANDURL )
                {
                    aProp[j].Value >>= aCommandURL;
                }
                else if ( aProp[j].Name == ITEM_DESCRIPTOR_VISIBLE )
                {
                    aProp[j].Value >>= bVisible;
                    nVisibleIndex = j;
                }
            }

            if (( aCommandURL == rCommand ) && ( nVisibleIndex >= 0 ))
            {
                // We have found the requested item, toggle the visible flag
                // and write back the configuration settings to the toolbar
                aProp.getArray()[nVisibleIndex].Value <<= !bVisible;
                try
                {
                    xItemContainer->replaceByIndex( i, Any( aProp ));
                    xUIElementSettings->setSettings( xItemContainer );
                    Reference< XPropertySet > xPropSet( xUIElementSettings, UNO_QUERY );
                    if ( xPropSet.is() )
                    {
                        Reference< XUIConfigurationPersistence > xUICfgMgr;
                        if (( xPropSet->getPropertyValue("ConfigurationSource") >>= xUICfgMgr ) && ( xUICfgMgr.is() ))
                            xUICfgMgr->store();
                    }
                }
                catch (const Exception&)
                {
                }
                break;
            }
        }
    }
}

IMPL_LINK( ToolBarManager, MenuButton, ToolBox*, pToolBar, void )
{
    SolarMutexGuard g;
@@ -2158,64 +2233,11 @@ IMPL_LINK( ToolBarManager, MenuSelect, Menu*, pMenu, bool )
                {
                    // toggle toolbar button visibility
                    OUString aCommand = pMenu->GetItemCommand( nId );

                    Reference< XLayoutManager > xLayoutManager = getLayoutManagerFromFrame( m_xFrame );
                    if ( xLayoutManager.is() )
                    {
                        Reference< XUIElementSettings > xUIElementSettings( xLayoutManager->getElement( m_aResourceName ), UNO_QUERY );
                        if ( xUIElementSettings.is() )
                        {
                            Reference< XIndexContainer > xItemContainer( xUIElementSettings->getSettings( true ), UNO_QUERY );
                            sal_Int32 nCount = xItemContainer->getCount();
                            for ( sal_Int32 i = 0; i < nCount; i++ )
                            {
                                Sequence< PropertyValue > aProp;
                                sal_Int32                 nVisibleIndex( -1 );
                                OUString             aCommandURL;
                                bool                  bVisible( false );

                                if ( xItemContainer->getByIndex( i ) >>= aProp )
                                {
                                    for ( sal_Int32 j = 0; j < aProp.getLength(); j++ )
                                    {
                                        if ( aProp[j].Name == ITEM_DESCRIPTOR_COMMANDURL )
                                        {
                                            aProp[j].Value >>= aCommandURL;
                                        }
                                        else if ( aProp[j].Name == ITEM_DESCRIPTOR_VISIBLE )
                                        {
                                            aProp[j].Value >>= bVisible;
                                            nVisibleIndex = j;
                                        }
                                    }

                                    if (( aCommandURL == aCommand ) && ( nVisibleIndex >= 0 ))
                                    {
                                        // We have found the requested item, toggle the visible flag
                                        // and write back the configuration settings to the toolbar
                                        aProp.getArray()[nVisibleIndex].Value <<= !bVisible;
                                        try
                                        {
                                            xItemContainer->replaceByIndex( i, Any( aProp ));
                                            xUIElementSettings->setSettings( xItemContainer );
                                            Reference< XPropertySet > xPropSet( xUIElementSettings, UNO_QUERY );
                                            if ( xPropSet.is() )
                                            {
                                                Reference< XUIConfigurationPersistence > xUICfgMgr;
                                                if (( xPropSet->getPropertyValue("ConfigurationSource") >>= xUICfgMgr ) && ( xUICfgMgr.is() ))
                                                    xUICfgMgr->store();
                                            }
                                        }
                                        catch (const Exception&)
                                        {
                                        }

                                        break;
                                    }
                                }
                            }
                        }
                    }
                    if (m_aContextResourceName.isEmpty() ||
                        nId - STARTID_CUSTOMIZE_POPUPMENU < m_nContextMinPos)
                        ToggleButton(m_aResourceName, aCommand);
                    else
                        ToggleButton(m_aContextResourceName, aCommand);
                }
                break;
            }
diff --git a/framework/source/uielement/toolbarmerger.cxx b/framework/source/uielement/toolbarmerger.cxx
index 2657873..db9416a 100644
--- a/framework/source/uielement/toolbarmerger.cxx
+++ b/framework/source/uielement/toolbarmerger.cxx
@@ -216,6 +216,10 @@ void ToolBarMerger::ConvertSequenceToValues(

     Must be a valid pointer to a toolbar with items which
     should be searched.
@param
     nFirstItem

     First toolbar item to search from.

 @param
     rReferencePoint
@@ -228,7 +232,7 @@ void ToolBarMerger::ConvertSequenceToValues(
     position of the reference point and the toolbar used.
*/
ReferenceToolbarPathInfo ToolBarMerger::FindReferencePoint(
    const ToolBox*   pToolbar,
    const ToolBox* pToolbar, sal_uInt16 nFirstItem,
    std::u16string_view rReferencePoint )
{
    ReferenceToolbarPathInfo aResult;
@@ -237,7 +241,7 @@ ReferenceToolbarPathInfo ToolBarMerger::FindReferencePoint(

    const ToolBox::ImplToolItems::size_type nSize( pToolbar->GetItemCount() );

    for ( ToolBox::ImplToolItems::size_type i = 0; i < nSize; i++ )
    for ( ToolBox::ImplToolItems::size_type i = nFirstItem; i < nSize; i++ )
    {
        const ToolBoxItemId nItemId = pToolbar->GetItemId( i );
        if ( nItemId > ToolBoxItemId(0) )
diff --git a/framework/source/uielement/toolbarwrapper.cxx b/framework/source/uielement/toolbarwrapper.cxx
index 9bf9a4b..146cddf 100644
--- a/framework/source/uielement/toolbarwrapper.cxx
+++ b/framework/source/uielement/toolbarwrapper.cxx
@@ -20,11 +20,11 @@
#include <uielement/toolbarwrapper.hxx>
#include <uielement/toolbarmanager.hxx>

#include <com/sun/star/ui/ContextChangeEventMultiplexer.hpp>
#include <com/sun/star/ui/UIElementType.hpp>
#include <com/sun/star/lang/DisposedException.hpp>

#include <toolkit/helper/vclunohelper.hxx>
#include <cppuhelper/queryinterface.hxx>

#include <vcl/svapp.hxx>
#include <vcl/toolbox.hxx>
@@ -43,7 +43,7 @@ namespace framework
{

ToolBarWrapper::ToolBarWrapper( const Reference< XComponentContext >& rxContext ) :
    UIConfigElementWrapperBase( UIElementType::TOOLBAR ),
    ImplInheritanceHelper( UIElementType::TOOLBAR ),
    m_xContext( rxContext )
{
}
@@ -55,29 +55,6 @@ ToolBarWrapper::~ToolBarWrapper()
    m_xBuilder.reset(nullptr);
}

// XInterface
void SAL_CALL ToolBarWrapper::acquire() noexcept
{
    UIConfigElementWrapperBase::acquire();
}

void SAL_CALL ToolBarWrapper::release() noexcept
{
    UIConfigElementWrapperBase::release();
}

uno::Any SAL_CALL ToolBarWrapper::queryInterface( const uno::Type & rType )
{
    Any a = ::cppu::queryInterface(
                rType ,
                static_cast< css::ui::XUIFunctionListener* >(this) );

    if( a.hasValue() )
        return a;

    return UIConfigElementWrapperBase::queryInterface( rType );
}

// XComponent
void SAL_CALL ToolBarWrapper::dispose()
{
@@ -94,6 +71,14 @@ void SAL_CALL ToolBarWrapper::dispose()

    SolarMutexGuard g;

    auto xMultiplexer( ContextChangeEventMultiplexer::get( m_xContext ) );
    xMultiplexer->removeAllContextChangeEventListeners( this );

    Reference< XComponent > xComponent( m_xSubElement, UNO_QUERY );
    if ( xComponent.is() )
        xComponent->removeEventListener( Reference< XUIConfigurationListener >( this ));
    m_xSubElement.clear();

    if ( m_xToolBarManager.is() )
        m_xToolBarManager->dispose();
    m_xToolBarManager.clear();
@@ -134,9 +119,23 @@ void SAL_CALL ToolBarWrapper::initialize( const Sequence< Any >& aArguments )
    if ( !(xFrame.is() && m_xConfigSource.is()) )
        return;

    OUString aContextPart;
    if ( m_aResourceURL.startsWith( "private:resource/toolbar/singlemode", &aContextPart ) && aContextPart.isEmpty() )
    {
        auto xMultiplexer( ContextChangeEventMultiplexer::get( m_xContext ) );
        try
        {
            xMultiplexer->addContextChangeEventListener( this, xFrame->getController() );
        }
        catch( const Exception& )
        {
        }
    }

    // Create VCL based toolbar which will be filled with settings data
    VclPtr<ToolBox> pToolBar;
    rtl::Reference<ToolBarManager> pToolBarManager;
    if ( aContextPart.isEmpty() )
    {
        SolarMutexGuard aSolarMutexGuard;
        if ( !xParentWindow.is() )
@@ -171,7 +170,7 @@ void SAL_CALL ToolBarWrapper::initialize( const Sequence< Any >& aArguments )
        if ( m_xConfigData.is() && (pToolBar || m_xWeldedToolbar) && pToolBarManager )
        {
            // Fill toolbar with container contents
            pToolBarManager->FillToolbar( m_xConfigData );
            impl_fillNewData();
            if (pToolBar)
            {
                pToolBar->EnableCustomize();
@@ -199,9 +198,10 @@ void SAL_CALL ToolBarWrapper::initialize( const Sequence< Any >& aArguments )
}

// XEventListener
void SAL_CALL ToolBarWrapper::disposing( const css::lang::EventObject& )
void SAL_CALL ToolBarWrapper::disposing( const css::lang::EventObject& aEvent )
{
    // nothing todo
    if ( aEvent.Source == m_xSubElement )
        m_xSubElement.clear();
}

// XUpdatable
@@ -225,22 +225,21 @@ void SAL_CALL ToolBarWrapper::updateSettings()
    if ( m_bDisposed )
        throw DisposedException();

    if ( !m_xToolBarManager.is() )
        return;

    if ( m_xConfigSource.is() && m_bPersistent )
    {
        try
        {
            ToolBarManager* pToolBarManager = static_cast< ToolBarManager *>( m_xToolBarManager.get() );

            m_xConfigData = m_xConfigSource->getSettings( m_aResourceURL, false );
            if ( m_xConfigData.is() )
                pToolBarManager->FillToolbar( m_xConfigData );
                impl_fillNewData();
        }
        catch ( const NoSuchElementException& )
        {
        }

        auto pContainer( m_aListenerContainer.getContainer( cppu::UnoType< XEventListener >::get() ) );
        if ( pContainer )
            pContainer->forEach< XUIElementSettings >([]( const Reference<XUIElementSettings>& xListener ){ xListener->updateSettings(); });
    }
    else if ( !m_bPersistent )
    {
@@ -250,10 +249,55 @@ void SAL_CALL ToolBarWrapper::updateSettings()

void ToolBarWrapper::impl_fillNewData()
{
    // Transient toolbar => Fill toolbar with new data
    ToolBarManager* pToolBarManager = static_cast< ToolBarManager *>( m_xToolBarManager.get() );
    if ( pToolBarManager )
        pToolBarManager->FillToolbar( m_xConfigData );
    {
        Reference< XUIElementSettings > xUIElementSettings( m_xSubElement, UNO_QUERY );
        Reference< XIndexAccess > xContextData = xUIElementSettings.is() ? xUIElementSettings->getSettings( false ) : nullptr;
        OUString aContextToolbar = xContextData.is() ? m_xSubElement->getResourceURL() : OUString();
        pToolBarManager->FillToolbar( m_xConfigData, xContextData, aContextToolbar );
    }
}

//XContextChangeEventListener
void SAL_CALL ToolBarWrapper::notifyContextChangeEvent( const ContextChangeEventObject& aEvent )
{
    SolarMutexGuard g;

    if ( m_bDisposed )
        throw DisposedException();

    if ( aEvent.ContextName.isEmpty() )
        return;

    const OUString aContextToolbar( m_aResourceURL + "-" + aEvent.ContextName.toAsciiLowerCase() );
    if ( m_xSubElement.is() && m_xSubElement->getResourceURL() == aContextToolbar )
        return;

    Reference< XComponent > xComponent( m_xSubElement, UNO_QUERY );
    if ( xComponent.is() )
        xComponent->removeEventListener( Reference< XUIConfigurationListener >( this ));
    m_xSubElement.clear();

    Reference< XLayoutManager > xLayoutManager;
    Reference< XPropertySet > xPropSet( m_xWeakFrame.get(), UNO_QUERY );
    if ( xPropSet.is() )
        xPropSet->getPropertyValue("LayoutManager") >>= xLayoutManager;
    if ( !xLayoutManager.is() )
        return;

    xLayoutManager->createElement( aContextToolbar );
    m_xSubElement.set( xLayoutManager->getElement( aContextToolbar ) );
    xComponent.set( m_xSubElement, UNO_QUERY );
    if ( xComponent.is() )
        xComponent->addEventListener( Reference< XUIConfigurationListener >( this ));

    if ( m_xConfigData.is() )
    {
        xLayoutManager->lock();
        impl_fillNewData();
        xLayoutManager->unlock();
    }
}

// XUIElement interface
diff --git a/include/sfx2/notebookbar/SfxNotebookBar.hxx b/include/sfx2/notebookbar/SfxNotebookBar.hxx
index 66286b8..96f5805 100644
--- a/include/sfx2/notebookbar/SfxNotebookBar.hxx
+++ b/include/sfx2/notebookbar/SfxNotebookBar.hxx
@@ -44,7 +44,7 @@ public:
    static void CloseMethod(SfxBindings& rBindings);
    static void CloseMethod(SystemWindow* pSysWindow);

    static bool IsActive();
    static bool IsActive(bool bConsiderSingleToolbar = false);

    /// Function to be called from the sdi's ExecMethod.
    static void ExecMethod(SfxBindings& rBindings, const OUString& rUIName);
diff --git a/sfx2/source/appl/workwin.cxx b/sfx2/source/appl/workwin.cxx
index 4874db7..fb3955e 100644
--- a/sfx2/source/appl/workwin.cxx
+++ b/sfx2/source/appl/workwin.cxx
@@ -1195,7 +1195,7 @@ void SfxWorkWindow::UpdateObjectBars_Impl2()

    // Iterate over all Toolboxes
    xLayoutManager->lock();
    const bool isNotebookBarActive = sfx2::SfxNotebookBar::IsActive();
    const bool isNotebookBarActive = sfx2::SfxNotebookBar::IsActive(true);
    for ( auto const & n: aObjBarList )
    {
        ToolbarId eId = n.eId;
diff --git a/sfx2/source/notebookbar/SfxNotebookBar.cxx b/sfx2/source/notebookbar/SfxNotebookBar.cxx
index 451c94c..ec1f5bf 100644
--- a/sfx2/source/notebookbar/SfxNotebookBar.cxx
+++ b/sfx2/source/notebookbar/SfxNotebookBar.cxx
@@ -221,7 +221,7 @@ void SfxNotebookBar::UnlockNotebookBar()
    m_bLock = false;
}

bool SfxNotebookBar::IsActive()
bool SfxNotebookBar::IsActive(bool bConsiderSingleToolbar)
{
    if (m_bHide)
        return false;
@@ -265,6 +265,9 @@ bool SfxNotebookBar::IsActive()

    OUString aActive = comphelper::getString( aAppNode.getNodeValue( "Active" ) );

    if (bConsiderSingleToolbar && aActive == "Single")
        return true;

    if (comphelper::LibreOfficeKit::isActive() && aActive == "notebookbar_online.ui")
        return true;