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>
30#include <osl/mutex.hxx>
35using namespace css::uno;
36using namespace css::lang;
37using namespace css::frame;
38using namespace css::beans;
39using namespace css::util;
46struct PopupMenuControllerBaseDispatchInfo
50 const Sequence< PropertyValue >
maArgs;
52 PopupMenuControllerBaseDispatchInfo(
const Reference< XDispatch >& xDispatch, URL aURL,
const Sequence< PropertyValue >& rArgs )
58PopupMenuControllerBase::PopupMenuControllerBase(
const Reference< XComponentContext >& xContext ) :
59 m_bInitialized( false )
62 m_xURLTransformer.set( util::URLTransformer::create( xContext ) );
65PopupMenuControllerBase::~PopupMenuControllerBase()
70void PopupMenuControllerBase::resetPopupMenu( css::uno::Reference< css::awt::XPopupMenu >
const & rPopupMenu )
72 if ( rPopupMenu.is() && rPopupMenu->getItemCount() > 0 )
78void PopupMenuControllerBase::disposing(std::unique_lock<std::mutex>& )
87sal_Bool SAL_CALL PopupMenuControllerBase::supportsService(
const OUString& ServiceName )
93void SAL_CALL PopupMenuControllerBase::disposing(
const EventObject& )
95 std::unique_lock aLock( m_aMutex );
102void SAL_CALL PopupMenuControllerBase::itemHighlighted(
const awt::MenuEvent& )
106void SAL_CALL PopupMenuControllerBase::itemSelected(
const awt::MenuEvent& rEvent )
108 std::unique_lock aLock( m_aMutex );
109 throwIfDisposed(aLock);
111 if( m_xPopupMenu.is() )
113 Sequence<PropertyValue> aArgs;
114 dispatchCommandImpl( aLock, m_xPopupMenu->getCommand( rEvent.MenuId ), aArgs, OUString() );
118void PopupMenuControllerBase::dispatchCommand(
const OUString& sCommandURL,
119 const css::uno::Sequence< css::beans::PropertyValue >& rArgs,
120 const OUString& sTarget )
122 std::unique_lock aLock( m_aMutex );
123 throwIfDisposed(aLock);
124 dispatchCommandImpl(aLock, sCommandURL, rArgs, sTarget);
127void PopupMenuControllerBase::dispatchCommandImpl( std::unique_lock<std::mutex>& ,
128 const OUString& sCommandURL,
129 const css::uno::Sequence< css::beans::PropertyValue >& rArgs,
130 const OUString& sTarget )
135 Reference< XDispatchProvider > xDispatchProvider(
m_xFrame, UNO_QUERY_THROW );
137 aURL.Complete = sCommandURL;
138 m_xURLTransformer->parseStrict( aURL );
140 Reference< XDispatch >
xDispatch( xDispatchProvider->queryDispatch( aURL, sTarget, 0 ), UNO_SET_THROW );
142 Application::PostUserEvent(
LINK(
nullptr, PopupMenuControllerBase, ExecuteHdl_Impl),
new PopupMenuControllerBaseDispatchInfo( xDispatch, std::move(aURL), rArgs ) );
153 PopupMenuControllerBaseDispatchInfo* pDispatchInfo =
static_cast<PopupMenuControllerBaseDispatchInfo*
>(
p);
154 pDispatchInfo->mxDispatch->dispatch( pDispatchInfo->maURL, pDispatchInfo->maArgs );
155 delete pDispatchInfo;
158void SAL_CALL PopupMenuControllerBase::itemActivated(
const awt::MenuEvent& )
162void SAL_CALL PopupMenuControllerBase::itemDeactivated(
const awt::MenuEvent& )
166void SAL_CALL PopupMenuControllerBase::updatePopupMenu()
169 std::unique_lock aLock(m_aMutex);
170 throwIfDisposed(aLock);
173 updateCommand( m_aCommandURL );
176void PopupMenuControllerBase::updateCommand(
const OUString& rCommandURL )
178 std::unique_lock aLock( m_aMutex );
179 Reference< XStatusListener > xStatusListener(
this);
183 m_xURLTransformer->parseStrict( aTargetURL );
189 xDispatch->addStatusListener( xStatusListener, aTargetURL );
190 xDispatch->removeStatusListener( xStatusListener, aTargetURL );
196Reference< XDispatch > SAL_CALL
197PopupMenuControllerBase::queryDispatch(
203 std::unique_lock aLock( m_aMutex );
204 throwIfDisposed(aLock);
206 return Reference< XDispatch >();
209Sequence< Reference< XDispatch > > SAL_CALL PopupMenuControllerBase::queryDispatches(
const Sequence< DispatchDescriptor >& lDescriptor )
214 std::unique_lock aLock(m_aMutex);
215 throwIfDisposed(aLock);
218 sal_Int32
nCount = lDescriptor.getLength();
219 uno::Sequence< uno::Reference< frame::XDispatch > > lDispatcher( nCount );
222 std::transform(lDescriptor.begin(), lDescriptor.end(), lDispatcher.getArray(),
223 [
this](
const DispatchDescriptor& rDesc) -> uno::Reference< frame::XDispatch > {
224 return queryDispatch(rDesc.FeatureURL, rDesc.FrameName, rDesc.SearchFlags); });
231PopupMenuControllerBase::dispatch(
233 const Sequence< PropertyValue >& )
236 std::unique_lock aLock( m_aMutex );
237 throwIfDisposed(aLock);
241PopupMenuControllerBase::addStatusListener(
242 const Reference< XStatusListener >& xControl,
245 std::unique_lock aLock( m_aMutex );
246 throwIfDisposed(aLock);
248 bool bStatusUpdate(
false );
249 maStatusListeners.addInterface( aLock, xControl );
251 if (
aURL.Complete.startsWith( m_aBaseURL ) )
252 bStatusUpdate =
true;
263 xControl->statusChanged( aEvent );
267void SAL_CALL PopupMenuControllerBase::removeStatusListener(
268 const Reference< XStatusListener >& xControl,
271 std::unique_lock aLock( m_aMutex );
272 maStatusListeners.removeInterface( aLock, xControl );
275OUString PopupMenuControllerBase::determineBaseURL( std::u16string_view aURL )
278 OUString aMainURL(
"vnd.sun.star.popup:" );
280 size_t nSchemePart =
aURL.find(
':' );
281 if (( nSchemePart != std::u16string_view::npos && nSchemePart > 0 ) &&
282 (
aURL.size() > ( nSchemePart+1 )))
284 size_t nQueryPart =
aURL.find(
'?', nSchemePart );
285 if ( nQueryPart != std::u16string_view::npos && nQueryPart > 0 )
286 aMainURL +=
aURL.substr( nSchemePart, nQueryPart-nSchemePart );
287 else if ( nQueryPart == std::u16string_view::npos )
288 aMainURL +=
aURL.substr( nSchemePart+1 );
295void SAL_CALL PopupMenuControllerBase::initialize(
const Sequence< Any >& aArguments )
297 std::unique_lock aLock( m_aMutex );
298 initializeImpl(aLock, aArguments);
302void PopupMenuControllerBase::initializeImpl( std::unique_lock<std::mutex>& ,
const Sequence< Any >& aArguments )
308 PropertyValue aPropValue;
309 OUString aCommandURL;
310 Reference< XFrame >
xFrame;
312 for (
const auto& rArgument : aArguments )
314 if ( rArgument >>= aPropValue )
316 if ( aPropValue.Name ==
"Frame" )
317 aPropValue.Value >>=
xFrame;
318 else if ( aPropValue.Name ==
"CommandURL" )
319 aPropValue.Value >>= aCommandURL;
320 else if ( aPropValue.Name ==
"ModuleIdentifier" )
321 aPropValue.Value >>= m_aModuleName;
325 if (
xFrame.is() && !aCommandURL.isEmpty() )
328 m_aCommandURL = aCommandURL;
329 m_aBaseURL = determineBaseURL( aCommandURL );
330 m_bInitialized =
true;
334void SAL_CALL PopupMenuControllerBase::setPopupMenu(
const Reference< awt::XPopupMenu >& xPopupMenu )
337 std::unique_lock aLock( m_aMutex );
338 throwIfDisposed(aLock);
340 if ( !
m_xFrame.is() || m_xPopupMenu.is() )
346 m_xPopupMenu =
dynamic_cast<VCLXPopupMenu*
>(xPopupMenu.get());
347 assert(
bool(xPopupMenu) ==
bool(m_xPopupMenu) &&
"we only support VCLXPopupMenu");
348 m_xPopupMenu->addMenuListener( Reference< awt::XMenuListener >(
this) );
350 Reference< XDispatchProvider > xDispatchProvider(
m_xFrame, UNO_QUERY );
354 m_xURLTransformer->parseStrict( aTargetURL );
355 m_xDispatch = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
361void PopupMenuControllerBase::impl_setPopupMenu()
css::uno::Reference< css::lang::XComponent > m_xFrame
css::uno::Reference< css::frame::XDispatch > m_xDispatch
static ImplSVEvent * PostUserEvent(const Link< void *, void > &rLink, void *pCaller=nullptr, bool bReferenceLink=false)
Reference< XDispatch > xDispatch
#define LINK(Instance, Class, Member)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
IMPL_STATIC_LINK(PopupMenuControllerBase, ExecuteHdl_Impl, void *, p, void)
Reference< XFrame > xFrame