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