fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / svtools / source / uno / popupmenucontrollerbase.cxx
blobc369bf8a2814b6a16b771223c4bbfea5bc3105f5
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 "svtools/popupmenucontrollerbase.hxx"
22 #include <com/sun/star/awt/XDevice.hpp>
23 #include <com/sun/star/beans/PropertyValue.hpp>
24 #include <com/sun/star/awt/MenuItemStyle.hpp>
25 #include <com/sun/star/frame/XDispatchProvider.hpp>
26 #include <com/sun/star/lang/DisposedException.hpp>
27 #include <com/sun/star/awt/XMenuExtended.hpp>
28 #include <com/sun/star/util/URLTransformer.hpp>
30 #include <vcl/menu.hxx>
31 #include <vcl/svapp.hxx>
32 #include <rtl/ustrbuf.hxx>
33 #include <rtl/logfile.hxx>
34 #include <osl/mutex.hxx>
35 #include <comphelper/processfactory.hxx>
37 //_________________________________________________________________________________________________________________
38 // Defines
39 //_________________________________________________________________________________________________________________
43 using namespace com::sun::star;
44 using namespace com::sun::star::uno;
45 using namespace com::sun::star::lang;
46 using namespace com::sun::star::frame;
47 using namespace com::sun::star::beans;
48 using namespace com::sun::star::util;
50 namespace svt
53 struct PopupMenuControllerBaseDispatchInfo
55 Reference< XDispatch > mxDispatch;
56 const URL maURL;
57 const Sequence< PropertyValue > maArgs;
59 PopupMenuControllerBaseDispatchInfo( const Reference< XDispatch >& xDispatch, const URL& rURL, const Sequence< PropertyValue >& rArgs )
60 : mxDispatch( xDispatch ), maURL( rURL ), maArgs( rArgs ) {}
63 PopupMenuControllerBase::PopupMenuControllerBase( const Reference< XMultiServiceFactory >& xServiceManager ) :
64 ::comphelper::OBaseMutex(),
65 PopupMenuControllerBaseType(m_aMutex),
66 m_bInitialized( false ),
67 m_xServiceManager( xServiceManager )
69 if ( m_xServiceManager.is() )
70 m_xURLTransformer.set( util::URLTransformer::create( ::comphelper::getComponentContext(m_xServiceManager) ) );
73 PopupMenuControllerBase::~PopupMenuControllerBase()
77 // protected function
78 void PopupMenuControllerBase::throwIfDisposed() throw ( RuntimeException )
80 if (rBHelper.bDisposed || rBHelper.bInDispose)
81 throw com::sun::star::lang::DisposedException();
84 // protected function
85 void PopupMenuControllerBase::resetPopupMenu( com::sun::star::uno::Reference< com::sun::star::awt::XPopupMenu >& rPopupMenu )
87 if ( rPopupMenu.is() && rPopupMenu->getItemCount() > 0 )
89 VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( rPopupMenu );
90 if ( pPopupMenu )
92 SolarMutexGuard aSolarMutexGuard;
94 PopupMenu* pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu();
95 pVCLPopupMenu->Clear();
100 void SAL_CALL PopupMenuControllerBase::disposing()
102 // Reset our members and set disposed flag
103 osl::MutexGuard aLock( m_aMutex );
104 m_xFrame.clear();
105 m_xDispatch.clear();
106 m_xPopupMenu.clear();
107 m_xServiceManager.clear();
110 // XServiceInfo
112 sal_Bool SAL_CALL PopupMenuControllerBase::supportsService( const OUString& ServiceName ) throw (RuntimeException)
114 const Sequence< OUString > aSNL( getSupportedServiceNames() );
115 const OUString * pArray = aSNL.getConstArray();
117 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
118 if( pArray[i] == ServiceName )
119 return true;
121 return false;
124 // XEventListener
125 void SAL_CALL PopupMenuControllerBase::disposing( const EventObject& ) throw ( RuntimeException )
127 osl::MutexGuard aLock( m_aMutex );
128 m_xFrame.clear();
129 m_xDispatch.clear();
130 m_xPopupMenu.clear();
133 // XMenuListener
134 void SAL_CALL PopupMenuControllerBase::highlight( const awt::MenuEvent& ) throw (RuntimeException)
138 void PopupMenuControllerBase::impl_select(const Reference< XDispatch >& _xDispatch,const URL& aURL)
140 Sequence<PropertyValue> aArgs;
141 OSL_ENSURE(_xDispatch.is(),"PopupMenuControllerBase::impl_select: No dispatch");
142 if ( _xDispatch.is() )
143 _xDispatch->dispatch( aURL, aArgs );
146 void SAL_CALL PopupMenuControllerBase::select( const awt::MenuEvent& rEvent ) throw (RuntimeException)
148 throwIfDisposed();
150 osl::MutexGuard aLock( m_aMutex );
152 Reference< awt::XMenuExtended > xExtMenu( m_xPopupMenu, UNO_QUERY );
153 if( xExtMenu.is() )
155 Sequence<PropertyValue> aArgs;
156 dispatchCommand( xExtMenu->getCommand( rEvent.MenuId ), aArgs );
160 void PopupMenuControllerBase::dispatchCommand( const OUString& sCommandURL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rArgs )
162 osl::MutexGuard aLock( m_aMutex );
164 throwIfDisposed();
168 Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY_THROW );
169 URL aURL;
170 aURL.Complete = sCommandURL;
171 m_xURLTransformer->parseStrict( aURL );
173 Reference< XDispatch > xDispatch( xDispatchProvider->queryDispatch( aURL, OUString(), 0 ), UNO_QUERY_THROW );
175 Application::PostUserEvent( STATIC_LINK(0, PopupMenuControllerBase, ExecuteHdl_Impl), new PopupMenuControllerBaseDispatchInfo( xDispatch, aURL, rArgs ) );
178 catch( Exception& )
184 IMPL_STATIC_LINK_NOINSTANCE( PopupMenuControllerBase, ExecuteHdl_Impl, PopupMenuControllerBaseDispatchInfo*, pDispatchInfo )
186 pDispatchInfo->mxDispatch->dispatch( pDispatchInfo->maURL, pDispatchInfo->maArgs );
187 delete pDispatchInfo;
188 return 0;
191 void SAL_CALL PopupMenuControllerBase::activate( const awt::MenuEvent& ) throw (RuntimeException)
195 void SAL_CALL PopupMenuControllerBase::deactivate( const awt::MenuEvent& ) throw (RuntimeException)
199 void SAL_CALL PopupMenuControllerBase::updatePopupMenu() throw ( ::com::sun::star::uno::RuntimeException )
201 osl::ClearableMutexGuard aLock( m_aMutex );
202 throwIfDisposed();
203 aLock.clear();
205 updateCommand( m_aCommandURL );
208 void SAL_CALL PopupMenuControllerBase::updateCommand( const OUString& rCommandURL )
210 osl::ClearableMutexGuard aLock( m_aMutex );
211 Reference< XStatusListener > xStatusListener( static_cast< OWeakObject* >( this ), UNO_QUERY );
212 Reference< XDispatch > xDispatch( m_xDispatch );
213 URL aTargetURL;
214 aTargetURL.Complete = rCommandURL;
215 m_xURLTransformer->parseStrict( aTargetURL );
216 aLock.clear();
218 // Add/remove status listener to get a status update once
219 if ( xDispatch.is() )
221 xDispatch->addStatusListener( xStatusListener, aTargetURL );
222 xDispatch->removeStatusListener( xStatusListener, aTargetURL );
227 // XDispatchProvider
228 Reference< XDispatch > SAL_CALL
229 PopupMenuControllerBase::queryDispatch(
230 const URL& /*aURL*/,
231 const OUString& /*sTarget*/,
232 sal_Int32 /*nFlags*/ )
233 throw( RuntimeException )
235 // must be implemented by subclass
236 osl::MutexGuard aLock( m_aMutex );
237 throwIfDisposed();
239 return Reference< XDispatch >();
242 Sequence< Reference< XDispatch > > SAL_CALL PopupMenuControllerBase::queryDispatches( const Sequence< DispatchDescriptor >& lDescriptor ) throw( RuntimeException )
244 // Create return list - which must have same size then the given descriptor
245 // It's not allowed to pack it!
246 osl::ClearableMutexGuard aLock( m_aMutex );
247 throwIfDisposed();
248 aLock.clear();
250 sal_Int32 nCount = lDescriptor.getLength();
251 uno::Sequence< uno::Reference< frame::XDispatch > > lDispatcher( nCount );
253 // Step over all descriptors and try to get any dispatcher for it.
254 for( sal_Int32 i=0; i<nCount; ++i )
256 lDispatcher[i] = queryDispatch( lDescriptor[i].FeatureURL ,
257 lDescriptor[i].FrameName ,
258 lDescriptor[i].SearchFlags );
261 return lDispatcher;
264 // XDispatch
265 void SAL_CALL
266 PopupMenuControllerBase::dispatch(
267 const URL& /*aURL*/,
268 const Sequence< PropertyValue >& /*seqProperties*/ )
269 throw( ::com::sun::star::uno::RuntimeException )
271 // must be implemented by subclass
272 osl::MutexGuard aLock( m_aMutex );
273 throwIfDisposed();
276 void SAL_CALL
277 PopupMenuControllerBase::addStatusListener(
278 const Reference< XStatusListener >& xControl,
279 const URL& aURL )
280 throw( ::com::sun::star::uno::RuntimeException )
282 osl::ResettableMutexGuard aLock( m_aMutex );
283 throwIfDisposed();
284 aLock.clear();
286 bool bStatusUpdate( false );
287 rBHelper.addListener( ::getCppuType( &xControl ), xControl );
289 aLock.reset();
290 if ( aURL.Complete.indexOf( m_aBaseURL ) == 0 )
291 bStatusUpdate = true;
292 aLock.clear();
294 if ( bStatusUpdate )
296 // Dummy update for popup menu controllers
297 FeatureStateEvent aEvent;
298 aEvent.FeatureURL = aURL;
299 aEvent.IsEnabled = sal_True;
300 aEvent.Requery = sal_False;
301 aEvent.State = Any();
302 xControl->statusChanged( aEvent );
306 void SAL_CALL PopupMenuControllerBase::removeStatusListener(
307 const Reference< XStatusListener >& xControl,
308 const URL& /*aURL*/ )
309 throw( ::com::sun::star::uno::RuntimeException )
311 rBHelper.removeListener( ::getCppuType( &xControl ), xControl );
314 OUString PopupMenuControllerBase::determineBaseURL( const OUString& aURL )
316 // Just use the main part of the URL for popup menu controllers
317 sal_Int32 nQueryPart( 0 );
318 sal_Int32 nSchemePart( 0 );
319 OUString aMainURL( "vnd.sun.star.popup:" );
321 nSchemePart = aURL.indexOf( ':' );
322 if (( nSchemePart > 0 ) &&
323 ( aURL.getLength() > ( nSchemePart+1 )))
325 nQueryPart = aURL.indexOf( '?', nSchemePart );
326 if ( nQueryPart > 0 )
327 aMainURL += aURL.copy( nSchemePart, nQueryPart-nSchemePart );
328 else if ( nQueryPart == -1 )
329 aMainURL += aURL.copy( nSchemePart+1 );
332 return aMainURL;
335 // XInitialization
336 void SAL_CALL PopupMenuControllerBase::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException )
338 osl::MutexGuard aLock( m_aMutex );
340 sal_Bool bInitalized( m_bInitialized );
341 if ( !bInitalized )
343 PropertyValue aPropValue;
344 OUString aCommandURL;
345 Reference< XFrame > xFrame;
347 for ( int i = 0; i < aArguments.getLength(); i++ )
349 if ( aArguments[i] >>= aPropValue )
351 if ( aPropValue.Name == "Frame" )
352 aPropValue.Value >>= xFrame;
353 else if ( aPropValue.Name == "CommandURL" )
354 aPropValue.Value >>= aCommandURL;
355 else if ( aPropValue.Name == "ModuleName" )
356 aPropValue.Value >>= m_aModuleName;
360 if ( xFrame.is() && !aCommandURL.isEmpty() )
362 m_xFrame = xFrame;
363 m_aCommandURL = aCommandURL;
364 m_aBaseURL = determineBaseURL( aCommandURL );
365 m_bInitialized = true;
369 // XPopupMenuController
370 void SAL_CALL PopupMenuControllerBase::setPopupMenu( const Reference< awt::XPopupMenu >& xPopupMenu ) throw ( RuntimeException )
372 osl::MutexGuard aLock( m_aMutex );
373 throwIfDisposed();
375 if ( m_xFrame.is() && !m_xPopupMenu.is() )
377 // Create popup menu on demand
378 SolarMutexGuard aSolarMutexGuard;
380 m_xPopupMenu = xPopupMenu;
381 m_xPopupMenu->addMenuListener( Reference< awt::XMenuListener >( (OWeakObject*)this, UNO_QUERY ));
383 Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
385 URL aTargetURL;
386 aTargetURL.Complete = m_aCommandURL;
387 m_xURLTransformer->parseStrict( aTargetURL );
388 m_xDispatch = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
390 impl_setPopupMenu();
392 updatePopupMenu();
395 void PopupMenuControllerBase::impl_setPopupMenu()
400 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */