LibreOffice Module framework (master) 1
toolbarsmenucontroller.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
21
22#include <algorithm>
23#include <string_view>
24#include <unordered_map>
25
26#include <services.h>
27#include <strings.hrc>
28#include <classes/fwkresid.hxx>
31
32#include <com/sun/star/beans/PropertyValue.hpp>
33#include <com/sun/star/awt/MenuItemStyle.hpp>
34#include <com/sun/star/frame/ModuleManager.hpp>
35#include <com/sun/star/frame/XDispatchProvider.hpp>
36#include <com/sun/star/util/XURLTransformer.hpp>
37#include <com/sun/star/beans/XPropertySet.hpp>
38#include <com/sun/star/frame/XLayoutManager.hpp>
39#include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
40#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
41#include <com/sun/star/ui/UIElementType.hpp>
42#include <com/sun/star/ui/theWindowStateConfiguration.hpp>
43
45#include <officecfg/Office/Common.hxx>
46#include <vcl/svapp.hxx>
47#include <vcl/settings.hxx>
49#include <rtl/ustrbuf.hxx>
52#include <vcl/window.hxx>
57
58// Defines
59
60using namespace ::com::sun::star;
61using namespace ::com::sun::star::uno;
62using namespace ::com::sun::star::lang;
63using namespace ::com::sun::star::frame;
64using namespace ::com::sun::star::beans;
65using namespace ::com::sun::star::util;
66using namespace ::com::sun::star::container;
67using namespace ::com::sun::star::ui;
68
69constexpr OUStringLiteral CMD_RESTOREVISIBILITY = u".cmd:RestoreVisibility";
70constexpr OUStringLiteral CMD_LOCKTOOLBARS = u".uno:ToolbarLock";
71
72constexpr OUStringLiteral STATIC_CMD_PART = u".uno:AvailableToolbars?Toolbar:string=";
73const char STATIC_INTERNAL_CMD_PART[] = ".cmd:";
74
75namespace framework
76{
77
78typedef std::unordered_map< OUString, OUString > ToolbarHashMap;
79
80namespace {
81
82struct ToolBarEntry
83{
84 OUString aUIName;
85 OUString aCommand;
88};
89
90}
91
92static bool CompareToolBarEntry( const ToolBarEntry& aOne, const ToolBarEntry& aTwo )
93{
94 sal_Int32 nComp = aOne.pCollatorWrapper->compareString( aOne.aUIName, aTwo.aUIName );
95
96 return nComp < 0;
97}
98
99static Reference< XLayoutManager > getLayoutManagerFromFrame( const Reference< XFrame >& rFrame )
100{
101 Reference< XPropertySet > xPropSet( rFrame, UNO_QUERY );
102 Reference< XLayoutManager > xLayoutManager;
103
104 try
105 {
106 xPropSet->getPropertyValue("LayoutManager") >>= xLayoutManager;
107 }
108 catch ( const UnknownPropertyException& )
109 {
110 }
111
112 return xLayoutManager;
113}
114
115namespace {
116
117struct ToolBarInfo
118{
121};
122
123}
124
125// XInterface, XTypeProvider, XServiceInfo
126
128{
129 return "com.sun.star.comp.framework.ToolBarsMenuController";
130}
131
132sal_Bool SAL_CALL ToolbarsMenuController::supportsService( const OUString& sServiceName )
133{
135}
136
137css::uno::Sequence< OUString > SAL_CALL ToolbarsMenuController::getSupportedServiceNames()
138{
140}
141
142constexpr OUStringLiteral g_aPropUIName( u"UIName" );
143constexpr OUStringLiteral g_aPropResourceURL( u"ResourceURL" );
144
145ToolbarsMenuController::ToolbarsMenuController( const css::uno::Reference< css::uno::XComponentContext >& xContext ) :
146 svt::PopupMenuControllerBase( xContext ),
147 m_xContext( xContext ),
148 m_bResetActive( false ),
149 m_aIntlWrapper(SvtSysLocale().GetUILanguageTag())
150{
151}
152
154{
155}
156
158 Reference< css::awt::XPopupMenu > const & rPopupMenu, const OUString& rCommandURL, const OUString& rLabel )
159{
160 sal_uInt16 nItemId = m_xPopupMenu->getItemCount()+1;
161
162 OUString aLabel;
163 if ( rLabel.isEmpty() )
164 {
165 auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(rCommandURL, m_aModuleName);
167 }
168 else
169 aLabel = rLabel;
170
171 rPopupMenu->insertItem( nItemId, aLabel, 0, nItemId );
172 rPopupMenu->setCommand( nItemId, rCommandURL );
173
174 bool bInternal = rCommandURL.startsWith( STATIC_INTERNAL_CMD_PART );
175 if ( !bInternal )
176 {
177 if ( !getDispatchFromCommandURL( rCommandURL ).is() )
178 m_xPopupMenu->enableItem( nItemId, false );
179 }
180
181 SolarMutexGuard aSolarMutexGuard;
182
183 css::uno::Reference<css::graphic::XGraphic> xGraphic;
185
186 if ( rSettings.GetUseImagesInMenus() )
188
189 if (xGraphic.is())
190 rPopupMenu->setItemImage(nItemId, xGraphic, false);
191
192 m_aCommandVector.push_back( rCommandURL );
193}
194
195Reference< XDispatch > ToolbarsMenuController::getDispatchFromCommandURL( const OUString& rCommandURL )
196{
198 Reference< XURLTransformer > xURLTransformer;
199 Reference< XFrame > xFrame;
200
201 {
202 SolarMutexGuard aSolarMutexGuard;
203 xURLTransformer = m_xURLTransformer;
205 }
206
207 aTargetURL.Complete = rCommandURL;
208 xURLTransformer->parseStrict( aTargetURL );
209 Reference< XDispatchProvider > xDispatchProvider( xFrame, UNO_QUERY );
210 if ( xDispatchProvider.is() )
211 return xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
212 else
213 return Reference< XDispatch >();
214}
215
216static void fillHashMap( const Sequence< Sequence< css::beans::PropertyValue > >& rSeqToolBars,
217 ToolbarHashMap& rHashMap )
218{
219 for ( Sequence< css::beans::PropertyValue > const & props : rSeqToolBars )
220 {
221 OUString aResourceURL;
222 OUString aUIName;
223 for ( css::beans::PropertyValue const & prop : props )
224 {
225 if ( prop.Name == "ResourceURL" )
226 prop.Value >>= aResourceURL;
227 else if ( prop.Name == "UIName" )
228 prop.Value >>= aUIName;
229 }
230
231 if ( !aResourceURL.isEmpty() &&
232 rHashMap.find( aResourceURL ) == rHashMap.end() )
233 rHashMap.emplace( aResourceURL, aUIName );
234 }
235}
236
237// private function
238Sequence< Sequence< css::beans::PropertyValue > > ToolbarsMenuController::getLayoutManagerToolbars( const Reference< css::frame::XLayoutManager >& rLayoutManager )
239{
240 std::vector< ToolBarInfo > aToolBarArray;
241 const Sequence< Reference< XUIElement > > aUIElements = rLayoutManager->getElements();
242 for ( Reference< XUIElement > const & xUIElement : aUIElements )
243 {
244 Reference< XPropertySet > xPropSet( xUIElement, UNO_QUERY );
245 if ( xPropSet.is() && xUIElement.is() )
246 {
247 try
248 {
249 OUString aResName;
250 sal_Int16 nType( -1 );
251 xPropSet->getPropertyValue("Type") >>= nType;
252 xPropSet->getPropertyValue("ResourceURL") >>= aResName;
253
254 if (( nType == css::ui::UIElementType::TOOLBAR ) &&
255 !aResName.isEmpty() )
256 {
257 ToolBarInfo aToolBarInfo;
258
259 aToolBarInfo.aToolBarResName = aResName;
260
261 SolarMutexGuard aGuard;
262 Reference< css::awt::XWindow > xWindow( xUIElement->getRealInterface(), UNO_QUERY );
263 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
264 if ( pWindow )
265 aToolBarInfo.aToolBarUIName = pWindow->GetText();
266
267 aToolBarArray.push_back( aToolBarInfo );
268 }
269 }
270 catch ( const Exception& )
271 {
272 }
273 }
274 }
275
276 Sequence< Sequence< css::beans::PropertyValue > > aSeq( aToolBarArray.size() );
277 auto pSeq = aSeq.getArray();
278 const sal_uInt32 nCount = aToolBarArray.size();
279 for ( sal_uInt32 i = 0; i < nCount; i++ )
280 {
281 Sequence< css::beans::PropertyValue > aTbSeq{
284 };
285 pSeq[i] = aTbSeq;
286 }
287
288 return aSeq;
289}
290
291
292void ToolbarsMenuController::fillPopupMenu( Reference< css::awt::XPopupMenu > const & rPopupMenu )
293{
294 if( officecfg::Office::Common::Misc::DisableUICustomization::get() )
295 return;
296
297 SolarMutexGuard aSolarMutexGuard;
298 resetPopupMenu( rPopupMenu );
299
300 m_aCommandVector.clear();
301
302 // Retrieve layout manager for additional information
303 Reference< XLayoutManager > xLayoutManager( getLayoutManagerFromFrame( m_xFrame ));
304
305 m_bResetActive = false;
306 if ( !xLayoutManager.is() )
307 return;
308
309 ToolbarHashMap aToolbarHashMap;
310
311 if ( m_xDocCfgMgr.is() )
312 {
313 Sequence< Sequence< css::beans::PropertyValue > > aSeqDocToolBars =
314 m_xDocCfgMgr->getUIElementsInfo( UIElementType::TOOLBAR );
315 fillHashMap( aSeqDocToolBars, aToolbarHashMap );
316 }
317
318 if ( m_xModuleCfgMgr.is() )
319 {
320 Sequence< Sequence< css::beans::PropertyValue > > aSeqToolBars =
321 m_xModuleCfgMgr->getUIElementsInfo( UIElementType::TOOLBAR );
322 fillHashMap( aSeqToolBars, aToolbarHashMap );
323 }
324
325 std::vector< ToolBarEntry > aSortedTbs;
326 OUString aStaticCmdPart( STATIC_CMD_PART );
327
328 Sequence< Sequence< css::beans::PropertyValue > > aSeqFrameToolBars = getLayoutManagerToolbars( xLayoutManager );
329 fillHashMap( aSeqFrameToolBars, aToolbarHashMap );
330
331 for (auto const& toolbar : aToolbarHashMap)
332 {
333 OUString aUIName = toolbar.second;
334 bool bHideFromMenu( false );
335 bool bContextSensitive( false );
336 if ( aUIName.isEmpty() &&
338 {
339 bool bVisible( false );
340
341 try
342 {
343 Sequence< PropertyValue > aWindowState;
344 Any a( m_xPersistentWindowState->getByName( toolbar.first ));
345
346 if ( a >>= aWindowState )
347 {
348 for ( PropertyValue const & prop : std::as_const(aWindowState) )
349 {
350 if ( prop.Name == WINDOWSTATE_PROPERTY_UINAME )
351 prop.Value >>= aUIName;
352 else if ( prop.Name == WINDOWSTATE_PROPERTY_HIDEFROMENU )
353 prop.Value >>= bHideFromMenu;
354 else if ( prop.Name == WINDOWSTATE_PROPERTY_CONTEXT )
355 prop.Value >>= bContextSensitive;
356 else if ( prop.Name == WINDOWSTATE_PROPERTY_VISIBLE )
357 prop.Value >>= bVisible;
358 }
359 }
360 }
361 catch ( const Exception& )
362 {
363 }
364
365 // Check if we have to enable/disable "Reset" menu item
366 if ( bContextSensitive && !bVisible )
367 m_bResetActive = true;
368
369 }
370
371 if ( !aUIName.isEmpty() && !bHideFromMenu )
372 {
373 ToolBarEntry aTbEntry;
374 aTbEntry.aUIName = aUIName;
375 aTbEntry.aCommand = toolbar.first;
376 aTbEntry.bVisible = xLayoutManager->isElementVisible( toolbar.first );
377 aTbEntry.pCollatorWrapper = m_aIntlWrapper.getCaseCollator();
378 aSortedTbs.push_back( aTbEntry );
379 }
380 }
381
382 // sort toolbars
383 std::sort( aSortedTbs.begin(), aSortedTbs.end(), CompareToolBarEntry );
384
385 sal_Int16 nIndex( 1 );
386 const sal_uInt32 nCount = aSortedTbs.size();
387 for ( sal_uInt32 i = 0; i < nCount; i++ )
388 {
389 sal_uInt16 nItemCount = m_xPopupMenu->getItemCount();
390 m_xPopupMenu->insertItem( nIndex, aSortedTbs[i].aUIName, css::awt::MenuItemStyle::CHECKABLE, nItemCount );
391 if ( aSortedTbs[i].bVisible )
392 m_xPopupMenu->checkItem( nIndex, true );
393
394 OUStringBuffer aStrBuf( aStaticCmdPart );
395
396 sal_Int32 n = aSortedTbs[i].aCommand.lastIndexOf( '/' );
397 if (( n > 0 ) && (( n+1 ) < aSortedTbs[i].aCommand.getLength() ))
398 aStrBuf.append( aSortedTbs[i].aCommand.subView(n+1) );
399
400 OUString aCmd( aStrBuf.makeStringAndClear() );
401
402 // Store complete uno-command so it can also be dispatched. This is necessary to support
403 // the test tool!
404 rPopupMenu->setCommand( nIndex, aCmd );
405 ++nIndex;
406 }
407
408 // Create commands for non-toolbars
409
410 bool bAddCommand( true );
411 SvtCommandOptions aCmdOptions;
412
413 if ( aCmdOptions.HasEntriesDisabled() && aCmdOptions.LookupDisabled("ConfigureDialog"))
414 bAddCommand = false;
415
416 if ( bAddCommand )
417 {
418 // Create command for configure
419 if ( m_xPopupMenu->getItemCount() > 0 )
420 {
421 sal_uInt16 nItemCount = m_xPopupMenu->getItemCount();
422 m_xPopupMenu->insertSeparator( nItemCount+1 );
423 }
424
425 addCommand( m_xPopupMenu, ".uno:ConfigureDialog", "" );
426 }
427
428 // Add separator if no configure has been added
429 if ( !bAddCommand )
430 {
431 // Create command for configure
432 if ( m_xPopupMenu->getItemCount() > 0 )
433 {
434 sal_uInt16 nItemCount = m_xPopupMenu->getItemCount();
435 m_xPopupMenu->insertSeparator( nItemCount+1 );
436 }
437 }
438
439 OUString aLabelStr(FwkResId(STR_RESTORE_TOOLBARS));
440 addCommand( m_xPopupMenu, CMD_RESTOREVISIBILITY, aLabelStr );
441 aLabelStr = FwkResId(STR_LOCK_TOOLBARS);
442 addCommand( m_xPopupMenu, CMD_LOCKTOOLBARS, aLabelStr );
443}
444
445// XEventListener
446void SAL_CALL ToolbarsMenuController::disposing( const EventObject& )
447{
448 Reference< css::awt::XMenuListener > xHolder(this);
449
450 std::unique_lock aLock( m_aMutex );
451 m_xFrame.clear();
452 m_xDispatch.clear();
453 m_xDocCfgMgr.clear();
454 m_xModuleCfgMgr.clear();
455 m_xContext.clear();
456
457 if ( m_xPopupMenu.is() )
458 m_xPopupMenu->removeMenuListener( Reference< css::awt::XMenuListener >(this) );
459 m_xPopupMenu.clear();
460}
461
462// XStatusListener
463void SAL_CALL ToolbarsMenuController::statusChanged( const FeatureStateEvent& Event )
464{
465 OUString aFeatureURL( Event.FeatureURL.Complete );
466
467 // All other status events will be processed here
468 std::unique_lock aLock( m_aMutex );
469 Reference< css::awt::XPopupMenu > xPopupMenu( m_xPopupMenu );
470 aLock.unlock();
471
472 if ( !xPopupMenu.is() )
473 return;
474
475 SolarMutexGuard aGuard;
476
477 bool bSetCheckmark = false;
478 bool bCheckmark = false;
479 for (sal_Int16 i = 0, nCount = xPopupMenu->getItemCount(); i < nCount; ++i)
480 {
481 sal_Int16 nId = xPopupMenu->getItemId(i);
482 if ( nId == 0 )
483 continue;
484
485 OUString aCmd = xPopupMenu->getCommand(nId);
486 if ( aCmd == aFeatureURL )
487 {
488 // Enable/disable item
489 xPopupMenu->enableItem(nId, Event.IsEnabled);
490
491 // Checkmark
492 if ( Event.State >>= bCheckmark )
493 bSetCheckmark = true;
494
495 if ( bSetCheckmark )
496 xPopupMenu->checkItem(nId, bCheckmark);
497 else
498 {
499 OUString aItemText;
500
501 if ( Event.State >>= aItemText )
502 xPopupMenu->setItemText(nId, aItemText);
503 }
504 }
505 }
506}
507
508// XMenuListener
509void SAL_CALL ToolbarsMenuController::itemSelected( const css::awt::MenuEvent& rEvent )
510{
511 Reference< css::awt::XPopupMenu > xPopupMenu;
512 Reference< XComponentContext > xContext;
513 Reference< XURLTransformer > xURLTransformer;
514 Reference< XFrame > xFrame;
515 Reference< XNameAccess > xPersistentWindowState;
516
517 {
518 std::unique_lock aLock(m_aMutex);
519 xPopupMenu = m_xPopupMenu;
520 xContext = m_xContext;
521 xURLTransformer = m_xURLTransformer;
523 xPersistentWindowState = m_xPersistentWindowState;
524 }
525
526 if ( !xPopupMenu.is() )
527 return;
528
529 SolarMutexGuard aSolarMutexGuard;
530
531 OUString aCmd(xPopupMenu->getCommand(rEvent.MenuId));
532 if ( aCmd.startsWith( STATIC_INTERNAL_CMD_PART ) )
533 {
534 // Command to restore the visibility of all context sensitive toolbars
535 Reference< XNameReplace > xNameReplace( xPersistentWindowState, UNO_QUERY );
536 if ( xPersistentWindowState.is() && xNameReplace.is() )
537 {
538 try
539 {
540 Sequence< OUString > aElementNames = xPersistentWindowState->getElementNames();
541 sal_Int32 nCount = aElementNames.getLength();
542 bool bRefreshToolbars( false );
543
544 for ( sal_Int32 i = 0; i < nCount; i++ )
545 {
546 try
547 {
548 OUString aElementName = aElementNames[i];
549 Sequence< PropertyValue > aWindowState;
550
551 if ( xPersistentWindowState->getByName( aElementName ) >>= aWindowState )
552 {
553 bool bVisible( false );
554 bool bContextSensitive( false );
555 sal_Int32 nVisibleIndex( -1 );
556 for ( sal_Int32 j = 0; j < aWindowState.getLength(); j++ )
557 {
558 if ( aWindowState[j].Name == WINDOWSTATE_PROPERTY_VISIBLE )
559 {
560 aWindowState[j].Value >>= bVisible;
561 nVisibleIndex = j;
562 }
563 else if ( aWindowState[j].Name == WINDOWSTATE_PROPERTY_CONTEXT )
564 aWindowState[j].Value >>= bContextSensitive;
565 }
566
567 if ( !bVisible && bContextSensitive && nVisibleIndex >= 0 )
568 {
569 // Default is: Every context sensitive toolbar is visible
570 aWindowState.getArray()[nVisibleIndex].Value <<= true;
571 xNameReplace->replaceByName( aElementName, Any( aWindowState ));
572 bRefreshToolbars = true;
573 }
574 }
575 }
576 catch ( const NoSuchElementException& )
577 {
578 }
579 }
580
581 if ( bRefreshToolbars )
582 {
583 Reference< XLayoutManager > xLayoutManager( getLayoutManagerFromFrame( xFrame ));
584 if ( xLayoutManager.is() )
585 {
586 Reference< XPropertySet > xPropSet( xLayoutManager, UNO_QUERY );
587 if ( xPropSet.is() )
588 {
589 try
590 {
591 xPropSet->setPropertyValue("RefreshContextToolbarVisibility", Any( true ));
592 }
593 catch ( const RuntimeException& )
594 {
595 }
596 catch ( const Exception& )
597 {
598 }
599 }
600 }
602 }
603 }
604 catch ( const RuntimeException& )
605 {
606 throw;
607 }
608 catch ( const Exception& )
609 {
610 }
611 }
612 }
613 else if ( aCmd.indexOf( STATIC_CMD_PART ) < 0 )
614 {
616 Sequence<PropertyValue> aArgs;
617
618 aTargetURL.Complete = aCmd;
619 xURLTransformer->parseStrict( aTargetURL );
620 Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
621 if ( xDispatchProvider.is() )
622 {
623 Reference< XDispatch > xDispatch = xDispatchProvider->queryDispatch(
624 aTargetURL, OUString(), 0 );
625
626 ExecuteInfo* pExecuteInfo = new ExecuteInfo;
627 pExecuteInfo->xDispatch = xDispatch;
628 pExecuteInfo->aTargetURL = aTargetURL;
629 pExecuteInfo->aArgs = aArgs;
630 Application::PostUserEvent( LINK(nullptr, ToolbarsMenuController, ExecuteHdl_Impl), pExecuteInfo );
631 }
632 }
633 else
634 {
635 Reference< XLayoutManager > xLayoutManager( getLayoutManagerFromFrame( xFrame ));
636 if ( xLayoutManager.is() )
637 {
638 // Extract toolbar name from the combined uno-command.
639 sal_Int32 nIndex = aCmd.indexOf( '=' );
640 if (( nIndex > 0 ) && (( nIndex+1 ) < aCmd.getLength() ))
641 {
642 OUString aToolBarResName = OUString::Concat("private:resource/toolbar/") + aCmd.subView(nIndex+1);
643
644 const bool bShow(!xPopupMenu->isItemChecked(rEvent.MenuId));
645 if ( bShow )
646 {
647 xLayoutManager->createElement( aToolBarResName );
648 xLayoutManager->showElement( aToolBarResName );
649 }
650 else
651 {
652 // closing means:
653 // hide and destroy element
654 xLayoutManager->hideElement( aToolBarResName );
655 xLayoutManager->destroyElement( aToolBarResName );
656 }
657 }
658 }
659 }
660}
661
662void SAL_CALL ToolbarsMenuController::itemActivated( const css::awt::MenuEvent& )
663{
664 std::vector< OUString > aCmdVector;
665 Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
666 Reference< XURLTransformer > xURLTransformer( m_xURLTransformer );
667 {
668 std::unique_lock aLock( m_aMutex );
669 fillPopupMenu( m_xPopupMenu );
670 aCmdVector = m_aCommandVector;
671 }
672
673 // Update status for all commands inside our toolbars popup menu
674 const sal_uInt32 nCount = aCmdVector.size();
675 for ( sal_uInt32 i = 0; i < nCount; i++ )
676 {
677 bool bInternal = aCmdVector[i].startsWith( STATIC_INTERNAL_CMD_PART );
678
679 if ( !bInternal )
680 {
682 aTargetURL.Complete = aCmdVector[i];
683 xURLTransformer->parseStrict( aTargetURL );
684 Reference< XDispatch > xDispatch = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
685 if ( xDispatch.is() )
686 {
687 xDispatch->addStatusListener( static_cast< XStatusListener* >(this), aTargetURL );
688 xDispatch->removeStatusListener( static_cast< XStatusListener* >(this), aTargetURL );
689 }
690 }
691 else if ( aCmdVector[i] == CMD_RESTOREVISIBILITY )
692 {
693 // Special code to determine the enable/disable state of this command
694 FeatureStateEvent aFeatureStateEvent;
695 aFeatureStateEvent.FeatureURL.Complete = aCmdVector[i];
696 aFeatureStateEvent.IsEnabled = m_bResetActive; // is context sensitive toolbar non visible
697 statusChanged( aFeatureStateEvent );
698 }
699 }
700}
701
702// XPopupMenuController
703void SAL_CALL ToolbarsMenuController::setPopupMenu( const Reference< css::awt::XPopupMenu >& xPopupMenu )
704{
705 std::unique_lock aLock( m_aMutex );
706
707 throwIfDisposed(aLock);
708
709 if ( m_xFrame.is() && !m_xPopupMenu.is() )
710 {
711 // Create popup menu on demand
712 SolarMutexGuard aSolarMutexGuard;
713
714 m_xPopupMenu = dynamic_cast<VCLXPopupMenu*>(xPopupMenu.get());
715 assert(bool(xPopupMenu) == bool(m_xPopupMenu) && "we only support VCLXPopupMenu");
716 m_xPopupMenu->addMenuListener( Reference< css::awt::XMenuListener >(this) );
717 fillPopupMenu( m_xPopupMenu );
718 }
719}
720
721// XInitialization
722void ToolbarsMenuController::initializeImpl( std::unique_lock<std::mutex>& rGuard, const Sequence< Any >& aArguments )
723{
724 bool bInitialized( m_bInitialized );
725 if ( bInitialized )
726 return;
727
728 svt::PopupMenuControllerBase::initializeImpl(rGuard, aArguments);
729
730 if ( !m_bInitialized )
731 return;
732
733 Reference< XModuleManager2 > xModuleManager = ModuleManager::create( m_xContext );
734 Reference< XNameAccess > xPersistentWindowStateSupplier = css::ui::theWindowStateConfiguration::get( m_xContext );
735
736 // Retrieve persistent window state reference for our module
737 try
738 {
739 OUString aModuleIdentifier = xModuleManager->identify( m_xFrame );
740 xPersistentWindowStateSupplier->getByName( aModuleIdentifier ) >>= m_xPersistentWindowState;
741
742 Reference< XModuleUIConfigurationManagerSupplier > xModuleCfgSupplier =
743 theModuleUIConfigurationManagerSupplier::get( m_xContext );
744 m_xModuleCfgMgr = xModuleCfgSupplier->getUIConfigurationManager( aModuleIdentifier );
745
746 Reference< XController > xController = m_xFrame->getController();
747 Reference< XModel > xModel;
748 if ( xController.is() )
749 xModel = xController->getModel();
750 if ( xModel.is() )
751 {
752 Reference< XUIConfigurationManagerSupplier > xUIConfigurationManagerSupplier( xModel, UNO_QUERY );
753 if ( xUIConfigurationManagerSupplier.is() )
754 m_xDocCfgMgr = xUIConfigurationManagerSupplier->getUIConfigurationManager();
755 }
756 }
757 catch ( const Exception& )
758 {
759 }
760}
761
762IMPL_STATIC_LINK( ToolbarsMenuController, ExecuteHdl_Impl, void*, p, void )
763{
764 ExecuteInfo* pExecuteInfo = static_cast<ExecuteInfo*>(p);
765 try
766 {
767 // Asynchronous execution as this can lead to our own destruction!
768 // Framework can recycle our current frame and the layout manager disposes all user interface
769 // elements if a component gets detached from its frame!
770 if ( pExecuteInfo->xDispatch.is() )
771 {
772 pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs );
773 }
774 }
775 catch ( const Exception& )
776 {
777 }
778
779 delete pExecuteInfo;
780}
781
782}
783
784extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
786 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
787{
788 return cppu::acquire(new framework::ToolbarsMenuController(context));
789}
790
791/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
PropertiesInfo aProperties
constexpr OUStringLiteral sServiceName
css::uno::Reference< css::lang::XComponent > m_xFrame
css::uno::Reference< css::frame::XDispatch > m_xDispatch
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
static ImplSVEvent * PostUserEvent(const Link< void *, void > &rLink, void *pCaller=nullptr, bool bReferenceLink=false)
const CollatorWrapper * getCaseCollator() const
bool GetUseImagesInMenus() const
bool LookupDisabled(const OUString &aCommandURL) const
bool HasEntriesDisabled() const
static vcl::Window * GetWindow(const css::uno::Reference< css::awt::XWindow > &rxWindow)
virtual void SAL_CALL itemSelected(const css::awt::MenuEvent &rEvent) override
css::uno::Reference< css::ui::XUIConfigurationManager > m_xModuleCfgMgr
css::uno::Reference< css::container::XNameAccess > m_xPersistentWindowState
ToolbarsMenuController(const css::uno::Reference< css::uno::XComponentContext > &xContext)
virtual void SAL_CALL itemActivated(const css::awt::MenuEvent &rEvent) override
virtual OUString SAL_CALL getImplementationName() override
virtual sal_Bool SAL_CALL supportsService(const OUString &sServiceName) override
css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > getLayoutManagerToolbars(const css::uno::Reference< css::frame::XLayoutManager > &rLayoutManager)
void fillPopupMenu(css::uno::Reference< css::awt::XPopupMenu > const &rPopupMenu)
void addCommand(css::uno::Reference< css::awt::XPopupMenu > const &rPopupMenu, const OUString &rCommandURL, const OUString &aLabel)
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
css::uno::Reference< css::ui::XUIConfigurationManager > m_xDocCfgMgr
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
css::uno::Reference< css::frame::XDispatch > getDispatchFromCommandURL(const OUString &rCommandURL)
virtual void SAL_CALL statusChanged(const css::frame::FeatureStateEvent &Event) override
virtual void initializeImpl(std::unique_lock< std::mutex > &rGuard, const css::uno::Sequence< css::uno::Any > &aArguments) override
css::uno::Reference< css::uno::XComponentContext > m_xContext
virtual void SAL_CALL setPopupMenu(const css::uno::Reference< css::awt::XPopupMenu > &PopupMenu) override
int nCount
Reference< XDispatch > xDispatch
float u
OUString FwkResId(TranslateId aId)
Definition: fwkresid.cxx:22
css::uno::Reference< css::uno::XComponentContext > m_xContext
Sequence< PropertyValue > aArguments
sal_Int32 nIndex
void * p
sal_Int64 n
uno_Any a
Sequence< sal_Int8 > aSeq
@ Exception
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
constexpr OUStringLiteral g_aPropResourceURL(u"ResourceURL")
constexpr OUStringLiteral g_aPropUIName(u"UIName")
static void fillHashMap(const Sequence< Sequence< css::beans::PropertyValue > > &rSeqToolBars, ToolbarHashMap &rHashMap)
IMPL_STATIC_LINK(ComplexToolbarController, ExecuteHdl_Impl, void *, p, void)
constexpr OUStringLiteral SERVICENAME_POPUPMENUCONTROLLER
Definition: services.h:33
void RefreshToolbars(css::uno::Reference< css::frame::XFrame > const &rFrame)
static bool CompareToolBarEntry(const ToolBarEntry &aOne, const ToolBarEntry &aTwo)
std::unordered_map< OUString, OUString > ToolbarHashMap
static css::uno::Reference< css::frame::XLayoutManager > getLayoutManagerFromFrame(css::uno::Reference< css::frame::XFrame > const &rFrame)
int i
dictionary props
Sequence< beans::PropertyValue > GetCommandProperties(const OUString &rsCommandName, const OUString &rsModuleName)
Reference< graphic::XGraphic > GetXGraphicForCommand(const OUString &rsCommandName, const Reference< frame::XFrame > &rxFrame, vcl::ImageType eImageType)
OUString GetMenuLabelForCommand(const css::uno::Sequence< css::beans::PropertyValue > &rProperties)
sal_Int16 nId
QPRO_FUNC_TYPE nType
css::uno::Reference< css::frame::XDispatch > xDispatch
css::uno::Sequence< css::beans::PropertyValue > aArgs
Reference< XController > xController
Reference< XFrame > xFrame
Reference< XModel > xModel
OUString aToolBarResName
constexpr OUStringLiteral CMD_RESTOREVISIBILITY
const char STATIC_INTERNAL_CMD_PART[]
OUString aUIName
constexpr OUStringLiteral CMD_LOCKTOOLBARS
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * framework_ToolbarsMenuController_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
constexpr OUStringLiteral STATIC_CMD_PART
bool bVisible
OUString aCommand
const CollatorWrapper * pCollatorWrapper
OUString aToolBarUIName
OUString Name
unsigned char sal_Bool
std::mutex m_aMutex
OUString aTargetURL
OUString aLabel
constexpr OUStringLiteral WINDOWSTATE_PROPERTY_VISIBLE
constexpr OUStringLiteral WINDOWSTATE_PROPERTY_HIDEFROMENU
constexpr OUStringLiteral WINDOWSTATE_PROPERTY_UINAME
constexpr OUStringLiteral WINDOWSTATE_PROPERTY_CONTEXT