diff options
Diffstat (limited to '')
-rw-r--r-- | sfx2/source/notebookbar/SfxNotebookBar.cxx | 550 |
1 files changed, 550 insertions, 0 deletions
diff --git a/sfx2/source/notebookbar/SfxNotebookBar.cxx b/sfx2/source/notebookbar/SfxNotebookBar.cxx new file mode 100644 index 000000000..674caf4b0 --- /dev/null +++ b/sfx2/source/notebookbar/SfxNotebookBar.cxx @@ -0,0 +1,550 @@ +/* -*- 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/. + */ + +#include <sfx2/bindings.hxx> +#include <sfx2/viewsh.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/notebookbar/SfxNotebookBar.hxx> +#include <vcl/notebookbar.hxx> +#include <vcl/syswin.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/sfxsids.hrc> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/frame/UnknownModuleException.hpp> +#include <com/sun/star/ui/ContextChangeEventMultiplexer.hpp> +#include <com/sun/star/ui/XContextChangeEventMultiplexer.hpp> +#include <com/sun/star/frame/XLayoutManager.hpp> +#include <officecfg/Office/UI/ToolbarMode.hxx> +#include <com/sun/star/frame/XModuleManager.hpp> +#include <com/sun/star/frame/ModuleManager.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <unotools/confignode.hxx> +#include <comphelper/types.hxx> +#include <framework/addonsoptions.hxx> +#include <vcl/NotebookBarAddonsMerger.hxx> +#include <vector> +using namespace sfx2; +using namespace css::uno; +using namespace css::ui; +using namespace css; + +#define MENUBAR_STR "private:resource/menubar/menubar" + +static const char MERGE_NOTEBOOKBAR_URL[] = "URL"; +static const char MERGE_NOTEBOOKBAR_IMAGEID[] = "ImageIdentifier"; + +bool SfxNotebookBar::m_bLock = false; +bool SfxNotebookBar::m_bHide = false; + +static void NotebookbarAddonValues( + std::vector<Image>& aImageValues, + std::vector<css::uno::Sequence<css::uno::Sequence<css::beans::PropertyValue>>>& + aExtensionValues) +{ + framework::AddonsOptions aAddonsItems; + + for (int nIdx = 0; nIdx < aAddonsItems.GetAddonsNotebookBarCount(); nIdx++) + { + const css::uno::Sequence<css::uno::Sequence<css::beans::PropertyValue>> aExtension + = aAddonsItems.GetAddonsNotebookBarPart(nIdx); + for (const css::uno::Sequence<css::beans::PropertyValue>& rExtensionVal : aExtension) + { + Image aImage; + bool isBigImage = true; + for (const auto& rProp : rExtensionVal) + { + OUString sImage; + if (rProp.Name == MERGE_NOTEBOOKBAR_IMAGEID) + { + rProp.Value >>= sImage; + aImage = framework::AddonsOptions().GetImageFromURL(sImage, isBigImage); + } + } + if(!aImage) + { + for (const auto& rProp : rExtensionVal) + { + OUString sImage; + if (rProp.Name == MERGE_NOTEBOOKBAR_URL) + { + rProp.Value >>= sImage; + aImage = framework::AddonsOptions().GetImageFromURL(sImage, isBigImage); + } + } + } + aImageValues.push_back(aImage); + } + aExtensionValues.push_back(aExtension); + } +} + +static Reference<frame::XLayoutManager> lcl_getLayoutManager( const Reference<frame::XFrame>& xFrame ) +{ + css::uno::Reference<css::frame::XLayoutManager> xLayoutManager; + + if (xFrame.is()) + { + Reference<css::beans::XPropertySet> xPropSet(xFrame, UNO_QUERY); + + if (xPropSet.is()) + { + Any aValue = xPropSet->getPropertyValue("LayoutManager"); + aValue >>= xLayoutManager; + } + } + + return xLayoutManager; +} + +static OUString lcl_getAppName( vcl::EnumContext::Application eApp ) +{ + switch ( eApp ) + { + case vcl::EnumContext::Application::Writer: + return "Writer"; + break; + case vcl::EnumContext::Application::Calc: + return "Calc"; + break; + case vcl::EnumContext::Application::Impress: + return "Impress"; + break; + case vcl::EnumContext::Application::Draw: + return "Draw"; + break; + case vcl::EnumContext::Application::Formula: + return "Formula"; + break; + default: + return OUString(); + break; + } +} + +static void lcl_setNotebookbarFileName( vcl::EnumContext::Application eApp, const OUString& sFileName ) +{ + std::shared_ptr<comphelper::ConfigurationChanges> aBatch( + comphelper::ConfigurationChanges::create( ::comphelper::getProcessComponentContext() ) ); + switch ( eApp ) + { + case vcl::EnumContext::Application::Writer: + officecfg::Office::UI::ToolbarMode::ActiveWriter::set( sFileName, aBatch ); + break; + case vcl::EnumContext::Application::Calc: + officecfg::Office::UI::ToolbarMode::ActiveCalc::set( sFileName, aBatch ); + break; + case vcl::EnumContext::Application::Impress: + officecfg::Office::UI::ToolbarMode::ActiveImpress::set( sFileName, aBatch ); + break; + case vcl::EnumContext::Application::Draw: + officecfg::Office::UI::ToolbarMode::ActiveDraw::set( sFileName, aBatch ); + break; + default: + break; + } + aBatch->commit(); +} + +static OUString lcl_getNotebookbarFileName( vcl::EnumContext::Application eApp ) +{ + switch ( eApp ) + { + case vcl::EnumContext::Application::Writer: + return officecfg::Office::UI::ToolbarMode::ActiveWriter::get(); + break; + case vcl::EnumContext::Application::Calc: + return officecfg::Office::UI::ToolbarMode::ActiveCalc::get(); + break; + case vcl::EnumContext::Application::Impress: + return officecfg::Office::UI::ToolbarMode::ActiveImpress::get(); + break; + case vcl::EnumContext::Application::Draw: + return officecfg::Office::UI::ToolbarMode::ActiveDraw::get(); + break; + + default: + break; + } + return OUString(); +} + +static utl::OConfigurationTreeRoot lcl_getCurrentImplConfigRoot() +{ + return utl::OConfigurationTreeRoot(::comphelper::getProcessComponentContext(), + "org.openoffice.Office.UI.ToolbarMode/", + true); +} + +static utl::OConfigurationNode lcl_getCurrentImplConfigNode(const Reference<css::frame::XFrame>& xFrame, + utl::OConfigurationTreeRoot const & rNotebookbarNode ) +{ + if (!rNotebookbarNode.isValid()) + return utl::OConfigurationNode(); + + const Reference<frame::XModuleManager> xModuleManager = frame::ModuleManager::create( ::comphelper::getProcessComponentContext() ); + + vcl::EnumContext::Application eApp = vcl::EnumContext::GetApplicationEnum( xModuleManager->identify( xFrame ) ); + OUString aActive = lcl_getNotebookbarFileName( eApp ); + + const utl::OConfigurationNode aImplsNode = rNotebookbarNode.openNode("Applications/" + lcl_getAppName( eApp) + "/Modes"); + const Sequence<OUString> aModeNodeNames( aImplsNode.getNodeNames() ); + + for ( const auto& rModeNodeName : aModeNodeNames ) + { + const utl::OConfigurationNode aImplNode( aImplsNode.openNode( rModeNodeName ) ); + if ( !aImplNode.isValid() ) + continue; + + OUString aCommandArg = comphelper::getString( aImplNode.getNodeValue( "CommandArg" ) ); + + if ( aCommandArg == aActive ) + { + return aImplNode; + } + } + + return utl::OConfigurationNode(); +} + +void SfxNotebookBar::CloseMethod(SfxBindings& rBindings) +{ + SfxFrame& rFrame = rBindings.GetDispatcher_Impl()->GetFrame()->GetFrame(); + CloseMethod(rFrame.GetSystemWindow()); +} + +void SfxNotebookBar::CloseMethod(SystemWindow* pSysWindow) +{ + if (pSysWindow) + { + RemoveListeners(pSysWindow); + if(pSysWindow->GetNotebookBar()) + pSysWindow->CloseNotebookBar(); + if (SfxViewFrame::Current()) + SfxNotebookBar::ShowMenubar(SfxViewFrame::Current(), true); + } +} + +void SfxNotebookBar::LockNotebookBar() +{ + m_bHide = true; + m_bLock = true; +} + +void SfxNotebookBar::UnlockNotebookBar() +{ + m_bHide = false; + m_bLock = false; +} + +bool SfxNotebookBar::IsActive() +{ + if (m_bHide) + return false; + + vcl::EnumContext::Application eApp = vcl::EnumContext::Application::Any; + + if (SfxViewFrame::Current()) + { + const Reference<frame::XFrame>& xFrame = SfxViewFrame::Current()->GetFrame().GetFrameInterface(); + if (!xFrame.is()) + return false; + + const Reference<frame::XModuleManager> xModuleManager = frame::ModuleManager::create( ::comphelper::getProcessComponentContext() ); + try + { + eApp = vcl::EnumContext::GetApplicationEnum(xModuleManager->identify(xFrame)); + } + catch (css::frame::UnknownModuleException& e) + { + SAL_WARN("sfx.appl", "SfxNotebookBar::IsActive(): " + e.Message); + return false; + } + } + else + return false; + + OUString appName(lcl_getAppName( eApp )); + + if (appName.isEmpty()) + return false; + + + OUString aPath = "org.openoffice.Office.UI.ToolbarMode/Applications/" + appName; + + const utl::OConfigurationTreeRoot aAppNode( + ::comphelper::getProcessComponentContext(), + aPath, + false); + if ( !aAppNode.isValid() ) + return false; + + OUString aActive = comphelper::getString( aAppNode.getNodeValue( "Active" ) ); + + const utl::OConfigurationNode aModesNode = aAppNode.openNode("Modes"); + const Sequence<OUString> aModeNodeNames( aModesNode.getNodeNames() ); + + for ( const auto& rModeNodeName : aModeNodeNames ) + { + const utl::OConfigurationNode aModeNode( aModesNode.openNode( rModeNodeName ) ); + if ( !aModeNode.isValid() ) + continue; + + OUString aCommandArg = comphelper::getString( aModeNode.getNodeValue( "CommandArg" ) ); + + if ( aCommandArg == aActive ) + { + return comphelper::getBOOL( aModeNode.getNodeValue( "HasNotebookbar" ) ); + } + } + return false; +} + +void SfxNotebookBar::ExecMethod(SfxBindings& rBindings, const OUString& rUIName) +{ + // Save active UI file name + if ( !rUIName.isEmpty() && SfxViewFrame::Current() ) + { + const Reference<frame::XFrame>& xFrame = SfxViewFrame::Current()->GetFrame().GetFrameInterface(); + if (xFrame.is()) + { + const Reference<frame::XModuleManager> xModuleManager = frame::ModuleManager::create( ::comphelper::getProcessComponentContext() ); + vcl::EnumContext::Application eApp = vcl::EnumContext::GetApplicationEnum(xModuleManager->identify(xFrame)); + lcl_setNotebookbarFileName( eApp, rUIName ); + } + } + + // trigger the StateMethod + rBindings.Invalidate(SID_NOTEBOOKBAR); + rBindings.Update(); +} + +bool SfxNotebookBar::StateMethod(SfxBindings& rBindings, const OUString& rUIFile, + bool bReloadNotebookbar) +{ + SfxFrame& rFrame = rBindings.GetDispatcher_Impl()->GetFrame()->GetFrame(); + return StateMethod(rFrame.GetSystemWindow(), rFrame.GetFrameInterface(), rUIFile, + bReloadNotebookbar); +} + +bool SfxNotebookBar::StateMethod(SystemWindow* pSysWindow, + const Reference<css::frame::XFrame>& xFrame, + const OUString& rUIFile, bool bReloadNotebookbar) +{ + if (!pSysWindow) + { + if (SfxViewFrame::Current() && SfxViewFrame::Current()->GetWindow().GetSystemWindow()) + pSysWindow = SfxViewFrame::Current()->GetWindow().GetSystemWindow(); + else + return false; + } + + if (IsActive()) + { + css::uno::Reference<css::uno::XComponentContext> xContext = comphelper::getProcessComponentContext(); + const Reference<frame::XModuleManager> xModuleManager = frame::ModuleManager::create( xContext ); + OUString aModuleName = xModuleManager->identify( xFrame ); + vcl::EnumContext::Application eApp = vcl::EnumContext::GetApplicationEnum( aModuleName ); + OUString sFile = lcl_getNotebookbarFileName( eApp ); + OUString sNewFile = rUIFile + sFile; + OUString sCurrentFile; + VclPtr<NotebookBar> pNotebookBar = pSysWindow->GetNotebookBar(); + if ( pNotebookBar ) + sCurrentFile = OStringToOUString( pNotebookBar->getUIFile(), RTL_TEXTENCODING_ASCII_US ); + + bool bChangedFile = true; + if ( sCurrentFile.getLength() && sNewFile.getLength() ) + { + // delete "/" + sCurrentFile = sCurrentFile.copy( 0, sCurrentFile.getLength() - 1 ); + // delete ".ui" + sNewFile = sNewFile.copy( 0, sNewFile.getLength() - 3 ); + + bChangedFile = sNewFile != sCurrentFile; + } + + if ((!sFile.isEmpty() && bChangedFile) || !pNotebookBar || !pNotebookBar->IsVisible() + || bReloadNotebookbar) + { + RemoveListeners(pSysWindow); + + OUString aBuf = rUIFile + sFile; + + //Addons For Notebookbar + std::vector<Image> aImageValues; + std::vector<css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > > aExtensionValues; + NotebookBarAddonsItem aNotebookBarAddonsItem; + NotebookbarAddonValues(aImageValues , aExtensionValues); + aNotebookBarAddonsItem.aAddonValues = aExtensionValues; + aNotebookBarAddonsItem.aImageValues = aImageValues; + + // setup if necessary + pSysWindow->SetNotebookBar(aBuf, xFrame, aNotebookBarAddonsItem , bReloadNotebookbar); + pNotebookBar = pSysWindow->GetNotebookBar(); + pNotebookBar->Show(); + pNotebookBar->GetParent()->Resize(); + + utl::OConfigurationTreeRoot aRoot(lcl_getCurrentImplConfigRoot()); + const utl::OConfigurationNode aModeNode(lcl_getCurrentImplConfigNode(xFrame, aRoot)); + SfxNotebookBar::ShowMenubar( comphelper::getBOOL( aModeNode.getNodeValue( "HasMenubar" ) ) ); + + SfxViewFrame* pView = SfxViewFrame::Current(); + + if(pView) + { + pNotebookBar->ControlListenerForCurrentController(true); + } + } + + return true; + } + else if (auto pNotebookBar = pSysWindow->GetNotebookBar()) + { + pNotebookBar->Hide(); + pNotebookBar->GetParent()->Resize(); + SfxNotebookBar::ShowMenubar(true); + } + + return false; +} + +void SfxNotebookBar::RemoveListeners(SystemWindow const * pSysWindow) +{ + if (auto pNotebookBar = pSysWindow->GetNotebookBar()) + { + pNotebookBar->StopListeningAllControllers(); + } +} + +void SfxNotebookBar::ShowMenubar(bool bShow) +{ + if (m_bLock) + return; + + m_bLock = true; + + Reference<frame::XFrame> xFrame; + vcl::EnumContext::Application eCurrentApp = vcl::EnumContext::Application::NONE; + uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext(); + const Reference<frame::XModuleManager> xModuleManager = frame::ModuleManager::create( xContext ); + + if ( SfxViewFrame::Current() ) + { + xFrame = SfxViewFrame::Current()->GetFrame().GetFrameInterface(); + eCurrentApp = vcl::EnumContext::GetApplicationEnum( xModuleManager->identify( xFrame ) ); + } + + SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst(); + while( pViewFrame ) + { + xFrame = pViewFrame->GetFrame().GetFrameInterface(); + if ( xFrame.is() ) + { + vcl::EnumContext::Application eApp = + vcl::EnumContext::GetApplicationEnum( xModuleManager->identify( xFrame ) ); + + if ( eApp == eCurrentApp ) + { + const Reference<frame::XLayoutManager>& xLayoutManager = + lcl_getLayoutManager( xFrame ); + + if (xLayoutManager.is()) + { + xLayoutManager->lock(); + + if (xLayoutManager->getElement(MENUBAR_STR).is()) + { + if (xLayoutManager->isElementVisible(MENUBAR_STR) && !bShow) + xLayoutManager->hideElement(MENUBAR_STR); + else if(!xLayoutManager->isElementVisible(MENUBAR_STR) && bShow) + xLayoutManager->showElement(MENUBAR_STR); + } + + xLayoutManager->unlock(); + } + } + } + + pViewFrame = SfxViewFrame::GetNext( *pViewFrame ); + } + m_bLock = false; +} + +void SfxNotebookBar::ShowMenubar(SfxViewFrame const * pViewFrame, bool bShow) +{ + if (m_bLock) + return; + + m_bLock = true; + + Reference<frame::XFrame> xFrame = pViewFrame->GetFrame().GetFrameInterface(); + if (xFrame.is()) + { + const Reference<frame::XLayoutManager>& xLayoutManager = lcl_getLayoutManager(xFrame); + if (xLayoutManager.is()) + { + xLayoutManager->lock(); + + if (xLayoutManager->getElement(MENUBAR_STR).is()) + { + if (xLayoutManager->isElementVisible(MENUBAR_STR) && !bShow) + xLayoutManager->hideElement(MENUBAR_STR); + else if (!xLayoutManager->isElementVisible(MENUBAR_STR) && bShow) + xLayoutManager->showElement(MENUBAR_STR); + } + + xLayoutManager->unlock(); + } + } + m_bLock = false; +} + +void SfxNotebookBar::ToggleMenubar() +{ + if (!SfxViewFrame::Current()) + return; + + const Reference<frame::XFrame>& xFrame = SfxViewFrame::Current()->GetFrame().GetFrameInterface(); + if (!xFrame.is()) + return; + + const Reference<frame::XLayoutManager>& xLayoutManager = + lcl_getLayoutManager(xFrame); + + bool bShow = true; + if (xLayoutManager.is() && xLayoutManager->getElement(MENUBAR_STR).is()) + { + if (xLayoutManager->isElementVisible(MENUBAR_STR)) + { + SfxNotebookBar::ShowMenubar(false); + bShow = false; + } + else + SfxNotebookBar::ShowMenubar(true); + } + + // Save menubar settings + if (IsActive()) + { + utl::OConfigurationTreeRoot aRoot(lcl_getCurrentImplConfigRoot()); + utl::OConfigurationNode aModeNode(lcl_getCurrentImplConfigNode(xFrame, aRoot)); + aModeNode.setNodeValue( "HasMenubar", toAny<bool>( bShow ) ); + aRoot.commit(); + } +} + +void SfxNotebookBar::ReloadNotebookBar(const OUString& sUIPath) +{ + if (SfxNotebookBar::IsActive()) + { + SfxViewShell* pViewShell = SfxViewShell::Current(); + sfx2::SfxNotebookBar::StateMethod(pViewShell->GetViewFrame()->GetBindings(), sUIPath, true); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |