xref: /trunk/main/sfx2/source/menu/virtmenu.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sfx2.hxx"
30 
31 #include <sot/factory.hxx>
32 #include <svtools/menuoptions.hxx>
33 #include <svtools/imagemgr.hxx>
34 #include <svl/imageitm.hxx>
35 #include <com/sun/star/container/XEnumeration.hpp>
36 #include <com/sun/star/frame/XDesktop.hpp>
37 #include <com/sun/star/frame/XFramesSupplier.hpp>
38 #include <comphelper/processfactory.hxx>
39 #include <toolkit/unohlp.hxx>
40 #include <tools/urlobj.hxx>
41 
42 #include "virtmenu.hxx"
43 #include <sfx2/msgpool.hxx>
44 #include "statcach.hxx"
45 #include <sfx2/msg.hxx>
46 #include "idpool.hxx"
47 #include <sfx2/mnuitem.hxx>
48 #include <sfx2/mnumgr.hxx>
49 #include <sfx2/bindings.hxx>
50 #include <sfx2/dispatch.hxx>
51 #include <sfx2/app.hxx>
52 #include "sfxtypes.hxx"
53 #include "arrdecl.hxx"
54 #include <sfx2/sfx.hrc>
55 #include <sfx2/viewsh.hxx>
56 #include "sfxpicklist.hxx"
57 #include "sfx2/sfxresid.hxx"
58 #include "menu.hrc"
59 #include "sfx2/imagemgr.hxx"
60 #include <sfx2/viewfrm.hxx>
61 #include <sfx2/objsh.hxx>
62 #include <framework/addonsoptions.hxx>
63 
64 #ifndef __FRAMEWORK_CLASSES_ADDONMENUS_HXX_
65 #include <framework/addonmenu.hxx>
66 #endif
67 #include <framework/menuconfiguration.hxx>
68 
69 using namespace ::com::sun::star::container;
70 using namespace ::com::sun::star::frame;
71 using namespace ::com::sun::star::uno;
72 
73 //=========================================================================
74 
75 DBG_NAME(SfxVirtualMenu)
76 
77 //=========================================================================
78 
79 typedef SfxMenuControl* SfxMenuControlPtr;
80 SV_IMPL_PTRARR(SfxMenuCtrlArr_Impl, SfxMenuControlPtr);
81 
82 class SfxMenuImageControl_Impl : public SfxControllerItem
83 {
84     SfxVirtualMenu*     pMenu;
85     long                lRotation;
86     sal_Bool                bIsMirrored;
87 
88 protected:
89     virtual void        StateChanged( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState );
90 public:
91                         SfxMenuImageControl_Impl( sal_uInt16 nSlotId, SfxBindings& rBindings, SfxVirtualMenu* pVMenu )
92                             : SfxControllerItem( nSlotId, rBindings )
93                             , pMenu( pVMenu )
94                             , lRotation( 0 )
95                             , bIsMirrored( sal_False )
96                         {}
97     void                Update();
98 };
99 
100 void SfxMenuImageControl_Impl::StateChanged( sal_uInt16 /*nSID*/, SfxItemState /*eState*/, const SfxPoolItem* pState )
101 {
102     const SfxImageItem* pItem = PTR_CAST( SfxImageItem, pState );
103     if ( pItem )
104     {
105         lRotation = pItem->GetRotation();
106         bIsMirrored = pItem->IsMirrored();
107         Update();
108     }
109 }
110 
111 void SfxMenuImageControl_Impl::Update()
112 {
113     SfxViewFrame* pViewFrame = GetBindings().GetDispatcher_Impl()->GetFrame();
114     SfxModule* pModule = pViewFrame->GetObjectShell()->GetModule();
115     SfxSlotPool* pPool = pModule->GetSlotPool();
116     Menu* pSVMenu = pMenu->GetSVMenu();
117     for (sal_uInt16 nPos = 0; nPos<pSVMenu->GetItemCount(); nPos++)
118     {
119         sal_uInt16 nslotId = pSVMenu->GetItemId( nPos );
120         const SfxSlot* pSlot = pPool->GetSlot( nslotId );
121         if ( pSlot && pSlot->IsMode( SFX_SLOT_IMAGEROTATION ) )
122         {
123             pSVMenu->SetItemImageMirrorMode( nslotId, sal_False );
124             pSVMenu->SetItemImageAngle( nslotId, lRotation );
125         }
126 
127         if ( pSlot && pSlot->IsMode( SFX_SLOT_IMAGEREFLECTION ) )
128             pSVMenu->SetItemImageMirrorMode( nslotId, bIsMirrored );
129     }
130 }
131 
132 //=========================================================================
133 
134 static Image RetrieveAddOnImage( Reference< com::sun::star::frame::XFrame >& rFrame,
135                                  const rtl::OUString& aImageId,
136                                  const rtl::OUString& aURL,
137                                  sal_Bool bBigImage,
138                                  sal_Bool bHiContrast )
139 {
140     Image aImage;
141 
142     if ( aImageId.getLength() > 0 )
143     {
144         aImage = GetImage( rFrame, aImageId, bBigImage, bHiContrast );
145         if ( !!aImage )
146             return aImage;
147     }
148 
149     aImage = GetImage( rFrame, aURL, bBigImage, bHiContrast );
150     if ( !aImage )
151         aImage = framework::AddonsOptions().GetImageFromURL( aURL, bBigImage, bHiContrast );
152 
153     return aImage;
154 }
155 
156 //=========================================================================
157 
158 /*  Diese Hilfsfunktion pr"uft, ob eine Slot-Id im aktuellen Applikations-
159     Status sichtbar ist oder nicht. Dabei bezieht sich der Applikations-Status
160     darauf, ob die Applikation OLE-Server ist oder nicht.
161 */
162 
163 sal_Bool IsItemHidden_Impl( sal_uInt16 nItemId, int bOleServer, int bMac )
164 {
165     return ( bMac &&
166              ( nItemId == SID_MINIMIZED ) ) ||
167            (  bOleServer &&
168              ( nItemId == SID_QUITAPP || nItemId == SID_SAVEDOC ||
169                nItemId == SID_OPENDOC || nItemId == SID_SAVEASDOC ||
170                nItemId == SID_NEWDOC ) ) ||
171            ( !bOleServer &&
172              ( nItemId == SID_EXITANDRETURN || nItemId == SID_UPDATEDOC ) );
173 }
174 
175 //====================================================================
176 
177 void SfxVirtualMenu::Construct_Impl()
178 {
179     pSVMenu->SetHighlightHdl( LINK(this, SfxVirtualMenu, Highlight) );
180     pSVMenu->SetActivateHdl( LINK(this, SfxVirtualMenu, Activate) );
181     pSVMenu->SetDeactivateHdl( LINK(this, SfxVirtualMenu, Deactivate) );
182     pSVMenu->SetSelectHdl( LINK(this, SfxVirtualMenu, Select) );
183 
184     // #107258# accelerator keys are needed for accessibility
185     //if ( bOLE )
186     //    InvalidateKeyCodes();
187 
188     if ( !pResMgr && pParent )
189         pResMgr = pParent->pResMgr;
190 }
191 
192 //--------------------------------------------------------------------
193 
194 SfxVirtualMenu::SfxVirtualMenu( sal_uInt16 nOwnId,
195                 SfxVirtualMenu* pOwnParent, Menu& rMenu, sal_Bool bWithHelp,
196                 SfxBindings &rBindings, sal_Bool bOLEServer, sal_Bool bRes, sal_Bool bIsAddonMenu ):
197     pItems(0),
198        pImageControl(0),
199     pBindings(&rBindings),
200     pResMgr(0),
201     pAutoDeactivate(0),
202     nLocks(0),
203     bHelpInitialized( bWithHelp ),
204     bWasHighContrast( sal_False ),
205     bIsAddonPopupMenu( bIsAddonMenu )
206 {
207     DBG_MEMTEST();
208     DBG_CTOR(SfxVirtualMenu, 0);
209     pSVMenu = &rMenu;
210 
211     bResCtor = bRes;
212     bOLE = bOLEServer;
213     nId = nOwnId;
214     pParent = pOwnParent;
215     nVisibleItems = 0;
216     pAppCtrl = 0;
217     pWindowMenu = NULL;
218     pPickMenu = NULL;
219     pAddonsMenu = NULL;
220     bIsActive = sal_False;
221     bControllersUnBound = sal_False;
222     CreateFromSVMenu();
223     Construct_Impl();
224     bHelpInitialized = sal_False;
225 }
226 
227 //--------------------------------------------------------------------
228 
229 // creates a virtual menu from a StarView MenuBar or PopupMenu
230 
231 SfxVirtualMenu::SfxVirtualMenu( Menu *pStarViewMenu, sal_Bool bWithHelp,
232                     SfxBindings &rBindings, sal_Bool bOLEServer, sal_Bool bRes, sal_Bool bIsAddonMenu ):
233     pItems(0),
234        pImageControl(0),
235     pBindings(&rBindings),
236     pResMgr(0),
237     pAutoDeactivate(0),
238     nLocks(0),
239     bHelpInitialized( bWithHelp ),
240     bWasHighContrast( sal_False ),
241     bIsAddonPopupMenu( bIsAddonMenu )
242 {
243     DBG_MEMTEST();
244     DBG_CTOR(SfxVirtualMenu, 0);
245 
246     pSVMenu = pStarViewMenu;
247 
248     bResCtor = bRes;
249     bOLE = bOLEServer;
250     nId = 0;
251     pParent = 0;
252     pAppCtrl = 0;
253     nVisibleItems = 0;
254     pWindowMenu = NULL;
255     pPickMenu = NULL;
256     pAddonsMenu = NULL;
257     bIsActive = sal_False;
258     bControllersUnBound = sal_False;
259     CreateFromSVMenu();
260     Construct_Impl();
261     bHelpInitialized = sal_False;
262 }
263 
264 //--------------------------------------------------------------------
265 
266 /*  Der Destruktor der Klasse SfxVirtualMenu gib die gebundenen Items frei
267     und klinkt das zugeh"orige StarView-PopupMenu aus seinem Parent aus.
268     Falls es sich um das Pickmenu oder das MDI-Menu handelt, wird es
269     dort abgemeldet.
270 */
271 
272 SfxVirtualMenu::~SfxVirtualMenu()
273 {
274     DBG_MEMTEST();
275     DBG_DTOR(SfxVirtualMenu, 0);
276 
277     DELETEZ( pImageControl );
278     SvtMenuOptions().RemoveListenerLink( LINK( this, SfxVirtualMenu, SettingsChanged ) );
279 
280     if ( bIsActive )
281     {
282         pBindings->LEAVEREGISTRATIONS(); --nLocks; bIsActive = sal_False;
283     }
284 
285     // QAP-Hack
286     if ( pAutoDeactivate )
287     {
288         if ( pAutoDeactivate->IsActive() )
289             Deactivate(0);
290         DELETEX(pAutoDeactivate);
291     }
292 
293     if (pItems)
294     {
295         delete [] pItems;
296     }
297 
298     delete pAppCtrl;
299     pBindings = 0;
300 
301     // Alle Menues, die von SV erzeugt wurden, werden auch dort wieder
302     // gel"oscht (also die beim Laden aus der Resource erzeugten).
303     // Das Top-Level-Menu wird nie von SV gel"oscht, da die Allocierung
304     // im SFX erfolgt
305     if ( !bResCtor || !pParent)
306     {
307         if ( pParent )
308         {
309             if( pParent->pSVMenu->GetItemPos( nId ) != MENU_ITEM_NOTFOUND )
310                 pParent->pSVMenu->SetPopupMenu( nId, 0 );
311             if ( pParent->pPickMenu == pSVMenu )
312                 pParent->pPickMenu = 0;
313             if ( pParent->pWindowMenu == pSVMenu)
314                 pParent->pWindowMenu = 0;
315             if ( pParent->pAddonsMenu == pSVMenu )
316                 pParent->pAddonsMenu = 0;
317         }
318 
319         delete pSVMenu;
320     }
321 
322     DBG_OUTF( ("SfxVirtualMenu %lx destroyed", this) );
323     DBG_ASSERT( !nLocks, "destroying active menu" );
324 }
325 //--------------------------------------------------------------------
326 
327 sal_Bool SfxVirtualMenu::IsHiContrastMode() const
328 {
329     const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
330     return rSettings.GetHighContrastMode();
331 }
332 
333 //--------------------------------------------------------------------
334 // internal: creates the virtual menu from the pSVMenu
335 
336 void SfxVirtualMenu::CreateFromSVMenu()
337 {
338     DBG_MEMTEST();
339     DBG_CHKTHIS(SfxVirtualMenu, 0);
340 
341     // Merge Addon popup menus into the SV Menu
342     SfxViewFrame* pViewFrame = pBindings->GetDispatcher()->GetFrame();
343     SfxSlotPool* pSlotPool = pViewFrame->GetObjectShell()->GetModule()->GetSlotPool();
344     Reference< com::sun::star::frame::XFrame > xFrame( pViewFrame->GetFrame().GetFrameInterface() );
345 
346     if ( pSVMenu->IsMenuBar() )
347     {
348         sal_uInt16 nPos = pSVMenu->GetItemPos( SID_MDIWINDOWLIST );
349         if ( nPos != MENU_ITEM_NOTFOUND && xFrame.is() )
350         {
351             // Retrieve addon popup menus and add them to our menu bar
352             Reference< com::sun::star::frame::XModel >      xModel;
353             Reference< com::sun::star::frame::XController > xController( xFrame->getController(), UNO_QUERY );
354             if ( xController.is() )
355                 xModel = Reference< com::sun::star::frame::XModel >( xController->getModel(), UNO_QUERY );
356             framework::AddonMenuManager::MergeAddonPopupMenus( xFrame, xModel, nPos, (MenuBar *)pSVMenu );
357         }
358 
359         // Merge the Add-Ons help menu items into the Office help menu
360         if ( xFrame.is() )
361             framework::AddonMenuManager::MergeAddonHelpMenu( xFrame, (MenuBar *)pSVMenu );
362 
363         // Set addon menu pointer here to avoid problems. When accessibility is enabled, the whole menu
364         // is created immediately!
365         pAddonsMenu = pSVMenu->GetPopupMenu( SID_ADDONLIST );
366     }
367     else if ( pParent )
368     {
369         if ( pSVMenu == pParent->pAddonsMenu &&
370              framework::AddonsOptions().HasAddonsMenu() &&
371              !pSVMenu->GetPopupMenu( SID_ADDONS ) )
372         {
373             // Create menu item at the end of the tools popup menu for the addons popup menu
374             InsertAddOnsMenuItem( pSVMenu );
375         }
376     }
377 
378     // get and store the number of items
379     nCount = pSVMenu->GetItemCount();
380 
381     // Achtung: nur zu diesem Zeitpunkt ist garantiert, da\s nCount und
382     // der ItemCount des SV-Menues "ubereinstimmen; sp"ater kann das SvMenue
383     // auch mehr Eintr"age haben (Pickliste!)
384     if (nCount)
385         pItems = new SfxMenuControl[nCount];
386 
387     // remember some values
388     SFX_APP();
389     const int bOleServer = sal_False;
390     const int bMac = sal_False;
391     SvtMenuOptions aOptions;
392     aOptions.AddListenerLink( LINK( this, SfxVirtualMenu, SettingsChanged ) );
393 
394     // iterate through the items
395     pBindings->ENTERREGISTRATIONS(); ++nLocks;
396     pImageControl = new SfxMenuImageControl_Impl( SID_IMAGE_ORIENTATION, *pBindings, this );
397 
398     // Update high contrast state
399     bWasHighContrast = IsHiContrastMode();
400 
401     sal_uInt16 nSVPos = 0;
402     for ( sal_uInt16 nPos=0; nPos<nCount; ++nPos, ++nSVPos )
403     {
404         sal_uInt16 nSlotId = pSVMenu->GetItemId(nSVPos);
405         PopupMenu* pPopup = pSVMenu->GetPopupMenu(nSlotId);
406         if( pPopup && nSlotId >= SID_OBJECTMENU0 && nSlotId <= SID_OBJECTMENU_LAST )
407         {
408             // artefact in XML menuconfig: every entry in root menu must have a popup!
409             pSVMenu->SetPopupMenu( nSlotId, NULL );
410             DELETEZ( pPopup );
411         }
412 
413         const String sItemText = pSVMenu->GetItemText(nSlotId);
414         const String sHelpText = pSVMenu->GetHelpText(nSlotId);
415 
416         if ( pPopup )
417         {
418 
419             SfxMenuControl *pMnuCtrl =
420                 SfxMenuControl::CreateControl(nSlotId, *pPopup, *pBindings);
421 
422             if ( pMnuCtrl )
423             {
424                 // Das Popup war offensichtlich kein "echtes"; solche werden
425                 // niemals aus der Resource geladen und m"ussen daher explizit
426                 // gel"oscht werden
427                 if ( pSVMenu->GetPopupMenu( nSlotId ) == pPopup )
428                     pSVMenu->SetPopupMenu( nSlotId, NULL );
429                 delete pPopup;
430                 pPopup = 0;
431 
432                 SfxMenuCtrlArr_Impl &rCtrlArr = GetAppCtrl_Impl();
433                 rCtrlArr.C40_INSERT( SfxMenuControl, pMnuCtrl, rCtrlArr.Count() );
434                 (pItems+nPos)->Bind( 0, nSlotId, sItemText, sHelpText, *pBindings);
435                 pMnuCtrl->Bind( this, nSlotId, sItemText, sHelpText, *pBindings);
436 
437                 if (  Application::GetSettings().GetStyleSettings().GetUseImagesInMenus() )
438                 {
439                     rtl::OUString aSlotURL( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
440                     aSlotURL += rtl::OUString::valueOf( sal_Int32( nSlotId ));
441                     Image aImage = GetImage( xFrame, aSlotURL, sal_False, bWasHighContrast );
442                     pSVMenu->SetItemImage( nSlotId, aImage );
443                 }
444             }
445             else
446             {
447                 const SfxSlot* pSlot = pSlotPool->GetSlot( nSlotId );
448                 if ( pSlot )
449                 {
450                     rtl::OString aCmd(".uno:");
451                     aCmd += pSlot->GetUnoName();
452                     pSVMenu->SetHelpId( nSlotId, pSlot->GetUnoName() );
453                 }
454 
455                 pMnuCtrl = pItems+nPos;
456 
457                 // normalerweise jetzt erst im Activate-Handler
458                 if ( bOLE )
459                 {
460                     pMnuCtrl->Bind( this, nSlotId,
461                         *new SfxVirtualMenu(nSlotId, this, *pPopup, bHelpInitialized, *pBindings, bOLE, bResCtor),
462                         sItemText, sHelpText,
463                         *pBindings );
464                 }
465             }
466 
467             ++nVisibleItems;
468         }
469         else
470         {
471             switch ( pSVMenu->GetItemType(nSVPos) )
472             {
473                 case MENUITEM_STRING:
474                 case MENUITEM_STRINGIMAGE:
475                 {
476                     SfxMenuControl *pMnuCtrl=0;
477                     String aCmd( pSVMenu->GetItemCommand( nSlotId ) );
478                     if ( aCmd.Len() && (( nSlotId < SID_SFX_START ) || ( nSlotId > SHRT_MAX )) )
479                     {
480                         // try to create control via comand name
481                         pMnuCtrl = SfxMenuControl::CreateControl( aCmd, nSlotId, *pSVMenu, sItemText, sHelpText, *pBindings, this );
482                         if ( pMnuCtrl )
483                         {
484                             SfxMenuCtrlArr_Impl &rCtrlArr = GetAppCtrl_Impl();
485                             rCtrlArr.C40_INSERT( SfxMenuControl, pMnuCtrl, rCtrlArr.Count());
486                             (pItems+nPos)->Bind( 0, nSlotId, sItemText, sHelpText, *pBindings);
487                         }
488                     }
489 
490                     if ( !pMnuCtrl )
491                     {
492                         // try to create control via Id
493                         pMnuCtrl = SfxMenuControl::CreateControl(nSlotId, *pSVMenu, *pBindings);
494                         if ( pMnuCtrl )
495                         {
496                             SfxMenuCtrlArr_Impl &rCtrlArr = GetAppCtrl_Impl();
497                             rCtrlArr.C40_INSERT( SfxMenuControl, pMnuCtrl, rCtrlArr.Count());
498                             (pItems+nPos)->Bind( 0, nSlotId, sItemText, sHelpText, *pBindings);
499                         }
500                         else
501                             // take default control
502                             pMnuCtrl = (pItems+nPos);
503 
504                         pMnuCtrl->Bind( this, nSlotId, sItemText, sHelpText, *pBindings);
505                     }
506 
507                     if ( Application::GetSettings().GetStyleSettings().GetUseImagesInMenus() )
508                     {
509                         Image aImage;
510                         if ( bIsAddonPopupMenu || framework::AddonMenuManager::IsAddonMenuId( nSlotId ))
511                         {
512                             rtl::OUString aImageId;
513 
514                             ::framework::MenuConfiguration::Attributes* pMenuAttributes =
515                                 (::framework::MenuConfiguration::Attributes*)pSVMenu->GetUserValue( nSlotId );
516 
517                             if ( pMenuAttributes )
518                                 aImageId = pMenuAttributes->aImageId; // Retrieve image id from menu attributes
519 
520                             aImage = RetrieveAddOnImage( xFrame, aImageId, aCmd, sal_False, bWasHighContrast );
521                         }
522                         else
523                         {
524                             rtl::OUString aSlotURL( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
525                             aSlotURL += rtl::OUString::valueOf( sal_Int32( nSlotId ));
526                             aImage = GetImage( xFrame, aSlotURL, sal_False, bWasHighContrast );
527                         }
528 
529                         if ( !!aImage )
530                             pSVMenu->SetItemImage( nSlotId, aImage );
531                     }
532 
533                     if ( !IsItemHidden_Impl(nSlotId, bOleServer, bMac) )
534                         ++nVisibleItems;
535                     else
536                         pSVMenu->RemoveItem( nSVPos-- );
537                     break;
538                 }
539 
540                 case MENUITEM_IMAGE:
541                     //! not implemented
542                     break;
543 
544                 case MENUITEM_SEPARATOR:
545                     //! not implemented
546                     break;
547                 default:
548                     break; // DONTKNOW and STRINGIMAGE not handled.
549             }
550         }
551     }
552     pBindings->LEAVEREGISTRATIONS(); --nLocks;
553 }
554 
555 //--------------------------------------------------------------------
556 
557 // called on activation of the SV-Menu
558 
559 IMPL_LINK( SfxVirtualMenu, Highlight, Menu *, pMenu )
560 {
561     DBG_MEMTEST();
562     DBG_CHKTHIS(SfxVirtualMenu, 0);
563 
564     // eigenes StarView-Menu
565     if ( pMenu == pSVMenu )
566     {
567         // AutoDeactivate ist jetzt nicht mehr n"otig
568         //sal_uInt16 nSlotId = pMenu->GetCurItemId();
569         if ( pAutoDeactivate )
570             pAutoDeactivate->Stop();
571     }
572 
573     return sal_True;
574 }
575 
576 IMPL_LINK( SfxVirtualMenu, SettingsChanged, void*, EMPTYARG )
577 {
578     sal_uInt16 nItemCount = pSVMenu->GetItemCount();
579     SfxViewFrame *pViewFrame = pBindings->GetDispatcher()->GetFrame();
580     sal_Bool bIcons = Application::GetSettings().GetStyleSettings().GetUseImagesInMenus();
581     sal_Bool bIsHiContrastMode = IsHiContrastMode();
582     Reference<com::sun::star::frame::XFrame> xFrame( pViewFrame->GetFrame().GetFrameInterface() );
583 
584     if ( !bIsAddonPopupMenu )
585     {
586         for ( sal_uInt16 nSVPos=0; nSVPos<nItemCount; ++nSVPos )
587         {
588             sal_uInt16          nSlotId = pSVMenu->GetItemId( nSVPos );
589             MenuItemType    nType   = pSVMenu->GetItemType( nSVPos );
590             if ( nType == MENUITEM_STRING && bIcons )
591             {
592                 if ( framework::AddonMenuManager::IsAddonMenuId( nSlotId ))
593                 {
594                     // Special code for Add-On menu items. They can appear inside the help menu.
595                     rtl::OUString aCmd( pSVMenu->GetItemCommand( nSlotId ) );
596                     rtl::OUString aImageId;
597 
598                     ::framework::MenuConfiguration::Attributes* pMenuAttributes =
599                         (::framework::MenuConfiguration::Attributes*)pSVMenu->GetUserValue( nSlotId );
600 
601                     if ( pMenuAttributes )
602                         aImageId = pMenuAttributes->aImageId; // Retrieve image id from menu attributes
603 
604                     pSVMenu->SetItemImage( nSlotId, RetrieveAddOnImage( xFrame, aImageId, aCmd, sal_False, bIsHiContrastMode ));
605                 }
606                 else
607                 {
608                     rtl::OUString aSlotURL( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
609                     aSlotURL += rtl::OUString::valueOf( sal_Int32( nSlotId ));
610                     pSVMenu->SetItemImage( nSlotId, GetImage( xFrame, aSlotURL, sal_False, bWasHighContrast ));
611                 }
612             }
613             else if( nType == MENUITEM_STRINGIMAGE && !bIcons )
614             {
615                 pSVMenu->SetItemImage( nSlotId, Image() );
616             }
617         }
618     }
619     else
620     {
621         // Remove/update images from Add-Ons top-level popup menus when settings have changed
622         if ( !bIcons )
623             RemoveMenuImages( pSVMenu );
624         else
625             UpdateImages( pSVMenu );
626     }
627 
628     // Special code to remove menu images from runtime popup menus when settings have changed
629     if ( pParent && pSVMenu == pParent->pAddonsMenu )
630     {
631         if ( !bIcons )
632             RemoveMenuImages( pParent->pAddonsMenu->GetPopupMenu( SID_ADDONS ));
633         else
634             UpdateImages( pParent->pAddonsMenu->GetPopupMenu( SID_ADDONS ));
635     }
636 
637     if ( pImageControl )
638         pImageControl->Update();
639 
640     return 0;
641 }
642 
643 //--------------------------------------------------------------------
644 
645 void SfxVirtualMenu::UpdateImages()
646 {
647     sal_Bool bIcons = Application::GetSettings().GetStyleSettings().GetUseImagesInMenus();
648 
649     if ( bIcons )
650     {
651         sal_Bool            bIsHiContrastMode   = IsHiContrastMode();
652         sal_uInt16          nItemCount          = pSVMenu->GetItemCount();
653         SfxViewFrame *  pViewFrame          = pBindings->GetDispatcher()->GetFrame();
654         Reference<com::sun::star::frame::XFrame> xFrame( pViewFrame->GetFrame().GetFrameInterface() );
655 
656         for ( sal_uInt16 nSVPos=0; nSVPos < nItemCount; ++nSVPos )
657         {
658             sal_uInt16 nSlotId = pSVMenu->GetItemId( nSVPos );
659             if ( pSVMenu->GetItemType( nSVPos ) == MENUITEM_STRINGIMAGE )
660             {
661                 if ( framework::AddonMenuManager::IsAddonMenuId( nSlotId ))
662                 {
663                     // Special code for Add-On menu items. They can appear inside the help menu.
664                     rtl::OUString aCmd( pSVMenu->GetItemCommand( nSlotId ) );
665                     rtl::OUString aImageId;
666 
667                     ::framework::MenuConfiguration::Attributes* pMenuAttributes =
668                         (::framework::MenuConfiguration::Attributes*)pSVMenu->GetUserValue( nSlotId );
669 
670                     if ( pMenuAttributes )
671                         aImageId = pMenuAttributes->aImageId; // Retrieve image id from menu attributes
672 
673                     pSVMenu->SetItemImage( nSlotId, RetrieveAddOnImage( xFrame, aImageId, aCmd, sal_False, bIsHiContrastMode ));
674                 }
675                 else
676                 {
677                     rtl::OUString aSlotURL( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
678                     aSlotURL += rtl::OUString::valueOf( sal_Int32( nSlotId ));
679                     pSVMenu->SetItemImage( nSlotId, GetImage( xFrame, aSlotURL, sal_False, bWasHighContrast ));
680                 }
681             }
682         }
683 
684         if ( pImageControl )
685             pImageControl->Update();
686     }
687 }
688 
689 //--------------------------------------------------------------------
690 
691 void SfxVirtualMenu::UpdateImages( Menu* pMenu )
692 {
693     if ( !pMenu )
694         return;
695 
696     framework::AddonsOptions    aAddonOptions;
697 
698     sal_Bool bIcons = Application::GetSettings().GetStyleSettings().GetUseImagesInMenus();
699     if ( bIcons )
700     {
701         sal_Bool            bIsHiContrastMode   = IsHiContrastMode();
702         sal_uInt16          nItemCount          = pMenu->GetItemCount();
703         Reference<com::sun::star::frame::XFrame> aXFrame( pBindings->GetDispatcher_Impl()->GetFrame()->GetFrame().GetFrameInterface() );
704 
705         for ( sal_uInt16 nPos=0; nPos < nItemCount; ++nPos )
706         {
707             sal_uInt16 nSlotId = pMenu->GetItemId( nPos );
708             PopupMenu* pPopup = pMenu->GetPopupMenu( nSlotId );
709             if ( pMenu->GetItemType( nPos ) != MENUITEM_SEPARATOR )
710             {
711                 rtl::OUString aImageId;
712 
713                 ::framework::MenuConfiguration::Attributes* pMenuAttributes =
714                     (::framework::MenuConfiguration::Attributes*)pMenu->GetUserValue( nSlotId );
715 
716                 if ( pMenuAttributes )
717                     aImageId = pMenuAttributes->aImageId; // Retrieve image id from menu attributes
718 
719                 pMenu->SetItemImage( nSlotId, RetrieveAddOnImage( aXFrame, aImageId, pMenu->GetItemCommand( nSlotId ), sal_False, bIsHiContrastMode ));
720             }
721 
722             if ( pPopup )
723                 UpdateImages( pPopup );
724         }
725 
726         if ( pImageControl )
727             pImageControl->Update();
728     }
729 }
730 
731 //--------------------------------------------------------------------
732 
733 void SfxVirtualMenu::RemoveMenuImages( Menu* pMenu )
734 {
735     if ( !pMenu )
736         return;
737 
738     sal_uInt16 nItemCount = pMenu->GetItemCount();
739     for ( sal_uInt16 nPos=0; nPos < nItemCount; ++nPos )
740     {
741         sal_uInt16 nSlotId = pMenu->GetItemId( nPos );
742         PopupMenu* pPopup = pMenu->GetPopupMenu( nSlotId );
743         if ( pMenu->GetItemType( nPos ) == MENUITEM_STRINGIMAGE )
744             pMenu->SetItemImage( nSlotId, Image() );
745         if ( pPopup )
746             RemoveMenuImages( pPopup );
747     }
748 }
749 
750 //--------------------------------------------------------------------
751 
752 bool SfxVirtualMenu::Bind_Impl( Menu *pMenu )
753 {
754     // Selber suchen, da SV mit 'sal_uInt16 nSID = pSVMenu->GetCurItemId();' immer
755     // 0 liefert. Das ist so, weil die Event-Weiterleitung lt. TH nichts mit
756     // CurItem des Parent-Menus zu tun hat.
757     sal_uInt32 nAddonsPopupPrefixLen = ADDONSPOPUPMENU_URL_PREFIX.getLength();
758 
759     for ( sal_uInt16 nPos = 0; nPos < nCount; ++nPos )
760     {
761         // angesprochenes Sub-Menu gefunden?
762         bool bFound = false;
763         sal_uInt16 nSID = pSVMenu->GetItemId(nPos);
764         SfxMenuControl &rCtrl = pItems[nPos];
765         bFound = pSVMenu->GetPopupMenu(nSID) == pMenu;
766         SfxVirtualMenu *pSubMenu = rCtrl.GetPopupMenu();
767 
768         if ( bFound )
769         {
770             // Nur ein gebundener Menu-Controller hat schon seine Id!
771             if ( !rCtrl.GetId() )
772             {
773                 bIsAddonPopupMenu = sal_False;
774                 DBG_ASSERT( !pSubMenu, "Popup schon vorhanden!");
775 
776                 // Check if the popup is an Add-On popup menu
777                 // Either the popup menu has a special ID  or a special command URL prefix!
778                 rtl::OUString aCommand = pSVMenu->GetItemCommand( nSID );
779                 if ( ( nSID == SID_ADDONS ) ||
780                      ( nSID == SID_ADDONHELP ) ||
781                      (( (sal_uInt32)aCommand.getLength() > nAddonsPopupPrefixLen ) &&
782                       ( aCommand.indexOf( ADDONSPOPUPMENU_URL_PREFIX ) == 0 )) )
783                     bIsAddonPopupMenu = sal_True;
784 
785                 // VirtualMenu f"ur Sub-Menu erzeugen
786                 sal_Bool bRes = bResCtor;
787                 pSubMenu = new SfxVirtualMenu( nSID, this,
788                         *pMenu, sal_False, *pBindings, bOLE, bRes, bIsAddonPopupMenu );
789 
790                 DBG_OUTF( ("Neues VirtualMenu %lx erzeugt", pSubMenu) );
791 
792                 rCtrl.Bind( this, nSID, *pSubMenu,
793                     pSVMenu->GetItemText(nSID), pSVMenu->GetHelpText(nSID),
794                     *pBindings );
795 
796                 // Activate weiterleiten
797                 pSubMenu->Bind_Impl( pMenu );
798                 pSubMenu->Activate( pMenu );
799             }
800         }
801 
802         // rekursiv weitersuchen (SV Activate nur am Menu selbst und Top-Menu)
803         if ( !bFound && pSubMenu )
804             bFound = pSubMenu->Bind_Impl( pMenu );
805 
806         // gefunden, dann abbrechen
807         if ( bFound )
808             return true;
809     }
810 
811     // nicht in diesem Untermenu gefunden
812     return false;
813 }
814 
815 void SfxVirtualMenu::BindControllers()
816 {
817     pBindings->ENTERREGISTRATIONS();
818 
819     sal_uInt16 nPos;
820     for ( nPos = 0; nPos < nCount; ++nPos )
821     {
822         SfxMenuControl& rCtrl = pItems[nPos];
823         if ( rCtrl.IsBindable_Impl() && !rCtrl.GetPopupMenu() )
824             rCtrl.ReBind();
825     }
826 
827     SfxMenuCtrlArr_Impl& rCtrlArr = GetAppCtrl_Impl();
828     for ( nPos=0; nPos<rCtrlArr.Count(); nPos++ )
829     {
830         SfxMenuControl* pCtrl = rCtrlArr[nPos];
831         sal_uInt16 nSlotId = pCtrl->GetId();
832         if ( !pSVMenu->GetItemCommand(nSlotId).Len() )
833             pCtrl->ReBind();
834     }
835 
836     pBindings->LEAVEREGISTRATIONS();
837     bControllersUnBound = sal_False;
838 }
839 
840 void SfxVirtualMenu::UnbindControllers()
841 {
842     pBindings->ENTERREGISTRATIONS();
843 
844     sal_uInt16 nPos;
845     for ( nPos = 0; nPos < nCount; ++nPos )
846     {
847         SfxMenuControl &rCtrl = pItems[nPos];
848         if ( rCtrl.IsBound() )
849             rCtrl.UnBind();
850     }
851 
852     SfxMenuCtrlArr_Impl& rCtrlArr = GetAppCtrl_Impl();
853     for ( nPos=0; nPos<rCtrlArr.Count(); nPos++ )
854     {
855         SfxMenuControl* pCtrl = rCtrlArr[nPos];
856         if ( pCtrl->IsBound() )
857             // UnoController sind nicht gebunden!
858             pCtrl->UnBind();
859     }
860 
861     pBindings->LEAVEREGISTRATIONS();
862     bControllersUnBound = sal_True;
863 }
864 
865 
866 //--------------------------------------------------------------------
867 void SfxVirtualMenu::InsertAddOnsMenuItem( Menu* pMenu )
868 {
869     // Create special popup menu that is filled with the 3rd party components popup menu items
870     Reference<com::sun::star::lang::XMultiServiceFactory> aXMultiServiceFactory(::comphelper::getProcessServiceFactory());
871     ::framework::MenuConfiguration aConf( aXMultiServiceFactory );
872     Reference<com::sun::star::frame::XFrame> xFrame( pBindings->GetDispatcher_Impl()->GetFrame()->GetFrame().GetFrameInterface() );
873 
874     PopupMenu* pAddonMenu = NULL;
875     try
876     {
877         pAddonMenu = framework::AddonMenuManager::CreateAddonMenu( xFrame );
878     }
879     catch ( ::com::sun::star::lang::WrappedTargetException )
880     {
881     }
882 
883     // Create menu item at the end of the tools popup menu for the addons popup menu
884     if ( pAddonMenu && pAddonMenu->GetItemCount() > 0 )
885     {
886         sal_uInt16 nItemCount = pMenu->GetItemCount();
887         String aAddonsTitle( SfxResId( STR_MENU_ADDONS ));
888         if ( nItemCount > 0 && pMenu->GetItemType( nItemCount-1 ) != MENUITEM_SEPARATOR )
889             pMenu->InsertSeparator();
890         pMenu->InsertItem( SID_ADDONS, aAddonsTitle );
891         pMenu->SetPopupMenu( SID_ADDONS, pAddonMenu );
892 
893         if ( Application::GetSettings().GetStyleSettings().GetUseImagesInMenus() )
894         {
895                rtl::OUString aSlotURL( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
896                aSlotURL += rtl::OUString::valueOf( sal_Int32( SID_ADDONS ));
897          pMenu->SetItemImage( SID_ADDONS, GetImage( xFrame, aSlotURL, sal_False, bWasHighContrast ));
898         }
899     }
900     else
901         delete pAddonMenu;
902 }
903 
904 //--------------------------------------------------------------------
905 
906 // called on activation of the SV-Menu
907 
908 IMPL_LINK( SfxVirtualMenu, Activate, Menu *, pMenu )
909 {
910     DBG_MEMTEST();
911     DBG_CHKTHIS(SfxVirtualMenu, 0);
912     DBG_OUTF( ("SfxVirtualMenu %lx activated %lx, own %lx", this, pMenu, pSVMenu));
913 
914     // MI: wozu war der noch gut?
915     // MBA: scheint ein alter QAP-Hack gewesen zu sein ( in rev.1.41 eingecheckt ! )
916 //  if ( Application::IsInModalMode() )
917 //      return TRUE; // abw"urgen
918 
919     if ( pMenu )
920     {
921         sal_Bool bDontHide = SvtMenuOptions().IsEntryHidingEnabled();
922         sal_uInt16 nFlag = pMenu->GetMenuFlags();
923         if ( bDontHide )
924             nFlag &= ~MENU_FLAG_HIDEDISABLEDENTRIES;
925         else
926             nFlag |= MENU_FLAG_HIDEDISABLEDENTRIES;
927         pMenu->SetMenuFlags( nFlag );
928     }
929 
930     // eigenes StarView-Menu
931     if ( pMenu == pSVMenu )
932     {
933         // doppelt-Activate verhindern
934         if ( bIsActive )
935             return sal_True;
936 
937         // ggf. Pick-Menu erzeugen
938         if ( pParent && pSVMenu == pParent->pPickMenu )
939         {
940             SfxPickList::Get()->CreateMenuEntries( pParent->pPickMenu );
941         }
942         else
943             pPickMenu = pSVMenu->GetPopupMenu(SID_PICKLIST);
944 
945         if ( pParent && pSVMenu == pParent->pWindowMenu )
946         {
947             // update window list
948             ::std::vector< ::rtl::OUString > aNewWindowListVector;
949             Reference< XDesktop > xDesktop( ::comphelper::getProcessServiceFactory()->createInstance(
950                                             DEFINE_CONST_OUSTRING( "com.sun.star.frame.Desktop" ) ), UNO_QUERY );
951 
952             sal_uInt16  nActiveItemId = 0;
953             sal_uInt16  nItemId = START_ITEMID_WINDOWLIST;
954 
955             if ( xDesktop.is() )
956             {
957                 Reference< XFramesSupplier > xTasksSupplier( xDesktop, UNO_QUERY );
958                 Reference< XFrame > xCurrentFrame = xDesktop->getCurrentFrame();
959                 Reference< XIndexAccess > xList ( xTasksSupplier->getFrames(), UNO_QUERY );
960                 sal_Int32 nFrameCount = xList->getCount();
961                 for( sal_Int32 i=0; i<nFrameCount; ++i )
962                 {
963                     Reference< XFrame > xFrame;
964                     Any aVal = xList->getByIndex(i);
965                     if (!(aVal>>=xFrame) || !xFrame.is() )
966                         continue;
967 
968                     if ( xFrame == xCurrentFrame )
969                         nActiveItemId = nItemId;
970 
971                     Window* pWin = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() );
972                     if ( pWin && pWin->IsVisible() )
973                     {
974                         aNewWindowListVector.push_back( pWin->GetText() );
975                         ++nItemId;
976                     }
977                 }
978             }
979 
980             int nItemCount       = pMenu->GetItemCount();
981 
982             if ( nItemCount > 0 )
983             {
984                 // remove all old window list entries from menu
985                 sal_uInt16 nPos = pMenu->GetItemPos( START_ITEMID_WINDOWLIST );
986                 for ( sal_uInt16 n = nPos; n < pMenu->GetItemCount(); )
987                     pMenu->RemoveItem( n );
988 
989                 if ( pMenu->GetItemType( pMenu->GetItemCount()-1 ) == MENUITEM_SEPARATOR )
990                     pMenu->RemoveItem( pMenu->GetItemCount()-1 );
991             }
992 
993             if ( aNewWindowListVector.size() > 0 )
994             {
995                 // append new window list entries to menu
996                 pMenu->InsertSeparator();
997                 nItemId = START_ITEMID_WINDOWLIST;
998                 for ( sal_uInt32 i = 0; i < aNewWindowListVector.size(); i++ )
999                 {
1000                     pMenu->InsertItem( nItemId, aNewWindowListVector.at( i ), MIB_RADIOCHECK );
1001                     if ( nItemId == nActiveItemId )
1002                         pMenu->CheckItem( nItemId );
1003                     ++nItemId;
1004                 }
1005             }
1006         }
1007         else
1008             pWindowMenu = pSVMenu->GetPopupMenu(SID_MDIWINDOWLIST);
1009 
1010         if ( !pParent && pSVMenu->IsMenuBar() && !pAddonsMenu )
1011         {
1012             // Store Add-Ons parents of our runtime menu items
1013             pAddonsMenu = pSVMenu->GetPopupMenu( SID_ADDONLIST );
1014         }
1015 
1016         // f"ur konstistenten Status sorgen
1017         if ( bControllersUnBound )
1018             BindControllers();
1019 
1020         //InvalidateKeyCodes();
1021         pBindings->GetDispatcher_Impl()->Flush();
1022         for ( sal_uInt16 nPos = 0; nPos < nCount; ++nPos )
1023         {
1024             sal_uInt16 nSlotId = (pItems+nPos)->GetId();
1025             if ( nSlotId && nSlotId > END_ITEMID_WINDOWLIST )
1026                 pBindings->Update(nSlotId);
1027         }
1028 
1029         pBindings->Update( SID_IMAGE_ORIENTATION );
1030 
1031         // HelpText on-demand
1032         if ( !bHelpInitialized )
1033         {
1034             // TODO/CLEANUP: do we need help texts in context menus?
1035             // old way with SlotInfo doesn't work anymore
1036         }
1037 
1038         // bis zum Deactivate die Statusupdates unterdr"ucken
1039         pBindings->ENTERREGISTRATIONS(); ++nLocks; bIsActive = sal_True;
1040 
1041         if ( pAutoDeactivate ) // QAP-Hack
1042             pAutoDeactivate->Start();
1043 
1044         if ( IsHiContrastMode() != bWasHighContrast )
1045         {
1046             // Refresh images as our background color changed and remember it!!
1047             bWasHighContrast = IsHiContrastMode();
1048             if ( bIsAddonPopupMenu )
1049                 UpdateImages( pSVMenu );
1050             else
1051                 UpdateImages();
1052         }
1053 
1054         // erledigt
1055         return sal_True;
1056     }
1057     else
1058     {
1059         // VirtualMenu fuer SubMenu finden und ggf. an VirtualMenu binden
1060         bool bRet = Bind_Impl( pMenu );
1061 #ifdef DBG_UTIL
1062         if ( !bRet)
1063             DBG_WARNING( "W1: Virtual menu konnte nicht erzeugt werden!" );
1064 #endif
1065         return bRet;
1066     }
1067 }
1068 
1069 //--------------------------------------------------------------------
1070 
1071 IMPL_LINK( SfxVirtualMenu, Deactivate, Menu *, pMenu )
1072 {
1073     DBG_MEMTEST();
1074     DBG_OUTF( ("SfxVirtualMenu %lx deactivated %lx, own %lx", this, pMenu, pSVMenu) );
1075     if ( bIsActive && ( 0 == pMenu || pMenu == pSVMenu ) )
1076     {
1077         if ( pAutoDeactivate )
1078             pAutoDeactivate->Stop();
1079 
1080         // Bis auf die Menubar k"onnen alle Controller unbinded werden, wenn
1081         // das Menue deaktiviert ( = zugeklappt ) wird
1082         if ( pParent )
1083             UnbindControllers();
1084         pBindings->LEAVEREGISTRATIONS(); --nLocks; bIsActive = sal_False;
1085     }
1086     return sal_True;
1087 }
1088 //--------------------------------------------------------------------
1089 
1090 // called on activation of the SV-Menu
1091 
1092 IMPL_LINK( SfxVirtualMenu, Select, Menu *, pMenu )
1093 {
1094     sal_uInt16 nSlotId = (sal_uInt16) pMenu->GetCurItemId();
1095     DBG_OUTF( ("SfxVirtualMenu %lx selected %u from %lx", this, nSlotId, pMenu) );
1096 /*
1097     if ( pSVMenu->GetItemCommand( nSlotId ).Len() )
1098     {
1099         SfxMenuCtrlArr_Impl& rCtrlArr = GetAppCtrl_Impl();
1100         for ( sal_uInt16 nPos=0; nPos<rCtrlArr.Count(); nPos++ )
1101         {
1102             SfxMenuControl* pCtrl = rCtrlArr[nPos];
1103             if ( pCtrl->GetId() == nSlotId )
1104             {
1105                 SfxUnoMenuControl *pUnoCtrl = (SfxUnoMenuControl*) pCtrl;
1106                 pUnoCtrl->Select();
1107                 return sal_True;
1108             }
1109         }
1110     }
1111 */
1112     if ( nSlotId >= START_ITEMID_WINDOWLIST && nSlotId <= END_ITEMID_WINDOWLIST )
1113     {
1114         // window list menu item selected
1115         Reference< XFramesSupplier > xDesktop( ::comphelper::getProcessServiceFactory()->createInstance(
1116                                         DEFINE_CONST_OUSTRING( "com.sun.star.frame.Desktop" ) ), UNO_QUERY );
1117         if ( xDesktop.is() )
1118         {
1119             sal_uInt16 nTaskId = START_ITEMID_WINDOWLIST;
1120             Reference< XIndexAccess > xList( xDesktop->getFrames(), UNO_QUERY );
1121             sal_Int32 nFrameCount = xList->getCount();
1122             for ( sal_Int32 i=0; i<nFrameCount; ++i )
1123             {
1124                 Any aItem = xList->getByIndex(i);
1125                 Reference< XFrame > xFrame;
1126                 if (( aItem >>= xFrame ) && xFrame.is() && nTaskId == nSlotId )
1127                 {
1128                     Window* pWin = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() );
1129                     pWin->GrabFocus();
1130                     pWin->ToTop( TOTOP_RESTOREWHENMIN );
1131                     break;
1132                 }
1133 
1134                 nTaskId++;
1135             }
1136         }
1137 
1138         return sal_True;
1139     }
1140     else if ( nSlotId >= START_ITEMID_PICKLIST && nSlotId <= END_ITEMID_PICKLIST )
1141     {
1142         SfxPickList::Get()->ExecuteMenuEntry( nSlotId );
1143         return sal_True;
1144     }
1145 
1146     if ( pMenu->GetItemCommand( nSlotId ).Len() )
1147         pBindings->ExecuteCommand_Impl( pMenu->GetItemCommand( nSlotId ) );
1148     else
1149         pBindings->Execute( nSlotId );
1150 
1151     return sal_True;
1152 }
1153 
1154 //--------------------------------------------------------------------
1155 
1156 // returns the associated StarView-menu
1157 
1158 Menu* SfxVirtualMenu::GetSVMenu() const
1159 {
1160     DBG_MEMTEST();
1161     DBG_CHKTHIS(SfxVirtualMenu, 0);
1162 
1163     return pSVMenu;
1164 }
1165 
1166 //--------------------------------------------------------------------
1167 
1168 // return the position of the specified item
1169 
1170 sal_uInt16 SfxVirtualMenu::GetItemPos( sal_uInt16 nItemId ) const
1171 {
1172     DBG_MEMTEST();
1173     DBG_CHKTHIS(SfxVirtualMenu, 0);
1174 
1175     for ( sal_uInt16 nPos = 0; nPos < nCount; ++nPos )
1176         if ( (pItems+nPos)->GetId() == nItemId )
1177             return nPos;
1178     return MENU_ITEM_NOTFOUND;
1179 }
1180 
1181 //--------------------------------------------------------------------
1182 
1183 // returns the popup-menu assigned to the item or 0 if none
1184 
1185 SfxVirtualMenu* SfxVirtualMenu::GetPopupMenu( sal_uInt16 nItemId ) const
1186 {
1187     DBG_MEMTEST();
1188     DBG_CHKTHIS(SfxVirtualMenu, 0);
1189 
1190     sal_uInt16 nPos = GetItemPos(nItemId);
1191     if ( nPos != MENU_ITEM_NOTFOUND )
1192         return (pItems+nPos)->GetPopupMenu();
1193     return 0;
1194 }
1195 //--------------------------------------------------------------------
1196 
1197 // returns the text of the item as currently shown in the menu
1198 
1199 String SfxVirtualMenu::GetItemText( sal_uInt16 nSlotId ) const
1200 {
1201     DBG_MEMTEST();
1202     DBG_CHKTHIS(SfxVirtualMenu, 0);
1203 
1204     sal_uInt16 nPos = GetItemPos(nSlotId);
1205     if ( nPos != MENU_ITEM_NOTFOUND )
1206         return (pItems+nPos)->GetTitle();
1207     return String();
1208 }
1209 //--------------------------------------------------------------------
1210 
1211 // returns the text of the item as currently shown in the menu
1212 
1213 String SfxVirtualMenu::GetItemHelpText( sal_uInt16 nSlotId ) const
1214 {
1215     DBG_MEMTEST();
1216     DBG_CHKTHIS(SfxVirtualMenu, 0);
1217 
1218     sal_uInt16 nPos = GetItemPos(nSlotId);
1219     if ( nPos != MENU_ITEM_NOTFOUND )
1220         return (pItems+nPos)->GetHelpText();
1221     return String();
1222 }
1223 
1224 //--------------------------------------------------------------------
1225 
1226 // set the checkmark of the specified item
1227 
1228 void SfxVirtualMenu::CheckItem( sal_uInt16 nItemId, sal_Bool bCheck )
1229 {
1230     DBG_MEMTEST();
1231     DBG_CHKTHIS(SfxVirtualMenu, 0);
1232     DBG_ASSERT( this != 0, "");
1233     DBG_ASSERT( pSVMenu != 0, "" );
1234     if (pSVMenu->GetItemPos( nItemId ) != MENU_ITEM_NOTFOUND )
1235         pSVMenu->CheckItem( nItemId, bCheck );
1236 }
1237 //--------------------------------------------------------------------
1238 
1239 // set the enabled-state of the specified item
1240 
1241 void SfxVirtualMenu::EnableItem( sal_uInt16 nItemId, sal_Bool bEnable )
1242 {
1243     DBG_MEMTEST();
1244     DBG_CHKTHIS(SfxVirtualMenu, 0);
1245     DBG_ASSERT( this != 0, "");
1246     DBG_ASSERT( pSVMenu != 0, "" );
1247 
1248     if (pSVMenu->GetItemPos( nItemId ) != MENU_ITEM_NOTFOUND )
1249         pSVMenu->EnableItem( nItemId, bEnable );
1250 }
1251 //--------------------------------------------------------------------
1252 
1253 // set the text of the specified item
1254 
1255 void SfxVirtualMenu::SetItemText( sal_uInt16 nItemId, const String& rText )
1256 {
1257     DBG_MEMTEST();
1258     DBG_CHKTHIS(SfxVirtualMenu, 0);
1259     DBG_ASSERT( this != 0, "");
1260     DBG_ASSERT( pSVMenu != 0, "" );
1261     if (pSVMenu->GetItemPos( nItemId ) != MENU_ITEM_NOTFOUND )
1262         pSVMenu->SetItemText( nItemId, rText );
1263 }
1264 
1265 //--------------------------------------------------------------------
1266 
1267 //
1268 
1269 void SfxVirtualMenu::SetPopupMenu( sal_uInt16 nItemId, PopupMenu *pMenu )
1270 {
1271     DBG_MEMTEST();
1272     DBG_CHKTHIS(SfxVirtualMenu, 0);
1273 
1274     if (pSVMenu->GetItemPos( nItemId ) != MENU_ITEM_NOTFOUND )
1275         GetSVMenu()->SetPopupMenu( nItemId, pMenu );
1276     for ( sal_uInt16 n = 0; n < nCount; ++n )
1277     {
1278         SfxVirtualMenu *pSubMenu = (pItems+n)->GetPopupMenu();
1279         if ( pSubMenu )
1280             pSubMenu->SetPopupMenu( nItemId, pMenu );
1281     }
1282 }
1283 
1284 //--------------------------------------------------------------------
1285 
1286 // Erzwingt die Initialisierung, die sonst nur im Activate kommt
1287 
1288 void SfxVirtualMenu::InitPopup( sal_uInt16 nPos, sal_Bool /*bOLE*/ )
1289 {
1290     DBG_MEMTEST();
1291     DBG_CHKTHIS(SfxVirtualMenu, 0);
1292 
1293     sal_uInt16 nSID = pSVMenu->GetItemId(nPos);
1294     PopupMenu *pMenu = pSVMenu->GetPopupMenu( nSID );
1295 
1296     DBG_ASSERT( pMenu, "Hier gibt es kein Popup!");
1297 
1298     SfxMenuControl &rCtrl = pItems[nPos];
1299     if ( !rCtrl.GetId() )
1300     {
1301         // VirtualMenu f"ur Sub-Menu erzeugen
1302         sal_Bool bRes = bResCtor;
1303         SfxVirtualMenu *pSubMenu =
1304             new SfxVirtualMenu(nSID, this, *pMenu, sal_False, *pBindings, bOLE, bRes);
1305 
1306         DBG_OUTF( ("Neues VirtualMenu %lx erzeugt", pSubMenu) );
1307 
1308         rCtrl.Bind( this, nSID, *pSubMenu,
1309             pSVMenu->GetItemText(nSID), pSVMenu->GetHelpText(nSID),
1310             *pBindings );
1311     }
1312 }
1313 
1314 void SfxVirtualMenu::InitializeHelp()
1315 {
1316     for ( sal_uInt16 nPos = 0; nPos<pSVMenu->GetItemCount(); ++nPos )
1317     {
1318         sal_uInt16 nSlotId = pSVMenu->GetItemId(nPos);
1319         // TODO/CLEANUP: this code does nothing!
1320 //        if ( !bHelpInitialized )
1321 //            pSVMenu->SetHelpText( nId, rSlotPool.GetSlotHelpText_Impl( nId ) );
1322         SfxMenuControl &rCtrl = pItems[nPos];
1323         if ( nSlotId && !rCtrl.GetId() )
1324         {
1325             InitPopup( nPos, sal_True );
1326         }
1327 
1328         SfxVirtualMenu *pSubMenu = rCtrl.GetPopupMenu();
1329         if ( pSubMenu )
1330             pSubMenu->InitializeHelp();
1331     }
1332 
1333     bHelpInitialized = sal_True;
1334 }
1335 
1336 typedef sal_uIntPtr (__LOADONCALLAPI *HelpIdFunc) ( const String& );
1337 
1338 void SfxVirtualMenu::SetHelpIds( ResMgr *pRes )
1339 {
1340     pResMgr = pRes;
1341 }
1342 
1343