merge the formfield patch from ooo-build
[ooovba.git] / framework / source / uielement / newmenucontroller.cxx
blob7dc52b4f5a09d9f128f39e41bb6c204971bfce44
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: newmenucontroller.cxx,v $
10 * $Revision: 1.12.40.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_framework.hxx"
33 #include <uielement/newmenucontroller.hxx>
35 //_________________________________________________________________________________________________________________
36 // my own includes
37 //_________________________________________________________________________________________________________________
38 #include <threadhelp/resetableguard.hxx>
39 #include "services.h"
40 #ifndef __FRAMEWORK_CLASSES_RESOURCE_HRC_
41 #include <classes/resource.hrc>
42 #endif
43 #include <classes/fwkresid.hxx>
44 #include <classes/bmkmenu.hxx>
45 #include <helper/imageproducer.hxx>
46 #include <xml/menuconfiguration.hxx>
48 //_________________________________________________________________________________________________________________
49 // interface includes
50 //_________________________________________________________________________________________________________________
51 #include <com/sun/star/awt/XDevice.hpp>
52 #include <com/sun/star/beans/PropertyValue.hpp>
53 #include <com/sun/star/awt/MenuItemStyle.hpp>
54 #include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp>
55 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
56 #include <com/sun/star/frame/XModuleManager.hpp>
57 #include <com/sun/star/container/XNameAccess.hpp>
58 #include <com/sun/star/document/CorruptedFilterConfigurationException.hpp>
60 //_________________________________________________________________________________________________________________
61 // includes of other projects
62 //_________________________________________________________________________________________________________________
63 #include <vcl/svapp.hxx>
64 #include <vcl/i18nhelp.hxx>
65 #include <tools/urlobj.hxx>
66 #include <rtl/ustrbuf.hxx>
67 #include <cppuhelper/implbase1.hxx>
68 #include <osl/file.hxx>
69 #include <svtools/menuoptions.hxx>
70 #include <svtools/acceleratorexecute.hxx>
71 #include <svtools/moduleoptions.hxx>
72 #include <dispatch/uieventloghelper.hxx>
74 //_________________________________________________________________________________________________________________
75 // Defines
76 //_________________________________________________________________________________________________________________
79 using namespace com::sun::star::uno;
80 using namespace com::sun::star::lang;
81 using namespace com::sun::star::frame;
82 using namespace com::sun::star::beans;
83 using namespace com::sun::star::util;
84 using namespace com::sun::star::container;
85 using namespace com::sun::star::ui;
87 static const char SFX_REFERER_USER[] = "private:user";
89 namespace framework
92 DEFINE_XSERVICEINFO_MULTISERVICE ( NewMenuController ,
93 OWeakObject ,
94 SERVICENAME_POPUPMENUCONTROLLER ,
95 IMPLEMENTATIONNAME_NEWMENUCONTROLLER
98 DEFINE_INIT_SERVICE ( NewMenuController, {} )
100 void NewMenuController::setMenuImages( PopupMenu* pPopupMenu, sal_Bool bSetImages, sal_Bool bHiContrast )
102 USHORT nItemCount = pPopupMenu->GetItemCount();
103 Image aImage;
104 Reference< XFrame > xFrame( m_xFrame );
106 for ( USHORT i = 0; i < nItemCount; i++ )
108 USHORT nItemId = pPopupMenu->GetItemId( sal::static_int_cast<USHORT>( i ));
109 if ( nItemId != 0 )
111 if ( bSetImages )
113 sal_Bool bImageSet( sal_False );
114 ::rtl::OUString aImageId;
116 AddInfoForId::const_iterator pInfo = m_aAddInfoForItem.find( nItemId );
117 if ( pInfo != m_aAddInfoForItem.end() )
118 aImageId = pInfo->second.aImageId; // Retrieve image id for menu item
120 if ( aImageId.getLength() > 0 )
122 aImage = GetImageFromURL( xFrame, aImageId, FALSE, bHiContrast );
123 if ( !!aImage )
125 bImageSet = sal_True;
126 pPopupMenu->SetItemImage( nItemId, aImage );
130 if ( !bImageSet )
132 String aCmd( pPopupMenu->GetItemCommand( nItemId ) );
133 if ( aCmd.Len() )
134 aImage = GetImageFromURL( xFrame, aCmd, FALSE, bHiContrast );
136 if ( !!aImage )
137 pPopupMenu->SetItemImage( nItemId, aImage );
140 else
141 pPopupMenu->SetItemImage( nItemId, aImage );
146 void NewMenuController::determineAndSetNewDocAccel( PopupMenu* pPopupMenu, const KeyCode& rKeyCode )
148 USHORT nCount( pPopupMenu->GetItemCount() );
149 USHORT nId( 0 );
150 sal_Bool bFound( sal_False );
151 rtl::OUString aCommand;
153 if ( m_aEmptyDocURL.getLength() > 0 )
155 // Search for the empty document URL
157 for ( sal_uInt32 i = 0; i < sal_uInt32( nCount ); i++ )
159 nId = pPopupMenu->GetItemId( USHORT( i ));
160 if ( nId != 0 && pPopupMenu->GetItemType( nId ) != MENUITEM_SEPARATOR )
162 aCommand = pPopupMenu->GetItemCommand( nId );
163 if ( aCommand.indexOf( m_aEmptyDocURL ) == 0 )
165 pPopupMenu->SetAccelKey( nId, rKeyCode );
166 bFound = sal_True;
167 break;
173 if ( !bFound )
175 // Search for the default module name
176 rtl::OUString aDefaultModuleName( SvtModuleOptions().GetDefaultModuleName() );
177 if ( aDefaultModuleName.getLength() > 0 )
179 for ( sal_uInt32 i = 0; i < sal_uInt32( nCount ); i++ )
181 nId = pPopupMenu->GetItemId( USHORT( i ));
182 if ( nId != 0 && pPopupMenu->GetItemType( nId ) != MENUITEM_SEPARATOR )
184 aCommand = pPopupMenu->GetItemCommand( nId );
185 if ( aCommand.indexOf( aDefaultModuleName ) >= 0 )
187 pPopupMenu->SetAccelKey( nId, rKeyCode );
188 break;
196 void NewMenuController::setAccelerators( PopupMenu* pPopupMenu )
198 if ( m_bModuleIdentified )
200 Reference< XAcceleratorConfiguration > xDocAccelCfg( m_xDocAcceleratorManager );
201 Reference< XAcceleratorConfiguration > xModuleAccelCfg( m_xModuleAcceleratorManager );
202 Reference< XAcceleratorConfiguration > xGlobalAccelCfg( m_xGlobalAcceleratorManager );
204 if ( !m_bAcceleratorCfg )
206 // Retrieve references on demand
207 m_bAcceleratorCfg = sal_True;
208 if ( !xDocAccelCfg.is() )
210 Reference< XController > xController = m_xFrame->getController();
211 Reference< XModel > xModel;
212 if ( xController.is() )
214 xModel = xController->getModel();
215 if ( xModel.is() )
217 Reference< XUIConfigurationManagerSupplier > xSupplier( xModel, UNO_QUERY );
218 if ( xSupplier.is() )
220 Reference< XUIConfigurationManager > xDocUICfgMgr( xSupplier->getUIConfigurationManager(), UNO_QUERY );
221 if ( xDocUICfgMgr.is() )
223 xDocAccelCfg = Reference< XAcceleratorConfiguration >( xDocUICfgMgr->getShortCutManager(), UNO_QUERY );
224 m_xDocAcceleratorManager = xDocAccelCfg;
231 if ( !xModuleAccelCfg.is() )
233 Reference< XModuleUIConfigurationManagerSupplier > xModuleCfgMgrSupplier( m_xServiceManager->createInstance(
234 SERVICENAME_MODULEUICONFIGURATIONMANAGERSUPPLIER ),
235 UNO_QUERY );
236 Reference< XUIConfigurationManager > xUICfgMgr = xModuleCfgMgrSupplier->getUIConfigurationManager( m_aModuleIdentifier );
237 if ( xUICfgMgr.is() )
239 xModuleAccelCfg = Reference< XAcceleratorConfiguration >( xUICfgMgr->getShortCutManager(), UNO_QUERY );
240 m_xModuleAcceleratorManager = xModuleAccelCfg;
244 if ( !xGlobalAccelCfg.is() )
246 xGlobalAccelCfg = Reference< XAcceleratorConfiguration >( m_xServiceManager->createInstance(
247 SERVICENAME_GLOBALACCELERATORCONFIGURATION ),
248 UNO_QUERY );
249 m_xGlobalAcceleratorManager = xGlobalAccelCfg;
253 KeyCode aEmptyKeyCode;
254 sal_uInt32 nItemCount( pPopupMenu->GetItemCount() );
255 std::vector< KeyCode > aMenuShortCuts;
256 std::vector< rtl::OUString > aCmds;
257 std::vector< sal_uInt32 > aIds;
258 for ( sal_uInt32 i = 0; i < nItemCount; i++ )
260 USHORT nId( pPopupMenu->GetItemId( USHORT( i )));
261 if ( nId & ( pPopupMenu->GetItemType( nId ) != MENUITEM_SEPARATOR ))
263 aIds.push_back( nId );
264 aMenuShortCuts.push_back( aEmptyKeyCode );
265 aCmds.push_back( pPopupMenu->GetItemCommand( nId ));
269 sal_uInt32 nSeqCount( aIds.size() );
271 if ( m_bNewMenu )
272 nSeqCount+=1;
274 Sequence< rtl::OUString > aSeq( nSeqCount );
276 // Add a special command for our "New" menu.
277 if ( m_bNewMenu )
279 aSeq[nSeqCount-1] = m_aCommandURL;
280 aMenuShortCuts.push_back( aEmptyKeyCode );
283 const sal_uInt32 nCount = aCmds.size();
284 for ( sal_uInt32 i = 0; i < nCount; i++ )
285 aSeq[i] = aCmds[i];
287 if ( m_xGlobalAcceleratorManager.is() )
288 retrieveShortcutsFromConfiguration( xGlobalAccelCfg, aSeq, aMenuShortCuts );
289 if ( m_xModuleAcceleratorManager.is() )
290 retrieveShortcutsFromConfiguration( xModuleAccelCfg, aSeq, aMenuShortCuts );
291 if ( m_xDocAcceleratorManager.is() )
292 retrieveShortcutsFromConfiguration( xGlobalAccelCfg, aSeq, aMenuShortCuts );
294 const sal_uInt32 nCount2 = aIds.size();
295 for ( sal_uInt32 i = 0; i < nCount2; i++ )
296 pPopupMenu->SetAccelKey( USHORT( aIds[i] ), aMenuShortCuts[i] );
298 // Special handling for "New" menu short-cut should be set at the
299 // document which will be opened using it.
300 if ( m_bNewMenu )
302 if ( aMenuShortCuts[nSeqCount-1] != aEmptyKeyCode )
303 determineAndSetNewDocAccel( pPopupMenu, aMenuShortCuts[nSeqCount-1] );
308 void NewMenuController::retrieveShortcutsFromConfiguration(
309 const Reference< XAcceleratorConfiguration >& rAccelCfg,
310 const Sequence< rtl::OUString >& rCommands,
311 std::vector< KeyCode >& aMenuShortCuts )
313 if ( rAccelCfg.is() )
317 com::sun::star::awt::KeyEvent aKeyEvent;
318 Sequence< Any > aSeqKeyCode = rAccelCfg->getPreferredKeyEventsForCommandList( rCommands );
319 for ( sal_Int32 i = 0; i < aSeqKeyCode.getLength(); i++ )
321 if ( aSeqKeyCode[i] >>= aKeyEvent )
322 aMenuShortCuts[i] = svt::AcceleratorExecute::st_AWTKey2VCLKey( aKeyEvent );
325 catch ( IllegalArgumentException& )
331 NewMenuController::NewMenuController( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ) :
332 PopupMenuControllerBase( xServiceManager ),
333 m_bShowImages( sal_True ),
334 m_bHiContrast( sal_False ),
335 m_bNewMenu( sal_False ),
336 m_bModuleIdentified( sal_False ),
337 m_bAcceleratorCfg( sal_False ),
338 m_aTargetFrame( RTL_CONSTASCII_USTRINGPARAM( "_default" ))
342 NewMenuController::~NewMenuController()
346 // private function
347 void NewMenuController::fillPopupMenu( Reference< css::awt::XPopupMenu >& rPopupMenu )
349 VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( rPopupMenu );
350 PopupMenu* pVCLPopupMenu = 0;
352 vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
354 resetPopupMenu( rPopupMenu );
355 if ( pPopupMenu )
356 pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu();
358 if ( pVCLPopupMenu )
360 MenuConfiguration aMenuCfg( m_xServiceManager );
361 BmkMenu* pSubMenu( 0 );
363 if ( m_bNewMenu )
364 pSubMenu = (BmkMenu*)aMenuCfg.CreateBookmarkMenu( m_xFrame, BOOKMARK_NEWMENU );
365 else
366 pSubMenu = (BmkMenu*)aMenuCfg.CreateBookmarkMenu( m_xFrame, BOOKMARK_WIZARDMENU );
368 // copy entries as we have to use the provided popup menu
369 *pVCLPopupMenu = *pSubMenu;
371 Image aImage;
372 AddInfo aAddInfo;
374 // retrieve additional parameters from bookmark menu and
375 // store it in a hash_map.
376 for ( USHORT i = 0; i < pSubMenu->GetItemCount(); i++ )
378 USHORT nItemId = pSubMenu->GetItemId( sal::static_int_cast<USHORT>( i ) );
379 if (( nItemId != 0 ) &&
380 ( pSubMenu->GetItemType( nItemId ) != MENUITEM_SEPARATOR ))
382 MenuConfiguration::Attributes* pBmkAttributes = (MenuConfiguration::Attributes *)(pSubMenu->GetUserValue( nItemId ));
383 if ( pBmkAttributes != 0 )
385 aAddInfo.aTargetFrame = pBmkAttributes->aTargetFrame;
386 aAddInfo.aImageId = pBmkAttributes->aImageId;
388 m_aAddInfoForItem.insert( AddInfoForId::value_type( nItemId, aAddInfo ));
393 if ( m_bShowImages )
394 setMenuImages( pVCLPopupMenu, m_bShowImages, m_bHiContrast );
396 delete pSubMenu;
400 // XEventListener
401 void SAL_CALL NewMenuController::disposing( const EventObject& ) throw ( RuntimeException )
403 Reference< css::awt::XMenuListener > xHolder(( OWeakObject *)this, UNO_QUERY );
405 ResetableGuard aLock( m_aLock );
406 m_xFrame.clear();
407 m_xDispatch.clear();
408 m_xServiceManager.clear();
410 if ( m_xPopupMenu.is() )
411 m_xPopupMenu->removeMenuListener( Reference< css::awt::XMenuListener >(( OWeakObject *)this, UNO_QUERY ));
412 m_xPopupMenu.clear();
415 // XStatusListener
416 void SAL_CALL NewMenuController::statusChanged( const FeatureStateEvent& ) throw ( RuntimeException )
420 // XMenuListener
421 void SAL_CALL NewMenuController::select( const css::awt::MenuEvent& rEvent ) throw (RuntimeException)
423 Reference< css::awt::XPopupMenu > xPopupMenu;
424 Reference< XDispatch > xDispatch;
425 Reference< XDispatchProvider > xDispatchProvider;
426 Reference< XMultiServiceFactory > xServiceManager;
427 Reference< XURLTransformer > xURLTransformer;
429 ResetableGuard aLock( m_aLock );
430 xPopupMenu = m_xPopupMenu;
431 xDispatchProvider = Reference< XDispatchProvider >( m_xFrame, UNO_QUERY );
432 xServiceManager = m_xServiceManager;
433 xURLTransformer = m_xURLTransformer;
434 aLock.unlock();
436 css::util::URL aTargetURL;
437 Sequence< PropertyValue > aArgsList( 1 );
439 if ( xPopupMenu.is() && xDispatchProvider.is() )
441 VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXPopupMenu::GetImplementation( xPopupMenu );
442 if ( pPopupMenu )
445 vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
446 PopupMenu* pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu();
447 aTargetURL.Complete = pVCLPopupMenu->GetItemCommand( rEvent.MenuId );
450 xURLTransformer->parseStrict( aTargetURL );
452 aArgsList[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Referer" ));
453 aArgsList[0].Value = makeAny( ::rtl::OUString::createFromAscii( SFX_REFERER_USER ));
455 rtl::OUString aTargetFrame( m_aTargetFrame );
456 AddInfoForId::const_iterator pItem = m_aAddInfoForItem.find( rEvent.MenuId );
457 if ( pItem != m_aAddInfoForItem.end() )
458 aTargetFrame = pItem->second.aTargetFrame;
460 xDispatch = xDispatchProvider->queryDispatch( aTargetURL, aTargetFrame, 0 );
464 if ( xDispatch.is() )
466 // Call dispatch asychronously as we can be destroyed while dispatch is
467 // executed. VCL is not able to survive this as it wants to call listeners
468 // after select!!!
469 NewDocument* pNewDocument = new NewDocument;
470 pNewDocument->xDispatch = xDispatch;
471 pNewDocument->aTargetURL = aTargetURL;
472 pNewDocument->aArgSeq = aArgsList;
473 if(::comphelper::UiEventsLogger::isEnabled()) //#i88653#
474 UiEventLogHelper(::rtl::OUString::createFromAscii("NewMenuController")).log(m_xServiceManager, m_xFrame, aTargetURL, aArgsList);
475 Application::PostUserEvent( STATIC_LINK(0, NewMenuController, ExecuteHdl_Impl), pNewDocument );
479 void SAL_CALL NewMenuController::activate( const css::awt::MenuEvent& ) throw (RuntimeException)
481 vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
482 if ( m_xFrame.is() && m_xPopupMenu.is() )
484 VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXPopupMenu::GetImplementation( m_xPopupMenu );
485 if ( pPopupMenu )
487 const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
488 sal_Bool bShowImages( rSettings.GetUseImagesInMenus() );
489 sal_Bool bHiContrast( rSettings.GetHighContrastMode() );
491 PopupMenu* pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu();
493 if (( m_bShowImages != bShowImages ) ||
494 ( m_bHiContrast != bHiContrast ))
496 m_bShowImages = bShowImages;
497 m_bHiContrast = bHiContrast;
499 setMenuImages( pVCLPopupMenu, m_bShowImages, m_bHiContrast );
502 setAccelerators( pVCLPopupMenu );
507 // XPopupMenuController
508 void NewMenuController::impl_setPopupMenu()
511 if ( m_xPopupMenu.is() )
512 fillPopupMenu( m_xPopupMenu );
514 // Identify module that we are attach to. It's our context that we need to know.
515 Reference< XModuleManager > xModuleManager( m_xServiceManager->createInstance( SERVICENAME_MODULEMANAGER ),UNO_QUERY );
516 if ( xModuleManager.is() )
520 m_aModuleIdentifier = xModuleManager->identify( m_xFrame );
521 m_bModuleIdentified = sal_True;
523 Reference< XNameAccess > xNameAccess( xModuleManager, UNO_QUERY );
524 if (( m_aModuleIdentifier.getLength() > 0 ) && xNameAccess.is() )
526 Sequence< PropertyValue > aSeq;
528 if ( xNameAccess->getByName( m_aModuleIdentifier ) >>= aSeq )
530 for ( sal_Int32 y = 0; y < aSeq.getLength(); y++ )
532 if ( aSeq[y].Name.equalsAscii("ooSetupFactoryEmptyDocumentURL") )
534 aSeq[y].Value >>= m_aEmptyDocURL;
535 break;
541 catch ( RuntimeException& e )
543 throw e;
545 catch ( Exception& )
551 // XInitialization
552 void SAL_CALL NewMenuController::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException )
554 ResetableGuard aLock( m_aLock );
556 sal_Bool bInitalized( m_bInitialized );
557 if ( !bInitalized )
559 PopupMenuControllerBase::initialize( aArguments );
561 if ( m_bInitialized )
563 const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
565 m_bShowImages = rSettings.GetUseImagesInMenus();
566 m_bHiContrast = rSettings.GetHighContrastMode();
568 m_bNewMenu = m_aCommandURL.equalsAscii( ".uno:AddDirect" );
573 IMPL_STATIC_LINK_NOINSTANCE( NewMenuController, ExecuteHdl_Impl, NewDocument*, pNewDocument )
575 /* i62706: Don't catch all exceptions. We hide all problems here and are not able
576 to handle them on higher levels.
580 // Asynchronous execution as this can lead to our own destruction!
581 // Framework can recycle our current frame and the layout manager disposes all user interface
582 // elements if a component gets detached from its frame!
583 pNewDocument->xDispatch->dispatch( pNewDocument->aTargetURL, pNewDocument->aArgSeq );
586 catch (const ::com::sun::star::document::CorruptedFilterConfigurationException& exFilters)
588 throw exFilters;
590 catch (const Exception& )
594 delete pNewDocument;
595 return 0;