1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: menumanager.cxx,v $
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 //_________________________________________________________________________________________________________________
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>
47 #include "classes/resource.hrc"
49 //_________________________________________________________________________________________________________________
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>
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 //_________________________________________________________________________________________________________________
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
>
103 virtual ~StringLength() {}
106 sal_Int32 SAL_CALL
queryStringWidth( const ::rtl::OUString
& aString
)
107 throw (::com::sun::star::uno::RuntimeException
)
109 return aString
.getLength();
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:" ));
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
)
147 ThreadHelpBase( &Application::GetSolarMutex() ),
148 mxServiceFactory(xServiceFactory
)
150 m_bActive
= sal_False
;
151 m_bDeleteMenu
= bDelete
;
152 m_bDeleteChildren
= bDeleteChildren
;
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
.GetMenuColor().IsDark();
161 m_bShowMenuImages
= rSettings
.GetUseImagesInMenus();
163 sal_Int32 nAddonsURLPrefixLength
= ADDONSPOPUPMENU_URL_PREFIX
.getLength();
165 ::std::vector
< USHORT
> aQueryLabelItemIdVector
;
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
);
178 AddMenu(pPopupMenu
,aItemCommand
,nItemId
,bDeleteChildren
,bDeleteChildren
);
179 if (! (( aItemCommand
.getLength() > nAddonsURLPrefixLength
) &&
180 ( aItemCommand
.indexOf( ADDONSPOPUPMENU_URL_PREFIX
) == 0 )) )
183 // MenuManager* pSubMenuManager = new MenuManager( rFrame, pPopupMenu, bDeleteChildren, bDeleteChildren );
185 if ( pMenu
->GetItemText( nItemId
).Len() == 0 )
186 aQueryLabelItemIdVector
.push_back( nItemId
);
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() )
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
);
213 // MenuManager* pSubMenuManager = new MenuManager( rFrame, pSubMenu, sal_True, sal_False );
214 AddMenu(pSubMenu
,::rtl::OUString(),nItemId
,sal_True
,sal_False
);
216 if ( pMenu
->GetItemText( nItemId
).Len() == 0 )
217 aQueryLabelItemIdVector
.push_back( nItemId
);
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
);
224 pPopupMenu
->SetItemImage( ITEMID_ADDONLIST
, aImage
);
234 if ( nItemId
== SID_NEWDOCDIRECT
||
235 aItemCommand
== aSlotNewDocDirect
)
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
);
245 // MenuManager* pSubMenuManager = new MenuManager( rFrame, pSubMenu, sal_True, sal_False );
246 AddMenu(pSubMenu
,::rtl::OUString(),nItemId
,sal_True
,sal_False
);
248 if ( pMenu
->GetItemText( nItemId
).Len() == 0 )
249 aQueryLabelItemIdVector
.push_back( nItemId
);
252 if ( m_bShowMenuImages
&& !pMenu
->GetItemImage( nItemId
))
254 Image aImage
= GetImageFromURL( rFrame
, aItemCommand
, FALSE
, m_bWasHiContrast
);
256 pMenu
->SetItemImage( nItemId
, aImage
);
259 else if ( nItemId
== SID_AUTOPILOTMENU
||
260 aItemCommand
== aSlotAutoPilot
)
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
);
270 // MenuManager* pSubMenuManager = new MenuManager( rFrame, pSubMenu, sal_True, sal_False );
271 AddMenu(pSubMenu
,::rtl::OUString(),nItemId
,sal_True
,sal_False
);
273 if ( pMenu
->GetItemText( nItemId
).Len() == 0 )
274 aQueryLabelItemIdVector
.push_back( nItemId
);
277 if ( m_bShowMenuImages
&& !pMenu
->GetItemImage( nItemId
))
279 Image aImage
= GetImageFromURL( rFrame
, aItemCommand
, FALSE
, m_bWasHiContrast
);
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
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
);
305 aImage
= GetImageFromURL( rFrame
, aItemCommand
, FALSE
, m_bWasHiContrast
);
307 aImage
= AddonsOptions().GetImageFromURL( aItemCommand
, FALSE
, m_bWasHiContrast
);
311 pMenu
->SetItemImage( nItemId
, aImage
);
313 else if ( !pMenu
->GetItemImage( nItemId
))
315 Image aImage
= GetImageFromURL( rFrame
, aItemCommand
, FALSE
, m_bWasHiContrast
);
317 pMenu
->SetItemImage( nItemId
, aImage
);
321 REFERENCE
< XDISPATCH
> aXDispatchRef
;
322 m_aMenuItemHandlerVector
.push_back( new MenuItemHandler( nItemId
, NULL
, aXDispatchRef
));
324 if ( pMenu
->GetItemText( nItemId
).Len() == 0 )
325 aQueryLabelItemIdVector
.push_back( nItemId
);
332 // retrieve label information for all menu items without item text
334 if ( aQueryLabelItemIdVector
.size() > 0 )
336 Sequence
< ::rtl::OUString
> aURLSequence( aQueryLabelItemIdVector
.size() );
337 Sequence
< ::rtl::OUString
> aLabelSequence( aQueryLabelItemIdVector
.size() );
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
);
348 xDIP
->queryDispatchInformations( aURLSequence
, aLabelSequence
);
349 for ( p
= aQueryLabelItemIdVector
.begin(); p
!= aQueryLabelItemIdVector
.end(); p
++ )
350 pMenu
->SetItemText( *p
, aLabelSequence( nPos
++ ));
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
)
362 ThreadHelpBase( &Application::GetSolarMutex() ),
363 mxServiceFactory(xServiceFactory
)
365 m_bActive
= sal_False
;
366 m_bDeleteMenu
= bDelete
;
367 m_bDeleteChildren
= bDeleteChildren
;
368 m_pVCLMenu
= pAddonMenu
;
370 m_bInitialized
= sal_False
;
371 m_bIsBookmarkMenu
= sal_True
;
373 const StyleSettings
& rSettings
= Application::GetSettings().GetStyleSettings();
374 m_bWasHiContrast
= rSettings
.GetMenuColor().IsDark();
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
);
389 // MenuManager* pSubMenuManager = new MenuManager( rFrame, pPopupMenu, bDeleteChildren, bDeleteChildren );
390 AddMenu(pPopupMenu
,aItemCommand
,nItemId
,bDeleteChildren
,bDeleteChildren
);
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
);
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();
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
)
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
;
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
;
496 m_pVCLMenu
->CheckItem( pStatusChangedMenu
->nItemId
, bCheckmark
);
502 aTargetURL
.Complete
= pStatusChangedMenu
->aMenuItemURL
;
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
);
528 void MenuManager::ClearMenuDispatch(const EVENTOBJECT
& Source
,bool _bRemoveOnly
)
530 // disposing called from parent dispatcher
531 // remove all listener to prepare shutdown
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() )
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
)
552 pItemHandler
->pSubMenuManager
->RemoveListener();
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);
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
;
586 if ( pMenuItemDisposing
)
589 aTargetURL
.Complete
= pMenuItemDisposing
->aMenuItemURL
;
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
)
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(
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() )
643 REFERENCE
< XDISPATCHPROVIDER
> xDispatchProvider( m_xFrame
, UNO_QUERY
);
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
);
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
;
714 aMenuShortCut
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "1~0: " ));
717 menuShortCut
[1] = (char)( '1' + i
);
718 aMenuShortCut
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( menuShortCut
));
723 aMenuShortCut
= rtl::OUString::valueOf((sal_Int32
)( i
+ 1 ));
724 aMenuShortCut
+= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ": " ));
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
);
745 aMenuTitle
= String( aCompactedSystemPath
);
747 aMenuTitle
= aSystemPath
;
751 // Use INetURLObject to abbreviate all other URLs
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
;
775 Reference
< XDesktop
> xDesktop( xServiceFactory
->createInstance( SERVICENAME_DESKTOP
), UNO_QUERY
);
777 USHORT nActiveItemId
= 0;
778 USHORT nItemId
= START_ITEMID_WINDOWLIST
;
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
;
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() );
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
);
841 void MenuManager::CreatePicklistArguments( Sequence
< PropertyValue
>& aArgsList
, const MenuItemHandler
* pMenuItemHandler
)
843 int NUM_OF_PICKLIST_ARGS
= 3;
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( '|' );
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" ));
876 aArgsList
[NUM_OF_PICKLIST_ARGS
-1].Value
= a
;
880 //_________________________________________________________________________________________________________________
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();
895 nFlag
&= ~MENU_FLAG_HIDEDISABLEDENTRIES
;
897 nFlag
|= MENU_FLAG_HIDEDISABLEDENTRIES
;
898 pMenu
->SetMenuFlags( nFlag
);
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
.GetMenuColor().IsDark();
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
)
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 );
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
);
983 pMenu
->EnableItem( pMenuItemHandler
->nItemId
, sal_False
);
995 IMPL_LINK( MenuManager
, Deactivate
, Menu
*, pMenu
)
997 if ( pMenu
== m_pVCLMenu
)
998 m_bActive
= sal_False
;
1004 IMPL_LINK( MenuManager
, Select
, Menu
*, pMenu
)
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
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() );
1041 pWin
->ToTop( TOTOP_RESTOREWHENMIN
);
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
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
);
1084 IMPL_LINK( MenuManager
, Highlight
, Menu
*, EMPTYARG
)
1090 const ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XMultiServiceFactory
>& MenuManager::getServiceFactory()
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(
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
);
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
);
1150 bImageSet
= sal_True
;
1151 _pMenu
->SetItemImage( nId
, aImage
);
1157 rtl::OUString aMenuItemCommand
= _pMenu
->GetItemCommand( nId
);
1158 Image aImage
= GetImageFromURL( _xFrame
, aMenuItemCommand
, FALSE
, bIsHiContrast
);
1160 aImage
= aAddonOptions
.GetImageFromURL( aMenuItemCommand
, FALSE
, bIsHiContrast
);
1162 _pMenu
->SetItemImage( nId
, aImage
);
1166 _pMenu
->SetItemImage( nId
, Image() );