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