fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / framework / source / classes / menumanager.cxx
blob7cd0e7dd6c06345d1d59e9afda4d421210a395a3
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 <framework/addonsoptions.hxx>
26 #include <classes/fwkresid.hxx>
27 #include <services.h>
28 #include "classes/resource.hrc"
30 #include <com/sun/star/frame/XDispatchProvider.hpp>
31 #include <com/sun/star/frame/XDispatch.hpp>
32 #include <com/sun/star/util/URLTransformer.hpp>
33 #include <com/sun/star/util/XURLTransformer.hpp>
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/frame/XFramesSupplier.hpp>
36 #include <com/sun/star/frame/Desktop.hpp>
37 #include <com/sun/star/container/XEnumeration.hpp>
38 #include <com/sun/star/util/XStringWidth.hpp>
40 #include <comphelper/processfactory.hxx>
42 #include <comphelper/extract.hxx>
43 #include <svtools/menuoptions.hxx>
44 #include <unotools/historyoptions.hxx>
45 #include <unotools/pathoptions.hxx>
46 #include <unotools/localfilehelper.hxx>
48 #include <toolkit/helper/vclunohelper.hxx>
49 #include <tools/urlobj.hxx>
51 #include <vcl/svapp.hxx>
52 #include <vcl/window.hxx>
53 #include <vcl/settings.hxx>
55 #include <osl/mutex.hxx>
56 #include <osl/file.hxx>
57 #include <cppuhelper/implbase1.hxx>
59 using namespace ::cppu;
60 using namespace ::com::sun::star::uno;
61 using namespace ::com::sun::star::util;
62 using namespace ::com::sun::star::beans;
63 using namespace ::com::sun::star::frame;
64 using namespace ::com::sun::star::lang;
65 using namespace ::com::sun::star::container;
67 class StringLength : public ::cppu::WeakImplHelper1< XStringWidth >
69 public:
70 StringLength() {}
71 virtual ~StringLength() {}
73 // XStringWidth
74 sal_Int32 SAL_CALL queryStringWidth( const OUString& aString )
75 throw (RuntimeException, std::exception) SAL_OVERRIDE
77 return aString.getLength();
81 namespace framework
84 // special menu ids/command ids for dynamic popup menus
85 #define SID_SFX_START 5000
86 #define SID_NEWDOCDIRECT (SID_SFX_START + 537)
87 #define SID_AUTOPILOTMENU (SID_SFX_START + 1381)
88 #define SID_ADDONLIST (SID_SFX_START + 1677)
90 #define aSlotNewDocDirect "slot:5537"
91 #define aSlotAutoPilot "slot:6381"
93 #define aSpecialFileMenu "file"
94 #define aSpecialWindowMenu "window"
95 #define aSlotSpecialFileMenu "slot:5510"
96 #define aSlotSpecialWindowMenu "slot:5610"
97 #define aSlotSpecialToolsMenu "slot:6677"
99 // special uno commands for picklist and window list
100 #define aSpecialFileCommand "PickList"
101 #define aSpecialWindowCommand "WindowList"
103 const char UNO_COMMAND[] = ".uno:";
105 MenuManager::MenuManager(
106 const Reference< XComponentContext >& rxContext,
107 Reference< XFrame >& rFrame, Menu* pMenu, bool bDelete, bool bDeleteChildren )
109 m_xContext(rxContext)
111 m_bActive = false;
112 m_bDeleteMenu = bDelete;
113 m_bDeleteChildren = bDeleteChildren;
114 m_pVCLMenu = pMenu;
115 m_xFrame = rFrame;
116 m_bInitialized = false;
117 m_bIsBookmarkMenu = false;
118 acquire();
119 const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
120 m_bShowMenuImages = rSettings.GetUseImagesInMenus();
122 sal_uInt16 nItemCount = pMenu->GetItemCount();
123 m_aMenuItemHandlerVector.reserve(nItemCount);
124 OUString aItemCommand;
125 for ( sal_uInt16 i = 0; i < nItemCount; i++ )
127 sal_uInt16 nItemId = FillItemCommand(aItemCommand,pMenu, i );
128 bool bShowMenuImages( m_bShowMenuImages );
130 // overwrite the show icons on menu option?
131 if (!bShowMenuImages)
133 MenuItemBits nBits = pMenu->GetItemBits( nItemId );
134 bShowMenuImages = ( ( nBits & MenuItemBits::ICON ) == MenuItemBits::ICON );
137 PopupMenu* pPopupMenu = pMenu->GetPopupMenu( nItemId );
138 if ( pPopupMenu )
140 AddMenu(pPopupMenu,aItemCommand,nItemId,bDeleteChildren,bDeleteChildren);
141 if (! ( aItemCommand.startsWith( ADDONSPOPUPMENU_URL_PREFIX_STR ) ) )
144 // Create addon popup menu if there exist elements and this is the tools popup menu
145 if ( ( nItemId == SID_ADDONLIST || aItemCommand == aSlotSpecialToolsMenu )
146 && AddonMenuManager::HasAddonMenuElements() )
148 AddonMenu* pSubMenu = AddonMenuManager::CreateAddonMenu(rFrame, rxContext);
149 if ( pSubMenu && ( pSubMenu->GetItemCount() > 0 ))
151 sal_uInt16 nCount = 0;
152 if ( pPopupMenu->GetItemType( nCount-1 ) != MenuItemType::SEPARATOR )
153 pPopupMenu->InsertSeparator();
155 // Use resource to load popup menu title
156 OUString aAddonsStrRes(FWK_RESSTR(STR_MENU_ADDONS));
157 pPopupMenu->InsertItem( ITEMID_ADDONLIST, aAddonsStrRes );
158 pPopupMenu->SetPopupMenu( ITEMID_ADDONLIST, pSubMenu );
160 // Set item command for popup menu to enable it for GetImageFromURL
161 aItemCommand = "slot:" + OUString::number( ITEMID_ADDONLIST );
162 pPopupMenu->SetItemCommand( ITEMID_ADDONLIST, aItemCommand );
164 AddMenu(pSubMenu,OUString(),nItemId,true,false);
165 // Set image for the addon popup menu item
166 if ( bShowMenuImages && !pPopupMenu->GetItemImage( ITEMID_ADDONLIST ))
168 Image aImage = GetImageFromURL( rFrame, aItemCommand, false );
169 if ( !!aImage )
170 pPopupMenu->SetItemImage( ITEMID_ADDONLIST, aImage );
173 else
174 delete pSubMenu;
178 else
180 if ( nItemId == SID_NEWDOCDIRECT || aItemCommand == aSlotNewDocDirect )
182 MenuConfiguration aMenuCfg( m_xContext );
183 BmkMenu* pSubMenu = static_cast<BmkMenu*>(aMenuCfg.CreateBookmarkMenu( rFrame, BOOKMARK_NEWMENU ));
184 pMenu->SetPopupMenu( nItemId, pSubMenu );
186 AddMenu(pSubMenu,OUString(),nItemId,true,false);
187 if ( bShowMenuImages && !pMenu->GetItemImage( nItemId ))
189 Image aImage = GetImageFromURL( rFrame, aItemCommand, false );
190 if ( !!aImage )
191 pMenu->SetItemImage( nItemId, aImage );
194 else if ( nItemId == SID_AUTOPILOTMENU || aItemCommand == aSlotAutoPilot )
196 MenuConfiguration aMenuCfg( m_xContext );
197 BmkMenu* pSubMenu = static_cast<BmkMenu*>(aMenuCfg.CreateBookmarkMenu( rFrame, BOOKMARK_WIZARDMENU ));
198 pMenu->SetPopupMenu( nItemId, pSubMenu );
200 AddMenu(pSubMenu,OUString(),nItemId,true,false);
202 if ( bShowMenuImages && !pMenu->GetItemImage( nItemId ))
204 Image aImage = GetImageFromURL( rFrame, aItemCommand, false );
205 if ( !!aImage )
206 pMenu->SetItemImage( nItemId, aImage );
209 else if ( pMenu->GetItemType( i ) != MenuItemType::SEPARATOR )
211 if ( bShowMenuImages )
213 if ( AddonMenuManager::IsAddonMenuId( nItemId ))
215 // Add-Ons uses a images from different places
216 Image aImage;
217 OUString aImageId;
219 MenuAttributes* pMenuAttributes =
220 reinterpret_cast<MenuAttributes*>(pMenu->GetUserValue( nItemId ));
222 if ( pMenuAttributes && !pMenuAttributes->aImageId.isEmpty() )
224 // Retrieve image id from menu attributes
225 aImage = GetImageFromURL( rFrame, aImageId, false );
228 if ( !aImage )
230 aImage = GetImageFromURL( rFrame, aItemCommand, false );
231 if ( !aImage )
232 aImage = AddonsOptions().GetImageFromURL( aItemCommand, false );
235 if ( !!aImage )
236 pMenu->SetItemImage( nItemId, aImage );
238 else if ( !pMenu->GetItemImage( nItemId ))
240 Image aImage = GetImageFromURL( rFrame, aItemCommand, false );
241 if ( !!aImage )
242 pMenu->SetItemImage( nItemId, aImage );
246 Reference< XDispatch > aXDispatchRef;
247 m_aMenuItemHandlerVector.push_back( new MenuItemHandler( nItemId, NULL, aXDispatchRef ));
253 // retrieve label information for all menu items without item text
255 SetHdl();
258 void MenuManager::SetHdl()
260 m_pVCLMenu->SetHighlightHdl( LINK( this, MenuManager, Highlight ));
261 m_pVCLMenu->SetActivateHdl( LINK( this, MenuManager, Activate ));
262 m_pVCLMenu->SetDeactivateHdl( LINK( this, MenuManager, Deactivate ));
263 m_pVCLMenu->SetSelectHdl( LINK( this, MenuManager, Select ));
265 if ( m_xContext.is() )
266 m_xURLTransformer.set( URLTransformer::create( m_xContext ) );
269 MenuManager::~MenuManager()
271 std::vector< MenuItemHandler* >::iterator p;
272 for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); ++p )
274 MenuItemHandler* pItemHandler = *p;
275 pItemHandler->xMenuItemDispatch.clear();
276 if ( pItemHandler->pSubMenuManager )
277 (static_cast< XInterface* >((OWeakObject*)pItemHandler->pSubMenuManager))->release();
278 delete pItemHandler;
281 if ( m_bDeleteMenu )
282 delete m_pVCLMenu;
285 MenuManager::MenuItemHandler* MenuManager::GetMenuItemHandler( sal_uInt16 nItemId )
287 SolarMutexGuard g;
289 std::vector< MenuItemHandler* >::iterator p;
290 for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); ++p )
292 MenuItemHandler* pItemHandler = *p;
293 if ( pItemHandler->nItemId == nItemId )
294 return pItemHandler;
297 return 0;
300 void SAL_CALL MenuManager::statusChanged( const FeatureStateEvent& Event )
301 throw ( RuntimeException, std::exception )
303 OUString aFeatureURL = Event.FeatureURL.Complete;
304 MenuItemHandler* pStatusChangedMenu = NULL;
307 SolarMutexGuard g;
309 std::vector< MenuItemHandler* >::iterator p;
310 for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); ++p )
312 MenuItemHandler* pMenuItemHandler = *p;
313 if ( pMenuItemHandler->aMenuItemURL == aFeatureURL )
315 pStatusChangedMenu = pMenuItemHandler;
316 break;
321 if ( pStatusChangedMenu )
323 SolarMutexGuard aSolarGuard;
325 bool bSetCheckmark = false;
326 bool bCheckmark = false;
327 bool bMenuItemEnabled = m_pVCLMenu->IsItemEnabled( pStatusChangedMenu->nItemId );
329 if ( bool(Event.IsEnabled) != bMenuItemEnabled )
330 m_pVCLMenu->EnableItem( pStatusChangedMenu->nItemId, Event.IsEnabled );
332 if ( Event.State >>= bCheckmark )
333 bSetCheckmark = true;
335 if ( bSetCheckmark )
336 m_pVCLMenu->CheckItem( pStatusChangedMenu->nItemId, bCheckmark );
339 if ( Event.Requery )
341 URL aTargetURL;
342 aTargetURL.Complete = pStatusChangedMenu->aMenuItemURL;
344 m_xURLTransformer->parseStrict( aTargetURL );
346 Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
347 Reference< XDispatch > xMenuItemDispatch = xDispatchProvider->queryDispatch(
348 aTargetURL, OUString(), 0 );
350 if ( xMenuItemDispatch.is() )
352 pStatusChangedMenu->xMenuItemDispatch = xMenuItemDispatch;
353 pStatusChangedMenu->aMenuItemURL = aTargetURL.Complete;
354 xMenuItemDispatch->addStatusListener( (static_cast< XStatusListener* >(this)), aTargetURL );
360 void MenuManager::RemoveListener()
362 SolarMutexGuard g;
363 ClearMenuDispatch();
366 void MenuManager::ClearMenuDispatch(const EventObject& Source,bool _bRemoveOnly)
368 // disposing called from parent dispatcher
369 // remove all listener to prepare shutdown
371 std::vector< MenuItemHandler* >::iterator p;
372 for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); ++p )
374 MenuItemHandler* pItemHandler = *p;
375 if ( pItemHandler->xMenuItemDispatch.is() )
377 URL aTargetURL;
378 aTargetURL.Complete = pItemHandler->aMenuItemURL;
379 m_xURLTransformer->parseStrict( aTargetURL );
381 pItemHandler->xMenuItemDispatch->removeStatusListener(
382 (static_cast< XStatusListener* >(this)), aTargetURL );
385 pItemHandler->xMenuItemDispatch.clear();
386 if ( pItemHandler->pSubMenuManager )
388 if ( _bRemoveOnly )
389 pItemHandler->pSubMenuManager->RemoveListener();
390 else
391 pItemHandler->pSubMenuManager->disposing( Source );
396 void SAL_CALL MenuManager::disposing( const EventObject& Source ) throw ( RuntimeException, std::exception )
398 if ( Source.Source == m_xFrame )
400 SolarMutexGuard g;
401 ClearMenuDispatch(Source,false);
403 else
405 // disposing called from menu item dispatcher, remove listener
406 MenuItemHandler* pMenuItemDisposing = NULL;
409 SolarMutexGuard g;
411 std::vector< MenuItemHandler* >::iterator p;
412 for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); ++p )
414 MenuItemHandler* pMenuItemHandler = *p;
415 if ( pMenuItemHandler->xMenuItemDispatch == Source.Source )
417 pMenuItemDisposing = pMenuItemHandler;
418 break;
422 if ( pMenuItemDisposing )
424 URL aTargetURL;
425 aTargetURL.Complete = pMenuItemDisposing->aMenuItemURL;
427 m_xURLTransformer->parseStrict( aTargetURL );
429 pMenuItemDisposing->xMenuItemDispatch->removeStatusListener((static_cast< XStatusListener* >(this)), aTargetURL );
430 pMenuItemDisposing->xMenuItemDispatch.clear();
436 void MenuManager::UpdateSpecialFileMenu( Menu* pMenu )
438 // update picklist
439 Sequence< Sequence< PropertyValue > > aHistoryList = SvtHistoryOptions().GetList( ePICKLIST );
440 ::std::vector< MenuItemHandler* > aNewPickVector;
441 Reference< XStringWidth > xStringLength( new StringLength );
443 sal_uInt16 nPickItemId = START_ITEMID_PICKLIST;
444 int nPickListMenuItems = ( aHistoryList.getLength() > 99 ) ? 99 : aHistoryList.getLength();
446 aNewPickVector.reserve(nPickListMenuItems);
447 for ( int i = 0; i < nPickListMenuItems; i++ )
449 Sequence< PropertyValue > aPickListEntry = aHistoryList[i];
451 Reference< XDispatch > aXDispatchRef;
452 MenuItemHandler* pNewMenuItemHandler = new MenuItemHandler(
453 nPickItemId++,
454 NULL,
455 aXDispatchRef );
457 for ( int j = 0; j < aPickListEntry.getLength(); j++ )
459 Any a = aPickListEntry[j].Value;
461 if ( aPickListEntry[j].Name == HISTORY_PROPERTYNAME_URL )
462 a >>= pNewMenuItemHandler->aMenuItemURL;
463 else if ( aPickListEntry[j].Name == HISTORY_PROPERTYNAME_FILTER )
464 a >>= pNewMenuItemHandler->aFilter;
465 else if ( aPickListEntry[j].Name == HISTORY_PROPERTYNAME_TITLE )
466 a >>= pNewMenuItemHandler->aTitle;
467 else if ( aPickListEntry[j].Name == HISTORY_PROPERTYNAME_PASSWORD )
468 a >>= pNewMenuItemHandler->aPassword;
471 aNewPickVector.push_back( pNewMenuItemHandler );
474 if ( !aNewPickVector.empty() )
476 URL aTargetURL;
477 Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
479 Reference< XDispatch > xMenuItemDispatch;
481 static const char s_sDefault[] = "_default";
482 // query for dispatcher
483 std::vector< MenuItemHandler* >::iterator p;
484 for ( p = aNewPickVector.begin(); p != aNewPickVector.end(); ++p )
486 MenuItemHandler* pMenuItemHandler = *p;
488 aTargetURL.Complete = pMenuItemHandler->aMenuItemURL;
489 m_xURLTransformer->parseStrict( aTargetURL );
491 if ( !xMenuItemDispatch.is() )
493 // attention: this code assume that "_blank" can only be consumed by desktop service
494 xMenuItemDispatch = xDispatchProvider->queryDispatch( aTargetURL, s_sDefault, 0 );
497 if ( xMenuItemDispatch.is() )
499 pMenuItemHandler->xMenuItemDispatch = xMenuItemDispatch;
500 pMenuItemHandler->aMenuItemURL = aTargetURL.Complete;
505 SolarMutexGuard g;
507 int nItemCount = pMenu->GetItemCount();
509 if ( nItemCount > 0 )
511 int nRemoveItemCount = 0;
513 // remove all old picklist entries from menu
514 sal_uInt16 nPos = pMenu->GetItemPos( START_ITEMID_PICKLIST );
515 for ( sal_uInt16 n = nPos; n < pMenu->GetItemCount(); )
517 pMenu->RemoveItem( n );
518 ++nRemoveItemCount;
521 if ( pMenu->GetItemType( pMenu->GetItemCount()-1 ) == MenuItemType::SEPARATOR )
522 pMenu->RemoveItem( pMenu->GetItemCount()-1 );
524 // remove all old picklist entries from menu handler
525 if ( nRemoveItemCount > 0 )
527 for( sal_uInt32 nIndex = m_aMenuItemHandlerVector.size() - nRemoveItemCount;
528 nIndex < m_aMenuItemHandlerVector.size(); )
530 delete m_aMenuItemHandlerVector.at( nIndex );
531 m_aMenuItemHandlerVector.erase( m_aMenuItemHandlerVector.begin() + nIndex );
536 // append new picklist menu entries
537 aNewPickVector.reserve(aNewPickVector.size());
538 pMenu->InsertSeparator();
539 const sal_uInt32 nCount = aNewPickVector.size();
540 for ( sal_uInt32 i = 0; i < nCount; i++ )
542 char menuShortCut[5] = "~n: ";
544 OUString aMenuShortCut;
545 if ( i <= 9 )
547 if ( i == 9 )
548 aMenuShortCut = "1~0: ";
549 else
551 menuShortCut[1] = (char)( '1' + i );
552 aMenuShortCut = OUString::createFromAscii( menuShortCut );
555 else
557 aMenuShortCut = OUString::number(( i + 1 ));
558 aMenuShortCut += ": ";
561 // Abbreviate URL
562 OUString aURLString( aNewPickVector.at( i )->aMenuItemURL );
563 OUString aTipHelpText;
564 OUString aMenuTitle;
565 INetURLObject aURL( aURLString );
567 if ( aURL.GetProtocol() == INetProtocol::File )
569 // Do handle file URL differently => convert it to a system
570 // path and abbreviate it with a special function:
571 OUString aFileSystemPath( aURL.getFSysPath( INetURLObject::FSYS_DETECT ) );
573 OUString aSystemPath( aFileSystemPath );
574 OUString aCompactedSystemPath;
576 aTipHelpText = aSystemPath;
577 oslFileError nError = osl_abbreviateSystemPath( aSystemPath.pData, &aCompactedSystemPath.pData, 46, NULL );
578 if ( !nError )
579 aMenuTitle = aCompactedSystemPath;
580 else
581 aMenuTitle = aSystemPath;
583 else
585 // Use INetURLObject to abbreviate all other URLs
586 OUString aShortURL;
587 aShortURL = aURL.getAbbreviated( xStringLength, 46, INetURLObject::DECODE_UNAMBIGUOUS );
588 aMenuTitle += aShortURL;
589 aTipHelpText = aURLString;
592 OUString aTitle( aMenuShortCut + aMenuTitle );
594 MenuItemHandler* pMenuItemHandler = aNewPickVector.at( i );
595 pMenu->InsertItem( pMenuItemHandler->nItemId, aTitle );
596 pMenu->SetTipHelpText( pMenuItemHandler->nItemId, aTipHelpText );
597 m_aMenuItemHandlerVector.push_back( pMenuItemHandler );
603 void MenuManager::UpdateSpecialWindowMenu( Menu* pMenu,const Reference< XComponentContext >& xContext )
605 // update window list
606 ::std::vector< OUString > aNewWindowListVector;
608 Reference< XDesktop2 > xDesktop = Desktop::create( xContext );
610 sal_uInt16 nActiveItemId = 0;
611 sal_uInt16 nItemId = START_ITEMID_WINDOWLIST;
613 Reference< XFrame > xCurrentFrame = xDesktop->getCurrentFrame();
614 Reference< XIndexAccess > xList( xDesktop->getFrames(), UNO_QUERY );
615 sal_Int32 nFrameCount = xList->getCount();
616 aNewWindowListVector.reserve(nFrameCount);
617 for (sal_Int32 i=0; i<nFrameCount; ++i )
619 Reference< XFrame > xFrame;
620 xList->getByIndex(i) >>= xFrame;
622 if (xFrame.is())
624 if ( xFrame == xCurrentFrame )
625 nActiveItemId = nItemId;
627 vcl::Window* pWin = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() );
628 if ( pWin && pWin->IsVisible() )
630 aNewWindowListVector.push_back( pWin->GetText() );
631 ++nItemId;
637 SolarMutexGuard g;
639 int nItemCount = pMenu->GetItemCount();
641 if ( nItemCount > 0 )
643 // remove all old window list entries from menu
644 sal_uInt16 nPos = pMenu->GetItemPos( START_ITEMID_WINDOWLIST );
645 for ( sal_uInt16 n = nPos; n < pMenu->GetItemCount(); )
646 pMenu->RemoveItem( n );
648 if ( pMenu->GetItemType( pMenu->GetItemCount()-1 ) == MenuItemType::SEPARATOR )
649 pMenu->RemoveItem( pMenu->GetItemCount()-1 );
652 if ( !aNewWindowListVector.empty() )
654 // append new window list entries to menu
655 pMenu->InsertSeparator();
656 nItemId = START_ITEMID_WINDOWLIST;
657 const sal_uInt32 nCount = aNewWindowListVector.size();
658 for ( sal_uInt32 i = 0; i < nCount; i++ )
660 pMenu->InsertItem( nItemId, aNewWindowListVector.at( i ), MenuItemBits::RADIOCHECK );
661 if ( nItemId == nActiveItemId )
662 pMenu->CheckItem( nItemId );
663 ++nItemId;
669 void MenuManager::CreatePicklistArguments( Sequence< PropertyValue >& aArgsList, const MenuItemHandler* pMenuItemHandler )
671 int NUM_OF_PICKLIST_ARGS = 3;
673 Any a;
674 aArgsList.realloc( NUM_OF_PICKLIST_ARGS );
676 aArgsList[0].Name = "FileName";
677 a <<= pMenuItemHandler->aMenuItemURL;
678 aArgsList[0].Value = a;
680 aArgsList[1].Name = "Referer";
681 a <<= OUString( "private:user" );
682 aArgsList[1].Value = a;
684 OUString aFilter( pMenuItemHandler->aFilter );
686 sal_Int32 nPos = aFilter.indexOf( '|' );
687 if ( nPos >= 0 )
689 OUString aFilterOptions;
691 if ( nPos < ( aFilter.getLength() - 1 ) )
692 aFilterOptions = aFilter.copy( nPos+1 );
694 aArgsList[2].Name = "FilterOptions";
695 a <<= aFilterOptions;
696 aArgsList[2].Value = a;
698 aFilter = aFilter.copy( 0, nPos-1 );
699 aArgsList.realloc( ++NUM_OF_PICKLIST_ARGS );
702 aArgsList[NUM_OF_PICKLIST_ARGS-1].Name = "FilterName";
703 a <<= aFilter;
704 aArgsList[NUM_OF_PICKLIST_ARGS-1].Value = a;
707 // vcl handler
709 IMPL_LINK_TYPED( MenuManager, Activate, Menu *, pMenu, bool )
711 if ( pMenu == m_pVCLMenu )
713 // set/unset hiding disabled menu entries
714 bool bDontHide = SvtMenuOptions().IsEntryHidingEnabled();
715 const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
716 bool bShowMenuImages = rSettings.GetUseImagesInMenus();
718 MenuFlags nFlag = pMenu->GetMenuFlags();
719 if ( bDontHide )
720 nFlag &= ~MenuFlags::HideDisabledEntries;
721 else
722 nFlag |= MenuFlags::HideDisabledEntries;
723 pMenu->SetMenuFlags( nFlag );
725 if ( m_bActive )
726 return false;
728 m_bActive = true;
730 OUString aCommand( m_aMenuItemCommand );
731 if (m_aMenuItemCommand.matchIgnoreAsciiCase(UNO_COMMAND))
733 // Remove protocol part from command so we can use an easier comparison method
734 aCommand = aCommand.copy(RTL_CONSTASCII_LENGTH(UNO_COMMAND));
737 if ( m_aMenuItemCommand == aSpecialFileMenu || m_aMenuItemCommand == aSlotSpecialFileMenu || aCommand == aSpecialFileCommand )
738 UpdateSpecialFileMenu( pMenu );
739 else if ( m_aMenuItemCommand == aSpecialWindowMenu || m_aMenuItemCommand == aSlotSpecialWindowMenu || aCommand == aSpecialWindowCommand )
740 UpdateSpecialWindowMenu( pMenu, m_xContext );
742 // Check if some modes have changed so we have to update our menu images
743 if ( bShowMenuImages != m_bShowMenuImages )
745 // The mode changed so we have to replace all images
746 m_bShowMenuImages = bShowMenuImages;
747 FillMenuImages( m_xFrame, pMenu, bShowMenuImages );
750 if ( m_bInitialized )
751 return false;
752 else
754 URL aTargetURL;
756 SolarMutexGuard g;
758 Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
759 if ( xDispatchProvider.is() )
761 std::vector< MenuItemHandler* >::iterator p;
762 for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); ++p )
764 MenuItemHandler* pMenuItemHandler = *p;
765 if ( pMenuItemHandler &&
766 pMenuItemHandler->pSubMenuManager == 0 &&
767 !pMenuItemHandler->xMenuItemDispatch.is() )
769 // There is no dispatch mechanism for the special window list menu items,
770 // because they are handled directly through XFrame->activate!!!
771 if ( pMenuItemHandler->nItemId < START_ITEMID_WINDOWLIST ||
772 pMenuItemHandler->nItemId > END_ITEMID_WINDOWLIST )
774 OUString aItemCommand = pMenu->GetItemCommand( pMenuItemHandler->nItemId );
775 if ( aItemCommand.isEmpty() )
777 aItemCommand = "slot:" + OUString::number( pMenuItemHandler->nItemId );
778 pMenu->SetItemCommand( pMenuItemHandler->nItemId, aItemCommand );
781 aTargetURL.Complete = aItemCommand;
783 m_xURLTransformer->parseStrict( aTargetURL );
785 Reference< XDispatch > xMenuItemDispatch;
786 if ( m_bIsBookmarkMenu )
787 xMenuItemDispatch = xDispatchProvider->queryDispatch( aTargetURL, pMenuItemHandler->aTargetFrame, 0 );
788 else
789 xMenuItemDispatch = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
791 if ( xMenuItemDispatch.is() )
793 pMenuItemHandler->xMenuItemDispatch = xMenuItemDispatch;
794 pMenuItemHandler->aMenuItemURL = aTargetURL.Complete;
795 xMenuItemDispatch->addStatusListener( (static_cast< XStatusListener* >(this)), aTargetURL );
797 else
798 pMenu->EnableItem( pMenuItemHandler->nItemId, false );
806 return true;
809 IMPL_LINK_TYPED( MenuManager, Deactivate, Menu *, pMenu, bool )
811 if ( pMenu == m_pVCLMenu )
812 m_bActive = false;
814 return true;
817 IMPL_LINK( MenuManager, Select, Menu *, pMenu )
819 URL aTargetURL;
820 Sequence<PropertyValue> aArgs;
821 Reference< XDispatch > xDispatch;
824 SolarMutexGuard g;
826 sal_uInt16 nCurItemId = pMenu->GetCurItemId();
827 if ( pMenu == m_pVCLMenu &&
828 pMenu->GetItemType( nCurItemId ) != MenuItemType::SEPARATOR )
830 if ( nCurItemId >= START_ITEMID_WINDOWLIST &&
831 nCurItemId <= END_ITEMID_WINDOWLIST )
833 // window list menu item selected
835 Reference< XDesktop2 > xDesktop = Desktop::create( m_xContext );
837 sal_uInt16 nTaskId = START_ITEMID_WINDOWLIST;
838 Reference< XIndexAccess > xList( xDesktop->getFrames(), UNO_QUERY );
839 sal_Int32 nCount = xList->getCount();
840 for ( sal_Int32 i=0; i<nCount; ++i )
842 Reference< XFrame > xFrame;
843 xList->getByIndex(i) >>= xFrame;
845 if ( xFrame.is() && nTaskId == nCurItemId )
847 vcl::Window* pWin = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() );
848 pWin->GrabFocus();
849 pWin->ToTop( TOTOP_RESTOREWHENMIN );
850 break;
853 nTaskId++;
856 else
858 MenuItemHandler* pMenuItemHandler = GetMenuItemHandler( nCurItemId );
859 if ( pMenuItemHandler && pMenuItemHandler->xMenuItemDispatch.is() )
861 aTargetURL.Complete = pMenuItemHandler->aMenuItemURL;
862 m_xURLTransformer->parseStrict( aTargetURL );
864 if ( nCurItemId >= START_ITEMID_PICKLIST &&
865 nCurItemId < START_ITEMID_WINDOWLIST )
867 // picklist menu item selected
868 CreatePicklistArguments( aArgs, pMenuItemHandler );
870 else if ( m_bIsBookmarkMenu )
872 // bookmark menu item selected
873 aArgs.realloc( 1 );
874 aArgs[0].Name = "Referer";
875 aArgs[0].Value <<= OUString( "private:user" );
878 xDispatch = pMenuItemHandler->xMenuItemDispatch;
884 if ( xDispatch.is() )
885 xDispatch->dispatch( aTargetURL, aArgs );
887 return 1;
890 IMPL_LINK_NOARG_TYPED(MenuManager, Highlight, Menu *, bool)
892 return false;
895 void MenuManager::AddMenu(PopupMenu* _pPopupMenu,const OUString& _sItemCommand,sal_uInt16 _nItemId,bool _bDelete,bool _bDeleteChildren)
897 MenuManager* pSubMenuManager = new MenuManager( m_xContext, m_xFrame, _pPopupMenu, _bDelete, _bDeleteChildren );
899 // store menu item command as we later have to know which menu is active (see Activate handler)
900 pSubMenuManager->m_aMenuItemCommand = _sItemCommand;
902 Reference< XDispatch > aXDispatchRef;
903 MenuItemHandler* pMenuItemHandler = new MenuItemHandler(
904 _nItemId,
905 pSubMenuManager,
906 aXDispatchRef );
907 m_aMenuItemHandlerVector.push_back( pMenuItemHandler );
910 sal_uInt16 MenuManager::FillItemCommand(OUString& _rItemCommand, Menu* _pMenu,sal_uInt16 _nIndex) const
912 sal_uInt16 nItemId = _pMenu->GetItemId( _nIndex );
914 _rItemCommand = _pMenu->GetItemCommand( nItemId );
915 if ( _rItemCommand.isEmpty() )
917 _rItemCommand = "slot:" + OUString::number( nItemId );
918 _pMenu->SetItemCommand( nItemId, _rItemCommand );
920 return nItemId;
922 void MenuManager::FillMenuImages(Reference< XFrame >& _xFrame, Menu* _pMenu,bool bShowMenuImages)
924 AddonsOptions aAddonOptions;
926 for ( sal_uInt16 nPos = 0; nPos < _pMenu->GetItemCount(); nPos++ )
928 sal_uInt16 nId = _pMenu->GetItemId( nPos );
929 if ( _pMenu->GetItemType( nPos ) != MenuItemType::SEPARATOR )
931 bool bTmpShowMenuImages( bShowMenuImages );
932 // overwrite the show icons on menu option?
933 if (!bTmpShowMenuImages)
935 MenuItemBits nBits = _pMenu->GetItemBits( nId );
936 bTmpShowMenuImages = ( ( nBits & MenuItemBits::ICON ) == MenuItemBits::ICON );
939 if ( bTmpShowMenuImages )
941 bool bImageSet = false;
942 OUString aImageId;
944 ::framework::MenuAttributes* pMenuAttributes =
945 reinterpret_cast< ::framework::MenuAttributes*>(_pMenu->GetUserValue( nId ));
947 if ( pMenuAttributes )
948 aImageId = pMenuAttributes->aImageId; // Retrieve image id from menu attributes
950 if ( !aImageId.isEmpty() )
952 Image aImage = GetImageFromURL( _xFrame, aImageId, false );
953 if ( !!aImage )
955 bImageSet = true;
956 _pMenu->SetItemImage( nId, aImage );
960 if ( !bImageSet )
962 OUString aMenuItemCommand = _pMenu->GetItemCommand( nId );
963 Image aImage = GetImageFromURL( _xFrame, aMenuItemCommand, false );
964 if ( !aImage )
965 aImage = aAddonOptions.GetImageFromURL( aMenuItemCommand, false );
967 _pMenu->SetItemImage( nId, aImage );
970 else
971 _pMenu->SetItemImage( nId, Image() );
977 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */