LibreOffice Module framework (master) 1
menubarmanager.cxx
Go to the documentation of this file.
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
22#include <menuconfiguration.hxx>
23#include <addonmenu.hxx>
25#include <classes/fwkresid.hxx>
26#include <strings.hrc>
27
28#include <com/sun/star/frame/XDispatch.hpp>
29#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
30#include <com/sun/star/lang/DisposedException.hpp>
31#include <com/sun/star/uno/XComponentContext.hpp>
32#include <com/sun/star/uno/XCurrentContext.hpp>
33#include <com/sun/star/frame/XPopupMenuController.hpp>
34#include <com/sun/star/frame/thePopupMenuControllerFactory.hpp>
35#include <com/sun/star/lang/SystemDependent.hpp>
36#include <com/sun/star/ui/GlobalAcceleratorConfiguration.hpp>
37#include <com/sun/star/ui/ItemType.hpp>
38#include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
39#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
40#include <com/sun/star/ui/ItemStyle.hpp>
41#include <com/sun/star/frame/status/Visibility.hpp>
42#include <com/sun/star/util/URLTransformer.hpp>
43
46#include <officecfg/Office/Common.hxx>
48#include <uno/current_context.hxx>
51#include <utility>
52#include <vcl/svapp.hxx>
53#include <vcl/sysdata.hxx>
54#include <vcl/menu.hxx>
55#include <vcl/settings.hxx>
57#include <sal/log.hxx>
59#include <svtools/miscopt.hxx>
61#include <tools/urlobj.hxx>
62
63using namespace ::cppu;
64using namespace ::com::sun::star;
65using namespace ::com::sun::star::uno;
66using namespace ::com::sun::star::util;
67using namespace ::com::sun::star::beans;
68using namespace ::com::sun::star::frame;
69using namespace ::com::sun::star::container;
70using namespace ::com::sun::star::lang;
71using namespace ::com::sun::star::ui;
72
73const sal_uInt16 ADDONMENU_MERGE_ITEMID_START = 1500;
74const sal_uInt16 ITEMID_ADDONLIST = 6678; // used to be a SID in sfx2, now just a unique id...
75
76namespace framework
77{
78
79constexpr OUStringLiteral aCmdHelpIndex = u".uno:HelpIndex";
80constexpr OUStringLiteral aCmdToolsMenu = u".uno:ToolsMenu";
81constexpr OUStringLiteral aCmdHelpMenu = u".uno:HelpMenu";
82constexpr OUStringLiteral aSpecialWindowCommand = u".uno:WindowList";
83
85 const Reference< XComponentContext >& rxContext,
86 const Reference< XFrame >& rFrame,
87 const Reference< XURLTransformer >& _xURLTransformer,
88 const Reference< XDispatchProvider >& rDispatchProvider,
89 const OUString& rModuleIdentifier,
90 Menu* pMenu, bool bDelete, bool bHasMenuBar ):
91 m_bRetrieveImages( false )
92 , m_bAcceleratorCfg( false )
93 , m_bHasMenuBar( bHasMenuBar )
94 , m_xContext(rxContext)
95 , m_xURLTransformer(_xURLTransformer)
96 , m_sIconTheme( SvtMiscOptions::GetIconTheme() )
97 , m_aAsyncSettingsTimer( "framework::MenuBarManager::Deactivate m_aAsyncSettingsTimer" )
98{
99 m_xPopupMenuControllerFactory = frame::thePopupMenuControllerFactory::get(m_xContext);
100 FillMenuManager( pMenu, rFrame, rDispatchProvider, rModuleIdentifier, bDelete );
101}
102
103Any SAL_CALL MenuBarManager::getMenuHandle( const Sequence< sal_Int8 >& /*ProcessId*/, sal_Int16 SystemType )
104{
105 SolarMutexGuard aSolarGuard;
106
107 if ( m_bDisposed )
108 throw css::lang::DisposedException();
109
110 Any a;
111
112 if ( m_pVCLMenu )
113 {
114 SystemMenuData aSystemMenuData;
115
116 m_pVCLMenu->GetSystemMenuData( &aSystemMenuData );
117#ifdef _WIN32
118 if( SystemType == SystemDependent::SYSTEM_WIN32 )
119 {
120 a <<= sal_Int64(
121 reinterpret_cast<sal_IntPtr>(aSystemMenuData.hMenu));
122 }
123#else
124 (void) SystemType;
125#endif
126 }
127
128 return a;
129}
130
132{
133 // stop asynchronous settings timer
136
137 SAL_WARN_IF( OWeakObject::m_refCount != 0, "fwk.uielement", "Who wants to delete an object with refcount > 0!" );
138}
139
140// XComponent
141void MenuBarManager::disposing(std::unique_lock<std::mutex>& )
142{
143 Reference< XComponent > xThis( this );
144
146
147 // stop asynchronous settings timer and
148 // release deferred item container reference
152
154
155 if ( m_bDeleteMenu )
156 {
158 }
159
160 if ( m_xDocImageManager.is() )
161 {
162 try
163 {
164 m_xDocImageManager->removeConfigurationListener(
165 Reference< XUIConfigurationListener >(this) );
166 }
167 catch ( const Exception& )
168 {
169 }
170 }
171 if ( m_xModuleImageManager.is() )
172 {
173 try
174 {
175 m_xModuleImageManager->removeConfigurationListener(
176 Reference< XUIConfigurationListener >(this) );
177 }
178 catch ( const Exception& )
179 {
180 }
181 }
182 m_xDocImageManager.clear();
183 m_xModuleImageManager.clear();
188 m_xContext.clear();
189}
190
191void SAL_CALL MenuBarManager::elementInserted( const css::ui::ConfigurationEvent& Event )
192{
194
195 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
196 if ( m_bDisposed )
197 return;
198
199 sal_Int16 nImageType = sal_Int16();
200 if (( Event.aInfo >>= nImageType ) && nImageType == 0 )
202}
203
204void SAL_CALL MenuBarManager::elementRemoved( const css::ui::ConfigurationEvent& Event )
205{
206 elementInserted(Event);
207}
208
209void SAL_CALL MenuBarManager::elementReplaced( const css::ui::ConfigurationEvent& Event )
210{
211 elementInserted(Event);
212}
213
214// XFrameActionListener
215void SAL_CALL MenuBarManager::frameAction( const FrameActionEvent& Action )
216{
218
219 if ( m_bDisposed )
220 throw css::lang::DisposedException();
221
222 if ( Action.Action != FrameAction_CONTEXT_CHANGED )
223 return;
224
225 for (auto const& menuItemHandler : m_aMenuItemHandlerVector)
226 {
227 // Clear dispatch reference as we will requery it later
228 if ( menuItemHandler->xMenuItemDispatch.is() )
229 {
231 aTargetURL.Complete = menuItemHandler->aMenuItemURL;
232 m_xURLTransformer->parseStrict( aTargetURL );
233
234 menuItemHandler->xMenuItemDispatch->removeStatusListener( this, aTargetURL );
235 }
236 menuItemHandler->xMenuItemDispatch.clear();
237 }
238}
239
240// XStatusListener
241void SAL_CALL MenuBarManager::statusChanged( const FeatureStateEvent& Event )
242{
243 OUString aFeatureURL = Event.FeatureURL.Complete;
244
245 SolarMutexGuard aSolarGuard;
246 {
247 if ( m_bDisposed )
248 return;
249
250 // We have to check all menu entries as there can be identical entries in a popup menu.
251 for (auto const& menuItemHandler : m_aMenuItemHandlerVector)
252 {
253 if ( menuItemHandler->aParsedItemURL == aFeatureURL )
254 {
255 bool bCheckmark( false );
256 bool bMenuItemEnabled( m_pVCLMenu->IsItemEnabled( menuItemHandler->nItemId ));
257 bool bEnabledItem( Event.IsEnabled );
258 OUString aItemText;
259 status::Visibility aVisibilityStatus;
260
261 #ifdef UNIX
262 //enable some slots hardly, because UNIX clipboard does not notify all changes
263 // Can be removed if follow up task will be fixed directly within applications.
264 // Note: PasteSpecial is handled specifically by calc
265 // Calc also disables Paste under some circumstances, do not override.
266 /* TODO: is this workaround even needed anymore? Was introduced
267 * in 2009 with commit 426ab2c0e8f6e3fe2b766f74f6b8da873d860260
268 * as some "metropatch" and the other places it touched seem to
269 * be gone. */
270 if ( (menuItemHandler->aMenuItemURL == ".uno:Paste" &&
271 m_aModuleIdentifier != "com.sun.star.sheet.SpreadsheetDocument")
272 || menuItemHandler->aMenuItemURL == ".uno:PasteClipboard" ) // special for draw/impress
273 bEnabledItem = true;
274 #endif
275
276 // Enable/disable item
277 if ( bEnabledItem != bMenuItemEnabled )
278 {
279 m_pVCLMenu->EnableItem( menuItemHandler->nItemId, bEnabledItem );
280
281 // Remove "checked" mark for disabled menu items.
282 // Initially disabled but checkable menu items do not receive
283 // checked/unchecked state, so can appear inconsistently after
284 // enabling/disabling. Since we can not pass checked state for disabled
285 // items, we will just reset checked state for them, anyway correct state
286 // will be transferred from controller once item enabled.
287 if ( !bEnabledItem && m_pVCLMenu->IsItemChecked( menuItemHandler->nItemId ) )
288 m_pVCLMenu->CheckItem( menuItemHandler->nItemId, false );
289 }
290
291 if ( Event.State >>= bCheckmark )
292 {
293 // Checkmark or RadioButton
294 m_pVCLMenu->CheckItem( menuItemHandler->nItemId, bCheckmark );
295 // If not already designated RadioButton set as CheckMark
296 MenuItemBits nBits = m_pVCLMenu->GetItemBits( menuItemHandler->nItemId );
297 if (!(nBits & MenuItemBits::RADIOCHECK))
298 m_pVCLMenu->SetItemBits( menuItemHandler->nItemId, nBits | MenuItemBits::CHECKABLE );
299
300 if ( menuItemHandler->bMadeInvisible )
301 m_pVCLMenu->ShowItem( menuItemHandler->nItemId );
302 }
303 else if ( Event.State >>= aItemText )
304 {
305 INetURLObject aURL( aFeatureURL );
306 OUString aEnumPart = aURL.GetURLPath().getToken( 1, '.' );
307 if ( !aEnumPart.isEmpty() && aURL.GetProtocol() == INetProtocol::Uno )
308 {
309 // Checkmark or RadioButton
310 m_pVCLMenu->CheckItem( menuItemHandler->nItemId, aItemText == aEnumPart );
311 // If not already designated RadioButton set as CheckMark
312 MenuItemBits nBits = m_pVCLMenu->GetItemBits( menuItemHandler->nItemId );
313 if (!(nBits & MenuItemBits::RADIOCHECK))
314 m_pVCLMenu->SetItemBits( menuItemHandler->nItemId, nBits | MenuItemBits::CHECKABLE );
315 }
316 else
317 {
318 // Replacement for place holders
319 if ( aItemText.startsWith("($1)") )
320 {
321 aItemText = FwkResId(STR_UPDATEDOC) + " " + aItemText.subView( 4 );
322 }
323 else if ( aItemText.startsWith("($2)") )
324 {
325 aItemText = FwkResId(STR_CLOSEDOC_ANDRETURN) + aItemText.subView( 4 );
326 }
327 else if ( aItemText.startsWith("($3)") )
328 {
329 aItemText = FwkResId(STR_SAVECOPYDOC) + aItemText.subView( 4 );
330 }
331
332 m_pVCLMenu->SetItemText( menuItemHandler->nItemId, aItemText );
333 }
334
335 if ( menuItemHandler->bMadeInvisible )
336 m_pVCLMenu->ShowItem( menuItemHandler->nItemId );
337 }
338 else if ( Event.State >>= aVisibilityStatus )
339 {
340 // Visibility
341 m_pVCLMenu->ShowItem( menuItemHandler->nItemId, aVisibilityStatus.bVisible );
342 menuItemHandler->bMadeInvisible = !aVisibilityStatus.bVisible;
343 }
344 else if ( menuItemHandler->bMadeInvisible )
345 m_pVCLMenu->ShowItem( menuItemHandler->nItemId );
346 }
347
348 if ( Event.Requery )
349 {
350 // Release dispatch object - will be required on the next activate!
351 menuItemHandler->xMenuItemDispatch.clear();
352 }
353 }
354 }
355}
356
357// Helper to retrieve own structure from item ID
359{
361
362 for (auto const& menuItemHandler : m_aMenuItemHandlerVector)
363 {
364 if ( menuItemHandler->nItemId == nItemId )
365 return menuItemHandler.get();
366 }
367
368 return nullptr;
369}
370
371// Helper to set request images flag
373{
374
375 m_bRetrieveImages = true;
376 for (auto const& menuItemHandler : m_aMenuItemHandlerVector)
377 {
378 if ( menuItemHandler->xSubMenuManager.is() )
379 {
380 MenuBarManager* pMenuBarManager = static_cast<MenuBarManager*>(menuItemHandler->xSubMenuManager.get());
381 pMenuBarManager->RequestImages();
382 }
383 }
384}
385
386// Helper to reset objects to prepare shutdown
388{
390
391 for (auto const& menuItemHandler : m_aMenuItemHandlerVector)
392 {
393 if ( menuItemHandler->xMenuItemDispatch.is() )
394 {
396 aTargetURL.Complete = menuItemHandler->aMenuItemURL;
397 m_xURLTransformer->parseStrict( aTargetURL );
398
399 menuItemHandler->xMenuItemDispatch->removeStatusListener(
400 static_cast< XStatusListener* >( this ), aTargetURL );
401 }
402
403 menuItemHandler->xMenuItemDispatch.clear();
404
405 if ( menuItemHandler->xPopupMenu.is() )
406 {
407 {
408 // Remove popup menu from menu structure
409 m_pVCLMenu->SetPopupMenu( menuItemHandler->nItemId, nullptr );
410 }
411
412 Reference< css::lang::XEventListener > xEventListener( menuItemHandler->xPopupMenuController, UNO_QUERY );
413 if ( xEventListener.is() )
414 {
415 EventObject aEventObject;
416 aEventObject.Source = static_cast<OWeakObject *>(this);
417 xEventListener->disposing( aEventObject );
418 }
419
420 // We now provide a popup menu controller to external code.
421 // Therefore the life-time must be explicitly handled via
422 // dispose!!
423 try
424 {
425 Reference< XComponent > xComponent( menuItemHandler->xPopupMenuController, UNO_QUERY );
426 if ( xComponent.is() )
427 xComponent->dispose();
428 }
429 catch ( const RuntimeException& )
430 {
431 throw;
432 }
433 catch ( const Exception& )
434 {
435 }
436
437 // Release references to controller and popup menu
438 menuItemHandler->xPopupMenuController.clear();
439 menuItemHandler->xPopupMenu.clear();
440 }
441
442 Reference< XComponent > xComponent( menuItemHandler->xSubMenuManager, UNO_QUERY );
443 if ( xComponent.is() )
444 xComponent->dispose();
445 }
446
447 try
448 {
449 if ( m_xFrame.is() )
450 m_xFrame->removeFrameActionListener( Reference< XFrameActionListener >(this) );
451 }
452 catch ( const Exception& )
453 {
454 }
455
456 m_xFrame = nullptr;
457}
458
459void SAL_CALL MenuBarManager::disposing( const EventObject& Source )
460{
461 MenuItemHandler* pMenuItemDisposing = nullptr;
462
464
465 for (auto const& menuItemHandler : m_aMenuItemHandlerVector)
466 {
467 if ( menuItemHandler->xMenuItemDispatch.is() &&
468 menuItemHandler->xMenuItemDispatch == Source.Source )
469 {
470 // disposing called from menu item dispatcher, remove listener
471 pMenuItemDisposing = menuItemHandler.get();
472 break;
473 }
474 }
475
476 if ( pMenuItemDisposing )
477 {
478 // Release references to the dispatch object
480 aTargetURL.Complete = pMenuItemDisposing->aMenuItemURL;
481
482 m_xURLTransformer->parseStrict( aTargetURL );
483
484 pMenuItemDisposing->xMenuItemDispatch->removeStatusListener(
485 static_cast< XStatusListener* >( this ), aTargetURL );
486 pMenuItemDisposing->xMenuItemDispatch.clear();
487 if ( pMenuItemDisposing->xPopupMenu.is() )
488 {
489 Reference< css::lang::XEventListener > xEventListener( pMenuItemDisposing->xPopupMenuController, UNO_QUERY );
490 if ( xEventListener.is() )
491 xEventListener->disposing( Source );
492
493 {
494 // Remove popup menu from menu structure as we release our reference to
495 // the controller.
496 m_pVCLMenu->SetPopupMenu( pMenuItemDisposing->nItemId, nullptr );
497 }
498
499 pMenuItemDisposing->xPopupMenuController.clear();
500 pMenuItemDisposing->xPopupMenu.clear();
501 }
502 return;
503 }
504 else if ( Source.Source == m_xFrame )
505 {
506 // Our frame gets disposed. We have to remove all our listeners
508 }
509 else if ( Source.Source == Reference< XInterface >( m_xDocImageManager, UNO_QUERY ))
510 m_xDocImageManager.clear();
511 else if ( Source.Source == Reference< XInterface >( m_xModuleImageManager, UNO_QUERY ))
512 m_xModuleImageManager.clear();
513}
514
515static void lcl_CheckForChildren(Menu* pMenu, sal_uInt16 nItemId)
516{
517 if (PopupMenu* pThisPopup = pMenu->GetPopupMenu( nItemId ))
518 pMenu->EnableItem( nItemId, pThisPopup->GetItemCount() != 0 && pThisPopup->HasValidEntries(true));
519}
520
521// vcl handler
522
523namespace {
524
525class QuietInteractionContext:
526 public cppu::WeakImplHelper< css::uno::XCurrentContext >
527{
528public:
529 explicit QuietInteractionContext(
530 css::uno::Reference< css::uno::XCurrentContext > context):
531 context_(std::move(context)) {}
532 QuietInteractionContext(const QuietInteractionContext&) = delete;
533 QuietInteractionContext& operator=(const QuietInteractionContext&) = delete;
534
535private:
536 virtual ~QuietInteractionContext() override {}
537
538 virtual css::uno::Any SAL_CALL getValueByName(
539 OUString const & Name) override
540 {
542 ? context_->getValueByName(Name)
543 : css::uno::Any();
544 }
545
546 css::uno::Reference< css::uno::XCurrentContext >
548};
549
550}
551
552IMPL_LINK( MenuBarManager, Activate, Menu *, pMenu, bool )
553{
554 if ( pMenu != m_pVCLMenu )
555 return true;
556
557 css::uno::ContextLayer layer(
558 new QuietInteractionContext(
559 css::uno::getCurrentContext()));
560
561 // set/unset hiding disabled menu entries
562 bool bDontHide = officecfg::Office::Common::View::Menu::DontHideDisabledEntry::get();
564 bool bShowMenuImages = rSettings.GetUseImagesInMenus();
565 bool bShowShortcuts = m_bHasMenuBar || rSettings.GetContextMenuShortcuts();
566 bool bHasDisabledEntries = SvtCommandOptions().HasEntriesDisabled();
567
569
570 MenuFlags nFlag = pMenu->GetMenuFlags();
571 if ( bDontHide )
572 nFlag &= ~MenuFlags::HideDisabledEntries;
573 else
574 nFlag |= MenuFlags::HideDisabledEntries;
575 pMenu->SetMenuFlags( nFlag );
576
577 if ( m_bActive )
578 return false;
579
580 m_bActive = true;
581
582 // Check if some modes have changed so we have to update our menu images
583 OUString sIconTheme = SvtMiscOptions::GetIconTheme();
584
585 if ( m_bRetrieveImages ||
586 bShowMenuImages != m_bShowMenuImages ||
587 sIconTheme != m_sIconTheme )
588 {
589 m_bShowMenuImages = bShowMenuImages;
590 m_bRetrieveImages = false;
591 m_sIconTheme = sIconTheme;
592 FillMenuImages( m_xFrame, pMenu, bShowMenuImages );
593 }
594
595 // Try to map commands to labels
596 for ( sal_uInt16 nPos = 0; nPos < pMenu->GetItemCount(); nPos++ )
597 {
598 sal_uInt16 nItemId = pMenu->GetItemId( nPos );
599 if (( pMenu->GetItemType( nPos ) != MenuItemType::SEPARATOR ) &&
600 ( pMenu->GetItemText( nItemId ).isEmpty() ))
601 {
602 OUString aCommand = pMenu->GetItemCommand( nItemId );
603 if ( !aCommand.isEmpty() ) {
604 pMenu->SetItemText( nItemId, RetrieveLabelFromCommand( aCommand ));
605 }
606 }
607 }
608
609 // Try to set accelerator keys
610 {
611 if ( bShowShortcuts )
612 RetrieveShortcuts( m_aMenuItemHandlerVector );
613
614 for (auto const& menuItemHandler : m_aMenuItemHandlerVector)
615 {
616 if ( !bShowShortcuts )
617 {
618 pMenu->SetAccelKey( menuItemHandler->nItemId, vcl::KeyCode() );
619 }
620 else if ( menuItemHandler->aMenuItemURL == aCmdHelpIndex )
621 {
622 // Set key code, workaround for hard-coded shortcut F1 mapped to .uno:HelpIndex
623 // Only non-popup menu items can have a short-cut
624 vcl::KeyCode aKeyCode( KEY_F1 );
625 pMenu->SetAccelKey( menuItemHandler->nItemId, aKeyCode );
626 }
627 else if ( pMenu->GetPopupMenu( menuItemHandler->nItemId ) == nullptr )
628 pMenu->SetAccelKey( menuItemHandler->nItemId, menuItemHandler->aKeyCode );
629 }
630 }
631
633
634 // Use provided dispatch provider => fallback to frame as dispatch provider
635 Reference< XDispatchProvider > xDispatchProvider;
636 if ( m_xDispatchProvider.is() )
637 xDispatchProvider = m_xDispatchProvider;
638 else
639 xDispatchProvider.set( m_xFrame, UNO_QUERY );
640
641 if ( !xDispatchProvider.is() )
642 return true;
643
644 SvtCommandOptions aCmdOptions;
645 for (auto const& menuItemHandler : m_aMenuItemHandlerVector)
646 {
647 if (menuItemHandler)
648 {
649 if ( !menuItemHandler->xMenuItemDispatch.is() &&
650 !menuItemHandler->xSubMenuManager.is() )
651 {
652 Reference< XDispatch > xMenuItemDispatch;
653
654 aTargetURL.Complete = menuItemHandler->aMenuItemURL;
655
656 m_xURLTransformer->parseStrict( aTargetURL );
657
658 if ( bHasDisabledEntries )
659 {
660 if ( aCmdOptions.LookupDisabled( aTargetURL.Path ))
661 pMenu->HideItem( menuItemHandler->nItemId );
662 }
663
664 if ( aTargetURL.Complete.startsWith( ".uno:StyleApply?" ) )
665 xMenuItemDispatch = new StyleDispatcher( m_xFrame, m_xURLTransformer, aTargetURL );
666 else
667 xMenuItemDispatch = xDispatchProvider->queryDispatch( aTargetURL, menuItemHandler->aTargetFrame, 0 );
668
669 bool bPopupMenu( false );
670 if ( !menuItemHandler->xPopupMenuController.is() &&
671 m_xPopupMenuControllerFactory->hasController( menuItemHandler->aMenuItemURL, m_aModuleIdentifier ) )
672 {
673 if( xMenuItemDispatch.is() || menuItemHandler->aMenuItemURL != ".uno:RecentFileList" )
674 bPopupMenu = CreatePopupMenuController(menuItemHandler.get(), m_xDispatchProvider, m_aModuleIdentifier);
675
676 if (bPopupMenu && menuItemHandler->xPopupMenuController.is())
677 {
678 if (PopupMenu* pThisPopup = pMenu->GetPopupMenu(menuItemHandler->nItemId))
679 {
680 pThisPopup->Activate();
681 pThisPopup->Deactivate();
682 }
683 }
684 }
685 else if ( menuItemHandler->xPopupMenuController.is() )
686 {
687 // Force update of popup menu
688 menuItemHandler->xPopupMenuController->updatePopupMenu();
689 bPopupMenu = true;
690 if (PopupMenu* pThisPopup = pMenu->GetPopupMenu( menuItemHandler->nItemId ))
691 {
692 pThisPopup->Activate();
693 pThisPopup->Deactivate();
694 }
695 }
696 lcl_CheckForChildren(pMenu, menuItemHandler->nItemId);
697
698 if ( xMenuItemDispatch.is() )
699 {
700 menuItemHandler->xMenuItemDispatch = xMenuItemDispatch;
701 menuItemHandler->aParsedItemURL = aTargetURL.Complete;
702
703 if ( !bPopupMenu )
704 {
705 xMenuItemDispatch->addStatusListener( static_cast< XStatusListener* >( this ), aTargetURL );
706 // For the menubar, we have to keep status listening to support Ubuntu's HUD.
707 if ( !m_bHasMenuBar )
708 xMenuItemDispatch->removeStatusListener( static_cast< XStatusListener* >( this ), aTargetURL );
709 }
710 }
711 else if ( !bPopupMenu )
712 pMenu->EnableItem( menuItemHandler->nItemId, false );
713 }
714 else if ( menuItemHandler->xPopupMenuController.is() )
715 {
716 // Force update of popup menu
717 menuItemHandler->xPopupMenuController->updatePopupMenu();
718 if (PopupMenu* pThisPopup = pMenu->GetPopupMenu(menuItemHandler->nItemId))
719 {
720 pThisPopup->Activate();
721 pThisPopup->Deactivate();
722 }
723 lcl_CheckForChildren(pMenu, menuItemHandler->nItemId);
724 }
725 else if ( menuItemHandler->xMenuItemDispatch.is() )
726 {
727 // We need an update to reflect the current state
728 try
729 {
730 aTargetURL.Complete = menuItemHandler->aMenuItemURL;
731 m_xURLTransformer->parseStrict( aTargetURL );
732
733 menuItemHandler->xMenuItemDispatch->addStatusListener(
734 static_cast< XStatusListener* >( this ), aTargetURL );
735 menuItemHandler->xMenuItemDispatch->removeStatusListener(
736 static_cast< XStatusListener* >( this ), aTargetURL );
737 }
738 catch ( const Exception& )
739 {
740 }
741 }
742 else if (menuItemHandler->xSubMenuManager.is())
743 {
744 MenuBarManager* pMenuBarManager = static_cast<MenuBarManager*>(menuItemHandler->xSubMenuManager.get());
745 if (pMenuBarManager)
746 {
747 pMenuBarManager->Activate(pMenuBarManager->GetMenuBar());
748 pMenuBarManager->Deactivate(pMenuBarManager->GetMenuBar());
749 }
750 lcl_CheckForChildren(pMenu, menuItemHandler->nItemId);
751 }
752 }
753 }
754
755 return true;
756}
757
758IMPL_LINK( MenuBarManager, Deactivate, Menu *, pMenu, bool )
759{
760 if ( pMenu == m_pVCLMenu )
761 {
762 m_bActive = false;
763 if ( pMenu->IsMenuBar() && m_xDeferredItemContainer.is() )
764 {
765 // Start timer to handle settings asynchronous
766 // Changing the menu inside this handler leads to
767 // a crash under X!
768 m_aAsyncSettingsTimer.SetInvokeHandler(LINK(this, MenuBarManager, AsyncSettingsHdl));
769 m_aAsyncSettingsTimer.SetTimeout(10);
770 m_aAsyncSettingsTimer.Start();
771 }
772 }
773
774 return true;
775}
776
777IMPL_LINK_NOARG( MenuBarManager, AsyncSettingsHdl, Timer*, void)
778{
780 Reference< XInterface > xSelfHold(
781 static_cast< ::cppu::OWeakObject* >( this ), UNO_QUERY_THROW );
782
783 m_aAsyncSettingsTimer.Stop();
784 if ( !m_bActive && m_xDeferredItemContainer.is() )
785 {
786 SetItemContainer( m_xDeferredItemContainer );
787 m_xDeferredItemContainer.clear();
788 }
789}
790
791IMPL_LINK( MenuBarManager, Select, Menu *, pMenu, bool )
792{
794 Sequence<PropertyValue> aArgs;
795 Reference< XDispatch > xDispatch;
796
797 {
799
800 sal_uInt16 nCurItemId = pMenu->GetCurItemId();
801 sal_uInt16 nCurPos = pMenu->GetItemPos( nCurItemId );
802 if ( pMenu == m_pVCLMenu &&
803 pMenu->GetItemType( nCurPos ) != MenuItemType::SEPARATOR )
804 {
805 MenuItemHandler* pMenuItemHandler = GetMenuItemHandler( nCurItemId );
806 if ( pMenuItemHandler && pMenuItemHandler->xMenuItemDispatch.is() )
807 {
808 aTargetURL.Complete = pMenuItemHandler->aMenuItemURL;
809 m_xURLTransformer->parseStrict( aTargetURL );
810
811 if ( pMenu->GetUserValue( nCurItemId ) )
812 {
813 // addon menu item selected
814 aArgs = { comphelper::makePropertyValue("Referer", OUString("private:user")) };
815 }
816
817 xDispatch = pMenuItemHandler->xMenuItemDispatch;
818 }
819 }
820 }
821
822 // tdf#126054 don't let dispatch destroy this until after function completes
823 rtl::Reference<MenuBarManager> xKeepAlive(this);
824 if (xDispatch.is())
825 {
826 SolarMutexReleaser aReleaser;
827 xDispatch->dispatch( aTargetURL, aArgs );
828 }
829
830 if ( !m_bHasMenuBar )
831 // Standalone (non-native) popup menu doesn't fire deactivate event
832 // in this case, so we have to reset the active flag here.
833 m_bActive = false;
834
835 return true;
836}
837
838bool MenuBarManager::MustBeHidden( PopupMenu* pPopupMenu, const Reference< XURLTransformer >& rTransformer )
839{
840 if ( !pPopupMenu )
841 return true;
842
844 SvtCommandOptions aCmdOptions;
845
846 sal_uInt16 nCount = pPopupMenu->GetItemCount();
847 sal_uInt16 nHideCount( 0 );
848
849 for ( sal_uInt16 i = 0; i < nCount; i++ )
850 {
851 sal_uInt16 nId = pPopupMenu->GetItemId( i );
852 if ( nId > 0 )
853 {
854 PopupMenu* pSubPopupMenu = pPopupMenu->GetPopupMenu( nId );
855 if ( pSubPopupMenu )
856 {
857 if ( MustBeHidden( pSubPopupMenu, rTransformer ))
858 {
859 pPopupMenu->HideItem( nId );
860 ++nHideCount;
861 }
862 }
863 else
864 {
865 aTargetURL.Complete = pPopupMenu->GetItemCommand( nId );
866 rTransformer->parseStrict( aTargetURL );
867
868 if ( aCmdOptions.LookupDisabled( aTargetURL.Path ))
869 ++nHideCount;
870 }
871 }
872 else
873 ++nHideCount;
874 }
875
876 return ( nCount == nHideCount );
877}
878
879OUString MenuBarManager::RetrieveLabelFromCommand(const OUString& rCmdURL)
880{
882 if ( !m_bHasMenuBar )
883 {
884 // This is a context menu, prefer "PopupLabel" over "Label".
886 }
888}
889
891 const css::uno::Reference< css::frame::XDispatchProvider >& rDispatchProvider,
892 const OUString& rModuleIdentifier )
893{
894 OUString aItemCommand( pMenuItemHandler->aMenuItemURL );
895
896 // Try instantiate a popup menu controller. It is stored in the menu item handler.
898 return false;
899
901 { "DispatchProvider", Any(rDispatchProvider) },
902 { "ModuleIdentifier", Any(rModuleIdentifier) },
903 { "Frame", Any(m_xFrame) },
904 { "InToolbar", Any(!m_bHasMenuBar) }
905 } ) );
906
907 Reference< XPopupMenuController > xPopupMenuController(
908 m_xPopupMenuControllerFactory->createInstanceWithArgumentsAndContext(
909 aItemCommand,
910 aSeq,
911 m_xContext ),
912 UNO_QUERY );
913
914 if ( xPopupMenuController.is() )
915 {
916 // Provide our awt popup menu to the popup menu controller
917 pMenuItemHandler->xPopupMenuController = xPopupMenuController;
918 xPopupMenuController->setPopupMenu( pMenuItemHandler->xPopupMenu );
919 return true;
920 }
921
922 return false;
923}
924
925void MenuBarManager::FillMenuManager( Menu* pMenu, const Reference< XFrame >& rFrame,
926 const Reference< XDispatchProvider >& rDispatchProvider,
927 const OUString& rModuleIdentifier, bool bDelete )
928{
929 m_xFrame = rFrame;
930 m_bActive = false;
931 m_bDeleteMenu = bDelete;
932 m_pVCLMenu = pMenu;
933 m_xDispatchProvider = rDispatchProvider;
934
937 m_bRetrieveImages = false;
938
939 // Set module identifier when provided from outside
940 if (!rModuleIdentifier.isEmpty())
941 m_aModuleIdentifier = rModuleIdentifier;
942 else
944
945 // Add root as ui configuration listener
947
948 if ( pMenu->IsMenuBar() && rFrame.is() )
949 {
950 // First merge all addon popup menus into our structure
951 sal_uInt16 nPos = 0;
952 for ( nPos = 0; nPos < pMenu->GetItemCount(); nPos++ )
953 {
954 sal_uInt16 nItemId = pMenu->GetItemId( nPos );
955 OUString aCommand = pMenu->GetItemCommand( nItemId );
957 {
958 // Retrieve addon popup menus and add them to our menu bar
959 framework::AddonMenuManager::MergeAddonPopupMenus( rFrame, nPos, static_cast<MenuBar *>(pMenu) );
960 break;
961 }
962 }
963
964 // Merge the Add-Ons help menu items into the Office help menu
965 framework::AddonMenuManager::MergeAddonHelpMenu( rFrame, static_cast<MenuBar *>(pMenu) );
966 }
967
968 bool bAccessibilityEnabled( Application::GetSettings().GetMiscSettings().GetEnableATToolSupport() );
969 sal_uInt16 nItemCount = pMenu->GetItemCount();
970 OUString aItemCommand;
971 m_aMenuItemHandlerVector.reserve(nItemCount);
972 for ( sal_uInt16 i = 0; i < nItemCount; i++ )
973 {
974 sal_uInt16 nItemId = FillItemCommand(aItemCommand,pMenu, i );
975
976 if (( pMenu->IsMenuBar() || bAccessibilityEnabled ) &&
977 ( pMenu->GetItemText( nItemId ).isEmpty() ))
978 {
979 if ( !aItemCommand.isEmpty() )
980 pMenu->SetItemText( nItemId, RetrieveLabelFromCommand( aItemCommand ));
981 }
982
983 // Command can be just an alias to another command.
986 if ( !aRealCommand.isEmpty() )
987 aItemCommand = aRealCommand;
988
989 Reference< XDispatch > xDispatch;
990 Reference< XStatusListener > xStatusListener;
991 VclPtr<PopupMenu> pPopup = pMenu->GetPopupMenu( nItemId );
992 // overwrite the show icons on menu option?
993 MenuItemBits nBits = pMenu->GetItemBits( nItemId ) & ( MenuItemBits::ICON | MenuItemBits::TEXT );
994 bool bItemShowMenuImages = ( m_bShowMenuImages && nBits != MenuItemBits::TEXT ) || nBits & MenuItemBits::ICON;
995
996 if ( pPopup )
997 {
998 // Retrieve module identifier from Help Command entry
999 OUString aModuleIdentifier( rModuleIdentifier );
1000 if (!pMenu->GetHelpCommand(nItemId).isEmpty())
1001 {
1002 aModuleIdentifier = pMenu->GetHelpCommand( nItemId );
1003 pMenu->SetHelpCommand( nItemId, "" );
1004 }
1005
1006 // Retrieve possible attributes struct
1007 Reference< XDispatchProvider > xPopupMenuDispatchProvider( rDispatchProvider );
1008 MenuAttributes* pAttributes = static_cast<MenuAttributes *>(pMenu->GetUserValue( nItemId ));
1009 if ( pAttributes )
1010 xPopupMenuDispatchProvider = pAttributes->xDispatchProvider;
1011
1013 m_xPopupMenuControllerFactory->hasController( aItemCommand, aModuleIdentifier )
1014 )
1015 {
1016 // Check if we have to create a popup menu for a uno based popup menu controller.
1017 // We have to set an empty popup menu into our menu structure so the controller also
1018 // works with inplace OLE.
1019 MenuItemHandler* pItemHandler = new MenuItemHandler( nItemId, xStatusListener, xDispatch );
1020 rtl::Reference<VCLXPopupMenu> pVCLXPopupMenu = new VCLXPopupMenu(pPopup);
1021 pItemHandler->xPopupMenu = pVCLXPopupMenu;
1022 pItemHandler->aMenuItemURL = aItemCommand;
1023 m_aMenuItemHandlerVector.push_back( std::unique_ptr<MenuItemHandler>(pItemHandler) );
1024
1025 if ( bAccessibilityEnabled || pMenu->IsMenuBar())
1026 {
1027 if ( CreatePopupMenuController( pItemHandler, xPopupMenuDispatchProvider, aModuleIdentifier ))
1028 pItemHandler->xPopupMenuController->updatePopupMenu();
1029 }
1030 lcl_CheckForChildren(pMenu, nItemId);
1031 }
1032 else
1033 {
1034 // Check if this is the tools menu. Add menu item if needed
1035 if ( aItemCommand == aCmdToolsMenu && AddonMenuManager::HasAddonMenuElements() )
1036 {
1037 // Create addon popup menu if there exist elements and this is the tools popup menu
1039 if ( pSubMenu && ( pSubMenu->GetItemCount() > 0 ))
1040 {
1041 if ( pPopup->GetItemType( pPopup->GetItemCount() - 1 ) != MenuItemType::SEPARATOR )
1042 pPopup->InsertSeparator();
1043
1044 pPopup->InsertItem( ITEMID_ADDONLIST, OUString() );
1045 pPopup->SetPopupMenu( ITEMID_ADDONLIST, pSubMenu );
1046 pPopup->SetItemCommand( ITEMID_ADDONLIST, ".uno:Addons" );
1047 }
1048 else
1049 pSubMenu.disposeAndClear();
1050 }
1051
1053 xPopupMenuDispatchProvider, aModuleIdentifier, pPopup, false, m_bHasMenuBar );
1054
1055 AddMenu(pSubMenuManager.get(), aItemCommand, nItemId);
1056 }
1057 }
1058 else if ( pMenu->GetItemType( i ) != MenuItemType::SEPARATOR )
1059 {
1060 if ( bItemShowMenuImages )
1061 m_bRetrieveImages = true;
1062
1063 std::unique_ptr<MenuItemHandler> pItemHandler(new MenuItemHandler( nItemId, xStatusListener, xDispatch ));
1064 // Retrieve possible attributes struct
1065 MenuAttributes* pAttributes = static_cast<MenuAttributes *>(pMenu->GetUserValue( nItemId ));
1066 if ( pAttributes )
1067 pItemHandler->aTargetFrame = pAttributes->aTargetFrame;
1068 pItemHandler->aMenuItemURL = aItemCommand;
1069
1071 m_xPopupMenuControllerFactory->hasController( aItemCommand, m_aModuleIdentifier ) )
1072 {
1073 // Check if we have to create a popup menu for a uno based popup menu controller.
1074 // We have to set an empty popup menu into our menu structure so the controller also
1075 // works with inplace OLE.
1076 rtl::Reference<VCLXPopupMenu> pVCLXPopupMenu = new VCLXPopupMenu;
1077 PopupMenu* pPopupMenu = static_cast<PopupMenu *>(pVCLXPopupMenu->GetMenu());
1078 pMenu->SetPopupMenu( pItemHandler->nItemId, pPopupMenu );
1079 pItemHandler->xPopupMenu = pVCLXPopupMenu;
1080
1081 if ( bAccessibilityEnabled && CreatePopupMenuController( pItemHandler.get(), m_xDispatchProvider, m_aModuleIdentifier ) )
1082 {
1083 pItemHandler->xPopupMenuController->updatePopupMenu();
1084 }
1085
1086 lcl_CheckForChildren(pMenu, pItemHandler->nItemId);
1087 }
1088
1089 m_aMenuItemHandlerVector.push_back( std::move(pItemHandler) );
1090 }
1091 }
1092
1093 if ( m_bHasMenuBar && bAccessibilityEnabled )
1094 {
1096 for (auto const& menuItemHandler : m_aMenuItemHandlerVector)
1097 {
1098 // Set key code, workaround for hard-coded shortcut F1 mapped to .uno:HelpIndex
1099 // Only non-popup menu items can have a short-cut
1100 if ( menuItemHandler->aMenuItemURL == aCmdHelpIndex )
1101 {
1102 vcl::KeyCode aKeyCode( KEY_F1 );
1103 pMenu->SetAccelKey( menuItemHandler->nItemId, aKeyCode );
1104 }
1105 else if ( pMenu->GetPopupMenu( menuItemHandler->nItemId ) == nullptr )
1106 pMenu->SetAccelKey( menuItemHandler->nItemId, menuItemHandler->aKeyCode );
1107 }
1108 }
1109
1110 SetHdl();
1111}
1112
1114 const Reference< XAcceleratorConfiguration >& rAccelCfg,
1115 const Sequence< OUString >& rCommands,
1116 std::vector< std::unique_ptr<MenuItemHandler> >& aMenuShortCuts )
1117{
1118 if ( !rAccelCfg.is() )
1119 return;
1120
1121 try
1122 {
1123 css::awt::KeyEvent aKeyEvent;
1124 Sequence< Any > aSeqKeyCode = rAccelCfg->getPreferredKeyEventsForCommandList( rCommands );
1125 for ( sal_Int32 i = 0; i < aSeqKeyCode.getLength(); i++ )
1126 {
1127 if ( aSeqKeyCode[i] >>= aKeyEvent )
1128 aMenuShortCuts[i]->aKeyCode = svt::AcceleratorExecute::st_AWTKey2VCLKey( aKeyEvent );
1129 }
1130 }
1131 catch ( const IllegalArgumentException& )
1132 {
1133 }
1134}
1135
1136void MenuBarManager::RetrieveShortcuts( std::vector< std::unique_ptr<MenuItemHandler> >& aMenuShortCuts )
1137{
1138 Reference< XAcceleratorConfiguration > xDocAccelCfg( m_xDocAcceleratorManager );
1139 Reference< XAcceleratorConfiguration > xModuleAccelCfg( m_xModuleAcceleratorManager );
1140 Reference< XAcceleratorConfiguration > xGlobalAccelCfg( m_xGlobalAcceleratorManager );
1141
1142 if ( !m_bAcceleratorCfg )
1143 {
1144 // Retrieve references on demand
1145 m_bAcceleratorCfg = true;
1146 if ( !xDocAccelCfg.is() )
1147 {
1148 Reference< XController > xController = m_xFrame->getController();
1149 Reference< XModel > xModel;
1150 if ( xController.is() )
1151 {
1152 xModel = xController->getModel();
1153 if ( xModel.is() )
1154 {
1155 Reference< XUIConfigurationManagerSupplier > xSupplier( xModel, UNO_QUERY );
1156 if ( xSupplier.is() )
1157 {
1158 Reference< XUIConfigurationManager > xDocUICfgMgr = xSupplier->getUIConfigurationManager();
1159 if ( xDocUICfgMgr.is() )
1160 {
1161 xDocAccelCfg = xDocUICfgMgr->getShortCutManager();
1162 m_xDocAcceleratorManager = xDocAccelCfg;
1163 }
1164 }
1165 }
1166 }
1167 }
1168
1169 if ( !xModuleAccelCfg.is() )
1170 {
1171 Reference< XModuleUIConfigurationManagerSupplier > xModuleCfgMgrSupplier =
1172 theModuleUIConfigurationManagerSupplier::get( m_xContext );
1173 try
1174 {
1175 Reference< XUIConfigurationManager > xUICfgMgr = xModuleCfgMgrSupplier->getUIConfigurationManager( m_aModuleIdentifier );
1176 if ( xUICfgMgr.is() )
1177 {
1178 xModuleAccelCfg = xUICfgMgr->getShortCutManager();
1179 m_xModuleAcceleratorManager = xModuleAccelCfg;
1180 }
1181 }
1182 catch ( const RuntimeException& )
1183 {
1184 throw;
1185 }
1186 catch ( const Exception& )
1187 {
1188 }
1189 }
1190
1191 if ( !xGlobalAccelCfg.is() ) try
1192 {
1193 xGlobalAccelCfg = GlobalAcceleratorConfiguration::create( m_xContext );
1194 m_xGlobalAcceleratorManager = xGlobalAccelCfg;
1195 }
1196 catch ( const css::uno::DeploymentException& )
1197 {
1198 SAL_WARN("fwk.uielement", "GlobalAcceleratorConfiguration"
1199 " not available. This should happen only on mobile platforms.");
1200 }
1201 }
1202
1203 vcl::KeyCode aEmptyKeyCode;
1204 Sequence< OUString > aSeq( aMenuShortCuts.size() );
1205 auto aSeqRange = asNonConstRange(aSeq);
1206 const sal_uInt32 nCount = aMenuShortCuts.size();
1207 for ( sal_uInt32 i = 0; i < nCount; ++i )
1208 {
1209 aSeqRange[i] = aMenuShortCuts[i]->aMenuItemURL;
1210 aMenuShortCuts[i]->aKeyCode = aEmptyKeyCode;
1211 }
1212
1213 if ( m_xGlobalAcceleratorManager.is() )
1214 impl_RetrieveShortcutsFromConfiguration( xGlobalAccelCfg, aSeq, aMenuShortCuts );
1215 if ( m_xModuleAcceleratorManager.is() )
1216 impl_RetrieveShortcutsFromConfiguration( xModuleAccelCfg, aSeq, aMenuShortCuts );
1217 if ( m_xDocAcceleratorManager.is() )
1218 impl_RetrieveShortcutsFromConfiguration( xDocAccelCfg, aSeq, aMenuShortCuts );
1219}
1220
1222{
1223 if ( !m_xDocImageManager.is() )
1224 {
1225 Reference< XController > xController = m_xFrame->getController();
1226 Reference< XModel > xModel;
1227 if ( xController.is() )
1228 {
1229 xModel = xController->getModel();
1230 if ( xModel.is() )
1231 {
1232 Reference< XUIConfigurationManagerSupplier > xSupplier( xModel, UNO_QUERY );
1233 if ( xSupplier.is() )
1234 {
1235 Reference< XUIConfigurationManager > xDocUICfgMgr = xSupplier->getUIConfigurationManager();
1236 m_xDocImageManager.set( xDocUICfgMgr->getImageManager(), UNO_QUERY );
1237 m_xDocImageManager->addConfigurationListener(
1238 Reference< XUIConfigurationListener >(this) );
1239 }
1240 }
1241 }
1242 }
1243
1244 if ( !m_xModuleImageManager.is() )
1245 {
1246 Reference< XModuleUIConfigurationManagerSupplier > xModuleCfgMgrSupplier =
1247 theModuleUIConfigurationManagerSupplier::get( m_xContext );
1248 Reference< XUIConfigurationManager > xUICfgMgr = xModuleCfgMgrSupplier->getUIConfigurationManager( m_aModuleIdentifier );
1249 m_xModuleImageManager.set( xUICfgMgr->getImageManager(), UNO_QUERY );
1250 m_xModuleImageManager->addConfigurationListener( Reference< XUIConfigurationListener >(this) );
1251 }
1252}
1253
1255 sal_uInt16& nId,
1256 Menu* pMenu,
1257 const OUString& rModuleIdentifier,
1258 const Reference< XIndexAccess >& rItemContainer,
1259 const Reference< XURLTransformer >& rTransformer )
1260{
1261 Reference< XDispatchProvider > xEmptyDispatchProvider;
1262 MenuBarManager::FillMenu( nId, pMenu, rModuleIdentifier, rItemContainer, xEmptyDispatchProvider );
1263
1264 // Merge add-on menu entries into the menu bar
1266 AddonsOptions().GetMergeMenuInstructions(),
1267 rModuleIdentifier );
1268
1269 bool bHasDisabledEntries = SvtCommandOptions().HasEntriesDisabled();
1270 if ( !bHasDisabledEntries )
1271 return;
1272
1273 sal_uInt16 nCount = pMenu->GetItemCount();
1274 for ( sal_uInt16 i = 0; i < nCount; i++ )
1275 {
1276 sal_uInt16 nID = pMenu->GetItemId( i );
1277 if ( nID > 0 )
1278 {
1279 PopupMenu* pPopupMenu = pMenu->GetPopupMenu( nID );
1280 if ( pPopupMenu )
1281 {
1282 if ( MustBeHidden( pPopupMenu, rTransformer ))
1283 pMenu->HideItem( nId );
1284 }
1285 }
1286 }
1287}
1288
1290 sal_uInt16& nId,
1291 Menu* pMenu,
1292 const OUString& rModuleIdentifier,
1293 const Reference< XIndexAccess >& rItemContainer,
1294 const Reference< XDispatchProvider >& rDispatchProvider )
1295{
1296 // Fill menu bar with container contents
1297 for ( sal_Int32 n = 0; n < rItemContainer->getCount(); n++ )
1298 {
1299 Sequence< PropertyValue > aProps;
1300 OUString aCommandURL;
1301 OUString aLabel;
1302 OUString aModuleIdentifier( rModuleIdentifier );
1303 sal_uInt16 nType = 0;
1304 Reference< XIndexAccess > xIndexContainer;
1305 Reference< XDispatchProvider > xDispatchProvider( rDispatchProvider );
1306 sal_Int16 nStyle = 0;
1307 try
1308 {
1309 if ( rItemContainer->getByIndex( n ) >>= aProps )
1310 {
1311 bool bShow = true;
1312 bool bEnabled = true;
1313
1314 for ( beans::PropertyValue const & rProp : std::as_const(aProps) )
1315 {
1316 OUString aPropName = rProp.Name;
1317 if ( aPropName == "CommandURL" )
1318 rProp.Value >>= aCommandURL;
1319 else if ( aPropName == "ItemDescriptorContainer" )
1320 rProp.Value >>= xIndexContainer;
1321 else if ( aPropName == "Label" )
1322 rProp.Value >>= aLabel;
1323 else if ( aPropName == "Type" )
1324 rProp.Value >>= nType;
1325 else if ( aPropName == "ModuleIdentifier" )
1326 rProp.Value >>= aModuleIdentifier;
1327 else if ( aPropName == "DispatchProvider" )
1328 rProp.Value >>= xDispatchProvider;
1329 else if ( aPropName == "Style" )
1330 rProp.Value >>= nStyle;
1331 else if ( aPropName == "IsVisible" )
1332 rProp.Value >>= bShow;
1333 else if ( aPropName == "Enabled" )
1334 rProp.Value >>= bEnabled;
1335 }
1336
1337 if (!aCommandURL.isEmpty() && vcl::CommandInfoProvider::IsExperimental(aCommandURL, rModuleIdentifier) &&
1338 !officecfg::Office::Common::Misc::ExperimentalMode::get())
1339 {
1340 continue;
1341 }
1342
1343 if ( nType == css::ui::ItemType::DEFAULT )
1344 {
1345 pMenu->InsertItem( nId, aLabel );
1346 pMenu->SetItemCommand( nId, aCommandURL );
1347
1348 if ( nStyle )
1349 {
1350 MenuItemBits nBits = pMenu->GetItemBits( nId );
1351 if ( nStyle & css::ui::ItemStyle::ICON )
1352 nBits |= MenuItemBits::ICON;
1353 if ( nStyle & css::ui::ItemStyle::TEXT )
1354 nBits |= MenuItemBits::TEXT;
1355 if ( nStyle & css::ui::ItemStyle::RADIO_CHECK )
1356 nBits |= MenuItemBits::RADIOCHECK;
1357 pMenu->SetItemBits( nId, nBits );
1358 }
1359
1360 if ( !bShow )
1361 pMenu->HideItem( nId );
1362
1363 if ( !bEnabled)
1364 pMenu->EnableItem( nId, false );
1365
1366 if ( xIndexContainer.is() )
1367 {
1369 pMenu->SetPopupMenu( nId, pNewPopupMenu );
1370 // Use the command URL as the Help ID for the sub menu
1371 pNewPopupMenu->SetHelpId(aCommandURL);
1372
1373 if ( xDispatchProvider.is() )
1374 {
1375 // Use attributes struct to transport special dispatch provider
1376 void* nAttributePtr = MenuAttributes::CreateAttribute(xDispatchProvider);
1377 pMenu->SetUserValue(nId, nAttributePtr, MenuAttributes::ReleaseAttribute);
1378 }
1379
1380 // Use help command to transport module identifier
1381 if ( !aModuleIdentifier.isEmpty() )
1382 pMenu->SetHelpCommand( nId, aModuleIdentifier );
1383
1384 ++nId;
1385 FillMenu( nId, pNewPopupMenu, aModuleIdentifier, xIndexContainer, xDispatchProvider );
1386 }
1387 else
1388 ++nId;
1389 }
1390 else
1391 {
1392 pMenu->InsertSeparator();
1393 ++nId;
1394 }
1395 }
1396 }
1397 catch ( const IndexOutOfBoundsException& )
1398 {
1399 break;
1400 }
1401 }
1402}
1403
1405 Menu* pMenuBar,
1406 const MergeMenuInstructionContainer& aMergeInstructionContainer,
1407 const OUString& rModuleIdentifier )
1408{
1409 // set start value for the item ID for the new addon menu items
1410 sal_uInt16 nItemId = ADDONMENU_MERGE_ITEMID_START;
1411
1412 const sal_uInt32 nCount = aMergeInstructionContainer.size();
1413 for ( sal_uInt32 i = 0; i < nCount; i++ )
1414 {
1415 const MergeMenuInstruction& rMergeInstruction = aMergeInstructionContainer[i];
1416
1417 if ( MenuBarMerger::IsCorrectContext( rMergeInstruction.aMergeContext, rModuleIdentifier ))
1418 {
1419 ::std::vector< OUString > aMergePath;
1420
1421 // retrieve the merge path from the merge point string
1422 MenuBarMerger::RetrieveReferencePath( rMergeInstruction.aMergePoint, aMergePath );
1423
1424 // convert the sequence/sequence property value to a more convenient vector<>
1425 AddonMenuContainer aMergeMenuItems;
1426 MenuBarMerger::GetSubMenu( rMergeInstruction.aMergeMenu, aMergeMenuItems );
1427
1428 // try to find the reference point for our merge operation
1429 Menu* pMenu = pMenuBar;
1430 ReferencePathInfo aResult = MenuBarMerger::FindReferencePath( aMergePath, pMenu );
1431
1432 if ( aResult.eResult == RP_OK )
1433 {
1434 // normal merge operation
1436 aResult.nPos,
1437 nItemId,
1438 rMergeInstruction.aMergeCommand,
1439 rMergeInstruction.aMergeCommandParameter,
1440 rModuleIdentifier,
1441 aMergeMenuItems );
1442 }
1443 else
1444 {
1445 // fallback
1447 nItemId,
1448 rMergeInstruction.aMergeCommand,
1449 rMergeInstruction.aMergeFallback,
1450 aMergePath,
1451 rModuleIdentifier,
1452 aMergeMenuItems );
1453 }
1454 }
1455 }
1456}
1457
1458void MenuBarManager::SetItemContainer( const Reference< XIndexAccess >& rItemContainer )
1459{
1460 SolarMutexGuard aSolarMutexGuard;
1461
1462 Reference< XFrame > xFrame = m_xFrame;
1463
1464 // Clear MenuBarManager structures
1465 {
1466 // Check active state as we cannot change our VCL menu during activation by the user
1467 if ( m_bActive )
1468 {
1469 m_xDeferredItemContainer = rItemContainer;
1470 return;
1471 }
1472
1475 m_pVCLMenu->Clear();
1476
1477 sal_uInt16 nId = 1;
1478
1479 // Fill menu bar with container contents
1481
1482 // Refill menu manager again
1483 Reference< XDispatchProvider > xDispatchProvider;
1484 FillMenuManager( m_pVCLMenu, xFrame, xDispatchProvider, m_aModuleIdentifier, false );
1485
1486 // add itself as frame action listener
1487 m_xFrame->addFrameActionListener( Reference< XFrameActionListener >(this) );
1488 }
1489}
1490
1492{
1493
1494 SolarMutexGuard aSolarMutexGuard;
1495
1496 for (auto const& menuItemHandler : m_aMenuItemHandlerVector)
1497 {
1498 if ( menuItemHandler->xPopupMenuController.is() )
1499 {
1500 Reference< XDispatchProvider > xDispatchProvider( menuItemHandler->xPopupMenuController, UNO_QUERY );
1501
1502 PopupControllerEntry aPopupControllerEntry;
1503 aPopupControllerEntry.m_xDispatchProvider = xDispatchProvider;
1504
1505 // Just use the main part of the URL for popup menu controllers
1506 sal_Int32 nSchemePart( 0 );
1507 OUString aMenuURL( menuItemHandler->aMenuItemURL );
1508
1509 nSchemePart = aMenuURL.indexOf( ':' );
1510 if (( nSchemePart > 0 ) &&
1511 ( aMenuURL.getLength() > ( nSchemePart+1 )))
1512 {
1513 OUString aMainURL( "vnd.sun.star.popup:" );
1514 sal_Int32 nQueryPart = aMenuURL.indexOf( '?', nSchemePart );
1515 if ( nQueryPart > 0 )
1516 aMainURL += aMenuURL.subView( nSchemePart, nQueryPart-nSchemePart );
1517 else if ( nQueryPart == -1 )
1518 aMainURL += aMenuURL.subView( nSchemePart+1 );
1519
1520 rPopupController.emplace( aMainURL, aPopupControllerEntry );
1521 }
1522 }
1523 if ( menuItemHandler->xSubMenuManager.is() )
1524 {
1525 MenuBarManager* pMenuBarManager = static_cast<MenuBarManager*>(menuItemHandler->xSubMenuManager.get());
1526 if ( pMenuBarManager )
1527 pMenuBarManager->GetPopupController( rPopupController );
1528 }
1529 }
1530}
1531
1532void MenuBarManager::AddMenu(MenuBarManager* pSubMenuManager,const OUString& _sItemCommand,sal_uInt16 _nItemId)
1533{
1534 Reference< XStatusListener > xSubMenuManager( pSubMenuManager );
1535 m_xFrame->addFrameActionListener( Reference< XFrameActionListener >( xSubMenuManager, UNO_QUERY ));
1536
1537 Reference< XDispatch > xDispatch;
1538 std::unique_ptr<MenuItemHandler> pMenuItemHandler(new MenuItemHandler(
1539 _nItemId,
1540 xSubMenuManager,
1541 xDispatch ));
1542 pMenuItemHandler->aMenuItemURL = _sItemCommand;
1543 m_aMenuItemHandlerVector.push_back( std::move(pMenuItemHandler) );
1544}
1545
1546sal_uInt16 MenuBarManager::FillItemCommand(OUString& _rItemCommand, Menu* _pMenu,sal_uInt16 _nIndex) const
1547{
1548 sal_uInt16 nItemId = _pMenu->GetItemId( _nIndex );
1549
1550 _rItemCommand = _pMenu->GetItemCommand( nItemId );
1551 if ( _rItemCommand.isEmpty() )
1552 {
1553 _rItemCommand = "slot:" + OUString::number( nItemId );
1554 _pMenu->SetItemCommand( nItemId, _rItemCommand );
1555 }
1556 return nItemId;
1557}
1558
1560{
1561 m_pVCLMenu->SetActivateHdl( LINK( this, MenuBarManager, Activate ));
1562 m_pVCLMenu->SetDeactivateHdl( LINK( this, MenuBarManager, Deactivate ));
1563 m_pVCLMenu->SetSelectHdl( LINK( this, MenuBarManager, Select ));
1564
1565 if ( !m_xURLTransformer.is() && m_xContext.is() )
1566 m_xURLTransformer.set( URLTransformer::create( m_xContext) );
1567}
1568
1569void MenuBarManager::FillMenuImages(Reference< XFrame > const & _xFrame, Menu* _pMenu,bool bShowMenuImages)
1570{
1571 AddonsOptions aAddonOptions;
1572
1573 for ( sal_uInt16 nPos = 0; nPos < _pMenu->GetItemCount(); nPos++ )
1574 {
1575 sal_uInt16 nId = _pMenu->GetItemId( nPos );
1576 if ( _pMenu->GetItemType( nPos ) != MenuItemType::SEPARATOR )
1577 {
1578 // overwrite the show icons on menu option?
1579 MenuItemBits nBits = _pMenu->GetItemBits( nId ) & ( MenuItemBits::ICON | MenuItemBits::TEXT );
1580 bool bTmpShowMenuImages = ( bShowMenuImages && nBits != MenuItemBits::TEXT ) || nBits & MenuItemBits::ICON;
1581
1582 if ( bTmpShowMenuImages )
1583 {
1584 OUString aMenuItemCommand = _pMenu->GetItemCommand( nId );
1585 Image aImage = vcl::CommandInfoProvider::GetImageForCommand(aMenuItemCommand, _xFrame);
1586 if ( !aImage )
1587 aImage = Image(aAddonOptions.GetImageFromURL(aMenuItemCommand, false));
1588
1589 _pMenu->SetItemImage( nId, aImage );
1590 }
1591 else
1592 _pMenu->SetItemImage( nId, Image() );
1593 }
1594 }
1595}
1596
1597}
1598
1599/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
PropertiesInfo aProperties
css::uno::Reference< css::lang::XComponent > m_xFrame
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
void SetItemImage(sal_uInt16 nItemId, const Image &rImage)
void InsertSeparator(const OUString &rIdent={}, sal_uInt16 nPos=MENU_APPEND)
void SetItemText(sal_uInt16 nItemId, const OUString &rStr)
OUString GetItemText(sal_uInt16 nItemId) const
virtual bool IsMenuBar() const=0
MenuItemBits GetItemBits(sal_uInt16 nItemId) const
MenuItemType GetItemType(sal_uInt16 nPos) const
OUString GetItemCommand(sal_uInt16 nItemId) const
sal_uInt16 GetItemId(sal_uInt16 nPos) const
void SetUserValue(sal_uInt16 nItemId, void *nUserValue, MenuUserDataReleaseFunction aFunc=nullptr)
void SetAccelKey(sal_uInt16 nItemId, const vcl::KeyCode &rKeyCode)
void SetItemCommand(sal_uInt16 nItemId, const OUString &rCommand)
PopupMenu * GetPopupMenu(sal_uInt16 nItemId) const
void EnableItem(sal_uInt16 nItemId, bool bEnable=true)
void SetPopupMenu(sal_uInt16 nItemId, PopupMenu *pMenu)
void * GetUserValue(sal_uInt16 nItemId) const
void SetItemBits(sal_uInt16 nItemId, MenuItemBits nBits)
void HideItem(sal_uInt16 nItemId)
void SetHelpCommand(sal_uInt16 nItemId, const OUString &rString)
void InsertItem(sal_uInt16 nItemId, const OUString &rStr, MenuItemBits nItemBits=MenuItemBits::NONE, const OUString &rIdent={}, sal_uInt16 nPos=MENU_APPEND)
OUString GetHelpCommand(sal_uInt16 nItemId) const
sal_uInt16 GetItemCount() const
bool GetContextMenuShortcuts() const
bool GetUseImagesInMenus() const
bool LookupDisabled(const OUString &aCommandURL) const
bool HasEntriesDisabled() const
static OUString GetIconTheme()
void Stop()
void disposeAndClear()
void clear()
static VclPtr< reference_type > Create(Arg &&... arg)
static bool HasAddonMenuElements()
Definition: addonmenu.cxx:38
static void MergeAddonPopupMenus(const css::uno::Reference< css::frame::XFrame > &rFrame, sal_uInt16 nMergeAtPos, MenuBar *pMergeMenuBar)
Definition: addonmenu.cxx:134
static void MergeAddonHelpMenu(const css::uno::Reference< css::frame::XFrame > &rFrame, MenuBar const *pMergeMenuBar)
Definition: addonmenu.cxx:89
static VclPtr< PopupMenu > CreateAddonMenu(const css::uno::Reference< css::frame::XFrame > &rFrame)
Definition: addonmenu.cxx:44
virtual void SAL_CALL frameAction(const css::frame::FrameActionEvent &Action) override
css::uno::Reference< css::frame::XDispatchProvider > m_xDispatchProvider
css::uno::Reference< css::uno::XComponentContext > m_xContext
static bool MustBeHidden(PopupMenu *pPopupMenu, const css::uno::Reference< css::util::XURLTransformer > &rTransformer)
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
virtual css::uno::Any SAL_CALL getMenuHandle(const css::uno::Sequence< sal_Int8 > &ProcessId, sal_Int16 SystemType) override
css::uno::Reference< css::ui::XImageManager > m_xDocImageManager
static void FillMenuImages(css::uno::Reference< css::frame::XFrame > const &xFrame, Menu *_pMenu, bool bShowMenuImages)
void AddMenu(MenuBarManager *pSubMenuManager, const OUString &_sItemCommand, sal_uInt16 _nItemId)
css::uno::Reference< css::ui::XAcceleratorConfiguration > m_xDocAcceleratorManager
bool CreatePopupMenuController(MenuItemHandler *pMenuItemHandler, const css::uno::Reference< css::frame::XDispatchProvider > &rDispatchProvider, const OUString &rModuleIdentifier)
css::uno::Reference< css::frame::XUIControllerFactory > m_xPopupMenuControllerFactory
void RetrieveShortcuts(std::vector< std::unique_ptr< MenuItemHandler > > &aMenuShortCuts)
sal_uInt16 FillItemCommand(OUString &_rItemCommand, Menu *_pMenu, sal_uInt16 _nIndex) const
virtual void SAL_CALL elementRemoved(const css::ui::ConfigurationEvent &Event) override
css::uno::Reference< css::ui::XImageManager > m_xModuleImageManager
static void MergeAddonMenus(Menu *pMenuBar, const MergeMenuInstructionContainer &, const OUString &aModuleIdentifier)
css::uno::Reference< css::ui::XAcceleratorConfiguration > m_xGlobalAcceleratorManager
::std::vector< std::unique_ptr< MenuItemHandler > > m_aMenuItemHandlerVector
virtual ~MenuBarManager() override
void FillMenuManager(Menu *pMenu, const css::uno::Reference< css::frame::XFrame > &rFrame, const css::uno::Reference< css::frame::XDispatchProvider > &rDispatchProvider, const OUString &rModuleIdentifier, bool bDelete)
void GetPopupController(PopupControllerCache &rPopupController)
OUString RetrieveLabelFromCommand(const OUString &rCmdURL)
virtual void SAL_CALL elementInserted(const css::ui::ConfigurationEvent &Event) override
void SetItemContainer(const css::uno::Reference< css::container::XIndexAccess > &rItemContainer)
MenuBarManager(const css::uno::Reference< css::uno::XComponentContext > &xContext, const css::uno::Reference< css::frame::XFrame > &rFrame, const css::uno::Reference< css::util::XURLTransformer > &_xURLTransformer, const css::uno::Reference< css::frame::XDispatchProvider > &rDispatchProvider, const OUString &aModuleIdentifier, Menu *pMenu, bool bDelete, bool bHasMenuBar=true)
css::uno::Reference< css::frame::XFrame > m_xFrame
virtual void SAL_CALL statusChanged(const css::frame::FeatureStateEvent &Event) override
css::uno::Reference< css::ui::XAcceleratorConfiguration > m_xModuleAcceleratorManager
css::uno::Reference< css::container::XIndexAccess > m_xDeferredItemContainer
MenuItemHandler * GetMenuItemHandler(sal_uInt16 nItemId)
static void impl_RetrieveShortcutsFromConfiguration(const css::uno::Reference< css::ui::XAcceleratorConfiguration > &rAccelCfg, const css::uno::Sequence< OUString > &rCommands, std::vector< std::unique_ptr< MenuItemHandler > > &aMenuShortCuts)
static void FillMenuWithConfiguration(sal_uInt16 &nId, Menu *pMenu, const OUString &rModuleIdentifier, const css::uno::Reference< css::container::XIndexAccess > &rItemContainer, const css::uno::Reference< css::util::XURLTransformer > &rTransformer)
css::uno::Reference< css::util::XURLTransformer > m_xURLTransformer
virtual void SAL_CALL elementReplaced(const css::ui::ConfigurationEvent &Event) override
static void FillMenu(sal_uInt16 &nId, Menu *pMenu, const OUString &rModuleIdentifier, const css::uno::Reference< css::container::XIndexAccess > &rItemContainer, const css::uno::Reference< css::frame::XDispatchProvider > &rDispatchProvider)
A dispatcher that serves as a proxy for style commands with arguments i.e.
static vcl::KeyCode st_AWTKey2VCLKey(const css::awt::KeyEvent &aKey)
int nCount
Reference< XDispatch > xDispatch
URL aURL
float u
OUString FwkResId(TranslateId aId)
Definition: fwkresid.cxx:22
css::uno::Reference< css::uno::XComponentContext > m_xContext
constexpr OUStringLiteral JAVA_INTERACTION_HANDLER_NAME
sal_Int64 n
uno_Any a
constexpr sal_uInt16 KEY_F1
sal_uInt16 nPos
Sequence< sal_Int8 > aSeq
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
MenuFlags
css::uno::Reference< css::uno::XCurrentContext > context_
const sal_uInt16 ITEMID_ADDONLIST
const sal_uInt16 ADDONMENU_MERGE_ITEMID_START
@ Exception
css::uno::Sequence< css::uno::Any > InitAnyPropertySequence(::std::initializer_list< ::std::pair< OUString, css::uno::Any > > vInit)
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
bool ProcessFallbackOperation(const ReferencePathInfo &aRefPathInfo, sal_uInt16 &rItemId, std::u16string_view rMergeCommand, std::u16string_view rMergeFallback, const ::std::vector< OUString > &rReferencePath, std::u16string_view rModuleIdentifier, const AddonMenuContainer &rAddonMenuItems)
void GetSubMenu(const css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > &rSubMenuEntries, AddonMenuContainer &rSubMenu)
bool ProcessMergeOperation(Menu *pMenu, sal_uInt16 nPos, sal_uInt16 &rItemId, std::u16string_view rMergeCommand, std::u16string_view rMergeCommandParameter, const OUString &rModuleIdentifier, const AddonMenuContainer &rAddonMenuItems)
bool IsCorrectContext(std::u16string_view aContext, std::u16string_view aModuleIdentifier)
Check whether a module identifier is part of a context defined by a colon separated list of module id...
void RetrieveReferencePath(std::u16string_view, std::vector< OUString > &aReferencePath)
ReferencePathInfo FindReferencePath(const std::vector< OUString > &aReferencePath, Menu *pMenu)
::std::vector< MergeMenuInstruction > MergeMenuInstructionContainer
std::unordered_map< OUString, PopupControllerEntry > PopupControllerCache
constexpr OUStringLiteral aCmdToolsMenu
static void lcl_CheckForChildren(Menu *pMenu, sal_uInt16 nItemId)
IMPL_LINK(WindowCommandDispatch, impl_notifyCommand, VclWindowEvent &, rEvent, void)
::std::vector< AddonMenuItem > AddonMenuContainer
IMPL_LINK_NOARG(CloseDispatcher, impl_asyncCallback, LinkParamNone *, void)
asynchronous callback @descr We start all actions inside this object asynchronous (see comments there...
constexpr OUStringLiteral aCmdHelpIndex
constexpr OUStringLiteral aSpecialWindowCommand
constexpr OUStringLiteral aCmdHelpMenu
int i
OUString aPropName
Sequence< beans::PropertyValue > GetCommandProperties(const OUString &rsCommandName, const OUString &rsModuleName)
OUString GetRealCommandForCommand(const css::uno::Sequence< css::beans::PropertyValue > &rProperties)
OUString GetModuleIdentifier(const Reference< frame::XFrame > &rxFrame)
OUString GetPopupLabelForCommand(const css::uno::Sequence< css::beans::PropertyValue > &rProperties)
Image GetImageForCommand(const OUString &rsCommandName, const Reference< frame::XFrame > &rxFrame, vcl::ImageType eImageType)
bool IsExperimental(const OUString &rsCommandName, const OUString &rModuleName)
OUString GetMenuLabelForCommand(const css::uno::Sequence< css::beans::PropertyValue > &rProperties)
sal_Int16 nId
QPRO_FUNC_TYPE nType
static void ReleaseAttribute(void *nAttributePtr)
css::uno::WeakReference< css::frame::XDispatchProvider > xDispatchProvider
static void * CreateAttribute(const OUString &rFrame, const OUString &rImageIdStr)
css::uno::Reference< css::frame::XPopupMenuController > xPopupMenuController
css::uno::Reference< css::awt::XPopupMenu > xPopupMenu
css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > aMergeMenu
css::uno::WeakReference< css::frame::XDispatchProvider > m_xDispatchProvider
Reference< XController > xController
Reference< XFrame > xFrame
Reference< XModel > xModel
OUString aCommand
OUString Name
OUString aTargetURL
OUString aLabel
MenuItemBits