| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the 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 |