1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <dispatch/popupmenudispatcher.hxx>
22 #include <properties.h>
24 #include <com/sun/star/frame/XLayoutManager2.hpp>
25 #include <com/sun/star/beans/XPropertySet.hpp>
26 #include <com/sun/star/uri/UriReferenceFactory.hpp>
27 #include <com/sun/star/ui/XUIElement.hpp>
29 #include <cppuhelper/supportsservice.hxx>
30 #include <sal/log.hxx>
32 #include <vcl/svapp.hxx>
36 using namespace ::com::sun::star
;
37 using namespace ::com::sun::star::awt
;
38 using namespace ::com::sun::star::beans
;
39 using namespace ::com::sun::star::container
;
40 using namespace ::com::sun::star::frame
;
41 using namespace ::com::sun::star::lang
;
42 using namespace ::com::sun::star::uno
;
43 using namespace ::com::sun::star::util
;
44 using namespace ::cppu
;
45 using namespace ::osl
;
47 PopupMenuDispatcher::PopupMenuDispatcher(
48 uno::Reference
< XComponentContext
> xContext
)
49 : m_xContext (std::move( xContext
))
50 , m_bAlreadyDisposed ( false )
51 , m_bActivateListener ( false )
55 PopupMenuDispatcher::~PopupMenuDispatcher()
57 // Warn programmer if he forgot to dispose this instance.
58 // We must release all our references ...
59 // and a dtor isn't the best place to do that!
62 OUString SAL_CALL
PopupMenuDispatcher::getImplementationName()
64 return u
"com.sun.star.comp.framework.PopupMenuControllerDispatcher"_ustr
;
67 sal_Bool SAL_CALL
PopupMenuDispatcher::supportsService( const OUString
& sServiceName
)
69 return cppu::supportsService(this, sServiceName
);
72 css::uno::Sequence
< OUString
> SAL_CALL
PopupMenuDispatcher::getSupportedServiceNames()
74 return { SERVICENAME_PROTOCOLHANDLER
};
77 void SAL_CALL
PopupMenuDispatcher::initialize( const css::uno::Sequence
< css::uno::Any
>& lArguments
)
79 css::uno::Reference
< css::frame::XFrame
> xFrame
;
82 for (int a
=0; a
<lArguments
.getLength(); ++a
)
86 lArguments
[a
] >>= xFrame
;
87 m_xWeakFrame
= xFrame
;
89 m_bActivateListener
= true;
90 uno::Reference
< css::frame::XFrameActionListener
> xFrameActionListener(this);
91 xFrame
->addFrameActionListener( xFrameActionListener
);
96 css::uno::Reference
< css::frame::XDispatch
>
97 SAL_CALL
PopupMenuDispatcher::queryDispatch(
98 const css::util::URL
& rURL
,
99 const OUString
& sTarget
,
102 if ( !rURL
.Complete
.startsWith( "vnd.sun.star.popup:" ) )
106 SolarMutexClearableGuard aGuard
;
107 impl_RetrievePopupControllerQuery();
108 if ( !m_xUriRefFactory
.is() )
109 m_xUriRefFactory
= css::uri::UriReferenceFactory::create( m_xContext
);
111 css::uno::Reference
< css::container::XNameAccess
> xPopupCtrlQuery( m_xPopupCtrlQuery
);
115 if ( !xPopupCtrlQuery
.is() )
118 css::uno::Reference
< css::frame::XDispatch
> xDispatch
;
122 // Just use the main part of the URL for popup menu controllers
123 sal_Int32
nSchemePart( 0 );
124 OUString
aBaseURL( u
"vnd.sun.star.popup:"_ustr
);
125 OUString
aURL( rURL
.Complete
);
127 nSchemePart
= aURL
.indexOf( ':' );
128 if (( nSchemePart
> 0 ) &&
129 ( aURL
.getLength() > ( nSchemePart
+1 )))
131 sal_Int32 nQueryPart
= aURL
.indexOf( '?', nSchemePart
);
132 if ( nQueryPart
> 0 )
133 aBaseURL
+= aURL
.subView( nSchemePart
+1, nQueryPart
-(nSchemePart
+1) );
134 else if ( nQueryPart
== -1 )
135 aBaseURL
+= aURL
.subView( nSchemePart
+1 );
138 css::uno::Reference
< css::frame::XDispatchProvider
> xDispatchProvider
;
140 // Find popup menu controller using the base URL
141 xPopupCtrlQuery
->getByName( aBaseURL
) >>= xDispatchProvider
;
143 // Ask popup menu dispatch provider for dispatch object
144 if ( xDispatchProvider
.is() )
145 xDispatch
= xDispatchProvider
->queryDispatch( rURL
, sTarget
, nFlags
);
147 catch ( const RuntimeException
& )
151 catch ( const Exception
& )
157 css::uno::Sequence
< css::uno::Reference
< css::frame::XDispatch
> > SAL_CALL
158 PopupMenuDispatcher::queryDispatches(
159 const css::uno::Sequence
< css::frame::DispatchDescriptor
>& lDescriptor
)
161 sal_Int32 nCount
= lDescriptor
.getLength();
162 css::uno::Sequence
< css::uno::Reference
< css::frame::XDispatch
> > lDispatcher( nCount
);
163 auto lDispatcherRange
= asNonConstRange(lDispatcher
);
164 for( sal_Int32 i
=0; i
<nCount
; ++i
)
166 lDispatcherRange
[i
] = queryDispatch(
167 lDescriptor
[i
].FeatureURL
,
168 lDescriptor
[i
].FrameName
,
169 lDescriptor
[i
].SearchFlags
);
174 void SAL_CALL
PopupMenuDispatcher::dispatch( const URL
& /*aURL*/, const Sequence
< PropertyValue
>& /*seqProperties*/ )
178 void SAL_CALL
PopupMenuDispatcher::addStatusListener( const uno::Reference
< XStatusListener
>& /*xControl*/,
179 const URL
& /*aURL*/ )
183 void SAL_CALL
PopupMenuDispatcher::removeStatusListener( const uno::Reference
< XStatusListener
>& /*xControl*/,
184 const URL
& /*aURL*/ )
188 void SAL_CALL
PopupMenuDispatcher::frameAction( const FrameActionEvent
& aEvent
)
191 if (( aEvent
.Action
== css::frame::FrameAction_COMPONENT_DETACHING
) ||
192 ( aEvent
.Action
== css::frame::FrameAction_COMPONENT_ATTACHED
))
194 // Reset query reference to requery it again next time
195 m_xPopupCtrlQuery
.clear();
199 void SAL_CALL
PopupMenuDispatcher::disposing( const EventObject
& )
202 // Safe impossible cases
203 SAL_WARN_IF( m_bAlreadyDisposed
, "fwk", "MenuDispatcher::disposing(): Object already disposed .. don't call it again!" );
205 if( m_bAlreadyDisposed
)
208 m_bAlreadyDisposed
= true;
210 if ( m_bActivateListener
)
212 uno::Reference
< XFrame
> xFrame( m_xWeakFrame
.get(), UNO_QUERY
);
215 xFrame
->removeFrameActionListener( uno::Reference
< XFrameActionListener
>(this) );
216 m_bActivateListener
= false;
220 // Forget our factory.
224 void PopupMenuDispatcher::impl_RetrievePopupControllerQuery()
226 if ( m_xPopupCtrlQuery
.is() )
229 css::uno::Reference
< css::frame::XLayoutManager2
> xLayoutManager
;
230 css::uno::Reference
< css::frame::XFrame
> xFrame( m_xWeakFrame
);
235 css::uno::Reference
< css::beans::XPropertySet
> xPropSet( xFrame
, css::uno::UNO_QUERY
);
236 if ( !xPropSet
.is() )
241 xPropSet
->getPropertyValue( FRAME_PROPNAME_ASCII_LAYOUTMANAGER
) >>= xLayoutManager
;
243 if ( xLayoutManager
.is() )
245 css::uno::Reference
< css::ui::XUIElement
> xMenuBar
= xLayoutManager
->getElement( u
"private:resource/menubar/menubar"_ustr
);
247 m_xPopupCtrlQuery
.set( xMenuBar
, css::uno::UNO_QUERY
);
250 catch ( const css::uno::RuntimeException
& )
254 catch ( const css::uno::Exception
& )
259 } // namespace framework
262 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
263 framework_PopupMenuDispatcher_get_implementation(
264 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const& )
266 return cppu::acquire(new framework::PopupMenuDispatcher(context
));
269 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */