Hi Frank,
sorry for the delay on this (copy and paste from the apology I'm sending to everyone: the end of the first academic semester [it ended last Friday here in Argentina - followed by a 2 weeks winter holidays] kept me too busy; to this add a Patagonian trip to see the glacier tearing apart [same as http://es.youtube.com/watch?v=TZJYN8qnirE] and a 22 nights Krystov Kieslowski film retrospective; all this together kept me away from hobby-things like playing with OOo API). I just started testing the css.sdb.application.DefaultViewController, but as the first try reveals two important issues, I decided to report my findings before finishing a nicer/cleaner demo. "Important issue" means that the first two features I tested up to know (the context menu interceptor and the css.view.XSelectionSuplier) can not be used: the first not work and the later crashes OOo. The demo can be found in http://www.ArielConstenlaHaile.com.ar/ooo/tmp/dbaccess/DatabaseControllerDemo.zip it's a NetBeans project, oxt inside the dist folder; to debug the NBP you may need to change the settings (I can't recall what I've done to make it work with the 3-layer OOo), or you can simply install the extension (it is ridiculously verbose, so if you run OOo from the command line will get info about what's going on). The extension is copy&paste from other working code, but does nothing useful, anyway it may help to test the features [well.. the "Edit hyperlink" entry on Writer has been very useful for me!]. Check the extension in a Writer document context menu and then in a Base one to see the differences. ********************************************************************** ********************************************************************** Context menu interceptor In case you are too busy for this, take a look at the two pictures that show the issue: http://www.ArielConstenlaHaile.com.ar/ooo/tmp/dbaccess/no_seps_no_menu_item_image.png http://www.ArielConstenlaHaile.com.ar/ooo/tmp/dbaccess/with_seps_and_menu_item_image.png just by looking at them you'll see that on the context menu: 1. separators are converted to common menu items 2. menu item images are removed 3. although not visible [and AFAIK useless in context menus], the help command is not preserved 4. [and if you select an entry added by the extension] the menu item command is never executed Ad 1.: in DBTreeListBox::CreateContextMenu [1], if the PopupMenu is modified by a context menu interceptor, you also modify the menu item IDs in lcl_adjustMenuItemIDs with a new ID generated for its command. Inside the <code>for</code> loop in lcl_adjustMenuItemIDs you don't check if the menu item is a seperator, so it ends up converting separators in common menu items. Here adding the following code solves the problem: void lcl_adjustMenuItemIDs( Menu& _rMenu, IController& _rCommandController ) { USHORT nCount = _rMenu.GetItemCount(); for ( USHORT pos = 0; pos < nCount; ++pos ) { // do NOT adjust SEPARATORS! MenuItemType nItemType = _rMenu.GetItemType( pos ); if ( nItemType == MENUITEM_SEPARATOR ) continue; //... } } Ad 2.: commands added by context menu interceptors may have an image [never tested setting the property "Image" in the ActionTrigger - at least getting it has issues], lcl_adjustMenuItemIDs ignores that. The following keeps the menu item images: Image aImage = _rMenu.GetItemImage( nId ); if ( !!aImage ) _rMenu.SetItemImage( nCommandId, aImage ); Ad 3.: the ActionTrigger has also a "HelpURL" property, that may also be conserved by a _rMenu.GetHelpCommand and _rMenu.SetHelpCommand... although I have no idea if the new extensible help feature will work if the client code sets a custom help command here: F1 when a mouse is over a context menu item does nothing, no matter if the command is built-in. Anyway the following conserves the help command url: ::rtl::OUString aHelpURL = _rMenu.GetHelpCommand( nId ); if ( aHelpURL.getLength() ) _rMenu.SetHelpCommand( nCommandId, aHelpURL ); So that 1, 2 and 3 together make: void lcl_adjustMenuItemIDs( Menu& _rMenu, IController& _rCommandController ) { USHORT nCount = _rMenu.GetItemCount(); for ( USHORT pos = 0; pos < nCount; ++pos ) { // do NOT adjust SEPARATORS! MenuItemType nItemType = _rMenu.GetItemType( pos ); if ( nItemType == MENUITEM_SEPARATOR ) continue; 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 ); // first preserve IMAGES! Image aImage = _rMenu.GetItemImage( nId ); if ( !!aImage ) _rMenu.SetItemImage( nCommandId, aImage ); // and preserve HELP command URL ::rtl::OUString aHelpURL = _rMenu.GetHelpCommand( nId ); if ( aHelpURL.getLength() ) _rMenu.SetHelpCommand( nCommandId, aHelpURL ); _rMenu.RemoveItem( pos+1 ); } } This code makes the PopupMenu look like the image in http://www.ArielConstenlaHaile.com.ar/ooo/tmp/dbaccess/with_seps_and_menu_item_image.png Ad 4.: the issue for the command not being dispatched is a complex one: * when the user chooses a context menu item, DBTreeListBox::ExcecuteContextMenuAction invokes OApplicationController::executeChecked(sal_uInt16 _nCommandId, const Sequence< PropertyValue >& aArgs) with the item ID of the selected menu item * OApplicationController::executeChecked forwards the call to OGenericUnoController::executeChecked * OGenericUnoController::executeChecked will * first check if the command corresponding to this ID is enabled [isCommandEnabled(_nCommandId)] * then, if enable, execute it The first problem here is when isCommandEnabled checks the feature state: * OApplicationController::GetState switches all the IDs it can handle and as <code>default</code> forwards to its base class, this will be the case when the ID corresponds to a command added by a context menu interceptor * but in OGenericUnoController::GetState there is no code enabling so called "user defined features", so it returns always in this case a feature automatically disabled, and the command is then never executed A very dummy hack enabling all "user defined features" FeatureState OGenericUnoController::GetState(sal_uInt16 nId) const { FeatureState aReturn; // (disabled automatically) try { switch (nId) { case ID_BROWSER_UNDO: case ID_BROWSER_SAVEDOC: aReturn.bEnabled = sal_True; break; default: if ( ( nId >= FIRST_USER_DEFINED_FEATURE ) && ( nId < LAST_USER_DEFINED_FEATURE ) ) { aReturn.bEnabled = sal_True; } } } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); } return aReturn; } does not solve the problem, and discovers new ones: * isCommandEnabled returns true (because we force GetState( _nCommandId ).bEnabled = sal_True for all "user defined features", so the command ID will be executed * OApplicationController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& aArgs) forwards to its base when the ID belongs to a "user defined features" * OGenericUnoController::Execute * first gets the fully parsed command URL for this command ID * then queries a dispatch object * and ask the dispatch to execute the URL The problem in these last steps is that OGenericUnoController::queryDispatch checks that the command is among its supported features and returns itself as dispatch object, even when it is a "user defined features". So that looking at the code void OGenericUnoController::Execute( sal_uInt16 _nId, const Sequence< PropertyValue>& _rArgs ) { OSL_ENSURE( isUserDefinedFeature( _nId ), "OGenericUnoController::Execute: responsible for user defined features only!" ); URL aFeatureURL( getURLForId( _nId ) ); // user defined features can be handled by dispatch interceptors only. So, we need to do // a queryDispatch, and dispatch the URL try { Reference< XDispatch > xDispatch( queryDispatch( aFeatureURL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_self" ) ), FrameSearchFlag::AUTO ) ); if ( xDispatch == *this ) xDispatch.clear(); if ( xDispatch.is() ) xDispatch->dispatch( aFeatureURL, _rArgs ); } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); } } it's is obvious that: * the controller returns *itself* as dispatch for the command * but then the reference is *cleared* * so the dispatch *never* dispatches the URL Not clearing the reference does not solve anything: the application controller won't dispatch the URL anyway. Forcing to query the slave dispatch providers when it is a user defined feature won't either solve the problem: I'm not sure if the comment "user defined features can be handled by dispatch interceptors *only*. So, we need to do a queryDispatch, and dispatch the URL" is completely wrong (I never use dispatch interceptors because it is quite useless, as it may happen that more than one registers for the same command and nobody can assure who wins the battle - the same happens with the context menu interceptors, but here there is no other way to achieve the same, while in the other case a ProtocolHandler is more convenient), but I'm sure that: * a context menu interceptor can add commands handled by itself, so that its own ProtocolHandler is the one that is queried for a dispatch * this way also an extension binds commands to images, and the images are display in the context menu * again, the extension's ProtocolHandler is queried for a dispatch, not the controller, nor slaves dispatches I tried the dummy hack of querying the controller's frame for a dispatch object, but that does not work: void OGenericUnoController::Execute( sal_uInt16 _nId, const Sequence< PropertyValue>& _rArgs ) { OSL_ENSURE( isUserDefinedFeature( _nId ), "OGenericUnoController::Execute: responsible for user defined features only!" ); URL aFeatureURL( getURLForId( _nId ) ); // user defined features can be handled by dispatch interceptors only. So, we need to do // a queryDispatch, and dispatch the URL try { Reference< XDispatchProvider > xDispatchProvider( getFrame(), UNO_QUERY ); Reference< XDispatch > xDispatch; if ( xDispatchProvider.is() ) { xDispatch = xDispatchProvider->queryDispatch( aFeatureURL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_self" ) ), FrameSearchFlag::AUTO ); OSL_TRACE("trying with getFrame()"); } /*Reference< XDispatch > xDispatch( queryDispatch( aFeatureURL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_self" ) ), FrameSearchFlag::AUTO ) );*/ if ( xDispatch == *this ) xDispatch.clear(); if ( xDispatch.is() ) xDispatch->dispatch( aFeatureURL, _rArgs ); } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); } } I thought that getFrame() will return an css.frame.XFrame reference to the controller's frame, and querying the frame for a dispatch for my URL, it will query in turn my ProtocolHandler [as stated in http://api.openoffice.org/docs/common/ref/com/sun/star/frame/ProtocolHandler.html: "The generic dispatch mechanism on a Frame search for such registered protocol handler and use it if it agrees with the dispatched URL."]
It seems that the other day (well...night at 2:00 AM) I was quite asleep, although now it's 2 AM again, the distance gives me new eyes: yes, getting the XFrame and querying it for a dispatch will end up querying my ProtocolHandler. I was dummy not to hack enough also OGenericUnoController::queryDispatch, I only added an OSL_TRACE, but the controller *must* not return itself as dispatch object in the case of "user defined commands", so now I make it this way: Reference< XDispatch > OGenericUnoController::queryDispatch(const URL& aURL, const ::rtl::OUString& aTargetFrameName, sal_Int32 nSearchFlags) throw( RuntimeException ) { Reference< XDispatch > xReturn; OSL_PRECOND( !m_aSupportedFeatures.empty(), "OGenericUnoController::queryDispatch: shouldn't this be filled at construction time?" ); if ( m_aSupportedFeatures.empty() ) fillSupportedFeatures(); // first check our supported features if ( aURL.Complete.equals( getConfirmDeletionURL() ) || ( m_aSupportedFeatures.find( aURL.Complete ) != m_aSupportedFeatures.end() ) ) { // if the feature is user defined, do *not* return ourselves! if ( isUserDefinedFeature( m_aSupportedFeatures[ aURL.Complete ].nFeatureId ) ) { OSL_TRACE("Is user defined!"); return xReturn; } // URL's we can handle ourself? xReturn = this; } // no? -> ask the slave dispatcher else if ( m_xSlaveDispatcher.is() ) { xReturn = m_xSlaveDispatcher->queryDispatch(aURL, aTargetFrameName, nSearchFlags); } // outta here return xReturn; } [mmm... seems I'm not taking care of the slave dispatchers...] What was happening here? I was right to use getFrame() to take the XFrame as dispatch provider in OGenericUnoController::Execute instead of invoking queryDispatch(). But the problem was that when the frame [in fact it's not himself but a helper class DispatchProvider impl. in framework/source/dispatch/dispatchprovider.cxx] searches for someone to handle the URL, in this case he will query *first* it's controller, and if it disagrees, *then* it searches among the registered protocol handlers. For all this stuff, look at framework/source/dispatch/dispatchprovider.cxx , in DEV300_m25 is v. 1.37, DispatchProvider::implts_queryFrameDispatch, spec. ll. 455 ss, the comments there are very clear. In conclusion, now [in my build] the the context menu interceptor has a nice PopupMenu with images and separators, and dispatches its commands. I send you the patch (DEV300_m25 against DEV300_m28) so you can follow the mail. It is very simple, I only touched two files. The OGenericUnoController fix is too hacky for my taste, sure you find something more elegant; the PopupMenu fix I find it acceptable and nice. Regards Ariel. PS: reading at the sources I found a pair of things I'd like to have at the XDatabaseDocumentUI, may I ask them for? -- Ariel Constenla-Haile La Plata, Argentina [EMAIL PROTECTED] [EMAIL PROTECTED] http://www.ArielConstenlaHaile.com.ar/ooo/ "Aus der Kriegsschule des Lebens - Was mich nicht umbringt, macht mich härter." Nietzsche Götzendämmerung, Sprüche und Pfeile, 8.
Index: app/AppController.cxx =================================================================== RCS file: /cvs/dba/dbaccess/source/ui/app/AppController.cxx,v retrieving revision 1.63 diff -u -r1.63 AppController.cxx --- app/AppController.cxx 25 Jun 2008 12:35:22 -0000 1.63 +++ app/AppController.cxx 1 Aug 2008 04:22:41 -0000 @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2008 by Sun Microsystems, Inc. * * OpenOffice.org - a multi-platform office productivity suite @@ -628,7 +628,7 @@ ::std::compose1(::std::select2nd<TTypeFrame>(),::std::select2nd<TFrames::value_type>()))); if ( aFind2 != m_aSpecialSubFrames.end() ) m_aSpecialSubFrames.erase(aFind2); - + } if ( xContainer.is() ) { @@ -1628,7 +1628,7 @@ implDescribeSupportedFeature( ".uno:OpenUrl", SID_OPENURL, CommandGroup::APPLICATION ); // this one should not appear under Tools->Customize->Keyboard - implDescribeSupportedFeature( ".uno:DBNewReportWithPreSelection", + implDescribeSupportedFeature( ".uno:DBNewReportWithPreSelection", SID_APP_NEW_REPORT_PRE_SEL,CommandGroup::INTERNAL ); implDescribeSupportedFeature( ".uno:DBDSImport", SID_DB_APP_DSIMPORT, CommandGroup::INTERNAL); implDescribeSupportedFeature( ".uno:DBDSExport", SID_DB_APP_DSEXPORT, CommandGroup::INTERNAL); Index: browser/genericcontroller.cxx =================================================================== RCS file: /cvs/dba/dbaccess/source/ui/browser/genericcontroller.cxx,v retrieving revision 1.94 diff -u -r1.94 genericcontroller.cxx --- browser/genericcontroller.cxx 26 Jun 2008 11:43:10 -0000 1.94 +++ browser/genericcontroller.cxx 1 Aug 2008 04:20:51 -0000 @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2008 by Sun Microsystems, Inc. * * OpenOffice.org - a multi-platform office productivity suite @@ -387,7 +387,7 @@ //------------------------------------------------------------------------ void OGenericUnoController::modified(const EventObject& aEvent) throw( RuntimeException ) { - ::osl::MutexGuard aGuard(m_aMutex); + ::osl::MutexGuard aGuard(m_aMutex); if ( !isDataSourceReadOnly() ) { Reference<XModifiable> xModi(aEvent.Source,UNO_QUERY); @@ -415,7 +415,7 @@ void OGenericUnoController::attachFrame( const Reference< XFrame >& _rxFrame ) throw( RuntimeException ) { vos::OGuard aSolarGuard( Application::GetSolarMutex() ); - ::osl::MutexGuard aGuard(m_aMutex); + ::osl::MutexGuard aGuard(m_aMutex); stopFrameListening( m_aCurrentFrame.getFrame() ); Reference< XFrame > xFrame = m_aCurrentFrame.attachFrame( _rxFrame ); @@ -664,7 +664,7 @@ { // --------------------------------- // invalidate all aupported features - + for ( SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.begin(); aIter != m_aSupportedFeatures.end(); ++aIter @@ -684,17 +684,23 @@ Reference< XDispatch > OGenericUnoController::queryDispatch(const URL& aURL, const ::rtl::OUString& aTargetFrameName, sal_Int32 nSearchFlags) throw( RuntimeException ) { Reference< XDispatch > xReturn; - OSL_PRECOND( !m_aSupportedFeatures.empty(), "OGenericUnoController::queryDispatch: shouldn't this be filled at construction time?" ); if ( m_aSupportedFeatures.empty() ) fillSupportedFeatures(); - // URL's we can handle ourself? - if ( aURL.Complete.equals( getConfirmDeletionURL() ) + // first check our supported features + if ( aURL.Complete.equals( getConfirmDeletionURL() ) || ( m_aSupportedFeatures.find( aURL.Complete ) != m_aSupportedFeatures.end() ) ) { - xReturn = this; + // if the feature is user defined, do not return ourselves! + if ( isUserDefinedFeature( m_aSupportedFeatures[ aURL.Complete ].nFeatureId ) ) + { + OSL_TRACE("Is user defined!"); + return xReturn; + } + // URL's we can handle ourself? + xReturn = this; } // no? -> ask the slave dispatcher else if ( m_xSlaveDispatcher.is() ) @@ -843,7 +849,7 @@ Dispatch aStatusListener = m_arrStatusListener; Dispatch::iterator aEnd = aStatusListener.end(); for (Dispatch::iterator aIter = aStatusListener.begin(); aIter != aEnd; ++aIter) - { + { aIter->xListener->disposing(aDisposeEvent); } m_arrStatusListener.clear(); @@ -945,6 +951,12 @@ case ID_BROWSER_SAVEDOC: aReturn.bEnabled = sal_True; break; + default: + // do something to enable user defined features, or they will never be executed! + if ( ( nId >= FIRST_USER_DEFINED_FEATURE ) && ( nId < LAST_USER_DEFINED_FEATURE ) ) + { + aReturn.bEnabled = sal_True; + } } } catch( const Exception& ) @@ -960,17 +972,28 @@ { OSL_ENSURE( isUserDefinedFeature( _nId ), "OGenericUnoController::Execute: responsible for user defined features only!" ); + URL aFeatureURL( getURLForId( _nId ) ); - // user defined features can be handled by dispatch interceptors only. So, we need to do - // a queryDispatch, and dispatch the URL try { - Reference< XDispatch > xDispatch( queryDispatch( + Reference< XDispatchProvider > xDispatchProvider( getFrame(), UNO_QUERY ); + Reference< XDispatch > xDispatch; + + if ( xDispatchProvider.is() ) + { + xDispatch = xDispatchProvider->queryDispatch( + aFeatureURL, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_self" ) ), + FrameSearchFlag::AUTO ); + OSL_TRACE("trying with getFrame()"); + } + /*Reference< XDispatch > xDispatch( queryDispatch( aFeatureURL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_self" ) ), FrameSearchFlag::AUTO - ) ); + ) );*/ + if ( xDispatch == *this ) xDispatch.clear(); @@ -1197,6 +1220,7 @@ if ( aIter != m_aSupportedFeatures.end() ) { sal_uInt16 nFeatureId = aIter->second.nFeatureId; + if ( GetState( nFeatureId ).bEnabled ) Execute( nFeatureId, aArgs ); } @@ -1325,7 +1349,7 @@ } URL aURL; aURL.Complete = suURL; - + openHelpAgent( aURL ); } @@ -1388,10 +1412,10 @@ { Reference< XUntitledNumbers > xUntitledProvider(getPrivateModel(), UNO_QUERY ); Reference< XController > xThis(static_cast< XController* >(this), UNO_QUERY_THROW); - + ::framework::TitleHelper* pHelper = new ::framework::TitleHelper(m_xServiceFactory); m_xTitleHelper.set( static_cast< ::cppu::OWeakObject* >(pHelper), UNO_QUERY_THROW); - + pHelper->setOwner (xThis ); pHelper->connectWithUntitledNumbers (xUntitledProvider); } @@ -1420,7 +1444,7 @@ m_bExternalTitle = sal_True; impl_getTitleHelper_throw()->setTitle (sTitle); } - + //============================================================================= // XTitleChangeBroadcaster void SAL_CALL OGenericUnoController::addTitleChangeListener(const Reference< XTitleChangeListener >& xListener) @@ -1538,14 +1562,14 @@ sal_Bool OGenericUnoController::isCommandChecked(sal_uInt16 _nCommandId) const { FeatureState aState = GetState( _nCommandId ); - + return aState.bChecked && (sal_Bool)*aState.bChecked; } // ----------------------------------------------------------------------------- sal_Bool OGenericUnoController::isCommandEnabled( const ::rtl::OUString& _rCompleteCommandURL ) const { OSL_ENSURE( _rCompleteCommandURL.getLength(), "OGenericUnoController::isCommandEnabled: Empty command url!" ); - + sal_Bool bIsEnabled = sal_False; SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( _rCompleteCommandURL ); if ( aIter != m_aSupportedFeatures.end() ) Index: control/dbtreelistbox.cxx =================================================================== RCS file: /cvs/dba/dbaccess/source/ui/control/dbtreelistbox.cxx,v retrieving revision 1.20 diff -u -r1.20 dbtreelistbox.cxx --- control/dbtreelistbox.cxx 25 Jun 2008 12:43:33 -0000 1.20 +++ control/dbtreelistbox.cxx 1 Aug 2008 04:24:03 -0000 @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2008 by Sun Microsystems, Inc. * * OpenOffice.org - a multi-platform office productivity suite @@ -50,7 +50,7 @@ #ifndef _COM_SUN_STAR_DATATRANSFER_DND_XDRAGGESTURELISTENER_HDL_ #include <com/sun/star/datatransfer/dnd/XDragGestureListener.hdl> #endif -#ifndef _COM_SUN_STAR_DATATRANSFER_DND_XDRAGGESTURERECOGNIZER_HPP_ +#ifndef _COM_SUN_STAR_DATATRANSFER_DND_XDRAGGESTURERECOGNIZER_HPP_ #include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp> #endif #ifndef _COM_SUN_STAR_UI_XCONTEXTMENUINTERCEPTOR_HPP_ @@ -68,6 +68,9 @@ #ifndef _SV_HELP_HXX #include <vcl/help.hxx> #endif +#ifndef _SV_IMAGE_HXX +#include <vcl/image.hxx> +#endif #ifndef _DBAUI_TABLETREE_HRC_ #include "tabletree.hrc" #endif @@ -127,7 +130,7 @@ ,m_xORB(_rxORB) { DBG_CTOR(DBTreeListBox,NULL); - init(); + init(); } // ----------------------------------------------------------------------------- void DBTreeListBox::init() @@ -150,7 +153,7 @@ { DBG_DTOR(DBTreeListBox,NULL); if(m_aTimer.IsActive()) - m_aTimer.Stop(); + m_aTimer.Stop(); } //------------------------------------------------------------------------ SvLBoxEntry* DBTreeListBox::GetEntryPosByName( const String& aName, SvLBoxEntry* pStart, const IEntryFilter* _pFilter ) const @@ -464,7 +467,7 @@ // 2002-12-02 - 105831 - [EMAIL PROTECTED] } - if ( !bHandled ) + if ( !bHandled ) SvTreeListBox::KeyInput(rKEvt); } // ----------------------------------------------------------------------------- @@ -485,7 +488,7 @@ m_pSelectedEntry = NULL; // to force that the renamed selection will be reselected } SetEntryText(pEntry,aEntry.aNewText); - + return FALSE; // we never want that the base change our text } @@ -559,21 +562,38 @@ { void lcl_adjustMenuItemIDs( Menu& _rMenu, IController& _rCommandController ) { - USHORT nCount = _rMenu.GetItemCount(); + 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 ); + // do NOT adjust SEPARATORS! + MenuItemType nItemType = _rMenu.GetItemType( pos ); + if ( nItemType == MENUITEM_SEPARATOR ) continue; - } + + 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 ); + + _rMenu.InsertItem( nCommandId, _rMenu.GetItemText( nId ), _rMenu.GetItemBits( nId ), pos ); + + // first preserve IMAGES! + Image aImage = _rMenu.GetItemImage( nId ); + if ( !!aImage ) + _rMenu.SetItemImage( nCommandId, aImage ); + + // and preserve HELP command URL + ::rtl::OUString aHelpURL = _rMenu.GetHelpCommand( nId ); + if ( aHelpURL.getLength() ) + _rMenu.SetHelpCommand( nCommandId, aHelpURL ); + + _rMenu.RemoveItem( pos+1 ); } } // ========================================================================= @@ -609,20 +629,20 @@ 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) { @@ -727,7 +747,7 @@ if(m_aTimer.IsActive()) m_aTimer.Stop(); if (m_pSelectedEntry) - aSelectHdl.Call( m_pSelectedEntry ); + aSelectHdl.Call( m_pSelectedEntry ); return 0L; } // -----------------------------------------------------------------------------
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]