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_sfx2.hxx" 30 31 #ifdef SOLARIS 32 // HACK: prevent conflict between STLPORT and Workshop headers on Solaris 8 33 #include <ctime> 34 #endif 35 36 #include <string> // HACK: prevent conflict between STLPORT and Workshop includes 37 #include <com/sun/star/uno/Reference.h> 38 #include <com/sun/star/frame/XDispatch.hpp> 39 #include <com/sun/star/frame/XDispatchProvider.hpp> 40 #include <com/sun/star/frame/XFrame.hpp> 41 #include <com/sun/star/util/URL.hpp> 42 #include <com/sun/star/beans/PropertyValue.hpp> 43 #ifndef _UNOTOOLS_PROCESSFACTORY_HXX 44 #include <comphelper/processfactory.hxx> 45 #endif 46 #include <com/sun/star/util/XURLTransformer.hpp> 47 #ifndef _UNOTOOLS_PROCESSFACTORY_HXX 48 #include <comphelper/processfactory.hxx> 49 #endif 50 #include <tools/urlobj.hxx> 51 #include <svl/eitem.hxx> 52 #include <svl/stritem.hxx> 53 #include <svtools/imagemgr.hxx> 54 #include <svtools/menuoptions.hxx> 55 #include <framework/menuconfiguration.hxx> 56 #ifndef GCC 57 #endif 58 59 #include <sfx2/app.hxx> 60 #include <sfx2/sfx.hrc> 61 #include <sfx2/msgpool.hxx> 62 #include <sfx2/msg.hxx> 63 #include <sfx2/bindings.hxx> 64 #include <sfx2/dispatch.hxx> 65 #include "idpool.hxx" 66 #include "sfxtypes.hxx" 67 #include "virtmenu.hxx" 68 #include <sfx2/mnuitem.hxx> 69 #include <sfx2/tbxctrl.hxx> 70 #include "arrdecl.hxx" 71 #include <sfx2/module.hxx> 72 #include <sfx2/unoctitm.hxx> 73 #include <sfx2/viewfrm.hxx> 74 #include "sfx2/imgmgr.hxx" 75 #include "sfx2/imagemgr.hxx" 76 #include "sfx2/sfxresid.hxx" 77 #include "../doc/doc.hrc" 78 79 using namespace ::com::sun::star::uno; 80 using namespace ::com::sun::star::frame; 81 using namespace ::com::sun::star::beans; 82 using namespace ::com::sun::star::util; 83 84 //==================================================================== 85 86 class SfxEnumMenu: public PopupMenu 87 { 88 sal_uInt16 nSlot; 89 SfxEnumItem *pItem; 90 SfxBindings* pBindings; 91 92 protected: 93 virtual void Select(); 94 95 public: 96 SfxEnumMenu( sal_uInt16 nSlot, SfxBindings* pBind, const SfxEnumItem &rItem ); 97 ~SfxEnumMenu(); 98 }; 99 100 //========================================================================= 101 102 SfxEnumMenu::SfxEnumMenu( sal_uInt16 nSlotId, SfxBindings* pBind, const SfxEnumItem &rItem ): 103 nSlot( nSlotId ), 104 pItem( (SfxEnumItem*) rItem.Clone() ), 105 pBindings( pBind ) 106 { 107 for ( sal_uInt16 nVal = 0; nVal < pItem->GetValueCount(); ++nVal ) 108 InsertItem( nVal+1, pItem->GetValueTextByPos(nVal) ); 109 CheckItem( pItem->GetValue() + 1, sal_True ); 110 } 111 112 //------------------------------------------------------------------------- 113 114 SfxEnumMenu::~SfxEnumMenu() 115 { 116 delete pItem; 117 } 118 119 //------------------------------------------------------------------------- 120 121 void SfxEnumMenu::Select() 122 { 123 pItem->SetValue( GetCurItemId()-1 ); 124 pBindings->GetDispatcher()->Execute( nSlot, 125 SFX_CALLMODE_ASYNCHRON|SFX_CALLMODE_RECORD, 126 pItem, 0L, 0L ); 127 } 128 129 //-------------------------------------------------------------------- 130 131 void SfxMenuControl::SetOwnMenu( SfxVirtualMenu* pMenu ) 132 { 133 pOwnMenu = pMenu; 134 if ( pSubMenu ) 135 pSubMenu->SetParentMenu( pMenu ); 136 } 137 138 139 //-------------------------------------------------------------------- 140 141 // binds the instance to the specified id and assignes the title 142 143 void SfxMenuControl::Bind( 144 SfxVirtualMenu* pOwn, 145 sal_uInt16 nSlotId, 146 const String& rTitle, 147 const String &rHelpText, 148 SfxBindings &rBindings ) 149 { 150 DBG_MEMTEST(); 151 152 aTitle = rTitle; 153 aHelpText = rHelpText; 154 pOwnMenu = pOwn; 155 pSubMenu = 0; 156 if ( pOwn ) 157 SfxControllerItem::Bind(nSlotId, &rBindings); 158 else 159 SetId( nSlotId ); 160 161 DBG( CheckConfigure_Impl(SFX_SLOT_MENUCONFIG) ); 162 } 163 164 165 //-------------------------------------------------------------------- 166 167 // binds the item to the specified menu and assignes the title 168 169 void SfxMenuControl::Bind( 170 SfxVirtualMenu* pOwn, 171 sal_uInt16 nSlotId, 172 SfxVirtualMenu& rMenu, 173 const String& rTitle, 174 const String &rHelpText, 175 SfxBindings &rBindings ) 176 { 177 DBG_MEMTEST(); 178 SetId( nSlotId ); 179 SetBindings(rBindings); 180 pOwnMenu = pOwn; 181 pSubMenu = &rMenu; 182 aTitle = rTitle; 183 aHelpText = rHelpText; 184 } 185 186 //-------------------------------------------------------------------- 187 188 // ctor for explicit registration 189 190 SfxMenuControl::SfxMenuControl( sal_Bool bShowStrings ) 191 : pOwnMenu(0), 192 pSubMenu(0), 193 b_ShowStrings(bShowStrings) 194 { 195 DBG_MEMTEST(); 196 } 197 198 //-------------------------------------------------------------------- 199 200 // ctor for array 201 202 SfxMenuControl::SfxMenuControl(): 203 pOwnMenu(0), 204 pSubMenu(0), 205 b_ShowStrings(sal_False) 206 { 207 DBG_MEMTEST(); 208 } 209 210 //-------------------------------------------------------------------- 211 212 SfxMenuControl::SfxMenuControl(sal_uInt16 nSlotId, SfxBindings& rBindings): 213 SfxControllerItem(nSlotId, rBindings), 214 pOwnMenu(0), 215 pSubMenu(0), 216 b_ShowStrings(sal_False) 217 { 218 DBG_MEMTEST(); 219 220 // Dieser Ctor soll es erm"oglichen, w"ahrend der Konstruktion schon 221 // auf die Bindings zur"uckgreifen zu k"onnen, aber gebunden wird 222 // wie immer erst sp"ater. Anwendung z.B. wenn im ctor der abgeleiteten 223 // Klasse z.B. ein StatusForwarder erzeugt werden soll. 224 UnBind(); 225 } 226 227 228 //-------------------------------------------------------------------- 229 230 // dtor 231 232 SfxMenuControl::~SfxMenuControl() 233 { 234 delete pSubMenu; 235 } 236 237 void SfxMenuControl::RemovePopup() 238 { 239 DELETEZ( pSubMenu ); 240 } 241 242 //-------------------------------------------------------------------- 243 244 // changes the state in the virtual menu 245 246 void SfxMenuControl::StateChanged 247 ( 248 sal_uInt16 nSID, 249 SfxItemState eState, 250 const SfxPoolItem* pState 251 ) 252 { 253 (void)nSID; //unused 254 DBG_MEMTEST(); 255 DBG_ASSERT( nSID == GetId(), "strange SID" ); 256 DBG_ASSERT( pOwnMenu != 0, "setting state to dangling SfxMenuControl" ); 257 258 bool bIsObjMenu = 259 GetId() >= SID_OBJECTMENU0 && GetId() < SID_OBJECTMENU_LAST; 260 261 // enabled/disabled-Flag pauschal korrigieren 262 263 #ifdef UNIX 264 if (nSID == SID_PASTE) 265 pOwnMenu->EnableItem( GetId(), sal_True ); 266 else 267 #endif 268 pOwnMenu->EnableItem( GetId(), bIsObjMenu 269 ? 0 != pOwnMenu->GetSVMenu()->GetPopupMenu( GetId() ) 270 : eState != SFX_ITEM_DISABLED ); 271 272 if ( eState != SFX_ITEM_AVAILABLE ) 273 { 274 // checken nur bei nicht-Object-Menus 275 if ( !bIsObjMenu ) 276 pOwnMenu->CheckItem( GetId(), sal_False ); 277 278 // SetItemText flackert in MenuBar insbes. unter OS/2 (Bug #20658) 279 if ( // !bIsObjMenu && nicht wegen "Format/Datenbank" 280 pOwnMenu->GetSVMenu()->GetItemText( GetId() ) != GetTitle() ) 281 { 282 DBG_WARNING("Title of menu item changed - please check if this needs correction!"); 283 // pOwnMenu->SetItemText( GetId(), GetTitle() ); 284 } 285 return; 286 } 287 288 // ggf. das alte Enum-Menu entfernen/loeschen 289 //! delete pOwnMenu->GetMenu().ChangePopupMenu( GetId(), 0 ); 290 291 bool bCheck = false; 292 if ( pState->ISA(SfxBoolItem) ) 293 { 294 // BoolItem fuer checken 295 DBG_ASSERT( GetId() < SID_OBJECTMENU0 || GetId() > SID_OBJECTMENU_LAST, 296 "SfxBoolItem not allowed for SID_OBJECTMENUx" ); 297 bCheck = ((const SfxBoolItem*)pState)->GetValue(); 298 } 299 else if ( pState->ISA(SfxEnumItemInterface) && 300 ((SfxEnumItemInterface *)pState)->HasBoolValue() ) 301 { 302 // EnumItem wie Bool behandeln 303 DBG_ASSERT( GetId() < SID_OBJECTMENU0 || GetId() > SID_OBJECTMENU_LAST, 304 "SfxEnumItem not allowed for SID_OBJECTMENUx" ); 305 bCheck = ((SfxEnumItemInterface *)pState)->GetBoolValue(); 306 } 307 else if ( ( b_ShowStrings || bIsObjMenu ) && pState->ISA(SfxStringItem) ) 308 { 309 // MenuText aus SfxStringItem holen 310 String aStr( ((const SfxStringItem*)pState)->GetValue() ); 311 if ( aStr.CompareToAscii("($1)",4) == COMPARE_EQUAL ) 312 { 313 String aEntry(SfxResId(STR_UPDATEDOC)); 314 aEntry += ' '; 315 aEntry += aStr.Copy(4); 316 aStr = aEntry; 317 } 318 else if ( aStr.CompareToAscii("($2)",4) == COMPARE_EQUAL ) 319 { 320 String aEntry(SfxResId(STR_CLOSEDOC_ANDRETURN)); 321 aEntry += aStr.Copy(4); 322 aStr = aEntry; 323 } 324 325 pOwnMenu->SetItemText( GetId(), aStr ); 326 } 327 328 #ifdef enum_item_menu_ok 329 else if ( aType == TYPE(SfxEnumItem) ) 330 { 331 DBG_ASSERT( GetId() < SID_OBJECTMENU0 || GetId() > SID_OBJECTMENU_LAST, 332 "SfxEnumItem not allowed for SID_OBJECTMENUx" ); 333 pOwnMenu->GetMenu().ChangePopupMenu( GetId(), &GetBindings(), 334 new SfxEnumMenu( GetId(), *(const SfxEnumItem*)pState ) ); 335 } 336 #endif 337 338 pOwnMenu->CheckItem( GetId(), bCheck ); 339 } 340 341 //-------------------------------------------------------------------- 342 343 SfxMenuControl* SfxMenuControl::CreateImpl( sal_uInt16 /*nId*/, Menu& /*rMenu*/, SfxBindings& /*rBindings*/ ) 344 { 345 return new SfxMenuControl( sal_True ); 346 } 347 348 //-------------------------------------------------------------------- 349 350 void SfxMenuControl::RegisterControl( sal_uInt16 nSlotId, SfxModule *pMod ) 351 { 352 RegisterMenuControl( pMod, new SfxMenuCtrlFactory( 353 SfxMenuControl::CreateImpl, TYPE(SfxStringItem), nSlotId ) ); 354 } 355 356 //-------------------------------------------------------------------- 357 void SfxMenuControl::RegisterMenuControl(SfxModule* pMod, SfxMenuCtrlFactory* pFact) 358 { 359 SFX_APP()->RegisterMenuControl_Impl( pMod, pFact ); 360 } 361 362 SfxMenuControl* SfxMenuControl::CreateControl( sal_uInt16 nId, Menu &rMenu, SfxBindings &rBindings ) 363 { 364 TypeId aSlotType = SFX_SLOTPOOL().GetSlotType(nId); 365 if ( aSlotType ) 366 { 367 SfxApplication *pApp = SFX_APP(); 368 SfxDispatcher *pDisp = rBindings.GetDispatcher_Impl(); 369 SfxModule *pMod = pDisp ? SfxModule::GetActiveModule( pDisp->GetFrame() ) :0; 370 if ( pMod ) 371 { 372 SfxMenuCtrlFactArr_Impl *pFactories = pMod->GetMenuCtrlFactories_Impl(); 373 if ( pFactories ) 374 { 375 SfxMenuCtrlFactArr_Impl &rFactories = *pFactories; 376 for ( sal_uInt16 nFactory = 0; nFactory < rFactories.Count(); ++nFactory ) 377 if ( rFactories[nFactory]->nTypeId == aSlotType && 378 ( ( rFactories[nFactory]->nSlotId == 0 ) || 379 ( rFactories[nFactory]->nSlotId == nId) ) ) 380 return rFactories[nFactory]->pCtor( nId, rMenu, rBindings ); 381 } 382 } 383 384 SfxMenuCtrlFactArr_Impl &rFactories = pApp->GetMenuCtrlFactories_Impl(); 385 386 for ( sal_uInt16 nFactory = 0; nFactory < rFactories.Count(); ++nFactory ) 387 if ( rFactories[nFactory]->nTypeId == aSlotType && 388 ( ( rFactories[nFactory]->nSlotId == 0 ) || 389 ( rFactories[nFactory]->nSlotId == nId) ) ) 390 return rFactories[nFactory]->pCtor( nId, rMenu, rBindings ); 391 } 392 return 0; 393 } 394 395 sal_Bool SfxMenuControl::IsSpecialControl( sal_uInt16 nId, SfxModule* pMod ) 396 { 397 TypeId aSlotType = SFX_SLOTPOOL().GetSlotType( nId ); 398 if ( aSlotType ) 399 { 400 if ( pMod ) 401 { 402 SfxMenuCtrlFactArr_Impl *pFactories = pMod->GetMenuCtrlFactories_Impl(); 403 if ( pFactories ) 404 { 405 SfxMenuCtrlFactArr_Impl &rFactories = *pFactories; 406 for ( sal_uInt16 nFactory = 0; nFactory < rFactories.Count(); ++nFactory ) 407 if ( rFactories[nFactory]->nTypeId == aSlotType && 408 ( ( rFactories[nFactory]->nSlotId == 0 ) || 409 ( rFactories[nFactory]->nSlotId == nId) ) ) 410 return sal_True; 411 } 412 } 413 414 SfxMenuCtrlFactArr_Impl &rFactories = SFX_APP()->GetMenuCtrlFactories_Impl(); 415 416 for ( sal_uInt16 nFactory = 0; nFactory < rFactories.Count(); ++nFactory ) 417 if ( rFactories[nFactory]->nTypeId == aSlotType && 418 ( ( rFactories[nFactory]->nSlotId == 0 ) || 419 ( rFactories[nFactory]->nSlotId == nId) ) ) 420 return sal_True; 421 } 422 return 0; 423 } 424 425 //-------------------------------------------------------------------- 426 427 PopupMenu* SfxMenuControl::GetPopup () const 428 { 429 if (GetPopupMenu()) 430 return (PopupMenu*)GetPopupMenu()->GetSVMenu(); 431 else 432 return 0; 433 } 434 435 long Select_Impl( void* pHdl, void* pVoid ); 436 437 SFX_IMPL_MENU_CONTROL( SfxAppMenuControl_Impl, SfxStringItem ); 438 439 SfxAppMenuControl_Impl::SfxAppMenuControl_Impl( 440 sal_uInt16 nPos, Menu& rMenu, SfxBindings& rBindings ) 441 : SfxMenuControl( nPos, rBindings ), pMenu(0) 442 { 443 String aText = rMenu.GetItemText( nPos ); 444 445 // Determine the current background color setting for menus 446 const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); 447 m_nSymbolsStyle = rSettings.GetSymbolsStyle(); 448 m_bWasHiContrastMode = rSettings.GetHighContrastMode(); 449 m_bShowMenuImages = rSettings.GetUseImagesInMenus(); 450 451 Reference<com::sun::star::lang::XMultiServiceFactory> aXMultiServiceFactory(::comphelper::getProcessServiceFactory()); 452 ::framework::MenuConfiguration aConf( aXMultiServiceFactory ); 453 Reference<com::sun::star::frame::XFrame> aXFrame( GetBindings().GetDispatcher_Impl()->GetFrame()->GetFrame().GetFrameInterface() ); 454 pMenu = aConf.CreateBookmarkMenu( aXFrame, GetId() == SID_NEWDOCDIRECT ? BOOKMARK_NEWMENU : BOOKMARK_WIZARDMENU ); 455 if( pMenu ) 456 { 457 pMenu->SetSelectHdl( Link( &(this->GetBindings()), Select_Impl ) ); 458 pMenu->SetActivateHdl( LINK(this, SfxAppMenuControl_Impl, Activate) ); 459 rMenu.SetPopupMenu( nPos, pMenu ); 460 } 461 } 462 463 SfxAppMenuControl_Impl::~SfxAppMenuControl_Impl() 464 { 465 delete pMenu; 466 } 467 468 IMPL_LINK( SfxAppMenuControl_Impl, Activate, Menu *, pActMenu ) 469 { 470 if ( pActMenu ) 471 { 472 const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); 473 sal_uIntPtr nSymbolsStyle = rSettings.GetSymbolsStyle(); 474 sal_Bool bIsHiContrastMode = rSettings.GetHighContrastMode(); 475 sal_Bool bShowMenuImages = rSettings.GetUseImagesInMenus(); 476 477 if (( nSymbolsStyle != m_nSymbolsStyle ) || 478 ( bIsHiContrastMode != m_bWasHiContrastMode ) || 479 ( bShowMenuImages != m_bShowMenuImages )) 480 { 481 m_nSymbolsStyle = nSymbolsStyle; 482 m_bWasHiContrastMode = bIsHiContrastMode; 483 m_bShowMenuImages = bShowMenuImages; 484 485 sal_uInt16 nCount = pActMenu->GetItemCount(); 486 for ( sal_uInt16 nSVPos = 0; nSVPos < nCount; nSVPos++ ) 487 { 488 sal_uInt16 nItemId = pActMenu->GetItemId( nSVPos ); 489 if ( pActMenu->GetItemType( nSVPos ) != MENUITEM_SEPARATOR ) 490 { 491 if ( bShowMenuImages ) 492 { 493 sal_Bool bImageSet = sal_False; 494 ::rtl::OUString aImageId; 495 ::framework::MenuConfiguration::Attributes* pMenuAttributes = 496 (::framework::MenuConfiguration::Attributes*)pMenu->GetUserValue( nItemId ); 497 498 if ( pMenuAttributes ) 499 aImageId = pMenuAttributes->aImageId; // Retrieve image id from menu attributes 500 501 if ( aImageId.getLength() > 0 ) 502 { 503 Reference< ::com::sun::star::frame::XFrame > xFrame; 504 Image aImage = GetImage( xFrame, aImageId, sal_False, bIsHiContrastMode ); 505 if ( !!aImage ) 506 { 507 bImageSet = sal_True; 508 pActMenu->SetItemImage( nItemId, aImage ); 509 } 510 } 511 512 String aCmd( pActMenu->GetItemCommand( nItemId ) ); 513 if ( !bImageSet && aCmd.Len() ) 514 { 515 Image aImage = SvFileInformationManager::GetImage( 516 INetURLObject(aCmd), sal_False, bIsHiContrastMode ); 517 if ( !!aImage ) 518 pActMenu->SetItemImage( nItemId, aImage ); 519 } 520 } 521 else 522 pActMenu->SetItemImage( nItemId, Image() ); 523 } 524 } 525 } 526 527 return sal_True; 528 } 529 530 return sal_False; 531 } 532 533 SfxUnoMenuControl* SfxMenuControl::CreateControl( const String& rCmd, 534 sal_uInt16 nId, Menu& rMenu, SfxBindings &rBindings, SfxVirtualMenu* pVirt ) 535 { 536 return new SfxUnoMenuControl( rCmd, nId, rMenu, rBindings, pVirt ); 537 } 538 539 SfxUnoMenuControl* SfxMenuControl::CreateControl( const String& rCmd, 540 sal_uInt16 nId, Menu& rMenu, const String& sItemText, const String& sHelpText, 541 SfxBindings& rBindings, SfxVirtualMenu* pVirt) 542 { 543 return new SfxUnoMenuControl( rCmd, nId, rMenu, sItemText, sHelpText, rBindings, pVirt); 544 } 545 546 SfxUnoMenuControl::SfxUnoMenuControl( const String& rCmd, sal_uInt16 nSlotId, 547 Menu& rMenu, SfxBindings& rBindings, SfxVirtualMenu* pVirt ) 548 : SfxMenuControl( nSlotId, rBindings ) 549 { 550 Bind( pVirt, nSlotId, rMenu.GetItemText(nSlotId), 551 rMenu.GetHelpText(nSlotId), rBindings); 552 UnBind(); 553 pUnoCtrl = new SfxUnoControllerItem( this, rBindings, rCmd ); 554 pUnoCtrl->acquire(); 555 pUnoCtrl->GetNewDispatch(); 556 } 557 558 SfxUnoMenuControl::SfxUnoMenuControl( 559 const String& rCmd, sal_uInt16 nSlotId, Menu& /*rMenu*/, 560 const String& rItemText, const String& rHelpText, 561 SfxBindings& rBindings, SfxVirtualMenu* pVirt) 562 : SfxMenuControl( nSlotId, rBindings ) 563 { 564 Bind( pVirt, nSlotId, rItemText, rHelpText, rBindings); 565 UnBind(); 566 pUnoCtrl = new SfxUnoControllerItem( this, rBindings, rCmd ); 567 pUnoCtrl->acquire(); 568 pUnoCtrl->GetNewDispatch(); 569 } 570 571 SfxUnoMenuControl::~SfxUnoMenuControl() 572 { 573 pUnoCtrl->UnBind(); 574 pUnoCtrl->release(); 575 } 576 577 void SfxUnoMenuControl::Select() 578 { 579 pUnoCtrl->Execute(); 580 } 581