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 <framework/menuconfiguration.hxx>
23 #include <framework/addonmenu.hxx>
25 #include <properties.h>
27 #include <com/sun/star/frame/FrameSearchFlag.hpp>
28 #include <com/sun/star/frame/XLayoutManager2.hpp>
29 #include <com/sun/star/awt/WindowAttribute.hpp>
30 #include <com/sun/star/awt/WindowDescriptor.hpp>
31 #include <com/sun/star/awt/PosSize.hpp>
32 #include <com/sun/star/awt/XWindowPeer.hpp>
33 #include <com/sun/star/beans/UnknownPropertyException.hpp>
34 #include <com/sun/star/lang/WrappedTargetException.hpp>
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/container/XEnumeration.hpp>
37 #include <com/sun/star/uri/UriReferenceFactory.hpp>
38 #include <com/sun/star/ui/XUIElement.hpp>
40 #include <cppuhelper/supportsservice.hxx>
41 #include <osl/mutex.hxx>
42 #include <rtl/ustrbuf.hxx>
43 #include <ucbhelper/content.hxx>
44 #include <vcl/svapp.hxx>
48 using namespace ::com::sun::star
;
49 using namespace ::com::sun::star::awt
;
50 using namespace ::com::sun::star::beans
;
51 using namespace ::com::sun::star::container
;
52 using namespace ::com::sun::star::frame
;
53 using namespace ::com::sun::star::lang
;
54 using namespace ::com::sun::star::uno
;
55 using namespace ::com::sun::star::util
;
56 using namespace ::cppu
;
57 using namespace ::osl
;
59 PopupMenuDispatcher::PopupMenuDispatcher(
60 const uno::Reference
< XComponentContext
>& xContext
)
61 : m_xContext ( xContext
)
62 , m_aListenerContainer ( m_mutex
)
63 , m_bAlreadyDisposed ( false )
64 , m_bActivateListener ( false )
68 PopupMenuDispatcher::~PopupMenuDispatcher()
70 // Warn programmer if he forgot to dispose this instance.
71 // We must release all our references ...
72 // and a dtor isn't the best place to do that!
75 OUString SAL_CALL
PopupMenuDispatcher::getImplementationName() throw( css::uno::RuntimeException
, std::exception
)
77 return impl_getStaticImplementationName();
80 sal_Bool SAL_CALL
PopupMenuDispatcher::supportsService( const OUString
& sServiceName
)
81 throw( css::uno::RuntimeException
, std::exception
)
83 return cppu::supportsService(this, sServiceName
);
86 css::uno::Sequence
< OUString
> SAL_CALL
PopupMenuDispatcher::getSupportedServiceNames()
87 throw( css::uno::RuntimeException
, std::exception
)
89 return impl_getStaticSupportedServiceNames();
92 css::uno::Sequence
< OUString
> PopupMenuDispatcher::impl_getStaticSupportedServiceNames()
94 css::uno::Sequence
< OUString
> seqServiceNames( 1 );
95 seqServiceNames
.getArray() [0] = SERVICENAME_PROTOCOLHANDLER
;
96 return seqServiceNames
;
99 OUString
PopupMenuDispatcher::impl_getStaticImplementationName()
101 return IMPLEMENTATIONNAME_POPUPMENUDISPATCHER
;
104 css::uno::Reference
< css::uno::XInterface
>
105 SAL_CALL
PopupMenuDispatcher::impl_createInstance( const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xServiceManager
)
106 throw( css::uno::Exception
)
108 /* create new instance of service */
109 PopupMenuDispatcher
* pClass
= new PopupMenuDispatcher( comphelper::getComponentContext(xServiceManager
) );
110 /* hold it alive by increasing his ref count!!! */
111 css::uno::Reference
< css::uno::XInterface
> xService( static_cast< ::cppu::OWeakObject
* >(pClass
), css::uno::UNO_QUERY
);
112 /* initialize new service instance ... he can use his own refcount ... we hold it! */
113 pClass
->impl_initService();
114 /* return new created service as reference */
118 css::uno::Reference
< css::lang::XSingleServiceFactory
>
119 PopupMenuDispatcher::impl_createFactory( const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xServiceManager
)
121 css::uno::Reference
< css::lang::XSingleServiceFactory
> xReturn (
122 cppu::createSingleFactory ( xServiceManager
,
123 PopupMenuDispatcher::impl_getStaticImplementationName() ,
124 PopupMenuDispatcher::impl_createInstance
,
125 PopupMenuDispatcher::impl_getStaticSupportedServiceNames() )
130 DEFINE_INIT_SERVICE(PopupMenuDispatcher
,
133 I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
134 to create a new instance of this class by our own supported service factory.
135 see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further information!
140 void SAL_CALL
PopupMenuDispatcher::initialize( const css::uno::Sequence
< css::uno::Any
>& lArguments
)
141 throw( css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
143 css::uno::Reference
< css::frame::XFrame
> xFrame
;
146 for (int a
=0; a
<lArguments
.getLength(); ++a
)
150 lArguments
[a
] >>= xFrame
;
151 m_xWeakFrame
= xFrame
;
153 m_bActivateListener
= true;
154 uno::Reference
< css::frame::XFrameActionListener
> xFrameActionListener(
155 (OWeakObject
*)this, css::uno::UNO_QUERY
);
156 xFrame
->addFrameActionListener( xFrameActionListener
);
161 css::uno::Reference
< css::frame::XDispatch
>
162 SAL_CALL
PopupMenuDispatcher::queryDispatch(
163 const css::util::URL
& rURL
,
164 const OUString
& sTarget
,
166 throw( css::uno::RuntimeException
, std::exception
)
168 css::uno::Reference
< css::frame::XDispatch
> xDispatch
;
170 if ( rURL
.Complete
.startsWith( "vnd.sun.star.popup:" ) )
173 SolarMutexClearableGuard aGuard
;
174 impl_RetrievePopupControllerQuery();
175 impl_CreateUriRefFactory();
177 css::uno::Reference
< css::container::XNameAccess
> xPopupCtrlQuery( m_xPopupCtrlQuery
);
178 css::uno::Reference
< css::uri::XUriReferenceFactory
> xUriRefFactory( m_xUriRefFactory
);
182 if ( xPopupCtrlQuery
.is() )
186 // Just use the main part of the URL for popup menu controllers
187 sal_Int32
nQueryPart( 0 );
188 sal_Int32
nSchemePart( 0 );
189 OUString
aBaseURL( "vnd.sun.star.popup:" );
190 OUString
aURL( rURL
.Complete
);
192 nSchemePart
= aURL
.indexOf( ':' );
193 if (( nSchemePart
> 0 ) &&
194 ( aURL
.getLength() > ( nSchemePart
+1 )))
196 nQueryPart
= aURL
.indexOf( '?', nSchemePart
);
197 if ( nQueryPart
> 0 )
198 aBaseURL
+= aURL
.copy( nSchemePart
+1, nQueryPart
-(nSchemePart
+1) );
199 else if ( nQueryPart
== -1 )
200 aBaseURL
+= aURL
.copy( nSchemePart
+1 );
203 css::uno::Reference
< css::frame::XDispatchProvider
> xDispatchProvider
;
205 // Find popup menu controller using the base URL
206 xPopupCtrlQuery
->getByName( aBaseURL
) >>= xDispatchProvider
;
209 // Ask popup menu dispatch provider for dispatch object
210 if ( xDispatchProvider
.is() )
211 xDispatch
= xDispatchProvider
->queryDispatch( rURL
, sTarget
, nFlags
);
213 catch ( const RuntimeException
& )
217 catch ( const Exception
& )
225 css::uno::Sequence
< css::uno::Reference
< css::frame::XDispatch
> > SAL_CALL
226 PopupMenuDispatcher::queryDispatches(
227 const css::uno::Sequence
< css::frame::DispatchDescriptor
>& lDescriptor
)
228 throw( css::uno::RuntimeException
, std::exception
)
230 sal_Int32 nCount
= lDescriptor
.getLength();
231 css::uno::Sequence
< css::uno::Reference
< css::frame::XDispatch
> > lDispatcher( nCount
);
232 for( sal_Int32 i
=0; i
<nCount
; ++i
)
234 lDispatcher
[i
] = this->queryDispatch(
235 lDescriptor
[i
].FeatureURL
,
236 lDescriptor
[i
].FrameName
,
237 lDescriptor
[i
].SearchFlags
);
242 void SAL_CALL
PopupMenuDispatcher::dispatch( const URL
& /*aURL*/, const Sequence
< PropertyValue
>& /*seqProperties*/ )
243 throw( RuntimeException
, std::exception
)
247 void SAL_CALL
PopupMenuDispatcher::addStatusListener( const uno::Reference
< XStatusListener
>& xControl
,
249 throw( RuntimeException
, std::exception
)
252 // Safe impossible cases
253 // Add listener to container.
254 m_aListenerContainer
.addInterface( aURL
.Complete
, xControl
);
257 void SAL_CALL
PopupMenuDispatcher::removeStatusListener( const uno::Reference
< XStatusListener
>& xControl
,
259 throw( RuntimeException
, std::exception
)
262 // Safe impossible cases
263 // Add listener to container.
264 m_aListenerContainer
.removeInterface( aURL
.Complete
, xControl
);
267 void SAL_CALL
PopupMenuDispatcher::frameAction( const FrameActionEvent
& aEvent
)
268 throw ( RuntimeException
, std::exception
)
271 if (( aEvent
.Action
== css::frame::FrameAction_COMPONENT_DETACHING
) ||
272 ( aEvent
.Action
== css::frame::FrameAction_COMPONENT_ATTACHED
))
274 // Reset query reference to requery it again next time
275 m_xPopupCtrlQuery
.clear();
279 void SAL_CALL
PopupMenuDispatcher::disposing( const EventObject
& ) throw( RuntimeException
, std::exception
)
282 // Safe impossible cases
283 SAL_WARN_IF( m_bAlreadyDisposed
, "fwk", "MenuDispatcher::disposing(): Object already disposed .. don't call it again!" );
285 if( !m_bAlreadyDisposed
)
287 m_bAlreadyDisposed
= true;
289 if ( m_bActivateListener
)
291 uno::Reference
< XFrame
> xFrame( m_xWeakFrame
.get(), UNO_QUERY
);
294 xFrame
->removeFrameActionListener( uno::Reference
< XFrameActionListener
>( (OWeakObject
*)this, UNO_QUERY
));
295 m_bActivateListener
= false;
299 // Forget our factory.
300 m_xContext
= uno::Reference
< XComponentContext
>();
304 void PopupMenuDispatcher::impl_RetrievePopupControllerQuery()
306 if ( !m_xPopupCtrlQuery
.is() )
308 css::uno::Reference
< css::frame::XLayoutManager2
> xLayoutManager
;
309 css::uno::Reference
< css::frame::XFrame
> xFrame( m_xWeakFrame
);
313 css::uno::Reference
< css::beans::XPropertySet
> xPropSet( xFrame
, css::uno::UNO_QUERY
);
318 xPropSet
->getPropertyValue( FRAME_PROPNAME_LAYOUTMANAGER
) >>= xLayoutManager
;
320 if ( xLayoutManager
.is() )
322 css::uno::Reference
< css::ui::XUIElement
> xMenuBar
;
323 OUString
aMenuBar( "private:resource/menubar/menubar" );
324 xMenuBar
= xLayoutManager
->getElement( aMenuBar
);
326 m_xPopupCtrlQuery
= css::uno::Reference
< css::container::XNameAccess
>(
327 xMenuBar
, css::uno::UNO_QUERY
);
330 catch ( const css::uno::RuntimeException
& )
334 catch ( const css::uno::Exception
& )
342 void PopupMenuDispatcher::impl_CreateUriRefFactory()
344 if ( !m_xUriRefFactory
.is() )
346 m_xUriRefFactory
= css::uri::UriReferenceFactory::create( m_xContext
);
350 } // namespace framework
352 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */