fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / framework / source / uielement / newmenucontroller.cxx
blob9a02716b1082c10e82d3fae394b4b1c3c3d546a5
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 <uielement/newmenucontroller.hxx>
22 #include "services.h"
23 #include <classes/resource.hrc>
24 #include <classes/fwkresid.hxx>
25 #include <framework/bmkmenu.hxx>
26 #include <framework/imageproducer.hxx>
27 #include <framework/menuconfiguration.hxx>
29 #include <com/sun/star/awt/XDevice.hpp>
30 #include <com/sun/star/beans/PropertyValue.hpp>
31 #include <com/sun/star/awt/MenuItemStyle.hpp>
32 #include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
33 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
34 #include <com/sun/star/ui/GlobalAcceleratorConfiguration.hpp>
35 #include <com/sun/star/frame/ModuleManager.hpp>
37 #include <vcl/svapp.hxx>
38 #include <vcl/i18nhelp.hxx>
39 #include <vcl/settings.hxx>
40 #include <rtl/ustrbuf.hxx>
41 #include <cppuhelper/implbase1.hxx>
42 #include <osl/file.hxx>
43 #include <svtools/menuoptions.hxx>
44 #include <svtools/acceleratorexecute.hxx>
45 #include <unotools/moduleoptions.hxx>
46 #include <osl/mutex.hxx>
47 #include <boost/scoped_ptr.hpp>
49 // Defines
51 using namespace com::sun::star::uno;
52 using namespace com::sun::star::lang;
53 using namespace com::sun::star::frame;
54 using namespace com::sun::star::beans;
55 using namespace com::sun::star::util;
56 using namespace com::sun::star::container;
57 using namespace com::sun::star::ui;
59 namespace framework
62 DEFINE_XSERVICEINFO_MULTISERVICE_2 ( NewMenuController ,
63 OWeakObject ,
64 SERVICENAME_POPUPMENUCONTROLLER ,
65 IMPLEMENTATIONNAME_NEWMENUCONTROLLER
68 DEFINE_INIT_SERVICE ( NewMenuController, {} )
70 void NewMenuController::setMenuImages( PopupMenu* pPopupMenu, bool bSetImages )
72 sal_uInt16 nItemCount = pPopupMenu->GetItemCount();
73 Image aImage;
74 Reference< XFrame > xFrame( m_xFrame );
76 for ( sal_uInt16 i = 0; i < nItemCount; i++ )
78 sal_uInt16 nItemId = pPopupMenu->GetItemId( sal::static_int_cast<sal_uInt16>( i ));
79 if ( nItemId != 0 )
81 if ( bSetImages )
83 bool bImageSet( false );
84 OUString aImageId;
86 sal_uIntPtr nAttributePtr = pPopupMenu->GetUserValue(sal::static_int_cast<sal_uInt16>(i));
87 MenuAttributes* pAttributes = reinterpret_cast<MenuAttributes *>(nAttributePtr);
88 if (pAttributes)
89 aImageId = pAttributes->aImageId;
91 if ( !aImageId.isEmpty() )
93 aImage = GetImageFromURL( xFrame, aImageId, false );
94 if ( !!aImage )
96 bImageSet = true;
97 pPopupMenu->SetItemImage( nItemId, aImage );
101 if ( !bImageSet )
103 OUString aCmd( pPopupMenu->GetItemCommand( nItemId ) );
104 if ( !aCmd.isEmpty() )
105 aImage = GetImageFromURL( xFrame, aCmd, false );
107 if ( !!aImage )
108 pPopupMenu->SetItemImage( nItemId, aImage );
111 else
112 pPopupMenu->SetItemImage( nItemId, aImage );
117 void NewMenuController::determineAndSetNewDocAccel( PopupMenu* pPopupMenu, const vcl::KeyCode& rKeyCode )
119 sal_uInt16 nCount( pPopupMenu->GetItemCount() );
120 sal_uInt16 nId( 0 );
121 bool bFound( false );
122 OUString aCommand;
124 if ( !m_aEmptyDocURL.isEmpty() )
126 // Search for the empty document URL
128 for ( sal_uInt32 i = 0; i < sal_uInt32( nCount ); i++ )
130 nId = pPopupMenu->GetItemId( sal_uInt16( i ));
131 if ( nId != 0 && pPopupMenu->GetItemType( nId ) != MenuItemType::SEPARATOR )
133 aCommand = pPopupMenu->GetItemCommand( nId );
134 if ( aCommand.startsWith( m_aEmptyDocURL ) )
136 pPopupMenu->SetAccelKey( nId, rKeyCode );
137 bFound = true;
138 break;
144 if ( !bFound )
146 // Search for the default module name
147 OUString aDefaultModuleName( SvtModuleOptions().GetDefaultModuleName() );
148 if ( !aDefaultModuleName.isEmpty() )
150 for ( sal_uInt32 i = 0; i < sal_uInt32( nCount ); i++ )
152 nId = pPopupMenu->GetItemId( sal_uInt16( i ));
153 if ( nId != 0 && pPopupMenu->GetItemType( nId ) != MenuItemType::SEPARATOR )
155 aCommand = pPopupMenu->GetItemCommand( nId );
156 if ( aCommand.indexOf( aDefaultModuleName ) >= 0 )
158 pPopupMenu->SetAccelKey( nId, rKeyCode );
159 break;
167 void NewMenuController::setAccelerators( PopupMenu* pPopupMenu )
169 if ( m_bModuleIdentified )
171 Reference< XAcceleratorConfiguration > xDocAccelCfg( m_xDocAcceleratorManager );
172 Reference< XAcceleratorConfiguration > xModuleAccelCfg( m_xModuleAcceleratorManager );
173 Reference< XAcceleratorConfiguration > xGlobalAccelCfg( m_xGlobalAcceleratorManager );
175 if ( !m_bAcceleratorCfg )
177 // Retrieve references on demand
178 m_bAcceleratorCfg = true;
179 if ( !xDocAccelCfg.is() )
181 Reference< XController > xController = m_xFrame->getController();
182 Reference< XModel > xModel;
183 if ( xController.is() )
185 xModel = xController->getModel();
186 if ( xModel.is() )
188 Reference< XUIConfigurationManagerSupplier > xSupplier( xModel, UNO_QUERY );
189 if ( xSupplier.is() )
191 Reference< XUIConfigurationManager > xDocUICfgMgr( xSupplier->getUIConfigurationManager(), UNO_QUERY );
192 if ( xDocUICfgMgr.is() )
194 xDocAccelCfg = xDocUICfgMgr->getShortCutManager();
195 m_xDocAcceleratorManager = xDocAccelCfg;
202 if ( !xModuleAccelCfg.is() )
204 Reference< XModuleUIConfigurationManagerSupplier > xModuleCfgMgrSupplier =
205 theModuleUIConfigurationManagerSupplier::get( m_xContext );
206 Reference< XUIConfigurationManager > xUICfgMgr = xModuleCfgMgrSupplier->getUIConfigurationManager( m_aModuleIdentifier );
207 if ( xUICfgMgr.is() )
209 xModuleAccelCfg = xUICfgMgr->getShortCutManager();
210 m_xModuleAcceleratorManager = xModuleAccelCfg;
214 if ( !xGlobalAccelCfg.is() )
216 xGlobalAccelCfg = GlobalAcceleratorConfiguration::create( m_xContext );
217 m_xGlobalAcceleratorManager = xGlobalAccelCfg;
221 vcl::KeyCode aEmptyKeyCode;
222 sal_uInt32 nItemCount( pPopupMenu->GetItemCount() );
223 std::vector< vcl::KeyCode > aMenuShortCuts;
224 std::vector< OUString > aCmds;
225 std::vector< sal_uInt32 > aIds;
226 for ( sal_uInt32 i = 0; i < nItemCount; i++ )
228 sal_uInt16 nId( pPopupMenu->GetItemId( sal_uInt16( i )));
229 if ( nId && ( pPopupMenu->GetItemType( nId ) != MenuItemType::SEPARATOR ))
231 aIds.push_back( nId );
232 aMenuShortCuts.push_back( aEmptyKeyCode );
233 aCmds.push_back( pPopupMenu->GetItemCommand( nId ));
237 sal_uInt32 nSeqCount( aIds.size() );
239 if ( m_bNewMenu )
240 nSeqCount+=1;
242 Sequence< OUString > aSeq( nSeqCount );
244 // Add a special command for our "New" menu.
245 if ( m_bNewMenu )
247 aSeq[nSeqCount-1] = m_aCommandURL;
248 aMenuShortCuts.push_back( aEmptyKeyCode );
251 const sal_uInt32 nCount = aCmds.size();
252 for ( sal_uInt32 i = 0; i < nCount; i++ )
253 aSeq[i] = aCmds[i];
255 if ( m_xGlobalAcceleratorManager.is() )
256 retrieveShortcutsFromConfiguration( xGlobalAccelCfg, aSeq, aMenuShortCuts );
257 if ( m_xModuleAcceleratorManager.is() )
258 retrieveShortcutsFromConfiguration( xModuleAccelCfg, aSeq, aMenuShortCuts );
259 if ( m_xDocAcceleratorManager.is() )
260 retrieveShortcutsFromConfiguration( xGlobalAccelCfg, aSeq, aMenuShortCuts );
262 const sal_uInt32 nCount2 = aIds.size();
263 for ( sal_uInt32 i = 0; i < nCount2; i++ )
264 pPopupMenu->SetAccelKey( sal_uInt16( aIds[i] ), aMenuShortCuts[i] );
266 // Special handling for "New" menu short-cut should be set at the
267 // document which will be opened using it.
268 if ( m_bNewMenu )
270 if ( aMenuShortCuts[nSeqCount-1] != aEmptyKeyCode )
271 determineAndSetNewDocAccel( pPopupMenu, aMenuShortCuts[nSeqCount-1] );
276 void NewMenuController::retrieveShortcutsFromConfiguration(
277 const Reference< XAcceleratorConfiguration >& rAccelCfg,
278 const Sequence< OUString >& rCommands,
279 std::vector< vcl::KeyCode >& aMenuShortCuts )
281 if ( rAccelCfg.is() )
285 com::sun::star::awt::KeyEvent aKeyEvent;
286 Sequence< Any > aSeqKeyCode = rAccelCfg->getPreferredKeyEventsForCommandList( rCommands );
287 for ( sal_Int32 i = 0; i < aSeqKeyCode.getLength(); i++ )
289 if ( aSeqKeyCode[i] >>= aKeyEvent )
290 aMenuShortCuts[i] = svt::AcceleratorExecute::st_AWTKey2VCLKey( aKeyEvent );
293 catch ( const IllegalArgumentException& )
299 NewMenuController::NewMenuController( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& xContext ) :
300 svt::PopupMenuControllerBase( xContext ),
301 m_bShowImages( true ),
302 m_bNewMenu( false ),
303 m_bModuleIdentified( false ),
304 m_bAcceleratorCfg( false ),
305 m_aTargetFrame( "_default" ),
306 m_xContext( xContext )
310 NewMenuController::~NewMenuController()
314 // private function
315 void NewMenuController::fillPopupMenu( Reference< css::awt::XPopupMenu >& rPopupMenu )
317 VCLXPopupMenu* pPopupMenu = static_cast<VCLXPopupMenu *>(VCLXMenu::GetImplementation( rPopupMenu ));
318 PopupMenu* pVCLPopupMenu = 0;
320 SolarMutexGuard aSolarMutexGuard;
322 resetPopupMenu( rPopupMenu );
323 if ( pPopupMenu )
324 pVCLPopupMenu = static_cast<PopupMenu *>(pPopupMenu->GetMenu());
326 if ( pVCLPopupMenu )
328 MenuConfiguration aMenuCfg( m_xContext );
329 boost::scoped_ptr<BmkMenu> pSubMenu;
331 if ( m_bNewMenu )
332 pSubMenu.reset(static_cast<BmkMenu*>(aMenuCfg.CreateBookmarkMenu( m_xFrame, BOOKMARK_NEWMENU )));
333 else
334 pSubMenu.reset(static_cast<BmkMenu*>(aMenuCfg.CreateBookmarkMenu( m_xFrame, BOOKMARK_WIZARDMENU )));
336 // copy entries as we have to use the provided popup menu
337 *pVCLPopupMenu = *pSubMenu;
339 Image aImage;
341 // retrieve additional parameters from bookmark menu and
342 // store it in a unordered_map.
343 for ( sal_uInt16 i = 0; i < pSubMenu->GetItemCount(); i++ )
345 sal_uInt16 nItemId = pSubMenu->GetItemId( sal::static_int_cast<sal_uInt16>( i ) );
346 if (( nItemId != 0 ) &&
347 ( pSubMenu->GetItemType( nItemId ) != MenuItemType::SEPARATOR ))
349 sal_uIntPtr nAttributePtr = pSubMenu->GetUserValue(nItemId);
350 if (nAttributePtr)
352 MenuAttributes* pAttributes = reinterpret_cast<MenuAttributes *>(nAttributePtr);
353 pAttributes->acquire();
354 pVCLPopupMenu->SetUserValue(nItemId, nAttributePtr, MenuAttributes::ReleaseAttribute);
359 if ( m_bShowImages )
360 setMenuImages( pVCLPopupMenu, m_bShowImages );
364 // XEventListener
365 void SAL_CALL NewMenuController::disposing( const EventObject& ) throw ( RuntimeException, std::exception )
367 Reference< css::awt::XMenuListener > xHolder(( OWeakObject *)this, UNO_QUERY );
369 osl::MutexGuard aLock( m_aMutex );
370 m_xFrame.clear();
371 m_xDispatch.clear();
372 m_xContext.clear();
374 if ( m_xPopupMenu.is() )
375 m_xPopupMenu->removeMenuListener( Reference< css::awt::XMenuListener >(( OWeakObject *)this, UNO_QUERY ));
376 m_xPopupMenu.clear();
379 // XStatusListener
380 void SAL_CALL NewMenuController::statusChanged( const FeatureStateEvent& ) throw ( RuntimeException, std::exception )
384 // XMenuListener
385 void SAL_CALL NewMenuController::itemSelected( const css::awt::MenuEvent& rEvent ) throw (RuntimeException, std::exception)
387 Reference< css::awt::XPopupMenu > xPopupMenu;
388 Reference< XDispatch > xDispatch;
389 Reference< XDispatchProvider > xDispatchProvider;
390 Reference< XComponentContext > xContext;
391 Reference< XURLTransformer > xURLTransformer;
393 osl::ClearableMutexGuard aLock( m_aMutex );
394 xPopupMenu = m_xPopupMenu;
395 xDispatchProvider = Reference< XDispatchProvider >( m_xFrame, UNO_QUERY );
396 xContext = m_xContext;
397 xURLTransformer = m_xURLTransformer;
398 aLock.clear();
400 css::util::URL aTargetURL;
401 Sequence< PropertyValue > aArgsList( 1 );
403 if ( xPopupMenu.is() && xDispatchProvider.is() )
405 VCLXPopupMenu* pPopupMenu = static_cast<VCLXPopupMenu *>(VCLXPopupMenu::GetImplementation( xPopupMenu ));
406 if ( pPopupMenu )
408 OUString aTargetFrame( m_aTargetFrame );
411 SolarMutexGuard aSolarMutexGuard;
412 PopupMenu* pVCLPopupMenu = static_cast<PopupMenu *>(pPopupMenu->GetMenu());
413 aTargetURL.Complete = pVCLPopupMenu->GetItemCommand(rEvent.MenuId);
414 sal_uIntPtr nAttributePtr = pVCLPopupMenu->GetUserValue(rEvent.MenuId);
415 MenuAttributes* pAttributes = reinterpret_cast<MenuAttributes *>(nAttributePtr);
416 if (pAttributes)
417 aTargetFrame = pAttributes->aTargetFrame;
420 xURLTransformer->parseStrict( aTargetURL );
422 aArgsList[0].Name = "Referer";
423 aArgsList[0].Value = makeAny( OUString( "private:user" ));
425 xDispatch = xDispatchProvider->queryDispatch( aTargetURL, aTargetFrame, 0 );
429 if ( xDispatch.is() )
431 // Call dispatch asychronously as we can be destroyed while dispatch is
432 // executed. VCL is not able to survive this as it wants to call listeners
433 // after select!!!
434 NewDocument* pNewDocument = new NewDocument;
435 pNewDocument->xDispatch = xDispatch;
436 pNewDocument->aTargetURL = aTargetURL;
437 pNewDocument->aArgSeq = aArgsList;
438 Application::PostUserEvent( LINK(0, NewMenuController, ExecuteHdl_Impl), pNewDocument );
442 void SAL_CALL NewMenuController::itemActivated( const css::awt::MenuEvent& ) throw (RuntimeException, std::exception)
444 SolarMutexGuard aSolarMutexGuard;
445 if ( m_xFrame.is() && m_xPopupMenu.is() )
447 VCLXPopupMenu* pPopupMenu = static_cast<VCLXPopupMenu *>(VCLXPopupMenu::GetImplementation( m_xPopupMenu ));
448 if ( pPopupMenu )
450 const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
451 bool bShowImages( rSettings.GetUseImagesInMenus() );
453 PopupMenu* pVCLPopupMenu = static_cast<PopupMenu *>(pPopupMenu->GetMenu());
455 if ( m_bShowImages != bShowImages )
457 m_bShowImages = bShowImages;
458 setMenuImages( pVCLPopupMenu, m_bShowImages );
461 setAccelerators( pVCLPopupMenu );
466 // XPopupMenuController
467 void NewMenuController::impl_setPopupMenu()
470 if ( m_xPopupMenu.is() )
471 fillPopupMenu( m_xPopupMenu );
473 // Identify module that we are attach to. It's our context that we need to know.
474 Reference< XModuleManager2 > xModuleManager = ModuleManager::create( m_xContext );
477 m_aModuleIdentifier = xModuleManager->identify( m_xFrame );
478 m_bModuleIdentified = true;
480 if ( !m_aModuleIdentifier.isEmpty() )
482 Sequence< PropertyValue > aSeq;
484 if ( xModuleManager->getByName( m_aModuleIdentifier ) >>= aSeq )
486 for ( sal_Int32 y = 0; y < aSeq.getLength(); y++ )
488 if ( aSeq[y].Name == "ooSetupFactoryEmptyDocumentURL" )
490 aSeq[y].Value >>= m_aEmptyDocURL;
491 break;
497 catch ( const RuntimeException& )
499 throw;
501 catch ( const Exception& )
506 // XInitialization
507 void SAL_CALL NewMenuController::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException, std::exception )
509 osl::MutexGuard aLock( m_aMutex );
511 bool bInitalized( m_bInitialized );
512 if ( !bInitalized )
514 svt::PopupMenuControllerBase::initialize( aArguments );
516 if ( m_bInitialized )
518 const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
520 m_bShowImages = rSettings.GetUseImagesInMenus();
521 m_bNewMenu = m_aCommandURL == ".uno:AddDirect";
526 IMPL_STATIC_LINK( NewMenuController, ExecuteHdl_Impl, NewDocument*, pNewDocument )
528 /* i62706: Don't catch all exceptions. We hide all problems here and are not able
529 to handle them on higher levels.
533 // Asynchronous execution as this can lead to our own destruction!
534 // Framework can recycle our current frame and the layout manager disposes all user interface
535 // elements if a component gets detached from its frame!
536 pNewDocument->xDispatch->dispatch( pNewDocument->aTargetURL, pNewDocument->aArgSeq );
537 delete pNewDocument;
538 return 0;
543 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */