Update ooo320-m1
[ooovba.git] / framework / source / classes / menumanager.cxx
blobb245cff3ad5fa4fdb8c434c778ec7d690c7ad41f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: menumanager.cxx,v $
10 * $Revision: 1.41 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_framework.hxx"
35 //_________________________________________________________________________________________________________________
36 // my own includes
37 //_________________________________________________________________________________________________________________
38 #include <classes/menumanager.hxx>
39 #include <xml/menuconfiguration.hxx>
40 #include <classes/bmkmenu.hxx>
41 #include <classes/addonmenu.hxx>
42 #include <helper/imageproducer.hxx>
43 #include <threadhelp/resetableguard.hxx>
44 #include "classes/addonsoptions.hxx"
45 #include <classes/fwkresid.hxx>
46 #include <services.h>
47 #include "classes/resource.hrc"
49 //_________________________________________________________________________________________________________________
50 // interface includes
51 //_________________________________________________________________________________________________________________
52 #include <com/sun/star/frame/XDispatchProvider.hpp>
53 #include <com/sun/star/frame/XDispatch.hpp>
54 #include <com/sun/star/util/XURLTransformer.hpp>
55 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
56 #include <com/sun/star/beans/XPropertySet.hpp>
57 #include <com/sun/star/frame/XFramesSupplier.hpp>
58 #include <com/sun/star/frame/XDesktop.hpp>
59 #include <com/sun/star/container/XEnumeration.hpp>
60 #include <com/sun/star/util/XStringWidth.hpp>
62 //_________________________________________________________________________________________________________________
63 // includes of other projects
64 //_________________________________________________________________________________________________________________
65 #include <comphelper/processfactory.hxx>
67 #include <comphelper/extract.hxx>
68 #include <svtools/menuoptions.hxx>
69 #include <svtools/historyoptions.hxx>
70 #include <svtools/pathoptions.hxx>
71 #include <unotools/localfilehelper.hxx>
73 #ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_
74 #include <toolkit/unohlp.hxx>
75 #endif
76 #include <tools/urlobj.hxx>
78 #include <vcl/svapp.hxx>
79 #include <vcl/window.hxx>
80 #include <vos/mutex.hxx>
81 #include <vcl/svapp.hxx>
82 #include <osl/file.hxx>
83 #include <cppuhelper/implbase1.hxx>
85 //_________________________________________________________________________________________________________________
86 // namespace
87 //_________________________________________________________________________________________________________________
89 using namespace ::cppu;
90 using namespace ::vos;
91 using namespace ::com::sun::star::uno;
92 using namespace ::com::sun::star::util;
93 using namespace ::com::sun::star::beans;
94 using namespace ::com::sun::star::frame;
95 using namespace ::com::sun::star::lang;
96 using namespace ::com::sun::star::container;
99 class StringLength : public ::cppu::WeakImplHelper1< ::com::sun::star::util::XStringWidth >
101 public:
102 StringLength() {}
103 virtual ~StringLength() {}
105 // XStringWidth
106 sal_Int32 SAL_CALL queryStringWidth( const ::rtl::OUString& aString )
107 throw (::com::sun::star::uno::RuntimeException)
109 return aString.getLength();
113 namespace framework
116 // special menu ids/command ids for dynamic popup menus
117 #define SID_SFX_START 5000
118 #define SID_NEWDOCDIRECT (SID_SFX_START + 537)
119 #define SID_AUTOPILOTMENU (SID_SFX_START + 1381)
120 #define SID_PICKLIST (SID_SFX_START + 510)
121 #define SID_MDIWINDOWLIST (SID_SFX_START + 610)
122 #define SID_ADDONLIST (SID_SFX_START + 1677)
123 #define SID_HELPMENU (SID_SFX_START + 410)
125 #define SFX_REFERER_USER "private:user"
127 const ::rtl::OUString aSlotNewDocDirect( RTL_CONSTASCII_USTRINGPARAM( "slot:5537" ));
128 const ::rtl::OUString aSlotAutoPilot( RTL_CONSTASCII_USTRINGPARAM( "slot:6381" ));
130 const ::rtl::OUString aSpecialFileMenu( RTL_CONSTASCII_USTRINGPARAM( "file" ));
131 const ::rtl::OUString aSpecialWindowMenu( RTL_CONSTASCII_USTRINGPARAM( "window" ));
132 const ::rtl::OUString aSlotSpecialFileMenu( RTL_CONSTASCII_USTRINGPARAM( "slot:5510" ));
133 const ::rtl::OUString aSlotSpecialWindowMenu( RTL_CONSTASCII_USTRINGPARAM( "slot:5610" ));
134 const ::rtl::OUString aSlotSpecialToolsMenu( RTL_CONSTASCII_USTRINGPARAM( "slot:6677" ));
136 // special uno commands for picklist and window list
137 const ::rtl::OUString aSpecialFileCommand( RTL_CONSTASCII_USTRINGPARAM( "PickList" ));
138 const ::rtl::OUString aSpecialWindowCommand( RTL_CONSTASCII_USTRINGPARAM( "WindowList" ));
140 const ::rtl::OUString UNO_COMMAND( RTL_CONSTASCII_USTRINGPARAM( ".uno:" ));
142 // #110897#
143 MenuManager::MenuManager(
144 const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory,
145 REFERENCE< XFRAME >& rFrame, Menu* pMenu, sal_Bool bDelete, sal_Bool bDeleteChildren )
146 : // #110897#
147 ThreadHelpBase( &Application::GetSolarMutex() ),
148 mxServiceFactory(xServiceFactory)
150 m_bActive = sal_False;
151 m_bDeleteMenu = bDelete;
152 m_bDeleteChildren = bDeleteChildren;
153 m_pVCLMenu = pMenu;
154 m_xFrame = rFrame;
155 m_bInitialized = sal_False;
156 m_bIsBookmarkMenu = sal_False;
157 SAL_STATIC_CAST( ::com::sun::star::uno::XInterface*, (OWeakObject*)this )->acquire();
159 const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
160 m_bWasHiContrast = rSettings.GetHighContrastMode();
161 m_bShowMenuImages = rSettings.GetUseImagesInMenus();
163 sal_Int32 nAddonsURLPrefixLength = ADDONSPOPUPMENU_URL_PREFIX.getLength();
164 #if 0
165 ::std::vector< USHORT > aQueryLabelItemIdVector;
166 #endif
168 USHORT nItemCount = pMenu->GetItemCount();
169 m_aMenuItemHandlerVector.reserve(nItemCount);
170 ::rtl::OUString aItemCommand;
171 for ( USHORT i = 0; i < nItemCount; i++ )
173 USHORT nItemId = FillItemCommand(aItemCommand,pMenu, i );
175 PopupMenu* pPopupMenu = pMenu->GetPopupMenu( nItemId );
176 if ( pPopupMenu )
178 AddMenu(pPopupMenu,aItemCommand,nItemId,bDeleteChildren,bDeleteChildren);
179 if (! (( aItemCommand.getLength() > nAddonsURLPrefixLength ) &&
180 ( aItemCommand.indexOf( ADDONSPOPUPMENU_URL_PREFIX ) == 0 )) )
182 // #110897#
183 // MenuManager* pSubMenuManager = new MenuManager( rFrame, pPopupMenu, bDeleteChildren, bDeleteChildren );
184 #if 0
185 if ( pMenu->GetItemText( nItemId ).Len() == 0 )
186 aQueryLabelItemIdVector.push_back( nItemId );
187 #endif
189 // Create addon popup menu if there exist elements and this is the tools popup menu
190 if (( nItemId == SID_ADDONLIST ||
191 aItemCommand == aSlotSpecialToolsMenu ) &&
192 AddonMenuManager::HasAddonMenuElements() )
194 USHORT nCount = 0;
195 AddonMenu* pSubMenu = AddonMenuManager::CreateAddonMenu( rFrame );
196 if ( pSubMenu && ( pSubMenu->GetItemCount() > 0 ))
198 if ( pPopupMenu->GetItemType( nCount-1 ) != MENUITEM_SEPARATOR )
199 pPopupMenu->InsertSeparator();
201 // Use resource to load popup menu title
202 String aAddonsStrRes = String( FwkResId( STR_MENU_ADDONS ));
203 pPopupMenu->InsertItem( ITEMID_ADDONLIST, aAddonsStrRes );
204 pPopupMenu->SetPopupMenu( ITEMID_ADDONLIST, pSubMenu );
206 // Set item command for popup menu to enable it for GetImageFromURL
207 const static ::rtl::OUString aSlotString( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
208 aItemCommand = aSlotString;
209 aItemCommand += ::rtl::OUString::valueOf( (sal_Int32)ITEMID_ADDONLIST );
210 pPopupMenu->SetItemCommand( ITEMID_ADDONLIST, aItemCommand );
212 // #110897#
213 // MenuManager* pSubMenuManager = new MenuManager( rFrame, pSubMenu, sal_True, sal_False );
214 AddMenu(pSubMenu,::rtl::OUString(),nItemId,sal_True,sal_False);
215 #if 0
216 if ( pMenu->GetItemText( nItemId ).Len() == 0 )
217 aQueryLabelItemIdVector.push_back( nItemId );
218 #endif
219 // Set image for the addon popup menu item
220 if ( m_bShowMenuImages && !pPopupMenu->GetItemImage( ITEMID_ADDONLIST ))
222 Image aImage = GetImageFromURL( rFrame, aItemCommand, FALSE, m_bWasHiContrast );
223 if ( !!aImage )
224 pPopupMenu->SetItemImage( ITEMID_ADDONLIST, aImage );
227 else
228 delete pSubMenu;
232 else
234 if ( nItemId == SID_NEWDOCDIRECT ||
235 aItemCommand == aSlotNewDocDirect )
237 // #110897#
238 // Reference< ::com::sun::star::lang::XMultiServiceFactory > aMultiServiceFactory(::comphelper::getProcessServiceFactory());
239 // MenuConfiguration aMenuCfg( aMultiServiceFactory );
240 MenuConfiguration aMenuCfg( getServiceFactory() );
241 BmkMenu* pSubMenu = (BmkMenu*)aMenuCfg.CreateBookmarkMenu( rFrame, BOOKMARK_NEWMENU );
242 pMenu->SetPopupMenu( nItemId, pSubMenu );
244 // #110897#
245 // MenuManager* pSubMenuManager = new MenuManager( rFrame, pSubMenu, sal_True, sal_False );
246 AddMenu(pSubMenu,::rtl::OUString(),nItemId,sal_True,sal_False);
247 #if 0
248 if ( pMenu->GetItemText( nItemId ).Len() == 0 )
249 aQueryLabelItemIdVector.push_back( nItemId );
250 #endif
252 if ( m_bShowMenuImages && !pMenu->GetItemImage( nItemId ))
254 Image aImage = GetImageFromURL( rFrame, aItemCommand, FALSE, m_bWasHiContrast );
255 if ( !!aImage )
256 pMenu->SetItemImage( nItemId, aImage );
259 else if ( nItemId == SID_AUTOPILOTMENU ||
260 aItemCommand == aSlotAutoPilot )
262 // #110897#
263 // Reference< ::com::sun::star::lang::XMultiServiceFactory > aMultiServiceFactory(::comphelper::getProcessServiceFactory());
264 // MenuConfiguration aMenuCfg( aMultiServiceFactory );
265 MenuConfiguration aMenuCfg( getServiceFactory() );
266 BmkMenu* pSubMenu = (BmkMenu*)aMenuCfg.CreateBookmarkMenu( rFrame, BOOKMARK_WIZARDMENU );
267 pMenu->SetPopupMenu( nItemId, pSubMenu );
269 // #110897#
270 // MenuManager* pSubMenuManager = new MenuManager( rFrame, pSubMenu, sal_True, sal_False );
271 AddMenu(pSubMenu,::rtl::OUString(),nItemId,sal_True,sal_False);
272 #if 0
273 if ( pMenu->GetItemText( nItemId ).Len() == 0 )
274 aQueryLabelItemIdVector.push_back( nItemId );
275 #endif
277 if ( m_bShowMenuImages && !pMenu->GetItemImage( nItemId ))
279 Image aImage = GetImageFromURL( rFrame, aItemCommand, FALSE, m_bWasHiContrast );
280 if ( !!aImage )
281 pMenu->SetItemImage( nItemId, aImage );
284 else if ( pMenu->GetItemType( i ) != MENUITEM_SEPARATOR )
286 if ( m_bShowMenuImages )
288 if ( AddonMenuManager::IsAddonMenuId( nItemId ))
290 // Add-Ons uses a images from different places
291 Image aImage;
292 rtl::OUString aImageId;
294 MenuConfiguration::Attributes* pMenuAttributes =
295 (MenuConfiguration::Attributes*)pMenu->GetUserValue( nItemId );
297 if ( pMenuAttributes && pMenuAttributes->aImageId.getLength() > 0 )
299 // Retrieve image id from menu attributes
300 aImage = GetImageFromURL( rFrame, aImageId, FALSE, m_bWasHiContrast );
303 if ( !aImage )
305 aImage = GetImageFromURL( rFrame, aItemCommand, FALSE, m_bWasHiContrast );
306 if ( !aImage )
307 aImage = AddonsOptions().GetImageFromURL( aItemCommand, FALSE, m_bWasHiContrast );
310 if ( !!aImage )
311 pMenu->SetItemImage( nItemId, aImage );
313 else if ( !pMenu->GetItemImage( nItemId ))
315 Image aImage = GetImageFromURL( rFrame, aItemCommand, FALSE, m_bWasHiContrast );
316 if ( !!aImage )
317 pMenu->SetItemImage( nItemId, aImage );
321 REFERENCE< XDISPATCH > aXDispatchRef;
322 m_aMenuItemHandlerVector.push_back( new MenuItemHandler( nItemId, NULL, aXDispatchRef ));
323 #if 0
324 if ( pMenu->GetItemText( nItemId ).Len() == 0 )
325 aQueryLabelItemIdVector.push_back( nItemId );
326 #endif
332 // retrieve label information for all menu items without item text
333 #if 0
334 if ( aQueryLabelItemIdVector.size() > 0 )
336 Sequence< ::rtl::OUString > aURLSequence( aQueryLabelItemIdVector.size() );
337 Sequence< ::rtl::OUString > aLabelSequence( aQueryLabelItemIdVector.size() );
339 sal_uInt32 nPos = 0;
340 ::std::vector< USHORT >::iterator p;
341 for ( p = aQueryLabelItemIdVector.begin(); p != aQueryLabelItemIdVector.end(); p++ )
342 aURLSequence[nPos++] = pMenu->GetItemCommand( *p );
344 Reference< XDispatchInformationProvider > xDIP( xFrame, UNO_QUERY );
345 if ( xDIP.is() )
347 nPos = 0;
348 xDIP->queryDispatchInformations( aURLSequence, aLabelSequence );
349 for ( p = aQueryLabelItemIdVector.begin(); p != aQueryLabelItemIdVector.end(); p++ )
350 pMenu->SetItemText( *p, aLabelSequence( nPos++ ));
353 #endif
354 SetHdl();
357 // #110897#
358 MenuManager::MenuManager(
359 const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory,
360 REFERENCE< XFRAME >& rFrame, AddonMenu* pAddonMenu, sal_Bool bDelete, sal_Bool bDeleteChildren )
361 : // #110897#
362 ThreadHelpBase( &Application::GetSolarMutex() ),
363 mxServiceFactory(xServiceFactory)
365 m_bActive = sal_False;
366 m_bDeleteMenu = bDelete;
367 m_bDeleteChildren = bDeleteChildren;
368 m_pVCLMenu = pAddonMenu;
369 m_xFrame = rFrame;
370 m_bInitialized = sal_False;
371 m_bIsBookmarkMenu = sal_True;
373 const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
374 m_bWasHiContrast = rSettings.GetHighContrastMode();
376 SAL_STATIC_CAST( ::com::sun::star::uno::XInterface*, (OWeakObject*)this )->acquire();
378 USHORT nItemCount = pAddonMenu->GetItemCount();
379 m_aMenuItemHandlerVector.reserve(nItemCount);
380 ::rtl::OUString aItemCommand;
381 for ( USHORT i = 0; i < nItemCount; i++ )
383 USHORT nItemId = FillItemCommand(aItemCommand,pAddonMenu, i );
385 PopupMenu* pPopupMenu = pAddonMenu->GetPopupMenu( nItemId );
386 if ( pPopupMenu )
388 // #110897#
389 // MenuManager* pSubMenuManager = new MenuManager( rFrame, pPopupMenu, bDeleteChildren, bDeleteChildren );
390 AddMenu(pPopupMenu,aItemCommand,nItemId,bDeleteChildren,bDeleteChildren);
392 else
394 if ( pAddonMenu->GetItemType( i ) != MENUITEM_SEPARATOR )
396 MenuConfiguration::Attributes* pAddonAttributes = (MenuConfiguration::Attributes *)(pAddonMenu->GetUserValue( nItemId ));
397 REFERENCE< XDISPATCH > aXDispatchRef;
398 MenuItemHandler* pMenuItemHandler = new MenuItemHandler( nItemId, NULL, aXDispatchRef );
400 if ( pAddonAttributes )
402 // read additional attributes from attributes struct and AddonMenu implementation will delete all attributes itself!!
403 pMenuItemHandler->aTargetFrame = pAddonAttributes->aTargetFrame;
406 m_aMenuItemHandlerVector.push_back( pMenuItemHandler );
411 SetHdl();
414 void MenuManager::SetHdl()
416 m_pVCLMenu->SetHighlightHdl( LINK( this, MenuManager, Highlight ));
417 m_pVCLMenu->SetActivateHdl( LINK( this, MenuManager, Activate ));
418 m_pVCLMenu->SetDeactivateHdl( LINK( this, MenuManager, Deactivate ));
419 m_pVCLMenu->SetSelectHdl( LINK( this, MenuManager, Select ));
421 if ( mxServiceFactory.is() )
422 m_xURLTransformer.set( mxServiceFactory->createInstance(SERVICENAME_URLTRANSFORMER),UNO_QUERY );
425 MenuManager::~MenuManager()
427 std::vector< MenuItemHandler* >::iterator p;
428 for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ )
430 MenuItemHandler* pItemHandler = *p;
431 pItemHandler->xMenuItemDispatch.clear();
432 if ( pItemHandler->pSubMenuManager )
433 SAL_STATIC_CAST( ::com::sun::star::uno::XInterface*, (OWeakObject*)pItemHandler->pSubMenuManager )->release();
434 delete pItemHandler;
437 if ( m_bDeleteMenu )
438 delete m_pVCLMenu;
442 MenuManager::MenuItemHandler* MenuManager::GetMenuItemHandler( USHORT nItemId )
444 ResetableGuard aGuard( m_aLock );
446 std::vector< MenuItemHandler* >::iterator p;
447 for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ )
449 MenuItemHandler* pItemHandler = *p;
450 if ( pItemHandler->nItemId == nItemId )
451 return pItemHandler;
454 return 0;
458 void SAL_CALL MenuManager::statusChanged( const FEATURSTATEEVENT& Event )
459 throw ( RuntimeException )
461 ::rtl::OUString aFeatureURL = Event.FeatureURL.Complete;
462 MenuItemHandler* pStatusChangedMenu = NULL;
465 ResetableGuard aGuard( m_aLock );
467 std::vector< MenuItemHandler* >::iterator p;
468 for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ )
470 MenuItemHandler* pMenuItemHandler = *p;
471 if ( pMenuItemHandler->aMenuItemURL == aFeatureURL )
473 pStatusChangedMenu = pMenuItemHandler;
474 break;
479 if ( pStatusChangedMenu )
481 OGuard aSolarGuard( Application::GetSolarMutex() );
483 ResetableGuard aGuard( m_aLock );
485 sal_Bool bSetCheckmark = sal_False;
486 sal_Bool bCheckmark = sal_False;
487 sal_Bool bMenuItemEnabled = m_pVCLMenu->IsItemEnabled( pStatusChangedMenu->nItemId );
489 if ( Event.IsEnabled != bMenuItemEnabled )
490 m_pVCLMenu->EnableItem( pStatusChangedMenu->nItemId, Event.IsEnabled );
492 if ( Event.State >>= bCheckmark )
493 bSetCheckmark = sal_True;
495 if ( bSetCheckmark )
496 m_pVCLMenu->CheckItem( pStatusChangedMenu->nItemId, bCheckmark );
499 if ( Event.Requery )
501 URL aTargetURL;
502 aTargetURL.Complete = pStatusChangedMenu->aMenuItemURL;
504 // #110897#
505 m_xURLTransformer->parseStrict( aTargetURL );
507 REFERENCE< XDISPATCHPROVIDER > xDispatchProvider( m_xFrame, UNO_QUERY );
508 REFERENCE< XDISPATCH > xMenuItemDispatch = xDispatchProvider->queryDispatch(
509 aTargetURL, ::rtl::OUString(), 0 );
511 if ( xMenuItemDispatch.is() )
513 pStatusChangedMenu->xMenuItemDispatch = xMenuItemDispatch;
514 pStatusChangedMenu->aMenuItemURL = aTargetURL.Complete;
515 xMenuItemDispatch->addStatusListener( SAL_STATIC_CAST( XSTATUSLISTENER*, this ), aTargetURL );
522 void MenuManager::RemoveListener()
524 ResetableGuard aGuard( m_aLock );
525 ClearMenuDispatch();
528 void MenuManager::ClearMenuDispatch(const EVENTOBJECT& Source,bool _bRemoveOnly)
530 // disposing called from parent dispatcher
531 // remove all listener to prepare shutdown
533 // #110897#
534 std::vector< MenuItemHandler* >::iterator p;
535 for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ )
537 MenuItemHandler* pItemHandler = *p;
538 if ( pItemHandler->xMenuItemDispatch.is() )
540 URL aTargetURL;
541 aTargetURL.Complete = pItemHandler->aMenuItemURL;
542 m_xURLTransformer->parseStrict( aTargetURL );
544 pItemHandler->xMenuItemDispatch->removeStatusListener(
545 SAL_STATIC_CAST( XSTATUSLISTENER*, this ), aTargetURL );
548 pItemHandler->xMenuItemDispatch.clear();
549 if ( pItemHandler->pSubMenuManager )
551 if ( _bRemoveOnly )
552 pItemHandler->pSubMenuManager->RemoveListener();
553 else
554 pItemHandler->pSubMenuManager->disposing( Source );
560 void SAL_CALL MenuManager::disposing( const EVENTOBJECT& Source ) throw ( RUNTIMEEXCEPTION )
562 if ( Source.Source == m_xFrame )
564 ResetableGuard aGuard( m_aLock );
565 ClearMenuDispatch(Source,false);
567 else
569 // disposing called from menu item dispatcher, remove listener
570 MenuItemHandler* pMenuItemDisposing = NULL;
573 ResetableGuard aGuard( m_aLock );
575 std::vector< MenuItemHandler* >::iterator p;
576 for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ )
578 MenuItemHandler* pMenuItemHandler = *p;
579 if ( pMenuItemHandler->xMenuItemDispatch == Source.Source )
581 pMenuItemDisposing = pMenuItemHandler;
582 break;
586 if ( pMenuItemDisposing )
588 URL aTargetURL;
589 aTargetURL.Complete = pMenuItemDisposing->aMenuItemURL;
591 // #110897#
592 m_xURLTransformer->parseStrict( aTargetURL );
594 pMenuItemDisposing->xMenuItemDispatch->removeStatusListener(SAL_STATIC_CAST( XSTATUSLISTENER*, this ), aTargetURL );
595 pMenuItemDisposing->xMenuItemDispatch.clear();
602 void MenuManager::UpdateSpecialFileMenu( Menu* pMenu )
604 // update picklist
605 Sequence< Sequence< PropertyValue > > aHistoryList = SvtHistoryOptions().GetList( ePICKLIST );
606 ::std::vector< MenuItemHandler* > aNewPickVector;
607 Reference< XStringWidth > xStringLength( new StringLength );
609 USHORT nPickItemId = START_ITEMID_PICKLIST;
610 int nPickListMenuItems = ( aHistoryList.getLength() > 99 ) ? 99 : aHistoryList.getLength();
612 aNewPickVector.reserve(nPickListMenuItems);
613 for ( int i = 0; i < nPickListMenuItems; i++ )
615 Sequence< PropertyValue > aPickListEntry = aHistoryList[i];
617 REFERENCE< XDISPATCH > aXDispatchRef;
618 MenuItemHandler* pNewMenuItemHandler = new MenuItemHandler(
619 nPickItemId++,
620 NULL,
621 aXDispatchRef );
623 for ( int j = 0; j < aPickListEntry.getLength(); j++ )
625 Any a = aPickListEntry[j].Value;
627 if ( aPickListEntry[j].Name == HISTORY_PROPERTYNAME_URL )
628 a >>= pNewMenuItemHandler->aMenuItemURL;
629 else if ( aPickListEntry[j].Name == HISTORY_PROPERTYNAME_FILTER )
630 a >>= pNewMenuItemHandler->aFilter;
631 else if ( aPickListEntry[j].Name == HISTORY_PROPERTYNAME_TITLE )
632 a >>= pNewMenuItemHandler->aTitle;
633 else if ( aPickListEntry[j].Name == HISTORY_PROPERTYNAME_PASSWORD )
634 a >>= pNewMenuItemHandler->aPassword;
637 aNewPickVector.push_back( pNewMenuItemHandler );
640 if ( !aNewPickVector.empty() )
642 URL aTargetURL;
643 REFERENCE< XDISPATCHPROVIDER > xDispatchProvider( m_xFrame, UNO_QUERY );
645 // #110897#
646 REFERENCE< XDISPATCH > xMenuItemDispatch;
648 static const ::rtl::OUString s_sDefault(RTL_CONSTASCII_USTRINGPARAM("_default"));
649 // query for dispatcher
650 std::vector< MenuItemHandler* >::iterator p;
651 for ( p = aNewPickVector.begin(); p != aNewPickVector.end(); p++ )
653 MenuItemHandler* pMenuItemHandler = *p;
655 aTargetURL.Complete = pMenuItemHandler->aMenuItemURL;
656 m_xURLTransformer->parseStrict( aTargetURL );
658 if ( !xMenuItemDispatch.is() )
660 // attention: this code assume that "_blank" can only be consumed by desktop service
661 xMenuItemDispatch = xDispatchProvider->queryDispatch( aTargetURL, s_sDefault, 0 );
664 if ( xMenuItemDispatch.is() )
666 pMenuItemHandler->xMenuItemDispatch = xMenuItemDispatch;
667 pMenuItemHandler->aMenuItemURL = aTargetURL.Complete;
672 ResetableGuard aGuard( m_aLock );
674 int nRemoveItemCount = 0;
675 int nItemCount = pMenu->GetItemCount();
677 if ( nItemCount > 0 )
679 // remove all old picklist entries from menu
680 sal_uInt16 nPos = pMenu->GetItemPos( START_ITEMID_PICKLIST );
681 for ( sal_uInt16 n = nPos; n < pMenu->GetItemCount(); )
683 pMenu->RemoveItem( n );
684 ++nRemoveItemCount;
687 if ( pMenu->GetItemType( pMenu->GetItemCount()-1 ) == MENUITEM_SEPARATOR )
688 pMenu->RemoveItem( pMenu->GetItemCount()-1 );
690 // remove all old picklist entries from menu handler
691 if ( nRemoveItemCount > 0 )
693 for( sal_uInt32 nIndex = m_aMenuItemHandlerVector.size() - nRemoveItemCount;
694 nIndex < m_aMenuItemHandlerVector.size(); )
696 delete m_aMenuItemHandlerVector.at( nIndex );
697 m_aMenuItemHandlerVector.erase( m_aMenuItemHandlerVector.begin() + nIndex );
702 // append new picklist menu entries
703 aNewPickVector.reserve(aNewPickVector.size());
704 pMenu->InsertSeparator();
705 const sal_uInt32 nCount = aNewPickVector.size();
706 for ( sal_uInt32 i = 0; i < nCount; i++ )
708 char menuShortCut[5] = "~n: ";
710 ::rtl::OUString aMenuShortCut;
711 if ( i <= 9 )
713 if ( i == 9 )
714 aMenuShortCut = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "1~0: " ));
715 else
717 menuShortCut[1] = (char)( '1' + i );
718 aMenuShortCut = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( menuShortCut ));
721 else
723 aMenuShortCut = rtl::OUString::valueOf((sal_Int32)( i + 1 ));
724 aMenuShortCut += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ": " ));
727 // Abbreviate URL
728 rtl::OUString aURLString( aNewPickVector.at( i )->aMenuItemURL );
729 rtl::OUString aTipHelpText;
730 rtl::OUString aMenuTitle;
731 INetURLObject aURL( aURLString );
733 if ( aURL.GetProtocol() == INET_PROT_FILE )
735 // Do handle file URL differently => convert it to a system
736 // path and abbreviate it with a special function:
737 String aFileSystemPath( aURL.getFSysPath( INetURLObject::FSYS_DETECT ) );
739 ::rtl::OUString aSystemPath( aFileSystemPath );
740 ::rtl::OUString aCompactedSystemPath;
742 aTipHelpText = aSystemPath;
743 oslFileError nError = osl_abbreviateSystemPath( aSystemPath.pData, &aCompactedSystemPath.pData, 46, NULL );
744 if ( !nError )
745 aMenuTitle = String( aCompactedSystemPath );
746 else
747 aMenuTitle = aSystemPath;
749 else
751 // Use INetURLObject to abbreviate all other URLs
752 String aShortURL;
753 aShortURL = aURL.getAbbreviated( xStringLength, 46, INetURLObject::DECODE_UNAMBIGUOUS );
754 aMenuTitle += aShortURL;
755 aTipHelpText = aURLString;
758 ::rtl::OUString aTitle( aMenuShortCut + aMenuTitle );
760 MenuItemHandler* pMenuItemHandler = aNewPickVector.at( i );
761 pMenu->InsertItem( pMenuItemHandler->nItemId, aTitle );
762 pMenu->SetTipHelpText( pMenuItemHandler->nItemId, aTipHelpText );
763 m_aMenuItemHandlerVector.push_back( pMenuItemHandler );
769 void MenuManager::UpdateSpecialWindowMenu( Menu* pMenu,const Reference< XMultiServiceFactory >& xServiceFactory,framework::IMutex& _rMutex )
771 // update window list
772 ::std::vector< ::rtl::OUString > aNewWindowListVector;
774 // #110897#
775 Reference< XDesktop > xDesktop( xServiceFactory->createInstance( SERVICENAME_DESKTOP ), UNO_QUERY );
777 USHORT nActiveItemId = 0;
778 USHORT nItemId = START_ITEMID_WINDOWLIST;
780 if ( xDesktop.is() )
782 Reference< XFramesSupplier > xTasksSupplier( xDesktop, UNO_QUERY );
783 Reference< XFrame > xCurrentFrame = xDesktop->getCurrentFrame();
784 Reference< XIndexAccess > xList( xTasksSupplier->getFrames(), UNO_QUERY );
785 sal_Int32 nCount = xList->getCount();
786 aNewWindowListVector.reserve(nCount);
787 for (sal_Int32 i=0; i<nCount; ++i )
789 Reference< XFrame > xFrame;
790 xList->getByIndex(i) >>= xFrame;
792 if (xFrame.is())
794 if ( xFrame == xCurrentFrame )
795 nActiveItemId = nItemId;
797 Window* pWin = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() );
798 if ( pWin && pWin->IsVisible() )
800 aNewWindowListVector.push_back( pWin->GetText() );
801 ++nItemId;
808 ResetableGuard aGuard( _rMutex );
810 int nItemCount = pMenu->GetItemCount();
812 if ( nItemCount > 0 )
814 // remove all old window list entries from menu
815 sal_uInt16 nPos = pMenu->GetItemPos( START_ITEMID_WINDOWLIST );
816 for ( sal_uInt16 n = nPos; n < pMenu->GetItemCount(); )
817 pMenu->RemoveItem( n );
819 if ( pMenu->GetItemType( pMenu->GetItemCount()-1 ) == MENUITEM_SEPARATOR )
820 pMenu->RemoveItem( pMenu->GetItemCount()-1 );
823 if ( !aNewWindowListVector.empty() )
825 // append new window list entries to menu
826 pMenu->InsertSeparator();
827 nItemId = START_ITEMID_WINDOWLIST;
828 const sal_uInt32 nCount = aNewWindowListVector.size();
829 for ( sal_uInt32 i = 0; i < nCount; i++ )
831 pMenu->InsertItem( nItemId, aNewWindowListVector.at( i ), MIB_RADIOCHECK );
832 if ( nItemId == nActiveItemId )
833 pMenu->CheckItem( nItemId );
834 ++nItemId;
841 void MenuManager::CreatePicklistArguments( Sequence< PropertyValue >& aArgsList, const MenuItemHandler* pMenuItemHandler )
843 int NUM_OF_PICKLIST_ARGS = 3;
845 Any a;
846 aArgsList.realloc( NUM_OF_PICKLIST_ARGS );
848 aArgsList[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FileName" ));
849 a <<= pMenuItemHandler->aMenuItemURL;
850 aArgsList[0].Value = a;
852 aArgsList[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Referer" ));
853 a <<= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SFX_REFERER_USER ));
854 aArgsList[1].Value = a;
856 ::rtl::OUString aFilter( pMenuItemHandler->aFilter );
858 sal_Int32 nPos = aFilter.indexOf( '|' );
859 if ( nPos >= 0 )
861 ::rtl::OUString aFilterOptions;
863 if ( nPos < ( aFilter.getLength() - 1 ) )
864 aFilterOptions = aFilter.copy( nPos+1 );
866 aArgsList[2].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterOptions" ));
867 a <<= aFilterOptions;
868 aArgsList[2].Value = a;
870 aFilter = aFilter.copy( 0, nPos-1 );
871 aArgsList.realloc( ++NUM_OF_PICKLIST_ARGS );
874 aArgsList[NUM_OF_PICKLIST_ARGS-1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" ));
875 a <<= aFilter;
876 aArgsList[NUM_OF_PICKLIST_ARGS-1].Value = a;
880 //_________________________________________________________________________________________________________________
881 // vcl handler
882 //_________________________________________________________________________________________________________________
884 IMPL_LINK( MenuManager, Activate, Menu *, pMenu )
886 if ( pMenu == m_pVCLMenu )
888 // set/unset hiding disabled menu entries
889 sal_Bool bDontHide = SvtMenuOptions().IsEntryHidingEnabled();
890 const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
891 sal_Bool bShowMenuImages = rSettings.GetUseImagesInMenus();
893 sal_uInt16 nFlag = pMenu->GetMenuFlags();
894 if ( bDontHide )
895 nFlag &= ~MENU_FLAG_HIDEDISABLEDENTRIES;
896 else
897 nFlag |= MENU_FLAG_HIDEDISABLEDENTRIES;
898 pMenu->SetMenuFlags( nFlag );
900 if ( m_bActive )
901 return 0;
903 m_bActive = TRUE;
905 ::rtl::OUString aCommand( m_aMenuItemCommand );
906 if ( m_aMenuItemCommand.matchIgnoreAsciiCase( UNO_COMMAND, 0 ))
908 // Remove protocol part from command so we can use an easier comparision method
909 aCommand = aCommand.copy( UNO_COMMAND.getLength() );
912 if ( m_aMenuItemCommand == aSpecialFileMenu ||
913 m_aMenuItemCommand == aSlotSpecialFileMenu ||
914 aCommand == aSpecialFileCommand )
915 UpdateSpecialFileMenu( pMenu );
916 else if ( m_aMenuItemCommand == aSpecialWindowMenu ||
917 m_aMenuItemCommand == aSlotSpecialWindowMenu ||
918 aCommand == aSpecialWindowCommand )
919 UpdateSpecialWindowMenu( pMenu,getServiceFactory(),m_aLock );
921 // Check if some modes have changed so we have to update our menu images
922 sal_Bool bIsHiContrast = rSettings.GetHighContrastMode();
924 if ( m_bWasHiContrast != bIsHiContrast || bShowMenuImages != m_bShowMenuImages )
926 // The mode changed so we have to replace all images
927 m_bWasHiContrast = bIsHiContrast;
928 m_bShowMenuImages = bShowMenuImages;
929 FillMenuImages(m_xFrame,pMenu,bIsHiContrast,bShowMenuImages);
932 if ( m_bInitialized )
933 return 0;
934 else
936 URL aTargetURL;
938 // #110897#
939 ResetableGuard aGuard( m_aLock );
941 REFERENCE< XDISPATCHPROVIDER > xDispatchProvider( m_xFrame, UNO_QUERY );
942 if ( xDispatchProvider.is() )
944 std::vector< MenuItemHandler* >::iterator p;
945 for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ )
947 MenuItemHandler* pMenuItemHandler = *p;
948 if ( pMenuItemHandler &&
949 pMenuItemHandler->pSubMenuManager == 0 &&
950 !pMenuItemHandler->xMenuItemDispatch.is() )
952 // There is no dispatch mechanism for the special window list menu items,
953 // because they are handled directly through XFrame->activate!!!
954 if ( pMenuItemHandler->nItemId < START_ITEMID_WINDOWLIST ||
955 pMenuItemHandler->nItemId > END_ITEMID_WINDOWLIST )
957 ::rtl::OUString aItemCommand = pMenu->GetItemCommand( pMenuItemHandler->nItemId );
958 if ( !aItemCommand.getLength() )
960 const static ::rtl::OUString aSlotString( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
961 aItemCommand = aSlotString;
962 aItemCommand += ::rtl::OUString::valueOf( (sal_Int32)pMenuItemHandler->nItemId );
963 pMenu->SetItemCommand( pMenuItemHandler->nItemId, aItemCommand );
966 aTargetURL.Complete = aItemCommand;
968 m_xURLTransformer->parseStrict( aTargetURL );
970 REFERENCE< XDISPATCH > xMenuItemDispatch;
971 if ( m_bIsBookmarkMenu )
972 xMenuItemDispatch = xDispatchProvider->queryDispatch( aTargetURL, pMenuItemHandler->aTargetFrame, 0 );
973 else
974 xMenuItemDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 );
976 if ( xMenuItemDispatch.is() )
978 pMenuItemHandler->xMenuItemDispatch = xMenuItemDispatch;
979 pMenuItemHandler->aMenuItemURL = aTargetURL.Complete;
980 xMenuItemDispatch->addStatusListener( SAL_STATIC_CAST( XSTATUSLISTENER*, this ), aTargetURL );
982 else
983 pMenu->EnableItem( pMenuItemHandler->nItemId, sal_False );
991 return 1;
995 IMPL_LINK( MenuManager, Deactivate, Menu *, pMenu )
997 if ( pMenu == m_pVCLMenu )
998 m_bActive = sal_False;
1000 return 1;
1004 IMPL_LINK( MenuManager, Select, Menu *, pMenu )
1006 URL aTargetURL;
1007 Sequence<PropertyValue> aArgs;
1008 REFERENCE< XDISPATCH > xDispatch;
1011 ResetableGuard aGuard( m_aLock );
1013 USHORT nCurItemId = pMenu->GetCurItemId();
1014 if ( pMenu == m_pVCLMenu &&
1015 pMenu->GetItemType( nCurItemId ) != MENUITEM_SEPARATOR )
1017 if ( nCurItemId >= START_ITEMID_WINDOWLIST &&
1018 nCurItemId <= END_ITEMID_WINDOWLIST )
1020 // window list menu item selected
1022 // #110897#
1023 // Reference< XFramesSupplier > xDesktop( ::comphelper::getProcessServiceFactory()->createInstance(
1024 // DESKTOP_SERVICE ), UNO_QUERY );
1025 Reference< XFramesSupplier > xDesktop( getServiceFactory()->createInstance( SERVICENAME_DESKTOP ), UNO_QUERY );
1027 if ( xDesktop.is() )
1029 USHORT nTaskId = START_ITEMID_WINDOWLIST;
1030 Reference< XIndexAccess > xList( xDesktop->getFrames(), UNO_QUERY );
1031 sal_Int32 nCount = xList->getCount();
1032 for ( sal_Int32 i=0; i<nCount; ++i )
1034 Reference< XFrame > xFrame;
1035 xList->getByIndex(i) >>= xFrame;
1037 if ( xFrame.is() && nTaskId == nCurItemId )
1039 Window* pWin = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() );
1040 pWin->GrabFocus();
1041 pWin->ToTop( TOTOP_RESTOREWHENMIN );
1042 break;
1045 nTaskId++;
1049 else
1051 MenuItemHandler* pMenuItemHandler = GetMenuItemHandler( nCurItemId );
1052 if ( pMenuItemHandler && pMenuItemHandler->xMenuItemDispatch.is() )
1054 aTargetURL.Complete = pMenuItemHandler->aMenuItemURL;
1055 m_xURLTransformer->parseStrict( aTargetURL );
1057 if ( nCurItemId >= START_ITEMID_PICKLIST &&
1058 nCurItemId < START_ITEMID_WINDOWLIST )
1060 // picklist menu item selected
1061 CreatePicklistArguments( aArgs, pMenuItemHandler );
1063 else if ( m_bIsBookmarkMenu )
1065 // bookmark menu item selected
1066 aArgs.realloc( 1 );
1067 aArgs[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Referer" ));
1068 aArgs[0].Value <<= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SFX_REFERER_USER ));
1071 xDispatch = pMenuItemHandler->xMenuItemDispatch;
1077 if ( xDispatch.is() )
1078 xDispatch->dispatch( aTargetURL, aArgs );
1080 return 1;
1084 IMPL_LINK( MenuManager, Highlight, Menu *, EMPTYARG )
1086 return 0;
1089 // #110897#
1090 const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& MenuManager::getServiceFactory()
1092 // #110897#
1093 return mxServiceFactory;
1096 void MenuManager::AddMenu(PopupMenu* _pPopupMenu,const ::rtl::OUString& _sItemCommand,USHORT _nItemId,sal_Bool _bDelete,sal_Bool _bDeleteChildren)
1098 MenuManager* pSubMenuManager = new MenuManager( getServiceFactory(), m_xFrame, _pPopupMenu, _bDelete, _bDeleteChildren );
1100 // store menu item command as we later have to know which menu is active (see Activate handler)
1101 pSubMenuManager->m_aMenuItemCommand = _sItemCommand;
1103 REFERENCE< XDISPATCH > aXDispatchRef;
1104 MenuItemHandler* pMenuItemHandler = new MenuItemHandler(
1105 _nItemId,
1106 pSubMenuManager,
1107 aXDispatchRef );
1108 m_aMenuItemHandlerVector.push_back( pMenuItemHandler );
1111 USHORT MenuManager::FillItemCommand(::rtl::OUString& _rItemCommand,Menu* _pMenu,USHORT _nIndex) const
1113 USHORT nItemId = _pMenu->GetItemId( _nIndex );
1115 _rItemCommand = _pMenu->GetItemCommand( nItemId );
1116 if ( !_rItemCommand.getLength() )
1118 const static ::rtl::OUString aSlotString( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
1119 _rItemCommand = aSlotString;
1120 _rItemCommand += ::rtl::OUString::valueOf( (sal_Int32)nItemId );
1121 _pMenu->SetItemCommand( nItemId, _rItemCommand );
1123 return nItemId;
1125 void MenuManager::FillMenuImages(Reference< XFrame >& _xFrame,Menu* _pMenu,sal_Bool bIsHiContrast,sal_Bool bShowMenuImages)
1127 AddonsOptions aAddonOptions;
1129 for ( USHORT nPos = 0; nPos < _pMenu->GetItemCount(); nPos++ )
1131 USHORT nId = _pMenu->GetItemId( nPos );
1132 if ( _pMenu->GetItemType( nPos ) != MENUITEM_SEPARATOR )
1134 if ( bShowMenuImages )
1136 sal_Bool bImageSet = sal_False;
1137 ::rtl::OUString aImageId;
1139 ::framework::MenuConfiguration::Attributes* pMenuAttributes =
1140 (::framework::MenuConfiguration::Attributes*)_pMenu->GetUserValue( nId );
1142 if ( pMenuAttributes )
1143 aImageId = pMenuAttributes->aImageId; // Retrieve image id from menu attributes
1145 if ( aImageId.getLength() > 0 )
1147 Image aImage = GetImageFromURL( _xFrame, aImageId, FALSE, bIsHiContrast );
1148 if ( !!aImage )
1150 bImageSet = sal_True;
1151 _pMenu->SetItemImage( nId, aImage );
1155 if ( !bImageSet )
1157 rtl::OUString aMenuItemCommand = _pMenu->GetItemCommand( nId );
1158 Image aImage = GetImageFromURL( _xFrame, aMenuItemCommand, FALSE, bIsHiContrast );
1159 if ( !aImage )
1160 aImage = aAddonOptions.GetImageFromURL( aMenuItemCommand, FALSE, bIsHiContrast );
1162 _pMenu->SetItemImage( nId, aImage );
1165 else
1166 _pMenu->SetItemImage( nId, Image() );