1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_framework.hxx" 26 #include <uielement/toolbarsmenucontroller.hxx> 27 28 #include <algorithm> 29 30 //_________________________________________________________________________________________________________________ 31 // my own includes 32 //_________________________________________________________________________________________________________________ 33 #include <threadhelp/resetableguard.hxx> 34 #include "services.h" 35 #ifndef __FRAMEWORK_CLASSES_RESOURCE_HRC_ 36 #include <classes/resource.hrc> 37 #endif 38 #include <classes/fwkresid.hxx> 39 #include <uiconfiguration/windowstateconfiguration.hxx> 40 #include <framework/imageproducer.hxx> 41 #include <framework/sfxhelperfunctions.hxx> 42 43 //_________________________________________________________________________________________________________________ 44 // interface includes 45 //_________________________________________________________________________________________________________________ 46 #include <com/sun/star/awt/XDevice.hpp> 47 #include <com/sun/star/beans/PropertyValue.hpp> 48 #include <com/sun/star/awt/MenuItemStyle.hpp> 49 #include <com/sun/star/frame/XDispatchProvider.hpp> 50 #include <com/sun/star/container/XNameContainer.hpp> 51 #include <com/sun/star/beans/XPropertySet.hpp> 52 #include <com/sun/star/frame/XLayoutManager.hpp> 53 #include <com/sun/star/ui/XUIElementSettings.hpp> 54 #include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp> 55 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp> 56 #include <com/sun/star/ui/UIElementType.hpp> 57 58 //_________________________________________________________________________________________________________________ 59 // includes of other projects 60 //_________________________________________________________________________________________________________________ 61 62 #ifndef _VCL_MENU_HXX_ 63 #include <vcl/menu.hxx> 64 #endif 65 #include <vcl/svapp.hxx> 66 #include <vcl/i18nhelp.hxx> 67 #include <vcl/image.hxx> 68 #include <tools/urlobj.hxx> 69 #include <rtl/ustrbuf.hxx> 70 #ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ 71 #include <toolkit/unohlp.hxx> 72 #endif 73 #include <vcl/window.hxx> 74 #include <svtools/menuoptions.hxx> 75 #include <unotools/cmdoptions.hxx> 76 #include <dispatch/uieventloghelper.hxx> 77 #include <rtl/logfile.hxx> 78 79 //_________________________________________________________________________________________________________________ 80 // Defines 81 //_________________________________________________________________________________________________________________ 82 // 83 84 using namespace ::com::sun::star; 85 using namespace ::com::sun::star::uno; 86 using namespace ::com::sun::star::lang; 87 using namespace ::com::sun::star::frame; 88 using namespace ::com::sun::star::beans; 89 using namespace ::com::sun::star::util; 90 using namespace ::com::sun::star::container; 91 using namespace ::com::sun::star::frame; 92 using namespace ::com::sun::star::ui; 93 94 static const char CONFIGURE_TOOLBARS_CMD[] = "ConfigureDialog"; 95 static const char CONFIGURE_TOOLBARS[] = ".uno:ConfigureDialog"; 96 static const char CMD_COLORBAR[] = ".uno:ColorControl"; 97 static const char CMD_HYPERLINKBAR[] = ".uno:InsertHyperlink"; 98 static const char CMD_FORMULABAR[] = ".uno:InsertFormula"; 99 static const char CMD_INPUTLINEBAR[] = ".uno:InputLineVisible"; 100 static const char CMD_RESTOREVISIBILITY[] = ".cmd:RestoreVisibility"; 101 static const char ITEM_DESCRIPTOR_RESOURCEURL[] = "ResourceURL"; 102 static const char ITEM_DESCRIPTOR_UINAME[] = "UIName"; 103 static const char STATIC_PRIVATE_TB_RESOURCE[] = "private:resource/toolbar/"; 104 105 static const char STATIC_CMD_PART[] = ".uno:AvailableToolbars?Toolbar:string="; 106 static const char STATIC_INTERNAL_CMD_PART[] = ".cmd:"; 107 108 namespace framework 109 { 110 111 typedef std::hash_map< rtl::OUString, rtl::OUString, 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 122 sal_Bool CompareToolBarEntry( const ToolBarEntry& aOne, const ToolBarEntry& aTwo ) 123 { 124 sal_Int32 nComp = aOne.pCollatorWrapper->compareString( aOne.aUIName, aTwo.aUIName ); 125 126 if ( nComp < 0 ) 127 return sal_True; 128 else if ( nComp > 0 ) 129 return sal_False; 130 else 131 return sal_False; 132 } 133 134 Reference< XLayoutManager > getLayoutManagerFromFrame( const Reference< XFrame >& rFrame ) 135 { 136 Reference< XPropertySet > xPropSet( rFrame, UNO_QUERY ); 137 Reference< XLayoutManager > xLayoutManager; 138 139 try 140 { 141 xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" ))) >>= xLayoutManager; 142 } 143 catch ( UnknownPropertyException& ) 144 { 145 } 146 147 return xLayoutManager; 148 } 149 150 struct ToolBarInfo 151 { 152 rtl::OUString aToolBarResName; 153 rtl::OUString aToolBarUIName; 154 }; 155 156 DEFINE_XSERVICEINFO_MULTISERVICE ( ToolbarsMenuController , 157 OWeakObject , 158 SERVICENAME_POPUPMENUCONTROLLER , 159 IMPLEMENTATIONNAME_TOOLBARSMENUCONTROLLER 160 ) 161 162 DEFINE_INIT_SERVICE ( ToolbarsMenuController, {} ) 163 164 ToolbarsMenuController::ToolbarsMenuController( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ) : 165 svt::PopupMenuControllerBase( xServiceManager ), 166 m_aPropUIName( RTL_CONSTASCII_USTRINGPARAM( "UIName" )), 167 m_aPropResourceURL( RTL_CONSTASCII_USTRINGPARAM( "ResourceURL" )), 168 m_bModuleIdentified( sal_False ), 169 m_bResetActive( sal_False ), 170 m_aIntlWrapper( xServiceManager, Application::GetSettings().GetLocale() ) 171 { 172 } 173 174 ToolbarsMenuController::~ToolbarsMenuController() 175 { 176 } 177 178 void ToolbarsMenuController::addCommand( 179 Reference< css::awt::XPopupMenu >& rPopupMenu, const rtl::OUString& rCommandURL, const rtl::OUString& rLabel ) 180 { 181 sal_uInt16 nItemId = m_xPopupMenu->getItemCount()+1; 182 183 rtl::OUString aLabel; 184 if ( rLabel.getLength() == 0 ) 185 aLabel = getUINameFromCommand( rCommandURL ); 186 else 187 aLabel = rLabel; 188 189 rPopupMenu->insertItem( nItemId, aLabel, 0, nItemId ); 190 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 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 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 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 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 366 sal_Bool ToolbarsMenuController::isContextSensitiveToolbarNonVisible() 367 { 368 return m_bResetActive; 369 } 370 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 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 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 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 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 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 840 void SAL_CALL ToolbarsMenuController::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException ) 841 { 842 osl::MutexGuard aLock( m_aMutex ); 843 sal_Bool bInitalized( m_bInitialized ); 844 if ( !bInitalized ) 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 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