1 /*
2  * This file is part of the LibreOffice project.
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  *
8  * This file incorporates work covered by the following license notice:
9  *
10  *   Licensed to the Apache Software Foundation (ASF) under one or more
11  *   contributor license agreements. See the NOTICE file distributed
12  *   with this work for additional information regarding copyright
13  *   ownership. The ASF licenses this file to you under the Apache
14  *   License, Version 2.0 (the "License"); you may not use this file
15  *   except in compliance with the License. You may obtain a copy of
16  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
17  */
18 
19 #include <sal/config.h>
20 #include <sal/log.hxx>
21 
22 #include <cassert>
23 
24 #include <uielement/toolbarmanager.hxx>
25 
26 #include <uielement/generictoolbarcontroller.hxx>
27 #include <uielement/styletoolbarcontroller.hxx>
28 #include <services.h>
29 #include <general.h>
30 #include <properties.h>
31 #include <framework/sfxhelperfunctions.hxx>
32 #include <classes/fwkresid.hxx>
33 #include <classes/resource.hxx>
34 #include <strings.hrc>
35 #include <framework/addonsoptions.hxx>
36 #include <uielement/toolbarmerger.hxx>
37 
38 #include <com/sun/star/ui/ItemType.hpp>
39 #include <com/sun/star/frame/XDispatchProvider.hpp>
40 #include <com/sun/star/beans/XPropertySet.hpp>
41 #include <com/sun/star/awt/XDockableWindow.hpp>
42 #include <com/sun/star/frame/XLayoutManager.hpp>
43 #include <com/sun/star/ui/DockingArea.hpp>
44 #include <com/sun/star/graphic/XGraphic.hpp>
45 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
46 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
47 #include <com/sun/star/frame/ModuleManager.hpp>
48 #include <com/sun/star/frame/theToolbarControllerFactory.hpp>
49 #include <com/sun/star/ui/ItemStyle.hpp>
50 #include <com/sun/star/ui/XUIElementSettings.hpp>
51 #include <com/sun/star/ui/XUIConfigurationPersistence.hpp>
52 #include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
53 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
54 #include <com/sun/star/ui/ImageType.hpp>
55 #include <com/sun/star/ui/UIElementType.hpp>
56 #include <com/sun/star/lang/DisposedException.hpp>
57 #include <com/sun/star/util/URLTransformer.hpp>
58 
59 #include <svtools/toolboxcontroller.hxx>
60 #include <unotools/cmdoptions.hxx>
61 #include <toolkit/helper/vclunohelper.hxx>
62 #include <unotools/mediadescriptor.hxx>
63 #include <comphelper/sequence.hxx>
64 #include <svtools/miscopt.hxx>
65 #include <svtools/imgdef.hxx>
66 #include <vcl/event.hxx>
67 #include <vcl/svapp.hxx>
68 #include <vcl/menu.hxx>
69 #include <vcl/syswin.hxx>
70 #include <vcl/taskpanelist.hxx>
71 #include <vcl/toolbox.hxx>
72 #include <vcl/settings.hxx>
73 #include <vcl/commandinfoprovider.hxx>
74 #include <tools/debug.hxx>
75 
76 #include <svtools/menuoptions.hxx>
77 
78 //  namespaces
79 
80 using namespace ::com::sun::star::awt;
81 using namespace ::com::sun::star::beans;
82 using namespace ::com::sun::star::uno;
83 using namespace ::com::sun::star::lang;
84 using namespace ::com::sun::star::frame;
85 using namespace ::com::sun::star::graphic;
86 using namespace ::com::sun::star::util;
87 using namespace ::com::sun::star::container;
88 using namespace ::com::sun::star::ui;
89 using namespace ::com::sun::star;
90 
91 namespace framework
92 {
93 
94 static const char ITEM_DESCRIPTOR_COMMANDURL[] = "CommandURL";
95 static const char ITEM_DESCRIPTOR_VISIBLE[]    = "IsVisible";
96 
97 static const sal_uInt16 STARTID_CUSTOMIZE_POPUPMENU = 1000;
98 
getLayoutManagerFromFrame(css::uno::Reference<css::frame::XFrame> const & rFrame)99 static css::uno::Reference< css::frame::XLayoutManager > getLayoutManagerFromFrame(
100     css::uno::Reference< css::frame::XFrame > const & rFrame )
101 {
102     css::uno::Reference< css::frame::XLayoutManager > xLayoutManager;
103 
104     Reference< XPropertySet > xPropSet( rFrame, UNO_QUERY );
105     if ( xPropSet.is() )
106     {
107         try
108         {
109             xPropSet->getPropertyValue("LayoutManager") >>= xLayoutManager;
110         }
111         catch (const RuntimeException&)
112         {
113             throw;
114         }
115         catch (const Exception&)
116         {
117         }
118     }
119 
120     return xLayoutManager;
121 }
122 namespace
123 {
124 
getCurrentImageType()125 sal_Int16 getCurrentImageType()
126 {
127     SvtMiscOptions aMiscOptions;
128     sal_Int16 nImageType = css::ui::ImageType::SIZE_DEFAULT;
129     if (aMiscOptions.GetCurrentSymbolsSize() == SFX_SYMBOLS_SIZE_LARGE)
130         nImageType |= css::ui::ImageType::SIZE_LARGE;
131     else if (aMiscOptions.GetCurrentSymbolsSize() == SFX_SYMBOLS_SIZE_32)
132         nImageType |= css::ui::ImageType::SIZE_32;
133     return nImageType;
134 }
135 
136 } // end anonymous namespace
137 
138 //  XInterface, XTypeProvider, XServiceInfo
139 
ToolBarManager(const Reference<XComponentContext> & rxContext,const Reference<XFrame> & rFrame,const OUString & rResourceName,ToolBox * pToolBar)140 ToolBarManager::ToolBarManager( const Reference< XComponentContext >& rxContext,
141                                 const Reference< XFrame >& rFrame,
142                                 const OUString& rResourceName,
143                                 ToolBox* pToolBar ) :
144     m_bDisposed( false ),
145     m_bAddedToTaskPaneList( true ),
146     m_bFrameActionRegistered( false ),
147     m_bUpdateControllers( false ),
148     m_eSymbolSize(SvtMiscOptions().GetCurrentSymbolsSize()),
149     m_pToolBar( pToolBar ),
150     m_aResourceName( rResourceName ),
151     m_xFrame( rFrame ),
152     m_aListenerContainer( m_mutex ),
153     m_xContext( rxContext ),
154     m_sIconTheme( SvtMiscOptions().GetIconTheme() )
155 {
156     OSL_ASSERT( m_xContext.is() );
157 
158     vcl::Window* pWindow = m_pToolBar;
159     while ( pWindow && !pWindow->IsSystemWindow() )
160         pWindow = pWindow->GetParent();
161 
162     if ( pWindow )
163         static_cast<SystemWindow *>(pWindow)->GetTaskPaneList()->AddWindow( m_pToolBar );
164 
165     m_xToolbarControllerFactory = frame::theToolbarControllerFactory::get( m_xContext );
166     m_xURLTransformer = URLTransformer::create( m_xContext );
167 
168     m_pToolBar->SetSelectHdl( LINK( this, ToolBarManager, Select) );
169     m_pToolBar->SetClickHdl( LINK( this, ToolBarManager, Click ) );
170     m_pToolBar->SetDropdownClickHdl( LINK( this, ToolBarManager, DropdownClick ) );
171     m_pToolBar->SetDoubleClickHdl( LINK( this, ToolBarManager, DoubleClick ) );
172     m_pToolBar->SetStateChangedHdl( LINK( this, ToolBarManager, StateChanged ) );
173     m_pToolBar->SetDataChangedHdl( LINK( this, ToolBarManager, DataChanged ) );
174 
175     if (m_eSymbolSize == SFX_SYMBOLS_SIZE_LARGE)
176         m_pToolBar->SetToolboxButtonSize(ToolBoxButtonSize::Large);
177     else if (m_eSymbolSize == SFX_SYMBOLS_SIZE_32)
178         m_pToolBar->SetToolboxButtonSize(ToolBoxButtonSize::Size32);
179     else
180         m_pToolBar->SetToolboxButtonSize(ToolBoxButtonSize::Small);
181 
182     // enables a menu for clipped items and customization
183     SvtCommandOptions aCmdOptions;
184     ToolBoxMenuType nMenuType = ToolBoxMenuType::ClippedItems;
185     if ( !aCmdOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED, "CreateDialog"))
186          nMenuType |= ToolBoxMenuType::Customize;
187 
188     m_pToolBar->SetMenuType( nMenuType );
189     m_pToolBar->SetMenuButtonHdl( LINK( this, ToolBarManager, MenuButton ) );
190     m_pToolBar->SetMenuExecuteHdl( LINK( this, ToolBarManager, MenuPreExecute ) );
191     m_pToolBar->GetMenu()->SetSelectHdl( LINK( this, ToolBarManager, MenuSelect ) );
192 
193     // set name for testtool, the useful part is after the last '/'
194     sal_Int32 idx = rResourceName.lastIndexOf('/');
195     idx++; // will become 0 if '/' not found: use full string
196     OString  aHelpIdAsString( ".HelpId:" );
197     OUString  aToolbarName = rResourceName.copy( idx );
198     aHelpIdAsString += OUStringToOString( aToolbarName, RTL_TEXTENCODING_UTF8 );
199     m_pToolBar->SetHelpId( aHelpIdAsString );
200 
201     m_aAsyncUpdateControllersTimer.SetTimeout( 50 );
202     m_aAsyncUpdateControllersTimer.SetInvokeHandler( LINK( this, ToolBarManager, AsyncUpdateControllersHdl ) );
203     m_aAsyncUpdateControllersTimer.SetDebugName( "framework::ToolBarManager m_aAsyncUpdateControllersTimer" );
204 
205     SvtMiscOptions().AddListenerLink( LINK( this, ToolBarManager, MiscOptionsChanged ) );
206 }
207 
~ToolBarManager()208 ToolBarManager::~ToolBarManager()
209 {
210     assert(!m_aAsyncUpdateControllersTimer.IsActive());
211     assert(!m_pToolBar); // must be disposed by ToolbarLayoutManager
212     OSL_ASSERT( !m_bAddedToTaskPaneList );
213 }
214 
Destroy()215 void ToolBarManager::Destroy()
216 {
217     OSL_ASSERT( m_pToolBar != nullptr );
218     SolarMutexGuard g;
219     if ( m_bAddedToTaskPaneList )
220     {
221         vcl::Window* pWindow = m_pToolBar;
222         while ( pWindow && !pWindow->IsSystemWindow() )
223             pWindow = pWindow->GetParent();
224 
225         if ( pWindow )
226             static_cast<SystemWindow *>(pWindow)->GetTaskPaneList()->RemoveWindow( m_pToolBar );
227         m_bAddedToTaskPaneList = false;
228     }
229 
230     // Delete the additional add-ons data
231     for ( ToolBox::ImplToolItems::size_type i = 0; i < m_pToolBar->GetItemCount(); i++ )
232     {
233         sal_uInt16 nItemId = m_pToolBar->GetItemId( i );
234         if ( nItemId > 0 )
235             delete static_cast< AddonsParams* >( m_pToolBar->GetItemData( nItemId ));
236     }
237 
238     // tdf#119390 this will reparent the toolbar, so focus is restored from a
239     // floating toolbar to the last focused control of the application window.
240     m_pToolBar->SetParentToDefaultWindow();
241     // #i93173# note we can still be in one of the toolbar's handlers
242     m_pToolBar->SetSelectHdl( Link<ToolBox *, void>() );
243     m_pToolBar->SetActivateHdl( Link<ToolBox *, void>() );
244     m_pToolBar->SetDeactivateHdl( Link<ToolBox *, void>() );
245     m_pToolBar->SetClickHdl( Link<ToolBox *, void>() );
246     m_pToolBar->SetDropdownClickHdl( Link<ToolBox *, void>() );
247     m_pToolBar->SetDoubleClickHdl( Link<ToolBox *, void>() );
248     m_pToolBar->SetStateChangedHdl( Link<StateChangedType const *, void>() );
249     m_pToolBar->SetDataChangedHdl( Link<DataChangedEvent const *, void>() );
250 
251     m_pToolBar.disposeAndClear();
252 
253     SvtMiscOptions().RemoveListenerLink( LINK( this, ToolBarManager, MiscOptionsChanged ) );
254 }
255 
GetToolBar() const256 ToolBox* ToolBarManager::GetToolBar() const
257 {
258     SolarMutexGuard g;
259     return m_pToolBar;
260 }
261 
CheckAndUpdateImages()262 void ToolBarManager::CheckAndUpdateImages()
263 {
264     SolarMutexGuard g;
265     bool bRefreshImages = false;
266 
267     SvtMiscOptions aMiscOptions;
268     sal_Int16 eNewSymbolSize = aMiscOptions.GetCurrentSymbolsSize();
269 
270     if (m_eSymbolSize != eNewSymbolSize )
271     {
272         bRefreshImages = true;
273         m_eSymbolSize = eNewSymbolSize;
274     }
275 
276     const OUString& sCurrentIconTheme = aMiscOptions.GetIconTheme();
277     if ( m_sIconTheme != sCurrentIconTheme )
278     {
279         bRefreshImages = true;
280         m_sIconTheme = sCurrentIconTheme;
281     }
282 
283     // Refresh images if requested
284     if ( bRefreshImages )
285         RefreshImages();
286 }
287 
RefreshImages()288 void ToolBarManager::RefreshImages()
289 {
290     SolarMutexGuard g;
291 
292     vcl::ImageType eImageType = vcl::ImageType::Size16;
293 
294     if (m_eSymbolSize == SFX_SYMBOLS_SIZE_LARGE)
295     {
296         m_pToolBar->SetToolboxButtonSize(ToolBoxButtonSize::Large);
297         eImageType = vcl::ImageType::Size26;
298     }
299     else if (m_eSymbolSize == SFX_SYMBOLS_SIZE_32)
300     {
301         eImageType = vcl::ImageType::Size32;
302         m_pToolBar->SetToolboxButtonSize(ToolBoxButtonSize::Size32);
303     }
304     else
305     {
306         m_pToolBar->SetToolboxButtonSize(ToolBoxButtonSize::Small);
307     }
308 
309     for ( auto const& it : m_aControllerMap )
310     {
311         Reference< XSubToolbarController > xController( it.second, UNO_QUERY );
312         if ( xController.is() && xController->opensSubToolbar() )
313         {
314             // The button should show the last function that was selected from the
315             // dropdown. The controller should know better than us what it was.
316             xController->updateImage();
317         }
318         else
319         {
320             OUString aCommandURL = m_pToolBar->GetItemCommand( it.first );
321             Image aImage = vcl::CommandInfoProvider::GetImageForCommand(aCommandURL, m_xFrame, eImageType);
322             // Try also to query for add-on images before giving up and use an
323             // empty image.
324             bool bBigImages = eImageType != vcl::ImageType::Size16;
325             if ( !aImage )
326                 aImage = framework::AddonsOptions().GetImageFromURL(aCommandURL, bBigImages);
327             m_pToolBar->SetItemImage( it.first, aImage );
328         }
329     }
330 
331     ::Size aSize = m_pToolBar->CalcWindowSizePixel();
332     m_pToolBar->SetOutputSizePixel( aSize );
333 }
334 
UpdateControllers()335 void ToolBarManager::UpdateControllers()
336 {
337 
338     if( SvtMiscOptions().DisableUICustomization() )
339     {
340         Any a;
341         Reference< XLayoutManager > xLayoutManager;
342         Reference< XPropertySet > xFramePropSet( m_xFrame, UNO_QUERY );
343         if ( xFramePropSet.is() )
344             a = xFramePropSet->getPropertyValue("LayoutManager");
345         a >>= xLayoutManager;
346         Reference< XDockableWindow > xDockable( VCLUnoHelper::GetInterface( m_pToolBar ), UNO_QUERY );
347         if ( xLayoutManager.is() && xDockable.is() )
348         {
349             css::awt::Point aPoint;
350             aPoint.X = aPoint.Y = SAL_MAX_INT32;
351             xLayoutManager->dockWindow( m_aResourceName, DockingArea_DOCKINGAREA_DEFAULT, aPoint );
352             xLayoutManager->lockWindow( m_aResourceName );
353         }
354     }
355 
356     if ( !m_bUpdateControllers )
357     {
358         m_bUpdateControllers = true;
359         for (auto const& controller : m_aControllerMap)
360         {
361             try
362             {
363                 Reference< XUpdatable > xUpdatable( controller.second, UNO_QUERY );
364                 if ( xUpdatable.is() )
365                     xUpdatable->update();
366             }
367             catch (const Exception&)
368             {
369             }
370         }
371     }
372     m_bUpdateControllers = false;
373 }
374 
375 //for update toolbar controller via Support Visible
UpdateController(const css::uno::Reference<css::frame::XToolbarController> & xController)376 void ToolBarManager::UpdateController( const css::uno::Reference< css::frame::XToolbarController >& xController)
377 {
378 
379     if ( !m_bUpdateControllers )
380     {
381         m_bUpdateControllers = true;
382         try
383         {   if(xController.is())
384             {
385                 Reference< XUpdatable > xUpdatable( xController, UNO_QUERY );
386                 if ( xUpdatable.is() )
387                     xUpdatable->update();
388             }
389          }
390          catch (const Exception&)
391          {
392          }
393 
394     }
395     m_bUpdateControllers = false;
396 }
397 
frameAction(const FrameActionEvent & Action)398 void ToolBarManager::frameAction( const FrameActionEvent& Action )
399 {
400     SolarMutexGuard g;
401     if ( Action.Action == FrameAction_CONTEXT_CHANGED && !m_bDisposed )
402     {
403         m_aAsyncUpdateControllersTimer.Start();
404     }
405 }
406 
disposing(const EventObject & Source)407 void SAL_CALL ToolBarManager::disposing( const EventObject& Source )
408 {
409     SolarMutexGuard g;
410 
411     if ( m_bDisposed )
412         return;
413 
414     RemoveControllers();
415 
416     if ( m_xDocImageManager.is() )
417     {
418         try
419         {
420             m_xDocImageManager->removeConfigurationListener(
421                 Reference< XUIConfigurationListener >(
422                     static_cast< OWeakObject* >( this ), UNO_QUERY ));
423         }
424         catch (const Exception&)
425         {
426         }
427     }
428 
429     if ( m_xModuleImageManager.is() )
430     {
431         try
432         {
433             m_xModuleImageManager->removeConfigurationListener(
434                 Reference< XUIConfigurationListener >(
435                     static_cast< OWeakObject* >( this ), UNO_QUERY ));
436         }
437         catch (const Exception&)
438         {
439         }
440     }
441 
442     m_xDocImageManager.clear();
443     m_xModuleImageManager.clear();
444 
445     if ( Source.Source == Reference< XInterface >( m_xFrame, UNO_QUERY ))
446         m_xFrame.clear();
447 
448     m_xContext.clear();
449 }
450 
451 // XComponent
dispose()452 void SAL_CALL ToolBarManager::dispose()
453 {
454     Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY );
455 
456     EventObject aEvent( xThis );
457     m_aListenerContainer.disposeAndClear( aEvent );
458 
459     {
460         SolarMutexGuard g;
461 
462         if (m_bDisposed)
463         {
464             return;
465         }
466 
467         RemoveControllers();
468 
469         if ( m_xDocImageManager.is() )
470         {
471             try
472             {
473                 m_xDocImageManager->removeConfigurationListener(
474                     Reference< XUIConfigurationListener >(
475                         static_cast< OWeakObject* >( this ), UNO_QUERY ));
476             }
477             catch (const Exception&)
478             {
479             }
480         }
481         m_xDocImageManager.clear();
482         if ( m_xModuleImageManager.is() )
483         {
484             try
485             {
486                 m_xModuleImageManager->removeConfigurationListener(
487                     Reference< XUIConfigurationListener >(
488                         static_cast< OWeakObject* >( this ), UNO_QUERY ));
489             }
490             catch (const Exception&)
491             {
492             }
493         }
494         m_xModuleImageManager.clear();
495 
496         if ( m_aOverflowManager.is() )
497         {
498             m_aOverflowManager->dispose();
499             m_aOverflowManager.clear();
500         }
501 
502         // We have to destroy our toolbar instance now.
503         Destroy();
504         m_pToolBar.clear();
505 
506         if ( m_bFrameActionRegistered && m_xFrame.is() )
507         {
508             try
509             {
510                 m_xFrame->removeFrameActionListener( Reference< XFrameActionListener >(
511                                                         static_cast< ::cppu::OWeakObject *>( this ), UNO_QUERY ));
512             }
513             catch (const Exception&)
514             {
515             }
516         }
517 
518         m_xFrame.clear();
519         m_xContext.clear();
520 
521         // stop timer to prevent timer events after dispose
522         // do it last because other calls could restart timer in StateChanged()
523         m_aAsyncUpdateControllersTimer.Stop();
524 
525         m_bDisposed = true;
526     }
527 }
528 
addEventListener(const Reference<XEventListener> & xListener)529 void SAL_CALL ToolBarManager::addEventListener( const Reference< XEventListener >& xListener )
530 {
531     SolarMutexGuard g;
532 
533     /* SAFE AREA ----------------------------------------------------------------------------------------------- */
534     if ( m_bDisposed )
535         throw DisposedException();
536 
537     m_aListenerContainer.addInterface( cppu::UnoType<XEventListener>::get(), xListener );
538 }
539 
removeEventListener(const Reference<XEventListener> & xListener)540 void SAL_CALL ToolBarManager::removeEventListener( const Reference< XEventListener >& xListener )
541 {
542     m_aListenerContainer.removeInterface( cppu::UnoType<XEventListener>::get(), xListener );
543 }
544 
545 // XUIConfigurationListener
elementInserted(const css::ui::ConfigurationEvent & Event)546 void SAL_CALL ToolBarManager::elementInserted( const css::ui::ConfigurationEvent& Event )
547 {
548     impl_elementChanged(false,Event);
549 }
550 
elementRemoved(const css::ui::ConfigurationEvent & Event)551 void SAL_CALL ToolBarManager::elementRemoved( const css::ui::ConfigurationEvent& Event )
552 {
553     impl_elementChanged(true,Event);
554 }
impl_elementChanged(bool const isRemove,const css::ui::ConfigurationEvent & Event)555 void ToolBarManager::impl_elementChanged(bool const isRemove,
556         const css::ui::ConfigurationEvent& Event)
557 {
558     SolarMutexGuard g;
559 
560     /* SAFE AREA ----------------------------------------------------------------------------------------------- */
561     if ( m_bDisposed )
562         return;
563 
564     Reference< XNameAccess > xNameAccess;
565     sal_Int16                nImageType = sal_Int16();
566     sal_Int16                nCurrentImageType = getCurrentImageType();
567 
568     if (( Event.aInfo >>= nImageType ) &&
569         ( nImageType == nCurrentImageType ) &&
570         ( Event.Element >>= xNameAccess ))
571     {
572         sal_Int16 nImageInfo( 1 );
573         Reference< XInterface > xIfacDocImgMgr( m_xDocImageManager, UNO_QUERY );
574         if ( xIfacDocImgMgr == Event.Source )
575             nImageInfo = 0;
576 
577         Sequence< OUString > aSeq = xNameAccess->getElementNames();
578         for ( sal_Int32 i = 0; i < aSeq.getLength(); i++ )
579         {
580             CommandToInfoMap::iterator pIter = m_aCommandMap.find( aSeq[i] );
581             if ( pIter != m_aCommandMap.end() && ( pIter->second.nImageInfo >= nImageInfo ))
582             {
583                 if (isRemove)
584                 {
585                     Image aImage;
586                     if (( pIter->second.nImageInfo == 0 ) && ( pIter->second.nImageInfo == nImageInfo ))
587                     {
588                         // Special case: An image from the document image manager has been removed.
589                         // It is possible that we have an image at our module image manager. Before
590                         // we can remove our image we have to ask our module image manager.
591                         Sequence< OUString > aCmdURLSeq( 1 );
592                         Sequence< Reference< XGraphic > > aGraphicSeq;
593                         aCmdURLSeq[0] = pIter->first;
594                         aGraphicSeq = m_xModuleImageManager->getImages( nImageType, aCmdURLSeq );
595                         aImage = Image( aGraphicSeq[0] );
596                     }
597 
598                     setToolBarImage(aImage,pIter);
599                 } // if (isRemove)
600                 else
601                 {
602                     Reference< XGraphic > xGraphic;
603                     if ( xNameAccess->getByName( aSeq[i] ) >>= xGraphic )
604                     {
605                         Image aImage( xGraphic );
606                         setToolBarImage(aImage,pIter);
607                     }
608                     pIter->second.nImageInfo = nImageInfo;
609                 }
610             }
611         }
612     }
613 }
setToolBarImage(const Image & rImage,const CommandToInfoMap::const_iterator & rIter)614 void ToolBarManager::setToolBarImage(const Image& rImage,
615         const CommandToInfoMap::const_iterator& rIter)
616 {
617     const ::std::vector<sal_uInt16>& rIDs = rIter->second.aIds;
618     m_pToolBar->SetItemImage( rIter->second.nId, rImage );
619     for (auto const& it : rIDs)
620     {
621         m_pToolBar->SetItemImage(it, rImage);
622     }
623 }
624 
elementReplaced(const css::ui::ConfigurationEvent & Event)625 void SAL_CALL ToolBarManager::elementReplaced( const css::ui::ConfigurationEvent& Event )
626 {
627     impl_elementChanged(false,Event);
628 }
629 
RemoveControllers()630 void ToolBarManager::RemoveControllers()
631 {
632     DBG_TESTSOLARMUTEX();
633     assert(!m_bDisposed);
634 
635     m_aSubToolBarControllerMap.clear();
636 
637     // i90033
638     // Remove item window pointers from the toolbar. They were
639     // destroyed by the dispose() at the XComponent. This is needed
640     // as VCL code later tries to access the item window data in certain
641     // dtors where the item window is already invalid!
642     for ( ToolBox::ImplToolItems::size_type i = 0; i < m_pToolBar->GetItemCount(); i++ )
643     {
644         sal_uInt16 nItemId = m_pToolBar->GetItemId( i );
645         if ( nItemId > 0 )
646         {
647             Reference< XComponent > xComponent( m_aControllerMap[ nItemId ], UNO_QUERY );
648             if ( xComponent.is() )
649             {
650                 try
651                 {
652                     xComponent->dispose();
653                 }
654                 catch (const Exception&)
655                 {
656                 }
657             }
658             m_pToolBar->SetItemWindow(nItemId, nullptr);
659         }
660     }
661     m_aControllerMap.clear();
662 }
663 
CreateControllers()664 void ToolBarManager::CreateControllers()
665 {
666     Reference< XWindow > xToolbarWindow = VCLUnoHelper::GetInterface( m_pToolBar );
667 
668     css::util::URL      aURL;
669     bool                bHasDisabledEntries = SvtCommandOptions().HasEntries( SvtCommandOptions::CMDOPTION_DISABLED );
670     SvtCommandOptions   aCmdOptions;
671 
672     for ( ToolBox::ImplToolItems::size_type i = 0; i < m_pToolBar->GetItemCount(); i++ )
673     {
674         sal_uInt16 nId = m_pToolBar->GetItemId( i );
675         if ( nId == 0 )
676             continue;
677 
678         bool                     bInit( true );
679         bool                     bCreate( true );
680         Reference< XStatusListener > xController;
681 
682         svt::ToolboxController* pController( nullptr );
683 
684         OUString aCommandURL( m_pToolBar->GetItemCommand( nId ) );
685         // Command can be just an alias to another command.
686         auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(aCommandURL, m_aModuleIdentifier);
687         OUString aRealCommandURL( vcl::CommandInfoProvider::GetRealCommandForCommand(aProperties) );
688         if ( !aRealCommandURL.isEmpty() )
689             aCommandURL = aRealCommandURL;
690 
691         if ( bHasDisabledEntries )
692         {
693             aURL.Complete = aCommandURL;
694             m_xURLTransformer->parseStrict( aURL );
695             if ( aCmdOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED, aURL.Path ))
696             {
697                 m_aControllerMap[ nId ] = xController;
698                 m_pToolBar->HideItem( nId );
699                 continue;
700             }
701         }
702 
703         if ( m_xToolbarControllerFactory.is() &&
704              m_xToolbarControllerFactory->hasController( aCommandURL, m_aModuleIdentifier ))
705         {
706             PropertyValue aPropValue;
707             std::vector< Any > aPropertyVector;
708 
709             aPropValue.Name     = "ModuleIdentifier";
710             aPropValue.Value    <<= m_aModuleIdentifier;
711             aPropertyVector.push_back( makeAny( aPropValue ));
712             aPropValue.Name     = "Frame";
713             aPropValue.Value    <<= m_xFrame;
714             aPropertyVector.push_back( makeAny( aPropValue ));
715             aPropValue.Name     = "ServiceManager";
716             Reference<XMultiServiceFactory> xMSF(m_xContext->getServiceManager(), UNO_QUERY_THROW);
717             aPropValue.Value    <<= xMSF;
718             aPropertyVector.push_back( makeAny( aPropValue ));
719             aPropValue.Name     = "ParentWindow";
720             aPropValue.Value    <<= xToolbarWindow;
721             aPropertyVector.push_back( makeAny( aPropValue ));
722             aPropValue.Name     = "Identifier";
723             aPropValue.Value    <<= nId;
724             aPropertyVector.push_back( uno::makeAny( aPropValue ) );
725 
726             Sequence< Any > aArgs( comphelper::containerToSequence( aPropertyVector ));
727             xController.set( m_xToolbarControllerFactory->createInstanceWithArgumentsAndContext( aCommandURL, aArgs, m_xContext ),
728                              UNO_QUERY );
729             bInit = false; // Initialization is done through the factory service
730         }
731 
732         if (( aCommandURL == ".uno:OpenUrl" ) && ( !m_pToolBar->IsItemVisible(nId)))
733             bCreate = false;
734 
735         if ( !xController.is() && bCreate )
736         {
737             pController = CreateToolBoxController( m_xFrame, m_pToolBar, nId, aCommandURL );
738             if ( !pController )
739             {
740                 if ( m_pToolBar->GetItemData( nId ) != nullptr )
741                 {
742                     // retrieve additional parameters
743                     OUString aControlType = static_cast< AddonsParams* >( m_pToolBar->GetItemData( nId ))->aControlType;
744                     sal_uInt16 nWidth = static_cast< AddonsParams* >( m_pToolBar->GetItemData( nId ))->nWidth;
745 
746                     Reference< XStatusListener > xStatusListener(
747                         ToolBarMerger::CreateController( m_xContext,
748                                                          m_xFrame,
749                                                          m_pToolBar,
750                                                          aCommandURL,
751                                                          nId,
752                                                          nWidth,
753                                                          aControlType ), UNO_QUERY );
754 
755                     xController = xStatusListener;
756                 }
757                 else if ( aCommandURL.startsWith( ".uno:StyleApply?" ) )
758                 {
759                     xController.set( new StyleToolbarController( m_xContext, m_xFrame, aCommandURL ));
760                     m_pToolBar->SetItemBits( nId, m_pToolBar->GetItemBits( nId ) | ToolBoxItemBits::CHECKABLE );
761                 }
762                 else if ( aCommandURL.startsWith( "private:resource/menubar/" ) )
763                 {
764                     xController.set( new MenuToolbarController );
765                 }
766                 else
767                 {
768                     xController.set(
769                         new GenericToolbarController( m_xContext, m_xFrame, m_pToolBar, nId, aCommandURL ));
770 
771                     // Accessibility support: Set toggle button role for specific commands
772                     sal_Int32 nProps = vcl::CommandInfoProvider::GetPropertiesForCommand(aCommandURL, m_aModuleIdentifier);
773                     if ( nProps & UICOMMANDDESCRIPTION_PROPERTIES_TOGGLEBUTTON )
774                         m_pToolBar->SetItemBits( nId, m_pToolBar->GetItemBits( nId ) | ToolBoxItemBits::CHECKABLE );
775                 }
776             }
777             else if ( pController )
778             {
779                 xController.set( static_cast< ::cppu::OWeakObject *>( pController ), UNO_QUERY );
780             }
781         }
782 
783         // Associate ID and controller to be able to retrieve
784         // the controller from the ID later.
785         m_aControllerMap[ nId ] = xController;
786 
787         // Fill sub-toolbars into our hash-map
788         Reference< XSubToolbarController > xSubToolBar( xController, UNO_QUERY );
789         if ( xSubToolBar.is() && xSubToolBar->opensSubToolbar() )
790         {
791             OUString aSubToolBarName = xSubToolBar->getSubToolbarName();
792             if ( !aSubToolBarName.isEmpty() )
793             {
794                 SubToolBarToSubToolBarControllerMap::iterator pIter =
795                     m_aSubToolBarControllerMap.find( aSubToolBarName );
796                 if ( pIter == m_aSubToolBarControllerMap.end() )
797                 {
798                     SubToolBarControllerVector aSubToolBarVector;
799                     aSubToolBarVector.push_back( xSubToolBar );
800                     m_aSubToolBarControllerMap.emplace(
801                             aSubToolBarName, aSubToolBarVector );
802                 }
803                 else
804                     pIter->second.push_back( xSubToolBar );
805             }
806         }
807 
808         Reference< XInitialization > xInit( xController, UNO_QUERY );
809         if ( xInit.is() )
810         {
811             if ( bInit )
812             {
813                 PropertyValue aPropValue;
814                 std::vector< Any > aPropertyVector;
815 
816                 aPropValue.Name = "Frame";
817                 aPropValue.Value <<= m_xFrame;
818                 aPropertyVector.push_back( makeAny( aPropValue ));
819                 aPropValue.Name = "CommandURL";
820                 aPropValue.Value <<= aCommandURL;
821                 aPropertyVector.push_back( makeAny( aPropValue ));
822                 aPropValue.Name = "ServiceManager";
823                 Reference<XMultiServiceFactory> xMSF(m_xContext->getServiceManager(), UNO_QUERY_THROW);
824                 aPropValue.Value <<= xMSF;
825                 aPropertyVector.push_back( makeAny( aPropValue ));
826                 aPropValue.Name = "ParentWindow";
827                 aPropValue.Value <<= xToolbarWindow;
828                 aPropertyVector.push_back( makeAny( aPropValue ));
829                 aPropValue.Name = "ModuleIdentifier";
830                 aPropValue.Value <<= m_aModuleIdentifier;
831                 aPropertyVector.push_back( makeAny( aPropValue ));
832                 aPropValue.Name     = "Identifier";
833                 aPropValue.Value    <<= nId;
834                 aPropertyVector.push_back( uno::makeAny( aPropValue ) );
835 
836                 Sequence< Any > aArgs( comphelper::containerToSequence( aPropertyVector ));
837                 xInit->initialize( aArgs );
838 
839                 if (pController)
840                 {
841                     if (aCommandURL == ".uno:SwitchXFormsDesignMode" || aCommandURL == ".uno:ViewDataSourceBrowser")
842                         pController->setFastPropertyValue_NoBroadcast(1, makeAny(true));
843                 }
844             }
845 
846             // Request an item window from the toolbar controller and set it at the VCL toolbar
847             Reference< XToolbarController > xTbxController( xController, UNO_QUERY );
848             if ( xTbxController.is() && xToolbarWindow.is() )
849             {
850                 Reference< XWindow > xWindow = xTbxController->createItemWindow( xToolbarWindow );
851                 if ( xWindow.is() )
852                 {
853                     VclPtr<vcl::Window> pItemWin = VCLUnoHelper::GetWindow( xWindow );
854                     if ( pItemWin )
855                     {
856                         WindowType nType = pItemWin->GetType();
857                         if ( nType == WindowType::LISTBOX || nType == WindowType::MULTILISTBOX || nType == WindowType::COMBOBOX )
858                             pItemWin->SetAccessibleName( m_pToolBar->GetItemText( nId ) );
859                         m_pToolBar->SetItemWindow( nId, pItemWin );
860                     }
861                 }
862             }
863         }
864 
865         //for update Controller via support visible state
866         Reference< XPropertySet > xPropSet( xController, UNO_QUERY );
867         if ( xPropSet.is() )
868         {
869             try
870             {
871                 bool bSupportVisible = true;
872                 Any a( xPropSet->getPropertyValue("SupportsVisible") );
873                 a >>= bSupportVisible;
874                 if (bSupportVisible)
875                 {
876                     Reference< XToolbarController > xTbxController( xController, UNO_QUERY );
877                     UpdateController(xTbxController);
878                 }
879             }
880             catch (const RuntimeException&)
881             {
882                 throw;
883             }
884             catch (const Exception&)
885             {
886             }
887         }
888     }
889 
890     AddFrameActionListener();
891 }
892 
AddFrameActionListener()893 void ToolBarManager::AddFrameActionListener()
894 {
895     if ( !m_bFrameActionRegistered && m_xFrame.is() )
896     {
897         m_bFrameActionRegistered = true;
898         m_xFrame->addFrameActionListener( Reference< XFrameActionListener >(
899                                             static_cast< ::cppu::OWeakObject *>( this ), UNO_QUERY ));
900     }
901 }
902 
ConvertStyleToToolboxItemBits(sal_Int32 nStyle)903 ToolBoxItemBits ToolBarManager::ConvertStyleToToolboxItemBits( sal_Int32 nStyle )
904 {
905     ToolBoxItemBits nItemBits( ToolBoxItemBits::NONE );
906     if ( nStyle & css::ui::ItemStyle::RADIO_CHECK )
907         nItemBits |= ToolBoxItemBits::RADIOCHECK;
908     if ( nStyle & css::ui::ItemStyle::ALIGN_LEFT )
909         nItemBits |= ToolBoxItemBits::LEFT;
910     if ( nStyle & css::ui::ItemStyle::AUTO_SIZE )
911         nItemBits |= ToolBoxItemBits::AUTOSIZE;
912     if ( nStyle & css::ui::ItemStyle::DROP_DOWN )
913         nItemBits |= ToolBoxItemBits::DROPDOWN;
914     if ( nStyle & css::ui::ItemStyle::REPEAT )
915         nItemBits |= ToolBoxItemBits::REPEAT;
916     if ( nStyle & css::ui::ItemStyle::DROPDOWN_ONLY )
917         nItemBits |= ToolBoxItemBits::DROPDOWNONLY;
918     if ( nStyle & css::ui::ItemStyle::TEXT )
919         nItemBits |= ToolBoxItemBits::TEXT_ONLY;
920     if ( nStyle & css::ui::ItemStyle::ICON )
921         nItemBits |= ToolBoxItemBits::ICON_ONLY;
922 
923     return nItemBits;
924 }
925 
InitImageManager()926 void ToolBarManager::InitImageManager()
927 {
928     Reference< XModuleManager2 > xModuleManager = ModuleManager::create( m_xContext );
929     if ( !m_xDocImageManager.is() )
930     {
931         Reference< XModel > xModel( GetModelFromFrame() );
932         if ( xModel.is() )
933         {
934             Reference< XUIConfigurationManagerSupplier > xSupplier( xModel, UNO_QUERY );
935             if ( xSupplier.is() )
936             {
937                 Reference< XUIConfigurationManager > xDocUICfgMgr = xSupplier->getUIConfigurationManager();
938                 m_xDocImageManager.set( xDocUICfgMgr->getImageManager(), UNO_QUERY );
939                 m_xDocImageManager->addConfigurationListener(
940                                         Reference< XUIConfigurationListener >(
941                                             static_cast< OWeakObject* >( this ), UNO_QUERY ));
942             }
943         }
944     }
945 
946     try
947     {
948         m_aModuleIdentifier = xModuleManager->identify( Reference< XInterface >( m_xFrame, UNO_QUERY ) );
949     }
950     catch (const Exception&)
951     {
952     }
953 
954     if ( !m_xModuleImageManager.is() )
955     {
956         Reference< XModuleUIConfigurationManagerSupplier > xModuleCfgMgrSupplier =
957             theModuleUIConfigurationManagerSupplier::get( m_xContext );
958         Reference< XUIConfigurationManager > xUICfgMgr = xModuleCfgMgrSupplier->getUIConfigurationManager( m_aModuleIdentifier );
959         m_xModuleImageManager.set( xUICfgMgr->getImageManager(), UNO_QUERY );
960         m_xModuleImageManager->addConfigurationListener( Reference< XUIConfigurationListener >(
961                                                             static_cast< OWeakObject* >( this ), UNO_QUERY ));
962     }
963 }
964 
FillToolbar(const Reference<XIndexAccess> & rItemContainer)965 void ToolBarManager::FillToolbar( const Reference< XIndexAccess >& rItemContainer )
966 {
967     OString aTbxName = OUStringToOString( m_aResourceName, RTL_TEXTENCODING_ASCII_US );
968     SAL_INFO( "fwk.uielement", "framework (cd100003) ::ToolBarManager::FillToolbar " << aTbxName );
969 
970     SolarMutexGuard g;
971 
972     if ( m_bDisposed )
973         return;
974 
975     InitImageManager();
976 
977     RemoveControllers();
978 
979     // reset and fill command map
980     m_pToolBar->Clear();
981     m_aControllerMap.clear();
982     m_aCommandMap.clear();
983 
984     sal_uInt16 nId( 1 );
985     CommandInfo aCmdInfo;
986     for ( sal_Int32 n = 0; n < rItemContainer->getCount(); n++ )
987     {
988         Sequence< PropertyValue >   aProp;
989         OUString                    aCommandURL;
990         OUString                    aLabel;
991         OUString                    aTooltip;
992         sal_uInt16                  nType( css::ui::ItemType::DEFAULT );
993         sal_uInt32                  nStyle( 0 );
994 
995         try
996         {
997             if ( rItemContainer->getByIndex( n ) >>= aProp )
998             {
999                 bool bIsVisible( true );
1000                 for ( int i = 0; i < aProp.getLength(); i++ )
1001                 {
1002                     if ( aProp[i].Name == ITEM_DESCRIPTOR_COMMANDURL )
1003                         aProp[i].Value >>= aCommandURL;
1004                     else if ( aProp[i].Name == "Label" )
1005                         aProp[i].Value >>= aLabel;
1006                     else if ( aProp[i].Name == "Tooltip" )
1007                         aProp[i].Value >>= aTooltip;
1008                     else if ( aProp[i].Name == "Type" )
1009                         aProp[i].Value >>= nType;
1010                     else if ( aProp[i].Name == ITEM_DESCRIPTOR_VISIBLE )
1011                         aProp[i].Value >>= bIsVisible;
1012                     else if ( aProp[i].Name == "Style" )
1013                         aProp[i].Value >>= nStyle;
1014                 }
1015 
1016                 if (!aCommandURL.isEmpty() && vcl::CommandInfoProvider::IsExperimental(aCommandURL, m_aModuleIdentifier) &&
1017                     !SvtMiscOptions().IsExperimentalMode())
1018                 {
1019                     continue;
1020                 }
1021 
1022                 if (( nType == css::ui::ItemType::DEFAULT ) && !aCommandURL.isEmpty() )
1023                 {
1024                     auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(aCommandURL, m_aModuleIdentifier);
1025                     OUString aString(vcl::CommandInfoProvider::GetLabelForCommand(aProperties));
1026 
1027                     ToolBoxItemBits nItemBits = ConvertStyleToToolboxItemBits( nStyle );
1028                     m_pToolBar->InsertItem( nId, aString, nItemBits );
1029                     m_pToolBar->SetItemCommand( nId, aCommandURL );
1030                     if ( !aTooltip.isEmpty() )
1031                         m_pToolBar->SetQuickHelpText(nId, aTooltip);
1032                     else
1033                         m_pToolBar->SetQuickHelpText(nId, vcl::CommandInfoProvider::GetTooltipForCommand(aCommandURL, aProperties, m_xFrame));
1034 
1035                     if ( !aLabel.isEmpty() )
1036                     {
1037                         m_pToolBar->SetItemText( nId, aLabel );
1038                     }
1039                     else
1040                     {
1041                         m_pToolBar->SetItemText( nId, aString );
1042                     }
1043                     m_pToolBar->EnableItem( nId );
1044                     m_pToolBar->SetItemState( nId, TRISTATE_FALSE );
1045 
1046                     // Fill command map. It stores all our commands and from what
1047                     // image manager we got our image. So we can decide if we have to use an
1048                     // image from a notification message.
1049                     auto pIter = m_aCommandMap.emplace( aCommandURL, aCmdInfo );
1050                     if ( pIter.second )
1051                     {
1052                         aCmdInfo.nId = nId;
1053                         pIter.first->second.nId = nId;
1054                     }
1055                     else
1056                     {
1057                         pIter.first->second.aIds.push_back( nId );
1058                     }
1059 
1060                     if ( !bIsVisible )
1061                         m_pToolBar->HideItem( nId );
1062 
1063                     ++nId;
1064                 }
1065                 else if ( nType == css::ui::ItemType::SEPARATOR_LINE )
1066                 {
1067                     m_pToolBar->InsertSeparator();
1068                 }
1069                 else if ( nType == css::ui::ItemType::SEPARATOR_SPACE )
1070                 {
1071                     m_pToolBar->InsertSpace();
1072                 }
1073                 else if ( nType == css::ui::ItemType::SEPARATOR_LINEBREAK )
1074                 {
1075                     m_pToolBar->InsertBreak();
1076                 }
1077             }
1078         }
1079         catch (const css::lang::IndexOutOfBoundsException&)
1080         {
1081             break;
1082         }
1083     }
1084 
1085     // Support add-on toolbar merging here. Working directly on the toolbar object is much
1086     // simpler and faster.
1087     const sal_uInt16 TOOLBAR_ITEM_STARTID = 1000;
1088 
1089     MergeToolbarInstructionContainer aMergeInstructionContainer;
1090 
1091     // Retrieve the toolbar name from the resource name
1092     OUString aToolbarName( m_aResourceName );
1093     sal_Int32 nIndex = aToolbarName.lastIndexOf( '/' );
1094     if (( nIndex > 0 ) && ( nIndex < aToolbarName.getLength() ))
1095         aToolbarName = aToolbarName.copy( nIndex+1 );
1096 
1097     AddonsOptions().GetMergeToolbarInstructions( aToolbarName, aMergeInstructionContainer );
1098 
1099     if ( !aMergeInstructionContainer.empty() )
1100     {
1101         sal_uInt16 nItemId( TOOLBAR_ITEM_STARTID );
1102         const sal_uInt32 nCount = aMergeInstructionContainer.size();
1103         for ( sal_uInt32 i=0; i < nCount; i++ )
1104         {
1105             MergeToolbarInstruction& rInstruction = aMergeInstructionContainer[i];
1106             if ( ToolBarMerger::IsCorrectContext( rInstruction.aMergeContext, m_aModuleIdentifier ))
1107             {
1108                 ReferenceToolbarPathInfo aRefPoint = ToolBarMerger::FindReferencePoint( m_pToolBar, rInstruction.aMergePoint );
1109 
1110                 // convert the sequence< sequence< propertyvalue > > structure to
1111                 // something we can better handle. A vector with item data
1112                 AddonToolbarItemContainer aItems;
1113                 ToolBarMerger::ConvertSeqSeqToVector( rInstruction.aMergeToolbarItems, aItems );
1114 
1115                 if ( aRefPoint.bResult )
1116                 {
1117                     ToolBarMerger::ProcessMergeOperation( m_pToolBar,
1118                                                           aRefPoint.nPos,
1119                                                           nItemId,
1120                                                           m_aCommandMap,
1121                                                           m_aModuleIdentifier,
1122                                                           rInstruction.aMergeCommand,
1123                                                           rInstruction.aMergeCommandParameter,
1124                                                           aItems );
1125                 }
1126                 else
1127                 {
1128                     ToolBarMerger::ProcessMergeFallback( m_pToolBar,
1129                                                          nItemId,
1130                                                          m_aCommandMap,
1131                                                          m_aModuleIdentifier,
1132                                                          rInstruction.aMergeCommand,
1133                                                          rInstruction.aMergeFallback,
1134                                                          aItems );
1135                 }
1136             }
1137         }
1138     }
1139 
1140     // Request images for all toolbar items. Must be done before CreateControllers as
1141     // some controllers need access to the image.
1142     RequestImages();
1143 
1144     // Create controllers after we set the images. There are controllers which needs
1145     // an image at the toolbar at creation time!
1146     CreateControllers();
1147 
1148     // Notify controllers that they are now correctly initialized and can start listening
1149     // toolbars that will open in popup mode will be updated immediately to avoid flickering
1150     if( m_pToolBar->WillUsePopupMode() )
1151         UpdateControllers();
1152     else if ( m_pToolBar->IsReallyVisible() )
1153     {
1154         m_aAsyncUpdateControllersTimer.Start();
1155     }
1156 
1157     // Try to retrieve UIName from the container property set and set it as the title
1158     // if it is not empty.
1159     Reference< XPropertySet > xPropSet( rItemContainer, UNO_QUERY );
1160     if ( xPropSet.is() )
1161     {
1162         try
1163         {
1164             OUString aUIName;
1165             xPropSet->getPropertyValue("UIName") >>= aUIName;
1166             if ( !aUIName.isEmpty() )
1167                 m_pToolBar->SetText( aUIName );
1168         }
1169         catch (const Exception&)
1170         {
1171         }
1172     }
1173 }
1174 
FillOverflowToolbar(ToolBox const * pParent)1175 void ToolBarManager::FillOverflowToolbar( ToolBox const * pParent )
1176 {
1177     CommandInfo aCmdInfo;
1178     bool bInsertSeparator = false;
1179     for ( ToolBox::ImplToolItems::size_type i = 0; i < pParent->GetItemCount(); ++i )
1180     {
1181         sal_uInt16 nId = pParent->GetItemId( i );
1182         if ( pParent->IsItemClipped( nId ) )
1183         {
1184             if ( bInsertSeparator )
1185             {
1186                 m_pToolBar->InsertSeparator();
1187                 bInsertSeparator = false;
1188             }
1189 
1190             const OUString aCommandURL( pParent->GetItemCommand( nId ) );
1191             m_pToolBar->InsertItem( nId, pParent->GetItemText( nId ) );
1192             m_pToolBar->SetItemCommand( nId, aCommandURL );
1193             m_pToolBar->SetQuickHelpText( nId, pParent->GetQuickHelpText( nId ) );
1194 
1195             // Handle possible add-on controls.
1196             AddonsParams* pAddonParams = static_cast< AddonsParams* >( pParent->GetItemData( nId ) );
1197             if ( pAddonParams )
1198                 m_pToolBar->SetItemData( nId, new AddonsParams( *pAddonParams ) );
1199 
1200             // Fill command map. It stores all our commands and from what
1201             // image manager we got our image. So we can decide if we have to use an
1202             // image from a notification message.
1203             auto pIter = m_aCommandMap.emplace( aCommandURL, aCmdInfo );
1204             if ( pIter.second )
1205             {
1206                 aCmdInfo.nId = nId;
1207                 pIter.first->second.nId = nId;
1208             }
1209             else
1210             {
1211                 pIter.first->second.aIds.push_back( nId );
1212             }
1213         }
1214         else
1215         {
1216             ToolBoxItemType eType = pParent->GetItemType( i );
1217             if ( m_pToolBar->GetItemCount() &&
1218                 ( eType == ToolBoxItemType::SEPARATOR || eType == ToolBoxItemType::BREAK ) )
1219                 bInsertSeparator = true;
1220         }
1221     }
1222 
1223     InitImageManager();
1224 
1225     // Request images for all toolbar items. Must be done before CreateControllers as
1226     // some controllers need access to the image.
1227     RequestImages();
1228 
1229     // Create controllers after we set the images. There are controllers which needs
1230     // an image at the toolbar at creation time!
1231     CreateControllers();
1232 
1233     // Notify controllers that they are now correctly initialized and can start listening
1234     // toolbars that will open in popup mode will be updated immediately to avoid flickering
1235     UpdateControllers();
1236 }
1237 
RequestImages()1238 void ToolBarManager::RequestImages()
1239 {
1240 
1241     // Request images from image manager
1242     Sequence< OUString > aCmdURLSeq( comphelper::mapKeysToSequence(m_aCommandMap) );
1243     Sequence< Reference< XGraphic > > aDocGraphicSeq;
1244     Sequence< Reference< XGraphic > > aModGraphicSeq;
1245 
1246     SvtMiscOptions aMiscOptions;
1247 
1248     sal_Int16 nImageType = getCurrentImageType();
1249 
1250     if ( m_xDocImageManager.is() )
1251         aDocGraphicSeq = m_xDocImageManager->getImages(nImageType, aCmdURLSeq);
1252     aModGraphicSeq = m_xModuleImageManager->getImages(nImageType, aCmdURLSeq);
1253 
1254     sal_uInt32 i = 0;
1255     CommandToInfoMap::iterator pIter = m_aCommandMap.begin();
1256     CommandToInfoMap::iterator pEnd = m_aCommandMap.end();
1257     while ( pIter != pEnd )
1258     {
1259         Image aImage;
1260         if ( aDocGraphicSeq.hasElements() )
1261             aImage = Image( aDocGraphicSeq[i] );
1262         if ( !aImage )
1263         {
1264             aImage = Image( aModGraphicSeq[i] );
1265             // Try also to query for add-on images before giving up and use an
1266             // empty image.
1267             if ( !aImage )
1268                 aImage = framework::AddonsOptions().GetImageFromURL( aCmdURLSeq[i], aMiscOptions.AreCurrentSymbolsLarge());
1269 
1270             pIter->second.nImageInfo = 1; // mark image as module based
1271         }
1272         else
1273         {
1274             pIter->second.nImageInfo = 0; // mark image as document based
1275         }
1276         setToolBarImage(aImage,pIter);
1277         ++pIter;
1278         ++i;
1279     }
1280 }
1281 
notifyRegisteredControllers(const OUString & aUIElementName,const OUString & aCommand)1282 void ToolBarManager::notifyRegisteredControllers( const OUString& aUIElementName, const OUString& aCommand )
1283 {
1284     SolarMutexClearableGuard aGuard;
1285     if ( !m_aSubToolBarControllerMap.empty() )
1286     {
1287         SubToolBarToSubToolBarControllerMap::const_iterator pIter =
1288             m_aSubToolBarControllerMap.find( aUIElementName );
1289 
1290         if ( pIter != m_aSubToolBarControllerMap.end() )
1291         {
1292             const SubToolBarControllerVector& rSubToolBarVector = pIter->second;
1293             if ( !rSubToolBarVector.empty() )
1294             {
1295                 SubToolBarControllerVector aNotifyVector = rSubToolBarVector;
1296                 aGuard.clear();
1297 
1298                 const sal_uInt32 nCount = aNotifyVector.size();
1299                 for ( sal_uInt32 i=0; i < nCount; i++ )
1300                 {
1301                     try
1302                     {
1303                         Reference< XSubToolbarController > xController = aNotifyVector[i];
1304                         if ( xController.is() )
1305                             xController->functionSelected( aCommand );
1306                     }
1307                     catch (const RuntimeException&)
1308                     {
1309                         throw;
1310                     }
1311                     catch (const Exception&)
1312                     {
1313                     }
1314                 }
1315             }
1316         }
1317     }
1318 }
1319 
HandleClick(void (SAL_CALL XToolbarController::* _pClick)())1320 void ToolBarManager::HandleClick(void ( SAL_CALL XToolbarController::*_pClick )())
1321 {
1322     SolarMutexGuard g;
1323 
1324     if ( m_bDisposed )
1325         return;
1326 
1327     sal_uInt16 nId( m_pToolBar->GetCurItemId() );
1328     ToolBarControllerMap::const_iterator pIter = m_aControllerMap.find( nId );
1329     if ( pIter != m_aControllerMap.end() )
1330     {
1331         Reference< XToolbarController > xController( pIter->second, UNO_QUERY );
1332 
1333         if ( xController.is() )
1334             (xController.get()->*_pClick)( );
1335     }
1336 }
1337 
IMPL_LINK_NOARG(ToolBarManager,Click,ToolBox *,void)1338 IMPL_LINK_NOARG(ToolBarManager, Click, ToolBox *, void)
1339 {
1340     HandleClick(&XToolbarController::click);
1341 }
1342 
IMPL_LINK_NOARG(ToolBarManager,DropdownClick,ToolBox *,void)1343 IMPL_LINK_NOARG(ToolBarManager, DropdownClick, ToolBox *, void)
1344 {
1345     SolarMutexGuard g;
1346 
1347     if ( m_bDisposed )
1348         return;
1349 
1350     sal_uInt16 nId( m_pToolBar->GetCurItemId() );
1351     ToolBarControllerMap::const_iterator pIter = m_aControllerMap.find( nId );
1352     if ( pIter != m_aControllerMap.end() )
1353     {
1354         Reference< XToolbarController > xController( pIter->second, UNO_QUERY );
1355 
1356         if ( xController.is() )
1357         {
1358             Reference< XWindow > xWin = xController->createPopupWindow();
1359             if ( xWin.is() )
1360                 xWin->setFocus();
1361         }
1362     }
1363 }
1364 
IMPL_LINK_NOARG(ToolBarManager,DoubleClick,ToolBox *,void)1365 IMPL_LINK_NOARG(ToolBarManager, DoubleClick, ToolBox *, void)
1366 {
1367     HandleClick(&XToolbarController::doubleClick);
1368 }
1369 
GetModelFromFrame() const1370 Reference< XModel > ToolBarManager::GetModelFromFrame() const
1371 {
1372     Reference< XController > xController = m_xFrame->getController();
1373     Reference< XModel > xModel;
1374     if ( xController.is() )
1375         xModel = xController->getModel();
1376 
1377     return xModel;
1378 }
1379 
IsPluginMode() const1380 bool ToolBarManager::IsPluginMode() const
1381 {
1382     bool bPluginMode( false );
1383 
1384     if ( m_xFrame.is() )
1385     {
1386         Reference< XModel > xModel = GetModelFromFrame();
1387         if ( xModel.is() )
1388         {
1389             Sequence< PropertyValue > aSeq = xModel->getArgs();
1390             utl::MediaDescriptor aMediaDescriptor( aSeq );
1391             bPluginMode = aMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_VIEWONLY(), false );
1392         }
1393     }
1394 
1395     return bPluginMode;
1396 }
1397 
MenuItemAllowed(sal_uInt16) const1398 bool ToolBarManager::MenuItemAllowed( sal_uInt16 ) const
1399 {
1400     return true;
1401 }
1402 
AddCustomizeMenuItems(ToolBox const * pToolBar)1403 void ToolBarManager::AddCustomizeMenuItems(ToolBox const * pToolBar)
1404 {
1405     // No config menu entries if command ".uno:ConfigureDialog" is not enabled
1406     Reference< XDispatch > xDisp;
1407     css::util::URL aURL;
1408     if ( m_xFrame.is() )
1409     {
1410         Reference< XDispatchProvider > xProv( m_xFrame, UNO_QUERY );
1411         aURL.Complete = ".uno:ConfigureDialog";
1412         m_xURLTransformer->parseStrict( aURL );
1413         if ( xProv.is() )
1414             xDisp = xProv->queryDispatch( aURL, OUString(), 0 );
1415 
1416         if ( !xDisp.is() || IsPluginMode() )
1417             return;
1418     }
1419 
1420     // popup menu for quick customization
1421     bool bHideDisabledEntries = !SvtMenuOptions().IsEntryHidingEnabled();
1422 
1423     ::PopupMenu *pMenu = pToolBar->GetMenu();
1424 
1425     // copy all menu items 'Visible buttons, Customize toolbar, Dock toolbar,
1426     // Dock all Toolbars) from the loaded resource into the toolbar menu
1427     sal_uInt16 nGroupLen = pMenu->GetItemCount();
1428     if (nGroupLen)
1429         pMenu->InsertSeparator();
1430 
1431     VclPtr<PopupMenu> xVisibleItemsPopupMenu;
1432 
1433     if (MenuItemAllowed(MENUITEM_TOOLBAR_VISIBLEBUTTON))
1434     {
1435         pMenu->InsertItem(MENUITEM_TOOLBAR_VISIBLEBUTTON, FwkResId(STR_TOOLBAR_VISIBLE_BUTTONS));
1436         xVisibleItemsPopupMenu = VclPtr<PopupMenu>::Create();
1437         pMenu->SetPopupMenu(MENUITEM_TOOLBAR_VISIBLEBUTTON, xVisibleItemsPopupMenu);
1438     }
1439 
1440     if (MenuItemAllowed(MENUITEM_TOOLBAR_CUSTOMIZETOOLBAR) && m_pToolBar->IsCustomize())
1441     {
1442         pMenu->InsertItem(MENUITEM_TOOLBAR_CUSTOMIZETOOLBAR, FwkResId(STR_TOOLBAR_CUSTOMIZE_TOOLBAR));
1443         pMenu->SetItemCommand(MENUITEM_TOOLBAR_CUSTOMIZETOOLBAR, ".uno:ConfigureToolboxVisible");
1444     }
1445 
1446     if (nGroupLen != pMenu->GetItemCount())
1447     {
1448         pMenu->InsertSeparator();
1449         nGroupLen = pMenu->GetItemCount();
1450     }
1451 
1452     if (MenuItemAllowed(MENUITEM_TOOLBAR_DOCKTOOLBAR))
1453         pMenu->InsertItem(MENUITEM_TOOLBAR_DOCKTOOLBAR, FwkResId(STR_TOOLBAR_DOCK_TOOLBAR));
1454 
1455     if (MenuItemAllowed(MENUITEM_TOOLBAR_DOCKALLTOOLBAR))
1456         pMenu->InsertItem(MENUITEM_TOOLBAR_DOCKALLTOOLBAR, FwkResId(STR_TOOLBAR_DOCK_ALL_TOOLBARS));
1457 
1458     if (nGroupLen != pMenu->GetItemCount())
1459     {
1460         pMenu->InsertSeparator();
1461         nGroupLen = pMenu->GetItemCount();
1462     }
1463 
1464     if (MenuItemAllowed(MENUITEM_TOOLBAR_LOCKTOOLBARPOSITION))
1465         pMenu->InsertItem(MENUITEM_TOOLBAR_LOCKTOOLBARPOSITION, FwkResId(STR_TOOLBAR_LOCK_TOOLBAR));
1466 
1467     if (MenuItemAllowed(MENUITEM_TOOLBAR_CLOSE))
1468         pMenu->InsertItem(MENUITEM_TOOLBAR_CLOSE, FwkResId(STR_TOOLBAR_CLOSE_TOOLBAR));
1469 
1470     if (m_pToolBar->IsCustomize())
1471     {
1472         bool    bIsFloating( false );
1473 
1474         DockingManager* pDockMgr = vcl::Window::GetDockingManager();
1475         if ( pDockMgr )
1476             bIsFloating = pDockMgr->IsFloating( m_pToolBar );
1477 
1478         if ( !bIsFloating )
1479         {
1480             pMenu->EnableItem(MENUITEM_TOOLBAR_DOCKTOOLBAR, false);
1481             pMenu->EnableItem(MENUITEM_TOOLBAR_DOCKALLTOOLBAR, false);
1482             Reference< XDockableWindow > xDockable( VCLUnoHelper::GetInterface( m_pToolBar ), UNO_QUERY );
1483             if( xDockable.is() )
1484                 pMenu->CheckItem(MENUITEM_TOOLBAR_LOCKTOOLBARPOSITION, xDockable->isLocked());
1485         }
1486         else
1487             pMenu->EnableItem(MENUITEM_TOOLBAR_LOCKTOOLBARPOSITION, false);
1488 
1489         if (SvtMiscOptions().DisableUICustomization())
1490         {
1491             pMenu->EnableItem(MENUITEM_TOOLBAR_VISIBLEBUTTON, false);
1492             pMenu->EnableItem(MENUITEM_TOOLBAR_CUSTOMIZETOOLBAR, false);
1493             pMenu->EnableItem(MENUITEM_TOOLBAR_LOCKTOOLBARPOSITION, false);
1494         }
1495 
1496         // Disable menu item CLOSE if the toolbar has no closer
1497         if( !(pToolBar->GetFloatStyle() & WB_CLOSEABLE) )
1498             pMenu->EnableItem(MENUITEM_TOOLBAR_CLOSE, false);
1499 
1500         // Temporary stores a Command --> Url map to update contextual menu with the
1501         // correct icons. The popup icons are by default the same as those in the
1502         // toolbar. They are not correct for contextual popup menu.
1503         std::map< OUString, Image > commandToImage;
1504 
1505         if (xVisibleItemsPopupMenu)
1506         {
1507             // Go through all toolbar items and add them to the context menu
1508             for ( ToolBox::ImplToolItems::size_type nPos = 0; nPos < m_pToolBar->GetItemCount(); ++nPos )
1509             {
1510                 if ( m_pToolBar->GetItemType(nPos) == ToolBoxItemType::BUTTON )
1511                 {
1512                     sal_uInt16 nId = m_pToolBar->GetItemId(nPos);
1513                     OUString aCommandURL = m_pToolBar->GetItemCommand( nId );
1514                     xVisibleItemsPopupMenu->InsertItem( STARTID_CUSTOMIZE_POPUPMENU+nPos, m_pToolBar->GetItemText( nId ), MenuItemBits::CHECKABLE );
1515                     xVisibleItemsPopupMenu->CheckItem( STARTID_CUSTOMIZE_POPUPMENU+nPos, m_pToolBar->IsItemVisible( nId ) );
1516                     xVisibleItemsPopupMenu->SetItemCommand( STARTID_CUSTOMIZE_POPUPMENU+nPos, aCommandURL );
1517                     Image aImage(vcl::CommandInfoProvider::GetImageForCommand(aCommandURL, m_xFrame));
1518                     commandToImage[aCommandURL] = aImage;
1519                     xVisibleItemsPopupMenu->SetItemImage( STARTID_CUSTOMIZE_POPUPMENU+nPos, aImage );
1520                 }
1521                 else
1522                 {
1523                     xVisibleItemsPopupMenu->InsertSeparator();
1524                 }
1525             }
1526         }
1527 
1528         // Now we go through all the contextual menu to update the icons
1529         std::map< OUString, Image >::iterator it;
1530         for ( sal_uInt16 nPos = 0; nPos < pMenu->GetItemCount(); ++nPos )
1531         {
1532             sal_uInt16 nId = pMenu->GetItemId( nPos );
1533             OUString cmdUrl = pMenu->GetItemCommand( nId );
1534             it = commandToImage.find( cmdUrl );
1535             if (it != commandToImage.end()) {
1536                 pMenu->SetItemImage( nId, it->second );
1537             }
1538         }
1539     }
1540 
1541     // Set the title of the menu
1542     pMenu->SetText( pToolBar->GetText() );
1543 
1544     if ( bHideDisabledEntries )
1545         pMenu->RemoveDisabledEntries();
1546 }
1547 
IMPL_LINK(ToolBarManager,MenuButton,ToolBox *,pToolBar,void)1548 IMPL_LINK( ToolBarManager, MenuButton, ToolBox*, pToolBar, void )
1549 {
1550     SolarMutexGuard g;
1551 
1552     if ( m_bDisposed )
1553         return;
1554 
1555     assert( !m_aOverflowManager.is() );
1556 
1557     VclPtrInstance<ToolBox> pOverflowToolBar( pToolBar, WB_BORDER | WB_SCROLL );
1558     pOverflowToolBar->SetLineSpacing(true);
1559     pOverflowToolBar->SetOutStyle( pToolBar->GetOutStyle() );
1560     m_aOverflowManager.set( new ToolBarManager( m_xContext, m_xFrame, OUString(), pOverflowToolBar ) );
1561     m_aOverflowManager->FillOverflowToolbar( pToolBar );
1562 
1563     ::Size aActSize( pOverflowToolBar->GetSizePixel() );
1564     ::Size aSize( pOverflowToolBar->CalcWindowSizePixel() );
1565     aSize.setWidth( aActSize.Width() );
1566     pOverflowToolBar->SetOutputSizePixel( aSize );
1567 
1568     aSize = pOverflowToolBar->CalcPopupWindowSizePixel();
1569     pOverflowToolBar->SetSizePixel( aSize );
1570 
1571     pOverflowToolBar->EnableDocking();
1572     pOverflowToolBar->AddEventListener( LINK( this, ToolBarManager, OverflowEventListener ) );
1573     vcl::Window::GetDockingManager()->StartPopupMode( pToolBar, pOverflowToolBar, FloatWinPopupFlags::AllMouseButtonClose );
1574 
1575     // send HOME key to subtoolbar in order to select first item if keyboard activated
1576     if(pToolBar->IsKeyEvent() )
1577     {
1578         ::KeyEvent aEvent( 0, vcl::KeyCode( KEY_HOME ) );
1579         pOverflowToolBar->KeyInput(aEvent);
1580     }
1581 }
1582 
IMPL_LINK(ToolBarManager,OverflowEventListener,VclWindowEvent &,rWindowEvent,void)1583 IMPL_LINK( ToolBarManager, OverflowEventListener, VclWindowEvent&, rWindowEvent, void )
1584 {
1585     if ( rWindowEvent.GetId() != VclEventId::WindowEndPopupMode )
1586         return;
1587 
1588     if ( m_aOverflowManager.is() )
1589     {
1590         m_aOverflowManager->dispose();
1591         m_aOverflowManager.clear();
1592     }
1593 }
1594 
IMPL_LINK(ToolBarManager,MenuPreExecute,ToolBox *,pToolBar,void)1595 IMPL_LINK( ToolBarManager, MenuPreExecute, ToolBox*, pToolBar, void )
1596 {
1597     SolarMutexGuard g;
1598 
1599     if ( m_bDisposed )
1600         return;
1601 
1602     AddCustomizeMenuItems( pToolBar );
1603 }
1604 
IMPL_LINK(ToolBarManager,MenuSelect,Menu *,pMenu,bool)1605 IMPL_LINK( ToolBarManager, MenuSelect, Menu*, pMenu, bool )
1606 {
1607     // We have to hold a reference to ourself as it is possible that we will be disposed and
1608     // our refcount could be zero (destruction) otherwise.
1609     Reference< XInterface > xInterface( static_cast< OWeakObject* >( this ), UNO_QUERY );
1610 
1611     {
1612         // The guard must be in its own context as the we can get destroyed when our
1613         // own xInterface reference get destroyed!
1614         SolarMutexGuard g;
1615 
1616         if ( m_bDisposed )
1617             return true;
1618 
1619         switch ( pMenu->GetCurItemId() )
1620         {
1621             case MENUITEM_TOOLBAR_CUSTOMIZETOOLBAR:
1622             {
1623                 Reference< XDispatch > xDisp;
1624                 css::util::URL aURL;
1625                 if ( m_xFrame.is() )
1626                 {
1627                     Reference< XDispatchProvider > xProv( m_xFrame, UNO_QUERY );
1628                     aURL.Complete = ".uno:ConfigureDialog";
1629                     m_xURLTransformer->parseStrict( aURL );
1630                     if ( xProv.is() )
1631                         xDisp = xProv->queryDispatch( aURL, OUString(), 0 );
1632                 }
1633 
1634                 if ( xDisp.is() )
1635                 {
1636                     Sequence< PropertyValue > aPropSeq( 1 );
1637 
1638                     aPropSeq[ 0 ].Name = "ResourceURL";
1639                     aPropSeq[ 0 ].Value <<= m_aResourceName;
1640 
1641                     xDisp->dispatch( aURL, aPropSeq );
1642                 }
1643                 break;
1644             }
1645 
1646             case MENUITEM_TOOLBAR_DOCKTOOLBAR:
1647             {
1648                 ExecuteInfo* pExecuteInfo = new ExecuteInfo;
1649 
1650                 pExecuteInfo->aToolbarResName = m_aResourceName;
1651                 pExecuteInfo->nCmd            = EXEC_CMD_DOCKTOOLBAR;
1652                 pExecuteInfo->xLayoutManager  = getLayoutManagerFromFrame( m_xFrame );
1653 
1654                 Application::PostUserEvent( LINK(nullptr, ToolBarManager, ExecuteHdl_Impl), pExecuteInfo );
1655                 break;
1656             }
1657 
1658             case MENUITEM_TOOLBAR_DOCKALLTOOLBAR:
1659             {
1660                 ExecuteInfo* pExecuteInfo = new ExecuteInfo;
1661 
1662                 pExecuteInfo->aToolbarResName = m_aResourceName;
1663                 pExecuteInfo->nCmd            = EXEC_CMD_DOCKALLTOOLBARS;
1664                 pExecuteInfo->xLayoutManager  = getLayoutManagerFromFrame( m_xFrame );
1665 
1666                 Application::PostUserEvent( LINK(nullptr, ToolBarManager, ExecuteHdl_Impl), pExecuteInfo );
1667                 break;
1668             }
1669 
1670             case MENUITEM_TOOLBAR_LOCKTOOLBARPOSITION:
1671             {
1672                 Reference< XLayoutManager > xLayoutManager = getLayoutManagerFromFrame( m_xFrame );
1673                 if ( xLayoutManager.is() )
1674                 {
1675                     Reference< XDockableWindow > xDockable( VCLUnoHelper::GetInterface( m_pToolBar ), UNO_QUERY );
1676 
1677                     if( xDockable->isLocked() )
1678                         xLayoutManager->unlockWindow( m_aResourceName );
1679                     else
1680                         xLayoutManager->lockWindow( m_aResourceName );
1681                 }
1682                 break;
1683             }
1684 
1685             case MENUITEM_TOOLBAR_CLOSE:
1686             {
1687                 ExecuteInfo* pExecuteInfo = new ExecuteInfo;
1688 
1689                 pExecuteInfo->aToolbarResName = m_aResourceName;
1690                 pExecuteInfo->nCmd            = EXEC_CMD_CLOSETOOLBAR;
1691                 pExecuteInfo->xLayoutManager  = getLayoutManagerFromFrame( m_xFrame );
1692                 pExecuteInfo->xWindow         = VCLUnoHelper::GetInterface( m_pToolBar );
1693 
1694                 Application::PostUserEvent( LINK(nullptr, ToolBarManager, ExecuteHdl_Impl), pExecuteInfo );
1695                 break;
1696             }
1697 
1698             default:
1699             {
1700                 sal_uInt16 nId = pMenu->GetCurItemId();
1701                 if(( nId > 0 ) && ( nId < TOOLBOX_MENUITEM_START ))
1702                 // Items in the "enable/disable" sub-menu
1703                 {
1704                     // toggle toolbar button visibility
1705                     OUString aCommand = pMenu->GetItemCommand( nId );
1706 
1707                     Reference< XLayoutManager > xLayoutManager = getLayoutManagerFromFrame( m_xFrame );
1708                     if ( xLayoutManager.is() )
1709                     {
1710                         Reference< XUIElementSettings > xUIElementSettings( xLayoutManager->getElement( m_aResourceName ), UNO_QUERY );
1711                         if ( xUIElementSettings.is() )
1712                         {
1713                             Reference< XIndexContainer > xItemContainer( xUIElementSettings->getSettings( true ), UNO_QUERY );
1714                             sal_Int32 nCount = xItemContainer->getCount();
1715                             for ( sal_Int32 i = 0; i < nCount; i++ )
1716                             {
1717                                 Sequence< PropertyValue > aProp;
1718                                 sal_Int32                 nVisibleIndex( -1 );
1719                                 OUString             aCommandURL;
1720                                 bool                  bVisible( false );
1721 
1722                                 if ( xItemContainer->getByIndex( i ) >>= aProp )
1723                                 {
1724                                     for ( sal_Int32 j = 0; j < aProp.getLength(); j++ )
1725                                     {
1726                                         if ( aProp[j].Name == ITEM_DESCRIPTOR_COMMANDURL )
1727                                         {
1728                                             aProp[j].Value >>= aCommandURL;
1729                                         }
1730                                         else if ( aProp[j].Name == ITEM_DESCRIPTOR_VISIBLE )
1731                                         {
1732                                             aProp[j].Value >>= bVisible;
1733                                             nVisibleIndex = j;
1734                                         }
1735                                     }
1736 
1737                                     if (( aCommandURL == aCommand ) && ( nVisibleIndex >= 0 ))
1738                                     {
1739                                         // We have found the requested item, toggle the visible flag
1740                                         // and write back the configuration settings to the toolbar
1741                                         aProp[nVisibleIndex].Value <<= !bVisible;
1742                                         try
1743                                         {
1744                                             xItemContainer->replaceByIndex( i, makeAny( aProp ));
1745                                             xUIElementSettings->setSettings( xItemContainer );
1746                                             Reference< XPropertySet > xPropSet( xUIElementSettings, UNO_QUERY );
1747                                             if ( xPropSet.is() )
1748                                             {
1749                                                 Reference< XUIConfigurationPersistence > xUICfgMgr;
1750                                                 if (( xPropSet->getPropertyValue("ConfigurationSource") >>= xUICfgMgr ) && ( xUICfgMgr.is() ))
1751                                                     xUICfgMgr->store();
1752                                             }
1753                                         }
1754                                         catch (const Exception&)
1755                                         {
1756                                         }
1757 
1758                                         break;
1759                                     }
1760                                 }
1761                             }
1762                         }
1763                     }
1764                 }
1765                 break;
1766             }
1767         }
1768     }
1769 
1770     return true;
1771 }
1772 
IMPL_LINK_NOARG(ToolBarManager,Select,ToolBox *,void)1773 IMPL_LINK_NOARG(ToolBarManager, Select, ToolBox *, void)
1774 {
1775     if ( m_bDisposed )
1776         return;
1777 
1778     sal_Int16   nKeyModifier( static_cast<sal_Int16>(m_pToolBar->GetModifier()) );
1779     sal_uInt16      nId( m_pToolBar->GetCurItemId() );
1780 
1781     ToolBarControllerMap::const_iterator pIter = m_aControllerMap.find( nId );
1782     if ( pIter != m_aControllerMap.end() )
1783     {
1784         Reference< XToolbarController > xController( pIter->second, UNO_QUERY );
1785 
1786         if ( xController.is() )
1787             xController->execute( nKeyModifier );
1788     }
1789 }
1790 
IMPL_LINK(ToolBarManager,StateChanged,StateChangedType const *,pStateChangedType,void)1791 IMPL_LINK( ToolBarManager, StateChanged, StateChangedType const *, pStateChangedType, void )
1792 {
1793     if ( m_bDisposed )
1794         return;
1795 
1796     if ( *pStateChangedType == StateChangedType::ControlBackground )
1797     {
1798         CheckAndUpdateImages();
1799     }
1800     else if ( *pStateChangedType == StateChangedType::Visible )
1801     {
1802         if ( m_pToolBar->IsReallyVisible() )
1803         {
1804             m_aAsyncUpdateControllersTimer.Start();
1805         }
1806     }
1807     else if ( *pStateChangedType == StateChangedType::InitShow )
1808     {
1809         m_aAsyncUpdateControllersTimer.Start();
1810     }
1811 }
1812 
IMPL_LINK(ToolBarManager,DataChanged,DataChangedEvent const *,pDataChangedEvent,void)1813 IMPL_LINK( ToolBarManager, DataChanged, DataChangedEvent const *, pDataChangedEvent, void )
1814 {
1815     if ((( pDataChangedEvent->GetType() == DataChangedEventType::SETTINGS )   ||
1816         (  pDataChangedEvent->GetType() == DataChangedEventType::DISPLAY  ))  &&
1817         ( pDataChangedEvent->GetFlags() & AllSettingsFlags::STYLE        ))
1818     {
1819         CheckAndUpdateImages();
1820     }
1821 
1822     for ( ToolBox::ImplToolItems::size_type nPos = 0; nPos < m_pToolBar->GetItemCount(); ++nPos )
1823     {
1824         const sal_uInt16 nId = m_pToolBar->GetItemId(nPos);
1825         vcl::Window* pWindow = m_pToolBar->GetItemWindow( nId );
1826         if ( pWindow )
1827         {
1828             const DataChangedEvent& rDCEvt( *pDataChangedEvent );
1829             pWindow->DataChanged( rDCEvt );
1830         }
1831     }
1832 
1833     if ( !m_pToolBar->IsFloatingMode() &&
1834          m_pToolBar->IsVisible() )
1835     {
1836         // Resize toolbar, layout manager is resize listener and will calc
1837         // the layout automatically.
1838         ::Size aSize( m_pToolBar->CalcWindowSizePixel() );
1839         m_pToolBar->SetOutputSizePixel( aSize );
1840     }
1841 }
1842 
IMPL_LINK_NOARG(ToolBarManager,MiscOptionsChanged,LinkParamNone *,void)1843 IMPL_LINK_NOARG(ToolBarManager, MiscOptionsChanged, LinkParamNone*, void)
1844 {
1845     CheckAndUpdateImages();
1846 }
1847 
IMPL_LINK_NOARG(ToolBarManager,AsyncUpdateControllersHdl,Timer *,void)1848 IMPL_LINK_NOARG(ToolBarManager, AsyncUpdateControllersHdl, Timer *, void)
1849 {
1850     // The guard must be in its own context as the we can get destroyed when our
1851     // own xInterface reference get destroyed!
1852     Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY );
1853 
1854     SolarMutexGuard g;
1855 
1856     if ( m_bDisposed )
1857         return;
1858 
1859     // Request to update our controllers
1860     m_aAsyncUpdateControllersTimer.Stop();
1861     UpdateControllers();
1862 }
1863 
IMPL_STATIC_LINK(ToolBarManager,ExecuteHdl_Impl,void *,p,void)1864 IMPL_STATIC_LINK( ToolBarManager, ExecuteHdl_Impl, void*, p, void )
1865 {
1866     ExecuteInfo* pExecuteInfo = static_cast<ExecuteInfo*>(p);
1867     try
1868     {
1869         // Asynchronous execution as this can lead to our own destruction!
1870         if (( pExecuteInfo->nCmd == EXEC_CMD_CLOSETOOLBAR ) &&
1871             ( pExecuteInfo->xLayoutManager.is() ) &&
1872             ( pExecuteInfo->xWindow.is() ))
1873         {
1874             // Use docking window close to close the toolbar. The toolbar layout manager is
1875             // listener and will react correctly according to the context sensitive
1876             // flag of our toolbar.
1877             VclPtr<vcl::Window> pWin = VCLUnoHelper::GetWindow( pExecuteInfo->xWindow );
1878             DockingWindow* pDockWin = dynamic_cast< DockingWindow* >( pWin.get() );
1879             if ( pDockWin )
1880                 pDockWin->Close();
1881         }
1882         else if (( pExecuteInfo->nCmd == EXEC_CMD_DOCKTOOLBAR ) &&
1883                  ( pExecuteInfo->xLayoutManager.is() ))
1884         {
1885             css::awt::Point aPoint;
1886             aPoint.X = aPoint.Y = SAL_MAX_INT32;
1887             pExecuteInfo->xLayoutManager->dockWindow( pExecuteInfo->aToolbarResName,
1888                                                       DockingArea_DOCKINGAREA_DEFAULT,
1889                                                       aPoint );
1890         }
1891         else if (( pExecuteInfo->nCmd == EXEC_CMD_DOCKALLTOOLBARS ) &&
1892                  ( pExecuteInfo->xLayoutManager.is() ))
1893         {
1894             pExecuteInfo->xLayoutManager->dockAllWindows( UIElementType::TOOLBAR );
1895         }
1896     }
1897     catch (const Exception&)
1898     {
1899     }
1900 
1901     delete pExecuteInfo;
1902 }
1903 }
1904 
1905 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1906