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/addonstoolbarmanager.hxx> 31 #include <uielement/toolbarmerger.hxx> 32 33 //_________________________________________________________________________________________________________________ 34 // my own includes 35 //_________________________________________________________________________________________________________________ 36 37 38 #ifndef __FRAMEWORK_UIELEMENT_TOOLBAR_HXX 39 #include <uielement/toolbar.hxx> 40 #endif 41 #ifndef __FRAMEWORK_UIELEMENT_GENERICTOOLBARCONTROLLER_HXX 42 #include <uielement/generictoolbarcontroller.hxx> 43 #endif 44 #include <threadhelp/resetableguard.hxx> 45 #include "services.h" 46 #include <framework/imageproducer.hxx> 47 #include <framework/sfxhelperfunctions.hxx> 48 #include <classes/fwkresid.hxx> 49 #ifndef __FRAMEWORK_CLASES_RESOURCE_HRC_ 50 #include <classes/resource.hrc> 51 #endif 52 #include <framework/addonsoptions.hxx> 53 #ifndef __FRAMEWORK_UIELEMENT_COMBOBOXTOOLBARCONTROLLER_HXX 54 #include <uielement/comboboxtoolbarcontroller.hxx> 55 #endif 56 #ifndef __FRAMEWORK_UIELEMENT_IMAGEBUTTONTOOLBARCONTROLLER_HXX 57 #include <uielement/imagebuttontoolbarcontroller.hxx> 58 #endif 59 #ifndef __FRAMEWORK_UIELEMENT_TOGGLEBUTTONTOOLBARCONTROLLER_HXX 60 #include <uielement/togglebuttontoolbarcontroller.hxx> 61 #endif 62 #include <uielement/buttontoolbarcontroller.hxx> 63 #include <uielement/spinfieldtoolbarcontroller.hxx> 64 #include <uielement/edittoolbarcontroller.hxx> 65 #include <uielement/dropdownboxtoolbarcontroller.hxx> 66 #include <uielement/toolbarmerger.hxx> 67 68 //_________________________________________________________________________________________________________________ 69 // interface includes 70 //_________________________________________________________________________________________________________________ 71 #include <com/sun/star/ui/ItemType.hpp> 72 #include <com/sun/star/frame/XToolbarController.hpp> 73 #include <com/sun/star/frame/XDispatchProvider.hpp> 74 #ifndef _COM_SUN_STAR_BEANS_XLAYOUTMANAGER_HPP_ 75 #include <com/sun/star/beans/XPropertySet.hpp> 76 #endif 77 #include <com/sun/star/lang/XServiceInfo.hpp> 78 #include <com/sun/star/frame/XLayoutManager.hpp> 79 #ifndef _COM_SUN_STAR_UI_XDOCKINGAREA_HPP_ 80 #include <com/sun/star/ui/DockingArea.hpp> 81 #endif 82 #include <com/sun/star/lang/XMultiComponentFactory.hpp> 83 84 //_________________________________________________________________________________________________________________ 85 // other includes 86 //_________________________________________________________________________________________________________________ 87 #include <svtools/imgdef.hxx> 88 #include <svtools/toolboxcontroller.hxx> 89 #ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ 90 #include <toolkit/unohlp.hxx> 91 #endif 92 93 #include <svtools/miscopt.hxx> 94 #include <vcl/svapp.hxx> 95 #include <vcl/menu.hxx> 96 #include <vcl/syswin.hxx> 97 #include <vcl/taskpanelist.hxx> 98 99 //_________________________________________________________________________________________________________________ 100 // namespaces 101 //_________________________________________________________________________________________________________________ 102 103 using namespace ::com::sun::star; 104 using namespace ::com::sun::star::awt; 105 using namespace ::com::sun::star::beans; 106 using namespace ::com::sun::star::uno; 107 using namespace ::com::sun::star::lang; 108 using namespace ::com::sun::star::frame; 109 using namespace ::com::sun::star::util; 110 using namespace ::com::sun::star::container; 111 using namespace ::com::sun::star::frame; 112 using namespace ::com::sun::star::ui; 113 114 namespace framework 115 { 116 117 static const char TOOLBOXITEM_SEPARATOR_STR[] = "private:separator"; 118 static const sal_uInt16 TOOLBOXITEM_SEPARATOR_STR_LEN = sizeof( TOOLBOXITEM_SEPARATOR_STR )-1; 119 120 AddonsToolBarManager::AddonsToolBarManager( const Reference< XMultiServiceFactory >& rServiceManager, 121 const Reference< XFrame >& rFrame, 122 const rtl::OUString& rResourceName, 123 ToolBar* pToolBar ) : 124 ToolBarManager( rServiceManager, rFrame, rResourceName, pToolBar ) 125 { 126 // Configuration data is retrieved from non-writable configuration layer. Therefor we 127 // must disable some menu entries. 128 m_bCanBeCustomized = sal_False; 129 130 m_pToolBar->SetMenuType( TOOLBOX_MENUTYPE_CLIPPEDITEMS ); 131 m_pToolBar->SetSelectHdl( LINK( this, AddonsToolBarManager, Select) ); 132 m_pToolBar->SetActivateHdl( LINK( this, AddonsToolBarManager, Activate) ); 133 m_pToolBar->SetDeactivateHdl( LINK( this, AddonsToolBarManager, Deactivate) ); 134 m_pToolBar->SetClickHdl( LINK( this, AddonsToolBarManager, Click ) ); 135 m_pToolBar->SetDoubleClickHdl( LINK( this, AddonsToolBarManager, DoubleClick ) ); 136 m_pToolBar->SetCommandHdl( LINK( this, AddonsToolBarManager, Command ) ); 137 m_pToolBar->SetStateChangedHdl( LINK( this, AddonsToolBarManager, StateChanged ) ); 138 m_pToolBar->SetDataChangedHdl( LINK( this, AddonsToolBarManager, DataChanged ) ); 139 } 140 141 AddonsToolBarManager::~AddonsToolBarManager() 142 { 143 } 144 145 static sal_Bool IsCorrectContext( const ::rtl::OUString& rModuleIdentifier, const ::rtl::OUString& aContextList ) 146 { 147 if ( aContextList.getLength() == 0 ) 148 return sal_True; 149 150 if ( rModuleIdentifier.getLength() > 0 ) 151 { 152 sal_Int32 nIndex = aContextList.indexOf( rModuleIdentifier ); 153 return ( nIndex >= 0 ); 154 } 155 156 return sal_False; 157 } 158 159 static Image RetrieveImage( Reference< com::sun::star::frame::XFrame >& rFrame, 160 const rtl::OUString& aImageId, 161 const rtl::OUString& aURL, 162 sal_Bool bBigImage, 163 sal_Bool bHiContrast ) 164 { 165 Image aImage; 166 167 if ( aImageId.getLength() > 0 ) 168 { 169 aImage = framework::AddonsOptions().GetImageFromURL( aImageId, bBigImage, bHiContrast ); 170 if ( !!aImage ) 171 return aImage; 172 else 173 aImage = GetImageFromURL( rFrame, aImageId, bBigImage, bHiContrast ); 174 if ( !!aImage ) 175 return aImage; 176 } 177 178 aImage = framework::AddonsOptions().GetImageFromURL( aURL, bBigImage, bHiContrast ); 179 if ( !aImage ) 180 aImage = GetImageFromURL( rFrame, aImageId, bBigImage, bHiContrast ); 181 182 return aImage; 183 } 184 185 // XComponent 186 void SAL_CALL AddonsToolBarManager::dispose() throw( RuntimeException ) 187 { 188 Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY ); 189 190 { 191 // Remove addon specific data from toolbar items. 192 ResetableGuard aGuard( m_aLock ); 193 for ( sal_uInt16 n = 0; n < m_pToolBar->GetItemCount(); n++ ) 194 { 195 sal_uInt16 nId( m_pToolBar->GetItemId( n ) ); 196 197 if ( nId > 0 ) 198 { 199 AddonsParams* pRuntimeItemData = (AddonsParams*)m_pToolBar->GetItemData( nId ); 200 if ( pRuntimeItemData ) 201 delete pRuntimeItemData; 202 m_pToolBar->SetItemData( nId, NULL ); 203 } 204 } 205 } 206 207 // Base class will destroy our m_pToolBar member 208 ToolBarManager::dispose(); 209 } 210 211 bool AddonsToolBarManager::MenuItemAllowed( sal_uInt16 nId ) const 212 { 213 if (( nId == MENUITEM_TOOLBAR_VISIBLEBUTTON ) || 214 ( nId == MENUITEM_TOOLBAR_CUSTOMIZETOOLBAR )) 215 return false; 216 else 217 return true; 218 } 219 220 void AddonsToolBarManager::RefreshImages() 221 { 222 sal_Bool bBigImages( SvtMiscOptions().AreCurrentSymbolsLarge() ); 223 for ( sal_uInt16 nPos = 0; nPos < m_pToolBar->GetItemCount(); nPos++ ) 224 { 225 sal_uInt16 nId( m_pToolBar->GetItemId( nPos ) ); 226 227 if ( nId > 0 ) 228 { 229 ::rtl::OUString aCommandURL = m_pToolBar->GetItemCommand( nId ); 230 ::rtl::OUString aImageId; 231 AddonsParams* pRuntimeItemData = (AddonsParams*)m_pToolBar->GetItemData( nId ); 232 if ( pRuntimeItemData ) 233 aImageId = pRuntimeItemData->aImageId; 234 235 m_pToolBar->SetItemImage( nId, RetrieveImage( m_xFrame, 236 aImageId, 237 aCommandURL, 238 bBigImages, 239 m_bIsHiContrast )); 240 } 241 } 242 } 243 244 void AddonsToolBarManager::FillToolbar( const Sequence< Sequence< PropertyValue > >& rAddonToolbar ) 245 { 246 ResetableGuard aGuard( m_aLock ); 247 248 if ( m_bDisposed ) 249 return; 250 251 sal_uInt16 nId( 1 ); 252 253 RemoveControllers(); 254 255 m_pToolBar->Clear(); 256 m_aControllerMap.clear(); 257 258 ::rtl::OUString aModuleIdentifier; 259 try 260 { 261 Reference< XModuleManager > xModuleManager( 262 m_xServiceManager->createInstance( SERVICENAME_MODULEMANAGER ), UNO_QUERY_THROW ); 263 aModuleIdentifier = xModuleManager->identify( m_xFrame ); 264 } 265 catch ( Exception& ) 266 { 267 } 268 269 Reference< XMultiComponentFactory > xToolbarControllerFactory( m_xToolbarControllerRegistration, UNO_QUERY ); 270 Reference< XComponentContext > xComponentContext; 271 Reference< XPropertySet > xProps( m_xServiceManager, UNO_QUERY ); 272 273 if ( xProps.is() ) 274 xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xComponentContext; 275 276 sal_uInt32 nElements( 0 ); 277 sal_Bool bAppendSeparator( sal_False ); 278 Reference< XWindow > xToolbarWindow = VCLUnoHelper::GetInterface( m_pToolBar ); 279 for ( sal_uInt32 n = 0; n < (sal_uInt32)rAddonToolbar.getLength(); n++ ) 280 { 281 rtl::OUString aValueName; 282 283 rtl::OUString aURL; 284 rtl::OUString aTitle; 285 rtl::OUString aImageId; 286 rtl::OUString aContext; 287 rtl::OUString aTarget; 288 rtl::OUString aControlType; 289 sal_uInt16 nWidth( 0 ); 290 291 const Sequence< PropertyValue >& rSeq = rAddonToolbar[n]; 292 293 ToolBarMerger::ConvertSequenceToValues( rSeq, aURL, aTitle, aImageId, aTarget, aContext, aControlType, nWidth ); 294 295 if ( IsCorrectContext( aModuleIdentifier, aContext )) 296 { 297 if ( aURL.equalsAsciiL( TOOLBOXITEM_SEPARATOR_STR, TOOLBOXITEM_SEPARATOR_STR_LEN )) 298 { 299 sal_uInt16 nCount = m_pToolBar->GetItemCount(); 300 if ( nCount > 0 && ( m_pToolBar->GetItemType( nCount-1 ) != TOOLBOXITEM_SEPARATOR ) && nElements > 0 ) 301 { 302 nElements = 0; 303 m_pToolBar->InsertSeparator(); 304 } 305 } 306 else 307 { 308 sal_uInt16 nCount = m_pToolBar->GetItemCount(); 309 if ( bAppendSeparator && nCount > 0 && ( m_pToolBar->GetItemType( nCount-1 ) != TOOLBOXITEM_SEPARATOR )) 310 { 311 // We have to append a separator first if the last item is not a separator 312 m_pToolBar->InsertSeparator(); 313 } 314 bAppendSeparator = sal_False; 315 316 m_pToolBar->InsertItem( nId, aTitle ); 317 318 Image aImage = RetrieveImage( m_xFrame, aImageId, aURL, !m_bSmallSymbols, m_bIsHiContrast ); 319 if ( !!aImage ) 320 m_pToolBar->SetItemImage( nId, aImage ); 321 322 // Create TbRuntimeItemData to hold additional information we will need in the future 323 AddonsParams* pRuntimeItemData = new AddonsParams; 324 pRuntimeItemData->aImageId = aImageId; 325 pRuntimeItemData->aTarget = aTarget; 326 m_pToolBar->SetItemData( nId, pRuntimeItemData ); 327 m_pToolBar->SetItemCommand( nId, aURL ); 328 329 Reference< XStatusListener > xController; 330 331 sal_Bool bMustBeInit( sal_True ); 332 333 // Support external toolbar controller for add-ons! 334 if ( m_xToolbarControllerRegistration.is() && 335 m_xToolbarControllerRegistration->hasController( aURL, m_aModuleIdentifier )) 336 { 337 if ( xToolbarControllerFactory.is() ) 338 { 339 Sequence< Any > aArgs(5); 340 PropertyValue aPropValue; 341 342 aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ModuleName" )); 343 aPropValue.Value <<= m_aModuleIdentifier; 344 aArgs[0] <<= aPropValue; 345 aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" )); 346 aPropValue.Value <<= m_xFrame; 347 aArgs[1] <<= aPropValue; 348 aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ServiceManager" )); 349 aPropValue.Value <<= m_xServiceManager; 350 aArgs[2] <<= aPropValue; 351 aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ParentWindow" )); 352 aPropValue.Value <<= xToolbarWindow; 353 aArgs[3] <<= aPropValue; 354 aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ItemId" )); 355 aPropValue.Value = makeAny( sal_Int32( nId )); 356 aArgs[4] <<= aPropValue; 357 358 try 359 { 360 xController = Reference< XStatusListener >( xToolbarControllerFactory->createInstanceWithArgumentsAndContext( 361 aURL, aArgs, xComponentContext ), 362 UNO_QUERY ); 363 } 364 catch ( uno::Exception& ) 365 { 366 } 367 bMustBeInit = sal_False; // factory called init already! 368 } 369 } 370 else 371 { 372 ::cppu::OWeakObject* pController = 0; 373 374 pController = ToolBarMerger::CreateController( m_xServiceManager, m_xFrame, m_pToolBar, aURL, nId, nWidth, aControlType ); 375 xController = Reference< XStatusListener >( pController, UNO_QUERY ); 376 } 377 378 // insert controller to the map 379 m_aControllerMap[nId] = xController; 380 381 Reference< XInitialization > xInit( xController, UNO_QUERY ); 382 if ( xInit.is() && bMustBeInit ) 383 { 384 PropertyValue aPropValue; 385 Sequence< Any > aArgs( 3 ); 386 aPropValue.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" )); 387 aPropValue.Value <<= m_xFrame; 388 aArgs[0] <<= aPropValue; 389 aPropValue.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CommandURL" )); 390 aPropValue.Value <<= aURL; 391 aArgs[1] <<= aPropValue; 392 aPropValue.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ServiceManager" )); 393 aPropValue.Value <<= m_xServiceManager; 394 aArgs[2] <<= aPropValue; 395 try 396 { 397 xInit->initialize( aArgs ); 398 } 399 catch ( uno::Exception& ) 400 { 401 } 402 } 403 404 // Request a item window from the toolbar controller and set it at the VCL toolbar 405 Reference< XToolbarController > xTbxController( xController, UNO_QUERY ); 406 if ( xTbxController.is() && xToolbarWindow.is() ) 407 { 408 Reference< XWindow > xWindow = xTbxController->createItemWindow( xToolbarWindow ); 409 if ( xWindow.is() ) 410 { 411 Window* pItemWin = VCLUnoHelper::GetWindow( xWindow ); 412 if ( pItemWin ) 413 { 414 WindowType nType = pItemWin->GetType(); 415 if ( nType == WINDOW_LISTBOX || nType == WINDOW_MULTILISTBOX || nType == WINDOW_COMBOBOX ) 416 pItemWin->SetAccessibleName( m_pToolBar->GetItemText( nId ) ); 417 m_pToolBar->SetItemWindow( nId, pItemWin ); 418 } 419 } 420 } 421 422 // Notify controller implementation to its listeners. Controller is now useable from outside. 423 Reference< XUpdatable > xUpdatable( xController, UNO_QUERY ); 424 if ( xUpdatable.is() ) 425 { 426 try 427 { 428 xUpdatable->update(); 429 } 430 catch ( uno::Exception& ) 431 { 432 } 433 } 434 435 ++nId; 436 ++nElements; 437 } 438 } 439 } 440 441 AddFrameActionListener(); 442 } 443 444 IMPL_LINK( AddonsToolBarManager, Click, ToolBox*, EMPTYARG ) 445 { 446 if ( m_bDisposed ) 447 return 1; 448 449 sal_uInt16 nId( m_pToolBar->GetCurItemId() ); 450 ToolBarControllerMap::const_iterator pIter = m_aControllerMap.find( nId ); 451 if ( pIter != m_aControllerMap.end() ) 452 { 453 Reference< XToolbarController > xController( pIter->second, UNO_QUERY ); 454 455 if ( xController.is() ) 456 xController->click(); 457 } 458 459 return 1; 460 } 461 462 IMPL_LINK( AddonsToolBarManager, DoubleClick, ToolBox*, EMPTYARG ) 463 { 464 if ( m_bDisposed ) 465 return 1; 466 467 sal_uInt16 nId( m_pToolBar->GetCurItemId() ); 468 ToolBarControllerMap::const_iterator pIter = m_aControllerMap.find( nId ); 469 if ( pIter != m_aControllerMap.end() ) 470 { 471 Reference< XToolbarController > xController( pIter->second, UNO_QUERY ); 472 473 if ( xController.is() ) 474 xController->doubleClick(); 475 } 476 477 return 1; 478 } 479 480 IMPL_LINK( AddonsToolBarManager, Command, CommandEvent*, EMPTYARG ) 481 { 482 ResetableGuard aGuard( m_aLock ); 483 484 if ( m_bDisposed ) 485 return 1; 486 487 return 0; 488 } 489 490 IMPL_LINK( AddonsToolBarManager, Select, ToolBox*, EMPTYARG ) 491 { 492 if ( m_bDisposed ) 493 return 1; 494 495 sal_Int16 nKeyModifier( (sal_Int16)m_pToolBar->GetModifier() ); 496 sal_uInt16 nId( m_pToolBar->GetCurItemId() ); 497 ToolBarControllerMap::const_iterator pIter = m_aControllerMap.find( nId ); 498 if ( pIter != m_aControllerMap.end() ) 499 { 500 Reference< XToolbarController > xController( pIter->second, UNO_QUERY ); 501 502 if ( xController.is() ) 503 xController->execute( nKeyModifier ); 504 } 505 506 return 1; 507 } 508 509 IMPL_LINK( AddonsToolBarManager, Highlight, ToolBox*, EMPTYARG ) 510 { 511 return 1; 512 } 513 514 IMPL_LINK( AddonsToolBarManager, Activate, ToolBox*, EMPTYARG ) 515 { 516 return 1; 517 } 518 519 IMPL_LINK( AddonsToolBarManager, Deactivate, ToolBox*, EMPTYARG ) 520 { 521 return 1; 522 } 523 524 IMPL_LINK( AddonsToolBarManager, StateChanged, StateChangedType*, pStateChangedType ) 525 { 526 if ( *pStateChangedType == STATE_CHANGE_CONTROLBACKGROUND ) 527 { 528 // Check if we need to get new images for normal/high contrast mode 529 CheckAndUpdateImages(); 530 } 531 return 1; 532 } 533 534 IMPL_LINK( AddonsToolBarManager, DataChanged, DataChangedEvent*, pDataChangedEvent ) 535 { 536 if ((( pDataChangedEvent->GetType() == DATACHANGED_SETTINGS ) || 537 ( pDataChangedEvent->GetType() == DATACHANGED_DISPLAY )) && 538 ( pDataChangedEvent->GetFlags() & SETTINGS_STYLE )) 539 { 540 // Check if we need to get new images for normal/high contrast mode 541 CheckAndUpdateImages(); 542 } 543 544 for ( sal_uInt16 nPos = 0; nPos < m_pToolBar->GetItemCount(); ++nPos ) 545 { 546 const sal_uInt16 nId = m_pToolBar->GetItemId(nPos); 547 Window* pWindow = m_pToolBar->GetItemWindow( nId ); 548 if ( pWindow ) 549 { 550 const DataChangedEvent& rDCEvt( *pDataChangedEvent ); 551 pWindow->DataChanged( rDCEvt ); 552 } 553 } 554 555 return 1; 556 } 557 558 } 559 560