diff options
Diffstat (limited to 'sfx2/source/menu/virtmenu.cxx')
-rw-r--r-- | sfx2/source/menu/virtmenu.cxx | 1015 |
1 files changed, 1015 insertions, 0 deletions
diff --git a/sfx2/source/menu/virtmenu.cxx b/sfx2/source/menu/virtmenu.cxx new file mode 100644 index 000000000000..03be92c5ebbd --- /dev/null +++ b/sfx2/source/menu/virtmenu.cxx @@ -0,0 +1,1015 @@ +/************************************************************************* + * + * $RCSfile: virtmenu.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:52:35 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include <sot/factory.hxx> +#include <vcl/system.hxx> +#include <svtools/libcall.hxx> +#pragma hdrstop + +#include "virtmenu.hxx" +#include "msgpool.hxx" +#include "statcach.hxx" +#include "msg.hxx" +#include "idpool.hxx" +#include "mnuitem.hxx" +#include "mnumgr.hxx" +#include "bindings.hxx" +#include "dispatch.hxx" +#include "app.hxx" +#include "accmgr.hxx" +#include "sfxtypes.hxx" +#include "arrdecl.hxx" +#include "sfx.hrc" +#include "ipfrm.hxx" +#include "ipenv.hxx" +#include "appdata.hxx" +#include "picklist.hxx" +#include "viewsh.hxx" + +//========================================================================= + +DBG_NAME(SfxVirtualMenu); + +static long nAutoDeactivateTimeout_Impl = -1; + +//========================================================================= + +typedef SfxMenuControl* SfxMenuControlPtr; +SV_IMPL_PTRARR(SfxMenuCtrlArr_Impl, SfxMenuControlPtr); + +//========================================================================= + +/* 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_ARRANGEICONS || nItemId == SID_MINIMIZEWINS ) ) || + ( 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() +{ + pWindowMenu = NULL; + pPickMenu = NULL; + bIsActive = FALSE; + bControllersUnBound = FALSE; + pSVMenu->SetHighlightHdl( LINK(this, SfxVirtualMenu, Highlight) ); + pSVMenu->SetActivateHdl( LINK(this, SfxVirtualMenu, Activate) ); + pSVMenu->SetDeactivateHdl( LINK(this, SfxVirtualMenu, Deactivate) ); + pSVMenu->SetSelectHdl( LINK(this, SfxVirtualMenu, Select) ); + + // Accels eintragen + InvalidateKeyCodes(); + + if ( !pResMgr && pParent ) + pResMgr = pParent->pResMgr; +} + +//-------------------------------------------------------------------- + +SfxVirtualMenu::SfxVirtualMenu( USHORT nOwnId, + SfxVirtualMenu* pOwnParent, Menu& rMenu, BOOL bWithHelp, + SfxBindings &rBindings, BOOL bOLEServer, BOOL bRes ): + pItems(0), + pBindings(&rBindings), + pResMgr(0), + nLocks(0), pAutoDeactivate(0), bHelpInitialized( bWithHelp ) + , bRemoveDisabledEntries( FALSE ) +{ + DBG_MEMTEST(); + DBG_CTOR(SfxVirtualMenu, 0); + pSVMenu = &rMenu; + +#ifdef UNX + USHORT nPos = pSVMenu->GetItemPos( SID_DESKTOPMODE ); + if ( nPos != MENU_ITEM_NOTFOUND ) + pSVMenu->RemoveItem( nPos ); +#endif + + bResCtor = bRes; + bOLE = bOLEServer; + nId = nOwnId; + pParent = pOwnParent; + nVisibleItems = 0; + pAppCtrl = 0; + 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 ): + pItems(0), + pBindings(&rBindings), + pResMgr(0), + nLocks(0), pAutoDeactivate(0), bHelpInitialized( bWithHelp ) + , bRemoveDisabledEntries( FALSE ) +{ + DBG_MEMTEST(); + DBG_CTOR(SfxVirtualMenu, 0); + +#ifdef UNX + USHORT nPos = pStarViewMenu->GetItemPos( SID_DESKTOPMODE ); + if ( nPos != MENU_ITEM_NOTFOUND ) + pStarViewMenu->RemoveItem( nPos ); +#endif + + pSVMenu = pStarViewMenu; + + bResCtor = bRes; + bOLE = bOLEServer; + nId = 0; + pParent = 0; + pAppCtrl = 0; + nVisibleItems = 0; + 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); + + if ( bIsActive ) + { + pBindings->LEAVEREGISTRATIONS(); --nLocks; bIsActive = FALSE; + } + + // QAP-Hack + if ( pAutoDeactivate ) + { + if ( pAutoDeactivate->IsActive() ) + Deactivate(0); + DELETEX(pAutoDeactivate); + } + + if (pItems) + { +#ifdef MPW + // der MPW-Compiler ruft sonst keine Dtoren! + for ( USHORT n = 0; n < nCount; ++n ) + (pItems+n)->SfxMenuControl::~SfxMenuControl(); + delete (void*) pItems; +#else + __DELETE(nCount) pItems; +#endif + } + + 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; + } + + delete pSVMenu; + } + + DBG_OUTF( ("SfxVirtualMenu %lx destroyed", this) ); + DBG_ASSERT( !nLocks, "destroying active menu" ); +} +//-------------------------------------------------------------------- + +// internal: creates the virtual menu from the pSVMenu + +void SfxVirtualMenu::CreateFromSVMenu() +{ + DBG_MEMTEST(); + DBG_CHKTHIS(SfxVirtualMenu, 0); + + // 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 + SfxApplication *pSfxApp = SFX_APP(); + const int bOleServer = FALSE; + const int bMac = FALSE; + + // iterate through the items + pBindings->ENTERREGISTRATIONS(); ++nLocks; + USHORT nSVPos = 0; + for ( USHORT nPos = 0; nPos < nCount; ++nPos, ++nSVPos ) + { + USHORT nId = pSVMenu->GetItemId(nSVPos); + PopupMenu* pPopup = pSVMenu->GetPopupMenu(nId); + if ( pPopup ) + { + DBG_ASSERT( SfxMenuManager::IsPopupFunction(nId) || + !SFX_SLOTPOOL().GetIdPool().IsLocked(nId), + "popupmenu with existing func-id" ); + SfxMenuControl *pMnuCtrl = + SfxMenuControl::CreateControl(nId, *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( nId ) == pPopup ) + pSVMenu->SetPopupMenu( nId, NULL ); + DELETEZ( pPopup ); + + SfxMenuCtrlArr_Impl &rCtrlArr = GetAppCtrl_Impl(); + rCtrlArr.C40_INSERT( SfxMenuControl, pMnuCtrl, rCtrlArr.Count() ); + (pItems+nPos)->Bind( 0, nId, pSVMenu->GetItemText(nId), + pSVMenu->GetHelpText(nId), *pBindings); + pMnuCtrl->Bind( this, nId, pSVMenu->GetItemText(nId), + pSVMenu->GetHelpText(nId), *pBindings); + } + else + { +/* + if ( nId >= SID_SFX_START && !SfxMenuManager::IsPopupFunction(nId) ) + { + // Echte Popups sollen keine SlotIds haben; leider sind + // da noch Altlasten mit herumzuschleppen ... + String aTitle = pSVMenu->GetItemText( nId ); + pSVMenu->SetPopupMenu( nId, NULL ); + USHORT nPos = pSVMenu->GetItemPos( nId ); + pSVMenu->RemoveItem( nPos ); + nId = 1; + while ( pSVMenu->GetItemPos(nId) != MENU_ITEM_NOTFOUND ) + nId++; + pSVMenu->InsertItem( nId, aTitle, 0, nPos ); + pSVMenu->SetPopupMenu( nId, pPopup ); + } +*/ + + pSVMenu->SetHelpId( nId, 0L ); + pMnuCtrl = pItems+nPos; + + // normalerweise jetzt erst im Activate-Handler + if ( bOLE ) + { + pMnuCtrl->Bind( this, nId, + *new SfxVirtualMenu(nId, this, *pPopup, bHelpInitialized, *pBindings, bOLE, bResCtor), + pSVMenu->GetItemText(nId), pSVMenu->GetHelpText(nId), + *pBindings ); + } + } + + ++nVisibleItems; + } + else + { + switch ( pSVMenu->GetItemType(nSVPos) ) + { + case MENUITEM_STRING: + { + SfxMenuControl *pMnuCtrl; + String aCmd( pSVMenu->GetItemCommand( nId ) ); + if ( aCmd.Len() ) + { + pMnuCtrl = SfxMenuControl::CreateControl( aCmd, nId, + *pSVMenu, *pBindings, this ); + if ( pMnuCtrl ) + { + SfxMenuCtrlArr_Impl &rCtrlArr = GetAppCtrl_Impl(); + rCtrlArr.C40_INSERT( SfxMenuControl, + pMnuCtrl, rCtrlArr.Count()); + (pItems+nPos)->Bind( 0, nId, pSVMenu->GetItemText(nId), + pSVMenu->GetHelpText(nId), *pBindings); + } + else + { + pMnuCtrl = (pItems+nPos); + pMnuCtrl->Bind( this, nId, pSVMenu->GetItemText(nId), + pSVMenu->GetHelpText(nId), *pBindings); + } + } + else + { + pMnuCtrl = SfxMenuControl::CreateControl(nId, + *pSVMenu, *pBindings); + + if ( pMnuCtrl ) + { + SfxMenuCtrlArr_Impl &rCtrlArr = GetAppCtrl_Impl(); + rCtrlArr.C40_INSERT( SfxMenuControl, + pMnuCtrl, rCtrlArr.Count()); + (pItems+nPos)->Bind( 0, nId, pSVMenu->GetItemText(nId), + pSVMenu->GetHelpText(nId), *pBindings); + } + else + pMnuCtrl = (pItems+nPos); + + pMnuCtrl->Bind( this, nId, pSVMenu->GetItemText(nId), + pSVMenu->GetHelpText(nId), *pBindings); + } + + if ( !IsItemHidden_Impl(nId, bOleServer, bMac) ) + ++nVisibleItems; + else + pSVMenu->RemoveItem( nSVPos-- ); + break; + } + + case MENUITEM_IMAGE: + //! not implemented + break; + + case MENUITEM_SEPARATOR: + //! not implemented + break; + } + } + } + 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 nId = pMenu->GetCurItemId(); + if ( pAutoDeactivate ) + pAutoDeactivate->Stop(); + } + + return TRUE; +} +//-------------------------------------------------------------------- + +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. + 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() ) + { + DBG_ASSERT( !pSubMenu, "Popup schon vorhanden!"); + + // 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 ); + + // 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 nId = pCtrl->GetId(); + if ( !pSVMenu->GetItemCommand(nId).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; +} + + +//-------------------------------------------------------------------- + +// called on activation of the SV-Menu + +#define ITEMID_MDIWINDOW SHRT_MAX // all values greater than maximum value for slotids + +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 = (sal_Bool)(sal_uInt16) + SFX_INIMANAGER()->Get( SFX_KEY_DONTHIDE_DISABLEDENTRIES ).ToInt32(); + 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_Impl::Get()->SetPickMenu( pParent->pPickMenu ); + } + else + pPickMenu = pSVMenu->GetPopupMenu(SID_PICKLIST); + + if ( pParent && pSVMenu == pParent->pWindowMenu ) + { + PopupMenu* pWindowMenu = pParent->pWindowMenu; + sal_uInt16 nPos = pWindowMenu->GetItemPos( ITEMID_MDIWINDOW ); + for ( sal_uInt16 n=nPos; n<pWindowMenu->GetItemCount(); ) + pWindowMenu->RemoveItem( n ); + if ( pWindowMenu->GetItemType( pWindowMenu->GetItemCount()-1 ) == MENUITEM_SEPARATOR ) + pWindowMenu->RemoveItem( pWindowMenu->GetItemCount()-1 ); + + SfxViewFrame *pView = pBindings->GetDispatcher()->GetFrame(); + while ( pView->GetParentViewFrame_Impl() ) + pView = pView->GetParentViewFrame_Impl(); + SfxFrame *pActive = pView->GetFrame(); + + SfxFrameArr_Impl& rArr = *SFX_APP()->Get_Impl()->pTopFrames; + if ( rArr.Count() > 0 && + pWindowMenu->GetItemType( pWindowMenu->GetItemCount()-1 ) != MENUITEM_SEPARATOR ) + pWindowMenu->InsertSeparator(); + sal_uInt16 nNo; + sal_uInt16 nAllowedMenuSize = USHRT_MAX - ITEMID_MDIWINDOW; + for ( nNo = 0, nPos = 0; ( nPos < nAllowedMenuSize ) && ( nNo < rArr.Count() ); ++nNo ) + { + SfxFrame *pFrame = rArr[nNo]; + if ( pFrame->GetCurrentViewFrame() && pFrame->GetCurrentViewFrame()->IsVisible() ) + { + pWindowMenu->InsertItem( ITEMID_MDIWINDOW + nNo, + pFrame->GetWindow().GetText(), MIB_RADIOCHECK ); + if ( pFrame == pActive ) + pWindowMenu->CheckItem( ITEMID_MDIWINDOW + nNo, sal_True ); + nPos++; + } + } + } + else + pWindowMenu = pSVMenu->GetPopupMenu(SID_MDIWINDOWLIST); + + // f"ur konstistenten Status sorgen + if ( bControllersUnBound ) + BindControllers(); + + pBindings->GetDispatcher_Impl()->Flush(); + for ( USHORT nPos = 0; nPos < nCount; ++nPos ) + { + USHORT nId = (pItems+nPos)->GetId(); + if ( nId && nId < ITEMID_MDIWINDOW ) + pBindings->Update(nId); + } + + if ( bRemoveDisabledEntries ) + RemoveDisabledEntries(); + + // HelpText on-demand + if ( !bHelpInitialized ) + { + bHelpInitialized = TRUE; + SfxSlotPool &rSlotPool = SFX_SLOTPOOL(); + for ( USHORT nPos = 0; nPos < pMenu->GetItemCount(); ++nPos ) + { + USHORT nId = pMenu->GetItemId(nPos); + pMenu->SetHelpText( nId, rSlotPool.GetSlotHelpText_Impl(nId) ); + } + } + + // bis zum Deactivate die Statusupdates unterdr"ucken + pBindings->ENTERREGISTRATIONS(); ++nLocks; bIsActive = TRUE; + + if ( pAutoDeactivate ) // QAP-Hack + pAutoDeactivate->Start(); + + // 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; + } + + return FALSE; // dead code for WTC +} + +//-------------------------------------------------------------------- + +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 nId = (USHORT) pMenu->GetCurItemId(); + DBG_OUTF( ("SfxVirtualMenu %lx selected %u from %lx", this, nId, pMenu) ); + + if ( pSVMenu->GetItemCommand( nId ).Len() ) + { + SfxMenuCtrlArr_Impl& rCtrlArr = GetAppCtrl_Impl(); + for ( USHORT nPos=0; nPos<rCtrlArr.Count(); nPos++ ) + { + SfxMenuControl* pCtrl = rCtrlArr[nPos]; + if ( pCtrl->GetId() == nId ) + { + SfxUnoMenuControl *pUnoCtrl = (SfxUnoMenuControl*) pCtrl; + pUnoCtrl->Select(); + return TRUE; + } + } + } + + if ( nId >= ITEMID_MDIWINDOW ) + { + SfxFrameArr_Impl& rArr = *SFX_APP()->Get_Impl()->pTopFrames; + sal_uInt16 nWindowId = nId - ITEMID_MDIWINDOW; + if ( nWindowId < rArr.Count() ) + { + SfxFrame *pFrame = rArr[ nWindowId ]; + SfxViewFrame *pView = pFrame->GetCurrentViewFrame(); + pView->MakeActive_Impl( TRUE ); + return sal_True; + } + } + + pBindings->Execute( nId ); + + return TRUE; +} +//-------------------------------------------------------------------- + +// 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 associated StarView-menu + +Menu* SfxVirtualMenu::GetSVMenu() const +{ + DBG_MEMTEST(); + DBG_CHKTHIS(SfxVirtualMenu, 0); + + return pSVMenu; +} + +//-------------------------------------------------------------------- + +// returns the popup-menu assigned to the item or 0 if none + +SfxVirtualMenu* SfxVirtualMenu::GetPopupMenu( USHORT nId ) const +{ + DBG_MEMTEST(); + DBG_CHKTHIS(SfxVirtualMenu, 0); + + USHORT nPos = GetItemPos(nId); + 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 nId ) const +{ + DBG_MEMTEST(); + DBG_CHKTHIS(SfxVirtualMenu, 0); + + USHORT nPos = GetItemPos(nId); + 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 nId ) const +{ + DBG_MEMTEST(); + DBG_CHKTHIS(SfxVirtualMenu, 0); + + USHORT nPos = GetItemPos(nId); + if ( nPos != MENU_ITEM_NOTFOUND ) + return (pItems+nPos)->GetHelpText(); + return String(); +} + +//-------------------------------------------------------------------- + +void SfxVirtualMenu::InvalidateKeyCodes() +{ + DBG_ASSERT( pSVMenu, "invalidating key of incomplete menu" ); + + SfxApplication* pSfxApp = SFX_APP(); + SfxViewFrame *pViewFrame = pSfxApp->GetViewFrame(); + SfxAcceleratorManager* pAccMgr = pViewFrame->GetViewShell()->GetAccMgr_Impl(); + if ( !pAccMgr ) + return; + + SfxAcceleratorManager* pAppAccel = pSfxApp->GetAppAccel_Impl(); + for ( USHORT nPos = 0; nPos < pSVMenu->GetItemCount(); ++nPos ) + { + USHORT nId = pSVMenu->GetItemId(nPos); + SfxVirtualMenu *pPopup = GetPopupMenu(nId); + if ( pPopup ) + pPopup->InvalidateKeyCodes(); + else if ( nId ) + { + KeyCode aCode = pAccMgr->GetKeyCode( nId ); + if ( !aCode.GetCode() && pAccMgr != pAppAccel ) + aCode = pAppAccel->GetKeyCode( nId ); + pSVMenu->SetAccelKey( nId, aCode ); + } + } +} + +//-------------------------------------------------------------------- + +// 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 nId, PopupMenu *pMenu ) +{ + DBG_MEMTEST(); + DBG_CHKTHIS(SfxVirtualMenu, 0); + + if (pSVMenu->GetItemPos( nId ) != MENU_ITEM_NOTFOUND ) + GetSVMenu()->SetPopupMenu( nId, pMenu ); + for ( USHORT n = 0; n < nCount; ++n ) + { + SfxVirtualMenu *pSubMenu = (pItems+n)->GetPopupMenu(); + if ( pSubMenu ) + pSubMenu->SetPopupMenu( nId, 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() +{ + SfxSlotPool &rSlotPool = SFX_SLOTPOOL(); + for ( USHORT nPos = 0; nPos<pSVMenu->GetItemCount(); ++nPos ) + { + USHORT nId = pSVMenu->GetItemId(nPos); + if ( !bHelpInitialized ) + pSVMenu->SetHelpText( nId, rSlotPool.GetSlotHelpText_Impl( nId ) ); + SfxMenuControl &rCtrl = pItems[nPos]; + if ( nId && !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; +/* SvLibrary aLib( SVLIBRARY( "ss" ) ); + if ( aLib.ModulFound() ) + { + HelpIdFunc pFunc = (HelpIdFunc) aLib.GetFunction( DEFINE_CONST_UNICODE("GetHelpId") ); + if ( pFunc ) + { + for ( USHORT nPos=0; nPos<pSVMenu->GetItemCount(); nPos++ ) + { + USHORT nId = pSVMenu->GetItemId( nPos ); + SfxVirtualMenu *pPopup = GetPopupMenu(nId); + if ( pPopup ) + pPopup->SetHelpIds( pResMgr ); + else + { + USHORT nHelpId = (*pFunc)( pSVMenu->GetItemCommand( nId ) ); + pSVMenu->SetHelpId( nId, nHelpId ); + } + } + } + }*/ +} + +void SfxVirtualMenu::SetRemoveDisabledEntries() +{ + bRemoveDisabledEntries = TRUE; +} + +void SfxVirtualMenu::RemoveDisabledEntries() +{ + pBindings->ENTERREGISTRATIONS(); + + // Zuerst die Spezial-Controller + SfxMenuCtrlArr_Impl& rCtrlArr = GetAppCtrl_Impl(); + USHORT nPos; + for ( nPos=0; nPos<rCtrlArr.Count(); nPos++ ) + { + SfxMenuControl* pCtrl = rCtrlArr[nPos]; + USHORT nId = pCtrl->GetId(); + if ( !pSVMenu->IsItemEnabled( nId ) && pCtrl->IsBound() ) + pCtrl->UnBind(); + } + + for ( nPos = 0; nPos<nCount; ++nPos ) + { + SfxMenuControl &rCtrl = pItems[nPos]; + USHORT nId = rCtrl.GetId(); + if ( nId && !pSVMenu->IsItemEnabled( nId ) && rCtrl.IsBound() ) + rCtrl.UnBind(); + + SfxVirtualMenu *pPopup = rCtrl.GetPopupMenu(); + if ( pPopup ) + { + pPopup->RemoveDisabledEntries(); + if ( !pPopup->pSVMenu->GetItemCount() ) + { + rCtrl.RemovePopup(); + pSVMenu->RemoveItem( pSVMenu->GetItemPos( nId ) ); + } + } + } + + pSVMenu->RemoveDisabledEntries( FALSE, FALSE ); + pBindings->LEAVEREGISTRATIONS(); +} + + |