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