GPU-Calc: remove Alloc_Host_Ptr for clmem of NAN vector
[LibreOffice.git] / svtools / source / uno / contextmenuhelper.cxx
blob7c8abc6353018849fde29bdeaced75fbe28fb69c
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 .
21 #include <svtools/contextmenuhelper.hxx>
22 #include <svtools/menuoptions.hxx>
23 #include <svtools/miscopt.hxx>
25 #include <com/sun/star/frame/XDispatch.hpp>
26 #include <com/sun/star/frame/XDispatchProvider.hpp>
27 #include <com/sun/star/frame/ModuleManager.hpp>
28 #include <com/sun/star/frame/XStatusListener.hpp>
29 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
30 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
31 #include <com/sun/star/ui/XUIConfigurationManager.hpp>
32 #include <com/sun/star/ui/ModuleUIConfigurationManagerSupplier.hpp>
33 #include <com/sun/star/ui/ImageType.hpp>
34 #include <com/sun/star/frame/UICommandDescription.hpp>
35 #include <com/sun/star/util/URLTransformer.hpp>
36 #include <com/sun/star/beans/PropertyValue.hpp>
38 #include <osl/conditn.hxx>
39 #include <cppuhelper/weak.hxx>
40 #include <comphelper/processfactory.hxx>
41 #include <osl/mutex.hxx>
42 #include <vcl/svapp.hxx>
43 #include <vcl/image.hxx>
44 #include <toolkit/helper/vclunohelper.hxx>
45 #include <toolkit/awt/vclxwindow.hxx>
46 #include <toolkit/awt/vclxmenu.hxx>
48 using namespace ::com::sun::star;
50 namespace svt
53 // internal helper class to retrieve status updates
54 class StateEventHelper : public ::com::sun::star::frame::XStatusListener,
55 public ::cppu::OWeakObject
57 public:
58 StateEventHelper( const uno::Reference< frame::XDispatchProvider >& xDispatchProvider,
59 const uno::Reference< util::XURLTransformer >& xURLTransformer,
60 const OUString& aCommandURL );
61 virtual ~StateEventHelper();
63 bool isCommandEnabled();
65 // XInterface
66 virtual uno::Any SAL_CALL queryInterface( const uno::Type& aType ) throw ( uno::RuntimeException);
67 virtual void SAL_CALL acquire() throw ();
68 virtual void SAL_CALL release() throw ();
70 // XEventListener
71 virtual void SAL_CALL disposing(const lang::EventObject& Source) throw( uno::RuntimeException );
73 // XStatusListener
74 virtual void SAL_CALL statusChanged(const frame::FeatureStateEvent& Event) throw( uno::RuntimeException );
76 private:
77 StateEventHelper();
78 StateEventHelper( const StateEventHelper& );
79 StateEventHelper& operator=( const StateEventHelper& );
81 bool m_bCurrentCommandEnabled;
82 OUString m_aCommandURL;
83 uno::Reference< frame::XDispatchProvider > m_xDispatchProvider;
84 uno::Reference< util::XURLTransformer > m_xURLTransformer;
85 osl::Condition m_aCondition;
88 StateEventHelper::StateEventHelper(
89 const uno::Reference< frame::XDispatchProvider >& xDispatchProvider,
90 const uno::Reference< util::XURLTransformer >& xURLTransformer,
91 const OUString& rCommandURL ) :
92 m_bCurrentCommandEnabled( true ),
93 m_aCommandURL( rCommandURL ),
94 m_xDispatchProvider( xDispatchProvider ),
95 m_xURLTransformer( xURLTransformer )
97 m_aCondition.reset();
100 StateEventHelper::~StateEventHelper()
103 uno::Any SAL_CALL StateEventHelper::queryInterface(
104 const uno::Type& aType )
105 throw ( uno::RuntimeException )
107 uno::Any a = ::cppu::queryInterface(
108 aType,
109 (static_cast< XStatusListener* >(this)));
111 if( a.hasValue() )
112 return a;
114 return ::cppu::OWeakObject::queryInterface( aType );
117 void SAL_CALL StateEventHelper::acquire()
118 throw ()
120 ::cppu::OWeakObject::acquire();
123 void SAL_CALL StateEventHelper::release()
124 throw ()
126 ::cppu::OWeakObject::release();
129 void SAL_CALL StateEventHelper::disposing(
130 const lang::EventObject& )
131 throw ( uno::RuntimeException )
133 SolarMutexGuard aSolarGuard;
134 m_xDispatchProvider.clear();
135 m_xURLTransformer.clear();
136 m_aCondition.set();
139 void SAL_CALL StateEventHelper::statusChanged(
140 const frame::FeatureStateEvent& Event )
141 throw ( uno::RuntimeException )
143 SolarMutexGuard aSolarGuard;
144 m_bCurrentCommandEnabled = Event.IsEnabled;
145 m_aCondition.set();
148 bool StateEventHelper::isCommandEnabled()
150 // Be sure that we cannot die during condition wait
151 uno::Reference< frame::XStatusListener > xSelf(
152 (static_cast< frame::XStatusListener* >(this)));
154 uno::Reference< frame::XDispatch > xDispatch;
155 util::URL aTargetURL;
157 SolarMutexGuard aSolarGuard;
158 if ( m_xDispatchProvider.is() && m_xURLTransformer.is() )
160 OUString aSelf( "_self" );
162 aTargetURL.Complete = m_aCommandURL;
163 m_xURLTransformer->parseStrict( aTargetURL );
167 xDispatch = m_xDispatchProvider->queryDispatch( aTargetURL, aSelf, 0 );
169 catch ( uno::RuntimeException& )
171 throw;
173 catch ( uno::Exception& )
179 bool bResult( false );
180 if ( xDispatch.is() )
184 // add/remove ourself to retrieve status by callback
185 xDispatch->addStatusListener( xSelf, aTargetURL );
186 xDispatch->removeStatusListener( xSelf, aTargetURL );
188 // wait for anwser
189 m_aCondition.wait();
191 catch ( uno::RuntimeException& )
193 throw;
195 catch ( uno::Exception& )
199 SolarMutexGuard aSolarGuard;
200 bResult = m_bCurrentCommandEnabled;
203 return bResult;
206 /*************************************************************************/
208 struct ExecuteInfo
210 uno::Reference< frame::XDispatch > xDispatch;
211 util::URL aTargetURL;
212 uno::Sequence< beans::PropertyValue > aArgs;
215 static const PopupMenu* lcl_FindPopupFromItemId( const PopupMenu* pPopupMenu, sal_uInt16 nItemId )
217 if ( pPopupMenu )
219 sal_uInt16 nCount = pPopupMenu->GetItemCount();
220 for ( sal_uInt16 i = 0; i < nCount; i++ )
222 sal_uInt16 nId = pPopupMenu->GetItemId( i );
223 if ( nId == nItemId )
224 return pPopupMenu;
225 else
227 const PopupMenu* pResult( 0 );
229 const PopupMenu* pSubPopup = pPopupMenu->GetPopupMenu( i );
230 if ( pPopupMenu )
231 pResult = lcl_FindPopupFromItemId( pSubPopup, nItemId );
232 if ( pResult != 0 )
233 return pResult;
238 return NULL;
241 static OUString lcl_GetItemCommandRecursive( const PopupMenu* pPopupMenu, sal_uInt16 nItemId )
243 const PopupMenu* pPopup = lcl_FindPopupFromItemId( pPopupMenu, nItemId );
244 if ( pPopup )
245 return pPopup->GetItemCommand( nItemId );
246 else
247 return OUString();
250 /*************************************************************************/
252 ContextMenuHelper::ContextMenuHelper(
253 const uno::Reference< frame::XFrame >& xFrame,
254 bool bAutoRefresh ) :
255 m_xWeakFrame( xFrame ),
256 m_aSelf( "_self" ),
257 m_bAutoRefresh( bAutoRefresh ),
258 m_bUICfgMgrAssociated( false )
262 ContextMenuHelper::~ContextMenuHelper()
266 void
267 ContextMenuHelper::completeAndExecute(
268 const Point& aPos,
269 PopupMenu& rPopupMenu )
271 SolarMutexGuard aSolarGuard;
273 associateUIConfigurationManagers();
274 completeMenuProperties( &rPopupMenu );
275 executePopupMenu( aPos, &rPopupMenu );
276 resetAssociations();
279 void
280 ContextMenuHelper::completeAndExecute(
281 const Point& aPos,
282 const uno::Reference< awt::XPopupMenu >& xPopupMenu )
284 SolarMutexGuard aSolarGuard;
286 VCLXMenu* pXMenu = VCLXMenu::GetImplementation( xPopupMenu );
287 if ( pXMenu )
289 PopupMenu* pPopupMenu = dynamic_cast< PopupMenu* >( pXMenu->GetMenu() );
290 // as dynamic_cast can return zero check pointer
291 if ( pPopupMenu )
293 associateUIConfigurationManagers();
294 completeMenuProperties( pPopupMenu );
295 executePopupMenu( aPos, pPopupMenu );
296 resetAssociations();
301 // private member
303 void
304 ContextMenuHelper::executePopupMenu(
305 const Point& rPos,
306 PopupMenu* pMenu )
308 if ( pMenu )
310 uno::Reference< frame::XFrame > xFrame( m_xWeakFrame );
311 if ( xFrame.is() )
313 uno::Reference< awt::XWindow > xWindow( xFrame->getContainerWindow() );
314 if ( xWindow.is() )
316 Window* pParent = VCLUnoHelper::GetWindow( xWindow );
317 sal_uInt16 nResult = pMenu->Execute( pParent, rPos );
319 if ( nResult > 0 )
321 OUString aCommand = lcl_GetItemCommandRecursive( pMenu, nResult );
322 if ( !aCommand.isEmpty() )
323 dispatchCommand( xFrame, aCommand );
330 bool
331 ContextMenuHelper::dispatchCommand(
332 const uno::Reference< ::frame::XFrame >& rFrame,
333 const OUString& aCommandURL )
335 if ( !m_xURLTransformer.is() )
337 m_xURLTransformer = util::URLTransformer::create( ::comphelper::getProcessComponentContext() );
340 util::URL aTargetURL;
341 aTargetURL.Complete = aCommandURL;
342 m_xURLTransformer->parseStrict( aTargetURL );
344 uno::Reference< frame::XDispatch > xDispatch;
345 uno::Reference< frame::XDispatchProvider > xDispatchProvider(
346 rFrame, uno::UNO_QUERY );
347 if ( xDispatchProvider.is() )
351 xDispatch = xDispatchProvider->queryDispatch( aTargetURL, m_aSelf, 0 );
353 catch ( uno::RuntimeException& )
355 throw;
357 catch ( uno::Exception& )
362 if ( xDispatch.is() )
364 ExecuteInfo* pExecuteInfo = new ExecuteInfo;
365 pExecuteInfo->xDispatch = xDispatch;
366 pExecuteInfo->aTargetURL = aTargetURL;
367 pExecuteInfo->aArgs = m_aDefaultArgs;
369 Application::PostUserEvent( STATIC_LINK(0, ContextMenuHelper , ExecuteHdl_Impl), pExecuteInfo );
370 return true;
373 return false;
376 // retrieves and stores references to our user-interface
377 // configuration managers, like image manager, ui command
378 // description manager.
379 bool
380 ContextMenuHelper::associateUIConfigurationManagers()
382 uno::Reference< frame::XFrame > xFrame( m_xWeakFrame );
383 if ( !m_bUICfgMgrAssociated && xFrame.is() )
385 // clear current state
386 m_xDocImageMgr.clear();
387 m_xModuleImageMgr.clear();
388 m_xUICommandLabels.clear();
392 uno::Reference < frame::XController > xController;
393 uno::Reference < frame::XModel > xModel;
394 xController = xFrame->getController();
395 if ( xController.is() )
396 xModel = xController->getModel();
398 if ( xModel.is() )
400 // retrieve document image manager form model
401 uno::Reference< ui::XUIConfigurationManagerSupplier > xSupplier( xModel, uno::UNO_QUERY );
402 if ( xSupplier.is() )
404 uno::Reference< ui::XUIConfigurationManager > xDocUICfgMgr(
405 xSupplier->getUIConfigurationManager(), uno::UNO_QUERY );
406 m_xDocImageMgr = uno::Reference< ui::XImageManager >(
407 xDocUICfgMgr->getImageManager(), uno::UNO_QUERY );
411 uno::Reference< frame::XModuleManager2 > xModuleManager(
412 frame::ModuleManager::create( ::comphelper::getProcessComponentContext() ) );
414 uno::Reference< ui::XImageManager > xModuleImageManager;
415 OUString aModuleId;
416 // retrieve module image manager
417 aModuleId = xModuleManager->identify( xFrame );
419 uno::Reference< ui::XModuleUIConfigurationManagerSupplier > xModuleCfgMgrSupplier(
420 ui::ModuleUIConfigurationManagerSupplier::create(
421 ::comphelper::getProcessComponentContext() ) );
422 uno::Reference< ui::XUIConfigurationManager > xUICfgMgr(
423 xModuleCfgMgrSupplier->getUIConfigurationManager( aModuleId ));
424 if ( xUICfgMgr.is() )
426 m_xModuleImageMgr = uno::Reference< ui::XImageManager >(
427 xUICfgMgr->getImageManager(), uno::UNO_QUERY );
430 uno::Reference< container::XNameAccess > xNameAccess(
431 frame::UICommandDescription::create(
432 ::comphelper::getProcessComponentContext()),
433 uno::UNO_QUERY_THROW );
436 uno::Any a = xNameAccess->getByName( aModuleId );
437 a >>= m_xUICommandLabels;
439 catch ( container::NoSuchElementException& )
443 catch ( uno::RuntimeException& )
445 throw;
447 catch ( uno::Exception& )
449 m_bUICfgMgrAssociated = true;
450 return false;
452 m_bUICfgMgrAssociated = true;
455 return true;
458 Image
459 ContextMenuHelper::getImageFromCommandURL( const OUString& aCmdURL ) const
461 Image aImage;
462 sal_Int16 nImageType( ui::ImageType::COLOR_NORMAL|
463 ui::ImageType::SIZE_DEFAULT );
465 uno::Sequence< uno::Reference< graphic::XGraphic > > aGraphicSeq;
466 uno::Sequence< OUString > aImageCmdSeq( 1 );
467 aImageCmdSeq[0] = aCmdURL;
469 if ( m_xDocImageMgr.is() )
473 aGraphicSeq = m_xDocImageMgr->getImages( nImageType, aImageCmdSeq );
474 uno::Reference< graphic::XGraphic > xGraphic = aGraphicSeq[0];
475 aImage = Image( xGraphic );
477 if ( !!aImage )
478 return aImage;
480 catch ( uno::RuntimeException& )
482 throw;
484 catch ( uno::Exception& )
489 if ( m_xModuleImageMgr.is() )
493 aGraphicSeq = m_xModuleImageMgr->getImages( nImageType, aImageCmdSeq );
494 uno::Reference< ::com::sun::star::graphic::XGraphic > xGraphic = aGraphicSeq[0];
495 aImage = Image( xGraphic );
497 if ( !!aImage )
498 return aImage;
500 catch ( uno::RuntimeException& )
502 throw;
504 catch ( uno::Exception& )
509 return aImage;
512 OUString
513 ContextMenuHelper::getLabelFromCommandURL(
514 const OUString& aCmdURL ) const
516 OUString aLabel;
518 if ( m_xUICommandLabels.is() )
522 if ( !aCmdURL.isEmpty() )
524 OUString aStr;
525 uno::Sequence< beans::PropertyValue > aPropSeq;
526 uno::Any a( m_xUICommandLabels->getByName( aCmdURL ));
527 if ( a >>= aPropSeq )
529 for ( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ )
531 if ( aPropSeq[i].Name == "Label" )
533 aPropSeq[i].Value >>= aStr;
534 break;
538 aLabel = aStr;
541 catch ( uno::RuntimeException& )
544 catch ( uno::Exception& )
549 return aLabel;
552 void
553 ContextMenuHelper::completeMenuProperties(
554 Menu* pMenu )
556 // Retrieve some settings necessary to display complete context
557 // menu correctly.
558 const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
559 bool bShowMenuImages( rSettings.GetUseImagesInMenus() );
561 if ( pMenu )
563 uno::Reference< frame::XFrame > xFrame( m_xWeakFrame );
564 uno::Reference< frame::XDispatchProvider > xDispatchProvider( xFrame, uno::UNO_QUERY );
566 if ( !m_xURLTransformer.is() )
568 m_xURLTransformer = util::URLTransformer::create( ::comphelper::getProcessComponentContext() );
571 for ( sal_uInt16 nPos = 0; nPos < pMenu->GetItemCount(); nPos++ )
573 sal_uInt16 nId = pMenu->GetItemId( nPos );
574 PopupMenu* pPopupMenu = pMenu->GetPopupMenu( nId );
575 if ( pPopupMenu )
576 completeMenuProperties( pPopupMenu );
577 if ( pMenu->GetItemType( nPos ) != MENUITEM_SEPARATOR )
579 OUString aCmdURL( pMenu->GetItemCommand( nId ));
581 if ( bShowMenuImages )
583 Image aImage;
584 if ( !aCmdURL.isEmpty() )
585 aImage = getImageFromCommandURL( aCmdURL );
586 pMenu->SetItemImage( nId, aImage );
588 else
589 pMenu->SetItemImage( nId, Image() );
591 if (pMenu->GetItemText(nId).isEmpty())
593 OUString aLabel( getLabelFromCommandURL( aCmdURL ));
594 pMenu->SetItemText( nId, aLabel );
597 // Use helper to retrieve state of the command URL
598 StateEventHelper* pHelper = new StateEventHelper(
599 xDispatchProvider,
600 m_xURLTransformer,
601 aCmdURL );
603 uno::Reference< frame::XStatusListener > xHelper( pHelper );
604 pMenu->EnableItem( nId, pHelper->isCommandEnabled() );
611 IMPL_STATIC_LINK_NOINSTANCE( ContextMenuHelper, ExecuteHdl_Impl, ExecuteInfo*, pExecuteInfo )
613 // Release solar mutex to prevent deadlocks with clipboard thread
614 const sal_uInt32 nRef = Application::ReleaseSolarMutex();
617 // Asynchronous execution as this can lead to our own destruction while we are
618 // on the stack. Stack unwinding would access the destroyed context menu.
619 pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs );
621 catch ( uno::Exception& )
625 // Acquire solar mutex again
626 Application::AcquireSolarMutex( nRef );
627 delete pExecuteInfo;
628 return 0;
631 } // namespace svt
633 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */