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