1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_framework.hxx"
26 #include <uielement/toolbarsmenucontroller.hxx>
27 
28 #include <algorithm>
29 
30 //_________________________________________________________________________________________________________________
31 //	my own includes
32 //_________________________________________________________________________________________________________________
33 #include <threadhelp/resetableguard.hxx>
34 #include "services.h"
35 #ifndef __FRAMEWORK_CLASSES_RESOURCE_HRC_
36 #include <classes/resource.hrc>
37 #endif
38 #include <classes/fwkresid.hxx>
39 #include <uiconfiguration/windowstateconfiguration.hxx>
40 #include <framework/imageproducer.hxx>
41 #include <framework/sfxhelperfunctions.hxx>
42 
43 //_________________________________________________________________________________________________________________
44 //	interface includes
45 //_________________________________________________________________________________________________________________
46 #include <com/sun/star/awt/XDevice.hpp>
47 #include <com/sun/star/beans/PropertyValue.hpp>
48 #include <com/sun/star/awt/MenuItemStyle.hpp>
49 #include <com/sun/star/frame/XDispatchProvider.hpp>
50 #include <com/sun/star/container/XNameContainer.hpp>
51 #include <com/sun/star/beans/XPropertySet.hpp>
52 #include <com/sun/star/frame/XLayoutManager.hpp>
53 #include <com/sun/star/ui/XUIElementSettings.hpp>
54 #include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp>
55 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
56 #include <com/sun/star/ui/UIElementType.hpp>
57 
58 //_________________________________________________________________________________________________________________
59 //	includes of other projects
60 //_________________________________________________________________________________________________________________
61 
62 #ifndef _VCL_MENU_HXX_
63 #include <vcl/menu.hxx>
64 #endif
65 #include <vcl/svapp.hxx>
66 #include <vcl/i18nhelp.hxx>
67 #include <vcl/image.hxx>
68 #include <tools/urlobj.hxx>
69 #include <rtl/ustrbuf.hxx>
70 #ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_
71 #include <toolkit/unohlp.hxx>
72 #endif
73 #include <vcl/window.hxx>
74 #include <svtools/menuoptions.hxx>
75 #include <unotools/cmdoptions.hxx>
76 #include <dispatch/uieventloghelper.hxx>
77 #include <rtl/logfile.hxx>
78 
79 //_________________________________________________________________________________________________________________
80 //	Defines
81 //_________________________________________________________________________________________________________________
82 //
83 
84 using namespace ::com::sun::star;
85 using namespace ::com::sun::star::uno;
86 using namespace ::com::sun::star::lang;
87 using namespace ::com::sun::star::frame;
88 using namespace ::com::sun::star::beans;
89 using namespace ::com::sun::star::util;
90 using namespace ::com::sun::star::container;
91 using namespace ::com::sun::star::frame;
92 using namespace ::com::sun::star::ui;
93 
94 static const char CONFIGURE_TOOLBARS_CMD[]      = "ConfigureDialog";
95 static const char CONFIGURE_TOOLBARS[]          = ".uno:ConfigureDialog";
96 static const char CMD_COLORBAR[]                = ".uno:ColorControl";
97 static const char CMD_HYPERLINKBAR[]            = ".uno:InsertHyperlink";
98 static const char CMD_FORMULABAR[]              = ".uno:InsertFormula";
99 static const char CMD_INPUTLINEBAR[]            = ".uno:InputLineVisible";
100 static const char CMD_RESTOREVISIBILITY[]       = ".cmd:RestoreVisibility";
101 static const char ITEM_DESCRIPTOR_RESOURCEURL[] = "ResourceURL";
102 static const char ITEM_DESCRIPTOR_UINAME[]		= "UIName";
103 static const char STATIC_PRIVATE_TB_RESOURCE[]  = "private:resource/toolbar/";
104 
105 static const char STATIC_CMD_PART[]             = ".uno:AvailableToolbars?Toolbar:string=";
106 static const char STATIC_INTERNAL_CMD_PART[]    = ".cmd:";
107 
108 namespace framework
109 {
110 
111 typedef std::hash_map< rtl::OUString, rtl::OUString, OUStringHashCode, ::std::equal_to< ::rtl::OUString > > ToolbarHashMap;
112 
113 struct ToolBarEntry
114 {
115     rtl::OUString           aUIName;
116     rtl::OUString           aCommand;
117     sal_Bool                bVisible;
118     sal_Bool                bContextSensitive;
119     const CollatorWrapper*  pCollatorWrapper;
120 };
121 
122 sal_Bool CompareToolBarEntry( const ToolBarEntry& aOne, const ToolBarEntry& aTwo )
123 {
124     sal_Int32 nComp = aOne.pCollatorWrapper->compareString( aOne.aUIName, aTwo.aUIName );
125 
126     if ( nComp < 0 )
127 		return sal_True;
128 	else if ( nComp > 0 )
129 		return sal_False;
130 	else
131 		return sal_False;
132 }
133 
134 Reference< XLayoutManager > getLayoutManagerFromFrame( const Reference< XFrame >& rFrame )
135 {
136     Reference< XPropertySet >   xPropSet( rFrame, UNO_QUERY );
137     Reference< XLayoutManager > xLayoutManager;
138 
139     try
140     {
141 	    xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" ))) >>= xLayoutManager;
142     }
143     catch ( UnknownPropertyException& )
144     {
145     }
146 
147     return xLayoutManager;
148 }
149 
150 struct ToolBarInfo
151 {
152     rtl::OUString aToolBarResName;
153     rtl::OUString aToolBarUIName;
154 };
155 
156 DEFINE_XSERVICEINFO_MULTISERVICE        (   ToolbarsMenuController				    ,
157                                             OWeakObject                             ,
158                                             SERVICENAME_POPUPMENUCONTROLLER		    ,
159 											IMPLEMENTATIONNAME_TOOLBARSMENUCONTROLLER
160 										)
161 
162 DEFINE_INIT_SERVICE                     (   ToolbarsMenuController, {} )
163 
164 ToolbarsMenuController::ToolbarsMenuController( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ) :
165 	svt::PopupMenuControllerBase( xServiceManager ),
166     m_aPropUIName( RTL_CONSTASCII_USTRINGPARAM( "UIName" )),
167     m_aPropResourceURL( RTL_CONSTASCII_USTRINGPARAM( "ResourceURL" )),
168     m_bModuleIdentified( sal_False ),
169     m_bResetActive( sal_False ),
170     m_aIntlWrapper( xServiceManager, Application::GetSettings().GetLocale() )
171 {
172 }
173 
174 ToolbarsMenuController::~ToolbarsMenuController()
175 {
176 }
177 
178 void ToolbarsMenuController::addCommand(
179     Reference< css::awt::XPopupMenu >& rPopupMenu, const rtl::OUString& rCommandURL, const rtl::OUString& rLabel )
180 {
181     sal_uInt16        nItemId    = m_xPopupMenu->getItemCount()+1;
182 
183     rtl::OUString aLabel;
184     if ( rLabel.getLength() == 0 )
185         aLabel = getUINameFromCommand( rCommandURL );
186     else
187         aLabel = rLabel;
188 
189 	rPopupMenu->insertItem( nItemId, aLabel, 0, nItemId );
190     Reference< awt::XMenuExtended > xMenuExtended( m_xPopupMenu, UNO_QUERY );
191     xMenuExtended->setCommand( nItemId, rCommandURL );
192 
193     bool bInternal = ( rCommandURL.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STATIC_INTERNAL_CMD_PART ))) == 0);
194     if ( !bInternal )
195     {
196         if ( !getDispatchFromCommandURL( rCommandURL ).is() )
197             m_xPopupMenu->enableItem( nItemId, sal_False );
198     }
199 
200     vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
201 
202     Image                aImage;
203 	const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
204 
205     if ( rSettings.GetUseImagesInMenus() )
206         aImage = GetImageFromURL( m_xFrame, rCommandURL, sal_False, rSettings.GetHighContrastMode() );
207 
208     VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXPopupMenu::GetImplementation( rPopupMenu );
209     if ( pPopupMenu )
210     {
211         PopupMenu* pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu();
212         if ( !!aImage )
213             pVCLPopupMenu->SetItemImage( nItemId, aImage );
214     }
215 
216     m_aCommandVector.push_back( rCommandURL );
217 }
218 
219 Reference< XDispatch > ToolbarsMenuController::getDispatchFromCommandURL( const rtl::OUString& rCommandURL )
220 {
221     URL                          aTargetURL;
222 	Sequence<PropertyValue>	     aArgs;
223     Reference< XURLTransformer > xURLTransformer;
224     Reference< XFrame >          xFrame;
225 
226     {
227         vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
228         xURLTransformer = m_xURLTransformer;
229         xFrame = m_xFrame;
230     }
231 
232     aTargetURL.Complete = rCommandURL;
233     xURLTransformer->parseStrict( aTargetURL );
234 	Reference< XDispatchProvider > xDispatchProvider( xFrame, UNO_QUERY );
235     if ( xDispatchProvider.is() )
236         return xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 );
237     else
238         return Reference< XDispatch >();
239 }
240 
241 // private function
242 rtl::OUString ToolbarsMenuController::getUINameFromCommand( const rtl::OUString& rCommandURL )
243 {
244     rtl::OUString aLabel;
245 
246     if ( !m_bModuleIdentified  )
247     {
248 		try
249         {
250             Reference< XModuleManager > xModuleManager( m_xServiceManager->createInstance( SERVICENAME_MODULEMANAGER ), UNO_QUERY_THROW );
251             m_aModuleIdentifier = xModuleManager->identify( m_xFrame );
252             Reference< XNameAccess > xNameAccess( m_xServiceManager->createInstance(
253                                                                     SERVICENAME_UICOMMANDDESCRIPTION ),
254                                                                 UNO_QUERY );
255             xNameAccess->getByName( m_aModuleIdentifier ) >>= m_xUICommandDescription;
256         }
257         catch ( Exception& )
258         {
259         }
260     }
261 
262     if ( m_xUICommandDescription.is() )
263     {
264         try
265         {
266             Sequence< PropertyValue > aPropSeq;
267             rtl::OUString             aStr;
268             if ( m_xUICommandDescription->getByName( rCommandURL ) >>= aPropSeq )
269             {
270                 for ( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ )
271                 {
272                     if ( aPropSeq[i].Name.equalsAscii( "Label" ))
273                     {
274                         aPropSeq[i].Value >>= aStr;
275                         break;
276                     }
277                 }
278             }
279             aLabel = aStr;
280         }
281         catch ( Exception& )
282         {
283         }
284     }
285 
286     return aLabel;
287 }
288 
289 static void fillHashMap( const Sequence< Sequence< ::com::sun::star::beans::PropertyValue > >& rSeqToolBars,
290                          ToolbarHashMap& rHashMap )
291 {
292     for ( sal_Int32 i = 0; i < rSeqToolBars.getLength(); i++ )
293     {
294         rtl::OUString aResourceURL;
295         rtl::OUString aUIName;
296         const PropertyValue* pProperties = rSeqToolBars[i].getConstArray();
297         for ( sal_Int32 j = 0; j < rSeqToolBars[i].getLength(); j++ )
298 		{
299 			if ( pProperties[j].Name.equalsAscii( ITEM_DESCRIPTOR_RESOURCEURL) )
300 				pProperties[j].Value >>= aResourceURL;
301 			else if ( pProperties[j].Name.equalsAscii( ITEM_DESCRIPTOR_UINAME) )
302                 pProperties[j].Value >>= aUIName;
303         }
304 
305         if ( aResourceURL.getLength() > 0 &&
306              rHashMap.find( aResourceURL ) == rHashMap.end() )
307             rHashMap.insert( ToolbarHashMap::value_type( aResourceURL, aUIName ));
308     }
309 }
310 
311 // private function
312 Sequence< Sequence< com::sun::star::beans::PropertyValue > > ToolbarsMenuController::getLayoutManagerToolbars( const Reference< ::com::sun::star::frame::XLayoutManager >& rLayoutManager )
313 {
314     std::vector< ToolBarInfo > aToolBarArray;
315     Sequence< Reference< XUIElement > > aUIElements = rLayoutManager->getElements();
316     for ( sal_Int32 i = 0; i < aUIElements.getLength(); i++ )
317     {
318         Reference< XUIElement > xUIElement( aUIElements[i] );
319         Reference< XPropertySet > xPropSet( aUIElements[i], UNO_QUERY );
320         if ( xPropSet.is() && xUIElement.is() )
321         {
322             try
323             {
324                 rtl::OUString   aResName;
325                 sal_Int16       nType( -1 );
326                 xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Type" ))) >>= nType;
327                 xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ResourceURL" ))) >>= aResName;
328 
329                 if (( nType == ::com::sun::star::ui::UIElementType::TOOLBAR ) &&
330                     ( aResName.getLength() > 0 ))
331                 {
332 		            ToolBarInfo aToolBarInfo;
333 
334                     aToolBarInfo.aToolBarResName = aResName;
335 
336                     vos::OGuard	aGuard( Application::GetSolarMutex() );
337                     Reference< css::awt::XWindow > xWindow( xUIElement->getRealInterface(), UNO_QUERY );
338                     Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
339                     if ( pWindow )
340                         aToolBarInfo.aToolBarUIName = pWindow->GetText();
341 
342                     aToolBarArray.push_back( aToolBarInfo );
343                 }
344             }
345             catch ( Exception& )
346             {
347             }
348         }
349     }
350 
351     Sequence< com::sun::star::beans::PropertyValue > aTbSeq( 2 );
352     aTbSeq[0].Name = m_aPropUIName;
353     aTbSeq[1].Name = m_aPropResourceURL;
354 
355     Sequence< Sequence< com::sun::star::beans::PropertyValue > > aSeq( aToolBarArray.size() );
356     const sal_uInt32 nCount = aToolBarArray.size();
357     for ( sal_uInt32 i = 0; i < nCount; i++ )
358     {
359         aTbSeq[0].Value <<= aToolBarArray[i].aToolBarUIName;
360         aTbSeq[1].Value <<= aToolBarArray[i].aToolBarResName;
361         aSeq[i] = aTbSeq;
362     }
363 
364     return aSeq;
365 }
366 
367 sal_Bool ToolbarsMenuController::isContextSensitiveToolbarNonVisible()
368 {
369     return m_bResetActive;
370 }
371 
372 void ToolbarsMenuController::fillPopupMenu( Reference< css::awt::XPopupMenu >& rPopupMenu )
373 {
374     vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
375     resetPopupMenu( rPopupMenu );
376 
377     m_aCommandVector.clear();
378 
379     // Retrieve layout manager for additional information
380     rtl::OUString                   aEmptyString;
381     Reference< awt::XMenuExtended > xMenuExtended( rPopupMenu, UNO_QUERY );
382     Reference< XLayoutManager >     xLayoutManager( getLayoutManagerFromFrame( m_xFrame ));
383 
384     m_bResetActive = sal_False;
385     if ( xLayoutManager.is() )
386     {
387         ToolbarHashMap aToolbarHashMap;
388 
389         if ( m_xDocCfgMgr.is() )
390         {
391             Sequence< Sequence< com::sun::star::beans::PropertyValue > > aSeqDocToolBars =
392                 m_xDocCfgMgr->getUIElementsInfo( UIElementType::TOOLBAR );
393             fillHashMap( aSeqDocToolBars, aToolbarHashMap );
394         }
395 
396         if ( m_xModuleCfgMgr.is() )
397         {
398             Sequence< Sequence< com::sun::star::beans::PropertyValue > > aSeqToolBars =
399                 m_xModuleCfgMgr->getUIElementsInfo( UIElementType::TOOLBAR );
400             fillHashMap( aSeqToolBars, aToolbarHashMap );
401         }
402 
403         std::vector< ToolBarEntry > aSortedTbs;
404         rtl::OUString               aStaticCmdPart( RTL_CONSTASCII_USTRINGPARAM( STATIC_CMD_PART ));
405 
406         Sequence< Sequence< com::sun::star::beans::PropertyValue > > aSeqFrameToolBars = getLayoutManagerToolbars( xLayoutManager );
407         fillHashMap( aSeqFrameToolBars, aToolbarHashMap );
408 
409         ToolbarHashMap::const_iterator pIter = aToolbarHashMap.begin();
410         while ( pIter != aToolbarHashMap.end() )
411         {
412             rtl::OUString aUIName = pIter->second;
413             sal_Bool      bHideFromMenu( sal_False );
414             sal_Bool      bContextSensitive( sal_False );
415             sal_Bool      bVisible( sal_False );
416             if ( aUIName.getLength() == 0 &&
417                  m_xPersistentWindowState.is() )
418             {
419                 try
420                 {
421                     Sequence< PropertyValue > aWindowState;
422                     Any                       a( m_xPersistentWindowState->getByName( pIter->first ));
423 
424                     if ( a >>= aWindowState )
425                     {
426                         for ( sal_Int32 i = 0; i < aWindowState.getLength(); i++ )
427                         {
428                             if ( aWindowState[i].Name.equalsAscii( WINDOWSTATE_PROPERTY_UINAME ))
429                                 aWindowState[i].Value >>= aUIName;
430                             else if ( aWindowState[i].Name.equalsAscii( WINDOWSTATE_PROPERTY_HIDEFROMENU ))
431                                 aWindowState[i].Value >>= bHideFromMenu;
432                             else if ( aWindowState[i].Name.equalsAscii( WINDOWSTATE_PROPERTY_CONTEXT ))
433                                 aWindowState[i].Value >>= bContextSensitive;
434                             else if ( aWindowState[i].Name.equalsAscii( WINDOWSTATE_PROPERTY_VISIBLE ))
435                                 aWindowState[i].Value >>= bVisible;
436                         }
437                     }
438                 }
439                 catch ( Exception& )
440                 {
441                 }
442 
443                 // Check if we have to enable/disable "Reset" menu item
444                 if ( bContextSensitive && !bVisible )
445                     m_bResetActive = sal_True;
446 
447             }
448 
449             if (( aUIName.getLength() > 0 ) && ( !bHideFromMenu ))
450             {
451                 ToolBarEntry aTbEntry;
452                 aTbEntry.aUIName = aUIName;
453                 aTbEntry.aCommand = pIter->first;
454                 aTbEntry.bVisible = xLayoutManager->isElementVisible( pIter->first );
455                 aTbEntry.bContextSensitive = bContextSensitive;
456                 aTbEntry.pCollatorWrapper = m_aIntlWrapper.getCaseCollator();
457                 aSortedTbs.push_back( aTbEntry );
458             }
459             pIter++;
460         }
461 
462         // sort toolbars
463         std::sort( aSortedTbs.begin(), aSortedTbs.end(), CompareToolBarEntry );
464 
465         sal_Int16 nIndex( 1 );
466         const sal_uInt32 nCount = aSortedTbs.size();
467         for ( sal_uInt32 i = 0; i < nCount; i++ )
468         {
469             sal_uInt16 nItemCount = m_xPopupMenu->getItemCount();
470             m_xPopupMenu->insertItem( nIndex, aSortedTbs[i].aUIName, css::awt::MenuItemStyle::CHECKABLE, nItemCount );
471             if ( aSortedTbs[i].bVisible )
472                 m_xPopupMenu->checkItem( nIndex, sal_True );
473 
474             {
475                 vos::OGuard	aGuard( Application::GetSolarMutex() );
476                 VCLXPopupMenu* pXPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( m_xPopupMenu );
477                 PopupMenu*     pVCLPopupMenu = (PopupMenu *)pXPopupMenu->GetMenu();
478 
479                 pVCLPopupMenu->SetUserValue( nIndex, sal_uIntPtr( aSortedTbs[i].bContextSensitive ? 1L : 0L ));
480             }
481 
482             // use VCL popup menu pointer to set vital information that are not part of the awt implementation
483             rtl::OUStringBuffer aStrBuf( aStaticCmdPart );
484 
485             sal_Int32 n = aSortedTbs[i].aCommand.lastIndexOf( '/' );
486             if (( n > 0 ) && (( n+1 ) < aSortedTbs[i].aCommand.getLength() ))
487                 aStrBuf.append( aSortedTbs[i].aCommand.copy( n+1 ));
488 
489             rtl::OUString aCmd( aStrBuf.makeStringAndClear() );
490 
491             // Store complete uno-command so it can also be dispatched. This is necessary to support
492             // the test tool!
493 		    xMenuExtended->setCommand( nIndex, aCmd );
494             ++nIndex;
495         }
496 
497         // Create commands for non-toolbars
498         if ( m_aModuleIdentifier.equalsAscii( "com.sun.star.text.TextDocument" ) ||
499              m_aModuleIdentifier.equalsAscii( "com.sun.star.text.WebDocument" ) ||
500              m_aModuleIdentifier.equalsAscii( "com.sun.star.text.GlobalDocument" ) ||
501              m_aModuleIdentifier.equalsAscii( "com.sun.star.drawing.DrawingDocument" ) ||
502              m_aModuleIdentifier.equalsAscii( "com.sun.star.presentation.PresentationDocument" ) ||
503              m_aModuleIdentifier.equalsAscii( "com.sun.star.sheet.SpreadsheetDocument" ))
504         {
505             addCommand( m_xPopupMenu, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CMD_HYPERLINKBAR )), aEmptyString );
506             if ( m_aModuleIdentifier.equalsAscii( "com.sun.star.drawing.DrawingDocument" ) ||
507                  m_aModuleIdentifier.equalsAscii( "com.sun.star.presentation.PresentationDocument" ))
508                 addCommand( m_xPopupMenu, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CMD_COLORBAR )), aEmptyString );
509             else if ( m_aModuleIdentifier.equalsAscii( "com.sun.star.sheet.SpreadsheetDocument" ))
510                 addCommand( m_xPopupMenu, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CMD_INPUTLINEBAR )), aEmptyString );
511             else
512                 addCommand( m_xPopupMenu, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CMD_FORMULABAR )), aEmptyString );
513         }
514 
515         sal_Bool          bAddCommand( sal_True );
516         SvtCommandOptions aCmdOptions;
517         rtl::OUString     aConfigureToolbar( RTL_CONSTASCII_USTRINGPARAM( CONFIGURE_TOOLBARS ));
518 
519         if ( aCmdOptions.HasEntries( SvtCommandOptions::CMDOPTION_DISABLED ))
520         {
521             if ( aCmdOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED,
522                                      rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CONFIGURE_TOOLBARS_CMD ))))
523                 bAddCommand = sal_False;
524         }
525 
526         if ( bAddCommand )
527         {
528             // Create command for configure
529             if ( m_xPopupMenu->getItemCount() > 0 )
530             {
531                 sal_uInt16        nItemCount = m_xPopupMenu->getItemCount();
532                 m_xPopupMenu->insertSeparator( nItemCount+1 );
533             }
534 
535             addCommand( m_xPopupMenu, aConfigureToolbar, aEmptyString );
536         }
537 
538         // Add separator if no configure has been added
539         if ( !bAddCommand )
540         {
541             // Create command for configure
542             if ( m_xPopupMenu->getItemCount() > 0 )
543             {
544                 sal_uInt16        nItemCount = m_xPopupMenu->getItemCount();
545                 m_xPopupMenu->insertSeparator( nItemCount+1 );
546             }
547         }
548 
549         String aLabelStr = String( FwkResId( STR_RESTORE_TOOLBARS ));
550         rtl::OUString aRestoreCmd( RTL_CONSTASCII_USTRINGPARAM( CMD_RESTOREVISIBILITY ));
551         addCommand( m_xPopupMenu, aRestoreCmd, aLabelStr );
552     }
553 }
554 
555 // XEventListener
556 void SAL_CALL ToolbarsMenuController::disposing( const EventObject& ) throw ( RuntimeException )
557 {
558     Reference< css::awt::XMenuListener > xHolder(( OWeakObject *)this, UNO_QUERY );
559 
560     osl::MutexGuard aLock( m_aMutex );
561     m_xFrame.clear();
562     m_xDispatch.clear();
563     m_xDocCfgMgr.clear();
564     m_xModuleCfgMgr.clear();
565     m_xServiceManager.clear();
566 
567     if ( m_xPopupMenu.is() )
568         m_xPopupMenu->removeMenuListener( Reference< css::awt::XMenuListener >(( OWeakObject *)this, UNO_QUERY ));
569     m_xPopupMenu.clear();
570 }
571 
572 // XStatusListener
573 void SAL_CALL ToolbarsMenuController::statusChanged( const FeatureStateEvent& Event ) throw ( RuntimeException )
574 {
575     rtl::OUString aFeatureURL( Event.FeatureURL.Complete );
576 
577     // All other status events will be processed here
578     sal_Bool bSetCheckmark      = sal_False;
579 	sal_Bool bCheckmark			= sal_False;
580 
581     osl::ClearableMutexGuard aLock( m_aMutex );
582     Reference< css::awt::XPopupMenu > xPopupMenu( m_xPopupMenu );
583     aLock.clear();
584 
585 	if ( xPopupMenu.is() )
586     {
587         vos::OGuard	aGuard( Application::GetSolarMutex() );
588         VCLXPopupMenu* pXPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( xPopupMenu );
589         PopupMenu*     pVCLPopupMenu = (PopupMenu *)pXPopupMenu->GetMenu();
590 
591         for ( sal_uInt16 i = 0; i < pVCLPopupMenu->GetItemCount(); i++ )
592         {
593             sal_uInt16 nId = pVCLPopupMenu->GetItemId( i );
594             if ( nId == 0 )
595                 continue;
596 
597             rtl::OUString aCmd = pVCLPopupMenu->GetItemCommand( nId );
598             if ( aCmd == aFeatureURL )
599             {
600                 // Enable/disable item
601                 pVCLPopupMenu->EnableItem( nId, Event.IsEnabled );
602 
603                 // Checkmark
604                 if ( Event.State >>= bCheckmark )
605 				    bSetCheckmark = sal_True;
606 
607                 if ( bSetCheckmark )
608                     pVCLPopupMenu->CheckItem( nId, bCheckmark );
609                 else
610                 {
611                     rtl::OUString aItemText;
612 
613                     if ( Event.State >>= aItemText )
614                         pVCLPopupMenu->SetItemText( nId, aItemText );
615                 }
616             }
617         }
618     }
619 }
620 
621 // XMenuListener
622 void SAL_CALL ToolbarsMenuController::select( const css::awt::MenuEvent& rEvent ) throw (RuntimeException)
623 {
624     Reference< css::awt::XPopupMenu >   xPopupMenu;
625     Reference< XMultiServiceFactory >   xServiceManager;
626     Reference< XURLTransformer >        xURLTransformer;
627     Reference< XFrame >                 xFrame;
628     Reference< XNameAccess >            xPersistentWindowState;
629 
630     osl::ClearableMutexGuard aLock( m_aMutex );
631     xPopupMenu             = m_xPopupMenu;
632     xServiceManager        = m_xServiceManager;
633     xURLTransformer        = m_xURLTransformer;
634     xFrame                 = m_xFrame;
635     xPersistentWindowState = m_xPersistentWindowState;
636     aLock.clear();
637 
638     if ( xPopupMenu.is() )
639     {
640         VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXPopupMenu::GetImplementation( xPopupMenu );
641         if ( pPopupMenu )
642         {
643             vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
644             PopupMenu* pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu();
645 
646             rtl::OUString aCmd( pVCLPopupMenu->GetItemCommand( rEvent.MenuId ));
647             if ( aCmd.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STATIC_INTERNAL_CMD_PART ))) == 0 )
648             {
649                 // Command to restore the visibility of all context sensitive toolbars
650                 Reference< XNameReplace > xNameReplace( xPersistentWindowState, UNO_QUERY );
651                 if ( xPersistentWindowState.is() && xNameReplace.is() )
652                 {
653                     try
654                     {
655                         Sequence< rtl::OUString > aElementNames = xPersistentWindowState->getElementNames();
656                         sal_Int32 nCount = aElementNames.getLength();
657                         bool      bRefreshToolbars( false );
658 
659                         for ( sal_Int32 i = 0; i < nCount; i++ )
660                         {
661                             try
662                             {
663                                 rtl::OUString aElementName = aElementNames[i];
664                                 Sequence< PropertyValue > aWindowState;
665 
666                                 if ( xPersistentWindowState->getByName( aElementName ) >>= aWindowState )
667                                 {
668                                     sal_Bool  bVisible( sal_False );
669                                     sal_Bool  bContextSensitive( sal_False );
670                                     sal_Int32 nVisibleIndex( -1 );
671                                     for ( sal_Int32 j = 0; j < aWindowState.getLength(); j++ )
672                                     {
673                                         if ( aWindowState[j].Name.equalsAscii( WINDOWSTATE_PROPERTY_VISIBLE ))
674                                         {
675                                             aWindowState[j].Value >>= bVisible;
676                                             nVisibleIndex = j;
677                                         }
678                                         else if ( aWindowState[j].Name.equalsAscii( WINDOWSTATE_PROPERTY_CONTEXT ))
679                                             aWindowState[j].Value >>= bContextSensitive;
680                                     }
681 
682                                     if ( !bVisible && bContextSensitive && nVisibleIndex >= 0 )
683                                     {
684                                         // Default is: Every context sensitive toolbar is visible
685                                         aWindowState[nVisibleIndex].Value <<= sal_True;
686                                         xNameReplace->replaceByName( aElementName, makeAny( aWindowState ));
687                                         bRefreshToolbars = true;
688                                     }
689                                 }
690                             }
691                             catch ( NoSuchElementException& )
692                             {
693                             }
694                         }
695 
696                         if ( bRefreshToolbars )
697                         {
698                             Reference< XLayoutManager > xLayoutManager( getLayoutManagerFromFrame( xFrame ));
699                             if ( xLayoutManager.is() )
700                             {
701                                 Reference< XPropertySet > xPropSet( xLayoutManager, UNO_QUERY );
702                                 if ( xPropSet.is() )
703                                 {
704                                     try
705                                     {
706                                         xPropSet->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RefreshContextToolbarVisibility" )), makeAny( sal_True ));
707                                     }
708                                     catch ( RuntimeException& )
709                                     {
710                                     }
711                                     catch ( Exception& )
712                                     {
713                                     }
714                                 }
715                             }
716                             RefreshToolbars( xFrame );
717                         }
718                     }
719                     catch ( RuntimeException& )
720                     {
721                         throw;
722                     }
723                     catch ( Exception& )
724                     {
725                     }
726                 }
727             }
728             else if ( aCmd.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STATIC_CMD_PART ))) < 0 )
729             {
730                 URL                     aTargetURL;
731                 Sequence<PropertyValue>	aArgs;
732 
733                 aTargetURL.Complete = aCmd;
734                 xURLTransformer->parseStrict( aTargetURL );
735 		        Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
736                 if ( xDispatchProvider.is() )
737                 {
738 		            Reference< XDispatch > xDispatch = xDispatchProvider->queryDispatch(
739 														    aTargetURL, ::rtl::OUString(), 0 );
740 
741                     ExecuteInfo* pExecuteInfo = new ExecuteInfo;
742                     pExecuteInfo->xDispatch     = xDispatch;
743                     pExecuteInfo->aTargetURL    = aTargetURL;
744                     pExecuteInfo->aArgs         = aArgs;
745                     if(::comphelper::UiEventsLogger::isEnabled()) //#i88653#
746                         UiEventLogHelper(::rtl::OUString::createFromAscii("ToolbarsMenuController")).log(m_xServiceManager, m_xFrame, aTargetURL, aArgs);
747                     Application::PostUserEvent( STATIC_LINK(0, ToolbarsMenuController, ExecuteHdl_Impl), pExecuteInfo );
748                 }
749             }
750             else
751             {
752                 Reference< XLayoutManager > xLayoutManager( getLayoutManagerFromFrame( xFrame ));
753                 if ( xLayoutManager.is() )
754                 {
755                     // Extract toolbar name from the combined uno-command.
756                     sal_Int32 nIndex = aCmd.indexOf( '=' );
757                     if (( nIndex > 0 ) && (( nIndex+1 ) < aCmd.getLength() ))
758                     {
759                         rtl::OUStringBuffer aBuf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STATIC_PRIVATE_TB_RESOURCE )));
760                         aBuf.append( aCmd.copy( nIndex+1 ));
761 
762                         sal_Bool      bShow( !pVCLPopupMenu->IsItemChecked( rEvent.MenuId ));
763                         rtl::OUString aToolBarResName( aBuf.makeStringAndClear() );
764                         if ( bShow )
765                         {
766                             xLayoutManager->createElement( aToolBarResName );
767                             xLayoutManager->showElement( aToolBarResName );
768                         }
769                         else
770                         {
771                             // closing means:
772                             // hide and destroy element
773                             xLayoutManager->hideElement( aToolBarResName );
774                             xLayoutManager->destroyElement( aToolBarResName );
775                         }
776                     }
777                 }
778             }
779         }
780     }
781 }
782 
783 void SAL_CALL ToolbarsMenuController::activate( const css::awt::MenuEvent& ) throw (RuntimeException)
784 {
785     std::vector< rtl::OUString >   aCmdVector;
786     Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
787     Reference< XURLTransformer >   xURLTransformer( m_xURLTransformer );
788     {
789         osl::MutexGuard aLock( m_aMutex );
790         fillPopupMenu( m_xPopupMenu );
791         aCmdVector = m_aCommandVector;
792     }
793 
794     // Update status for all commands inside our toolbars popup menu
795     const sal_uInt32 nCount = aCmdVector.size();
796     for ( sal_uInt32 i = 0; i < nCount; i++ )
797     {
798         bool bInternal = ( aCmdVector[i].indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STATIC_INTERNAL_CMD_PART ))) == 0);
799 
800         if ( !bInternal )
801         {
802             URL aTargetURL;
803             aTargetURL.Complete = aCmdVector[i];
804             xURLTransformer->parseStrict( aTargetURL );
805             Reference< XDispatch > xDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 );
806             if ( xDispatch.is() )
807             {
808 			    xDispatch->addStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL );
809 			    xDispatch->removeStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL );
810             }
811         }
812         else if ( aCmdVector[i].equalsAscii( CMD_RESTOREVISIBILITY ))
813         {
814             // Special code to determine the enable/disable state of this command
815             FeatureStateEvent aFeatureStateEvent;
816             aFeatureStateEvent.FeatureURL.Complete = aCmdVector[i];
817             aFeatureStateEvent.IsEnabled = isContextSensitiveToolbarNonVisible();
818             statusChanged( aFeatureStateEvent );
819         }
820     }
821 }
822 
823 // XPopupMenuController
824 void SAL_CALL ToolbarsMenuController::setPopupMenu( const Reference< css::awt::XPopupMenu >& xPopupMenu ) throw ( RuntimeException )
825 {
826     osl::MutexGuard aLock( m_aMutex );
827 
828     throwIfDisposed();
829 
830     if ( m_xFrame.is() && !m_xPopupMenu.is() )
831     {
832         // Create popup menu on demand
833         vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
834 
835         m_xPopupMenu = xPopupMenu;
836 	    m_xPopupMenu->addMenuListener( Reference< css::awt::XMenuListener >( (OWeakObject*)this, UNO_QUERY ));
837         fillPopupMenu( m_xPopupMenu );
838     }
839 }
840 
841 // XInitialization
842 void SAL_CALL ToolbarsMenuController::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException )
843 {
844     osl::MutexGuard aLock( m_aMutex );
845     sal_Bool bInitalized( m_bInitialized );
846     if ( !bInitalized )
847     {
848 		svt::PopupMenuControllerBase::initialize(aArguments);
849 
850         if ( m_bInitialized )
851         {
852             Reference< XModuleManager > xModuleManager( m_xServiceManager->createInstance(
853                                                             SERVICENAME_MODULEMANAGER ),
854                                                         UNO_QUERY );
855             Reference< XNameAccess > xPersistentWindowStateSupplier( m_xServiceManager->createInstance(
856                                                                         SERVICENAME_WINDOWSTATECONFIGURATION ),
857                                                                      UNO_QUERY );
858 
859             // Retrieve persistent window state reference for our module
860             if ( xPersistentWindowStateSupplier.is() && xModuleManager.is() )
861             {
862                 rtl::OUString aModuleIdentifier;
863                 try
864                 {
865                     aModuleIdentifier = xModuleManager->identify( m_xFrame );
866                     xPersistentWindowStateSupplier->getByName( aModuleIdentifier ) >>= m_xPersistentWindowState;
867 
868                     Reference< XModuleUIConfigurationManagerSupplier > xModuleCfgSupplier;
869                     if ( m_xServiceManager.is() )
870                         xModuleCfgSupplier = Reference< XModuleUIConfigurationManagerSupplier >(
871                             m_xServiceManager->createInstance( SERVICENAME_MODULEUICONFIGURATIONMANAGERSUPPLIER ), UNO_QUERY );
872                     m_xModuleCfgMgr = xModuleCfgSupplier->getUIConfigurationManager( aModuleIdentifier );
873 
874                     Reference< XController > xController = m_xFrame->getController();
875                     Reference< XModel >      xModel;
876                     if ( xController.is() )
877                         xModel = xController->getModel();
878                     if ( xModel.is() )
879                     {
880                         Reference< XUIConfigurationManagerSupplier > xUIConfigurationManagerSupplier( xModel, UNO_QUERY );
881                         if ( xUIConfigurationManagerSupplier.is() )
882                             m_xDocCfgMgr = xUIConfigurationManagerSupplier->getUIConfigurationManager();
883                     }
884                     m_aModuleIdentifier = aModuleIdentifier;
885                 }
886                 catch ( Exception& )
887                 {
888                 }
889             }
890         }
891     }
892 }
893 
894 IMPL_STATIC_LINK_NOINSTANCE( ToolbarsMenuController, ExecuteHdl_Impl, ExecuteInfo*, pExecuteInfo )
895 {
896     try
897     {
898         // Asynchronous execution as this can lead to our own destruction!
899         // Framework can recycle our current frame and the layout manager disposes all user interface
900         // elements if a component gets detached from its frame!
901         if ( pExecuteInfo->xDispatch.is() )
902         {
903             pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs );
904         }
905     }
906     catch ( Exception& )
907     {
908     }
909 
910     delete pExecuteInfo;
911     return 0;
912 }
913 
914 }
915