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/helper/vclunohelper.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, rtl::OUStringHash, ::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 
CompareToolBarEntry(const ToolBarEntry & aOne,const ToolBarEntry & aTwo)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 
getLayoutManagerFromFrame(const Reference<XFrame> & rFrame)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 
DEFINE_XSERVICEINFO_MULTISERVICE(ToolbarsMenuController,OWeakObject,SERVICENAME_POPUPMENUCONTROLLER,IMPLEMENTATIONNAME_TOOLBARSMENUCONTROLLER)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 
~ToolbarsMenuController()174 ToolbarsMenuController::~ToolbarsMenuController()
175 {
176 }
177 
addCommand(Reference<css::awt::XPopupMenu> & rPopupMenu,const rtl::OUString & rCommandURL,const rtl::OUString & rLabel)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     rPopupMenu->setCommand( nItemId, rCommandURL );
191 
192     bool bInternal = ( rCommandURL.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STATIC_INTERNAL_CMD_PART ))) == 0);
193     if ( !bInternal )
194     {
195         if ( !getDispatchFromCommandURL( rCommandURL ).is() )
196             m_xPopupMenu->enableItem( nItemId, sal_False );
197     }
198 
199     vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
200 
201     Image                aImage;
202 	const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
203 
204     if ( rSettings.GetUseImagesInMenus() )
205         aImage = GetImageFromURL( m_xFrame, rCommandURL, sal_False, rSettings.GetHighContrastMode() );
206 
207     VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXPopupMenu::GetImplementation( rPopupMenu );
208     if ( pPopupMenu )
209     {
210         PopupMenu* pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu();
211         if ( !!aImage )
212             pVCLPopupMenu->SetItemImage( nItemId, aImage );
213     }
214 
215     m_aCommandVector.push_back( rCommandURL );
216 }
217 
getDispatchFromCommandURL(const rtl::OUString & rCommandURL)218 Reference< XDispatch > ToolbarsMenuController::getDispatchFromCommandURL( const rtl::OUString& rCommandURL )
219 {
220     URL                          aTargetURL;
221 	Sequence<PropertyValue>	     aArgs;
222     Reference< XURLTransformer > xURLTransformer;
223     Reference< XFrame >          xFrame;
224 
225     {
226         vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
227         xURLTransformer = m_xURLTransformer;
228         xFrame = m_xFrame;
229     }
230 
231     aTargetURL.Complete = rCommandURL;
232     xURLTransformer->parseStrict( aTargetURL );
233 	Reference< XDispatchProvider > xDispatchProvider( xFrame, UNO_QUERY );
234     if ( xDispatchProvider.is() )
235         return xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 );
236     else
237         return Reference< XDispatch >();
238 }
239 
240 // private function
getUINameFromCommand(const rtl::OUString & rCommandURL)241 rtl::OUString ToolbarsMenuController::getUINameFromCommand( const rtl::OUString& rCommandURL )
242 {
243     rtl::OUString aLabel;
244 
245     if ( !m_bModuleIdentified  )
246     {
247 		try
248         {
249             Reference< XModuleManager > xModuleManager( m_xServiceManager->createInstance( SERVICENAME_MODULEMANAGER ), UNO_QUERY_THROW );
250             m_aModuleIdentifier = xModuleManager->identify( m_xFrame );
251             Reference< XNameAccess > xNameAccess( m_xServiceManager->createInstance(
252                                                                     SERVICENAME_UICOMMANDDESCRIPTION ),
253                                                                 UNO_QUERY );
254             xNameAccess->getByName( m_aModuleIdentifier ) >>= m_xUICommandDescription;
255         }
256         catch ( Exception& )
257         {
258         }
259     }
260 
261     if ( m_xUICommandDescription.is() )
262     {
263         try
264         {
265             Sequence< PropertyValue > aPropSeq;
266             rtl::OUString             aStr;
267             if ( m_xUICommandDescription->getByName( rCommandURL ) >>= aPropSeq )
268             {
269                 for ( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ )
270                 {
271                     if ( aPropSeq[i].Name.equalsAscii( "Label" ))
272                     {
273                         aPropSeq[i].Value >>= aStr;
274                         break;
275                     }
276                 }
277             }
278             aLabel = aStr;
279         }
280         catch ( Exception& )
281         {
282         }
283     }
284 
285     return aLabel;
286 }
287 
fillHashMap(const Sequence<Sequence<::com::sun::star::beans::PropertyValue>> & rSeqToolBars,ToolbarHashMap & rHashMap)288 static void fillHashMap( const Sequence< Sequence< ::com::sun::star::beans::PropertyValue > >& rSeqToolBars,
289                          ToolbarHashMap& rHashMap )
290 {
291     for ( sal_Int32 i = 0; i < rSeqToolBars.getLength(); i++ )
292     {
293         rtl::OUString aResourceURL;
294         rtl::OUString aUIName;
295         const PropertyValue* pProperties = rSeqToolBars[i].getConstArray();
296         for ( sal_Int32 j = 0; j < rSeqToolBars[i].getLength(); j++ )
297 		{
298 			if ( pProperties[j].Name.equalsAscii( ITEM_DESCRIPTOR_RESOURCEURL) )
299 				pProperties[j].Value >>= aResourceURL;
300 			else if ( pProperties[j].Name.equalsAscii( ITEM_DESCRIPTOR_UINAME) )
301                 pProperties[j].Value >>= aUIName;
302         }
303 
304         if ( aResourceURL.getLength() > 0 &&
305              rHashMap.find( aResourceURL ) == rHashMap.end() )
306             rHashMap.insert( ToolbarHashMap::value_type( aResourceURL, aUIName ));
307     }
308 }
309 
310 // private function
getLayoutManagerToolbars(const Reference<::com::sun::star::frame::XLayoutManager> & rLayoutManager)311 Sequence< Sequence< com::sun::star::beans::PropertyValue > > ToolbarsMenuController::getLayoutManagerToolbars( const Reference< ::com::sun::star::frame::XLayoutManager >& rLayoutManager )
312 {
313     std::vector< ToolBarInfo > aToolBarArray;
314     Sequence< Reference< XUIElement > > aUIElements = rLayoutManager->getElements();
315     for ( sal_Int32 i = 0; i < aUIElements.getLength(); i++ )
316     {
317         Reference< XUIElement > xUIElement( aUIElements[i] );
318         Reference< XPropertySet > xPropSet( aUIElements[i], UNO_QUERY );
319         if ( xPropSet.is() && xUIElement.is() )
320         {
321             try
322             {
323                 rtl::OUString   aResName;
324                 sal_Int16       nType( -1 );
325                 xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Type" ))) >>= nType;
326                 xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ResourceURL" ))) >>= aResName;
327 
328                 if (( nType == ::com::sun::star::ui::UIElementType::TOOLBAR ) &&
329                     ( aResName.getLength() > 0 ))
330                 {
331 		            ToolBarInfo aToolBarInfo;
332 
333                     aToolBarInfo.aToolBarResName = aResName;
334 
335                     vos::OGuard	aGuard( Application::GetSolarMutex() );
336                     Reference< css::awt::XWindow > xWindow( xUIElement->getRealInterface(), UNO_QUERY );
337                     Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
338                     if ( pWindow )
339                         aToolBarInfo.aToolBarUIName = pWindow->GetText();
340 
341                     aToolBarArray.push_back( aToolBarInfo );
342                 }
343             }
344             catch ( Exception& )
345             {
346             }
347         }
348     }
349 
350     Sequence< com::sun::star::beans::PropertyValue > aTbSeq( 2 );
351     aTbSeq[0].Name = m_aPropUIName;
352     aTbSeq[1].Name = m_aPropResourceURL;
353 
354     Sequence< Sequence< com::sun::star::beans::PropertyValue > > aSeq( aToolBarArray.size() );
355     const sal_uInt32 nCount = aToolBarArray.size();
356     for ( sal_uInt32 i = 0; i < nCount; i++ )
357     {
358         aTbSeq[0].Value <<= aToolBarArray[i].aToolBarUIName;
359         aTbSeq[1].Value <<= aToolBarArray[i].aToolBarResName;
360         aSeq[i] = aTbSeq;
361     }
362 
363     return aSeq;
364 }
365 
isContextSensitiveToolbarNonVisible()366 sal_Bool ToolbarsMenuController::isContextSensitiveToolbarNonVisible()
367 {
368     return m_bResetActive;
369 }
370 
fillPopupMenu(Reference<css::awt::XPopupMenu> & rPopupMenu)371 void ToolbarsMenuController::fillPopupMenu( Reference< css::awt::XPopupMenu >& rPopupMenu )
372 {
373     vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
374     resetPopupMenu( rPopupMenu );
375 
376     m_aCommandVector.clear();
377 
378     // Retrieve layout manager for additional information
379     rtl::OUString aEmptyString;
380     Reference< XLayoutManager > xLayoutManager( getLayoutManagerFromFrame( m_xFrame ));
381 
382     m_bResetActive = sal_False;
383     if ( xLayoutManager.is() )
384     {
385         ToolbarHashMap aToolbarHashMap;
386 
387         if ( m_xDocCfgMgr.is() )
388         {
389             Sequence< Sequence< com::sun::star::beans::PropertyValue > > aSeqDocToolBars =
390                 m_xDocCfgMgr->getUIElementsInfo( UIElementType::TOOLBAR );
391             fillHashMap( aSeqDocToolBars, aToolbarHashMap );
392         }
393 
394         if ( m_xModuleCfgMgr.is() )
395         {
396             Sequence< Sequence< com::sun::star::beans::PropertyValue > > aSeqToolBars =
397                 m_xModuleCfgMgr->getUIElementsInfo( UIElementType::TOOLBAR );
398             fillHashMap( aSeqToolBars, aToolbarHashMap );
399         }
400 
401         std::vector< ToolBarEntry > aSortedTbs;
402         rtl::OUString               aStaticCmdPart( RTL_CONSTASCII_USTRINGPARAM( STATIC_CMD_PART ));
403 
404         Sequence< Sequence< com::sun::star::beans::PropertyValue > > aSeqFrameToolBars = getLayoutManagerToolbars( xLayoutManager );
405         fillHashMap( aSeqFrameToolBars, aToolbarHashMap );
406 
407         ToolbarHashMap::const_iterator pIter = aToolbarHashMap.begin();
408         while ( pIter != aToolbarHashMap.end() )
409         {
410             rtl::OUString aUIName = pIter->second;
411             sal_Bool      bHideFromMenu( sal_False );
412             sal_Bool      bContextSensitive( sal_False );
413             sal_Bool      bVisible( sal_False );
414             if ( aUIName.getLength() == 0 &&
415                  m_xPersistentWindowState.is() )
416             {
417                 try
418                 {
419                     Sequence< PropertyValue > aWindowState;
420                     Any                       a( m_xPersistentWindowState->getByName( pIter->first ));
421 
422                     if ( a >>= aWindowState )
423                     {
424                         for ( sal_Int32 i = 0; i < aWindowState.getLength(); i++ )
425                         {
426                             if ( aWindowState[i].Name.equalsAscii( WINDOWSTATE_PROPERTY_UINAME ))
427                                 aWindowState[i].Value >>= aUIName;
428                             else if ( aWindowState[i].Name.equalsAscii( WINDOWSTATE_PROPERTY_HIDEFROMENU ))
429                                 aWindowState[i].Value >>= bHideFromMenu;
430                             else if ( aWindowState[i].Name.equalsAscii( WINDOWSTATE_PROPERTY_CONTEXT ))
431                                 aWindowState[i].Value >>= bContextSensitive;
432                             else if ( aWindowState[i].Name.equalsAscii( WINDOWSTATE_PROPERTY_VISIBLE ))
433                                 aWindowState[i].Value >>= bVisible;
434                         }
435                     }
436                 }
437                 catch ( Exception& )
438                 {
439                 }
440 
441                 // Check if we have to enable/disable "Reset" menu item
442                 if ( bContextSensitive && !bVisible )
443                     m_bResetActive = sal_True;
444 
445             }
446 
447             if (( aUIName.getLength() > 0 ) && ( !bHideFromMenu ))
448             {
449                 ToolBarEntry aTbEntry;
450                 aTbEntry.aUIName = aUIName;
451                 aTbEntry.aCommand = pIter->first;
452                 aTbEntry.bVisible = xLayoutManager->isElementVisible( pIter->first );
453                 aTbEntry.bContextSensitive = bContextSensitive;
454                 aTbEntry.pCollatorWrapper = m_aIntlWrapper.getCaseCollator();
455                 aSortedTbs.push_back( aTbEntry );
456             }
457             pIter++;
458         }
459 
460         // sort toolbars
461         std::sort( aSortedTbs.begin(), aSortedTbs.end(), CompareToolBarEntry );
462 
463         sal_Int16 nIndex( 1 );
464         const sal_uInt32 nCount = aSortedTbs.size();
465         for ( sal_uInt32 i = 0; i < nCount; i++ )
466         {
467             sal_uInt16 nItemCount = m_xPopupMenu->getItemCount();
468             m_xPopupMenu->insertItem( nIndex, aSortedTbs[i].aUIName, css::awt::MenuItemStyle::CHECKABLE, nItemCount );
469             if ( aSortedTbs[i].bVisible )
470                 m_xPopupMenu->checkItem( nIndex, sal_True );
471 
472             {
473                 vos::OGuard	aGuard( Application::GetSolarMutex() );
474                 VCLXPopupMenu* pXPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( m_xPopupMenu );
475                 PopupMenu*     pVCLPopupMenu = (PopupMenu *)pXPopupMenu->GetMenu();
476 
477                 pVCLPopupMenu->SetUserValue( nIndex, sal_uIntPtr( aSortedTbs[i].bContextSensitive ? 1L : 0L ));
478             }
479 
480             // use VCL popup menu pointer to set vital information that are not part of the awt implementation
481             rtl::OUStringBuffer aStrBuf( aStaticCmdPart );
482 
483             sal_Int32 n = aSortedTbs[i].aCommand.lastIndexOf( '/' );
484             if (( n > 0 ) && (( n+1 ) < aSortedTbs[i].aCommand.getLength() ))
485                 aStrBuf.append( aSortedTbs[i].aCommand.copy( n+1 ));
486 
487             rtl::OUString aCmd( aStrBuf.makeStringAndClear() );
488 
489             // Store complete uno-command so it can also be dispatched. This is necessary to support
490             // the test tool!
491 		    rPopupMenu->setCommand( nIndex, aCmd );
492             ++nIndex;
493         }
494 
495         // Create commands for non-toolbars
496         if ( m_aModuleIdentifier.equalsAscii( "com.sun.star.text.TextDocument" ) ||
497              m_aModuleIdentifier.equalsAscii( "com.sun.star.text.WebDocument" ) ||
498              m_aModuleIdentifier.equalsAscii( "com.sun.star.text.GlobalDocument" ) ||
499              m_aModuleIdentifier.equalsAscii( "com.sun.star.drawing.DrawingDocument" ) ||
500              m_aModuleIdentifier.equalsAscii( "com.sun.star.presentation.PresentationDocument" ) ||
501              m_aModuleIdentifier.equalsAscii( "com.sun.star.sheet.SpreadsheetDocument" ))
502         {
503             addCommand( m_xPopupMenu, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CMD_HYPERLINKBAR )), aEmptyString );
504             if ( m_aModuleIdentifier.equalsAscii( "com.sun.star.drawing.DrawingDocument" ) ||
505                  m_aModuleIdentifier.equalsAscii( "com.sun.star.presentation.PresentationDocument" ))
506                 addCommand( m_xPopupMenu, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CMD_COLORBAR )), aEmptyString );
507             else if ( m_aModuleIdentifier.equalsAscii( "com.sun.star.sheet.SpreadsheetDocument" ))
508                 addCommand( m_xPopupMenu, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CMD_INPUTLINEBAR )), aEmptyString );
509             else
510                 addCommand( m_xPopupMenu, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CMD_FORMULABAR )), aEmptyString );
511         }
512 
513         sal_Bool          bAddCommand( sal_True );
514         SvtCommandOptions aCmdOptions;
515         rtl::OUString     aConfigureToolbar( RTL_CONSTASCII_USTRINGPARAM( CONFIGURE_TOOLBARS ));
516 
517         if ( aCmdOptions.HasEntries( SvtCommandOptions::CMDOPTION_DISABLED ))
518         {
519             if ( aCmdOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED,
520                                      rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CONFIGURE_TOOLBARS_CMD ))))
521                 bAddCommand = sal_False;
522         }
523 
524         if ( bAddCommand )
525         {
526             // Create command for configure
527             if ( m_xPopupMenu->getItemCount() > 0 )
528             {
529                 sal_uInt16        nItemCount = m_xPopupMenu->getItemCount();
530                 m_xPopupMenu->insertSeparator( nItemCount+1 );
531             }
532 
533             addCommand( m_xPopupMenu, aConfigureToolbar, aEmptyString );
534         }
535 
536         // Add separator if no configure has been added
537         if ( !bAddCommand )
538         {
539             // Create command for configure
540             if ( m_xPopupMenu->getItemCount() > 0 )
541             {
542                 sal_uInt16        nItemCount = m_xPopupMenu->getItemCount();
543                 m_xPopupMenu->insertSeparator( nItemCount+1 );
544             }
545         }
546 
547         String aLabelStr = String( FwkResId( STR_RESTORE_TOOLBARS ));
548         rtl::OUString aRestoreCmd( RTL_CONSTASCII_USTRINGPARAM( CMD_RESTOREVISIBILITY ));
549         addCommand( m_xPopupMenu, aRestoreCmd, aLabelStr );
550     }
551 }
552 
553 // XEventListener
disposing(const EventObject &)554 void SAL_CALL ToolbarsMenuController::disposing( const EventObject& ) throw ( RuntimeException )
555 {
556     Reference< css::awt::XMenuListener > xHolder(( OWeakObject *)this, UNO_QUERY );
557 
558     osl::MutexGuard aLock( m_aMutex );
559     m_xFrame.clear();
560     m_xDispatch.clear();
561     m_xDocCfgMgr.clear();
562     m_xModuleCfgMgr.clear();
563     m_xServiceManager.clear();
564 
565     if ( m_xPopupMenu.is() )
566         m_xPopupMenu->removeMenuListener( Reference< css::awt::XMenuListener >(( OWeakObject *)this, UNO_QUERY ));
567     m_xPopupMenu.clear();
568 }
569 
570 // XStatusListener
statusChanged(const FeatureStateEvent & Event)571 void SAL_CALL ToolbarsMenuController::statusChanged( const FeatureStateEvent& Event ) throw ( RuntimeException )
572 {
573     rtl::OUString aFeatureURL( Event.FeatureURL.Complete );
574 
575     // All other status events will be processed here
576     sal_Bool bSetCheckmark      = sal_False;
577 	sal_Bool bCheckmark			= sal_False;
578 
579     osl::ClearableMutexGuard aLock( m_aMutex );
580     Reference< css::awt::XPopupMenu > xPopupMenu( m_xPopupMenu );
581     aLock.clear();
582 
583 	if ( xPopupMenu.is() )
584     {
585         vos::OGuard	aGuard( Application::GetSolarMutex() );
586         VCLXPopupMenu* pXPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( xPopupMenu );
587         PopupMenu*     pVCLPopupMenu = (PopupMenu *)pXPopupMenu->GetMenu();
588 
589         for ( sal_uInt16 i = 0; i < pVCLPopupMenu->GetItemCount(); i++ )
590         {
591             sal_uInt16 nId = pVCLPopupMenu->GetItemId( i );
592             if ( nId == 0 )
593                 continue;
594 
595             rtl::OUString aCmd = pVCLPopupMenu->GetItemCommand( nId );
596             if ( aCmd == aFeatureURL )
597             {
598                 // Enable/disable item
599                 pVCLPopupMenu->EnableItem( nId, Event.IsEnabled );
600 
601                 // Checkmark
602                 if ( Event.State >>= bCheckmark )
603 				    bSetCheckmark = sal_True;
604 
605                 if ( bSetCheckmark )
606                     pVCLPopupMenu->CheckItem( nId, bCheckmark );
607                 else
608                 {
609                     rtl::OUString aItemText;
610 
611                     if ( Event.State >>= aItemText )
612                         pVCLPopupMenu->SetItemText( nId, aItemText );
613                 }
614             }
615         }
616     }
617 }
618 
619 // XMenuListener
itemSelected(const css::awt::MenuEvent & rEvent)620 void SAL_CALL ToolbarsMenuController::itemSelected( const css::awt::MenuEvent& rEvent ) throw (RuntimeException)
621 {
622     Reference< css::awt::XPopupMenu >   xPopupMenu;
623     Reference< XMultiServiceFactory >   xServiceManager;
624     Reference< XURLTransformer >        xURLTransformer;
625     Reference< XFrame >                 xFrame;
626     Reference< XNameAccess >            xPersistentWindowState;
627 
628     osl::ClearableMutexGuard aLock( m_aMutex );
629     xPopupMenu             = m_xPopupMenu;
630     xServiceManager        = m_xServiceManager;
631     xURLTransformer        = m_xURLTransformer;
632     xFrame                 = m_xFrame;
633     xPersistentWindowState = m_xPersistentWindowState;
634     aLock.clear();
635 
636     if ( xPopupMenu.is() )
637     {
638         VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXPopupMenu::GetImplementation( xPopupMenu );
639         if ( pPopupMenu )
640         {
641             vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
642             PopupMenu* pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu();
643 
644             rtl::OUString aCmd( pVCLPopupMenu->GetItemCommand( rEvent.MenuId ));
645             if ( aCmd.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STATIC_INTERNAL_CMD_PART ))) == 0 )
646             {
647                 // Command to restore the visibility of all context sensitive toolbars
648                 Reference< XNameReplace > xNameReplace( xPersistentWindowState, UNO_QUERY );
649                 if ( xPersistentWindowState.is() && xNameReplace.is() )
650                 {
651                     try
652                     {
653                         Sequence< rtl::OUString > aElementNames = xPersistentWindowState->getElementNames();
654                         sal_Int32 nCount = aElementNames.getLength();
655                         bool      bRefreshToolbars( false );
656 
657                         for ( sal_Int32 i = 0; i < nCount; i++ )
658                         {
659                             try
660                             {
661                                 rtl::OUString aElementName = aElementNames[i];
662                                 Sequence< PropertyValue > aWindowState;
663 
664                                 if ( xPersistentWindowState->getByName( aElementName ) >>= aWindowState )
665                                 {
666                                     sal_Bool  bVisible( sal_False );
667                                     sal_Bool  bContextSensitive( sal_False );
668                                     sal_Int32 nVisibleIndex( -1 );
669                                     for ( sal_Int32 j = 0; j < aWindowState.getLength(); j++ )
670                                     {
671                                         if ( aWindowState[j].Name.equalsAscii( WINDOWSTATE_PROPERTY_VISIBLE ))
672                                         {
673                                             aWindowState[j].Value >>= bVisible;
674                                             nVisibleIndex = j;
675                                         }
676                                         else if ( aWindowState[j].Name.equalsAscii( WINDOWSTATE_PROPERTY_CONTEXT ))
677                                             aWindowState[j].Value >>= bContextSensitive;
678                                     }
679 
680                                     if ( !bVisible && bContextSensitive && nVisibleIndex >= 0 )
681                                     {
682                                         // Default is: Every context sensitive toolbar is visible
683                                         aWindowState[nVisibleIndex].Value <<= sal_True;
684                                         xNameReplace->replaceByName( aElementName, makeAny( aWindowState ));
685                                         bRefreshToolbars = true;
686                                     }
687                                 }
688                             }
689                             catch ( NoSuchElementException& )
690                             {
691                             }
692                         }
693 
694                         if ( bRefreshToolbars )
695                         {
696                             Reference< XLayoutManager > xLayoutManager( getLayoutManagerFromFrame( xFrame ));
697                             if ( xLayoutManager.is() )
698                             {
699                                 Reference< XPropertySet > xPropSet( xLayoutManager, UNO_QUERY );
700                                 if ( xPropSet.is() )
701                                 {
702                                     try
703                                     {
704                                         xPropSet->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RefreshContextToolbarVisibility" )), makeAny( sal_True ));
705                                     }
706                                     catch ( RuntimeException& )
707                                     {
708                                     }
709                                     catch ( Exception& )
710                                     {
711                                     }
712                                 }
713                             }
714                             RefreshToolbars( xFrame );
715                         }
716                     }
717                     catch ( RuntimeException& )
718                     {
719                         throw;
720                     }
721                     catch ( Exception& )
722                     {
723                     }
724                 }
725             }
726             else if ( aCmd.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STATIC_CMD_PART ))) < 0 )
727             {
728                 URL                     aTargetURL;
729                 Sequence<PropertyValue>	aArgs;
730 
731                 aTargetURL.Complete = aCmd;
732                 xURLTransformer->parseStrict( aTargetURL );
733 		        Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
734                 if ( xDispatchProvider.is() )
735                 {
736 		            Reference< XDispatch > xDispatch = xDispatchProvider->queryDispatch(
737 														    aTargetURL, ::rtl::OUString(), 0 );
738 
739                     ExecuteInfo* pExecuteInfo = new ExecuteInfo;
740                     pExecuteInfo->xDispatch     = xDispatch;
741                     pExecuteInfo->aTargetURL    = aTargetURL;
742                     pExecuteInfo->aArgs         = aArgs;
743                     if(::comphelper::UiEventsLogger::isEnabled()) //#i88653#
744                         UiEventLogHelper(::rtl::OUString::createFromAscii("ToolbarsMenuController")).log(m_xServiceManager, m_xFrame, aTargetURL, aArgs);
745                     Application::PostUserEvent( STATIC_LINK(0, ToolbarsMenuController, ExecuteHdl_Impl), pExecuteInfo );
746                 }
747             }
748             else
749             {
750                 Reference< XLayoutManager > xLayoutManager( getLayoutManagerFromFrame( xFrame ));
751                 if ( xLayoutManager.is() )
752                 {
753                     // Extract toolbar name from the combined uno-command.
754                     sal_Int32 nIndex = aCmd.indexOf( '=' );
755                     if (( nIndex > 0 ) && (( nIndex+1 ) < aCmd.getLength() ))
756                     {
757                         rtl::OUStringBuffer aBuf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STATIC_PRIVATE_TB_RESOURCE )));
758                         aBuf.append( aCmd.copy( nIndex+1 ));
759 
760                         sal_Bool      bShow( !pVCLPopupMenu->IsItemChecked( rEvent.MenuId ));
761                         rtl::OUString aToolBarResName( aBuf.makeStringAndClear() );
762                         if ( bShow )
763                         {
764                             xLayoutManager->createElement( aToolBarResName );
765                             xLayoutManager->showElement( aToolBarResName );
766                         }
767                         else
768                         {
769                             // closing means:
770                             // hide and destroy element
771                             xLayoutManager->hideElement( aToolBarResName );
772                             xLayoutManager->destroyElement( aToolBarResName );
773                         }
774                     }
775                 }
776             }
777         }
778     }
779 }
780 
itemActivated(const css::awt::MenuEvent &)781 void SAL_CALL ToolbarsMenuController::itemActivated( const css::awt::MenuEvent& ) throw (RuntimeException)
782 {
783     std::vector< rtl::OUString >   aCmdVector;
784     Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
785     Reference< XURLTransformer >   xURLTransformer( m_xURLTransformer );
786     {
787         osl::MutexGuard aLock( m_aMutex );
788         fillPopupMenu( m_xPopupMenu );
789         aCmdVector = m_aCommandVector;
790     }
791 
792     // Update status for all commands inside our toolbars popup menu
793     const sal_uInt32 nCount = aCmdVector.size();
794     for ( sal_uInt32 i = 0; i < nCount; i++ )
795     {
796         bool bInternal = ( aCmdVector[i].indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STATIC_INTERNAL_CMD_PART ))) == 0);
797 
798         if ( !bInternal )
799         {
800             URL aTargetURL;
801             aTargetURL.Complete = aCmdVector[i];
802             xURLTransformer->parseStrict( aTargetURL );
803             Reference< XDispatch > xDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 );
804             if ( xDispatch.is() )
805             {
806 			    xDispatch->addStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL );
807 			    xDispatch->removeStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL );
808             }
809         }
810         else if ( aCmdVector[i].equalsAscii( CMD_RESTOREVISIBILITY ))
811         {
812             // Special code to determine the enable/disable state of this command
813             FeatureStateEvent aFeatureStateEvent;
814             aFeatureStateEvent.FeatureURL.Complete = aCmdVector[i];
815             aFeatureStateEvent.IsEnabled = isContextSensitiveToolbarNonVisible();
816             statusChanged( aFeatureStateEvent );
817         }
818     }
819 }
820 
821 // XPopupMenuController
setPopupMenu(const Reference<css::awt::XPopupMenu> & xPopupMenu)822 void SAL_CALL ToolbarsMenuController::setPopupMenu( const Reference< css::awt::XPopupMenu >& xPopupMenu ) throw ( RuntimeException )
823 {
824     osl::MutexGuard aLock( m_aMutex );
825 
826     throwIfDisposed();
827 
828     if ( m_xFrame.is() && !m_xPopupMenu.is() )
829     {
830         // Create popup menu on demand
831         vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
832 
833         m_xPopupMenu = xPopupMenu;
834 	    m_xPopupMenu->addMenuListener( Reference< css::awt::XMenuListener >( (OWeakObject*)this, UNO_QUERY ));
835         fillPopupMenu( m_xPopupMenu );
836     }
837 }
838 
839 // XInitialization
initialize(const Sequence<Any> & aArguments)840 void SAL_CALL ToolbarsMenuController::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException )
841 {
842     osl::MutexGuard aLock( m_aMutex );
843     sal_Bool bInitialized( m_bInitialized );
844     if ( !bInitialized )
845     {
846 		svt::PopupMenuControllerBase::initialize(aArguments);
847 
848         if ( m_bInitialized )
849         {
850             Reference< XModuleManager > xModuleManager( m_xServiceManager->createInstance(
851                                                             SERVICENAME_MODULEMANAGER ),
852                                                         UNO_QUERY );
853             Reference< XNameAccess > xPersistentWindowStateSupplier( m_xServiceManager->createInstance(
854                                                                         SERVICENAME_WINDOWSTATECONFIGURATION ),
855                                                                      UNO_QUERY );
856 
857             // Retrieve persistent window state reference for our module
858             if ( xPersistentWindowStateSupplier.is() && xModuleManager.is() )
859             {
860                 rtl::OUString aModuleIdentifier;
861                 try
862                 {
863                     aModuleIdentifier = xModuleManager->identify( m_xFrame );
864                     xPersistentWindowStateSupplier->getByName( aModuleIdentifier ) >>= m_xPersistentWindowState;
865 
866                     Reference< XModuleUIConfigurationManagerSupplier > xModuleCfgSupplier;
867                     if ( m_xServiceManager.is() )
868                         xModuleCfgSupplier = Reference< XModuleUIConfigurationManagerSupplier >(
869                             m_xServiceManager->createInstance( SERVICENAME_MODULEUICONFIGURATIONMANAGERSUPPLIER ), UNO_QUERY );
870                     m_xModuleCfgMgr = xModuleCfgSupplier->getUIConfigurationManager( aModuleIdentifier );
871 
872                     Reference< XController > xController = m_xFrame->getController();
873                     Reference< XModel >      xModel;
874                     if ( xController.is() )
875                         xModel = xController->getModel();
876                     if ( xModel.is() )
877                     {
878                         Reference< XUIConfigurationManagerSupplier > xUIConfigurationManagerSupplier( xModel, UNO_QUERY );
879                         if ( xUIConfigurationManagerSupplier.is() )
880                             m_xDocCfgMgr = xUIConfigurationManagerSupplier->getUIConfigurationManager();
881                     }
882                     m_aModuleIdentifier = aModuleIdentifier;
883                 }
884                 catch ( Exception& )
885                 {
886                 }
887             }
888         }
889     }
890 }
891 
IMPL_STATIC_LINK_NOINSTANCE(ToolbarsMenuController,ExecuteHdl_Impl,ExecuteInfo *,pExecuteInfo)892 IMPL_STATIC_LINK_NOINSTANCE( ToolbarsMenuController, ExecuteHdl_Impl, ExecuteInfo*, pExecuteInfo )
893 {
894     try
895     {
896         // Asynchronous execution as this can lead to our own destruction!
897         // Framework can recycle our current frame and the layout manager disposes all user interface
898         // elements if a component gets detached from its frame!
899         if ( pExecuteInfo->xDispatch.is() )
900         {
901             pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs );
902         }
903     }
904     catch ( Exception& )
905     {
906     }
907 
908     delete pExecuteInfo;
909     return 0;
910 }
911 
912 }
913