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