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