diff options
Diffstat (limited to 'framework/source/uielement')
43 files changed, 19227 insertions, 0 deletions
diff --git a/framework/source/uielement/addonstoolbarmanager.cxx b/framework/source/uielement/addonstoolbarmanager.cxx new file mode 100644 index 000000000000..0c4c610bd4b0 --- /dev/null +++ b/framework/source/uielement/addonstoolbarmanager.cxx @@ -0,0 +1,559 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include <uielement/addonstoolbarmanager.hxx> +#include <uielement/toolbarmerger.hxx> + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ + + +#ifndef __FRAMEWORK_UIELEMENT_TOOLBAR_HXX +#include <uielement/toolbar.hxx> +#endif +#ifndef __FRAMEWORK_UIELEMENT_GENERICTOOLBARCONTROLLER_HXX +#include <uielement/generictoolbarcontroller.hxx> +#endif +#include <threadhelp/resetableguard.hxx> +#include "services.h" +#include <helper/imageproducer.hxx> +#include <classes/sfxhelperfunctions.hxx> +#include <classes/fwkresid.hxx> +#ifndef __FRAMEWORK_CLASES_RESOURCE_HRC_ +#include <classes/resource.hrc> +#endif +#include <classes/addonsoptions.hxx> +#ifndef __FRAMEWORK_UIELEMENT_COMBOBOXTOOLBARCONTROLLER_HXX +#include <uielement/comboboxtoolbarcontroller.hxx> +#endif +#ifndef __FRAMEWORK_UIELEMENT_IMAGEBUTTONTOOLBARCONTROLLER_HXX +#include <uielement/imagebuttontoolbarcontroller.hxx> +#endif +#ifndef __FRAMEWORK_UIELEMENT_TOGGLEBUTTONTOOLBARCONTROLLER_HXX +#include <uielement/togglebuttontoolbarcontroller.hxx> +#endif +#include <uielement/buttontoolbarcontroller.hxx> +#include <uielement/spinfieldtoolbarcontroller.hxx> +#include <uielement/edittoolbarcontroller.hxx> +#include <uielement/dropdownboxtoolbarcontroller.hxx> +#include <uielement/toolbarmerger.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/ui/ItemType.hpp> +#include <com/sun/star/frame/XToolbarController.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#ifndef _COM_SUN_STAR_BEANS_XLAYOUTMANAGER_HPP_ +#include <com/sun/star/beans/XPropertySet.hpp> +#endif +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/frame/XLayoutManager.hpp> +#ifndef _COM_SUN_STAR_UI_XDOCKINGAREA_HPP_ +#include <com/sun/star/ui/DockingArea.hpp> +#endif +#include <com/sun/star/lang/XMultiComponentFactory.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ +#include <svtools/imgdef.hxx> +#include <svtools/toolboxcontroller.hxx> +#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ +#include <toolkit/unohlp.hxx> +#endif + +#include <svtools/miscopt.hxx> +#include <vcl/svapp.hxx> +#include <vcl/menu.hxx> +#include <vcl/syswin.hxx> +#include <vcl/taskpanelist.hxx> + +//_________________________________________________________________________________________________________________ +// namespaces +//_________________________________________________________________________________________________________________ + +using namespace ::com::sun::star; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::ui; + +namespace framework +{ + +static const char TOOLBOXITEM_SEPARATOR_STR[] = "private:separator"; +static const USHORT TOOLBOXITEM_SEPARATOR_STR_LEN = sizeof( TOOLBOXITEM_SEPARATOR_STR )-1; + +AddonsToolBarManager::AddonsToolBarManager( const Reference< XMultiServiceFactory >& rServiceManager, + const Reference< XFrame >& rFrame, + const rtl::OUString& rResourceName, + ToolBar* pToolBar ) : + ToolBarManager( rServiceManager, rFrame, rResourceName, pToolBar ) +{ + // Configuration data is retrieved from non-writable configuration layer. Therefor we + // must disable some menu entries. + m_bCanBeCustomized = sal_False; + + m_pToolBar->SetMenuType( TOOLBOX_MENUTYPE_CLIPPEDITEMS ); + m_pToolBar->SetSelectHdl( LINK( this, AddonsToolBarManager, Select) ); + m_pToolBar->SetActivateHdl( LINK( this, AddonsToolBarManager, Activate) ); + m_pToolBar->SetDeactivateHdl( LINK( this, AddonsToolBarManager, Deactivate) ); + m_pToolBar->SetClickHdl( LINK( this, AddonsToolBarManager, Click ) ); + m_pToolBar->SetDoubleClickHdl( LINK( this, AddonsToolBarManager, DoubleClick ) ); + m_pToolBar->SetCommandHdl( LINK( this, AddonsToolBarManager, Command ) ); + m_pToolBar->SetStateChangedHdl( LINK( this, AddonsToolBarManager, StateChanged ) ); + m_pToolBar->SetDataChangedHdl( LINK( this, AddonsToolBarManager, DataChanged ) ); +} + +AddonsToolBarManager::~AddonsToolBarManager() +{ +} + +static sal_Bool IsCorrectContext( const ::rtl::OUString& rModuleIdentifier, const ::rtl::OUString& aContextList ) +{ + if ( aContextList.getLength() == 0 ) + return sal_True; + + if ( rModuleIdentifier.getLength() > 0 ) + { + sal_Int32 nIndex = aContextList.indexOf( rModuleIdentifier ); + return ( nIndex >= 0 ); + } + + return sal_False; +} + +static Image RetrieveImage( Reference< com::sun::star::frame::XFrame >& rFrame, + const rtl::OUString& aImageId, + const rtl::OUString& aURL, + BOOL bBigImage, + BOOL bHiContrast ) +{ + Image aImage; + + if ( aImageId.getLength() > 0 ) + { + aImage = framework::AddonsOptions().GetImageFromURL( aImageId, bBigImage, bHiContrast ); + if ( !!aImage ) + return aImage; + else + aImage = GetImageFromURL( rFrame, aImageId, bBigImage, bHiContrast ); + if ( !!aImage ) + return aImage; + } + + aImage = framework::AddonsOptions().GetImageFromURL( aURL, bBigImage, bHiContrast ); + if ( !aImage ) + aImage = GetImageFromURL( rFrame, aImageId, bBigImage, bHiContrast ); + + return aImage; +} + +// XComponent +void SAL_CALL AddonsToolBarManager::dispose() throw( RuntimeException ) +{ + Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY ); + + { + // Remove addon specific data from toolbar items. + ResetableGuard aGuard( m_aLock ); + for ( sal_uInt16 n = 0; n < m_pToolBar->GetItemCount(); n++ ) + { + USHORT nId( m_pToolBar->GetItemId( n ) ); + + if ( nId > 0 ) + { + AddonsParams* pRuntimeItemData = (AddonsParams*)m_pToolBar->GetItemData( nId ); + if ( pRuntimeItemData ) + delete pRuntimeItemData; + m_pToolBar->SetItemData( nId, NULL ); + } + } + } + + // Base class will destroy our m_pToolBar member + ToolBarManager::dispose(); +} + +bool AddonsToolBarManager::MenuItemAllowed( sal_uInt16 nId ) const +{ + if (( nId == MENUITEM_TOOLBAR_VISIBLEBUTTON ) || + ( nId == MENUITEM_TOOLBAR_CUSTOMIZETOOLBAR )) + return false; + else + return true; +} + +void AddonsToolBarManager::RefreshImages() +{ + sal_Bool bBigImages( SvtMiscOptions().AreCurrentSymbolsLarge() ); + for ( USHORT nPos = 0; nPos < m_pToolBar->GetItemCount(); nPos++ ) + { + USHORT nId( m_pToolBar->GetItemId( nPos ) ); + + if ( nId > 0 ) + { + ::rtl::OUString aCommandURL = m_pToolBar->GetItemCommand( nId ); + ::rtl::OUString aImageId; + AddonsParams* pRuntimeItemData = (AddonsParams*)m_pToolBar->GetItemData( nId ); + if ( pRuntimeItemData ) + aImageId = pRuntimeItemData->aImageId; + + m_pToolBar->SetItemImage( nId, RetrieveImage( m_xFrame, + aImageId, + aCommandURL, + bBigImages, + m_bIsHiContrast )); + } + } +} + +void AddonsToolBarManager::FillToolbar( const Sequence< Sequence< PropertyValue > >& rAddonToolbar ) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + return; + + USHORT nId( 1 ); + + RemoveControllers(); + + m_pToolBar->Clear(); + m_aControllerMap.clear(); + + ::rtl::OUString aModuleIdentifier; + try + { + Reference< XModuleManager > xModuleManager( + m_xServiceManager->createInstance( SERVICENAME_MODULEMANAGER ), UNO_QUERY_THROW ); + aModuleIdentifier = xModuleManager->identify( m_xFrame ); + } + catch ( Exception& ) + { + } + + Reference< XMultiComponentFactory > xToolbarControllerFactory( m_xToolbarControllerRegistration, UNO_QUERY ); + Reference< XComponentContext > xComponentContext; + Reference< XPropertySet > xProps( m_xServiceManager, UNO_QUERY ); + + if ( xProps.is() ) + xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xComponentContext; + + sal_uInt32 nElements( 0 ); + sal_Bool bAppendSeparator( sal_False ); + Reference< XWindow > xToolbarWindow = VCLUnoHelper::GetInterface( m_pToolBar ); + for ( sal_uInt32 n = 0; n < (sal_uInt32)rAddonToolbar.getLength(); n++ ) + { + rtl::OUString aValueName; + + rtl::OUString aURL; + rtl::OUString aTitle; + rtl::OUString aImageId; + rtl::OUString aContext; + rtl::OUString aTarget; + rtl::OUString aControlType; + sal_uInt16 nWidth( 0 ); + + const Sequence< PropertyValue >& rSeq = rAddonToolbar[n]; + + ToolBarMerger::ConvertSequenceToValues( rSeq, aURL, aTitle, aImageId, aTarget, aContext, aControlType, nWidth ); + + if ( IsCorrectContext( aModuleIdentifier, aContext )) + { + if ( aURL.equalsAsciiL( TOOLBOXITEM_SEPARATOR_STR, TOOLBOXITEM_SEPARATOR_STR_LEN )) + { + USHORT nCount = m_pToolBar->GetItemCount(); + if ( nCount > 0 && ( m_pToolBar->GetItemType( nCount-1 ) != TOOLBOXITEM_SEPARATOR ) && nElements > 0 ) + { + nElements = 0; + m_pToolBar->InsertSeparator(); + } + } + else + { + USHORT nCount = m_pToolBar->GetItemCount(); + if ( bAppendSeparator && nCount > 0 && ( m_pToolBar->GetItemType( nCount-1 ) != TOOLBOXITEM_SEPARATOR )) + { + // We have to append a separator first if the last item is not a separator + m_pToolBar->InsertSeparator(); + } + bAppendSeparator = FALSE; + + m_pToolBar->InsertItem( nId, aTitle ); + + Image aImage = RetrieveImage( m_xFrame, aImageId, aURL, !m_bSmallSymbols, m_bIsHiContrast ); + if ( !!aImage ) + m_pToolBar->SetItemImage( nId, aImage ); + + // Create TbRuntimeItemData to hold additional information we will need in the future + AddonsParams* pRuntimeItemData = new AddonsParams; + pRuntimeItemData->aImageId = aImageId; + pRuntimeItemData->aTarget = aTarget; + m_pToolBar->SetItemData( nId, pRuntimeItemData ); + m_pToolBar->SetItemCommand( nId, aURL ); + + Reference< XStatusListener > xController; + + sal_Bool bMustBeInit( sal_True ); + + // Support external toolbar controller for add-ons! + if ( m_xToolbarControllerRegistration.is() && + m_xToolbarControllerRegistration->hasController( aURL, m_aModuleIdentifier )) + { + if ( xToolbarControllerFactory.is() ) + { + Sequence< Any > aArgs(5); + PropertyValue aPropValue; + + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ModuleName" )); + aPropValue.Value <<= m_aModuleIdentifier; + aArgs[0] <<= aPropValue; + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" )); + aPropValue.Value <<= m_xFrame; + aArgs[1] <<= aPropValue; + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ServiceManager" )); + aPropValue.Value <<= m_xServiceManager; + aArgs[2] <<= aPropValue; + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ParentWindow" )); + aPropValue.Value <<= xToolbarWindow; + aArgs[3] <<= aPropValue; + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ItemId" )); + aPropValue.Value = makeAny( sal_Int32( nId )); + aArgs[4] <<= aPropValue; + + try + { + xController = Reference< XStatusListener >( xToolbarControllerFactory->createInstanceWithArgumentsAndContext( + aURL, aArgs, xComponentContext ), + UNO_QUERY ); + } + catch ( uno::Exception& ) + { + } + bMustBeInit = sal_False; // factory called init already! + } + } + else + { + ::cppu::OWeakObject* pController = 0; + + pController = ToolBarMerger::CreateController( m_xServiceManager, m_xFrame, m_pToolBar, aURL, nId, nWidth, aControlType ); + xController = Reference< XStatusListener >( pController, UNO_QUERY ); + } + + // insert controller to the map + m_aControllerMap[nId] = xController; + + Reference< XInitialization > xInit( xController, UNO_QUERY ); + if ( xInit.is() && bMustBeInit ) + { + PropertyValue aPropValue; + Sequence< Any > aArgs( 3 ); + aPropValue.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" )); + aPropValue.Value <<= m_xFrame; + aArgs[0] <<= aPropValue; + aPropValue.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CommandURL" )); + aPropValue.Value <<= aURL; + aArgs[1] <<= aPropValue; + aPropValue.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ServiceManager" )); + aPropValue.Value <<= m_xServiceManager; + aArgs[2] <<= aPropValue; + try + { + xInit->initialize( aArgs ); + } + catch ( uno::Exception& ) + { + } + } + + // Request a item window from the toolbar controller and set it at the VCL toolbar + Reference< XToolbarController > xTbxController( xController, UNO_QUERY ); + if ( xTbxController.is() && xToolbarWindow.is() ) + { + Reference< XWindow > xWindow = xTbxController->createItemWindow( xToolbarWindow ); + if ( xWindow.is() ) + { + Window* pItemWin = VCLUnoHelper::GetWindow( xWindow ); + if ( pItemWin ) + { + WindowType nType = pItemWin->GetType(); + if ( nType == WINDOW_LISTBOX || nType == WINDOW_MULTILISTBOX || nType == WINDOW_COMBOBOX ) + pItemWin->SetAccessibleName( m_pToolBar->GetItemText( nId ) ); + m_pToolBar->SetItemWindow( nId, pItemWin ); + } + } + } + + // Notify controller implementation to its listeners. Controller is now useable from outside. + Reference< XUpdatable > xUpdatable( xController, UNO_QUERY ); + if ( xUpdatable.is() ) + { + try + { + xUpdatable->update(); + } + catch ( uno::Exception& ) + { + } + } + + ++nId; + ++nElements; + } + } + } + + AddFrameActionListener(); +} + +IMPL_LINK( AddonsToolBarManager, Click, ToolBox*, EMPTYARG ) +{ + if ( m_bDisposed ) + return 1; + + USHORT nId( m_pToolBar->GetCurItemId() ); + ToolBarControllerMap::const_iterator pIter = m_aControllerMap.find( nId ); + if ( pIter != m_aControllerMap.end() ) + { + Reference< XToolbarController > xController( pIter->second, UNO_QUERY ); + + if ( xController.is() ) + xController->click(); + } + + return 1; +} + +IMPL_LINK( AddonsToolBarManager, DoubleClick, ToolBox*, EMPTYARG ) +{ + if ( m_bDisposed ) + return 1; + + USHORT nId( m_pToolBar->GetCurItemId() ); + ToolBarControllerMap::const_iterator pIter = m_aControllerMap.find( nId ); + if ( pIter != m_aControllerMap.end() ) + { + Reference< XToolbarController > xController( pIter->second, UNO_QUERY ); + + if ( xController.is() ) + xController->doubleClick(); + } + + return 1; +} + +IMPL_LINK( AddonsToolBarManager, Command, CommandEvent*, EMPTYARG ) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + return 1; + + return 0; +} + +IMPL_LINK( AddonsToolBarManager, Select, ToolBox*, EMPTYARG ) +{ + if ( m_bDisposed ) + return 1; + + sal_Int16 nKeyModifier( (sal_Int16)m_pToolBar->GetModifier() ); + USHORT nId( m_pToolBar->GetCurItemId() ); + ToolBarControllerMap::const_iterator pIter = m_aControllerMap.find( nId ); + if ( pIter != m_aControllerMap.end() ) + { + Reference< XToolbarController > xController( pIter->second, UNO_QUERY ); + + if ( xController.is() ) + xController->execute( nKeyModifier ); + } + + return 1; +} + +IMPL_LINK( AddonsToolBarManager, Highlight, ToolBox*, EMPTYARG ) +{ + return 1; +} + +IMPL_LINK( AddonsToolBarManager, Activate, ToolBox*, EMPTYARG ) +{ + return 1; +} + +IMPL_LINK( AddonsToolBarManager, Deactivate, ToolBox*, EMPTYARG ) +{ + return 1; +} + +IMPL_LINK( AddonsToolBarManager, StateChanged, StateChangedType*, pStateChangedType ) +{ + if ( *pStateChangedType == STATE_CHANGE_CONTROLBACKGROUND ) + { + // Check if we need to get new images for normal/high contrast mode + CheckAndUpdateImages(); + } + return 1; +} + +IMPL_LINK( AddonsToolBarManager, DataChanged, DataChangedEvent*, pDataChangedEvent ) +{ + if ((( pDataChangedEvent->GetType() == DATACHANGED_SETTINGS ) || + ( pDataChangedEvent->GetType() == DATACHANGED_DISPLAY )) && + ( pDataChangedEvent->GetFlags() & SETTINGS_STYLE )) + { + // Check if we need to get new images for normal/high contrast mode + CheckAndUpdateImages(); + } + + for ( USHORT nPos = 0; nPos < m_pToolBar->GetItemCount(); ++nPos ) + { + const USHORT nId = m_pToolBar->GetItemId(nPos); + Window* pWindow = m_pToolBar->GetItemWindow( nId ); + if ( pWindow ) + { + const DataChangedEvent& rDCEvt( *pDataChangedEvent ); + pWindow->DataChanged( rDCEvt ); + } + } + + return 1; +} + +} + diff --git a/framework/source/uielement/addonstoolbarwrapper.cxx b/framework/source/uielement/addonstoolbarwrapper.cxx new file mode 100644 index 000000000000..315d1b6e0bf8 --- /dev/null +++ b/framework/source/uielement/addonstoolbarwrapper.cxx @@ -0,0 +1,196 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ + + +#include <uielement/addonstoolbarwrapper.hxx> +#include <threadhelp/resetableguard.hxx> +#include <helper/actiontriggerhelper.hxx> +#include <uielement/constitemcontainer.hxx> +#include <uielement/rootitemcontainer.hxx> +#include <uielement/addonstoolbarmanager.hxx> + +#ifndef __FRAMEWORK_UIELEMENT_TOOLBARW_HXX_ +#include <uielement/toolbar.hxx> +#endif + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/awt/XSystemDependentMenuPeer.hpp> +#include <com/sun/star/awt/XMenuBar.hpp> +#include <com/sun/star/container/XIndexContainer.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/ui/UIElementType.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ + +#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ +#include <toolkit/unohlp.hxx> +#endif +#include <toolkit/awt/vclxwindow.hxx> +#include <comphelper/processfactory.hxx> + +#include <svtools/miscopt.hxx> +#include <vcl/svapp.hxx> +#include <vcl/toolbox.hxx> +#include <rtl/logfile.hxx> + +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; +using namespace com::sun::star::frame; +using namespace com::sun::star::lang; +using namespace com::sun::star::container; +using namespace com::sun::star::awt; +using namespace ::com::sun::star::ui; + +namespace framework +{ + +AddonsToolBarWrapper::AddonsToolBarWrapper( const Reference< XMultiServiceFactory >& xServiceManager ) : + UIElementWrapperBase( UIElementType::TOOLBAR ), + m_xServiceManager( xServiceManager ) +{ +} + +AddonsToolBarWrapper::~AddonsToolBarWrapper() +{ +} + +// XComponent +void SAL_CALL AddonsToolBarWrapper::dispose() throw ( RuntimeException ) +{ + Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY ); + + com::sun::star::lang::EventObject aEvent( xThis ); + m_aListenerContainer.disposeAndClear( aEvent ); + + ResetableGuard aLock( m_aLock ); + + if ( m_xToolBarManager.is() ) + m_xToolBarManager->dispose(); + m_xToolBarManager.clear(); + m_xToolBarWindow.clear(); + + m_bDisposed = sal_True; +} + +// XInitialization +void SAL_CALL AddonsToolBarWrapper::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException ) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + if ( !m_bInitialized ) + { + UIElementWrapperBase::initialize( aArguments ); + + for ( sal_Int32 n = 0; n < aArguments.getLength(); n++ ) + { + PropertyValue aPropValue; + if ( aArguments[n] >>= aPropValue ) + { + if ( aPropValue.Name.equalsAscii( "ConfigurationData" )) + aPropValue.Value >>= m_aConfigData; + } + } + + Reference< XFrame > xFrame( m_xWeakFrame ); + if ( xFrame.is() && m_aConfigData.getLength() > 0 ) + { + // Create VCL based toolbar which will be filled with settings data + ToolBar* pToolBar = 0; + AddonsToolBarManager* pToolBarManager = 0; + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + Window* pWindow = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() ); + if ( pWindow ) + { + ULONG nStyles = WB_LINESPACING | WB_BORDER | WB_SCROLL | WB_MOVEABLE | WB_3DLOOK | WB_DOCKABLE | WB_SIZEABLE | WB_CLOSEABLE; + + pToolBar = new ToolBar( pWindow, nStyles ); + m_xToolBarWindow = VCLUnoHelper::GetInterface( pToolBar ); + pToolBarManager = new AddonsToolBarManager( m_xServiceManager, xFrame, m_aResourceURL, pToolBar ); + pToolBar->SetToolBarManager( pToolBarManager ); + m_xToolBarManager = Reference< XComponent >( static_cast< OWeakObject *>( pToolBarManager ), UNO_QUERY ); + } + } + + try + { + if (( m_aConfigData.getLength() > 0 ) && pToolBar && pToolBarManager ) + { + // Fill toolbar with container contents + pToolBarManager->FillToolbar( m_aConfigData ); + pToolBar->SetOutStyle( SvtMiscOptions().GetToolboxStyle() ); + pToolBar->EnableCustomize( TRUE ); + ::Size aActSize( pToolBar->GetSizePixel() ); + ::Size aSize( pToolBar->CalcWindowSizePixel() ); + aSize.Width() = aActSize.Width(); + pToolBar->SetSizePixel( aSize ); + } + } + catch ( NoSuchElementException& ) + { + } + } + } +} + +// XUIElement interface +Reference< XInterface > SAL_CALL AddonsToolBarWrapper::getRealInterface() throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_xToolBarManager.is() ) + { + AddonsToolBarManager* pToolBarManager = static_cast< AddonsToolBarManager *>( m_xToolBarManager.get() ); + if ( pToolBarManager ) + { + Window* pWindow = (Window *)pToolBarManager->GetToolBar(); + return Reference< XInterface >( VCLUnoHelper::GetInterface( pWindow ), UNO_QUERY ); + } + } + + return Reference< XInterface >(); +} + +} // namespace framework + diff --git a/framework/source/uielement/buttontoolbarcontroller.cxx b/framework/source/uielement/buttontoolbarcontroller.cxx new file mode 100644 index 000000000000..4f55448d65d1 --- /dev/null +++ b/framework/source/uielement/buttontoolbarcontroller.cxx @@ -0,0 +1,337 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + +#ifndef __FRAMEWORK_UIELEMENT_BUTTONTOOLBARCONTROLLER_HXX +#include "uielement/buttontoolbarcontroller.hxx" +#endif + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ + +#ifndef __FRAMEWORK_TOOLBAR_HXX_ +#include "uielement/toolbar.hxx" +#endif + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include "com/sun/star/util/XMacroExpander.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/beans/XPropertySet.hpp" + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ + +#include <rtl/uri.hxx> +#include <vos/mutex.hxx> +#include <comphelper/processfactory.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <tools/urlobj.hxx> +#include <vcl/svapp.hxx> +#include <vcl/mnemonic.hxx> +#include <vcl/window.hxx> +#include <vcl/graph.hxx> +#include <vcl/bitmap.hxx> +#include <svtools/filter.hxx> +#include <svtools/miscopt.hxx> +#include <dispatch/uieventloghelper.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::util; + +namespace framework +{ + +ButtonToolbarController::ButtonToolbarController( + const uno::Reference< lang::XMultiServiceFactory >& rServiceManager, + ToolBox* pToolBar, + const rtl::OUString& aCommand ) : + cppu::OWeakObject(), + m_bInitialized( sal_False ), + m_bDisposed( sal_False ), + m_aCommandURL( aCommand ), + m_xServiceManager( rServiceManager ), + m_pToolbar( pToolBar ) +{ +} + +ButtonToolbarController::~ButtonToolbarController() +{ +} + + // XInterface +uno::Any SAL_CALL ButtonToolbarController::queryInterface( const uno::Type& rType ) +throw (::com::sun::star::uno::RuntimeException) +{ + Any a = ::cppu::queryInterface( + rType , + static_cast< frame::XStatusListener* >( this ), + static_cast< frame::XToolbarController* >( this ), + static_cast< lang::XInitialization* >( this ), + static_cast< lang::XComponent* >( this ), + static_cast< util::XUpdatable* >( this )); + + if ( a.hasValue() ) + return a; + + return cppu::OWeakObject::queryInterface( rType ); +} + +void SAL_CALL ButtonToolbarController::acquire() throw () +{ + cppu::OWeakObject::acquire(); +} + +void SAL_CALL ButtonToolbarController::release() throw () +{ + cppu::OWeakObject::release(); +} + +// XInitialization +void SAL_CALL ButtonToolbarController::initialize( + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) +throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + const rtl::OUString aFrameName( RTL_CONSTASCII_USTRINGPARAM( "Frame" )); + const rtl::OUString aCommandURLName( RTL_CONSTASCII_USTRINGPARAM( "CommandURL" )); + const rtl::OUString aServiceManagerName( RTL_CONSTASCII_USTRINGPARAM( "ServiceManager" )); + + bool bInitialized( true ); + + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + if ( m_bDisposed ) + throw DisposedException(); + + bInitialized = m_bInitialized; + } + + if ( !bInitialized ) + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + m_bInitialized = sal_True; + + PropertyValue aPropValue; + for ( int i = 0; i < aArguments.getLength(); i++ ) + { + if ( aArguments[i] >>= aPropValue ) + { + if ( aPropValue.Name.equalsAscii( "Frame" )) + m_xFrame.set(aPropValue.Value,UNO_QUERY); + else if ( aPropValue.Name.equalsAscii( "CommandURL" )) + aPropValue.Value >>= m_aCommandURL; + else if ( aPropValue.Name.equalsAscii( "ServiceManager" )) + m_xServiceManager.set(aPropValue.Value,UNO_QUERY); + } + } + } +} + +// XComponent +void SAL_CALL ButtonToolbarController::dispose() throw (::com::sun::star::uno::RuntimeException) +{ + Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY ); + + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + if ( m_bDisposed ) + throw DisposedException(); + + m_xServiceManager.clear(); + m_xURLTransformer.clear(); + m_xFrame.clear(); + m_pToolbar = 0; + m_bDisposed = sal_True; + } +} + +void SAL_CALL ButtonToolbarController::addEventListener( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& ) +throw (::com::sun::star::uno::RuntimeException) +{ + // do nothing +} + +void SAL_CALL ButtonToolbarController::removeEventListener( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& ) +throw (::com::sun::star::uno::RuntimeException) +{ + // do nothing +} + +// XUpdatable +void SAL_CALL ButtonToolbarController::update() +throw (::com::sun::star::uno::RuntimeException) +{ + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + if ( m_bDisposed ) + throw DisposedException(); +} + +// XEventListener +void SAL_CALL ButtonToolbarController::disposing( + const com::sun::star::lang::EventObject& Source ) +throw ( ::com::sun::star::uno::RuntimeException ) +{ + uno::Reference< uno::XInterface > xSource( Source.Source ); + + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + if ( m_bDisposed ) + return; + + uno::Reference< uno::XInterface > xIfac( m_xFrame, uno::UNO_QUERY ); + if ( xIfac == xSource ) + m_xFrame.clear(); +} + +void SAL_CALL ButtonToolbarController::statusChanged( const ::com::sun::star::frame::FeatureStateEvent& ) +throw ( ::com::sun::star::uno::RuntimeException ) +{ + // do nothing + if ( m_bDisposed ) + throw DisposedException(); +} + +// XToolbarController +void SAL_CALL ButtonToolbarController::execute( sal_Int16 KeyModifier ) +throw (::com::sun::star::uno::RuntimeException) +{ + uno::Reference< frame::XDispatch > xDispatch; + uno::Reference< frame::XFrame > xFrame; + uno::Reference< util::XURLTransformer > xURLTransformer; + rtl::OUString aCommandURL; + ::com::sun::star::util::URL aTargetURL; + + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + if ( m_bDisposed ) + throw DisposedException(); + + if ( m_bInitialized && + m_xFrame.is() && + m_xServiceManager.is() && + m_aCommandURL.getLength() ) + { + if ( !m_xURLTransformer.is() ) + { + m_xURLTransformer = uno::Reference< util::XURLTransformer >( + m_xServiceManager->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.URLTransformer" ))), + uno::UNO_QUERY_THROW ); + } + + xFrame = m_xFrame; + aCommandURL = m_aCommandURL; + xURLTransformer = m_xURLTransformer; + } + } + + uno::Reference< frame::XDispatchProvider > xDispatchProvider( xFrame, uno::UNO_QUERY ); + if ( xDispatchProvider.is() ) + { + aTargetURL.Complete = aCommandURL; + xURLTransformer->parseStrict( aTargetURL ); + xDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 ); + } + + if ( xDispatch.is() ) + { + try + { + Sequence<PropertyValue> aArgs( 1 ); + + // Provide key modifier information to dispatch function + aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "KeyModifier" )); + aArgs[0].Value <<= KeyModifier; + + if(::comphelper::UiEventsLogger::isEnabled()) //#i88653# + UiEventLogHelper(::rtl::OUString::createFromAscii("ButtonToolbarController")).log(m_xServiceManager, m_xFrame, aTargetURL, aArgs); + xDispatch->dispatch( aTargetURL, aArgs ); + } + catch ( DisposedException& ) + { + } + } +} + +void SAL_CALL ButtonToolbarController::click() +throw (::com::sun::star::uno::RuntimeException) +{ + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + if ( m_bDisposed ) + throw DisposedException(); + + sal_Int16 nKeyModifier( (sal_Int16)m_pToolbar->GetModifier() ); + execute( nKeyModifier ); +} + +void SAL_CALL ButtonToolbarController::doubleClick() +throw (::com::sun::star::uno::RuntimeException) +{ + // do nothing + if ( m_bDisposed ) + throw DisposedException(); +} + +uno::Reference< awt::XWindow > SAL_CALL ButtonToolbarController::createPopupWindow() +throw (::com::sun::star::uno::RuntimeException) +{ + if ( m_bDisposed ) + throw DisposedException(); + + return uno::Reference< awt::XWindow >(); +} + +uno::Reference< awt::XWindow > SAL_CALL ButtonToolbarController::createItemWindow( + const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow >& ) +throw (::com::sun::star::uno::RuntimeException) +{ + if ( m_bDisposed ) + throw DisposedException(); + + return uno::Reference< awt::XWindow >(); +} + +} // namespace + diff --git a/framework/source/uielement/comboboxtoolbarcontroller.cxx b/framework/source/uielement/comboboxtoolbarcontroller.cxx new file mode 100644 index 000000000000..3921625cc76f --- /dev/null +++ b/framework/source/uielement/comboboxtoolbarcontroller.cxx @@ -0,0 +1,439 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + +#ifndef __FRAMEWORK_UIELEMENT_COMBOBOXTOOLBARCONTROLLER_HXX +#include "uielement/comboboxtoolbarcontroller.hxx" +#endif + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ + +#ifndef __FRAMEWORK_TOOLBAR_HXX_ +#include "uielement/toolbar.hxx" +#endif + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/frame/status/ItemStatus.hpp> +#include <com/sun/star/frame/status/ItemState.hpp> +#include <com/sun/star/frame/status/Visibility.hpp> +#include <com/sun/star/frame/XControlNotificationListener.hpp> +#include <com/sun/star/util/Color.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ +#include <svtools/toolboxcontroller.hxx> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> +#ifndef _VCL_MNEMONIC_HXX_ +#include <vcl/mnemonic.hxx> +#endif +#include <vcl/toolbox.hxx> +#include <vcl/combobox.hxx> +#include <tools/urlobj.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::frame::status; +using namespace ::com::sun::star::util; + +namespace framework +{ + +// ------------------------------------------------------------------ + +// Wrapper class to notify controller about events from combobox. +// Unfortunaltly the events are notifed through virtual methods instead +// of Listeners. + +class ComboBoxControl : public ComboBox +{ + public: + ComboBoxControl( Window* pParent, WinBits nStyle, IComboBoxListener* pComboBoxListener ); + virtual ~ComboBoxControl(); + + virtual void Select(); + virtual void DoubleClick(); + virtual void Modify(); + virtual void KeyInput( const ::KeyEvent& rKEvt ); + virtual void GetFocus(); + virtual void LoseFocus(); + virtual long PreNotify( NotifyEvent& rNEvt ); + + private: + IComboBoxListener* m_pComboBoxListener; +}; + +ComboBoxControl::ComboBoxControl( Window* pParent, WinBits nStyle, IComboBoxListener* pComboBoxListener ) : + ComboBox( pParent, nStyle ) + , m_pComboBoxListener( pComboBoxListener ) +{ +} + +ComboBoxControl::~ComboBoxControl() +{ + m_pComboBoxListener = 0; +} + +void ComboBoxControl::Select() +{ + ComboBox::Select(); + if ( m_pComboBoxListener ) + m_pComboBoxListener->Select(); +} + +void ComboBoxControl::DoubleClick() +{ + ComboBox::DoubleClick(); + if ( m_pComboBoxListener ) + m_pComboBoxListener->DoubleClick(); +} + +void ComboBoxControl::Modify() +{ + ComboBox::Modify(); + if ( m_pComboBoxListener ) + m_pComboBoxListener->Modify(); +} + +void ComboBoxControl::KeyInput( const ::KeyEvent& rKEvt ) +{ + ComboBox::KeyInput( rKEvt ); + if ( m_pComboBoxListener ) + m_pComboBoxListener->KeyInput( rKEvt ); +} + +void ComboBoxControl::GetFocus() +{ + ComboBox::GetFocus(); + if ( m_pComboBoxListener ) + m_pComboBoxListener->GetFocus(); +} + +void ComboBoxControl::LoseFocus() +{ + ComboBox::LoseFocus(); + if ( m_pComboBoxListener ) + m_pComboBoxListener->LoseFocus(); +} + +long ComboBoxControl::PreNotify( NotifyEvent& rNEvt ) +{ + long nRet( 0 ); + if ( m_pComboBoxListener ) + nRet = m_pComboBoxListener->PreNotify( rNEvt ); + if ( nRet == 0 ) + nRet = ComboBox::PreNotify( rNEvt ); + + return nRet; +} + +// ------------------------------------------------------------------ + +ComboboxToolbarController::ComboboxToolbarController( + const Reference< XMultiServiceFactory >& rServiceManager, + const Reference< XFrame >& rFrame, + ToolBox* pToolbar, + USHORT nID, + sal_Int32 nWidth, + const ::rtl::OUString& aCommand ) : + ComplexToolbarController( rServiceManager, rFrame, pToolbar, nID, aCommand ) + , m_pComboBox( 0 ) +{ + m_pComboBox = new ComboBoxControl( m_pToolbar, WB_DROPDOWN, this ); + if ( nWidth == 0 ) + nWidth = 100; + + // default dropdown size + ::Size aLogicalSize( 8, 160 ); + ::Size aPixelSize = m_pComboBox->LogicToPixel( aLogicalSize, MAP_APPFONT ); + + m_pComboBox->SetSizePixel( ::Size( nWidth, aPixelSize.Height() )); + m_pToolbar->SetItemWindow( m_nID, m_pComboBox ); +} + +// ------------------------------------------------------------------ + +ComboboxToolbarController::~ComboboxToolbarController() +{ +} + +// ------------------------------------------------------------------ + +void SAL_CALL ComboboxToolbarController::dispose() +throw ( RuntimeException ) +{ + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + m_pToolbar->SetItemWindow( m_nID, 0 ); + delete m_pComboBox; + + ComplexToolbarController::dispose(); + + m_pComboBox = 0; +} + +// ------------------------------------------------------------------ +Sequence<PropertyValue> ComboboxToolbarController::getExecuteArgs(sal_Int16 KeyModifier) const +{ + Sequence<PropertyValue> aArgs( 2 ); + ::rtl::OUString aSelectedText = m_pComboBox->GetText(); + + // Add key modifier to argument list + aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "KeyModifier" )); + aArgs[0].Value <<= KeyModifier; + aArgs[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" )); + aArgs[1].Value <<= aSelectedText; + return aArgs; +} + +// ------------------------------------------------------------------ + +void ComboboxToolbarController::Select() +{ + if ( m_pComboBox->GetEntryCount() > 0 ) + { + Window::PointerState aState = m_pComboBox->GetPointerState(); + + sal_uInt16 nKeyModifier = sal_uInt16( aState.mnState & KEY_MODTYPE ); + execute( nKeyModifier ); + } +} + +void ComboboxToolbarController::DoubleClick() +{ +} + +void ComboboxToolbarController::Modify() +{ + notifyTextChanged( m_pComboBox->GetText() ); +} + +void ComboboxToolbarController::KeyInput( const ::KeyEvent& ) +{ +} + +void ComboboxToolbarController::GetFocus() +{ + notifyFocusGet(); +} + +void ComboboxToolbarController::LoseFocus() +{ + notifyFocusLost(); +} + +long ComboboxToolbarController::PreNotify( NotifyEvent& rNEvt ) +{ + if( rNEvt.GetType() == EVENT_KEYINPUT ) + { + const ::KeyEvent* pKeyEvent = rNEvt.GetKeyEvent(); + const KeyCode& rKeyCode = pKeyEvent->GetKeyCode(); + if(( rKeyCode.GetModifier() | rKeyCode.GetCode()) == KEY_RETURN ) + { + // Call execute only with non-empty text + if ( m_pComboBox->GetText().Len() > 0 ) + execute( rKeyCode.GetModifier() ); + return 1; + } + } + + return 0; +} + +// -------------------------------------------------------- + +void ComboboxToolbarController::executeControlCommand( const ::com::sun::star::frame::ControlCommand& rControlCommand ) +{ + if ( rControlCommand.Command.equalsAsciiL( "SetText", 7 )) + { + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Text", 4 )) + { + rtl::OUString aText; + rControlCommand.Arguments[i].Value >>= aText; + m_pComboBox->SetText( aText ); + + // send notification + notifyTextChanged( aText ); + break; + } + } + } + else if ( rControlCommand.Command.equalsAsciiL( "SetList", 7 )) + { + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "List", 4 )) + { + Sequence< ::rtl::OUString > aList; + m_pComboBox->Clear(); + + rControlCommand.Arguments[i].Value >>= aList; + for ( sal_Int32 j = 0; j < aList.getLength(); j++ ) + m_pComboBox->InsertEntry( aList[j] ); + + // send notification + uno::Sequence< beans::NamedValue > aInfo( 1 ); + aInfo[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "List" )); + aInfo[0].Value <<= aList; + addNotifyInfo( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ListChanged" )), + getDispatchFromCommand( m_aCommandURL ), + aInfo ); + + break; + } + } + } + else if ( rControlCommand.Command.equalsAsciiL( "AddEntry", 8 )) + { + sal_uInt16 nPos( COMBOBOX_APPEND ); + rtl::OUString aText; + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Text", 4 )) + { + if ( rControlCommand.Arguments[i].Value >>= aText ) + m_pComboBox->InsertEntry( aText, nPos ); + break; + } + } + } + else if ( rControlCommand.Command.equalsAsciiL( "InsertEntry", 11 )) + { + sal_uInt16 nPos( COMBOBOX_APPEND ); + rtl::OUString aText; + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Pos", 3 )) + { + sal_Int32 nTmpPos = 0; + if ( rControlCommand.Arguments[i].Value >>= nTmpPos ) + { + if (( nTmpPos >= 0 ) && + ( nTmpPos < sal_Int32( m_pComboBox->GetEntryCount() ))) + nPos = sal_uInt16( nTmpPos ); + } + } + else if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Text", 4 )) + rControlCommand.Arguments[i].Value >>= aText; + } + + m_pComboBox->InsertEntry( aText, nPos ); + } + else if ( rControlCommand.Command.equalsAsciiL( "RemoveEntryPos", 14 )) + { + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Pos", 3 )) + { + sal_Int32 nPos( -1 ); + if ( rControlCommand.Arguments[i].Value >>= nPos ) + { + if ( nPos < sal_Int32( m_pComboBox->GetEntryCount() )) + m_pComboBox->RemoveEntry( sal_uInt16( nPos )); + } + break; + } + } + } + else if ( rControlCommand.Command.equalsAsciiL( "RemoveEntryText", 15 )) + { + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Text", 4 )) + { + rtl::OUString aText; + if ( rControlCommand.Arguments[i].Value >>= aText ) + m_pComboBox->RemoveEntry( aText ); + break; + } + } + } + else if ( rControlCommand.Command.equalsAsciiL( "SetDropDownLines", 16 )) + { + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Lines", 5 )) + { + sal_Int32 nValue( 5 ); + rControlCommand.Arguments[i].Value >>= nValue; + m_pComboBox->SetDropDownLineCount( sal_uInt16( nValue )); + break; + } + } + } + else if ( rControlCommand.Command.equalsAsciiL( "SetBackgroundColor", 18 )) + { + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Color", 5 )) + { + com::sun::star::util::Color aColor(0); + if ( rControlCommand.Arguments[i].Value >>= aColor ) + { + ::Color aBackColor( static_cast< UINT32 >( aColor )); + m_pComboBox->SetControlBackground( aBackColor ); + } + break; + } + } + } + else if ( rControlCommand.Command.equalsAsciiL( "SetTextColor", 12 )) + { + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Color", 5 )) + { + com::sun::star::util::Color aColor(0); + if ( rControlCommand.Arguments[i].Value >>= aColor ) + { + ::Color aForeColor( static_cast< UINT32 >( aColor )); + m_pComboBox->SetControlForeground( aForeColor ); + } + break; + } + } + } +} + +} // namespace + diff --git a/framework/source/uielement/complextoolbarcontroller.cxx b/framework/source/uielement/complextoolbarcontroller.cxx new file mode 100644 index 000000000000..2e1c88740750 --- /dev/null +++ b/framework/source/uielement/complextoolbarcontroller.cxx @@ -0,0 +1,390 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + +#ifndef __FRAMEWORK_UIELEMENT_COMPLEXTOOLBARCONTROLLER_HXX +#include "uielement/complextoolbarcontroller.hxx" +#endif + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ + +#ifndef __FRAMEWORK_TOOLBAR_HXX_ +#include "uielement/toolbar.hxx" +#endif + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/frame/status/ItemStatus.hpp> +#include <com/sun/star/frame/status/ItemState.hpp> +#include <com/sun/star/frame/status/Visibility.hpp> +#include <com/sun/star/frame/XControlNotificationListener.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ +#include <svtools/toolboxcontroller.hxx> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> +#ifndef _VCL_MNEMONIC_HXX_ +#include <vcl/mnemonic.hxx> +#endif +#include <tools/urlobj.hxx> +#include <dispatch/uieventloghelper.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::frame::status; +using namespace ::com::sun::star::util; + +namespace framework +{ + +// ------------------------------------------------------------------ + +ComplexToolbarController::ComplexToolbarController( + const Reference< XMultiServiceFactory >& rServiceManager, + const Reference< XFrame >& rFrame, + ToolBox* pToolbar, + USHORT nID, + const ::rtl::OUString& aCommand ) : + svt::ToolboxController( rServiceManager, rFrame, aCommand ) + , m_pToolbar( pToolbar ) + , m_nID( nID ) + , m_bMadeInvisible( sal_False ) +{ + m_xURLTransformer.set( m_xServiceManager->createInstance( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.URLTransformer" ))), + UNO_QUERY_THROW ); +} + +// ------------------------------------------------------------------ + +ComplexToolbarController::~ComplexToolbarController() +{ +} + +// ------------------------------------------------------------------ + +void SAL_CALL ComplexToolbarController::dispose() +throw ( RuntimeException ) +{ + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + m_pToolbar->SetItemWindow( m_nID, 0 ); + svt::ToolboxController::dispose(); + + m_xURLTransformer.clear(); + m_pToolbar = 0; + m_nID = 0; +} + +// ------------------------------------------------------------------ +Sequence<PropertyValue> ComplexToolbarController::getExecuteArgs(sal_Int16 KeyModifier) const +{ + Sequence<PropertyValue> aArgs( 1 ); + + // Add key modifier to argument list + aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "KeyModifier" )); + aArgs[0].Value <<= KeyModifier; + return aArgs; +} +// ----------------------------------------------------------------------------- +void SAL_CALL ComplexToolbarController::execute( sal_Int16 KeyModifier ) +throw ( RuntimeException ) +{ + Reference< XDispatch > xDispatch; + Reference< XURLTransformer > xURLTransformer; + ::rtl::OUString aCommandURL; + ::com::sun::star::util::URL aTargetURL; + Sequence<PropertyValue> aArgs; + + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + if ( m_bDisposed ) + throw DisposedException(); + + if ( m_bInitialized && + m_xFrame.is() && + m_xServiceManager.is() && + m_aCommandURL.getLength() ) + { + xURLTransformer = m_xURLTransformer; + xDispatch = getDispatchFromCommand( m_aCommandURL ); + aCommandURL = m_aCommandURL; + aTargetURL = getInitializedURL(); + aArgs = getExecuteArgs(KeyModifier); + } + } + + if ( xDispatch.is() && aTargetURL.Complete.getLength() > 0 ) + { + // Execute dispatch asynchronously + ExecuteInfo* pExecuteInfo = new ExecuteInfo; + pExecuteInfo->xDispatch = xDispatch; + pExecuteInfo->aTargetURL = aTargetURL; + pExecuteInfo->aArgs = aArgs; + if(::comphelper::UiEventsLogger::isEnabled()) //#i88653# + UiEventLogHelper(::rtl::OUString::createFromAscii("ComplexToolbarController")).log( + m_xServiceManager, + m_xFrame, + aTargetURL, + aArgs); + Application::PostUserEvent( STATIC_LINK(0, ComplexToolbarController , ExecuteHdl_Impl), pExecuteInfo ); + } +} + +// ------------------------------------------------------------------ + +void ComplexToolbarController::statusChanged( const FeatureStateEvent& Event ) +throw ( RuntimeException ) +{ + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + if ( m_bDisposed ) + return; + + if ( m_pToolbar ) + { + m_pToolbar->EnableItem( m_nID, Event.IsEnabled ); + + USHORT nItemBits = m_pToolbar->GetItemBits( m_nID ); + nItemBits &= ~TIB_CHECKABLE; + TriState eTri = STATE_NOCHECK; + + sal_Bool bValue = sal_Bool(); + rtl::OUString aStrValue; + ItemStatus aItemState; + Visibility aItemVisibility; + ControlCommand aControlCommand; + + if ( Event.State >>= bValue ) + { + // Boolean, treat it as checked/unchecked + if ( m_bMadeInvisible ) + m_pToolbar->ShowItem( m_nID, TRUE ); + m_pToolbar->CheckItem( m_nID, bValue ); + if ( bValue ) + eTri = STATE_CHECK; + nItemBits |= TIB_CHECKABLE; + } + else if ( Event.State >>= aStrValue ) + { + ::rtl::OUString aText( MnemonicGenerator::EraseAllMnemonicChars( aStrValue ) ); + m_pToolbar->SetItemText( m_nID, aText ); + m_pToolbar->SetQuickHelpText( m_nID, aText ); + + if ( m_bMadeInvisible ) + m_pToolbar->ShowItem( m_nID, TRUE ); + } + else if ( Event.State >>= aItemState ) + { + eTri = STATE_DONTKNOW; + nItemBits |= TIB_CHECKABLE; + if ( m_bMadeInvisible ) + m_pToolbar->ShowItem( m_nID, TRUE ); + } + else if ( Event.State >>= aItemVisibility ) + { + m_pToolbar->ShowItem( m_nID, aItemVisibility.bVisible ); + m_bMadeInvisible = !aItemVisibility.bVisible; + } + else if ( Event.State >>= aControlCommand ) + { + executeControlCommand( aControlCommand ); + if ( m_bMadeInvisible ) + m_pToolbar->ShowItem( m_nID, TRUE ); + } + + else if ( m_bMadeInvisible ) + m_pToolbar->ShowItem( m_nID, TRUE ); + + m_pToolbar->SetItemState( m_nID, eTri ); + m_pToolbar->SetItemBits( m_nID, nItemBits ); + } +} + +// ------------------------------------------------------------------ + +IMPL_STATIC_LINK_NOINSTANCE( ComplexToolbarController, ExecuteHdl_Impl, ExecuteInfo*, pExecuteInfo ) +{ + const sal_uInt32 nRef = Application::ReleaseSolarMutex(); + 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! + pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs ); + } + catch ( Exception& ) + { + } + + Application::AcquireSolarMutex( nRef ); + delete pExecuteInfo; + return 0; +} + +// ------------------------------------------------------------------ + +IMPL_STATIC_LINK_NOINSTANCE( ComplexToolbarController, Notify_Impl, NotifyInfo*, pNotifyInfo ) +{ + const sal_uInt32 nRef = Application::ReleaseSolarMutex(); + 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! + frame::ControlEvent aEvent; + aEvent.aURL = pNotifyInfo->aSourceURL; + aEvent.Event = pNotifyInfo->aEventName; + aEvent.aInformation = pNotifyInfo->aInfoSeq; + pNotifyInfo->xNotifyListener->controlEvent( aEvent ); + } + catch ( Exception& ) + { + } + + Application::AcquireSolarMutex( nRef ); + delete pNotifyInfo; + return 0; +} + +// ------------------------------------------------------------------ + +void ComplexToolbarController::addNotifyInfo( + const rtl::OUString& aEventName, + const uno::Reference< frame::XDispatch >& xDispatch, + const uno::Sequence< beans::NamedValue >& rInfo ) +{ + uno::Reference< frame::XControlNotificationListener > xControlNotify( xDispatch, uno::UNO_QUERY ); + + if ( xControlNotify.is() ) + { + // Execute notification asynchronously + NotifyInfo* pNotifyInfo = new NotifyInfo; + + pNotifyInfo->aEventName = aEventName; + pNotifyInfo->xNotifyListener = xControlNotify; + pNotifyInfo->aSourceURL = getInitializedURL(); + + // Add frame as source to the information sequence + sal_Int32 nCount = rInfo.getLength(); + uno::Sequence< beans::NamedValue > aInfoSeq( rInfo ); + aInfoSeq.realloc( nCount+1 ); + aInfoSeq[nCount].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Source" )); + aInfoSeq[nCount].Value = uno::makeAny( getFrameInterface() ); + pNotifyInfo->aInfoSeq = aInfoSeq; + + Application::PostUserEvent( STATIC_LINK(0, ComplexToolbarController, Notify_Impl), pNotifyInfo ); + } +} + +// -------------------------------------------------------- +sal_Int32 ComplexToolbarController::getFontSizePixel( const Window* pWindow ) +{ + const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); + const Font& rFont = rSettings.GetAppFont(); + + // Calculate height of the application font used by window + sal_Int32 nHeight = sal_Int32( rFont.GetHeight() ); + ::Size aPixelSize = pWindow->LogicToPixel( ::Size( 0, nHeight ), MAP_APPFONT ); + return aPixelSize.Height(); +} + +// -------------------------------------------------------- + +uno::Reference< frame::XDispatch > ComplexToolbarController::getDispatchFromCommand( const rtl::OUString& aCommand ) const +{ + uno::Reference< frame::XDispatch > xDispatch; + + if ( m_bInitialized && m_xFrame.is() && m_xServiceManager.is() && aCommand.getLength() ) + { + URLToDispatchMap::const_iterator pIter = m_aListenerMap.find( aCommand ); + if ( pIter != m_aListenerMap.end() ) + xDispatch = pIter->second; + } + + return xDispatch; +} + +// -------------------------------------------------------- + +const ::com::sun::star::util::URL& ComplexToolbarController::getInitializedURL() +{ + if ( m_aURL.Complete.getLength() == 0 ) + { + m_aURL.Complete = m_aCommandURL; + m_xURLTransformer->parseStrict( m_aURL ); + } + return m_aURL; +} + +void ComplexToolbarController::notifyFocusGet() +{ + // send focus get notification + uno::Sequence< beans::NamedValue > aInfo; + addNotifyInfo( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FocusSet" )), + getDispatchFromCommand( m_aCommandURL ), + aInfo ); +} + +void ComplexToolbarController::notifyFocusLost() +{ + // send focus lost notification + uno::Sequence< beans::NamedValue > aInfo; + addNotifyInfo( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FocusLost" )), + getDispatchFromCommand( m_aCommandURL ), + aInfo ); +} + +void ComplexToolbarController::notifyTextChanged( const ::rtl::OUString& aText ) +{ + // send text changed notification + uno::Sequence< beans::NamedValue > aInfo( 1 ); + aInfo[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" )); + aInfo[0].Value <<= aText; + addNotifyInfo( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TextChanged" )), + getDispatchFromCommand( m_aCommandURL ), + aInfo ); +} + +} // namespace + diff --git a/framework/source/uielement/constitemcontainer.cxx b/framework/source/uielement/constitemcontainer.cxx new file mode 100644 index 000000000000..9ef9a72e5093 --- /dev/null +++ b/framework/source/uielement/constitemcontainer.cxx @@ -0,0 +1,479 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <uielement/constitemcontainer.hxx> +#include <uielement/rootitemcontainer.hxx> +#include <uielement/itemcontainer.hxx> +#include <threadhelp/resetableguard.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/beans/PropertyAttribute.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ +#include <cppuhelper/implbase1.hxx> + +using namespace cppu; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::container; + +const char WRONG_TYPE_EXCEPTION[] = "Type must be com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >"; + +const int PROPHANDLE_UINAME = 1; +const int PROPCOUNT = 1; +const rtl::OUString PROPNAME_UINAME( RTL_CONSTASCII_USTRINGPARAM( "UIName" )); + +namespace framework +{ + +/** + * The class which implements the PropertySetInfo interface. + */ +extern "C" +{ +static int SAL_CALL compare_OUString_Property_Impl( const void *arg1, const void *arg2 ) SAL_THROW( () ) +{ + return ((::rtl::OUString *)arg1)->compareTo( ((Property *)arg2)->Name ); +} +} + +class OPropertySetHelperInfo_Impl + : public WeakImplHelper1< ::com::sun::star::beans::XPropertySetInfo > +{ + Sequence < Property > aInfos; + +public: + OPropertySetHelperInfo_Impl( IPropertyArrayHelper & rHelper_ ) SAL_THROW( () ); + + // XPropertySetInfo-Methoden + virtual Sequence< Property > SAL_CALL getProperties(void) throw(::com::sun::star::uno::RuntimeException); + virtual Property SAL_CALL getPropertyByName(const ::rtl::OUString& PropertyName) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasPropertyByName(const ::rtl::OUString& PropertyName) throw(::com::sun::star::uno::RuntimeException); +}; + + +/** + * Create an object that implements XPropertySetInfo IPropertyArrayHelper. + */ +OPropertySetHelperInfo_Impl::OPropertySetHelperInfo_Impl( + IPropertyArrayHelper & rHelper_ ) + SAL_THROW( () ) + :aInfos( rHelper_.getProperties() ) +{ +} + +/** + * Return the sequence of properties, which are provided throug the constructor. + */ +Sequence< Property > OPropertySetHelperInfo_Impl::getProperties(void) throw(::com::sun::star::uno::RuntimeException) +{ + return aInfos; +} + +/** + * Return the sequence of properties, which are provided throug the constructor. + */ +Property OPropertySetHelperInfo_Impl::getPropertyByName( const ::rtl::OUString & PropertyName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException) +{ + Property * pR; + pR = (Property *)bsearch( &PropertyName, aInfos.getConstArray(), aInfos.getLength(), + sizeof( Property ), + compare_OUString_Property_Impl ); + if( !pR ) { + throw UnknownPropertyException(); + } + + return *pR; +} + +/** + * Return the sequence of properties, which are provided throug the constructor. + */ +sal_Bool OPropertySetHelperInfo_Impl::hasPropertyByName( const ::rtl::OUString & PropertyName ) throw(::com::sun::star::uno::RuntimeException) +{ + Property * pR; + pR = (Property *)bsearch( &PropertyName, aInfos.getConstArray(), aInfos.getLength(), + sizeof( Property ), + compare_OUString_Property_Impl ); + return pR != NULL; +} + +//***************************************************************************************************************** +// XInterface, XTypeProvider +//***************************************************************************************************************** +DEFINE_XINTERFACE_6 ( ConstItemContainer , + OWeakObject , + DIRECT_INTERFACE( ::com::sun::star::lang::XTypeProvider ), + DIRECT_INTERFACE( ::com::sun::star::container::XElementAccess ), + DIRECT_INTERFACE( ::com::sun::star::container::XIndexAccess ), + DIRECT_INTERFACE( ::com::sun::star::beans::XFastPropertySet ), + DIRECT_INTERFACE( ::com::sun::star::beans::XPropertySet ), + DIRECT_INTERFACE( ::com::sun::star::lang::XUnoTunnel ) + ) + +DEFINE_XTYPEPROVIDER_6 ( ConstItemContainer , + ::com::sun::star::lang::XTypeProvider , + ::com::sun::star::container::XIndexAccess , + ::com::sun::star::container::XElementAccess , + ::com::sun::star::beans::XFastPropertySet , + ::com::sun::star::beans::XPropertySet , + ::com::sun::star::lang::XUnoTunnel + ) + +ConstItemContainer::ConstItemContainer() : ::cppu::OWeakObject() +{ +} + +ConstItemContainer::ConstItemContainer( const RootItemContainer& rRootItemContainer, sal_Bool bFastCopy ) +{ + ShareGuard( rRootItemContainer.m_aShareMutex ); + + // If bFastCopy is set the onwer of the root item container will transfer ownership to us. So + // it is possible to copy only the root part. + m_aUIName = rRootItemContainer.m_aUIName; + if ( bFastCopy ) + m_aItemVector = rRootItemContainer.m_aItemVector; + else + copyItemContainer( rRootItemContainer.m_aItemVector ); +} + +ConstItemContainer::ConstItemContainer( const ItemContainer& rItemContainer ) +{ + ShareGuard( rItemContainer.m_aShareMutex ); + copyItemContainer( rItemContainer.m_aItemVector ); +} + +ConstItemContainer::ConstItemContainer( const Reference< XIndexAccess >& rSourceContainer, sal_Bool bFastCopy ) +{ + // We also have to copy the UIName property + try + { + Reference< XPropertySet > xPropSet( rSourceContainer, UNO_QUERY ); + if ( xPropSet.is() ) + { + rtl::OUString aUIName; + xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UIName" ))) >>= m_aUIName; + } + } + catch ( Exception& ) + { + } + + if ( rSourceContainer.is() ) + { + try + { + sal_Int32 nCount = rSourceContainer->getCount(); + m_aItemVector.reserve(nCount); + if ( bFastCopy ) + { + for ( sal_Int32 i = 0; i < nCount; i++ ) + { + Sequence< PropertyValue > aPropSeq; + if ( rSourceContainer->getByIndex( i ) >>= aPropSeq ) + m_aItemVector.push_back( aPropSeq ); + } + } + else + { + for ( sal_Int32 i = 0; i < nCount; i++ ) + { + Sequence< PropertyValue > aPropSeq; + if ( rSourceContainer->getByIndex( i ) >>= aPropSeq ) + { + sal_Int32 nContainerIndex = -1; + Reference< XIndexAccess > xIndexAccess; + for ( sal_Int32 j = 0; j < aPropSeq.getLength(); j++ ) + { + if ( aPropSeq[j].Name.equalsAscii( "ItemDescriptorContainer" )) + { + aPropSeq[j].Value >>= xIndexAccess; + nContainerIndex = j; + break; + } + } + + if ( xIndexAccess.is() && nContainerIndex >= 0 ) + aPropSeq[nContainerIndex].Value <<= deepCopyContainer( xIndexAccess ); + + m_aItemVector.push_back( aPropSeq ); + } + } + } + } + catch ( IndexOutOfBoundsException& ) + { + } + } +} + +ConstItemContainer::~ConstItemContainer() +{ +} + +// private +void ConstItemContainer::copyItemContainer( const std::vector< Sequence< PropertyValue > >& rSourceVector ) +{ + const sal_uInt32 nCount = rSourceVector.size(); + for ( sal_uInt32 i = 0; i < nCount; i++ ) + { + sal_Int32 nContainerIndex = -1; + Sequence< PropertyValue > aPropSeq( rSourceVector[i] ); + Reference< XIndexAccess > xIndexAccess; + for ( sal_Int32 j = 0; j < aPropSeq.getLength(); j++ ) + { + if ( aPropSeq[j].Name.equalsAscii( "ItemDescriptorContainer" )) + { + aPropSeq[j].Value >>= xIndexAccess; + nContainerIndex = j; + break; + } + } + + if ( xIndexAccess.is() && nContainerIndex >= 0 ) + aPropSeq[nContainerIndex].Value <<= deepCopyContainer( xIndexAccess ); + + m_aItemVector.push_back( aPropSeq ); + } +} + +Reference< XIndexAccess > ConstItemContainer::deepCopyContainer( const Reference< XIndexAccess >& rSubContainer ) +{ + Reference< XIndexAccess > xReturn; + if ( rSubContainer.is() ) + { + ItemContainer* pSource = ItemContainer::GetImplementation( rSubContainer ); + ConstItemContainer* pSubContainer( 0 ); + if ( pSource ) + pSubContainer = new ConstItemContainer( *pSource ); + else + pSubContainer = new ConstItemContainer( rSubContainer ); + xReturn = Reference< XIndexAccess >( static_cast< OWeakObject* >( pSubContainer ), UNO_QUERY ); + } + + return xReturn; +} + +// XUnoTunnel +sal_Int64 ConstItemContainer::getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& rIdentifier ) throw(::com::sun::star::uno::RuntimeException) +{ + if( ( rIdentifier.getLength() == 16 ) && ( 0 == rtl_compareMemory( ConstItemContainer::GetUnoTunnelId().getConstArray(), rIdentifier.getConstArray(), 16 ) ) ) + { + return reinterpret_cast< sal_Int64 >( this ); + } + return 0; +} + +const Sequence< sal_Int8 >& ConstItemContainer::GetUnoTunnelId() throw() +{ + static ::com::sun::star::uno::Sequence< sal_Int8 > * pSeq = NULL; + if( !pSeq ) + { + ::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static ::com::sun::star::uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +ConstItemContainer* ConstItemContainer::GetImplementation( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rxIFace ) throw() +{ + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XUnoTunnel > xUT( rxIFace, ::com::sun::star::uno::UNO_QUERY ); + return xUT.is() ? reinterpret_cast< ConstItemContainer* >(sal::static_int_cast< sal_IntPtr >( + xUT->getSomething( ConstItemContainer::GetUnoTunnelId() ))) : NULL; +} + +// XElementAccess +sal_Bool SAL_CALL ConstItemContainer::hasElements() +throw ( RuntimeException ) +{ + return ( !m_aItemVector.empty() ); +} + +// XIndexAccess +sal_Int32 SAL_CALL ConstItemContainer::getCount() +throw ( RuntimeException ) +{ + return m_aItemVector.size(); +} + +Any SAL_CALL ConstItemContainer::getByIndex( sal_Int32 Index ) +throw ( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) +{ + if ( sal_Int32( m_aItemVector.size()) > Index ) + return makeAny( m_aItemVector[Index] ); + else + throw IndexOutOfBoundsException( ::rtl::OUString(), (OWeakObject *)this ); +} + +// XPropertySet +Reference< XPropertySetInfo > SAL_CALL ConstItemContainer::getPropertySetInfo() +throw (::com::sun::star::uno::RuntimeException) +{ + // Optimize this method ! + // We initialize a static variable only one time. And we don't must use a mutex at every call! + // For the first call; pInfo is NULL - for the second call pInfo is different from NULL! + static Reference< XPropertySetInfo >* pInfo = NULL; + + if( pInfo == NULL ) + { + // Ready for multithreading + osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ; + // Control this pointer again, another instance can be faster then these! + if( pInfo == NULL ) + { + // Create structure of propertysetinfo for baseclass "OPropertySetHelper". + // (Use method "getInfoHelper()".) + static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) ); + pInfo = &xInfo; + } + } + + return (*pInfo); +} + +void SAL_CALL ConstItemContainer::setPropertyValue( const ::rtl::OUString&, const Any& ) +throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) +{ +} + +Any SAL_CALL ConstItemContainer::getPropertyValue( const ::rtl::OUString& PropertyName ) +throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) +{ + if ( PropertyName.equals( PROPNAME_UINAME )) + return makeAny( m_aUIName ); + + throw UnknownPropertyException(); +} + +void SAL_CALL ConstItemContainer::addPropertyChangeListener( const ::rtl::OUString&, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& ) +throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) +{ +} + +void SAL_CALL ConstItemContainer::removePropertyChangeListener( const ::rtl::OUString&, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& ) +throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) +{ + // Only read-only properties - do nothing +} + +void SAL_CALL ConstItemContainer::addVetoableChangeListener( const ::rtl::OUString&, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& ) +throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) +{ + // Only read-only properties - do nothing +} + +void SAL_CALL ConstItemContainer::removeVetoableChangeListener( const ::rtl::OUString&, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& ) +throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) +{ + // Only read-only properties - do nothing +} + +// XFastPropertySet +void SAL_CALL ConstItemContainer::setFastPropertyValue( sal_Int32, const ::com::sun::star::uno::Any& ) +throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) +{ +} + +Any SAL_CALL ConstItemContainer::getFastPropertyValue( sal_Int32 nHandle ) +throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) +{ + if ( nHandle == PROPHANDLE_UINAME ) + return makeAny( m_aUIName ); + + throw UnknownPropertyException(); +} + +::cppu::IPropertyArrayHelper& SAL_CALL ConstItemContainer::getInfoHelper() +{ + // Optimize this method ! + // We initialize a static variable only one time. And we don't must use a mutex at every call! + // For the first call; pInfoHelper is NULL - for the second call pInfoHelper is different from NULL! + static ::cppu::OPropertyArrayHelper* pInfoHelper = NULL; + + if( pInfoHelper == NULL ) + { + // Ready for multithreading + osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ; + + // Control this pointer again, another instance can be faster then these! + if( pInfoHelper == NULL ) + { + // Define static member to give structure of properties to baseclass "OPropertySetHelper". + // "impl_getStaticPropertyDescriptor" is a non exported and static funtion, who will define a static propertytable. + // "sal_True" say: Table is sorted by name. + static ::cppu::OPropertyArrayHelper aInfoHelper( impl_getStaticPropertyDescriptor(), sal_True ); + pInfoHelper = &aInfoHelper; + } + } + + return(*pInfoHelper); +} + +const com::sun::star::uno::Sequence< com::sun::star::beans::Property > ConstItemContainer::impl_getStaticPropertyDescriptor() +{ + // Create a new static property array to initialize sequence! + // Table of all predefined properties of this class. Its used from OPropertySetHelper-class! + // Don't forget to change the defines (see begin of this file), if you add, change or delete a property in this list!!! + // It's necessary for methods of OPropertySetHelper. + // ATTENTION: + // YOU MUST SORT FOLLOW TABLE BY NAME ALPHABETICAL !!! + + static const com::sun::star::beans::Property pProperties[] = + { + com::sun::star::beans::Property( PROPNAME_UINAME, PROPHANDLE_UINAME , + ::getCppuType((const rtl::OUString*)NULL), + com::sun::star::beans::PropertyAttribute::TRANSIENT | com::sun::star::beans::PropertyAttribute::READONLY ) + }; + // Use it to initialize sequence! + static const com::sun::star::uno::Sequence< com::sun::star::beans::Property > lPropertyDescriptor( pProperties, PROPCOUNT ); + // Return static "PropertyDescriptor" + return lPropertyDescriptor; +} + +Reference < XPropertySetInfo > ConstItemContainer::createPropertySetInfo( + IPropertyArrayHelper & rProperties ) SAL_THROW( () ) +{ + return static_cast< XPropertySetInfo * >( new OPropertySetHelperInfo_Impl( rProperties ) ); +} + +} // namespace framework + diff --git a/framework/source/uielement/controlmenucontroller.cxx b/framework/source/uielement/controlmenucontroller.cxx new file mode 100644 index 000000000000..0672ac69d351 --- /dev/null +++ b/framework/source/uielement/controlmenucontroller.cxx @@ -0,0 +1,443 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include <uielement/controlmenucontroller.hxx> + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <threadhelp/resetableguard.hxx> +#include "services.h" + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/awt/XDevice.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/awt/MenuItemStyle.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/style/XStyleFamiliesSupplier.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> + +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ + +#include <vcl/menu.hxx> +#include <vcl/svapp.hxx> +#include <vcl/i18nhelp.hxx> +#include <tools/urlobj.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/strbuf.hxx> +#include <svl/solar.hrc> +#include <tools/rcid.h> +#include <vcl/image.hxx> +#include <svtools/menuoptions.hxx> +#include <dispatch/uieventloghelper.hxx> + +// Copied from svx +// Function-Id's +#define RID_FMSHELL_CONVERSIONMENU (RID_FORMS_START + 4) +#define RID_SVXIMGLIST_FMEXPL (RID_FORMS_START + 0) +#define RID_SVXIMGLIST_FMEXPL_HC (RID_FORMS_START + 2) + +// Forms - Ids, used to address images from image list +#define SID_FMSLOTS_START (SID_SVX_START + 592) +#define SID_MORE_FMSLOTS_START (SID_SVX_START + 702) + +#define SID_FM_CONVERTTO_EDIT (SID_MORE_FMSLOTS_START + 32) +#define SID_FM_CONVERTTO_BUTTON (SID_MORE_FMSLOTS_START + 33) +#define SID_FM_CONVERTTO_FIXEDTEXT (SID_MORE_FMSLOTS_START + 34) +#define SID_FM_CONVERTTO_LISTBOX (SID_MORE_FMSLOTS_START + 35) +#define SID_FM_CONVERTTO_CHECKBOX (SID_MORE_FMSLOTS_START + 36) +#define SID_FM_CONVERTTO_RADIOBUTTON (SID_MORE_FMSLOTS_START + 37) +#define SID_FM_CONVERTTO_GROUPBOX (SID_MORE_FMSLOTS_START + 38) +#define SID_FM_CONVERTTO_COMBOBOX (SID_MORE_FMSLOTS_START + 39) +#define SID_FM_CONVERTTO_GRID (SID_MORE_FMSLOTS_START + 40) +#define SID_FM_CONVERTTO_IMAGEBUTTON (SID_MORE_FMSLOTS_START + 41) +#define SID_FM_CONVERTTO_FILECONTROL (SID_MORE_FMSLOTS_START + 42) +#define SID_FM_CONVERTTO_DATE (SID_MORE_FMSLOTS_START + 43) +#define SID_FM_CONVERTTO_TIME (SID_MORE_FMSLOTS_START + 44) +#define SID_FM_CONVERTTO_NUMERIC (SID_MORE_FMSLOTS_START + 45) +#define SID_FM_CONVERTTO_CURRENCY (SID_MORE_FMSLOTS_START + 46) +#define SID_FM_CONVERTTO_PATTERN (SID_MORE_FMSLOTS_START + 47) +#define SID_FM_CONVERTTO_IMAGECONTROL (SID_MORE_FMSLOTS_START + 48) +#define SID_FM_CONVERTTO_FORMATTED (SID_MORE_FMSLOTS_START + 49) +#define SID_FM_CONVERTTO_SCROLLBAR (SID_MORE_FMSLOTS_START + 68) +#define SID_FM_CONVERTTO_SPINBUTTON (SID_MORE_FMSLOTS_START + 69) + +#define SID_FM_DATEFIELD (SID_MORE_FMSLOTS_START + 2) +#define SID_FM_TIMEFIELD (SID_MORE_FMSLOTS_START + 3) +#define SID_FM_NUMERICFIELD (SID_MORE_FMSLOTS_START + 4) +#define SID_FM_CURRENCYFIELD (SID_MORE_FMSLOTS_START + 5) +#define SID_FM_PATTERNFIELD (SID_MORE_FMSLOTS_START + 6) +#define SID_FM_IMAGECONTROL (SID_MORE_FMSLOTS_START + 8) +#define SID_FM_FORMATTEDFIELD (SID_MORE_FMSLOTS_START + 26) +#define SID_FM_SCROLLBAR (SID_MORE_FMSLOTS_START + 66) +#define SID_FM_SPINBUTTON (SID_MORE_FMSLOTS_START + 67) +#define SID_FM_CONFIG (SID_FMSLOTS_START + 1) +#define SID_FM_PUSHBUTTON (SID_FMSLOTS_START + 2) +#define SID_FM_RADIOBUTTON (SID_FMSLOTS_START + 3) +#define SID_FM_CHECKBOX (SID_FMSLOTS_START + 4) +#define SID_FM_FIXEDTEXT (SID_FMSLOTS_START + 5) +#define SID_FM_GROUPBOX (SID_FMSLOTS_START + 6) +#define SID_FM_EDIT (SID_FMSLOTS_START + 7) +#define SID_FM_LISTBOX (SID_FMSLOTS_START + 8) +#define SID_FM_COMBOBOX (SID_FMSLOTS_START + 9) +#define SID_FM_URLBUTTON (SID_FMSLOTS_START + 10) +#define SID_FM_DBGRID (SID_FMSLOTS_START + 11) +#define SID_FM_IMAGEBUTTON (SID_FMSLOTS_START + 12) +#define SID_FM_FILECONTROL (SID_FMSLOTS_START + 13) + +sal_Int16 nConvertSlots[] = +{ + SID_FM_CONVERTTO_EDIT, + SID_FM_CONVERTTO_BUTTON, + SID_FM_CONVERTTO_FIXEDTEXT, + SID_FM_CONVERTTO_LISTBOX, + SID_FM_CONVERTTO_CHECKBOX, + SID_FM_CONVERTTO_RADIOBUTTON, + SID_FM_CONVERTTO_GROUPBOX, + SID_FM_CONVERTTO_COMBOBOX, +// SID_FM_CONVERTTO_GRID, + SID_FM_CONVERTTO_IMAGEBUTTON, + SID_FM_CONVERTTO_FILECONTROL, + SID_FM_CONVERTTO_DATE, + SID_FM_CONVERTTO_TIME, + SID_FM_CONVERTTO_NUMERIC, + SID_FM_CONVERTTO_CURRENCY, + SID_FM_CONVERTTO_PATTERN, + SID_FM_CONVERTTO_IMAGECONTROL, + SID_FM_CONVERTTO_FORMATTED, + SID_FM_CONVERTTO_SCROLLBAR, + SID_FM_CONVERTTO_SPINBUTTON +}; + +sal_Int16 nCreateSlots[] = +{ + SID_FM_EDIT, + SID_FM_PUSHBUTTON, + SID_FM_FIXEDTEXT, + SID_FM_LISTBOX, + SID_FM_CHECKBOX, + SID_FM_RADIOBUTTON, + SID_FM_GROUPBOX, + SID_FM_COMBOBOX, +// SID_FM_DBGRID, + SID_FM_IMAGEBUTTON, + SID_FM_FILECONTROL, + SID_FM_DATEFIELD, + SID_FM_TIMEFIELD, + SID_FM_NUMERICFIELD, + SID_FM_CURRENCYFIELD, + SID_FM_PATTERNFIELD, + SID_FM_IMAGECONTROL, + SID_FM_FORMATTEDFIELD, + SID_FM_SCROLLBAR, + SID_FM_SPINBUTTON +}; + +const char* aCommands[] = +{ + ".uno:ConvertToEdit", + ".uno:ConvertToButton", + ".uno:ConvertToFixed", + ".uno:ConvertToList", + ".uno:ConvertToCheckBox", + ".uno:ConvertToRadio", + ".uno:ConvertToGroup", + ".uno:ConvertToCombo", +// ".uno:ConvertToGrid", + ".uno:ConvertToImageBtn", + ".uno:ConvertToFileControl", + ".uno:ConvertToDate", + ".uno:ConvertToTime", + ".uno:ConvertToNumeric", + ".uno:ConvertToCurrency", + ".uno:ConvertToPattern", + ".uno:ConvertToImageControl", + ".uno:ConvertToFormatted", + ".uno:ConvertToScrollBar", + ".uno:ConvertToSpinButton" +}; + +//_________________________________________________________________________________________________________________ +// Defines +//_________________________________________________________________________________________________________________ +// + +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::style; +using namespace com::sun::star::container; + +namespace framework +{ + +DEFINE_XSERVICEINFO_MULTISERVICE ( ControlMenuController , + OWeakObject , + SERVICENAME_POPUPMENUCONTROLLER , + IMPLEMENTATIONNAME_CONTROLMENUCONTROLLER + ) + +DEFINE_INIT_SERVICE ( ControlMenuController, {} ) + +ControlMenuController::ControlMenuController( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ) : + PopupMenuControllerBase( xServiceManager ), + m_pResPopupMenu( 0 ) +{ + const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); + m_bWasHiContrast = rSettings.GetHighContrastMode(); + m_bShowMenuImages = rSettings.GetUseImagesInMenus(); + +} + +ControlMenuController::~ControlMenuController() +{ +} + +// private function +void ControlMenuController::updateImagesPopupMenu( PopupMenu* pPopupMenu ) +{ + rtl::OUString aResName( RTL_CONSTASCII_USTRINGPARAM( "svx" )); + + ResMgr* pResMgr = ResMgr::CreateResMgr( rtl::OUStringToOString( aResName, RTL_TEXTENCODING_ASCII_US )); + ResId aResId( m_bWasHiContrast ? RID_SVXIMGLIST_FMEXPL_HC : RID_SVXIMGLIST_FMEXPL, *pResMgr ); + aResId.SetRT( RSC_IMAGELIST ); + + if ( pResMgr->IsAvailable( aResId )) + { + ImageList aImageList( aResId ); + for ( sal_uInt32 i=0; i < sizeof(nConvertSlots)/sizeof(nConvertSlots[0]); ++i ) + { + // das entsprechende Image dran + if ( m_bShowMenuImages ) + pPopupMenu->SetItemImage( nConvertSlots[i], aImageList.GetImage(nCreateSlots[i])); + else + pPopupMenu->SetItemImage( nConvertSlots[i], Image() ); + } + } + + delete pResMgr; +} + +// private function +void ControlMenuController::fillPopupMenu( Reference< css::awt::XPopupMenu >& rPopupMenu ) +{ + VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( rPopupMenu ); + PopupMenu* pVCLPopupMenu = 0; + + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + resetPopupMenu( rPopupMenu ); + if ( pPopupMenu ) + pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu(); + + if ( pVCLPopupMenu && m_pResPopupMenu ) + *pVCLPopupMenu = *m_pResPopupMenu; +} + +// XEventListener +void SAL_CALL ControlMenuController::disposing( const EventObject& ) throw ( RuntimeException ) +{ + Reference< css::awt::XMenuListener > xHolder(( OWeakObject *)this, UNO_QUERY ); + + ResetableGuard aLock( m_aLock ); + m_xFrame.clear(); + m_xDispatch.clear(); + m_xServiceManager.clear(); + + if ( m_xPopupMenu.is() ) + m_xPopupMenu->removeMenuListener( Reference< css::awt::XMenuListener >(( OWeakObject *)this, UNO_QUERY )); + m_xPopupMenu.clear(); + delete m_pResPopupMenu; +} + +// XStatusListener +void SAL_CALL ControlMenuController::statusChanged( const FeatureStateEvent& Event ) throw ( RuntimeException ) +{ + ResetableGuard aLock( m_aLock ); + + USHORT nMenuId = 0; + for (sal_uInt32 i=0; i < sizeof(aCommands)/sizeof(aCommands[0]); ++i) + { + if ( Event.FeatureURL.Complete.equalsAscii( aCommands[i] )) + { + nMenuId = nConvertSlots[i]; + break; + } + } + + if ( nMenuId ) + { + VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( m_xPopupMenu ); + + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + PopupMenu* pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu(); + + if ( !Event.IsEnabled && pVCLPopupMenu->GetItemPos( nMenuId ) != MENU_ITEM_NOTFOUND ) + pVCLPopupMenu->RemoveItem( pVCLPopupMenu->GetItemPos( nMenuId )); + else if ( Event.IsEnabled && pVCLPopupMenu->GetItemPos( nMenuId ) == MENU_ITEM_NOTFOUND ) + { + sal_Int16 nSourcePos = m_pResPopupMenu->GetItemPos(nMenuId); + sal_Int16 nPrevInSource = nSourcePos; + sal_uInt16 nPrevInConversion = MENU_ITEM_NOTFOUND; + while (nPrevInSource>0) + { + sal_Int16 nPrevId = m_pResPopupMenu->GetItemId(--nPrevInSource); + + // do we have the source's predecessor in our conversion menu, too ? + nPrevInConversion = pVCLPopupMenu->GetItemPos( nPrevId ); + if ( nPrevInConversion != MENU_ITEM_NOTFOUND ) + break; + } + + if ( MENU_ITEM_NOTFOUND == nPrevInConversion ) + // none of the items which precede the nSID-slot in the source menu are present in our conversion menu + nPrevInConversion = sal::static_int_cast< sal_uInt16 >(-1); // put the item at the first position + + pVCLPopupMenu->InsertItem( nMenuId, m_pResPopupMenu->GetItemText( nMenuId ), m_pResPopupMenu->GetItemBits( nMenuId ), ++nPrevInConversion ); + pVCLPopupMenu->SetItemImage( nMenuId, m_pResPopupMenu->GetItemImage( nMenuId )); + pVCLPopupMenu->SetHelpId( nMenuId, m_pResPopupMenu->GetHelpId( nMenuId )); + } + } +} + +// XMenuListener +void ControlMenuController::impl_select(const Reference< XDispatch >& /*_xDispatch*/,const ::com::sun::star::util::URL& aURL) +{ + UrlToDispatchMap::iterator pIter = m_aURLToDispatchMap.find( aURL.Complete ); + if ( pIter != m_aURLToDispatchMap.end() ) + { + Sequence<PropertyValue> aArgs; + Reference< XDispatch > xDispatch = pIter->second; + if(::comphelper::UiEventsLogger::isEnabled()) //#i88653# + UiEventLogHelper(::rtl::OUString::createFromAscii("ControlMenuController")).log(m_xServiceManager, m_xFrame, aURL, aArgs); + if ( xDispatch.is() ) + xDispatch->dispatch( aURL, aArgs ); + } +} + +void SAL_CALL ControlMenuController::activate( const css::awt::MenuEvent& ) throw (RuntimeException) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_xPopupMenu.is() ) + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + // Check if some modes have changed so we have to update our menu images + const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); + sal_Bool bIsHiContrast = rSettings.GetHighContrastMode(); + sal_Bool bShowMenuImages = rSettings.GetUseImagesInMenus(); + sal_Bool bUpdateImages = (( m_bWasHiContrast != bIsHiContrast ) || ( bShowMenuImages != m_bShowMenuImages )); + + if ( bUpdateImages ) + { + // The mode has changed or the complete menu so we have to retrieve all images again + m_bWasHiContrast = bIsHiContrast; + m_bShowMenuImages = bShowMenuImages; + + VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXPopupMenu::GetImplementation( m_xPopupMenu ); + if ( pPopupMenu ) + { + PopupMenu* pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu(); + if ( pVCLPopupMenu && bUpdateImages ) + updateImagesPopupMenu( pVCLPopupMenu ); + } + } + } +} + +// XPopupMenuController +void ControlMenuController::impl_setPopupMenu() +{ + if ( m_pResPopupMenu == 0 ) + { + rtl::OStringBuffer aBuf( 32 ); + aBuf.append( "svx" ); + + ResMgr* pResMgr = ResMgr::CreateResMgr( aBuf.getStr() ); + if ( pResMgr ) + { + ResId aResId( RID_FMSHELL_CONVERSIONMENU, *pResMgr ); + aResId.SetRT( RSC_MENU ); + if ( pResMgr->IsAvailable( aResId )) + m_pResPopupMenu = new PopupMenu( aResId ); + + updateImagesPopupMenu( m_pResPopupMenu ); + delete pResMgr; + } + } // if ( m_pResPopupMenu == 0 ) +} + +void SAL_CALL ControlMenuController::updatePopupMenu() throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + if ( m_xFrame.is() && m_xPopupMenu.is() ) + { + URL aTargetURL; + Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY ); + fillPopupMenu( m_xPopupMenu ); + m_aURLToDispatchMap.free(); + + for (sal_uInt32 i=0; i<sizeof(aCommands)/sizeof(aCommands[0]); ++i) + { + aTargetURL.Complete = rtl::OUString::createFromAscii( aCommands[i] ); + m_xURLTransformer->parseStrict( aTargetURL ); + + Reference< XDispatch > xDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 ); + if ( xDispatch.is() ) + { + xDispatch->addStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL ); + xDispatch->removeStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL ); + m_aURLToDispatchMap.insert( UrlToDispatchMap::value_type( aTargetURL.Complete, xDispatch )); + } + } + } +} + +// XInitialization +void SAL_CALL ControlMenuController::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException ) +{ + ResetableGuard aLock( m_aLock ); + PopupMenuControllerBase::initialize(aArguments); + m_aBaseURL = ::rtl::OUString(); +} + +} diff --git a/framework/source/uielement/dropdownboxtoolbarcontroller.cxx b/framework/source/uielement/dropdownboxtoolbarcontroller.cxx new file mode 100644 index 000000000000..43b50eb2a49a --- /dev/null +++ b/framework/source/uielement/dropdownboxtoolbarcontroller.cxx @@ -0,0 +1,354 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + +#ifndef __FRAMEWORK_UIELEMENT_DROPDOWNBOXTOOLBARCONTROLLER_HXX +#include "uielement/dropdownboxtoolbarcontroller.hxx" +#endif + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ + +#ifndef __FRAMEWORK_TOOLBAR_HXX_ +#include "uielement/toolbar.hxx" +#endif + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/frame/status/ItemStatus.hpp> +#include <com/sun/star/frame/status/ItemState.hpp> +#include <com/sun/star/frame/status/Visibility.hpp> +#include <com/sun/star/frame/XControlNotificationListener.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ +#include <svtools/toolboxcontroller.hxx> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> +#ifndef _VCL_MNEMONIC_HXX_ +#include <vcl/mnemonic.hxx> +#endif +#include <tools/urlobj.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::frame::status; +using namespace ::com::sun::star::util; + +namespace framework +{ + +// ------------------------------------------------------------------ + +// Wrapper class to notify controller about events from ListBox. +// Unfortunaltly the events are notifed through virtual methods instead +// of Listeners. + +class ListBoxControl : public ListBox +{ + public: + ListBoxControl( Window* pParent, WinBits nStyle, IListBoxListener* pListBoxListener ); + virtual ~ListBoxControl(); + + virtual void Select(); + virtual void DoubleClick(); + virtual void GetFocus(); + virtual void LoseFocus(); + virtual long PreNotify( NotifyEvent& rNEvt ); + + private: + IListBoxListener* m_pListBoxListener; +}; + +ListBoxControl::ListBoxControl( Window* pParent, WinBits nStyle, IListBoxListener* pListBoxListener ) : + ListBox( pParent, nStyle ) + , m_pListBoxListener( pListBoxListener ) +{ +} + +ListBoxControl::~ListBoxControl() +{ + m_pListBoxListener = 0; +} + +void ListBoxControl::Select() +{ + ListBox::Select(); + if ( m_pListBoxListener ) + m_pListBoxListener->Select(); +} + +void ListBoxControl::DoubleClick() +{ + ListBox::DoubleClick(); + if ( m_pListBoxListener ) + m_pListBoxListener->DoubleClick(); +} + +void ListBoxControl::GetFocus() +{ + ListBox::GetFocus(); + if ( m_pListBoxListener ) + m_pListBoxListener->GetFocus(); +} + +void ListBoxControl::LoseFocus() +{ + ListBox::LoseFocus(); + if ( m_pListBoxListener ) + m_pListBoxListener->LoseFocus(); +} + +long ListBoxControl::PreNotify( NotifyEvent& rNEvt ) +{ + long nRet( 0 ); + if ( m_pListBoxListener ) + nRet = m_pListBoxListener->PreNotify( rNEvt ); + if ( nRet == 0 ) + nRet = ListBox::PreNotify( rNEvt ); + + return nRet; +} + +// ------------------------------------------------------------------ + +DropdownToolbarController::DropdownToolbarController( + const Reference< XMultiServiceFactory >& rServiceManager, + const Reference< XFrame >& rFrame, + ToolBox* pToolbar, + USHORT nID, + sal_Int32 nWidth, + const ::rtl::OUString& aCommand ) : + ComplexToolbarController( rServiceManager, rFrame, pToolbar, nID, aCommand ) + , m_pListBoxControl( 0 ) +{ + m_pListBoxControl = new ListBoxControl( m_pToolbar, WB_DROPDOWN|WB_AUTOHSCROLL|WB_BORDER, this ); + if ( nWidth == 0 ) + nWidth = 100; + + // default dropdown size + ::Size aLogicalSize( 0, 160 ); + ::Size aPixelSize = m_pListBoxControl->LogicToPixel( aLogicalSize, MAP_APPFONT ); + + m_pListBoxControl->SetSizePixel( ::Size( nWidth, aPixelSize.Height() )); + m_pToolbar->SetItemWindow( m_nID, m_pListBoxControl ); + m_pListBoxControl->SetDropDownLineCount( 5 ); +} + +// ------------------------------------------------------------------ + +DropdownToolbarController::~DropdownToolbarController() +{ +} + +// ------------------------------------------------------------------ + +void SAL_CALL DropdownToolbarController::dispose() +throw ( RuntimeException ) +{ + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + m_pToolbar->SetItemWindow( m_nID, 0 ); + delete m_pListBoxControl; + + ComplexToolbarController::dispose(); + + m_pListBoxControl = 0; +} + +// ------------------------------------------------------------------ +Sequence<PropertyValue> DropdownToolbarController::getExecuteArgs(sal_Int16 KeyModifier) const +{ + Sequence<PropertyValue> aArgs( 2 ); + ::rtl::OUString aSelectedText = m_pListBoxControl->GetText(); + + // Add key modifier to argument list + aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "KeyModifier" )); + aArgs[0].Value <<= KeyModifier; + aArgs[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" )); + aArgs[1].Value <<= aSelectedText; + return aArgs; +} + +// ------------------------------------------------------------------ + +void DropdownToolbarController::Select() +{ + if ( m_pListBoxControl->GetEntryCount() > 0 ) + { + Window::PointerState aState = m_pListBoxControl->GetPointerState(); + + sal_uInt16 nKeyModifier = sal_uInt16( aState.mnState & KEY_MODTYPE ); + execute( nKeyModifier ); + } +} + +void DropdownToolbarController::DoubleClick() +{ +} + +void DropdownToolbarController::GetFocus() +{ + notifyFocusGet(); +} + +void DropdownToolbarController::LoseFocus() +{ + notifyFocusLost(); +} + +long DropdownToolbarController::PreNotify( NotifyEvent& /*rNEvt*/ ) +{ + return 0; +} + +// -------------------------------------------------------- + +void DropdownToolbarController::executeControlCommand( const ::com::sun::star::frame::ControlCommand& rControlCommand ) +{ + if ( rControlCommand.Command.equalsAsciiL( "SetList", 7 )) + { + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "List", 4 )) + { + Sequence< ::rtl::OUString > aList; + m_pListBoxControl->Clear(); + + rControlCommand.Arguments[i].Value >>= aList; + for ( sal_Int32 j = 0; j < aList.getLength(); j++ ) + m_pListBoxControl->InsertEntry( aList[j] ); + + m_pListBoxControl->SelectEntryPos( 0 ); + + // send notification + uno::Sequence< beans::NamedValue > aInfo( 1 ); + aInfo[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "List" )); + aInfo[0].Value <<= aList; + addNotifyInfo( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ListChanged" )), + getDispatchFromCommand( m_aCommandURL ), + aInfo ); + + break; + } + } + } + else if ( rControlCommand.Command.equalsAsciiL( "AddEntry", 8 )) + { + sal_uInt16 nPos( LISTBOX_APPEND ); + rtl::OUString aText; + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Text", 4 )) + { + if ( rControlCommand.Arguments[i].Value >>= aText ) + m_pListBoxControl->InsertEntry( aText, nPos ); + break; + } + } + } + else if ( rControlCommand.Command.equalsAsciiL( "InsertEntry", 11 )) + { + sal_uInt16 nPos( LISTBOX_APPEND ); + rtl::OUString aText; + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Pos", 3 )) + { + sal_Int32 nTmpPos = 0; + if ( rControlCommand.Arguments[i].Value >>= nTmpPos ) + { + if (( nTmpPos >= 0 ) && + ( nTmpPos < sal_Int32( m_pListBoxControl->GetEntryCount() ))) + nPos = sal_uInt16( nTmpPos ); + } + } + else if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Text", 4 )) + rControlCommand.Arguments[i].Value >>= aText; + } + + m_pListBoxControl->InsertEntry( aText, nPos ); + } + else if ( rControlCommand.Command.equalsAsciiL( "RemoveEntryPos", 14 )) + { + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Pos", 3 )) + { + sal_Int32 nPos( -1 ); + if ( rControlCommand.Arguments[i].Value >>= nPos ) + { + if ( nPos < sal_Int32( m_pListBoxControl->GetEntryCount() )) + m_pListBoxControl->RemoveEntry( sal_uInt16( nPos )); + } + break; + } + } + } + else if ( rControlCommand.Command.equalsAsciiL( "RemoveEntryText", 15 )) + { + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Text", 4 )) + { + rtl::OUString aText; + if ( rControlCommand.Arguments[i].Value >>= aText ) + m_pListBoxControl->RemoveEntry( aText ); + break; + } + } + } + else if ( rControlCommand.Command.equalsAsciiL( "SetDropDownLines", 16 )) + { + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Lines", 5 )) + { + sal_Int32 nValue( 5 ); + rControlCommand.Arguments[i].Value >>= nValue; + m_pListBoxControl->SetDropDownLineCount( sal_uInt16( nValue )); + break; + } + } + } +} + +} // namespace + diff --git a/framework/source/uielement/edittoolbarcontroller.cxx b/framework/source/uielement/edittoolbarcontroller.cxx new file mode 100644 index 000000000000..3ad4b11fd1e9 --- /dev/null +++ b/framework/source/uielement/edittoolbarcontroller.cxx @@ -0,0 +1,269 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + +#ifndef __FRAMEWORK_UIELEMENT_EDITTOOLBARCONTROLLER_HXX +#include "uielement/edittoolbarcontroller.hxx" +#endif + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ + +#ifndef __FRAMEWORK_TOOLBAR_HXX_ +#include "uielement/toolbar.hxx" +#endif + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/frame/status/ItemStatus.hpp> +#include <com/sun/star/frame/status/ItemState.hpp> +#include <com/sun/star/frame/status/Visibility.hpp> +#include <com/sun/star/frame/XControlNotificationListener.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ +#include <svtools/toolboxcontroller.hxx> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> +#ifndef _VCL_MNEMONIC_HXX_ +#include <vcl/mnemonic.hxx> +#endif +#include <tools/urlobj.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::frame::status; +using namespace ::com::sun::star::util; + +namespace framework +{ + +// ------------------------------------------------------------------ + +// Wrapper class to notify controller about events from edit. +// Unfortunaltly the events are notifed through virtual methods instead +// of Listeners. + +class EditControl : public Edit +{ + public: + EditControl( Window* pParent, WinBits nStyle, IEditListener* pEditListener ); + virtual ~EditControl(); + + virtual void Modify(); + virtual void KeyInput( const ::KeyEvent& rKEvt ); + virtual void GetFocus(); + virtual void LoseFocus(); + virtual long PreNotify( NotifyEvent& rNEvt ); + + private: + IEditListener* m_pEditListener; +}; + +EditControl::EditControl( Window* pParent, WinBits nStyle, IEditListener* pEditListener ) : + Edit( pParent, nStyle ) + , m_pEditListener( pEditListener ) +{ +} + +EditControl::~EditControl() +{ + m_pEditListener = 0; +} + +void EditControl::Modify() +{ + Edit::Modify(); + if ( m_pEditListener ) + m_pEditListener->Modify(); +} + +void EditControl::KeyInput( const ::KeyEvent& rKEvt ) +{ + Edit::KeyInput( rKEvt ); + if ( m_pEditListener ) + m_pEditListener->KeyInput( rKEvt ); +} + +void EditControl::GetFocus() +{ + Edit::GetFocus(); + if ( m_pEditListener ) + m_pEditListener->GetFocus(); +} + +void EditControl::LoseFocus() +{ + Edit::LoseFocus(); + if ( m_pEditListener ) + m_pEditListener->LoseFocus(); +} + +long EditControl::PreNotify( NotifyEvent& rNEvt ) +{ + long nRet( 0 ); + if ( m_pEditListener ) + nRet = m_pEditListener->PreNotify( rNEvt ); + if ( nRet == 0 ) + nRet = Edit::PreNotify( rNEvt ); + + return nRet; +} + +// ------------------------------------------------------------------ + +EditToolbarController::EditToolbarController( + const Reference< XMultiServiceFactory >& rServiceManager, + const Reference< XFrame >& rFrame, + ToolBox* pToolbar, + USHORT nID, + sal_Int32 nWidth, + const ::rtl::OUString& aCommand ) : + ComplexToolbarController( rServiceManager, rFrame, pToolbar, nID, aCommand ) + , m_pEditControl( 0 ) +{ + m_pEditControl = new EditControl( m_pToolbar, WB_BORDER, this ); + if ( nWidth == 0 ) + nWidth = 100; + + // Calculate height of the edit field according to the application font height + sal_Int32 nHeight = getFontSizePixel( m_pEditControl ) + 6 + 1; + + m_pEditControl->SetSizePixel( ::Size( nWidth, nHeight )); + m_pToolbar->SetItemWindow( m_nID, m_pEditControl ); +} + +// ------------------------------------------------------------------ + +EditToolbarController::~EditToolbarController() +{ +} + +// ------------------------------------------------------------------ + +void SAL_CALL EditToolbarController::dispose() +throw ( RuntimeException ) +{ + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + m_pToolbar->SetItemWindow( m_nID, 0 ); + delete m_pEditControl; + + ComplexToolbarController::dispose(); + + m_pEditControl = 0; +} + +// ------------------------------------------------------------------ +Sequence<PropertyValue> EditToolbarController::getExecuteArgs(sal_Int16 KeyModifier) const +{ + Sequence<PropertyValue> aArgs( 2 ); + ::rtl::OUString aSelectedText = m_pEditControl->GetText(); + + // Add key modifier to argument list + aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "KeyModifier" )); + aArgs[0].Value <<= KeyModifier; + aArgs[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" )); + aArgs[1].Value <<= aSelectedText; + return aArgs; +} + +// ------------------------------------------------------------------ + +void EditToolbarController::Modify() +{ + notifyTextChanged( m_pEditControl->GetText() ); +} + +void EditToolbarController::KeyInput( const ::KeyEvent& /*rKEvt*/ ) +{ +} + +void EditToolbarController::GetFocus() +{ + notifyFocusGet(); +} + +void EditToolbarController::LoseFocus() +{ + notifyFocusLost(); +} + +long EditToolbarController::PreNotify( NotifyEvent& rNEvt ) +{ + if( rNEvt.GetType() == EVENT_KEYINPUT ) + { + const ::KeyEvent* pKeyEvent = rNEvt.GetKeyEvent(); + const KeyCode& rKeyCode = pKeyEvent->GetKeyCode(); + if(( rKeyCode.GetModifier() | rKeyCode.GetCode()) == KEY_RETURN ) + { + // Call execute only with non-empty text + if ( m_pEditControl->GetText().Len() > 0 ) + execute( rKeyCode.GetModifier() ); + return 1; + } + } + + return 0; +} + +// -------------------------------------------------------- + +void EditToolbarController::executeControlCommand( const ::com::sun::star::frame::ControlCommand& rControlCommand ) +{ + if ( rControlCommand.Command.equalsAsciiL( "SetText", 7 )) + { + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Text", 4 )) + { + rtl::OUString aText; + rControlCommand.Arguments[i].Value >>= aText; + m_pEditControl->SetText( aText ); + + // send notification + notifyTextChanged( aText ); + break; + } + } + } +} + +} // namespace + diff --git a/framework/source/uielement/fontmenucontroller.cxx b/framework/source/uielement/fontmenucontroller.cxx new file mode 100644 index 000000000000..7110ea5aa519 --- /dev/null +++ b/framework/source/uielement/fontmenucontroller.cxx @@ -0,0 +1,261 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include <uielement/fontmenucontroller.hxx> + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <threadhelp/resetableguard.hxx> +#include "services.h" + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/awt/XDevice.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/awt/MenuItemStyle.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> + + +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ + +#ifndef _VCL_MENU_HXX_ +#include <vcl/menu.hxx> +#endif +#include <vcl/svapp.hxx> +#include <vcl/i18nhelp.hxx> +#include <tools/urlobj.hxx> +#include <rtl/ustrbuf.hxx> +#ifndef _VCL_MNEMONIC_HXX_ +#include <vcl/mnemonic.hxx> +#endif +#include <dispatch/uieventloghelper.hxx> + +//_________________________________________________________________________________________________________________ +// Defines +//_________________________________________________________________________________________________________________ +// + +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 std; + +bool lcl_I18nCompareString(const rtl::OUString& rStr1, const rtl::OUString& rStr2) +{ + const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper(); + return rI18nHelper.CompareString( rStr1, rStr2 ) < 0 ? true : false; +} + +namespace framework +{ + +DEFINE_XSERVICEINFO_MULTISERVICE ( FontMenuController , + OWeakObject , + SERVICENAME_POPUPMENUCONTROLLER , + IMPLEMENTATIONNAME_FONTMENUCONTROLLER + ) + +DEFINE_INIT_SERVICE ( FontMenuController, {} ) + +FontMenuController::FontMenuController( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ) : + PopupMenuControllerBase( xServiceManager ) +{ +} + +FontMenuController::~FontMenuController() +{ +} + +// private function +void FontMenuController::fillPopupMenu( const Sequence< ::rtl::OUString >& rFontNameSeq, Reference< css::awt::XPopupMenu >& rPopupMenu ) +{ + const rtl::OUString* pFontNameArray = rFontNameSeq.getConstArray(); + VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( rPopupMenu ); + PopupMenu* pVCLPopupMenu = 0; + + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + resetPopupMenu( rPopupMenu ); + if ( pPopupMenu ) + pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu(); + + if ( pVCLPopupMenu ) + { + vector<rtl::OUString> aVector; + aVector.reserve(rFontNameSeq.getLength()); + for ( USHORT i = 0; i < rFontNameSeq.getLength(); i++ ) + { + aVector.push_back(MnemonicGenerator::EraseAllMnemonicChars(pFontNameArray[i])); + } + sort(aVector.begin(), aVector.end(), lcl_I18nCompareString ); + + const rtl::OUString aFontNameCommandPrefix( RTL_CONSTASCII_USTRINGPARAM( ".uno:CharFontName?CharFontName.FamilyName:string=" )); + const sal_Int16 nCount = (sal_Int16)aVector.size(); + for ( sal_Int16 i = 0; i < nCount; i++ ) + { + const rtl::OUString& rName = aVector[i]; + m_xPopupMenu->insertItem( i+1, rName, css::awt::MenuItemStyle::RADIOCHECK | css::awt::MenuItemStyle::AUTOCHECK, i ); + if ( rName == m_aFontFamilyName ) + m_xPopupMenu->checkItem( i+1, sal_True ); + // use VCL popup menu pointer to set vital information that are not part of the awt implementation + rtl::OUStringBuffer aCommandBuffer( aFontNameCommandPrefix ); + aCommandBuffer.append( INetURLObject::encode( rName, INetURLObject::PART_HTTP_QUERY, '%', INetURLObject::ENCODE_ALL )); + rtl::OUString aFontNameCommand = aCommandBuffer.makeStringAndClear(); + pVCLPopupMenu->SetItemCommand( i+1, aFontNameCommand ); // Store font name into item command. + } + + } +} + +// XEventListener +void SAL_CALL FontMenuController::disposing( const EventObject& ) throw ( RuntimeException ) +{ + Reference< css::awt::XMenuListener > xHolder(( OWeakObject *)this, UNO_QUERY ); + + ResetableGuard aLock( m_aLock ); + m_xFrame.clear(); + m_xDispatch.clear(); + m_xFontListDispatch.clear(); + m_xServiceManager.clear(); + + if ( m_xPopupMenu.is() ) + m_xPopupMenu->removeMenuListener( Reference< css::awt::XMenuListener >(( OWeakObject *)this, UNO_QUERY )); + m_xPopupMenu.clear(); +} + +// XStatusListener +void SAL_CALL FontMenuController::statusChanged( const FeatureStateEvent& Event ) throw ( RuntimeException ) +{ + com::sun::star::awt::FontDescriptor aFontDescriptor; + Sequence< rtl::OUString > aFontNameSeq; + + if ( Event.State >>= aFontDescriptor ) + { + ResetableGuard aLock( m_aLock ); + m_aFontFamilyName = aFontDescriptor.Name; + } + else if ( Event.State >>= aFontNameSeq ) + { + ResetableGuard aLock( m_aLock ); + if ( m_xPopupMenu.is() ) + fillPopupMenu( aFontNameSeq, m_xPopupMenu ); + } +} + +// XMenuListener +void FontMenuController::impl_select(const Reference< XDispatch >& _xDispatch,const ::com::sun::star::util::URL& aTargetURL) +{ + Sequence<PropertyValue> aArgs; + if(::comphelper::UiEventsLogger::isEnabled()) //#i88653# + UiEventLogHelper(::rtl::OUString::createFromAscii("FontMenuController")).log( + m_xServiceManager, + m_xFrame, + aTargetURL, + Sequence<PropertyValue>()); + OSL_ENSURE(_xDispatch.is(),"FontMenuController::impl_select: No dispatch"); + if ( _xDispatch.is() ) + _xDispatch->dispatch( aTargetURL, aArgs ); +} + +void SAL_CALL FontMenuController::activate( const css::awt::MenuEvent& ) throw (RuntimeException) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_xPopupMenu.is() ) + { + // find new font name and set check mark! + USHORT nChecked = 0; + USHORT nItemCount = m_xPopupMenu->getItemCount(); + rtl::OUString aEmpty; + for( USHORT i = 0; i < nItemCount; i++ ) + { + USHORT nItemId = m_xPopupMenu->getItemId( i ); + + if ( m_xPopupMenu->isItemChecked( nItemId ) ) + nChecked = nItemId; + + rtl::OUString aText = m_xPopupMenu->getItemText( nItemId ); + + // TODO: must be replaced by implementation of VCL, when available + sal_Int32 nIndex = aText.indexOf( (sal_Unicode)'~' ); + if ( nIndex >= 0 ) + aText = aText.replaceAt( nIndex, 1, aEmpty ); + // TODO: must be replaced by implementation of VCL, when available + + if ( aText == m_aFontFamilyName ) + { + m_xPopupMenu->checkItem( nItemId, sal_True ); + return; + } + } + + if ( nChecked ) + m_xPopupMenu->checkItem( nChecked, sal_False ); + } +} + +// XPopupMenuController +void FontMenuController::impl_setPopupMenu() +{ + Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY ); + + com::sun::star::util::URL aTargetURL; + // Register for font list updates to get the current font list from the controller + aTargetURL.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:FontNameList" )); + m_xURLTransformer->parseStrict( aTargetURL ); + m_xFontListDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 ); +} + +void SAL_CALL FontMenuController::updatePopupMenu() throw ( ::com::sun::star::uno::RuntimeException ) +{ + PopupMenuControllerBase::updatePopupMenu(); + + ResetableGuard aLock( m_aLock ); + Reference< XDispatch > xDispatch( m_xFontListDispatch ); + com::sun::star::util::URL aTargetURL; + aTargetURL.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:FontNameList" )); + m_xURLTransformer->parseStrict( aTargetURL ); + aLock.unlock(); + + if ( xDispatch.is() ) + { + xDispatch->addStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL ); + xDispatch->removeStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL ); + } +} + +} + diff --git a/framework/source/uielement/fontsizemenucontroller.cxx b/framework/source/uielement/fontsizemenucontroller.cxx new file mode 100644 index 000000000000..8dbd608a28e0 --- /dev/null +++ b/framework/source/uielement/fontsizemenucontroller.cxx @@ -0,0 +1,363 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include <uielement/fontsizemenucontroller.hxx> + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <threadhelp/resetableguard.hxx> +#include "services.h" + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/awt/XDevice.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/awt/MenuItemStyle.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/view/XPrintable.hpp> + +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ + +#ifndef _VCL_MENU_HXX_ +#include <vcl/menu.hxx> +#endif +#include <vcl/mapunit.hxx> +#ifndef _VCL_SVAPP_HXX_ +#include <vcl/svapp.hxx> +#endif +#include <vcl/i18nhelp.hxx> +#ifndef _VCL_OUTPUTDEVICE_HXX_ +#include <vcl/outdev.hxx> +#endif +#include <vcl/print.hxx> +#ifndef _SVTOOLS_CTRLTOOL_HXX_ +#include <svtools/ctrltool.hxx> +#endif +#include <dispatch/uieventloghelper.hxx> + +//_________________________________________________________________________________________________________________ +// Defines +//_________________________________________________________________________________________________________________ +// + +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::view; +using namespace com::sun::star::beans; + +namespace framework +{ + +DEFINE_XSERVICEINFO_MULTISERVICE ( FontSizeMenuController , + OWeakObject , + SERVICENAME_POPUPMENUCONTROLLER , + IMPLEMENTATIONNAME_FONTSIZEMENUCONTROLLER + ) + +DEFINE_INIT_SERVICE ( FontSizeMenuController, {} ) + +FontSizeMenuController::FontSizeMenuController( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ) : + PopupMenuControllerBase( xServiceManager ), + m_pHeightArray( 0 ), + m_bRebuildMenu( sal_True ) +{ +} + +FontSizeMenuController::~FontSizeMenuController() +{ + delete []m_pHeightArray; +} + +// private function +rtl::OUString FontSizeMenuController::retrievePrinterName( com::sun::star::uno::Reference< com::sun::star::frame::XFrame >& rFrame ) +{ + rtl::OUString aPrinterName; + + if ( rFrame.is() ) + { + Reference< XController > xController = m_xFrame->getController(); + if ( xController.is() ) + { + Reference< XPrintable > xPrintable( xController->getModel(), UNO_QUERY ); + if ( xPrintable.is() ) + { + Sequence< PropertyValue > aPrinterSeq = xPrintable->getPrinter(); + for ( int i = 0; i < aPrinterSeq.getLength(); i++ ) + { + if ( aPrinterSeq[i].Name.equalsAscii( "Name" )) + { + aPrinterSeq[i].Value >>= aPrinterName; + break; + } + } + } + } + } + + return aPrinterName; +} + +// private function +void FontSizeMenuController::setCurHeight( long nHeight, Reference< css::awt::XPopupMenu >& rPopupMenu ) +{ + // check menu item + rtl::OUString aHeight = Application::GetSettings().GetUILocaleI18nHelper().GetNum( nHeight, 1, TRUE, FALSE ); + USHORT nChecked = 0; + USHORT nItemCount = rPopupMenu->getItemCount(); + for( USHORT i = 0; i < nItemCount; i++ ) + { + USHORT nItemId = rPopupMenu->getItemId( i ); + + if ( m_pHeightArray[i] == nHeight ) + { + rPopupMenu->checkItem( nItemId, TRUE ); + return; + } + + if ( rPopupMenu->isItemChecked( nItemId ) ) + nChecked = nItemId; + } + + if ( nChecked ) + rPopupMenu->checkItem( nChecked, FALSE ); +} + +// private function +void FontSizeMenuController::fillPopupMenu( Reference< css::awt::XPopupMenu >& rPopupMenu ) +{ + const rtl::OUString aFontNameCommand( RTL_CONSTASCII_USTRINGPARAM( ".uno:FontHeight?FontHeight=" )); + VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( rPopupMenu ); + PopupMenu* pVCLPopupMenu = 0; + + resetPopupMenu( rPopupMenu ); + if ( pPopupMenu ) + pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu(); + + if ( pVCLPopupMenu ) + { + FontList* pFontList = 0; + Printer* pInfoPrinter = 0; + rtl::OUString aPrinterName; + + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + // try to retrieve printer name of document + aPrinterName = retrievePrinterName( m_xFrame ); + if ( aPrinterName.getLength() > 0 ) + { + pInfoPrinter = new Printer( aPrinterName ); + if ( pInfoPrinter && pInfoPrinter->GetDevFontCount() > 0 ) + pFontList = new FontList( pInfoPrinter ); + } + + if ( pFontList == 0 ) + pFontList = new FontList( Application::GetDefaultDevice() ); + + FontInfo aFntInfo = pFontList->Get( m_aFontDescriptor.Name, m_aFontDescriptor.StyleName ); + + // setup font size array + if ( m_pHeightArray ) + delete m_pHeightArray; + + const long* pTempAry; + const long* pAry = pFontList->GetSizeAry( aFntInfo ); + USHORT nSizeCount = 0; + while ( pAry[nSizeCount] ) + nSizeCount++; + + USHORT nPos = 0; + const rtl::OUString aFontHeightCommand( RTL_CONSTASCII_USTRINGPARAM( ".uno:FontHeight?FontHeight.Height:float=" )); + + // first insert font size names (for simplified/traditional chinese) + float fPoint; + rtl::OUString aHeightString; + FontSizeNames aFontSizeNames( Application::GetSettings().GetUILanguage() ); + m_pHeightArray = new long[nSizeCount+aFontSizeNames.Count()]; + rtl::OUString aCommand; + + if ( !aFontSizeNames.IsEmpty() ) + { + if ( pAry == pFontList->GetStdSizeAry() ) + { + // for scalable fonts all font size names + ULONG nCount = aFontSizeNames.Count(); + for( ULONG i = 0; i < nCount; i++ ) + { + String aSizeName = aFontSizeNames.GetIndexName( i ); + long nSize = aFontSizeNames.GetIndexSize( i ); + m_pHeightArray[nPos] = nSize; + nPos++; // Id is nPos+1 + pVCLPopupMenu->InsertItem( nPos, aSizeName, MIB_RADIOCHECK | MIB_AUTOCHECK ); + fPoint = float( m_pHeightArray[nPos-1] ) / 10; + + // Create dispatchable .uno command and set it + aCommand = aFontHeightCommand + rtl::OUString::valueOf( fPoint ); + pVCLPopupMenu->SetItemCommand( nPos, aCommand ); + } + } + else + { + // for fixed size fonts only selectable font size names + pTempAry = pAry; + while ( *pTempAry ) + { + String aSizeName = aFontSizeNames.Size2Name( *pTempAry ); + if ( aSizeName.Len() ) + { + m_pHeightArray[nPos] = *pTempAry; + nPos++; // Id is nPos+1 + pVCLPopupMenu->InsertItem( nPos, aSizeName, MIB_RADIOCHECK | MIB_AUTOCHECK ); + fPoint = float( m_pHeightArray[nPos-1] ) / 10; + + // Create dispatchable .uno command and set it + aCommand = aFontHeightCommand + rtl::OUString::valueOf( fPoint ); + pVCLPopupMenu->SetItemCommand( nPos, aCommand ); + } + pTempAry++; + } + } + } + + // then insert numerical font size values + const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper(); + pTempAry = pAry; + while ( *pTempAry ) + { + m_pHeightArray[nPos] = *pTempAry; + nPos++; // Id is nPos+1 + pVCLPopupMenu->InsertItem( nPos, rI18nHelper.GetNum( *pTempAry, 1, TRUE, FALSE ), MIB_RADIOCHECK | MIB_AUTOCHECK ); + fPoint = float( m_pHeightArray[nPos-1] ) / 10; + + // Create dispatchable .uno command and set it + aCommand = aFontHeightCommand + rtl::OUString::valueOf( fPoint ); + pVCLPopupMenu->SetItemCommand( nPos, aCommand ); + + pTempAry++; + } + + setCurHeight( long( m_aFontHeight.Height * 10), rPopupMenu ); + + delete pFontList; + delete pInfoPrinter; + } +} + +// XEventListener +void SAL_CALL FontSizeMenuController::disposing( const EventObject& ) throw ( RuntimeException ) +{ + Reference< css::awt::XMenuListener > xHolder(( OWeakObject *)this, UNO_QUERY ); + + ResetableGuard aLock( m_aLock ); + m_xFrame.clear(); + m_xDispatch.clear(); + m_xCurrentFontDispatch.clear(); + if ( m_xPopupMenu.is() ) + m_xPopupMenu->removeMenuListener( Reference< css::awt::XMenuListener >(( OWeakObject *)this, UNO_QUERY )); + m_xPopupMenu.clear(); +} + +// XStatusListener +void SAL_CALL FontSizeMenuController::statusChanged( const FeatureStateEvent& Event ) throw ( RuntimeException ) +{ + com::sun::star::awt::FontDescriptor aFontDescriptor; + ::com::sun::star::frame::status::FontHeight aFontHeight; + + if ( Event.State >>= aFontDescriptor ) + { + ResetableGuard aLock( m_aLock ); + m_aFontDescriptor = aFontDescriptor; + + if ( m_xPopupMenu.is() ) + fillPopupMenu( m_xPopupMenu ); + + } + else if ( Event.State >>= aFontHeight ) + { + ResetableGuard aLock( m_aLock ); + m_aFontHeight = aFontHeight; + + if ( m_xPopupMenu.is() ) + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + setCurHeight( long( m_aFontHeight.Height * 10), m_xPopupMenu ); + } + } +} + +// XMenuListener +void FontSizeMenuController::impl_select(const Reference< XDispatch >& _xDispatch,const ::com::sun::star::util::URL& aTargetURL) +{ + Sequence<PropertyValue> aArgs; + if(::comphelper::UiEventsLogger::isEnabled()) //#i88653# + UiEventLogHelper(::rtl::OUString::createFromAscii("FontSizeMenuController")).log(m_xServiceManager, m_xFrame, aTargetURL, aArgs); + OSL_ENSURE(_xDispatch.is(),"FontSizeMenuController::impl_select: No dispatch"); + if ( _xDispatch.is() ) + _xDispatch->dispatch( aTargetURL, aArgs ); +} + +// XPopupMenuController +void FontSizeMenuController::impl_setPopupMenu() +{ + Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY ); + com::sun::star::util::URL aTargetURL; + // Register for font name updates which gives us info about the current font! + aTargetURL.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:CharFontName" )); + m_xURLTransformer->parseStrict( aTargetURL ); + m_xCurrentFontDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 ); +} + +void SAL_CALL FontSizeMenuController::updatePopupMenu() throw ( ::com::sun::star::uno::RuntimeException ) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + Reference< XDispatch > xDispatch( m_xCurrentFontDispatch ); + com::sun::star::util::URL aTargetURL; + aTargetURL.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:CharFontName" )); + m_xURLTransformer->parseStrict( aTargetURL ); + aLock.unlock(); + + if ( xDispatch.is() ) + { + xDispatch->addStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL ); + xDispatch->removeStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL ); + } + + PopupMenuControllerBase::updatePopupMenu(); +} +} diff --git a/framework/source/uielement/footermenucontroller.cxx b/framework/source/uielement/footermenucontroller.cxx new file mode 100644 index 000000000000..16f26404697c --- /dev/null +++ b/framework/source/uielement/footermenucontroller.cxx @@ -0,0 +1,97 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include <uielement/footermenucontroller.hxx> + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <threadhelp/resetableguard.hxx> +#include "services.h" +#ifndef __FRAMEWORK_CLASSES_RESOURCE_HRC_ +#include <classes/resource.hrc> +#endif +#include <classes/fwlresid.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/awt/XDevice.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/awt/MenuItemStyle.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/style/XStyleFamiliesSupplier.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> + +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ + +#ifndef _VCL_MENU_HXX_ +#include <vcl/menu.hxx> +#endif +#include <vcl/svapp.hxx> +#include <vcl/i18nhelp.hxx> +#include <tools/urlobj.hxx> +#include <rtl/ustrbuf.hxx> +#include <dispatch/uieventloghelper.hxx> + +//_________________________________________________________________________________________________________________ +// Defines +//_________________________________________________________________________________________________________________ +// + +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::style; +using namespace com::sun::star::container; + +namespace framework +{ + +DEFINE_XSERVICEINFO_MULTISERVICE ( FooterMenuController , + OWeakObject , + SERVICENAME_POPUPMENUCONTROLLER , + IMPLEMENTATIONNAME_FOOTERMENUCONTROLLER + ) + +FooterMenuController::FooterMenuController( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ) : + HeaderMenuController( xServiceManager,true ) +{ +} + +FooterMenuController::~FooterMenuController() +{ +} +} diff --git a/framework/source/uielement/generictoolbarcontroller.cxx b/framework/source/uielement/generictoolbarcontroller.cxx new file mode 100644 index 000000000000..3f37050e6780 --- /dev/null +++ b/framework/source/uielement/generictoolbarcontroller.cxx @@ -0,0 +1,393 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + +#ifndef __FRAMEWORK_UIELEMENT_GENERICTOOLBARCONTROLLER_HXX +#include "uielement/generictoolbarcontroller.hxx" +#endif + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ + +#ifndef __FRAMEWORK_TOOLBAR_HXX_ +#include "uielement/toolbar.hxx" +#endif + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/frame/status/ItemStatus.hpp> +#include <com/sun/star/frame/status/ItemState.hpp> +#include <com/sun/star/frame/status/Visibility.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ +#include <svtools/toolboxcontroller.hxx> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> +#ifndef _VCL_MNEMONIC_HXX_ +#include <vcl/mnemonic.hxx> +#endif +#include <tools/urlobj.hxx> +#include <classes/resource.hrc> +#include <classes/fwkresid.hxx> +#include <dispatch/uieventloghelper.hxx> + +#include <xml/menuconfiguration.hxx> +#include <uielement/menubarmanager.hxx> + +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::frame::status; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::container; + +namespace framework +{ + +static sal_Bool isEnumCommand( const rtl::OUString& rCommand ) +{ + INetURLObject aURL( rCommand ); + + if (( aURL.GetProtocol() == INET_PROT_UNO ) && + ( aURL.GetURLPath().indexOf( '.' ) != -1)) + return sal_True; + + return sal_False; +} + +static rtl::OUString getEnumCommand( const rtl::OUString& rCommand ) +{ + INetURLObject aURL( rCommand ); + + rtl::OUString aEnumCommand; + String aURLPath = aURL.GetURLPath(); + xub_StrLen nIndex = aURLPath.Search( '.' ); + if (( nIndex > 0 ) && ( nIndex < aURLPath.Len() )) + aEnumCommand = aURLPath.Copy( nIndex+1 ); + + return aEnumCommand; +} + +static rtl::OUString getMasterCommand( const rtl::OUString& rCommand ) +{ + rtl::OUString aMasterCommand( rCommand ); + INetURLObject aURL( rCommand ); + if ( aURL.GetProtocol() == INET_PROT_UNO ) + { + sal_Int32 nIndex = aURL.GetURLPath().indexOf( '.' ); + if ( nIndex ) + { + aURL.SetURLPath( aURL.GetURLPath().copy( 0, nIndex ) ); + aMasterCommand = aURL.GetMainURL( INetURLObject::NO_DECODE ); + } + } + return aMasterCommand; +} + +struct ExecuteInfo +{ + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDispatch; + ::com::sun::star::util::URL aTargetURL; + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aArgs; +}; + +GenericToolbarController::GenericToolbarController( const Reference< XMultiServiceFactory >& rServiceManager, + const Reference< XFrame >& rFrame, + ToolBox* pToolbar, + USHORT nID, + const ::rtl::OUString& aCommand ) : + svt::ToolboxController( rServiceManager, rFrame, aCommand ) + , m_pToolbar( pToolbar ) + , m_nID( nID ) + , m_bEnumCommand( isEnumCommand( aCommand )) + , m_bMadeInvisible( sal_False ) + , m_aEnumCommand( getEnumCommand( aCommand )) +{ + if ( m_bEnumCommand ) + addStatusListener( getMasterCommand( aCommand ) ); +} + +GenericToolbarController::~GenericToolbarController() +{ +} + +void SAL_CALL GenericToolbarController::dispose() +throw ( RuntimeException ) +{ + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + svt::ToolboxController::dispose(); + + m_pToolbar = 0; + m_nID = 0; +} + +void SAL_CALL GenericToolbarController::execute( sal_Int16 KeyModifier ) +throw ( RuntimeException ) +{ + Reference< XDispatch > xDispatch; + Reference< XURLTransformer > xURLTransformer; + ::rtl::OUString aCommandURL; + + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + if ( m_bDisposed ) + throw DisposedException(); + + if ( m_bInitialized && + m_xFrame.is() && + m_xServiceManager.is() && + m_aCommandURL.getLength() ) + { + xURLTransformer = Reference< XURLTransformer >( m_xServiceManager->createInstance( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.URLTransformer" ))), + UNO_QUERY ); + + aCommandURL = m_aCommandURL; + URLToDispatchMap::iterator pIter = m_aListenerMap.find( m_aCommandURL ); + if ( pIter != m_aListenerMap.end() ) + xDispatch = pIter->second; + } + } + + if ( xDispatch.is() && xURLTransformer.is() ) + { + com::sun::star::util::URL aTargetURL; + Sequence<PropertyValue> aArgs( 1 ); + + // Add key modifier to argument list + aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "KeyModifier" )); + aArgs[0].Value <<= KeyModifier; + + aTargetURL.Complete = aCommandURL; + xURLTransformer->parseStrict( aTargetURL ); + + // Execute dispatch asynchronously + ExecuteInfo* pExecuteInfo = new ExecuteInfo; + pExecuteInfo->xDispatch = xDispatch; + pExecuteInfo->aTargetURL = aTargetURL; + pExecuteInfo->aArgs = aArgs; + if(::comphelper::UiEventsLogger::isEnabled()) //#i88653# + UiEventLogHelper(::rtl::OUString::createFromAscii("GenericToolbarController")).log( m_xServiceManager, m_xFrame, aTargetURL, aArgs); + Application::PostUserEvent( STATIC_LINK(0, GenericToolbarController , ExecuteHdl_Impl), pExecuteInfo ); + } +} + +void GenericToolbarController::statusChanged( const FeatureStateEvent& Event ) +throw ( RuntimeException ) +{ + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + if ( m_bDisposed ) + return; + + if ( m_pToolbar ) + { + m_pToolbar->EnableItem( m_nID, Event.IsEnabled ); + + USHORT nItemBits = m_pToolbar->GetItemBits( m_nID ); + nItemBits &= ~TIB_CHECKABLE; + TriState eTri = STATE_NOCHECK; + + sal_Bool bValue = sal_Bool(); + rtl::OUString aStrValue; + ItemStatus aItemState; + Visibility aItemVisibility; + + if (( Event.State >>= bValue ) && !m_bEnumCommand ) + { + // Boolean, treat it as checked/unchecked + if ( m_bMadeInvisible ) + m_pToolbar->ShowItem( m_nID, TRUE ); + m_pToolbar->CheckItem( m_nID, bValue ); + if ( bValue ) + eTri = STATE_CHECK; + nItemBits |= TIB_CHECKABLE; + } + else if ( Event.State >>= aStrValue ) + { + if ( m_bEnumCommand ) + { + if ( aStrValue == m_aEnumCommand ) + bValue = sal_True; + else + bValue = sal_False; + + m_pToolbar->CheckItem( m_nID, bValue ); + if ( bValue ) + eTri = STATE_CHECK; + nItemBits |= TIB_CHECKABLE; + } + else + { + // Replacement for place holders + if ( aStrValue.matchAsciiL( "($1)", 4 )) + { + String aResStr = String( FwkResId( STR_UPDATEDOC )); + rtl::OUString aTmp( aResStr ); + aTmp += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " )); + aTmp += aStrValue.copy( 4 ); + aStrValue = aTmp; + } + else if ( aStrValue.matchAsciiL( "($2)", 4 )) + { + String aResStr = String( FwkResId( STR_CLOSEDOC_ANDRETURN )); + rtl::OUString aTmp( aResStr ); + aTmp += aStrValue.copy( 4 ); + aStrValue = aTmp; + } + else if ( aStrValue.matchAsciiL( "($3)", 4 )) + { + String aResStr = String( FwkResId( STR_SAVECOPYDOC )); + rtl::OUString aTmp( aResStr ); + aTmp += aStrValue.copy( 4 ); + aStrValue = aTmp; + } + ::rtl::OUString aText( MnemonicGenerator::EraseAllMnemonicChars( aStrValue ) ); + m_pToolbar->SetItemText( m_nID, aText ); + m_pToolbar->SetQuickHelpText( m_nID, aText ); + } + + if ( m_bMadeInvisible ) + m_pToolbar->ShowItem( m_nID, TRUE ); + } + else if (( Event.State >>= aItemState ) && !m_bEnumCommand ) + { + eTri = STATE_DONTKNOW; + nItemBits |= TIB_CHECKABLE; + if ( m_bMadeInvisible ) + m_pToolbar->ShowItem( m_nID, TRUE ); + } + else if ( Event.State >>= aItemVisibility ) + { + m_pToolbar->ShowItem( m_nID, aItemVisibility.bVisible ); + m_bMadeInvisible = !aItemVisibility.bVisible; + } + else if ( m_bMadeInvisible ) + m_pToolbar->ShowItem( m_nID, TRUE ); + + m_pToolbar->SetItemState( m_nID, eTri ); + m_pToolbar->SetItemBits( m_nID, nItemBits ); + } +} + +IMPL_STATIC_LINK_NOINSTANCE( GenericToolbarController, ExecuteHdl_Impl, ExecuteInfo*, pExecuteInfo ) +{ + const sal_uInt32 nRef = Application::ReleaseSolarMutex(); + 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! + pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs ); + } + catch ( Exception& ) + { + } + + Application::AcquireSolarMutex( nRef ); + delete pExecuteInfo; + return 0; +} + +MenuToolbarController::MenuToolbarController( const Reference< XMultiServiceFactory >& rServiceManager, const Reference< XFrame >& rFrame, ToolBox* pToolBar, USHORT nID, const rtl::OUString& aCommand, const rtl::OUString& aModuleIdentifier, const Reference< XIndexAccess >& xMenuDesc ) : GenericToolbarController( rServiceManager, rFrame, pToolBar, nID, aCommand ), m_xMenuDesc( xMenuDesc ), pMenu( NULL ), m_aModuleIdentifier( aModuleIdentifier ) +{ +} + +MenuToolbarController::~MenuToolbarController() +{ + try + { + if ( m_xMenuManager.is() ) + m_xMenuManager->dispose(); + } + catch( Exception& ) {} + if ( pMenu ) + { + delete pMenu; + pMenu = NULL; + } + +} + +class Toolbarmenu : public PopupMenu +{ + public: + Toolbarmenu(); + ~Toolbarmenu(); +}; + +Toolbarmenu::Toolbarmenu() +{ + OSL_TRACE("**** contstructing Toolbarmenu 0x%x", this ); +} + +Toolbarmenu::~Toolbarmenu() +{ + OSL_TRACE("**** destructing Toolbarmenu 0x%x", this ); +} + +void SAL_CALL MenuToolbarController::click() throw (RuntimeException) +{ + createPopupWindow(); +} + +Reference< XWindow > SAL_CALL +MenuToolbarController::createPopupWindow() throw (::com::sun::star::uno::RuntimeException) +{ + if ( !pMenu ) + { + Reference< XDispatchProvider > xDispatch; + Reference< XURLTransformer > xURLTransformer( m_xServiceManager->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.URLTransformer" ))), UNO_QUERY ); + pMenu = new Toolbarmenu(); + m_xMenuManager.set( new MenuBarManager( m_xServiceManager, m_xFrame, xURLTransformer, xDispatch, m_aModuleIdentifier, pMenu, sal_True, sal_True ) ); + if ( m_xMenuManager.is() ) + { + MenuBarManager* pMgr = dynamic_cast< MenuBarManager* >( m_xMenuManager.get() ); + pMgr->SetItemContainer( m_xMenuDesc ); + } + } + + ::Rectangle aRect( m_pToolbar->GetItemRect( m_nID ) ); + pMenu->Execute( m_pToolbar, aRect, POPUPMENU_EXECUTE_DOWN ); + return NULL; +} +} // namespace + diff --git a/framework/source/uielement/headermenucontroller.cxx b/framework/source/uielement/headermenucontroller.cxx new file mode 100644 index 000000000000..50b2ed65e2d2 --- /dev/null +++ b/framework/source/uielement/headermenucontroller.cxx @@ -0,0 +1,277 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include <uielement/headermenucontroller.hxx> + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <threadhelp/resetableguard.hxx> +#include "services.h" + +#ifndef __FRAMEWORK_CLASSES_RESOURCE_HRC_ +#include <classes/resource.hrc> +#endif +#include <classes/fwlresid.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/awt/XDevice.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/awt/MenuItemStyle.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/style/XStyleFamiliesSupplier.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/DisposedException.hpp> + +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ + +#ifndef _VCL_MENU_HXX_ +#include <vcl/menu.hxx> +#endif +#include <vcl/svapp.hxx> +#include <vcl/i18nhelp.hxx> +#include <tools/urlobj.hxx> +#include <rtl/ustrbuf.hxx> +//#include <tools/solar.hrc> +#include <dispatch/uieventloghelper.hxx> + +//_________________________________________________________________________________________________________________ +// Defines +//_________________________________________________________________________________________________________________ +// + +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::style; +using namespace com::sun::star::container; + +// Copied from Writer module +//#define RID_SW_SHELLRES (RID_SW_START + 1250 + 1) +//#define STR_ALLPAGE_HEADFOOT 14 + +const USHORT ALL_MENUITEM_ID = 1; + +namespace framework +{ + +DEFINE_XSERVICEINFO_MULTISERVICE ( HeaderMenuController , + OWeakObject , + SERVICENAME_POPUPMENUCONTROLLER , + IMPLEMENTATIONNAME_HEADERMENUCONTROLLER + ) + +DEFINE_INIT_SERVICE ( HeaderMenuController, {} ) + +HeaderMenuController::HeaderMenuController( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager,bool _bFooter ) : + PopupMenuControllerBase( xServiceManager ) + ,m_bFooter(_bFooter) +{ +} + +HeaderMenuController::~HeaderMenuController() +{ +} + +// private function +void HeaderMenuController::fillPopupMenu( const Reference< ::com::sun::star::frame::XModel >& rModel, Reference< css::awt::XPopupMenu >& rPopupMenu ) +{ + VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( rPopupMenu ); + PopupMenu* pVCLPopupMenu = 0; + + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + resetPopupMenu( rPopupMenu ); + if ( pPopupMenu ) + pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu(); + + Reference< XStyleFamiliesSupplier > xStyleFamiliesSupplier( rModel, UNO_QUERY ); + if ( pVCLPopupMenu && xStyleFamiliesSupplier.is()) + { + Reference< XNameAccess > xStyleFamilies = xStyleFamiliesSupplier->getStyleFamilies(); + + rtl::OUString aCmd( RTL_CONSTASCII_USTRINGPARAM( ".uno:InsertPageHeader" )); + rtl::OUString aHeaderFooterIsOnStr(RTL_CONSTASCII_USTRINGPARAM( "HeaderIsOn" )); + if ( m_bFooter ) + { + aCmd = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:InsertPageFooter" )); + aHeaderFooterIsOnStr = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "FooterIsOn" )); + } + const rtl::OUString aIsPhysicalStr( RTL_CONSTASCII_USTRINGPARAM( "IsPhysical" )); + const rtl::OUString aDisplayNameStr( RTL_CONSTASCII_USTRINGPARAM( "DisplayName" )); + + try + { + Reference< XNameContainer > xNameContainer; + if ( xStyleFamilies->getByName( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PageStyles" ))) >>= xNameContainer ) + { + Sequence< rtl::OUString > aSeqNames = xNameContainer->getElementNames(); + + USHORT nId = 2; + USHORT nCount = 0; + sal_Bool bAllOneState( sal_True ); + sal_Bool bLastCheck( sal_True ); + sal_Bool bFirstChecked( sal_False ); + sal_Bool bFirstItemInserted( sal_False ); + for ( sal_Int32 n = 0; n < aSeqNames.getLength(); n++ ) + { + rtl::OUString aName = aSeqNames[n]; + Reference< XPropertySet > xPropSet( xNameContainer->getByName( aName ), UNO_QUERY ); + if ( xPropSet.is() ) + { + sal_Bool bIsPhysical( sal_False ); + if (( xPropSet->getPropertyValue( aIsPhysicalStr ) >>= bIsPhysical ) && bIsPhysical ) + { + rtl::OUString aDisplayName; + sal_Bool bHeaderIsOn( sal_False ); + xPropSet->getPropertyValue( aDisplayNameStr ) >>= aDisplayName; + xPropSet->getPropertyValue( aHeaderFooterIsOnStr ) >>= bHeaderIsOn; + + rtl::OUStringBuffer aStrBuf( aCmd ); + aStrBuf.appendAscii( "?PageStyle:string="); + aStrBuf.append( aDisplayName ); + aStrBuf.appendAscii( "&On:bool=" ); + if ( !bHeaderIsOn ) + aStrBuf.appendAscii( "true" ); + else + aStrBuf.appendAscii( "false" ); + rtl::OUString aCommand( aStrBuf.makeStringAndClear() ); + pVCLPopupMenu->InsertItem( nId, aDisplayName, MIB_CHECKABLE ); + if ( !bFirstItemInserted ) + { + bFirstItemInserted = sal_True; + bFirstChecked = bHeaderIsOn; + } + + pVCLPopupMenu->SetItemCommand( nId, aCommand ); + + if ( bHeaderIsOn ) + pVCLPopupMenu->CheckItem( nId, sal_True ); + ++nId; + + // Check if all entries have the same state + if( bAllOneState && n && bHeaderIsOn != bLastCheck ) + bAllOneState = FALSE; + bLastCheck = bHeaderIsOn; + ++nCount; + } + } + } + + if ( bAllOneState && ( nCount > 1 )) + { + // Insert special item for all command + pVCLPopupMenu->InsertItem( ALL_MENUITEM_ID, String( FwlResId( STR_MENU_HEADFOOTALL )), 0, 0 ); + + rtl::OUStringBuffer aStrBuf( aCmd ); + aStrBuf.appendAscii( "?On:bool=" ); + + // Command depends on check state of first menu item entry + if ( !bFirstChecked ) + aStrBuf.appendAscii( "true" ); + else + aStrBuf.appendAscii( "false" ); + + pVCLPopupMenu->SetItemCommand( 1, aStrBuf.makeStringAndClear() ); + pVCLPopupMenu->InsertSeparator( 1 ); + } + } + } + catch ( com::sun::star::container::NoSuchElementException& ) + { + } + } +} + +// XEventListener +void SAL_CALL HeaderMenuController::disposing( const EventObject& ) throw ( RuntimeException ) +{ + Reference< css::awt::XMenuListener > xHolder(( OWeakObject *)this, UNO_QUERY ); + + ResetableGuard aLock( m_aLock ); + m_xFrame.clear(); + m_xDispatch.clear(); + m_xServiceManager.clear(); + + if ( m_xPopupMenu.is() ) + m_xPopupMenu->removeMenuListener( Reference< css::awt::XMenuListener >(( OWeakObject *)this, UNO_QUERY )); + m_xPopupMenu.clear(); +} + +// XStatusListener +void SAL_CALL HeaderMenuController::statusChanged( const FeatureStateEvent& Event ) throw ( RuntimeException ) +{ + Reference< com::sun::star::frame::XModel > xModel; + + if ( Event.State >>= xModel ) + { + ResetableGuard aLock( m_aLock ); + m_xModel = xModel; + if ( m_xPopupMenu.is() ) + fillPopupMenu( xModel, m_xPopupMenu ); + } +} + +// XMenuListener +void HeaderMenuController::impl_select(const Reference< XDispatch >& _xDispatch,const ::com::sun::star::util::URL& aTargetURL) +{ + Sequence<PropertyValue> aArgs; + if(::comphelper::UiEventsLogger::isEnabled()) //#i88653# + UiEventLogHelper(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(m_bFooter ? "FooterMenuController" : "HeaderMenuController"))).log(m_xServiceManager, m_xFrame, aTargetURL, aArgs); + OSL_ENSURE(_xDispatch.is(),"HeaderMenuController::impl_select: No dispatch"); + if ( _xDispatch.is() ) + _xDispatch->dispatch( aTargetURL, aArgs ); +} + +void SAL_CALL HeaderMenuController::updatePopupMenu() throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + Reference< com::sun::star::frame::XModel > xModel( m_xModel ); + aLock.unlock(); + + if ( !xModel.is() ) + PopupMenuControllerBase::updatePopupMenu(); + + aLock.lock(); + if ( m_xPopupMenu.is() && m_xModel.is() ) + fillPopupMenu( m_xModel, m_xPopupMenu ); +} + +} diff --git a/framework/source/uielement/imagebuttontoolbarcontroller.cxx b/framework/source/uielement/imagebuttontoolbarcontroller.cxx new file mode 100644 index 000000000000..d9af2fb4f9f9 --- /dev/null +++ b/framework/source/uielement/imagebuttontoolbarcontroller.cxx @@ -0,0 +1,236 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + +#ifndef __FRAMEWORK_UIELEMENT_IMAGEBUTTONTOOLBARCONTROLLER_HXX +#include "uielement/imagebuttontoolbarcontroller.hxx" +#endif + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <classes/addonsoptions.hxx> +#ifndef __FRAMEWORK_TOOLBAR_HXX_ +#include "uielement/toolbar.hxx" +#endif + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/frame/XControlNotificationListener.hpp> +#include "com/sun/star/util/XMacroExpander.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/beans/XPropertySet.hpp" + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ + +#include <rtl/uri.hxx> +#include <vos/mutex.hxx> +#include <comphelper/processfactory.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <tools/urlobj.hxx> +#include <vcl/svapp.hxx> +#include <vcl/mnemonic.hxx> +#include <vcl/window.hxx> +#include <vcl/graph.hxx> +#include <vcl/bitmap.hxx> +#include <svtools/filter.hxx> +#include <svtools/miscopt.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::util; + +#define EXPAND_PROTOCOL "vnd.sun.star.expand:" + +const ::Size aImageSizeSmall( 16, 16 ); +const ::Size aImageSizeBig( 26, 26 ); + +namespace framework +{ + +static uno::WeakReference< util::XMacroExpander > m_xMacroExpander; + +// ------------------------------------------------------------------ + +uno::Reference< util::XMacroExpander > GetMacroExpander() +{ + uno::Reference< util::XMacroExpander > xMacroExpander( m_xMacroExpander ); + if ( !xMacroExpander.is() ) + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + if ( !xMacroExpander.is() ) + { + uno::Reference< uno::XComponentContext > xContext; + uno::Reference< beans::XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), UNO_QUERY ); + xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext; + if ( xContext.is() ) + { + m_xMacroExpander = Reference< com::sun::star::util::XMacroExpander >( xContext->getValueByName( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/singletons/com.sun.star.util.theMacroExpander"))), + UNO_QUERY ); + xMacroExpander = m_xMacroExpander; + } + } + } + + return xMacroExpander; +} + +static void SubstituteVariables( ::rtl::OUString& aURL ) +{ + if ( aURL.compareToAscii( RTL_CONSTASCII_STRINGPARAM( EXPAND_PROTOCOL )) == 0 ) + { + uno::Reference< util::XMacroExpander > xMacroExpander = GetMacroExpander(); + + // cut protocol + rtl::OUString aMacro( aURL.copy( sizeof ( EXPAND_PROTOCOL ) -1 ) ); + // decode uric class chars + aMacro = ::rtl::Uri::decode( aMacro, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 ); + // expand macro string + aURL = xMacroExpander->expandMacros( aMacro ); + } +} + +// ------------------------------------------------------------------ + +ImageButtonToolbarController::ImageButtonToolbarController( + const Reference< XMultiServiceFactory >& rServiceManager, + const Reference< XFrame >& rFrame, + ToolBox* pToolbar, + USHORT nID, + const ::rtl::OUString& aCommand ) : + ComplexToolbarController( rServiceManager, rFrame, pToolbar, nID, aCommand ) +{ + sal_Bool bBigImages( SvtMiscOptions().AreCurrentSymbolsLarge() ); + sal_Bool bHiContrast( pToolbar->GetSettings().GetStyleSettings().GetHighContrastMode() ); + + Image aImage = AddonsOptions().GetImageFromURL( aCommand, bBigImages, bHiContrast, sal_True ); + + // Height will be controlled by scaling according to button height + m_pToolbar->SetItemImage( m_nID, aImage ); +} + +// ------------------------------------------------------------------ + +ImageButtonToolbarController::~ImageButtonToolbarController() +{ +} + +// ------------------------------------------------------------------ + +void SAL_CALL ImageButtonToolbarController::dispose() +throw ( RuntimeException ) +{ + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + ComplexToolbarController::dispose(); +} + +// ------------------------------------------------------------------ + +void ImageButtonToolbarController::executeControlCommand( const ::com::sun::star::frame::ControlCommand& rControlCommand ) +{ + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + // i73486 to be downward compatible use old and "wrong" also! + if (( rControlCommand.Command.equalsAsciiL( "SetImag", 7 )) || + ( rControlCommand.Command.equalsAsciiL( "SetImage", 8 )) ) + { + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "URL", 3 )) + { + rtl::OUString aURL; + rControlCommand.Arguments[i].Value >>= aURL; + + SubstituteVariables( aURL ); + + Image aImage; + if ( ReadImageFromURL( SvtMiscOptions().AreCurrentSymbolsLarge(), + aURL, + aImage )) + { + m_pToolbar->SetItemImage( m_nID, aImage ); + + // send notification + uno::Sequence< beans::NamedValue > aInfo( 1 ); + aInfo[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" )); + aInfo[0].Value <<= aURL; + addNotifyInfo( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ImageChanged" )), + getDispatchFromCommand( m_aCommandURL ), + aInfo ); + break; + } + } + } + } +} + +sal_Bool ImageButtonToolbarController::ReadImageFromURL( sal_Bool bBigImage, const ::rtl::OUString& aImageURL, Image& aImage ) +{ + SvStream* pStream = utl::UcbStreamHelper::CreateStream( aImageURL, STREAM_STD_READ ); + if ( pStream && ( pStream->GetErrorCode() == 0 )) + { + // Use graphic class to also support more graphic formats (bmp,png,...) + Graphic aGraphic; + + GraphicFilter* pGF = GraphicFilter::GetGraphicFilter(); + pGF->ImportGraphic( aGraphic, String(), *pStream, GRFILTER_FORMAT_DONTKNOW ); + + BitmapEx aBitmapEx = aGraphic.GetBitmapEx(); + + const ::Size aSize = bBigImage ? aImageSizeBig : aImageSizeSmall; // Sizes used for toolbar images + + ::Size aBmpSize = aBitmapEx.GetSizePixel(); + if ( aBmpSize.Width() > 0 && aBmpSize.Height() > 0 ) + { + ::Size aNoScaleSize( aBmpSize.Width(), aSize.Height() ); + if ( aBmpSize != aNoScaleSize ) + aBitmapEx.Scale( aNoScaleSize, BMP_SCALE_INTERPOLATE ); + aImage = Image( aBitmapEx ); + return sal_True; + } + } + + delete pStream; + return sal_False; +} + +} // namespace + diff --git a/framework/source/uielement/itemcontainer.cxx b/framework/source/uielement/itemcontainer.cxx new file mode 100644 index 000000000000..943a5abe2f03 --- /dev/null +++ b/framework/source/uielement/itemcontainer.cxx @@ -0,0 +1,266 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <uielement/itemcontainer.hxx> +#include <uielement/constitemcontainer.hxx> +#include <threadhelp/resetableguard.hxx> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ + +using namespace cppu; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::container; + +const char WRONG_TYPE_EXCEPTION[] = "Type must be com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >"; + +namespace framework +{ + +//***************************************************************************************************************** +// XInterface, XTypeProvider +//***************************************************************************************************************** + +ItemContainer::ItemContainer( const ShareableMutex& rMutex ) : + m_aShareMutex( rMutex ) +{ +} + + +ItemContainer::ItemContainer( const ConstItemContainer& rConstItemContainer, const ShareableMutex& rMutex ) : m_aShareMutex( rMutex ) +{ + copyItemContainer( rConstItemContainer.m_aItemVector, rMutex ); +} + +ItemContainer::ItemContainer( const Reference< XIndexAccess >& rSourceContainer, const ShareableMutex& rMutex ) : + m_aShareMutex( rMutex ) +{ + if ( rSourceContainer.is() ) + { + sal_Int32 nCount = rSourceContainer->getCount(); + try + { + for ( sal_Int32 i = 0; i < nCount; i++ ) + { + Sequence< PropertyValue > aPropSeq; + if ( rSourceContainer->getByIndex( i ) >>= aPropSeq ) + { + sal_Int32 nContainerIndex = -1; + Reference< XIndexAccess > xIndexAccess; + for ( sal_Int32 j = 0; j < aPropSeq.getLength(); j++ ) + { + if ( aPropSeq[j].Name.equalsAscii( "ItemDescriptorContainer" )) + { + aPropSeq[j].Value >>= xIndexAccess; + nContainerIndex = j; + break; + } + } + + if ( xIndexAccess.is() && nContainerIndex >= 0 ) + aPropSeq[nContainerIndex].Value <<= deepCopyContainer( xIndexAccess, rMutex ); + + m_aItemVector.push_back( aPropSeq ); + } + } + } + catch ( IndexOutOfBoundsException& ) + { + } + } +} + +ItemContainer::~ItemContainer() +{ +} + +// private +void ItemContainer::copyItemContainer( const std::vector< Sequence< PropertyValue > >& rSourceVector, const ShareableMutex& rMutex ) +{ + const sal_uInt32 nCount = rSourceVector.size(); + for ( sal_uInt32 i = 0; i < nCount; ++i ) + { + sal_Int32 nContainerIndex = -1; + Sequence< PropertyValue > aPropSeq( rSourceVector[i] ); + Reference< XIndexAccess > xIndexAccess; + for ( sal_Int32 j = 0; j < aPropSeq.getLength(); j++ ) + { + if ( aPropSeq[j].Name.equalsAscii( "ItemDescriptorContainer" )) + { + aPropSeq[j].Value >>= xIndexAccess; + nContainerIndex = j; + break; + } + } + + if ( xIndexAccess.is() && nContainerIndex >= 0 ) + aPropSeq[nContainerIndex].Value <<= deepCopyContainer( xIndexAccess, rMutex ); + + m_aItemVector.push_back( aPropSeq ); + } +} + +Reference< XIndexAccess > ItemContainer::deepCopyContainer( const Reference< XIndexAccess >& rSubContainer, const ShareableMutex& rMutex ) +{ + Reference< XIndexAccess > xReturn; + if ( rSubContainer.is() ) + { + ConstItemContainer* pSource = ConstItemContainer::GetImplementation( rSubContainer ); + ItemContainer* pSubContainer( 0 ); + if ( pSource ) + pSubContainer = new ItemContainer( *pSource, rMutex ); + else + pSubContainer = new ItemContainer( rSubContainer, rMutex ); + xReturn = Reference< XIndexAccess >( static_cast< OWeakObject* >( pSubContainer ), UNO_QUERY ); + } + + return xReturn; +} + +// XUnoTunnel +sal_Int64 ItemContainer::getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& rIdentifier ) throw(::com::sun::star::uno::RuntimeException) +{ + if( ( rIdentifier.getLength() == 16 ) && ( 0 == rtl_compareMemory( ItemContainer::GetUnoTunnelId().getConstArray(), rIdentifier.getConstArray(), 16 ) ) ) + return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >( this )); + + return 0; +} + +const Sequence< sal_Int8 >& ItemContainer::GetUnoTunnelId() throw() +{ + static ::com::sun::star::uno::Sequence< sal_Int8 > * pSeq = NULL; + if( !pSeq ) + { + ::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static ::com::sun::star::uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +ItemContainer* ItemContainer::GetImplementation( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rxIFace ) throw() +{ + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XUnoTunnel > xUT( rxIFace, ::com::sun::star::uno::UNO_QUERY ); + return xUT.is() ? reinterpret_cast< ItemContainer* >(sal::static_int_cast< sal_IntPtr >( + xUT->getSomething( ItemContainer::GetUnoTunnelId() ))) : NULL; +} + +// XElementAccess +sal_Bool SAL_CALL ItemContainer::hasElements() +throw ( RuntimeException ) +{ + ShareGuard aLock( m_aShareMutex ); + return ( !m_aItemVector.empty() ); +} + +// XIndexAccess +sal_Int32 SAL_CALL ItemContainer::getCount() +throw ( RuntimeException ) +{ + ShareGuard aLock( m_aShareMutex ); + return m_aItemVector.size(); +} + +Any SAL_CALL ItemContainer::getByIndex( sal_Int32 Index ) +throw ( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) +{ + ShareGuard aLock( m_aShareMutex ); + if ( sal_Int32( m_aItemVector.size()) > Index ) + return makeAny( m_aItemVector[Index] ); + else + throw IndexOutOfBoundsException( ::rtl::OUString(), (OWeakObject *)this ); +} + +// XIndexContainer +void SAL_CALL ItemContainer::insertByIndex( sal_Int32 Index, const Any& aItem ) +throw ( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) +{ + Sequence< PropertyValue > aSeq; + if ( aItem >>= aSeq ) + { + ShareGuard aLock( m_aShareMutex ); + if ( sal_Int32( m_aItemVector.size()) == Index ) + m_aItemVector.push_back( aSeq ); + else if ( sal_Int32( m_aItemVector.size()) >Index ) + { + std::vector< Sequence< PropertyValue > >::iterator aIter = m_aItemVector.begin(); + aIter += Index; + m_aItemVector.insert( aIter, aSeq ); + } + else + throw IndexOutOfBoundsException( ::rtl::OUString(), (OWeakObject *)this ); + } + else + throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( WRONG_TYPE_EXCEPTION )), + (OWeakObject *)this, 2 ); +} + +void SAL_CALL ItemContainer::removeByIndex( sal_Int32 Index ) +throw ( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) +{ + ShareGuard aLock( m_aShareMutex ); + if ( (sal_Int32)m_aItemVector.size() > Index ) + { + std::vector< Sequence< PropertyValue > >::iterator aIter = m_aItemVector.begin(); + aIter += Index; + m_aItemVector.erase( aIter ); + } + else + throw IndexOutOfBoundsException( ::rtl::OUString(), (OWeakObject *)this ); +} + +void SAL_CALL ItemContainer::replaceByIndex( sal_Int32 Index, const Any& aItem ) +throw ( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) +{ + Sequence< PropertyValue > aSeq; + if ( aItem >>= aSeq ) + { + ShareGuard aLock( m_aShareMutex ); + if ( sal_Int32( m_aItemVector.size()) > Index ) + m_aItemVector[Index] = aSeq; + else + throw IndexOutOfBoundsException( ::rtl::OUString(), (OWeakObject *)this ); + } + else + throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( WRONG_TYPE_EXCEPTION )), + (OWeakObject *)this, 2 ); +} + +} // namespace framework + diff --git a/framework/source/uielement/langselectionmenucontroller.cxx b/framework/source/uielement/langselectionmenucontroller.cxx new file mode 100644 index 000000000000..9c8e68e24734 --- /dev/null +++ b/framework/source/uielement/langselectionmenucontroller.cxx @@ -0,0 +1,436 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include <uielement/langselectionmenucontroller.hxx> + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <threadhelp/resetableguard.hxx> +#include "services.h" + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/awt/XDevice.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/awt/MenuItemStyle.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> + +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ + +#ifndef _VCL_MENU_HXX_ +#include <vcl/menu.hxx> +#endif +#include <vcl/svapp.hxx> +#include <vcl/i18nhelp.hxx> +#include <tools/urlobj.hxx> +#include <rtl/ustrbuf.hxx> +#ifndef _VCL_MNEMONIC_HXX_ +#include <vcl/mnemonic.hxx> +#endif +#include <com/sun/star/awt/XMenuExtended.hpp> +#include <comphelper/processfactory.hxx> + +#include <com/sun/star/document/XDocumentLanguages.hpp> +#include <com/sun/star/frame/XPopupMenuController.hpp> +#include <com/sun/star/linguistic2/XLanguageGuessing.hpp> +#include <map> +#include <i18npool/mslangid.hxx> +#include <svl/languageoptions.hxx> +#include <com/sun/star/awt/MenuItemStyle.hpp> +#include <svtools/langtab.hxx> +#include <classes/fwlresid.hxx> + +#ifndef __FRAMEWORK_CLASSES_RESOURCE_HRC_ +#include <classes/resource.hrc> +#endif +#include <dispatch/uieventloghelper.hxx> + +#include "helper/mischelper.hxx" + +//_________________________________________________________________________________________________________________ +// 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; + + +namespace framework +{ + +DEFINE_XSERVICEINFO_MULTISERVICE ( LanguageSelectionMenuController , + OWeakObject , + SERVICENAME_POPUPMENUCONTROLLER , + IMPLEMENTATIONNAME_LANGUAGESELECTIONMENUCONTROLLER + ) + +DEFINE_INIT_SERVICE ( LanguageSelectionMenuController, {} ) + +LanguageSelectionMenuController::LanguageSelectionMenuController( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ) : + PopupMenuControllerBase( xServiceManager ), + m_bShowMenu( sal_True ) + ,m_aLangGuessHelper(xServiceManager) +{ +} + +LanguageSelectionMenuController::~LanguageSelectionMenuController() +{ +} + +// XEventListener +void SAL_CALL LanguageSelectionMenuController::disposing( const EventObject& ) throw ( RuntimeException ) +{ + Reference< css::awt::XMenuListener > xHolder(( OWeakObject *)this, UNO_QUERY ); + + ResetableGuard aLock( m_aLock ); + m_xFrame.clear(); + m_xDispatch.clear(); + m_xLanguageDispatch.clear(); + m_xServiceManager.clear(); + + if ( m_xPopupMenu.is() ) + m_xPopupMenu->removeMenuListener( Reference< css::awt::XMenuListener >(( OWeakObject *)this, UNO_QUERY )); + m_xPopupMenu.clear(); +} + +// XStatusListener +void SAL_CALL LanguageSelectionMenuController::statusChanged( const FeatureStateEvent& Event ) throw ( RuntimeException ) +{ + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + if ( m_bDisposed ) + return; + + m_bShowMenu = sal_True; + m_nScriptType=7;//set the default value + + rtl::OUString aStrValue; + Sequence< ::rtl::OUString > aSeq; + + if ( Event.State >>= aStrValue ) + { + m_aCurrentLanguage=aStrValue; + } + else if ( Event.State >>= aSeq ) + { + if ( aSeq.getLength() == 4 ) + { + // Retrieve all other values from the sequence and + // store it members! + m_aCurLang=aSeq[0]; + m_nScriptType= static_cast< sal_Int16 >(aSeq[1].toInt32()); + m_aKeyboardLang=aSeq[2]; + m_aGuessedText=aSeq[3]; + } + } + else if ( !Event.State.hasValue() ) + { + m_bShowMenu = sal_False; // no language -> no sub-menu entries -> disable menu + } +} + +// XMenuListener +void LanguageSelectionMenuController::impl_select(const Reference< XDispatch >& _xDispatch,const ::com::sun::star::util::URL& aTargetURL) +{ + Reference< XDispatch > xDispatch = _xDispatch; + + if ( aTargetURL.Complete == m_aMenuCommandURL_Font ) + { //open format/character dialog for current selection + xDispatch = m_xMenuDispatch_Font; + } + else if ( aTargetURL.Complete == m_aMenuCommandURL_Lang ) + { //open language tab-page in tools/options dialog + xDispatch = m_xMenuDispatch_Lang; + } + else if ( aTargetURL.Complete == m_aMenuCommandURL_CharDlgForParagraph ) + { //open format/character dialog for current selection + xDispatch = m_xMenuDispatch_CharDlgForParagraph; + } + + if ( !xDispatch.is() ) + { + Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY ); + if ( xDispatchProvider.is() ) + xDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 ); + } + + if ( xDispatch.is() ) + { + Sequence<PropertyValue> aArgs; + if(::comphelper::UiEventsLogger::isEnabled()) //#i88653# + UiEventLogHelper(::rtl::OUString::createFromAscii("LanguageSelectionMenuController")).log(m_xServiceManager, m_xFrame, aTargetURL, aArgs); + xDispatch->dispatch( aTargetURL, aArgs ); + } +} + +// XPopupMenuController +void LanguageSelectionMenuController::impl_setPopupMenu() +{ + Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY ); + + com::sun::star::util::URL aTargetURL; + + // Register for language updates + aTargetURL.Complete = m_aLangStatusCommandURL; + m_xURLTransformer->parseStrict( aTargetURL ); + m_xLanguageDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 ); + + // Register for setting languages and opening language dialog + aTargetURL.Complete = m_aMenuCommandURL_Lang; + m_xURLTransformer->parseStrict( aTargetURL ); + m_xMenuDispatch_Lang = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 ); + + // Register for opening character dialog + aTargetURL.Complete = m_aMenuCommandURL_Font; + m_xURLTransformer->parseStrict( aTargetURL ); + m_xMenuDispatch_Font = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 ); + + // Register for opening character dialog with preselected paragraph + aTargetURL.Complete = m_aMenuCommandURL_CharDlgForParagraph; + m_xURLTransformer->parseStrict( aTargetURL ); + m_xMenuDispatch_CharDlgForParagraph = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 ); +} + +void LanguageSelectionMenuController::fillPopupMenu( Reference< css::awt::XPopupMenu >& rPopupMenu , const Mode eMode ) +{ + VCLXPopupMenu* pVCLPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( rPopupMenu ); + PopupMenu* pPopupMenu = 0; + + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + resetPopupMenu( rPopupMenu ); + if (!m_bShowMenu) + return; + + if ( pVCLPopupMenu ) + pPopupMenu = (PopupMenu *)pVCLPopupMenu->GetMenu(); + + String aCmd; + String aCmd_Dialog; + String aCmd_Language; + if( eMode == MODE_SetLanguageSelectionMenu ) + { + aCmd_Dialog+=String::CreateFromAscii(".uno:FontDialog?Language:string=*"); + aCmd_Language+=String::CreateFromAscii(".uno:LanguageStatus?Language:string=Current_"); + } + else if ( eMode == MODE_SetLanguageParagraphMenu ) + { + aCmd_Dialog+=String::CreateFromAscii(".uno:FontDialogForParagraph"); + aCmd_Language+=String::CreateFromAscii(".uno:LanguageStatus?Language:string=Paragraph_"); + } + else if ( eMode == MODE_SetLanguageAllTextMenu ) + { + aCmd_Dialog+=String::CreateFromAscii(".uno:LanguageStatus?Language:string=*"); + aCmd_Language+=String::CreateFromAscii(".uno:LanguageStatus?Language:string=Default_"); + } + + //Reference< awt::XMenuExtended > m_xMenuExtended( m_xPopupMenu, UNO_QUERY ); + std::map< ::rtl::OUString, ::rtl::OUString > LangItems; + + SvtLanguageTable aLanguageTable; + USHORT nItemId = 1; + + //1--add current language + if(m_aCurLang.getLength()) + { + LangItems[m_aCurLang]=m_aCurLang; + } + + SvtLanguageTable aLangTable; + //2--System + const AllSettings& rAllSettings=Application::GetSettings(); + LanguageType rSystemLanguage = rAllSettings.GetLanguage(); + if(rSystemLanguage!=LANGUAGE_DONTKNOW) + { + if (IsScriptTypeMatchingToLanguage(m_nScriptType,rSystemLanguage )) + LangItems[::rtl::OUString(aLangTable.GetString(rSystemLanguage))]=::rtl::OUString(aLangTable.GetString(rSystemLanguage)); + } + + //3--UI + LanguageType rUILanguage = rAllSettings.GetUILanguage(); + if(rUILanguage!=LANGUAGE_DONTKNOW) + { + if (IsScriptTypeMatchingToLanguage(m_nScriptType, rUILanguage )) + LangItems[::rtl::OUString(aLangTable.GetString(rUILanguage))]=::rtl::OUString(aLangTable.GetString(rUILanguage)); + } + + //4--guessed language + uno::Reference< linguistic2::XLanguageGuessing > xLangGuesser( m_aLangGuessHelper.GetGuesser() ); + if (xLangGuesser.is() && m_aGuessedText.getLength() > 0) + { + ::com::sun::star::lang::Locale aLocale(xLangGuesser->guessPrimaryLanguage( m_aGuessedText, 0, m_aGuessedText.getLength()) ); + LanguageType nLang = MsLangId::convertLocaleToLanguageWithFallback( aLocale ); + if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_NONE && nLang != LANGUAGE_SYSTEM + && IsScriptTypeMatchingToLanguage( m_nScriptType, nLang )) + LangItems[aLangTable.GetString(nLang)]=aLangTable.GetString(nLang); + } + + //5--keyboard language + if(m_aKeyboardLang!=::rtl::OUString::createFromAscii("")) + { + if (IsScriptTypeMatchingToLanguage(m_nScriptType, aLanguageTable.GetType(m_aKeyboardLang))) + LangItems[m_aKeyboardLang] = m_aKeyboardLang; + } + + //6--all languages used in current document + Reference< com::sun::star::frame::XModel > xModel; + if ( m_xFrame.is() ) + { + Reference< com::sun::star::frame::XController > xController( m_xFrame->getController(), UNO_QUERY ); + if ( xController.is() ) + xModel = xController->getModel(); + } + Reference< document::XDocumentLanguages > xDocumentLanguages( xModel, UNO_QUERY ); + /*the description of m_nScriptType + LATIN : 1 + ASIAN : 2 + COMPLEX:4 + LATIN + ASIAN : 3 + LATIN + COMPLEX : 5 + ASIAN + COMPLEX : 6 + LATIN + ASIAN + COMPLEX : 7 + */ + + sal_Int16 nCount=7; + if(xDocumentLanguages.is()) + { + Sequence< Locale > rLocales(xDocumentLanguages->getDocumentLanguages(m_nScriptType,nCount)); + if(rLocales.getLength()>0) + { + for(USHORT i = 0; i<rLocales.getLength();++i) + { + if (LangItems.size()==7) + break; + const Locale& rLocale=rLocales[i]; + if(IsScriptTypeMatchingToLanguage(m_nScriptType, aLanguageTable.GetType(rLocale.Language))) + LangItems[rLocale.Language] = rLocale.Language; + } + } + } + std::map< sal_Int16, ::rtl::OUString > LangTable; + + const ::rtl::OUString sAsterix(RTL_CONSTASCII_USTRINGPARAM("*")); + for(std::map< ::rtl::OUString, ::rtl::OUString >::const_iterator it = LangItems.begin(); it != LangItems.end(); ++it) + { + if(it->first != ::rtl::OUString( aLangTable.GetString( LANGUAGE_NONE ) )&& + it->first != sAsterix && + it->first.getLength()) + { + ++nItemId; + pPopupMenu->InsertItem( nItemId,it->first); + LangTable[nItemId] = it->first; + if(it->first == m_aCurLang && eMode == MODE_SetLanguageSelectionMenu ) + { + //make a sign for the current language + pPopupMenu->CheckItem(nItemId,TRUE); + } + aCmd=aCmd_Language; + aCmd+=(String)it->first; + pPopupMenu->SetItemCommand(nItemId,aCmd); + } + } + + //7--none + nItemId++; + pPopupMenu->InsertItem( nItemId, String(FwlResId( STR_LANGSTATUS_NONE )) ); + aCmd=aCmd_Language; + aCmd+=String::CreateFromAscii("LANGUAGE_NONE"); + pPopupMenu->SetItemCommand(nItemId,aCmd); + + //More... + nItemId++; + pPopupMenu->InsertItem( nItemId, String(FwlResId( STR_LANGSTATUS_MORE ))); + pPopupMenu->SetItemCommand(nItemId,aCmd_Dialog); +} + + +void SAL_CALL LanguageSelectionMenuController::updatePopupMenu() throw ( ::com::sun::star::uno::RuntimeException ) +{ + PopupMenuControllerBase::updatePopupMenu(); + + // Force status update to get information about the current languages + ResetableGuard aLock( m_aLock ); + Reference< XDispatch > xDispatch( m_xLanguageDispatch ); + com::sun::star::util::URL aTargetURL; + aTargetURL.Complete = m_aLangStatusCommandURL; + m_xURLTransformer->parseStrict( aTargetURL ); + aLock.unlock(); + + if ( xDispatch.is() ) + { + xDispatch->addStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL ); + xDispatch->removeStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL ); + } + + // TODO: Fill menu with the information retrieved by the status update + + if( m_aCommandURL.equalsAscii( ".uno:SetLanguageSelectionMenu" )) + { + fillPopupMenu(m_xPopupMenu, MODE_SetLanguageSelectionMenu ); + } + else if( m_aCommandURL.equalsAscii( ".uno:SetLanguageParagraphMenu" )) + { + fillPopupMenu(m_xPopupMenu, MODE_SetLanguageParagraphMenu ); + } + else if( m_aCommandURL.equalsAscii( ".uno:SetLanguageAllTextMenu" )) + { + fillPopupMenu(m_xPopupMenu, MODE_SetLanguageAllTextMenu ); + } +} + +// XInitialization +void SAL_CALL LanguageSelectionMenuController::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException ) +{ + ResetableGuard aLock( m_aLock ); + + sal_Bool bInitalized( m_bInitialized ); + if ( !bInitalized ) + { + PopupMenuControllerBase::initialize(aArguments); + + if ( m_bInitialized ) + { + m_aLangStatusCommandURL = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:LanguageStatus" )); + m_aMenuCommandURL_Lang = m_aLangStatusCommandURL; + m_aMenuCommandURL_Font = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:FontDialog" )); + m_aMenuCommandURL_CharDlgForParagraph = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:FontDialogForParagraph" )); + } + } +} + +} + diff --git a/framework/source/uielement/langselectionstatusbarcontroller.cxx b/framework/source/uielement/langselectionstatusbarcontroller.cxx new file mode 100644 index 000000000000..953470314785 --- /dev/null +++ b/framework/source/uielement/langselectionstatusbarcontroller.cxx @@ -0,0 +1,487 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include <uielement/langselectionstatusbarcontroller.hxx> +#include <classes/fwkresid.hxx> +#include <services.h> +#include <classes/resource.hrc> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> +#include <vcl/window.hxx> +#include <vcl/status.hxx> +#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ +#include <toolkit/unohlp.hxx> +#endif +#include <toolkit/helper/convert.hxx> + +#include <com/sun/star/frame/XPopupMenuController.hpp> +#include <toolkit/helper/vclunohelper.hxx> +#include <com/sun/star/awt/PopupMenuDirection.hpp> +#include <svtools/langtab.hxx> +#include "sal/types.h" +#include <vcl/svapp.hxx> +#include <com/sun/star/awt/MenuItemStyle.hpp> +#include <com/sun/star/document/XDocumentLanguages.hpp> +#include <i18npool/mslangid.hxx> +#include <com/sun/star/i18n/ScriptType.hpp> +#include <com/sun/star/frame/XModule.hpp> +#include <com/sun/star/frame/XModel.hpp> + +#include <map> +#include <set> +#include <classes/fwkresid.hxx> +#ifndef __FRAMEWORK_CLASSES_RESOURCE_HRC_ +#include <classes/resource.hrc> +#endif +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <comphelper/processfactory.hxx> + +#include <toolkit/unohlp.hxx> +#include <tools/gen.hxx> +#include <com/sun/star/awt/Command.hpp> +#include <svl/languageoptions.hxx> +#include <com/sun/star/linguistic2/XLanguageGuessing.hpp> +#include <dispatch/uieventloghelper.hxx> + +#include "helper/mischelper.hxx" + +using namespace ::cppu; +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::i18n; +using namespace ::com::sun::star::document; + +namespace framework +{ + +DEFINE_XSERVICEINFO_MULTISERVICE ( LangSelectionStatusbarController , + OWeakObject , + SERVICENAME_STATUSBARCONTROLLER , + IMPLEMENTATIONNAME_LANGSELECTIONSTATUSBARCONTROLLER + ) + +DEFINE_INIT_SERVICE ( LangSelectionStatusbarController, {} ) + +LangSelectionStatusbarController::LangSelectionStatusbarController( const uno::Reference< lang::XMultiServiceFactory >& xServiceManager ) : + svt::StatusbarController( xServiceManager, uno::Reference< frame::XFrame >(), rtl::OUString(), 0 ), + m_bShowMenu( sal_True ), + m_nScriptType( 7 ) + ,m_aLangGuessHelper(xServiceManager) +{ +} + +// XInterface +Any SAL_CALL LangSelectionStatusbarController::queryInterface( const Type& rType ) +throw ( RuntimeException ) +{ + return svt::StatusbarController::queryInterface( rType ); +} + +void SAL_CALL LangSelectionStatusbarController::acquire() throw () +{ + svt::StatusbarController::acquire(); +} + +void SAL_CALL LangSelectionStatusbarController::release() throw () +{ + svt::StatusbarController::release(); +} + +void SAL_CALL LangSelectionStatusbarController::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) +throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::initialize" ); + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + svt::StatusbarController::initialize( aArguments ); + + if ( m_xParentWindow.is() && m_nID > 0 ) + { + Window* pWindow = VCLUnoHelper::GetWindow( m_xParentWindow ); + if ( pWindow && ( pWindow->GetType() == WINDOW_STATUSBAR )) + { + StatusBar* pStatusBar = (StatusBar *)pWindow; + pStatusBar->SetItemText( m_nID, FwkResId( STR_LANGSTATUS_MULTIPLE_LANGUAGES ) ); + } + } +} + +// XComponent +void SAL_CALL LangSelectionStatusbarController::dispose() +throw (::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::dispose" ); + svt::StatusbarController::dispose(); +} + +// XEventListener +void SAL_CALL LangSelectionStatusbarController::disposing( const com::sun::star::lang::EventObject& Source ) +throw ( RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::disposing" ); + svt::StatusbarController::disposing( Source ); +} + +// XStatusbarController +::sal_Bool SAL_CALL LangSelectionStatusbarController::mouseButtonDown( + const ::com::sun::star::awt::MouseEvent& ) +throw (::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::mouseButtonDown" ); + return sal_False; +} + +::sal_Bool SAL_CALL LangSelectionStatusbarController::mouseMove( + const ::com::sun::star::awt::MouseEvent& ) +throw (::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::mouseMove" ); + return sal_False; +} + +::sal_Bool SAL_CALL LangSelectionStatusbarController::mouseButtonUp( + const ::com::sun::star::awt::MouseEvent& ) +throw (::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::mouseButtonUp" ); + return sal_False; +} + +void LangSelectionStatusbarController::LangMenu()throw (::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::LangMenu" ); + if (!m_bShowMenu) + return; + + //add context menu + const static ::rtl::OUString s_sPopupMenu(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.PopupMenu")); + Reference< awt::XPopupMenu > xPopupMenu( m_xServiceManager->createInstance( s_sPopupMenu ), UNO_QUERY ); + //sub menu that contains all items except the last two items: Separator + Set Language for Paragraph + Reference< awt::XPopupMenu > subPopupMenu(m_xServiceManager->createInstance( s_sPopupMenu ), UNO_QUERY ); + + std::set< ::rtl::OUString > LangItems; + + SvtLanguageTable aLanguageTable; + USHORT nItemId=1; + + //1--add current language + if( m_aCurLang != ::rtl::OUString( ) && + LANGUAGE_DONTKNOW != aLanguageTable.GetType( m_aCurLang )) + LangItems.insert( m_aCurLang ); + + //2--System + SvtLanguageTable aLangTable; + const AllSettings& rAllSettings = Application::GetSettings(); + LanguageType rSystemLanguage = rAllSettings.GetLanguage(); + if( rSystemLanguage != LANGUAGE_DONTKNOW ) + { + if ( IsScriptTypeMatchingToLanguage( m_nScriptType, rSystemLanguage )) + LangItems.insert( ::rtl::OUString( aLangTable.GetString( rSystemLanguage )) ); + } + + //3--UI + LanguageType rUILanguage = rAllSettings.GetUILanguage(); + if( rUILanguage != LANGUAGE_DONTKNOW ) + { + if ( IsScriptTypeMatchingToLanguage( m_nScriptType, rUILanguage )) + LangItems.insert( ::rtl::OUString( aLangTable.GetString( rUILanguage )) ); + } + + //4--guessed language + uno::Reference< linguistic2::XLanguageGuessing > xLangGuesser( m_aLangGuessHelper.GetGuesser() ); + if ( xLangGuesser.is() && m_aGuessedText.getLength() > 0) + { + ::com::sun::star::lang::Locale aLocale(xLangGuesser->guessPrimaryLanguage( m_aGuessedText, 0, m_aGuessedText.getLength()) ); + LanguageType nLang = MsLangId::convertLocaleToLanguageWithFallback( aLocale ); + if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_NONE && nLang != LANGUAGE_SYSTEM + && IsScriptTypeMatchingToLanguage( m_nScriptType, nLang )) + LangItems.insert( aLangTable.GetString( nLang )); + } + + //5--keyboard language + if( m_aKeyboardLang != ::rtl::OUString::createFromAscii( "" )) + { + if ( IsScriptTypeMatchingToLanguage( m_nScriptType, aLanguageTable.GetType( m_aKeyboardLang ))) + LangItems.insert( m_aKeyboardLang ); + } + + //6--all languages used in current document + Reference< com::sun::star::frame::XModel > xModel; + if ( m_xFrame.is() ) + { + Reference< com::sun::star::frame::XController > xController( m_xFrame->getController(), UNO_QUERY ); + if ( xController.is() ) + xModel = xController->getModel(); + } + Reference< document::XDocumentLanguages > xDocumentLanguages( xModel, UNO_QUERY ); + /*the description of m_nScriptType + LATIN : 1 + ASIAN : 2 + COMPLEX:4 + LATIN + ASIAN : 3 + LATIN + COMPLEX : 5 + ASIAN + COMPLEX : 6 + LATIN + ASIAN + COMPLEX : 7 + */ + + sal_Int16 nCount=7; + if ( xDocumentLanguages.is() ) + { + Sequence< Locale > rLocales( xDocumentLanguages->getDocumentLanguages( m_nScriptType, nCount )); + if ( rLocales.getLength() > 0 ) + { + for ( USHORT i = 0; i<rLocales.getLength();++i ) + { + if ( LangItems.size() == 7 ) + break; + const Locale& rLocale=rLocales[i]; + if( IsScriptTypeMatchingToLanguage( m_nScriptType, aLangTable.GetType( rLocale.Language ))) + LangItems.insert( ::rtl::OUString( rLocale.Language ) ); + } + } + } + std::map< sal_Int16, ::rtl::OUString > LangTable; + + for( std::set< ::rtl::OUString >::const_iterator it = LangItems.begin(); it != LangItems.end(); ++it ) + { + if ( *it != ::rtl::OUString( aLangTable.GetString( LANGUAGE_NONE ) )&& + *it != ::rtl::OUString::createFromAscii( "*" ) && + *it != ::rtl::OUString::createFromAscii( "" )) + { + //nItemId = xPopupMenu->getItemCount()+1; + nItemId++; + xPopupMenu->insertItem( nItemId, *it, css::awt::MenuItemStyle::RADIOCHECK, nItemId ); + LangTable[nItemId]=*it; + if( *it == m_aCurLang ) + { + //make a sign for the current language + xPopupMenu->checkItem( nItemId, TRUE ); + } + } + } + + //7--none + nItemId++; + xPopupMenu->insertItem( nItemId, String( FwkResId( STR_LANGSTATUS_NONE )), css::awt::MenuItemStyle::RADIOCHECK, nItemId ); + //More... + nItemId++; + xPopupMenu->insertItem( nItemId, String( FwkResId( STR_LANGSTATUS_MORE )), css::awt::MenuItemStyle::RADIOCHECK, nItemId ); + + for( ::std::set< ::rtl::OUString >::const_iterator it = LangItems.begin(); it != LangItems.end(); ++it ) + { + if( *it != ::rtl::OUString( aLangTable.GetString( LANGUAGE_NONE ) )&& + *it != ::rtl::OUString::createFromAscii( "*" ) && + *it != ::rtl::OUString::createFromAscii( "" )) + { + nItemId++; + subPopupMenu->insertItem( nItemId, *it, css::awt::MenuItemStyle::RADIOCHECK, nItemId ); + LangTable[nItemId]=*it; + } + } + //7--none + nItemId++; + subPopupMenu->insertItem( nItemId, String( FwkResId( STR_LANGSTATUS_NONE )), css::awt::MenuItemStyle::RADIOCHECK, nItemId ); + //More + nItemId++; + subPopupMenu->insertItem( nItemId, String( FwkResId( STR_LANGSTATUS_MORE )), css::awt::MenuItemStyle::RADIOCHECK, nItemId ); + + nItemId++; + xPopupMenu->insertSeparator(nItemId); + + nItemId++; + xPopupMenu->insertItem( nItemId, String( FwkResId( STR_SET_LANGUAGE_FOR_PARAGRAPH )), css::awt::MenuItemStyle::RADIOCHECK, nItemId ); + xPopupMenu->setPopupMenu( nItemId, subPopupMenu ); + + //display the popup menu and execute every command + + Reference< awt::XWindowPeer > xParent( m_xParentWindow, UNO_QUERY ); + + com::sun::star::awt::Rectangle mRectangle; + Window* pWindow = VCLUnoHelper::GetWindow( m_xParentWindow ); + const Point mMousePos = pWindow->GetPointerPosPixel(); + mRectangle.X = mMousePos.X(); + mRectangle.Y = mMousePos.Y(); + sal_Int16 nId = xPopupMenu->execute( xParent, mRectangle, com::sun::star::awt::PopupMenuDirection::EXECUTE_UP+16 ); + //click "More..." + if ( nId && m_xFrame.is() ) + { + uno::Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY ); + util::URL aURL; + + if ( nId < nItemId-3-subPopupMenu->getItemCount() ) + { + //1..7 + //set selected language as current language for selection + String SelectedLang = LangTable[nId]; + aURL.Complete+=String::CreateFromAscii(".uno:LanguageStatus?Language:string=Current_"); + aURL.Complete+=SelectedLang; + } + else if ( nId == nItemId-3-subPopupMenu->getItemCount() ) + { + //8 + //set None as current language for selection + aURL.Complete+=String::CreateFromAscii(".uno:LanguageStatus?Language:string=Current_LANGUAGE_NONE"); + } + else if ( nId == nItemId-2-subPopupMenu->getItemCount() ) + { + //9 (more)... + //open the dialog "format/character" for current selection + aURL.Complete+=String::CreateFromAscii(".uno:FontDialog?Language:string=*"); + } + else if ( nId < nItemId-3 && nId>nItemId-2-subPopupMenu->getItemCount() ) + { + //1..7 para + //set selected language for current paragraph + String SelectedLang = LangTable[nId]; + aURL.Complete+=String::CreateFromAscii(".uno:LanguageStatus?Language:string=Paragraph_"); + aURL.Complete+=SelectedLang; + } + else if ( nId==nItemId-3 ) + { + //8 para + //set None as language for current paragraph + aURL.Complete+=String::CreateFromAscii(".uno:LanguageStatus?Language:string=Paragraph_LANGUAGE_NONE"); + } + else if ( nId==nItemId-2 ) + { + //9 (more) para... + //open the dialog "format/character" for current paragraph + aURL.Complete+=String::CreateFromAscii(".uno:FontDialogForParagraph"); + } + + uno::Reference< util::XURLTransformer > xURLTransformer( m_xServiceManager->createInstance( rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" )), uno::UNO_QUERY ); + xURLTransformer->parseStrict( aURL ); + uno::Reference< XDispatch > xDispatch = xDispatchProvider->queryDispatch(aURL,::rtl::OUString(),0); + if( xDispatch.is() ) + { + uno::Sequence< beans::PropertyValue > aPV; + if(::comphelper::UiEventsLogger::isEnabled()) //#i88653# + UiEventLogHelper(::rtl::OUString::createFromAscii("ButtonToolbarController")).log(m_xServiceManager, m_xFrame, aURL, aPV); + xDispatch->dispatch( aURL, aPV); + } + } +} + +void SAL_CALL LangSelectionStatusbarController::command( + const ::com::sun::star::awt::Point& /*aPos*/, + ::sal_Int32 nCommand, + ::sal_Bool /*bMouseEvent*/, + const ::com::sun::star::uno::Any& /*aData*/ ) +throw (::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::command" ); + if ( nCommand & ::awt::Command::CONTEXTMENU ) + { + LangMenu(); + } +} + +void SAL_CALL LangSelectionStatusbarController::paint( + const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics >& xGraphics, + const ::com::sun::star::awt::Rectangle& rOutputRectangle, + ::sal_Int32 nItemId, + ::sal_Int32 nStyle ) +throw (::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::paint" ); + svt::StatusbarController::paint( xGraphics, rOutputRectangle, nItemId, nStyle ); +} + +void SAL_CALL LangSelectionStatusbarController::click() +throw (::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::click" ); + LangMenu(); +} + +void SAL_CALL LangSelectionStatusbarController::doubleClick() +throw (::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::doubleClick" ); + svt::StatusbarController::doubleClick(); +} + +// XStatusListener +void SAL_CALL LangSelectionStatusbarController::statusChanged( const FeatureStateEvent& Event ) +throw ( RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::statusChanged" ); + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + if ( m_bDisposed ) + return; + + m_bShowMenu = sal_True; + + m_nScriptType=7;//set the default value + Window* pWindow = VCLUnoHelper::GetWindow( m_xParentWindow ); + if ( pWindow && pWindow->GetType() == WINDOW_STATUSBAR && m_nID != 0 ) + { + rtl::OUString aStrValue; + Sequence< ::rtl::OUString > aSeq; + + StatusBar* pStatusBar = (StatusBar *)pWindow; + if ( Event.State >>= aStrValue ) + { + pStatusBar->SetItemText( m_nID, aStrValue ); + m_aCurrentLanguage = aStrValue; + } + else if ( Event.State >>= aSeq ) + { + if ( aSeq.getLength() == 4 ) + { + const String aMultipleLangText( FwkResId( STR_LANGSTATUS_MULTIPLE_LANGUAGES ) ); + ::rtl::OUString aStatusText = aSeq[0]; + if ( 0 == aStatusText.compareToAscii( "*" )) + aStatusText = aMultipleLangText; + pStatusBar->SetItemText( m_nID, aStatusText ); + + // Retrieve all other values from the sequence and + // store it members! + m_aCurLang = aSeq[0]; + m_nScriptType = static_cast< sal_Int16 >( aSeq[1].toInt32() ); + m_aKeyboardLang = aSeq[2]; + m_aGuessedText = aSeq[3]; + } + } + else if ( !Event.State.hasValue() ) + { + pStatusBar->SetItemText( m_nID, String() ); + m_bShowMenu = sal_False; // no language -> no menu + } + } +} + +} + diff --git a/framework/source/uielement/logoimagestatusbarcontroller.cxx b/framework/source/uielement/logoimagestatusbarcontroller.cxx new file mode 100644 index 000000000000..10dc8489e592 --- /dev/null +++ b/framework/source/uielement/logoimagestatusbarcontroller.cxx @@ -0,0 +1,177 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include <uielement/logoimagestatusbarcontroller.hxx> +#include <classes/fwlresid.hxx> +#include <services.h> +#include <classes/resource.hrc> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> +#include <vcl/window.hxx> +#include <vcl/status.hxx> +#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ +#include <toolkit/unohlp.hxx> +#endif +#include <toolkit/helper/convert.hxx> + +using namespace ::rtl; +using namespace ::cppu; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; + +namespace framework +{ + +DEFINE_XSERVICEINFO_MULTISERVICE ( LogoImageStatusbarController , + OWeakObject , + SERVICENAME_STATUSBARCONTROLLER , + IMPLEMENTATIONNAME_LOGOIMAGESTATUSBARCONTROLLER + ) + +DEFINE_INIT_SERVICE ( LogoImageStatusbarController, {} ) + +LogoImageStatusbarController::LogoImageStatusbarController( const uno::Reference< lang::XMultiServiceFactory >& xServiceManager ) : + svt::StatusbarController( xServiceManager, uno::Reference< frame::XFrame >(), rtl::OUString(), 0 ) +{ + Image aImage( FwlResId( RID_IMAGE_STATUSBAR_LOGO )); + m_aLogoImage = aImage; +} + +LogoImageStatusbarController::~LogoImageStatusbarController() +{ +} + +// XInterface +Any SAL_CALL LogoImageStatusbarController::queryInterface( const Type& rType ) +throw ( RuntimeException ) +{ + return svt::StatusbarController::queryInterface( rType ); +} + +void SAL_CALL LogoImageStatusbarController::acquire() throw () +{ + svt::StatusbarController::acquire(); +} + +void SAL_CALL LogoImageStatusbarController::release() throw () +{ + svt::StatusbarController::release(); +} + +void SAL_CALL LogoImageStatusbarController::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) +throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + svt::StatusbarController::initialize( aArguments ); +} + +// XComponent +void SAL_CALL LogoImageStatusbarController::dispose() +throw (::com::sun::star::uno::RuntimeException) +{ + svt::StatusbarController::dispose(); +} + +// XEventListener +void SAL_CALL LogoImageStatusbarController::disposing( const EventObject& Source ) +throw ( RuntimeException ) +{ + svt::StatusbarController::disposing( Source ); +} + +// XStatusListener +void SAL_CALL LogoImageStatusbarController::statusChanged( const FeatureStateEvent& ) +throw ( RuntimeException ) +{ +} + +// XStatusbarController +::sal_Bool SAL_CALL LogoImageStatusbarController::mouseButtonDown( + const awt::MouseEvent& ) +throw (::com::sun::star::uno::RuntimeException) +{ + return sal_False; +} + +::sal_Bool SAL_CALL LogoImageStatusbarController::mouseMove( + const awt::MouseEvent& ) +throw (::com::sun::star::uno::RuntimeException) +{ + return sal_False; +} + +::sal_Bool SAL_CALL LogoImageStatusbarController::mouseButtonUp( + const awt::MouseEvent& ) +throw (::com::sun::star::uno::RuntimeException) +{ + return sal_False; +} + +void SAL_CALL LogoImageStatusbarController::command( + const awt::Point& aPos, + ::sal_Int32 nCommand, + ::sal_Bool bMouseEvent, + const ::com::sun::star::uno::Any& aData ) +throw (::com::sun::star::uno::RuntimeException) +{ + svt::StatusbarController::command( aPos, nCommand, bMouseEvent, aData ); +} + +void SAL_CALL LogoImageStatusbarController::paint( + const ::com::sun::star::uno::Reference< awt::XGraphics >& xGraphics, + const awt::Rectangle& rOutputRectangle, + ::sal_Int32 /*nItemId*/, + ::sal_Int32 /*nStyle*/ ) +throw (::com::sun::star::uno::RuntimeException) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + OutputDevice* pOutDev = VCLUnoHelper::GetOutputDevice( xGraphics );; + if ( pOutDev ) + { + ::Rectangle aRect = VCLRectangle( rOutputRectangle ); + pOutDev->DrawImage( aRect.TopLeft(), aRect.GetSize(), m_aLogoImage ); + } +} + +void SAL_CALL LogoImageStatusbarController::click() +throw (::com::sun::star::uno::RuntimeException) +{ + svt::StatusbarController::click(); +} + +void SAL_CALL LogoImageStatusbarController::doubleClick() throw (::com::sun::star::uno::RuntimeException) +{ + svt::StatusbarController::doubleClick(); +} + +} diff --git a/framework/source/uielement/logotextstatusbarcontroller.cxx b/framework/source/uielement/logotextstatusbarcontroller.cxx new file mode 100644 index 000000000000..606c644eeba9 --- /dev/null +++ b/framework/source/uielement/logotextstatusbarcontroller.cxx @@ -0,0 +1,180 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include <uielement/logotextstatusbarcontroller.hxx> +#include <classes/fwlresid.hxx> +#include <services.h> +#include <classes/resource.hrc> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> +#include <vcl/window.hxx> +#include <vcl/status.hxx> +#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ +#include <toolkit/unohlp.hxx> +#endif +#include <toolkit/helper/convert.hxx> + +using namespace ::rtl; +using namespace ::cppu; +using namespace ::com::sun::star; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; + +namespace framework +{ + +DEFINE_XSERVICEINFO_MULTISERVICE ( LogoTextStatusbarController , + OWeakObject , + SERVICENAME_STATUSBARCONTROLLER , + IMPLEMENTATIONNAME_LOGOTEXTSTATUSBARCONTROLLER + ) + +DEFINE_INIT_SERVICE ( LogoTextStatusbarController, {} ) + +LogoTextStatusbarController::LogoTextStatusbarController( const uno::Reference< lang::XMultiServiceFactory >& xServiceManager ) : + svt::StatusbarController( xServiceManager, uno::Reference< frame::XFrame >(), rtl::OUString(), 0 ) +{ + m_aLogoText = String( FwlResId( STR_STATUSBAR_LOGOTEXT )); +} + +LogoTextStatusbarController::~LogoTextStatusbarController() +{ +} + +// XInterface +Any SAL_CALL LogoTextStatusbarController::queryInterface( const Type& rType ) +throw ( RuntimeException ) +{ + return svt::StatusbarController::queryInterface( rType ); +} + +void SAL_CALL LogoTextStatusbarController::acquire() throw () +{ + svt::StatusbarController::acquire(); +} + +void SAL_CALL LogoTextStatusbarController::release() throw () +{ + svt::StatusbarController::release(); +} + +void SAL_CALL LogoTextStatusbarController::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) +throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + svt::StatusbarController::initialize( aArguments ); + + if ( m_xParentWindow.is() && m_nID > 0 ) + { + Window* pWindow = VCLUnoHelper::GetWindow( m_xParentWindow ); + if ( pWindow && ( pWindow->GetType() == WINDOW_STATUSBAR )) + { + StatusBar* pStatusBar = (StatusBar *)pWindow; + pStatusBar->SetItemText( m_nID, m_aLogoText ); + } + } +} + +// XComponent +void SAL_CALL LogoTextStatusbarController::dispose() +throw (::com::sun::star::uno::RuntimeException) +{ + svt::StatusbarController::dispose(); +} + +// XEventListener +void SAL_CALL LogoTextStatusbarController::disposing( const EventObject& Source ) +throw ( RuntimeException ) +{ + svt::StatusbarController::disposing( Source ); +} + +// XStatusListener +void SAL_CALL LogoTextStatusbarController::statusChanged( const FeatureStateEvent& ) +throw ( RuntimeException ) +{ +} + +// XStatusbarController +::sal_Bool SAL_CALL LogoTextStatusbarController::mouseButtonDown( + const ::com::sun::star::awt::MouseEvent& ) +throw (::com::sun::star::uno::RuntimeException) +{ + return sal_False; +} + +::sal_Bool SAL_CALL LogoTextStatusbarController::mouseMove( + const ::com::sun::star::awt::MouseEvent& ) +throw (::com::sun::star::uno::RuntimeException) +{ + return sal_False; +} + +::sal_Bool SAL_CALL LogoTextStatusbarController::mouseButtonUp( + const ::com::sun::star::awt::MouseEvent& ) +throw (::com::sun::star::uno::RuntimeException) +{ + return sal_False; +} + +void SAL_CALL LogoTextStatusbarController::command( + const ::com::sun::star::awt::Point& aPos, + ::sal_Int32 nCommand, + ::sal_Bool bMouseEvent, + const ::com::sun::star::uno::Any& aData ) +throw (::com::sun::star::uno::RuntimeException) +{ + svt::StatusbarController::command( aPos, nCommand, bMouseEvent, aData ); +} + +void SAL_CALL LogoTextStatusbarController::paint( + const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics >& xGraphics, + const ::com::sun::star::awt::Rectangle& rOutputRectangle, + ::sal_Int32 nItemId, + ::sal_Int32 nStyle ) +throw (::com::sun::star::uno::RuntimeException) +{ + svt::StatusbarController::paint( xGraphics, rOutputRectangle, nItemId, nStyle ); +} + +void SAL_CALL LogoTextStatusbarController::click() +throw (::com::sun::star::uno::RuntimeException) +{ + svt::StatusbarController::click(); +} + +void SAL_CALL LogoTextStatusbarController::doubleClick() throw (::com::sun::star::uno::RuntimeException) +{ + svt::StatusbarController::doubleClick(); +} + +} diff --git a/framework/source/uielement/macrosmenucontroller.cxx b/framework/source/uielement/macrosmenucontroller.cxx new file mode 100644 index 000000000000..f0f5d52a47d6 --- /dev/null +++ b/framework/source/uielement/macrosmenucontroller.cxx @@ -0,0 +1,231 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + +#include <uielement/macrosmenucontroller.hxx> +#include <uielement/menubarmanager.hxx> +#include <threadhelp/resetableguard.hxx> +#include "services.h" +#include <classes/resource.hrc> +#include <classes/fwkresid.hxx> +#include <helper/imageproducer.hxx> +#include <com/sun/star/awt/MenuItemStyle.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XContentEnumerationAccess.hpp> +#include <com/sun/star/style/XStyleFamiliesSupplier.hpp> +#include <com/sun/star/frame/XModuleManager.hpp> +#include <comphelper/processfactory.hxx> +#include <vcl/svapp.hxx> +#include <vcl/i18nhelp.hxx> +#include <tools/urlobj.hxx> +#include <rtl/ustrbuf.hxx> +#include <dispatch/uieventloghelper.hxx> +#include "helper/mischelper.hxx" + +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::style; +using namespace com::sun::star::container; +using namespace ::com::sun::star::frame; + +namespace framework +{ +class +DEFINE_XSERVICEINFO_MULTISERVICE ( MacrosMenuController , + OWeakObject , + SERVICENAME_POPUPMENUCONTROLLER , + IMPLEMENTATIONNAME_MACROSMENUCONTROLLER + ) + +DEFINE_INIT_SERVICE ( MacrosMenuController, {} ) + +MacrosMenuController::MacrosMenuController( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ) : + PopupMenuControllerBase( xServiceManager ), + m_xServiceManager( xServiceManager) +{ +} + +MacrosMenuController::~MacrosMenuController() +{ + OSL_TRACE("calling dtor"); +} + +// private function +void MacrosMenuController::fillPopupMenu( Reference< css::awt::XPopupMenu >& rPopupMenu ) +{ + VCLXPopupMenu* pVCLPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( rPopupMenu ); + PopupMenu* pPopupMenu = 0; + + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + resetPopupMenu( rPopupMenu ); + if ( pVCLPopupMenu ) + pPopupMenu = (PopupMenu *)pVCLPopupMenu->GetMenu(); + + // insert basic + String aCommand = String::CreateFromAscii( ".uno:MacroDialog" ); + String aDisplayName = RetrieveLabelFromCommand( aCommand ); + pPopupMenu->InsertItem( 2, aDisplayName ); + pPopupMenu->SetItemCommand( 2, aCommand ); + //pPopupMenu->SetHelpId( 2, HID_SVX_BASIC_MACRO_ORGANIZER ); + pPopupMenu->SetHelpId( 2, 40012 ); + + // insert providers but not basic or java + addScriptItems( pPopupMenu, 4); +} + +// XEventListener +void SAL_CALL MacrosMenuController::disposing( const EventObject& ) throw ( RuntimeException ) +{ + Reference< css::awt::XMenuListener > xHolder(( OWeakObject *)this, UNO_QUERY ); + + ResetableGuard aLock( m_aLock ); + OSL_TRACE("disposing"); + m_xFrame.clear(); + m_xDispatch.clear(); + m_xServiceManager.clear(); + + if ( m_xPopupMenu.is() ) + { + m_xPopupMenu->removeMenuListener( Reference< css::awt::XMenuListener >(( OWeakObject *)this, UNO_QUERY )); + OSL_TRACE("removed listener"); + } + m_xPopupMenu.clear(); +} + +// XStatusListener +void SAL_CALL MacrosMenuController::statusChanged( const FeatureStateEvent& ) throw ( RuntimeException ) +{ + ResetableGuard aLock( m_aLock ); + if ( m_xPopupMenu.is() ) + { + fillPopupMenu( m_xPopupMenu ); + } +} + +// XMenuListener +void MacrosMenuController::impl_select(const Reference< XDispatch >& /*_xDispatch*/,const ::com::sun::star::util::URL& aTargetURL) +{ + // need to requery, since we handle more than one type of Command + // if we don't do this only .uno:ScriptOrganizer commands are executed + Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY ); + Reference< XDispatch > xDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 ); + if( xDispatch.is() ) + { + ExecuteInfo* pExecuteInfo = new ExecuteInfo; + pExecuteInfo->xDispatch = xDispatch; + pExecuteInfo->aTargetURL = aTargetURL; + //pExecuteInfo->aArgs = aArgs; + if(::comphelper::UiEventsLogger::isEnabled()) //#i88653# + UiEventLogHelper(::rtl::OUString::createFromAscii("MacrosMenuController")).log(m_xServiceManager, m_xFrame, aTargetURL, pExecuteInfo->aArgs); +// xDispatch->dispatch( aTargetURL, aArgs ); + Application::PostUserEvent( STATIC_LINK(0, MacrosMenuController , ExecuteHdl_Impl), pExecuteInfo ); + } + else + { + } +} + + +IMPL_STATIC_LINK_NOINSTANCE( MacrosMenuController, ExecuteHdl_Impl, ExecuteInfo*, pExecuteInfo ) +{ + 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! + pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs ); + } + catch ( Exception& ) + { + } + delete pExecuteInfo; + return 0; +} + +String MacrosMenuController::RetrieveLabelFromCommand( const String& aCmdURL ) +{ + sal_Bool bModuleIdentified = m_aModuleIdentifier.getLength() != 0; + return framework::RetrieveLabelFromCommand(aCmdURL,m_xServiceManager,m_xUICommandLabels,m_xFrame,m_aModuleIdentifier,bModuleIdentified,"Label"); +} + +void MacrosMenuController::addScriptItems( PopupMenu* pPopupMenu, USHORT startItemId ) +{ + const String aCmdBase = String::CreateFromAscii( ".uno:ScriptOrganizer?ScriptOrganizer.Language:string=" ); + const String ellipsis = String::CreateFromAscii( "..." ); + const ::rtl::OUString providerKey = + ::rtl::OUString::createFromAscii("com.sun.star.script.provider.ScriptProviderFor" ); + const ::rtl::OUString languageProviderName = + ::rtl::OUString::createFromAscii("com.sun.star.script.provider.LanguageScriptProvider" ); + USHORT itemId = startItemId; + Reference< XContentEnumerationAccess > xEnumAccess = Reference< XContentEnumerationAccess >( m_xServiceManager, UNO_QUERY_THROW ); + Reference< XEnumeration > xEnum = xEnumAccess->createContentEnumeration ( languageProviderName ); + + while ( xEnum->hasMoreElements() ) + { + Reference< XServiceInfo > xServiceInfo; + if ( sal_False == ( xEnum->nextElement() >>= xServiceInfo ) ) + { + break; + } + Sequence< ::rtl::OUString > serviceNames = xServiceInfo->getSupportedServiceNames(); + + if ( serviceNames.getLength() > 0 ) + { + for ( sal_Int32 index = 0; index < serviceNames.getLength(); index++ ) + { + if ( serviceNames[ index ].indexOf( providerKey ) == 0 ) + { + ::rtl::OUString serviceName = serviceNames[ index ]; + String aCommand = aCmdBase; + String aDisplayName = String( serviceName.copy( providerKey.getLength() ) ); + if( aDisplayName.Equals( String::CreateFromAscii( "Java" ) ) || aDisplayName.Equals( String::CreateFromAscii( "Basic" ) ) ) + { + // no entries for Java & Basic added elsewhere + break; + } + aCommand.Append( aDisplayName ); + aDisplayName.Append( ellipsis ); + pPopupMenu->InsertItem( itemId, aDisplayName ); + pPopupMenu->SetItemCommand( itemId, aCommand ); + //pPopupMenu->SetHelpId( itemId, HID_SVX_COMMON_MACRO_ORGANIZER ); + pPopupMenu->SetHelpId( itemId, 40014 ); + itemId++; + break; + } + } + } + } +} + +} diff --git a/framework/source/uielement/makefile.mk b/framework/source/uielement/makefile.mk new file mode 100644 index 000000000000..da4ab3d34c74 --- /dev/null +++ b/framework/source/uielement/makefile.mk @@ -0,0 +1,86 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME= framework +TARGET= fwk_uielement +USE_DEFFILE= TRUE +ENABLE_EXCEPTIONS= TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Generate ----------------------------------------------------- + +SLOFILES= \ + $(SLO)$/addonstoolbarmanager.obj \ + $(SLO)$/addonstoolbarwrapper.obj \ + $(SLO)$/buttontoolbarcontroller.obj \ + $(SLO)$/comboboxtoolbarcontroller.obj \ + $(SLO)$/complextoolbarcontroller.obj \ + $(SLO)$/constitemcontainer.obj \ + $(SLO)$/controlmenucontroller.obj \ + $(SLO)$/dropdownboxtoolbarcontroller.obj \ + $(SLO)$/edittoolbarcontroller.obj \ + $(SLO)$/fontmenucontroller.obj \ + $(SLO)$/fontsizemenucontroller.obj \ + $(SLO)$/footermenucontroller.obj \ + $(SLO)$/generictoolbarcontroller.obj \ + $(SLO)$/headermenucontroller.obj \ + $(SLO)$/imagebuttontoolbarcontroller.obj \ + $(SLO)$/itemcontainer.obj \ + $(SLO)$/langselectionmenucontroller.obj \ + $(SLO)$/langselectionstatusbarcontroller.obj \ + $(SLO)$/logoimagestatusbarcontroller.obj \ + $(SLO)$/logotextstatusbarcontroller.obj \ + $(SLO)$/macrosmenucontroller.obj \ + $(SLO)$/menubarmanager.obj \ + $(SLO)$/menubarmerger.obj \ + $(SLO)$/menubarwrapper.obj \ + $(SLO)$/newmenucontroller.obj \ + $(SLO)$/objectmenucontroller.obj \ + $(SLO)$/progressbarwrapper.obj \ + $(SLO)$/recentfilesmenucontroller.obj \ + $(SLO)$/rootitemcontainer.obj \ + $(SLO)$/simpletextstatusbarcontroller.obj \ + $(SLO)$/spinfieldtoolbarcontroller.obj \ + $(SLO)$/statusbar.obj \ + $(SLO)$/statusbarmanager.obj \ + $(SLO)$/statusbarwrapper.obj \ + $(SLO)$/statusindicatorinterfacewrapper.obj \ + $(SLO)$/togglebuttontoolbarcontroller.obj \ + $(SLO)$/toolbar.obj \ + $(SLO)$/toolbarmanager.obj \ + $(SLO)$/toolbarmerger.obj \ + $(SLO)$/toolbarsmenucontroller.obj \ + $(SLO)$/toolbarwrapper.obj \ + $(SLO)$/uicommanddescription.obj \ + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/framework/source/uielement/menubarmanager.cxx b/framework/source/uielement/menubarmanager.cxx new file mode 100644 index 000000000000..9fbdf87336cc --- /dev/null +++ b/framework/source/uielement/menubarmanager.cxx @@ -0,0 +1,2146 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <uielement/menubarmanager.hxx> +#include <xml/menuconfiguration.hxx> +#include <classes/bmkmenu.hxx> +#include <classes/addonmenu.hxx> +#include <helper/imageproducer.hxx> +#include <threadhelp/resetableguard.hxx> +#include "classes/addonsoptions.hxx" +#include <classes/fwkresid.hxx> +#include <classes/menumanager.hxx> +#include <helper/acceleratorinfo.hxx> +#include <helper/mischelper.hxx> +#include <classes/menuextensionsupplier.hxx> +#include <classes/resource.hrc> +#include <services.h> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/frame/XFramesSupplier.hpp> +#include <com/sun/star/frame/XDesktop.hpp> +#include <com/sun/star/container/XEnumeration.hpp> +#include <com/sun/star/util/XStringWidth.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> +#include <com/sun/star/frame/XPopupMenuController.hpp> +#include <com/sun/star/frame/XUIControllerRegistration.hpp> +#ifndef _COM_SUN_STAR_LANG_XSYSTEMDEPENDENT_HPP_ +#include <com/sun/star/lang/SystemDependent.hpp> +#endif +#include <com/sun/star/ui/ItemType.hpp> +#include <com/sun/star/ui/ImageType.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/frame/XModuleManager.hpp> +#include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp> +#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp> +#include <com/sun/star/ui/ItemStyle.hpp> +#include <com/sun/star/frame/status/Visibility.hpp> + +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ +#include <comphelper/processfactory.hxx> +#include <comphelper/extract.hxx> +#include <svtools/menuoptions.hxx> +#include <unotools/historyoptions.hxx> +#include <unotools/pathoptions.hxx> +#include <unotools/cmdoptions.hxx> +#include <unotools/localfilehelper.hxx> +#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ +#include <toolkit/unohlp.hxx> +#endif +#include <tools/urlobj.hxx> +#include <vcl/svapp.hxx> +#include <vcl/window.hxx> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> +#include <osl/file.hxx> +#include <cppuhelper/implbase1.hxx> +#include <svtools/acceleratorexecute.hxx> +#include <rtl/logfile.hxx> +#include "svtools/miscopt.hxx" +#include <classes/addonmenu.hxx> +#include <uielement/menubarmerger.hxx> +#include <dispatch/uieventloghelper.hxx> + +// Be careful removing this "bad" construct. There are serious problems +// with #define STRICT and including windows.h. Changing this needs some +// redesign on other projects, too. Especially sal/main.h which defines +// HINSTANCE depending on STRCIT!!!!!!!!!!!!!!! +struct SystemMenuData +{ + unsigned long nSize; + long hMenu; +}; + +//_________________________________________________________________________________________________________________ +// namespace +//_________________________________________________________________________________________________________________ + +using namespace ::cppu; +using namespace ::vos; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::ui; + +static const char ITEM_DESCRIPTOR_COMMANDURL[] = "CommandURL"; +static const char ITEM_DESCRIPTOR_HELPURL[] = "HelpURL"; +static const char ITEM_DESCRIPTOR_CONTAINER[] = "ItemDescriptorContainer"; +static const char ITEM_DESCRIPTOR_LABEL[] = "Label"; +static const char ITEM_DESCRIPTOR_TYPE[] = "Type"; +static const char ITEM_DESCRIPTOR_MODULEIDENTIFIER[] = "ModuleIdentifier"; +static const char ITEM_DESCRIPTOR_DISPATCHPROVIDER[] = "DispatchProvider"; +static const char ITEM_DESCRIPTOR_STYLE[] = "Style"; + +const sal_Int32 LEN_DESCRIPTOR_COMMANDURL = 10; +const sal_Int32 LEN_DESCRIPTOR_HELPURL = 7; +const sal_Int32 LEN_DESCRIPTOR_CONTAINER = 23; +const sal_Int32 LEN_DESCRIPTOR_LABEL = 5; +const sal_Int32 LEN_DESCRIPTOR_TYPE = 4; +const sal_Int32 LEN_DESCRIPTOR_MODULEIDENTIFIER = 16; +const sal_Int32 LEN_DESCRIPTOR_DISPATCHPROVIDER = 16; +static const sal_Int32 ITEM_DESCRIPTOR_STYLE_LEN = 5; + +const sal_uInt16 ADDONMENU_MERGE_ITEMID_START = 1500; + +class StringLength : public ::cppu::WeakImplHelper1< ::com::sun::star::util::XStringWidth > +{ + public: + StringLength() {} + virtual ~StringLength() {} + + // XStringWidth + sal_Int32 SAL_CALL queryStringWidth( const ::rtl::OUString& aString ) + throw (RuntimeException) + { + return aString.getLength(); + } +}; + +namespace framework +{ + +// special menu ids/command ids for dynamic popup menus +#define SID_SFX_START 5000 +#define SID_NEWDOCDIRECT (SID_SFX_START + 537) +#define SID_AUTOPILOTMENU (SID_SFX_START + 1381) +#define SID_PICKLIST (SID_SFX_START + 510) +#define SID_MDIWINDOWLIST (SID_SFX_START + 610) +#define SID_ADDONLIST (SID_SFX_START + 1677) +#define SID_HELPMENU (SID_SFX_START + 410) + +#define SFX_REFERER_USER "private:user" + +const ::rtl::OUString aCmdHelpIndex( RTL_CONSTASCII_USTRINGPARAM( ".uno:HelpIndex" )); +const ::rtl::OUString aCmdToolsMenu( RTL_CONSTASCII_USTRINGPARAM( ".uno:ToolsMenu" )); +const ::rtl::OUString aCmdHelpMenu( RTL_CONSTASCII_USTRINGPARAM( ".uno:HelpMenu" )); +const ::rtl::OUString aSlotHelpMenu( RTL_CONSTASCII_USTRINGPARAM( "slot:5410" )); + +const ::rtl::OUString aSpecialFileMenu( RTL_CONSTASCII_USTRINGPARAM( "file" )); +const ::rtl::OUString aSpecialWindowMenu( RTL_CONSTASCII_USTRINGPARAM( "window" )); +const ::rtl::OUString aSlotSpecialFileMenu( RTL_CONSTASCII_USTRINGPARAM( "slot:5510" )); +const ::rtl::OUString aSlotSpecialWindowMenu( RTL_CONSTASCII_USTRINGPARAM( "slot:5610" )); +const ::rtl::OUString aSlotSpecialToolsMenu( RTL_CONSTASCII_USTRINGPARAM( "slot:6677" )); + +// special uno commands for picklist and window list +const ::rtl::OUString aSpecialFileCommand( RTL_CONSTASCII_USTRINGPARAM( ".uno:PickList" )); +const ::rtl::OUString aSpecialWindowCommand( RTL_CONSTASCII_USTRINGPARAM( ".uno:WindowList" )); + +const ::rtl::OUString UNO_COMMAND( RTL_CONSTASCII_USTRINGPARAM( ".uno:" )); + +static sal_Int16 getImageTypeFromBools( sal_Bool bBig, sal_Bool bHighContrast ) +{ + sal_Int16 n( 0 ); + if ( bBig ) + n |= ::com::sun::star::ui::ImageType::SIZE_LARGE; + if ( bHighContrast ) + n |= ::com::sun::star::ui::ImageType::COLOR_HIGHCONTRAST; + return n; +} + +// #110897# +MenuBarManager::MenuBarManager( + const Reference< XMultiServiceFactory >& xServiceFactory, + const Reference< XFrame >& rFrame, + const Reference< XURLTransformer >& _xURLTransformer, + const Reference< XDispatchProvider >& rDispatchProvider, + const rtl::OUString& rModuleIdentifier, + Menu* pMenu, sal_Bool bDelete, sal_Bool bDeleteChildren ) +: ThreadHelpBase( &Application::GetSolarMutex() ), OWeakObject() + , m_bDisposed( sal_False ) + , m_bRetrieveImages( sal_False ) + , m_bAcceleratorCfg( sal_False ) + , m_bModuleIdentified( sal_False ) + , m_aListenerContainer( m_aLock.getShareableOslMutex() ) + , mxServiceFactory(xServiceFactory) + , m_xURLTransformer(_xURLTransformer) + , m_nSymbolsStyle( SvtMiscOptions().GetCurrentSymbolsStyle() ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::MenuBarManager" ); + m_xPopupMenuControllerRegistration = Reference< ::com::sun::star::frame::XUIControllerRegistration >( + getServiceFactory()->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.PopupMenuControllerFactory" ))), + UNO_QUERY ); + FillMenuManager( pMenu, rFrame, rDispatchProvider, rModuleIdentifier, bDelete, bDeleteChildren ); +} + +// #110897# +MenuBarManager::MenuBarManager( + const Reference< XMultiServiceFactory >& xServiceFactory, + const Reference< XFrame >& rFrame, + const Reference< XURLTransformer >& _xURLTransformer, + AddonMenu* pAddonMenu, + sal_Bool bDelete, + sal_Bool bDeleteChildren ) +: ThreadHelpBase( &Application::GetSolarMutex() ) + , OWeakObject() + , m_bDisposed( sal_False ) + , m_bRetrieveImages( sal_True ) + , m_bAcceleratorCfg( sal_False ) + , m_bModuleIdentified( sal_False ) + , m_aListenerContainer( m_aLock.getShareableOslMutex() ) + , mxServiceFactory(xServiceFactory) + , m_xURLTransformer(_xURLTransformer) + , m_nSymbolsStyle( SvtMiscOptions().GetCurrentSymbolsStyle() ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::MenuBarManager" ); + Init(rFrame,pAddonMenu,bDelete,bDeleteChildren); +} + +// #110897# +MenuBarManager::MenuBarManager( + const Reference< XMultiServiceFactory >& xServiceFactory, + const Reference< XFrame >& rFrame, + const Reference< XURLTransformer >& _xURLTransformer, + AddonPopupMenu* pAddonPopupMenu, + sal_Bool bDelete, + sal_Bool bDeleteChildren ) +: ThreadHelpBase( &Application::GetSolarMutex() ) + , OWeakObject() + , m_bDisposed( sal_False ) + , m_bRetrieveImages( sal_True ) + , m_bAcceleratorCfg( sal_False ) + , m_bModuleIdentified( sal_False ) + , m_aListenerContainer( m_aLock.getShareableOslMutex() ) + , mxServiceFactory(xServiceFactory) + , m_xURLTransformer(_xURLTransformer) + , m_nSymbolsStyle( SvtMiscOptions().GetCurrentSymbolsStyle() ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::MenuBarManager" ); + Init(rFrame,pAddonPopupMenu,bDelete,bDeleteChildren,true); +} + +Any SAL_CALL MenuBarManager::queryInterface( const Type & rType ) throw ( RuntimeException ) +{ + Any a = ::cppu::queryInterface( + rType , + SAL_STATIC_CAST( ::com::sun::star::frame::XStatusListener*, this ), + SAL_STATIC_CAST( ::com::sun::star::frame::XFrameActionListener*, this ), + SAL_STATIC_CAST( ::com::sun::star::ui::XUIConfigurationListener*, this ), + SAL_STATIC_CAST( XEventListener*, (XStatusListener *)this ), + SAL_STATIC_CAST( XComponent*, this ), + SAL_STATIC_CAST( ::com::sun::star::awt::XSystemDependentMenuPeer*, this )); + + if ( a.hasValue() ) + return a; + + return OWeakObject::queryInterface( rType ); +} + + +void SAL_CALL MenuBarManager::acquire() throw() +{ + OWeakObject::acquire(); +} + + +void SAL_CALL MenuBarManager::release() throw() +{ + OWeakObject::release(); +} + + +Any SAL_CALL MenuBarManager::getMenuHandle( const Sequence< sal_Int8 >& /*ProcessId*/, sal_Int16 SystemType ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::getMenuHandle" ); + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw com::sun::star::lang::DisposedException(); + + Any a; + + if ( m_pVCLMenu ) + { + OGuard aSolarGuard( Application::GetSolarMutex() ); + + SystemMenuData aSystemMenuData; + aSystemMenuData.nSize = sizeof( SystemMenuData ); + + m_pVCLMenu->GetSystemMenuData( &aSystemMenuData ); +#ifdef QUARTZ + if( SystemType == SystemDependent::SYSTEM_MAC ) + { + } +#elif (defined WNT) + if( SystemType == SystemDependent::SYSTEM_WIN32 ) + { + a <<= (long) aSystemMenuData.hMenu; + } +#elif (defined UNX) + if( SystemType == SystemDependent::SYSTEM_XWINDOW ) + { + } +#endif + } + + return a; +} + +MenuBarManager::~MenuBarManager() +{ + // stop asynchronous settings timer + m_xDeferedItemContainer.clear(); + m_aAsyncSettingsTimer.Stop(); + + DBG_ASSERT( OWeakObject::m_refCount == 0, "Who wants to delete an object with refcount > 0!" ); +} + +void MenuBarManager::Destroy() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::Destroy" ); + OGuard aGuard( Application::GetSolarMutex() ); + + if ( !m_bDisposed ) + { + // stop asynchronous settings timer and + // release defered item container reference + m_aAsyncSettingsTimer.Stop(); + m_xDeferedItemContainer.clear(); + RemoveListener(); + + std::vector< MenuItemHandler* >::iterator p; + for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ ) + { + MenuItemHandler* pItemHandler = *p; + pItemHandler->xMenuItemDispatch.clear(); + pItemHandler->xSubMenuManager.clear(); + pItemHandler->xPopupMenu.clear(); + delete pItemHandler; + } + m_aMenuItemHandlerVector.clear(); + + if ( m_bDeleteMenu ) + { + delete m_pVCLMenu; + m_pVCLMenu = 0; + } + } +} + +// XComponent +void SAL_CALL MenuBarManager::dispose() throw( RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::dispose" ); + Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY ); + + EventObject aEvent( xThis ); + m_aListenerContainer.disposeAndClear( aEvent ); + + { + ResetableGuard aGuard( m_aLock ); +// RemoveListener(); + Destroy(); + m_bDisposed = sal_True; + + if ( m_xDocImageManager.is() ) + { + try + { + m_xDocImageManager->removeConfigurationListener( + Reference< XUIConfigurationListener >( + static_cast< OWeakObject* >( this ), UNO_QUERY )); + } + catch ( Exception& ) + { + } + } + if ( m_xModuleImageManager.is() ) + { + try + { + m_xModuleImageManager->removeConfigurationListener( + Reference< XUIConfigurationListener >( + static_cast< OWeakObject* >( this ), UNO_QUERY )); + } + catch ( Exception& ) + { + } + } + m_xDocImageManager.clear(); + m_xModuleImageManager.clear(); + m_xGlobalAcceleratorManager.clear(); + m_xModuleAcceleratorManager.clear(); + m_xDocAcceleratorManager.clear(); + m_xUICommandLabels.clear(); + m_xPopupMenuControllerRegistration.clear(); + mxServiceFactory.clear(); + } +} + +void SAL_CALL MenuBarManager::addEventListener( const Reference< XEventListener >& xListener ) throw( RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::addEventListener" ); + ResetableGuard aGuard( m_aLock ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + if ( m_bDisposed ) + throw DisposedException(); + + m_aListenerContainer.addInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), xListener ); +} + +void SAL_CALL MenuBarManager::removeEventListener( const Reference< XEventListener >& xListener ) throw( RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::removeEventListener" ); + ResetableGuard aGuard( m_aLock ); + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + m_aListenerContainer.removeInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), xListener ); +} + +void SAL_CALL MenuBarManager::elementInserted( const ::com::sun::star::ui::ConfigurationEvent& Event ) +throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::elementInserted" ); + ResetableGuard aGuard( m_aLock ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + if ( m_bDisposed ) + return; + + sal_Int16 nImageType = sal_Int16(); + sal_Int16 nCurrentImageType = getImageTypeFromBools( sal_False, m_bWasHiContrast ); + if (( Event.aInfo >>= nImageType ) && + ( nImageType == nCurrentImageType )) + RequestImages(); +} + +void SAL_CALL MenuBarManager::elementRemoved( const ::com::sun::star::ui::ConfigurationEvent& Event ) +throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::elementRemoved" ); + elementInserted(Event); +} + +void SAL_CALL MenuBarManager::elementReplaced( const ::com::sun::star::ui::ConfigurationEvent& Event ) +throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::elementReplaced" ); + elementInserted(Event); +} + +// XFrameActionListener +void SAL_CALL MenuBarManager::frameAction( const FrameActionEvent& Action ) +throw ( RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::frameAction" ); + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw com::sun::star::lang::DisposedException(); + + if ( Action.Action == FrameAction_CONTEXT_CHANGED ) + { + std::vector< MenuItemHandler* >::iterator p; + for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ ) + { + // Clear dispatch reference as we will requery it later o + MenuItemHandler* pItemHandler = *p; + pItemHandler->xMenuItemDispatch.clear(); + } + } +} + +// XStatusListener +void SAL_CALL MenuBarManager::statusChanged( const FeatureStateEvent& Event ) +throw ( RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::statusChanged" ); + ::rtl::OUString aFeatureURL = Event.FeatureURL.Complete; + + OGuard aSolarGuard( Application::GetSolarMutex() ); + { + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + return; + + // We have to check all menu entries as there can be identical entries in a popup menu. + std::vector< MenuItemHandler* >::iterator p; + for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ ) + { + MenuItemHandler* pMenuItemHandler = *p; + if ( pMenuItemHandler->aMenuItemURL == aFeatureURL ) + { + sal_Bool bCheckmark( sal_False ); + sal_Bool bMenuItemEnabled( m_pVCLMenu->IsItemEnabled( pMenuItemHandler->nItemId )); + sal_Bool bEnabledItem( Event.IsEnabled ); + rtl::OUString aItemText; + status::Visibility aVisibilityStatus; + + #ifdef UNIX + // #b6673979# enable some slots hardly, because UNIX clipboard does not notify all changes + // Can be removed if follow up task will be fixed directly within applications. + if ( + ( pMenuItemHandler->aMenuItemURL.equalsAscii (".uno:Paste" ) ) || + ( pMenuItemHandler->aMenuItemURL.equalsAscii (".uno:PasteSpecial" ) ) || + ( pMenuItemHandler->aMenuItemURL.equalsAscii (".uno:PasteClipboard") ) // special for draw/impress + ) + bEnabledItem = sal_True; + #endif + + // Enable/disable item + if ( bEnabledItem != bMenuItemEnabled ) + m_pVCLMenu->EnableItem( pMenuItemHandler->nItemId, bEnabledItem ); + + if ( Event.State >>= bCheckmark ) + { + // Checkmark + m_pVCLMenu->ShowItem( pMenuItemHandler->nItemId, TRUE ); + m_pVCLMenu->CheckItem( pMenuItemHandler->nItemId, bCheckmark ); + m_pVCLMenu->SetItemBits( pMenuItemHandler->nItemId, + m_pVCLMenu->GetItemBits( pMenuItemHandler->nItemId ) | MIB_CHECKABLE ); + } + else if ( Event.State >>= aItemText ) + { + // Replacement for place holders + if ( aItemText.matchAsciiL( "($1)", 4 )) + { + String aResStr = String( FwkResId( STR_UPDATEDOC )); + rtl::OUString aTmp( aResStr ); + aTmp += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " )); + aTmp += aItemText.copy( 4 ); + aItemText = aTmp; + } + else if ( aItemText.matchAsciiL( "($2)", 4 )) + { + String aResStr = String( FwkResId( STR_CLOSEDOC_ANDRETURN )); + rtl::OUString aTmp( aResStr ); + aTmp += aItemText.copy( 4 ); + aItemText = aTmp; + } + else if ( aItemText.matchAsciiL( "($3)", 4 )) + { + String aResStr = String( FwkResId( STR_SAVECOPYDOC )); + rtl::OUString aTmp( aResStr ); + aTmp += aItemText.copy( 4 ); + aItemText = aTmp; + } + + m_pVCLMenu->ShowItem( pMenuItemHandler->nItemId, TRUE ); + m_pVCLMenu->SetItemText( pMenuItemHandler->nItemId, aItemText ); + } + else if ( Event.State >>= aVisibilityStatus ) + { + // Visibility + m_pVCLMenu->ShowItem( pMenuItemHandler->nItemId, aVisibilityStatus.bVisible ); + } + else + m_pVCLMenu->ShowItem( pMenuItemHandler->nItemId, TRUE ); + } + + if ( Event.Requery ) + { + // Release dispatch object - will be requeried on the next activate! + pMenuItemHandler->xMenuItemDispatch.clear(); + } + } + } +} + +// Helper to retrieve own structure from item ID +MenuBarManager::MenuItemHandler* MenuBarManager::GetMenuItemHandler( USHORT nItemId ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::GetMenuItemHandler" ); + ResetableGuard aGuard( m_aLock ); + + std::vector< MenuItemHandler* >::iterator p; + for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ ) + { + MenuItemHandler* pItemHandler = *p; + if ( pItemHandler->nItemId == nItemId ) + return pItemHandler; + } + + return 0; +} + +// Helper to set request images flag +void MenuBarManager::RequestImages() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::RequestImages" ); + // must be locked from callee + // ResetableGuard aGuard( m_aLock ); + + m_bRetrieveImages = sal_True; + const sal_uInt32 nCount = m_aMenuItemHandlerVector.size(); + for ( sal_uInt32 i = 0; i < nCount; ++i ) + { + MenuItemHandler* pItemHandler = m_aMenuItemHandlerVector[i]; + if ( pItemHandler->xSubMenuManager.is() ) + { + MenuBarManager* pMenuBarManager = (MenuBarManager*)(pItemHandler->xSubMenuManager.get()); + pMenuBarManager->RequestImages(); + } + } +} + +// Helper to reset objects to prepare shutdown +void MenuBarManager::RemoveListener() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::RemoveListener" ); + ResetableGuard aGuard( m_aLock ); + + // Check service manager reference. Remove listener can be called due + // to a disposing call from the frame and therefore we already removed + // our listeners and release the service manager reference! + Reference< XMultiServiceFactory > xServiceManager = getServiceFactory(); + if ( xServiceManager.is() ) + { + std::vector< MenuItemHandler* >::iterator p; + for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ ) + { + MenuItemHandler* pItemHandler = *p; + if ( pItemHandler->xMenuItemDispatch.is() ) + { + URL aTargetURL; + aTargetURL.Complete = pItemHandler->aMenuItemURL; + m_xURLTransformer->parseStrict( aTargetURL ); + + pItemHandler->xMenuItemDispatch->removeStatusListener( + static_cast< XStatusListener* >( this ), aTargetURL ); + } + + pItemHandler->xMenuItemDispatch.clear(); + if ( pItemHandler->xPopupMenu.is() ) + { + { + // Remove popup menu from menu structure + OGuard aGuard2( Application::GetSolarMutex() ); + m_pVCLMenu->SetPopupMenu( pItemHandler->nItemId, 0 ); + } + + Reference< com::sun::star::lang::XEventListener > xEventListener( pItemHandler->xPopupMenuController, UNO_QUERY ); + if ( xEventListener.is() ) + { + EventObject aEventObject; + aEventObject.Source = (OWeakObject *)this; + xEventListener->disposing( aEventObject ); + } + + // We now provide a popup menu controller to external code. + // Therefore the life-time must be explicitly handled via + // dispose!! + try + { + Reference< XComponent > xComponent( pItemHandler->xPopupMenuController, UNO_QUERY ); + if ( xComponent.is() ) + xComponent->dispose(); + } + catch ( RuntimeException& ) + { + throw; + } + catch ( Exception& ) + { + } + + // Release references to controller and popup menu + pItemHandler->xPopupMenuController.clear(); + pItemHandler->xPopupMenu.clear(); + } + + Reference< XComponent > xComponent( pItemHandler->xSubMenuManager, UNO_QUERY ); + if ( xComponent.is() ) + xComponent->dispose(); + } + } + + try + { + if ( m_xFrame.is() ) + m_xFrame->removeFrameActionListener( Reference< XFrameActionListener >( + static_cast< OWeakObject* >( this ), UNO_QUERY )); + } + catch ( Exception& ) + { + } + + m_xFrame = 0; +} + +void SAL_CALL MenuBarManager::disposing( const EventObject& Source ) throw ( RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::disposing(evt)" ); + MenuItemHandler* pMenuItemDisposing = NULL; + + ResetableGuard aGuard( m_aLock ); + + std::vector< MenuItemHandler* >::iterator p; + for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ ) + { + MenuItemHandler* pMenuItemHandler = *p; + if ( pMenuItemHandler->xMenuItemDispatch.is() && + pMenuItemHandler->xMenuItemDispatch == Source.Source ) + { + // disposing called from menu item dispatcher, remove listener + pMenuItemDisposing = pMenuItemHandler; + break; + } + } + + if ( pMenuItemDisposing ) + { + // Release references to the dispatch object + URL aTargetURL; + aTargetURL.Complete = pMenuItemDisposing->aMenuItemURL; + + // Check reference of service manager before we use it. Reference could + // be cleared due to RemoveListener call! + Reference< XMultiServiceFactory > xServiceManager( getServiceFactory() ); + if ( xServiceManager.is() ) + { + m_xURLTransformer->parseStrict( aTargetURL ); + + pMenuItemDisposing->xMenuItemDispatch->removeStatusListener( + static_cast< XStatusListener* >( this ), aTargetURL ); + pMenuItemDisposing->xMenuItemDispatch = Reference< XDispatch >(); + if ( pMenuItemDisposing->xPopupMenu.is() ) + { + Reference< com::sun::star::lang::XEventListener > xEventListener( pMenuItemDisposing->xPopupMenuController, UNO_QUERY ); + if ( xEventListener.is() ) + xEventListener->disposing( Source ); + + { + // Remove popup menu from menu structure as we release our reference to + // the controller. + OGuard aGuard2( Application::GetSolarMutex() ); + m_pVCLMenu->SetPopupMenu( pMenuItemDisposing->nItemId, 0 ); + } + + pMenuItemDisposing->xPopupMenuController.clear(); + pMenuItemDisposing->xPopupMenu.clear(); + } + } + return; + } + else if ( Source.Source == m_xFrame ) + { + // Our frame gets disposed. We have to remove all our listeners + RemoveListener(); + } + else if ( Source.Source == Reference< XInterface >( m_xDocImageManager, UNO_QUERY )) + m_xDocImageManager.clear(); + else if ( Source.Source == Reference< XInterface >( m_xModuleImageManager, UNO_QUERY )) + m_xModuleImageManager.clear(); +} + + +void MenuBarManager::CheckAndAddMenuExtension( Menu* pMenu ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::CheckAndAddMenuExtension" ); + static const char REFERENCECOMMAND_AFTER[] = ".uno:OnlineRegistrationDlg"; + static const char REFERENCECOMMAND_BEFORE[] = ".uno:About"; + + // retrieve menu extension item + MenuExtensionItem aMenuItem( GetMenuExtension() ); + if (( aMenuItem.aURL.getLength() > 0 ) && + ( aMenuItem.aLabel.getLength() > 0 )) + { + // remove all old window list entries from menu + sal_uInt16 nNewItemId( 0 ); + sal_uInt16 nInsertPos( MENU_APPEND ); + sal_uInt16 nAfterPos( MENU_APPEND ); + sal_uInt16 nBeforePos( MENU_APPEND ); + String aCommandAfter( String::CreateFromAscii ( REFERENCECOMMAND_AFTER )); + String aCommandBefore( String::CreateFromAscii ( REFERENCECOMMAND_BEFORE )); + for ( sal_uInt16 n = 0; n < pMenu->GetItemCount(); n++ ) + { + sal_uInt16 nItemId = pMenu->GetItemId( n ); + nNewItemId = std::max( nItemId, nNewItemId ); + if ( pMenu->GetItemCommand( nItemId ) == aCommandAfter ) + nAfterPos = n+1; + else if ( pMenu->GetItemCommand( nItemId ) == aCommandBefore ) + nBeforePos = n; + } + ++nNewItemId; + + if ( nAfterPos != MENU_APPEND ) + nInsertPos = nAfterPos; + else if ( nBeforePos != MENU_APPEND ) + nInsertPos = nBeforePos; + + pMenu->InsertItem( nNewItemId, aMenuItem.aLabel, 0, nInsertPos ); + pMenu->SetItemCommand( nNewItemId, aMenuItem.aURL ); + } +} + +static void lcl_CheckForChildren(Menu* pMenu, USHORT nItemId) +{ + if (PopupMenu* pThisPopup = pMenu->GetPopupMenu( nItemId )) + pMenu->EnableItem( nItemId, pThisPopup->GetItemCount() ? true : false ); +} + +//_________________________________________________________________________________________________________________ +// vcl handler +//_________________________________________________________________________________________________________________ + +IMPL_LINK( MenuBarManager, Activate, Menu *, pMenu ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::Activate" ); + if ( pMenu == m_pVCLMenu ) + { + // set/unset hiding disabled menu entries + sal_Bool bDontHide = SvtMenuOptions().IsEntryHidingEnabled(); + const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); + sal_Bool bShowMenuImages = rSettings.GetUseImagesInMenus(); + sal_Bool bHasDisabledEntries = SvtCommandOptions().HasEntries( SvtCommandOptions::CMDOPTION_DISABLED ); + + ResetableGuard aGuard( m_aLock ); + + sal_uInt16 nFlag = pMenu->GetMenuFlags(); + if ( bDontHide ) + nFlag &= ~MENU_FLAG_HIDEDISABLEDENTRIES; + else + nFlag |= MENU_FLAG_HIDEDISABLEDENTRIES; + pMenu->SetMenuFlags( nFlag ); + + if ( m_bActive ) + return 0; + + m_bActive = TRUE; + + ::rtl::OUString aMenuCommand( m_aMenuItemCommand ); + if ( m_aMenuItemCommand == aSpecialWindowMenu || + m_aMenuItemCommand == aSlotSpecialWindowMenu || + aMenuCommand == aSpecialWindowCommand ) + MenuManager::UpdateSpecialWindowMenu( pMenu,getServiceFactory(),m_aLock ); + + // Check if some modes have changed so we have to update our menu images + sal_Bool bIsHiContrast = rSettings.GetHighContrastMode(); + sal_Int16 nSymbolsStyle = SvtMiscOptions().GetCurrentSymbolsStyle(); + + if ( m_bRetrieveImages || + m_bWasHiContrast != bIsHiContrast || + bShowMenuImages != m_bShowMenuImages || + nSymbolsStyle != m_nSymbolsStyle ) + { + // The mode changed so we have to replace all images + m_bWasHiContrast = bIsHiContrast; + m_bShowMenuImages = bShowMenuImages; + m_bRetrieveImages = sal_False; + m_nSymbolsStyle = nSymbolsStyle; + MenuManager::FillMenuImages(m_xFrame,pMenu,bIsHiContrast,bShowMenuImages); + } + + // Try to map commands to labels + for ( USHORT nPos = 0; nPos < pMenu->GetItemCount(); nPos++ ) + { + USHORT nItemId = pMenu->GetItemId( nPos ); + if (( pMenu->GetItemType( nPos ) != MENUITEM_SEPARATOR ) && + ( pMenu->GetItemText( nItemId ).Len() == 0 )) + { + String aCommand = pMenu->GetItemCommand( nItemId ); + if ( aCommand.Len() > 0 ) + pMenu->SetItemText( nItemId, RetrieveLabelFromCommand( aCommand )); + } + } + + // Try to set accelerator keys + { + RetrieveShortcuts( m_aMenuItemHandlerVector ); + std::vector< MenuItemHandler* >::iterator p; + for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ ) + { + MenuItemHandler* pMenuItemHandler = *p; + + // Set key code, workaround for hard-coded shortcut F1 mapped to .uno:HelpIndex + // Only non-popup menu items can have a short-cut + if ( pMenuItemHandler->aMenuItemURL == aCmdHelpIndex ) + { + KeyCode aKeyCode( KEY_F1 ); + pMenu->SetAccelKey( pMenuItemHandler->nItemId, aKeyCode ); + } + else if ( pMenu->GetPopupMenu( pMenuItemHandler->nItemId ) == 0 ) + pMenu->SetAccelKey( pMenuItemHandler->nItemId, pMenuItemHandler->aKeyCode ); + } + } + + URL aTargetURL; + + // Use provided dispatch provider => fallback to frame as dispatch provider + Reference< XDispatchProvider > xDispatchProvider; + if ( m_xDispatchProvider.is() ) + xDispatchProvider = m_xDispatchProvider; + else + xDispatchProvider = Reference< XDispatchProvider >( m_xFrame, UNO_QUERY ); + + if ( xDispatchProvider.is() ) + { + KeyCode aEmptyKeyCode; + SvtCommandOptions aCmdOptions; + std::vector< MenuItemHandler* >::iterator p; + for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ ) + { + MenuItemHandler* pMenuItemHandler = *p; + if ( pMenuItemHandler ) + { + if ( !pMenuItemHandler->xMenuItemDispatch.is() && + !pMenuItemHandler->xSubMenuManager.is() ) + { + // There is no dispatch mechanism for the special window list menu items, + // because they are handled directly through XFrame->activate!!! + // Don't update dispatches for special file menu items. + if ( !(( pMenuItemHandler->nItemId >= START_ITEMID_WINDOWLIST && + pMenuItemHandler->nItemId < END_ITEMID_WINDOWLIST ))) + { + Reference< XDispatch > xMenuItemDispatch; + + ::rtl::OUString aItemCommand = pMenu->GetItemCommand( pMenuItemHandler->nItemId ); + if ( !aItemCommand.getLength() ) + { + aItemCommand = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "slot:" )); + aItemCommand += ::rtl::OUString::valueOf( (sal_Int32)pMenuItemHandler->nItemId ); + pMenu->SetItemCommand( pMenuItemHandler->nItemId, aItemCommand ); + } + + aTargetURL.Complete = aItemCommand; + + m_xURLTransformer->parseStrict( aTargetURL ); + + if ( bHasDisabledEntries ) + { + if ( aCmdOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED, aTargetURL.Path )) + pMenu->HideItem( pMenuItemHandler->nItemId ); + } + + if ( m_bIsBookmarkMenu ) + xMenuItemDispatch = xDispatchProvider->queryDispatch( aTargetURL, pMenuItemHandler->aTargetFrame, 0 ); + else + xMenuItemDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 ); + + sal_Bool bPopupMenu( sal_False ); + if ( !pMenuItemHandler->xPopupMenuController.is() && + m_xPopupMenuControllerRegistration->hasController( aItemCommand, rtl::OUString() )) + { + bPopupMenu = CreatePopupMenuController( pMenuItemHandler ); + } + else if ( pMenuItemHandler->xPopupMenuController.is() ) + { + // Force update of popup menu + pMenuItemHandler->xPopupMenuController->updatePopupMenu(); + bPopupMenu = sal_True; + if (PopupMenu* pThisPopup = pMenu->GetPopupMenu( pMenuItemHandler->nItemId )) + pMenu->EnableItem( pMenuItemHandler->nItemId, pThisPopup->GetItemCount() ? true : false ); + } + + lcl_CheckForChildren(pMenu, pMenuItemHandler->nItemId); + + if ( xMenuItemDispatch.is() ) + { + pMenuItemHandler->xMenuItemDispatch = xMenuItemDispatch; + pMenuItemHandler->aMenuItemURL = aTargetURL.Complete; + + if ( !bPopupMenu ) + { + // We need only an update to reflect the current state + xMenuItemDispatch->addStatusListener( static_cast< XStatusListener* >( this ), aTargetURL ); + xMenuItemDispatch->removeStatusListener( static_cast< XStatusListener* >( this ), aTargetURL ); + } + } + else if ( !bPopupMenu ) + pMenu->EnableItem( pMenuItemHandler->nItemId, sal_False ); + } + } + else if ( pMenuItemHandler->xPopupMenuController.is() ) + { + // Force update of popup menu + pMenuItemHandler->xPopupMenuController->updatePopupMenu(); + lcl_CheckForChildren(pMenu, pMenuItemHandler->nItemId); + } + else if ( pMenuItemHandler->xMenuItemDispatch.is() ) + { + // We need an update to reflect the current state + try + { + aTargetURL.Complete = pMenuItemHandler->aMenuItemURL; + m_xURLTransformer->parseStrict( aTargetURL ); + + pMenuItemHandler->xMenuItemDispatch->addStatusListener( + static_cast< XStatusListener* >( this ), aTargetURL ); + pMenuItemHandler->xMenuItemDispatch->removeStatusListener( + static_cast< XStatusListener* >( this ), aTargetURL ); + } + catch ( Exception& ) + { + } + } + else if ( pMenuItemHandler->xSubMenuManager.is() ) + lcl_CheckForChildren(pMenu, pMenuItemHandler->nItemId); + } + } + } + } + + return 1; +} + + +IMPL_LINK( MenuBarManager, Deactivate, Menu *, pMenu ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::Deactivate" ); + if ( pMenu == m_pVCLMenu ) + { + m_bActive = sal_False; + if ( pMenu->IsMenuBar() && m_xDeferedItemContainer.is() ) + { + // Start timer to handle settings asynchronous + // Changing the menu inside this handler leads to + // a crash under X! + m_aAsyncSettingsTimer.SetTimeoutHdl(LINK(this, MenuBarManager, AsyncSettingsHdl)); + m_aAsyncSettingsTimer.SetTimeout(10); + m_aAsyncSettingsTimer.Start(); + } + } + + return 1; +} + +IMPL_LINK( MenuBarManager, AsyncSettingsHdl, Timer*,) +{ + OGuard aGuard( Application::GetSolarMutex() ); + Reference< XInterface > xSelfHold( + static_cast< ::cppu::OWeakObject* >( this ), UNO_QUERY_THROW ); + + m_aAsyncSettingsTimer.Stop(); + if ( !m_bActive && m_xDeferedItemContainer.is() ) + { + SetItemContainer( m_xDeferedItemContainer ); + m_xDeferedItemContainer.clear(); + } + + return 0; +} + +IMPL_LINK( MenuBarManager, Select, Menu *, pMenu ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::Select" ); + URL aTargetURL; + Sequence<PropertyValue> aArgs; + Reference< XDispatch > xDispatch; + + { + ResetableGuard aGuard( m_aLock ); + + USHORT nCurItemId = pMenu->GetCurItemId(); + USHORT nCurPos = pMenu->GetItemPos( nCurItemId ); + if ( pMenu == m_pVCLMenu && + pMenu->GetItemType( nCurPos ) != MENUITEM_SEPARATOR ) + { + if ( nCurItemId >= START_ITEMID_WINDOWLIST && + nCurItemId <= END_ITEMID_WINDOWLIST ) + { + // window list menu item selected + + // #110897# + // Reference< XFramesSupplier > xDesktop( ::comphelper::getProcessServiceFactory()->createInstance( DESKTOP_SERVICE ), UNO_QUERY ); + Reference< XFramesSupplier > xDesktop( getServiceFactory()->createInstance( SERVICENAME_DESKTOP ), UNO_QUERY ); + + if ( xDesktop.is() ) + { + USHORT nTaskId = START_ITEMID_WINDOWLIST; + Reference< XIndexAccess > xList( xDesktop->getFrames(), UNO_QUERY ); + sal_Int32 nCount = xList->getCount(); + for ( sal_Int32 i=0; i<nCount; ++i ) + { + Reference< XFrame > xFrame; + xList->getByIndex(i) >>= xFrame; + if ( xFrame.is() && nTaskId == nCurItemId ) + { + Window* pWin = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() ); + pWin->GrabFocus(); + pWin->ToTop( TOTOP_RESTOREWHENMIN ); + break; + } + + nTaskId++; + } + } + } + else + { + MenuItemHandler* pMenuItemHandler = GetMenuItemHandler( nCurItemId ); + if ( pMenuItemHandler && pMenuItemHandler->xMenuItemDispatch.is() ) + { + aTargetURL.Complete = pMenuItemHandler->aMenuItemURL; + m_xURLTransformer->parseStrict( aTargetURL ); + + if ( m_bIsBookmarkMenu ) + { + // bookmark menu item selected + aArgs.realloc( 1 ); + aArgs[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Referer" )); + aArgs[0].Value <<= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SFX_REFERER_USER )); + } + + xDispatch = pMenuItemHandler->xMenuItemDispatch; + } + } + } + } + + if ( xDispatch.is() ) + { + const sal_uInt32 nRef = Application::ReleaseSolarMutex(); + if(::comphelper::UiEventsLogger::isEnabled()) //#i88653# + UiEventLogHelper(::rtl::OUString::createFromAscii("MenuBarManager")).log(getServiceFactory(), m_xFrame, aTargetURL, aArgs); + xDispatch->dispatch( aTargetURL, aArgs ); + Application::AcquireSolarMutex( nRef ); + } + + return 1; +} + + +IMPL_LINK( MenuBarManager, Highlight, Menu *, EMPTYARG ) +{ + return 0; +} + +sal_Bool MenuBarManager::MustBeHidden( PopupMenu* pPopupMenu, const Reference< XURLTransformer >& rTransformer ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::MustBeHidden" ); + if ( pPopupMenu ) + { + URL aTargetURL; + SvtCommandOptions aCmdOptions; + + sal_uInt16 nCount = pPopupMenu->GetItemCount(); + sal_uInt16 nHideCount( 0 ); + + for ( sal_uInt16 i = 0; i < nCount; i++ ) + { + sal_uInt16 nId = pPopupMenu->GetItemId( i ); + if ( nId > 0 ) + { + PopupMenu* pSubPopupMenu = pPopupMenu->GetPopupMenu( nId ); + if ( pSubPopupMenu ) + { + if ( MustBeHidden( pSubPopupMenu, rTransformer )) + { + pPopupMenu->HideItem( nId ); + ++nHideCount; + } + } + else + { + aTargetURL.Complete = pPopupMenu->GetItemCommand( nId ); + rTransformer->parseStrict( aTargetURL ); + + if ( aCmdOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED, aTargetURL.Path )) + ++nHideCount; + } + } + else + ++nHideCount; + } + + return ( nCount == nHideCount ); + } + + return sal_True; +} +String MenuBarManager::RetrieveLabelFromCommand( const String& aCmdURL ) +{ + return framework::RetrieveLabelFromCommand(aCmdURL,mxServiceFactory,m_xUICommandLabels,m_xFrame,m_aModuleIdentifier,m_bModuleIdentified,"Label"); +} + + + +sal_Bool MenuBarManager::CreatePopupMenuController( MenuItemHandler* pMenuItemHandler ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::CreatePopupMenuController" ); + rtl::OUString aItemCommand( pMenuItemHandler->aMenuItemURL ); + + // Try instanciate a popup menu controller. It is stored in the menu item handler. + Reference< XMultiComponentFactory > xPopupMenuControllerFactory( m_xPopupMenuControllerRegistration, UNO_QUERY ); + if ( xPopupMenuControllerFactory.is() ) + { + Sequence< Any > aSeq( 2 ); + PropertyValue aPropValue; + + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ModuleName" )); + aPropValue.Value <<= m_aModuleIdentifier; + aSeq[0] <<= aPropValue; + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" )); + aPropValue.Value <<= m_xFrame; + aSeq[1] <<= aPropValue; + + Reference< XComponentContext > xComponentContext; + Reference< XPropertySet > xProps( getServiceFactory(), UNO_QUERY ); + + xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= + xComponentContext; + + Reference< XPopupMenuController > xPopupMenuController( + xPopupMenuControllerFactory->createInstanceWithArgumentsAndContext( + aItemCommand, + aSeq, + xComponentContext ), + UNO_QUERY ); + + if ( xPopupMenuController.is() ) + { + // Provide our awt popup menu to the popup menu controller + pMenuItemHandler->xPopupMenuController = xPopupMenuController; + xPopupMenuController->setPopupMenu( pMenuItemHandler->xPopupMenu ); + return sal_True; + } + } + + return sal_False; +} + +void MenuBarManager::FillMenuManager( Menu* pMenu, const Reference< XFrame >& rFrame, const Reference< XDispatchProvider >& rDispatchProvider, const rtl::OUString& rModuleIdentifier, sal_Bool bDelete, sal_Bool bDeleteChildren ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::FillMenuManager" ); + m_xFrame = rFrame; + m_bActive = sal_False; + m_bDeleteMenu = bDelete; + m_bDeleteChildren = bDeleteChildren; + m_pVCLMenu = pMenu; + m_bInitialized = sal_False; + m_bIsBookmarkMenu = sal_False; + m_xDispatchProvider = rDispatchProvider; + + const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); + m_bWasHiContrast = rSettings.GetHighContrastMode(); + m_bShowMenuImages = rSettings.GetUseImagesInMenus(); + m_bRetrieveImages = sal_False; + + sal_Int32 nAddonsURLPrefixLength = ADDONSPOPUPMENU_URL_PREFIX.getLength(); + + // Add root as ui configuration listener + RetrieveImageManagers(); + + if ( pMenu->IsMenuBar() && rFrame.is() ) + { + // First merge all addon popup menus into our structure + USHORT nPos = 0; + for ( nPos = 0; nPos < pMenu->GetItemCount(); nPos++ ) + { + USHORT nItemId = pMenu->GetItemId( nPos ); + ::rtl::OUString aCommand = pMenu->GetItemCommand( nItemId ); + if ( nItemId == SID_MDIWINDOWLIST || + aCommand == aSpecialWindowCommand ) + { + // Retrieve addon popup menus and add them to our menu bar + Reference< com::sun::star::frame::XModel > xModel; + Reference< com::sun::star::frame::XController > xController( rFrame->getController(), UNO_QUERY ); + if ( xController.is() ) + xModel = Reference< com::sun::star::frame::XModel >( xController->getModel(), UNO_QUERY ); + framework::AddonMenuManager::MergeAddonPopupMenus( rFrame, xModel, nPos, (MenuBar *)pMenu ); + break; + } + } + + // Merge the Add-Ons help menu items into the Office help menu + framework::AddonMenuManager::MergeAddonHelpMenu( rFrame, (MenuBar *)pMenu ); + } + + String aEmpty; + sal_Bool bAccessibilityEnabled( Application::GetSettings().GetMiscSettings().GetEnableATToolSupport() ); + USHORT nItemCount = pMenu->GetItemCount(); + ::rtl::OUString aItemCommand; + m_aMenuItemHandlerVector.reserve(nItemCount); + for ( USHORT i = 0; i < nItemCount; i++ ) + { + USHORT nItemId = FillItemCommand(aItemCommand,pMenu, i ); + + // Set module identifier when provided from outside + if ( rModuleIdentifier.getLength() > 0 ) + { + m_aModuleIdentifier = rModuleIdentifier; + m_bModuleIdentified = sal_True; + } + + if (( pMenu->IsMenuBar() || bAccessibilityEnabled ) && + ( pMenu->GetItemText( nItemId ).Len() == 0 )) + { + if ( aItemCommand.getLength() > 0 ) + pMenu->SetItemText( nItemId, RetrieveLabelFromCommand( aItemCommand )); + } + + Reference< XDispatch > xDispatch; + Reference< XStatusListener > xStatusListener; + PopupMenu* pPopup = pMenu->GetPopupMenu( nItemId ); + bool bItemShowMenuImages = m_bShowMenuImages; + MenuItemBits nBits = pMenu->GetItemBits( nItemId ); + // overwrite the show icons on menu option? + if ( nBits ) + bItemShowMenuImages = ( ( nBits & MIB_ICON ) == MIB_ICON ); + if ( pPopup ) + { + // Retrieve module identifier from Help Command entry + rtl::OUString aModuleIdentifier( rModuleIdentifier ); + if ( pMenu->GetHelpCommand( nItemId ).Len() > 0 ) + { + aModuleIdentifier = pMenu->GetHelpCommand( nItemId ); + pMenu->SetHelpCommand( nItemId, aEmpty ); + } + + if ( m_xPopupMenuControllerRegistration.is() && + pPopup->GetItemCount() == 0 && + m_xPopupMenuControllerRegistration->hasController( aItemCommand, rtl::OUString() ) + ) + { + // Check if we have to create a popup menu for a uno based popup menu controller. + // We have to set an empty popup menu into our menu structure so the controller also + // works with inplace OLE. Remove old dummy popup menu! + MenuItemHandler* pItemHandler = new MenuItemHandler( nItemId, xStatusListener, xDispatch ); + VCLXPopupMenu* pVCLXPopupMenu = new VCLXPopupMenu; + PopupMenu* pNewPopupMenu = (PopupMenu *)pVCLXPopupMenu->GetMenu(); + pMenu->SetPopupMenu( nItemId, pNewPopupMenu ); + pItemHandler->xPopupMenu = Reference< com::sun::star::awt::XPopupMenu >( (OWeakObject *)pVCLXPopupMenu, UNO_QUERY ); + pItemHandler->aMenuItemURL = aItemCommand; + m_aMenuItemHandlerVector.push_back( pItemHandler ); + delete pPopup; + + if ( bAccessibilityEnabled ) + { + if ( CreatePopupMenuController( pItemHandler )) + pItemHandler->xPopupMenuController->updatePopupMenu(); + } + lcl_CheckForChildren(pMenu, nItemId); + } + else if (( aItemCommand.getLength() > nAddonsURLPrefixLength ) && + ( aItemCommand.indexOf( ADDONSPOPUPMENU_URL_PREFIX ) == 0 )) + { + // A special addon popup menu, must be created with a different ctor + // #110897# + MenuBarManager* pSubMenuManager = new MenuBarManager( getServiceFactory(), m_xFrame, m_xURLTransformer,(AddonPopupMenu *)pPopup, bDeleteChildren, bDeleteChildren ); + AddMenu(pSubMenuManager,aItemCommand,nItemId); + } + else + { + Reference< XDispatchProvider > xPopupMenuDispatchProvider( rDispatchProvider ); + + // Retrieve possible attributes struct + MenuConfiguration::Attributes* pAttributes = (MenuConfiguration::Attributes *)(pMenu->GetUserValue( nItemId )); + if ( pAttributes ) + xPopupMenuDispatchProvider = pAttributes->xDispatchProvider; + + // Check if this is the help menu. Add menu item if needed + if ( nItemId == SID_HELPMENU || aItemCommand == aSlotHelpMenu || aItemCommand == aCmdHelpMenu ) + { + // Check if this is the help menu. Add menu item if needed + CheckAndAddMenuExtension( pPopup ); + } + else if (( nItemId == SID_ADDONLIST || aItemCommand == aSlotSpecialToolsMenu || aItemCommand == aCmdToolsMenu ) && + AddonMenuManager::HasAddonMenuElements() ) + { + // Create addon popup menu if there exist elements and this is the tools popup menu + USHORT nCount = 0; + AddonMenu* pSubMenu = AddonMenuManager::CreateAddonMenu( rFrame ); + if ( pSubMenu && ( pSubMenu->GetItemCount() > 0 )) + { + if ( pPopup->GetItemType( nCount-1 ) != MENUITEM_SEPARATOR ) + pPopup->InsertSeparator(); + + // Use resource to load popup menu title + String aAddonsStrRes = String( FwkResId( STR_MENU_ADDONS )); + pPopup->InsertItem( ITEMID_ADDONLIST, aAddonsStrRes ); + pPopup->SetPopupMenu( ITEMID_ADDONLIST, pSubMenu ); + + // Set item command for popup menu to enable it for GetImageFromURL + const ::rtl::OUString aSlotString( RTL_CONSTASCII_USTRINGPARAM( "slot:" )); + ::rtl::OUString aNewItemCommand( aSlotString ); + aNewItemCommand += ::rtl::OUString::valueOf( (sal_Int32)ITEMID_ADDONLIST ); + pPopup->SetItemCommand( ITEMID_ADDONLIST, aNewItemCommand ); + } + else + delete pSubMenu; + } + + if ( nItemId == ITEMID_ADDONLIST ) + { + // Create control structure within the "Tools" sub menu for the Add-Ons popup menu + // #110897# MenuBarManager* pSubMenuManager = new MenuBarManager( rFrame, pSubMenu, sal_True, sal_False ); + AddonMenu* pSubMenu = dynamic_cast< AddonMenu* >( pPopup ); + if ( pSubMenu ) + { + MenuBarManager* pSubMenuManager = new MenuBarManager( getServiceFactory(), m_xFrame, m_xURLTransformer,pSubMenu, sal_True, sal_False ); + AddMenu(pSubMenuManager,aItemCommand,nItemId); + pSubMenuManager->m_aMenuItemCommand = ::rtl::OUString(); + + // Set image for the addon popup menu item + if ( bItemShowMenuImages && !pPopup->GetItemImage( ITEMID_ADDONLIST )) + { + Reference< XFrame > xTemp( rFrame ); + Image aImage = GetImageFromURL( xTemp, aItemCommand, FALSE, m_bWasHiContrast ); + if ( !!aImage ) + pPopup->SetItemImage( ITEMID_ADDONLIST, aImage ); + } + } + } + else + { + // #110897# MenuBarManager* pSubMenuManager = new MenuBarManager( rFrame, pPopupMenu, bDeleteChildren, bDeleteChildren ); + MenuBarManager* pSubMenuMgr = new MenuBarManager( getServiceFactory(), rFrame, m_xURLTransformer,rDispatchProvider, aModuleIdentifier, pPopup, bDeleteChildren, bDeleteChildren ); + AddMenu(pSubMenuMgr,aItemCommand,nItemId); + } + } + } + else if ( pMenu->GetItemType( i ) != MENUITEM_SEPARATOR ) + { + if ( bItemShowMenuImages ) + { + if ( AddonMenuManager::IsAddonMenuId( nItemId )) + { + // Add-Ons uses images from different places + Image aImage; + rtl::OUString aImageId; + + MenuConfiguration::Attributes* pMenuAttributes = + (MenuConfiguration::Attributes*)pMenu->GetUserValue( nItemId ); + + if ( pMenuAttributes && pMenuAttributes->aImageId.getLength() > 0 ) + { + // Retrieve image id from menu attributes + aImage = GetImageFromURL( m_xFrame, aImageId, FALSE, m_bWasHiContrast ); + } + + if ( !aImage ) + { + aImage = GetImageFromURL( m_xFrame, aItemCommand, FALSE, m_bWasHiContrast ); + if ( !aImage ) + aImage = AddonsOptions().GetImageFromURL( aItemCommand, FALSE, m_bWasHiContrast ); + } + + if ( !!aImage ) + pMenu->SetItemImage( nItemId, aImage ); + else + m_bRetrieveImages = sal_True; + } + m_bRetrieveImages = sal_True; + } + + MenuItemHandler* pItemHandler = new MenuItemHandler( nItemId, xStatusListener, xDispatch ); + pItemHandler->aMenuItemURL = aItemCommand; + + if ( m_xPopupMenuControllerRegistration.is() && + m_xPopupMenuControllerRegistration->hasController( aItemCommand, rtl::OUString() )) + { + // Check if we have to create a popup menu for a uno based popup menu controller. + // We have to set an empty popup menu into our menu structure so the controller also + // works with inplace OLE. + VCLXPopupMenu* pVCLXPopupMenu = new VCLXPopupMenu; + PopupMenu* pPopupMenu = (PopupMenu *)pVCLXPopupMenu->GetMenu(); + pMenu->SetPopupMenu( pItemHandler->nItemId, pPopupMenu ); + pItemHandler->xPopupMenu = Reference< com::sun::star::awt::XPopupMenu >( (OWeakObject *)pVCLXPopupMenu, UNO_QUERY ); + + if ( bAccessibilityEnabled && CreatePopupMenuController( pItemHandler ) ) + { + pItemHandler->xPopupMenuController->updatePopupMenu(); + } + + lcl_CheckForChildren(pMenu, pItemHandler->nItemId); + } + + m_aMenuItemHandlerVector.push_back( pItemHandler ); + } + } + + if ( bAccessibilityEnabled ) + { + RetrieveShortcuts( m_aMenuItemHandlerVector ); + std::vector< MenuItemHandler* >::iterator p; + for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ ) + { + MenuItemHandler* pMenuItemHandler = *p; + + // Set key code, workaround for hard-coded shortcut F1 mapped to .uno:HelpIndex + // Only non-popup menu items can have a short-cut + if ( pMenuItemHandler->aMenuItemURL == aCmdHelpIndex ) + { + KeyCode aKeyCode( KEY_F1 ); + pMenu->SetAccelKey( pMenuItemHandler->nItemId, aKeyCode ); + } + else if ( pMenu->GetPopupMenu( pMenuItemHandler->nItemId ) == 0 ) + pMenu->SetAccelKey( pMenuItemHandler->nItemId, pMenuItemHandler->aKeyCode ); + } + } + + SetHdl(); +} + +void MenuBarManager::impl_RetrieveShortcutsFromConfiguration( + const Reference< XAcceleratorConfiguration >& rAccelCfg, + const Sequence< rtl::OUString >& rCommands, + std::vector< MenuItemHandler* >& aMenuShortCuts ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::impl_RetrieveShortcutsFromConfiguration" ); + if ( rAccelCfg.is() ) + { + try + { + com::sun::star::awt::KeyEvent aKeyEvent; + Sequence< Any > aSeqKeyCode = rAccelCfg->getPreferredKeyEventsForCommandList( rCommands ); + for ( sal_Int32 i = 0; i < aSeqKeyCode.getLength(); i++ ) + { + if ( aSeqKeyCode[i] >>= aKeyEvent ) + aMenuShortCuts[i]->aKeyCode = svt::AcceleratorExecute::st_AWTKey2VCLKey( aKeyEvent ); + } + } + catch ( IllegalArgumentException& ) + { + } + } +} + +void MenuBarManager::RetrieveShortcuts( std::vector< MenuItemHandler* >& aMenuShortCuts ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::RetrieveShortcuts" ); + if ( !m_bModuleIdentified ) + { + m_bModuleIdentified = sal_True; + Reference< XModuleManager > xModuleManager; + xModuleManager = Reference< XModuleManager >( getServiceFactory()->createInstance( SERVICENAME_MODULEMANAGER ), UNO_QUERY_THROW ); + + try + { + m_aModuleIdentifier = xModuleManager->identify( m_xFrame ); + } + catch( Exception& ) + { + } + } + + if ( m_bModuleIdentified ) + { + Reference< XAcceleratorConfiguration > xDocAccelCfg( m_xDocAcceleratorManager ); + Reference< XAcceleratorConfiguration > xModuleAccelCfg( m_xModuleAcceleratorManager ); + Reference< XAcceleratorConfiguration > xGlobalAccelCfg( m_xGlobalAcceleratorManager ); + + if ( !m_bAcceleratorCfg ) + { + // Retrieve references on demand + m_bAcceleratorCfg = sal_True; + if ( !xDocAccelCfg.is() ) + { + Reference< XController > xController = m_xFrame->getController(); + Reference< XModel > xModel; + if ( xController.is() ) + { + xModel = xController->getModel(); + if ( xModel.is() ) + { + Reference< XUIConfigurationManagerSupplier > xSupplier( xModel, UNO_QUERY ); + if ( xSupplier.is() ) + { + Reference< XUIConfigurationManager > xDocUICfgMgr( xSupplier->getUIConfigurationManager(), UNO_QUERY ); + if ( xDocUICfgMgr.is() ) + { + xDocAccelCfg = Reference< XAcceleratorConfiguration >( xDocUICfgMgr->getShortCutManager(), UNO_QUERY ); + m_xDocAcceleratorManager = xDocAccelCfg; + } + } + } + } + } + + if ( !xModuleAccelCfg.is() ) + { + Reference< XModuleUIConfigurationManagerSupplier > xModuleCfgMgrSupplier( getServiceFactory()->createInstance( + SERVICENAME_MODULEUICONFIGURATIONMANAGERSUPPLIER ), + UNO_QUERY ); + try + { + Reference< XUIConfigurationManager > xUICfgMgr = xModuleCfgMgrSupplier->getUIConfigurationManager( m_aModuleIdentifier ); + if ( xUICfgMgr.is() ) + { + xModuleAccelCfg = Reference< XAcceleratorConfiguration >( xUICfgMgr->getShortCutManager(), UNO_QUERY ); + m_xModuleAcceleratorManager = xModuleAccelCfg; + } + } + catch ( RuntimeException& ) + { + throw; + } + catch ( Exception& ) + { + } + } + + if ( !xGlobalAccelCfg.is() ) + { + xGlobalAccelCfg = Reference< XAcceleratorConfiguration >( getServiceFactory()->createInstance( + SERVICENAME_GLOBALACCELERATORCONFIGURATION ), + UNO_QUERY ); + m_xGlobalAcceleratorManager = xGlobalAccelCfg; + } + } + + KeyCode aEmptyKeyCode; + Sequence< rtl::OUString > aSeq( aMenuShortCuts.size() ); + const sal_uInt32 nCount = aMenuShortCuts.size(); + for ( sal_uInt32 i = 0; i < nCount; ++i ) + { + aSeq[i] = aMenuShortCuts[i]->aMenuItemURL; + aMenuShortCuts[i]->aKeyCode = aEmptyKeyCode; + } + + if ( m_xGlobalAcceleratorManager.is() ) + impl_RetrieveShortcutsFromConfiguration( xGlobalAccelCfg, aSeq, aMenuShortCuts ); + if ( m_xModuleAcceleratorManager.is() ) + impl_RetrieveShortcutsFromConfiguration( xModuleAccelCfg, aSeq, aMenuShortCuts ); + if ( m_xDocAcceleratorManager.is() ) + impl_RetrieveShortcutsFromConfiguration( xGlobalAccelCfg, aSeq, aMenuShortCuts ); + } +} + +void MenuBarManager::RetrieveImageManagers() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::RetrieveImageManagers" ); + if ( !m_xDocImageManager.is() ) + { + Reference< XController > xController = m_xFrame->getController(); + Reference< XModel > xModel; + if ( xController.is() ) + { + xModel = xController->getModel(); + if ( xModel.is() ) + { + Reference< XUIConfigurationManagerSupplier > xSupplier( xModel, UNO_QUERY ); + if ( xSupplier.is() ) + { + Reference< XUIConfigurationManager > xDocUICfgMgr( xSupplier->getUIConfigurationManager(), UNO_QUERY ); + m_xDocImageManager = Reference< XImageManager >( xDocUICfgMgr->getImageManager(), UNO_QUERY ); + m_xDocImageManager->addConfigurationListener( + Reference< XUIConfigurationListener >( + static_cast< OWeakObject* >( this ), UNO_QUERY )); + } + } + } + } + + Reference< XModuleManager > xModuleManager; + if ( m_aModuleIdentifier.getLength() == 0 ) + xModuleManager.set( getServiceFactory()->createInstance( SERVICENAME_MODULEMANAGER ), UNO_QUERY_THROW ); + + try + { + if ( xModuleManager.is() ) + m_aModuleIdentifier = xModuleManager->identify( Reference< XInterface >( m_xFrame, UNO_QUERY ) ); + } + catch( Exception& ) + { + } + + if ( !m_xModuleImageManager.is() ) + { + Reference< XModuleUIConfigurationManagerSupplier > xModuleCfgMgrSupplier( getServiceFactory()->createInstance( + SERVICENAME_MODULEUICONFIGURATIONMANAGERSUPPLIER ), + UNO_QUERY ); + Reference< XUIConfigurationManager > xUICfgMgr = xModuleCfgMgrSupplier->getUIConfigurationManager( m_aModuleIdentifier ); + m_xModuleImageManager.set( xUICfgMgr->getImageManager(), UNO_QUERY ); + m_xModuleImageManager->addConfigurationListener( Reference< XUIConfigurationListener >( + static_cast< OWeakObject* >( this ), UNO_QUERY )); + } +} + +void MenuBarManager::FillMenuWithConfiguration( + USHORT& nId, + Menu* pMenu, + const ::rtl::OUString& rModuleIdentifier, + const Reference< XIndexAccess >& rItemContainer, + const Reference< XURLTransformer >& rTransformer ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::FillMenuWithConfiguration" ); + Reference< XDispatchProvider > xEmptyDispatchProvider; + MenuBarManager::FillMenu( nId, pMenu, rModuleIdentifier, rItemContainer, xEmptyDispatchProvider ); + + // Merge add-on menu entries into the menu bar + MenuBarManager::MergeAddonMenus( static_cast< Menu* >( pMenu ), + AddonsOptions().GetMergeMenuInstructions(), + rModuleIdentifier ); + + sal_Bool bHasDisabledEntries = SvtCommandOptions().HasEntries( SvtCommandOptions::CMDOPTION_DISABLED ); + if ( bHasDisabledEntries ) + { + sal_uInt16 nCount = pMenu->GetItemCount(); + for ( sal_uInt16 i = 0; i < nCount; i++ ) + { + sal_uInt16 nID = pMenu->GetItemId( i ); + if ( nID > 0 ) + { + PopupMenu* pPopupMenu = pMenu->GetPopupMenu( nID ); + if ( pPopupMenu ) + { + if ( MustBeHidden( pPopupMenu, rTransformer )) + pMenu->HideItem( nId ); + } + } + } + } +} + +void MenuBarManager::FillMenu( + USHORT& nId, + Menu* pMenu, + const rtl::OUString& rModuleIdentifier, + const Reference< XIndexAccess >& rItemContainer, + const Reference< XDispatchProvider >& rDispatchProvider ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::FillMenu" ); + // Fill menu bar with container contents + for ( sal_Int32 n = 0; n < rItemContainer->getCount(); n++ ) + { + Sequence< PropertyValue > aProp; + rtl::OUString aCommandURL; + rtl::OUString aLabel; + rtl::OUString aHelpURL; + rtl::OUString aModuleIdentifier( rModuleIdentifier ); + sal_uInt16 nType = 0; + Reference< XIndexAccess > xIndexContainer; + Reference< XDispatchProvider > xDispatchProvider( rDispatchProvider ); + sal_Int16 nStyle = 0; + try + { + if ( rItemContainer->getByIndex( n ) >>= aProp ) + { + for ( int i = 0; i < aProp.getLength(); i++ ) + { + rtl::OUString aPropName = aProp[i].Name; + if ( aPropName.equalsAsciiL( ITEM_DESCRIPTOR_COMMANDURL, + LEN_DESCRIPTOR_COMMANDURL )) + aProp[i].Value >>= aCommandURL; + else if ( aPropName.equalsAsciiL( ITEM_DESCRIPTOR_HELPURL, + LEN_DESCRIPTOR_HELPURL )) + aProp[i].Value >>= aHelpURL; + else if ( aPropName.equalsAsciiL( ITEM_DESCRIPTOR_CONTAINER, + LEN_DESCRIPTOR_CONTAINER )) + aProp[i].Value >>= xIndexContainer; + else if ( aPropName.equalsAsciiL( ITEM_DESCRIPTOR_LABEL, + LEN_DESCRIPTOR_LABEL )) + aProp[i].Value >>= aLabel; + else if ( aPropName.equalsAsciiL( ITEM_DESCRIPTOR_TYPE, + LEN_DESCRIPTOR_TYPE )) + aProp[i].Value >>= nType; + else if ( aPropName.equalsAsciiL( ITEM_DESCRIPTOR_MODULEIDENTIFIER, + LEN_DESCRIPTOR_MODULEIDENTIFIER )) + aProp[i].Value >>= aModuleIdentifier; + else if ( aPropName.equalsAsciiL( ITEM_DESCRIPTOR_DISPATCHPROVIDER, + LEN_DESCRIPTOR_DISPATCHPROVIDER )) + aProp[i].Value >>= xDispatchProvider; + else if ( aProp[i].Name.equalsAsciiL( ITEM_DESCRIPTOR_STYLE, ITEM_DESCRIPTOR_STYLE_LEN )) + aProp[i].Value >>= nStyle; + } + + if ( nType == ::com::sun::star::ui::ItemType::DEFAULT ) + { + pMenu->InsertItem( nId, aLabel ); + pMenu->SetItemCommand( nId, aCommandURL ); + + sal_Int32 nHelpId = aHelpURL.toInt32(); + if ( nHelpId > 0 ) + pMenu->SetHelpId( nId, (USHORT)nHelpId ); + if ( nStyle ) + { + MenuItemBits nBits = pMenu->GetItemBits( nId ); + if ( nStyle & ::com::sun::star::ui::ItemStyle::ICON ) + nBits |= MIB_ICON; + if ( nStyle & ::com::sun::star::ui::ItemStyle::TEXT ) + nBits |= MIB_TEXT; + pMenu->SetItemBits( nId, nBits ); + } + if ( xIndexContainer.is() ) + { + PopupMenu* pNewPopupMenu = new PopupMenu; + pMenu->SetPopupMenu( nId, pNewPopupMenu ); + + if ( xDispatchProvider.is() ) + { + // Use attributes struct to transport special dispatch provider + MenuConfiguration::Attributes* pAttributes = new MenuConfiguration::Attributes; + pAttributes->xDispatchProvider = xDispatchProvider; + pMenu->SetUserValue( nId, (ULONG)( pAttributes )); + } + + // Use help command to transport module identifier + if ( aModuleIdentifier.getLength() > 0 ) + pMenu->SetHelpCommand( nId, aModuleIdentifier ); + + ++nId; + FillMenu( nId, pNewPopupMenu, aModuleIdentifier, xIndexContainer, xDispatchProvider ); + } + else + ++nId; + } + else + { + pMenu->InsertSeparator(); + ++nId; + } + } + } + catch ( IndexOutOfBoundsException& ) + { + break; + } + } +} + +void MenuBarManager::MergeAddonMenus( + Menu* pMenuBar, + const MergeMenuInstructionContainer& aMergeInstructionContainer, + const ::rtl::OUString& rModuleIdentifier ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::MergeAddonMenus" ); + // set start value for the item ID for the new addon menu items + sal_uInt16 nItemId = ADDONMENU_MERGE_ITEMID_START; + + const sal_uInt32 nCount = aMergeInstructionContainer.size(); + for ( sal_uInt32 i = 0; i < nCount; i++ ) + { + const MergeMenuInstruction& rMergeInstruction = aMergeInstructionContainer[i]; + + if ( MenuBarMerger::IsCorrectContext( rMergeInstruction.aMergeContext, rModuleIdentifier )) + { + ::std::vector< ::rtl::OUString > aMergePath; + + // retrieve the merge path from the merge point string + MenuBarMerger::RetrieveReferencePath( rMergeInstruction.aMergePoint, aMergePath ); + + // convert the sequence/sequence property value to a more convenient vector<> + AddonMenuContainer aMergeMenuItems; + MenuBarMerger::GetSubMenu( rMergeInstruction.aMergeMenu, aMergeMenuItems ); + + // try to find the reference point for our merge operation + Menu* pMenu = pMenuBar; + ReferencePathInfo aResult = MenuBarMerger::FindReferencePath( aMergePath, pMenu ); + + if ( aResult.eResult == RP_OK ) + { + // normal merge operation + MenuBarMerger::ProcessMergeOperation( aResult.pPopupMenu, + aResult.nPos, + nItemId, + rMergeInstruction.aMergeCommand, + rMergeInstruction.aMergeCommandParameter, + rModuleIdentifier, + aMergeMenuItems ); + } + else + { + // fallback + MenuBarMerger::ProcessFallbackOperation( aResult, + nItemId, + rMergeInstruction.aMergeCommand, + rMergeInstruction.aMergeFallback, + aMergePath, + rModuleIdentifier, + aMergeMenuItems ); + } + } + } +} + +void MenuBarManager::SetItemContainer( const Reference< XIndexAccess >& rItemContainer ) +{ + RTL_LOGFILE_CONTEXT( aLog, "framework (cd100003) ::MenuBarManager::SetItemContainer" ); + + ResetableGuard aGuard( m_aLock ); + + Reference< XFrame > xFrame = m_xFrame; + + if ( !m_bModuleIdentified ) + { + m_bModuleIdentified = sal_True; + Reference< XModuleManager > xModuleManager; + xModuleManager = Reference< XModuleManager >( getServiceFactory()->createInstance( SERVICENAME_MODULEMANAGER ), UNO_QUERY_THROW ); + + try + { + m_aModuleIdentifier = xModuleManager->identify( xFrame ); + } + catch( Exception& ) + { + } + } + + // Clear MenuBarManager structures + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + // Check active state as we cannot change our VCL menu during activation by the user + if ( m_bActive ) + { + m_xDeferedItemContainer = rItemContainer; + return; + } + + RemoveListener(); + std::vector< MenuItemHandler* >::iterator p; + for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ ) + { + MenuItemHandler* pItemHandler = *p; + pItemHandler->xMenuItemDispatch.clear(); + pItemHandler->xSubMenuManager.clear(); + delete pItemHandler; + } + m_aMenuItemHandlerVector.clear(); + + // Remove top-level parts + m_pVCLMenu->Clear(); + + USHORT nId = 1; + + // Fill menu bar with container contents + FillMenuWithConfiguration( nId, (Menu *)m_pVCLMenu, m_aModuleIdentifier, rItemContainer, m_xURLTransformer ); + + // Refill menu manager again + Reference< XDispatchProvider > xDispatchProvider; + FillMenuManager( m_pVCLMenu, xFrame, xDispatchProvider, m_aModuleIdentifier, sal_False, sal_True ); + + // add itself as frame action listener + m_xFrame->addFrameActionListener( Reference< XFrameActionListener >( static_cast< OWeakObject* >( this ), UNO_QUERY )); + } +} + +void MenuBarManager::GetPopupController( PopupControllerCache& rPopupController ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::GetPopupController" ); + String aPopupScheme = String::CreateFromAscii( "vnd.sun.star.popup:" ); + + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + std::vector< MenuItemHandler* >::iterator p; + for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ ) + { + MenuItemHandler* pItemHandler = *p; + if ( pItemHandler->xPopupMenuController.is() ) + { + Reference< XDispatchProvider > xDispatchProvider( pItemHandler->xPopupMenuController, UNO_QUERY ); + + PopupControllerEntry aPopupControllerEntry; + aPopupControllerEntry.m_xDispatchProvider = xDispatchProvider; + + // Just use the main part of the URL for popup menu controllers + sal_Int32 nQueryPart( 0 ); + sal_Int32 nSchemePart( 0 ); + rtl::OUString aMainURL( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.popup:" )); + rtl::OUString aMenuURL( pItemHandler->aMenuItemURL ); + + nSchemePart = aMenuURL.indexOf( ':' ); + if (( nSchemePart > 0 ) && + ( aMenuURL.getLength() > ( nSchemePart+1 ))) + { + nQueryPart = aMenuURL.indexOf( '?', nSchemePart ); + if ( nQueryPart > 0 ) + aMainURL += aMenuURL.copy( nSchemePart, nQueryPart-nSchemePart ); + else if ( nQueryPart == -1 ) + aMainURL += aMenuURL.copy( nSchemePart+1 ); + + rPopupController.insert( PopupControllerCache::value_type( + aMainURL, aPopupControllerEntry )); + } + } + if ( pItemHandler->xSubMenuManager.is() ) + { + MenuBarManager* pMenuBarManager = (MenuBarManager*)(pItemHandler->xSubMenuManager.get()); + if ( pMenuBarManager ) + pMenuBarManager->GetPopupController( rPopupController ); + } + } +} + +// #110897# +const Reference< XMultiServiceFactory >& MenuBarManager::getServiceFactory() +{ + // #110897# + return mxServiceFactory; +} + +void MenuBarManager::AddMenu(MenuBarManager* pSubMenuManager,const ::rtl::OUString& _sItemCommand,USHORT _nItemId) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::AddMenu" ); + Reference< XStatusListener > xSubMenuManager( static_cast< OWeakObject *>( pSubMenuManager ), UNO_QUERY ); + m_xFrame->addFrameActionListener( Reference< XFrameActionListener >( xSubMenuManager, UNO_QUERY )); + + // store menu item command as we later have to know which menu is active (see Activate handler) + pSubMenuManager->m_aMenuItemCommand = _sItemCommand; + Reference< XDispatch > xDispatch; + MenuItemHandler* pMenuItemHandler = new MenuItemHandler( + _nItemId, + xSubMenuManager, + xDispatch ); + pMenuItemHandler->aMenuItemURL = _sItemCommand; + m_aMenuItemHandlerVector.push_back( pMenuItemHandler ); +} + +USHORT MenuBarManager::FillItemCommand(::rtl::OUString& _rItemCommand,Menu* _pMenu,USHORT _nIndex) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::FillItemCommand" ); + USHORT nItemId = _pMenu->GetItemId( _nIndex ); + + _rItemCommand = _pMenu->GetItemCommand( nItemId ); + if ( !_rItemCommand.getLength() ) + { + const static ::rtl::OUString aSlotString( RTL_CONSTASCII_USTRINGPARAM( "slot:" )); + _rItemCommand = aSlotString; + _rItemCommand += ::rtl::OUString::valueOf( (sal_Int32)nItemId ); + _pMenu->SetItemCommand( nItemId, _rItemCommand ); + } + return nItemId; +} +void MenuBarManager::Init(const Reference< XFrame >& rFrame,AddonMenu* pAddonMenu,sal_Bool bDelete,sal_Bool bDeleteChildren,bool _bHandlePopUp) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::Init" ); + m_bActive = sal_False; + m_bDeleteMenu = bDelete; + m_bDeleteChildren = bDeleteChildren; + m_pVCLMenu = pAddonMenu; + m_xFrame = rFrame; + m_bInitialized = sal_False; + m_bIsBookmarkMenu = sal_True; + + rtl::OUString aModuleIdentifier; + m_xPopupMenuControllerRegistration = Reference< ::com::sun::star::frame::XUIControllerRegistration >( + getServiceFactory()->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.PopupMenuControllerFactory" ))), + UNO_QUERY ); + + const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); + m_bWasHiContrast = rSettings.GetHighContrastMode(); + + Reference< XStatusListener > xStatusListener; + Reference< XDispatch > xDispatch; + USHORT nItemCount = pAddonMenu->GetItemCount(); + ::rtl::OUString aItemCommand; + m_aMenuItemHandlerVector.reserve(nItemCount); + for ( USHORT i = 0; i < nItemCount; i++ ) + { + USHORT nItemId = FillItemCommand(aItemCommand,pAddonMenu, i ); + + PopupMenu* pPopupMenu = pAddonMenu->GetPopupMenu( nItemId ); + if ( pPopupMenu ) + { + // #110897# + Reference< XDispatchProvider > xDispatchProvider; + MenuBarManager* pSubMenuManager = new MenuBarManager( getServiceFactory(), rFrame, m_xURLTransformer,xDispatchProvider, aModuleIdentifier, pPopupMenu, _bHandlePopUp ? sal_False : bDeleteChildren, _bHandlePopUp ? sal_False : bDeleteChildren ); + + Reference< XStatusListener > xSubMenuManager( static_cast< OWeakObject *>( pSubMenuManager ), UNO_QUERY ); + + // store menu item command as we later have to know which menu is active (see Acivate handler) + pSubMenuManager->m_aMenuItemCommand = aItemCommand; + + MenuItemHandler* pMenuItemHandler = new MenuItemHandler( + nItemId, + xSubMenuManager, + xDispatch ); + m_aMenuItemHandlerVector.push_back( pMenuItemHandler ); + } + else + { + if ( pAddonMenu->GetItemType( i ) != MENUITEM_SEPARATOR ) + { + MenuConfiguration::Attributes* pAddonAttributes = (MenuConfiguration::Attributes *)(pAddonMenu->GetUserValue( nItemId )); + MenuItemHandler* pMenuItemHandler = new MenuItemHandler( nItemId, xStatusListener, xDispatch ); + + if ( pAddonAttributes ) + { + // read additional attributes from attributes struct and AddonMenu implementation will delete all attributes itself!! + pMenuItemHandler->aTargetFrame = pAddonAttributes->aTargetFrame; + } + + pMenuItemHandler->aMenuItemURL = aItemCommand; + if ( _bHandlePopUp ) + { + // Check if we have to create a popup menu for a uno based popup menu controller. + // We have to set an empty popup menu into our menu structure so the controller also + // works with inplace OLE. + if ( m_xPopupMenuControllerRegistration.is() && + m_xPopupMenuControllerRegistration->hasController( aItemCommand, rtl::OUString() )) + { + VCLXPopupMenu* pVCLXPopupMenu = new VCLXPopupMenu; + PopupMenu* pCtlPopupMenu = (PopupMenu *)pVCLXPopupMenu->GetMenu(); + pAddonMenu->SetPopupMenu( pMenuItemHandler->nItemId, pCtlPopupMenu ); + pMenuItemHandler->xPopupMenu = Reference< com::sun::star::awt::XPopupMenu >( (OWeakObject *)pVCLXPopupMenu, UNO_QUERY ); + + } + } + m_aMenuItemHandlerVector.push_back( pMenuItemHandler ); + } + } + } + + SetHdl(); +} + +void MenuBarManager::SetHdl() +{ + m_pVCLMenu->SetHighlightHdl( LINK( this, MenuBarManager, Highlight )); + m_pVCLMenu->SetActivateHdl( LINK( this, MenuBarManager, Activate )); + m_pVCLMenu->SetDeactivateHdl( LINK( this, MenuBarManager, Deactivate )); + m_pVCLMenu->SetSelectHdl( LINK( this, MenuBarManager, Select )); + + if ( !m_xURLTransformer.is() && mxServiceFactory.is() ) + m_xURLTransformer.set( mxServiceFactory->createInstance( + SERVICENAME_URLTRANSFORMER), + UNO_QUERY ); +} + +} diff --git a/framework/source/uielement/menubarmerger.cxx b/framework/source/uielement/menubarmerger.cxx new file mode 100644 index 000000000000..f82253345778 --- /dev/null +++ b/framework/source/uielement/menubarmerger.cxx @@ -0,0 +1,441 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + +#include <uielement/menubarmerger.hxx> +#include <classes/addonsoptions.hxx> + +using namespace ::com::sun::star; + +static const char SEPARATOR_STRING[] = "private:separator"; +static const sal_uInt32 SEPARATOR_STRING_LEN = 17; + +static const char MERGECOMMAND_ADDAFTER[] = "AddAfter"; +static const sal_uInt32 MERGECOMMAND_ADDAFTER_LEN = 8; +static const char MERGECOMMAND_ADDBEFORE[] = "AddBefore"; +static const sal_uInt32 MERGECOMMAND_ADDBEFORE_LEN = 9; +static const char MERGECOMMAND_REPLACE[] = "Replace"; +static const sal_uInt32 MERGECOMMAND_REPLACE_LEN = 7; +static const char MERGECOMMAND_REMOVE[] = "Remove"; +static const sal_uInt32 MERGECOMMAND_REMOVE_LEN = 6; + +static const char MERGEFALLBACK_ADDPATH[] = "AddPath"; +static const char MERGEFALLBACK_ADDPATH_LEN = 7; +static const char MERGEFALLBACK_IGNORE[] = "Ignore"; +static const char MERGEFALLBACK_IGNORE_LEN = 6; + + +namespace framework +{ + +/** + Check whether a module identifier is part of a context + defined by a colon separated list of module identifier. + + @param + rContext + + Describes a context string list where all contexts + are delimited by a colon. For more information about + the module identifier used as context strings see the + IDL description of com::sun::star::frame::XModuleManager + + @param + rModuleIdentifier + + A string describing a module identifier. See IDL + description of com::sun::star::frame::XModuleManager. + +*/ +bool MenuBarMerger::IsCorrectContext( const ::rtl::OUString& rContext, const ::rtl::OUString& rModuleIdentifier ) +{ + return (( rContext.getLength() == 0 ) || ( rContext.indexOf( rModuleIdentifier ) >= 0 )); +} + +void MenuBarMerger::RetrieveReferencePath( + const ::rtl::OUString& rReferencePathString, + ::std::vector< ::rtl::OUString >& rReferencePath ) +{ + const sal_Char aDelimiter = '\\'; + + rReferencePath.clear(); + sal_Int32 nIndex( 0 ); + do + { + ::rtl::OUString aToken = rReferencePathString.getToken( 0, aDelimiter, nIndex ); + if ( aToken.getLength() > 0 ) + rReferencePath.push_back( aToken ); + } + while ( nIndex >= 0 ); +} + +ReferencePathInfo MenuBarMerger::FindReferencePath( + const ::std::vector< ::rtl::OUString >& rReferencePath, + Menu* pMenu ) +{ + sal_uInt32 i( 0 ); + const sal_uInt32 nCount( rReferencePath.size() ); + Menu* pCurrMenu( pMenu ); + RPResultInfo eResult( RP_OK ); + + sal_Int32 nLevel( - 1 ); + sal_uInt16 nPos( MENU_ITEM_NOTFOUND ); + do + { + ++nLevel; + ::rtl::OUString aCmd( rReferencePath[i] ); + + if ( i == nCount-1 ) + { + // Check last reference path element. Must be a leave (menu item). + sal_uInt16 nTmpPos = FindMenuItem( aCmd, pCurrMenu ); + if ( nTmpPos != MENU_ITEM_NOTFOUND ) + nPos = nTmpPos; + eResult = ( nTmpPos != MENU_ITEM_NOTFOUND ) ? RP_OK : RP_MENUITEM_NOT_FOUND; + } + else + { + // Check reference path element. Must be a node (popup menu)! + sal_uInt16 nTmpPos = FindMenuItem( aCmd, pCurrMenu ); + if ( nTmpPos != MENU_ITEM_NOTFOUND ) + { + sal_uInt16 nItemId = pCurrMenu->GetItemId( nTmpPos ); + Menu* pTmpMenu = pCurrMenu->GetPopupMenu( nItemId ); + if ( pTmpMenu != 0 ) + pCurrMenu = pTmpMenu; + else + { + nPos = nTmpPos; + eResult = RP_MENUITEM_INSTEAD_OF_POPUPMENU_FOUND; + } + } + else + eResult = RP_POPUPMENU_NOT_FOUND; + } + i++; + } + while (( pCurrMenu != 0 ) && ( i < nCount ) && ( eResult == RP_OK )); + + ReferencePathInfo aResult; + aResult.pPopupMenu = pCurrMenu; + aResult.nPos = nPos; + aResult.nLevel = nLevel; + aResult.eResult = eResult; + + return aResult; +} + +sal_uInt16 MenuBarMerger::FindMenuItem( const ::rtl::OUString& rCmd, Menu* pCurrMenu ) +{ + for ( sal_uInt16 i = 0; i < pCurrMenu->GetItemCount(); i++ ) + { + const sal_uInt16 nItemId = pCurrMenu->GetItemId( i ); + if ( nItemId > 0 ) + { + if ( rCmd == ::rtl::OUString( pCurrMenu->GetItemCommand( nItemId ))) + return i; + } + } + + return MENU_ITEM_NOTFOUND; +} + +bool MenuBarMerger::CreateSubMenu( + Menu* pSubMenu, + sal_uInt16& nItemId, + const ::rtl::OUString& rModuleIdentifier, + const AddonMenuContainer& rAddonSubMenu ) +{ + const sal_uInt32 nSize = rAddonSubMenu.size(); + for ( sal_uInt32 i = 0; i < nSize; i++ ) + { + const AddonMenuItem& rMenuItem = rAddonSubMenu[i]; + + if ( IsCorrectContext( rMenuItem.aContext, rModuleIdentifier )) + { + if ( rMenuItem.aURL.equalsAsciiL( SEPARATOR_STRING, SEPARATOR_STRING_LEN )) + { + pSubMenu->InsertSeparator( MENU_APPEND ); + } + else + { + pSubMenu->InsertItem( nItemId, rMenuItem.aTitle, 0, MENU_APPEND ); + pSubMenu->SetItemCommand( nItemId, rMenuItem.aURL ); + if ( !rMenuItem.aSubMenu.empty() ) + { + PopupMenu* pPopupMenu = new PopupMenu(); + pSubMenu->SetPopupMenu( nItemId, pPopupMenu ); + ++nItemId; + + CreateSubMenu( pPopupMenu, nItemId, rModuleIdentifier, rMenuItem.aSubMenu ); + } + else + ++nItemId; + } + } + } + + return true; +} + +bool MenuBarMerger::MergeMenuItems( + Menu* pMenu, + sal_uInt16 nPos, + sal_uInt16 nModIndex, + sal_uInt16& nItemId, + const ::rtl::OUString& rModuleIdentifier, + const AddonMenuContainer& rAddonMenuItems ) +{ + sal_uInt16 nIndex( 0 ); + const sal_uInt32 nSize = rAddonMenuItems.size(); + for ( sal_uInt32 i = 0; i < nSize; i++ ) + { + const AddonMenuItem& rMenuItem = rAddonMenuItems[i]; + + if ( IsCorrectContext( rMenuItem.aContext, rModuleIdentifier )) + { + if ( rMenuItem.aURL.equalsAsciiL( SEPARATOR_STRING, SEPARATOR_STRING_LEN )) + { + pMenu->InsertSeparator( nPos+nModIndex+nIndex ); + } + else + { + pMenu->InsertItem( nItemId, rMenuItem.aTitle, 0, nPos+nModIndex+nIndex ); + pMenu->SetItemCommand( nItemId, rMenuItem.aURL ); + if ( !rMenuItem.aSubMenu.empty() ) + { + PopupMenu* pSubMenu = new PopupMenu(); + pMenu->SetPopupMenu( nItemId, pSubMenu ); + ++nItemId; + + CreateSubMenu( pSubMenu, nItemId, rModuleIdentifier, rMenuItem.aSubMenu ); + } + else + ++nItemId; + } + ++nIndex; + } + } + + return true; +} + +bool MenuBarMerger::ReplaceMenuItem( + Menu* pMenu, + sal_uInt16 nPos, + sal_uInt16& rItemId, + const ::rtl::OUString& rModuleIdentifier, + const AddonMenuContainer& rAddonMenuItems ) +{ + // There is no replace available. Therfore we first have to + // remove the old menu entry, + pMenu->RemoveItem( nPos ); + + return MergeMenuItems( pMenu, nPos, 0, rItemId, rModuleIdentifier, rAddonMenuItems ); +} + +bool MenuBarMerger::RemoveMenuItems( + Menu* pMenu, + sal_uInt16 nPos, + const ::rtl::OUString& rMergeCommandParameter ) +{ + const sal_uInt16 nParam( sal_uInt16( rMergeCommandParameter.toInt32() )); + sal_uInt16 nCount( 1 ); + + nCount = std::max( nParam, nCount ); + + sal_uInt16 i = 0; + while (( nPos < pMenu->GetItemCount() ) && ( i < nCount )) + { + pMenu->RemoveItem( nPos ); + ++i; + } + + return true; +} + +bool MenuBarMerger::ProcessMergeOperation( + Menu* pMenu, + sal_uInt16 nPos, + sal_uInt16& nItemId, + const ::rtl::OUString& rMergeCommand, + const ::rtl::OUString& rMergeCommandParameter, + const ::rtl::OUString& rModuleIdentifier, + const AddonMenuContainer& rAddonMenuItems ) +{ + sal_uInt16 nModIndex( 0 ); + + if ( rMergeCommand.equalsAsciiL( MERGECOMMAND_ADDBEFORE, MERGECOMMAND_ADDBEFORE_LEN )) + { + nModIndex = 0; + return MergeMenuItems( pMenu, nPos, nModIndex, nItemId, rModuleIdentifier, rAddonMenuItems ); + } + else if ( rMergeCommand.equalsAsciiL( MERGECOMMAND_ADDAFTER, MERGECOMMAND_ADDAFTER_LEN )) + { + nModIndex = 1; + return MergeMenuItems( pMenu, nPos, nModIndex, nItemId, rModuleIdentifier, rAddonMenuItems ); + } + else if ( rMergeCommand.equalsAsciiL( MERGECOMMAND_REPLACE, MERGECOMMAND_REPLACE_LEN )) + { + return ReplaceMenuItem( pMenu, nPos, nItemId, rModuleIdentifier, rAddonMenuItems ); + } + else if ( rMergeCommand.equalsAsciiL( MERGECOMMAND_REMOVE, MERGECOMMAND_REMOVE_LEN )) + { + return RemoveMenuItems( pMenu, nPos, rMergeCommandParameter ); + } + + return false; +} + +bool MenuBarMerger::ProcessFallbackOperation( + const ReferencePathInfo& aRefPathInfo, + sal_uInt16& rItemId, + const ::rtl::OUString& rMergeCommand, + const ::rtl::OUString& rMergeFallback, + const ::std::vector< ::rtl::OUString >& rReferencePath, + const ::rtl::OUString& rModuleIdentifier, + const AddonMenuContainer& rAddonMenuItems ) +{ + if (( rMergeFallback.equalsAsciiL( MERGEFALLBACK_IGNORE, MERGEFALLBACK_IGNORE_LEN )) || + ( rMergeCommand.equalsAsciiL( MERGECOMMAND_REPLACE, MERGECOMMAND_REPLACE_LEN )) || + ( rMergeCommand.equalsAsciiL( MERGECOMMAND_REMOVE, MERGECOMMAND_REMOVE_LEN )) ) + { + return true; + } + else if ( rMergeFallback.equalsAsciiL( MERGEFALLBACK_ADDPATH, MERGEFALLBACK_ADDPATH_LEN )) + { + Menu* pCurrMenu( aRefPathInfo.pPopupMenu ); + sal_Int32 nLevel( aRefPathInfo.nLevel ); + const sal_Int32 nSize( rReferencePath.size() ); + bool bFirstLevel( true ); + + while ( nLevel < nSize ) + { + if ( nLevel == nSize-1 ) + { + const sal_uInt32 nCount = rAddonMenuItems.size(); + for ( sal_uInt32 i = 0; i < nCount; ++i ) + { + const AddonMenuItem& rMenuItem = rAddonMenuItems[i]; + if ( IsCorrectContext( rMenuItem.aContext, rModuleIdentifier )) + { + if ( rMenuItem.aURL.equalsAsciiL( SEPARATOR_STRING, SEPARATOR_STRING_LEN )) + pCurrMenu->InsertSeparator( MENU_APPEND ); + else + { + pCurrMenu->InsertItem( rItemId, rMenuItem.aTitle, 0, MENU_APPEND ); + pCurrMenu->SetItemCommand( rItemId, rMenuItem.aURL ); + ++rItemId; + } + } + } + } + else + { + const ::rtl::OUString aCmd( rReferencePath[nLevel] ); + + sal_uInt16 nInsPos( MENU_APPEND ); + PopupMenu* pPopupMenu( new PopupMenu ); + + if ( bFirstLevel && ( aRefPathInfo.eResult == RP_MENUITEM_INSTEAD_OF_POPUPMENU_FOUND )) + { + // special case: menu item without popup + nInsPos = aRefPathInfo.nPos; + sal_uInt16 nSetItemId = pCurrMenu->GetItemId( nInsPos ); + pCurrMenu->SetItemCommand( nSetItemId, aCmd ); + pCurrMenu->SetPopupMenu( nSetItemId, pPopupMenu ); + } + else + { + // normal case: insert a new item with popup + pCurrMenu->InsertItem( rItemId, ::rtl::OUString(), 0, MENU_APPEND ); + pCurrMenu->SetItemCommand( rItemId, aCmd ); + pCurrMenu->SetPopupMenu( rItemId, pPopupMenu ); + } + + pCurrMenu = pPopupMenu; + ++rItemId; + bFirstLevel = false; + } + ++nLevel; + } + return true; + } + + return false; +} + +void MenuBarMerger::GetMenuEntry( + const uno::Sequence< beans::PropertyValue >& rAddonMenuEntry, + AddonMenuItem& rAddonMenuItem ) +{ + // Reset submenu member + rAddonMenuItem.aSubMenu.clear(); + + for ( sal_Int32 i = 0; i < rAddonMenuEntry.getLength(); i++ ) + { + ::rtl::OUString aMenuEntryPropName = rAddonMenuEntry[i].Name; + if ( aMenuEntryPropName.equalsAsciiL( ADDONSMENUITEM_STRING_URL, ADDONSMENUITEM_URL_LEN )) + rAddonMenuEntry[i].Value >>= rAddonMenuItem.aURL; + else if ( aMenuEntryPropName.equalsAsciiL( ADDONSMENUITEM_STRING_TITLE, ADDONSMENUITEM_TITLE_LEN )) + rAddonMenuEntry[i].Value >>= rAddonMenuItem.aTitle; + else if ( aMenuEntryPropName.equalsAsciiL( ADDONSMENUITEM_STRING_TARGET, ADDONSMENUITEM_TARGET_LEN )) + rAddonMenuEntry[i].Value >>= rAddonMenuItem.aTarget; + else if ( aMenuEntryPropName.equalsAsciiL( ADDONSMENUITEM_STRING_SUBMENU, ADDONSMENUITEM_SUBMENU_LEN )) + { + uno::Sequence< uno::Sequence< beans::PropertyValue > > aSubMenu; + rAddonMenuEntry[i].Value >>= aSubMenu; + GetSubMenu( aSubMenu, rAddonMenuItem.aSubMenu ); + } + else if ( aMenuEntryPropName.equalsAsciiL( ADDONSMENUITEM_STRING_CONTEXT, ADDONSMENUITEM_CONTEXT_LEN )) + rAddonMenuEntry[i].Value >>= rAddonMenuItem.aContext; + else if ( aMenuEntryPropName.equalsAsciiL( ADDONSMENUITEM_STRING_IMAGEIDENTIFIER, ADDONSMENUITEM_IMAGEIDENTIFIER_LEN )) + rAddonMenuEntry[i].Value >>= rAddonMenuItem.aImageId; + } +} + +void MenuBarMerger::GetSubMenu( + const uno::Sequence< uno::Sequence< beans::PropertyValue > >& rSubMenuEntries, + AddonMenuContainer& rSubMenu ) +{ + rSubMenu.clear(); + + const sal_Int32 nCount = rSubMenuEntries.getLength(); + rSubMenu.reserve(rSubMenu.size() + nCount); + for ( sal_Int32 i = 0; i < nCount; i++ ) + { + const uno::Sequence< beans::PropertyValue >& rMenuEntry = rSubMenuEntries[ i ]; + + AddonMenuItem aMenuItem; + GetMenuEntry( rMenuEntry, aMenuItem ); + rSubMenu.push_back( aMenuItem ); + } +} + +} // namespace framework diff --git a/framework/source/uielement/menubarwrapper.cxx b/framework/source/uielement/menubarwrapper.cxx new file mode 100644 index 000000000000..da3092c2c725 --- /dev/null +++ b/framework/source/uielement/menubarwrapper.cxx @@ -0,0 +1,379 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <uielement/menubarwrapper.hxx> +#include <threadhelp/resetableguard.hxx> +#include <helper/actiontriggerhelper.hxx> +#include <services.h> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/awt/XSystemDependentMenuPeer.hpp> +#include <com/sun/star/awt/XMenuBar.hpp> +#include <com/sun/star/container/XIndexContainer.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/ui/UIElementType.hpp> +#include <com/sun/star/frame/XModuleManager.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ +#include <comphelper/processfactory.hxx> +#include <tools/solar.h> +#include <vcl/svapp.hxx> +#include <rtl/logfile.hxx> + +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; +using namespace com::sun::star::frame; +using namespace com::sun::star::lang; +using namespace com::sun::star::container; +using namespace com::sun::star::awt; +using namespace com::sun::star::util; +using namespace ::com::sun::star::ui; + +namespace framework +{ + +//***************************************************************************************************************** +// XInterface, XTypeProvider +//***************************************************************************************************************** +DEFINE_XINTERFACE_11 ( MenuBarWrapper , + UIConfigElementWrapperBase , + DIRECT_INTERFACE( ::com::sun::star::lang::XTypeProvider ), + DIRECT_INTERFACE( ::com::sun::star::ui::XUIElement ), + DIRECT_INTERFACE( ::com::sun::star::ui::XUIElementSettings ), + DIRECT_INTERFACE( ::com::sun::star::beans::XMultiPropertySet ), + DIRECT_INTERFACE( ::com::sun::star::beans::XFastPropertySet ), + DIRECT_INTERFACE( ::com::sun::star::beans::XPropertySet ), + DIRECT_INTERFACE( ::com::sun::star::lang::XInitialization ), + DIRECT_INTERFACE( ::com::sun::star::lang::XComponent ), + DIRECT_INTERFACE( ::com::sun::star::util::XUpdatable ), + DIRECT_INTERFACE( ::com::sun::star::ui::XUIConfigurationListener ), + DERIVED_INTERFACE( ::com::sun::star::container::XNameAccess, ::com::sun::star::container::XElementAccess ) + ) + +DEFINE_XTYPEPROVIDER_11 ( MenuBarWrapper , + ::com::sun::star::lang::XTypeProvider , + ::com::sun::star::ui::XUIElement , + ::com::sun::star::ui::XUIElementSettings , + ::com::sun::star::beans::XMultiPropertySet , + ::com::sun::star::beans::XFastPropertySet , + ::com::sun::star::beans::XPropertySet , + ::com::sun::star::lang::XInitialization , + ::com::sun::star::lang::XComponent , + ::com::sun::star::util::XUpdatable , + ::com::sun::star::ui::XUIConfigurationListener , + ::com::sun::star::container::XNameAccess + ) + +// #110897# +MenuBarWrapper::MenuBarWrapper( + const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& xServiceManager + ) +: UIConfigElementWrapperBase( UIElementType::MENUBAR,xServiceManager ), + m_bRefreshPopupControllerCache( sal_True ) +{ +} + +MenuBarWrapper::~MenuBarWrapper() +{ +} + +void SAL_CALL MenuBarWrapper::dispose() throw (::com::sun::star::uno::RuntimeException) +{ + Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY ); + + com::sun::star::lang::EventObject aEvent( xThis ); + m_aListenerContainer.disposeAndClear( aEvent ); + + ResetableGuard aLock( m_aLock ); + + m_xMenuBarManager->dispose(); + m_xMenuBarManager.clear(); + m_xConfigSource.clear(); + m_xConfigData.clear(); + + m_xMenuBar.clear(); + m_bDisposed = sal_True; +} + +// XInitialization +void SAL_CALL MenuBarWrapper::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT( aLog, "framework (cd100003) ::MenuBarWrapper::initialize" ); + + ResetableGuard aLock( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + if ( !m_bInitialized ) + { + rtl::OUString aModuleIdentifier; + UIConfigElementWrapperBase::initialize( aArguments ); + + Reference< XFrame > xFrame( m_xWeakFrame ); + if ( xFrame.is() && m_xConfigSource.is() ) + { + // Create VCL menubar which will be filled with settings data + MenuBar* pVCLMenuBar = 0; + VCLXMenuBar* pAwtMenuBar = 0; + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + pVCLMenuBar = new MenuBar(); + } + + Reference< XModuleManager > xModuleManager; + xModuleManager = Reference< XModuleManager >( + m_xServiceFactory->createInstance( + SERVICENAME_MODULEMANAGER ), UNO_QUERY_THROW ); + + try + { + aModuleIdentifier = xModuleManager->identify( xFrame ); + } + catch( Exception& ) + { + } + + Reference< XURLTransformer > xTrans; + try + { + xTrans.set( m_xServiceFactory->createInstance( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.util.URLTransformer" ))), UNO_QUERY ); + m_xConfigData = m_xConfigSource->getSettings( m_aResourceURL, sal_False ); + if ( m_xConfigData.is() ) + { + // Fill menubar with container contents + USHORT nId = 1; + MenuBarManager::FillMenuWithConfiguration( nId, pVCLMenuBar, aModuleIdentifier, m_xConfigData, xTrans ); + } + } + catch ( NoSuchElementException& ) + { + } + + sal_Bool bMenuOnly( sal_False ); + for ( sal_Int32 n = 0; n < aArguments.getLength(); n++ ) + { + PropertyValue aPropValue; + if ( aArguments[n] >>= aPropValue ) + { + if ( aPropValue.Name.equalsAscii( "MenuOnly" )) + aPropValue.Value >>= bMenuOnly; + } + } + + if ( !bMenuOnly ) + { + // Initialize menubar manager with our vcl menu bar. There are some situations where we only want to get the menu without any + // interaction which is done by the menu bar manager. This must be requested by a special property called "MenuOnly". Be careful + // a menu bar created with this property is not fully supported. It must be attached to a real menu bar manager to have full + // support. This feature is currently used for "Inplace editing"! + Reference< XDispatchProvider > xDispatchProvider; + + // #110897# + MenuBarManager* pMenuBarManager = new MenuBarManager( m_xServiceFactory, + xFrame, + xTrans, + xDispatchProvider, + aModuleIdentifier, + pVCLMenuBar, + sal_False, + sal_True ); + + m_xMenuBarManager = Reference< XComponent >( static_cast< OWeakObject *>( pMenuBarManager ), UNO_QUERY ); + } + + // Initialize toolkit menu bar implementation to have awt::XMenuBar for data exchange. + // Don't use this toolkit menu bar or one of its functions. It is only used as a data container! + pAwtMenuBar = new VCLXMenuBar( pVCLMenuBar ); + m_xMenuBar = Reference< XMenuBar >( static_cast< OWeakObject *>( pAwtMenuBar ), UNO_QUERY ); + } + } +} + +// XUIElementSettings +void SAL_CALL MenuBarWrapper::updateSettings() throw ( RuntimeException ) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + if ( m_xMenuBarManager.is() ) + { + if ( m_xConfigSource.is() && m_bPersistent ) + { + try + { + MenuBarManager* pMenuBarManager = static_cast< MenuBarManager *>( m_xMenuBarManager.get() ); + + m_xConfigData = m_xConfigSource->getSettings( m_aResourceURL, sal_False ); + if ( m_xConfigData.is() ) + pMenuBarManager->SetItemContainer( m_xConfigData ); + } + catch ( NoSuchElementException& ) + { + } + } + else if ( !m_bPersistent ) + { + // Transient menubar: do nothing + } + } +} +void MenuBarWrapper::impl_fillNewData() +{ + // Transient menubar => Fill menubar with new data + MenuBarManager* pMenuBarManager = static_cast< MenuBarManager *>( m_xMenuBarManager.get() ); + + if ( pMenuBarManager ) + pMenuBarManager->SetItemContainer( m_xConfigData ); +} + + +void MenuBarWrapper::fillPopupControllerCache() +{ + if ( m_bRefreshPopupControllerCache ) + { + MenuBarManager* pMenuBarManager = static_cast< MenuBarManager *>( m_xMenuBarManager.get() ); + if ( pMenuBarManager ) + pMenuBarManager->GetPopupController( m_aPopupControllerCache ); + if ( !m_aPopupControllerCache.empty() ) + m_bRefreshPopupControllerCache = sal_False; + } +} + +// XElementAccess +Type SAL_CALL MenuBarWrapper::getElementType() +throw (::com::sun::star::uno::RuntimeException) +{ + return ::getCppuType(( Reference< XDispatchProvider >*)0); +} + +::sal_Bool SAL_CALL MenuBarWrapper::hasElements() +throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + fillPopupControllerCache(); + return ( !m_aPopupControllerCache.empty() ); +} + +// XNameAccess +Any SAL_CALL MenuBarWrapper::getByName( + const ::rtl::OUString& aName ) +throw ( container::NoSuchElementException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + fillPopupControllerCache(); + + PopupControllerCache::const_iterator pIter = m_aPopupControllerCache.find( aName ); + if ( pIter != m_aPopupControllerCache.end() ) + { + uno::Reference< frame::XDispatchProvider > xDispatchProvider; + xDispatchProvider = pIter->second.m_xDispatchProvider; + return uno::makeAny( xDispatchProvider ); + } + else + throw container::NoSuchElementException(); +} + +Sequence< ::rtl::OUString > SAL_CALL MenuBarWrapper::getElementNames() +throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + fillPopupControllerCache(); + + Sequence< rtl::OUString > aSeq( m_aPopupControllerCache.size() ); + + sal_Int32 i( 0 ); + PopupControllerCache::const_iterator pIter = m_aPopupControllerCache.begin(); + while ( pIter != m_aPopupControllerCache.end() ) + { + aSeq[i++] = pIter->first; + ++pIter; + } + + return aSeq; +} + +::sal_Bool SAL_CALL MenuBarWrapper::hasByName( + const ::rtl::OUString& aName ) +throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + fillPopupControllerCache(); + + PopupControllerCache::const_iterator pIter = m_aPopupControllerCache.find( aName ); + if ( pIter != m_aPopupControllerCache.end() ) + return sal_True; + else + return sal_False; +} + +// XUIElement +Reference< XInterface > SAL_CALL MenuBarWrapper::getRealInterface() throw ( RuntimeException ) +{ + if ( m_bDisposed ) + throw DisposedException(); + + return Reference< XInterface >( m_xMenuBarManager, UNO_QUERY ); +} + +} // namespace framework + diff --git a/framework/source/uielement/newmenucontroller.cxx b/framework/source/uielement/newmenucontroller.cxx new file mode 100644 index 000000000000..3ac78726d799 --- /dev/null +++ b/framework/source/uielement/newmenucontroller.cxx @@ -0,0 +1,595 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include <uielement/newmenucontroller.hxx> + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <threadhelp/resetableguard.hxx> +#include "services.h" +#ifndef __FRAMEWORK_CLASSES_RESOURCE_HRC_ +#include <classes/resource.hrc> +#endif +#include <classes/fwkresid.hxx> +#include <classes/bmkmenu.hxx> +#include <helper/imageproducer.hxx> +#include <xml/menuconfiguration.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/awt/XDevice.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/awt/MenuItemStyle.hpp> +#include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp> +#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp> +#include <com/sun/star/frame/XModuleManager.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/document/CorruptedFilterConfigurationException.hpp> + +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ +#include <vcl/svapp.hxx> +#include <vcl/i18nhelp.hxx> +#include <tools/urlobj.hxx> +#include <rtl/ustrbuf.hxx> +#include <cppuhelper/implbase1.hxx> +#include <osl/file.hxx> +#include <svtools/menuoptions.hxx> +#include <svtools/acceleratorexecute.hxx> +#include <unotools/moduleoptions.hxx> +#include <dispatch/uieventloghelper.hxx> + +//_________________________________________________________________________________________________________________ +// Defines +//_________________________________________________________________________________________________________________ +// + +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; + +static const char SFX_REFERER_USER[] = "private:user"; + +namespace framework +{ + +DEFINE_XSERVICEINFO_MULTISERVICE ( NewMenuController , + OWeakObject , + SERVICENAME_POPUPMENUCONTROLLER , + IMPLEMENTATIONNAME_NEWMENUCONTROLLER + ) + +DEFINE_INIT_SERVICE ( NewMenuController, {} ) + +void NewMenuController::setMenuImages( PopupMenu* pPopupMenu, sal_Bool bSetImages, sal_Bool bHiContrast ) +{ + USHORT nItemCount = pPopupMenu->GetItemCount(); + Image aImage; + Reference< XFrame > xFrame( m_xFrame ); + + for ( USHORT i = 0; i < nItemCount; i++ ) + { + USHORT nItemId = pPopupMenu->GetItemId( sal::static_int_cast<USHORT>( i )); + if ( nItemId != 0 ) + { + if ( bSetImages ) + { + sal_Bool bImageSet( sal_False ); + ::rtl::OUString aImageId; + + AddInfoForId::const_iterator pInfo = m_aAddInfoForItem.find( nItemId ); + if ( pInfo != m_aAddInfoForItem.end() ) + aImageId = pInfo->second.aImageId; // Retrieve image id for menu item + + if ( aImageId.getLength() > 0 ) + { + aImage = GetImageFromURL( xFrame, aImageId, FALSE, bHiContrast ); + if ( !!aImage ) + { + bImageSet = sal_True; + pPopupMenu->SetItemImage( nItemId, aImage ); + } + } + + if ( !bImageSet ) + { + String aCmd( pPopupMenu->GetItemCommand( nItemId ) ); + if ( aCmd.Len() ) + aImage = GetImageFromURL( xFrame, aCmd, FALSE, bHiContrast ); + + if ( !!aImage ) + pPopupMenu->SetItemImage( nItemId, aImage ); + } + } + else + pPopupMenu->SetItemImage( nItemId, aImage ); + } + } +} + +void NewMenuController::determineAndSetNewDocAccel( PopupMenu* pPopupMenu, const KeyCode& rKeyCode ) +{ + USHORT nCount( pPopupMenu->GetItemCount() ); + USHORT nId( 0 ); + sal_Bool bFound( sal_False ); + rtl::OUString aCommand; + + if ( m_aEmptyDocURL.getLength() > 0 ) + { + // Search for the empty document URL + + for ( sal_uInt32 i = 0; i < sal_uInt32( nCount ); i++ ) + { + nId = pPopupMenu->GetItemId( USHORT( i )); + if ( nId != 0 && pPopupMenu->GetItemType( nId ) != MENUITEM_SEPARATOR ) + { + aCommand = pPopupMenu->GetItemCommand( nId ); + if ( aCommand.indexOf( m_aEmptyDocURL ) == 0 ) + { + pPopupMenu->SetAccelKey( nId, rKeyCode ); + bFound = sal_True; + break; + } + } + } + } + + if ( !bFound ) + { + // Search for the default module name + rtl::OUString aDefaultModuleName( SvtModuleOptions().GetDefaultModuleName() ); + if ( aDefaultModuleName.getLength() > 0 ) + { + for ( sal_uInt32 i = 0; i < sal_uInt32( nCount ); i++ ) + { + nId = pPopupMenu->GetItemId( USHORT( i )); + if ( nId != 0 && pPopupMenu->GetItemType( nId ) != MENUITEM_SEPARATOR ) + { + aCommand = pPopupMenu->GetItemCommand( nId ); + if ( aCommand.indexOf( aDefaultModuleName ) >= 0 ) + { + pPopupMenu->SetAccelKey( nId, rKeyCode ); + break; + } + } + } + } + } +} + +void NewMenuController::setAccelerators( PopupMenu* pPopupMenu ) +{ + if ( m_bModuleIdentified ) + { + Reference< XAcceleratorConfiguration > xDocAccelCfg( m_xDocAcceleratorManager ); + Reference< XAcceleratorConfiguration > xModuleAccelCfg( m_xModuleAcceleratorManager ); + Reference< XAcceleratorConfiguration > xGlobalAccelCfg( m_xGlobalAcceleratorManager ); + + if ( !m_bAcceleratorCfg ) + { + // Retrieve references on demand + m_bAcceleratorCfg = sal_True; + if ( !xDocAccelCfg.is() ) + { + Reference< XController > xController = m_xFrame->getController(); + Reference< XModel > xModel; + if ( xController.is() ) + { + xModel = xController->getModel(); + if ( xModel.is() ) + { + Reference< XUIConfigurationManagerSupplier > xSupplier( xModel, UNO_QUERY ); + if ( xSupplier.is() ) + { + Reference< XUIConfigurationManager > xDocUICfgMgr( xSupplier->getUIConfigurationManager(), UNO_QUERY ); + if ( xDocUICfgMgr.is() ) + { + xDocAccelCfg = Reference< XAcceleratorConfiguration >( xDocUICfgMgr->getShortCutManager(), UNO_QUERY ); + m_xDocAcceleratorManager = xDocAccelCfg; + } + } + } + } + } + + if ( !xModuleAccelCfg.is() ) + { + Reference< XModuleUIConfigurationManagerSupplier > xModuleCfgMgrSupplier( m_xServiceManager->createInstance( + SERVICENAME_MODULEUICONFIGURATIONMANAGERSUPPLIER ), + UNO_QUERY ); + Reference< XUIConfigurationManager > xUICfgMgr = xModuleCfgMgrSupplier->getUIConfigurationManager( m_aModuleIdentifier ); + if ( xUICfgMgr.is() ) + { + xModuleAccelCfg = Reference< XAcceleratorConfiguration >( xUICfgMgr->getShortCutManager(), UNO_QUERY ); + m_xModuleAcceleratorManager = xModuleAccelCfg; + } + } + + if ( !xGlobalAccelCfg.is() ) + { + xGlobalAccelCfg = Reference< XAcceleratorConfiguration >( m_xServiceManager->createInstance( + SERVICENAME_GLOBALACCELERATORCONFIGURATION ), + UNO_QUERY ); + m_xGlobalAcceleratorManager = xGlobalAccelCfg; + } + } + + KeyCode aEmptyKeyCode; + sal_uInt32 nItemCount( pPopupMenu->GetItemCount() ); + std::vector< KeyCode > aMenuShortCuts; + std::vector< rtl::OUString > aCmds; + std::vector< sal_uInt32 > aIds; + for ( sal_uInt32 i = 0; i < nItemCount; i++ ) + { + USHORT nId( pPopupMenu->GetItemId( USHORT( i ))); + if ( nId & ( pPopupMenu->GetItemType( nId ) != MENUITEM_SEPARATOR )) + { + aIds.push_back( nId ); + aMenuShortCuts.push_back( aEmptyKeyCode ); + aCmds.push_back( pPopupMenu->GetItemCommand( nId )); + } + } + + sal_uInt32 nSeqCount( aIds.size() ); + + if ( m_bNewMenu ) + nSeqCount+=1; + + Sequence< rtl::OUString > aSeq( nSeqCount ); + + // Add a special command for our "New" menu. + if ( m_bNewMenu ) + { + aSeq[nSeqCount-1] = m_aCommandURL; + aMenuShortCuts.push_back( aEmptyKeyCode ); + } + + const sal_uInt32 nCount = aCmds.size(); + for ( sal_uInt32 i = 0; i < nCount; i++ ) + aSeq[i] = aCmds[i]; + + if ( m_xGlobalAcceleratorManager.is() ) + retrieveShortcutsFromConfiguration( xGlobalAccelCfg, aSeq, aMenuShortCuts ); + if ( m_xModuleAcceleratorManager.is() ) + retrieveShortcutsFromConfiguration( xModuleAccelCfg, aSeq, aMenuShortCuts ); + if ( m_xDocAcceleratorManager.is() ) + retrieveShortcutsFromConfiguration( xGlobalAccelCfg, aSeq, aMenuShortCuts ); + + const sal_uInt32 nCount2 = aIds.size(); + for ( sal_uInt32 i = 0; i < nCount2; i++ ) + pPopupMenu->SetAccelKey( USHORT( aIds[i] ), aMenuShortCuts[i] ); + + // Special handling for "New" menu short-cut should be set at the + // document which will be opened using it. + if ( m_bNewMenu ) + { + if ( aMenuShortCuts[nSeqCount-1] != aEmptyKeyCode ) + determineAndSetNewDocAccel( pPopupMenu, aMenuShortCuts[nSeqCount-1] ); + } + } +} + +void NewMenuController::retrieveShortcutsFromConfiguration( + const Reference< XAcceleratorConfiguration >& rAccelCfg, + const Sequence< rtl::OUString >& rCommands, + std::vector< KeyCode >& aMenuShortCuts ) +{ + if ( rAccelCfg.is() ) + { + try + { + com::sun::star::awt::KeyEvent aKeyEvent; + Sequence< Any > aSeqKeyCode = rAccelCfg->getPreferredKeyEventsForCommandList( rCommands ); + for ( sal_Int32 i = 0; i < aSeqKeyCode.getLength(); i++ ) + { + if ( aSeqKeyCode[i] >>= aKeyEvent ) + aMenuShortCuts[i] = svt::AcceleratorExecute::st_AWTKey2VCLKey( aKeyEvent ); + } + } + catch ( IllegalArgumentException& ) + { + } + } +} + +NewMenuController::NewMenuController( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ) : + PopupMenuControllerBase( xServiceManager ), + m_bShowImages( sal_True ), + m_bHiContrast( sal_False ), + m_bNewMenu( sal_False ), + m_bModuleIdentified( sal_False ), + m_bAcceleratorCfg( sal_False ), + m_aTargetFrame( RTL_CONSTASCII_USTRINGPARAM( "_default" )) +{ +} + +NewMenuController::~NewMenuController() +{ +} + +// private function +void NewMenuController::fillPopupMenu( Reference< css::awt::XPopupMenu >& rPopupMenu ) +{ + VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( rPopupMenu ); + PopupMenu* pVCLPopupMenu = 0; + + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + resetPopupMenu( rPopupMenu ); + if ( pPopupMenu ) + pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu(); + + if ( pVCLPopupMenu ) + { + MenuConfiguration aMenuCfg( m_xServiceManager ); + BmkMenu* pSubMenu( 0 ); + + if ( m_bNewMenu ) + pSubMenu = (BmkMenu*)aMenuCfg.CreateBookmarkMenu( m_xFrame, BOOKMARK_NEWMENU ); + else + pSubMenu = (BmkMenu*)aMenuCfg.CreateBookmarkMenu( m_xFrame, BOOKMARK_WIZARDMENU ); + + // copy entries as we have to use the provided popup menu + *pVCLPopupMenu = *pSubMenu; + + Image aImage; + AddInfo aAddInfo; + + // retrieve additional parameters from bookmark menu and + // store it in a hash_map. + for ( USHORT i = 0; i < pSubMenu->GetItemCount(); i++ ) + { + USHORT nItemId = pSubMenu->GetItemId( sal::static_int_cast<USHORT>( i ) ); + if (( nItemId != 0 ) && + ( pSubMenu->GetItemType( nItemId ) != MENUITEM_SEPARATOR )) + { + MenuConfiguration::Attributes* pBmkAttributes = (MenuConfiguration::Attributes *)(pSubMenu->GetUserValue( nItemId )); + if ( pBmkAttributes != 0 ) + { + aAddInfo.aTargetFrame = pBmkAttributes->aTargetFrame; + aAddInfo.aImageId = pBmkAttributes->aImageId; + + m_aAddInfoForItem.insert( AddInfoForId::value_type( nItemId, aAddInfo )); + } + } + } + + if ( m_bShowImages ) + setMenuImages( pVCLPopupMenu, m_bShowImages, m_bHiContrast ); + + delete pSubMenu; + } +} + +// XEventListener +void SAL_CALL NewMenuController::disposing( const EventObject& ) throw ( RuntimeException ) +{ + Reference< css::awt::XMenuListener > xHolder(( OWeakObject *)this, UNO_QUERY ); + + ResetableGuard aLock( m_aLock ); + m_xFrame.clear(); + m_xDispatch.clear(); + m_xServiceManager.clear(); + + if ( m_xPopupMenu.is() ) + m_xPopupMenu->removeMenuListener( Reference< css::awt::XMenuListener >(( OWeakObject *)this, UNO_QUERY )); + m_xPopupMenu.clear(); +} + +// XStatusListener +void SAL_CALL NewMenuController::statusChanged( const FeatureStateEvent& ) throw ( RuntimeException ) +{ +} + +// XMenuListener +void SAL_CALL NewMenuController::select( const css::awt::MenuEvent& rEvent ) throw (RuntimeException) +{ + Reference< css::awt::XPopupMenu > xPopupMenu; + Reference< XDispatch > xDispatch; + Reference< XDispatchProvider > xDispatchProvider; + Reference< XMultiServiceFactory > xServiceManager; + Reference< XURLTransformer > xURLTransformer; + + ResetableGuard aLock( m_aLock ); + xPopupMenu = m_xPopupMenu; + xDispatchProvider = Reference< XDispatchProvider >( m_xFrame, UNO_QUERY ); + xServiceManager = m_xServiceManager; + xURLTransformer = m_xURLTransformer; + aLock.unlock(); + + css::util::URL aTargetURL; + Sequence< PropertyValue > aArgsList( 1 ); + + if ( xPopupMenu.is() && xDispatchProvider.is() ) + { + VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXPopupMenu::GetImplementation( xPopupMenu ); + if ( pPopupMenu ) + { + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + PopupMenu* pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu(); + aTargetURL.Complete = pVCLPopupMenu->GetItemCommand( rEvent.MenuId ); + } + + xURLTransformer->parseStrict( aTargetURL ); + + aArgsList[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Referer" )); + aArgsList[0].Value = makeAny( ::rtl::OUString::createFromAscii( SFX_REFERER_USER )); + + rtl::OUString aTargetFrame( m_aTargetFrame ); + AddInfoForId::const_iterator pItem = m_aAddInfoForItem.find( rEvent.MenuId ); + if ( pItem != m_aAddInfoForItem.end() ) + aTargetFrame = pItem->second.aTargetFrame; + + xDispatch = xDispatchProvider->queryDispatch( aTargetURL, aTargetFrame, 0 ); + } + } + + if ( xDispatch.is() ) + { + // Call dispatch asychronously as we can be destroyed while dispatch is + // executed. VCL is not able to survive this as it wants to call listeners + // after select!!! + NewDocument* pNewDocument = new NewDocument; + pNewDocument->xDispatch = xDispatch; + pNewDocument->aTargetURL = aTargetURL; + pNewDocument->aArgSeq = aArgsList; + if(::comphelper::UiEventsLogger::isEnabled()) //#i88653# + UiEventLogHelper(::rtl::OUString::createFromAscii("NewMenuController")).log(m_xServiceManager, m_xFrame, aTargetURL, aArgsList); + Application::PostUserEvent( STATIC_LINK(0, NewMenuController, ExecuteHdl_Impl), pNewDocument ); + } +} + +void SAL_CALL NewMenuController::activate( const css::awt::MenuEvent& ) throw (RuntimeException) +{ + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + if ( m_xFrame.is() && m_xPopupMenu.is() ) + { + VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXPopupMenu::GetImplementation( m_xPopupMenu ); + if ( pPopupMenu ) + { + const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); + sal_Bool bShowImages( rSettings.GetUseImagesInMenus() ); + sal_Bool bHiContrast( rSettings.GetHighContrastMode() ); + + PopupMenu* pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu(); + + if (( m_bShowImages != bShowImages ) || + ( m_bHiContrast != bHiContrast )) + { + m_bShowImages = bShowImages; + m_bHiContrast = bHiContrast; + + setMenuImages( pVCLPopupMenu, m_bShowImages, m_bHiContrast ); + } + + setAccelerators( pVCLPopupMenu ); + } + } +} + +// XPopupMenuController +void NewMenuController::impl_setPopupMenu() +{ + + if ( m_xPopupMenu.is() ) + fillPopupMenu( m_xPopupMenu ); + + // Identify module that we are attach to. It's our context that we need to know. + Reference< XModuleManager > xModuleManager( m_xServiceManager->createInstance( SERVICENAME_MODULEMANAGER ),UNO_QUERY ); + if ( xModuleManager.is() ) + { + try + { + m_aModuleIdentifier = xModuleManager->identify( m_xFrame ); + m_bModuleIdentified = sal_True; + + Reference< XNameAccess > xNameAccess( xModuleManager, UNO_QUERY ); + if (( m_aModuleIdentifier.getLength() > 0 ) && xNameAccess.is() ) + { + Sequence< PropertyValue > aSeq; + + if ( xNameAccess->getByName( m_aModuleIdentifier ) >>= aSeq ) + { + for ( sal_Int32 y = 0; y < aSeq.getLength(); y++ ) + { + if ( aSeq[y].Name.equalsAscii("ooSetupFactoryEmptyDocumentURL") ) + { + aSeq[y].Value >>= m_aEmptyDocURL; + break; + } + } + } + } + } + catch ( RuntimeException& e ) + { + throw e; + } + catch ( Exception& ) + { + } + } +} + +// XInitialization +void SAL_CALL NewMenuController::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException ) +{ + ResetableGuard aLock( m_aLock ); + + sal_Bool bInitalized( m_bInitialized ); + if ( !bInitalized ) + { + PopupMenuControllerBase::initialize( aArguments ); + + if ( m_bInitialized ) + { + const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); + + m_bShowImages = rSettings.GetUseImagesInMenus(); + m_bHiContrast = rSettings.GetHighContrastMode(); + + m_bNewMenu = m_aCommandURL.equalsAscii( ".uno:AddDirect" ); + } + } +} + +IMPL_STATIC_LINK_NOINSTANCE( NewMenuController, ExecuteHdl_Impl, NewDocument*, pNewDocument ) +{ +/* i62706: Don't catch all exceptions. We hide all problems here and are not able + to handle them on higher levels. + 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! + pNewDocument->xDispatch->dispatch( pNewDocument->aTargetURL, pNewDocument->aArgSeq ); +/* + } + catch (const ::com::sun::star::document::CorruptedFilterConfigurationException& exFilters) + { + throw exFilters; + } + catch (const Exception& ) + { + } +*/ + delete pNewDocument; + return 0; +} + +} diff --git a/framework/source/uielement/objectmenucontroller.cxx b/framework/source/uielement/objectmenucontroller.cxx new file mode 100644 index 000000000000..f4d6aea0d82b --- /dev/null +++ b/framework/source/uielement/objectmenucontroller.cxx @@ -0,0 +1,165 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include <uielement/objectmenucontroller.hxx> + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <threadhelp/resetableguard.hxx> +#include "services.h" + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/awt/XDevice.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/awt/MenuItemStyle.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> + +#ifndef _COM_SUN_STAR_EMBED_VERBDATTRIBUTES_HPP_ +#include <com/sun/star/embed/VerbAttributes.hpp> +#endif + +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ + +#ifndef _VCL_MENU_HXX_ +#include <vcl/menu.hxx> +#endif +#include <vcl/svapp.hxx> +#include <vcl/i18nhelp.hxx> +#include <tools/urlobj.hxx> +#include <rtl/ustrbuf.hxx> +#include <dispatch/uieventloghelper.hxx> + +//_________________________________________________________________________________________________________________ +// Defines +//_________________________________________________________________________________________________________________ +// + +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; + +namespace framework +{ + +DEFINE_XSERVICEINFO_MULTISERVICE ( ObjectMenuController , + OWeakObject , + SERVICENAME_POPUPMENUCONTROLLER , + IMPLEMENTATIONNAME_OBJECTMENUCONTROLLER + ) + +DEFINE_INIT_SERVICE ( ObjectMenuController, {} ) + +ObjectMenuController::ObjectMenuController( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ) : + PopupMenuControllerBase( xServiceManager ) +{ +} + +ObjectMenuController::~ObjectMenuController() +{ +} + +// private function +void ObjectMenuController::fillPopupMenu( const Sequence< com::sun::star::embed::VerbDescriptor >& rVerbCommandSeq, Reference< css::awt::XPopupMenu >& rPopupMenu ) +{ + const com::sun::star::embed::VerbDescriptor* pVerbCommandArray = rVerbCommandSeq.getConstArray(); + VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( rPopupMenu ); + PopupMenu* pVCLPopupMenu = 0; + + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + resetPopupMenu( rPopupMenu ); + if ( pPopupMenu ) + pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu(); + + if ( pVCLPopupMenu ) + { + const rtl::OUString aVerbCommand( RTL_CONSTASCII_USTRINGPARAM( ".uno:ObjectMenue?VerbID:short=" )); + for ( USHORT i = 0; i < rVerbCommandSeq.getLength(); i++ ) + { + const com::sun::star::embed::VerbDescriptor& rVerb = pVerbCommandArray[i]; + if ( rVerb.VerbAttributes & com::sun::star::embed::VerbAttributes::MS_VERBATTR_ONCONTAINERMENU ) + { + m_xPopupMenu->insertItem( i+1, rVerb.VerbName, 0, i ); + // use VCL popup menu pointer to set vital information that are not part of the awt implementation + + rtl::OUString aCommand( aVerbCommand ); + aCommand += rtl::OUString::valueOf( rVerb.VerbID ); + pVCLPopupMenu->SetItemCommand( i+1, aCommand ); // Store verb command + } + } + } +} + +// XEventListener +void SAL_CALL ObjectMenuController::disposing( const EventObject& ) throw ( RuntimeException ) +{ + Reference< css::awt::XMenuListener > xHolder(( OWeakObject *)this, UNO_QUERY ); + + ResetableGuard aLock( m_aLock ); + m_xFrame.clear(); + m_xDispatch.clear(); + m_xObjectUpdateDispatch.clear(); + m_xServiceManager.clear(); + + if ( m_xPopupMenu.is() ) + m_xPopupMenu->removeMenuListener( Reference< css::awt::XMenuListener >(( OWeakObject *)this, UNO_QUERY )); + m_xPopupMenu.clear(); +} + +// XStatusListener +void SAL_CALL ObjectMenuController::statusChanged( const FeatureStateEvent& Event ) throw ( RuntimeException ) +{ + Sequence < com::sun::star::embed::VerbDescriptor > aVerbCommandSeq; + if ( Event.State >>= aVerbCommandSeq ) + { + ResetableGuard aLock( m_aLock ); + if ( m_xPopupMenu.is() ) + fillPopupMenu( aVerbCommandSeq, m_xPopupMenu ); + } +} + +// XMenuListener +void ObjectMenuController::impl_select(const Reference< XDispatch >& _xDispatch,const ::com::sun::star::util::URL& aTargetURL) +{ + Sequence<PropertyValue> aArgs; + if(::comphelper::UiEventsLogger::isEnabled()) //#i88653# + UiEventLogHelper(::rtl::OUString::createFromAscii("ObjectMenuController")).log(m_xServiceManager, m_xFrame, aTargetURL, aArgs); + OSL_ENSURE(_xDispatch.is(),"ObjectMenuController::impl_select: No dispatch"); + if ( _xDispatch.is() ) + _xDispatch->dispatch( aTargetURL, aArgs ); +} + +} diff --git a/framework/source/uielement/progressbarwrapper.cxx b/framework/source/uielement/progressbarwrapper.cxx new file mode 100644 index 000000000000..2cd0ed891db6 --- /dev/null +++ b/framework/source/uielement/progressbarwrapper.cxx @@ -0,0 +1,364 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + +#ifndef __FRAMEWORK_UIELEMENT_PROGRESSBARWRAPPER_HXX_ +#include <uielement/progressbarwrapper.hxx> +#endif + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <helper/statusindicator.hxx> +#include <threadhelp/resetableguard.hxx> +#include <uielement/statusindicatorinterfacewrapper.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/ui/UIElementType.hpp> + +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ +#include <vcl/svapp.hxx> +#include <toolkit/helper/vclunohelper.hxx> + +//_________________________________________________________________________________________________________________ +// namespace +//_________________________________________________________________________________________________________________ +using namespace ::com::sun::star; + +namespace framework{ + +//_________________________________________________________________________________________________________________ +// non exported const +//_________________________________________________________________________________________________________________ + +//_________________________________________________________________________________________________________________ +// non exported definitions +//_________________________________________________________________________________________________________________ + +//_________________________________________________________________________________________________________________ +// declarations +//_________________________________________________________________________________________________________________ + +ProgressBarWrapper::ProgressBarWrapper() : +UIElementWrapperBase( ::com::sun::star::ui::UIElementType::PROGRESSBAR ) + , m_bOwnsInstance( sal_False ) + , m_nRange( 100 ) + , m_nValue( 0 ) +{ +} + +ProgressBarWrapper::~ProgressBarWrapper() +{ +} + +// public interfaces +void ProgressBarWrapper::setStatusBar( const uno::Reference< awt::XWindow >& rStatusBar, sal_Bool bOwnsInstance ) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + return; + + if ( m_bOwnsInstance ) + { + // dispose XWindow reference our our status bar + uno::Reference< lang::XComponent > xComponent( m_xStatusBar, uno::UNO_QUERY ); + try + { + if ( xComponent.is() ) + xComponent->dispose(); + } + catch ( uno::Exception& ) + { + } + m_xStatusBar.clear(); + } + + m_bOwnsInstance = bOwnsInstance; + m_xStatusBar = rStatusBar; +} + +uno::Reference< awt::XWindow > ProgressBarWrapper::getStatusBar() const +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + return uno::Reference< awt::XWindow >(); + + return m_xStatusBar; +} + +// wrapped methods of ::com::sun::star::task::XStatusIndicator +void ProgressBarWrapper::start( const ::rtl::OUString& Text, ::sal_Int32 Range ) +throw (uno::RuntimeException) +{ + uno::Reference< awt::XWindow > xWindow; + sal_Int32 nValue( 0 ); + + { + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + return; + + xWindow = m_xStatusBar; + m_nValue = 0; + m_nRange = Range; + nValue = m_nValue; + } + + if ( xWindow.is() ) + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + Window* pWindow = VCLUnoHelper::GetWindow( xWindow ); + if ( pWindow && pWindow->GetType() == WINDOW_STATUSBAR ) + { + StatusBar* pStatusBar = (StatusBar *)pWindow; + if ( !pStatusBar->IsProgressMode() ) + pStatusBar->StartProgressMode( Text ); + else + { + pStatusBar->SetUpdateMode( FALSE ); + pStatusBar->EndProgressMode(); + pStatusBar->StartProgressMode( Text ); + pStatusBar->SetProgressValue( USHORT( nValue )); + pStatusBar->SetUpdateMode( TRUE ); + } + pStatusBar->Show( TRUE, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE ); + } + } +} + +void ProgressBarWrapper::end() +throw (uno::RuntimeException) +{ + uno::Reference< awt::XWindow > xWindow; + + { + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + return; + + xWindow = m_xStatusBar; + m_nRange = 100; + m_nValue = 0; + } + + if ( xWindow.is() ) + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + Window* pWindow = VCLUnoHelper::GetWindow( xWindow ); + if ( pWindow && pWindow->GetType() == WINDOW_STATUSBAR ) + { + StatusBar* pStatusBar = (StatusBar *)pWindow; + if ( pStatusBar->IsProgressMode() ) + pStatusBar->EndProgressMode(); + } + } +} + +void ProgressBarWrapper::setText( const ::rtl::OUString& Text ) +throw (uno::RuntimeException) +{ + uno::Reference< awt::XWindow > xWindow; + sal_Int32 nValue( 0 ); + + { + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + return; + + xWindow = m_xStatusBar; + m_aText = Text; + nValue = m_nValue; + } + + if ( xWindow.is() ) + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + Window* pWindow = VCLUnoHelper::GetWindow( xWindow ); + if ( pWindow && pWindow->GetType() == WINDOW_STATUSBAR ) + { + StatusBar* pStatusBar = (StatusBar *)pWindow; + if( pStatusBar->IsProgressMode() ) + { + pStatusBar->SetUpdateMode( FALSE ); + pStatusBar->EndProgressMode(); + pStatusBar->StartProgressMode( Text ); + pStatusBar->SetProgressValue( USHORT( nValue )); + pStatusBar->SetUpdateMode( TRUE ); + } + else + pStatusBar->SetText( Text ); + } + } +} + +void ProgressBarWrapper::setValue( ::sal_Int32 nValue ) +throw (uno::RuntimeException) +{ + uno::Reference< awt::XWindow > xWindow; + rtl::OUString aText; + sal_Bool bSetValue( sal_False ); + + { + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + return; + + xWindow = m_xStatusBar; + + double fVal( 0 ); + if ( m_nRange > 0 ) + { + fVal = ( double( nValue ) / double( m_nRange )) * 100; + fVal = std::max( double( 0 ), std::min( fVal, double( 100 ))); + } + + if ( m_nValue != sal_Int32( fVal )) + { + m_nValue = sal_Int32( fVal ); + bSetValue = sal_True; + } + + nValue = m_nValue; + aText = m_aText; + } + + if ( xWindow.is() && bSetValue ) + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + Window* pWindow = VCLUnoHelper::GetWindow( xWindow ); + if ( pWindow && pWindow->GetType() == WINDOW_STATUSBAR ) + { + StatusBar* pStatusBar = (StatusBar *)pWindow; + if ( !pStatusBar->IsProgressMode() ) + pStatusBar->StartProgressMode( aText ); + pStatusBar->SetProgressValue( USHORT( nValue )); + } + } +} + +void ProgressBarWrapper::reset() +throw (uno::RuntimeException) +{ + setText( rtl::OUString() ); + setValue( 0 ); +} + +// XInitialization +void SAL_CALL ProgressBarWrapper::initialize( const uno::Sequence< uno::Any >& ) +throw (uno::Exception, uno::RuntimeException) +{ + // dummy - do nothing +} + +// XUpdatable +void SAL_CALL ProgressBarWrapper::update() +throw (uno::RuntimeException) +{ + // dummy - do nothing +} + +// XComponent +void SAL_CALL ProgressBarWrapper::dispose() +throw (uno::RuntimeException) +{ + uno::Reference< lang::XComponent > xThis( + static_cast< cppu::OWeakObject* >(this), + uno::UNO_QUERY ); + + { + ResetableGuard aLock( m_aLock ); + + if ( m_bDisposed ) + return; + } + + { + lang::EventObject aEvent( xThis ); + m_aListenerContainer.disposeAndClear( aEvent ); + + ResetableGuard aLock( m_aLock ); + if ( m_bOwnsInstance ) + { + try + { + uno::Reference< lang::XComponent > xComponent( m_xStatusBar, uno::UNO_QUERY ); + if ( xComponent.is() ) + xComponent->dispose(); + } + catch ( lang::DisposedException& ) + { + } + } + + m_xStatusBar.clear(); + m_bDisposed = sal_True; + } +} + +// XUIElement +uno::Reference< uno::XInterface > SAL_CALL ProgressBarWrapper::getRealInterface() +throw (uno::RuntimeException) +{ + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + // Ready for multithreading + ResetableGuard aLock( m_aLock ); + + if ( m_bDisposed ) + return uno::Reference< uno::XInterface >(); + else + { + uno::Reference< uno::XInterface > xComp( m_xProgressBarIfacWrapper ); + if ( !xComp.is() ) + { + StatusIndicatorInterfaceWrapper* pWrapper = + new StatusIndicatorInterfaceWrapper( + uno::Reference< lang::XComponent >( + static_cast< cppu::OWeakObject* >( this ), + uno::UNO_QUERY )); + xComp = uno::Reference< uno::XInterface >( + static_cast< cppu::OWeakObject* >( pWrapper ), + uno::UNO_QUERY ); + m_xProgressBarIfacWrapper = xComp; + } + + return xComp; + } +} + +} // namespace framework diff --git a/framework/source/uielement/recentfilesmenucontroller.cxx b/framework/source/uielement/recentfilesmenucontroller.cxx new file mode 100644 index 000000000000..cec95485dacd --- /dev/null +++ b/framework/source/uielement/recentfilesmenucontroller.cxx @@ -0,0 +1,484 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include <uielement/recentfilesmenucontroller.hxx> + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <threadhelp/resetableguard.hxx> +#include "services.h" + +#ifndef __FRAMEWORK_CLASSES_RESOURCE_HRC_ +#include <classes/resource.hrc> +#endif +#include <classes/fwkresid.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/awt/XDevice.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/awt/MenuItemStyle.hpp> +#include <com/sun/star/util/XStringWidth.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ + +#ifndef _VCL_MENU_HXX_ +#include <vcl/menu.hxx> +#endif +#include <vcl/svapp.hxx> +#include <vcl/i18nhelp.hxx> +#include <tools/urlobj.hxx> +#include <rtl/ustrbuf.hxx> +#include <unotools/historyoptions.hxx> +#include <cppuhelper/implbase1.hxx> +#include <osl/file.hxx> +//#include <tools/solar.hrc> +#include <dispatch/uieventloghelper.hxx> + +//_________________________________________________________________________________________________________________ +// Defines +//_________________________________________________________________________________________________________________ +// + +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; + +static const char SFX_REFERER_USER[] = "private:user"; + +namespace framework +{ + +class RecentFilesStringLength : public ::cppu::WeakImplHelper1< ::com::sun::star::util::XStringWidth > +{ + public: + RecentFilesStringLength() {} + virtual ~RecentFilesStringLength() {} + + // XStringWidth + sal_Int32 SAL_CALL queryStringWidth( const ::rtl::OUString& aString ) + throw (::com::sun::star::uno::RuntimeException) + { + return aString.getLength(); + } +}; + +DEFINE_XSERVICEINFO_MULTISERVICE ( RecentFilesMenuController , + OWeakObject , + SERVICENAME_POPUPMENUCONTROLLER , + IMPLEMENTATIONNAME_RECENTFILESMENUCONTROLLER + ) + +DEFINE_INIT_SERVICE ( RecentFilesMenuController, {} ) + +RecentFilesMenuController::RecentFilesMenuController( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ) : + PopupMenuControllerBase( xServiceManager ), + m_bDisabled( sal_False ) +{ +} + +RecentFilesMenuController::~RecentFilesMenuController() +{ +} + +// private function +void RecentFilesMenuController::fillPopupMenu( Reference< css::awt::XPopupMenu >& rPopupMenu ) +{ + VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( rPopupMenu ); + PopupMenu* pVCLPopupMenu = 0; + + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + resetPopupMenu( rPopupMenu ); + if ( pPopupMenu ) + pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu(); + + if ( pVCLPopupMenu ) + { + Sequence< Sequence< PropertyValue > > aHistoryList = SvtHistoryOptions().GetList( ePICKLIST ); + Reference< XStringWidth > xStringLength( new RecentFilesStringLength ); + + int nPickListMenuItems = ( aHistoryList.getLength() > 99 ) ? 99 : aHistoryList.getLength(); + + // New vnd.sun.star.popup: command URL to support direct dispatches + const rtl::OUString aCmdPrefix( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.popup:RecentFileList?entry=" )); + + m_aRecentFilesItems.clear(); + if (( nPickListMenuItems > 0 ) && !m_bDisabled ) + { + for ( int i = 0; i < nPickListMenuItems; i++ ) + { + Sequence< PropertyValue >& rPickListEntry = aHistoryList[i]; + RecentFile aRecentFile; + + for ( int j = 0; j < rPickListEntry.getLength(); j++ ) + { + Any a = rPickListEntry[j].Value; + + if ( rPickListEntry[j].Name == HISTORY_PROPERTYNAME_URL ) + a >>= aRecentFile.aURL; + else if ( rPickListEntry[j].Name == HISTORY_PROPERTYNAME_FILTER ) + a >>= aRecentFile.aFilter; + else if ( rPickListEntry[j].Name == HISTORY_PROPERTYNAME_TITLE ) + a >>= aRecentFile.aTitle; + else if ( rPickListEntry[j].Name == HISTORY_PROPERTYNAME_PASSWORD ) + a >>= aRecentFile.aPassword; + } + + m_aRecentFilesItems.push_back( aRecentFile ); + } + } + + if ( !m_aRecentFilesItems.empty() ) + { + URL aTargetURL; + + const sal_uInt32 nCount = m_aRecentFilesItems.size(); + for ( sal_uInt32 i = 0; i < nCount; i++ ) + { + char menuShortCut[5] = "~n: "; + + ::rtl::OUString aMenuShortCut; + if ( i <= 9 ) + { + if ( i == 9 ) + aMenuShortCut = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "1~0: " )); + else + { + menuShortCut[1] = (char)( '1' + i ); + aMenuShortCut = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( menuShortCut )); + } + } + else + { + aMenuShortCut = rtl::OUString::valueOf((sal_Int32)( i + 1 )); + aMenuShortCut += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ": " )); + } + + // Abbreviate URL + rtl::OUString aURLString( aCmdPrefix + rtl::OUString::valueOf( sal_Int32( i ))); + rtl::OUString aTipHelpText; + rtl::OUString aMenuTitle; + INetURLObject aURL( m_aRecentFilesItems[i].aURL ); + + if ( aURL.GetProtocol() == INET_PROT_FILE ) + { + // Do handle file URL differently => convert it to a system + // path and abbreviate it with a special function: + String aFileSystemPath( aURL.getFSysPath( INetURLObject::FSYS_DETECT ) ); + + ::rtl::OUString aSystemPath( aFileSystemPath ); + ::rtl::OUString aCompactedSystemPath; + + aTipHelpText = aSystemPath; + oslFileError nError = osl_abbreviateSystemPath( aSystemPath.pData, &aCompactedSystemPath.pData, 46, NULL ); + if ( !nError ) + aMenuTitle = String( aCompactedSystemPath ); + else + aMenuTitle = aSystemPath; + } + else + { + // Use INetURLObject to abbreviate all other URLs + String aShortURL; + aShortURL = aURL.getAbbreviated( xStringLength, 46, INetURLObject::DECODE_UNAMBIGUOUS ); + aMenuTitle += aShortURL; + aTipHelpText = aURLString; + } + + ::rtl::OUString aTitle( aMenuShortCut + aMenuTitle ); + + pVCLPopupMenu->InsertItem( USHORT( i+1 ), aTitle ); + pVCLPopupMenu->SetTipHelpText( USHORT( i+1 ), aTipHelpText ); + pVCLPopupMenu->SetItemCommand( USHORT( i+1 ), aURLString ); + } + } + else + { + // No recent documents => insert "no document" string + String aNoDocumentStr = String( FwkResId( STR_NODOCUMENT )); + pVCLPopupMenu->InsertItem( 1, aNoDocumentStr ); + pVCLPopupMenu->EnableItem( 1, FALSE ); + } + } +} + +void RecentFilesMenuController::executeEntry( sal_Int32 nIndex ) +{ + static int NUM_OF_PICKLIST_ARGS = 3; + + Reference< css::awt::XPopupMenu > xPopupMenu; + Reference< XDispatch > xDispatch; + Reference< XDispatchProvider > xDispatchProvider; + Reference< XMultiServiceFactory > xServiceManager; + + ResetableGuard aLock( m_aLock ); + xPopupMenu = m_xPopupMenu; + xDispatchProvider = Reference< XDispatchProvider >( m_xFrame, UNO_QUERY ); + xServiceManager = m_xServiceManager; + aLock.unlock(); + + css::util::URL aTargetURL; + Sequence< PropertyValue > aArgsList; + + if (( nIndex >= 0 ) && + ( nIndex < sal::static_int_cast<sal_Int32>( m_aRecentFilesItems.size() ))) + { + const RecentFile& rRecentFile = m_aRecentFilesItems[ nIndex ]; + + aTargetURL.Complete = rRecentFile.aURL; + m_xURLTransformer->parseStrict( aTargetURL ); + + aArgsList.realloc( NUM_OF_PICKLIST_ARGS ); + aArgsList[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Referer" )); + aArgsList[0].Value = makeAny( ::rtl::OUString::createFromAscii( SFX_REFERER_USER )); + + // documents in the picklist will never be opened as templates + aArgsList[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AsTemplate" )); + aArgsList[1].Value = makeAny( (sal_Bool) sal_False ); + + ::rtl::OUString aFilter( rRecentFile.aFilter ); + sal_Int32 nPos = aFilter.indexOf( '|' ); + if ( nPos >= 0 ) + { + ::rtl::OUString aFilterOptions; + + if ( nPos < ( aFilter.getLength() - 1 ) ) + aFilterOptions = aFilter.copy( nPos+1 ); + + aArgsList[2].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterOptions" )); + aArgsList[2].Value <<= aFilterOptions; + + aFilter = aFilter.copy( 0, nPos-1 ); + aArgsList.realloc( ++NUM_OF_PICKLIST_ARGS ); + } + + aArgsList[NUM_OF_PICKLIST_ARGS-1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" )); + aArgsList[NUM_OF_PICKLIST_ARGS-1].Value <<= aFilter; + + xDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString::createFromAscii("_default"), 0 ); + } + + if ( xDispatch.is() ) + { + // Call dispatch asychronously as we can be destroyed while dispatch is + // executed. VCL is not able to survive this as it wants to call listeners + // after select!!! + LoadRecentFile* pLoadRecentFile = new LoadRecentFile; + pLoadRecentFile->xDispatch = xDispatch; + pLoadRecentFile->aTargetURL = aTargetURL; + pLoadRecentFile->aArgSeq = aArgsList; + if(::comphelper::UiEventsLogger::isEnabled()) //#i88653# + UiEventLogHelper(::rtl::OUString::createFromAscii("RecentFilesMenuController")).log(m_xServiceManager, m_xFrame, aTargetURL, aArgsList); + Application::PostUserEvent( STATIC_LINK(0, RecentFilesMenuController, ExecuteHdl_Impl), pLoadRecentFile ); + } +} + +// XEventListener +void SAL_CALL RecentFilesMenuController::disposing( const EventObject& ) throw ( RuntimeException ) +{ + Reference< css::awt::XMenuListener > xHolder(( OWeakObject *)this, UNO_QUERY ); + + ResetableGuard aLock( m_aLock ); + m_xFrame.clear(); + m_xDispatch.clear(); + m_xServiceManager.clear(); + + if ( m_xPopupMenu.is() ) + m_xPopupMenu->removeMenuListener( Reference< css::awt::XMenuListener >(( OWeakObject *)this, UNO_QUERY )); + m_xPopupMenu.clear(); +} + +// XStatusListener +void SAL_CALL RecentFilesMenuController::statusChanged( const FeatureStateEvent& Event ) throw ( RuntimeException ) +{ + ResetableGuard aLock( m_aLock ); + m_bDisabled = !Event.IsEnabled; +} + +void SAL_CALL RecentFilesMenuController::select( const css::awt::MenuEvent& rEvent ) throw (RuntimeException) +{ + Reference< css::awt::XPopupMenu > xPopupMenu; + Reference< XDispatch > xDispatch; + Reference< XDispatchProvider > xDispatchProvider; + Reference< XMultiServiceFactory > xServiceManager; + + ResetableGuard aLock( m_aLock ); + xPopupMenu = m_xPopupMenu; + xDispatchProvider = Reference< XDispatchProvider >( m_xFrame, UNO_QUERY ); + xServiceManager = m_xServiceManager; + aLock.unlock(); + + css::util::URL aTargetURL; + Sequence< PropertyValue > aArgsList; + + if ( xPopupMenu.is() && xDispatchProvider.is() ) + { + VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXPopupMenu::GetImplementation( xPopupMenu ); + if ( pPopupMenu ) + executeEntry( rEvent.MenuId-1 ); + } +} + +void SAL_CALL RecentFilesMenuController::activate( const css::awt::MenuEvent& ) throw (RuntimeException) +{ + ResetableGuard aLock( m_aLock ); + impl_setPopupMenu(); +} + +// XPopupMenuController +void RecentFilesMenuController::impl_setPopupMenu() +{ + if ( m_xPopupMenu.is() ) + fillPopupMenu( m_xPopupMenu ); +} + +void SAL_CALL RecentFilesMenuController::updatePopupMenu() throw (RuntimeException) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + Reference< XStatusListener > xStatusListener( static_cast< OWeakObject* >( this ), UNO_QUERY ); + Reference< XDispatch > xDispatch( m_xDispatch ); + com::sun::star::util::URL aTargetURL; + aTargetURL.Complete = m_aCommandURL; + m_xURLTransformer->parseStrict( aTargetURL ); + aLock.unlock(); + + // Add/remove status listener to get a status update once + if ( xDispatch.is() ) + { + xDispatch->addStatusListener( xStatusListener, aTargetURL ); + xDispatch->removeStatusListener( xStatusListener, aTargetURL ); + } +} + +// XDispatchProvider +Reference< XDispatch > SAL_CALL RecentFilesMenuController::queryDispatch( + const URL& aURL, + const ::rtl::OUString& /*sTarget*/, + sal_Int32 /*nFlags*/ ) +throw( RuntimeException ) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + if ( aURL.Complete.indexOf( m_aBaseURL ) == 0 ) + return Reference< XDispatch >( static_cast< OWeakObject* >( this ), UNO_QUERY ); + else + return Reference< XDispatch >(); +} + +// XDispatch +void SAL_CALL RecentFilesMenuController::dispatch( + const URL& aURL, + const Sequence< PropertyValue >& /*seqProperties*/ ) +throw( RuntimeException ) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + if ( aURL.Complete.indexOf( m_aBaseURL ) == 0 ) + { + // Parse URL to retrieve entry argument and its value + sal_Int32 nQueryPart = aURL.Complete.indexOf( '?', m_aBaseURL.getLength() ); + if ( nQueryPart > 0 ) + { + const rtl::OUString aEntryArgStr( RTL_CONSTASCII_USTRINGPARAM( "entry=" )); + sal_Int32 nEntryArg = aURL.Complete.indexOf( aEntryArgStr, nQueryPart ); + sal_Int32 nEntryPos = nEntryArg + aEntryArgStr.getLength(); + if (( nEntryArg > 0 ) && ( nEntryPos < aURL.Complete.getLength() )) + { + sal_Int32 nAddArgs = aURL.Complete.indexOf( '&', nEntryPos ); + rtl::OUString aEntryArg; + + if ( nAddArgs < 0 ) + aEntryArg = aURL.Complete.copy( nEntryPos ); + else + aEntryArg = aURL.Complete.copy( nEntryPos, nAddArgs-nEntryPos ); + + sal_Int32 nEntry = aEntryArg.toInt32(); + executeEntry( nEntry ); + } + } + } +} + +void SAL_CALL RecentFilesMenuController::addStatusListener( + const Reference< XStatusListener >& xControl, + const URL& aURL ) +throw( RuntimeException ) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + PopupMenuControllerBase::addStatusListener( xControl, aURL ); +} + +void SAL_CALL RecentFilesMenuController::removeStatusListener( + const Reference< XStatusListener >& xControl, + const URL& aURL ) +throw( RuntimeException ) +{ + PopupMenuControllerBase::removeStatusListener( xControl, aURL ); +} + +IMPL_STATIC_LINK_NOINSTANCE( RecentFilesMenuController, ExecuteHdl_Impl, LoadRecentFile*, pLoadRecentFile ) +{ + 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! + pLoadRecentFile->xDispatch->dispatch( pLoadRecentFile->aTargetURL, pLoadRecentFile->aArgSeq ); + } + catch ( Exception& ) + { + } + + delete pLoadRecentFile; + return 0; +} + +} diff --git a/framework/source/uielement/rootitemcontainer.cxx b/framework/source/uielement/rootitemcontainer.cxx new file mode 100644 index 000000000000..8c81f31f2394 --- /dev/null +++ b/framework/source/uielement/rootitemcontainer.cxx @@ -0,0 +1,466 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <uielement/rootitemcontainer.hxx> + +#ifndef __FRAMEWORK_UIELEMENT_ITEMCONTAINER_HHX_ +#include <uielement/itemcontainer.hxx> +#endif + +#ifndef __FRAMEWORK_UIELEMENT_CONSTITEMCONTAINER_HHX_ +#include <uielement/constitemcontainer.hxx> +#endif +#include <threadhelp/resetableguard.hxx> +#include <general.h> +#include <properties.h> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/beans/PropertyAttribute.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ + +using namespace cppu; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::container; + +const char WRONG_TYPE_EXCEPTION[] = "Type must be com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >"; + +const int PROPHANDLE_UINAME = 1; +const int PROPCOUNT = 1; +const rtl::OUString PROPNAME_UINAME( RTL_CONSTASCII_USTRINGPARAM( "UIName" )); + +namespace framework +{ + +//***************************************************************************************************************** +// XInterface, XTypeProvider +//***************************************************************************************************************** +DEFINE_XINTERFACE_10 ( RootItemContainer , + OWeakObject , + DIRECT_INTERFACE( ::com::sun::star::lang::XTypeProvider ), + DIRECT_INTERFACE( ::com::sun::star::container::XIndexContainer ), + DIRECT_INTERFACE( ::com::sun::star::lang::XUnoTunnel ), + DIRECT_INTERFACE( ::com::sun::star::lang::XSingleComponentFactory ), + DIRECT_INTERFACE( ::com::sun::star::beans::XMultiPropertySet ), + DIRECT_INTERFACE( ::com::sun::star::beans::XFastPropertySet ), + DIRECT_INTERFACE( ::com::sun::star::beans::XPropertySet ), + DERIVED_INTERFACE( ::com::sun::star::container::XIndexReplace, com::sun::star::container::XIndexContainer ), + DERIVED_INTERFACE( ::com::sun::star::container::XIndexAccess, com::sun::star::container::XIndexReplace ), + DERIVED_INTERFACE( ::com::sun::star::container::XElementAccess, ::com::sun::star::container::XIndexAccess ) + ) + +DEFINE_XTYPEPROVIDER_10 ( RootItemContainer , + ::com::sun::star::lang::XTypeProvider , + ::com::sun::star::container::XIndexContainer , + ::com::sun::star::container::XIndexReplace , + ::com::sun::star::container::XIndexAccess , + ::com::sun::star::container::XElementAccess , + ::com::sun::star::beans::XMultiPropertySet , + ::com::sun::star::beans::XFastPropertySet , + ::com::sun::star::beans::XPropertySet , + ::com::sun::star::lang::XUnoTunnel , + ::com::sun::star::lang::XSingleComponentFactory + ) + +RootItemContainer::RootItemContainer() + : ThreadHelpBase ( ) + , ::cppu::OBroadcastHelperVar< ::cppu::OMultiTypeInterfaceContainerHelper, ::cppu::OMultiTypeInterfaceContainerHelper::keyType >( m_aLock.getShareableOslMutex() ) + , ::cppu::OPropertySetHelper ( *(static_cast< ::cppu::OBroadcastHelper* >(this)) ) + , ::cppu::OWeakObject() +{ +} + +RootItemContainer::RootItemContainer( const ConstItemContainer& rConstItemContainer ) + : ThreadHelpBase ( ) + , ::cppu::OBroadcastHelperVar< ::cppu::OMultiTypeInterfaceContainerHelper, ::cppu::OMultiTypeInterfaceContainerHelper::keyType >( m_aLock.getShareableOslMutex() ) + , ::cppu::OPropertySetHelper ( *(static_cast< ::cppu::OBroadcastHelper* >(this)) ) + , ::cppu::OWeakObject() +{ + m_aUIName = rConstItemContainer.m_aUIName; + copyItemContainer( rConstItemContainer.m_aItemVector ); +} + +RootItemContainer::RootItemContainer( const Reference< XIndexAccess >& rSourceContainer ) + : ThreadHelpBase ( ) + , ::cppu::OBroadcastHelperVar< ::cppu::OMultiTypeInterfaceContainerHelper, ::cppu::OMultiTypeInterfaceContainerHelper::keyType >( m_aLock.getShareableOslMutex() ) + , ::cppu::OPropertySetHelper ( *(static_cast< ::cppu::OBroadcastHelper* >(this)) ) + , ::cppu::OWeakObject() +{ + // We also have to copy the UIName property + try + { + Reference< XPropertySet > xPropSet( rSourceContainer, UNO_QUERY ); + if ( xPropSet.is() ) + { + xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UIName" ))) >>= m_aUIName; + } + } + catch ( Exception& ) + { + } + + if ( rSourceContainer.is() ) + { + sal_Int32 nCount = rSourceContainer->getCount(); + try + { + for ( sal_Int32 i = 0; i < nCount; i++ ) + { + Sequence< PropertyValue > aPropSeq; + if ( rSourceContainer->getByIndex( i ) >>= aPropSeq ) + { + sal_Int32 nContainerIndex = -1; + Reference< XIndexAccess > xIndexAccess; + for ( sal_Int32 j = 0; j < aPropSeq.getLength(); j++ ) + { + if ( aPropSeq[j].Name.equalsAscii( "ItemDescriptorContainer" )) + { + aPropSeq[j].Value >>= xIndexAccess; + nContainerIndex = j; + break; + } + } + + if ( xIndexAccess.is() && nContainerIndex >= 0 ) + aPropSeq[nContainerIndex].Value <<= deepCopyContainer( xIndexAccess ); + + m_aItemVector.push_back( aPropSeq ); + } + } + } + catch ( IndexOutOfBoundsException& ) + { + } + } +} + +RootItemContainer::~RootItemContainer() +{ +} + +// private +void RootItemContainer::copyItemContainer( const std::vector< Sequence< PropertyValue > >& rSourceVector ) +{ + const sal_uInt32 nCount = rSourceVector.size(); + m_aItemVector.reserve(nCount); + for ( sal_uInt32 i = 0; i < nCount; i++ ) + { + sal_Int32 nContainerIndex = -1; + Sequence< PropertyValue > aPropSeq( rSourceVector[i] ); + Reference< XIndexAccess > xIndexAccess; + for ( sal_Int32 j = 0; j < aPropSeq.getLength(); j++ ) + { + if ( aPropSeq[j].Name.equalsAscii( "ItemDescriptorContainer" )) + { + aPropSeq[j].Value >>= xIndexAccess; + nContainerIndex = j; + break; + } + } + + if ( xIndexAccess.is() && nContainerIndex >= 0 ) + aPropSeq[nContainerIndex].Value <<= deepCopyContainer( xIndexAccess ); + + m_aItemVector.push_back( aPropSeq ); + } +} + +Reference< XIndexAccess > RootItemContainer::deepCopyContainer( const Reference< XIndexAccess >& rSubContainer ) +{ + Reference< XIndexAccess > xReturn; + if ( rSubContainer.is() ) + { + ConstItemContainer* pSource = ConstItemContainer::GetImplementation( rSubContainer ); + ItemContainer* pSubContainer( 0 ); + if ( pSource ) + pSubContainer = new ItemContainer( *pSource, m_aShareMutex ); + else + pSubContainer = new ItemContainer( rSubContainer, m_aShareMutex ); + xReturn = Reference< XIndexAccess >( static_cast< OWeakObject* >( pSubContainer ), UNO_QUERY ); + } + + return xReturn; +} + +// XUnoTunnel +sal_Int64 RootItemContainer::getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& rIdentifier ) throw(::com::sun::star::uno::RuntimeException) +{ + if( ( rIdentifier.getLength() == 16 ) && ( 0 == rtl_compareMemory( RootItemContainer::GetUnoTunnelId().getConstArray(), rIdentifier.getConstArray(), 16 ) ) ) + return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >( this )); + return 0; +} + +const Sequence< sal_Int8 >& RootItemContainer::GetUnoTunnelId() throw() +{ + static ::com::sun::star::uno::Sequence< sal_Int8 > * pSeq = NULL; + if( !pSeq ) + { + ::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static ::com::sun::star::uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +RootItemContainer* RootItemContainer::GetImplementation( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rxIFace ) throw() +{ + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XUnoTunnel > xUT( rxIFace, ::com::sun::star::uno::UNO_QUERY ); + return xUT.is() ? reinterpret_cast< RootItemContainer* >(sal::static_int_cast< sal_IntPtr >( + xUT->getSomething( RootItemContainer::GetUnoTunnelId() ))) : NULL; +} + +// XElementAccess +sal_Bool SAL_CALL RootItemContainer::hasElements() +throw ( RuntimeException ) +{ + ShareGuard aLock( m_aShareMutex ); + return ( !m_aItemVector.empty() ); +} + +// XIndexAccess +sal_Int32 SAL_CALL RootItemContainer::getCount() +throw ( RuntimeException ) +{ + ShareGuard aLock( m_aShareMutex ); + return m_aItemVector.size(); +} + +Any SAL_CALL RootItemContainer::getByIndex( sal_Int32 Index ) +throw ( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) +{ + ShareGuard aLock( m_aShareMutex ); + if ( sal_Int32( m_aItemVector.size()) > Index ) + return makeAny( m_aItemVector[Index] ); + else + throw IndexOutOfBoundsException( ::rtl::OUString(), (OWeakObject *)this ); +} + +// XIndexContainer +void SAL_CALL RootItemContainer::insertByIndex( sal_Int32 Index, const Any& aItem ) +throw ( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) +{ + Sequence< PropertyValue > aSeq; + if ( aItem >>= aSeq ) + { + ShareGuard aLock( m_aShareMutex ); + if ( sal_Int32( m_aItemVector.size()) == Index ) + m_aItemVector.push_back( aSeq ); + else if ( sal_Int32( m_aItemVector.size()) >Index ) + { + std::vector< Sequence< PropertyValue > >::iterator aIter = m_aItemVector.begin(); + aIter += Index; + m_aItemVector.insert( aIter, aSeq ); + } + else + throw IndexOutOfBoundsException( ::rtl::OUString(), (OWeakObject *)this ); + } + else + throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( WRONG_TYPE_EXCEPTION )), + (OWeakObject *)this, 2 ); +} + +void SAL_CALL RootItemContainer::removeByIndex( sal_Int32 Index ) +throw ( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) +{ + ShareGuard aLock( m_aShareMutex ); + if ( (sal_Int32)m_aItemVector.size() > Index ) + { + std::vector< Sequence< PropertyValue > >::iterator aIter = m_aItemVector.begin(); + aIter += Index; + m_aItemVector.erase( aIter ); + } + else + throw IndexOutOfBoundsException( ::rtl::OUString(), (OWeakObject *)this ); +} + +void SAL_CALL RootItemContainer::replaceByIndex( sal_Int32 Index, const Any& aItem ) +throw ( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) +{ + Sequence< PropertyValue > aSeq; + if ( aItem >>= aSeq ) + { + ShareGuard aLock( m_aShareMutex ); + if ( sal_Int32( m_aItemVector.size()) > Index ) + m_aItemVector[Index] = aSeq; + else + throw IndexOutOfBoundsException( ::rtl::OUString(), (OWeakObject *)this ); + } + else + throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( WRONG_TYPE_EXCEPTION )), + (OWeakObject *)this, 2 ); +} + +Reference< XInterface > SAL_CALL RootItemContainer::createInstanceWithContext( const Reference< XComponentContext >& ) +throw ( Exception, RuntimeException) +{ + return (OWeakObject *)(new ItemContainer( m_aShareMutex )); +} + +Reference< XInterface > SAL_CALL RootItemContainer::createInstanceWithArgumentsAndContext( const Sequence< Any >&, const Reference< XComponentContext >& ) +throw (Exception, RuntimeException) +{ + return (OWeakObject *)(new ItemContainer( m_aShareMutex )); +} + +// XPropertySet helper +sal_Bool SAL_CALL RootItemContainer::convertFastPropertyValue( Any& aConvertedValue , + Any& aOldValue , + sal_Int32 nHandle , + const Any& aValue ) +throw( com::sun::star::lang::IllegalArgumentException ) +{ + // Initialize state with FALSE !!! + // (Handle can be invalid) + sal_Bool bReturn = sal_False; + + switch( nHandle ) + { + case PROPHANDLE_UINAME: + bReturn = PropHelper::willPropertyBeChanged( + com::sun::star::uno::makeAny(m_aUIName), + aValue, + aOldValue, + aConvertedValue); + break; + } + + // Return state of operation. + return bReturn ; +} + +void SAL_CALL RootItemContainer::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle , + const com::sun::star::uno::Any& aValue ) +throw( com::sun::star::uno::Exception ) +{ + switch( nHandle ) + { + case PROPHANDLE_UINAME: + aValue >>= m_aUIName; + break; + } +} + +void SAL_CALL RootItemContainer::getFastPropertyValue( com::sun::star::uno::Any& aValue , + sal_Int32 nHandle ) const +{ + switch( nHandle ) + { + case PROPHANDLE_UINAME: + aValue <<= m_aUIName; + break; + } +} + +::cppu::IPropertyArrayHelper& SAL_CALL RootItemContainer::getInfoHelper() +{ + // Optimize this method ! + // We initialize a static variable only one time. And we don't must use a mutex at every call! + // For the first call; pInfoHelper is NULL - for the second call pInfoHelper is different from NULL! + static ::cppu::OPropertyArrayHelper* pInfoHelper = NULL; + + if( pInfoHelper == NULL ) + { + // Ready for multithreading + osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ; + + // Control this pointer again, another instance can be faster then these! + if( pInfoHelper == NULL ) + { + // Define static member to give structure of properties to baseclass "OPropertySetHelper". + // "impl_getStaticPropertyDescriptor" is a non exported and static funtion, who will define a static propertytable. + // "sal_True" say: Table is sorted by name. + static ::cppu::OPropertyArrayHelper aInfoHelper( impl_getStaticPropertyDescriptor(), sal_True ); + pInfoHelper = &aInfoHelper; + } + } + + return(*pInfoHelper); +} + +com::sun::star::uno::Reference< com::sun::star::beans::XPropertySetInfo > SAL_CALL RootItemContainer::getPropertySetInfo() +throw (::com::sun::star::uno::RuntimeException) +{ + // Optimize this method ! + // We initialize a static variable only one time. And we don't must use a mutex at every call! + // For the first call; pInfo is NULL - for the second call pInfo is different from NULL! + static com::sun::star::uno::Reference< com::sun::star::beans::XPropertySetInfo >* pInfo = NULL; + + if( pInfo == NULL ) + { + // Ready for multithreading + osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ; + // Control this pointer again, another instance can be faster then these! + if( pInfo == NULL ) + { + // Create structure of propertysetinfo for baseclass "OPropertySetHelper". + // (Use method "getInfoHelper()".) + static com::sun::star::uno::Reference< com::sun::star::beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) ); + pInfo = &xInfo; + } + } + + return (*pInfo); +} + +const com::sun::star::uno::Sequence< com::sun::star::beans::Property > RootItemContainer::impl_getStaticPropertyDescriptor() +{ + // Create a new static property array to initialize sequence! + // Table of all predefined properties of this class. Its used from OPropertySetHelper-class! + // Don't forget to change the defines (see begin of this file), if you add, change or delete a property in this list!!! + // It's necessary for methods of OPropertySetHelper. + // ATTENTION: + // YOU MUST SORT FOLLOW TABLE BY NAME ALPHABETICAL !!! + + static const com::sun::star::beans::Property pProperties[] = + { + com::sun::star::beans::Property( PROPNAME_UINAME, PROPHANDLE_UINAME , + ::getCppuType((const rtl::OUString*)NULL), + com::sun::star::beans::PropertyAttribute::TRANSIENT ) + }; + // Use it to initialize sequence! + static const com::sun::star::uno::Sequence< com::sun::star::beans::Property > lPropertyDescriptor( pProperties, PROPCOUNT ); + // Return static "PropertyDescriptor" + return lPropertyDescriptor; +} + +} // namespace framework + diff --git a/framework/source/uielement/simpletextstatusbarcontroller.cxx b/framework/source/uielement/simpletextstatusbarcontroller.cxx new file mode 100644 index 000000000000..4e7855fb4900 --- /dev/null +++ b/framework/source/uielement/simpletextstatusbarcontroller.cxx @@ -0,0 +1,196 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include <uielement/simpletextstatusbarcontroller.hxx> +#include <classes/fwkresid.hxx> +#include <services.h> +#include <classes/resource.hrc> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> +#include <vcl/window.hxx> +#include <vcl/status.hxx> +#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ +#include <toolkit/unohlp.hxx> +#endif +#include <toolkit/helper/convert.hxx> + +using namespace ::rtl; +using namespace ::cppu; +using namespace ::com::sun::star; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; + +namespace framework +{ + +DEFINE_XSERVICEINFO_MULTISERVICE ( SimpleTextStatusbarController , + OWeakObject , + SERVICENAME_STATUSBARCONTROLLER , + IMPLEMENTATIONNAME_SIMPLETEXTSTATUSBARCONTROLLER + ) + +DEFINE_INIT_SERVICE ( SimpleTextStatusbarController, {} ) + +SimpleTextStatusbarController::SimpleTextStatusbarController( const uno::Reference< lang::XMultiServiceFactory >& xServiceManager ) : + svt::StatusbarController( xServiceManager, uno::Reference< frame::XFrame >(), rtl::OUString(), 0 ) +{ +} + +SimpleTextStatusbarController::~SimpleTextStatusbarController() +{ +} + +// XInterface +Any SAL_CALL SimpleTextStatusbarController::queryInterface( const Type& rType ) +throw ( RuntimeException ) +{ + return svt::StatusbarController::queryInterface( rType ); +} + +void SAL_CALL SimpleTextStatusbarController::acquire() throw () +{ + svt::StatusbarController::acquire(); +} + +void SAL_CALL SimpleTextStatusbarController::release() throw () +{ + svt::StatusbarController::release(); +} + +void SAL_CALL SimpleTextStatusbarController::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) +throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + const rtl::OUString aPropValueName( RTL_CONSTASCII_USTRINGPARAM( "Value" )); + + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + svt::StatusbarController::initialize( aArguments ); + + rtl::OUString aValue; + beans::PropertyValue aPropValue; + + // Check arguments for optional "Value" property. We need it + // to set our internal simple text. + for ( int i = 0; i < aArguments.getLength(); i++ ) + { + if (( aArguments[i] >>= aPropValue ) && ( aPropValue.Name.equals( aPropValueName ))) + { + aPropValue.Value >>= aValue; + break; + } + } + + m_aText = aValue; + if ( m_xParentWindow.is() && m_nID > 0 ) + { + Window* pWindow = VCLUnoHelper::GetWindow( m_xParentWindow ); + if ( pWindow && ( pWindow->GetType() == WINDOW_STATUSBAR )) + { + StatusBar* pStatusBar = (StatusBar *)pWindow; + pStatusBar->SetItemText( m_nID, m_aText ); + } + } +} + +// XComponent +void SAL_CALL SimpleTextStatusbarController::dispose() +throw (::com::sun::star::uno::RuntimeException) +{ + svt::StatusbarController::dispose(); +} + +// XEventListener +void SAL_CALL SimpleTextStatusbarController::disposing( const EventObject& Source ) +throw ( RuntimeException ) +{ + svt::StatusbarController::disposing( Source ); +} + +// XStatusListener +void SAL_CALL SimpleTextStatusbarController::statusChanged( const FeatureStateEvent& ) +throw ( RuntimeException ) +{ +} + +// XStatusbarController +::sal_Bool SAL_CALL SimpleTextStatusbarController::mouseButtonDown( + const ::com::sun::star::awt::MouseEvent& ) +throw (::com::sun::star::uno::RuntimeException) +{ + return sal_False; +} + +::sal_Bool SAL_CALL SimpleTextStatusbarController::mouseMove( + const ::com::sun::star::awt::MouseEvent& ) +throw (::com::sun::star::uno::RuntimeException) +{ + return sal_False; +} + +::sal_Bool SAL_CALL SimpleTextStatusbarController::mouseButtonUp( + const ::com::sun::star::awt::MouseEvent& ) +throw (::com::sun::star::uno::RuntimeException) +{ + return sal_False; +} + +void SAL_CALL SimpleTextStatusbarController::command( + const ::com::sun::star::awt::Point& aPos, + ::sal_Int32 nCommand, + ::sal_Bool bMouseEvent, + const ::com::sun::star::uno::Any& aData ) +throw (::com::sun::star::uno::RuntimeException) +{ + svt::StatusbarController::command( aPos, nCommand, bMouseEvent, aData ); +} + +void SAL_CALL SimpleTextStatusbarController::paint( + const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics >& xGraphics, + const ::com::sun::star::awt::Rectangle& rOutputRectangle, + ::sal_Int32 nItemId, + ::sal_Int32 nStyle ) +throw (::com::sun::star::uno::RuntimeException) +{ + svt::StatusbarController::paint( xGraphics, rOutputRectangle, nItemId, nStyle ); +} + +void SAL_CALL SimpleTextStatusbarController::click() +throw (::com::sun::star::uno::RuntimeException) +{ + svt::StatusbarController::click(); +} + +void SAL_CALL SimpleTextStatusbarController::doubleClick() throw (::com::sun::star::uno::RuntimeException) +{ + svt::StatusbarController::doubleClick(); +} + +} diff --git a/framework/source/uielement/spinfieldtoolbarcontroller.cxx b/framework/source/uielement/spinfieldtoolbarcontroller.cxx new file mode 100644 index 000000000000..43ad09ffc1ee --- /dev/null +++ b/framework/source/uielement/spinfieldtoolbarcontroller.cxx @@ -0,0 +1,578 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + +#include <stdio.h> +#include <wchar.h> + +#ifndef __FRAMEWORK_UIELEMENT_SPINFIELDTOOLBARCONTROLLER_HXX +#include "uielement/spinfieldtoolbarcontroller.hxx" +#endif + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ + +#ifndef __FRAMEWORK_TOOLBAR_HXX_ +#include "uielement/toolbar.hxx" +#endif + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/frame/status/ItemStatus.hpp> +#include <com/sun/star/frame/status/ItemState.hpp> +#include <com/sun/star/frame/status/Visibility.hpp> +#include <com/sun/star/frame/XControlNotificationListener.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ +#include <svtools/toolboxcontroller.hxx> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> +#ifndef _VCL_MNEMONIC_HXX_ +#include <vcl/mnemonic.hxx> +#endif +#include <tools/urlobj.hxx> +#ifdef WINNT +#include <systools/win32/snprintf.h> +#endif + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::frame::status; +using namespace ::com::sun::star::util; + +namespace framework +{ + +// ------------------------------------------------------------------ + +// Wrapper class to notify controller about events from combobox. +// Unfortunaltly the events are notifed through virtual methods instead +// of Listeners. + +class SpinfieldControl : public SpinField +{ + public: + SpinfieldControl( Window* pParent, WinBits nStyle, ISpinfieldListener* pSpinFieldListener ); + virtual ~SpinfieldControl(); + + virtual void Up(); + virtual void Down(); + virtual void First(); + virtual void Last(); + virtual void KeyInput( const ::KeyEvent& rKEvt ); + virtual void Modify(); + virtual void GetFocus(); + virtual void LoseFocus(); + virtual void StateChanged( StateChangedType nType ); + virtual void DataChanged( const DataChangedEvent& rDCEvt ); + virtual long PreNotify( NotifyEvent& rNEvt ); + + private: + ISpinfieldListener* m_pSpinFieldListener; +}; + +SpinfieldControl::SpinfieldControl( Window* pParent, WinBits nStyle, ISpinfieldListener* pSpinFieldListener ) : + SpinField( pParent, nStyle ) + , m_pSpinFieldListener( pSpinFieldListener ) +{ +} + +SpinfieldControl::~SpinfieldControl() +{ + m_pSpinFieldListener = 0; +} + +void SpinfieldControl::Up() +{ + SpinField::Up(); + if ( m_pSpinFieldListener ) + m_pSpinFieldListener->Up(); +} + +void SpinfieldControl::Down() +{ + SpinField::Down(); + if ( m_pSpinFieldListener ) + m_pSpinFieldListener->Down(); +} + +void SpinfieldControl::First() +{ + SpinField::First(); + if ( m_pSpinFieldListener ) + m_pSpinFieldListener->First(); +} + +void SpinfieldControl::Last() +{ + SpinField::First(); + if ( m_pSpinFieldListener ) + m_pSpinFieldListener->Last(); +} + +void SpinfieldControl::KeyInput( const ::KeyEvent& rKEvt ) +{ + SpinField::KeyInput( rKEvt ); + if ( m_pSpinFieldListener ) + m_pSpinFieldListener->KeyInput( rKEvt ); +} + +void SpinfieldControl::Modify() +{ + SpinField::Modify(); + if ( m_pSpinFieldListener ) + m_pSpinFieldListener->Modify(); +} + +void SpinfieldControl::GetFocus() +{ + SpinField::GetFocus(); + if ( m_pSpinFieldListener ) + m_pSpinFieldListener->GetFocus(); +} + +void SpinfieldControl::LoseFocus() +{ + SpinField::GetFocus(); + if ( m_pSpinFieldListener ) + m_pSpinFieldListener->GetFocus(); +} + +void SpinfieldControl::StateChanged( StateChangedType nType ) +{ + SpinField::StateChanged( nType ); + if ( m_pSpinFieldListener ) + m_pSpinFieldListener->StateChanged( nType ); +} + +void SpinfieldControl::DataChanged( const DataChangedEvent& rDCEvt ) +{ + SpinField::DataChanged( rDCEvt ); + if ( m_pSpinFieldListener ) + m_pSpinFieldListener->DataChanged( rDCEvt ); +} + +long SpinfieldControl::PreNotify( NotifyEvent& rNEvt ) +{ + long nRet( 0 ); + if ( m_pSpinFieldListener ) + nRet = m_pSpinFieldListener->PreNotify( rNEvt ); + if ( nRet == 0 ) + nRet = SpinField::PreNotify( rNEvt ); + + return nRet; +} + +// ------------------------------------------------------------------ + +SpinfieldToolbarController::SpinfieldToolbarController( + const Reference< XMultiServiceFactory >& rServiceManager, + const Reference< XFrame >& rFrame, + ToolBox* pToolbar, + USHORT nID, + sal_Int32 nWidth, + const ::rtl::OUString& aCommand ) : + ComplexToolbarController( rServiceManager, rFrame, pToolbar, nID, aCommand ) + , m_bFloat( false ) + , m_bMaxSet( false ) + , m_bMinSet( false ) + , m_nMax( 0.0 ) + , m_nMin( 0.0 ) + , m_nValue( 0.0 ) + , m_nStep( 0.0 ) + , m_pSpinfieldControl( 0 ) +{ + m_pSpinfieldControl = new SpinfieldControl( m_pToolbar, WB_SPIN|WB_BORDER, this ); + if ( nWidth == 0 ) + nWidth = 100; + + // Calculate height of the spin field according to the application font height + sal_Int32 nHeight = getFontSizePixel( m_pSpinfieldControl ) + 5 + 1; + + m_pSpinfieldControl->SetSizePixel( ::Size( nWidth, nHeight )); + m_pToolbar->SetItemWindow( m_nID, m_pSpinfieldControl ); +} + +// ------------------------------------------------------------------ + +SpinfieldToolbarController::~SpinfieldToolbarController() +{ +} + +// ------------------------------------------------------------------ + +void SAL_CALL SpinfieldToolbarController::dispose() +throw ( RuntimeException ) +{ + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + m_pToolbar->SetItemWindow( m_nID, 0 ); + delete m_pSpinfieldControl; + + ComplexToolbarController::dispose(); + + m_pSpinfieldControl = 0; +} + +// ------------------------------------------------------------------ +Sequence<PropertyValue> SpinfieldToolbarController::getExecuteArgs(sal_Int16 KeyModifier) const +{ + Sequence<PropertyValue> aArgs( 2 ); + ::rtl::OUString aSpinfieldText = m_pSpinfieldControl->GetText(); + + // Add key modifier to argument list + aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "KeyModifier" )); + aArgs[0].Value <<= KeyModifier; + aArgs[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Value" )); + if ( m_bFloat ) + aArgs[1].Value <<= aSpinfieldText.toDouble(); + else + aArgs[1].Value <<= aSpinfieldText.toInt32(); + return aArgs; +} + +// ------------------------------------------------------------------ + +void SpinfieldToolbarController::Up() +{ + double nValue = m_nValue + m_nStep; + if ( m_bMaxSet && nValue > m_nMax ) + return; + + m_nValue = nValue; + + rtl::OUString aText = impl_formatOutputString( m_nValue ); + m_pSpinfieldControl->SetText( aText ); + execute( 0 ); +} + +void SpinfieldToolbarController::Down() +{ + double nValue = m_nValue - m_nStep; + if ( m_bMinSet && nValue < m_nMin ) + return; + + m_nValue = nValue; + + rtl::OUString aText = impl_formatOutputString( m_nValue ); + m_pSpinfieldControl->SetText( aText ); + execute( 0 ); +} + +void SpinfieldToolbarController::First() +{ + if ( m_bMinSet ) + { + m_nValue = m_nMin; + + rtl::OUString aText = impl_formatOutputString( m_nValue ); + m_pSpinfieldControl->SetText( aText ); + execute( 0 ); + } +} + +void SpinfieldToolbarController::Last() +{ + if ( m_bMaxSet ) + { + m_nValue = m_nMax; + + rtl::OUString aText = impl_formatOutputString( m_nValue ); + m_pSpinfieldControl->SetText( aText ); + execute( 0 ); + } +} + +void SpinfieldToolbarController::Modify() +{ + notifyTextChanged( m_pSpinfieldControl->GetText() ); +} + +void SpinfieldToolbarController::KeyInput( const ::KeyEvent& /*rKEvt*/ ) +{ +} + +void SpinfieldToolbarController::GetFocus() +{ + notifyFocusGet(); +} + +void SpinfieldToolbarController::LoseFocus() +{ + notifyFocusLost(); +} + +void SpinfieldToolbarController::StateChanged( StateChangedType /*nType*/ ) +{ +} + +void SpinfieldToolbarController::DataChanged( const DataChangedEvent& /*rDCEvt*/ ) +{ +} + +long SpinfieldToolbarController::PreNotify( NotifyEvent& rNEvt ) +{ + if( rNEvt.GetType() == EVENT_KEYINPUT ) + { + const ::KeyEvent* pKeyEvent = rNEvt.GetKeyEvent(); + const KeyCode& rKeyCode = pKeyEvent->GetKeyCode(); + if(( rKeyCode.GetModifier() | rKeyCode.GetCode()) == KEY_RETURN ) + { + // Call execute only with non-empty text + if ( m_pSpinfieldControl->GetText().Len() > 0 ) + execute( rKeyCode.GetModifier() ); + return 1; + } + } + + return 0; +} + +// -------------------------------------------------------- + +void SpinfieldToolbarController::executeControlCommand( const ::com::sun::star::frame::ControlCommand& rControlCommand ) +{ + rtl::OUString aValue; + rtl::OUString aMax; + rtl::OUString aMin; + rtl::OUString aStep; + bool bFloatValue( false ); + + if ( rControlCommand.Command.equalsAsciiL( "SetStep", 7 )) + { + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + sal_Int32 nValue; + double fValue; + bool bFloat( false ); + + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Step", 4 )) + { + if ( impl_getValue( rControlCommand.Arguments[i].Value, nValue, fValue, bFloat )) + aStep = bFloat ? ::rtl::OUString::valueOf( fValue ) : + ::rtl::OUString::valueOf( nValue ); + break; + } + } + } + else if ( rControlCommand.Command.equalsAsciiL( "SetValue", 8 )) + { + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Value", 5 )) + { + sal_Int32 nValue; + double fValue; + bool bFloat( false ); + + if ( impl_getValue( rControlCommand.Arguments[i].Value, nValue, fValue, bFloat )) + { + aValue = bFloat ? ::rtl::OUString::valueOf( fValue ) : ::rtl::OUString::valueOf( nValue ); + bFloatValue = bFloat; + } + break; + } + } + } + else if ( rControlCommand.Command.equalsAsciiL( "SetValues", 9 )) + { + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + sal_Int32 nValue; + double fValue; + bool bFloat( false ); + + rtl::OUString aName = rControlCommand.Arguments[i].Name; + if ( impl_getValue( rControlCommand.Arguments[i].Value, nValue, fValue, bFloat )) + { + if ( aName.equalsAsciiL( "Value", 5 )) + { + aValue = bFloat ? ::rtl::OUString::valueOf( fValue ) : ::rtl::OUString::valueOf( nValue ); + bFloatValue = bFloat; + } + else if ( aName.equalsAsciiL( "Step", 4 )) + aStep = bFloat ? ::rtl::OUString::valueOf( fValue ) : + ::rtl::OUString::valueOf( nValue ); + else if ( aName.equalsAsciiL( "LowerLimit", 10 )) + aMin = bFloat ? ::rtl::OUString::valueOf( fValue ) : + ::rtl::OUString::valueOf( nValue ); + else if ( aName.equalsAsciiL( "UpperLimit", 10 )) + aMax = bFloat ? ::rtl::OUString::valueOf( fValue ) : + ::rtl::OUString::valueOf( nValue ); + } + else if ( aName.equalsAsciiL( "OutputFormat", 12 )) + rControlCommand.Arguments[i].Value >>= m_aOutFormat; + } + } + else if ( rControlCommand.Command.equalsAsciiL( "SetLowerLimit", 13 )) + { + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + sal_Int32 nValue; + double fValue; + bool bFloat( false ); + + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "LowerLimit", 10 )) + { + if ( impl_getValue( rControlCommand.Arguments[i].Value, nValue, fValue, bFloat )) + aMin = bFloat ? ::rtl::OUString::valueOf( fValue ) : + ::rtl::OUString::valueOf( nValue ); + break; + } + } + } + else if ( rControlCommand.Command.equalsAsciiL( "SetUpperLimit", 13 )) + { + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + sal_Int32 nValue; + double fValue; + bool bFloat( false ); + + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "UpperLimit", 10 )) + { + if ( impl_getValue( rControlCommand.Arguments[i].Value, nValue, fValue, bFloat )) + aMax = bFloat ? ::rtl::OUString::valueOf( fValue ) : + ::rtl::OUString::valueOf( nValue ); + break; + } + } + } + else if ( rControlCommand.Command.equalsAsciiL( "SetOutputFormat", 15 )) + { + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "OutputFormat", 10 )) + { + rControlCommand.Arguments[i].Value >>= m_aOutFormat; + break; + } + } + } + + // Check values and set members + if ( aValue.getLength() > 0 ) + { + m_bFloat = bFloatValue; + m_nValue = aValue.toDouble(); + + rtl::OUString aOutString = impl_formatOutputString( m_nValue ); + m_pSpinfieldControl->SetText( aOutString ); + notifyTextChanged( aOutString ); + } + if ( aMax.getLength() > 0 ) + { + m_nMax = aMax.toDouble(); + m_bMaxSet = true; + } + if ( aMin.getLength() > 0 ) + { + m_nMin = aMin.toDouble(); + m_bMinSet = true; + } + if ( aStep.getLength() > 0 ) + m_nStep = aStep.toDouble(); +} + +bool SpinfieldToolbarController::impl_getValue( + const Any& rAny, sal_Int32& nValue, double& fValue, bool& bFloat ) +{ + using ::com::sun::star::uno::TypeClass; + + bool bValueValid( false ); + + bFloat = false; + TypeClass aTypeClass = rAny.getValueTypeClass(); + if (( aTypeClass == TypeClass( typelib_TypeClass_LONG )) || + ( aTypeClass == TypeClass( typelib_TypeClass_SHORT )) || + ( aTypeClass == TypeClass( typelib_TypeClass_BYTE ))) + bValueValid = rAny >>= nValue; + else if (( aTypeClass == TypeClass( typelib_TypeClass_FLOAT )) || + ( aTypeClass == TypeClass( typelib_TypeClass_DOUBLE ))) + { + bValueValid = rAny >>= fValue; + bFloat = true; + } + + return bValueValid; +} + +rtl::OUString SpinfieldToolbarController::impl_formatOutputString( double fValue ) +{ + if ( m_aOutFormat.getLength() == 0 ) + { + if ( m_bFloat ) + return rtl::OUString::valueOf( fValue ); + else + return rtl::OUString::valueOf( sal_Int32( fValue )); + } + else + { +#ifdef WNT + sal_Unicode aBuffer[128]; + + aBuffer[0] = 0; + if ( m_bFloat ) + snwprintf( reinterpret_cast<wchar_t *>(aBuffer), 128, reinterpret_cast<const wchar_t *>(m_aOutFormat.getStr()), fValue ); + else + snwprintf( reinterpret_cast<wchar_t *>(aBuffer), 128, reinterpret_cast<const wchar_t *>(m_aOutFormat.getStr()), sal_Int32( fValue )); + + sal_Int32 nSize = rtl_ustr_getLength( aBuffer ); + return rtl::OUString( aBuffer, nSize ); +#else + // Currently we have no support for a format string using sal_Unicode. wchar_t + // is 32 bit on Unix platform! + char aBuffer[128]; + + ::rtl::OString aFormat = OUStringToOString( m_aOutFormat, osl_getThreadTextEncoding() ); + if ( m_bFloat ) + snprintf( aBuffer, 128, aFormat.getStr(), fValue ); + else + snprintf( aBuffer, 128, aFormat.getStr(), static_cast<long>( fValue )); + + sal_Int32 nSize = strlen( aBuffer ); + rtl::OString aTmp( aBuffer, nSize ); + return rtl::OStringToOUString( aTmp, osl_getThreadTextEncoding() ); +#endif + } +} + +} // namespace + diff --git a/framework/source/uielement/statusbar.cxx b/framework/source/uielement/statusbar.cxx new file mode 100644 index 000000000000..132a42456d1e --- /dev/null +++ b/framework/source/uielement/statusbar.cxx @@ -0,0 +1,113 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include <uielement/statusbar.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ + +#include <vcl/svapp.hxx> + +namespace framework +{ + +FrameworkStatusBar::FrameworkStatusBar( + Window* pParent, + WinBits nWinBits ) : + StatusBar( pParent, nWinBits ), + m_pMgr( NULL ), + m_bShow( sal_False ), + m_bLock( sal_False ) +{ + // set optimal size + SetOutputSizePixel( CalcWindowSizePixel() ); +} + +FrameworkStatusBar::~FrameworkStatusBar() +{ +} + +void FrameworkStatusBar::SetStatusBarManager( StatusBarManager* pStatusBarManager ) +{ + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + m_pMgr = pStatusBarManager; +} + +void FrameworkStatusBar::UserDraw(const UserDrawEvent& rUDEvt) +{ + if ( m_pMgr ) + m_pMgr->UserDraw( rUDEvt ); +} + +void FrameworkStatusBar::Command( const CommandEvent& rEvt ) +{ + if ( m_pMgr ) + m_pMgr->Command( rEvt ); +} + +void FrameworkStatusBar::StateChanged( StateChangedType nType ) +{ + if ( m_pMgr ) + m_pMgr->StateChanged( nType ); +} + +void FrameworkStatusBar::DataChanged( const DataChangedEvent& rDCEvt ) +{ + StatusBar::DataChanged( rDCEvt ); + if ( m_pMgr ) + m_pMgr->DataChanged( rDCEvt ); +} + +void FrameworkStatusBar::MouseMove( const MouseEvent& rMEvt ) +{ + StatusBar::MouseMove( rMEvt ); + if ( m_pMgr ) + m_pMgr->MouseMove( rMEvt ); +} + +void FrameworkStatusBar::MouseButtonDown( const MouseEvent& rMEvt ) +{ + StatusBar::MouseButtonDown( rMEvt ); + if ( m_pMgr ) + m_pMgr->MouseButtonDown( rMEvt ); +} + +void FrameworkStatusBar::MouseButtonUp( const MouseEvent& rMEvt ) +{ + StatusBar::MouseButtonUp( rMEvt ); + if ( m_pMgr ) + m_pMgr->MouseButtonUp( rMEvt ); +} + +} diff --git a/framework/source/uielement/statusbarmanager.cxx b/framework/source/uielement/statusbarmanager.cxx new file mode 100644 index 000000000000..cb9cbb2896f7 --- /dev/null +++ b/framework/source/uielement/statusbarmanager.cxx @@ -0,0 +1,721 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + +#include <uielement/statusbarmanager.hxx> + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <threadhelp/threadhelpbase.hxx> +#include <threadhelp/resetableguard.hxx> +#include <classes/sfxhelperfunctions.hxx> +#include <macros/generic.hxx> +#include <macros/xinterface.hxx> +#include <macros/xtypeprovider.hxx> +#include <stdtypes.h> +#include "services.h" +#include "general.h" +#include "properties.h" +#include <helper/mischelper.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/XStatusListener.hpp> +#include <com/sun/star/util/XUpdatable.hpp> +#include <com/sun/star/ui/ItemStyle.hpp> +#include <com/sun/star/ui/ItemType.hpp> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/awt/Command.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ + +#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ +#include <toolkit/unohlp.hxx> +#endif +#include <svtools/statusbarcontroller.hxx> + +#include <vcl/status.hxx> +#include <vcl/svapp.hxx> +#include <rtl/logfile.hxx> + +using namespace ::com::sun::star; +#ifndef css +#define css ::com::sun::star +#endif +#ifndef css_ui +#define css_ui ::com::sun::star::ui +#endif + +const sal_Int32 HELPID_PREFIX_LENGTH = 7; +static const char* HELPID_PREFIX = "helpid:"; + +// Property names of a menu/menu item ItemDescriptor +static const char ITEM_DESCRIPTOR_COMMANDURL[] = "CommandURL"; +static const char ITEM_DESCRIPTOR_HELPURL[] = "HelpURL"; +static const char ITEM_DESCRIPTOR_OFFSET[] = "Offset"; +static const char ITEM_DESCRIPTOR_STYLE[] = "Style"; +static const char ITEM_DESCRIPTOR_WIDTH[] = "Width"; +static const char ITEM_DESCRIPTOR_TYPE[] = "Type"; + +namespace framework +{ + +static USHORT impl_convertItemStyleToItemBits( sal_Int16 nStyle ) +{ + USHORT nItemBits( 0 ); + + if (( nStyle & css_ui::ItemStyle::ALIGN_RIGHT ) == css_ui::ItemStyle::ALIGN_RIGHT ) + nItemBits |= SIB_RIGHT; + else if ( nStyle & css_ui::ItemStyle::ALIGN_LEFT ) + nItemBits |= SIB_LEFT; + else + nItemBits |= SIB_CENTER; + + if (( nStyle & css_ui::ItemStyle::DRAW_FLAT ) == css_ui::ItemStyle::DRAW_FLAT ) + nItemBits |= SIB_FLAT; + else if ( nStyle & css_ui::ItemStyle::DRAW_OUT3D ) + nItemBits |= SIB_OUT; + else + nItemBits |= SIB_IN; + + if (( nStyle & css_ui::ItemStyle::AUTO_SIZE ) == css_ui::ItemStyle::AUTO_SIZE ) + nItemBits |= SIB_AUTOSIZE; + if ( nStyle & css_ui::ItemStyle::OWNER_DRAW ) + nItemBits |= SIB_USERDRAW; + + return nItemBits; +} + +//***************************************************************************************************************** +// XInterface, XTypeProvider, XServiceInfo +//***************************************************************************************************************** +DEFINE_XINTERFACE_5 ( StatusBarManager , + ::cppu::OWeakObject , + DIRECT_INTERFACE( lang::XTypeProvider ), + DIRECT_INTERFACE( lang::XComponent ), + DIRECT_INTERFACE( frame::XFrameActionListener ), + DIRECT_INTERFACE( css::ui::XUIConfigurationListener ), + DERIVED_INTERFACE( lang::XEventListener, frame::XFrameActionListener ) + ) + +DEFINE_XTYPEPROVIDER_5 ( StatusBarManager , + lang::XTypeProvider , + lang::XComponent , + css::ui::XUIConfigurationListener , + frame::XFrameActionListener , + lang::XEventListener + ) + +StatusBarManager::StatusBarManager( + const uno::Reference< lang::XMultiServiceFactory >& rServiceManager, + const uno::Reference< frame::XFrame >& rFrame, + const rtl::OUString& rResourceName, + StatusBar* pStatusBar ) : + ThreadHelpBase( &Application::GetSolarMutex() ), + OWeakObject(), + m_bDisposed( sal_False ), + m_bFrameActionRegistered( sal_False ), + m_bUpdateControllers( sal_False ), + m_bModuleIdentified( sal_False ), + m_pStatusBar( pStatusBar ), + m_aResourceName( rResourceName ), + m_xFrame( rFrame ), + m_aListenerContainer( m_aLock.getShareableOslMutex() ), + m_xServiceManager( rServiceManager ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "StatusBarManager::StatusBarManager" ); + + if ( m_xServiceManager.is() ) + m_xStatusbarControllerRegistration = uno::Reference< css::frame::XUIControllerRegistration >( + m_xServiceManager->createInstance( SERVICENAME_STATUSBARCONTROLLERFACTORY ), + uno::UNO_QUERY ); + + m_pStatusBar->SetClickHdl( LINK( this, StatusBarManager, Click ) ); + m_pStatusBar->SetDoubleClickHdl( LINK( this, StatusBarManager, DoubleClick ) ); +} + +StatusBarManager::~StatusBarManager() +{ +} + +StatusBar* StatusBarManager::GetStatusBar() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "StatusBarManager::GetStatusBar" ); + ResetableGuard aGuard( m_aLock ); + return m_pStatusBar; +} + +void StatusBarManager::frameAction( const frame::FrameActionEvent& Action ) +throw ( uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "StatusBarManager::frameAction" ); + ResetableGuard aGuard( m_aLock ); + if ( Action.Action == frame::FrameAction_CONTEXT_CHANGED ) + UpdateControllers(); +} + +void SAL_CALL StatusBarManager::disposing( const lang::EventObject& Source ) throw ( uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "StatusBarManager::disposing" ); + { + ResetableGuard aGuard( m_aLock ); + if ( m_bDisposed ) + return; + } + + RemoveControllers(); + + { + ResetableGuard aGuard( m_aLock ); + if ( Source.Source == uno::Reference< uno::XInterface >( m_xFrame, uno::UNO_QUERY )) + m_xFrame.clear(); + + m_xServiceManager.clear(); + } +} + +// XComponent +void SAL_CALL StatusBarManager::dispose() throw( uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "StatusBarManager::dispose" ); + uno::Reference< lang::XComponent > xThis( + static_cast< OWeakObject* >(this), uno::UNO_QUERY ); + + lang::EventObject aEvent( xThis ); + m_aListenerContainer.disposeAndClear( aEvent ); + + { + ResetableGuard aGuard( m_aLock ); + if ( !m_bDisposed ) + { + RemoveControllers(); + + delete m_pStatusBar; + m_pStatusBar = 0; + + if ( m_bFrameActionRegistered && m_xFrame.is() ) + { + try + { + m_xFrame->removeFrameActionListener( uno::Reference< frame::XFrameActionListener >( + static_cast< ::cppu::OWeakObject *>( this ), + uno::UNO_QUERY )); + } + catch ( uno::Exception& ) + { + } + } + + m_xFrame.clear(); + m_xServiceManager.clear(); + + m_bDisposed = sal_True; + } + } +} + +void SAL_CALL StatusBarManager::addEventListener( const uno::Reference< lang::XEventListener >& xListener ) throw( uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "StatusBarManager::addEventListener" ); + ResetableGuard aGuard( m_aLock ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + if ( m_bDisposed ) + throw lang::DisposedException(); + + m_aListenerContainer.addInterface( ::getCppuType( + ( const uno::Reference< lang::XEventListener >* ) NULL ), xListener ); +} + +void SAL_CALL StatusBarManager::removeEventListener( const uno::Reference< lang::XEventListener >& xListener ) throw( uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "StatusBarManager::removeEventListener" ); + m_aListenerContainer.removeInterface( ::getCppuType( + ( const uno::Reference< lang::XEventListener >* ) NULL ), xListener ); +} + +// XUIConfigurationListener +void SAL_CALL StatusBarManager::elementInserted( const css::ui::ConfigurationEvent& ) throw ( uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "StatusBarManager::elementInserted" ); + ResetableGuard aGuard( m_aLock ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + if ( m_bDisposed ) + return; +} + +void SAL_CALL StatusBarManager::elementRemoved( const css::ui::ConfigurationEvent& ) throw ( uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "StatusBarManager::elementRemoved" ); + ResetableGuard aGuard( m_aLock ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + if ( m_bDisposed ) + return; +} + +void SAL_CALL StatusBarManager::elementReplaced( const css::ui::ConfigurationEvent& ) throw ( uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "StatusBarManager::elementReplaced" ); + ResetableGuard aGuard( m_aLock ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + if ( m_bDisposed ) + return; +} + +void StatusBarManager::UpdateControllers() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "StatusBarManager::UpdateControllers" ); + if ( !m_bUpdateControllers ) + { + m_bUpdateControllers = sal_True; + const sal_uInt32 nCount = m_aControllerVector.size(); + for ( sal_uInt32 n = 0; n < nCount; n++ ) + { + try + { + uno::Reference< util::XUpdatable > xUpdatable( m_aControllerVector[n], uno::UNO_QUERY ); + if ( xUpdatable.is() ) + xUpdatable->update(); + } + catch ( uno::Exception& ) + { + } + } + } + m_bUpdateControllers = sal_False; +} + +void StatusBarManager::RemoveControllers() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "StatusBarManager::RemoveControllers" ); + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + return; + + const sal_uInt32 nCount = m_aControllerVector.size(); + for ( sal_uInt32 n = 0; n < nCount; n++ ) + { + try + { + uno::Reference< lang::XComponent > xComponent( + m_aControllerVector[n], uno::UNO_QUERY ); + if ( xComponent.is() ) + xComponent->dispose(); + } + catch ( uno::Exception& ) + { + } + + m_aControllerVector[n].clear(); + } +} + +rtl::OUString StatusBarManager::RetrieveLabelFromCommand( const rtl::OUString& aCmdURL ) +{ + return framework::RetrieveLabelFromCommand(aCmdURL,m_xServiceManager,m_xUICommandLabels,m_xFrame,m_aModuleIdentifier,m_bModuleIdentified,"Name"); +} + +void StatusBarManager::CreateControllers() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "StatusBarManager::CreateControllers" ); + uno::Reference< lang::XMultiComponentFactory > xStatusbarControllerFactory( m_xStatusbarControllerRegistration, uno::UNO_QUERY ); + uno::Reference< uno::XComponentContext > xComponentContext; + uno::Reference< beans::XPropertySet > xProps( m_xServiceManager, uno::UNO_QUERY ); + uno::Reference< awt::XWindow > xStatusbarWindow = VCLUnoHelper::GetInterface( m_pStatusBar ); + + if ( xProps.is() ) + xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xComponentContext; + + for ( USHORT i = 0; i < m_pStatusBar->GetItemCount(); i++ ) + { + USHORT nId = m_pStatusBar->GetItemId( i ); + if ( nId == 0 ) + continue; + + rtl::OUString aCommandURL( m_pStatusBar->GetItemCommand( nId )); + sal_Bool bInit( sal_True ); + uno::Reference< frame::XStatusListener > xController; + + svt::StatusbarController* pController( 0 ); + + if ( m_xStatusbarControllerRegistration.is() && + m_xStatusbarControllerRegistration->hasController( aCommandURL, m_aModuleIdentifier )) + { + if ( xStatusbarControllerFactory.is() ) + { + uno::Sequence< uno::Any > aSeq( 5 ); + beans::PropertyValue aPropValue; + + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ModuleName" )); + aPropValue.Value = uno::makeAny( m_aModuleIdentifier ); + aSeq[0] = uno::makeAny( aPropValue ); + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" )); + aPropValue.Value = uno::makeAny( m_xFrame ); + aSeq[1] = uno::makeAny( aPropValue ); + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ServiceManager" )); + aPropValue.Value = uno::makeAny( m_xServiceManager ); + aSeq[2] = uno::makeAny( aPropValue ); + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ParentWindow" )); + aPropValue.Value = uno::makeAny( xStatusbarWindow ); + aSeq[3] = uno::makeAny( aPropValue ); + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Identifier" )); + aPropValue.Value = uno::makeAny( nId ); + aSeq[4] = uno::makeAny( aPropValue ); + + xController = uno::Reference< frame::XStatusListener >( + xStatusbarControllerFactory->createInstanceWithArgumentsAndContext( + aCommandURL, aSeq, xComponentContext ), + uno::UNO_QUERY ); + bInit = sal_False; // Initialization is done through the factory service + } + } + + if ( !xController.is() ) + { + pController = CreateStatusBarController( m_xFrame, m_pStatusBar, nId, aCommandURL ); + if ( !pController ) + pController = new svt::StatusbarController( m_xServiceManager, m_xFrame, aCommandURL, nId ); + + if ( pController ) + xController = uno::Reference< frame::XStatusListener >( + static_cast< ::cppu::OWeakObject *>( pController ), + uno::UNO_QUERY ); + } + + m_aControllerVector.push_back( xController ); + uno::Reference< lang::XInitialization > xInit( xController, uno::UNO_QUERY ); + + if ( xInit.is() ) + { + if ( bInit ) + { + beans::PropertyValue aPropValue; + uno::Sequence< uno::Any > aArgs( 5 ); + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" )); + aPropValue.Value = uno::makeAny( m_xFrame ); + aArgs[0] = uno::makeAny( aPropValue ); + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CommandURL" )); + aPropValue.Value = uno::makeAny( aCommandURL ); + aArgs[1] = uno::makeAny( aPropValue ); + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ServiceManager" )); + aPropValue.Value = uno::makeAny( m_xServiceManager ); + aArgs[2] = uno::makeAny( aPropValue ); + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ParentWindow" )); + aPropValue.Value = uno::makeAny( xStatusbarWindow ); + aArgs[3] = uno::makeAny( aPropValue ); + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Identifier" )); + aPropValue.Value = uno::makeAny( nId ); + aArgs[4] = uno::makeAny( aPropValue ); + xInit->initialize( aArgs ); + } + } + } + + AddFrameActionListener(); +} + +void StatusBarManager::AddFrameActionListener() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "StatusBarManager::AddFrameActionListener" ); + if ( !m_bFrameActionRegistered && m_xFrame.is() ) + { + m_bFrameActionRegistered = sal_True; + m_xFrame->addFrameActionListener( uno::Reference< frame::XFrameActionListener >( + static_cast< ::cppu::OWeakObject *>( this ), uno::UNO_QUERY )); + } +} + +void StatusBarManager::FillStatusBar( const uno::Reference< container::XIndexAccess >& rItemContainer ) +{ + RTL_LOGFILE_CONTEXT( aLog, "framework (cd100003) ::StatusBarManager::FillStatusbar" ); + + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed || !m_pStatusBar ) + return; + + USHORT nId( 1 ); + rtl::OUString aHelpIdPrefix( RTL_CONSTASCII_USTRINGPARAM( HELPID_PREFIX )); + + RemoveControllers(); + + // reset and fill command map + m_pStatusBar->Clear(); + m_aControllerVector.clear(); + + for ( sal_Int32 n = 0; n < rItemContainer->getCount(); n++ ) + { + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "StatusBarManager::FillStatusBar" ); + uno::Sequence< beans::PropertyValue > aProp; + rtl::OUString aCommandURL; + rtl::OUString aHelpURL; + sal_Int16 nOffset( 0 ); + sal_Int16 nStyle( 0 ); + sal_Int16 nWidth( 0 ); + sal_uInt16 nType( css_ui::ItemType::DEFAULT ); + + try + { + if ( rItemContainer->getByIndex( n ) >>= aProp ) + { + for ( int i = 0; i < aProp.getLength(); i++ ) + { + if ( aProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_COMMANDURL )) + { + aProp[i].Value >>= aCommandURL; + } + else if ( aProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_HELPURL )) + { + aProp[i].Value >>= aHelpURL; + } + else if ( aProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_STYLE )) + { + aProp[i].Value >>= nStyle; + } + else if ( aProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_TYPE )) + { + aProp[i].Value >>= nType; + } + else if ( aProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_WIDTH )) + { + aProp[i].Value >>= nWidth; + } + else if ( aProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_OFFSET )) + { + aProp[i].Value >>= nOffset; + } + } + + if (( nType == ::com::sun::star::ui::ItemType::DEFAULT ) && ( aCommandURL.getLength() > 0 )) + { + rtl::OUString aString( RetrieveLabelFromCommand( aCommandURL )); + USHORT nItemBits( impl_convertItemStyleToItemBits( nStyle )); + + m_pStatusBar->InsertItem( nId, nWidth, nItemBits, nOffset ); + m_pStatusBar->SetItemCommand( nId, aCommandURL ); + m_pStatusBar->SetAccessibleName( nId, aString ); +// m_pStatusBar->SetHelpText( nId, aString ); + + if ( aHelpURL.indexOf( aHelpIdPrefix ) == 0 ) + { + rtl::OUString aId( aHelpURL.copy( HELPID_PREFIX_LENGTH )); + sal_uInt16 nHelpId = (sal_uInt16)(aId.toInt32()); + if ( nHelpId > 0 ) + m_pStatusBar->SetHelpId( nId, nHelpId ); + } + + ++nId; + } + } + } + catch ( ::com::sun::star::lang::IndexOutOfBoundsException& ) + { + break; + } + } + + // Create controllers + CreateControllers(); + + // Notify controllers that they are now correctly initialized and can start listening + UpdateControllers(); +} + +void StatusBarManager::StateChanged( StateChangedType ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "StatusBarManager::StateChanged" ); +} + +void StatusBarManager::DataChanged( const DataChangedEvent& rDCEvt ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "StatusBarManager::DataChanged" ); + ResetableGuard aGuard( m_aLock ); + + if ((( rDCEvt.GetType() == DATACHANGED_SETTINGS ) || + ( rDCEvt.GetType() == DATACHANGED_FONTS ) || + ( rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION ) || + ( rDCEvt.GetType() == DATACHANGED_DISPLAY )) && + ( rDCEvt.GetFlags() & SETTINGS_STYLE )) + { + css::uno::Reference< css::frame::XLayoutManager > xLayoutManager; + css::uno::Reference< css::beans::XPropertySet > xPropSet( m_xFrame, css::uno::UNO_QUERY ); + if ( xPropSet.is() ) + xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" ))) >>= xLayoutManager; + if ( xLayoutManager.is() ) + { + aGuard.unlock(); + xLayoutManager->doLayout(); + } + } +} + +void StatusBarManager::UserDraw( const UserDrawEvent& rUDEvt ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "StatusBarManager::UserDraw" ); + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + return; + + USHORT nId( rUDEvt.GetItemId() ); + if (( nId > 0 ) && ( nId <= m_aControllerVector.size() )) + { + uno::Reference< frame::XStatusbarController > xController( + m_aControllerVector[nId-1], uno::UNO_QUERY ); + if ( xController.is() && rUDEvt.GetDevice() ) + { + uno::Reference< awt::XGraphics > xGraphics = + rUDEvt.GetDevice()->CreateUnoGraphics(); + + awt::Rectangle aRect( rUDEvt.GetRect().Left(), + rUDEvt.GetRect().Top(), + rUDEvt.GetRect().GetWidth(), + rUDEvt.GetRect().GetHeight() ); + aGuard.unlock(); + xController->paint( xGraphics, aRect, rUDEvt.GetItemId(), rUDEvt.GetStyle() ); + } + } +} + +void StatusBarManager::Command( const CommandEvent& rEvt ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "StatusBarManager::Command" ); + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + return; + + if ( rEvt.GetCommand() == COMMAND_CONTEXTMENU ) + { + USHORT nId = m_pStatusBar->GetItemId( rEvt.GetMousePosPixel() ); + if (( nId > 0 ) && ( nId <= m_aControllerVector.size() )) + { + uno::Reference< frame::XStatusbarController > xController( + m_aControllerVector[nId-1], uno::UNO_QUERY ); + if ( xController.is() ) + { + awt::Point aPos; + aPos.X = rEvt.GetMousePosPixel().X(); + aPos.Y = rEvt.GetMousePosPixel().Y(); + xController->command( aPos, awt::Command::CONTEXTMENU, sal_True, uno::Any() ); + } + } + } +} + +void StatusBarManager::MouseMove( const MouseEvent& rMEvt ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "StatusBarManager::MouseMove" ); + MouseButton(rMEvt,&frame::XStatusbarController::mouseMove); +} +void StatusBarManager::MouseButton( const MouseEvent& rMEvt ,sal_Bool ( SAL_CALL frame::XStatusbarController::*_pMethod )(const ::com::sun::star::awt::MouseEvent&)) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "StatusBarManager::MouseButton" ); + ResetableGuard aGuard( m_aLock ); + + if ( !m_bDisposed ) + { + USHORT nId = m_pStatusBar->GetItemId( rMEvt.GetPosPixel() ); + if (( nId > 0 ) && ( nId <= m_aControllerVector.size() )) + { + uno::Reference< frame::XStatusbarController > xController( + m_aControllerVector[nId-1], uno::UNO_QUERY ); + if ( xController.is() ) + { + ::com::sun::star::awt::MouseEvent aMouseEvent; + aMouseEvent.Buttons = rMEvt.GetButtons(); + aMouseEvent.X = rMEvt.GetPosPixel().X(); + aMouseEvent.Y = rMEvt.GetPosPixel().Y(); + aMouseEvent.ClickCount = rMEvt.GetClicks(); + (xController.get()->*_pMethod)( aMouseEvent); + } + } // if (( nId > 0 ) && ( nId <= m_aControllerVector.size() )) + } +} +void StatusBarManager::MouseButtonDown( const MouseEvent& rMEvt ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "StatusBarManager::MouseButtonDown" ); + MouseButton(rMEvt,&frame::XStatusbarController::mouseButtonDown); +} + +void StatusBarManager::MouseButtonUp( const MouseEvent& rMEvt ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "StatusBarManager::MouseButtonUp" ); + MouseButton(rMEvt,&frame::XStatusbarController::mouseButtonUp); +} + +IMPL_LINK( StatusBarManager, Click, StatusBar*, EMPTYARG ) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + return 1; + + USHORT nId = m_pStatusBar->GetCurItemId(); + if (( nId > 0 ) && ( nId <= m_aControllerVector.size() )) + { + uno::Reference< frame::XStatusbarController > xController( + m_aControllerVector[nId-1], uno::UNO_QUERY ); + if ( xController.is() ) + xController->click(); + } + + return 1; +} + +IMPL_LINK( StatusBarManager, DoubleClick, StatusBar*, EMPTYARG ) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + return 1; + + USHORT nId = m_pStatusBar->GetCurItemId(); + if (( nId > 0 ) && ( nId <= m_aControllerVector.size() )) + { + uno::Reference< frame::XStatusbarController > xController( + m_aControllerVector[nId-1], uno::UNO_QUERY ); + if ( xController.is() ) + xController->doubleClick(); + } + + return 1; +} + +} diff --git a/framework/source/uielement/statusbarwrapper.cxx b/framework/source/uielement/statusbarwrapper.cxx new file mode 100644 index 000000000000..030a790b35e3 --- /dev/null +++ b/framework/source/uielement/statusbarwrapper.cxx @@ -0,0 +1,205 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + +#include <uielement/statusbarwrapper.hxx> + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <threadhelp/resetableguard.hxx> +#include <helper/actiontriggerhelper.hxx> +#include <uielement/constitemcontainer.hxx> +#include <uielement/rootitemcontainer.hxx> +#include <uielement/statusbar.hxx> +#include <helpid.hrc> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/awt/XSystemDependentMenuPeer.hpp> +#include <com/sun/star/awt/XMenuBar.hpp> +#include <com/sun/star/container/XIndexContainer.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/ui/UIElementType.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ +#include <comphelper/processfactory.hxx> +#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ +#include <toolkit/unohlp.hxx> +#endif + +#include <tools/solar.h> +#include <vcl/svapp.hxx> +#include <rtl/logfile.hxx> + +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; +using namespace com::sun::star::frame; +using namespace com::sun::star::lang; +using namespace com::sun::star::container; +using namespace com::sun::star::awt; +using namespace ::com::sun::star::ui; + +namespace framework +{ + +StatusBarWrapper::StatusBarWrapper( + const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& xServiceManager + ) + : UIConfigElementWrapperBase( UIElementType::STATUSBAR,xServiceManager ) +{ +} + +StatusBarWrapper::~StatusBarWrapper() +{ +} + +void SAL_CALL StatusBarWrapper::dispose() throw (::com::sun::star::uno::RuntimeException) +{ + Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY ); + + com::sun::star::lang::EventObject aEvent( xThis ); + m_aListenerContainer.disposeAndClear( aEvent ); + + ResetableGuard aLock( m_aLock ); + if ( !m_bDisposed ) + { + if ( m_xStatusBarManager.is() ) + m_xStatusBarManager->dispose(); + m_xStatusBarManager.clear(); + m_xConfigSource.clear(); + m_xConfigData.clear(); + m_xServiceFactory.clear(); + + m_bDisposed = sal_True; + } + else + throw DisposedException(); +} + +// XInitialization +void SAL_CALL StatusBarWrapper::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException ) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + if ( !m_bInitialized ) + { + UIConfigElementWrapperBase::initialize( aArguments ); + + Reference< XFrame > xFrame( m_xWeakFrame ); + if ( xFrame.is() && m_xConfigSource.is() ) + { + // Create VCL based toolbar which will be filled with settings data + StatusBar* pStatusBar( 0 ); + StatusBarManager* pStatusBarManager( 0 ); + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + Window* pWindow = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() ); + if ( pWindow ) + { + ULONG nStyles = WinBits( WB_LEFT | WB_3DLOOK ); + + pStatusBar = new FrameworkStatusBar( pWindow, nStyles ); + pStatusBarManager = new StatusBarManager( m_xServiceFactory, xFrame, m_aResourceURL, pStatusBar ); + ((FrameworkStatusBar*)pStatusBar)->SetStatusBarManager( pStatusBarManager ); + m_xStatusBarManager = Reference< XComponent >( static_cast< OWeakObject *>( pStatusBarManager ), UNO_QUERY ); + pStatusBar->SetUniqueId( HID_STATUSBAR ); + } + } + + try + { + m_xConfigData = m_xConfigSource->getSettings( m_aResourceURL, sal_False ); + if ( m_xConfigData.is() && pStatusBar && pStatusBarManager ) + { + // Fill statusbar with container contents + pStatusBarManager->FillStatusBar( m_xConfigData ); + } + } + catch ( NoSuchElementException& ) + { + } + } + } +} + +// XUIElementSettings +void SAL_CALL StatusBarWrapper::updateSettings() throw ( RuntimeException ) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + if ( m_bPersistent && + m_xConfigSource.is() && + m_xStatusBarManager.is() ) + { + try + { + StatusBarManager* pStatusBarManager = static_cast< StatusBarManager *>( m_xStatusBarManager.get() ); + + m_xConfigData = m_xConfigSource->getSettings( m_aResourceURL, sal_False ); + if ( m_xConfigData.is() ) + pStatusBarManager->FillStatusBar( m_xConfigData ); + } + catch ( NoSuchElementException& ) + { + } + } +} + +Reference< XInterface > SAL_CALL StatusBarWrapper::getRealInterface() throw ( RuntimeException ) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_xStatusBarManager.is() ) + { + StatusBarManager* pStatusBarManager = static_cast< StatusBarManager *>( m_xStatusBarManager.get() ); + if ( pStatusBarManager ) + { + Window* pWindow = (Window *)pStatusBarManager->GetStatusBar(); + if ( pWindow ) + return Reference< XInterface >( VCLUnoHelper::GetInterface( pWindow ), UNO_QUERY ); + } + } + + return Reference< XInterface >(); +} + +} // namespace framework + diff --git a/framework/source/uielement/statusindicatorinterfacewrapper.cxx b/framework/source/uielement/statusindicatorinterfacewrapper.cxx new file mode 100644 index 000000000000..7be64c053b4e --- /dev/null +++ b/framework/source/uielement/statusindicatorinterfacewrapper.cxx @@ -0,0 +1,130 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <uielement/statusindicatorinterfacewrapper.hxx> +#include <uielement/progressbarwrapper.hxx> +#include <threadhelp/resetableguard.hxx> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ + +#include <vcl/svapp.hxx> +#include <vos/mutex.hxx> + +using namespace cppu; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; + +namespace framework +{ + + +StatusIndicatorInterfaceWrapper::StatusIndicatorInterfaceWrapper( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& rStatusIndicatorImpl ) : + m_xStatusIndicatorImpl( rStatusIndicatorImpl ) +{ +} + +StatusIndicatorInterfaceWrapper::~StatusIndicatorInterfaceWrapper() +{ +} + + +void SAL_CALL StatusIndicatorInterfaceWrapper::start( + const ::rtl::OUString& sText, + sal_Int32 nRange ) +throw( ::com::sun::star::uno::RuntimeException ) +{ + Reference< XComponent > xComp( m_xStatusIndicatorImpl ); + if ( xComp.is() ) + { + ProgressBarWrapper* pProgressBar = (ProgressBarWrapper*)xComp.get(); + if ( pProgressBar ) + pProgressBar->start( sText, nRange ); + } +} + +void SAL_CALL StatusIndicatorInterfaceWrapper::end() +throw( ::com::sun::star::uno::RuntimeException ) +{ + Reference< XComponent > xComp( m_xStatusIndicatorImpl ); + if ( xComp.is() ) + { + ProgressBarWrapper* pProgressBar = (ProgressBarWrapper*)xComp.get(); + if ( pProgressBar ) + pProgressBar->end(); + } +} + +void SAL_CALL StatusIndicatorInterfaceWrapper::reset() +throw( ::com::sun::star::uno::RuntimeException ) +{ + Reference< XComponent > xComp( m_xStatusIndicatorImpl ); + if ( xComp.is() ) + { + ProgressBarWrapper* pProgressBar = (ProgressBarWrapper*)xComp.get(); + if ( pProgressBar ) + pProgressBar->reset(); + } +} + +void SAL_CALL StatusIndicatorInterfaceWrapper::setText( + const ::rtl::OUString& sText ) +throw( ::com::sun::star::uno::RuntimeException ) +{ + Reference< XComponent > xComp( m_xStatusIndicatorImpl ); + if ( xComp.is() ) + { + ProgressBarWrapper* pProgressBar = (ProgressBarWrapper*)xComp.get(); + if ( pProgressBar ) + pProgressBar->setText( sText ); + } +} + +void SAL_CALL StatusIndicatorInterfaceWrapper::setValue( + sal_Int32 nValue ) +throw( ::com::sun::star::uno::RuntimeException ) +{ + Reference< XComponent > xComp( m_xStatusIndicatorImpl ); + if ( xComp.is() ) + { + ProgressBarWrapper* pProgressBar = (ProgressBarWrapper*)xComp.get(); + if ( pProgressBar ) + pProgressBar->setValue( nValue ); + } +} + +} // namespace framework + diff --git a/framework/source/uielement/togglebuttontoolbarcontroller.cxx b/framework/source/uielement/togglebuttontoolbarcontroller.cxx new file mode 100644 index 000000000000..a5e4263385fa --- /dev/null +++ b/framework/source/uielement/togglebuttontoolbarcontroller.cxx @@ -0,0 +1,323 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + +#ifndef __FRAMEWORK_UIELEMENT_TOGGLEBUTTONTOOLBARCONTROLLER_HXX +#include "uielement/togglebuttontoolbarcontroller.hxx" +#endif + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <classes/addonsoptions.hxx> +#ifndef __FRAMEWORK_TOOLBAR_HXX_ +#include "uielement/toolbar.hxx" +#endif + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/frame/XControlNotificationListener.hpp> +#include "com/sun/star/util/XMacroExpander.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/beans/XPropertySet.hpp" + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ + +#include <rtl/uri.hxx> +#include <vos/mutex.hxx> +#include <comphelper/processfactory.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <tools/urlobj.hxx> +#include <vcl/svapp.hxx> +#include <vcl/mnemonic.hxx> +#include <vcl/window.hxx> +#include <vcl/graph.hxx> +#include <vcl/bitmap.hxx> +#include <svtools/filter.hxx> +#include <svtools/miscopt.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::util; + +namespace framework +{ + +// ------------------------------------------------------------------ + +ToggleButtonToolbarController::ToggleButtonToolbarController( + const Reference< XMultiServiceFactory >& rServiceManager, + const Reference< XFrame >& rFrame, + ToolBox* pToolbar, + USHORT nID, + Style eStyle, + const ::rtl::OUString& aCommand ) : + ComplexToolbarController( rServiceManager, rFrame, pToolbar, nID, aCommand ), + m_eStyle( eStyle ) +{ + if ( eStyle == STYLE_DROPDOWNBUTTON ) + m_pToolbar->SetItemBits( m_nID, TIB_DROPDOWNONLY | m_pToolbar->GetItemBits( m_nID ) ); + else if ( eStyle == STYLE_TOGGLE_DROPDOWNBUTTON ) + m_pToolbar->SetItemBits( m_nID, TIB_DROPDOWN | m_pToolbar->GetItemBits( m_nID ) ); +} + +// ------------------------------------------------------------------ + +ToggleButtonToolbarController::~ToggleButtonToolbarController() +{ +} + +// ------------------------------------------------------------------ + +void SAL_CALL ToggleButtonToolbarController::dispose() +throw ( RuntimeException ) +{ + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + ComplexToolbarController::dispose(); +} + +// ------------------------------------------------------------------ +Sequence<PropertyValue> ToggleButtonToolbarController::getExecuteArgs(sal_Int16 KeyModifier) const +{ + Sequence<PropertyValue> aArgs( 2 ); + + // Add key modifier to argument list + aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "KeyModifier" )); + aArgs[0].Value <<= KeyModifier; + aArgs[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" )); + aArgs[1].Value <<= m_aCurrentSelection; + return aArgs; +} + +// ------------------------------------------------------------------ + +uno::Reference< awt::XWindow > SAL_CALL ToggleButtonToolbarController::createPopupWindow() +throw (::com::sun::star::uno::RuntimeException) +{ + uno::Reference< awt::XWindow > xWindow; + + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + if (( m_eStyle == STYLE_DROPDOWNBUTTON ) || + ( m_eStyle == STYLE_TOGGLE_DROPDOWNBUTTON )) + { + // create popup menu + PopupMenu aPopup; + const sal_uInt32 nCount = m_aDropdownMenuList.size(); + for ( sal_uInt32 i = 0; i < nCount; i++ ) + { + rtl::OUString aLabel( m_aDropdownMenuList[i] ); + aPopup.InsertItem( sal_uInt16( i+1 ), aLabel ); + if ( aLabel == m_aCurrentSelection ) + aPopup.CheckItem( sal_uInt16( i+1 ), sal_True ); + else + aPopup.CheckItem( sal_uInt16( i+1 ), sal_False ); + } + + m_pToolbar->SetItemDown( m_nID, TRUE ); + aPopup.SetSelectHdl( LINK( this, ToggleButtonToolbarController, MenuSelectHdl )); + aPopup.Execute( m_pToolbar, m_pToolbar->GetItemRect( m_nID )); + m_pToolbar->SetItemDown( m_nID, FALSE ); + } + + return xWindow; +} + +// ------------------------------------------------------------------ + +void ToggleButtonToolbarController::executeControlCommand( const ::com::sun::star::frame::ControlCommand& rControlCommand ) +{ + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + if (( m_eStyle == STYLE_DROPDOWNBUTTON ) || + ( m_eStyle == STYLE_TOGGLE_DROPDOWNBUTTON )) + { + if ( rControlCommand.Command.equalsAsciiL( "SetList", 7 )) + { + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "List", 4 )) + { + Sequence< ::rtl::OUString > aList; + m_aDropdownMenuList.clear(); + + rControlCommand.Arguments[i].Value >>= aList; + for ( sal_Int32 j = 0; j < aList.getLength(); j++ ) + m_aDropdownMenuList.push_back( aList[j] ); + + // send notification + uno::Sequence< beans::NamedValue > aInfo( 1 ); + aInfo[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "List" )); + aInfo[0].Value <<= aList; + addNotifyInfo( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ListChanged" )), + getDispatchFromCommand( m_aCommandURL ), + aInfo ); + + break; + } + } + } + else if ( rControlCommand.Command.equalsAsciiL( "CheckItemPos", 12 )) + { + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Pos", 3 )) + { + sal_Int32 nPos( -1 ); + + rControlCommand.Arguments[i].Value >>= nPos; + if ( nPos >= 0 && + ( sal::static_int_cast< sal_uInt32 >(nPos) + < m_aDropdownMenuList.size() ) ) + { + m_aCurrentSelection = m_aDropdownMenuList[nPos]; + + // send notification + uno::Sequence< beans::NamedValue > aInfo( 1 ); + aInfo[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ItemChecked" )); + aInfo[0].Value <<= nPos; + addNotifyInfo( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Pos" )), + getDispatchFromCommand( m_aCommandURL ), + aInfo ); + } + break; + } + } + } + else if ( rControlCommand.Command.equalsAsciiL( "AddEntry", 8 )) + { + rtl::OUString aText; + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Text", 4 )) + { + if ( rControlCommand.Arguments[i].Value >>= aText ) + m_aDropdownMenuList.push_back( aText ); + break; + } + } + } + else if ( rControlCommand.Command.equalsAsciiL( "InsertEntry", 11 )) + { + sal_Int32 nPos( COMBOBOX_APPEND ); + sal_Int32 nSize = sal_Int32( m_aDropdownMenuList.size() ); + rtl::OUString aText; + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Pos", 3 )) + { + sal_Int32 nTmpPos = 0; + if ( rControlCommand.Arguments[i].Value >>= nTmpPos ) + { + if (( nTmpPos >= 0 ) && ( nTmpPos < sal_Int32( nSize ))) + nPos = nTmpPos; + } + } + else if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Text", 4 )) + rControlCommand.Arguments[i].Value >>= aText; + } + + std::vector< ::rtl::OUString >::iterator aIter = m_aDropdownMenuList.begin(); + aIter += nPos; + m_aDropdownMenuList.insert( aIter, aText ); + } + else if ( rControlCommand.Command.equalsAsciiL( "RemoveEntryPos", 14 )) + { + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Pos", 3 )) + { + sal_Int32 nPos( -1 ); + if ( rControlCommand.Arguments[i].Value >>= nPos ) + { + if ( nPos < sal_Int32( m_aDropdownMenuList.size() )) + { + std::vector< ::rtl::OUString >::iterator aIter = m_aDropdownMenuList.begin(); + aIter += nPos; + m_aDropdownMenuList.erase( aIter ); + } + } + break; + } + } + } + else if ( rControlCommand.Command.equalsAsciiL( "RemoveEntryText", 15 )) + { + for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) + { + if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Text", 4 )) + { + rtl::OUString aText; + if ( rControlCommand.Arguments[i].Value >>= aText ) + { + sal_Int32 nSize = sal_Int32( m_aDropdownMenuList.size() ); + for ( sal_Int32 j = 0; j < nSize; j++ ) + { + if ( m_aDropdownMenuList[j] == aText ) + { + std::vector< ::rtl::OUString >::iterator aIter = m_aDropdownMenuList.begin(); + aIter += j; + m_aDropdownMenuList.erase( aIter ); + break; + } + } + } + break; + } + } + } + } +} + +IMPL_LINK( ToggleButtonToolbarController, MenuSelectHdl, Menu *, pMenu ) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + sal_uInt16 nItemId = pMenu->GetCurItemId(); + if ( nItemId > 0 && nItemId <= m_aDropdownMenuList.size() ) + { + m_aCurrentSelection = m_aDropdownMenuList[nItemId-1]; + + execute( 0 ); + } + return 0; +} + +} // namespace + diff --git a/framework/source/uielement/toolbar.cxx b/framework/source/uielement/toolbar.cxx new file mode 100644 index 000000000000..48716b89f0cd --- /dev/null +++ b/framework/source/uielement/toolbar.cxx @@ -0,0 +1,77 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <uielement/toolbar.hxx> +#include <uielement/toolbarmanager.hxx> +#include <rtl/logfile.hxx> + +namespace framework +{ + +ToolBar::ToolBar( Window* pParent, WinBits nWinBits ) : + ToolBox( pParent, nWinBits ) + , m_pToolBarManager( 0 ) +{ +} + +ToolBar::~ToolBar() +{ +} + +void ToolBar::SetToolBarManager( ToolBarManager* pTbMgr ) +{ + m_pToolBarManager = pTbMgr; +} + +void ToolBar::Command( const CommandEvent& rCEvt ) +{ + if ( m_aCommandHandler.IsSet() ) + m_aCommandHandler.Call( (void *)( &rCEvt )); + ToolBox::Command( rCEvt ); +} + +void ToolBar::StateChanged( StateChangedType nType ) +{ + ToolBox::StateChanged( nType ); + if ( m_aStateChangedHandler.IsSet() ) + m_aStateChangedHandler.Call( &nType ); +} + +void ToolBar::DataChanged( const DataChangedEvent& rDCEvt ) +{ + ToolBox::DataChanged( rDCEvt ); + if ( m_aDataChangedHandler.IsSet() ) + m_aDataChangedHandler.Call( (void*)&rDCEvt ); +} + +} diff --git a/framework/source/uielement/toolbarmanager.cxx b/framework/source/uielement/toolbarmanager.cxx new file mode 100644 index 000000000000..d89b81c0f9b6 --- /dev/null +++ b/framework/source/uielement/toolbarmanager.cxx @@ -0,0 +1,2108 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include <uielement/toolbarmanager.hxx> + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ + + +#ifndef __FRAMEWORK_UIELEMENT_TOOLBAR_HXX +#include <uielement/toolbar.hxx> +#endif +#ifndef __FRAMEWORK_UIELEMENT_GENERICTOOLBARCONTROLLER_HXX +#include <uielement/generictoolbarcontroller.hxx> +#endif +#include <threadhelp/resetableguard.hxx> +#include "services.h" +#include "general.h" +#include "properties.h" +#include <helper/imageproducer.hxx> +#include <classes/sfxhelperfunctions.hxx> +#include <classes/fwkresid.hxx> +#ifndef __FRAMEWORK_CLASES_RESOURCE_HRC_ +#include <classes/resource.hrc> +#endif +#include <classes/addonsoptions.hxx> +#include <uielement/toolbarmerger.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/ui/ItemType.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/awt/XDockableWindow.hpp> +#include <com/sun/star/frame/XLayoutManager.hpp> +#ifndef _COM_SUN_STAR_UI_XDOCKINGAREA_HPP_ +#include <com/sun/star/ui/DockingArea.hpp> +#endif +#include <com/sun/star/graphic/XGraphic.hpp> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> +#include <com/sun/star/frame/XModuleManager.hpp> +#include <com/sun/star/ui/XUIElementSettings.hpp> +#include <com/sun/star/ui/XUIConfigurationPersistence.hpp> +#include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp> +#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp> +#include <com/sun/star/ui/ImageType.hpp> +#include <com/sun/star/ui/UIElementType.hpp> +#include <comphelper/sequence.hxx> +#include <com/sun/star/frame/status/Visibility.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ +#include <svtools/imgdef.hxx> +#include <svtools/toolboxcontroller.hxx> +#include <unotools/cmdoptions.hxx> +#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ +#include <toolkit/unohlp.hxx> +#endif +#include <comphelper/mediadescriptor.hxx> +#include <svtools/miscopt.hxx> +#include <svl/imageitm.hxx> +#include <svtools/framestatuslistener.hxx> +#include <vcl/svapp.hxx> +#include <vcl/menu.hxx> +#include <vcl/syswin.hxx> +#include <vcl/taskpanelist.hxx> +#include <rtl/logfile.hxx> +#include <svtools/menuoptions.hxx> +#include <unotools/cmdoptions.hxx> +#include <boost/bind.hpp> + +//_________________________________________________________________________________________________________________ +// namespaces +//_________________________________________________________________________________________________________________ + +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::graphic; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::ui; + +namespace framework +{ + +static const char ITEM_DESCRIPTOR_COMMANDURL[] = "CommandURL"; +static const char ITEM_DESCRIPTOR_HELPURL[] = "HelpURL"; +static const char ITEM_DESCRIPTOR_TOOLTIP[] = "Tooltip"; +static const char ITEM_DESCRIPTOR_CONTAINER[] = "ItemDescriptorContainer"; +static const char ITEM_DESCRIPTOR_LABEL[] = "Label"; +static const char ITEM_DESCRIPTOR_TYPE[] = "Type"; +static const char ITEM_DESCRIPTOR_VISIBLE[] = "IsVisible"; +static const char ITEM_DESCRIPTOR_WIDTH[] = "Width"; +static const char ITEM_DESCRIPTOR_STYLE[] = "Style"; + +static const sal_Int32 ITEM_DESCRIPTOR_COMMANDURL_LEN = 10; +static const sal_Int32 ITEM_DESCRIPTOR_HELPURL_LEN = 7; +static const sal_Int32 ITEM_DESCRIPTOR_TOOLTIP_LEN = 7; +static const sal_Int32 ITEM_DESCRIPTOR_CONTAINER_LEN = 23; +static const sal_Int32 ITEM_DESCRIPTOR_LABEL_LEN = 5; +static const sal_Int32 ITEM_DESCRIPTOR_TYPE_LEN = 4; +static const sal_Int32 ITEM_DESCRIPTOR_VISIBLE_LEN = 9; +static const sal_Int32 ITEM_DESCRIPTOR_WIDTH_LEN = 5; +static const sal_Int32 ITEM_DESCRIPTOR_STYLE_LEN = 5; + +static const char HELPID_PREFIX[] = "helpid:"; +static const char HELPID_PREFIX_TESTTOOL[] = ".HelpId:"; +//static sal_Int32 HELPID_PREFIX_LENGTH = 7; +static const USHORT STARTID_CUSTOMIZE_POPUPMENU = 1000; + +#define MENUPREFIX "private:resource/menubar/" + +class ImageOrientationListener : public svt::FrameStatusListener +{ + public: + ImageOrientationListener( const Reference< XStatusListener > rReceiver, + const Reference< XMultiServiceFactory > rServiceManager, + const Reference< XFrame > rFrame ); + virtual ~ImageOrientationListener(); + + virtual void SAL_CALL statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event ) throw ( ::com::sun::star::uno::RuntimeException ); + + private: + Reference< XStatusListener > m_xReceiver; +}; + +ImageOrientationListener::ImageOrientationListener( + const Reference< XStatusListener > rReceiver, + const Reference< XMultiServiceFactory > rServiceManager, + const Reference< XFrame > rFrame ) : + FrameStatusListener( rServiceManager, rFrame ), + m_xReceiver( rReceiver ) +{ +} + +ImageOrientationListener::~ImageOrientationListener() +{ +} + +void SAL_CALL ImageOrientationListener::statusChanged( const FeatureStateEvent& Event ) +throw ( RuntimeException ) +{ + if ( m_xReceiver.is() ) + m_xReceiver->statusChanged( Event ); +} + +//***************************************************************************************************************** + +static sal_Int16 getImageTypeFromBools( sal_Bool bBig, sal_Bool bHighContrast ) +{ + sal_Int16 n( 0 ); + if ( bBig ) + n |= ::com::sun::star::ui::ImageType::SIZE_LARGE; + if ( bHighContrast ) + n |= ::com::sun::star::ui::ImageType::COLOR_HIGHCONTRAST; + return n; +} + +static ::com::sun::star::uno::Reference< ::com::sun::star::frame::XLayoutManager > getLayoutManagerFromFrame( + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame ) +{ + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager; + + Reference< XPropertySet > xPropSet( rFrame, UNO_QUERY ); + if ( xPropSet.is() ) + { + try + { + xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" ))) >>= xLayoutManager; + } + catch ( RuntimeException& ) + { + throw; + } + catch ( Exception& ) + { + } + } + + return xLayoutManager; +} + +//***************************************************************************************************************** +// XInterface, XTypeProvider, XServiceInfo +//***************************************************************************************************************** +DEFINE_XINTERFACE_6 ( ToolBarManager , + OWeakObject , + DIRECT_INTERFACE( ::com::sun::star::lang::XTypeProvider ), + DIRECT_INTERFACE( ::com::sun::star::lang::XComponent ), + DIRECT_INTERFACE( ::com::sun::star::frame::XFrameActionListener ), + DIRECT_INTERFACE( ::com::sun::star::ui::XUIConfigurationListener ), + DIRECT_INTERFACE( ::com::sun::star::frame::XStatusListener ), + DERIVED_INTERFACE( ::com::sun::star::lang::XEventListener, ::com::sun::star::frame::XFrameActionListener ) + ) + +DEFINE_XTYPEPROVIDER_6 ( ToolBarManager , + ::com::sun::star::lang::XTypeProvider , + ::com::sun::star::lang::XComponent , + ::com::sun::star::ui::XUIConfigurationListener , + ::com::sun::star::frame::XFrameActionListener , + ::com::sun::star::frame::XStatusListener , + ::com::sun::star::lang::XEventListener + ) + +ToolBarManager::ToolBarManager( const Reference< XMultiServiceFactory >& rServiceManager, + const Reference< XFrame >& rFrame, + const rtl::OUString& rResourceName, + ToolBar* pToolBar ) : + ThreadHelpBase( &Application::GetSolarMutex() ), + OWeakObject(), + m_bDisposed( sal_False ), + m_bIsHiContrast( pToolBar->GetSettings().GetStyleSettings().GetHighContrastMode() ), + m_bSmallSymbols( !SvtMiscOptions().AreCurrentSymbolsLarge() ), + m_bModuleIdentified( sal_False ), + m_bAddedToTaskPaneList( sal_True ), + m_bFrameActionRegistered( sal_False ), + m_bUpdateControllers( sal_False ), + m_bImageOrientationRegistered( sal_False ), + m_bImageMirrored( sal_False ), + m_bCanBeCustomized( sal_True ), + m_lImageRotation( 0 ), + m_pToolBar( pToolBar ), + m_aResourceName( rResourceName ), + m_xFrame( rFrame ), + m_aListenerContainer( m_aLock.getShareableOslMutex() ), + m_xServiceManager( rServiceManager ), + m_nSymbolsStyle( SvtMiscOptions().GetCurrentSymbolsStyle() ) +{ + Window* pWindow = m_pToolBar; + while ( pWindow && !pWindow->IsSystemWindow() ) + pWindow = pWindow->GetParent(); + + if ( pWindow ) + ((SystemWindow *)pWindow)->GetTaskPaneList()->AddWindow( m_pToolBar ); + + if ( m_xServiceManager.is() ) + { + m_xToolbarControllerRegistration = Reference< XUIControllerRegistration >( + m_xServiceManager->createInstance( SERVICENAME_TOOLBARCONTROLLERFACTORY ), + UNO_QUERY ); + + m_xURLTransformer.set( m_xServiceManager->createInstance( + SERVICENAME_URLTRANSFORMER), + UNO_QUERY ); + } + + m_pToolBar->SetSelectHdl( LINK( this, ToolBarManager, Select) ); + m_pToolBar->SetActivateHdl( LINK( this, ToolBarManager, Activate) ); + m_pToolBar->SetDeactivateHdl( LINK( this, ToolBarManager, Deactivate) ); + m_pToolBar->SetClickHdl( LINK( this, ToolBarManager, Click ) ); + m_pToolBar->SetDropdownClickHdl( LINK( this, ToolBarManager, DropdownClick ) ); + m_pToolBar->SetDoubleClickHdl( LINK( this, ToolBarManager, DoubleClick ) ); + m_pToolBar->SetStateChangedHdl( LINK( this, ToolBarManager, StateChanged ) ); + m_pToolBar->SetDataChangedHdl( LINK( this, ToolBarManager, DataChanged ) ); + m_pToolBar->SetToolboxButtonSize( m_bSmallSymbols ? TOOLBOX_BUTTONSIZE_SMALL : TOOLBOX_BUTTONSIZE_LARGE ); + + // enables a menu for clipped items and customization + SvtCommandOptions aCmdOptions; + USHORT nMenuType = TOOLBOX_MENUTYPE_CLIPPEDITEMS; + if ( !aCmdOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED, ::rtl::OUString::createFromAscii( "CreateDialog" ))) + nMenuType |= TOOLBOX_MENUTYPE_CUSTOMIZE; + //added for issue33668 by shizhoubo + m_pToolBar->SetCommandHdl( LINK( this, ToolBarManager, Command ) ); + //end + m_pToolBar->SetMenuType( nMenuType ); + m_pToolBar->SetMenuButtonHdl( LINK( this, ToolBarManager, MenuButton ) ); + m_pToolBar->GetMenu()->SetSelectHdl( LINK( this, ToolBarManager, MenuSelect ) ); + m_pToolBar->GetMenu()->SetDeactivateHdl( LINK( this, ToolBarManager, MenuDeactivate ) ); + + // set name for testtool, the useful part is after the last '/' + sal_Int32 idx = rResourceName.lastIndexOf('/'); + idx++; // will become 0 if '/' not found: use full string + ::rtl::OUString aHelpIdAsString( RTL_CONSTASCII_USTRINGPARAM( HELPID_PREFIX_TESTTOOL )); + ::rtl::OUString aToolbarName = rResourceName.copy( idx ); + aHelpIdAsString += aToolbarName; + m_pToolBar->SetSmartHelpId( SmartId( aHelpIdAsString ) ); + + m_aAsyncUpdateControllersTimer.SetTimeout( 50 ); + m_aAsyncUpdateControllersTimer.SetTimeoutHdl( LINK( this, ToolBarManager, AsyncUpdateControllersHdl ) ); +} + +ToolBarManager::~ToolBarManager() +{ + OSL_ASSERT( m_pToolBar == 0 ); + OSL_ASSERT( !m_bAddedToTaskPaneList ); +} + +void ToolBarManager::Destroy() +{ + ResetableGuard aGuard( m_aLock ); + if ( m_bAddedToTaskPaneList ) + { + Window* pWindow = m_pToolBar; + while ( pWindow && !pWindow->IsSystemWindow() ) + pWindow = pWindow->GetParent(); + + if ( pWindow ) + ((SystemWindow *)pWindow)->GetTaskPaneList()->RemoveWindow( m_pToolBar ); + m_bAddedToTaskPaneList = sal_False; + } + + // Delete the additional add-ons data + for ( sal_uInt16 i = 0; i < m_pToolBar->GetItemCount(); i++ ) + { + sal_uInt16 nItemId = m_pToolBar->GetItemId( i ); + if ( nItemId > 0 ) + delete static_cast< AddonsParams* >( m_pToolBar->GetItemData( nItemId )); + } + + // Hide toolbar as lazy delete can destroy the toolbar much later. + m_pToolBar->Hide(); + /* #i99167# removed change for i93173 since there is some weird crash */ + // #i93173# delete toolbar lazily as we can still be in one of its handlers + m_pToolBar->doLazyDelete(); + + Link aEmpty; + m_pToolBar->SetSelectHdl( aEmpty ); + m_pToolBar->SetActivateHdl( aEmpty ); + m_pToolBar->SetDeactivateHdl( aEmpty ); + m_pToolBar->SetClickHdl( aEmpty ); + m_pToolBar->SetDropdownClickHdl( aEmpty ); + m_pToolBar->SetDoubleClickHdl( aEmpty ); + m_pToolBar->SetStateChangedHdl( aEmpty ); + m_pToolBar->SetDataChangedHdl( aEmpty ); + +// delete m_pToolBar; + m_pToolBar = 0; +} + +ToolBox* ToolBarManager::GetToolBar() const +{ + ResetableGuard aGuard( m_aLock ); + return m_pToolBar; +} + +void ToolBarManager::CheckAndUpdateImages() +{ + ResetableGuard aGuard( m_aLock ); + sal_Bool bRefreshImages = sal_False; + + // Check if high contrast/normal mode have changed + if ( m_pToolBar->GetSettings().GetStyleSettings().GetHighContrastMode() ) + { + if ( !m_bIsHiContrast ) + { + bRefreshImages = TRUE; + m_bIsHiContrast = sal_True; + } + } + else if ( m_bIsHiContrast ) + { + bRefreshImages = sal_True; + m_bIsHiContrast = sal_False; + } + + SvtMiscOptions aMiscOptions; + bool bCurrentSymbolsSmall = !aMiscOptions.AreCurrentSymbolsLarge(); + if ( m_bSmallSymbols != bCurrentSymbolsSmall ) + { + bRefreshImages = sal_True; + m_bSmallSymbols = bCurrentSymbolsSmall; + } + + sal_Int16 nCurrentSymbolsStyle = aMiscOptions.GetCurrentSymbolsStyle(); + if ( m_nSymbolsStyle != nCurrentSymbolsStyle ) + { + bRefreshImages = sal_True; + m_nSymbolsStyle = nCurrentSymbolsStyle; + } + + // Refresh images if requested + if ( bRefreshImages ) + RefreshImages(); +} + +void ToolBarManager::RefreshImages() +{ + ResetableGuard aGuard( m_aLock ); + + sal_Bool bBigImages( SvtMiscOptions().AreCurrentSymbolsLarge() ); + for ( USHORT nPos = 0; nPos < m_pToolBar->GetItemCount(); nPos++ ) + { + USHORT nId( m_pToolBar->GetItemId( nPos ) ); + + if ( nId > 0 ) + { + ::rtl::OUString aCommandURL = m_pToolBar->GetItemCommand( nId ); + Image aImage = GetImageFromURL( m_xFrame, aCommandURL, bBigImages, m_bIsHiContrast ); + // Try also to query for add-on images before giving up and use an + // empty image. + if ( !aImage ) + aImage = QueryAddonsImage( aCommandURL, bBigImages, m_bIsHiContrast ); + m_pToolBar->SetItemImage( nId, aImage ); + } + } + + m_pToolBar->SetToolboxButtonSize( bBigImages ? TOOLBOX_BUTTONSIZE_LARGE : TOOLBOX_BUTTONSIZE_SMALL ); + ::Size aSize = m_pToolBar->CalcWindowSizePixel(); + m_pToolBar->SetOutputSizePixel( aSize ); +} + +void ToolBarManager::UpdateImageOrientation() +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_xUICommandLabels.is() ) + { + sal_Int32 i; + Sequence< rtl::OUString > aSeqMirrorCmd; + Sequence< rtl::OUString > aSeqRotateCmd; + m_xUICommandLabels->getByName( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( UICOMMANDDESCRIPTION_NAMEACCESS_COMMANDMIRRORIMAGELIST ))) >>= aSeqMirrorCmd; + m_xUICommandLabels->getByName( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( UICOMMANDDESCRIPTION_NAMEACCESS_COMMANDROTATEIMAGELIST ))) >>= aSeqRotateCmd; + + CommandToInfoMap::iterator pIter; + for ( i = 0; i < aSeqMirrorCmd.getLength(); i++ ) + { + rtl::OUString aMirrorCmd = aSeqMirrorCmd[i]; + pIter = m_aCommandMap.find( aMirrorCmd ); + if ( pIter != m_aCommandMap.end() ) + pIter->second.bMirrored = sal_True; + } + for ( i = 0; i < aSeqRotateCmd.getLength(); i++ ) + { + rtl::OUString aRotateCmd = aSeqRotateCmd[i]; + pIter = m_aCommandMap.find( aRotateCmd ); + if ( pIter != m_aCommandMap.end() ) + pIter->second.bRotated = sal_True; + } + } + + for ( USHORT nPos = 0; nPos < m_pToolBar->GetItemCount(); nPos++ ) + { + USHORT nId = m_pToolBar->GetItemId( nPos ); + if ( nId > 0 ) + { + rtl::OUString aCmd = m_pToolBar->GetItemCommand( nId ); + + CommandToInfoMap::const_iterator pIter = m_aCommandMap.find( aCmd ); + if ( pIter != m_aCommandMap.end() ) + { + if ( pIter->second.bRotated ) + { + m_pToolBar->SetItemImageMirrorMode( nId, FALSE ); + m_pToolBar->SetItemImageAngle( nId, m_lImageRotation ); + } + if ( pIter->second.bMirrored ) + m_pToolBar->SetItemImageMirrorMode( nId, m_bImageMirrored ); + } + } + } +} + +void ToolBarManager::UpdateControllers() +{ + RTL_LOGFILE_CONTEXT( aLog, "framework (cd100003) ::ToolBarManager::UpdateControllers" ); + + if ( !m_bUpdateControllers ) + { + m_bUpdateControllers = sal_True; + ToolBarControllerMap::iterator pIter = m_aControllerMap.begin(); + + while ( pIter != m_aControllerMap.end() ) + { + try + { + Reference< XUpdatable > xUpdatable( pIter->second, UNO_QUERY ); + if ( xUpdatable.is() ) + xUpdatable->update(); + } + catch ( Exception& ) + { + } + ++pIter; + } + } + m_bUpdateControllers = sal_False; +} + +void ToolBarManager::frameAction( const FrameActionEvent& Action ) +throw ( RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + if ( Action.Action == FrameAction_CONTEXT_CHANGED ) + m_aAsyncUpdateControllersTimer.Start(); +} + +void SAL_CALL ToolBarManager::statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event ) +throw ( ::com::sun::star::uno::RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + if ( m_bDisposed ) + return; + + if ( Event.FeatureURL.Complete.equalsAscii( ".uno:ImageOrientation" )) + { + SfxImageItem aItem( 1, 0 ); + aItem.PutValue( Event.State ); + + m_lImageRotation = aItem.GetRotation(); + m_bImageMirrored = aItem.IsMirrored(); + UpdateImageOrientation(); + } +} + +void SAL_CALL ToolBarManager::disposing( const EventObject& Source ) throw ( RuntimeException ) +{ + { + ResetableGuard aGuard( m_aLock ); + if ( m_bDisposed ) + return; + } + + RemoveControllers(); + + { + ResetableGuard aGuard( m_aLock ); + if ( m_xDocImageManager.is() ) + { + try + { + m_xDocImageManager->removeConfigurationListener( + Reference< XUIConfigurationListener >( + static_cast< OWeakObject* >( this ), UNO_QUERY )); + } + catch ( Exception& ) + { + } + } + + if ( m_xModuleImageManager.is() ) + { + try + { + m_xModuleImageManager->removeConfigurationListener( + Reference< XUIConfigurationListener >( + static_cast< OWeakObject* >( this ), UNO_QUERY )); + } + catch ( Exception& ) + { + } + } + + if ( m_xImageOrientationListener.is() ) + { + ImageOrientationListener* pImageOrientation = + (ImageOrientationListener*)m_xImageOrientationListener.get(); + pImageOrientation->unbindListener(); + m_xImageOrientationListener.clear(); + } + + m_xDocImageManager.clear(); + m_xModuleImageManager.clear(); + + if ( Source.Source == Reference< XInterface >( m_xFrame, UNO_QUERY )) + m_xFrame.clear(); + + m_xServiceManager.clear(); + } +} + +// XComponent +void SAL_CALL ToolBarManager::dispose() throw( RuntimeException ) +{ + Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY ); + + EventObject aEvent( xThis ); + m_aListenerContainer.disposeAndClear( aEvent ); + + { + ResetableGuard aGuard( m_aLock ); + + // stop timer to prevent timer events after dispose + m_aAsyncUpdateControllersTimer.Stop(); + + RemoveControllers(); + + if ( m_xDocImageManager.is() ) + { + try + { + m_xDocImageManager->removeConfigurationListener( + Reference< XUIConfigurationListener >( + static_cast< OWeakObject* >( this ), UNO_QUERY )); + } + catch ( Exception& ) + { + } + } + m_xDocImageManager.clear(); + if ( m_xModuleImageManager.is() ) + { + try + { + m_xModuleImageManager->removeConfigurationListener( + Reference< XUIConfigurationListener >( + static_cast< OWeakObject* >( this ), UNO_QUERY )); + } + catch ( Exception& ) + { + } + } + m_xModuleImageManager.clear(); + + ImplClearPopupMenu( m_pToolBar ); + + // We have to destroy our toolbar instance now. + Destroy(); + + if ( m_bFrameActionRegistered && m_xFrame.is() ) + { + try + { + m_xFrame->removeFrameActionListener( Reference< XFrameActionListener >( + static_cast< ::cppu::OWeakObject *>( this ), UNO_QUERY )); + } + catch ( Exception& ) + { + } + } + + if ( m_xImageOrientationListener.is() ) + { + ImageOrientationListener* pImageOrientation = + (ImageOrientationListener*)m_xImageOrientationListener.get(); + pImageOrientation->unbindListener(); + m_xImageOrientationListener.clear(); + } + + m_xFrame.clear(); + m_xServiceManager.clear(); + + m_bDisposed = sal_True; + } +} + +void SAL_CALL ToolBarManager::addEventListener( const Reference< XEventListener >& xListener ) throw( RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + if ( m_bDisposed ) + throw DisposedException(); + + m_aListenerContainer.addInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), xListener ); +} + +void SAL_CALL ToolBarManager::removeEventListener( const Reference< XEventListener >& xListener ) throw( RuntimeException ) +{ + m_aListenerContainer.removeInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), xListener ); +} + +// XUIConfigurationListener +void SAL_CALL ToolBarManager::elementInserted( const ::com::sun::star::ui::ConfigurationEvent& Event ) throw (::com::sun::star::uno::RuntimeException) +{ + impl_elementChanged(false,Event); +} + +void SAL_CALL ToolBarManager::elementRemoved( const ::com::sun::star::ui::ConfigurationEvent& Event ) throw (::com::sun::star::uno::RuntimeException) +{ + impl_elementChanged(true,Event); +} +void ToolBarManager::impl_elementChanged(bool _bRemove,const ::com::sun::star::ui::ConfigurationEvent& Event ) +{ + ResetableGuard aGuard( m_aLock ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + if ( m_bDisposed ) + return; + + Reference< XNameAccess > xNameAccess; + sal_Int16 nImageType = sal_Int16(); + sal_Int16 nCurrentImageType = getImageTypeFromBools( + SvtMiscOptions().AreCurrentSymbolsLarge(), + m_bIsHiContrast ); + + if (( Event.aInfo >>= nImageType ) && + ( nImageType == nCurrentImageType ) && + ( Event.Element >>= xNameAccess )) + { + sal_Int16 nImageInfo( 1 ); + Reference< XInterface > xIfacDocImgMgr( m_xDocImageManager, UNO_QUERY ); + if ( xIfacDocImgMgr == Event.Source ) + nImageInfo = 0; + + Sequence< rtl::OUString > aSeq = xNameAccess->getElementNames(); + for ( sal_Int32 i = 0; i < aSeq.getLength(); i++ ) + { + CommandToInfoMap::iterator pIter = m_aCommandMap.find( aSeq[i] ); + if ( pIter != m_aCommandMap.end() && ( pIter->second.nImageInfo >= nImageInfo )) + { + if ( _bRemove ) + { + Image aImage; + if (( pIter->second.nImageInfo == 0 ) && ( pIter->second.nImageInfo == nImageInfo )) + { + // Special case: An image from the document image manager has been removed. + // It is possible that we have a image at our module image manager. Before + // we can remove our image we have to ask our module image manager. + Sequence< rtl::OUString > aCmdURLSeq( 1 ); + Sequence< Reference< XGraphic > > aGraphicSeq; + aCmdURLSeq[0] = pIter->first; + aGraphicSeq = m_xModuleImageManager->getImages( nImageType, aCmdURLSeq ); + aImage = Image( aGraphicSeq[0] ); + } + + setToolBarImage(aImage,pIter); + } // if ( _bRemove ) + else + { + Reference< XGraphic > xGraphic; + if ( xNameAccess->getByName( aSeq[i] ) >>= xGraphic ) + { + Image aImage( xGraphic ); + setToolBarImage(aImage,pIter); + } + pIter->second.nImageInfo = nImageInfo; + } + } + } + } +} +void ToolBarManager::setToolBarImage(const Image& _aImage,const CommandToInfoMap::const_iterator& _pIter) +{ + const ::std::vector< USHORT >& _rIDs = _pIter->second.aIds; + m_pToolBar->SetItemImage( _pIter->second.nId, _aImage ); + ::std::for_each(_rIDs.begin(),_rIDs.end(),::boost::bind(&ToolBar::SetItemImage,m_pToolBar,_1,_aImage)); +} + +void SAL_CALL ToolBarManager::elementReplaced( const ::com::sun::star::ui::ConfigurationEvent& Event ) throw (::com::sun::star::uno::RuntimeException) +{ + impl_elementChanged(false,Event); +} + +void ToolBarManager::RemoveControllers() +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + return; + + m_aSubToolBarControllerMap.clear(); + + + // i90033 + // Remove item window pointers from the toolbar. They were + // destroyed by the dispose() at the XComponent. This is needed + // as VCL code later tries to access the item window data in certain + // dtors where the item window is already invalid! + for ( sal_uInt16 i = 0; i < m_pToolBar->GetItemCount(); i++ ) + { + sal_uInt16 nItemId = m_pToolBar->GetItemId( i ); + if ( nItemId > 0 ) + { + Reference< XComponent > xComponent( m_aControllerMap[ nItemId ], UNO_QUERY ); + if ( xComponent.is() ) + { + try + { + xComponent->dispose(); + } + catch ( Exception& ) + { + } + } + m_pToolBar->SetItemWindow(nItemId, 0); + } + } + m_aControllerMap.clear(); +} + +::rtl::OUString ToolBarManager::RetrieveLabelFromCommand( const ::rtl::OUString& aCmdURL ) +{ + ::rtl::OUString aLabel; + + // Retrieve popup menu labels + if ( !m_bModuleIdentified ) + { + Reference< XModuleManager > xModuleManager( m_xServiceManager->createInstance( SERVICENAME_MODULEMANAGER ), UNO_QUERY_THROW ); + Reference< XInterface > xIfac( m_xFrame, UNO_QUERY ); + try + { + m_bModuleIdentified = sal_True; + m_aModuleIdentifier = xModuleManager->identify( xIfac ); + + if ( m_aModuleIdentifier.getLength() > 0 ) + { + Reference< XNameAccess > xNameAccess( m_xServiceManager->createInstance( SERVICENAME_UICOMMANDDESCRIPTION ), UNO_QUERY ); + if ( xNameAccess.is() ) + { + xNameAccess->getByName( m_aModuleIdentifier ) >>= m_xUICommandLabels; + } + } + } + catch ( Exception& ) + { + } + } + + if ( m_xUICommandLabels.is() ) + { + try + { + if ( aCmdURL.getLength() > 0 ) + { + rtl::OUString aStr; + Sequence< PropertyValue > aPropSeq; + if ( m_xUICommandLabels->getByName( aCmdURL ) >>= aPropSeq ) + { + for ( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ ) + { + if ( aPropSeq[i].Name.equalsAscii( "Name" )) + { + aPropSeq[i].Value >>= aStr; + break; + } + } + } + aLabel = aStr; + } + } + catch ( com::sun::star::uno::Exception& ) + { + } + } + + return aLabel; +} + +void ToolBarManager::CreateControllers() +{ + RTL_LOGFILE_CONTEXT( aLog, "framework (cd100003) ::ToolBarManager::CreateControllers" ); + + Reference< XMultiComponentFactory > xToolbarControllerFactory( m_xToolbarControllerRegistration, UNO_QUERY ); + Reference< XComponentContext > xComponentContext; + Reference< XPropertySet > xProps( m_xServiceManager, UNO_QUERY ); + Reference< XWindow > xToolbarWindow = VCLUnoHelper::GetInterface( m_pToolBar ); + + css::util::URL aURL; + sal_Bool bHasDisabledEntries = SvtCommandOptions().HasEntries( SvtCommandOptions::CMDOPTION_DISABLED ); + SvtCommandOptions aCmdOptions; + + if ( xProps.is() ) + xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xComponentContext; + + for ( USHORT i = 0; i < m_pToolBar->GetItemCount(); i++ ) + { + USHORT nId = m_pToolBar->GetItemId( i ); + if ( nId == 0 ) + continue; + + sal_Int16 nWidth( sal_Int16( m_pToolBar->GetHelpId( nId ))); + rtl::OUString aLoadURL( RTL_CONSTASCII_USTRINGPARAM( ".uno:OpenUrl" )); + rtl::OUString aCommandURL( m_pToolBar->GetItemCommand( nId )); + sal_Bool bInit( sal_True ); + sal_Bool bCreate( sal_True ); + Reference< XStatusListener > xController; + + svt::ToolboxController* pController( 0 ); + + m_pToolBar->SetHelpId( nId, 0 ); // reset value again + if ( bHasDisabledEntries ) + { + aURL.Complete = aCommandURL; + m_xURLTransformer->parseStrict( aURL ); + if ( aCmdOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED, aURL.Path )) + { + m_aControllerMap[ nId ] = xController; + m_pToolBar->HideItem( nId ); + continue; + } + } + + if ( m_xToolbarControllerRegistration.is() && + m_xToolbarControllerRegistration->hasController( aCommandURL, m_aModuleIdentifier )) + { + if ( xToolbarControllerFactory.is() ) + { + PropertyValue aPropValue; + std::vector< Any > aPropertyVector; + + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ModuleName" )); + aPropValue.Value <<= m_aModuleIdentifier; + aPropertyVector.push_back( makeAny( aPropValue )); + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" )); + aPropValue.Value <<= m_xFrame; + aPropertyVector.push_back( makeAny( aPropValue )); + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ServiceManager" )); + aPropValue.Value <<= m_xServiceManager; + aPropertyVector.push_back( makeAny( aPropValue )); + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ParentWindow" )); + aPropValue.Value <<= xToolbarWindow; + aPropertyVector.push_back( makeAny( aPropValue )); + + if ( nWidth > 0 ) + { + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Width" )); + aPropValue.Value <<= nWidth; + aPropertyVector.push_back( makeAny( aPropValue )); + } + + Sequence< Any > aArgs( comphelper::containerToSequence( aPropertyVector )); + xController = Reference< XStatusListener >( xToolbarControllerFactory->createInstanceWithArgumentsAndContext( + aCommandURL, aArgs, xComponentContext ), + UNO_QUERY ); + bInit = sal_False; // Initialization is done through the factory service + } + } + + if (( aCommandURL == aLoadURL ) && ( !m_pToolBar->IsItemVisible(nId))) + bCreate = sal_False; + + if ( !xController.is() && m_pToolBar && bCreate ) + { + pController = CreateToolBoxController( m_xFrame, m_pToolBar, nId, aCommandURL ); + if ( !pController ) + { + if ( m_pToolBar->GetItemData( nId ) != 0 ) + { + // retrieve additional parameters + ::rtl::OUString aControlType = static_cast< AddonsParams* >( m_pToolBar->GetItemData( nId ))->aControlType; + + Reference< XStatusListener > xStatusListener( + ToolBarMerger::CreateController( m_xServiceManager, + m_xFrame, + m_pToolBar, + aCommandURL, + nId, + nWidth, + aControlType ), UNO_QUERY ); + + xController = xStatusListener; + } + else + { + MenuDescriptionMap::iterator it = m_aMenuMap.find( nId ); + if ( it == m_aMenuMap.end() ) + xController = Reference< XStatusListener >( + new GenericToolbarController( m_xServiceManager, m_xFrame, m_pToolBar, nId, aCommandURL )); + else + xController = Reference< XStatusListener >( + new MenuToolbarController( m_xServiceManager, m_xFrame, m_pToolBar, nId, aCommandURL, m_aModuleIdentifier, m_aMenuMap[ nId ] )); + } + } + else if ( pController ) + { + xController = Reference< XStatusListener >( static_cast< ::cppu::OWeakObject *>( pController ), UNO_QUERY ); + } + } + + // Associate ID and controller to be able to retrieve + // the controller from the ID later. + m_aControllerMap[ nId ] = xController; + + // Fill sub-toolbars into our hash-map + Reference< XSubToolbarController > xSubToolBar( xController, UNO_QUERY ); + if ( xSubToolBar.is() && xSubToolBar->opensSubToolbar() ) + { + rtl::OUString aSubToolBarName = xSubToolBar->getSubToolbarName(); + if ( aSubToolBarName.getLength() != 0 ) + { + SubToolBarToSubToolBarControllerMap::iterator pIter = + m_aSubToolBarControllerMap.find( aSubToolBarName ); + if ( pIter == m_aSubToolBarControllerMap.end() ) + { + SubToolBarControllerVector aSubToolBarVector; + aSubToolBarVector.push_back( xSubToolBar ); + m_aSubToolBarControllerMap.insert( + SubToolBarToSubToolBarControllerMap::value_type( + aSubToolBarName, aSubToolBarVector )); + } + else + pIter->second.push_back( xSubToolBar ); + } + } + + Reference< XInitialization > xInit( xController, UNO_QUERY ); + if ( xInit.is() ) + { + if ( bInit ) + { + PropertyValue aPropValue; + std::vector< Any > aPropertyVector; + + aPropValue.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" )); + aPropValue.Value <<= m_xFrame; + aPropertyVector.push_back( makeAny( aPropValue )); + aPropValue.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CommandURL" )); + aPropValue.Value <<= aCommandURL; + aPropertyVector.push_back( makeAny( aPropValue )); + aPropValue.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ServiceManager" )); + aPropValue.Value <<= m_xServiceManager; + aPropertyVector.push_back( makeAny( aPropValue )); + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ParentWindow" )); + aPropValue.Value <<= xToolbarWindow; + aPropertyVector.push_back( makeAny( aPropValue )); + if ( nWidth > 0 ) + { + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Width" )); + aPropValue.Value <<= nWidth; + aPropertyVector.push_back( makeAny( aPropValue )); + } + + Sequence< Any > aArgs( comphelper::containerToSequence( aPropertyVector )); + xInit->initialize( aArgs ); + } + + // Request a item window from the toolbar controller and set it at the VCL toolbar + Reference< XToolbarController > xTbxController( xController, UNO_QUERY ); + if ( xTbxController.is() && xToolbarWindow.is() ) + { + Reference< XWindow > xWindow = xTbxController->createItemWindow( xToolbarWindow ); + if ( xWindow.is() ) + { + Window* pItemWin = VCLUnoHelper::GetWindow( xWindow ); + if ( pItemWin ) + { + WindowType nType = pItemWin->GetType(); + if ( nType == WINDOW_LISTBOX || nType == WINDOW_MULTILISTBOX || nType == WINDOW_COMBOBOX ) + pItemWin->SetAccessibleName( m_pToolBar->GetItemText( nId ) ); + m_pToolBar->SetItemWindow( nId, pItemWin ); + } + } + } + } + } + + AddFrameActionListener(); + AddImageOrientationListener(); +} + +void ToolBarManager::AddFrameActionListener() +{ + if ( !m_bFrameActionRegistered && m_xFrame.is() ) + { + m_bFrameActionRegistered = sal_True; + m_xFrame->addFrameActionListener( Reference< XFrameActionListener >( + static_cast< ::cppu::OWeakObject *>( this ), UNO_QUERY )); + } +} + +void ToolBarManager::AddImageOrientationListener() +{ + if ( !m_bImageOrientationRegistered && m_xFrame.is() ) + { + m_bImageOrientationRegistered = sal_True; + ImageOrientationListener* pImageOrientation = new ImageOrientationListener( + Reference< XStatusListener >( static_cast< ::cppu::OWeakObject *>( this ), UNO_QUERY ), + m_xServiceManager, + m_xFrame ); + m_xImageOrientationListener = Reference< XComponent >( static_cast< ::cppu::OWeakObject *>( + pImageOrientation ), UNO_QUERY ); + pImageOrientation->addStatusListener( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:ImageOrientation" ))); + pImageOrientation->bindListener(); + } +} + +sal_uInt16 ToolBarManager::ConvertStyleToToolboxItemBits( sal_Int32 nStyle ) +{ + sal_uInt16 nItemBits( 0 ); + if ( nStyle & ::com::sun::star::ui::ItemStyle::RADIO_CHECK ) + nItemBits |= TIB_RADIOCHECK; + if ( nStyle & ::com::sun::star::ui::ItemStyle::ALIGN_LEFT ) + nItemBits |= TIB_LEFT; + if ( nStyle & ::com::sun::star::ui::ItemStyle::AUTO_SIZE ) + nItemBits |= TIB_AUTOSIZE; + if ( nStyle & ::com::sun::star::ui::ItemStyle::DROP_DOWN ) + nItemBits |= TIB_DROPDOWN; + if ( nStyle & ::com::sun::star::ui::ItemStyle::REPEAT ) + nItemBits |= TIB_REPEAT; + if ( nStyle & ::com::sun::star::ui::ItemStyle::DROPDOWN_ONLY ) + nItemBits |= TIB_DROPDOWNONLY; + if ( nStyle & ::com::sun::star::ui::ItemStyle::TEXT ) + nItemBits |= TIB_TEXT_ONLY; + if ( nStyle & ::com::sun::star::ui::ItemStyle::ICON ) + nItemBits |= TIB_ICON_ONLY; + + return nItemBits; +} + +void ToolBarManager::FillToolbar( const Reference< XIndexAccess >& rItemContainer ) +{ + ::rtl::OString aTbxName = rtl::OUStringToOString( m_aResourceName, RTL_TEXTENCODING_ASCII_US ); + + RTL_LOGFILE_CONTEXT( aLog, "framework (cd100003) ::ToolBarManager::FillToolbar" ); + RTL_LOGFILE_CONTEXT_TRACE1( aLog, "framework (cd100003) ::ToolBarManager::FillToolbar %s", aTbxName.getStr() ); + + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + return; + + USHORT nId( 1 ); + ::rtl::OUString aHelpIdPrefix( RTL_CONSTASCII_USTRINGPARAM( HELPID_PREFIX )); + + Reference< XModuleManager > xModuleManager( Reference< XModuleManager >( + m_xServiceManager->createInstance( SERVICENAME_MODULEMANAGER ), UNO_QUERY )); + if ( !m_xDocImageManager.is() ) + { + Reference< XModel > xModel( GetModelFromFrame() ); + if ( xModel.is() ) + { + Reference< XUIConfigurationManagerSupplier > xSupplier( xModel, UNO_QUERY ); + if ( xSupplier.is() ) + { + m_xDocUICfgMgr.set( xSupplier->getUIConfigurationManager(), UNO_QUERY ); + m_xDocImageManager = Reference< XImageManager >( m_xDocUICfgMgr->getImageManager(), UNO_QUERY ); + m_xDocImageManager->addConfigurationListener( + Reference< XUIConfigurationListener >( + static_cast< OWeakObject* >( this ), UNO_QUERY )); + } + } + } + + try + { + if ( xModuleManager.is() ) + m_aModuleIdentifier = xModuleManager->identify( Reference< XInterface >( m_xFrame, UNO_QUERY ) ); + } + catch( Exception& ) + { + } + + if ( !m_xModuleImageManager.is() ) + { + Reference< XModuleUIConfigurationManagerSupplier > xModuleCfgMgrSupplier( m_xServiceManager->createInstance( + SERVICENAME_MODULEUICONFIGURATIONMANAGERSUPPLIER ), + UNO_QUERY ); + m_xUICfgMgr = xModuleCfgMgrSupplier->getUIConfigurationManager( m_aModuleIdentifier ); + m_xModuleImageManager = Reference< XImageManager >( m_xUICfgMgr->getImageManager(), UNO_QUERY ); + m_xModuleImageManager->addConfigurationListener( Reference< XUIConfigurationListener >( + static_cast< OWeakObject* >( this ), UNO_QUERY )); + } + + RemoveControllers(); + + // reset and fill command map + m_pToolBar->Clear(); + m_aControllerMap.clear(); + m_aCommandMap.clear(); + + m_aMenuMap.clear(); + + CommandInfo aCmdInfo; + for ( sal_Int32 n = 0; n < rItemContainer->getCount(); n++ ) + { + Sequence< PropertyValue > aProp; + rtl::OUString aCommandURL; + rtl::OUString aLabel; + rtl::OUString aHelpURL; + rtl::OUString aTooltip; + sal_uInt16 nType( ::com::sun::star::ui::ItemType::DEFAULT ); + sal_uInt16 nWidth( 0 ); + sal_Bool bIsVisible( sal_True ); + sal_uInt32 nStyle( 0 ); + + Reference< XIndexAccess > aMenuDesc; + try + { + if ( rItemContainer->getByIndex( n ) >>= aProp ) + { + for ( int i = 0; i < aProp.getLength(); i++ ) + { + if ( aProp[i].Name.equalsAsciiL( ITEM_DESCRIPTOR_COMMANDURL, ITEM_DESCRIPTOR_COMMANDURL_LEN )) + { + aProp[i].Value >>= aCommandURL; + if ( aCommandURL.compareToAscii(MENUPREFIX, RTL_CONSTASCII_LENGTH(MENUPREFIX) ) == 0 ) + { + try + { + Reference< XIndexAccess > xMenuContainer; + if ( m_xDocUICfgMgr.is() ) + xMenuContainer = m_xDocUICfgMgr->getSettings( aCommandURL, sal_False ); + if ( !xMenuContainer.is() && m_xUICfgMgr.is() ) + xMenuContainer = m_xUICfgMgr->getSettings( aCommandURL, sal_False ); + if ( xMenuContainer.is() && xMenuContainer->getCount() ) + { + Sequence< PropertyValue > aProps; + // drop down menu info is currently + // the first ( and only ) menu + // in the menusettings container + xMenuContainer->getByIndex(0) >>= aProps; + for ( sal_Int32 index=0; index<aProps.getLength(); ++index ) + { + if ( aProps[ index ].Name.equalsAsciiL( ITEM_DESCRIPTOR_CONTAINER, ITEM_DESCRIPTOR_CONTAINER_LEN )) + + { + aProps[ index ].Value >>= aMenuDesc; + break; + } + } + } + } + catch( Exception& ) + { + } + } + } + else if ( aProp[i].Name.equalsAsciiL( ITEM_DESCRIPTOR_HELPURL, ITEM_DESCRIPTOR_HELPURL_LEN )) + aProp[i].Value >>= aHelpURL; + else if ( aProp[i].Name.equalsAsciiL( ITEM_DESCRIPTOR_TOOLTIP, ITEM_DESCRIPTOR_TOOLTIP_LEN )) + aProp[i].Value >>= aTooltip; + else if ( aProp[i].Name.equalsAsciiL( ITEM_DESCRIPTOR_LABEL, ITEM_DESCRIPTOR_LABEL_LEN )) + aProp[i].Value >>= aLabel; + else if ( aProp[i].Name.equalsAsciiL( ITEM_DESCRIPTOR_TYPE, ITEM_DESCRIPTOR_TYPE_LEN )) + aProp[i].Value >>= nType; + else if ( aProp[i].Name.equalsAsciiL( ITEM_DESCRIPTOR_VISIBLE, ITEM_DESCRIPTOR_VISIBLE_LEN )) + aProp[i].Value >>= bIsVisible; + else if ( aProp[i].Name.equalsAsciiL( ITEM_DESCRIPTOR_WIDTH, ITEM_DESCRIPTOR_WIDTH_LEN )) + aProp[i].Value >>= nWidth; + else if ( aProp[i].Name.equalsAsciiL( ITEM_DESCRIPTOR_STYLE, ITEM_DESCRIPTOR_STYLE_LEN )) + aProp[i].Value >>= nStyle; + } + + if (( nType == ::com::sun::star::ui::ItemType::DEFAULT ) && ( aCommandURL.getLength() > 0 )) + { + ::rtl::OUString aString( RetrieveLabelFromCommand( aCommandURL )); + + sal_uInt16 nItemBits = ConvertStyleToToolboxItemBits( nStyle ); + if ( aMenuDesc.is() ) + m_aMenuMap[ nId ] = aMenuDesc; + m_pToolBar->InsertItem( nId, aString, nItemBits ); + m_pToolBar->SetItemCommand( nId, aCommandURL ); + if ( aTooltip.getLength() ) + m_pToolBar->SetQuickHelpText( nId, aTooltip ); + else + m_pToolBar->SetQuickHelpText( nId, aString ); + if ( aLabel.getLength() > 0 ) + m_pToolBar->SetItemText( nId, aLabel ); + else + m_pToolBar->SetItemText( nId, aString ); + m_pToolBar->EnableItem( nId, sal_True ); + m_pToolBar->SetItemState( nId, STATE_NOCHECK ); + + // Fill command map. It stores all our commands and from what + // image manager we got our image. So we can decide if we have to use an + // image from a notification message. + CommandToInfoMap::iterator pIter = m_aCommandMap.find( aCommandURL ); + if ( pIter == m_aCommandMap.end()) + { + aCmdInfo.nId = nId; + m_aCommandMap.insert( CommandToInfoMap::value_type( aCommandURL, aCmdInfo )); + } + else + { + pIter->second.aIds.push_back( nId ); + } + + // Add additional information for the controller to the obsolete help id + m_pToolBar->SetHelpId( ULONG( nWidth )); + + if ( !bIsVisible ) + m_pToolBar->HideItem( nId ); + + ++nId; + } + else if ( nType == ::com::sun::star::ui::ItemType::SEPARATOR_LINE ) + { + m_pToolBar->InsertSeparator(); + } + else if ( nType == ::com::sun::star::ui::ItemType::SEPARATOR_SPACE ) + { + m_pToolBar->InsertSpace(); + } + else if ( nType == ::com::sun::star::ui::ItemType::SEPARATOR_LINEBREAK ) + { + m_pToolBar->InsertBreak(); + } + } + } + catch ( ::com::sun::star::lang::IndexOutOfBoundsException& ) + { + break; + } + } + + // Support add-on toolbar merging here. Working directly on the toolbar object is much + // simpler and faster. + const sal_uInt16 TOOLBAR_ITEM_STARTID = 1000; + + MergeToolbarInstructionContainer aMergeInstructionContainer; + + // Retrieve the toolbar name from the resource name + ::rtl::OUString aToolbarName( m_aResourceName ); + sal_Int32 nIndex = aToolbarName.lastIndexOf( '/' ); + if (( nIndex > 0 ) && ( nIndex < aToolbarName.getLength() )) + aToolbarName = aToolbarName.copy( nIndex+1 ); + + AddonsOptions().GetMergeToolbarInstructions( aToolbarName, aMergeInstructionContainer ); + + if ( !aMergeInstructionContainer.empty() ) + { + sal_uInt16 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 )) + { + ReferenceToolbarPathInfo aRefPoint = ToolBarMerger::FindReferencePoint( m_pToolBar, rInstruction.aMergePoint ); + + // convert the sequence< sequence< propertyvalue > > structure to + // something we can better handle. A vector with item data + AddonToolbarItemContainer aItems; + ToolBarMerger::ConvertSeqSeqToVector( rInstruction.aMergeToolbarItems, aItems ); + + if ( aRefPoint.bResult ) + { + ToolBarMerger::ProcessMergeOperation( m_xFrame, + m_pToolBar, + aRefPoint.nPos, + nItemId, + m_aCommandMap, + m_aModuleIdentifier, + rInstruction.aMergeCommand, + rInstruction.aMergeCommandParameter, + aItems ); + } + else + { + ToolBarMerger::ProcessMergeFallback( m_xFrame, + m_pToolBar, + aRefPoint.nPos, + nItemId, + m_aCommandMap, + m_aModuleIdentifier, + rInstruction.aMergeCommand, + rInstruction.aMergeFallback, + aItems ); + } + } + } + } + + // 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_pToolBar->WillUsePopupMode() ) + UpdateControllers(); + else if ( m_pToolBar->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() ) + { + try + { + rtl::OUString aUIName; + xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UIName" ))) >>= aUIName; + if ( aUIName.getLength() > 0 ) + m_pToolBar->SetText( aUIName ); + } + catch ( Exception& ) + { + } + } +} + +void ToolBarManager::RequestImages() +{ + RTL_LOGFILE_CONTEXT( aLog, "framework (cd100003) ::ToolBarManager::RequestImages" ); + + // Request images from image manager + Sequence< rtl::OUString > aCmdURLSeq( m_aCommandMap.size() ); + Sequence< Reference< XGraphic > > aDocGraphicSeq; + Sequence< Reference< XGraphic > > aModGraphicSeq; + + sal_uInt32 i = 0; + CommandToInfoMap::iterator pIter = m_aCommandMap.begin(); + CommandToInfoMap::iterator pEnd = m_aCommandMap.end(); + while ( pIter != pEnd ) + { + aCmdURLSeq[i++] = pIter->first; + ++pIter; + } + + sal_Bool bBigImages( SvtMiscOptions().AreCurrentSymbolsLarge() ); + m_bIsHiContrast = m_pToolBar->GetSettings().GetStyleSettings().GetHighContrastMode(); + sal_Int16 p = getImageTypeFromBools( SvtMiscOptions().AreCurrentSymbolsLarge(), m_bIsHiContrast ); + + if ( m_xDocImageManager.is() ) + aDocGraphicSeq = m_xDocImageManager->getImages( p, aCmdURLSeq ); + aModGraphicSeq = m_xModuleImageManager->getImages( p, aCmdURLSeq ); + + i = 0; + pIter = m_aCommandMap.begin(); + while ( pIter != pEnd ) + { + rtl::OUString aCommandURL = aCmdURLSeq[i]; + + Image aImage; + if ( aDocGraphicSeq.getLength() > 0 ) + aImage = Image( aDocGraphicSeq[i] ); + if ( !aImage ) + { + aImage = Image( aModGraphicSeq[i] ); + // Try also to query for add-on images before giving up and use an + // empty image. + if ( !aImage ) + aImage = QueryAddonsImage( aCmdURLSeq[i], bBigImages, m_bIsHiContrast ); + + pIter->second.nImageInfo = 1; // mark image as module based + } + else + { + pIter->second.nImageInfo = 0; // mark image as document based + } + setToolBarImage(aImage,pIter); + ++pIter; + ++i; + } +} + +void ToolBarManager::notifyRegisteredControllers( const rtl::OUString& aUIElementName, const rtl::OUString& aCommand ) +{ + ResetableGuard aGuard( m_aLock ); + if ( !m_aSubToolBarControllerMap.empty() ) + { + SubToolBarToSubToolBarControllerMap::const_iterator pIter = + m_aSubToolBarControllerMap.find( aUIElementName ); + + if ( pIter != m_aSubToolBarControllerMap.end() ) + { + const SubToolBarControllerVector& rSubToolBarVector = pIter->second; + if ( !rSubToolBarVector.empty() ) + { + SubToolBarControllerVector aNotifyVector = rSubToolBarVector; + aGuard.unlock(); + + const sal_uInt32 nCount = aNotifyVector.size(); + for ( sal_uInt32 i=0; i < nCount; i++ ) + { + try + { + Reference< XSubToolbarController > xController = aNotifyVector[i]; + if ( xController.is() ) + xController->functionSelected( aCommand ); + } + catch ( RuntimeException& e ) + { + throw e; + } + catch ( Exception& ) + { + } + } + } + } + } +} +long ToolBarManager::HandleClick(void ( SAL_CALL XToolbarController::*_pClick )()) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + return 1; + + USHORT nId( m_pToolBar->GetCurItemId() ); + ToolBarControllerMap::const_iterator pIter = m_aControllerMap.find( nId ); + if ( pIter != m_aControllerMap.end() ) + { + Reference< XToolbarController > xController( pIter->second, UNO_QUERY ); + + if ( xController.is() ) + (xController.get()->*_pClick)( ); + } // if ( pIter != m_aControllerMap.end() ) + return 1; +} + +IMPL_LINK( ToolBarManager, Click, ToolBox*, EMPTYARG ) +{ + return HandleClick(&XToolbarController::click); +} + +IMPL_LINK( ToolBarManager, DropdownClick, ToolBox*, EMPTYARG ) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + return 1; + + USHORT nId( m_pToolBar->GetCurItemId() ); + ToolBarControllerMap::const_iterator pIter = m_aControllerMap.find( nId ); + if ( pIter != m_aControllerMap.end() ) + { + Reference< XToolbarController > xController( pIter->second, UNO_QUERY ); + + if ( xController.is() ) + xController->createPopupWindow(); + } + return 1; +} + +IMPL_LINK( ToolBarManager, DoubleClick, ToolBox*, EMPTYARG ) +{ + return HandleClick(&XToolbarController::doubleClick); +} + +void ToolBarManager::ImplClearPopupMenu( ToolBox *pToolBar ) +{ + if ( m_bDisposed ) + return; + + PopupMenu *pMenu = pToolBar->GetMenu(); + + // remove config entries from menu, so we have a clean menu to start with + // remove submenu first + PopupMenu* pItemMenu = pMenu->GetPopupMenu( 1 ); + if( pItemMenu ) + { + pItemMenu->Clear(); + delete pItemMenu; + pItemMenu = NULL; + pMenu->SetPopupMenu( 1, pItemMenu ); + } + + // remove all items that were not added by the toolbar itself + USHORT i; + for( i=0; i<pMenu->GetItemCount(); ) + { + if( pMenu->GetItemId( i ) < TOOLBOX_MENUITEM_START ) + pMenu->RemoveItem( i ); + else + i++; + } +} + +IMPL_LINK( ToolBarManager, MenuDeactivate, Menu*, pMenu ) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + return 1; + + if( pMenu != m_pToolBar->GetMenu() ) + return 1; + + ImplClearPopupMenu( m_pToolBar ); + + return 0; +} + +Reference< XModel > ToolBarManager::GetModelFromFrame() const +{ + Reference< XController > xController = m_xFrame->getController(); + Reference< XModel > xModel; + if ( xController.is() ) + xModel = xController->getModel(); + + return xModel; +} + +sal_Bool ToolBarManager::IsPluginMode() const +{ + sal_Bool bPluginMode( sal_False ); + + if ( m_xFrame.is() ) + { + Reference< XModel > xModel = GetModelFromFrame(); + if ( xModel.is() ) + { + Sequence< PropertyValue > aSeq = xModel->getArgs(); + comphelper::MediaDescriptor aMediaDescriptor( aSeq ); + bPluginMode = aMediaDescriptor.getUnpackedValueOrDefault< sal_Bool >( + comphelper::MediaDescriptor::PROP_VIEWONLY(), sal_False ); + } + } + + return bPluginMode; +} + +bool ToolBarManager::MenuItemAllowed( sal_uInt16 ) const +{ + return true; +} + +//added for i33668 by shizhoubo : 200804 +PopupMenu * ToolBarManager::GetToolBarCustomMeun(ToolBox* pToolBar) +{ + PopupMenu *pMenu = pToolBar->GetMenu(); + // remove all entries before inserting new ones + ImplClearPopupMenu( pToolBar ); + // No config menu entries if command ".uno:ConfigureDialog" is not enabled + Reference< XDispatch > xDisp; + com::sun::star::util::URL aURL; + if ( m_xFrame.is() ) + { + Reference< XDispatchProvider > xProv( m_xFrame, UNO_QUERY ); + aURL.Complete = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:ConfigureDialog" )); + m_xURLTransformer->parseStrict( aURL ); + if ( xProv.is() ) + xDisp = xProv->queryDispatch( aURL, ::rtl::OUString(), 0 ); + + if ( !xDisp.is() || IsPluginMode() ) + return 0; + } + + // popup menu for quick customization + sal_Bool bHideDisabledEntries = !SvtMenuOptions().IsEntryHidingEnabled(); + PopupMenu aPopupMenu( FwkResId( POPUPMENU_TOOLBAR_QUICKCUSTOMIZATION )); + + if ( m_pToolBar->IsCustomize() ) + { + USHORT nPos( 0 ); + PopupMenu* pItemMenu( aPopupMenu.GetPopupMenu( 1 )); + + sal_Bool bIsFloating( sal_False ); + + DockingManager* pDockMgr = Window::GetDockingManager(); + if ( pDockMgr ) + bIsFloating = pDockMgr->IsFloating( m_pToolBar ); + + if ( !bIsFloating ) + { + aPopupMenu.EnableItem( MENUITEM_TOOLBAR_DOCKTOOLBAR, sal_False ); + aPopupMenu.EnableItem( MENUITEM_TOOLBAR_DOCKALLTOOLBAR, sal_False ); + Reference< XDockableWindow > xDockable( VCLUnoHelper::GetInterface( m_pToolBar ), UNO_QUERY ); + if( xDockable.is() ) + aPopupMenu.CheckItem( MENUITEM_TOOLBAR_LOCKTOOLBARPOSITION, xDockable->isLocked() ); + } + else + aPopupMenu.EnableItem( MENUITEM_TOOLBAR_LOCKTOOLBARPOSITION, sal_False ); + + if ( !m_bCanBeCustomized ) + { + // Non-configurable toolbars should disable configuration menu items + aPopupMenu.EnableItem( MENUITEM_TOOLBAR_VISIBLEBUTTON, sal_False ); + aPopupMenu.EnableItem( MENUITEM_TOOLBAR_CUSTOMIZETOOLBAR, sal_False ); + } + + // Disable menu item CLOSE if the toolbar has no closer + //added for issue64028 by shizhoubo + if( !(pToolBar->GetFloatStyle() & WB_CLOSEABLE) ) + aPopupMenu.EnableItem(MENUITEM_TOOLBAR_CLOSE, sal_False); + //end + + pItemMenu->SetMenuFlags (pItemMenu->GetMenuFlags () | + MENU_FLAG_SHOWCHECKIMAGES); + + for ( nPos = 0; nPos < m_pToolBar->GetItemCount(); ++nPos ) + { + if ( m_pToolBar->GetItemType(nPos) == TOOLBOXITEM_BUTTON ) + { + USHORT nId = m_pToolBar->GetItemId(nPos); + ::rtl::OUString aCommandURL = m_pToolBar->GetItemCommand( nId ); + pItemMenu->InsertItem( STARTID_CUSTOMIZE_POPUPMENU+nPos, m_pToolBar->GetItemText( nId ), MIB_CHECKABLE ); + pItemMenu->CheckItem( STARTID_CUSTOMIZE_POPUPMENU+nPos, m_pToolBar->IsItemVisible( nId ) ); + pItemMenu->SetItemCommand( STARTID_CUSTOMIZE_POPUPMENU+nPos, aCommandURL ); + pItemMenu->SetItemImage( STARTID_CUSTOMIZE_POPUPMENU+nPos, + GetImageFromURL( m_xFrame, + aCommandURL, + sal_False, + m_bIsHiContrast )); + } + else + { + pItemMenu->InsertSeparator(); + } + } + } + else + { + USHORT nPos = aPopupMenu.GetItemPos( MENUITEM_TOOLBAR_CUSTOMIZETOOLBAR ); + if ( nPos != MENU_ITEM_NOTFOUND ) + aPopupMenu.RemoveItem( nPos ); + } + + // copy all menu items to the toolbar menu + if( pMenu->GetItemCount() ) + pMenu->InsertSeparator(); + + USHORT i; + for( i=0; i< aPopupMenu.GetItemCount(); i++) + { + sal_uInt16 nId = aPopupMenu.GetItemId( i ); + if ( MenuItemAllowed( nId )) + pMenu->CopyItem( aPopupMenu, i, MENU_APPEND ); + } + + // set submenu to toolbar menu + if( aPopupMenu.GetPopupMenu( 1 ) ) + { + // create an own submenu to avoid auto-delete when resource menu is deleted + PopupMenu *pItemMenu = new PopupMenu(); + + pItemMenu->SetMenuFlags (pItemMenu->GetMenuFlags () | + MENU_FLAG_SHOWCHECKIMAGES); + + for( i=0; i< aPopupMenu.GetPopupMenu( 1 )->GetItemCount(); i++) + pItemMenu->CopyItem( *aPopupMenu.GetPopupMenu( 1 ), i, MENU_APPEND ); + + pMenu->SetPopupMenu( 1, pItemMenu ); + } + + if ( bHideDisabledEntries ) + pMenu->RemoveDisabledEntries(); + + return pMenu; +} + +// addd for 33668 by shizhoubo +IMPL_LINK( ToolBarManager, Command, CommandEvent*, pCmdEvt ) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + return 1; + if ( pCmdEvt->GetCommand() != COMMAND_CONTEXTMENU ) + return 0; + + PopupMenu * pMenu = GetToolBarCustomMeun(m_pToolBar); + if (pMenu) + { + // make sure all disabled entries will be shown + pMenu->SetMenuFlags( pMenu->GetMenuFlags() | MENU_FLAG_ALWAYSSHOWDISABLEDENTRIES ); + ::Point aPoint( pCmdEvt->GetMousePosPixel() ); + pMenu->Execute( m_pToolBar, aPoint ); + } + + return 0; +} +//end + +IMPL_LINK( ToolBarManager, MenuButton, ToolBox*, pToolBar ) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + return 1; + //modify for i33668 by shizhoubo:2008:04 + GetToolBarCustomMeun(pToolBar); + //end + return 0; + } + +IMPL_LINK( ToolBarManager, MenuSelect, Menu*, pMenu ) +{ + // We have to hold a reference to ourself as it is possible that we will be disposed and + // our refcount could be zero (destruction) otherwise. + Reference< XInterface > xInterface( static_cast< OWeakObject* >( this ), UNO_QUERY ); + + { + // The guard must be in its own context as the we can get destroyed when our + // own xInterface reference get destroyed! + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + return 1; + + switch ( pMenu->GetCurItemId() ) + { + case MENUITEM_TOOLBAR_CUSTOMIZETOOLBAR: + { + Reference< XDispatch > xDisp; + com::sun::star::util::URL aURL; + if ( m_xFrame.is() ) + { + Reference< XDispatchProvider > xProv( m_xFrame, UNO_QUERY ); + aURL.Complete = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:ConfigureDialog" )); + m_xURLTransformer->parseStrict( aURL ); + if ( xProv.is() ) + xDisp = xProv->queryDispatch( aURL, ::rtl::OUString(), 0 ); + } + + if ( xDisp.is() ) + { + Sequence< PropertyValue > aPropSeq( 1 ); + + aPropSeq[ 0 ].Name = + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ResourceURL")); + aPropSeq[ 0 ].Value <<= m_aResourceName; + + xDisp->dispatch( aURL, aPropSeq ); + } + break; + } + + case MENUITEM_TOOLBAR_DOCKTOOLBAR: + { + ExecuteInfo* pExecuteInfo = new ExecuteInfo; + + pExecuteInfo->aToolbarResName = m_aResourceName; + pExecuteInfo->nCmd = EXEC_CMD_DOCKTOOLBAR; + pExecuteInfo->xLayoutManager = getLayoutManagerFromFrame( m_xFrame ); + + Application::PostUserEvent( STATIC_LINK(0, ToolBarManager, ExecuteHdl_Impl), pExecuteInfo ); + break; + } + + case MENUITEM_TOOLBAR_DOCKALLTOOLBAR: + { + ExecuteInfo* pExecuteInfo = new ExecuteInfo; + + pExecuteInfo->aToolbarResName = m_aResourceName; + pExecuteInfo->nCmd = EXEC_CMD_DOCKALLTOOLBARS; + pExecuteInfo->xLayoutManager = getLayoutManagerFromFrame( m_xFrame ); + + Application::PostUserEvent( STATIC_LINK(0, ToolBarManager, ExecuteHdl_Impl), pExecuteInfo ); + break; + } + + case MENUITEM_TOOLBAR_LOCKTOOLBARPOSITION: + { + Reference< XLayoutManager > xLayoutManager = getLayoutManagerFromFrame( m_xFrame ); + if ( xLayoutManager.is() ) + { + Reference< XDockableWindow > xDockable( VCLUnoHelper::GetInterface( m_pToolBar ), UNO_QUERY ); + + if( xDockable->isLocked() ) + xLayoutManager->unlockWindow( m_aResourceName ); + else + xLayoutManager->lockWindow( m_aResourceName ); + } + break; + } + + case MENUITEM_TOOLBAR_CLOSE: + { + ExecuteInfo* pExecuteInfo = new ExecuteInfo; + + pExecuteInfo->aToolbarResName = m_aResourceName; + pExecuteInfo->nCmd = EXEC_CMD_CLOSETOOLBAR; + pExecuteInfo->xLayoutManager = getLayoutManagerFromFrame( m_xFrame ); + pExecuteInfo->xWindow = VCLUnoHelper::GetInterface( m_pToolBar ); + + Application::PostUserEvent( STATIC_LINK(0, ToolBarManager, ExecuteHdl_Impl), pExecuteInfo ); + } + + default: + { + USHORT nId = pMenu->GetCurItemId(); + if(( nId > 0 ) && ( nId < TOOLBOX_MENUITEM_START )) + { + // toggle toolbar button visibility + rtl::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( sal_True ), UNO_QUERY ); + sal_Int32 nCount = xItemContainer->getCount(); + for ( sal_Int32 i = 0; i < nCount; i++ ) + { + Sequence< PropertyValue > aProp; + sal_Int32 nVisibleIndex( -1 ); + rtl::OUString aCommandURL; + sal_Bool bVisible( sal_False ); + + if ( xItemContainer->getByIndex( i ) >>= aProp ) + { + for ( sal_Int32 j = 0; j < aProp.getLength(); j++ ) + { + if ( aProp[j].Name.equalsAscii( ITEM_DESCRIPTOR_COMMANDURL )) + { + aProp[j].Value >>= aCommandURL; + } + else if ( aProp[j].Name.equalsAscii( 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[nVisibleIndex].Value = makeAny( !bVisible ); + try + { + xItemContainer->replaceByIndex( i, makeAny( aProp )); + xUIElementSettings->setSettings( Reference< XIndexAccess >( xItemContainer, UNO_QUERY )); + Reference< XPropertySet > xPropSet( xUIElementSettings, UNO_QUERY ); + if ( xPropSet.is() ) + { + Reference< XUIConfigurationPersistence > xUICfgMgr; + if (( xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ConfigurationSource" ))) >>= xUICfgMgr ) && ( xUICfgMgr.is() )) + xUICfgMgr->store(); + } + } + catch ( Exception& ) + { + } + + break; + } + } + } + } + } + } + break; + } + } + + // remove all entries - deactivate is not reliable + // The method checks if we are already disposed and in that case does nothing! + ImplClearPopupMenu( m_pToolBar ); + } + + return 1; +} + +IMPL_LINK( ToolBarManager, Select, ToolBox*, EMPTYARG ) +{ + if ( m_bDisposed ) + return 1; + + sal_Int16 nKeyModifier( (sal_Int16)m_pToolBar->GetModifier() ); + USHORT nId( m_pToolBar->GetCurItemId() ); + + ToolBarControllerMap::const_iterator pIter = m_aControllerMap.find( nId ); + if ( pIter != m_aControllerMap.end() ) + { + Reference< XToolbarController > xController( pIter->second, UNO_QUERY ); + + if ( xController.is() ) + xController->execute( nKeyModifier ); + } + + return 1; +} + +IMPL_LINK( ToolBarManager, Highlight, ToolBox*, EMPTYARG ) +{ + return 1; +} + +IMPL_LINK( ToolBarManager, Activate, ToolBox*, EMPTYARG ) +{ + return 1; +} + +IMPL_LINK( ToolBarManager, Deactivate, ToolBox*, EMPTYARG ) +{ + return 1; +} + +IMPL_LINK( ToolBarManager, StateChanged, StateChangedType*, pStateChangedType ) +{ + if ( m_bDisposed ) + return 1; + + if ( *pStateChangedType == STATE_CHANGE_CONTROLBACKGROUND ) + { + // Check if we need to get new images for normal/high contrast mode + CheckAndUpdateImages(); + } + else if ( *pStateChangedType == STATE_CHANGE_VISIBLE ) + { + if ( m_pToolBar->IsReallyVisible() ) + m_aAsyncUpdateControllersTimer.Start(); + } + else if ( *pStateChangedType == STATE_CHANGE_INITSHOW ) + { + m_aAsyncUpdateControllersTimer.Start(); + } + return 1; +} + +IMPL_LINK( ToolBarManager, DataChanged, DataChangedEvent*, pDataChangedEvent ) +{ + if ((( pDataChangedEvent->GetType() == DATACHANGED_SETTINGS ) || + ( pDataChangedEvent->GetType() == DATACHANGED_DISPLAY )) && + ( pDataChangedEvent->GetFlags() & SETTINGS_STYLE )) + { + // Check if we need to get new images for normal/high contrast mode + CheckAndUpdateImages(); + } + + for ( USHORT nPos = 0; nPos < m_pToolBar->GetItemCount(); ++nPos ) + { + const USHORT nId = m_pToolBar->GetItemId(nPos); + Window* pWindow = m_pToolBar->GetItemWindow( nId ); + if ( pWindow ) + { + const DataChangedEvent& rDCEvt( *pDataChangedEvent ); + pWindow->DataChanged( rDCEvt ); + } + } + + if ( !m_pToolBar->IsFloatingMode() && + m_pToolBar->IsVisible() ) + { + // Resize toolbar, layout manager is resize listener and will calc + // the layout automatically. + ::Size aSize( m_pToolBar->CalcWindowSizePixel() ); + m_pToolBar->SetOutputSizePixel( aSize ); + } + + return 1; +} + +IMPL_LINK( ToolBarManager, AsyncUpdateControllersHdl, Timer *, EMPTYARG ) +{ + // The guard must be in its own context as the we can get destroyed when our + // own xInterface reference get destroyed! + Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY ); + + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + return 1; + + // Request to update our controllers + m_aAsyncUpdateControllersTimer.Stop(); + UpdateControllers(); + + return 0; +} + +IMPL_STATIC_LINK_NOINSTANCE( ToolBarManager, ExecuteHdl_Impl, ExecuteInfo*, pExecuteInfo ) +{ + try + { + // Asynchronous execution as this can lead to our own destruction! + if (( pExecuteInfo->nCmd == EXEC_CMD_CLOSETOOLBAR ) && + ( pExecuteInfo->xLayoutManager.is() ) && + ( pExecuteInfo->xWindow.is() )) + { + // Use docking window close to close the toolbar. The layout manager is + // listener and will react correctly according to the context sensitive + // flag of our toolbar. + Window* pWin = VCLUnoHelper::GetWindow( pExecuteInfo->xWindow ); + DockingWindow* pDockWin = dynamic_cast< DockingWindow* >( pWin ); + if ( pDockWin ) + pDockWin->Close(); + } + else if (( pExecuteInfo->nCmd == EXEC_CMD_DOCKTOOLBAR ) && + ( pExecuteInfo->xLayoutManager.is() )) + { + ::com::sun::star::awt::Point aPoint; + aPoint.X = aPoint.Y = SAL_MAX_INT32; + pExecuteInfo->xLayoutManager->dockWindow( pExecuteInfo->aToolbarResName, + DockingArea_DOCKINGAREA_DEFAULT, + aPoint ); + } + else if (( pExecuteInfo->nCmd == EXEC_CMD_DOCKALLTOOLBARS ) && + ( pExecuteInfo->xLayoutManager.is() )) + { + pExecuteInfo->xLayoutManager->dockAllWindows( UIElementType::TOOLBAR ); + } + } + catch ( Exception& ) + { + } + + delete pExecuteInfo; + return 0; +} + +Image ToolBarManager::QueryAddonsImage( const ::rtl::OUString& aCommandURL, bool bBigImages, bool bHiContrast ) +{ + Image aImage = framework::AddonsOptions().GetImageFromURL( aCommandURL, bBigImages, bHiContrast ); + return aImage; +} + +} + + + diff --git a/framework/source/uielement/toolbarmerger.cxx b/framework/source/uielement/toolbarmerger.cxx new file mode 100644 index 000000000000..83f280cb46a7 --- /dev/null +++ b/framework/source/uielement/toolbarmerger.cxx @@ -0,0 +1,714 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + +#include <uielement/toolbarmerger.hxx> +#include <uielement/generictoolbarcontroller.hxx> +#include <helper/imageproducer.hxx> + +#include <svtools/miscopt.hxx> + +namespace framework +{ + +static const char MERGE_TOOLBAR_URL[] = "URL"; +static const sal_uInt32 MERGE_TOOLBAR_URL_LEN = 3; +static const char MERGE_TOOLBAR_TITLE[] = "Title"; +static const sal_uInt32 MERGE_TOOLBAR_TITLE_LEN = 5; +static const char MERGE_TOOLBAR_IMAGEID[] = "ImageIdentifier"; +static const sal_uInt32 MERGE_TOOLBAR_IMAGEID_LEN = 15; +static const char MERGE_TOOLBAR_CONTEXT[] = "Context"; +static const sal_uInt32 MERGE_TOOLBAR_CONTEXT_LEN = 7; +static const char MERGE_TOOLBAR_TARGET[] = "Target"; +static const sal_uInt32 MERGE_TOOLBAR_TARGET_LEN = 6; +static const char MERGE_TOOLBAR_CONTROLTYPE[] = "ControlType"; +static const char MERGE_TOOLBAR_CONTROLTYPE_LEN = 11; +static const char MERGE_TOOLBAR_WIDTH[] = "Width"; +static const char MERGE_TOOLBAR_WIDTH_LEN = 5; + +static const char MERGECOMMAND_ADDAFTER[] = "AddAfter"; +static const sal_uInt32 MERGECOMMAND_ADDAFTER_LEN = 8; +static const char MERGECOMMAND_ADDBEFORE[] = "AddBefore"; +static const sal_uInt32 MERGECOMMAND_ADDBEFORE_LEN = 9; +static const char MERGECOMMAND_REPLACE[] = "Replace"; +static const sal_uInt32 MERGECOMMAND_REPLACE_LEN = 7; +static const char MERGECOMMAND_REMOVE[] = "Remove"; +static const sal_uInt32 MERGECOMMAND_REMOVE_LEN = 6; + +static const char MERGEFALLBACK_ADDLAST[] = "AddLast"; +static const char MERGEFALLBACK_ADDLAST_LEN = 7; +static const char MERGEFALLBACK_ADDFIRST[] = "AddFirst"; +static const char MERGEFALLBACK_ADDFIRST_LEN = 8; +static const char MERGEFALLBACK_IGNORE[] = "Ignore"; +static const char MERGEFALLBACK_IGNORE_LEN = 6; + +static const char TOOLBARCONTROLLER_BUTTON[] = "Button"; +static const sal_uInt32 TOOLBARCONTROLLER_BUTTON_LEN = 6; +static const char TOOLBARCONTROLLER_COMBOBOX[] = "Combobox"; +static const sal_uInt32 TOOLBARCONTROLLER_COMBOBOX_LEN = 8; +static const char TOOLBARCONTROLLER_EDIT[] = "Editfield"; +static const sal_uInt32 TOOLBARCONTROLLER_EDIT_LEN = 9; +static const char TOOLBARCONTROLLER_SPINFIELD[] = "Spinfield"; +static const sal_uInt32 TOOLBARCONTROLLER_SPINFIELD_LEN = 9; +static const char TOOLBARCONTROLLER_IMGBUTTON[] = "ImageButton"; +static const sal_uInt32 TOOLBARCONTROLLER_IMGBUTTON_LEN = 11; +static const char TOOLBARCONTROLLER_DROPDOWNBOX[] = "Dropdownbox"; +static const sal_uInt32 TOOLBARCONTROLLER_DROPDOWNBOX_LEN = 11; +static const char TOOLBARCONTROLLER_DROPDOWNBTN[] = "DropdownButton"; +static const sal_uInt32 TOOLBARCONTROLLER_DROPDOWNBTN_LEN = 14; +static const char TOOLBARCONTROLLER_TOGGLEDDBTN[] = "ToggleDropdownButton"; +static const sal_uInt32 TOOLBARCONTROLLER_TOGGLEDDBTN_LEN = 20; + +static const char TOOLBOXITEM_SEPARATOR_STR[] = "private:separator"; +static const USHORT TOOLBOXITEM_SEPARATOR_STR_LEN = sizeof( TOOLBOXITEM_SEPARATOR_STR )-1; + +using namespace ::com::sun::star; + +/** + Check whether a module identifier is part of a context + defined by a colon separated list of module identifier. + + @param + rContext + + Describes a context string list where all contexts + are delimited by a colon. For more information about + the module identifier used as context strings see the + IDL description of com::sun::star::frame::XModuleManager + + @param + rModuleIdentifier + + A string describing a module identifier. See IDL + description of com::sun::star::frame::XModuleManager. + + @result + The result is true if the rContext is an empty string + or rModuleIdentifier is part of the context string. + +*/ +bool ToolBarMerger::IsCorrectContext( + const ::rtl::OUString& rContext, + const ::rtl::OUString& rModuleIdentifier ) +{ + return (( rContext.getLength() == 0 ) || ( rContext.indexOf( rModuleIdentifier ) >= 0 )); +} + +/** + Converts a sequence, sequence of property values to + a vector of structs. + + @param + rSequence + + Provides a sequence, sequence of property values. + + @param + rContainer + + A vector of AddonToolbarItems which will hold the + conversion from the rSequence argument. + + @result + The result is true if the sequence, sequence of property + values could be converted to a vector of structs. + +*/ +bool ToolBarMerger::ConvertSeqSeqToVector( + const uno::Sequence< uno::Sequence< beans::PropertyValue > > rSequence, + AddonToolbarItemContainer& rContainer ) +{ + sal_Int32 nLen( rSequence.getLength() ); + for ( sal_Int32 i = 0; i < nLen; i++ ) + { + AddonToolbarItem aAddonToolbarItem; + ConvertSequenceToValues( rSequence[i], + aAddonToolbarItem.aCommandURL, + aAddonToolbarItem.aLabel, + aAddonToolbarItem.aImageIdentifier, + aAddonToolbarItem.aTarget, + aAddonToolbarItem.aContext, + aAddonToolbarItem.aControlType, + aAddonToolbarItem.nWidth ); + rContainer.push_back( aAddonToolbarItem ); + } + + return true; +} + +/** + Converts a sequence of property values to single + values. + + @param + rSequence + + Provides a sequence of property values. + + @param + rCommandURL + + Contains the value of the property with + Name="CommandURL". + + @param + rLabel + + Contains the value of the property with + Name="Title" + + @param + rImageIdentifier + + Contains the value of the property with + Name="ImageIdentifier" + + @param + rTarget + + Contains the value of the property with + Name="Target" + + @param + rContext + + Contains the value of the property with + Name="Context" + + @param + rControlType + + Contains the value of the property with + Name="ControlType" + + @result + All possible mapping between sequence of property + values and the single values are done. + +*/ +void ToolBarMerger::ConvertSequenceToValues( + const uno::Sequence< beans::PropertyValue > rSequence, + ::rtl::OUString& rCommandURL, + ::rtl::OUString& rLabel, + ::rtl::OUString& rImageIdentifier, + ::rtl::OUString& rTarget, + ::rtl::OUString& rContext, + ::rtl::OUString& rControlType, + sal_uInt16& rWidth ) +{ + for ( sal_Int32 i = 0; i < rSequence.getLength(); i++ ) + { + if ( rSequence[i].Name.equalsAsciiL( MERGE_TOOLBAR_URL, MERGE_TOOLBAR_URL_LEN )) + rSequence[i].Value >>= rCommandURL; + else if ( rSequence[i].Name.equalsAsciiL( MERGE_TOOLBAR_TITLE, MERGE_TOOLBAR_TITLE_LEN )) + rSequence[i].Value >>= rLabel; + else if ( rSequence[i].Name.equalsAsciiL( MERGE_TOOLBAR_IMAGEID, MERGE_TOOLBAR_IMAGEID_LEN )) + rSequence[i].Value >>= rImageIdentifier; + else if ( rSequence[i].Name.equalsAsciiL( MERGE_TOOLBAR_CONTEXT, MERGE_TOOLBAR_CONTEXT_LEN )) + rSequence[i].Value >>= rContext; + else if ( rSequence[i].Name.equalsAsciiL( MERGE_TOOLBAR_TARGET, MERGE_TOOLBAR_TARGET_LEN )) + rSequence[i].Value >>= rTarget; + else if ( rSequence[i].Name.equalsAsciiL( MERGE_TOOLBAR_CONTROLTYPE, MERGE_TOOLBAR_CONTROLTYPE_LEN )) + rSequence[i].Value >>= rControlType; + else if ( rSequence[i].Name.equalsAsciiL( MERGE_TOOLBAR_WIDTH, MERGE_TOOLBAR_WIDTH_LEN )) + { + sal_Int32 aValue = 0; + rSequence[i].Value >>= aValue; + rWidth = sal_uInt16( aValue ); + } + } +} + +/** + Tries to find the reference point provided and delivers + position and result of the search process. + + @param + pToolbar + + Must be a valid pointer to a toolbar with items which + should be searched. + + @param + rReferencePoint + + A command URL which should be the reference point for + the coming merge operation. + + @result + Provides information about the search result, the + position of the reference point and the toolbar used. +*/ +ReferenceToolbarPathInfo ToolBarMerger::FindReferencePoint( + ToolBox* pToolbar, + const ::rtl::OUString& rReferencePoint ) +{ + ReferenceToolbarPathInfo aResult; + aResult.bResult = false; + aResult.pToolbar = pToolbar; + aResult.nPos = TOOLBOX_ITEM_NOTFOUND; + + const sal_uInt16 nSize( pToolbar->GetItemCount() ); + + for ( sal_uInt16 i = 0; i < nSize; i++ ) + { + const sal_uInt16 nItemId = pToolbar->GetItemId( i ); + if ( nItemId > 0 ) + { + const ::rtl::OUString rCmd = pToolbar->GetItemCommand( nItemId ); + if ( rCmd == rReferencePoint ) + { + aResult.bResult = true; + aResult.nPos = i; + return aResult; + } + } + } + + return aResult; +} + +/** + Processes a merge operation. + + @param + xFrame + + Must be a valid reference to a frame. + + @param + pToolbar + + A valid pointer to the toolbar where the merge + operation is applied to. + + @param + nPos + + The reference position of the toolbar item for + the merge operation. Value must be between + 0 and number of toolbar items - 1. + + @param + rItemId + + A unique item ID. + + @param + rModuleIdentifier + + The current application module context. + + @param + rMergeCommand + + A merge command. + + @param + rMergeCommandParameter. + + An optional argument for the merge command. + + @param + rItems + + Toolbar items which are associated to the merge + command. + + @result + Returns true for a successful operation otherwise + false. +*/ +bool ToolBarMerger::ProcessMergeOperation( + const uno::Reference< frame::XFrame >& xFrame, + ToolBox* pToolbar, + sal_uInt16 nPos, + sal_uInt16& rItemId, + CommandToInfoMap& rCommandMap, + const ::rtl::OUString& rModuleIdentifier, + const ::rtl::OUString& rMergeCommand, + const ::rtl::OUString& rMergeCommandParameter, + const AddonToolbarItemContainer& rItems ) +{ + if ( rMergeCommand.equalsAsciiL( MERGECOMMAND_ADDAFTER, MERGECOMMAND_ADDAFTER_LEN )) + return MergeItems( xFrame, pToolbar, nPos, 1, rItemId, rCommandMap, rModuleIdentifier, rItems ); + else if ( rMergeCommand.equalsAsciiL( MERGECOMMAND_ADDBEFORE, MERGECOMMAND_ADDBEFORE_LEN )) + return MergeItems( xFrame, pToolbar, nPos, 0, rItemId, rCommandMap, rModuleIdentifier, rItems ); + else if ( rMergeCommand.equalsAsciiL( MERGECOMMAND_REPLACE, MERGECOMMAND_REPLACE_LEN )) + return ReplaceItem( xFrame, pToolbar, nPos, rItemId, rCommandMap, rModuleIdentifier, rItems ); + else if ( rMergeCommand.equalsAsciiL( MERGECOMMAND_REMOVE, MERGECOMMAND_REMOVE_LEN )) + return RemoveItems( pToolbar, nPos, rMergeCommandParameter ); + + return false; +} + +/** + Processes a merge fallback operation. + + @param + xFrame + + Must be a valid reference to a frame. + + @param + pToolbar + + A valid pointer to the toolbar where the merge + fall back operation is applied to. + + @param + nPos + + The reference position of the toolbar item for + the merge operation. Value must be between + 0 and number of toolbar items - 1. + + @param + rItemId + + A unique item ID. + + @param + rModuleIdentifier + + The current application module context. + + @param + rMergeCommand + + A merge command. + + @param + rItems + + Toolbar items which are associated to the merge + command. + + @result + Returns true for a successful operation otherwise + false. +*/ +bool ToolBarMerger::ProcessMergeFallback( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame, + ToolBox* pToolbar, + sal_uInt16 /*nPos*/, + sal_uInt16& rItemId, + CommandToInfoMap& rCommandMap, + const ::rtl::OUString& rModuleIdentifier, + const ::rtl::OUString& rMergeCommand, + const ::rtl::OUString& rMergeFallback, + const AddonToolbarItemContainer& rItems ) +{ + if (( rMergeFallback.equalsAsciiL( MERGEFALLBACK_IGNORE, MERGEFALLBACK_IGNORE_LEN )) || + ( rMergeCommand.equalsAsciiL( MERGECOMMAND_REPLACE, MERGECOMMAND_REPLACE_LEN )) || + ( rMergeCommand.equalsAsciiL( MERGECOMMAND_REMOVE, MERGECOMMAND_REMOVE_LEN )) ) + { + return true; + } + else if (( rMergeCommand.equalsAsciiL( MERGECOMMAND_ADDBEFORE, MERGECOMMAND_ADDBEFORE_LEN )) || + ( rMergeCommand.equalsAsciiL( MERGECOMMAND_ADDAFTER, MERGECOMMAND_ADDAFTER_LEN )) ) + { + if ( rMergeFallback.equalsAsciiL( MERGEFALLBACK_ADDFIRST, MERGEFALLBACK_ADDFIRST_LEN )) + return MergeItems( xFrame, pToolbar, 0, 0, rItemId, rCommandMap, rModuleIdentifier, rItems ); + else if ( rMergeFallback.equalsAsciiL( MERGEFALLBACK_ADDLAST, MERGEFALLBACK_ADDLAST_LEN )) + return MergeItems( xFrame, pToolbar, TOOLBOX_APPEND, 0, rItemId, rCommandMap, rModuleIdentifier, rItems ); + } + + return false; +} + +/** + Merges (adds) toolbar items into an existing toolbar. + + @param + xFrame + + Must be a valid reference to a frame. + + @param + pToolbar + + A valid pointer to the toolbar where the merge + fall back operation is applied to. + + @param + nPos + + The reference position of the toolbar item for + the merge operation. Value must be between + 0 and number of toolbar items - 1. + + @param + rItemId + + A unique item ID. + + @param + rModuleIdentifier + + The current application module context. + + @param + rItems + + Toolbar items which are associated to the merge + command. + + @result + Returns true for a successful operation otherwise + false. +*/ +bool ToolBarMerger::MergeItems( + const uno::Reference< frame::XFrame >& rFrame, + ToolBox* pToolbar, + sal_uInt16 nPos, + sal_uInt16 nModIndex, + sal_uInt16& rItemId, + CommandToInfoMap& rCommandMap, + const ::rtl::OUString& rModuleIdentifier, + const AddonToolbarItemContainer& rAddonToolbarItems ) +{ + const sal_Int32 nSize( rAddonToolbarItems.size() ); + + uno::Reference< frame::XFrame > xFrame( rFrame ); + + sal_uInt16 nIndex( 0 ); + for ( sal_Int32 i = 0; i < nSize; i++ ) + { + const AddonToolbarItem& rItem = rAddonToolbarItems[i]; + if ( IsCorrectContext( rItem.aContext, rModuleIdentifier )) + { + sal_Int32 nInsPos = nPos+nModIndex+i; + if ( nInsPos > sal_Int32( pToolbar->GetItemCount() )) + nInsPos = TOOLBOX_APPEND; + + if ( rItem.aCommandURL.equalsAsciiL( TOOLBOXITEM_SEPARATOR_STR, TOOLBOXITEM_SEPARATOR_STR_LEN )) + pToolbar->InsertSeparator( sal_uInt16( nInsPos )); + else + { + ToolBarMerger::CreateToolbarItem( pToolbar, sal_uInt16( nInsPos ), rItemId, rItem ); + CommandToInfoMap::iterator pIter = rCommandMap.find( rItem.aCommandURL ); + if ( pIter == rCommandMap.end()) + { + CommandInfo aCmdInfo; + aCmdInfo.nId = rItemId; + rCommandMap.insert( CommandToInfoMap::value_type( rItem.aCommandURL, aCmdInfo )); + } + else + { + pIter->second.aIds.push_back( rItemId ); + } + } + + ++nIndex; + ++rItemId; + } + } + + return true; +} + +/** + Replaces a toolbar item with new items for an + existing toolbar. + + @param + xFrame + + Must be a valid reference to a frame. + + @param + pToolbar + + A valid pointer to the toolbar where the merge + fall back operation is applied to. + + @param + nPos + + The reference position of the toolbar item for + the merge operation. Value must be between + 0 and number of toolbar items - 1. + + @param + rItemId + + A unique item ID. + + @param + rModuleIdentifier + + The current application module context. + + @param + rItems + + Toolbar items which are associated to the merge + command. + + @result + Returns true for a successful operation otherwise + false. +*/ +bool ToolBarMerger::ReplaceItem( + const uno::Reference< frame::XFrame >& xFrame, + ToolBox* pToolbar, + sal_uInt16 nPos, + sal_uInt16& rItemId, + CommandToInfoMap& rCommandMap, + const ::rtl::OUString& rModuleIdentifier, + const AddonToolbarItemContainer& rAddonToolbarItems ) +{ + pToolbar->RemoveItem( nPos ); + return MergeItems( xFrame, pToolbar, nPos, 0, rItemId, rCommandMap, rModuleIdentifier, rAddonToolbarItems ); +} + +/** + Removes toolbar items from an existing toolbar. + + @param + pToolbar + + A valid pointer to the toolbar where the merge + fall back operation is applied to. + + @param + nPos + + The reference position of the toolbar item for + the merge operation. Value must be between + 0 and number of toolbar items - 1. + + @param + rMergeCommandParameter. + + An optional argument for the merge command. + + @result + Returns true for a successful operation otherwise + false. +*/ +bool ToolBarMerger::RemoveItems( + ToolBox* pToolbar, + sal_uInt16 nPos, + const ::rtl::OUString& rMergeCommandParameter ) +{ + sal_Int32 nCount = rMergeCommandParameter.toInt32(); + if ( nCount > 0 ) + { + for ( sal_Int32 i = 0; i < nCount; i++ ) + { + if ( nPos < pToolbar->GetItemCount() ) + pToolbar->RemoveItem( nPos ); + } + } + return true; +} + +/** + Removes toolbar items from an existing toolbar. + + @param + pToolbar + + A valid pointer to the toolbar where the merge + fall back operation is applied to. + + @param + nPos + + The reference position of the toolbar item for + the merge operation. Value must be between + 0 and number of toolbar items - 1. + + @param + rMergeCommandParameter. + + An optional argument for the merge command. + + @result + Returns true for a successful operation otherwise + false. +*/ +::cppu::OWeakObject* ToolBarMerger::CreateController( + uno::Reference< lang::XMultiServiceFactory > xSMGR, + uno::Reference< frame::XFrame > xFrame, + ToolBox* pToolbar, + const ::rtl::OUString& rCommandURL, + sal_uInt16 nId, + sal_uInt16 nWidth, + const ::rtl::OUString& rControlType ) +{ + ::cppu::OWeakObject* pResult( 0 ); + + if ( rControlType.equalsAsciiL( TOOLBARCONTROLLER_BUTTON, TOOLBARCONTROLLER_BUTTON_LEN )) + pResult = new ButtonToolbarController( xSMGR, pToolbar, rCommandURL ); + else if ( rControlType.equalsAsciiL( TOOLBARCONTROLLER_COMBOBOX, TOOLBARCONTROLLER_COMBOBOX_LEN )) + pResult = new ComboboxToolbarController( xSMGR, xFrame, pToolbar, nId, nWidth, rCommandURL ); + else if ( rControlType.equalsAsciiL( TOOLBARCONTROLLER_EDIT, TOOLBARCONTROLLER_EDIT_LEN )) + pResult = new EditToolbarController( xSMGR, xFrame, pToolbar, nId, nWidth, rCommandURL ); + else if ( rControlType.equalsAsciiL( TOOLBARCONTROLLER_SPINFIELD, TOOLBARCONTROLLER_SPINFIELD_LEN )) + pResult = new SpinfieldToolbarController( xSMGR, xFrame, pToolbar, nId, nWidth, rCommandURL ); + else if ( rControlType.equalsAsciiL( TOOLBARCONTROLLER_IMGBUTTON, TOOLBARCONTROLLER_IMGBUTTON_LEN )) + pResult = new ImageButtonToolbarController( xSMGR, xFrame, pToolbar, nId, rCommandURL ); + else if ( rControlType.equalsAsciiL( TOOLBARCONTROLLER_DROPDOWNBOX, TOOLBARCONTROLLER_DROPDOWNBOX_LEN )) + pResult = new DropdownToolbarController( xSMGR, xFrame, pToolbar, nId, nWidth, rCommandURL ); + else if ( rControlType.equalsAsciiL( TOOLBARCONTROLLER_DROPDOWNBTN, TOOLBARCONTROLLER_DROPDOWNBTN_LEN )) + pResult = new ToggleButtonToolbarController( xSMGR, xFrame, pToolbar, nId, + ToggleButtonToolbarController::STYLE_DROPDOWNBUTTON, rCommandURL ); + else if ( rControlType.equalsAsciiL( TOOLBARCONTROLLER_TOGGLEDDBTN, TOOLBARCONTROLLER_TOGGLEDDBTN_LEN )) + pResult = new ToggleButtonToolbarController( xSMGR, xFrame, pToolbar, nId, + ToggleButtonToolbarController::STYLE_TOGGLE_DROPDOWNBUTTON, rCommandURL ); + else + pResult = new GenericToolbarController( xSMGR, xFrame, pToolbar, nId, rCommandURL ); + + return pResult; +} + +void ToolBarMerger::CreateToolbarItem( ToolBox* pToolbar, sal_uInt16 nPos, sal_uInt16 nItemId, const AddonToolbarItem& rItem ) +{ + pToolbar->InsertItem( nItemId, rItem.aLabel, 0, nPos ); + pToolbar->SetItemCommand( nItemId, rItem.aCommandURL ); + pToolbar->SetQuickHelpText( nItemId, rItem.aLabel ); + pToolbar->SetItemText( nItemId, rItem.aLabel ); + pToolbar->EnableItem( nItemId, sal_True ); + pToolbar->SetItemState( nItemId, STATE_NOCHECK ); + + // Use obsolete help id to transport the width of the item + pToolbar->SetHelpId( nItemId, rItem.nWidth ); + + // Use the user data to store add-on specific data with the toolbar item + AddonsParams* pAddonParams = new AddonsParams; + pAddonParams->aImageId = rItem.aImageIdentifier; + pAddonParams->aTarget = rItem.aTarget; + pAddonParams->aControlType = rItem.aControlType; + pToolbar->SetItemData( nItemId, pAddonParams ); +} + +} // namespace framework diff --git a/framework/source/uielement/toolbarsmenucontroller.cxx b/framework/source/uielement/toolbarsmenucontroller.cxx new file mode 100644 index 000000000000..02402205bd1c --- /dev/null +++ b/framework/source/uielement/toolbarsmenucontroller.cxx @@ -0,0 +1,921 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include <uielement/toolbarsmenucontroller.hxx> + +#include <algorithm> + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <threadhelp/resetableguard.hxx> +#include "services.h" +#ifndef __FRAMEWORK_CLASSES_RESOURCE_HRC_ +#include <classes/resource.hrc> +#endif +#include <classes/fwkresid.hxx> +#include <uiconfiguration/windowstateconfiguration.hxx> +#include <helper/imageproducer.hxx> +#include <classes/sfxhelperfunctions.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/awt/XDevice.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/awt/MenuItemStyle.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/frame/XLayoutManager.hpp> +#include <com/sun/star/ui/XUIElementSettings.hpp> +#include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp> +#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp> +#include <com/sun/star/ui/UIElementType.hpp> +#include <com/sun/star/lang/DisposedException.hpp> + +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ + +#ifndef _VCL_MENU_HXX_ +#include <vcl/menu.hxx> +#endif +#include <vcl/svapp.hxx> +#include <vcl/i18nhelp.hxx> +#include <vcl/image.hxx> +#include <tools/urlobj.hxx> +#include <rtl/ustrbuf.hxx> +#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ +#include <toolkit/unohlp.hxx> +#endif +#include <vcl/window.hxx> +#include <svtools/menuoptions.hxx> +#include <unotools/cmdoptions.hxx> +#include <dispatch/uieventloghelper.hxx> +#include <rtl/logfile.hxx> + +//_________________________________________________________________________________________________________________ +// 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::frame; +using namespace ::com::sun::star::ui; + +static const char CONFIGURE_TOOLBARS_CMD[] = "ConfigureDialog"; +static const char CONFIGURE_TOOLBARS[] = ".uno:ConfigureDialog"; +static const char CMD_COLORBAR[] = ".uno:ColorControl"; +static const char CMD_HYPERLINKBAR[] = ".uno:InsertHyperlink"; +static const char CMD_FORMULABAR[] = ".uno:InsertFormula"; +static const char CMD_INPUTLINEBAR[] = ".uno:InputLineVisible"; +static const char CMD_RESTOREVISIBILITY[] = ".cmd:RestoreVisibility"; +static const char ITEM_DESCRIPTOR_RESOURCEURL[] = "ResourceURL"; +static const char ITEM_DESCRIPTOR_UINAME[] = "UIName"; +static const char STATIC_PRIVATE_TB_RESOURCE[] = "private:resource/toolbar/"; + +static const char STATIC_CMD_PART[] = ".uno:AvailableToolbars?Toolbar:string="; +static const char STATIC_INTERNAL_CMD_PART[] = ".cmd:"; + +namespace framework +{ + +typedef std::hash_map< rtl::OUString, rtl::OUString, OUStringHashCode, ::std::equal_to< ::rtl::OUString > > ToolbarHashMap; + +struct ToolBarEntry +{ + rtl::OUString aUIName; + rtl::OUString aCommand; + sal_Bool bVisible; + sal_Bool bContextSensitive; + const CollatorWrapper* pCollatorWrapper; +}; + +sal_Bool CompareToolBarEntry( const ToolBarEntry& aOne, const ToolBarEntry& aTwo ) +{ + sal_Int32 nComp = aOne.pCollatorWrapper->compareString( aOne.aUIName, aTwo.aUIName ); + + if ( nComp < 0 ) + return sal_True; + else if ( nComp > 0 ) + return sal_False; + else + return sal_False; +} + +Reference< XLayoutManager > getLayoutManagerFromFrame( const Reference< XFrame >& rFrame ) +{ + Reference< XPropertySet > xPropSet( rFrame, UNO_QUERY ); + Reference< XLayoutManager > xLayoutManager; + + try + { + xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" ))) >>= xLayoutManager; + } + catch ( UnknownPropertyException& ) + { + } + + return xLayoutManager; +} + +struct ToolBarInfo +{ + rtl::OUString aToolBarResName; + rtl::OUString aToolBarUIName; +}; + +DEFINE_XSERVICEINFO_MULTISERVICE ( ToolbarsMenuController , + OWeakObject , + SERVICENAME_POPUPMENUCONTROLLER , + IMPLEMENTATIONNAME_TOOLBARSMENUCONTROLLER + ) + +DEFINE_INIT_SERVICE ( ToolbarsMenuController, {} ) + +ToolbarsMenuController::ToolbarsMenuController( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ) : + PopupMenuControllerBase( xServiceManager ), + m_aPropUIName( RTL_CONSTASCII_USTRINGPARAM( "UIName" )), + m_aPropResourceURL( RTL_CONSTASCII_USTRINGPARAM( "ResourceURL" )), + m_bModuleIdentified( sal_False ), + m_bResetActive( sal_False ), + m_aIntlWrapper( xServiceManager, Application::GetSettings().GetLocale() ) +{ +} + +ToolbarsMenuController::~ToolbarsMenuController() +{ +} + +void ToolbarsMenuController::addCommand( + Reference< css::awt::XPopupMenu >& rPopupMenu, const rtl::OUString& rCommandURL, USHORT nHelpId, const rtl::OUString& rLabel ) +{ + USHORT nItemId = m_xPopupMenu->getItemCount()+1; + + rtl::OUString aLabel; + if ( rLabel.getLength() == 0 ) + aLabel = getUINameFromCommand( rCommandURL ); + else + aLabel = rLabel; + + rPopupMenu->insertItem( nItemId, aLabel, 0, nItemId ); + Reference< awt::XMenuExtended > xMenuExtended( m_xPopupMenu, UNO_QUERY ); + xMenuExtended->setCommand( nItemId, rCommandURL ); + + bool bInternal = ( rCommandURL.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STATIC_INTERNAL_CMD_PART ))) == 0); + if ( !bInternal ) + { + if ( !getDispatchFromCommandURL( rCommandURL ).is() ) + m_xPopupMenu->enableItem( nItemId, sal_False ); + } + + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + Image aImage; + const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); + + if ( rSettings.GetUseImagesInMenus() ) + aImage = GetImageFromURL( m_xFrame, rCommandURL, FALSE, rSettings.GetHighContrastMode() ); + + VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXPopupMenu::GetImplementation( rPopupMenu ); + if ( pPopupMenu ) + { + PopupMenu* pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu(); + if ( !!aImage ) + pVCLPopupMenu->SetItemImage( nItemId, aImage ); + pVCLPopupMenu->SetHelpId( nItemId, nHelpId ); + } + + m_aCommandVector.push_back( rCommandURL ); +} + +Reference< XDispatch > ToolbarsMenuController::getDispatchFromCommandURL( const rtl::OUString& rCommandURL ) +{ + URL aTargetURL; + Sequence<PropertyValue> aArgs; + Reference< XURLTransformer > xURLTransformer; + Reference< XFrame > xFrame; + + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + xURLTransformer = m_xURLTransformer; + xFrame = m_xFrame; + } + + aTargetURL.Complete = rCommandURL; + xURLTransformer->parseStrict( aTargetURL ); + Reference< XDispatchProvider > xDispatchProvider( xFrame, UNO_QUERY ); + if ( xDispatchProvider.is() ) + return xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 ); + else + return Reference< XDispatch >(); +} + +// private function +rtl::OUString ToolbarsMenuController::getUINameFromCommand( const rtl::OUString& rCommandURL ) +{ + rtl::OUString aLabel; + + if ( !m_bModuleIdentified ) + { + try + { + Reference< XModuleManager > xModuleManager( m_xServiceManager->createInstance( SERVICENAME_MODULEMANAGER ), UNO_QUERY_THROW ); + m_aModuleIdentifier = xModuleManager->identify( m_xFrame ); + Reference< XNameAccess > xNameAccess( m_xServiceManager->createInstance( + SERVICENAME_UICOMMANDDESCRIPTION ), + UNO_QUERY ); + xNameAccess->getByName( m_aModuleIdentifier ) >>= m_xUICommandDescription; + } + catch ( Exception& ) + { + } + } + + if ( m_xUICommandDescription.is() ) + { + try + { + Sequence< PropertyValue > aPropSeq; + rtl::OUString aStr; + if ( m_xUICommandDescription->getByName( rCommandURL ) >>= aPropSeq ) + { + for ( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ ) + { + if ( aPropSeq[i].Name.equalsAscii( "Label" )) + { + aPropSeq[i].Value >>= aStr; + break; + } + } + } + aLabel = aStr; + } + catch ( Exception& ) + { + } + } + + return aLabel; +} + +static void fillHashMap( const Sequence< Sequence< ::com::sun::star::beans::PropertyValue > >& rSeqToolBars, + ToolbarHashMap& rHashMap ) +{ + for ( sal_Int32 i = 0; i < rSeqToolBars.getLength(); i++ ) + { + rtl::OUString aResourceURL; + rtl::OUString aUIName; + const PropertyValue* pProperties = rSeqToolBars[i].getConstArray(); + for ( sal_Int32 j = 0; j < rSeqToolBars[i].getLength(); j++ ) + { + if ( pProperties[j].Name.equalsAscii( ITEM_DESCRIPTOR_RESOURCEURL) ) + pProperties[j].Value >>= aResourceURL; + else if ( pProperties[j].Name.equalsAscii( ITEM_DESCRIPTOR_UINAME) ) + pProperties[j].Value >>= aUIName; + } + + if ( aResourceURL.getLength() > 0 && + rHashMap.find( aResourceURL ) == rHashMap.end() ) + rHashMap.insert( ToolbarHashMap::value_type( aResourceURL, aUIName )); + } +} + +// private function +Sequence< Sequence< com::sun::star::beans::PropertyValue > > ToolbarsMenuController::getLayoutManagerToolbars( const Reference< ::com::sun::star::frame::XLayoutManager >& rLayoutManager ) +{ + std::vector< ToolBarInfo > aToolBarArray; + Sequence< Reference< XUIElement > > aUIElements = rLayoutManager->getElements(); + for ( sal_Int32 i = 0; i < aUIElements.getLength(); i++ ) + { + Reference< XUIElement > xUIElement( aUIElements[i] ); + Reference< XPropertySet > xPropSet( aUIElements[i], UNO_QUERY ); + if ( xPropSet.is() && xUIElement.is() ) + { + try + { + rtl::OUString aResName; + sal_Int16 nType( -1 ); + xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Type" ))) >>= nType; + xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ResourceURL" ))) >>= aResName; + + if (( nType == ::com::sun::star::ui::UIElementType::TOOLBAR ) && + ( aResName.getLength() > 0 )) + { + ToolBarInfo aToolBarInfo; + + aToolBarInfo.aToolBarResName = aResName; + + vos::OGuard aGuard( Application::GetSolarMutex() ); + Reference< css::awt::XWindow > xWindow( xUIElement->getRealInterface(), UNO_QUERY ); + Window* pWindow = VCLUnoHelper::GetWindow( xWindow ); + if ( pWindow ) + aToolBarInfo.aToolBarUIName = pWindow->GetText(); + + aToolBarArray.push_back( aToolBarInfo ); + } + } + catch ( Exception& ) + { + } + } + } + + Sequence< com::sun::star::beans::PropertyValue > aTbSeq( 2 ); + aTbSeq[0].Name = m_aPropUIName; + aTbSeq[1].Name = m_aPropResourceURL; + + Sequence< Sequence< com::sun::star::beans::PropertyValue > > aSeq( aToolBarArray.size() ); + const sal_uInt32 nCount = aToolBarArray.size(); + for ( sal_uInt32 i = 0; i < nCount; i++ ) + { + aTbSeq[0].Value <<= aToolBarArray[i].aToolBarUIName; + aTbSeq[1].Value <<= aToolBarArray[i].aToolBarResName; + aSeq[i] = aTbSeq; + } + + return aSeq; +} + +sal_Bool ToolbarsMenuController::isContextSensitiveToolbarNonVisible() +{ + return m_bResetActive; +} + +void ToolbarsMenuController::fillPopupMenu( Reference< css::awt::XPopupMenu >& rPopupMenu ) +{ + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + resetPopupMenu( rPopupMenu ); + + m_aCommandVector.clear(); + + // Retrieve layout manager for additional information + rtl::OUString aEmptyString; + Reference< awt::XMenuExtended > xMenuExtended( rPopupMenu, UNO_QUERY ); + Reference< XLayoutManager > xLayoutManager( getLayoutManagerFromFrame( m_xFrame )); + + m_bResetActive = sal_False; + if ( xLayoutManager.is() ) + { + ToolbarHashMap aToolbarHashMap; + + if ( m_xDocCfgMgr.is() ) + { + Sequence< Sequence< com::sun::star::beans::PropertyValue > > aSeqDocToolBars = + m_xDocCfgMgr->getUIElementsInfo( UIElementType::TOOLBAR ); + fillHashMap( aSeqDocToolBars, aToolbarHashMap ); + } + + if ( m_xModuleCfgMgr.is() ) + { + Sequence< Sequence< com::sun::star::beans::PropertyValue > > aSeqToolBars = + m_xModuleCfgMgr->getUIElementsInfo( UIElementType::TOOLBAR ); + fillHashMap( aSeqToolBars, aToolbarHashMap ); + } + + std::vector< ToolBarEntry > aSortedTbs; + rtl::OUString aStaticCmdPart( RTL_CONSTASCII_USTRINGPARAM( STATIC_CMD_PART )); + + Sequence< Sequence< com::sun::star::beans::PropertyValue > > aSeqFrameToolBars = getLayoutManagerToolbars( xLayoutManager ); + fillHashMap( aSeqFrameToolBars, aToolbarHashMap ); + + ToolbarHashMap::const_iterator pIter = aToolbarHashMap.begin(); + while ( pIter != aToolbarHashMap.end() ) + { + rtl::OUString aUIName = pIter->second; + sal_Bool bHideFromMenu( sal_False ); + sal_Bool bContextSensitive( sal_False ); + sal_Bool bVisible( sal_False ); + if ( aUIName.getLength() == 0 && + m_xPersistentWindowState.is() ) + { + try + { + Sequence< PropertyValue > aWindowState; + Any a( m_xPersistentWindowState->getByName( pIter->first )); + + if ( a >>= aWindowState ) + { + for ( sal_Int32 i = 0; i < aWindowState.getLength(); i++ ) + { + if ( aWindowState[i].Name.equalsAscii( WINDOWSTATE_PROPERTY_UINAME )) + aWindowState[i].Value >>= aUIName; + else if ( aWindowState[i].Name.equalsAscii( WINDOWSTATE_PROPERTY_HIDEFROMENU )) + aWindowState[i].Value >>= bHideFromMenu; + else if ( aWindowState[i].Name.equalsAscii( WINDOWSTATE_PROPERTY_CONTEXT )) + aWindowState[i].Value >>= bContextSensitive; + else if ( aWindowState[i].Name.equalsAscii( WINDOWSTATE_PROPERTY_VISIBLE )) + aWindowState[i].Value >>= bVisible; + } + } + } + catch ( Exception& ) + { + } + + // Check if we have to enable/disable "Reset" menu item + if ( bContextSensitive && !bVisible ) + m_bResetActive = sal_True; + + } + + if (( aUIName.getLength() > 0 ) && ( !bHideFromMenu )) + { + ToolBarEntry aTbEntry; + aTbEntry.aUIName = aUIName; + aTbEntry.aCommand = pIter->first; + aTbEntry.bVisible = xLayoutManager->isElementVisible( pIter->first ); + aTbEntry.bContextSensitive = bContextSensitive; + aTbEntry.pCollatorWrapper = m_aIntlWrapper.getCaseCollator(); + aSortedTbs.push_back( aTbEntry ); + } + pIter++; + } + + // sort toolbars + std::sort( aSortedTbs.begin(), aSortedTbs.end(), CompareToolBarEntry ); + + sal_Int16 nIndex( 1 ); + const sal_uInt32 nCount = aSortedTbs.size(); + for ( sal_uInt32 i = 0; i < nCount; i++ ) + { + USHORT nItemCount = m_xPopupMenu->getItemCount(); + m_xPopupMenu->insertItem( nIndex, aSortedTbs[i].aUIName, css::awt::MenuItemStyle::CHECKABLE, nItemCount ); + if ( aSortedTbs[i].bVisible ) + m_xPopupMenu->checkItem( nIndex, sal_True ); + + { + vos::OGuard aGuard( Application::GetSolarMutex() ); + VCLXPopupMenu* pXPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( m_xPopupMenu ); + PopupMenu* pVCLPopupMenu = (PopupMenu *)pXPopupMenu->GetMenu(); + + pVCLPopupMenu->SetUserValue( nIndex, ULONG( aSortedTbs[i].bContextSensitive ? 1L : 0L )); + } + + // use VCL popup menu pointer to set vital information that are not part of the awt implementation + rtl::OUStringBuffer aStrBuf( aStaticCmdPart ); + + sal_Int32 n = aSortedTbs[i].aCommand.lastIndexOf( '/' ); + if (( n > 0 ) && (( n+1 ) < aSortedTbs[i].aCommand.getLength() )) + aStrBuf.append( aSortedTbs[i].aCommand.copy( n+1 )); + + rtl::OUString aCmd( aStrBuf.makeStringAndClear() ); + + // Store complete uno-command so it can also be dispatched. This is necessary to support + // the test tool! + xMenuExtended->setCommand( nIndex, aCmd ); + ++nIndex; + } + + // Create commands for non-toolbars + if ( m_aModuleIdentifier.equalsAscii( "com.sun.star.text.TextDocument" ) || + m_aModuleIdentifier.equalsAscii( "com.sun.star.text.WebDocument" ) || + m_aModuleIdentifier.equalsAscii( "com.sun.star.text.GlobalDocument" ) || + m_aModuleIdentifier.equalsAscii( "com.sun.star.drawing.DrawingDocument" ) || + m_aModuleIdentifier.equalsAscii( "com.sun.star.presentation.PresentationDocument" ) || + m_aModuleIdentifier.equalsAscii( "com.sun.star.sheet.SpreadsheetDocument" )) + { + addCommand( m_xPopupMenu, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CMD_HYPERLINKBAR )), 10360, aEmptyString ); + if ( m_aModuleIdentifier.equalsAscii( "com.sun.star.drawing.DrawingDocument" ) || + m_aModuleIdentifier.equalsAscii( "com.sun.star.presentation.PresentationDocument" )) + addCommand( m_xPopupMenu, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CMD_COLORBAR )), 10417, aEmptyString ); + else if ( m_aModuleIdentifier.equalsAscii( "com.sun.star.sheet.SpreadsheetDocument" )) + addCommand( m_xPopupMenu, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CMD_INPUTLINEBAR )), 26241, aEmptyString ); + else + addCommand( m_xPopupMenu, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CMD_FORMULABAR )), 20128, aEmptyString ); + } + + sal_Bool bAddCommand( sal_True ); + SvtCommandOptions aCmdOptions; + rtl::OUString aConfigureToolbar( RTL_CONSTASCII_USTRINGPARAM( CONFIGURE_TOOLBARS )); + + if ( aCmdOptions.HasEntries( SvtCommandOptions::CMDOPTION_DISABLED )) + { + if ( aCmdOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED, + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CONFIGURE_TOOLBARS_CMD )))) + bAddCommand = sal_False; + } + + if ( bAddCommand ) + { + // Create command for configure + if ( m_xPopupMenu->getItemCount() > 0 ) + { + USHORT nItemCount = m_xPopupMenu->getItemCount(); + m_xPopupMenu->insertSeparator( nItemCount+1 ); + } + + addCommand( m_xPopupMenu, aConfigureToolbar, 5904, aEmptyString ); + } + + // Add separator if no configure has been added + if ( !bAddCommand ) + { + // Create command for configure + if ( m_xPopupMenu->getItemCount() > 0 ) + { + USHORT nItemCount = m_xPopupMenu->getItemCount(); + m_xPopupMenu->insertSeparator( nItemCount+1 ); + } + } + + String aLabelStr = String( FwkResId( STR_RESTORE_TOOLBARS )); + rtl::OUString aRestoreCmd( RTL_CONSTASCII_USTRINGPARAM( CMD_RESTOREVISIBILITY )); + addCommand( m_xPopupMenu, aRestoreCmd, 9999, aLabelStr ); + } +} + +// XEventListener +void SAL_CALL ToolbarsMenuController::disposing( const EventObject& ) throw ( RuntimeException ) +{ + Reference< css::awt::XMenuListener > xHolder(( OWeakObject *)this, UNO_QUERY ); + + ResetableGuard aLock( m_aLock ); + m_xFrame.clear(); + m_xDispatch.clear(); + m_xDocCfgMgr.clear(); + m_xModuleCfgMgr.clear(); + m_xServiceManager.clear(); + + if ( m_xPopupMenu.is() ) + m_xPopupMenu->removeMenuListener( Reference< css::awt::XMenuListener >(( OWeakObject *)this, UNO_QUERY )); + m_xPopupMenu.clear(); +} + +// XStatusListener +void SAL_CALL ToolbarsMenuController::statusChanged( const FeatureStateEvent& Event ) throw ( RuntimeException ) +{ + rtl::OUString aFeatureURL( Event.FeatureURL.Complete ); + + // All other status events will be processed here + sal_Bool bSetCheckmark = sal_False; + sal_Bool bCheckmark = sal_False; + + ResetableGuard aLock( m_aLock ); + Reference< css::awt::XPopupMenu > xPopupMenu( m_xPopupMenu ); + aLock.unlock(); + + if ( xPopupMenu.is() ) + { + vos::OGuard aGuard( Application::GetSolarMutex() ); + VCLXPopupMenu* pXPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( xPopupMenu ); + PopupMenu* pVCLPopupMenu = (PopupMenu *)pXPopupMenu->GetMenu(); + + for ( USHORT i = 0; i < pVCLPopupMenu->GetItemCount(); i++ ) + { + USHORT nId = pVCLPopupMenu->GetItemId( i ); + if ( nId == 0 ) + continue; + + rtl::OUString aCmd = pVCLPopupMenu->GetItemCommand( nId ); + if ( aCmd == aFeatureURL ) + { + // Enable/disable item + pVCLPopupMenu->EnableItem( nId, Event.IsEnabled ); + + // Checkmark + if ( Event.State >>= bCheckmark ) + bSetCheckmark = sal_True; + + if ( bSetCheckmark ) + pVCLPopupMenu->CheckItem( nId, bCheckmark ); + else + { + rtl::OUString aItemText; + + if ( Event.State >>= aItemText ) + pVCLPopupMenu->SetItemText( nId, aItemText ); + } + } + } + } +} + +// XMenuListener +void SAL_CALL ToolbarsMenuController::select( const css::awt::MenuEvent& rEvent ) throw (RuntimeException) +{ + Reference< css::awt::XPopupMenu > xPopupMenu; + Reference< XMultiServiceFactory > xServiceManager; + Reference< XURLTransformer > xURLTransformer; + Reference< XFrame > xFrame; + Reference< XNameAccess > xPersistentWindowState; + + ResetableGuard aLock( m_aLock ); + xPopupMenu = m_xPopupMenu; + xServiceManager = m_xServiceManager; + xURLTransformer = m_xURLTransformer; + xFrame = m_xFrame; + xPersistentWindowState = m_xPersistentWindowState; + aLock.unlock(); + + if ( xPopupMenu.is() ) + { + VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXPopupMenu::GetImplementation( xPopupMenu ); + if ( pPopupMenu ) + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + PopupMenu* pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu(); + + rtl::OUString aCmd( pVCLPopupMenu->GetItemCommand( rEvent.MenuId )); + if ( aCmd.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STATIC_INTERNAL_CMD_PART ))) == 0 ) + { + // Command to restore the visibility of all context sensitive toolbars + Reference< XNameReplace > xNameReplace( xPersistentWindowState, UNO_QUERY ); + if ( xPersistentWindowState.is() && xNameReplace.is() ) + { + try + { + Sequence< rtl::OUString > aElementNames = xPersistentWindowState->getElementNames(); + sal_Int32 nCount = aElementNames.getLength(); + bool bRefreshToolbars( false ); + + for ( sal_Int32 i = 0; i < nCount; i++ ) + { + try + { + rtl::OUString aElementName = aElementNames[i]; + Sequence< PropertyValue > aWindowState; + + if ( xPersistentWindowState->getByName( aElementName ) >>= aWindowState ) + { + sal_Bool bVisible( sal_False ); + sal_Bool bContextSensitive( sal_False ); + sal_Int32 nVisibleIndex( -1 ); + for ( sal_Int32 j = 0; j < aWindowState.getLength(); j++ ) + { + if ( aWindowState[j].Name.equalsAscii( WINDOWSTATE_PROPERTY_VISIBLE )) + { + aWindowState[j].Value >>= bVisible; + nVisibleIndex = j; + } + else if ( aWindowState[j].Name.equalsAscii( WINDOWSTATE_PROPERTY_CONTEXT )) + aWindowState[j].Value >>= bContextSensitive; + } + + if ( !bVisible && bContextSensitive && nVisibleIndex >= 0 ) + { + // Default is: Every context sensitive toolbar is visible + aWindowState[nVisibleIndex].Value <<= sal_True; + xNameReplace->replaceByName( aElementName, makeAny( aWindowState )); + bRefreshToolbars = true; + } + } + } + catch ( NoSuchElementException& ) + { + } + } + + if ( bRefreshToolbars ) + { + Reference< XLayoutManager > xLayoutManager( getLayoutManagerFromFrame( xFrame )); + if ( xLayoutManager.is() ) + { + Reference< XPropertySet > xPropSet( xLayoutManager, UNO_QUERY ); + if ( xPropSet.is() ) + { + try + { + xPropSet->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RefreshContextToolbarVisibility" )), makeAny( sal_True )); + } + catch ( RuntimeException& ) + { + } + catch ( Exception& ) + { + } + } + } + RefreshToolbars( xFrame ); + } + } + catch ( RuntimeException& ) + { + throw; + } + catch ( Exception& ) + { + } + } + } + else if ( aCmd.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STATIC_CMD_PART ))) < 0 ) + { + URL aTargetURL; + Sequence<PropertyValue> aArgs; + + aTargetURL.Complete = aCmd; + xURLTransformer->parseStrict( aTargetURL ); + Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY ); + if ( xDispatchProvider.is() ) + { + Reference< XDispatch > xDispatch = xDispatchProvider->queryDispatch( + aTargetURL, ::rtl::OUString(), 0 ); + + ExecuteInfo* pExecuteInfo = new ExecuteInfo; + pExecuteInfo->xDispatch = xDispatch; + pExecuteInfo->aTargetURL = aTargetURL; + pExecuteInfo->aArgs = aArgs; + if(::comphelper::UiEventsLogger::isEnabled()) //#i88653# + UiEventLogHelper(::rtl::OUString::createFromAscii("ToolbarsMenuController")).log(m_xServiceManager, m_xFrame, aTargetURL, aArgs); + Application::PostUserEvent( STATIC_LINK(0, ToolbarsMenuController, ExecuteHdl_Impl), pExecuteInfo ); + } + } + else + { + Reference< XLayoutManager > xLayoutManager( getLayoutManagerFromFrame( xFrame )); + if ( xLayoutManager.is() ) + { + // Extract toolbar name from the combined uno-command. + sal_Int32 nIndex = aCmd.indexOf( '=' ); + if (( nIndex > 0 ) && (( nIndex+1 ) < aCmd.getLength() )) + { + rtl::OUStringBuffer aBuf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STATIC_PRIVATE_TB_RESOURCE ))); + aBuf.append( aCmd.copy( nIndex+1 )); + + sal_Bool bShow( !pVCLPopupMenu->IsItemChecked( rEvent.MenuId )); + rtl::OUString aToolBarResName( aBuf.makeStringAndClear() ); + if ( bShow ) + { + xLayoutManager->createElement( aToolBarResName ); + xLayoutManager->showElement( aToolBarResName ); + } + else + { + // closing means: + // hide and destroy element + xLayoutManager->hideElement( aToolBarResName ); + xLayoutManager->destroyElement( aToolBarResName ); + } + } + } + } + } + } +} + +void SAL_CALL ToolbarsMenuController::activate( const css::awt::MenuEvent& ) throw (RuntimeException) +{ + std::vector< rtl::OUString > aCmdVector; + Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY ); + Reference< XURLTransformer > xURLTransformer( m_xURLTransformer ); + { + ResetableGuard aLock( m_aLock ); + fillPopupMenu( m_xPopupMenu ); + aCmdVector = m_aCommandVector; + } + + // Update status for all commands inside our toolbars popup menu + const sal_uInt32 nCount = aCmdVector.size(); + for ( sal_uInt32 i = 0; i < nCount; i++ ) + { + bool bInternal = ( aCmdVector[i].indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STATIC_INTERNAL_CMD_PART ))) == 0); + + if ( !bInternal ) + { + URL aTargetURL; + aTargetURL.Complete = aCmdVector[i]; + xURLTransformer->parseStrict( aTargetURL ); + Reference< XDispatch > xDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 ); + if ( xDispatch.is() ) + { + xDispatch->addStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL ); + xDispatch->removeStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL ); + } + } + else if ( aCmdVector[i].equalsAscii( CMD_RESTOREVISIBILITY )) + { + // Special code to determine the enable/disable state of this command + FeatureStateEvent aFeatureStateEvent; + aFeatureStateEvent.FeatureURL.Complete = aCmdVector[i]; + aFeatureStateEvent.IsEnabled = isContextSensitiveToolbarNonVisible(); + statusChanged( aFeatureStateEvent ); + } + } +} + +// XPopupMenuController +void SAL_CALL ToolbarsMenuController::setPopupMenu( const Reference< css::awt::XPopupMenu >& xPopupMenu ) throw ( RuntimeException ) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + if ( m_xFrame.is() && !m_xPopupMenu.is() ) + { + // Create popup menu on demand + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + m_xPopupMenu = xPopupMenu; + m_xPopupMenu->addMenuListener( Reference< css::awt::XMenuListener >( (OWeakObject*)this, UNO_QUERY )); + fillPopupMenu( m_xPopupMenu ); + } +} + +// XInitialization +void SAL_CALL ToolbarsMenuController::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException ) +{ + ResetableGuard aLock( m_aLock ); + sal_Bool bInitalized( m_bInitialized ); + if ( !bInitalized ) + { + PopupMenuControllerBase::initialize(aArguments); + + if ( m_bInitialized ) + { + Reference< XModuleManager > xModuleManager( m_xServiceManager->createInstance( + SERVICENAME_MODULEMANAGER ), + UNO_QUERY ); + Reference< XNameAccess > xPersistentWindowStateSupplier( m_xServiceManager->createInstance( + SERVICENAME_WINDOWSTATECONFIGURATION ), + UNO_QUERY ); + + // Retrieve persistent window state reference for our module + if ( xPersistentWindowStateSupplier.is() && xModuleManager.is() ) + { + rtl::OUString aModuleIdentifier; + try + { + aModuleIdentifier = xModuleManager->identify( m_xFrame ); + xPersistentWindowStateSupplier->getByName( aModuleIdentifier ) >>= m_xPersistentWindowState; + + Reference< XModuleUIConfigurationManagerSupplier > xModuleCfgSupplier; + if ( m_xServiceManager.is() ) + xModuleCfgSupplier = Reference< XModuleUIConfigurationManagerSupplier >( + m_xServiceManager->createInstance( SERVICENAME_MODULEUICONFIGURATIONMANAGERSUPPLIER ), UNO_QUERY ); + m_xModuleCfgMgr = xModuleCfgSupplier->getUIConfigurationManager( aModuleIdentifier ); + + Reference< XController > xController = m_xFrame->getController(); + Reference< XModel > xModel; + if ( xController.is() ) + xModel = xController->getModel(); + if ( xModel.is() ) + { + Reference< XUIConfigurationManagerSupplier > xUIConfigurationManagerSupplier( xModel, UNO_QUERY ); + if ( xUIConfigurationManagerSupplier.is() ) + m_xDocCfgMgr = xUIConfigurationManagerSupplier->getUIConfigurationManager(); + } + m_aModuleIdentifier = aModuleIdentifier; + } + catch ( Exception& ) + { + } + } + } + } +} + +IMPL_STATIC_LINK_NOINSTANCE( ToolbarsMenuController, ExecuteHdl_Impl, ExecuteInfo*, pExecuteInfo ) +{ + 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 ( Exception& ) + { + } + + delete pExecuteInfo; + return 0; +} + +} diff --git a/framework/source/uielement/toolbarwrapper.cxx b/framework/source/uielement/toolbarwrapper.cxx new file mode 100644 index 000000000000..0e73b5616aa7 --- /dev/null +++ b/framework/source/uielement/toolbarwrapper.cxx @@ -0,0 +1,352 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ + + +#include <uielement/toolbarwrapper.hxx> +#include <threadhelp/resetableguard.hxx> +#include <helper/actiontriggerhelper.hxx> +#include <uielement/constitemcontainer.hxx> +#include <uielement/rootitemcontainer.hxx> +#include <uielement/toolbarmanager.hxx> + +#ifndef __FRAMEWORK_UIELEMENT_TOOLBARW_HXX_ +#include <uielement/toolbar.hxx> +#endif + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/awt/XSystemDependentMenuPeer.hpp> +#include <com/sun/star/awt/XMenuBar.hpp> +#include <com/sun/star/container/XIndexContainer.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/ui/UIElementType.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ + +#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ +#include <toolkit/unohlp.hxx> +#endif +#include <toolkit/awt/vclxwindow.hxx> +#include <comphelper/processfactory.hxx> + +#include <svtools/miscopt.hxx> +#include <vcl/svapp.hxx> +#include <vcl/toolbox.hxx> +#include <rtl/logfile.hxx> + +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; +using namespace com::sun::star::frame; +using namespace com::sun::star::lang; +using namespace com::sun::star::container; +using namespace com::sun::star::awt; +using namespace ::com::sun::star::ui; + +namespace framework +{ + +ToolBarWrapper::ToolBarWrapper( const Reference< XMultiServiceFactory >& xServiceManager ) : + UIConfigElementWrapperBase( UIElementType::TOOLBAR,xServiceManager ) +{ +} + +ToolBarWrapper::~ToolBarWrapper() +{ +} + +// XInterface +void SAL_CALL ToolBarWrapper::acquire() throw() +{ + UIConfigElementWrapperBase::acquire(); +} + +void SAL_CALL ToolBarWrapper::release() throw() +{ + UIConfigElementWrapperBase::release(); +} + +uno::Any SAL_CALL ToolBarWrapper::queryInterface( const uno::Type & rType ) +throw( ::com::sun::star::uno::RuntimeException ) +{ + Any a = ::cppu::queryInterface( + rType , + SAL_STATIC_CAST( ::com::sun::star::ui::XUIFunctionListener*, this ) ); + + if( a.hasValue() ) + return a; + + return UIConfigElementWrapperBase::queryInterface( rType ); +} + +// XComponent +void SAL_CALL ToolBarWrapper::dispose() throw ( RuntimeException ) +{ + Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY ); + + { + ResetableGuard aLock( m_aLock ); + if ( m_bDisposed ) + return; + } + + com::sun::star::lang::EventObject aEvent( xThis ); + m_aListenerContainer.disposeAndClear( aEvent ); + + ResetableGuard aLock( m_aLock ); + + if ( m_xToolBarManager.is() ) + m_xToolBarManager->dispose(); + m_xToolBarManager.clear(); + m_xConfigSource.clear(); + m_xConfigData.clear(); + m_xToolBarWindow.clear(); + + m_bDisposed = sal_True; +} + +// XInitialization +void SAL_CALL ToolBarWrapper::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException ) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + if ( !m_bInitialized ) + { + UIConfigElementWrapperBase::initialize( aArguments ); + + sal_Bool bPopupMode( sal_False ); + for ( sal_Int32 i = 0; i < aArguments.getLength(); i++ ) + { + PropertyValue aPropValue; + if ( aArguments[i] >>= aPropValue ) + { + if ( aPropValue.Name.equalsAsciiL( "PopupMode", 9 )) + { + aPropValue.Value >>= bPopupMode; + break; + } + } + } + + Reference< XFrame > xFrame( m_xWeakFrame ); + if ( xFrame.is() && m_xConfigSource.is() ) + { + // Create VCL based toolbar which will be filled with settings data + ToolBar* pToolBar = 0; + ToolBarManager* pToolBarManager = 0; + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + Window* pWindow = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() ); + if ( pWindow ) + { + ULONG nStyles = WB_LINESPACING | WB_BORDER | WB_SCROLL | WB_MOVEABLE | WB_3DLOOK | WB_DOCKABLE | WB_SIZEABLE | WB_CLOSEABLE; + + pToolBar = new ToolBar( pWindow, nStyles ); + m_xToolBarWindow = VCLUnoHelper::GetInterface( pToolBar ); + pToolBarManager = new ToolBarManager( m_xServiceFactory, xFrame, m_aResourceURL, pToolBar ); + pToolBar->SetToolBarManager( pToolBarManager ); + m_xToolBarManager = Reference< XComponent >( static_cast< OWeakObject *>( pToolBarManager ), UNO_QUERY ); + pToolBar->WillUsePopupMode( bPopupMode ); + } + } + + try + { + m_xConfigData = m_xConfigSource->getSettings( m_aResourceURL, sal_False ); + if ( m_xConfigData.is() && pToolBar && pToolBarManager ) + { + // Fill toolbar with container contents + pToolBarManager->FillToolbar( m_xConfigData ); + pToolBar->SetOutStyle( SvtMiscOptions().GetToolboxStyle() ); + pToolBar->EnableCustomize( TRUE ); + ::Size aActSize( pToolBar->GetSizePixel() ); + ::Size aSize( pToolBar->CalcWindowSizePixel() ); + aSize.Width() = aActSize.Width(); + pToolBar->SetOutputSizePixel( aSize ); + } + } + catch ( NoSuchElementException& ) + { + // No settings in our configuration manager. This means we are + // a transient toolbar which has no persistent settings. + m_bPersistent = sal_False; + if ( pToolBar && pToolBarManager ) + { + pToolBar->SetOutStyle( SvtMiscOptions().GetToolboxStyle() ); + pToolBar->EnableCustomize( TRUE ); + ::Size aActSize( pToolBar->GetSizePixel() ); + ::Size aSize( pToolBar->CalcWindowSizePixel() ); + aSize.Width() = aActSize.Width(); + pToolBar->SetOutputSizePixel( aSize ); + } + } + } + } +} + +// XEventListener +void SAL_CALL ToolBarWrapper::disposing( const ::com::sun::star::lang::EventObject& ) throw (::com::sun::star::uno::RuntimeException) +{ + // nothing todo +} + +// XUpdatable +void SAL_CALL ToolBarWrapper::update() throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + ToolBarManager* pToolBarManager = static_cast< ToolBarManager *>( m_xToolBarManager.get() ); + if ( pToolBarManager ) + pToolBarManager->CheckAndUpdateImages(); +} + +// XUIElementSettings +void SAL_CALL ToolBarWrapper::updateSettings() throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + if ( m_xToolBarManager.is() ) + { + if ( m_xConfigSource.is() && m_bPersistent ) + { + try + { + ToolBarManager* pToolBarManager = static_cast< ToolBarManager *>( m_xToolBarManager.get() ); + + m_xConfigData = m_xConfigSource->getSettings( m_aResourceURL, sal_False ); + if ( m_xConfigData.is() ) + pToolBarManager->FillToolbar( m_xConfigData ); + } + catch ( NoSuchElementException& ) + { + } + } + else if ( !m_bPersistent ) + { + // Transient toolbar: do nothing + } + } +} + +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 ); +} + +// XUIElement interface +Reference< XInterface > SAL_CALL ToolBarWrapper::getRealInterface( ) throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_xToolBarManager.is() ) + { + ToolBarManager* pToolBarManager = static_cast< ToolBarManager *>( m_xToolBarManager.get() ); + if ( pToolBarManager ) + { + Window* pWindow = (Window *)pToolBarManager->GetToolBar(); + return Reference< XInterface >( VCLUnoHelper::GetInterface( pWindow ), UNO_QUERY ); + } + } + + return Reference< XInterface >(); +} + +//XUIFunctionExecute +void SAL_CALL ToolBarWrapper::functionExecute( + const ::rtl::OUString& aUIElementName, + const ::rtl::OUString& aCommand ) +throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aLock( m_aLock ); + + if ( m_xToolBarManager.is() ) + { + ToolBarManager* pToolBarManager = static_cast< ToolBarManager *>( m_xToolBarManager.get() ); + if ( pToolBarManager ) + pToolBarManager->notifyRegisteredControllers( aUIElementName, aCommand ); + } +} + +void SAL_CALL ToolBarWrapper::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const com::sun::star::uno::Any& aValue ) throw( com::sun::star::uno::Exception ) +{ + ResetableGuard aLock( m_aLock ); + sal_Bool bNoClose( m_bNoClose ); + aLock.unlock(); + + UIConfigElementWrapperBase::setFastPropertyValue_NoBroadcast( nHandle, aValue ); + + aLock.lock(); + + sal_Bool bNewNoClose( m_bNoClose ); + if ( m_xToolBarManager.is() && !m_bDisposed && ( bNewNoClose != bNoClose )) + { + ToolBarManager* pToolBarManager = static_cast< ToolBarManager *>( m_xToolBarManager.get() ); + if ( pToolBarManager ) + { + ToolBox* pToolBox = pToolBarManager->GetToolBar(); + if ( pToolBox ) + { + if ( bNewNoClose ) + { + pToolBox->SetStyle( pToolBox->GetStyle() & ~WB_CLOSEABLE ); + pToolBox->SetFloatStyle( pToolBox->GetFloatStyle() & ~WB_CLOSEABLE ); + } + else + { + pToolBox->SetStyle( pToolBox->GetStyle() | WB_CLOSEABLE ); + pToolBox->SetFloatStyle( pToolBox->GetFloatStyle() | WB_CLOSEABLE ); + } + } + } + } +} + +} // namespace framework + diff --git a/framework/source/uielement/uicommanddescription.cxx b/framework/source/uielement/uicommanddescription.cxx new file mode 100644 index 000000000000..fdcd08f221fd --- /dev/null +++ b/framework/source/uielement/uicommanddescription.cxx @@ -0,0 +1,793 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include "uielement/uicommanddescription.hxx" +#include <threadhelp/resetableguard.hxx> +#include "services.h" + +#include "properties.h" + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/container/XContainer.hpp> + +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ +#include <rtl/ustrbuf.hxx> +#include <cppuhelper/implbase2.hxx> +#include <unotools/configmgr.hxx> +#include <tools/string.hxx> + +#ifndef _VCL_MNEMONIC_HXX_ +#include <vcl/mnemonic.hxx> +#endif +#include <comphelper/sequence.hxx> +#include <rtl/logfile.hxx> + +//_________________________________________________________________________________________________________________ +// Defines +//_________________________________________________________________________________________________________________ +// + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::container; +using namespace ::com::sun::star::frame; + +//_________________________________________________________________________________________________________________ +// Namespace +//_________________________________________________________________________________________________________________ +// + +struct ModuleToCommands +{ + const char* pModuleId; + const char* pCommands; +}; + +static const char GENERIC_UICOMMANDS[] = "generic"; +static const char COMMANDS[] = "Commands"; +static const char CONFIGURATION_ROOT_ACCESS[] = "/org.openoffice.Office.UI."; +static const char CONFIGURATION_CMD_ELEMENT_ACCESS[] = "/UserInterface/Commands"; +static const char CONFIGURATION_POP_ELEMENT_ACCESS[] = "/UserInterface/Popups"; +static const char CONFIGURATION_PROPERTY_LABEL[] = "Label"; +static const char CONFIGURATION_PROPERTY_CONTEXT_LABEL[] = "ContextLabel"; + +// Property names of the resulting Property Set +static const char PROPSET_LABEL[] = "Label"; +static const char PROPSET_NAME[] = "Name"; +static const char PROPSET_POPUP[] = "Popup"; +static const char PROPSET_PROPERTIES[] = "Properties"; + +// Special resource URLs to retrieve additional information +static const char PRIVATE_RESOURCE_URL[] = "private:"; + +const sal_Int32 COMMAND_PROPERTY_IMAGE = 1; +const sal_Int32 COMMAND_PROPERTY_ROTATE = 2; +const sal_Int32 COMMAND_PROPERTY_MIRROR = 4; + +namespace framework +{ + +//***************************************************************************************************************** +// Configuration access class for PopupMenuControllerFactory implementation +//***************************************************************************************************************** + +class ConfigurationAccess_UICommand : // Order is neccessary for right initialization! + private ThreadHelpBase , + public ::cppu::WeakImplHelper2<XNameAccess,XContainerListener> +{ + public: + ConfigurationAccess_UICommand( const ::rtl::OUString& aModuleName, const Reference< XNameAccess >& xGenericUICommands, const Reference< XMultiServiceFactory >& rServiceManager ); + virtual ~ConfigurationAccess_UICommand(); + + // XNameAccess + virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) + throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames() + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) + throw (::com::sun::star::uno::RuntimeException); + + // XElementAccess + virtual ::com::sun::star::uno::Type SAL_CALL getElementType() + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL hasElements() + throw (::com::sun::star::uno::RuntimeException); + + // container.XContainerListener + virtual void SAL_CALL elementInserted( const ContainerEvent& aEvent ) throw(RuntimeException); + virtual void SAL_CALL elementRemoved ( const ContainerEvent& aEvent ) throw(RuntimeException); + virtual void SAL_CALL elementReplaced( const ContainerEvent& aEvent ) throw(RuntimeException); + + // lang.XEventListener + virtual void SAL_CALL disposing( const EventObject& aEvent ) throw(RuntimeException); + + protected: + struct CmdToInfoMap + { + CmdToInfoMap() : bPopup( false ), + bCommandNameCreated( false ), + nProperties( 0 ) {} + + rtl::OUString aLabel; + rtl::OUString aContextLabel; + rtl::OUString aCommandName; + bool bPopup : 1, + bCommandNameCreated : 1; + sal_Int32 nProperties; + }; + + Any getSequenceFromCache( const rtl::OUString& aCommandURL ); + Any getInfoFromCommand( const rtl::OUString& rCommandURL ); + void fillInfoFromResult( CmdToInfoMap& rCmdInfo, const rtl::OUString& aLabel ); + Any getUILabelFromCommand( const rtl::OUString& rCommandURL ); + Sequence< rtl::OUString > getAllCommands(); + sal_Bool fillCache(); + sal_Bool addGenericInfoToCache(); + void impl_fill(const Reference< XNameAccess >& _xConfigAccess,sal_Bool _bPopup, + std::vector< ::rtl::OUString >& aImageCommandVector, + std::vector< ::rtl::OUString >& aImageRotateVector, + std::vector< ::rtl::OUString >& aImageMirrorVector); + + private: + typedef ::std::hash_map< ::rtl::OUString, + CmdToInfoMap, + OUStringHashCode, + ::std::equal_to< ::rtl::OUString > > CommandToInfoCache; + + sal_Bool initializeConfigAccess(); + + rtl::OUString m_aConfigCmdAccess; + rtl::OUString m_aConfigPopupAccess; + rtl::OUString m_aPropUILabel; + rtl::OUString m_aPropUIContextLabel; + rtl::OUString m_aPropLabel; + rtl::OUString m_aPropName; + rtl::OUString m_aPropPopup; + rtl::OUString m_aPropProperties; + rtl::OUString m_aBrandName; + rtl::OUString m_aXMLFileFormatVersion; + rtl::OUString m_aVersion; + rtl::OUString m_aExtension; + rtl::OUString m_aPrivateResourceURL; + Reference< XNameAccess > m_xGenericUICommands; + Reference< XMultiServiceFactory > m_xServiceManager; + Reference< XMultiServiceFactory > m_xConfigProvider; + //Reference< XMultiServiceFactory > m_xConfigProviderPopups; + Reference< XNameAccess > m_xConfigAccess; + Reference< XNameAccess > m_xConfigAccessPopups; + Sequence< rtl::OUString > m_aCommandImageList; + Sequence< rtl::OUString > m_aCommandRotateImageList; + Sequence< rtl::OUString > m_aCommandMirrorImageList; + CommandToInfoCache m_aCmdInfoCache; + sal_Bool m_bConfigAccessInitialized; + sal_Bool m_bCacheFilled; + sal_Bool m_bGenericDataRetrieved; +}; + +//***************************************************************************************************************** +// XInterface, XTypeProvider +//***************************************************************************************************************** +ConfigurationAccess_UICommand::ConfigurationAccess_UICommand( const rtl::OUString& aModuleName, const Reference< XNameAccess >& rGenericUICommands, const Reference< XMultiServiceFactory >& rServiceManager ) : + ThreadHelpBase(), + m_aConfigCmdAccess( RTL_CONSTASCII_USTRINGPARAM( CONFIGURATION_ROOT_ACCESS )), + m_aConfigPopupAccess( RTL_CONSTASCII_USTRINGPARAM( CONFIGURATION_ROOT_ACCESS )), + m_aPropUILabel( RTL_CONSTASCII_USTRINGPARAM( CONFIGURATION_PROPERTY_LABEL )), + m_aPropUIContextLabel( RTL_CONSTASCII_USTRINGPARAM( CONFIGURATION_PROPERTY_CONTEXT_LABEL )), + m_aPropLabel( RTL_CONSTASCII_USTRINGPARAM( PROPSET_LABEL )), + m_aPropName( RTL_CONSTASCII_USTRINGPARAM( PROPSET_NAME )), + m_aPropPopup( RTL_CONSTASCII_USTRINGPARAM( PROPSET_POPUP )), + m_aPropProperties( RTL_CONSTASCII_USTRINGPARAM( PROPSET_PROPERTIES )), + m_aPrivateResourceURL( RTL_CONSTASCII_USTRINGPARAM( PRIVATE_RESOURCE_URL )), + m_xGenericUICommands( rGenericUICommands ), + m_xServiceManager( rServiceManager ), + m_bConfigAccessInitialized( sal_False ), + m_bCacheFilled( sal_False ), + m_bGenericDataRetrieved( sal_False ) +{ + // Create configuration hierachical access name + m_aConfigCmdAccess += aModuleName; + m_aConfigCmdAccess += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CONFIGURATION_CMD_ELEMENT_ACCESS )); + + m_xConfigProvider = Reference< XMultiServiceFactory >( rServiceManager->createInstance(SERVICENAME_CFGPROVIDER),UNO_QUERY ); + + m_aConfigPopupAccess += aModuleName; + m_aConfigPopupAccess += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CONFIGURATION_POP_ELEMENT_ACCESS )); + //m_xConfigProviderPopups = Reference< XMultiServiceFactory >( rServiceManager->createInstance(SERVICENAME_CFGPROVIDER),UNO_QUERY ); + + rtl::OUString aTmp; + ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTNAME ) >>= aTmp; + m_aBrandName = aTmp; +} + +ConfigurationAccess_UICommand::~ConfigurationAccess_UICommand() +{ + // SAFE + ResetableGuard aLock( m_aLock ); + Reference< XContainer > xContainer( m_xConfigAccess, UNO_QUERY ); + if ( xContainer.is() ) + xContainer->removeContainerListener( this ); + xContainer = Reference< XContainer >( m_xConfigAccessPopups, UNO_QUERY ); + if ( xContainer.is() ) + xContainer->removeContainerListener( this ); +} + +// XNameAccess +Any SAL_CALL ConfigurationAccess_UICommand::getByName( const ::rtl::OUString& rCommandURL ) +throw ( NoSuchElementException, WrappedTargetException, RuntimeException) +{ + static sal_Int32 nRequests = 0; + + ResetableGuard aLock( m_aLock ); + if ( !m_bConfigAccessInitialized ) + { + initializeConfigAccess(); + m_bConfigAccessInitialized = sal_True; + fillCache(); + } + + if ( rCommandURL.indexOf( m_aPrivateResourceURL ) == 0 ) + { + // special keys to retrieve information about a set of commands + // SAFE + addGenericInfoToCache(); + + if ( rCommandURL.equalsIgnoreAsciiCaseAscii( UICOMMANDDESCRIPTION_NAMEACCESS_COMMANDIMAGELIST )) + return makeAny( m_aCommandImageList ); + else if ( rCommandURL.equalsIgnoreAsciiCaseAscii( UICOMMANDDESCRIPTION_NAMEACCESS_COMMANDROTATEIMAGELIST )) + return makeAny( m_aCommandRotateImageList ); + else if ( rCommandURL.equalsIgnoreAsciiCaseAscii( UICOMMANDDESCRIPTION_NAMEACCESS_COMMANDMIRRORIMAGELIST )) + return makeAny( m_aCommandMirrorImageList ); + else + throw NoSuchElementException(); + } + else + { + // SAFE + ++nRequests; + Any a = getInfoFromCommand( rCommandURL ); + + if ( !a.hasValue() ) + throw NoSuchElementException(); + + return a; + } +} + +Sequence< ::rtl::OUString > SAL_CALL ConfigurationAccess_UICommand::getElementNames() +throw ( RuntimeException ) +{ + return getAllCommands(); +} + +sal_Bool SAL_CALL ConfigurationAccess_UICommand::hasByName( const ::rtl::OUString& rCommandURL ) +throw (::com::sun::star::uno::RuntimeException) +{ + return getByName( rCommandURL ).hasValue(); +} + +// XElementAccess +Type SAL_CALL ConfigurationAccess_UICommand::getElementType() +throw ( RuntimeException ) +{ + return( ::getCppuType( (const Sequence< PropertyValue >*)NULL ) ); +} + +sal_Bool SAL_CALL ConfigurationAccess_UICommand::hasElements() +throw ( RuntimeException ) +{ + // There must are global commands! + return sal_True; +} + +void ConfigurationAccess_UICommand::fillInfoFromResult( CmdToInfoMap& rCmdInfo, const rtl::OUString& aLabel ) +{ + String rStr( aLabel ); + if ( rStr.SearchAscii( "%PRODUCT" ) != STRING_NOTFOUND ) + rStr.SearchAndReplaceAllAscii( "%PRODUCTNAME", m_aBrandName ); + rCmdInfo.aLabel = ::rtl::OUString( rStr ); + rStr.EraseTrailingChars( '.' ); // Remove "..." from string + rCmdInfo.aCommandName = ::rtl::OUString( MnemonicGenerator::EraseAllMnemonicChars( rStr )); + rCmdInfo.bCommandNameCreated = sal_True; +} + +Any ConfigurationAccess_UICommand::getSequenceFromCache( const ::rtl::OUString& aCommandURL ) +{ + CommandToInfoCache::iterator pIter = m_aCmdInfoCache.find( aCommandURL ); + if ( pIter != m_aCmdInfoCache.end() ) + { + if ( !pIter->second.bCommandNameCreated ) + fillInfoFromResult( pIter->second, pIter->second.aLabel ); + + Sequence< PropertyValue > aPropSeq( 3 ); + aPropSeq[0].Name = m_aPropLabel; + aPropSeq[0].Value = pIter->second.aContextLabel.getLength() ? + makeAny( pIter->second.aContextLabel ): makeAny( pIter->second.aLabel ); + aPropSeq[1].Name = m_aPropName; + aPropSeq[1].Value <<= pIter->second.aCommandName; + aPropSeq[2].Name = m_aPropPopup; + aPropSeq[2].Value <<= pIter->second.bPopup; + return makeAny( aPropSeq ); + } + + return Any(); +} +void ConfigurationAccess_UICommand::impl_fill(const Reference< XNameAccess >& _xConfigAccess,sal_Bool _bPopup, + std::vector< ::rtl::OUString >& aImageCommandVector, + std::vector< ::rtl::OUString >& aImageRotateVector, + std::vector< ::rtl::OUString >& aImageMirrorVector) +{ + if ( _xConfigAccess.is() ) + { + Sequence< ::rtl::OUString> aNameSeq = _xConfigAccess->getElementNames(); + const sal_Int32 nCount = aNameSeq.getLength(); + for ( sal_Int32 i = 0; i < nCount; i++ ) + { + try + { + Reference< XNameAccess > xNameAccess(_xConfigAccess->getByName( aNameSeq[i] ),UNO_QUERY); + if ( xNameAccess.is() ) + { + CmdToInfoMap aCmdToInfo; + + aCmdToInfo.bPopup = _bPopup; + xNameAccess->getByName( m_aPropUILabel ) >>= aCmdToInfo.aLabel; + xNameAccess->getByName( m_aPropUIContextLabel ) >>= aCmdToInfo.aContextLabel; + xNameAccess->getByName( m_aPropProperties ) >>= aCmdToInfo.nProperties; + + m_aCmdInfoCache.insert( CommandToInfoCache::value_type( aNameSeq[i], aCmdToInfo )); + + if ( aCmdToInfo.nProperties & COMMAND_PROPERTY_IMAGE ) + aImageCommandVector.push_back( aNameSeq[i] ); + if ( aCmdToInfo.nProperties & COMMAND_PROPERTY_ROTATE ) + aImageRotateVector.push_back( aNameSeq[i] ); + if ( aCmdToInfo.nProperties & COMMAND_PROPERTY_MIRROR ) + aImageMirrorVector.push_back( aNameSeq[i] ); + } + } + catch ( com::sun::star::lang::WrappedTargetException& ) + { + } + catch ( com::sun::star::container::NoSuchElementException& ) + { + } + } + } // if ( m_xConfigAccessPopups.is() ) +} +sal_Bool ConfigurationAccess_UICommand::fillCache() +{ + RTL_LOGFILE_CONTEXT( aLog, "framework (cd100003) ::ConfigurationAccess_UICommand::fillCache" ); + + if ( m_bCacheFilled ) + return sal_True; + + std::vector< ::rtl::OUString > aImageCommandVector; + std::vector< ::rtl::OUString > aImageRotateVector; + std::vector< ::rtl::OUString > aImageMirrorVector; + + impl_fill(m_xConfigAccess,sal_False,aImageCommandVector,aImageRotateVector,aImageMirrorVector); + impl_fill(m_xConfigAccessPopups,sal_True,aImageCommandVector,aImageRotateVector,aImageMirrorVector); + // Create cached sequences for fast retrieving + m_aCommandImageList = comphelper::containerToSequence( aImageCommandVector ); + m_aCommandRotateImageList = comphelper::containerToSequence( aImageRotateVector ); + m_aCommandMirrorImageList = comphelper::containerToSequence( aImageMirrorVector ); + + m_bCacheFilled = sal_True; + + return sal_True; +} + +sal_Bool ConfigurationAccess_UICommand::addGenericInfoToCache() +{ + if ( m_xGenericUICommands.is() && !m_bGenericDataRetrieved ) + { + Sequence< rtl::OUString > aCommandNameSeq; + try + { + if ( m_xGenericUICommands->getByName( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( UICOMMANDDESCRIPTION_NAMEACCESS_COMMANDROTATEIMAGELIST ))) >>= aCommandNameSeq ) + m_aCommandRotateImageList = comphelper::concatSequences< rtl::OUString >( m_aCommandRotateImageList, aCommandNameSeq ); + } + catch ( RuntimeException& e ) + { + throw e; + } + catch ( Exception& ) + { + } + + try + { + if ( m_xGenericUICommands->getByName( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( UICOMMANDDESCRIPTION_NAMEACCESS_COMMANDMIRRORIMAGELIST ))) >>= aCommandNameSeq ) + m_aCommandMirrorImageList = comphelper::concatSequences< rtl::OUString >( m_aCommandMirrorImageList, aCommandNameSeq ); + } + catch ( RuntimeException& e ) + { + throw e; + } + catch ( Exception& ) + { + } + + m_bGenericDataRetrieved = sal_True; + } + + return sal_True; +} + +Any ConfigurationAccess_UICommand::getInfoFromCommand( const rtl::OUString& rCommandURL ) +{ + Any a; + + try + { + a = getSequenceFromCache( rCommandURL ); + if ( !a.hasValue() ) + { + // First try to ask our global commands configuration access. It also caches maybe + // we find the entry in its cache first. + if ( m_xGenericUICommands.is() ) + { + try + { + return m_xGenericUICommands->getByName( rCommandURL ); + } + catch ( com::sun::star::lang::WrappedTargetException& ) + { + } + catch ( com::sun::star::container::NoSuchElementException& ) + { + } + } + } + } + catch( com::sun::star::container::NoSuchElementException& ) + { + } + catch ( com::sun::star::lang::WrappedTargetException& ) + { + } + + return a; +} + +Sequence< rtl::OUString > ConfigurationAccess_UICommand::getAllCommands() +{ + // SAFE + ResetableGuard aLock( m_aLock ); + + if ( !m_bConfigAccessInitialized ) + { + initializeConfigAccess(); + m_bConfigAccessInitialized = sal_True; + fillCache(); + } + + if ( m_xConfigAccess.is() ) + { + Reference< XNameAccess > xNameAccess; + + try + { + Sequence< ::rtl::OUString > aNameSeq = m_xConfigAccess->getElementNames(); + + if ( m_xGenericUICommands.is() ) + { + // Create concat list of supported user interface commands of the module + Sequence< ::rtl::OUString > aGenericNameSeq = m_xGenericUICommands->getElementNames(); + sal_uInt32 nCount1 = aNameSeq.getLength(); + sal_uInt32 nCount2 = aGenericNameSeq.getLength(); + + aNameSeq.realloc( nCount1 + nCount2 ); + ::rtl::OUString* pNameSeq = aNameSeq.getArray(); + const ::rtl::OUString* pGenericSeq = aGenericNameSeq.getConstArray(); + for ( sal_uInt32 i = 0; i < nCount2; i++ ) + pNameSeq[nCount1+i] = pGenericSeq[i]; + } + + return aNameSeq; + } + catch( com::sun::star::container::NoSuchElementException& ) + { + } + catch ( com::sun::star::lang::WrappedTargetException& ) + { + } + } + + return Sequence< rtl::OUString >(); +} + +sal_Bool ConfigurationAccess_UICommand::initializeConfigAccess() +{ + Sequence< Any > aArgs( 1 ); + PropertyValue aPropValue; + + try + { + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" )); + aPropValue.Value <<= m_aConfigCmdAccess; + aArgs[0] <<= aPropValue; + + m_xConfigAccess = Reference< XNameAccess >( m_xConfigProvider->createInstanceWithArguments(SERVICENAME_CFGREADACCESS,aArgs ),UNO_QUERY ); + if ( m_xConfigAccess.is() ) + { + // Add as container listener + Reference< XContainer > xContainer( m_xConfigAccess, UNO_QUERY ); + if ( xContainer.is() ) + xContainer->addContainerListener( this ); + } + + aPropValue.Value <<= m_aConfigPopupAccess; + aArgs[0] <<= aPropValue; + m_xConfigAccessPopups = Reference< XNameAccess >( m_xConfigProvider->createInstanceWithArguments(SERVICENAME_CFGREADACCESS,aArgs ),UNO_QUERY ); + if ( m_xConfigAccessPopups.is() ) + { + // Add as container listener + Reference< XContainer > xContainer( m_xConfigAccessPopups, UNO_QUERY ); + if ( xContainer.is() ) + xContainer->addContainerListener( this ); + } + + return sal_True; + } + catch ( WrappedTargetException& ) + { + } + catch ( Exception& ) + { + } + + return sal_False; +} + +// container.XContainerListener +void SAL_CALL ConfigurationAccess_UICommand::elementInserted( const ContainerEvent& ) throw(RuntimeException) +{ + ResetableGuard aLock( m_aLock ); + m_bCacheFilled = sal_False; + fillCache(); +} + +void SAL_CALL ConfigurationAccess_UICommand::elementRemoved( const ContainerEvent& ) throw(RuntimeException) +{ + ResetableGuard aLock( m_aLock ); + m_bCacheFilled = sal_False; + fillCache(); +} + +void SAL_CALL ConfigurationAccess_UICommand::elementReplaced( const ContainerEvent& ) throw(RuntimeException) +{ + ResetableGuard aLock( m_aLock ); + m_bCacheFilled = sal_False; + fillCache(); +} + +// lang.XEventListener +void SAL_CALL ConfigurationAccess_UICommand::disposing( const EventObject& aEvent ) throw(RuntimeException) +{ + // SAFE + // remove our reference to the config access + ResetableGuard aLock( m_aLock ); + + Reference< XInterface > xIfac1( aEvent.Source, UNO_QUERY ); + Reference< XInterface > xIfac2( m_xConfigAccess, UNO_QUERY ); + if ( xIfac1 == xIfac2 ) + m_xConfigAccess.clear(); + else + { + xIfac2 = Reference< XInterface >( m_xConfigAccessPopups, UNO_QUERY ); + if ( xIfac1 == xIfac2 ) + m_xConfigAccessPopups.clear(); + } +} + +//***************************************************************************************************************** +// XInterface, XTypeProvider, XServiceInfo +//***************************************************************************************************************** +DEFINE_XSERVICEINFO_ONEINSTANCESERVICE ( UICommandDescription , + ::cppu::OWeakObject , + SERVICENAME_UICOMMANDDESCRIPTION , + IMPLEMENTATIONNAME_UICOMMANDDESCRIPTION + ) + +DEFINE_INIT_SERVICE ( UICommandDescription, {} ) + +UICommandDescription::UICommandDescription( const Reference< XMultiServiceFactory >& xServiceManager ) : + ThreadHelpBase(), + m_aPrivateResourceURL( RTL_CONSTASCII_USTRINGPARAM( PRIVATE_RESOURCE_URL )), + m_xServiceManager( xServiceManager ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UICommandDescription::UICommandDescription" ); + Reference< XNameAccess > xEmpty; + rtl::OUString aGenericUICommand( ::rtl::OUString::createFromAscii( "GenericCommands" )); + m_xGenericUICommands = new ConfigurationAccess_UICommand( aGenericUICommand, xEmpty, xServiceManager ); + + impl_fillElements("ooSetupFactoryCommandConfigRef"); + + // insert generic commands + UICommandsHashMap::iterator pIter = m_aUICommandsHashMap.find( aGenericUICommand ); + if ( pIter != m_aUICommandsHashMap.end() ) + pIter->second = m_xGenericUICommands; +} +UICommandDescription::UICommandDescription( const Reference< XMultiServiceFactory >& xServiceManager,bool ) : + ThreadHelpBase(), + m_xServiceManager( xServiceManager ) +{ +} +UICommandDescription::~UICommandDescription() +{ + ResetableGuard aLock( m_aLock ); + m_aModuleToCommandFileMap.clear(); + m_aUICommandsHashMap.clear(); + m_xGenericUICommands.clear(); +} +void UICommandDescription::impl_fillElements(const sal_Char* _pName) +{ + m_xModuleManager.set( m_xServiceManager->createInstance( SERVICENAME_MODULEMANAGER ),UNO_QUERY ); + Reference< XNameAccess > xNameAccess( m_xModuleManager, UNO_QUERY_THROW ); + Sequence< rtl::OUString > aElementNames = xNameAccess->getElementNames(); + Sequence< PropertyValue > aSeq; + ::rtl::OUString aModuleIdentifier; + + for ( sal_Int32 i = 0; i < aElementNames.getLength(); i++ ) + { + aModuleIdentifier = aElementNames[i]; + if ( xNameAccess->getByName( aModuleIdentifier ) >>= aSeq ) + { + ::rtl::OUString aCommandStr; + for ( sal_Int32 y = 0; y < aSeq.getLength(); y++ ) + { + if ( aSeq[y].Name.equalsAscii(_pName) ) + { + aSeq[y].Value >>= aCommandStr; + break; + } + } + + // Create first mapping ModuleIdentifier ==> Command File + m_aModuleToCommandFileMap.insert( ModuleToCommandFileMap::value_type( aModuleIdentifier, aCommandStr )); + + // Create second mapping Command File ==> commands instance + UICommandsHashMap::iterator pIter = m_aUICommandsHashMap.find( aCommandStr ); + if ( pIter == m_aUICommandsHashMap.end() ) + m_aUICommandsHashMap.insert( UICommandsHashMap::value_type( aCommandStr, Reference< XNameAccess >() )); + } + } // for ( sal_Int32 i = 0; i < aElementNames.getLength(); i++ ) +} +Reference< XNameAccess > UICommandDescription::impl_createConfigAccess(const ::rtl::OUString& _sName) +{ + return new ConfigurationAccess_UICommand( _sName,m_xGenericUICommands,m_xServiceManager ); +} + +Any SAL_CALL UICommandDescription::getByName( const ::rtl::OUString& aName ) +throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UICommandDescription::getByName" ); + Any a; + + ResetableGuard aLock( m_aLock ); + + ModuleToCommandFileMap::const_iterator pM2CIter = m_aModuleToCommandFileMap.find( aName ); + if ( pM2CIter != m_aModuleToCommandFileMap.end() ) + { + ::rtl::OUString aCommandFile( pM2CIter->second ); + UICommandsHashMap::iterator pIter = m_aUICommandsHashMap.find( aCommandFile ); + if ( pIter != m_aUICommandsHashMap.end() ) + { + if ( pIter->second.is() ) + a <<= pIter->second; + else + { + Reference< XNameAccess > xUICommands; + ConfigurationAccess_UICommand* pUICommands = new ConfigurationAccess_UICommand( aCommandFile, + m_xGenericUICommands, + m_xServiceManager ); + xUICommands = Reference< XNameAccess >( static_cast< cppu::OWeakObject* >( pUICommands ),UNO_QUERY ); + pIter->second = xUICommands; + a <<= xUICommands; + } + } + } + else if ( m_aPrivateResourceURL.getLength() && aName.indexOf( m_aPrivateResourceURL ) == 0 ) + { + // special keys to retrieve information about a set of commands + return m_xGenericUICommands->getByName( aName ); + } + else + { + throw NoSuchElementException(); + } + + return a; +} + +Sequence< ::rtl::OUString > SAL_CALL UICommandDescription::getElementNames() +throw (::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UICommandDescription::getElementNames" ); + ResetableGuard aLock( m_aLock ); + + Sequence< rtl::OUString > aSeq( m_aModuleToCommandFileMap.size() ); + + sal_Int32 n = 0; + ModuleToCommandFileMap::const_iterator pIter = m_aModuleToCommandFileMap.begin(); + while ( pIter != m_aModuleToCommandFileMap.end() ) + { + aSeq[n] = pIter->first; + ++pIter; + } + + return aSeq; +} + +sal_Bool SAL_CALL UICommandDescription::hasByName( const ::rtl::OUString& aName ) +throw (::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UICommandDescription::hasByName" ); + ResetableGuard aLock( m_aLock ); + + ModuleToCommandFileMap::const_iterator pIter = m_aModuleToCommandFileMap.find( aName ); + return ( pIter != m_aModuleToCommandFileMap.end() ); +} + +// XElementAccess +Type SAL_CALL UICommandDescription::getElementType() +throw (::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UICommandDescription::getElementType" ); + return( ::getCppuType( (const Reference< XNameAccess >*)NULL ) ); +} + +sal_Bool SAL_CALL UICommandDescription::hasElements() +throw (::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UICommandDescription::hasElements" ); + // generic UI commands are always available! + return sal_True; +} + +} // namespace framework + |