bump product version to 4.1.6.2
[LibreOffice.git] / framework / source / classes / menumanager.cxx
blobfea88de034c9339bce42dc1dd889975180627ec9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <classes/menumanager.hxx>
21 #include <framework/menuconfiguration.hxx>
22 #include <framework/bmkmenu.hxx>
23 #include <framework/addonmenu.hxx>
24 #include <framework/imageproducer.hxx>
25 #include <threadhelp/resetableguard.hxx>
26 #include "framework/addonsoptions.hxx"
27 #include <classes/fwkresid.hxx>
28 #include <services.h>
29 #include "classes/resource.hrc"
31 #include <com/sun/star/frame/XDispatchProvider.hpp>
32 #include <com/sun/star/frame/XDispatch.hpp>
33 #include <com/sun/star/util/URLTransformer.hpp>
34 #include <com/sun/star/util/XURLTransformer.hpp>
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/frame/XFramesSupplier.hpp>
37 #include <com/sun/star/frame/Desktop.hpp>
38 #include <com/sun/star/container/XEnumeration.hpp>
39 #include <com/sun/star/util/XStringWidth.hpp>
41 #include <comphelper/processfactory.hxx>
43 #include <comphelper/extract.hxx>
44 #include <svtools/menuoptions.hxx>
45 #include <unotools/historyoptions.hxx>
46 #include <unotools/pathoptions.hxx>
47 #include <unotools/localfilehelper.hxx>
49 #include <toolkit/unohlp.hxx>
50 #include <tools/urlobj.hxx>
52 #include <vcl/svapp.hxx>
53 #include <vcl/window.hxx>
54 #include <osl/mutex.hxx>
55 #include <osl/file.hxx>
56 #include <cppuhelper/implbase1.hxx>
58 using namespace ::cppu;
59 using namespace ::com::sun::star::uno;
60 using namespace ::com::sun::star::util;
61 using namespace ::com::sun::star::beans;
62 using namespace ::com::sun::star::frame;
63 using namespace ::com::sun::star::lang;
64 using namespace ::com::sun::star::container;
66 class StringLength : public ::cppu::WeakImplHelper1< XStringWidth >
68 public:
69 StringLength() {}
70 virtual ~StringLength() {}
72 // XStringWidth
73 sal_Int32 SAL_CALL queryStringWidth( const OUString& aString )
74 throw (RuntimeException)
76 return aString.getLength();
80 namespace framework
83 // special menu ids/command ids for dynamic popup menus
84 #define SID_SFX_START 5000
85 #define SID_NEWDOCDIRECT (SID_SFX_START + 537)
86 #define SID_AUTOPILOTMENU (SID_SFX_START + 1381)
87 #define SID_ADDONLIST (SID_SFX_START + 1677)
89 #define SFX_REFERER_USER "private:user"
91 #define aSlotNewDocDirect "slot:5537"
92 #define aSlotAutoPilot "slot:6381"
94 #define aSpecialFileMenu "file"
95 #define aSpecialWindowMenu "window"
96 #define aSlotSpecialFileMenu "slot:5510"
97 #define aSlotSpecialWindowMenu "slot:5610"
98 #define aSlotSpecialToolsMenu "slot:6677"
100 // special uno commands for picklist and window list
101 #define aSpecialFileCommand "PickList"
102 #define aSpecialWindowCommand "WindowList"
104 const char UNO_COMMAND[] = ".uno:";
106 MenuManager::MenuManager(
107 const Reference< XComponentContext >& rxContext,
108 Reference< XFrame >& rFrame, Menu* pMenu, sal_Bool bDelete, sal_Bool bDeleteChildren )
110 ThreadHelpBase( &Application::GetSolarMutex() ),
111 m_xContext(rxContext)
113 m_bActive = sal_False;
114 m_bDeleteMenu = bDelete;
115 m_bDeleteChildren = bDeleteChildren;
116 m_pVCLMenu = pMenu;
117 m_xFrame = rFrame;
118 m_bInitialized = sal_False;
119 m_bIsBookmarkMenu = sal_False;
120 acquire();
121 const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
122 m_bShowMenuImages = rSettings.GetUseImagesInMenus();
124 sal_Int32 nAddonsURLPrefixLength = ADDONSPOPUPMENU_URL_PREFIX.getLength();
127 sal_uInt16 nItemCount = pMenu->GetItemCount();
128 m_aMenuItemHandlerVector.reserve(nItemCount);
129 OUString aItemCommand;
130 for ( sal_uInt16 i = 0; i < nItemCount; i++ )
132 sal_uInt16 nItemId = FillItemCommand(aItemCommand,pMenu, i );
133 bool bShowMenuImages( m_bShowMenuImages );
135 // overwrite the show icons on menu option?
136 if (!bShowMenuImages)
138 MenuItemBits nBits = pMenu->GetItemBits( nItemId );
139 bShowMenuImages = ( ( nBits & MIB_ICON ) == MIB_ICON );
142 PopupMenu* pPopupMenu = pMenu->GetPopupMenu( nItemId );
143 if ( pPopupMenu )
145 AddMenu(pPopupMenu,aItemCommand,nItemId,bDeleteChildren,bDeleteChildren);
146 if (! (( aItemCommand.getLength() > nAddonsURLPrefixLength ) &&
147 ( aItemCommand.indexOf( ADDONSPOPUPMENU_URL_PREFIX ) == 0 )) )
150 // Create addon popup menu if there exist elements and this is the tools popup menu
151 if ( ( nItemId == SID_ADDONLIST || aItemCommand == aSlotSpecialToolsMenu )
152 && AddonMenuManager::HasAddonMenuElements() )
154 AddonMenu* pSubMenu = AddonMenuManager::CreateAddonMenu( rFrame );
155 if ( pSubMenu && ( pSubMenu->GetItemCount() > 0 ))
157 sal_uInt16 nCount = 0;
158 if ( pPopupMenu->GetItemType( nCount-1 ) != MENUITEM_SEPARATOR )
159 pPopupMenu->InsertSeparator();
161 // Use resource to load popup menu title
162 String aAddonsStrRes = String( FwkResId( STR_MENU_ADDONS ));
163 pPopupMenu->InsertItem( ITEMID_ADDONLIST, aAddonsStrRes );
164 pPopupMenu->SetPopupMenu( ITEMID_ADDONLIST, pSubMenu );
166 // Set item command for popup menu to enable it for GetImageFromURL
167 const static OUString aSlotString( "slot:" );
168 aItemCommand = aSlotString;
169 aItemCommand += OUString::valueOf( (sal_Int32)ITEMID_ADDONLIST );
170 pPopupMenu->SetItemCommand( ITEMID_ADDONLIST, aItemCommand );
172 AddMenu(pSubMenu,OUString(),nItemId,sal_True,sal_False);
173 // Set image for the addon popup menu item
174 if ( bShowMenuImages && !pPopupMenu->GetItemImage( ITEMID_ADDONLIST ))
176 Image aImage = GetImageFromURL( rFrame, aItemCommand, false );
177 if ( !!aImage )
178 pPopupMenu->SetItemImage( ITEMID_ADDONLIST, aImage );
181 else
182 delete pSubMenu;
186 else
188 if ( nItemId == SID_NEWDOCDIRECT || aItemCommand == aSlotNewDocDirect )
190 MenuConfiguration aMenuCfg( m_xContext );
191 BmkMenu* pSubMenu = (BmkMenu*)aMenuCfg.CreateBookmarkMenu( rFrame, BOOKMARK_NEWMENU );
192 pMenu->SetPopupMenu( nItemId, pSubMenu );
194 AddMenu(pSubMenu,OUString(),nItemId,sal_True,sal_False);
195 if ( bShowMenuImages && !pMenu->GetItemImage( nItemId ))
197 Image aImage = GetImageFromURL( rFrame, aItemCommand, false );
198 if ( !!aImage )
199 pMenu->SetItemImage( nItemId, aImage );
202 else if ( nItemId == SID_AUTOPILOTMENU || aItemCommand == aSlotAutoPilot )
204 MenuConfiguration aMenuCfg( m_xContext );
205 BmkMenu* pSubMenu = (BmkMenu*)aMenuCfg.CreateBookmarkMenu( rFrame, BOOKMARK_WIZARDMENU );
206 pMenu->SetPopupMenu( nItemId, pSubMenu );
208 AddMenu(pSubMenu,OUString(),nItemId,sal_True,sal_False);
211 if ( bShowMenuImages && !pMenu->GetItemImage( nItemId ))
213 Image aImage = GetImageFromURL( rFrame, aItemCommand, false );
214 if ( !!aImage )
215 pMenu->SetItemImage( nItemId, aImage );
218 else if ( pMenu->GetItemType( i ) != MENUITEM_SEPARATOR )
220 if ( bShowMenuImages )
222 if ( AddonMenuManager::IsAddonMenuId( nItemId ))
224 // Add-Ons uses a images from different places
225 Image aImage;
226 OUString aImageId;
228 MenuConfiguration::Attributes* pMenuAttributes =
229 (MenuConfiguration::Attributes*)pMenu->GetUserValue( nItemId );
231 if ( pMenuAttributes && !pMenuAttributes->aImageId.isEmpty() )
233 // Retrieve image id from menu attributes
234 aImage = GetImageFromURL( rFrame, aImageId, false );
237 if ( !aImage )
239 aImage = GetImageFromURL( rFrame, aItemCommand, false );
240 if ( !aImage )
241 aImage = AddonsOptions().GetImageFromURL( aItemCommand, false );
244 if ( !!aImage )
245 pMenu->SetItemImage( nItemId, aImage );
247 else if ( !pMenu->GetItemImage( nItemId ))
249 Image aImage = GetImageFromURL( rFrame, aItemCommand, false );
250 if ( !!aImage )
251 pMenu->SetItemImage( nItemId, aImage );
255 Reference< XDispatch > aXDispatchRef;
256 m_aMenuItemHandlerVector.push_back( new MenuItemHandler( nItemId, NULL, aXDispatchRef ));
262 // retrieve label information for all menu items without item text
264 SetHdl();
268 void MenuManager::SetHdl()
270 m_pVCLMenu->SetHighlightHdl( LINK( this, MenuManager, Highlight ));
271 m_pVCLMenu->SetActivateHdl( LINK( this, MenuManager, Activate ));
272 m_pVCLMenu->SetDeactivateHdl( LINK( this, MenuManager, Deactivate ));
273 m_pVCLMenu->SetSelectHdl( LINK( this, MenuManager, Select ));
275 if ( m_xContext.is() )
276 m_xURLTransformer.set( URLTransformer::create( m_xContext ) );
279 MenuManager::~MenuManager()
281 std::vector< MenuItemHandler* >::iterator p;
282 for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); ++p )
284 MenuItemHandler* pItemHandler = *p;
285 pItemHandler->xMenuItemDispatch.clear();
286 if ( pItemHandler->pSubMenuManager )
287 (static_cast< XInterface* >((OWeakObject*)pItemHandler->pSubMenuManager))->release();
288 delete pItemHandler;
291 if ( m_bDeleteMenu )
292 delete m_pVCLMenu;
296 MenuManager::MenuItemHandler* MenuManager::GetMenuItemHandler( sal_uInt16 nItemId )
298 ResetableGuard aGuard( m_aLock );
300 std::vector< MenuItemHandler* >::iterator p;
301 for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); ++p )
303 MenuItemHandler* pItemHandler = *p;
304 if ( pItemHandler->nItemId == nItemId )
305 return pItemHandler;
308 return 0;
312 void SAL_CALL MenuManager::statusChanged( const FeatureStateEvent& Event )
313 throw ( RuntimeException )
315 OUString aFeatureURL = Event.FeatureURL.Complete;
316 MenuItemHandler* pStatusChangedMenu = NULL;
319 ResetableGuard aGuard( m_aLock );
321 std::vector< MenuItemHandler* >::iterator p;
322 for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); ++p )
324 MenuItemHandler* pMenuItemHandler = *p;
325 if ( pMenuItemHandler->aMenuItemURL == aFeatureURL )
327 pStatusChangedMenu = pMenuItemHandler;
328 break;
333 if ( pStatusChangedMenu )
335 SolarMutexGuard aSolarGuard;
337 ResetableGuard aGuard( m_aLock );
339 sal_Bool bSetCheckmark = sal_False;
340 sal_Bool bCheckmark = sal_False;
341 sal_Bool bMenuItemEnabled = m_pVCLMenu->IsItemEnabled( pStatusChangedMenu->nItemId );
343 if ( Event.IsEnabled != bMenuItemEnabled )
344 m_pVCLMenu->EnableItem( pStatusChangedMenu->nItemId, Event.IsEnabled );
346 if ( Event.State >>= bCheckmark )
347 bSetCheckmark = sal_True;
349 if ( bSetCheckmark )
350 m_pVCLMenu->CheckItem( pStatusChangedMenu->nItemId, bCheckmark );
353 if ( Event.Requery )
355 URL aTargetURL;
356 aTargetURL.Complete = pStatusChangedMenu->aMenuItemURL;
358 m_xURLTransformer->parseStrict( aTargetURL );
360 Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
361 Reference< XDispatch > xMenuItemDispatch = xDispatchProvider->queryDispatch(
362 aTargetURL, OUString(), 0 );
364 if ( xMenuItemDispatch.is() )
366 pStatusChangedMenu->xMenuItemDispatch = xMenuItemDispatch;
367 pStatusChangedMenu->aMenuItemURL = aTargetURL.Complete;
368 xMenuItemDispatch->addStatusListener( (static_cast< XStatusListener* >(this)), aTargetURL );
375 void MenuManager::RemoveListener()
377 ResetableGuard aGuard( m_aLock );
378 ClearMenuDispatch();
381 void MenuManager::ClearMenuDispatch(const EventObject& Source,bool _bRemoveOnly)
383 // disposing called from parent dispatcher
384 // remove all listener to prepare shutdown
386 std::vector< MenuItemHandler* >::iterator p;
387 for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); ++p )
389 MenuItemHandler* pItemHandler = *p;
390 if ( pItemHandler->xMenuItemDispatch.is() )
392 URL aTargetURL;
393 aTargetURL.Complete = pItemHandler->aMenuItemURL;
394 m_xURLTransformer->parseStrict( aTargetURL );
396 pItemHandler->xMenuItemDispatch->removeStatusListener(
397 (static_cast< XStatusListener* >(this)), aTargetURL );
400 pItemHandler->xMenuItemDispatch.clear();
401 if ( pItemHandler->pSubMenuManager )
403 if ( _bRemoveOnly )
404 pItemHandler->pSubMenuManager->RemoveListener();
405 else
406 pItemHandler->pSubMenuManager->disposing( Source );
412 void SAL_CALL MenuManager::disposing( const EventObject& Source ) throw ( RuntimeException )
414 if ( Source.Source == m_xFrame )
416 ResetableGuard aGuard( m_aLock );
417 ClearMenuDispatch(Source,false);
419 else
421 // disposing called from menu item dispatcher, remove listener
422 MenuItemHandler* pMenuItemDisposing = NULL;
425 ResetableGuard aGuard( m_aLock );
427 std::vector< MenuItemHandler* >::iterator p;
428 for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); ++p )
430 MenuItemHandler* pMenuItemHandler = *p;
431 if ( pMenuItemHandler->xMenuItemDispatch == Source.Source )
433 pMenuItemDisposing = pMenuItemHandler;
434 break;
438 if ( pMenuItemDisposing )
440 URL aTargetURL;
441 aTargetURL.Complete = pMenuItemDisposing->aMenuItemURL;
443 m_xURLTransformer->parseStrict( aTargetURL );
445 pMenuItemDisposing->xMenuItemDispatch->removeStatusListener((static_cast< XStatusListener* >(this)), aTargetURL );
446 pMenuItemDisposing->xMenuItemDispatch.clear();
453 void MenuManager::UpdateSpecialFileMenu( Menu* pMenu )
455 // update picklist
456 Sequence< Sequence< PropertyValue > > aHistoryList = SvtHistoryOptions().GetList( ePICKLIST );
457 ::std::vector< MenuItemHandler* > aNewPickVector;
458 Reference< XStringWidth > xStringLength( new StringLength );
460 sal_uInt16 nPickItemId = START_ITEMID_PICKLIST;
461 int nPickListMenuItems = ( aHistoryList.getLength() > 99 ) ? 99 : aHistoryList.getLength();
463 aNewPickVector.reserve(nPickListMenuItems);
464 for ( int i = 0; i < nPickListMenuItems; i++ )
466 Sequence< PropertyValue > aPickListEntry = aHistoryList[i];
468 Reference< XDispatch > aXDispatchRef;
469 MenuItemHandler* pNewMenuItemHandler = new MenuItemHandler(
470 nPickItemId++,
471 NULL,
472 aXDispatchRef );
474 for ( int j = 0; j < aPickListEntry.getLength(); j++ )
476 Any a = aPickListEntry[j].Value;
478 if ( aPickListEntry[j].Name == HISTORY_PROPERTYNAME_URL )
479 a >>= pNewMenuItemHandler->aMenuItemURL;
480 else if ( aPickListEntry[j].Name == HISTORY_PROPERTYNAME_FILTER )
481 a >>= pNewMenuItemHandler->aFilter;
482 else if ( aPickListEntry[j].Name == HISTORY_PROPERTYNAME_TITLE )
483 a >>= pNewMenuItemHandler->aTitle;
484 else if ( aPickListEntry[j].Name == HISTORY_PROPERTYNAME_PASSWORD )
485 a >>= pNewMenuItemHandler->aPassword;
488 aNewPickVector.push_back( pNewMenuItemHandler );
491 if ( !aNewPickVector.empty() )
493 URL aTargetURL;
494 Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
496 Reference< XDispatch > xMenuItemDispatch;
498 static const OUString s_sDefault("_default");
499 // query for dispatcher
500 std::vector< MenuItemHandler* >::iterator p;
501 for ( p = aNewPickVector.begin(); p != aNewPickVector.end(); ++p )
503 MenuItemHandler* pMenuItemHandler = *p;
505 aTargetURL.Complete = pMenuItemHandler->aMenuItemURL;
506 m_xURLTransformer->parseStrict( aTargetURL );
508 if ( !xMenuItemDispatch.is() )
510 // attention: this code assume that "_blank" can only be consumed by desktop service
511 xMenuItemDispatch = xDispatchProvider->queryDispatch( aTargetURL, s_sDefault, 0 );
514 if ( xMenuItemDispatch.is() )
516 pMenuItemHandler->xMenuItemDispatch = xMenuItemDispatch;
517 pMenuItemHandler->aMenuItemURL = aTargetURL.Complete;
522 ResetableGuard aGuard( m_aLock );
524 int nRemoveItemCount = 0;
525 int nItemCount = pMenu->GetItemCount();
527 if ( nItemCount > 0 )
529 // remove all old picklist entries from menu
530 sal_uInt16 nPos = pMenu->GetItemPos( START_ITEMID_PICKLIST );
531 for ( sal_uInt16 n = nPos; n < pMenu->GetItemCount(); )
533 pMenu->RemoveItem( n );
534 ++nRemoveItemCount;
537 if ( pMenu->GetItemType( pMenu->GetItemCount()-1 ) == MENUITEM_SEPARATOR )
538 pMenu->RemoveItem( pMenu->GetItemCount()-1 );
540 // remove all old picklist entries from menu handler
541 if ( nRemoveItemCount > 0 )
543 for( sal_uInt32 nIndex = m_aMenuItemHandlerVector.size() - nRemoveItemCount;
544 nIndex < m_aMenuItemHandlerVector.size(); )
546 delete m_aMenuItemHandlerVector.at( nIndex );
547 m_aMenuItemHandlerVector.erase( m_aMenuItemHandlerVector.begin() + nIndex );
552 // append new picklist menu entries
553 aNewPickVector.reserve(aNewPickVector.size());
554 pMenu->InsertSeparator();
555 const sal_uInt32 nCount = aNewPickVector.size();
556 for ( sal_uInt32 i = 0; i < nCount; i++ )
558 char menuShortCut[5] = "~n: ";
560 OUString aMenuShortCut;
561 if ( i <= 9 )
563 if ( i == 9 )
564 aMenuShortCut = OUString( "1~0: " );
565 else
567 menuShortCut[1] = (char)( '1' + i );
568 aMenuShortCut = OUString::createFromAscii( menuShortCut );
571 else
573 aMenuShortCut = OUString::valueOf((sal_Int32)( i + 1 ));
574 aMenuShortCut += ": ";
577 // Abbreviate URL
578 OUString aURLString( aNewPickVector.at( i )->aMenuItemURL );
579 OUString aTipHelpText;
580 OUString aMenuTitle;
581 INetURLObject aURL( aURLString );
583 if ( aURL.GetProtocol() == INET_PROT_FILE )
585 // Do handle file URL differently => convert it to a system
586 // path and abbreviate it with a special function:
587 String aFileSystemPath( aURL.getFSysPath( INetURLObject::FSYS_DETECT ) );
589 OUString aSystemPath( aFileSystemPath );
590 OUString aCompactedSystemPath;
592 aTipHelpText = aSystemPath;
593 oslFileError nError = osl_abbreviateSystemPath( aSystemPath.pData, &aCompactedSystemPath.pData, 46, NULL );
594 if ( !nError )
595 aMenuTitle = String( aCompactedSystemPath );
596 else
597 aMenuTitle = aSystemPath;
599 else
601 // Use INetURLObject to abbreviate all other URLs
602 String aShortURL;
603 aShortURL = aURL.getAbbreviated( xStringLength, 46, INetURLObject::DECODE_UNAMBIGUOUS );
604 aMenuTitle += aShortURL;
605 aTipHelpText = aURLString;
608 OUString aTitle( aMenuShortCut + aMenuTitle );
610 MenuItemHandler* pMenuItemHandler = aNewPickVector.at( i );
611 pMenu->InsertItem( pMenuItemHandler->nItemId, aTitle );
612 pMenu->SetTipHelpText( pMenuItemHandler->nItemId, aTipHelpText );
613 m_aMenuItemHandlerVector.push_back( pMenuItemHandler );
619 void MenuManager::UpdateSpecialWindowMenu( Menu* pMenu,const Reference< XComponentContext >& xContext,framework::IMutex& _rMutex )
621 // update window list
622 ::std::vector< OUString > aNewWindowListVector;
624 Reference< XDesktop2 > xDesktop = Desktop::create( xContext );
626 sal_uInt16 nActiveItemId = 0;
627 sal_uInt16 nItemId = START_ITEMID_WINDOWLIST;
629 Reference< XFrame > xCurrentFrame = xDesktop->getCurrentFrame();
630 Reference< XIndexAccess > xList( xDesktop->getFrames(), UNO_QUERY );
631 sal_Int32 nFrameCount = xList->getCount();
632 aNewWindowListVector.reserve(nFrameCount);
633 for (sal_Int32 i=0; i<nFrameCount; ++i )
635 Reference< XFrame > xFrame;
636 xList->getByIndex(i) >>= xFrame;
638 if (xFrame.is())
640 if ( xFrame == xCurrentFrame )
641 nActiveItemId = nItemId;
643 Window* pWin = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() );
644 if ( pWin && pWin->IsVisible() )
646 aNewWindowListVector.push_back( pWin->GetText() );
647 ++nItemId;
653 ResetableGuard aGuard( _rMutex );
655 int nItemCount = pMenu->GetItemCount();
657 if ( nItemCount > 0 )
659 // remove all old window list entries from menu
660 sal_uInt16 nPos = pMenu->GetItemPos( START_ITEMID_WINDOWLIST );
661 for ( sal_uInt16 n = nPos; n < pMenu->GetItemCount(); )
662 pMenu->RemoveItem( n );
664 if ( pMenu->GetItemType( pMenu->GetItemCount()-1 ) == MENUITEM_SEPARATOR )
665 pMenu->RemoveItem( pMenu->GetItemCount()-1 );
668 if ( !aNewWindowListVector.empty() )
670 // append new window list entries to menu
671 pMenu->InsertSeparator();
672 nItemId = START_ITEMID_WINDOWLIST;
673 const sal_uInt32 nCount = aNewWindowListVector.size();
674 for ( sal_uInt32 i = 0; i < nCount; i++ )
676 pMenu->InsertItem( nItemId, aNewWindowListVector.at( i ), MIB_RADIOCHECK );
677 if ( nItemId == nActiveItemId )
678 pMenu->CheckItem( nItemId );
679 ++nItemId;
686 void MenuManager::CreatePicklistArguments( Sequence< PropertyValue >& aArgsList, const MenuItemHandler* pMenuItemHandler )
688 int NUM_OF_PICKLIST_ARGS = 3;
690 Any a;
691 aArgsList.realloc( NUM_OF_PICKLIST_ARGS );
693 aArgsList[0].Name = OUString( "FileName" );
694 a <<= pMenuItemHandler->aMenuItemURL;
695 aArgsList[0].Value = a;
697 aArgsList[1].Name = OUString( "Referer" );
698 a <<= OUString( SFX_REFERER_USER );
699 aArgsList[1].Value = a;
701 OUString aFilter( pMenuItemHandler->aFilter );
703 sal_Int32 nPos = aFilter.indexOf( '|' );
704 if ( nPos >= 0 )
706 OUString aFilterOptions;
708 if ( nPos < ( aFilter.getLength() - 1 ) )
709 aFilterOptions = aFilter.copy( nPos+1 );
711 aArgsList[2].Name = OUString( "FilterOptions" );
712 a <<= aFilterOptions;
713 aArgsList[2].Value = a;
715 aFilter = aFilter.copy( 0, nPos-1 );
716 aArgsList.realloc( ++NUM_OF_PICKLIST_ARGS );
719 aArgsList[NUM_OF_PICKLIST_ARGS-1].Name = OUString( "FilterName" );
720 a <<= aFilter;
721 aArgsList[NUM_OF_PICKLIST_ARGS-1].Value = a;
725 //_________________________________________________________________________________________________________________
726 // vcl handler
727 //_________________________________________________________________________________________________________________
729 IMPL_LINK( MenuManager, Activate, Menu *, pMenu )
731 if ( pMenu == m_pVCLMenu )
733 // set/unset hiding disabled menu entries
734 sal_Bool bDontHide = SvtMenuOptions().IsEntryHidingEnabled();
735 const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
736 sal_Bool bShowMenuImages = rSettings.GetUseImagesInMenus();
738 sal_uInt16 nFlag = pMenu->GetMenuFlags();
739 if ( bDontHide )
740 nFlag &= ~MENU_FLAG_HIDEDISABLEDENTRIES;
741 else
742 nFlag |= MENU_FLAG_HIDEDISABLEDENTRIES;
743 pMenu->SetMenuFlags( nFlag );
745 if ( m_bActive )
746 return 0;
748 m_bActive = sal_True;
750 OUString aCommand( m_aMenuItemCommand );
751 if (m_aMenuItemCommand.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM(UNO_COMMAND)))
753 // Remove protocol part from command so we can use an easier comparision method
754 aCommand = aCommand.copy(RTL_CONSTASCII_LENGTH(UNO_COMMAND));
757 if ( m_aMenuItemCommand == aSpecialFileMenu || m_aMenuItemCommand == aSlotSpecialFileMenu || aCommand == aSpecialFileCommand )
758 UpdateSpecialFileMenu( pMenu );
759 else if ( m_aMenuItemCommand == aSpecialWindowMenu || m_aMenuItemCommand == aSlotSpecialWindowMenu || aCommand == aSpecialWindowCommand )
760 UpdateSpecialWindowMenu( pMenu, m_xContext, m_aLock );
762 // Check if some modes have changed so we have to update our menu images
763 if ( bShowMenuImages != m_bShowMenuImages )
765 // The mode changed so we have to replace all images
766 m_bShowMenuImages = bShowMenuImages;
767 FillMenuImages( m_xFrame, pMenu, bShowMenuImages );
770 if ( m_bInitialized )
771 return 0;
772 else
774 URL aTargetURL;
776 ResetableGuard aGuard( m_aLock );
778 Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
779 if ( xDispatchProvider.is() )
781 std::vector< MenuItemHandler* >::iterator p;
782 for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); ++p )
784 MenuItemHandler* pMenuItemHandler = *p;
785 if ( pMenuItemHandler &&
786 pMenuItemHandler->pSubMenuManager == 0 &&
787 !pMenuItemHandler->xMenuItemDispatch.is() )
789 // There is no dispatch mechanism for the special window list menu items,
790 // because they are handled directly through XFrame->activate!!!
791 if ( pMenuItemHandler->nItemId < START_ITEMID_WINDOWLIST ||
792 pMenuItemHandler->nItemId > END_ITEMID_WINDOWLIST )
794 OUString aItemCommand = pMenu->GetItemCommand( pMenuItemHandler->nItemId );
795 if ( aItemCommand.isEmpty() )
797 const static OUString aSlotString( "slot:" );
798 aItemCommand = aSlotString;
799 aItemCommand += OUString::valueOf( (sal_Int32)pMenuItemHandler->nItemId );
800 pMenu->SetItemCommand( pMenuItemHandler->nItemId, aItemCommand );
803 aTargetURL.Complete = aItemCommand;
805 m_xURLTransformer->parseStrict( aTargetURL );
807 Reference< XDispatch > xMenuItemDispatch;
808 if ( m_bIsBookmarkMenu )
809 xMenuItemDispatch = xDispatchProvider->queryDispatch( aTargetURL, pMenuItemHandler->aTargetFrame, 0 );
810 else
811 xMenuItemDispatch = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
813 if ( xMenuItemDispatch.is() )
815 pMenuItemHandler->xMenuItemDispatch = xMenuItemDispatch;
816 pMenuItemHandler->aMenuItemURL = aTargetURL.Complete;
817 xMenuItemDispatch->addStatusListener( (static_cast< XStatusListener* >(this)), aTargetURL );
819 else
820 pMenu->EnableItem( pMenuItemHandler->nItemId, sal_False );
828 return 1;
832 IMPL_LINK( MenuManager, Deactivate, Menu *, pMenu )
834 if ( pMenu == m_pVCLMenu )
835 m_bActive = sal_False;
837 return 1;
841 IMPL_LINK( MenuManager, Select, Menu *, pMenu )
843 URL aTargetURL;
844 Sequence<PropertyValue> aArgs;
845 Reference< XDispatch > xDispatch;
848 ResetableGuard aGuard( m_aLock );
850 sal_uInt16 nCurItemId = pMenu->GetCurItemId();
851 if ( pMenu == m_pVCLMenu &&
852 pMenu->GetItemType( nCurItemId ) != MENUITEM_SEPARATOR )
854 if ( nCurItemId >= START_ITEMID_WINDOWLIST &&
855 nCurItemId <= END_ITEMID_WINDOWLIST )
857 // window list menu item selected
859 Reference< XDesktop2 > xDesktop = Desktop::create( m_xContext );
861 sal_uInt16 nTaskId = START_ITEMID_WINDOWLIST;
862 Reference< XIndexAccess > xList( xDesktop->getFrames(), UNO_QUERY );
863 sal_Int32 nCount = xList->getCount();
864 for ( sal_Int32 i=0; i<nCount; ++i )
866 Reference< XFrame > xFrame;
867 xList->getByIndex(i) >>= xFrame;
869 if ( xFrame.is() && nTaskId == nCurItemId )
871 Window* pWin = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() );
872 pWin->GrabFocus();
873 pWin->ToTop( TOTOP_RESTOREWHENMIN );
874 break;
877 nTaskId++;
880 else
882 MenuItemHandler* pMenuItemHandler = GetMenuItemHandler( nCurItemId );
883 if ( pMenuItemHandler && pMenuItemHandler->xMenuItemDispatch.is() )
885 aTargetURL.Complete = pMenuItemHandler->aMenuItemURL;
886 m_xURLTransformer->parseStrict( aTargetURL );
888 if ( nCurItemId >= START_ITEMID_PICKLIST &&
889 nCurItemId < START_ITEMID_WINDOWLIST )
891 // picklist menu item selected
892 CreatePicklistArguments( aArgs, pMenuItemHandler );
894 else if ( m_bIsBookmarkMenu )
896 // bookmark menu item selected
897 aArgs.realloc( 1 );
898 aArgs[0].Name = OUString( "Referer" );
899 aArgs[0].Value <<= OUString( SFX_REFERER_USER );
902 xDispatch = pMenuItemHandler->xMenuItemDispatch;
908 if ( xDispatch.is() )
909 xDispatch->dispatch( aTargetURL, aArgs );
911 return 1;
915 IMPL_LINK_NOARG(MenuManager, Highlight)
917 return 0;
920 const Reference< XComponentContext >& MenuManager::getContext()
922 return m_xContext;
925 void MenuManager::AddMenu(PopupMenu* _pPopupMenu,const OUString& _sItemCommand,sal_uInt16 _nItemId,sal_Bool _bDelete,sal_Bool _bDeleteChildren)
927 MenuManager* pSubMenuManager = new MenuManager( m_xContext, m_xFrame, _pPopupMenu, _bDelete, _bDeleteChildren );
929 // store menu item command as we later have to know which menu is active (see Activate handler)
930 pSubMenuManager->m_aMenuItemCommand = _sItemCommand;
932 Reference< XDispatch > aXDispatchRef;
933 MenuItemHandler* pMenuItemHandler = new MenuItemHandler(
934 _nItemId,
935 pSubMenuManager,
936 aXDispatchRef );
937 m_aMenuItemHandlerVector.push_back( pMenuItemHandler );
940 sal_uInt16 MenuManager::FillItemCommand(OUString& _rItemCommand, Menu* _pMenu,sal_uInt16 _nIndex) const
942 sal_uInt16 nItemId = _pMenu->GetItemId( _nIndex );
944 _rItemCommand = _pMenu->GetItemCommand( nItemId );
945 if ( _rItemCommand.isEmpty() )
947 const static OUString aSlotString( "slot:" );
948 _rItemCommand = aSlotString;
949 _rItemCommand += OUString::valueOf( (sal_Int32)nItemId );
950 _pMenu->SetItemCommand( nItemId, _rItemCommand );
952 return nItemId;
954 void MenuManager::FillMenuImages(Reference< XFrame >& _xFrame, Menu* _pMenu,sal_Bool bShowMenuImages)
956 AddonsOptions aAddonOptions;
958 for ( sal_uInt16 nPos = 0; nPos < _pMenu->GetItemCount(); nPos++ )
960 sal_uInt16 nId = _pMenu->GetItemId( nPos );
961 if ( _pMenu->GetItemType( nPos ) != MENUITEM_SEPARATOR )
963 bool bTmpShowMenuImages( bShowMenuImages );
964 // overwrite the show icons on menu option?
965 if (!bTmpShowMenuImages)
967 MenuItemBits nBits = _pMenu->GetItemBits( nId );
968 bTmpShowMenuImages = ( ( nBits & MIB_ICON ) == MIB_ICON );
971 if ( bTmpShowMenuImages )
973 sal_Bool bImageSet = sal_False;
974 OUString aImageId;
976 ::framework::MenuConfiguration::Attributes* pMenuAttributes =
977 (::framework::MenuConfiguration::Attributes*)_pMenu->GetUserValue( nId );
979 if ( pMenuAttributes )
980 aImageId = pMenuAttributes->aImageId; // Retrieve image id from menu attributes
982 if ( !aImageId.isEmpty() )
984 Image aImage = GetImageFromURL( _xFrame, aImageId, false );
985 if ( !!aImage )
987 bImageSet = sal_True;
988 _pMenu->SetItemImage( nId, aImage );
992 if ( !bImageSet )
994 OUString aMenuItemCommand = _pMenu->GetItemCommand( nId );
995 Image aImage = GetImageFromURL( _xFrame, aMenuItemCommand, false );
996 if ( !aImage )
997 aImage = aAddonOptions.GetImageFromURL( aMenuItemCommand, false );
999 _pMenu->SetItemImage( nId, aImage );
1002 else
1003 _pMenu->SetItemImage( nId, Image() );
1009 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */