/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sfx2.hxx" #include #include #include #ifdef SOLARIS // HACK: prevent conflict between STLPORT and Workshop headers on Solaris 8 #include #endif #include // HACK: prevent conflict between STLPORT and Workshop headers #include // std::va_list #ifndef _POINTR_HXX //autogen #include #endif #ifndef GCC #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define _SVSTDARR_USHORTS #include #include #include "virtmenu.hxx" #include #include #include #include #include "sfxtypes.hxx" #include #include "mnucfga.hxx" #include "sfx2/sfxresid.hxx" #include #include #include "menu.hrc" #include #include #include #include "thessubmenu.hxx" static const sal_uInt16 nCompatVersion = 4; static const sal_uInt16 nVersion = 5; // static member initialization PopupMenu * SfxPopupMenuManager::pStaticThesSubMenu = NULL; using namespace com::sun::star; //========================================================================= DECL_PTRSTACK(SfxMenuCfgItemArrStack, SfxMenuCfgItemArr*, 4, 4 ); //------------------------------------------------------------------------- void TryToHideDisabledEntries_Impl( Menu* pMenu ) { DBG_ASSERT( pMenu, "invalid menu" ); if( SvtMenuOptions().IsEntryHidingEnabled() == sal_False ) { pMenu->SetMenuFlags( pMenu->GetMenuFlags() | MENU_FLAG_HIDEDISABLEDENTRIES ); } } //------------------------------------------------------------------------- SfxMenuManager::SfxMenuManager( const ResId& rResId, SfxBindings &rBindings ) : pMenu(0), pOldMenu(0), pBindings(&rBindings), pResMgr(rResId.GetResMgr()), nType( rResId.GetId() ) { bAddClipboardFuncs = sal_False; DBG_MEMTEST(); } //-------------------------------------------------------------------- SfxMenuManager::~SfxMenuManager() { DBG_MEMTEST(); pBindings->ENTERREGISTRATIONS(); delete pMenu; pBindings->LEAVEREGISTRATIONS(); } //-------------------------------------------------------------------- void SfxMenuManager::Construct( SfxVirtualMenu& rMenu ) { DBG_MEMTEST(); pMenu = &rMenu; // set the handlers Menu *pSvMenu = pMenu->GetSVMenu(); pSvMenu->SetSelectHdl( LINK(this, SfxMenuManager, Select) ); TryToHideDisabledEntries_Impl( pSvMenu ); } //------------------------------------------------------------------------- void InsertVerbs_Impl( SfxBindings* pBindings, const com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor >& aVerbs, Menu* pMenu ) { SfxViewShell *pView = pBindings->GetDispatcher()->GetFrame()->GetViewShell(); if ( pView && aVerbs.getLength() ) { SfxObjectShell* pDoc = pView->GetObjectShell(); pMenu->InsertSeparator(); sal_uInt16 nr=0; for ( sal_uInt16 n = 0; n < aVerbs.getLength(); ++n ) { // check for ReadOnly verbs if ( pDoc->IsReadOnly() && !(aVerbs[n].VerbAttributes & embed::VerbAttributes::MS_VERBATTR_NEVERDIRTIES) ) continue; // check for verbs that shouldn't appear in the menu if ( !(aVerbs[n].VerbAttributes & embed::VerbAttributes::MS_VERBATTR_ONCONTAINERMENU) ) continue; // neue Id vergeben sal_uInt16 nId = SID_VERB_START + nr++; DBG_ASSERT(nId <= SID_VERB_END, "Zuviele Verben!"); if ( nId > SID_VERB_END ) break; // einf"ugen pMenu->InsertItem( nId, aVerbs[n].VerbName ); } } } //-------------------------------------------------------------------- static Image lcl_GetImageFromPngUrl( const ::rtl::OUString &rFileUrl ) { Image aRes; ::rtl::OUString aTmp; osl::FileBase::getSystemPathFromFileURL( rFileUrl, aTmp ); Graphic aGraphic; const String aFilterName( RTL_CONSTASCII_USTRINGPARAM( IMP_PNG ) ); if( GRFILTER_OK == GraphicFilter::LoadGraphic( aTmp, aFilterName, aGraphic ) ) { aRes = Image( aGraphic.GetBitmapEx() ); } return aRes; } PopupMenu* InsertThesaurusSubmenu_Impl( SfxBindings* pBindings, Menu* pSVMenu ) { // // build thesaurus sub menu if look-up string is available // PopupMenu* pThesSubMenu = 0; SfxPoolItem *pItem = 0; pBindings->QueryState( SID_THES, pItem ); String aThesLookUpStr; SfxStringItem *pStrItem = dynamic_cast< SfxStringItem * >(pItem); xub_StrLen nDelimPos = STRING_LEN; if (pStrItem) { aThesLookUpStr = pStrItem->GetValue(); nDelimPos = aThesLookUpStr.SearchBackward( '#' ); } if (aThesLookUpStr.Len() > 0 && nDelimPos != STRING_NOTFOUND) { // get synonym list for sub menu std::vector< ::rtl::OUString > aSynonyms; SfxThesSubMenuHelper aHelper; ::rtl::OUString aText( aHelper.GetText( aThesLookUpStr, nDelimPos ) ); lang::Locale aLocale; aHelper.GetLocale( aLocale, aThesLookUpStr, nDelimPos ); const bool bHasMoreSynonyms = aHelper.GetMeanings( aSynonyms, aText, aLocale, 7 /*max number of synonyms to retrieve*/ ); (void) bHasMoreSynonyms; pThesSubMenu = new PopupMenu; pThesSubMenu->SetMenuFlags(MENU_FLAG_NOAUTOMNEMONICS); const size_t nNumSynonyms = aSynonyms.size(); if (nNumSynonyms > 0) { SvtLinguConfig aCfg; const bool bHC = Application::GetSettings().GetStyleSettings().GetHighContrastMode(); Image aImage; String sThesImplName( aHelper.GetThesImplName( aLocale ) ); ::rtl::OUString aSynonymsImageUrl( aCfg.GetSynonymsContextImage( sThesImplName, bHC ) ); if (sThesImplName.Len() > 0 && aSynonymsImageUrl.getLength() > 0) aImage = Image( lcl_GetImageFromPngUrl( aSynonymsImageUrl ) ); for (sal_uInt16 i = 0; (size_t)i < nNumSynonyms; ++i) { //! item ids should start with values > 0, since 0 has special meaning const sal_uInt16 nId = i + 1; String aItemText( linguistic::GetThesaurusReplaceText( aSynonyms[i] ) ); pThesSubMenu->InsertItem( nId, aItemText ); ::rtl::OUString aCmd( ::rtl::OUString::createFromAscii( ".uno:ThesaurusFromContext?WordReplace:string=" ) ); aCmd += aItemText; pThesSubMenu->SetItemCommand( nId, aCmd ); if (aSynonymsImageUrl.getLength() > 0) pThesSubMenu->SetItemImage( nId, aImage ); } } else // nNumSynonyms == 0 { const String aItemText( SfxResId( STR_MENU_NO_SYNONYM_FOUND ) ); pThesSubMenu->InsertItem( 1, aItemText, MIB_NOSELECT ); } pThesSubMenu->InsertSeparator(); const String sThesaurus( SfxResId( STR_MENU_THESAURUS ) ); pThesSubMenu->InsertItem( 100, sThesaurus ); pThesSubMenu->SetItemCommand( 100, ::rtl::OUString::createFromAscii( ".uno:ThesaurusDialog" ) ); pSVMenu->InsertSeparator(); const String sSynonyms( SfxResId( STR_MENU_SYNONYMS ) ); pSVMenu->InsertItem( SID_THES, sSynonyms ); pSVMenu->SetPopupMenu( SID_THES, pThesSubMenu ); } return pThesSubMenu; } //-------------------------------------------------------------------- void SfxMenuManager::UseDefault() { DBG_MEMTEST(); SFX_APP(); SfxVirtualMenu *pOldVirtMenu=0; if (pMenu) { pOldVirtMenu = pMenu; pBindings->ENTERREGISTRATIONS(); } SfxVirtualMenu *pVMenu = 0; { ResId aResId(GetType(),*pResMgr); aResId.SetRT(RSC_MENU); Menu *pSVMenu = new PopupMenu( aResId ); //SfxMenuManager::EraseItemCmds( pSVMenu ); // Remove .uno cmds to be compatible with 6.0/src641 if ( bAddClipboardFuncs ) { sal_uInt16 n, nCount = pSVMenu->GetItemCount(); for ( n=0; nGetItemId( n ); if ( nId == SID_COPY || nId == SID_CUT || nId == SID_PASTE ) break; } if ( n == nCount ) { PopupMenu aPop( SfxResId( MN_CLIPBOARDFUNCS ) ); nCount = aPop.GetItemCount(); pSVMenu->InsertSeparator(); for ( n=0; nInsertItem( nId, aPop.GetItemText( nId ), aPop.GetItemBits( nId ) ); } } } pVMenu = new SfxVirtualMenu( pSVMenu, sal_False, *pBindings, sal_True, sal_True ); } Construct(*pVMenu); if (pOldVirtMenu) { delete pOldVirtMenu; pBindings->LEAVEREGISTRATIONS(); } } // ------------------------------------------------------------------------ // executes the function for the selected item IMPL_LINK( SfxMenuManager, Select, Menu *, pSelMenu ) { DBG_MEMTEST(); sal_uInt16 nId = (sal_uInt16) pSelMenu->GetCurItemId(); String aCommand = pSelMenu->GetItemCommand( nId ); if ( !aCommand.Len() && pBindings ) { const SfxSlot* pSlot = SfxSlotPool::GetSlotPool( pBindings->GetDispatcher()->GetFrame() ).GetSlot( nId ); if ( pSlot && pSlot->pUnoName ) { aCommand = DEFINE_CONST_UNICODE(".uno:"); aCommand += String::CreateFromAscii( pSlot->GetUnoName() ); } } if ( aCommand.Len() ) { pBindings->ExecuteCommand_Impl( aCommand ); } else if ( pBindings->IsBound(nId) ) // normal function pBindings->Execute( nId ); else // special menu function pBindings->GetDispatcher_Impl()->Execute( nId ); return sal_True; } //-------------------------------------------------------------------- void SfxMenuManager::Construct_Impl( Menu* pSVMenu, sal_Bool bWithHelp ) { SfxVirtualMenu *pOldVirtMenu=0; if ( pMenu ) { // Es wird umkonfiguriert pOldVirtMenu = pMenu; pBindings->ENTERREGISTRATIONS(); } TryToHideDisabledEntries_Impl( pSVMenu ); SfxVirtualMenu *pVMenu = new SfxVirtualMenu( pSVMenu, bWithHelp, *pBindings, sal_True ); Construct(*pVMenu); if ( pOldVirtMenu ) { delete pOldVirtMenu; pBindings->LEAVEREGISTRATIONS(); } } //-------------------------------------------------------------------- // don't insert Popups into ConfigManager, they are not configurable at the moment ! SfxPopupMenuManager::SfxPopupMenuManager(const ResId& rResId, SfxBindings &rBindings ) : SfxMenuManager( rResId, rBindings ) , pSVMenu( NULL ) { DBG_MEMTEST(); } SfxPopupMenuManager::~SfxPopupMenuManager() { } //------------------------------------------------------------------------- void SfxPopupMenuManager::RemoveDisabledEntries() { if ( pSVMenu ) TryToHideDisabledEntries_Impl( pSVMenu ); } //-------------------------------------------------------------------- sal_uInt16 SfxPopupMenuManager::Execute( const Point& rPos, Window* pWindow ) { DBG_MEMTEST(); sal_uInt16 nVal = ( (PopupMenu*) GetMenu()->GetSVMenu() )->Execute( pWindow, rPos ); delete pStaticThesSubMenu; pStaticThesSubMenu = NULL; return nVal; } //-------------------------------------------------------------------- IMPL_LINK_INLINE_START( SfxPopupMenuManager, SelectHdl, void *, EMPTYARG ) { return 1; } IMPL_LINK_INLINE_END( SfxPopupMenuManager, SelectHdl, void *, EMPTYARG ) //-------------------------------------------------------------------- sal_uInt16 SfxPopupMenuManager::Execute( const Point& rPoint, Window* pWindow, va_list pArgs, const SfxPoolItem *pArg1 ) { DBG_MEMTEST(); PopupMenu* pPopMenu = ( (PopupMenu*)GetMenu()->GetSVMenu() ); pPopMenu->SetSelectHdl( LINK( this, SfxPopupMenuManager, SelectHdl ) ); sal_uInt16 nId = pPopMenu->Execute( pWindow, rPoint ); pPopMenu->SetSelectHdl( Link() ); if ( nId ) GetBindings().GetDispatcher()->_Execute( nId, SFX_CALLMODE_RECORD, pArgs, pArg1 ); return nId; } //-------------------------------------------------------------------- sal_uInt16 SfxPopupMenuManager::Execute( const Point& rPoint, Window* pWindow, const SfxPoolItem *pArg1, ... ) { DBG_MEMTEST(); va_list pArgs; va_start(pArgs, pArg1); return (Execute( rPoint, pWindow, pArgs, pArg1 )); } //------------------------------------------------------------------------- void SfxPopupMenuManager::StartInsert() { ResId aResId(GetType(),*pResMgr); aResId.SetRT(RSC_MENU); pSVMenu = new PopupMenu( aResId ); TryToHideDisabledEntries_Impl( pSVMenu ); } //------------------------------------------------------------------------- void SfxPopupMenuManager::EndInsert() { pBindings->ENTERREGISTRATIONS(); pMenu = new SfxVirtualMenu( pSVMenu, sal_False, *pBindings, sal_True, sal_True ); Construct( *pMenu ); pBindings->LEAVEREGISTRATIONS(); } //------------------------------------------------------------------------- void SfxPopupMenuManager::InsertSeparator( sal_uInt16 nPos ) { pSVMenu->InsertSeparator( nPos ); } //------------------------------------------------------------------------- void SfxPopupMenuManager::InsertItem( sal_uInt16 nId, const String& rName, MenuItemBits nBits, const rtl::OString& rHelpId, sal_uInt16 nPos ) { pSVMenu->InsertItem( nId, rName, nBits,nPos ); pSVMenu->SetHelpId( nId, rHelpId ); } //------------------------------------------------------------------------- void SfxPopupMenuManager::RemoveItem( sal_uInt16 nId ) { pSVMenu->RemoveItem( nId ); } //------------------------------------------------------------------------- void SfxPopupMenuManager::CheckItem( sal_uInt16 nId, sal_Bool bCheck ) { pSVMenu->CheckItem( nId, bCheck ); } void SfxPopupMenuManager::AddClipboardFunctions() { bAddClipboardFuncs = sal_True; } SfxMenuManager::SfxMenuManager( Menu* pMenuArg, SfxBindings &rBindings ) : pMenu(0), pOldMenu(0), pBindings(&rBindings), pResMgr(NULL), nType(0) { bAddClipboardFuncs = sal_False; SfxVirtualMenu* pVMenu = new SfxVirtualMenu( pMenuArg, sal_False, rBindings, sal_True, sal_True ); Construct(*pVMenu); } SfxPopupMenuManager::SfxPopupMenuManager( PopupMenu* pMenuArg, SfxBindings& rBindings ) : SfxMenuManager( pMenuArg, rBindings ) , pSVMenu( pMenuArg ) { } SfxPopupMenuManager* SfxPopupMenuManager::Popup( const ResId& rResId, SfxViewFrame* pFrame,const Point& rPoint, Window* pWindow ) { PopupMenu *pSVMenu = new PopupMenu( rResId ); sal_uInt16 n, nCount = pSVMenu->GetItemCount(); for ( n=0; nGetItemId( n ); if ( nId == SID_COPY || nId == SID_CUT || nId == SID_PASTE ) break; } PopupMenu* pThesSubMenu = InsertThesaurusSubmenu_Impl( &pFrame->GetBindings(), pSVMenu ); // #i107205# (see comment in header file) pStaticThesSubMenu = pThesSubMenu; if ( n == nCount ) { PopupMenu aPop( SfxResId( MN_CLIPBOARDFUNCS ) ); nCount = aPop.GetItemCount(); pSVMenu->InsertSeparator(); for ( n=0; nInsertItem( nId, aPop.GetItemText( nId ), aPop.GetItemBits( nId ) ); pSVMenu->SetHelpId( nId, aPop.GetHelpId( nId )); } } InsertVerbs_Impl( &pFrame->GetBindings(), pFrame->GetViewShell()->GetVerbs(), pSVMenu ); Menu* pMenu = NULL; ::com::sun::star::ui::ContextMenuExecuteEvent aEvent; aEvent.SourceWindow = VCLUnoHelper::GetInterface( pWindow ); aEvent.ExecutePosition.X = rPoint.X(); aEvent.ExecutePosition.Y = rPoint.Y(); ::rtl::OUString sDummyMenuName; if ( pFrame->GetViewShell()->TryContextMenuInterception( *pSVMenu, sDummyMenuName, pMenu, aEvent ) ) { if ( pMenu ) { delete pSVMenu; pSVMenu = (PopupMenu*) pMenu; } SfxPopupMenuManager* aMgr = new SfxPopupMenuManager( pSVMenu, pFrame->GetBindings()); aMgr->RemoveDisabledEntries(); return aMgr; } return 0; } void SfxPopupMenuManager::ExecutePopup( const ResId& rResId, SfxViewFrame* pFrame, const Point& rPoint, Window* pWindow ) { PopupMenu *pSVMenu = new PopupMenu( rResId ); sal_uInt16 n, nCount = pSVMenu->GetItemCount(); for ( n=0; nGetItemId( n ); if ( nId == SID_COPY || nId == SID_CUT || nId == SID_PASTE ) break; } PopupMenu* pThesSubMenu = InsertThesaurusSubmenu_Impl( &pFrame->GetBindings(), pSVMenu ); if ( n == nCount ) { PopupMenu aPop( SfxResId( MN_CLIPBOARDFUNCS ) ); nCount = aPop.GetItemCount(); pSVMenu->InsertSeparator(); for ( n=0; nInsertItem( nId, aPop.GetItemText( nId ), aPop.GetItemBits( nId ) ); pSVMenu->SetHelpId( nId, aPop.GetHelpId( nId )); } } InsertVerbs_Impl( &pFrame->GetBindings(), pFrame->GetViewShell()->GetVerbs(), pSVMenu ); Menu* pMenu = NULL; ::com::sun::star::ui::ContextMenuExecuteEvent aEvent; aEvent.SourceWindow = VCLUnoHelper::GetInterface( pWindow ); aEvent.ExecutePosition.X = rPoint.X(); aEvent.ExecutePosition.Y = rPoint.Y(); ::rtl::OUString sDummyMenuName; if ( pFrame->GetViewShell()->TryContextMenuInterception( *pSVMenu, sDummyMenuName, pMenu, aEvent ) ) { if ( pMenu ) { delete pSVMenu; pSVMenu = (PopupMenu*) pMenu; } SfxPopupMenuManager aPop( pSVMenu, pFrame->GetBindings() ); aPop.RemoveDisabledEntries(); aPop.Execute( rPoint, pWindow ); // #i112646 avoid crash when context menu is closed. // the (manually inserted) sub-menu needs to be destroyed before // aPop gets destroyed. delete pThesSubMenu; pThesSubMenu = 0; } delete pThesSubMenu; } Menu* SfxPopupMenuManager::GetSVMenu() { return (Menu*) GetMenu()->GetSVMenu(); }