diff options
Diffstat (limited to 'framework/source/dispatch/popupmenudispatcher.cxx')
-rw-r--r-- | framework/source/dispatch/popupmenudispatcher.cxx | 421 |
1 files changed, 421 insertions, 0 deletions
diff --git a/framework/source/dispatch/popupmenudispatcher.cxx b/framework/source/dispatch/popupmenudispatcher.cxx new file mode 100644 index 000000000000..8437b82961ea --- /dev/null +++ b/framework/source/dispatch/popupmenudispatcher.cxx @@ -0,0 +1,421 @@ +/************************************************************************* + * + * 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 <dispatch/popupmenudispatcher.hxx> +#include <general.h> +#include <framework/menuconfiguration.hxx> +#include <framework/addonmenu.hxx> +#include <services.h> +#include <properties.h> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#include <com/sun/star/awt/XToolkit.hpp> +#include <com/sun/star/awt/WindowAttribute.hpp> +#include <com/sun/star/awt/WindowDescriptor.hpp> +#include <com/sun/star/awt/PosSize.hpp> +#include <com/sun/star/awt/XWindowPeer.hpp> +#include <com/sun/star/beans/UnknownPropertyException.hpp> +#include <com/sun/star/lang/WrappedTargetException.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XEnumeration.hpp> + +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ + +#include <ucbhelper/content.hxx> +#include <vos/mutex.hxx> +#include <rtl/ustrbuf.hxx> +#include <vcl/svapp.hxx> + +//_________________________________________________________________________________________________________________ +// namespace +//_________________________________________________________________________________________________________________ + +namespace framework{ + +using namespace ::com::sun::star ; +using namespace ::com::sun::star::awt ; +using namespace ::com::sun::star::beans ; +using namespace ::com::sun::star::container ; +using namespace ::com::sun::star::frame ; +using namespace ::com::sun::star::lang ; +using namespace ::com::sun::star::uno ; +using namespace ::com::sun::star::util ; +using namespace ::cppu ; +using namespace ::osl ; +using namespace ::rtl ; +using namespace ::vos ; + +//_________________________________________________________________________________________________________________ +// non exported const +//_________________________________________________________________________________________________________________ +const char* PROTOCOL_VALUE = "vnd.sun.star.popup:"; +const sal_Int32 PROTOCOL_LENGTH = 19; + +//_________________________________________________________________________________________________________________ +// non exported definitions +//_________________________________________________________________________________________________________________ + +//_________________________________________________________________________________________________________________ +// declarations +//_________________________________________________________________________________________________________________ + +//***************************************************************************************************************** +// constructor +//***************************************************************************************************************** +PopupMenuDispatcher::PopupMenuDispatcher( + const uno::Reference< XMultiServiceFactory >& xFactory ) + // Init baseclasses first + : ThreadHelpBase ( &Application::GetSolarMutex() ) + , OWeakObject ( ) + // Init member + , m_xFactory ( xFactory ) + , m_aListenerContainer ( m_aLock.getShareableOslMutex() ) + , m_bAlreadyDisposed ( sal_False ) + , m_bActivateListener ( sal_False ) +{ +} + +//***************************************************************************************************************** +// destructor +//***************************************************************************************************************** +PopupMenuDispatcher::~PopupMenuDispatcher() +{ + // Warn programmer if he forgot to dispose this instance. + // We must release all our references ... + // and a dtor isn't the best place to do that! +} + +//***************************************************************************************************************** +// XInterface, XTypeProvider +//***************************************************************************************************************** +DEFINE_XINTERFACE_7 ( PopupMenuDispatcher , + ::cppu::OWeakObject , + DIRECT_INTERFACE( XTypeProvider ), + DIRECT_INTERFACE( XServiceInfo ), + DIRECT_INTERFACE( XDispatchProvider ), + DIRECT_INTERFACE( XDispatch ), + DIRECT_INTERFACE( XEventListener ), + DIRECT_INTERFACE( XInitialization ), + DERIVED_INTERFACE( XFrameActionListener, XEventListener ) + ) + +DEFINE_XTYPEPROVIDER_7 ( PopupMenuDispatcher , + XTypeProvider , + XServiceInfo , + XDispatchProvider , + XDispatch , + XEventListener , + XInitialization , + XFrameActionListener + ) + +DEFINE_XSERVICEINFO_MULTISERVICE( PopupMenuDispatcher , + ::cppu::OWeakObject , + SERVICENAME_PROTOCOLHANDLER , + IMPLEMENTATIONNAME_POPUPMENUDISPATCHER ) + +DEFINE_INIT_SERVICE(PopupMenuDispatcher, +{ + /*Attention + I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance() + to create a new instance of this class by our own supported service factory. + see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations! + */ +} +) + +//***************************************************************************************************************** +// XInitialization +//***************************************************************************************************************** +void SAL_CALL PopupMenuDispatcher::initialize( + const css::uno::Sequence< css::uno::Any >& lArguments ) +throw( css::uno::Exception, css::uno::RuntimeException) +{ + css::uno::Reference< css::frame::XFrame > xFrame; + + /* SAFE { */ + WriteGuard aWriteLock(m_aLock); + + for (int a=0; a<lArguments.getLength(); ++a) + { + if (a==0) + { + lArguments[a] >>= xFrame; + m_xWeakFrame = xFrame; + + m_bActivateListener = sal_True; + uno::Reference< css::frame::XFrameActionListener > xFrameActionListener( + (OWeakObject *)this, css::uno::UNO_QUERY ); + xFrame->addFrameActionListener( xFrameActionListener ); + } + } + + aWriteLock.unlock(); + /* } SAFE */ +} + +//***************************************************************************************************************** +// XDispatchProvider +//***************************************************************************************************************** +css::uno::Reference< css::frame::XDispatch > +SAL_CALL PopupMenuDispatcher::queryDispatch( + const css::util::URL& rURL , + const ::rtl::OUString& sTarget , + sal_Int32 nFlags ) +throw( css::uno::RuntimeException ) +{ + css::uno::Reference< css::frame::XDispatch > xDispatch; + + if ( rURL.Complete.compareToAscii( PROTOCOL_VALUE, PROTOCOL_LENGTH ) == 0 ) + { + // --- SAFE --- + ResetableGuard aGuard( m_aLock ); + impl_RetrievePopupControllerQuery(); + impl_CreateUriRefFactory(); + + css::uno::Reference< css::container::XNameAccess > xPopupCtrlQuery( m_xPopupCtrlQuery ); + css::uno::Reference< css::uri::XUriReferenceFactory > xUriRefFactory( m_xUriRefFactory ); + aGuard.unlock(); + // --- SAFE --- + + if ( xPopupCtrlQuery.is() ) + { + try + { + // Just use the main part of the URL for popup menu controllers + sal_Int32 nQueryPart( 0 ); + sal_Int32 nSchemePart( 0 ); + rtl::OUString aBaseURL( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.popup:" )); + rtl::OUString aURL( rURL.Complete ); + + nSchemePart = aURL.indexOf( ':' ); + if (( nSchemePart > 0 ) && + ( aURL.getLength() > ( nSchemePart+1 ))) + { + nQueryPart = aURL.indexOf( '?', nSchemePart ); + if ( nQueryPart > 0 ) + aBaseURL += aURL.copy( nSchemePart+1, nQueryPart-(nSchemePart+1) ); + else if ( nQueryPart == -1 ) + aBaseURL += aURL.copy( nSchemePart+1 ); + } + + css::uno::Reference< css::frame::XDispatchProvider > xDispatchProvider; + + // Find popup menu controller using the base URL + xPopupCtrlQuery->getByName( aBaseURL ) >>= xDispatchProvider; + aGuard.unlock(); + + // Ask popup menu dispatch provider for dispatch object + if ( xDispatchProvider.is() ) + xDispatch = xDispatchProvider->queryDispatch( rURL, sTarget, nFlags ); + } + catch ( RuntimeException& ) + { + throw; + } + catch ( Exception& ) + { + } + } + } + return xDispatch; +} + +css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL +PopupMenuDispatcher::queryDispatches( + const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor ) +throw( css::uno::RuntimeException ) +{ + sal_Int32 nCount = lDescriptor.getLength(); + css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatcher( nCount ); + for( sal_Int32 i=0; i<nCount; ++i ) + { + lDispatcher[i] = this->queryDispatch( + lDescriptor[i].FeatureURL, + lDescriptor[i].FrameName, + lDescriptor[i].SearchFlags); + } + return lDispatcher; +} + +//***************************************************************************************************************** +// XDispatch +//***************************************************************************************************************** +void +SAL_CALL PopupMenuDispatcher::dispatch( + const URL& /*aURL*/ , + const Sequence< PropertyValue >& /*seqProperties*/ ) +throw( RuntimeException ) +{ +} + +//***************************************************************************************************************** +// XDispatch +//***************************************************************************************************************** +void +SAL_CALL PopupMenuDispatcher::addStatusListener( + const uno::Reference< XStatusListener >& xControl, + const URL& aURL ) +throw( RuntimeException ) +{ + // Ready for multithreading + ResetableGuard aGuard( m_aLock ); + // Safe impossible cases + // Add listener to container. + m_aListenerContainer.addInterface( aURL.Complete, xControl ); +} + +//***************************************************************************************************************** +// XDispatch +//***************************************************************************************************************** +void +SAL_CALL PopupMenuDispatcher::removeStatusListener( + const uno::Reference< XStatusListener >& xControl, + const URL& aURL ) +throw( RuntimeException ) +{ + // Ready for multithreading + ResetableGuard aGuard( m_aLock ); + // Safe impossible cases + // Add listener to container. + m_aListenerContainer.removeInterface( aURL.Complete, xControl ); +} + +//***************************************************************************************************************** +// XFrameActionListener +//***************************************************************************************************************** + +void +SAL_CALL PopupMenuDispatcher::frameAction( + const FrameActionEvent& aEvent ) +throw ( RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + if (( aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING ) || + ( aEvent.Action == css::frame::FrameAction_COMPONENT_ATTACHED )) + { + // Reset query reference to requery it again next time + m_xPopupCtrlQuery.clear(); + } +} + +//***************************************************************************************************************** +// XEventListener +//***************************************************************************************************************** +void +SAL_CALL PopupMenuDispatcher::disposing( const EventObject& ) throw( RuntimeException ) +{ + // Ready for multithreading + ResetableGuard aGuard( m_aLock ); + // Safe impossible cases + LOG_ASSERT( !(m_bAlreadyDisposed==sal_True), "MenuDispatcher::disposing()\nObject already disposed .. don't call it again!\n" ) + + if( m_bAlreadyDisposed == sal_False ) + { + m_bAlreadyDisposed = sal_True; + + if ( m_bActivateListener ) + { + uno::Reference< XFrame > xFrame( m_xWeakFrame.get(), UNO_QUERY ); + if ( xFrame.is() ) + { + xFrame->removeFrameActionListener( uno::Reference< XFrameActionListener >( (OWeakObject *)this, UNO_QUERY )); + m_bActivateListener = sal_False; + } + } + + // Forget our factory. + m_xFactory = uno::Reference< XMultiServiceFactory >(); + } +} + +void PopupMenuDispatcher::impl_RetrievePopupControllerQuery() +{ + if ( !m_xPopupCtrlQuery.is() ) + { + css::uno::Reference< css::frame::XLayoutManager > xLayoutManager; + css::uno::Reference< css::frame::XFrame > xFrame( m_xWeakFrame ); + + if ( xFrame.is() ) + { + css::uno::Reference< css::beans::XPropertySet > xPropSet( xFrame, css::uno::UNO_QUERY ); + if ( xPropSet.is() ) + { + try + { + xPropSet->getPropertyValue( FRAME_PROPNAME_LAYOUTMANAGER ) >>= xLayoutManager; + + if ( xLayoutManager.is() ) + { + css::uno::Reference< css::ui::XUIElement > xMenuBar; + rtl::OUString aMenuBar( RTL_CONSTASCII_USTRINGPARAM( "private:resource/menubar/menubar" )); + xMenuBar = xLayoutManager->getElement( aMenuBar ); + + m_xPopupCtrlQuery = css::uno::Reference< css::container::XNameAccess >( + xMenuBar, css::uno::UNO_QUERY ); + } + } + catch ( css::uno::RuntimeException& ) + { + throw; + } + catch ( css::uno::Exception& ) + { + } + } + } + } +} + +void PopupMenuDispatcher::impl_CreateUriRefFactory() +{ + if ( !m_xUriRefFactory.is() ) + { + rtl::OUString aUriRefFactoryService( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.uri.UriReferenceFactory" )); + + m_xUriRefFactory = css::uno::Reference< css::uri::XUriReferenceFactory >( + m_xFactory->createInstance( aUriRefFactoryService ), + css::uno::UNO_QUERY); + + } +} + +} // namespace framework |