From dabb20ebd5fa3b0d4bdb063b32f6ffbe2f59c3a2 Mon Sep 17 00:00:00 2001 From: Szymon Kłos Date: Sat, 6 Aug 2016 23:31:18 +0200 Subject: GSoC: tdf#101249 Toolbar Mode switching + added registry entry for storing current toolbar mode for each application + registry entries to store toolbar mode configuration, remember additional visible toolbars activated by user + changing toolbar mode hides and shows suitable toolbars + added menu controller for toolbar mode + notebookbar implementation entries are disabled when notebookbar mode is not active + each mode can open/collapse the sidebar Change-Id: I2b03f87c6dce53190d12102892d9ad30fbfd3bf6 Reviewed-on: https://gerrit.libreoffice.org/27991 Reviewed-by: Samuel Mehrbrodt Tested-by: Samuel Mehrbrodt --- framework/Library_fwl.mk | 1 + framework/inc/services.h | 1 + .../inc/uielement/toolbarmodemenucontroller.hxx | 86 ++++++ framework/source/register/registertemp.cxx | 2 + .../source/uielement/notebookbarmenucontroller.cxx | 42 ++- .../source/uielement/toolbarmodemenucontroller.cxx | 325 +++++++++++++++++++++ framework/util/fwl.component | 3 + 7 files changed, 457 insertions(+), 3 deletions(-) create mode 100644 framework/inc/uielement/toolbarmodemenucontroller.hxx create mode 100644 framework/source/uielement/toolbarmodemenucontroller.cxx (limited to 'framework') diff --git a/framework/Library_fwl.mk b/framework/Library_fwl.mk index 33edfbc86603..44781e32977f 100644 --- a/framework/Library_fwl.mk +++ b/framework/Library_fwl.mk @@ -70,6 +70,7 @@ $(eval $(call gb_Library_add_exception_objects,fwl,\ framework/source/uielement/langselectionmenucontroller \ framework/source/uielement/macrosmenucontroller \ framework/source/uielement/newmenucontroller \ + framework/source/uielement/toolbarmodemenucontroller \ framework/source/uielement/toolbarsmenucontroller \ framework/source/uielement/notebookbarmenucontroller \ )) diff --git a/framework/inc/services.h b/framework/inc/services.h index c4a87babc92a..7e1166d81907 100644 --- a/framework/inc/services.h +++ b/framework/inc/services.h @@ -51,6 +51,7 @@ namespace framework{ #define IMPLEMENTATIONNAME_HEADERMENUCONTROLLER "com.sun.star.comp.framework.HeaderMenuController" #define IMPLEMENTATIONNAME_FOOTERMENUCONTROLLER "com.sun.star.comp.framework.FooterMenuController" #define IMPLEMENTATIONNAME_NEWMENUCONTROLLER "com.sun.star.comp.framework.NewMenuController" +#define IMPLEMENTATIONNAME_TOOLBARMODEMENUCONTROLLER "com.sun.star.comp.framework.ToolbarModeMenuController" #define IMPLEMENTATIONNAME_TOOLBARSMENUCONTROLLER "com.sun.star.comp.framework.ToolBarsMenuController" #define IMPLEMENTATIONNAME_NOTEBOOKBARMENUCONTROLLER "com.sun.star.comp.framework.NotebookbarMenuController" #define IMPLEMENTATIONNAME_HELPONSTARTUP "com.sun.star.comp.framework.HelpOnStartup" diff --git a/framework/inc/uielement/toolbarmodemenucontroller.hxx b/framework/inc/uielement/toolbarmodemenucontroller.hxx new file mode 100644 index 000000000000..6f084b733010 --- /dev/null +++ b/framework/inc/uielement/toolbarmodemenucontroller.hxx @@ -0,0 +1,86 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_FRAMEWORK_INC_UIELEMENT_TOOLBARMODEMENUCONTROLLER_HXX +#define INCLUDED_FRAMEWORK_INC_UIELEMENT_TOOLBARMODEMENUCONTROLLER_HXX + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +namespace framework +{ + class ToolbarModeMenuController : public svt::PopupMenuControllerBase + { + using svt::PopupMenuControllerBase::disposing; + + public: + ToolbarModeMenuController( const css::uno::Reference< css::uno::XComponentContext >& xContext ); + virtual ~ToolbarModeMenuController(); + + // XServiceInfo + DECLARE_XSERVICEINFO + + // XPopupMenuController + virtual void SAL_CALL setPopupMenu( const css::uno::Reference< css::awt::XPopupMenu >& PopupMenu ) throw (css::uno::RuntimeException, std::exception) override; + + // XStatusListener + virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& Event ) throw ( css::uno::RuntimeException, std::exception ) override; + + // XMenuListener + virtual void SAL_CALL itemSelected( const css::awt::MenuEvent& rEvent ) throw (css::uno::RuntimeException, std::exception) override; + virtual void SAL_CALL itemActivated( const css::awt::MenuEvent& rEvent ) throw (css::uno::RuntimeException, std::exception) override; + + // XEventListener + virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) throw ( css::uno::RuntimeException, std::exception ) override; + + struct ExecuteInfo + { + css::uno::Reference< css::frame::XDispatch > xDispatch; + css::util::URL aTargetURL; + css::uno::Sequence< css::beans::PropertyValue > aArgs; + }; + + DECL_STATIC_LINK_TYPED( ToolbarModeMenuController, ExecuteHdl_Impl, void*, void ); + + private: + void fillPopupMenu( css::uno::Reference< css::awt::XPopupMenu >& rPopupMenu ); + + css::uno::Reference< css::uno::XComponentContext > m_xContext; + }; +} + +#endif // INCLUDED_FRAMEWORK_INC_UIELEMENT_TOOLBARMODEMENUCONTROLLER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/register/registertemp.cxx b/framework/source/register/registertemp.cxx index fb6bdabca78b..80ca3da5ac77 100644 --- a/framework/source/register/registertemp.cxx +++ b/framework/source/register/registertemp.cxx @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -61,6 +62,7 @@ COMPONENTGETFACTORY ( fwl, IFFACTORY( ::framework::DispatchDisabler ) else IFFACTORY( ::framework::DispatchRecorder ) else IFFACTORY( ::framework::DispatchRecorderSupplier ) else + IFFACTORY( ::framework::ToolbarModeMenuController ) else IFFACTORY( ::framework::ToolbarsMenuController ) else IFFACTORY( ::framework::NotebookbarMenuController ) else IFFACTORY( ::framework::FontMenuController ) else diff --git a/framework/source/uielement/notebookbarmenucontroller.cxx b/framework/source/uielement/notebookbarmenucontroller.cxx index 1c08b6e2b2eb..c5de77f306b5 100644 --- a/framework/source/uielement/notebookbarmenucontroller.cxx +++ b/framework/source/uielement/notebookbarmenucontroller.cxx @@ -30,6 +30,9 @@ #include #include #include +#include +#include +#include #include #include @@ -199,9 +202,7 @@ void SAL_CALL NotebookbarMenuController::itemSelected( const css::awt::MenuEvent OUStringBuffer aBuf(".uno:Notebookbar?File:string="); aBuf.append( aCmd ); aTargetURL.Complete = aBuf.makeStringAndClear(); - std::shared_ptr batch( comphelper::ConfigurationChanges::create( m_xContext ) ); - officecfg::Office::UI::Notebookbar::Active::set( aCmd, batch ); - batch->commit(); + xURLTransformer->parseStrict( aTargetURL ); Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY ); if ( xDispatchProvider.is() ) @@ -223,8 +224,43 @@ void SAL_CALL NotebookbarMenuController::itemActivated( const css::awt::MenuEven { OUString aActive = officecfg::Office::UI::Notebookbar::Active::get( m_xContext ); + const Reference xModuleManager = frame::ModuleManager::create( m_xContext ); + vcl::EnumContext::Application eApp = vcl::EnumContext::GetApplicationEnum(xModuleManager->identify(m_xFrame)); + + OUStringBuffer aPath("org.openoffice.Office.UI.ToolbarMode/Applications/"); + switch ( eApp ) + { + case vcl::EnumContext::Application::Application_Writer: + aPath.append("Writer"); + break; + case vcl::EnumContext::Application::Application_Calc: + aPath.append("Calc"); + break; + case vcl::EnumContext::Application::Application_Impress: + aPath.append("Impress"); + break; + case vcl::EnumContext::Application::Application_Draw: + aPath.append("Draw"); + break; + default: + break; + } + + const utl::OConfigurationTreeRoot aModesNode( + m_xContext, + aPath.makeStringAndClear(), + false); + if ( !aModesNode.isValid() ) + return; + + // Entries are enabled only when Notebookbar mode is active + bool bActive = ( comphelper::getString( aModesNode.getNodeValue( "Active" ) ).compareTo("Notebookbar") == 0 ); + for ( int i = 0; i < m_xPopupMenu->getItemCount(); ++i ) + { m_xPopupMenu->checkItem( i+1, ( aActive.compareTo( m_xPopupMenu->getCommand( i+1 ) ) == 0 ) ); + m_xPopupMenu->enableItem( i+1, bActive ); + } } // XPopupMenuController diff --git a/framework/source/uielement/toolbarmodemenucontroller.cxx b/framework/source/uielement/toolbarmodemenucontroller.cxx new file mode 100644 index 000000000000..b39fa3b7877b --- /dev/null +++ b/framework/source/uielement/toolbarmodemenucontroller.cxx @@ -0,0 +1,325 @@ +/* -*- 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 + +#include "services.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Defines + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::ui; + +namespace framework +{ + +DEFINE_XSERVICEINFO_MULTISERVICE_2 ( ToolbarModeMenuController , + OWeakObject , + SERVICENAME_POPUPMENUCONTROLLER , + IMPLEMENTATIONNAME_TOOLBARMODEMENUCONTROLLER + ) + +DEFINE_INIT_SERVICE ( ToolbarModeMenuController, {} ) + +ToolbarModeMenuController::ToolbarModeMenuController( const css::uno::Reference< css::uno::XComponentContext >& xContext ) : + svt::PopupMenuControllerBase( xContext ), + m_xContext( xContext ) +{ +} + +ToolbarModeMenuController::~ToolbarModeMenuController() +{ +} + +void ToolbarModeMenuController::fillPopupMenu( Reference< css::awt::XPopupMenu >& rPopupMenu ) +{ + if ( SvtMiscOptions().DisableUICustomization() ) + return; + + SolarMutexGuard aSolarMutexGuard; + resetPopupMenu( rPopupMenu ); + + const Reference xContext (::comphelper::getProcessComponentContext() ); + const Reference xModuleManager = frame::ModuleManager::create( xContext ); + vcl::EnumContext::Application eApp = vcl::EnumContext::GetApplicationEnum(xModuleManager->identify(m_xFrame)); + + OUStringBuffer aPath("org.openoffice.Office.UI.ToolbarMode/Applications/"); + switch ( eApp ) + { + case vcl::EnumContext::Application::Application_Writer: + aPath.append("Writer"); + break; + case vcl::EnumContext::Application::Application_Calc: + aPath.append("Calc"); + break; + case vcl::EnumContext::Application::Application_Impress: + aPath.append("Impress"); + break; + case vcl::EnumContext::Application::Application_Draw: + aPath.append("Draw"); + break; + default: + break; + } + aPath.append("/Modes"); + + const utl::OConfigurationTreeRoot aModesNode( + m_xContext, + aPath.makeStringAndClear(), + false); + if ( !aModesNode.isValid() ) + return; + + const Sequence aModeNodeNames (aModesNode.getNodeNames()); + const sal_Int32 nCount(aModeNodeNames.getLength()); + + for ( sal_Int32 nReadIndex = 0; nReadIndex < nCount; ++nReadIndex ) + { + const utl::OConfigurationNode aModeNode(aModesNode.openNode(aModeNodeNames[nReadIndex])); + if ( !aModeNode.isValid() ) + continue; + + OUString aLabel = comphelper::getString( aModeNode.getNodeValue( "Label" ) ); + OUString aCommandArg = comphelper::getString( aModeNode.getNodeValue( "CommandArg" ) ); + long nPosition = comphelper::getINT32( aModeNode.getNodeValue( "MenuPosition" ) ); + + m_xPopupMenu->insertItem( nReadIndex+1, aLabel, css::awt::MenuItemStyle::RADIOCHECK, nPosition ); + rPopupMenu->setCommand( nReadIndex+1, aCommandArg ); + } +} + +// XEventListener +void SAL_CALL ToolbarModeMenuController::disposing( const EventObject& ) throw ( RuntimeException, std::exception ) +{ + Reference< css::awt::XMenuListener > xHolder(static_cast(this), UNO_QUERY ); + + osl::MutexGuard aLock( m_aMutex ); + m_xFrame.clear(); + m_xDispatch.clear(); + + if ( m_xPopupMenu.is() ) + m_xPopupMenu->removeMenuListener( Reference< css::awt::XMenuListener >(static_cast(this), UNO_QUERY )); + m_xPopupMenu.clear(); +} + +// XStatusListener +void SAL_CALL ToolbarModeMenuController::statusChanged( const FeatureStateEvent& Event ) throw ( RuntimeException, std::exception ) +{ + OUString aFeatureURL( Event.FeatureURL.Complete ); + + // All other status events will be processed here + osl::ClearableMutexGuard aLock( m_aMutex ); + Reference< css::awt::XPopupMenu > xPopupMenu( m_xPopupMenu ); + aLock.clear(); + + if ( xPopupMenu.is() ) + { + SolarMutexGuard aGuard; + VCLXPopupMenu* pXPopupMenu = static_cast(VCLXMenu::GetImplementation( xPopupMenu )); + PopupMenu* pVCLPopupMenu = pXPopupMenu ? static_cast(pXPopupMenu->GetMenu()) : nullptr; + + SAL_WARN_IF(!pVCLPopupMenu, "fwk.uielement", "worrying lack of popup menu"); + if (!pVCLPopupMenu) + return; + + bool bSetCheckmark = false; + bool bCheckmark = false; + for ( sal_uInt16 i = 0; i < pVCLPopupMenu->GetItemCount(); i++ ) + { + sal_uInt16 nId = pVCLPopupMenu->GetItemId( i ); + if ( nId == 0 ) + continue; + + OUString aCmd = pVCLPopupMenu->GetItemCommand( nId ); + if ( aCmd == aFeatureURL ) + { + // Enable/disable item + pVCLPopupMenu->EnableItem( nId, Event.IsEnabled ); + + // Checkmark + if ( Event.State >>= bCheckmark ) + bSetCheckmark = true; + + if ( bSetCheckmark ) + pVCLPopupMenu->CheckItem( nId, bCheckmark ); + else + { + OUString aItemText; + + if ( Event.State >>= aItemText ) + pVCLPopupMenu->SetItemText( nId, aItemText ); + } + } + } + } +} + +// XMenuListener +void SAL_CALL ToolbarModeMenuController::itemSelected( const css::awt::MenuEvent& rEvent ) throw (RuntimeException, std::exception) +{ + Reference< css::awt::XPopupMenu > xPopupMenu; + Reference< XURLTransformer > xURLTransformer; + Reference< XFrame > xFrame; + Reference< XNameAccess > xPersistentWindowState; + + osl::ClearableMutexGuard aLock( m_aMutex ); + xPopupMenu = m_xPopupMenu; + xURLTransformer = m_xURLTransformer; + xFrame = m_xFrame; + aLock.clear(); + + if ( xPopupMenu.is() ) + { + VCLXPopupMenu* pPopupMenu = static_cast(VCLXPopupMenu::GetImplementation( xPopupMenu )); + if ( pPopupMenu ) + { + SolarMutexGuard aSolarMutexGuard; + PopupMenu* pVCLPopupMenu = static_cast(pPopupMenu->GetMenu()); + + OUString aCmd( pVCLPopupMenu->GetItemCommand( rEvent.MenuId )); + OUStringBuffer aBuf(".uno:ToolbarMode?Mode:string="); + aBuf.append( aCmd ); + URL aTargetURL; + Sequence aArgs; + + aTargetURL.Complete = aBuf.makeStringAndClear(); + xURLTransformer->parseStrict( aTargetURL ); + Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY ); + if ( xDispatchProvider.is() ) + { + Reference< XDispatch > xDispatch = xDispatchProvider->queryDispatch( + aTargetURL, OUString(), 0 ); + + ExecuteInfo* pExecuteInfo = new ExecuteInfo; + pExecuteInfo->xDispatch = xDispatch; + pExecuteInfo->aTargetURL = aTargetURL; + pExecuteInfo->aArgs = aArgs; + Application::PostUserEvent( LINK(nullptr, ToolbarModeMenuController, ExecuteHdl_Impl), pExecuteInfo ); + } + } + } +} + +void SAL_CALL ToolbarModeMenuController::itemActivated( const css::awt::MenuEvent& ) throw (RuntimeException, std::exception) +{ + const Reference xModuleManager = frame::ModuleManager::create( m_xContext ); + vcl::EnumContext::Application eApp = vcl::EnumContext::GetApplicationEnum(xModuleManager->identify(m_xFrame)); + + OUStringBuffer aPath("org.openoffice.Office.UI.ToolbarMode/Applications/"); + switch ( eApp ) + { + case vcl::EnumContext::Application::Application_Writer: + aPath.append("Writer"); + break; + case vcl::EnumContext::Application::Application_Calc: + aPath.append("Calc"); + break; + case vcl::EnumContext::Application::Application_Impress: + aPath.append("Impress"); + break; + case vcl::EnumContext::Application::Application_Draw: + aPath.append("Draw"); + break; + default: + break; + } + + const utl::OConfigurationTreeRoot aModesNode( + m_xContext, + aPath.makeStringAndClear(), + false); + if ( !aModesNode.isValid() ) + return; + + OUString aMode = comphelper::getString( aModesNode.getNodeValue( "Active" ) ); + + for ( int i = 0; i < m_xPopupMenu->getItemCount(); ++i ) + m_xPopupMenu->checkItem( i+1, (aMode.compareTo( m_xPopupMenu->getCommand( i+1 ) ) == 0) ); +} + +// XPopupMenuController +void SAL_CALL ToolbarModeMenuController::setPopupMenu( const Reference< css::awt::XPopupMenu >& xPopupMenu ) throw ( RuntimeException, std::exception ) +{ + osl::MutexGuard aLock( m_aMutex ); + + throwIfDisposed(); + + if ( m_xFrame.is() && !m_xPopupMenu.is() ) + { + // Create popup menu on demand + SolarMutexGuard aSolarMutexGuard; + + m_xPopupMenu = xPopupMenu; + m_xPopupMenu->addMenuListener( Reference< css::awt::XMenuListener >( static_cast(this), UNO_QUERY )); + fillPopupMenu( m_xPopupMenu ); + } +} + +IMPL_STATIC_LINK_TYPED( ToolbarModeMenuController, ExecuteHdl_Impl, void*, p, void ) +{ + ExecuteInfo* pExecuteInfo = static_cast(p); + try + { + // Asynchronous execution as this can lead to our own destruction! + // Framework can recycle our current frame and the layout manager disposes all user interface + // elements if a component gets detached from its frame! + if ( pExecuteInfo->xDispatch.is() ) + { + pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs ); + } + } + catch ( const Exception& ) + { + } + + delete pExecuteInfo; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/util/fwl.component b/framework/util/fwl.component index 7e8fa1b140e7..b7a56dc96f7a 100644 --- a/framework/util/fwl.component +++ b/framework/util/fwl.component @@ -61,6 +61,9 @@ + + + -- cgit