xref: /trunk/main/framework/source/uielement/menubarmanager.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_framework.hxx"
26 
27 //_________________________________________________________________________________________________________________
28 //  my own includes
29 //_________________________________________________________________________________________________________________
30 #include <uielement/menubarmanager.hxx>
31 #include <framework/menuconfiguration.hxx>
32 #include <framework/bmkmenu.hxx>
33 #include <framework/addonmenu.hxx>
34 #include <framework/imageproducer.hxx>
35 #include <threadhelp/resetableguard.hxx>
36 #include "framework/addonsoptions.hxx"
37 #include <classes/fwkresid.hxx>
38 #include <classes/menumanager.hxx>
39 #include <framework/acceleratorinfo.hxx>
40 #include <helper/mischelper.hxx>
41 #include <framework/menuextensionsupplier.hxx>
42 #include <classes/resource.hrc>
43 #include <services.h>
44 
45 //_________________________________________________________________________________________________________________
46 //  interface includes
47 //_________________________________________________________________________________________________________________
48 #include <com/sun/star/frame/XDispatch.hpp>
49 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
50 #include <com/sun/star/lang/DisposedException.hpp>
51 #include <com/sun/star/beans/XPropertySet.hpp>
52 #include <com/sun/star/frame/XFramesSupplier.hpp>
53 #include <com/sun/star/frame/XDesktop.hpp>
54 #include <com/sun/star/container/XEnumeration.hpp>
55 #include <com/sun/star/util/XStringWidth.hpp>
56 #include <com/sun/star/uno/XComponentContext.hpp>
57 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
58 #include <com/sun/star/frame/XPopupMenuController.hpp>
59 #include <com/sun/star/frame/PopupMenuControllerFactory.hpp>
60 #ifndef _COM_SUN_STAR_LANG_XSYSTEMDEPENDENT_HPP_
61 #include <com/sun/star/lang/SystemDependent.hpp>
62 #endif
63 #include <com/sun/star/ui/ItemType.hpp>
64 #include <com/sun/star/ui/ImageType.hpp>
65 #include <com/sun/star/container/XNameAccess.hpp>
66 #include <com/sun/star/frame/XModuleManager.hpp>
67 #include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp>
68 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
69 #include <com/sun/star/ui/ItemStyle.hpp>
70 #include <com/sun/star/frame/status/Visibility.hpp>
71 
72 //_________________________________________________________________________________________________________________
73 //  includes of other projects
74 //_________________________________________________________________________________________________________________
75 #include <comphelper/processfactory.hxx>
76 #include <comphelper/extract.hxx>
77 #include <svtools/menuoptions.hxx>
78 #include <unotools/historyoptions.hxx>
79 #include <unotools/pathoptions.hxx>
80 #include <unotools/cmdoptions.hxx>
81 #include <unotools/localfilehelper.hxx>
82 #ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_
83 #include <toolkit/helper/vclunohelper.hxx>
84 #endif
85 #include <tools/urlobj.hxx>
86 #include <vcl/svapp.hxx>
87 #include <vcl/window.hxx>
88 #include <vos/mutex.hxx>
89 #include <vcl/svapp.hxx>
90 #include <osl/file.hxx>
91 #include <cppuhelper/implbase1.hxx>
92 #include <svtools/acceleratorexecute.hxx>
93 #include <rtl/logfile.hxx>
94 #include "svtools/miscopt.hxx"
95 #include <framework/addonmenu.hxx>
96 #include <uielement/menubarmerger.hxx>
97 #include <dispatch/uieventloghelper.hxx>
98 
99 // Be careful removing this "bad" construct. There are serious problems
100 // with #define STRICT and including windows.h. Changing this needs some
101 // redesign on other projects, too. Especially sal/main.h which defines
102 // HINSTANCE depending on STRICT!!!!!!!!!!!!!!!
103 struct SystemMenuData
104 {
105     unsigned long nSize;
106     long          hMenu;
107 };
108 
109 //_________________________________________________________________________________________________________________
110 //  namespace
111 //_________________________________________________________________________________________________________________
112 
113 using namespace ::cppu;
114 using namespace ::vos;
115 using namespace ::com::sun::star;
116 using namespace ::com::sun::star::uno;
117 using namespace ::com::sun::star::util;
118 using namespace ::com::sun::star::beans;
119 using namespace ::com::sun::star::frame;
120 using namespace ::com::sun::star::container;
121 using namespace ::com::sun::star::lang;
122 using namespace ::com::sun::star::frame;
123 using namespace ::com::sun::star::ui;
124 
125 static const char ITEM_DESCRIPTOR_COMMANDURL[]        = "CommandURL";
126 static const char ITEM_DESCRIPTOR_HELPURL[]           = "HelpURL";
127 static const char ITEM_DESCRIPTOR_CONTAINER[]         = "ItemDescriptorContainer";
128 static const char ITEM_DESCRIPTOR_LABEL[]             = "Label";
129 static const char ITEM_DESCRIPTOR_TYPE[]              = "Type";
130 static const char ITEM_DESCRIPTOR_MODULEIDENTIFIER[]  = "ModuleIdentifier";
131 static const char ITEM_DESCRIPTOR_DISPATCHPROVIDER[]  = "DispatchProvider";
132 static const char ITEM_DESCRIPTOR_STYLE[]             = "Style";
133 static const char ITEM_DESCRIPTOR_ISVISIBLE[]         = "IsVisible";
134 static const char ITEM_DESCRIPTOR_ENABLED[]           = "Enabled";
135 
136 static const sal_Int32 LEN_DESCRIPTOR_COMMANDURL       = 10;
137 static const sal_Int32 LEN_DESCRIPTOR_HELPURL          = 7;
138 static const sal_Int32 LEN_DESCRIPTOR_CONTAINER        = 23;
139 static const sal_Int32 LEN_DESCRIPTOR_LABEL            = 5;
140 static const sal_Int32 LEN_DESCRIPTOR_TYPE             = 4;
141 static const sal_Int32 LEN_DESCRIPTOR_MODULEIDENTIFIER = 16;
142 static const sal_Int32 LEN_DESCRIPTOR_DISPATCHPROVIDER = 16;
143 static const sal_Int32 LEN_DESCRIPTOR_STYLE            = 5;
144 static const sal_Int32 LEN_DESCRIPTOR_ISVISIBLE        = 9;
145 static const sal_Int32 LEN_DESCRIPTOR_ENABLED          = 7;
146 
147 const sal_uInt16 ADDONMENU_MERGE_ITEMID_START = 1500;
148 
149 class StringLength : public ::cppu::WeakImplHelper1< ::com::sun::star::util::XStringWidth >
150 {
151     public:
StringLength()152         StringLength() {}
~StringLength()153         virtual ~StringLength() {}
154 
155         // XStringWidth
queryStringWidth(const::rtl::OUString & aString)156         sal_Int32 SAL_CALL queryStringWidth( const ::rtl::OUString& aString )
157         {
158             return aString.getLength();
159         }
160 };
161 
162 namespace framework
163 {
164 
165 // special menu ids/command ids for dynamic popup menus
166 #define SID_SFX_START           5000
167 #define SID_NEWDOCDIRECT        (SID_SFX_START + 537)
168 #define SID_AUTOPILOTMENU       (SID_SFX_START + 1381)
169 #define SID_PICKLIST            (SID_SFX_START + 510)
170 #define SID_MDIWINDOWLIST       (SID_SFX_START + 610)
171 #define SID_ADDONLIST           (SID_SFX_START + 1677)
172 #define SID_HELPMENU            (SID_SFX_START + 410)
173 
174 #define SFX_REFERER_USER        "private:user"
175 
176 const ::rtl::OUString aCmdHelpIndex( RTL_CONSTASCII_USTRINGPARAM( ".uno:HelpIndex" ));
177 const ::rtl::OUString aCmdToolsMenu( RTL_CONSTASCII_USTRINGPARAM( ".uno:ToolsMenu" ));
178 const ::rtl::OUString aCmdHelpMenu( RTL_CONSTASCII_USTRINGPARAM( ".uno:HelpMenu" ));
179 const ::rtl::OUString aSlotHelpMenu( RTL_CONSTASCII_USTRINGPARAM( "slot:5410" ));
180 
181 const ::rtl::OUString aSpecialFileMenu( RTL_CONSTASCII_USTRINGPARAM( "file" ));
182 const ::rtl::OUString aSpecialWindowMenu( RTL_CONSTASCII_USTRINGPARAM( "window" ));
183 const ::rtl::OUString aSlotSpecialFileMenu( RTL_CONSTASCII_USTRINGPARAM( "slot:5510" ));
184 const ::rtl::OUString aSlotSpecialWindowMenu( RTL_CONSTASCII_USTRINGPARAM( "slot:5610" ));
185 const ::rtl::OUString aSlotSpecialToolsMenu( RTL_CONSTASCII_USTRINGPARAM( "slot:6677" ));
186 
187 // special uno commands for picklist and window list
188 const ::rtl::OUString aSpecialFileCommand( RTL_CONSTASCII_USTRINGPARAM( ".uno:PickList" ));
189 const ::rtl::OUString aSpecialWindowCommand( RTL_CONSTASCII_USTRINGPARAM( ".uno:WindowList" ));
190 
191 const ::rtl::OUString UNO_COMMAND( RTL_CONSTASCII_USTRINGPARAM( ".uno:" ));
192 
getImageTypeFromBools(sal_Bool bBig,sal_Bool bHighContrast)193 static sal_Int16 getImageTypeFromBools( sal_Bool bBig, sal_Bool bHighContrast )
194 {
195     sal_Int16 n( 0 );
196     if ( bBig )
197         n |= ::com::sun::star::ui::ImageType::SIZE_LARGE;
198     if ( bHighContrast )
199         n |= ::com::sun::star::ui::ImageType::COLOR_HIGHCONTRAST;
200     return n;
201 }
202 
203 // #110897#
MenuBarManager(const Reference<XMultiServiceFactory> & xServiceFactory,const Reference<XFrame> & rFrame,const Reference<XURLTransformer> & _xURLTransformer,const Reference<XDispatchProvider> & rDispatchProvider,const rtl::OUString & rModuleIdentifier,Menu * pMenu,sal_Bool bDelete,sal_Bool bDeleteChildren)204 MenuBarManager::MenuBarManager(
205     const Reference< XMultiServiceFactory >& xServiceFactory,
206     const Reference< XFrame >& rFrame,
207     const Reference< XURLTransformer >& _xURLTransformer,
208     const Reference< XDispatchProvider >& rDispatchProvider,
209     const rtl::OUString& rModuleIdentifier,
210     Menu* pMenu, sal_Bool bDelete, sal_Bool bDeleteChildren )
211 : ThreadHelpBase( &Application::GetSolarMutex() ), OWeakObject()
212     , m_bDisposed( sal_False )
213     , m_bRetrieveImages( sal_False )
214     , m_bAcceleratorCfg( sal_False )
215     , m_bModuleIdentified( sal_False )
216     , m_aListenerContainer( m_aLock.getShareableOslMutex() )
217     , mxServiceFactory(xServiceFactory)
218     , m_xURLTransformer(_xURLTransformer)
219     , m_nSymbolsStyle( SvtMiscOptions().GetCurrentSymbolsStyle() )
220 {
221     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::MenuBarManager" );
222     m_xPopupMenuControllerFactory = frame::PopupMenuControllerFactory::create(
223         ::comphelper::getProcessComponentContext() );
224     FillMenuManager( pMenu, rFrame, rDispatchProvider, rModuleIdentifier, bDelete, bDeleteChildren );
225 }
226 
227 // #110897#
MenuBarManager(const Reference<XMultiServiceFactory> & xServiceFactory,const Reference<XFrame> & rFrame,const Reference<XURLTransformer> & _xURLTransformer,AddonMenu * pAddonMenu,sal_Bool bDelete,sal_Bool bDeleteChildren)228 MenuBarManager::MenuBarManager(
229     const Reference< XMultiServiceFactory >& xServiceFactory,
230     const Reference< XFrame >& rFrame,
231     const Reference< XURLTransformer >& _xURLTransformer,
232     AddonMenu* pAddonMenu,
233     sal_Bool bDelete,
234     sal_Bool bDeleteChildren )
235 :   ThreadHelpBase( &Application::GetSolarMutex() )
236     , OWeakObject()
237     , m_bDisposed( sal_False )
238     , m_bRetrieveImages( sal_True )
239     , m_bAcceleratorCfg( sal_False )
240     , m_bModuleIdentified( sal_False )
241     , m_aListenerContainer( m_aLock.getShareableOslMutex() )
242     , mxServiceFactory(xServiceFactory)
243     , m_xURLTransformer(_xURLTransformer)
244     , m_nSymbolsStyle( SvtMiscOptions().GetCurrentSymbolsStyle() )
245 {
246     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::MenuBarManager" );
247     Init(rFrame,pAddonMenu,bDelete,bDeleteChildren);
248 }
249 
250 // #110897#
MenuBarManager(const Reference<XMultiServiceFactory> & xServiceFactory,const Reference<XFrame> & rFrame,const Reference<XURLTransformer> & _xURLTransformer,AddonPopupMenu * pAddonPopupMenu,sal_Bool bDelete,sal_Bool bDeleteChildren)251 MenuBarManager::MenuBarManager(
252     const Reference< XMultiServiceFactory >& xServiceFactory,
253     const Reference< XFrame >& rFrame,
254     const Reference< XURLTransformer >& _xURLTransformer,
255     AddonPopupMenu* pAddonPopupMenu,
256     sal_Bool bDelete,
257     sal_Bool bDeleteChildren )
258 :     ThreadHelpBase( &Application::GetSolarMutex() )
259     , OWeakObject()
260     , m_bDisposed( sal_False )
261     , m_bRetrieveImages( sal_True )
262     , m_bAcceleratorCfg( sal_False )
263     , m_bModuleIdentified( sal_False )
264     , m_aListenerContainer( m_aLock.getShareableOslMutex() )
265     , mxServiceFactory(xServiceFactory)
266     , m_xURLTransformer(_xURLTransformer)
267     , m_nSymbolsStyle( SvtMiscOptions().GetCurrentSymbolsStyle() )
268 {
269     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::MenuBarManager" );
270     Init(rFrame,pAddonPopupMenu,bDelete,bDeleteChildren,true);
271 }
272 
queryInterface(const Type & rType)273 Any SAL_CALL MenuBarManager::queryInterface( const Type & rType )
274 {
275     Any a = ::cppu::queryInterface(
276                 rType ,
277                 SAL_STATIC_CAST( ::com::sun::star::frame::XStatusListener*, this ),
278                 SAL_STATIC_CAST( ::com::sun::star::frame::XFrameActionListener*, this ),
279                 SAL_STATIC_CAST( ::com::sun::star::ui::XUIConfigurationListener*, this ),
280                 SAL_STATIC_CAST( XEventListener*, (XStatusListener *)this ),
281                 SAL_STATIC_CAST( XComponent*, this ),
282                 SAL_STATIC_CAST( ::com::sun::star::awt::XSystemDependentMenuPeer*, this ));
283 
284     if ( a.hasValue() )
285         return a;
286 
287     return OWeakObject::queryInterface( rType );
288 }
289 
290 
acquire()291 void SAL_CALL MenuBarManager::acquire() throw()
292 {
293     OWeakObject::acquire();
294 }
295 
296 
release()297 void SAL_CALL MenuBarManager::release() throw()
298 {
299     OWeakObject::release();
300 }
301 
302 
getMenuHandle(const Sequence<sal_Int8> &,sal_Int16 SystemType)303 Any SAL_CALL MenuBarManager::getMenuHandle( const Sequence< sal_Int8 >& /*ProcessId*/, sal_Int16 SystemType )
304 {
305     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::getMenuHandle" );
306     ResetableGuard aGuard( m_aLock );
307 
308     if ( m_bDisposed )
309         throw com::sun::star::lang::DisposedException();
310 
311     Any a;
312 
313     if ( m_pVCLMenu )
314     {
315         OGuard  aSolarGuard( Application::GetSolarMutex() );
316 
317         SystemMenuData aSystemMenuData;
318         aSystemMenuData.nSize = sizeof( SystemMenuData );
319 
320         m_pVCLMenu->GetSystemMenuData( &aSystemMenuData );
321 #ifdef QUARTZ
322         if( SystemType == SystemDependent::SYSTEM_MAC )
323         {
324         }
325 #elif (defined WNT)
326         if( SystemType == SystemDependent::SYSTEM_WIN32 )
327         {
328             a <<= (long) aSystemMenuData.hMenu;
329         }
330 #elif (defined UNX)
331         if( SystemType == SystemDependent::SYSTEM_XWINDOW )
332         {
333         }
334 #endif
335     }
336 
337     return a;
338 }
339 
~MenuBarManager()340 MenuBarManager::~MenuBarManager()
341 {
342     // stop asynchronous settings timer
343     m_xDeferedItemContainer.clear();
344     m_aAsyncSettingsTimer.Stop();
345 
346     DBG_ASSERT( OWeakObject::m_refCount == 0, "Who wants to delete an object with refcount > 0!" );
347 }
348 
Destroy()349 void MenuBarManager::Destroy()
350 {
351     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::Destroy" );
352     OGuard  aGuard( Application::GetSolarMutex() );
353 
354     if ( !m_bDisposed )
355     {
356         // stop asynchronous settings timer and
357         // release deferred item container reference
358         m_aAsyncSettingsTimer.Stop();
359         m_xDeferedItemContainer.clear();
360         RemoveListener();
361 
362         std::vector< MenuItemHandler* >::iterator p;
363         for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ )
364         {
365             MenuItemHandler* pItemHandler = *p;
366             pItemHandler->xMenuItemDispatch.clear();
367             pItemHandler->xSubMenuManager.clear();
368             pItemHandler->xPopupMenu.clear();
369             delete pItemHandler;
370         }
371         m_aMenuItemHandlerVector.clear();
372 
373         if ( m_bDeleteMenu )
374         {
375             delete m_pVCLMenu;
376             m_pVCLMenu = 0;
377         }
378     }
379 }
380 
381 // XComponent
dispose()382 void SAL_CALL MenuBarManager::dispose()
383 {
384     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::dispose" );
385     Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY );
386 
387     EventObject aEvent( xThis );
388     m_aListenerContainer.disposeAndClear( aEvent );
389 
390     {
391         ResetableGuard aGuard( m_aLock );
392 //        RemoveListener();
393         Destroy();
394         m_bDisposed = sal_True;
395 
396         if ( m_xDocImageManager.is() )
397         {
398             try
399             {
400                 m_xDocImageManager->removeConfigurationListener(
401                     Reference< XUIConfigurationListener >(
402                         static_cast< OWeakObject* >( this ), UNO_QUERY ));
403             }
404             catch ( Exception& )
405             {
406             }
407         }
408         if ( m_xModuleImageManager.is() )
409         {
410             try
411             {
412                 m_xModuleImageManager->removeConfigurationListener(
413                     Reference< XUIConfigurationListener >(
414                         static_cast< OWeakObject* >( this ), UNO_QUERY ));
415             }
416             catch ( Exception& )
417             {
418             }
419         }
420         m_xDocImageManager.clear();
421         m_xModuleImageManager.clear();
422         Reference< XComponent > xCompGAM( m_xGlobalAcceleratorManager, UNO_QUERY );
423         if ( xCompGAM.is() )
424             xCompGAM->dispose();
425         m_xGlobalAcceleratorManager.clear();
426         m_xModuleAcceleratorManager.clear();
427         m_xDocAcceleratorManager.clear();
428         m_xUICommandLabels.clear();
429         m_xPopupMenuControllerFactory.clear();
430         mxServiceFactory.clear();
431     }
432 }
433 
addEventListener(const Reference<XEventListener> & xListener)434 void SAL_CALL MenuBarManager::addEventListener( const Reference< XEventListener >& xListener )
435 {
436     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::addEventListener" );
437     ResetableGuard aGuard( m_aLock );
438 
439     /* SAFE AREA ----------------------------------------------------------------------------------------------- */
440     if ( m_bDisposed )
441         throw DisposedException();
442 
443     m_aListenerContainer.addInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), xListener );
444 }
445 
removeEventListener(const Reference<XEventListener> & xListener)446 void SAL_CALL MenuBarManager::removeEventListener( const Reference< XEventListener >& xListener )
447 {
448     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::removeEventListener" );
449     ResetableGuard aGuard( m_aLock );
450     /* SAFE AREA ----------------------------------------------------------------------------------------------- */
451     m_aListenerContainer.removeInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), xListener );
452 }
453 
elementInserted(const::com::sun::star::ui::ConfigurationEvent & Event)454 void SAL_CALL MenuBarManager::elementInserted( const ::com::sun::star::ui::ConfigurationEvent& Event )
455 {
456     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::elementInserted" );
457     ResetableGuard aGuard( m_aLock );
458 
459     /* SAFE AREA ----------------------------------------------------------------------------------------------- */
460     if ( m_bDisposed )
461         return;
462 
463     sal_Int16 nImageType = sal_Int16();
464     sal_Int16 nCurrentImageType = getImageTypeFromBools( sal_False, m_bWasHiContrast );
465     if (( Event.aInfo >>= nImageType ) &&
466         ( nImageType == nCurrentImageType ))
467         RequestImages();
468 }
469 
elementRemoved(const::com::sun::star::ui::ConfigurationEvent & Event)470 void SAL_CALL MenuBarManager::elementRemoved( const ::com::sun::star::ui::ConfigurationEvent& Event )
471 {
472     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::elementRemoved" );
473     elementInserted(Event);
474 }
475 
elementReplaced(const::com::sun::star::ui::ConfigurationEvent & Event)476 void SAL_CALL MenuBarManager::elementReplaced( const ::com::sun::star::ui::ConfigurationEvent& Event )
477 {
478     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::elementReplaced" );
479     elementInserted(Event);
480 }
481 
482 // XFrameActionListener
frameAction(const FrameActionEvent & Action)483 void SAL_CALL MenuBarManager::frameAction( const FrameActionEvent& Action )
484 {
485     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::frameAction" );
486     ResetableGuard aGuard( m_aLock );
487 
488     if ( m_bDisposed )
489         throw com::sun::star::lang::DisposedException();
490 
491     if ( Action.Action == FrameAction_CONTEXT_CHANGED )
492     {
493         std::vector< MenuItemHandler* >::iterator p;
494         for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ )
495         {
496             // Clear dispatch reference as we will requery it later on
497             MenuItemHandler* pItemHandler = *p;
498             pItemHandler->xMenuItemDispatch.clear();
499         }
500     }
501 }
502 
503 // XStatusListener
statusChanged(const FeatureStateEvent & Event)504 void SAL_CALL MenuBarManager::statusChanged( const FeatureStateEvent& Event )
505 {
506     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::statusChanged" );
507     ::rtl::OUString aFeatureURL = Event.FeatureURL.Complete;
508 
509     OGuard  aSolarGuard( Application::GetSolarMutex() );
510     {
511         ResetableGuard aGuard( m_aLock );
512 
513         if ( m_bDisposed )
514             return;
515 
516         // We have to check all menu entries as there can be identical entries in a popup menu.
517         std::vector< MenuItemHandler* >::iterator p;
518         for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ )
519         {
520             MenuItemHandler* pMenuItemHandler = *p;
521             if ( pMenuItemHandler->aMenuItemURL == aFeatureURL )
522             {
523                 sal_Bool            bCheckmark( sal_False );
524                 sal_Bool            bMenuItemEnabled( m_pVCLMenu->IsItemEnabled( pMenuItemHandler->nItemId ));
525                 sal_Bool            bEnabledItem( Event.IsEnabled );
526                 rtl::OUString       aItemText;
527                 status::Visibility  aVisibilityStatus;
528 
529                 #ifdef UNIX
530                 // #b6673979# enable some slots hardly, because UNIX clipboard does not notify all changes
531                 // Can be removed if follow up task will be fixed directly within applications.
532                 if (
533                     ( pMenuItemHandler->aMenuItemURL.equalsAscii (".uno:Paste"         ) ) ||
534                     ( pMenuItemHandler->aMenuItemURL.equalsAscii (".uno:PasteSpecial"  ) ) ||
535                     ( pMenuItemHandler->aMenuItemURL.equalsAscii (".uno:PasteClipboard") )      // special for draw/impress
536                    )
537                     bEnabledItem = sal_True;
538                 #endif
539 
540                 // Enable/disable item
541                 if ( bEnabledItem != bMenuItemEnabled )
542                     m_pVCLMenu->EnableItem( pMenuItemHandler->nItemId, bEnabledItem );
543 
544                 if ( Event.State >>= bCheckmark )
545                 {
546                     // Checkmark or RadioButton
547                     m_pVCLMenu->ShowItem( pMenuItemHandler->nItemId, sal_True );
548                     m_pVCLMenu->CheckItem( pMenuItemHandler->nItemId, bCheckmark );
549 
550                     MenuItemBits nBits = m_pVCLMenu->GetItemBits( pMenuItemHandler->nItemId );
551                     //If not already designated RadioButton set as CheckMark
552                     if (!(nBits & MIB_RADIOCHECK))
553                         m_pVCLMenu->SetItemBits( pMenuItemHandler->nItemId, nBits | MIB_CHECKABLE );
554                 }
555                 else if ( Event.State >>= aItemText )
556                 {
557                     // Replacement for place holders
558                     if ( aItemText.matchAsciiL( "($1)", 4 ))
559                     {
560                         String aResStr = String( FwkResId( STR_UPDATEDOC ));
561                         rtl::OUString aTmp( aResStr );
562                         aTmp += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ));
563                         aTmp += aItemText.copy( 4 );
564                         aItemText = aTmp;
565                     }
566                     else if ( aItemText.matchAsciiL( "($2)", 4 ))
567                     {
568                         String aResStr = String( FwkResId( STR_CLOSEDOC_ANDRETURN ));
569                         rtl::OUString aTmp( aResStr );
570                         aTmp += aItemText.copy( 4 );
571                         aItemText = aTmp;
572                     }
573                     else if ( aItemText.matchAsciiL( "($3)", 4 ))
574                     {
575                         String aResStr = String( FwkResId( STR_SAVECOPYDOC ));
576                         rtl::OUString aTmp( aResStr );
577                         aTmp += aItemText.copy( 4 );
578                         aItemText = aTmp;
579                     }
580 
581                     m_pVCLMenu->ShowItem( pMenuItemHandler->nItemId, sal_True );
582                     m_pVCLMenu->SetItemText( pMenuItemHandler->nItemId, aItemText );
583                 }
584                 else if ( Event.State >>= aVisibilityStatus )
585                 {
586                     // Visibility
587                     m_pVCLMenu->ShowItem( pMenuItemHandler->nItemId, aVisibilityStatus.bVisible );
588                 }
589                 else
590                     m_pVCLMenu->ShowItem( pMenuItemHandler->nItemId, sal_True );
591             }
592 
593             if ( Event.Requery )
594             {
595                 // Release dispatch object - will be requeried on the next activate!
596                 pMenuItemHandler->xMenuItemDispatch.clear();
597             }
598         }
599     }
600 }
601 
602 // Helper to retrieve own structure from item ID
GetMenuItemHandler(sal_uInt16 nItemId)603 MenuBarManager::MenuItemHandler* MenuBarManager::GetMenuItemHandler( sal_uInt16 nItemId )
604 {
605     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::GetMenuItemHandler" );
606     ResetableGuard aGuard( m_aLock );
607 
608     std::vector< MenuItemHandler* >::iterator p;
609     for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ )
610     {
611         MenuItemHandler* pItemHandler = *p;
612         if ( pItemHandler->nItemId == nItemId )
613             return pItemHandler;
614     }
615 
616     return 0;
617 }
618 
619 // Helper to set request images flag
RequestImages()620 void MenuBarManager::RequestImages()
621 {
622     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::RequestImages" );
623     // must be locked from callee
624     // ResetableGuard aGuard( m_aLock );
625 
626     m_bRetrieveImages = sal_True;
627     const sal_uInt32 nCount = m_aMenuItemHandlerVector.size();
628     for ( sal_uInt32 i = 0; i < nCount; ++i )
629     {
630         MenuItemHandler* pItemHandler = m_aMenuItemHandlerVector[i];
631         if ( pItemHandler->xSubMenuManager.is() )
632         {
633             MenuBarManager* pMenuBarManager = (MenuBarManager*)(pItemHandler->xSubMenuManager.get());
634             pMenuBarManager->RequestImages();
635         }
636     }
637 }
638 
639 // Helper to reset objects to prepare shutdown
RemoveListener()640 void MenuBarManager::RemoveListener()
641 {
642     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::RemoveListener" );
643     ResetableGuard aGuard( m_aLock );
644 
645     // Check service manager reference. Remove listener can be called due
646     // to a disposing call from the frame and therefore we already removed
647     // our listeners and released the service manager reference!
648     Reference< XMultiServiceFactory > xServiceManager = getServiceFactory();
649     if ( xServiceManager.is() )
650     {
651         std::vector< MenuItemHandler* >::iterator p;
652         for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ )
653         {
654             MenuItemHandler* pItemHandler = *p;
655             if ( pItemHandler->xMenuItemDispatch.is() )
656             {
657                 URL aTargetURL;
658                 aTargetURL.Complete = pItemHandler->aMenuItemURL;
659                 m_xURLTransformer->parseStrict( aTargetURL );
660 
661                 pItemHandler->xMenuItemDispatch->removeStatusListener(
662                     static_cast< XStatusListener* >( this ), aTargetURL );
663             }
664 
665             pItemHandler->xMenuItemDispatch.clear();
666             if ( pItemHandler->xPopupMenu.is() )
667             {
668                 {
669                     // Remove popup menu from menu structure
670                     OGuard  aGuard2( Application::GetSolarMutex() );
671                     m_pVCLMenu->SetPopupMenu( pItemHandler->nItemId, 0 );
672                 }
673 
674                 Reference< com::sun::star::lang::XEventListener > xEventListener( pItemHandler->xPopupMenuController, UNO_QUERY );
675                 if ( xEventListener.is() )
676                 {
677                     EventObject aEventObject;
678                     aEventObject.Source = (OWeakObject *)this;
679                     xEventListener->disposing( aEventObject );
680                 }
681 
682                 // We now provide a popup menu controller to external code.
683                 // Therefore the life-time must be explicitly handled via
684                 // dispose!!
685                 try
686                 {
687                     Reference< XComponent > xComponent( pItemHandler->xPopupMenuController, UNO_QUERY );
688                     if ( xComponent.is() )
689                         xComponent->dispose();
690                 }
691                 catch ( RuntimeException& )
692                 {
693                     throw;
694                 }
695                 catch ( Exception& )
696                 {
697                 }
698 
699                 // Release references to controller and popup menu
700                 pItemHandler->xPopupMenuController.clear();
701                 pItemHandler->xPopupMenu.clear();
702             }
703 
704             Reference< XComponent > xComponent( pItemHandler->xSubMenuManager, UNO_QUERY );
705             if ( xComponent.is() )
706                 xComponent->dispose();
707         }
708     }
709 
710     try
711     {
712         if ( m_xFrame.is() )
713             m_xFrame->removeFrameActionListener( Reference< XFrameActionListener >(
714                                                     static_cast< OWeakObject* >( this ), UNO_QUERY ));
715     }
716     catch ( Exception& )
717     {
718     }
719 
720     m_xFrame = 0;
721 }
722 
disposing(const EventObject & Source)723 void SAL_CALL MenuBarManager::disposing( const EventObject& Source )
724 {
725     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::disposing(evt)" );
726     MenuItemHandler* pMenuItemDisposing = NULL;
727 
728     ResetableGuard aGuard( m_aLock );
729 
730     std::vector< MenuItemHandler* >::iterator p;
731     for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ )
732     {
733         MenuItemHandler* pMenuItemHandler = *p;
734         if ( pMenuItemHandler->xMenuItemDispatch.is() &&
735              pMenuItemHandler->xMenuItemDispatch == Source.Source )
736         {
737             // disposing called from menu item dispatcher, remove listener
738             pMenuItemDisposing = pMenuItemHandler;
739             break;
740         }
741     }
742 
743     if ( pMenuItemDisposing )
744     {
745         // Release references to the dispatch object
746         URL aTargetURL;
747         aTargetURL.Complete = pMenuItemDisposing->aMenuItemURL;
748 
749         // Check reference of service manager before we use it. Reference could
750         // be cleared due to RemoveListener call!
751         Reference< XMultiServiceFactory > xServiceManager( getServiceFactory() );
752         if ( xServiceManager.is() )
753         {
754             m_xURLTransformer->parseStrict( aTargetURL );
755 
756             pMenuItemDisposing->xMenuItemDispatch->removeStatusListener(
757                 static_cast< XStatusListener* >( this ), aTargetURL );
758             pMenuItemDisposing->xMenuItemDispatch = Reference< XDispatch >();
759             if ( pMenuItemDisposing->xPopupMenu.is() )
760             {
761                 Reference< com::sun::star::lang::XEventListener > xEventListener( pMenuItemDisposing->xPopupMenuController, UNO_QUERY );
762                 if ( xEventListener.is() )
763                     xEventListener->disposing( Source );
764 
765                 {
766                     // Remove popup menu from menu structure as we release our reference to
767                     // the controller.
768                     OGuard  aGuard2( Application::GetSolarMutex() );
769                     m_pVCLMenu->SetPopupMenu( pMenuItemDisposing->nItemId, 0 );
770                 }
771 
772                 pMenuItemDisposing->xPopupMenuController.clear();
773                 pMenuItemDisposing->xPopupMenu.clear();
774             }
775         }
776         return;
777     }
778     else if ( Source.Source == m_xFrame )
779     {
780         // Our frame gets disposed. We have to remove all our listeners
781         RemoveListener();
782     }
783     else if ( Source.Source == Reference< XInterface >( m_xDocImageManager, UNO_QUERY ))
784         m_xDocImageManager.clear();
785     else if ( Source.Source == Reference< XInterface >( m_xModuleImageManager, UNO_QUERY ))
786         m_xModuleImageManager.clear();
787 }
788 
789 
CheckAndAddMenuExtension(Menu * pMenu)790 void MenuBarManager::CheckAndAddMenuExtension( Menu* pMenu )
791 {
792     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::CheckAndAddMenuExtension" );
793     static const char REFERENCECOMMAND_AFTER[]          = ".uno:HelpSupport";
794     static const char REFERENCECOMMAND_BEFORE[]         = ".uno:About";
795 
796     // retrieve menu extension item
797     MenuExtensionItem aMenuItem( GetMenuExtension() );
798     if (( aMenuItem.aURL.getLength() > 0 ) &&
799         ( aMenuItem.aLabel.getLength() > 0 ))
800     {
801         // remove all old window list entries from menu
802         sal_uInt16 nNewItemId( 0 );
803         sal_uInt16 nInsertPos( MENU_APPEND );
804         sal_uInt16 nAfterPos( MENU_APPEND );
805         sal_uInt16 nBeforePos( MENU_APPEND );
806         String     aCommandAfter( String::CreateFromAscii ( REFERENCECOMMAND_AFTER ));
807         String     aCommandBefore( String::CreateFromAscii ( REFERENCECOMMAND_BEFORE ));
808         for ( sal_uInt16 n = 0; n < pMenu->GetItemCount(); n++ )
809         {
810             sal_uInt16 nItemId = pMenu->GetItemId( n );
811             nNewItemId = std::max( nItemId, nNewItemId );
812             if ( pMenu->GetItemCommand( nItemId ) == aCommandAfter )
813                 nAfterPos = n+1;
814             else if ( pMenu->GetItemCommand( nItemId ) == aCommandBefore )
815                 nBeforePos = n;
816         }
817         ++nNewItemId;
818 
819         if ( nAfterPos != MENU_APPEND )
820             nInsertPos = nAfterPos;
821         else if ( nBeforePos != MENU_APPEND )
822             nInsertPos = nBeforePos;
823 
824         pMenu->InsertItem( nNewItemId, aMenuItem.aLabel, 0, nInsertPos );
825         pMenu->SetItemCommand( nNewItemId, aMenuItem.aURL );
826     }
827 }
828 
lcl_CheckForChildren(Menu * pMenu,sal_uInt16 nItemId)829 static void lcl_CheckForChildren(Menu* pMenu, sal_uInt16 nItemId)
830 {
831     if (PopupMenu* pThisPopup = pMenu->GetPopupMenu( nItemId ))
832         pMenu->EnableItem( nItemId, pThisPopup->GetItemCount() ? true : false );
833 }
834 
835 //_________________________________________________________________________________________________________________
836 // vcl handler
837 //_________________________________________________________________________________________________________________
838 
IMPL_LINK(MenuBarManager,Activate,Menu *,pMenu)839 IMPL_LINK( MenuBarManager, Activate, Menu *, pMenu )
840 {
841     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::Activate" );
842     if ( pMenu == m_pVCLMenu )
843     {
844         // set/unset hiding disabled menu entries
845         sal_Bool bDontHide           = SvtMenuOptions().IsEntryHidingEnabled();
846         const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
847         sal_Bool bShowMenuImages     = rSettings.GetUseImagesInMenus();
848         sal_Bool bHasDisabledEntries = SvtCommandOptions().HasEntries( SvtCommandOptions::CMDOPTION_DISABLED );
849 
850         ResetableGuard aGuard( m_aLock );
851 
852         sal_uInt16 nFlag = pMenu->GetMenuFlags();
853         if ( bDontHide )
854             nFlag &= ~MENU_FLAG_HIDEDISABLEDENTRIES;
855         else
856             nFlag |= MENU_FLAG_HIDEDISABLEDENTRIES;
857         pMenu->SetMenuFlags( nFlag );
858 
859         if ( m_bActive )
860             return 0;
861 
862         m_bActive = sal_True;
863 
864         ::rtl::OUString aMenuCommand( m_aMenuItemCommand );
865         if ( m_aMenuItemCommand == aSpecialWindowMenu ||
866              m_aMenuItemCommand == aSlotSpecialWindowMenu ||
867              aMenuCommand == aSpecialWindowCommand )
868              MenuManager::UpdateSpecialWindowMenu( pMenu,getServiceFactory(),m_aLock );
869 
870         // Check if some modes have changed so we have to update our menu images
871         sal_Bool bIsHiContrast = rSettings.GetHighContrastMode();
872         sal_Int16 nSymbolsStyle = SvtMiscOptions().GetCurrentSymbolsStyle();
873 
874         if ( m_bRetrieveImages ||
875              m_bWasHiContrast != bIsHiContrast ||
876              bShowMenuImages != m_bShowMenuImages ||
877              nSymbolsStyle != m_nSymbolsStyle )
878         {
879             // The mode changed so we have to replace all images
880             m_bWasHiContrast    = bIsHiContrast;
881             m_bShowMenuImages   = bShowMenuImages;
882             m_bRetrieveImages   = sal_False;
883             m_nSymbolsStyle     = nSymbolsStyle;
884             MenuManager::FillMenuImages(m_xFrame,pMenu,bIsHiContrast,bShowMenuImages);
885         }
886 
887         // Try to map commands to labels
888         for ( sal_uInt16 nPos = 0; nPos < pMenu->GetItemCount(); nPos++ )
889         {
890             sal_uInt16 nItemId = pMenu->GetItemId( nPos );
891             if (( pMenu->GetItemType( nPos ) != MENUITEM_SEPARATOR ) &&
892                 ( pMenu->GetItemText( nItemId ).Len() == 0 ))
893             {
894                 String aCommand = pMenu->GetItemCommand( nItemId );
895                 if ( aCommand.Len() > 0 )
896                     pMenu->SetItemText( nItemId, RetrieveLabelFromCommand( aCommand ));
897             }
898         }
899 
900         // Try to set accelerator keys
901         {
902             RetrieveShortcuts( m_aMenuItemHandlerVector );
903             std::vector< MenuItemHandler* >::iterator p;
904             for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ )
905             {
906                 MenuItemHandler* pMenuItemHandler = *p;
907 
908                 // Set key code, workaround for hard-coded shortcut F1 mapped to .uno:HelpIndex
909                 // Only non-popup menu items can have a short-cut
910                 if ( pMenuItemHandler->aMenuItemURL == aCmdHelpIndex )
911                 {
912                     KeyCode aKeyCode( KEY_F1 );
913                     pMenu->SetAccelKey( pMenuItemHandler->nItemId, aKeyCode );
914                 }
915                 else if ( pMenu->GetPopupMenu( pMenuItemHandler->nItemId ) == 0 )
916                     pMenu->SetAccelKey( pMenuItemHandler->nItemId, pMenuItemHandler->aKeyCode );
917             }
918         }
919 
920         URL aTargetURL;
921 
922         // Use provided dispatch provider => fallback to frame as dispatch provider
923         Reference< XDispatchProvider > xDispatchProvider;
924         if ( m_xDispatchProvider.is() )
925             xDispatchProvider = m_xDispatchProvider;
926         else
927             xDispatchProvider = Reference< XDispatchProvider >( m_xFrame, UNO_QUERY );
928 
929         if ( xDispatchProvider.is() )
930         {
931             KeyCode             aEmptyKeyCode;
932             SvtCommandOptions   aCmdOptions;
933             std::vector< MenuItemHandler* >::iterator p;
934             for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ )
935             {
936                 MenuItemHandler* pMenuItemHandler = *p;
937                 if ( pMenuItemHandler )
938                 {
939                     if ( !pMenuItemHandler->xMenuItemDispatch.is() &&
940                          !pMenuItemHandler->xSubMenuManager.is()      )
941                     {
942                         // There is no dispatch mechanism for the special window list menu items,
943                         // because they are handled directly through XFrame->activate!!!
944                         // Don't update dispatches for special file menu items.
945                         if ( !(( pMenuItemHandler->nItemId >= START_ITEMID_WINDOWLIST &&
946                                  pMenuItemHandler->nItemId < END_ITEMID_WINDOWLIST )))
947                         {
948                             Reference< XDispatch > xMenuItemDispatch;
949 
950                             ::rtl::OUString aItemCommand = pMenu->GetItemCommand( pMenuItemHandler->nItemId );
951                             if ( !aItemCommand.getLength() )
952                             {
953                                 aItemCommand = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
954                                 aItemCommand += ::rtl::OUString::valueOf( (sal_Int32)pMenuItemHandler->nItemId );
955                                 pMenu->SetItemCommand( pMenuItemHandler->nItemId, aItemCommand );
956                             }
957 
958                             aTargetURL.Complete = aItemCommand;
959 
960                             m_xURLTransformer->parseStrict( aTargetURL );
961 
962                             if ( bHasDisabledEntries )
963                             {
964                                 if ( aCmdOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED, aTargetURL.Path ))
965                                     pMenu->HideItem( pMenuItemHandler->nItemId );
966                             }
967 
968                             if ( m_bIsBookmarkMenu )
969                                 xMenuItemDispatch = xDispatchProvider->queryDispatch( aTargetURL, pMenuItemHandler->aTargetFrame, 0 );
970                             else
971                                 xMenuItemDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 );
972 
973                             sal_Bool bPopupMenu( sal_False );
974                             if ( !pMenuItemHandler->xPopupMenuController.is() &&
975                                  m_xPopupMenuControllerFactory->hasController( aItemCommand, rtl::OUString() ))
976                             {
977                                 bPopupMenu = CreatePopupMenuController( pMenuItemHandler );
978                             }
979                             else if ( pMenuItemHandler->xPopupMenuController.is() )
980                             {
981                                 // Force update of popup menu
982                                 pMenuItemHandler->xPopupMenuController->updatePopupMenu();
983                                 bPopupMenu = sal_True;
984                                 if (PopupMenu* pThisPopup = pMenu->GetPopupMenu( pMenuItemHandler->nItemId ))
985                                     pMenu->EnableItem( pMenuItemHandler->nItemId, pThisPopup->GetItemCount() ? true : false );
986                             }
987 
988                             lcl_CheckForChildren(pMenu, pMenuItemHandler->nItemId);
989 
990                             if ( xMenuItemDispatch.is() )
991                             {
992                                 pMenuItemHandler->xMenuItemDispatch = xMenuItemDispatch;
993                                 pMenuItemHandler->aMenuItemURL      = aTargetURL.Complete;
994 
995                                 if ( !bPopupMenu )
996                                 {
997                                     // We need only an update to reflect the current state
998                                     xMenuItemDispatch->addStatusListener( static_cast< XStatusListener* >( this ), aTargetURL );
999                                     xMenuItemDispatch->removeStatusListener( static_cast< XStatusListener* >( this ), aTargetURL );
1000                                 }
1001                             }
1002                             else if ( !bPopupMenu )
1003                                 pMenu->EnableItem( pMenuItemHandler->nItemId, sal_False );
1004                         }
1005                     }
1006                     else if ( pMenuItemHandler->xPopupMenuController.is() )
1007                     {
1008                         // Force update of popup menu
1009                         pMenuItemHandler->xPopupMenuController->updatePopupMenu();
1010                         lcl_CheckForChildren(pMenu, pMenuItemHandler->nItemId);
1011                     }
1012                     else if ( pMenuItemHandler->xMenuItemDispatch.is() )
1013                     {
1014                         // We need an update to reflect the current state
1015                         try
1016                         {
1017                             aTargetURL.Complete = pMenuItemHandler->aMenuItemURL;
1018                             m_xURLTransformer->parseStrict( aTargetURL );
1019 
1020                             pMenuItemHandler->xMenuItemDispatch->addStatusListener(
1021                                                                     static_cast< XStatusListener* >( this ), aTargetURL );
1022                             pMenuItemHandler->xMenuItemDispatch->removeStatusListener(
1023                                                                     static_cast< XStatusListener* >( this ), aTargetURL );
1024                         }
1025                         catch ( Exception& )
1026                         {
1027                         }
1028                     }
1029                     else if ( pMenuItemHandler->xSubMenuManager.is() )
1030                         lcl_CheckForChildren(pMenu, pMenuItemHandler->nItemId);
1031                 }
1032             }
1033         }
1034     }
1035 
1036     return 1;
1037 }
1038 
1039 
IMPL_LINK(MenuBarManager,Deactivate,Menu *,pMenu)1040 IMPL_LINK( MenuBarManager, Deactivate, Menu *, pMenu )
1041 {
1042     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::Deactivate" );
1043     if ( pMenu == m_pVCLMenu )
1044     {
1045         m_bActive = sal_False;
1046         if ( pMenu->IsMenuBar() && m_xDeferedItemContainer.is() )
1047         {
1048             // Start timer to handle settings asynchronous
1049             // Changing the menu inside this handler leads to
1050             // a crash under X!
1051             m_aAsyncSettingsTimer.SetTimeoutHdl(LINK(this, MenuBarManager, AsyncSettingsHdl));
1052             m_aAsyncSettingsTimer.SetTimeout(10);
1053             m_aAsyncSettingsTimer.Start();
1054         }
1055     }
1056 
1057     return 1;
1058 }
1059 
1060 IMPL_LINK( MenuBarManager, AsyncSettingsHdl, Timer*,)
1061 {
1062     OGuard  aGuard( Application::GetSolarMutex() );
1063     Reference< XInterface > xSelfHold(
1064         static_cast< ::cppu::OWeakObject* >( this ), UNO_QUERY_THROW );
1065 
1066     m_aAsyncSettingsTimer.Stop();
1067     if ( !m_bActive && m_xDeferedItemContainer.is() )
1068     {
1069         SetItemContainer( m_xDeferedItemContainer );
1070         m_xDeferedItemContainer.clear();
1071     }
1072 
1073     return 0;
1074 }
1075 
IMPL_LINK(MenuBarManager,Select,Menu *,pMenu)1076 IMPL_LINK( MenuBarManager, Select, Menu *, pMenu )
1077 {
1078     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::Select" );
1079     URL                     aTargetURL;
1080     Sequence<PropertyValue> aArgs;
1081     Reference< XDispatch >  xDispatch;
1082 
1083     {
1084         ResetableGuard aGuard( m_aLock );
1085 
1086         sal_uInt16 nCurItemId = pMenu->GetCurItemId();
1087         sal_uInt16 nCurPos    = pMenu->GetItemPos( nCurItemId );
1088         if ( pMenu == m_pVCLMenu &&
1089              pMenu->GetItemType( nCurPos ) != MENUITEM_SEPARATOR )
1090         {
1091             if ( nCurItemId >= START_ITEMID_WINDOWLIST &&
1092                  nCurItemId <= END_ITEMID_WINDOWLIST )
1093             {
1094                 // window list menu item selected
1095 
1096                 // #110897#
1097                 // Reference< XFramesSupplier > xDesktop( ::comphelper::getProcessServiceFactory()->createInstance( DESKTOP_SERVICE ), UNO_QUERY );
1098                 Reference< XFramesSupplier > xDesktop( getServiceFactory()->createInstance( SERVICENAME_DESKTOP ), UNO_QUERY );
1099 
1100                 if ( xDesktop.is() )
1101                 {
1102                     sal_uInt16 nTaskId = START_ITEMID_WINDOWLIST;
1103                     Reference< XIndexAccess > xList( xDesktop->getFrames(), UNO_QUERY );
1104                     sal_Int32 nCount = xList->getCount();
1105                     for ( sal_Int32 i=0; i<nCount; ++i )
1106                     {
1107                         Reference< XFrame > xFrame;
1108                         xList->getByIndex(i) >>= xFrame;
1109                         if ( xFrame.is() && nTaskId == nCurItemId )
1110                         {
1111                             Window* pWin = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() );
1112                             pWin->GrabFocus();
1113                             pWin->ToTop( TOTOP_RESTOREWHENMIN );
1114                             break;
1115                         }
1116 
1117                         nTaskId++;
1118                     }
1119                 }
1120             }
1121             else
1122             {
1123                 MenuItemHandler* pMenuItemHandler = GetMenuItemHandler( nCurItemId );
1124                 if ( pMenuItemHandler && pMenuItemHandler->xMenuItemDispatch.is() )
1125                 {
1126                     aTargetURL.Complete = pMenuItemHandler->aMenuItemURL;
1127                     m_xURLTransformer->parseStrict( aTargetURL );
1128 
1129                     aArgs.realloc( 1 );
1130                     aArgs[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Referer" ));
1131                     aArgs[0].Value <<= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SFX_REFERER_USER ));
1132 
1133                     xDispatch = pMenuItemHandler->xMenuItemDispatch;
1134                 }
1135             }
1136         }
1137     }
1138 
1139     if ( xDispatch.is() )
1140     {
1141         const sal_uInt32 nRef = Application::ReleaseSolarMutex();
1142         if(::comphelper::UiEventsLogger::isEnabled()) //#i88653#
1143             UiEventLogHelper(::rtl::OUString::createFromAscii("MenuBarManager")).log(getServiceFactory(), m_xFrame, aTargetURL, aArgs);
1144         xDispatch->dispatch( aTargetURL, aArgs );
1145         Application::AcquireSolarMutex( nRef );
1146     }
1147 
1148     return 1;
1149 }
1150 
1151 
IMPL_LINK(MenuBarManager,Highlight,Menu *,EMPTYARG)1152 IMPL_LINK( MenuBarManager, Highlight, Menu *, EMPTYARG )
1153 {
1154     return 0;
1155 }
1156 
MustBeHidden(PopupMenu * pPopupMenu,const Reference<XURLTransformer> & rTransformer)1157 sal_Bool MenuBarManager::MustBeHidden( PopupMenu* pPopupMenu, const Reference< XURLTransformer >& rTransformer )
1158 {
1159     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::MustBeHidden" );
1160     if ( pPopupMenu )
1161     {
1162         URL               aTargetURL;
1163         SvtCommandOptions aCmdOptions;
1164 
1165         sal_uInt16 nCount = pPopupMenu->GetItemCount();
1166         sal_uInt16 nHideCount( 0 );
1167 
1168         for ( sal_uInt16 i = 0; i < nCount; i++ )
1169         {
1170             sal_uInt16 nId = pPopupMenu->GetItemId( i );
1171             if ( nId > 0 )
1172             {
1173                 PopupMenu* pSubPopupMenu = pPopupMenu->GetPopupMenu( nId );
1174                 if ( pSubPopupMenu )
1175                 {
1176                     if ( MustBeHidden( pSubPopupMenu, rTransformer ))
1177                     {
1178                         pPopupMenu->HideItem( nId );
1179                         ++nHideCount;
1180                     }
1181                 }
1182                 else
1183                 {
1184                     aTargetURL.Complete = pPopupMenu->GetItemCommand( nId );
1185                     rTransformer->parseStrict( aTargetURL );
1186 
1187                     if ( aCmdOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED, aTargetURL.Path ))
1188                         ++nHideCount;
1189                 }
1190             }
1191             else
1192                 ++nHideCount;
1193         }
1194 
1195         return ( nCount == nHideCount );
1196     }
1197 
1198     return sal_True;
1199 }
RetrieveLabelFromCommand(const String & aCmdURL)1200 String MenuBarManager::RetrieveLabelFromCommand( const String& aCmdURL )
1201 {
1202     return framework::RetrieveLabelFromCommand(aCmdURL,mxServiceFactory,m_xUICommandLabels,m_xFrame,m_aModuleIdentifier,m_bModuleIdentified,"Label");
1203 }
1204 
1205 
1206 
CreatePopupMenuController(MenuItemHandler * pMenuItemHandler)1207 sal_Bool MenuBarManager::CreatePopupMenuController( MenuItemHandler* pMenuItemHandler )
1208 {
1209     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::CreatePopupMenuController" );
1210     rtl::OUString aItemCommand( pMenuItemHandler->aMenuItemURL );
1211 
1212     // Try instantiate a popup menu controller. It is stored in the menu item handler.
1213     if ( !m_xPopupMenuControllerFactory.is() )
1214         return sal_False;
1215 
1216     Sequence< Any > aSeq( 2 );
1217     PropertyValue aPropValue;
1218 
1219     aPropValue.Name         = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ModuleIdentifier" ));
1220     aPropValue.Value      <<= m_aModuleIdentifier;
1221     aSeq[0] <<= aPropValue;
1222     aPropValue.Name         = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" ));
1223     aPropValue.Value      <<= m_xFrame;
1224     aSeq[1] <<= aPropValue;
1225 
1226     Reference< XComponentContext > xComponentContext;
1227     Reference< XPropertySet >      xProps( getServiceFactory(), UNO_QUERY );
1228 
1229     xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>=
1230         xComponentContext;
1231 
1232     Reference< XPopupMenuController > xPopupMenuController(
1233                                             m_xPopupMenuControllerFactory->createInstanceWithArgumentsAndContext(
1234                                                 aItemCommand,
1235                                                 aSeq,
1236                                                 xComponentContext ),
1237                                             UNO_QUERY );
1238 
1239     if ( xPopupMenuController.is() )
1240     {
1241         // Provide our awt popup menu to the popup menu controller
1242         pMenuItemHandler->xPopupMenuController = xPopupMenuController;
1243         xPopupMenuController->setPopupMenu( pMenuItemHandler->xPopupMenu );
1244         return sal_True;
1245     }
1246 
1247     return sal_False;
1248 }
1249 
FillMenuManager(Menu * pMenu,const Reference<XFrame> & rFrame,const Reference<XDispatchProvider> & rDispatchProvider,const rtl::OUString & rModuleIdentifier,sal_Bool bDelete,sal_Bool bDeleteChildren)1250 void MenuBarManager::FillMenuManager( Menu* pMenu, const Reference< XFrame >& rFrame, const Reference< XDispatchProvider >& rDispatchProvider, const rtl::OUString& rModuleIdentifier, sal_Bool bDelete, sal_Bool bDeleteChildren )
1251 {
1252     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::FillMenuManager" );
1253     m_xFrame            = rFrame;
1254     m_bActive           = sal_False;
1255     m_bDeleteMenu       = bDelete;
1256     m_bDeleteChildren   = bDeleteChildren;
1257     m_pVCLMenu          = pMenu;
1258     m_bInitialized      = sal_False;
1259     m_bIsBookmarkMenu   = sal_False;
1260     m_xDispatchProvider = rDispatchProvider;
1261 
1262     const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
1263     m_bWasHiContrast    = rSettings.GetHighContrastMode();
1264     m_bShowMenuImages   = rSettings.GetUseImagesInMenus();
1265     m_bRetrieveImages   = sal_False;
1266 
1267     sal_Int32 nAddonsURLPrefixLength = ADDONSPOPUPMENU_URL_PREFIX.getLength();
1268 
1269     // Add root as ui configuration listener
1270     RetrieveImageManagers();
1271 
1272     if ( pMenu->IsMenuBar() && rFrame.is() )
1273     {
1274         // First merge all addon popup menus into our structure
1275         sal_uInt16 nPos = 0;
1276         for ( nPos = 0; nPos < pMenu->GetItemCount(); nPos++ )
1277         {
1278             sal_uInt16          nItemId  = pMenu->GetItemId( nPos );
1279             ::rtl::OUString aCommand = pMenu->GetItemCommand( nItemId );
1280             if ( nItemId == SID_MDIWINDOWLIST ||
1281                  aCommand == aSpecialWindowCommand )
1282             {
1283                 // Retrieve addon popup menus and add them to our menu bar
1284                 framework::AddonMenuManager::MergeAddonPopupMenus( rFrame, nPos, (MenuBar *)pMenu, mxServiceFactory );
1285                 break;
1286             }
1287         }
1288 
1289         // Merge the Add-Ons help menu items into the Office help menu
1290         framework::AddonMenuManager::MergeAddonHelpMenu( rFrame, (MenuBar *)pMenu, mxServiceFactory );
1291     }
1292 
1293     String      aEmpty;
1294     sal_Bool    bAccessibilityEnabled( Application::GetSettings().GetMiscSettings().GetEnableATToolSupport() );
1295     sal_uInt16 nItemCount = pMenu->GetItemCount();
1296     ::rtl::OUString aItemCommand;
1297     m_aMenuItemHandlerVector.reserve(nItemCount);
1298     for ( sal_uInt16 i = 0; i < nItemCount; i++ )
1299     {
1300         sal_uInt16 nItemId = FillItemCommand(aItemCommand,pMenu, i );
1301 
1302         // Set module identifier when provided from outside
1303         if ( rModuleIdentifier.getLength() > 0 )
1304         {
1305             m_aModuleIdentifier = rModuleIdentifier;
1306             m_bModuleIdentified = sal_True;
1307         }
1308 
1309         if (( pMenu->IsMenuBar() || bAccessibilityEnabled ) &&
1310             ( pMenu->GetItemText( nItemId ).Len() == 0 ))
1311         {
1312             if ( aItemCommand.getLength() > 0 )
1313                 pMenu->SetItemText( nItemId, RetrieveLabelFromCommand( aItemCommand ));
1314         }
1315 
1316         Reference< XDispatch > xDispatch;
1317         Reference< XStatusListener > xStatusListener;
1318         PopupMenu* pPopup = pMenu->GetPopupMenu( nItemId );
1319         bool bItemShowMenuImages = m_bShowMenuImages;
1320         MenuItemBits nBits = pMenu->GetItemBits( nItemId );
1321         // overwrite the show icons on menu option?
1322         if ( nBits )
1323             bItemShowMenuImages = ( ( nBits & MIB_ICON ) == MIB_ICON );
1324         if ( pPopup )
1325         {
1326             // Retrieve module identifier from Help Command entry
1327             rtl::OUString aModuleIdentifier( rModuleIdentifier );
1328             if ( pMenu->GetHelpCommand( nItemId ).Len() > 0 )
1329             {
1330                 aModuleIdentifier = pMenu->GetHelpCommand( nItemId );
1331                 pMenu->SetHelpCommand( nItemId, aEmpty );
1332             }
1333 
1334             if ( m_xPopupMenuControllerFactory.is() &&
1335                  pPopup->GetItemCount() == 0 &&
1336                  m_xPopupMenuControllerFactory->hasController( aItemCommand, rtl::OUString() )
1337                   )
1338             {
1339                 // Check if we have to create a popup menu for a uno based popup menu controller.
1340                 // We have to set an empty popup menu into our menu structure so the controller also
1341                 // works with inplace OLE. Remove old dummy popup menu!
1342                 MenuItemHandler* pItemHandler = new MenuItemHandler( nItemId, xStatusListener, xDispatch );
1343                 VCLXPopupMenu* pVCLXPopupMenu = new VCLXPopupMenu;
1344                 PopupMenu* pNewPopupMenu = (PopupMenu *)pVCLXPopupMenu->GetMenu();
1345                 pMenu->SetPopupMenu( nItemId, pNewPopupMenu );
1346                 pItemHandler->xPopupMenu = Reference< com::sun::star::awt::XPopupMenu >( (OWeakObject *)pVCLXPopupMenu, UNO_QUERY );
1347                 pItemHandler->aMenuItemURL = aItemCommand;
1348                 m_aMenuItemHandlerVector.push_back( pItemHandler );
1349                 delete pPopup;
1350 
1351                 if ( bAccessibilityEnabled )
1352                 {
1353                     if ( CreatePopupMenuController( pItemHandler ))
1354                         pItemHandler->xPopupMenuController->updatePopupMenu();
1355                 }
1356                 lcl_CheckForChildren(pMenu, nItemId);
1357             }
1358             else if (( aItemCommand.getLength() > nAddonsURLPrefixLength ) &&
1359                      ( aItemCommand.indexOf( ADDONSPOPUPMENU_URL_PREFIX ) == 0 ))
1360             {
1361                 // A special addon popup menu, must be created with a different ctor
1362                 // #110897#
1363                 MenuBarManager* pSubMenuManager = new MenuBarManager( getServiceFactory(), m_xFrame, m_xURLTransformer,(AddonPopupMenu *)pPopup, bDeleteChildren, bDeleteChildren );
1364                 AddMenu(pSubMenuManager,aItemCommand,nItemId);
1365             }
1366             else
1367             {
1368                 Reference< XDispatchProvider > xPopupMenuDispatchProvider( rDispatchProvider );
1369 
1370                 // Retrieve possible attributes struct
1371                 MenuConfiguration::Attributes* pAttributes = (MenuConfiguration::Attributes *)(pMenu->GetUserValue( nItemId ));
1372                 if ( pAttributes )
1373                     xPopupMenuDispatchProvider = pAttributes->xDispatchProvider;
1374 
1375                 // Check if this is the help menu. Add menu item if needed
1376                 if ( nItemId == SID_HELPMENU || aItemCommand == aSlotHelpMenu || aItemCommand == aCmdHelpMenu )
1377                 {
1378                     // Check if this is the help menu. Add menu item if needed
1379                     CheckAndAddMenuExtension( pPopup );
1380                 }
1381                 else if (( nItemId == SID_ADDONLIST || aItemCommand == aSlotSpecialToolsMenu || aItemCommand == aCmdToolsMenu ) &&
1382                          AddonMenuManager::HasAddonMenuElements() )
1383                 {
1384                     // Create addon popup menu if there exist elements and this is the tools popup menu
1385                     sal_uInt16      nCount   = 0;
1386                     AddonMenu*  pSubMenu = AddonMenuManager::CreateAddonMenu( rFrame, mxServiceFactory );
1387                     if ( pSubMenu && ( pSubMenu->GetItemCount() > 0 ))
1388                     {
1389                         if ( pPopup->GetItemType( nCount-1 ) != MENUITEM_SEPARATOR )
1390                             pPopup->InsertSeparator();
1391 
1392                         // Use resource to load popup menu title
1393                         String aAddonsStrRes = String( FwkResId( STR_MENU_ADDONS ));
1394                         pPopup->InsertItem( ITEMID_ADDONLIST, aAddonsStrRes );
1395                         pPopup->SetPopupMenu( ITEMID_ADDONLIST, pSubMenu );
1396 
1397                         // Set item command for popup menu to enable it for GetImageFromURL
1398                         const ::rtl::OUString aSlotString( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
1399                         ::rtl::OUString aNewItemCommand( aSlotString );
1400                         aNewItemCommand += ::rtl::OUString::valueOf( (sal_Int32)ITEMID_ADDONLIST );
1401                         pPopup->SetItemCommand( ITEMID_ADDONLIST, aNewItemCommand );
1402                     }
1403                     else
1404                         delete pSubMenu;
1405                 }
1406 
1407                 if ( nItemId == ITEMID_ADDONLIST )
1408                 {
1409                     // Create control structure within the "Tools" sub menu for the Add-Ons popup menu
1410                     // #110897# MenuBarManager* pSubMenuManager = new MenuBarManager( rFrame, pSubMenu, sal_True, sal_False );
1411                     AddonMenu* pSubMenu = dynamic_cast< AddonMenu* >( pPopup );
1412                     if ( pSubMenu )
1413                     {
1414                         MenuBarManager* pSubMenuManager = new MenuBarManager( getServiceFactory(), m_xFrame, m_xURLTransformer,pSubMenu, sal_True, sal_False );
1415                         AddMenu(pSubMenuManager,aItemCommand,nItemId);
1416                         pSubMenuManager->m_aMenuItemCommand = ::rtl::OUString();
1417 
1418                         // Set image for the addon popup menu item
1419                         if ( bItemShowMenuImages && !pPopup->GetItemImage( ITEMID_ADDONLIST ))
1420                         {
1421                             Reference< XFrame > xTemp( rFrame );
1422                             Image aImage = GetImageFromURL( xTemp, aItemCommand, sal_False, m_bWasHiContrast );
1423                             if ( !!aImage )
1424                                 pPopup->SetItemImage( ITEMID_ADDONLIST, aImage );
1425                         }
1426                     }
1427                 }
1428                 else
1429                 {
1430                     // #110897# MenuBarManager* pSubMenuManager = new MenuBarManager( rFrame, pPopupMenu, bDeleteChildren, bDeleteChildren );
1431                     MenuBarManager* pSubMenuMgr = new MenuBarManager( getServiceFactory(), rFrame, m_xURLTransformer,rDispatchProvider, aModuleIdentifier, pPopup, bDeleteChildren, bDeleteChildren );
1432                     AddMenu(pSubMenuMgr,aItemCommand,nItemId);
1433                 }
1434             }
1435         }
1436         else if ( pMenu->GetItemType( i ) != MENUITEM_SEPARATOR )
1437         {
1438             if ( bItemShowMenuImages )
1439             {
1440                 if ( AddonMenuManager::IsAddonMenuId( nItemId ))
1441                 {
1442                     // Add-Ons uses images from different places
1443                     Image           aImage;
1444                     rtl::OUString   aImageId;
1445 
1446                     MenuConfiguration::Attributes* pMenuAttributes =
1447                         (MenuConfiguration::Attributes*)pMenu->GetUserValue( nItemId );
1448 
1449                     if ( pMenuAttributes && pMenuAttributes->aImageId.getLength() > 0 )
1450                     {
1451                         // Retrieve image id from menu attributes
1452                         aImage = GetImageFromURL( m_xFrame, aImageId, sal_False, m_bWasHiContrast );
1453                     }
1454 
1455                     if ( !aImage )
1456                     {
1457                         aImage = GetImageFromURL( m_xFrame, aItemCommand, sal_False, m_bWasHiContrast );
1458                         if ( !aImage )
1459                             aImage = AddonsOptions().GetImageFromURL( aItemCommand, sal_False, m_bWasHiContrast );
1460                     }
1461 
1462                     if ( !!aImage )
1463                         pMenu->SetItemImage( nItemId, aImage );
1464                     else
1465                         m_bRetrieveImages = sal_True;
1466                 }
1467                 m_bRetrieveImages = sal_True;
1468             }
1469 
1470             MenuItemHandler* pItemHandler = new MenuItemHandler( nItemId, xStatusListener, xDispatch );
1471             pItemHandler->aMenuItemURL = aItemCommand;
1472 
1473             if ( m_xPopupMenuControllerFactory.is() &&
1474                  m_xPopupMenuControllerFactory->hasController( aItemCommand, rtl::OUString() ))
1475             {
1476                 // Check if we have to create a popup menu for a uno based popup menu controller.
1477                 // We have to set an empty popup menu into our menu structure so the controller also
1478                 // works with inplace OLE.
1479                 VCLXPopupMenu* pVCLXPopupMenu = new VCLXPopupMenu;
1480                 PopupMenu* pPopupMenu = (PopupMenu *)pVCLXPopupMenu->GetMenu();
1481                 pMenu->SetPopupMenu( pItemHandler->nItemId, pPopupMenu );
1482                 pItemHandler->xPopupMenu = Reference< com::sun::star::awt::XPopupMenu >( (OWeakObject *)pVCLXPopupMenu, UNO_QUERY );
1483 
1484                 if ( bAccessibilityEnabled && CreatePopupMenuController( pItemHandler ) )
1485                 {
1486                     pItemHandler->xPopupMenuController->updatePopupMenu();
1487                 }
1488 
1489                 lcl_CheckForChildren(pMenu, pItemHandler->nItemId);
1490             }
1491 
1492             m_aMenuItemHandlerVector.push_back( pItemHandler );
1493         }
1494     }
1495 
1496     if ( bAccessibilityEnabled )
1497     {
1498         RetrieveShortcuts( m_aMenuItemHandlerVector );
1499         std::vector< MenuItemHandler* >::iterator p;
1500         for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ )
1501         {
1502             MenuItemHandler* pMenuItemHandler = *p;
1503 
1504             // Set key code, workaround for hard-coded shortcut F1 mapped to .uno:HelpIndex
1505             // Only non-popup menu items can have a short-cut
1506             if ( pMenuItemHandler->aMenuItemURL == aCmdHelpIndex )
1507             {
1508                 KeyCode aKeyCode( KEY_F1 );
1509                 pMenu->SetAccelKey( pMenuItemHandler->nItemId, aKeyCode );
1510             }
1511             else if ( pMenu->GetPopupMenu( pMenuItemHandler->nItemId ) == 0 )
1512                 pMenu->SetAccelKey( pMenuItemHandler->nItemId, pMenuItemHandler->aKeyCode );
1513         }
1514     }
1515 
1516     SetHdl();
1517 }
1518 
impl_RetrieveShortcutsFromConfiguration(const Reference<XAcceleratorConfiguration> & rAccelCfg,const Sequence<rtl::OUString> & rCommands,std::vector<MenuItemHandler * > & aMenuShortCuts)1519 void MenuBarManager::impl_RetrieveShortcutsFromConfiguration(
1520     const Reference< XAcceleratorConfiguration >& rAccelCfg,
1521     const Sequence< rtl::OUString >& rCommands,
1522     std::vector< MenuItemHandler* >& aMenuShortCuts )
1523 {
1524     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::impl_RetrieveShortcutsFromConfiguration" );
1525     if ( rAccelCfg.is() )
1526     {
1527         try
1528         {
1529             com::sun::star::awt::KeyEvent aKeyEvent;
1530             Sequence< Any > aSeqKeyCode = rAccelCfg->getPreferredKeyEventsForCommandList( rCommands );
1531             for ( sal_Int32 i = 0; i < aSeqKeyCode.getLength(); i++ )
1532             {
1533                 if ( aSeqKeyCode[i] >>= aKeyEvent )
1534                     aMenuShortCuts[i]->aKeyCode = svt::AcceleratorExecute::st_AWTKey2VCLKey( aKeyEvent );
1535             }
1536         }
1537         catch ( IllegalArgumentException& )
1538         {
1539         }
1540     }
1541 }
1542 
RetrieveShortcuts(std::vector<MenuItemHandler * > & aMenuShortCuts)1543 void MenuBarManager::RetrieveShortcuts( std::vector< MenuItemHandler* >& aMenuShortCuts )
1544 {
1545     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::RetrieveShortcuts" );
1546     if ( !m_bModuleIdentified )
1547     {
1548         m_bModuleIdentified = sal_True;
1549         Reference< XModuleManager > xModuleManager;
1550         xModuleManager = Reference< XModuleManager >( getServiceFactory()->createInstance( SERVICENAME_MODULEMANAGER ), UNO_QUERY_THROW );
1551 
1552         try
1553         {
1554             m_aModuleIdentifier = xModuleManager->identify( m_xFrame );
1555         }
1556         catch( Exception& )
1557         {
1558         }
1559     }
1560 
1561     if ( m_bModuleIdentified )
1562     {
1563         Reference< XAcceleratorConfiguration > xDocAccelCfg( m_xDocAcceleratorManager );
1564         Reference< XAcceleratorConfiguration > xModuleAccelCfg( m_xModuleAcceleratorManager );
1565         Reference< XAcceleratorConfiguration > xGlobalAccelCfg( m_xGlobalAcceleratorManager );
1566 
1567         if ( !m_bAcceleratorCfg )
1568         {
1569             // Retrieve references on demand
1570             m_bAcceleratorCfg = sal_True;
1571             if ( !xDocAccelCfg.is() )
1572             {
1573                 Reference< XController > xController = m_xFrame->getController();
1574                 Reference< XModel > xModel;
1575                 if ( xController.is() )
1576                 {
1577                     xModel = xController->getModel();
1578                     if ( xModel.is() )
1579                     {
1580                         Reference< XUIConfigurationManagerSupplier > xSupplier( xModel, UNO_QUERY );
1581                         if ( xSupplier.is() )
1582                         {
1583                             Reference< XUIConfigurationManager > xDocUICfgMgr( xSupplier->getUIConfigurationManager(), UNO_QUERY );
1584                             if ( xDocUICfgMgr.is() )
1585                             {
1586                                 xDocAccelCfg = Reference< XAcceleratorConfiguration >( xDocUICfgMgr->getShortCutManager(), UNO_QUERY );
1587                                 m_xDocAcceleratorManager = xDocAccelCfg;
1588                             }
1589                         }
1590                     }
1591                 }
1592             }
1593 
1594             if ( !xModuleAccelCfg.is() )
1595             {
1596                 Reference< XModuleUIConfigurationManagerSupplier > xModuleCfgMgrSupplier( getServiceFactory()->createInstance(
1597                                                                                             SERVICENAME_MODULEUICONFIGURATIONMANAGERSUPPLIER ),
1598                                                                                         UNO_QUERY );
1599                 try
1600                 {
1601                     Reference< XUIConfigurationManager > xUICfgMgr = xModuleCfgMgrSupplier->getUIConfigurationManager( m_aModuleIdentifier );
1602                     if ( xUICfgMgr.is() )
1603                     {
1604                         xModuleAccelCfg = Reference< XAcceleratorConfiguration >( xUICfgMgr->getShortCutManager(), UNO_QUERY );
1605                         m_xModuleAcceleratorManager = xModuleAccelCfg;
1606                     }
1607                 }
1608                 catch ( RuntimeException& )
1609                 {
1610                     throw;
1611                 }
1612                 catch ( Exception& )
1613                 {
1614                 }
1615             }
1616 
1617             if ( !xGlobalAccelCfg.is() )
1618             {
1619                 xGlobalAccelCfg = Reference< XAcceleratorConfiguration >( getServiceFactory()->createInstance(
1620                                                                             SERVICENAME_GLOBALACCELERATORCONFIGURATION ),
1621                                                                           UNO_QUERY );
1622                 m_xGlobalAcceleratorManager = xGlobalAccelCfg;
1623             }
1624         }
1625 
1626         KeyCode aEmptyKeyCode;
1627         Sequence< rtl::OUString > aSeq( aMenuShortCuts.size() );
1628         const sal_uInt32 nCount = aMenuShortCuts.size();
1629         for ( sal_uInt32 i = 0; i < nCount; ++i )
1630         {
1631             aSeq[i] = aMenuShortCuts[i]->aMenuItemURL;
1632             aMenuShortCuts[i]->aKeyCode = aEmptyKeyCode;
1633         }
1634 
1635         if ( m_xGlobalAcceleratorManager.is() )
1636             impl_RetrieveShortcutsFromConfiguration( xGlobalAccelCfg, aSeq, aMenuShortCuts );
1637         if ( m_xModuleAcceleratorManager.is() )
1638             impl_RetrieveShortcutsFromConfiguration( xModuleAccelCfg, aSeq, aMenuShortCuts );
1639         if ( m_xDocAcceleratorManager.is() )
1640             impl_RetrieveShortcutsFromConfiguration( xGlobalAccelCfg, aSeq, aMenuShortCuts );
1641     }
1642 }
1643 
RetrieveImageManagers()1644 void MenuBarManager::RetrieveImageManagers()
1645 {
1646     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::RetrieveImageManagers" );
1647     if ( !m_xDocImageManager.is() )
1648     {
1649         Reference< XController > xController = m_xFrame->getController();
1650         Reference< XModel > xModel;
1651         if ( xController.is() )
1652         {
1653             xModel = xController->getModel();
1654             if ( xModel.is() )
1655             {
1656                 Reference< XUIConfigurationManagerSupplier > xSupplier( xModel, UNO_QUERY );
1657                 if ( xSupplier.is() )
1658                 {
1659                     Reference< XUIConfigurationManager > xDocUICfgMgr( xSupplier->getUIConfigurationManager(), UNO_QUERY );
1660                     m_xDocImageManager = Reference< XImageManager >( xDocUICfgMgr->getImageManager(), UNO_QUERY );
1661                     m_xDocImageManager->addConfigurationListener(
1662                                             Reference< XUIConfigurationListener >(
1663                                                 static_cast< OWeakObject* >( this ), UNO_QUERY ));
1664                 }
1665             }
1666         }
1667     }
1668 
1669     Reference< XModuleManager > xModuleManager;
1670     if ( m_aModuleIdentifier.getLength() == 0 )
1671         xModuleManager.set( getServiceFactory()->createInstance( SERVICENAME_MODULEMANAGER ), UNO_QUERY_THROW );
1672 
1673     try
1674     {
1675         if ( xModuleManager.is() )
1676             m_aModuleIdentifier = xModuleManager->identify( Reference< XInterface >( m_xFrame, UNO_QUERY ) );
1677     }
1678     catch( Exception& )
1679     {
1680     }
1681 
1682     if ( !m_xModuleImageManager.is() )
1683     {
1684         Reference< XModuleUIConfigurationManagerSupplier > xModuleCfgMgrSupplier( getServiceFactory()->createInstance(
1685                                                                                     SERVICENAME_MODULEUICONFIGURATIONMANAGERSUPPLIER ),
1686                                                                                   UNO_QUERY );
1687         Reference< XUIConfigurationManager > xUICfgMgr = xModuleCfgMgrSupplier->getUIConfigurationManager( m_aModuleIdentifier );
1688         m_xModuleImageManager.set( xUICfgMgr->getImageManager(), UNO_QUERY );
1689         m_xModuleImageManager->addConfigurationListener( Reference< XUIConfigurationListener >(
1690                                                             static_cast< OWeakObject* >( this ), UNO_QUERY ));
1691     }
1692 }
1693 
FillMenuWithConfiguration(sal_uInt16 & nId,Menu * pMenu,const::rtl::OUString & rModuleIdentifier,const Reference<XIndexAccess> & rItemContainer,const Reference<XURLTransformer> & rTransformer)1694 void MenuBarManager::FillMenuWithConfiguration(
1695     sal_uInt16&                             nId,
1696     Menu*                               pMenu,
1697     const ::rtl::OUString&              rModuleIdentifier,
1698     const Reference< XIndexAccess >&    rItemContainer,
1699     const Reference< XURLTransformer >& rTransformer )
1700 {
1701     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::FillMenuWithConfiguration" );
1702     Reference< XDispatchProvider > xEmptyDispatchProvider;
1703     MenuBarManager::FillMenu( nId, pMenu, rModuleIdentifier, rItemContainer, xEmptyDispatchProvider );
1704 
1705     // Merge add-on menu entries into the menu bar
1706     MenuBarManager::MergeAddonMenus( static_cast< Menu* >( pMenu ),
1707                                      AddonsOptions().GetMergeMenuInstructions(),
1708                                      rModuleIdentifier );
1709 
1710     sal_Bool bHasDisabledEntries = SvtCommandOptions().HasEntries( SvtCommandOptions::CMDOPTION_DISABLED );
1711     if ( bHasDisabledEntries )
1712     {
1713         sal_uInt16 nCount = pMenu->GetItemCount();
1714         for ( sal_uInt16 i = 0; i < nCount; i++ )
1715         {
1716             sal_uInt16 nID = pMenu->GetItemId( i );
1717             if ( nID > 0 )
1718             {
1719                 PopupMenu* pPopupMenu = pMenu->GetPopupMenu( nID );
1720                 if ( pPopupMenu )
1721                 {
1722                     if ( MustBeHidden( pPopupMenu, rTransformer ))
1723                         pMenu->HideItem( nId );
1724                 }
1725             }
1726         }
1727     }
1728 }
1729 
FillMenu(sal_uInt16 & nId,Menu * pMenu,const rtl::OUString & rModuleIdentifier,const Reference<XIndexAccess> & rItemContainer,const Reference<XDispatchProvider> & rDispatchProvider)1730 void MenuBarManager::FillMenu(
1731     sal_uInt16&                               nId,
1732     Menu*                                 pMenu,
1733     const rtl::OUString&                  rModuleIdentifier,
1734     const Reference< XIndexAccess >&      rItemContainer,
1735     const Reference< XDispatchProvider >& rDispatchProvider )
1736 {
1737     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::FillMenu" );
1738     // Fill menu bar with container contents
1739     for ( sal_Int32 n = 0; n < rItemContainer->getCount(); n++ )
1740     {
1741         Sequence< PropertyValue >       aProp;
1742         rtl::OUString                   aCommandURL;
1743         rtl::OUString                   aLabel;
1744         rtl::OUString                   aHelpURL;
1745         rtl::OUString                   aModuleIdentifier( rModuleIdentifier );
1746         sal_Bool                        bShow(sal_True);
1747         sal_Bool                        bEnabled(sal_True);
1748         sal_uInt16                      nType = 0;
1749         Reference< XIndexAccess >       xIndexContainer;
1750         Reference< XDispatchProvider >  xDispatchProvider( rDispatchProvider );
1751         sal_Int16 nStyle = 0;
1752         try
1753         {
1754             if ( rItemContainer->getByIndex( n ) >>= aProp )
1755             {
1756                 for ( int i = 0; i < aProp.getLength(); i++ )
1757                 {
1758                     rtl::OUString aPropName = aProp[i].Name;
1759                     if ( aPropName.equalsAsciiL( ITEM_DESCRIPTOR_COMMANDURL, LEN_DESCRIPTOR_COMMANDURL ))
1760                         aProp[i].Value >>= aCommandURL;
1761                     else if ( aPropName.equalsAsciiL( ITEM_DESCRIPTOR_HELPURL, LEN_DESCRIPTOR_HELPURL ))
1762                         aProp[i].Value >>= aHelpURL;
1763                     else if ( aPropName.equalsAsciiL( ITEM_DESCRIPTOR_CONTAINER, LEN_DESCRIPTOR_CONTAINER ))
1764                         aProp[i].Value >>= xIndexContainer;
1765                     else if ( aPropName.equalsAsciiL( ITEM_DESCRIPTOR_LABEL, LEN_DESCRIPTOR_LABEL ))
1766                         aProp[i].Value >>= aLabel;
1767                     else if ( aPropName.equalsAsciiL( ITEM_DESCRIPTOR_TYPE, LEN_DESCRIPTOR_TYPE ))
1768                         aProp[i].Value >>= nType;
1769                     else if ( aPropName.equalsAsciiL( ITEM_DESCRIPTOR_MODULEIDENTIFIER, LEN_DESCRIPTOR_MODULEIDENTIFIER ))
1770                         aProp[i].Value >>= aModuleIdentifier;
1771                     else if ( aPropName.equalsAsciiL( ITEM_DESCRIPTOR_DISPATCHPROVIDER, LEN_DESCRIPTOR_DISPATCHPROVIDER ))
1772                         aProp[i].Value >>= xDispatchProvider;
1773                     else if ( aProp[i].Name.equalsAsciiL( ITEM_DESCRIPTOR_STYLE, LEN_DESCRIPTOR_STYLE ))
1774                         aProp[i].Value >>= nStyle;
1775                     else if ( aProp[i].Name.equalsAsciiL( ITEM_DESCRIPTOR_ISVISIBLE, LEN_DESCRIPTOR_ISVISIBLE ))
1776                         aProp[i].Value >>= bShow;
1777                     else if ( aProp[i].Name.equalsAsciiL( ITEM_DESCRIPTOR_ENABLED, LEN_DESCRIPTOR_ENABLED ))
1778                         aProp[i].Value >>= bEnabled;
1779                 }
1780 
1781                 if ( nType == ::com::sun::star::ui::ItemType::DEFAULT )
1782                 {
1783                     pMenu->InsertItem( nId, aLabel );
1784                     pMenu->SetItemCommand( nId, aCommandURL );
1785 
1786                     if ( nStyle )
1787                     {
1788                         MenuItemBits nBits = pMenu->GetItemBits( nId );
1789                         if ( nStyle & ::com::sun::star::ui::ItemStyle::ICON )
1790                            nBits |= MIB_ICON;
1791                         if ( nStyle & ::com::sun::star::ui::ItemStyle::TEXT )
1792                            nBits |= MIB_TEXT;
1793                         if ( nStyle & ::com::sun::star::ui::ItemStyle::RADIO_CHECK )
1794                            nBits |= MIB_RADIOCHECK;
1795                         pMenu->SetItemBits( nId, nBits );
1796                     }
1797 
1798                     if ( !bShow )
1799                         pMenu->HideItem( nId );
1800 
1801                     if ( !bEnabled)
1802                         pMenu->EnableItem( nId, sal_False );
1803 
1804                     if ( xIndexContainer.is() )
1805                     {
1806                         PopupMenu* pNewPopupMenu = new PopupMenu;
1807                         pMenu->SetPopupMenu( nId, pNewPopupMenu );
1808 
1809                         if ( xDispatchProvider.is() )
1810                         {
1811                             // Use attributes struct to transport special dispatch provider
1812                             MenuConfiguration::Attributes* pAttributes = new MenuConfiguration::Attributes;
1813                             pAttributes->xDispatchProvider = xDispatchProvider;
1814                             pMenu->SetUserValue( nId, (sal_uIntPtr)( pAttributes ));
1815                         }
1816 
1817                         // Use help command to transport module identifier
1818                         if ( aModuleIdentifier.getLength() > 0 )
1819                             pMenu->SetHelpCommand( nId, aModuleIdentifier );
1820 
1821                         ++nId;
1822                         FillMenu( nId, pNewPopupMenu, aModuleIdentifier, xIndexContainer, xDispatchProvider );
1823                     }
1824                     else
1825                         ++nId;
1826                 }
1827                 else
1828                 {
1829                     pMenu->InsertSeparator();
1830                     ++nId;
1831                 }
1832             }
1833         }
1834         catch ( IndexOutOfBoundsException& )
1835         {
1836             break;
1837         }
1838     }
1839 }
1840 
MergeAddonMenus(Menu * pMenuBar,const MergeMenuInstructionContainer & aMergeInstructionContainer,const::rtl::OUString & rModuleIdentifier)1841 void MenuBarManager::MergeAddonMenus(
1842     Menu* pMenuBar,
1843     const MergeMenuInstructionContainer& aMergeInstructionContainer,
1844     const ::rtl::OUString& rModuleIdentifier )
1845 {
1846     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::MergeAddonMenus" );
1847     // set start value for the item ID for the new addon menu items
1848     sal_uInt16 nItemId = ADDONMENU_MERGE_ITEMID_START;
1849 
1850     const sal_uInt32 nCount = aMergeInstructionContainer.size();
1851     for ( sal_uInt32 i = 0; i < nCount; i++ )
1852     {
1853         const MergeMenuInstruction& rMergeInstruction = aMergeInstructionContainer[i];
1854 
1855         if ( MenuBarMerger::IsCorrectContext( rMergeInstruction.aMergeContext, rModuleIdentifier ))
1856         {
1857             ::std::vector< ::rtl::OUString > aMergePath;
1858 
1859             // retrieve the merge path from the merge point string
1860             MenuBarMerger::RetrieveReferencePath( rMergeInstruction.aMergePoint, aMergePath );
1861 
1862             // convert the sequence/sequence property value to a more convenient vector<>
1863             AddonMenuContainer aMergeMenuItems;
1864             MenuBarMerger::GetSubMenu( rMergeInstruction.aMergeMenu, aMergeMenuItems );
1865 
1866             // try to find the reference point for our merge operation
1867             Menu* pMenu = pMenuBar;
1868             ReferencePathInfo aResult = MenuBarMerger::FindReferencePath( aMergePath, pMenu );
1869 
1870             if ( aResult.eResult == RP_OK )
1871             {
1872                 // normal merge operation
1873                 MenuBarMerger::ProcessMergeOperation( aResult.pPopupMenu,
1874                                                       aResult.nPos,
1875                                                       nItemId,
1876                                                       rMergeInstruction.aMergeCommand,
1877                                                       rMergeInstruction.aMergeCommandParameter,
1878                                                       rModuleIdentifier,
1879                                                       aMergeMenuItems );
1880             }
1881             else
1882             {
1883                 // fallback
1884                 MenuBarMerger::ProcessFallbackOperation( aResult,
1885                                                          nItemId,
1886                                                          rMergeInstruction.aMergeCommand,
1887                                                          rMergeInstruction.aMergeFallback,
1888                                                          aMergePath,
1889                                                          rModuleIdentifier,
1890                                                          aMergeMenuItems );
1891             }
1892         }
1893     }
1894 }
1895 
SetItemContainer(const Reference<XIndexAccess> & rItemContainer)1896 void MenuBarManager::SetItemContainer( const Reference< XIndexAccess >& rItemContainer )
1897 {
1898     RTL_LOGFILE_CONTEXT( aLog, "framework (cd100003) ::MenuBarManager::SetItemContainer" );
1899 
1900     ResetableGuard aGuard( m_aLock );
1901 
1902     Reference< XFrame > xFrame = m_xFrame;
1903 
1904     if ( !m_bModuleIdentified )
1905     {
1906         m_bModuleIdentified = sal_True;
1907         Reference< XModuleManager > xModuleManager;
1908         xModuleManager = Reference< XModuleManager >( getServiceFactory()->createInstance( SERVICENAME_MODULEMANAGER ), UNO_QUERY_THROW );
1909 
1910         try
1911         {
1912             m_aModuleIdentifier = xModuleManager->identify( xFrame );
1913         }
1914         catch( Exception& )
1915         {
1916         }
1917     }
1918 
1919     // Clear MenuBarManager structures
1920     {
1921         vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
1922 
1923         // Check active state as we cannot change our VCL menu during activation by the user
1924         if ( m_bActive )
1925         {
1926             m_xDeferedItemContainer = rItemContainer;
1927             return;
1928         }
1929 
1930         RemoveListener();
1931         std::vector< MenuItemHandler* >::iterator p;
1932         for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ )
1933         {
1934             MenuItemHandler* pItemHandler = *p;
1935             pItemHandler->xMenuItemDispatch.clear();
1936             pItemHandler->xSubMenuManager.clear();
1937             delete pItemHandler;
1938         }
1939         m_aMenuItemHandlerVector.clear();
1940 
1941         // Remove top-level parts
1942         m_pVCLMenu->Clear();
1943 
1944         sal_uInt16          nId = 1;
1945 
1946         // Fill menu bar with container contents
1947         FillMenuWithConfiguration( nId, (Menu *)m_pVCLMenu, m_aModuleIdentifier, rItemContainer, m_xURLTransformer );
1948 
1949         // Refill menu manager again
1950         Reference< XDispatchProvider > xDispatchProvider;
1951         FillMenuManager( m_pVCLMenu, xFrame, xDispatchProvider, m_aModuleIdentifier, sal_False, sal_True );
1952 
1953         // add itself as frame action listener
1954         m_xFrame->addFrameActionListener( Reference< XFrameActionListener >( static_cast< OWeakObject* >( this ), UNO_QUERY ));
1955     }
1956 }
1957 
GetPopupController(PopupControllerCache & rPopupController)1958 void MenuBarManager::GetPopupController( PopupControllerCache& rPopupController )
1959 {
1960     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::GetPopupController" );
1961     String aPopupScheme = String::CreateFromAscii( "vnd.sun.star.popup:" );
1962 
1963     vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
1964 
1965     std::vector< MenuItemHandler* >::iterator p;
1966     for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); p++ )
1967     {
1968         MenuItemHandler* pItemHandler = *p;
1969         if ( pItemHandler->xPopupMenuController.is() )
1970         {
1971             Reference< XDispatchProvider > xDispatchProvider( pItemHandler->xPopupMenuController, UNO_QUERY );
1972 
1973             PopupControllerEntry aPopupControllerEntry;
1974             aPopupControllerEntry.m_xDispatchProvider = xDispatchProvider;
1975 
1976             // Just use the main part of the URL for popup menu controllers
1977             sal_Int32     nQueryPart( 0 );
1978             sal_Int32     nSchemePart( 0 );
1979             rtl::OUString aMainURL( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.popup:" ));
1980             rtl::OUString aMenuURL( pItemHandler->aMenuItemURL );
1981 
1982             nSchemePart = aMenuURL.indexOf( ':' );
1983             if (( nSchemePart > 0 ) &&
1984                 ( aMenuURL.getLength() > ( nSchemePart+1 )))
1985             {
1986                 nQueryPart = aMenuURL.indexOf( '?', nSchemePart );
1987                 if ( nQueryPart > 0 )
1988                     aMainURL += aMenuURL.copy( nSchemePart, nQueryPart-nSchemePart );
1989                 else if ( nQueryPart == -1 )
1990                     aMainURL += aMenuURL.copy( nSchemePart+1 );
1991 
1992                 rPopupController.insert( PopupControllerCache::value_type(
1993                                            aMainURL, aPopupControllerEntry ));
1994             }
1995         }
1996         if ( pItemHandler->xSubMenuManager.is() )
1997         {
1998             MenuBarManager* pMenuBarManager = (MenuBarManager*)(pItemHandler->xSubMenuManager.get());
1999             if ( pMenuBarManager )
2000                 pMenuBarManager->GetPopupController( rPopupController );
2001         }
2002     }
2003 }
2004 
2005 // #110897#
getServiceFactory()2006 const Reference< XMultiServiceFactory >& MenuBarManager::getServiceFactory()
2007 {
2008     // #110897#
2009     return mxServiceFactory;
2010 }
2011 
AddMenu(MenuBarManager * pSubMenuManager,const::rtl::OUString & _sItemCommand,sal_uInt16 _nItemId)2012 void MenuBarManager::AddMenu(MenuBarManager* pSubMenuManager,const ::rtl::OUString& _sItemCommand,sal_uInt16 _nItemId)
2013 {
2014     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::AddMenu" );
2015     Reference< XStatusListener > xSubMenuManager( static_cast< OWeakObject *>( pSubMenuManager ), UNO_QUERY );
2016     m_xFrame->addFrameActionListener( Reference< XFrameActionListener >( xSubMenuManager, UNO_QUERY ));
2017 
2018     // store menu item command as we later have to know which menu is active (see Activate handler)
2019     pSubMenuManager->m_aMenuItemCommand = _sItemCommand;
2020     Reference< XDispatch > xDispatch;
2021     MenuItemHandler* pMenuItemHandler = new MenuItemHandler(
2022                                                 _nItemId,
2023                                                 xSubMenuManager,
2024                                                 xDispatch );
2025     pMenuItemHandler->aMenuItemURL = _sItemCommand;
2026     m_aMenuItemHandlerVector.push_back( pMenuItemHandler );
2027 }
2028 
FillItemCommand(::rtl::OUString & _rItemCommand,Menu * _pMenu,sal_uInt16 _nIndex) const2029 sal_uInt16 MenuBarManager::FillItemCommand(::rtl::OUString& _rItemCommand,Menu* _pMenu,sal_uInt16 _nIndex) const
2030 {
2031     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::FillItemCommand" );
2032     sal_uInt16 nItemId = _pMenu->GetItemId( _nIndex );
2033 
2034     _rItemCommand = _pMenu->GetItemCommand( nItemId );
2035     if ( !_rItemCommand.getLength() )
2036     {
2037         const static ::rtl::OUString aSlotString( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
2038         _rItemCommand = aSlotString;
2039         _rItemCommand += ::rtl::OUString::valueOf( (sal_Int32)nItemId );
2040         _pMenu->SetItemCommand( nItemId, _rItemCommand );
2041     }
2042     return nItemId;
2043 }
Init(const Reference<XFrame> & rFrame,AddonMenu * pAddonMenu,sal_Bool bDelete,sal_Bool bDeleteChildren,bool _bHandlePopUp)2044 void MenuBarManager::Init(const Reference< XFrame >& rFrame,AddonMenu* pAddonMenu,sal_Bool bDelete,sal_Bool bDeleteChildren,bool _bHandlePopUp)
2045 {
2046     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::Init" );
2047     m_bActive           = sal_False;
2048     m_bDeleteMenu       = bDelete;
2049     m_bDeleteChildren   = bDeleteChildren;
2050     m_pVCLMenu          = pAddonMenu;
2051     m_xFrame            = rFrame;
2052     m_bInitialized      = sal_False;
2053     m_bIsBookmarkMenu   = sal_True;
2054 
2055     rtl::OUString aModuleIdentifier;
2056     m_xPopupMenuControllerFactory = frame::PopupMenuControllerFactory::create(
2057         ::comphelper::getProcessComponentContext());
2058 
2059     const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
2060     m_bWasHiContrast    = rSettings.GetHighContrastMode();
2061 
2062     Reference< XStatusListener > xStatusListener;
2063     Reference< XDispatch > xDispatch;
2064     sal_uInt16 nItemCount = pAddonMenu->GetItemCount();
2065     ::rtl::OUString aItemCommand;
2066     m_aMenuItemHandlerVector.reserve(nItemCount);
2067     for ( sal_uInt16 i = 0; i < nItemCount; i++ )
2068     {
2069         sal_uInt16 nItemId = FillItemCommand(aItemCommand,pAddonMenu, i );
2070 
2071         PopupMenu* pPopupMenu = pAddonMenu->GetPopupMenu( nItemId );
2072         if ( pPopupMenu )
2073         {
2074             // #110897#
2075             Reference< XDispatchProvider > xDispatchProvider;
2076             MenuBarManager* pSubMenuManager = new MenuBarManager( getServiceFactory(), rFrame, m_xURLTransformer,xDispatchProvider, aModuleIdentifier, pPopupMenu, _bHandlePopUp ? sal_False : bDeleteChildren, _bHandlePopUp ? sal_False : bDeleteChildren );
2077 
2078             Reference< XStatusListener > xSubMenuManager( static_cast< OWeakObject *>( pSubMenuManager ), UNO_QUERY );
2079 
2080             // store menu item command as we later have to know which menu is active (see Activate handler)
2081             pSubMenuManager->m_aMenuItemCommand = aItemCommand;
2082 
2083             MenuItemHandler* pMenuItemHandler = new MenuItemHandler(
2084                                                         nItemId,
2085                                                         xSubMenuManager,
2086                                                         xDispatch );
2087             m_aMenuItemHandlerVector.push_back( pMenuItemHandler );
2088         }
2089         else
2090         {
2091             if ( pAddonMenu->GetItemType( i ) != MENUITEM_SEPARATOR )
2092             {
2093                 MenuConfiguration::Attributes* pAddonAttributes = (MenuConfiguration::Attributes *)(pAddonMenu->GetUserValue( nItemId ));
2094                 MenuItemHandler* pMenuItemHandler = new MenuItemHandler( nItemId, xStatusListener, xDispatch );
2095 
2096                 if ( pAddonAttributes )
2097                 {
2098                     // read additional attributes from attributes struct and AddonMenu implementation will delete all attributes itself!!
2099                     pMenuItemHandler->aTargetFrame = pAddonAttributes->aTargetFrame;
2100                 }
2101 
2102                 pMenuItemHandler->aMenuItemURL = aItemCommand;
2103                 if ( _bHandlePopUp )
2104                 {
2105                     // Check if we have to create a popup menu for a uno based popup menu controller.
2106                     // We have to set an empty popup menu into our menu structure so the controller also
2107                     // works with inplace OLE.
2108                     if ( m_xPopupMenuControllerFactory.is() &&
2109                         m_xPopupMenuControllerFactory->hasController( aItemCommand, rtl::OUString() ))
2110                     {
2111                         VCLXPopupMenu* pVCLXPopupMenu = new VCLXPopupMenu;
2112                         PopupMenu* pCtlPopupMenu = (PopupMenu *)pVCLXPopupMenu->GetMenu();
2113                         pAddonMenu->SetPopupMenu( pMenuItemHandler->nItemId, pCtlPopupMenu );
2114                         pMenuItemHandler->xPopupMenu = Reference< com::sun::star::awt::XPopupMenu >( (OWeakObject *)pVCLXPopupMenu, UNO_QUERY );
2115 
2116                     }
2117                 }
2118                 m_aMenuItemHandlerVector.push_back( pMenuItemHandler );
2119             }
2120         }
2121     }
2122 
2123     SetHdl();
2124 }
2125 
SetHdl()2126 void MenuBarManager::SetHdl()
2127 {
2128     m_pVCLMenu->SetHighlightHdl( LINK( this, MenuBarManager, Highlight ));
2129     m_pVCLMenu->SetActivateHdl( LINK( this, MenuBarManager, Activate ));
2130     m_pVCLMenu->SetDeactivateHdl( LINK( this, MenuBarManager, Deactivate ));
2131     m_pVCLMenu->SetSelectHdl( LINK( this, MenuBarManager, Select ));
2132 
2133     if ( !m_xURLTransformer.is() && mxServiceFactory.is() )
2134         m_xURLTransformer.set( mxServiceFactory->createInstance(
2135                                                                 SERVICENAME_URLTRANSFORMER),
2136                                                              UNO_QUERY );
2137 }
2138 
2139 }
2140