nss: upgrade to release 3.73
[LibreOffice.git] / svtools / source / uno / popupmenucontrollerbase.cxx
blob6cd12e0e0df07d285ab96d278102d1df5fc6a95e
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/beans/PropertyValue.hpp>
23 #include <com/sun/star/frame/XDispatchProvider.hpp>
24 #include <com/sun/star/frame/XFrame.hpp>
25 #include <com/sun/star/lang/DisposedException.hpp>
26 #include <com/sun/star/util/URLTransformer.hpp>
28 #include <vcl/svapp.hxx>
29 #include <osl/mutex.hxx>
30 #include <cppuhelper/supportsservice.hxx>
32 using namespace com::sun::star;
33 using namespace css::uno;
34 using namespace css::lang;
35 using namespace css::frame;
36 using namespace css::beans;
37 using namespace css::util;
39 namespace svt
42 namespace {
44 struct PopupMenuControllerBaseDispatchInfo
46 Reference< XDispatch > mxDispatch;
47 const URL maURL;
48 const Sequence< PropertyValue > maArgs;
50 PopupMenuControllerBaseDispatchInfo( const Reference< XDispatch >& xDispatch, const URL& rURL, const Sequence< PropertyValue >& rArgs )
51 : mxDispatch( xDispatch ), maURL( rURL ), maArgs( rArgs ) {}
56 PopupMenuControllerBase::PopupMenuControllerBase( const Reference< XComponentContext >& xContext ) :
57 ::cppu::BaseMutex(),
58 PopupMenuControllerBaseType(m_aMutex),
59 m_bInitialized( false )
61 if ( xContext.is() )
62 m_xURLTransformer.set( util::URLTransformer::create( xContext ) );
65 PopupMenuControllerBase::~PopupMenuControllerBase()
69 // protected function
70 void PopupMenuControllerBase::throwIfDisposed()
72 if (rBHelper.bDisposed || rBHelper.bInDispose)
73 throw css::lang::DisposedException();
76 // protected function
77 void PopupMenuControllerBase::resetPopupMenu( css::uno::Reference< css::awt::XPopupMenu > const & rPopupMenu )
79 if ( rPopupMenu.is() && rPopupMenu->getItemCount() > 0 )
81 rPopupMenu->clear();
85 void SAL_CALL PopupMenuControllerBase::disposing()
87 // Reset our members and set disposed flag
88 osl::MutexGuard aLock( m_aMutex );
89 m_xFrame.clear();
90 m_xDispatch.clear();
91 m_xPopupMenu.clear();
94 // XServiceInfo
95 sal_Bool SAL_CALL PopupMenuControllerBase::supportsService( const OUString& ServiceName )
97 return cppu::supportsService(this, ServiceName);
100 // XEventListener
101 void SAL_CALL PopupMenuControllerBase::disposing( const EventObject& )
103 osl::MutexGuard aLock( m_aMutex );
104 m_xFrame.clear();
105 m_xDispatch.clear();
106 m_xPopupMenu.clear();
109 // XMenuListener
110 void SAL_CALL PopupMenuControllerBase::itemHighlighted( const awt::MenuEvent& )
114 void SAL_CALL PopupMenuControllerBase::itemSelected( const awt::MenuEvent& rEvent )
116 throwIfDisposed();
118 osl::MutexGuard aLock( m_aMutex );
120 if( m_xPopupMenu.is() )
122 Sequence<PropertyValue> aArgs;
123 dispatchCommand( m_xPopupMenu->getCommand( rEvent.MenuId ), aArgs );
127 void PopupMenuControllerBase::dispatchCommand( const OUString& sCommandURL,
128 const css::uno::Sequence< css::beans::PropertyValue >& rArgs,
129 const OUString& sTarget )
131 osl::MutexGuard aLock( m_aMutex );
133 throwIfDisposed();
137 Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY_THROW );
138 URL aURL;
139 aURL.Complete = sCommandURL;
140 m_xURLTransformer->parseStrict( aURL );
142 Reference< XDispatch > xDispatch( xDispatchProvider->queryDispatch( aURL, sTarget, 0 ), UNO_SET_THROW );
144 Application::PostUserEvent( LINK(nullptr, PopupMenuControllerBase, ExecuteHdl_Impl), new PopupMenuControllerBaseDispatchInfo( xDispatch, aURL, rArgs ) );
147 catch( Exception& )
153 IMPL_STATIC_LINK( PopupMenuControllerBase, ExecuteHdl_Impl, void*, p, void )
155 PopupMenuControllerBaseDispatchInfo* pDispatchInfo = static_cast<PopupMenuControllerBaseDispatchInfo*>(p);
156 pDispatchInfo->mxDispatch->dispatch( pDispatchInfo->maURL, pDispatchInfo->maArgs );
157 delete pDispatchInfo;
160 void SAL_CALL PopupMenuControllerBase::itemActivated( const awt::MenuEvent& )
164 void SAL_CALL PopupMenuControllerBase::itemDeactivated( const awt::MenuEvent& )
168 void SAL_CALL PopupMenuControllerBase::updatePopupMenu()
171 osl::MutexGuard aLock(m_aMutex);
172 throwIfDisposed();
175 updateCommand( m_aCommandURL );
178 void PopupMenuControllerBase::updateCommand( const OUString& rCommandURL )
180 osl::ClearableMutexGuard aLock( m_aMutex );
181 Reference< XStatusListener > xStatusListener( static_cast< OWeakObject* >( this ), UNO_QUERY );
182 Reference< XDispatch > xDispatch( m_xDispatch );
183 URL aTargetURL;
184 aTargetURL.Complete = rCommandURL;
185 m_xURLTransformer->parseStrict( aTargetURL );
186 aLock.clear();
188 // Add/remove status listener to get a status update once
189 if ( xDispatch.is() )
191 xDispatch->addStatusListener( xStatusListener, aTargetURL );
192 xDispatch->removeStatusListener( xStatusListener, aTargetURL );
197 // XDispatchProvider
198 Reference< XDispatch > SAL_CALL
199 PopupMenuControllerBase::queryDispatch(
200 const URL& /*aURL*/,
201 const OUString& /*sTarget*/,
202 sal_Int32 /*nFlags*/ )
204 // must be implemented by subclass
205 osl::MutexGuard aLock( m_aMutex );
206 throwIfDisposed();
208 return Reference< XDispatch >();
211 Sequence< Reference< XDispatch > > SAL_CALL PopupMenuControllerBase::queryDispatches( const Sequence< DispatchDescriptor >& lDescriptor )
213 // Create return list - which must have same size then the given descriptor
214 // It's not allowed to pack it!
216 osl::MutexGuard aLock(m_aMutex);
217 throwIfDisposed();
220 sal_Int32 nCount = lDescriptor.getLength();
221 uno::Sequence< uno::Reference< frame::XDispatch > > lDispatcher( nCount );
223 // Step over all descriptors and try to get any dispatcher for it.
224 std::transform(lDescriptor.begin(), lDescriptor.end(), lDispatcher.begin(),
225 [this](const DispatchDescriptor& rDesc) -> uno::Reference< frame::XDispatch > {
226 return queryDispatch(rDesc.FeatureURL, rDesc.FrameName, rDesc.SearchFlags); });
228 return lDispatcher;
231 // XDispatch
232 void SAL_CALL
233 PopupMenuControllerBase::dispatch(
234 const URL& /*aURL*/,
235 const Sequence< PropertyValue >& /*seqProperties*/ )
237 // must be implemented by subclass
238 osl::MutexGuard aLock( m_aMutex );
239 throwIfDisposed();
242 void SAL_CALL
243 PopupMenuControllerBase::addStatusListener(
244 const Reference< XStatusListener >& xControl,
245 const URL& aURL )
247 osl::ResettableMutexGuard aLock( m_aMutex );
248 throwIfDisposed();
249 aLock.clear();
251 bool bStatusUpdate( false );
252 rBHelper.addListener( cppu::UnoType<decltype(xControl)>::get(), xControl );
254 aLock.reset();
255 if ( aURL.Complete.startsWith( m_aBaseURL ) )
256 bStatusUpdate = true;
257 aLock.clear();
259 if ( bStatusUpdate )
261 // Dummy update for popup menu controllers
262 FeatureStateEvent aEvent;
263 aEvent.FeatureURL = aURL;
264 aEvent.IsEnabled = true;
265 aEvent.Requery = false;
266 aEvent.State = Any();
267 xControl->statusChanged( aEvent );
271 void SAL_CALL PopupMenuControllerBase::removeStatusListener(
272 const Reference< XStatusListener >& xControl,
273 const URL& /*aURL*/ )
275 rBHelper.removeListener( cppu::UnoType<decltype(xControl)>::get(), xControl );
278 OUString PopupMenuControllerBase::determineBaseURL( const OUString& aURL )
280 // Just use the main part of the URL for popup menu controllers
281 sal_Int32 nSchemePart( 0 );
282 OUString aMainURL( "vnd.sun.star.popup:" );
284 nSchemePart = aURL.indexOf( ':' );
285 if (( nSchemePart > 0 ) &&
286 ( aURL.getLength() > ( nSchemePart+1 )))
288 sal_Int32 nQueryPart = aURL.indexOf( '?', nSchemePart );
289 if ( nQueryPart > 0 )
290 aMainURL += aURL.subView( nSchemePart, nQueryPart-nSchemePart );
291 else if ( nQueryPart == -1 )
292 aMainURL += aURL.subView( nSchemePart+1 );
295 return aMainURL;
298 // XInitialization
299 void SAL_CALL PopupMenuControllerBase::initialize( const Sequence< Any >& aArguments )
301 osl::MutexGuard aLock( m_aMutex );
303 bool bInitalized( m_bInitialized );
304 if ( bInitalized )
305 return;
307 PropertyValue aPropValue;
308 OUString aCommandURL;
309 Reference< XFrame > xFrame;
311 for ( const auto& rArgument : aArguments )
313 if ( rArgument >>= aPropValue )
315 if ( aPropValue.Name == "Frame" )
316 aPropValue.Value >>= xFrame;
317 else if ( aPropValue.Name == "CommandURL" )
318 aPropValue.Value >>= aCommandURL;
319 else if ( aPropValue.Name == "ModuleIdentifier" )
320 aPropValue.Value >>= m_aModuleName;
324 if ( xFrame.is() && !aCommandURL.isEmpty() )
326 m_xFrame = xFrame;
327 m_aCommandURL = aCommandURL;
328 m_aBaseURL = determineBaseURL( aCommandURL );
329 m_bInitialized = true;
332 // XPopupMenuController
333 void SAL_CALL PopupMenuControllerBase::setPopupMenu( const Reference< awt::XPopupMenu >& xPopupMenu )
335 osl::MutexGuard aLock( m_aMutex );
336 throwIfDisposed();
338 if ( !m_xFrame.is() || m_xPopupMenu.is() )
339 return;
341 // Create popup menu on demand
342 SolarMutexGuard aSolarMutexGuard;
344 m_xPopupMenu = xPopupMenu;
345 m_xPopupMenu->addMenuListener( Reference< awt::XMenuListener >( static_cast<OWeakObject*>(this), UNO_QUERY ));
347 Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
349 URL aTargetURL;
350 aTargetURL.Complete = m_aCommandURL;
351 m_xURLTransformer->parseStrict( aTargetURL );
352 m_xDispatch = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
354 impl_setPopupMenu();
356 updatePopupMenu();
358 void PopupMenuControllerBase::impl_setPopupMenu()
363 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */