diff options
Diffstat (limited to 'sfx2/source/menu')
-rw-r--r-- | sfx2/source/menu/menu.hrc | 73 | ||||
-rw-r--r-- | sfx2/source/menu/menu.src | 98 | ||||
-rw-r--r-- | sfx2/source/menu/mnuitem.cxx | 583 | ||||
-rwxr-xr-x | sfx2/source/menu/mnumgr.cxx | 641 | ||||
-rw-r--r-- | sfx2/source/menu/objmnctl.cxx | 165 | ||||
-rwxr-xr-x | sfx2/source/menu/thessubmenu.cxx | 241 | ||||
-rw-r--r-- | sfx2/source/menu/thessubmenu.hxx | 103 | ||||
-rw-r--r-- | sfx2/source/menu/virtmenu.cxx | 1361 |
8 files changed, 3265 insertions, 0 deletions
diff --git a/sfx2/source/menu/menu.hrc b/sfx2/source/menu/menu.hrc new file mode 100644 index 000000000000..b437f797c26e --- /dev/null +++ b/sfx2/source/menu/menu.hrc @@ -0,0 +1,73 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _MNUCFG_HRC +#define _MNUCFG_HRC + +#include <sfx2/sfx.hrc> + +// #defines ***************************************************************** + +#define DLG_MENUCONFIG (RID_SFX_MENU_START+1) +#define IBX_MNUCFG_ALREADY_INCLUDED (RID_SFX_MENU_START+2) +#define QBX_MNUCFG_UNDEFINED_FUNCTIONS (RID_SFX_MENU_START+3) +#define QBX_MNUCFG_POPUP_FUNCTIONS (RID_SFX_MENU_START+4) + +#define BTN_OK 1 +#define BTN_CANCEL 2 +#define BTN_UP 3 +#define BTN_LEFT 4 +#define BTN_RIGHT 5 +#define BTN_DOWN 6 +#define BTN_NEW 7 +#define BTN_CHANGE 8 +#define BTN_REMOVE 9 +#define BOX_ENTRIES 10 +#define TXT_TEXT 11 +#define EDT_TEXT 12 +#define TXT_FUNCTIONTEXT 13 +#define TXT_FUNCTIONINFO 14 +#define TXT_DESCRIPTIONTEXT 15 +#define TXT_DESCRIPTIONINFO 16 +#define GRP_MENU 17 +#define TXT_GROUP 18 +#define BOX_GROUP 19 +#define TXT_FUNCTION 20 +#define BOX_FUNCTION 21 +#define GRP_FUNCTIONS 22 + +#define STR_MENU_CFGITEM RID_SFX_MENU_START+1 +#define STR_MENU_ADDONS RID_SFX_MENU_START+2 +#define STR_MENU_ADDONHELP RID_SFX_MENU_START+3 + +#define STR_MENU_SYNONYMS (RID_SFX_MENU_START+11) +#define STR_MENU_NO_SYNONYM_FOUND (RID_SFX_MENU_START+12) +#define STR_MENU_THESAURUS (RID_SFX_MENU_START+13) + +#define MN_CLIPBOARDFUNCS RID_SFX_MENU_START+1 +#endif + diff --git a/sfx2/source/menu/menu.src b/sfx2/source/menu/menu.src new file mode 100644 index 000000000000..5e3d8296bb59 --- /dev/null +++ b/sfx2/source/menu/menu.src @@ -0,0 +1,98 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "menu.hrc" +#include <sfx2/sfxcommands.h> + +String STR_MENU_CFGITEM +{ + Text [ en-US ] = "Configuration Menu" ; +}; + +String STR_MENU_ADDONS +{ + Text [ en-US ] = "~Add-Ons" ; +}; + +Menu MN_CLIPBOARDFUNCS +{ + ItemList = + { + MenuItem + { + Identifier = SID_CUT ; + HelpID = CMD_SID_CUT ; + Text [ en-US ] = "Cu~t" ; + }; + MenuItem + { + Identifier = SID_COPY ; + HelpID = CMD_SID_COPY ; + Text [ en-US ] = "~Copy" ; + }; + MenuItem + { + Identifier = SID_PASTE ; + HelpID = CMD_SID_PASTE ; + Text [ en-US ] = "~Paste" ; + }; + }; +}; + +String SID_WIN_FULLSCREEN +{ + Text [ en-US ] = "Leave Full-Screen Mode"; +}; + +String STR_MENU_ADDONHELP +{ + Text [ en-US ] = "Add-~On Help" ; +}; + +String STR_MENU_SYNONYMS +{ + Text [ en-US ] = "Synonyms" ; +}; + +String STR_MENU_NO_SYNONYM_FOUND +{ + Text [ en-US ] = "(none)" ; +}; + +String STR_MENU_THESAURUS +{ + Text [ en-US ] = "~Thesaurus..." ; +}; + +// ******************************************************************* EOF + + + + + + + diff --git a/sfx2/source/menu/mnuitem.cxx b/sfx2/source/menu/mnuitem.cxx new file mode 100644 index 000000000000..f101b0d426b9 --- /dev/null +++ b/sfx2/source/menu/mnuitem.cxx @@ -0,0 +1,583 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +#ifdef SOLARIS +// HACK: prevent conflict between STLPORT and Workshop headers on Solaris 8 +#include <ctime> +#endif + +#include <string> // HACK: prevent conflict between STLPORT and Workshop includes +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/util/URL.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#ifndef _UNOTOOLS_PROCESSFACTORY_HXX +#include <comphelper/processfactory.hxx> +#endif +#include <com/sun/star/util/XURLTransformer.hpp> +#ifndef _UNOTOOLS_PROCESSFACTORY_HXX +#include <comphelper/processfactory.hxx> +#endif +#include <tools/urlobj.hxx> +#include <svl/eitem.hxx> +#include <svl/stritem.hxx> +#include <svtools/imagemgr.hxx> +#include <svtools/menuoptions.hxx> +#include <framework/menuconfiguration.hxx> +#ifndef GCC +#endif + +#include <sfx2/app.hxx> +#include <sfx2/sfx.hrc> +#include <sfx2/msgpool.hxx> +#include <sfx2/msg.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include "idpool.hxx" +#include "sfxtypes.hxx" +#include <sfx2/macrconf.hxx> +#include "virtmenu.hxx" +#include <sfx2/mnuitem.hxx> +#include <sfx2/tbxctrl.hxx> +#include "arrdecl.hxx" +#include <sfx2/module.hxx> +#include <sfx2/unoctitm.hxx> +#include <sfx2/viewfrm.hxx> +#include "sfx2/imgmgr.hxx" +#include "sfx2/imagemgr.hxx" +#include "sfx2/sfxresid.hxx" +#include "../doc/doc.hrc" + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::util; + +//==================================================================== + +class SfxEnumMenu: public PopupMenu +{ + USHORT nSlot; + SfxEnumItem *pItem; + SfxBindings* pBindings; + +protected: + virtual void Select(); + +public: + SfxEnumMenu( USHORT nSlot, SfxBindings* pBind, const SfxEnumItem &rItem ); + ~SfxEnumMenu(); +}; + +//========================================================================= + +SfxEnumMenu::SfxEnumMenu( USHORT nSlotId, SfxBindings* pBind, const SfxEnumItem &rItem ): + nSlot( nSlotId ), + pItem( (SfxEnumItem*) rItem.Clone() ), + pBindings( pBind ) +{ + for ( USHORT nVal = 0; nVal < pItem->GetValueCount(); ++nVal ) + InsertItem( nVal+1, pItem->GetValueTextByPos(nVal) ); + CheckItem( pItem->GetValue() + 1, TRUE ); +} + +//------------------------------------------------------------------------- + +SfxEnumMenu::~SfxEnumMenu() +{ + delete pItem; +} + +//------------------------------------------------------------------------- + +void SfxEnumMenu::Select() +{ + pItem->SetValue( GetCurItemId()-1 ); + pBindings->GetDispatcher()->Execute( nSlot, + SFX_CALLMODE_ASYNCHRON|SFX_CALLMODE_RECORD, + pItem, 0L, 0L ); +} + +//-------------------------------------------------------------------- + +void SfxMenuControl::SetOwnMenu( SfxVirtualMenu* pMenu ) +{ + pOwnMenu = pMenu; + if ( pSubMenu ) + pSubMenu->SetParentMenu( pMenu ); +} + + +//-------------------------------------------------------------------- + +// binds the instance to the specified id and assignes the title + +void SfxMenuControl::Bind( + SfxVirtualMenu* pOwn, + USHORT nSlotId, + const String& rTitle, + const String &rHelpText, + SfxBindings &rBindings ) +{ + DBG_MEMTEST(); + + aTitle = rTitle; + aHelpText = rHelpText; + pOwnMenu = pOwn; + pSubMenu = 0; + if ( pOwn ) + SfxControllerItem::Bind(nSlotId, &rBindings); + else + SetId( nSlotId ); + + DBG( CheckConfigure_Impl(SFX_SLOT_MENUCONFIG) ); +} + + +//-------------------------------------------------------------------- + +// binds the item to the specified menu and assignes the title + +void SfxMenuControl::Bind( + SfxVirtualMenu* pOwn, + USHORT nSlotId, + SfxVirtualMenu& rMenu, + const String& rTitle, + const String &rHelpText, + SfxBindings &rBindings ) +{ + DBG_MEMTEST(); + SetId( nSlotId ); + SetBindings(rBindings); + pOwnMenu = pOwn; + pSubMenu = &rMenu; + aTitle = rTitle; + aHelpText = rHelpText; +} + +//-------------------------------------------------------------------- + +// ctor for explicit registration + +SfxMenuControl::SfxMenuControl( BOOL bShowStrings ) +: pOwnMenu(0), + pSubMenu(0), + b_ShowStrings(bShowStrings) +{ + DBG_MEMTEST(); +} + +//-------------------------------------------------------------------- + +// ctor for array + +SfxMenuControl::SfxMenuControl(): + pOwnMenu(0), + pSubMenu(0), + b_ShowStrings(FALSE) +{ + DBG_MEMTEST(); +} + +//-------------------------------------------------------------------- + +SfxMenuControl::SfxMenuControl(USHORT nSlotId, SfxBindings& rBindings): + SfxControllerItem(nSlotId, rBindings), + pOwnMenu(0), + pSubMenu(0), + b_ShowStrings(FALSE) +{ + DBG_MEMTEST(); + + // Dieser Ctor soll es erm"oglichen, w"ahrend der Konstruktion schon + // auf die Bindings zur"uckgreifen zu k"onnen, aber gebunden wird + // wie immer erst sp"ater. Anwendung z.B. wenn im ctor der abgeleiteten + // Klasse z.B. ein StatusForwarder erzeugt werden soll. + UnBind(); +} + + +//-------------------------------------------------------------------- + +// dtor + +SfxMenuControl::~SfxMenuControl() +{ + if ( SfxMacroConfig::IsMacroSlot( GetId() ) ) + SFX_APP()->GetMacroConfig()->ReleaseSlotId(GetId()); + delete pSubMenu; +} + +void SfxMenuControl::RemovePopup() +{ + DELETEZ( pSubMenu ); +} + +//-------------------------------------------------------------------- + +// changes the state in the virtual menu + +void SfxMenuControl::StateChanged +( + USHORT nSID, + SfxItemState eState, + const SfxPoolItem* pState +) +{ + (void)nSID; //unused + DBG_MEMTEST(); + DBG_ASSERT( nSID == GetId(), "strange SID" ); + DBG_ASSERT( pOwnMenu != 0, "setting state to dangling SfxMenuControl" ); + + FASTBOOL bIsObjMenu = + GetId() >= SID_OBJECTMENU0 && GetId() < SID_OBJECTMENU_LAST; + + // enabled/disabled-Flag pauschal korrigieren + +#ifdef UNIX + if (nSID == SID_PASTE) + pOwnMenu->EnableItem( GetId(), TRUE ); + else +#endif + pOwnMenu->EnableItem( GetId(), bIsObjMenu + ? 0 != pOwnMenu->GetSVMenu()->GetPopupMenu( GetId() ) + : eState != SFX_ITEM_DISABLED ); + + if ( eState != SFX_ITEM_AVAILABLE ) + { + // checken nur bei nicht-Object-Menus + if ( !bIsObjMenu ) + pOwnMenu->CheckItem( GetId(), FALSE ); + + // SetItemText flackert in MenuBar insbes. unter OS/2 (Bug #20658) + if ( // !bIsObjMenu && nicht wegen "Format/Datenbank" + pOwnMenu->GetSVMenu()->GetItemText( GetId() ) != GetTitle() ) + { + DBG_WARNING("Title of menu item changed - please check if this needs correction!"); + // pOwnMenu->SetItemText( GetId(), GetTitle() ); + } + return; + } + + // ggf. das alte Enum-Menu entfernen/loeschen + //! delete pOwnMenu->GetMenu().ChangePopupMenu( GetId(), 0 ); + + bool bCheck = false; + if ( pState->ISA(SfxBoolItem) ) + { + // BoolItem fuer checken + DBG_ASSERT( GetId() < SID_OBJECTMENU0 || GetId() > SID_OBJECTMENU_LAST, + "SfxBoolItem not allowed for SID_OBJECTMENUx" ); + bCheck = ((const SfxBoolItem*)pState)->GetValue(); + } + else if ( pState->ISA(SfxEnumItemInterface) && + ((SfxEnumItemInterface *)pState)->HasBoolValue() ) + { + // EnumItem wie Bool behandeln + DBG_ASSERT( GetId() < SID_OBJECTMENU0 || GetId() > SID_OBJECTMENU_LAST, + "SfxEnumItem not allowed for SID_OBJECTMENUx" ); + bCheck = ((SfxEnumItemInterface *)pState)->GetBoolValue(); + } + else if ( ( b_ShowStrings || bIsObjMenu ) && pState->ISA(SfxStringItem) ) + { + // MenuText aus SfxStringItem holen + String aStr( ((const SfxStringItem*)pState)->GetValue() ); + if ( aStr.CompareToAscii("($1)",4) == COMPARE_EQUAL ) + { + String aEntry(SfxResId(STR_UPDATEDOC)); + aEntry += ' '; + aEntry += aStr.Copy(4); + aStr = aEntry; + } + else if ( aStr.CompareToAscii("($2)",4) == COMPARE_EQUAL ) + { + String aEntry(SfxResId(STR_CLOSEDOC_ANDRETURN)); + aEntry += aStr.Copy(4); + aStr = aEntry; + } + + pOwnMenu->SetItemText( GetId(), aStr ); + } + +#ifdef enum_item_menu_ok + else if ( aType == TYPE(SfxEnumItem) ) + { + DBG_ASSERT( GetId() < SID_OBJECTMENU0 || GetId() > SID_OBJECTMENU_LAST, + "SfxEnumItem not allowed for SID_OBJECTMENUx" ); + pOwnMenu->GetMenu().ChangePopupMenu( GetId(), &GetBindings(), + new SfxEnumMenu( GetId(), *(const SfxEnumItem*)pState ) ); + } +#endif + + pOwnMenu->CheckItem( GetId(), bCheck ); +} + +//-------------------------------------------------------------------- + +SfxMenuControl* SfxMenuControl::CreateImpl( USHORT /*nId*/, Menu& /*rMenu*/, SfxBindings& /*rBindings*/ ) +{ + return new SfxMenuControl( TRUE ); +} + +//-------------------------------------------------------------------- + +void SfxMenuControl::RegisterControl( USHORT nSlotId, SfxModule *pMod ) +{ + RegisterMenuControl( pMod, new SfxMenuCtrlFactory( + SfxMenuControl::CreateImpl, TYPE(SfxStringItem), nSlotId ) ); +} + +//-------------------------------------------------------------------- +void SfxMenuControl::RegisterMenuControl(SfxModule* pMod, SfxMenuCtrlFactory* pFact) +{ + SFX_APP()->RegisterMenuControl_Impl( pMod, pFact ); +} + +SfxMenuControl* SfxMenuControl::CreateControl( USHORT nId, Menu &rMenu, SfxBindings &rBindings ) +{ + TypeId aSlotType = SFX_SLOTPOOL().GetSlotType(nId); + if ( aSlotType ) + { + SfxApplication *pApp = SFX_APP(); + SfxDispatcher *pDisp = rBindings.GetDispatcher_Impl(); + SfxModule *pMod = pDisp ? SfxModule::GetActiveModule( pDisp->GetFrame() ) :0; + if ( pMod ) + { + SfxMenuCtrlFactArr_Impl *pFactories = pMod->GetMenuCtrlFactories_Impl(); + if ( pFactories ) + { + SfxMenuCtrlFactArr_Impl &rFactories = *pFactories; + for ( USHORT nFactory = 0; nFactory < rFactories.Count(); ++nFactory ) + if ( rFactories[nFactory]->nTypeId == aSlotType && + ( ( rFactories[nFactory]->nSlotId == 0 ) || + ( rFactories[nFactory]->nSlotId == nId) ) ) + return rFactories[nFactory]->pCtor( nId, rMenu, rBindings ); + } + } + + SfxMenuCtrlFactArr_Impl &rFactories = pApp->GetMenuCtrlFactories_Impl(); + + for ( USHORT nFactory = 0; nFactory < rFactories.Count(); ++nFactory ) + if ( rFactories[nFactory]->nTypeId == aSlotType && + ( ( rFactories[nFactory]->nSlotId == 0 ) || + ( rFactories[nFactory]->nSlotId == nId) ) ) + return rFactories[nFactory]->pCtor( nId, rMenu, rBindings ); + } + return 0; +} + +BOOL SfxMenuControl::IsSpecialControl( USHORT nId, SfxModule* pMod ) +{ + TypeId aSlotType = SFX_SLOTPOOL().GetSlotType( nId ); + if ( aSlotType ) + { + if ( pMod ) + { + SfxMenuCtrlFactArr_Impl *pFactories = pMod->GetMenuCtrlFactories_Impl(); + if ( pFactories ) + { + SfxMenuCtrlFactArr_Impl &rFactories = *pFactories; + for ( USHORT nFactory = 0; nFactory < rFactories.Count(); ++nFactory ) + if ( rFactories[nFactory]->nTypeId == aSlotType && + ( ( rFactories[nFactory]->nSlotId == 0 ) || + ( rFactories[nFactory]->nSlotId == nId) ) ) + return TRUE; + } + } + + SfxMenuCtrlFactArr_Impl &rFactories = SFX_APP()->GetMenuCtrlFactories_Impl(); + + for ( USHORT nFactory = 0; nFactory < rFactories.Count(); ++nFactory ) + if ( rFactories[nFactory]->nTypeId == aSlotType && + ( ( rFactories[nFactory]->nSlotId == 0 ) || + ( rFactories[nFactory]->nSlotId == nId) ) ) + return TRUE; + } + return 0; +} + +//-------------------------------------------------------------------- + +PopupMenu* SfxMenuControl::GetPopup () const +{ + if (GetPopupMenu()) + return (PopupMenu*)GetPopupMenu()->GetSVMenu(); + else + return 0; +} + +long Select_Impl( void* pHdl, void* pVoid ); + +SFX_IMPL_MENU_CONTROL( SfxAppMenuControl_Impl, SfxStringItem ); + +SfxAppMenuControl_Impl::SfxAppMenuControl_Impl( + USHORT nPos, Menu& rMenu, SfxBindings& rBindings ) + : SfxMenuControl( nPos, rBindings ), pMenu(0) +{ + String aText = rMenu.GetItemText( nPos ); + + // Determine the current background color setting for menus + const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); + m_nSymbolsStyle = rSettings.GetSymbolsStyle(); + m_bWasHiContrastMode = rSettings.GetHighContrastMode(); + m_bShowMenuImages = rSettings.GetUseImagesInMenus(); + + Reference<com::sun::star::lang::XMultiServiceFactory> aXMultiServiceFactory(::comphelper::getProcessServiceFactory()); + ::framework::MenuConfiguration aConf( aXMultiServiceFactory ); + Reference<com::sun::star::frame::XFrame> aXFrame( GetBindings().GetDispatcher_Impl()->GetFrame()->GetFrame().GetFrameInterface() ); + pMenu = aConf.CreateBookmarkMenu( aXFrame, GetId() == SID_NEWDOCDIRECT ? BOOKMARK_NEWMENU : BOOKMARK_WIZARDMENU ); + if( pMenu ) + { + pMenu->SetSelectHdl( Link( &(this->GetBindings()), Select_Impl ) ); + pMenu->SetActivateHdl( LINK(this, SfxAppMenuControl_Impl, Activate) ); + rMenu.SetPopupMenu( nPos, pMenu ); + } +} + +SfxAppMenuControl_Impl::~SfxAppMenuControl_Impl() +{ + delete pMenu; +} + +IMPL_LINK( SfxAppMenuControl_Impl, Activate, Menu *, pActMenu ) +{ + if ( pActMenu ) + { + const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); + ULONG nSymbolsStyle = rSettings.GetSymbolsStyle(); + BOOL bIsHiContrastMode = rSettings.GetHighContrastMode(); + BOOL bShowMenuImages = rSettings.GetUseImagesInMenus(); + + if (( nSymbolsStyle != m_nSymbolsStyle ) || + ( bIsHiContrastMode != m_bWasHiContrastMode ) || + ( bShowMenuImages != m_bShowMenuImages )) + { + m_nSymbolsStyle = nSymbolsStyle; + m_bWasHiContrastMode = bIsHiContrastMode; + m_bShowMenuImages = bShowMenuImages; + + USHORT nCount = pActMenu->GetItemCount(); + for ( USHORT nSVPos = 0; nSVPos < nCount; nSVPos++ ) + { + USHORT nItemId = pActMenu->GetItemId( nSVPos ); + if ( pActMenu->GetItemType( nSVPos ) != MENUITEM_SEPARATOR ) + { + if ( bShowMenuImages ) + { + sal_Bool bImageSet = sal_False; + ::rtl::OUString aImageId; + ::framework::MenuConfiguration::Attributes* pMenuAttributes = + (::framework::MenuConfiguration::Attributes*)pMenu->GetUserValue( nItemId ); + + if ( pMenuAttributes ) + aImageId = pMenuAttributes->aImageId; // Retrieve image id from menu attributes + + if ( aImageId.getLength() > 0 ) + { + Reference< ::com::sun::star::frame::XFrame > xFrame; + Image aImage = GetImage( xFrame, aImageId, FALSE, bIsHiContrastMode ); + if ( !!aImage ) + { + bImageSet = sal_True; + pActMenu->SetItemImage( nItemId, aImage ); + } + } + + String aCmd( pActMenu->GetItemCommand( nItemId ) ); + if ( !bImageSet && aCmd.Len() ) + { + Image aImage = SvFileInformationManager::GetImage( + INetURLObject(aCmd), FALSE, bIsHiContrastMode ); + if ( !!aImage ) + pActMenu->SetItemImage( nItemId, aImage ); + } + } + else + pActMenu->SetItemImage( nItemId, Image() ); + } + } + } + + return TRUE; + } + + return FALSE; +} + +SfxUnoMenuControl* SfxMenuControl::CreateControl( const String& rCmd, + USHORT nId, Menu& rMenu, SfxBindings &rBindings, SfxVirtualMenu* pVirt ) +{ + return new SfxUnoMenuControl( rCmd, nId, rMenu, rBindings, pVirt ); +} + +SfxUnoMenuControl* SfxMenuControl::CreateControl( const String& rCmd, + USHORT nId, Menu& rMenu, const String& sItemText, const String& sHelpText, + SfxBindings& rBindings, SfxVirtualMenu* pVirt) +{ + return new SfxUnoMenuControl( rCmd, nId, rMenu, sItemText, sHelpText, rBindings, pVirt); +} + +SfxUnoMenuControl::SfxUnoMenuControl( const String& rCmd, USHORT nSlotId, + Menu& rMenu, SfxBindings& rBindings, SfxVirtualMenu* pVirt ) + : SfxMenuControl( nSlotId, rBindings ) +{ + Bind( pVirt, nSlotId, rMenu.GetItemText(nSlotId), + rMenu.GetHelpText(nSlotId), rBindings); + UnBind(); + pUnoCtrl = new SfxUnoControllerItem( this, rBindings, rCmd ); + pUnoCtrl->acquire(); + pUnoCtrl->GetNewDispatch(); +} + +SfxUnoMenuControl::SfxUnoMenuControl( + const String& rCmd, USHORT nSlotId, Menu& /*rMenu*/, + const String& rItemText, const String& rHelpText, + SfxBindings& rBindings, SfxVirtualMenu* pVirt) + : SfxMenuControl( nSlotId, rBindings ) +{ + Bind( pVirt, nSlotId, rItemText, rHelpText, rBindings); + UnBind(); + pUnoCtrl = new SfxUnoControllerItem( this, rBindings, rCmd ); + pUnoCtrl->acquire(); + pUnoCtrl->GetNewDispatch(); +} + +SfxUnoMenuControl::~SfxUnoMenuControl() +{ + pUnoCtrl->UnBind(); + pUnoCtrl->release(); +} + +void SfxUnoMenuControl::Select() +{ + pUnoCtrl->Execute(); +} diff --git a/sfx2/source/menu/mnumgr.cxx b/sfx2/source/menu/mnumgr.cxx new file mode 100755 index 000000000000..77dbd0dcb885 --- /dev/null +++ b/sfx2/source/menu/mnumgr.cxx @@ -0,0 +1,641 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +#include <com/sun/star/embed/VerbDescriptor.hpp> +#include <com/sun/star/embed/VerbAttributes.hpp> +#include <com/sun/star/container/XNamed.hpp> + +#ifdef SOLARIS +// HACK: prevent conflict between STLPORT and Workshop headers on Solaris 8 +#include <ctime> +#endif + +#include <string> // HACK: prevent conflict between STLPORT and Workshop headers +#include <cstdarg> // std::va_list + +#ifndef _POINTR_HXX //autogen +#include <vcl/pointr.hxx> +#endif +#ifndef GCC +#endif + +#include <unotools/streamwrap.hxx> +#include <sfx2/objsh.hxx> +#include <framework/menuconfiguration.hxx> +#include <framework/addonmenu.hxx> +#include <comphelper/processfactory.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <unotools/lingucfg.hxx> +#include <tools/urlobj.hxx> +#include <unotools/pathoptions.hxx> +#include <svl/stritem.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <osl/file.hxx> +#include <vcl/graph.hxx> +#include <svtools/filter.hxx> +#include <svl/lngmisc.hxx> + +#include <sfx2/mnumgr.hxx> + +#define _SVSTDARR_USHORTS +#include <svl/svstdarr.hxx> +#include <svtools/menuoptions.hxx> + +#include "virtmenu.hxx" +#include <sfx2/msg.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/minstack.hxx> +#include <sfx2/app.hxx> +#include "sfxtypes.hxx" +#include <sfx2/bindings.hxx> +#include "mnucfga.hxx" +#include "sfx2/sfxresid.hxx" +#include <sfx2/macrconf.hxx> +#include <sfx2/msgpool.hxx> +#include <sfx2/sfx.hrc> +#include "menu.hrc" +#include <sfx2/viewfrm.hxx> +#include <sfx2/viewsh.hxx> +#include <sfx2/objface.hxx> +#include "thessubmenu.hxx" + + +static const USHORT nCompatVersion = 4; +static const USHORT 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 = 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(); + USHORT nr=0; + for ( USHORT 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 + USHORT 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 (USHORT i = 0; (size_t)i < nNumSynonyms; ++i) + { + //! item ids should start with values > 0, since 0 has special meaning + const USHORT 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 ) + { + USHORT n, nCount = pSVMenu->GetItemCount(); + for ( n=0; n<nCount; n++ ) + { + USHORT nId = pSVMenu->GetItemId( 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; n<nCount; n++ ) + { + USHORT nId = aPop.GetItemId( n ); + pSVMenu->InsertItem( nId, aPop.GetItemText( nId ), aPop.GetItemBits( nId ) ); + } + } + } + + pVMenu = new SfxVirtualMenu( pSVMenu, FALSE, *pBindings, TRUE, TRUE ); + } + + Construct(*pVMenu); + if (pOldVirtMenu) + { + delete pOldVirtMenu; + pBindings->LEAVEREGISTRATIONS(); + } +} + +// ------------------------------------------------------------------------ + +// executes the function for the selected item +IMPL_LINK( SfxMenuManager, Select, Menu *, pSelMenu ) +{ + DBG_MEMTEST(); + + USHORT nId = (USHORT) 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 TRUE; +} + +//-------------------------------------------------------------------- + +void SfxMenuManager::Construct_Impl( Menu* pSVMenu, BOOL bWithHelp ) +{ + SfxVirtualMenu *pOldVirtMenu=0; + if ( pMenu ) + { + // Es wird umkonfiguriert + pOldVirtMenu = pMenu; + pBindings->ENTERREGISTRATIONS(); + } + + TryToHideDisabledEntries_Impl( pSVMenu ); + SfxVirtualMenu *pVMenu = new SfxVirtualMenu( pSVMenu, bWithHelp, *pBindings, 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 ); +} + +//-------------------------------------------------------------------- + +USHORT SfxPopupMenuManager::Execute( const Point& rPos, Window* pWindow ) +{ + DBG_MEMTEST(); + USHORT 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 ) + + +//-------------------------------------------------------------------- + +USHORT 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 ) ); + USHORT nId = pPopMenu->Execute( pWindow, rPoint ); + pPopMenu->SetSelectHdl( Link() ); + + if ( nId ) + GetBindings().GetDispatcher()->_Execute( nId, SFX_CALLMODE_RECORD, pArgs, pArg1 ); + + return nId; +} + +//-------------------------------------------------------------------- + +USHORT 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, FALSE, *pBindings, TRUE, TRUE ); + Construct( *pMenu ); + pBindings->LEAVEREGISTRATIONS(); +} + +//------------------------------------------------------------------------- + +void SfxPopupMenuManager::InsertSeparator( USHORT nPos ) +{ + pSVMenu->InsertSeparator( nPos ); +} + +//------------------------------------------------------------------------- + +void SfxPopupMenuManager::InsertItem( USHORT nId, const String& rName, MenuItemBits nBits, const rtl::OString& rHelpId, USHORT nPos ) +{ + pSVMenu->InsertItem( nId, rName, nBits,nPos ); + pSVMenu->SetHelpId( nId, rHelpId ); +} + +//------------------------------------------------------------------------- + +void SfxPopupMenuManager::RemoveItem( USHORT nId ) +{ + pSVMenu->RemoveItem( nId ); +} + +//------------------------------------------------------------------------- + +void SfxPopupMenuManager::CheckItem( USHORT nId, BOOL bCheck ) +{ + pSVMenu->CheckItem( nId, bCheck ); +} + +void SfxPopupMenuManager::AddClipboardFunctions() +{ + bAddClipboardFuncs = TRUE; +} + +SfxMenuManager::SfxMenuManager( Menu* pMenuArg, SfxBindings &rBindings ) +: pMenu(0), + pOldMenu(0), + pBindings(&rBindings), + pResMgr(NULL), + nType(0) +{ + bAddClipboardFuncs = FALSE; + SfxVirtualMenu* pVMenu = new SfxVirtualMenu( pMenuArg, FALSE, rBindings, TRUE, 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 ); + USHORT n, nCount = pSVMenu->GetItemCount(); + for ( n=0; n<nCount; n++ ) + { + USHORT nId = pSVMenu->GetItemId( 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; n<nCount; n++ ) + { + USHORT nId = aPop.GetItemId( n ); + pSVMenu->InsertItem( 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 ); + USHORT n, nCount = pSVMenu->GetItemCount(); + for ( n=0; n<nCount; n++ ) + { + USHORT nId = pSVMenu->GetItemId( 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; n<nCount; n++ ) + { + USHORT nId = aPop.GetItemId( n ); + pSVMenu->InsertItem( 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(); +} + diff --git a/sfx2/source/menu/objmnctl.cxx b/sfx2/source/menu/objmnctl.cxx new file mode 100644 index 000000000000..e9d609151504 --- /dev/null +++ b/sfx2/source/menu/objmnctl.cxx @@ -0,0 +1,165 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" +#include <com/sun/star/embed/VerbDescriptor.hpp> +#include <com/sun/star/embed/VerbAttributes.hpp> + +#include <tools/list.hxx> +#ifndef _MENU_HXX //autogen +#include <vcl/menu.hxx> +#endif +#ifndef _SXSTRITEM_HXX //autogen +#include <svl/stritem.hxx> +#endif +#ifndef GCC +#endif + +#include <sfx2/sfxsids.hrc> +#include "objmnctl.hxx" +#include <sfx2/dispatch.hxx> +#include <sfx2/viewsh.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/objsh.hxx> + +// STATIC DATA ----------------------------------------------------------- + +SFX_IMPL_MENU_CONTROL(SfxObjectVerbsControl, SfxStringItem); + +using namespace com::sun::star; +//-------------------------------------------------------------------- + +/* + Ctor; setzt Select-Handler am Menu und traegt Menu + in seinen Parent ein. + */ + +SfxObjectVerbsControl::SfxObjectVerbsControl(USHORT nSlotId, Menu &rMenu, SfxBindings &rBindings) + : SfxMenuControl( nSlotId, rBindings ) + , pMenu(new PopupMenu) + , rParent(rMenu) +{ + rMenu.SetPopupMenu(nSlotId, pMenu); + pMenu->SetSelectHdl(LINK(this, SfxObjectVerbsControl, MenuSelect)); + FillMenu(); +} + +//-------------------------------------------------------------------- + +/* + Fuellt das Menu mit den aktuellen Verben aus der ViewShell. + */ + +void SfxObjectVerbsControl::FillMenu() +{ + pMenu->Clear(); + SfxViewShell *pView = GetBindings().GetDispatcher()->GetFrame()->GetViewShell(); + if (pView) + { + SfxObjectShell* pDoc = pView->GetObjectShell(); + const com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor >& aVerbs = pView->GetVerbs(); + if ( aVerbs.getLength() ) + { + USHORT nSlotId = SID_VERB_START; + for (USHORT 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; + + DBG_ASSERT(nSlotId <= SID_VERB_END, "Zuviele Verben!"); + if (nSlotId > SID_VERB_END) + break; + + pMenu->InsertItem(nSlotId++, aVerbs[n].VerbName); + } + } + } + + rParent.EnableItem( GetId(), (BOOL)pMenu->GetItemCount() ); +} + +//-------------------------------------------------------------------- + +/* + Statusbenachrichtigung; + fuellt gfs. das Menu mit den aktuellen Verben aus der ViewShell. + der DocumentShell. + Ist die Funktionalit"at disabled, wird der entsprechende + Menueeintrag im Parentmenu disabled, andernfalls wird er enabled. + */ + +void SfxObjectVerbsControl::StateChanged( + USHORT /*nSID*/, + SfxItemState eState, + const SfxPoolItem* /*pState*/ ) +{ + rParent.EnableItem(GetId(), SFX_ITEM_AVAILABLE == eState ); + if ( SFX_ITEM_AVAILABLE == eState ) + FillMenu(); +} + +//-------------------------------------------------------------------- + +/* + Select-Handler des Menus; + das selektierte Verb mit ausgef"uhrt, + */ + +IMPL_LINK_INLINE_START( SfxObjectVerbsControl, MenuSelect, Menu *, pSelMenu ) +{ + const USHORT nSlotId = pSelMenu->GetCurItemId(); + if( nSlotId ) + GetBindings().Execute(nSlotId); + return 1; +} +IMPL_LINK_INLINE_END( SfxObjectVerbsControl, MenuSelect, Menu *, pSelMenu ) + +//-------------------------------------------------------------------- + +/* + Dtor; gibt das Menu frei. + */ + +SfxObjectVerbsControl::~SfxObjectVerbsControl() +{ + delete pMenu; +} + +//-------------------------------------------------------------------- + +PopupMenu* SfxObjectVerbsControl::GetPopup() const +{ + return pMenu; +} + + diff --git a/sfx2/source/menu/thessubmenu.cxx b/sfx2/source/menu/thessubmenu.cxx new file mode 100755 index 000000000000..d82c0a6dbdf3 --- /dev/null +++ b/sfx2/source/menu/thessubmenu.cxx @@ -0,0 +1,241 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: thessubmenu.cxx,v $ + * $Revision: 1.0 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/linguistic2/XThesaurus.hpp> +#include <com/sun/star/linguistic2/XMeaning.hpp> +#include <com/sun/star/linguistic2/XLinguServiceManager.hpp> + +#include <comphelper/processfactory.hxx> +#include <svl/stritem.hxx> +#include <tools/debug.hxx> +#include <vcl/graph.hxx> +#include <svtools/filter.hxx> + + +#include <vector> + +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/viewsh.hxx> +#include "thessubmenu.hxx" + + +using namespace ::com::sun::star; +using ::rtl::OUString; + + +// STATIC DATA ----------------------------------------------------------- + +SFX_IMPL_MENU_CONTROL(SfxThesSubMenuControl, SfxStringItem); + +//////////////////////////////////////////////////////////// + + +/* + Ctor; setzt Select-Handler am Menu und traegt Menu + in seinen Parent ein. + */ +SfxThesSubMenuControl::SfxThesSubMenuControl( USHORT nSlotId, Menu &rMenu, SfxBindings &rBindings ) + : SfxMenuControl( nSlotId, rBindings ), + pMenu(new PopupMenu), + rParent(rMenu) +{ + rMenu.SetPopupMenu(nSlotId, pMenu); + pMenu->SetSelectHdl(LINK(this, SfxThesSubMenuControl, MenuSelect)); + pMenu->Clear(); + rParent.EnableItem( GetId(), FALSE ); +} + + +SfxThesSubMenuControl::~SfxThesSubMenuControl() +{ + delete pMenu; +} + + +/* + Statusbenachrichtigung; + Ist die Funktionalit"at disabled, wird der entsprechende + Menueeintrag im Parentmenu disabled, andernfalls wird er enabled. + */ +void SfxThesSubMenuControl::StateChanged( + USHORT /*nSID*/, + SfxItemState eState, + const SfxPoolItem* /*pState*/ ) +{ + rParent.EnableItem(GetId(), SFX_ITEM_AVAILABLE == eState ); +} + + +/* + Select-Handler des Menus; + das selektierte Verb mit ausgef"uhrt, + */ +IMPL_LINK_INLINE_START( SfxThesSubMenuControl, MenuSelect, Menu *, pSelMenu ) +{ + const USHORT nSlotId = pSelMenu->GetCurItemId(); + if( nSlotId ) + GetBindings().Execute(nSlotId); + return 1; +} +IMPL_LINK_INLINE_END( SfxThesSubMenuControl, MenuSelect, Menu *, pSelMenu ) + + +PopupMenu* SfxThesSubMenuControl::GetPopup() const +{ + return pMenu; +} + + +//////////////////////////////////////////////////////////// + +OUString SfxThesSubMenuHelper::GetText( + const String &rLookUpString, + xub_StrLen nDelimPos ) +{ + return OUString( rLookUpString.Copy( 0, nDelimPos ) ); +} + + +void SfxThesSubMenuHelper::GetLocale( + lang::Locale /*out */ &rLocale, + const String &rLookUpString, + xub_StrLen nDelimPos ) +{ + String aIsoLang( rLookUpString.Copy( nDelimPos + 1) ); + const xub_StrLen nPos = aIsoLang.Search( '-' ); + if (nPos != STRING_NOTFOUND) + { + rLocale.Language = aIsoLang.Copy( 0, nPos ); + rLocale.Country = aIsoLang.Copy( nPos + 1 ); + rLocale.Variant = String::EmptyString(); + } +} + + +SfxThesSubMenuHelper::SfxThesSubMenuHelper() +{ + try + { + uno::Reference< lang::XMultiServiceFactory > xMSF( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW ); + m_xLngMgr = uno::Reference< linguistic2::XLinguServiceManager >( xMSF->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.linguistic2.LinguServiceManager" ))), uno::UNO_QUERY_THROW ); + m_xThesarus = m_xLngMgr->getThesaurus(); + } + catch (uno::Exception &e) + { + (void) e; + DBG_ASSERT( 0, "failed to get thesaurus" ); + } +} + + +SfxThesSubMenuHelper::~SfxThesSubMenuHelper() +{ +} + + +bool SfxThesSubMenuHelper::IsSupportedLocale( const lang::Locale & rLocale ) const +{ + return m_xThesarus.is() && m_xThesarus->hasLocale( rLocale ); +} + + +bool SfxThesSubMenuHelper::GetMeanings( + std::vector< OUString > & rSynonyms, + const OUString & rWord, + const lang::Locale & rLocale, + sal_Int16 nMaxSynonms ) +{ + bool bHasMoreSynonyms = false; + rSynonyms.clear(); + if (IsSupportedLocale( rLocale ) && rWord.getLength() && nMaxSynonms > 0) + { + try + { + // get all meannings + const uno::Sequence< uno::Reference< linguistic2::XMeaning > > aMeaningSeq( + m_xThesarus->queryMeanings( rWord, rLocale, uno::Sequence< beans::PropertyValue >() )); + const uno::Reference< linguistic2::XMeaning > *pxMeaning = aMeaningSeq.getConstArray(); + const sal_Int32 nMeanings = aMeaningSeq.getLength(); + + // iterate over all meanings until nMaxSynonms are found or all meanings are processed + sal_Int32 nCount = 0; + sal_Int32 i = 0; + for ( ; i < nMeanings && nCount < nMaxSynonms; ++i) + { + const uno::Sequence< OUString > aSynonymSeq( pxMeaning[i]->querySynonyms() ); + const OUString *pSynonyms = aSynonymSeq.getConstArray(); + const sal_Int32 nSynonyms = aSynonymSeq.getLength(); + sal_Int32 k = 0; + for ( ; k < nSynonyms && nCount < nMaxSynonms; ++k) + { + rSynonyms.push_back( pSynonyms[k] ); + ++nCount; + } + bHasMoreSynonyms = k < nSynonyms; // any synonym from this meaning skipped? + } + + bHasMoreSynonyms |= i < nMeanings; // any meaning skipped? + } + catch (uno::Exception &e) + { + (void) e; + DBG_ASSERT( 0, "failed to get synonyms" ); + } + } + return bHasMoreSynonyms; +} + + +String SfxThesSubMenuHelper::GetThesImplName( const lang::Locale &rLocale ) const +{ + String aRes; + DBG_ASSERT( m_xLngMgr.is(), "LinguServiceManager missing" ); + if (m_xLngMgr.is()) + { + uno::Sequence< OUString > aServiceNames = m_xLngMgr->getConfiguredServices( + OUString::createFromAscii("com.sun.star.linguistic2.Thesaurus"), rLocale ); + // there should be at most one thesaurus configured for each language + DBG_ASSERT( aServiceNames.getLength() <= 1, "more than one thesaurus found. Should not be possible" ); + if (aServiceNames.getLength() == 1) + aRes = aServiceNames[0]; + } + return aRes; +} + +//////////////////////////////////////////////////////////// + + diff --git a/sfx2/source/menu/thessubmenu.hxx b/sfx2/source/menu/thessubmenu.hxx new file mode 100644 index 000000000000..0b86a534de52 --- /dev/null +++ b/sfx2/source/menu/thessubmenu.hxx @@ -0,0 +1,103 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: thessubmenu.hxx,v $ + * $Revision: 1.0 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _THESSUBMENU_HXX_ +#define _THESSUBMENU_HXX_ + +#include <com/sun/star/linguistic2/XThesaurus.hpp> +#include <com/sun/star/linguistic2/XLinguServiceManager.hpp> + +#include <vcl/menu.hxx> +#include <sfx2/mnuitem.hxx> + +class SfxBindings; +class PopupMenu; +class Menu; + +namespace css = ::com::sun::star; + +//////////////////////////////////////////////////////////// + +class SfxThesSubMenuControl : public SfxMenuControl +{ + PopupMenu* pMenu; + Menu& rParent; + +private: + virtual void StateChanged( USHORT, SfxItemState, const SfxPoolItem* pState ); + DECL_LINK( MenuSelect, Menu * ); + +public: + SfxThesSubMenuControl(USHORT, Menu&, SfxBindings&); + ~SfxThesSubMenuControl(); + + virtual PopupMenu* GetPopup() const; + + SFX_DECL_MENU_CONTROL(); +}; + +//////////////////////////////////////////////////////////// + +class SfxThesSubMenuHelper +{ + css::uno::Reference< css::linguistic2::XLinguServiceManager > m_xLngMgr; + css::uno::Reference< css::linguistic2::XThesaurus > m_xThesarus; + +private: + + // don't use copy c-tor and assignment operator + SfxThesSubMenuHelper( const SfxThesSubMenuHelper & ); + SfxThesSubMenuHelper & operator = ( const SfxThesSubMenuHelper & ); + +public: + SfxThesSubMenuHelper(); + ~SfxThesSubMenuHelper(); + + static ::rtl::OUString GetText( const String &rLookUpString, xub_StrLen nDelimPos ); + + // returns the Locale to be used for the selected text when the thesaurus is to be called + static void GetLocale( css::lang::Locale /*out */ &rLocale, const String &rLookUpString, xub_StrLen nDelimPos ); + + // returns true if the locale is upported by the theasaurus + bool IsSupportedLocale( const css::lang::Locale & rLocale ) const; + + // get the first nMax Synonym entries, even if different meanings need to be evaluated + bool GetMeanings( std::vector< ::rtl::OUString > & rSynonyms, const ::rtl::OUString & rWord, const css::lang::Locale & rLocale, sal_Int16 nMaxSynonms ); + + String GetThesImplName( const css::lang::Locale &rLocale ) const; +}; + +//////////////////////////////////////////////////////////// + + +#endif + + diff --git a/sfx2/source/menu/virtmenu.cxx b/sfx2/source/menu/virtmenu.cxx new file mode 100644 index 000000000000..f0408a66a408 --- /dev/null +++ b/sfx2/source/menu/virtmenu.cxx @@ -0,0 +1,1361 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +#include <sot/factory.hxx> +#include <svtools/menuoptions.hxx> +#include <svtools/imagemgr.hxx> +#include <svl/imageitm.hxx> +#include <com/sun/star/container/XEnumeration.hpp> +#include <com/sun/star/frame/XDesktop.hpp> +#include <com/sun/star/frame/XFramesSupplier.hpp> +#include <comphelper/processfactory.hxx> +#include <toolkit/unohlp.hxx> +#include <tools/urlobj.hxx> + +#include "virtmenu.hxx" +#include <sfx2/msgpool.hxx> +#include "statcach.hxx" +#include <sfx2/msg.hxx> +#include "idpool.hxx" +#include <sfx2/mnuitem.hxx> +#include <sfx2/mnumgr.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/app.hxx> +#include "sfxtypes.hxx" +#include "arrdecl.hxx" +#include <sfx2/sfx.hrc> +#include <sfx2/viewsh.hxx> +#include "sfxpicklist.hxx" +#include <sfx2/macrconf.hxx> +#include "sfx2/sfxresid.hxx" +#include "menu.hrc" +#include "sfx2/imagemgr.hxx" +#include <sfx2/viewfrm.hxx> +#include <sfx2/objsh.hxx> +#include <framework/addonsoptions.hxx> + +#ifndef __FRAMEWORK_CLASSES_ADDONMENUS_HXX_ +#include <framework/addonmenu.hxx> +#endif +#include <framework/menuconfiguration.hxx> + +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::uno; + +//========================================================================= + +DBG_NAME(SfxVirtualMenu) + +//========================================================================= + +typedef SfxMenuControl* SfxMenuControlPtr; +SV_IMPL_PTRARR(SfxMenuCtrlArr_Impl, SfxMenuControlPtr); + +class SfxMenuImageControl_Impl : public SfxControllerItem +{ + SfxVirtualMenu* pMenu; + long lRotation; + BOOL bIsMirrored; + +protected: + virtual void StateChanged( USHORT nSID, SfxItemState eState, const SfxPoolItem* pState ); +public: + SfxMenuImageControl_Impl( USHORT nSlotId, SfxBindings& rBindings, SfxVirtualMenu* pVMenu ) + : SfxControllerItem( nSlotId, rBindings ) + , pMenu( pVMenu ) + , lRotation( 0 ) + , bIsMirrored( FALSE ) + {} + void Update(); +}; + +void SfxMenuImageControl_Impl::StateChanged( USHORT /*nSID*/, SfxItemState /*eState*/, const SfxPoolItem* pState ) +{ + const SfxImageItem* pItem = PTR_CAST( SfxImageItem, pState ); + if ( pItem ) + { + lRotation = pItem->GetRotation(); + bIsMirrored = pItem->IsMirrored(); + Update(); + } +} + +void SfxMenuImageControl_Impl::Update() +{ + SfxViewFrame* pViewFrame = GetBindings().GetDispatcher_Impl()->GetFrame(); + SfxModule* pModule = pViewFrame->GetObjectShell()->GetModule(); + SfxSlotPool* pPool = pModule->GetSlotPool(); + Menu* pSVMenu = pMenu->GetSVMenu(); + for (USHORT nPos = 0; nPos<pSVMenu->GetItemCount(); nPos++) + { + USHORT nslotId = pSVMenu->GetItemId( nPos ); + const SfxSlot* pSlot = pPool->GetSlot( nslotId ); + if ( pSlot && pSlot->IsMode( SFX_SLOT_IMAGEROTATION ) ) + { + pSVMenu->SetItemImageMirrorMode( nslotId, FALSE ); + pSVMenu->SetItemImageAngle( nslotId, lRotation ); + } + + if ( pSlot && pSlot->IsMode( SFX_SLOT_IMAGEREFLECTION ) ) + pSVMenu->SetItemImageMirrorMode( nslotId, bIsMirrored ); + } +} + +//========================================================================= + +static Image RetrieveAddOnImage( Reference< com::sun::star::frame::XFrame >& rFrame, + const rtl::OUString& aImageId, + const rtl::OUString& aURL, + BOOL bBigImage, + BOOL bHiContrast ) +{ + Image aImage; + + if ( aImageId.getLength() > 0 ) + { + aImage = GetImage( rFrame, aImageId, bBigImage, bHiContrast ); + if ( !!aImage ) + return aImage; + } + + aImage = GetImage( rFrame, aURL, bBigImage, bHiContrast ); + if ( !aImage ) + aImage = framework::AddonsOptions().GetImageFromURL( aURL, bBigImage, bHiContrast ); + + return aImage; +} + +//========================================================================= + +/* Diese Hilfsfunktion pr"uft, ob eine Slot-Id im aktuellen Applikations- + Status sichtbar ist oder nicht. Dabei bezieht sich der Applikations-Status + darauf, ob die Applikation OLE-Server ist oder nicht. +*/ + +BOOL IsItemHidden_Impl( USHORT nItemId, int bOleServer, int bMac ) +{ + return ( bMac && + ( nItemId == SID_MINIMIZED ) ) || + ( bOleServer && + ( nItemId == SID_QUITAPP || nItemId == SID_SAVEDOC || + nItemId == SID_OPENDOC || nItemId == SID_SAVEASDOC || + nItemId == SID_NEWDOC ) ) || + ( !bOleServer && + ( nItemId == SID_EXITANDRETURN || nItemId == SID_UPDATEDOC ) ); +} + +//==================================================================== + +void SfxVirtualMenu::Construct_Impl() +{ + pSVMenu->SetHighlightHdl( LINK(this, SfxVirtualMenu, Highlight) ); + pSVMenu->SetActivateHdl( LINK(this, SfxVirtualMenu, Activate) ); + pSVMenu->SetDeactivateHdl( LINK(this, SfxVirtualMenu, Deactivate) ); + pSVMenu->SetSelectHdl( LINK(this, SfxVirtualMenu, Select) ); + + // #107258# accelerator keys are needed for accessibility + //if ( bOLE ) + // InvalidateKeyCodes(); + + if ( !pResMgr && pParent ) + pResMgr = pParent->pResMgr; +} + +//-------------------------------------------------------------------- + +SfxVirtualMenu::SfxVirtualMenu( USHORT nOwnId, + SfxVirtualMenu* pOwnParent, Menu& rMenu, BOOL bWithHelp, + SfxBindings &rBindings, BOOL bOLEServer, BOOL bRes, BOOL bIsAddonMenu ): + pItems(0), + pImageControl(0), + pBindings(&rBindings), + pResMgr(0), + pAutoDeactivate(0), + nLocks(0), + bHelpInitialized( bWithHelp ), + bWasHighContrast( FALSE ), + bIsAddonPopupMenu( bIsAddonMenu ) +{ + DBG_MEMTEST(); + DBG_CTOR(SfxVirtualMenu, 0); + pSVMenu = &rMenu; + + bResCtor = bRes; + bOLE = bOLEServer; + nId = nOwnId; + pParent = pOwnParent; + nVisibleItems = 0; + pAppCtrl = 0; + pWindowMenu = NULL; + pPickMenu = NULL; + pAddonsMenu = NULL; + bIsActive = FALSE; + bControllersUnBound = FALSE; + CreateFromSVMenu(); + Construct_Impl(); + bHelpInitialized = FALSE; +} + +//-------------------------------------------------------------------- + +// creates a virtual menu from a StarView MenuBar or PopupMenu + +SfxVirtualMenu::SfxVirtualMenu( Menu *pStarViewMenu, BOOL bWithHelp, + SfxBindings &rBindings, BOOL bOLEServer, BOOL bRes, BOOL bIsAddonMenu ): + pItems(0), + pImageControl(0), + pBindings(&rBindings), + pResMgr(0), + pAutoDeactivate(0), + nLocks(0), + bHelpInitialized( bWithHelp ), + bWasHighContrast( FALSE ), + bIsAddonPopupMenu( bIsAddonMenu ) +{ + DBG_MEMTEST(); + DBG_CTOR(SfxVirtualMenu, 0); + + pSVMenu = pStarViewMenu; + + bResCtor = bRes; + bOLE = bOLEServer; + nId = 0; + pParent = 0; + pAppCtrl = 0; + nVisibleItems = 0; + pWindowMenu = NULL; + pPickMenu = NULL; + pAddonsMenu = NULL; + bIsActive = FALSE; + bControllersUnBound = FALSE; + CreateFromSVMenu(); + Construct_Impl(); + bHelpInitialized = FALSE; +} + +//-------------------------------------------------------------------- + +/* Der Destruktor der Klasse SfxVirtualMenu gib die gebundenen Items frei + und klinkt das zugeh"orige StarView-PopupMenu aus seinem Parent aus. + Falls es sich um das Pickmenu oder das MDI-Menu handelt, wird es + dort abgemeldet. +*/ + +SfxVirtualMenu::~SfxVirtualMenu() +{ + DBG_MEMTEST(); + DBG_DTOR(SfxVirtualMenu, 0); + + DELETEZ( pImageControl ); + SvtMenuOptions().RemoveListenerLink( LINK( this, SfxVirtualMenu, SettingsChanged ) ); + + if ( bIsActive ) + { + pBindings->LEAVEREGISTRATIONS(); --nLocks; bIsActive = FALSE; + } + + // QAP-Hack + if ( pAutoDeactivate ) + { + if ( pAutoDeactivate->IsActive() ) + Deactivate(0); + DELETEX(pAutoDeactivate); + } + + if (pItems) + { + delete [] pItems; + } + + delete pAppCtrl; + pBindings = 0; + + // Alle Menues, die von SV erzeugt wurden, werden auch dort wieder + // gel"oscht (also die beim Laden aus der Resource erzeugten). + // Das Top-Level-Menu wird nie von SV gel"oscht, da die Allocierung + // im SFX erfolgt + if ( !bResCtor || !pParent) + { + if ( pParent ) + { + if( pParent->pSVMenu->GetItemPos( nId ) != MENU_ITEM_NOTFOUND ) + pParent->pSVMenu->SetPopupMenu( nId, 0 ); + if ( pParent->pPickMenu == pSVMenu ) + pParent->pPickMenu = 0; + if ( pParent->pWindowMenu == pSVMenu) + pParent->pWindowMenu = 0; + if ( pParent->pAddonsMenu == pSVMenu ) + pParent->pAddonsMenu = 0; + } + + delete pSVMenu; + } + + DBG_OUTF( ("SfxVirtualMenu %lx destroyed", this) ); + DBG_ASSERT( !nLocks, "destroying active menu" ); +} +//-------------------------------------------------------------------- + +BOOL SfxVirtualMenu::IsHiContrastMode() const +{ + const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); + return rSettings.GetHighContrastMode(); +} + +//-------------------------------------------------------------------- +// internal: creates the virtual menu from the pSVMenu + +void SfxVirtualMenu::CreateFromSVMenu() +{ + DBG_MEMTEST(); + DBG_CHKTHIS(SfxVirtualMenu, 0); + + // Merge Addon popup menus into the SV Menu + SfxViewFrame* pViewFrame = pBindings->GetDispatcher()->GetFrame(); + SfxSlotPool* pSlotPool = pViewFrame->GetObjectShell()->GetModule()->GetSlotPool(); + Reference< com::sun::star::frame::XFrame > xFrame( pViewFrame->GetFrame().GetFrameInterface() ); + + if ( pSVMenu->IsMenuBar() ) + { + USHORT nPos = pSVMenu->GetItemPos( SID_MDIWINDOWLIST ); + if ( nPos != MENU_ITEM_NOTFOUND && xFrame.is() ) + { + // Retrieve addon popup menus and add them to our menu bar + Reference< com::sun::star::frame::XModel > xModel; + Reference< com::sun::star::frame::XController > xController( xFrame->getController(), UNO_QUERY ); + if ( xController.is() ) + xModel = Reference< com::sun::star::frame::XModel >( xController->getModel(), UNO_QUERY ); + framework::AddonMenuManager::MergeAddonPopupMenus( xFrame, xModel, nPos, (MenuBar *)pSVMenu ); + } + + // Merge the Add-Ons help menu items into the Office help menu + if ( xFrame.is() ) + framework::AddonMenuManager::MergeAddonHelpMenu( xFrame, (MenuBar *)pSVMenu ); + + // Set addon menu pointer here to avoid problems. When accessibility is enabled, the whole menu + // is created immediately! + pAddonsMenu = pSVMenu->GetPopupMenu( SID_ADDONLIST ); + } + else if ( pParent ) + { + if ( pSVMenu == pParent->pAddonsMenu && + framework::AddonsOptions().HasAddonsMenu() && + !pSVMenu->GetPopupMenu( SID_ADDONS ) ) + { + // Create menu item at the end of the tools popup menu for the addons popup menu + InsertAddOnsMenuItem( pSVMenu ); + } + } + + // get and store the number of items + nCount = pSVMenu->GetItemCount(); + + // Achtung: nur zu diesem Zeitpunkt ist garantiert, da\s nCount und + // der ItemCount des SV-Menues "ubereinstimmen; sp"ater kann das SvMenue + // auch mehr Eintr"age haben (Pickliste!) + if (nCount) + pItems = new SfxMenuControl[nCount]; + + // remember some values + SFX_APP(); + const int bOleServer = FALSE; + const int bMac = FALSE; + SvtMenuOptions aOptions; + aOptions.AddListenerLink( LINK( this, SfxVirtualMenu, SettingsChanged ) ); + + // iterate through the items + pBindings->ENTERREGISTRATIONS(); ++nLocks; + pImageControl = new SfxMenuImageControl_Impl( SID_IMAGE_ORIENTATION, *pBindings, this ); + + // Update high contrast state + bWasHighContrast = IsHiContrastMode(); + + USHORT nSVPos = 0; + for ( USHORT nPos=0; nPos<nCount; ++nPos, ++nSVPos ) + { + USHORT nSlotId = pSVMenu->GetItemId(nSVPos); + PopupMenu* pPopup = pSVMenu->GetPopupMenu(nSlotId); + if( pPopup && nSlotId >= SID_OBJECTMENU0 && nSlotId <= SID_OBJECTMENU_LAST ) + { + // artefact in XML menuconfig: every entry in root menu must have a popup! + pSVMenu->SetPopupMenu( nSlotId, NULL ); + DELETEZ( pPopup ); + } + + const String sItemText = pSVMenu->GetItemText(nSlotId); + const String sHelpText = pSVMenu->GetHelpText(nSlotId); + + if ( pPopup ) + { + + SfxMenuControl *pMnuCtrl = + SfxMenuControl::CreateControl(nSlotId, *pPopup, *pBindings); + + if ( pMnuCtrl ) + { + // Das Popup war offensichtlich kein "echtes"; solche werden + // niemals aus der Resource geladen und m"ussen daher explizit + // gel"oscht werden + if ( pSVMenu->GetPopupMenu( nSlotId ) == pPopup ) + pSVMenu->SetPopupMenu( nSlotId, NULL ); + delete pPopup; + pPopup = 0; + + SfxMenuCtrlArr_Impl &rCtrlArr = GetAppCtrl_Impl(); + rCtrlArr.C40_INSERT( SfxMenuControl, pMnuCtrl, rCtrlArr.Count() ); + (pItems+nPos)->Bind( 0, nSlotId, sItemText, sHelpText, *pBindings); + pMnuCtrl->Bind( this, nSlotId, sItemText, sHelpText, *pBindings); + + if ( Application::GetSettings().GetStyleSettings().GetUseImagesInMenus() ) + { + rtl::OUString aSlotURL( RTL_CONSTASCII_USTRINGPARAM( "slot:" )); + aSlotURL += rtl::OUString::valueOf( sal_Int32( nSlotId )); + Image aImage = GetImage( xFrame, aSlotURL, FALSE, bWasHighContrast ); + pSVMenu->SetItemImage( nSlotId, aImage ); + } + } + else + { + const SfxSlot* pSlot = pSlotPool->GetSlot( nSlotId ); + if ( pSlot ) + { + rtl::OString aCmd(".uno:"); + aCmd += pSlot->GetUnoName(); + pSVMenu->SetHelpId( nSlotId, pSlot->GetUnoName() ); + } + + pMnuCtrl = pItems+nPos; + + // normalerweise jetzt erst im Activate-Handler + if ( bOLE ) + { + pMnuCtrl->Bind( this, nSlotId, + *new SfxVirtualMenu(nSlotId, this, *pPopup, bHelpInitialized, *pBindings, bOLE, bResCtor), + sItemText, sHelpText, + *pBindings ); + } + } + + ++nVisibleItems; + } + else + { + switch ( pSVMenu->GetItemType(nSVPos) ) + { + case MENUITEM_STRING: + case MENUITEM_STRINGIMAGE: + { + SfxMenuControl *pMnuCtrl=0; + String aCmd( pSVMenu->GetItemCommand( nSlotId ) ); + if ( aCmd.CompareToAscii("slot:", 5) == 0 ) + { + SfxMacroConfig* pCfg = SFX_APP()->GetMacroConfig(); + if ( pCfg->IsMacroSlot( nSlotId ) ) + { + if ( pCfg->GetMacroInfo( nSlotId ) ) + { + pCfg->RegisterSlotId( nSlotId ); + pSVMenu->SetItemCommand( nSlotId, String() ); + aCmd.Erase(); + } + else + { + pSVMenu->SetItemCommand( nSlotId, String::CreateFromAscii("macro:///macro.not.founc") ); + } + } + } + + if ( aCmd.Len() && (( nSlotId < SID_SFX_START ) || ( nSlotId > SHRT_MAX )) ) + { + // try to create control via comand name + pMnuCtrl = SfxMenuControl::CreateControl( aCmd, nSlotId, *pSVMenu, sItemText, sHelpText, *pBindings, this ); + if ( pMnuCtrl ) + { + SfxMenuCtrlArr_Impl &rCtrlArr = GetAppCtrl_Impl(); + rCtrlArr.C40_INSERT( SfxMenuControl, pMnuCtrl, rCtrlArr.Count()); + (pItems+nPos)->Bind( 0, nSlotId, sItemText, sHelpText, *pBindings); + } + } + + if ( !pMnuCtrl ) + { + // try to create control via Id + pMnuCtrl = SfxMenuControl::CreateControl(nSlotId, *pSVMenu, *pBindings); + if ( pMnuCtrl ) + { + SfxMenuCtrlArr_Impl &rCtrlArr = GetAppCtrl_Impl(); + rCtrlArr.C40_INSERT( SfxMenuControl, pMnuCtrl, rCtrlArr.Count()); + (pItems+nPos)->Bind( 0, nSlotId, sItemText, sHelpText, *pBindings); + } + else + // take default control + pMnuCtrl = (pItems+nPos); + + pMnuCtrl->Bind( this, nSlotId, sItemText, sHelpText, *pBindings); + } + + if ( Application::GetSettings().GetStyleSettings().GetUseImagesInMenus() ) + { + Image aImage; + if ( bIsAddonPopupMenu || framework::AddonMenuManager::IsAddonMenuId( nSlotId )) + { + rtl::OUString aImageId; + + ::framework::MenuConfiguration::Attributes* pMenuAttributes = + (::framework::MenuConfiguration::Attributes*)pSVMenu->GetUserValue( nSlotId ); + + if ( pMenuAttributes ) + aImageId = pMenuAttributes->aImageId; // Retrieve image id from menu attributes + + aImage = RetrieveAddOnImage( xFrame, aImageId, aCmd, FALSE, bWasHighContrast ); + } + else + { + rtl::OUString aSlotURL( RTL_CONSTASCII_USTRINGPARAM( "slot:" )); + aSlotURL += rtl::OUString::valueOf( sal_Int32( nSlotId )); + aImage = GetImage( xFrame, aSlotURL, FALSE, bWasHighContrast ); + } + + if ( !!aImage ) + pSVMenu->SetItemImage( nSlotId, aImage ); + } + + if ( !IsItemHidden_Impl(nSlotId, bOleServer, bMac) ) + ++nVisibleItems; + else + pSVMenu->RemoveItem( nSVPos-- ); + break; + } + + case MENUITEM_IMAGE: + //! not implemented + break; + + case MENUITEM_SEPARATOR: + //! not implemented + break; + default: + break; // DONTKNOW and STRINGIMAGE not handled. + } + } + } + pBindings->LEAVEREGISTRATIONS(); --nLocks; +} + +//-------------------------------------------------------------------- + +// called on activation of the SV-Menu + +IMPL_LINK( SfxVirtualMenu, Highlight, Menu *, pMenu ) +{ + DBG_MEMTEST(); + DBG_CHKTHIS(SfxVirtualMenu, 0); + + // eigenes StarView-Menu + if ( pMenu == pSVMenu ) + { + // AutoDeactivate ist jetzt nicht mehr n"otig + //USHORT nSlotId = pMenu->GetCurItemId(); + if ( pAutoDeactivate ) + pAutoDeactivate->Stop(); + } + + return TRUE; +} + +IMPL_LINK( SfxVirtualMenu, SettingsChanged, void*, EMPTYARG ) +{ + USHORT nItemCount = pSVMenu->GetItemCount(); + SfxViewFrame *pViewFrame = pBindings->GetDispatcher()->GetFrame(); + BOOL bIcons = Application::GetSettings().GetStyleSettings().GetUseImagesInMenus(); + BOOL bIsHiContrastMode = IsHiContrastMode(); + Reference<com::sun::star::frame::XFrame> xFrame( pViewFrame->GetFrame().GetFrameInterface() ); + + if ( !bIsAddonPopupMenu ) + { + for ( USHORT nSVPos=0; nSVPos<nItemCount; ++nSVPos ) + { + USHORT nSlotId = pSVMenu->GetItemId( nSVPos ); + MenuItemType nType = pSVMenu->GetItemType( nSVPos ); + if ( nType == MENUITEM_STRING && bIcons ) + { + if ( framework::AddonMenuManager::IsAddonMenuId( nSlotId )) + { + // Special code for Add-On menu items. They can appear inside the help menu. + rtl::OUString aCmd( pSVMenu->GetItemCommand( nSlotId ) ); + rtl::OUString aImageId; + + ::framework::MenuConfiguration::Attributes* pMenuAttributes = + (::framework::MenuConfiguration::Attributes*)pSVMenu->GetUserValue( nSlotId ); + + if ( pMenuAttributes ) + aImageId = pMenuAttributes->aImageId; // Retrieve image id from menu attributes + + pSVMenu->SetItemImage( nSlotId, RetrieveAddOnImage( xFrame, aImageId, aCmd, FALSE, bIsHiContrastMode )); + } + else + { + rtl::OUString aSlotURL( RTL_CONSTASCII_USTRINGPARAM( "slot:" )); + aSlotURL += rtl::OUString::valueOf( sal_Int32( nSlotId )); + pSVMenu->SetItemImage( nSlotId, GetImage( xFrame, aSlotURL, FALSE, bWasHighContrast )); + } + } + else if( nType == MENUITEM_STRINGIMAGE && !bIcons ) + { + pSVMenu->SetItemImage( nSlotId, Image() ); + } + } + } + else + { + // Remove/update images from Add-Ons top-level popup menus when settings have changed + if ( !bIcons ) + RemoveMenuImages( pSVMenu ); + else + UpdateImages( pSVMenu ); + } + + // Special code to remove menu images from runtime popup menus when settings have changed + if ( pParent && pSVMenu == pParent->pAddonsMenu ) + { + if ( !bIcons ) + RemoveMenuImages( pParent->pAddonsMenu->GetPopupMenu( SID_ADDONS )); + else + UpdateImages( pParent->pAddonsMenu->GetPopupMenu( SID_ADDONS )); + } + + if ( pImageControl ) + pImageControl->Update(); + + return 0; +} + +//-------------------------------------------------------------------- + +void SfxVirtualMenu::UpdateImages() +{ + BOOL bIcons = Application::GetSettings().GetStyleSettings().GetUseImagesInMenus(); + + if ( bIcons ) + { + BOOL bIsHiContrastMode = IsHiContrastMode(); + USHORT nItemCount = pSVMenu->GetItemCount(); + SfxViewFrame * pViewFrame = pBindings->GetDispatcher()->GetFrame(); + Reference<com::sun::star::frame::XFrame> xFrame( pViewFrame->GetFrame().GetFrameInterface() ); + + for ( USHORT nSVPos=0; nSVPos < nItemCount; ++nSVPos ) + { + USHORT nSlotId = pSVMenu->GetItemId( nSVPos ); + if ( pSVMenu->GetItemType( nSVPos ) == MENUITEM_STRINGIMAGE ) + { + if ( framework::AddonMenuManager::IsAddonMenuId( nSlotId )) + { + // Special code for Add-On menu items. They can appear inside the help menu. + rtl::OUString aCmd( pSVMenu->GetItemCommand( nSlotId ) ); + rtl::OUString aImageId; + + ::framework::MenuConfiguration::Attributes* pMenuAttributes = + (::framework::MenuConfiguration::Attributes*)pSVMenu->GetUserValue( nSlotId ); + + if ( pMenuAttributes ) + aImageId = pMenuAttributes->aImageId; // Retrieve image id from menu attributes + + pSVMenu->SetItemImage( nSlotId, RetrieveAddOnImage( xFrame, aImageId, aCmd, FALSE, bIsHiContrastMode )); + } + else + { + rtl::OUString aSlotURL( RTL_CONSTASCII_USTRINGPARAM( "slot:" )); + aSlotURL += rtl::OUString::valueOf( sal_Int32( nSlotId )); + pSVMenu->SetItemImage( nSlotId, GetImage( xFrame, aSlotURL, FALSE, bWasHighContrast )); + } + } + } + + if ( pImageControl ) + pImageControl->Update(); + } +} + +//-------------------------------------------------------------------- + +void SfxVirtualMenu::UpdateImages( Menu* pMenu ) +{ + if ( !pMenu ) + return; + + framework::AddonsOptions aAddonOptions; + + BOOL bIcons = Application::GetSettings().GetStyleSettings().GetUseImagesInMenus(); + if ( bIcons ) + { + BOOL bIsHiContrastMode = IsHiContrastMode(); + USHORT nItemCount = pMenu->GetItemCount(); + Reference<com::sun::star::frame::XFrame> aXFrame( pBindings->GetDispatcher_Impl()->GetFrame()->GetFrame().GetFrameInterface() ); + + for ( USHORT nPos=0; nPos < nItemCount; ++nPos ) + { + USHORT nSlotId = pMenu->GetItemId( nPos ); + PopupMenu* pPopup = pMenu->GetPopupMenu( nSlotId ); + if ( pMenu->GetItemType( nPos ) != MENUITEM_SEPARATOR ) + { + rtl::OUString aImageId; + + ::framework::MenuConfiguration::Attributes* pMenuAttributes = + (::framework::MenuConfiguration::Attributes*)pMenu->GetUserValue( nSlotId ); + + if ( pMenuAttributes ) + aImageId = pMenuAttributes->aImageId; // Retrieve image id from menu attributes + + pMenu->SetItemImage( nSlotId, RetrieveAddOnImage( aXFrame, aImageId, pMenu->GetItemCommand( nSlotId ), FALSE, bIsHiContrastMode )); + } + + if ( pPopup ) + UpdateImages( pPopup ); + } + + if ( pImageControl ) + pImageControl->Update(); + } +} + +//-------------------------------------------------------------------- + +void SfxVirtualMenu::RemoveMenuImages( Menu* pMenu ) +{ + if ( !pMenu ) + return; + + USHORT nItemCount = pMenu->GetItemCount(); + for ( USHORT nPos=0; nPos < nItemCount; ++nPos ) + { + USHORT nSlotId = pMenu->GetItemId( nPos ); + PopupMenu* pPopup = pMenu->GetPopupMenu( nSlotId ); + if ( pMenu->GetItemType( nPos ) == MENUITEM_STRINGIMAGE ) + pMenu->SetItemImage( nSlotId, Image() ); + if ( pPopup ) + RemoveMenuImages( pPopup ); + } +} + +//-------------------------------------------------------------------- + +FASTBOOL SfxVirtualMenu::Bind_Impl( Menu *pMenu ) +{ + // Selber suchen, da SV mit 'USHORT nSID = pSVMenu->GetCurItemId();' immer + // 0 liefert. Das ist so, weil die Event-Weiterleitung lt. TH nichts mit + // CurItem des Parent-Menus zu tun hat. + sal_uInt32 nAddonsPopupPrefixLen = ADDONSPOPUPMENU_URL_PREFIX.getLength(); + + for ( USHORT nPos = 0; nPos < nCount; ++nPos ) + { + // angesprochenes Sub-Menu gefunden? + FASTBOOL bFound = FALSE; + USHORT nSID = pSVMenu->GetItemId(nPos); + SfxMenuControl &rCtrl = pItems[nPos]; + bFound = pSVMenu->GetPopupMenu(nSID) == pMenu; + SfxVirtualMenu *pSubMenu = rCtrl.GetPopupMenu(); + + if ( bFound ) + { + // Nur ein gebundener Menu-Controller hat schon seine Id! + if ( !rCtrl.GetId() ) + { + bIsAddonPopupMenu = FALSE; + DBG_ASSERT( !pSubMenu, "Popup schon vorhanden!"); + + // Check if the popup is an Add-On popup menu + // Either the popup menu has a special ID or a special command URL prefix! + rtl::OUString aCommand = pSVMenu->GetItemCommand( nSID ); + if ( ( nSID == SID_ADDONS ) || + ( nSID == SID_ADDONHELP ) || + (( (sal_uInt32)aCommand.getLength() > nAddonsPopupPrefixLen ) && + ( aCommand.indexOf( ADDONSPOPUPMENU_URL_PREFIX ) == 0 )) ) + bIsAddonPopupMenu = TRUE; + + // VirtualMenu f"ur Sub-Menu erzeugen + BOOL bRes = bResCtor; + pSubMenu = new SfxVirtualMenu( nSID, this, + *pMenu, FALSE, *pBindings, bOLE, bRes, bIsAddonPopupMenu ); + + DBG_OUTF( ("Neues VirtualMenu %lx erzeugt", pSubMenu) ); + + rCtrl.Bind( this, nSID, *pSubMenu, + pSVMenu->GetItemText(nSID), pSVMenu->GetHelpText(nSID), + *pBindings ); + + // Activate weiterleiten + pSubMenu->Bind_Impl( pMenu ); + pSubMenu->Activate( pMenu ); + } + } + + // rekursiv weitersuchen (SV Activate nur am Menu selbst und Top-Menu) + if ( !bFound && pSubMenu ) + bFound = pSubMenu->Bind_Impl( pMenu ); + + // gefunden, dann abbrechen + if ( bFound ) + return TRUE; + } + + // nicht in diesem Untermenu gefunden + return FALSE; +} + +void SfxVirtualMenu::BindControllers() +{ + pBindings->ENTERREGISTRATIONS(); + + USHORT nPos; + for ( nPos = 0; nPos < nCount; ++nPos ) + { + SfxMenuControl& rCtrl = pItems[nPos]; + if ( rCtrl.IsBindable_Impl() && !rCtrl.GetPopupMenu() ) + rCtrl.ReBind(); + } + + SfxMenuCtrlArr_Impl& rCtrlArr = GetAppCtrl_Impl(); + for ( nPos=0; nPos<rCtrlArr.Count(); nPos++ ) + { + SfxMenuControl* pCtrl = rCtrlArr[nPos]; + USHORT nSlotId = pCtrl->GetId(); + if ( !pSVMenu->GetItemCommand(nSlotId).Len() ) + pCtrl->ReBind(); + } + + pBindings->LEAVEREGISTRATIONS(); + bControllersUnBound = FALSE; +} + +void SfxVirtualMenu::UnbindControllers() +{ + pBindings->ENTERREGISTRATIONS(); + + USHORT nPos; + for ( nPos = 0; nPos < nCount; ++nPos ) + { + SfxMenuControl &rCtrl = pItems[nPos]; + if ( rCtrl.IsBound() ) + rCtrl.UnBind(); + } + + SfxMenuCtrlArr_Impl& rCtrlArr = GetAppCtrl_Impl(); + for ( nPos=0; nPos<rCtrlArr.Count(); nPos++ ) + { + SfxMenuControl* pCtrl = rCtrlArr[nPos]; + if ( pCtrl->IsBound() ) + // UnoController sind nicht gebunden! + pCtrl->UnBind(); + } + + pBindings->LEAVEREGISTRATIONS(); + bControllersUnBound = TRUE; +} + + +//-------------------------------------------------------------------- +void SfxVirtualMenu::InsertAddOnsMenuItem( Menu* pMenu ) +{ + // Create special popup menu that is filled with the 3rd party components popup menu items + Reference<com::sun::star::lang::XMultiServiceFactory> aXMultiServiceFactory(::comphelper::getProcessServiceFactory()); + ::framework::MenuConfiguration aConf( aXMultiServiceFactory ); + Reference<com::sun::star::frame::XFrame> xFrame( pBindings->GetDispatcher_Impl()->GetFrame()->GetFrame().GetFrameInterface() ); + + PopupMenu* pAddonMenu = NULL; + try + { + pAddonMenu = framework::AddonMenuManager::CreateAddonMenu( xFrame ); + } + catch ( ::com::sun::star::lang::WrappedTargetException ) + { + } + + // Create menu item at the end of the tools popup menu for the addons popup menu + if ( pAddonMenu && pAddonMenu->GetItemCount() > 0 ) + { + USHORT nItemCount = pMenu->GetItemCount(); + String aAddonsTitle( SfxResId( STR_MENU_ADDONS )); + if ( nItemCount > 0 && pMenu->GetItemType( nItemCount-1 ) != MENUITEM_SEPARATOR ) + pMenu->InsertSeparator(); + pMenu->InsertItem( SID_ADDONS, aAddonsTitle ); + pMenu->SetPopupMenu( SID_ADDONS, pAddonMenu ); + + if ( Application::GetSettings().GetStyleSettings().GetUseImagesInMenus() ) + { + rtl::OUString aSlotURL( RTL_CONSTASCII_USTRINGPARAM( "slot:" )); + aSlotURL += rtl::OUString::valueOf( sal_Int32( SID_ADDONS )); + pMenu->SetItemImage( SID_ADDONS, GetImage( xFrame, aSlotURL, FALSE, bWasHighContrast )); + } + } + else + delete pAddonMenu; +} + +//-------------------------------------------------------------------- + +// called on activation of the SV-Menu + +IMPL_LINK( SfxVirtualMenu, Activate, Menu *, pMenu ) +{ + DBG_MEMTEST(); + DBG_CHKTHIS(SfxVirtualMenu, 0); + DBG_OUTF( ("SfxVirtualMenu %lx activated %lx, own %lx", this, pMenu, pSVMenu)); + + // MI: wozu war der noch gut? + // MBA: scheint ein alter QAP-Hack gewesen zu sein ( in rev.1.41 eingecheckt ! ) +// if ( Application::IsInModalMode() ) +// return TRUE; // abw"urgen + + if ( pMenu ) + { + sal_Bool bDontHide = SvtMenuOptions().IsEntryHidingEnabled(); + sal_uInt16 nFlag = pMenu->GetMenuFlags(); + if ( bDontHide ) + nFlag &= ~MENU_FLAG_HIDEDISABLEDENTRIES; + else + nFlag |= MENU_FLAG_HIDEDISABLEDENTRIES; + pMenu->SetMenuFlags( nFlag ); + } + + // eigenes StarView-Menu + if ( pMenu == pSVMenu ) + { + // doppelt-Activate verhindern + if ( bIsActive ) + return TRUE; + + // ggf. Pick-Menu erzeugen + if ( pParent && pSVMenu == pParent->pPickMenu ) + { + SfxPickList::Get()->CreateMenuEntries( pParent->pPickMenu ); + } + else + pPickMenu = pSVMenu->GetPopupMenu(SID_PICKLIST); + + if ( pParent && pSVMenu == pParent->pWindowMenu ) + { + // update window list + ::std::vector< ::rtl::OUString > aNewWindowListVector; + Reference< XDesktop > xDesktop( ::comphelper::getProcessServiceFactory()->createInstance( + DEFINE_CONST_OUSTRING( "com.sun.star.frame.Desktop" ) ), UNO_QUERY ); + + USHORT nActiveItemId = 0; + USHORT nItemId = START_ITEMID_WINDOWLIST; + + if ( xDesktop.is() ) + { + Reference< XFramesSupplier > xTasksSupplier( xDesktop, UNO_QUERY ); + Reference< XFrame > xCurrentFrame = xDesktop->getCurrentFrame(); + Reference< XIndexAccess > xList ( xTasksSupplier->getFrames(), UNO_QUERY ); + sal_Int32 nFrameCount = xList->getCount(); + for( sal_Int32 i=0; i<nFrameCount; ++i ) + { + Reference< XFrame > xFrame; + Any aVal = xList->getByIndex(i); + if (!(aVal>>=xFrame) || !xFrame.is() ) + continue; + + if ( xFrame == xCurrentFrame ) + nActiveItemId = nItemId; + + Window* pWin = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() ); + if ( pWin && pWin->IsVisible() ) + { + aNewWindowListVector.push_back( pWin->GetText() ); + ++nItemId; + } + } + } + + int nItemCount = pMenu->GetItemCount(); + + if ( nItemCount > 0 ) + { + // remove all old window list entries from menu + sal_uInt16 nPos = pMenu->GetItemPos( START_ITEMID_WINDOWLIST ); + for ( sal_uInt16 n = nPos; n < pMenu->GetItemCount(); ) + pMenu->RemoveItem( n ); + + if ( pMenu->GetItemType( pMenu->GetItemCount()-1 ) == MENUITEM_SEPARATOR ) + pMenu->RemoveItem( pMenu->GetItemCount()-1 ); + } + + if ( aNewWindowListVector.size() > 0 ) + { + // append new window list entries to menu + pMenu->InsertSeparator(); + nItemId = START_ITEMID_WINDOWLIST; + for ( sal_uInt32 i = 0; i < aNewWindowListVector.size(); i++ ) + { + pMenu->InsertItem( nItemId, aNewWindowListVector.at( i ), MIB_RADIOCHECK ); + if ( nItemId == nActiveItemId ) + pMenu->CheckItem( nItemId ); + ++nItemId; + } + } + } + else + pWindowMenu = pSVMenu->GetPopupMenu(SID_MDIWINDOWLIST); + + if ( !pParent && pSVMenu->IsMenuBar() && !pAddonsMenu ) + { + // Store Add-Ons parents of our runtime menu items + pAddonsMenu = pSVMenu->GetPopupMenu( SID_ADDONLIST ); + } + + // f"ur konstistenten Status sorgen + if ( bControllersUnBound ) + BindControllers(); + + //InvalidateKeyCodes(); + pBindings->GetDispatcher_Impl()->Flush(); + for ( USHORT nPos = 0; nPos < nCount; ++nPos ) + { + USHORT nSlotId = (pItems+nPos)->GetId(); + if ( nSlotId && nSlotId > END_ITEMID_WINDOWLIST ) + pBindings->Update(nSlotId); + } + + pBindings->Update( SID_IMAGE_ORIENTATION ); + + // HelpText on-demand + if ( !bHelpInitialized ) + { + // TODO/CLEANUP: do we need help texts in context menus? + // old way with SlotInfo doesn't work anymore + } + + // bis zum Deactivate die Statusupdates unterdr"ucken + pBindings->ENTERREGISTRATIONS(); ++nLocks; bIsActive = TRUE; + + if ( pAutoDeactivate ) // QAP-Hack + pAutoDeactivate->Start(); + + if ( IsHiContrastMode() != bWasHighContrast ) + { + // Refresh images as our background color changed and remember it!! + bWasHighContrast = IsHiContrastMode(); + if ( bIsAddonPopupMenu ) + UpdateImages( pSVMenu ); + else + UpdateImages(); + } + + // erledigt + return TRUE; + } + else + { + // VirtualMenu fuer SubMenu finden und ggf. an VirtualMenu binden + bool bRet = Bind_Impl( pMenu ); +#ifdef DBG_UTIL + if ( !bRet) + DBG_WARNING( "W1: Virtual menu konnte nicht erzeugt werden!" ); +#endif + return bRet; + } +} + +//-------------------------------------------------------------------- + +IMPL_LINK( SfxVirtualMenu, Deactivate, Menu *, pMenu ) +{ + DBG_MEMTEST(); + DBG_OUTF( ("SfxVirtualMenu %lx deactivated %lx, own %lx", this, pMenu, pSVMenu) ); + if ( bIsActive && ( 0 == pMenu || pMenu == pSVMenu ) ) + { + if ( pAutoDeactivate ) + pAutoDeactivate->Stop(); + + // Bis auf die Menubar k"onnen alle Controller unbinded werden, wenn + // das Menue deaktiviert ( = zugeklappt ) wird + if ( pParent ) + UnbindControllers(); + pBindings->LEAVEREGISTRATIONS(); --nLocks; bIsActive = FALSE; + } + return TRUE; +} +//-------------------------------------------------------------------- + +// called on activation of the SV-Menu + +IMPL_LINK( SfxVirtualMenu, Select, Menu *, pMenu ) +{ + USHORT nSlotId = (USHORT) pMenu->GetCurItemId(); + DBG_OUTF( ("SfxVirtualMenu %lx selected %u from %lx", this, nSlotId, pMenu) ); +/* + if ( pSVMenu->GetItemCommand( nSlotId ).Len() ) + { + SfxMenuCtrlArr_Impl& rCtrlArr = GetAppCtrl_Impl(); + for ( USHORT nPos=0; nPos<rCtrlArr.Count(); nPos++ ) + { + SfxMenuControl* pCtrl = rCtrlArr[nPos]; + if ( pCtrl->GetId() == nSlotId ) + { + SfxUnoMenuControl *pUnoCtrl = (SfxUnoMenuControl*) pCtrl; + pUnoCtrl->Select(); + return TRUE; + } + } + } +*/ + if ( nSlotId >= START_ITEMID_WINDOWLIST && nSlotId <= END_ITEMID_WINDOWLIST ) + { + // window list menu item selected + Reference< XFramesSupplier > xDesktop( ::comphelper::getProcessServiceFactory()->createInstance( + DEFINE_CONST_OUSTRING( "com.sun.star.frame.Desktop" ) ), UNO_QUERY ); + if ( xDesktop.is() ) + { + USHORT nTaskId = START_ITEMID_WINDOWLIST; + Reference< XIndexAccess > xList( xDesktop->getFrames(), UNO_QUERY ); + sal_Int32 nFrameCount = xList->getCount(); + for ( sal_Int32 i=0; i<nFrameCount; ++i ) + { + Any aItem = xList->getByIndex(i); + Reference< XFrame > xFrame; + if (( aItem >>= xFrame ) && xFrame.is() && nTaskId == nSlotId ) + { + Window* pWin = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() ); + pWin->GrabFocus(); + pWin->ToTop( TOTOP_RESTOREWHENMIN ); + break; + } + + nTaskId++; + } + } + + return TRUE; + } + else if ( nSlotId >= START_ITEMID_PICKLIST && nSlotId <= END_ITEMID_PICKLIST ) + { + SfxPickList::Get()->ExecuteMenuEntry( nSlotId ); + return sal_True; + } + + if ( pMenu->GetItemCommand( nSlotId ).Len() ) + pBindings->ExecuteCommand_Impl( pMenu->GetItemCommand( nSlotId ) ); + else + pBindings->Execute( nSlotId ); + + return TRUE; +} + +//-------------------------------------------------------------------- + +// returns the associated StarView-menu + +Menu* SfxVirtualMenu::GetSVMenu() const +{ + DBG_MEMTEST(); + DBG_CHKTHIS(SfxVirtualMenu, 0); + + return pSVMenu; +} + +//-------------------------------------------------------------------- + +// return the position of the specified item + +USHORT SfxVirtualMenu::GetItemPos( USHORT nItemId ) const +{ + DBG_MEMTEST(); + DBG_CHKTHIS(SfxVirtualMenu, 0); + + for ( USHORT nPos = 0; nPos < nCount; ++nPos ) + if ( (pItems+nPos)->GetId() == nItemId ) + return nPos; + return MENU_ITEM_NOTFOUND; +} + +//-------------------------------------------------------------------- + +// returns the popup-menu assigned to the item or 0 if none + +SfxVirtualMenu* SfxVirtualMenu::GetPopupMenu( USHORT nItemId ) const +{ + DBG_MEMTEST(); + DBG_CHKTHIS(SfxVirtualMenu, 0); + + USHORT nPos = GetItemPos(nItemId); + if ( nPos != MENU_ITEM_NOTFOUND ) + return (pItems+nPos)->GetPopupMenu(); + return 0; +} +//-------------------------------------------------------------------- + +// returns the text of the item as currently shown in the menu + +String SfxVirtualMenu::GetItemText( USHORT nSlotId ) const +{ + DBG_MEMTEST(); + DBG_CHKTHIS(SfxVirtualMenu, 0); + + USHORT nPos = GetItemPos(nSlotId); + if ( nPos != MENU_ITEM_NOTFOUND ) + return (pItems+nPos)->GetTitle(); + return String(); +} +//-------------------------------------------------------------------- + +// returns the text of the item as currently shown in the menu + +String SfxVirtualMenu::GetItemHelpText( USHORT nSlotId ) const +{ + DBG_MEMTEST(); + DBG_CHKTHIS(SfxVirtualMenu, 0); + + USHORT nPos = GetItemPos(nSlotId); + if ( nPos != MENU_ITEM_NOTFOUND ) + return (pItems+nPos)->GetHelpText(); + return String(); +} + +//-------------------------------------------------------------------- + +// set the checkmark of the specified item + +void SfxVirtualMenu::CheckItem( USHORT nItemId, BOOL bCheck ) +{ + DBG_MEMTEST(); + DBG_CHKTHIS(SfxVirtualMenu, 0); + DBG_ASSERT( this != 0, ""); + DBG_ASSERT( pSVMenu != 0, "" ); + if (pSVMenu->GetItemPos( nItemId ) != MENU_ITEM_NOTFOUND ) + pSVMenu->CheckItem( nItemId, bCheck ); +} +//-------------------------------------------------------------------- + +// set the enabled-state of the specified item + +void SfxVirtualMenu::EnableItem( USHORT nItemId, BOOL bEnable ) +{ + DBG_MEMTEST(); + DBG_CHKTHIS(SfxVirtualMenu, 0); + DBG_ASSERT( this != 0, ""); + DBG_ASSERT( pSVMenu != 0, "" ); + + if (pSVMenu->GetItemPos( nItemId ) != MENU_ITEM_NOTFOUND ) + pSVMenu->EnableItem( nItemId, bEnable ); +} +//-------------------------------------------------------------------- + +// set the text of the specified item + +void SfxVirtualMenu::SetItemText( USHORT nItemId, const String& rText ) +{ + DBG_MEMTEST(); + DBG_CHKTHIS(SfxVirtualMenu, 0); + DBG_ASSERT( this != 0, ""); + DBG_ASSERT( pSVMenu != 0, "" ); + if (pSVMenu->GetItemPos( nItemId ) != MENU_ITEM_NOTFOUND ) + pSVMenu->SetItemText( nItemId, rText ); +} + +//-------------------------------------------------------------------- + +// + +void SfxVirtualMenu::SetPopupMenu( USHORT nItemId, PopupMenu *pMenu ) +{ + DBG_MEMTEST(); + DBG_CHKTHIS(SfxVirtualMenu, 0); + + if (pSVMenu->GetItemPos( nItemId ) != MENU_ITEM_NOTFOUND ) + GetSVMenu()->SetPopupMenu( nItemId, pMenu ); + for ( USHORT n = 0; n < nCount; ++n ) + { + SfxVirtualMenu *pSubMenu = (pItems+n)->GetPopupMenu(); + if ( pSubMenu ) + pSubMenu->SetPopupMenu( nItemId, pMenu ); + } +} + +//-------------------------------------------------------------------- + +// Erzwingt die Initialisierung, die sonst nur im Activate kommt + +void SfxVirtualMenu::InitPopup( USHORT nPos, BOOL /*bOLE*/ ) +{ + DBG_MEMTEST(); + DBG_CHKTHIS(SfxVirtualMenu, 0); + + USHORT nSID = pSVMenu->GetItemId(nPos); + PopupMenu *pMenu = pSVMenu->GetPopupMenu( nSID ); + + DBG_ASSERT( pMenu, "Hier gibt es kein Popup!"); + + SfxMenuControl &rCtrl = pItems[nPos]; + if ( !rCtrl.GetId() ) + { + // VirtualMenu f"ur Sub-Menu erzeugen + BOOL bRes = bResCtor; + SfxVirtualMenu *pSubMenu = + new SfxVirtualMenu(nSID, this, *pMenu, FALSE, *pBindings, bOLE, bRes); + + DBG_OUTF( ("Neues VirtualMenu %lx erzeugt", pSubMenu) ); + + rCtrl.Bind( this, nSID, *pSubMenu, + pSVMenu->GetItemText(nSID), pSVMenu->GetHelpText(nSID), + *pBindings ); + } +} + +void SfxVirtualMenu::InitializeHelp() +{ + for ( USHORT nPos = 0; nPos<pSVMenu->GetItemCount(); ++nPos ) + { + USHORT nSlotId = pSVMenu->GetItemId(nPos); + // TODO/CLEANUP: this code does nothing! +// if ( !bHelpInitialized ) +// pSVMenu->SetHelpText( nId, rSlotPool.GetSlotHelpText_Impl( nId ) ); + SfxMenuControl &rCtrl = pItems[nPos]; + if ( nSlotId && !rCtrl.GetId() ) + { + InitPopup( nPos, TRUE ); + } + + SfxVirtualMenu *pSubMenu = rCtrl.GetPopupMenu(); + if ( pSubMenu ) + pSubMenu->InitializeHelp(); + } + + bHelpInitialized = TRUE; +} + +typedef ULONG (__LOADONCALLAPI *HelpIdFunc) ( const String& ); + +void SfxVirtualMenu::SetHelpIds( ResMgr *pRes ) +{ + pResMgr = pRes; +} + |