Tag: cws_dev300_dba30d User: fs Date: 2008-06-01 20:58:34+0000 Modified: dba/dbaccess/source/ui/control/dbtreelistbox.cxx
Log: #i80943# use the IContextMenuProvider for context menu interception File Changes: Directory: /dba/dbaccess/source/ui/control/ =========================================== File [changed]: dbtreelistbox.cxx Url: http://dba.openoffice.org/source/browse/dba/dbaccess/source/ui/control/dbtreelistbox.cxx?r1=1.19.30.1&r2=1.19.30.2 Delta lines: +169 -6 --------------------- --- dbtreelistbox.cxx 2008-05-29 11:27:40+0000 1.19.30.1 +++ dbtreelistbox.cxx 2008-06-01 20:58:31+0000 1.19.30.2 @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: dbtreelistbox.cxx,v $ - * $Revision: 1.19.30.1 $ + * $Revision: 1.19.30.2 $ * * This file is part of OpenOffice.org. * @@ -53,12 +53,18 @@ #ifndef _COM_SUN_STAR_DATATRANSFER_DND_XDRAGGESTURERECOGNIZER_HPP_ #include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp> #endif +#ifndef _COM_SUN_STAR_UI_XCONTEXTMENUINTERCEPTOR_HPP_ +#include <com/sun/star/ui/XContextMenuInterceptor.hpp> +#endif #ifndef _COM_SUN_STAR_UTIL_URL_HPP_ #include <com/sun/star/util/URL.hpp> #endif #ifndef _CPPUHELPER_IMPLBASE1_HXX_ #include <cppuhelper/implbase1.hxx> #endif +#ifndef _CPPUHELPER_INTERFACECONTAINER_HXX_ +#include <cppuhelper/interfacecontainer.hxx> +#endif #ifndef _SV_HELP_HXX #include <vcl/help.hxx> #endif @@ -68,8 +74,14 @@ #ifndef DBAUI_ICONTROLLER_HXX #include "IController.hxx" #endif -#include <memory> +#ifndef __FRAMEWORK_HELPER_ACTIONTRIGGERHELPER_HXX_ +#include <framework/actiontriggerhelper.hxx> +#endif +#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ +#include <toolkit/helper/vclunohelper.hxx> +#endif +#include <memory> // ......................................................................... namespace dbaui @@ -80,6 +92,9 @@ using namespace ::com::sun::star::beans; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::datatransfer; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::ui; +using namespace ::com::sun::star::view; DBG_NAME(DBTreeListBox) #define SPACEBETWEENENTRIES 4 @@ -540,15 +555,163 @@ } // ----------------------------------------------------------------------------- +namespace +{ + void lcl_adjustMenuItemIDs( Menu& _rMenu, IController& _rCommandController ) + { + USHORT nCount = _rMenu.GetItemCount(); + for ( USHORT pos = 0; pos < nCount; ++pos ) + { + USHORT nId = _rMenu.GetItemId(pos); + String aCommand = _rMenu.GetItemCommand( nId ); + PopupMenu* pPopup = _rMenu.GetPopupMenu( nId ); + if ( pPopup ) + { + lcl_adjustMenuItemIDs( *pPopup, _rCommandController ); + continue; + } + + USHORT nCommandId = _rCommandController.registerCommandURL( aCommand ); + _rMenu.InsertItem( nCommandId, _rMenu.GetItemText( nId ), _rMenu.GetItemBits( nId ), pos ); + _rMenu.RemoveItem( pos+1 ); + } + } + // ========================================================================= + // = SelectionSupplier + // ========================================================================= + typedef ::cppu::WeakImplHelper1 < XSelectionSupplier + > SelectionSupplier_Base; + class SelectionSupplier : public SelectionSupplier_Base + { + public: + SelectionSupplier( const Any& _rSelection ) + :m_aSelection( _rSelection ) + { + } + + virtual ::sal_Bool SAL_CALL select( const Any& xSelection ) throw (IllegalArgumentException, RuntimeException); + virtual Any SAL_CALL getSelection( ) throw (RuntimeException); + virtual void SAL_CALL addSelectionChangeListener( const Reference< XSelectionChangeListener >& xListener ) throw (RuntimeException); + virtual void SAL_CALL removeSelectionChangeListener( const Reference< XSelectionChangeListener >& xListener ) throw (RuntimeException); + + protected: + virtual ~SelectionSupplier() + { + } + + private: + Any m_aSelection; + }; + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL SelectionSupplier::select( const Any& /*_Selection*/ ) throw (IllegalArgumentException, RuntimeException) + { + throw IllegalArgumentException(); + // API bug: this should be a NoSupportException + } + + //-------------------------------------------------------------------- + Any SAL_CALL SelectionSupplier::getSelection( ) throw (RuntimeException) + { + return m_aSelection; + } + + //-------------------------------------------------------------------- + void SAL_CALL SelectionSupplier::addSelectionChangeListener( const Reference< XSelectionChangeListener >& /*_Listener*/ ) throw (RuntimeException) + { + OSL_ENSURE( false, "SelectionSupplier::removeSelectionChangeListener: no support!" ); + // API bug: this should be a NoSupportException + } + + //-------------------------------------------------------------------- + void SAL_CALL SelectionSupplier::removeSelectionChangeListener( const Reference< XSelectionChangeListener >& /*_Listener*/ ) throw (RuntimeException) + { + OSL_ENSURE( false, "SelectionSupplier::removeSelectionChangeListener: no support!" ); + // API bug: this should be a NoSupportException + } +} + +// ----------------------------------------------------------------------------- PopupMenu* DBTreeListBox::CreateContextMenu( void ) { - PopupMenu* pContextMenu = NULL; + ::std::auto_ptr< PopupMenu > pContextMenu; + if ( m_pContextMenuProvider ) { - pContextMenu = m_pContextMenuProvider->getContextMenu( *this ); - lcl_enableEntries( pContextMenu, m_pContextMenuProvider->getCommandController() ); + // the basic context menu + pContextMenu.reset( m_pContextMenuProvider->getContextMenu( *this ) ); + // disable what is not available currently + lcl_enableEntries( pContextMenu.get(), m_pContextMenuProvider->getCommandController() ); + // allow context menu interception + ::cppu::OInterfaceContainerHelper* pInterceptors = m_pContextMenuProvider->getContextMenuInterceptors(); + if ( pInterceptors ) + { + ContextMenuExecuteEvent aEvent; + aEvent.SourceWindow = VCLUnoHelper::GetInterface( this ); + // TODO: obtain this from the base class + aEvent.ExecutePosition.X = -1; + aEvent.ExecutePosition.Y = -1; + aEvent.ActionTriggerContainer = ::framework::ActionTriggerHelper::CreateActionTriggerContainerFromMenu( + m_xORB, pContextMenu.get() ); + aEvent.Selection = new SelectionSupplier( m_pContextMenuProvider->getCurrentSelection( *this ) ); + + ::cppu::OInterfaceIteratorHelper aIter( *pInterceptors ); + bool bModifiedMenu = false; + bool bAskInterceptors = true; + while ( aIter.hasMoreElements() && bAskInterceptors ) + { + Reference< XContextMenuInterceptor > xInterceptor( aIter.next(), UNO_QUERY ); + if ( !xInterceptor.is() ) + continue; + + try + { + ContextMenuInterceptorAction eAction = xInterceptor->notifyContextMenuExecute( aEvent ); + switch ( eAction ) + { + case ContextMenuInterceptorAction_CANCELLED: + return NULL; + + case ContextMenuInterceptorAction_EXECUTE_MODIFIED: + bModifiedMenu = true; + bAskInterceptors = false; + break; + + case ContextMenuInterceptorAction_CONTINUE_MODIFIED: + bModifiedMenu = true; + bAskInterceptors = true; + break; + + default: + DBG_ERROR( "DBTreeListBox::CreateContextMenu: unexpected return value of the interceptor call!" ); + + case ContextMenuInterceptorAction_IGNORED: + break; + } + } + catch( const DisposedException& e ) + { + if ( e.Context == xInterceptor ) + aIter.remove(); + } + } + + if ( bModifiedMenu ) + { + // the interceptor(s) modified the menu description => create a new PopupMenu + PopupMenu* pModifiedMenu = new PopupMenu; + ::framework::ActionTriggerHelper::CreateMenuFromActionTriggerContainer( + pModifiedMenu, aEvent.ActionTriggerContainer ); + aEvent.ActionTriggerContainer.clear(); + pContextMenu.reset( pModifiedMenu ); + + // the interceptors only know command URLs, but our menus primarily work + // with IDs -> we need to translate the commands to IDs + lcl_adjustMenuItemIDs( *pModifiedMenu, m_pContextMenuProvider->getCommandController() ); + } + } } - return pContextMenu; + return pContextMenu.release(); } // ----------------------------------------------------------------------------- --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
