1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 //#include "precompiled_framework.hxx"
26
27 //_________________________________________________________________________________________________________________
28 // my own includes
29 //_________________________________________________________________________________________________________________
30
31 #include <dispatch/popupmenudispatcher.hxx>
32 #include <general.h>
33 #include <framework/menuconfiguration.hxx>
34 #include <framework/addonmenu.hxx>
35 #include <services.h>
36 #include <properties.h>
37
38 //_________________________________________________________________________________________________________________
39 // interface includes
40 //_________________________________________________________________________________________________________________
41 #include <com/sun/star/frame/FrameSearchFlag.hpp>
42 #include <com/sun/star/awt/XToolkit.hpp>
43 #include <com/sun/star/awt/WindowAttribute.hpp>
44 #include <com/sun/star/awt/WindowDescriptor.hpp>
45 #include <com/sun/star/awt/PosSize.hpp>
46 #include <com/sun/star/awt/XWindowPeer.hpp>
47 #include <com/sun/star/beans/UnknownPropertyException.hpp>
48 #include <com/sun/star/lang/WrappedTargetException.hpp>
49 #include <com/sun/star/beans/XPropertySet.hpp>
50 #include <com/sun/star/container/XEnumeration.hpp>
51
52 //_________________________________________________________________________________________________________________
53 // includes of other projects
54 //_________________________________________________________________________________________________________________
55
56 #include <ucbhelper/content.hxx>
57 #include <vos/mutex.hxx>
58 #include <rtl/ustrbuf.hxx>
59 #include <vcl/svapp.hxx>
60
61 //_________________________________________________________________________________________________________________
62 // namespace
63 //_________________________________________________________________________________________________________________
64
65 namespace framework{
66
67 using namespace ::com::sun::star ;
68 using namespace ::com::sun::star::awt ;
69 using namespace ::com::sun::star::beans ;
70 using namespace ::com::sun::star::container ;
71 using namespace ::com::sun::star::frame ;
72 using namespace ::com::sun::star::lang ;
73 using namespace ::com::sun::star::uno ;
74 using namespace ::com::sun::star::util ;
75 using namespace ::cppu ;
76 using namespace ::osl ;
77 using namespace ::rtl ;
78 using namespace ::vos ;
79
80 //_________________________________________________________________________________________________________________
81 // non exported const
82 //_________________________________________________________________________________________________________________
83 const char* PROTOCOL_VALUE = "vnd.sun.star.popup:";
84 const sal_Int32 PROTOCOL_LENGTH = 19;
85
86 //_________________________________________________________________________________________________________________
87 // non exported definitions
88 //_________________________________________________________________________________________________________________
89
90 //_________________________________________________________________________________________________________________
91 // declarations
92 //_________________________________________________________________________________________________________________
93
94 //*****************************************************************************************************************
95 // constructor
96 //*****************************************************************************************************************
PopupMenuDispatcher(const uno::Reference<XMultiServiceFactory> & xFactory)97 PopupMenuDispatcher::PopupMenuDispatcher(
98 const uno::Reference< XMultiServiceFactory >& xFactory )
99 // Init baseclasses first
100 : ThreadHelpBase ( &Application::GetSolarMutex() )
101 , OWeakObject ( )
102 // Init member
103 , m_xFactory ( xFactory )
104 , m_aListenerContainer ( m_aLock.getShareableOslMutex() )
105 , m_bAlreadyDisposed ( sal_False )
106 , m_bActivateListener ( sal_False )
107 {
108 }
109
110 //*****************************************************************************************************************
111 // destructor
112 //*****************************************************************************************************************
~PopupMenuDispatcher()113 PopupMenuDispatcher::~PopupMenuDispatcher()
114 {
115 // Warn programmer if he forgot to dispose this instance.
116 // We must release all our references ...
117 // and a dtor isn't the best place to do that!
118 }
119
120 //*****************************************************************************************************************
121 // XInterface, XTypeProvider
122 //*****************************************************************************************************************
DEFINE_XINTERFACE_7(PopupMenuDispatcher,::cppu::OWeakObject,DIRECT_INTERFACE (XTypeProvider),DIRECT_INTERFACE (XServiceInfo),DIRECT_INTERFACE (XDispatchProvider),DIRECT_INTERFACE (XDispatch),DIRECT_INTERFACE (XEventListener),DIRECT_INTERFACE (XInitialization),DERIVED_INTERFACE (XFrameActionListener,XEventListener))123 DEFINE_XINTERFACE_7 ( PopupMenuDispatcher ,
124 ::cppu::OWeakObject ,
125 DIRECT_INTERFACE( XTypeProvider ),
126 DIRECT_INTERFACE( XServiceInfo ),
127 DIRECT_INTERFACE( XDispatchProvider ),
128 DIRECT_INTERFACE( XDispatch ),
129 DIRECT_INTERFACE( XEventListener ),
130 DIRECT_INTERFACE( XInitialization ),
131 DERIVED_INTERFACE( XFrameActionListener, XEventListener )
132 )
133
134 DEFINE_XTYPEPROVIDER_7 ( PopupMenuDispatcher ,
135 XTypeProvider ,
136 XServiceInfo ,
137 XDispatchProvider ,
138 XDispatch ,
139 XEventListener ,
140 XInitialization ,
141 XFrameActionListener
142 )
143
144 DEFINE_XSERVICEINFO_MULTISERVICE( PopupMenuDispatcher ,
145 ::cppu::OWeakObject ,
146 SERVICENAME_PROTOCOLHANDLER ,
147 IMPLEMENTATIONNAME_POPUPMENUDISPATCHER )
148
149 DEFINE_INIT_SERVICE(PopupMenuDispatcher,
150 {
151 /*Attention
152 I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
153 to create a new instance of this class by our own supported service factory.
154 see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
155 */
156 }
157 )
158
159 //*****************************************************************************************************************
160 // XInitialization
161 //*****************************************************************************************************************
162 void SAL_CALL PopupMenuDispatcher::initialize(
163 const css::uno::Sequence< css::uno::Any >& lArguments )
164 throw( css::uno::Exception, css::uno::RuntimeException)
165 {
166 css::uno::Reference< css::frame::XFrame > xFrame;
167
168 /* SAFE { */
169 WriteGuard aWriteLock(m_aLock);
170
171 for (int a=0; a<lArguments.getLength(); ++a)
172 {
173 if (a==0)
174 {
175 lArguments[a] >>= xFrame;
176 m_xWeakFrame = xFrame;
177
178 m_bActivateListener = sal_True;
179 uno::Reference< css::frame::XFrameActionListener > xFrameActionListener(
180 (OWeakObject *)this, css::uno::UNO_QUERY );
181 xFrame->addFrameActionListener( xFrameActionListener );
182 }
183 }
184
185 aWriteLock.unlock();
186 /* } SAFE */
187 }
188
189 //*****************************************************************************************************************
190 // XDispatchProvider
191 //*****************************************************************************************************************
192 css::uno::Reference< css::frame::XDispatch >
queryDispatch(const css::util::URL & rURL,const::rtl::OUString & sTarget,sal_Int32 nFlags)193 SAL_CALL PopupMenuDispatcher::queryDispatch(
194 const css::util::URL& rURL ,
195 const ::rtl::OUString& sTarget ,
196 sal_Int32 nFlags )
197 throw( css::uno::RuntimeException )
198 {
199 css::uno::Reference< css::frame::XDispatch > xDispatch;
200
201 if ( rURL.Complete.compareToAscii( PROTOCOL_VALUE, PROTOCOL_LENGTH ) == 0 )
202 {
203 // --- SAFE ---
204 ResetableGuard aGuard( m_aLock );
205 impl_RetrievePopupControllerQuery();
206 impl_CreateUriRefFactory();
207
208 css::uno::Reference< css::container::XNameAccess > xPopupCtrlQuery( m_xPopupCtrlQuery );
209 css::uno::Reference< css::uri::XUriReferenceFactory > xUriRefFactory( m_xUriRefFactory );
210 aGuard.unlock();
211 // --- SAFE ---
212
213 if ( xPopupCtrlQuery.is() )
214 {
215 try
216 {
217 // Just use the main part of the URL for popup menu controllers
218 sal_Int32 nQueryPart( 0 );
219 sal_Int32 nSchemePart( 0 );
220 rtl::OUString aBaseURL( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.popup:" ));
221 rtl::OUString aURL( rURL.Complete );
222
223 nSchemePart = aURL.indexOf( ':' );
224 if (( nSchemePart > 0 ) &&
225 ( aURL.getLength() > ( nSchemePart+1 )))
226 {
227 nQueryPart = aURL.indexOf( '?', nSchemePart );
228 if ( nQueryPart > 0 )
229 aBaseURL += aURL.copy( nSchemePart+1, nQueryPart-(nSchemePart+1) );
230 else if ( nQueryPart == -1 )
231 aBaseURL += aURL.copy( nSchemePart+1 );
232 }
233
234 css::uno::Reference< css::frame::XDispatchProvider > xDispatchProvider;
235
236 // Find popup menu controller using the base URL
237 xPopupCtrlQuery->getByName( aBaseURL ) >>= xDispatchProvider;
238 aGuard.unlock();
239
240 // Ask popup menu dispatch provider for dispatch object
241 if ( xDispatchProvider.is() )
242 xDispatch = xDispatchProvider->queryDispatch( rURL, sTarget, nFlags );
243 }
244 catch ( RuntimeException& )
245 {
246 throw;
247 }
248 catch ( Exception& )
249 {
250 }
251 }
252 }
253 return xDispatch;
254 }
255
256 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL
queryDispatches(const css::uno::Sequence<css::frame::DispatchDescriptor> & lDescriptor)257 PopupMenuDispatcher::queryDispatches(
258 const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor )
259 throw( css::uno::RuntimeException )
260 {
261 sal_Int32 nCount = lDescriptor.getLength();
262 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatcher( nCount );
263 for( sal_Int32 i=0; i<nCount; ++i )
264 {
265 lDispatcher[i] = this->queryDispatch(
266 lDescriptor[i].FeatureURL,
267 lDescriptor[i].FrameName,
268 lDescriptor[i].SearchFlags);
269 }
270 return lDispatcher;
271 }
272
273 //*****************************************************************************************************************
274 // XDispatch
275 //*****************************************************************************************************************
276 void
dispatch(const URL &,const Sequence<PropertyValue> &)277 SAL_CALL PopupMenuDispatcher::dispatch(
278 const URL& /*aURL*/ ,
279 const Sequence< PropertyValue >& /*seqProperties*/ )
280 throw( RuntimeException )
281 {
282 }
283
284 //*****************************************************************************************************************
285 // XDispatch
286 //*****************************************************************************************************************
287 void
addStatusListener(const uno::Reference<XStatusListener> & xControl,const URL & aURL)288 SAL_CALL PopupMenuDispatcher::addStatusListener(
289 const uno::Reference< XStatusListener >& xControl,
290 const URL& aURL )
291 throw( RuntimeException )
292 {
293 // Ready for multithreading
294 ResetableGuard aGuard( m_aLock );
295 // Safe impossible cases
296 // Add listener to container.
297 m_aListenerContainer.addInterface( aURL.Complete, xControl );
298 }
299
300 //*****************************************************************************************************************
301 // XDispatch
302 //*****************************************************************************************************************
303 void
removeStatusListener(const uno::Reference<XStatusListener> & xControl,const URL & aURL)304 SAL_CALL PopupMenuDispatcher::removeStatusListener(
305 const uno::Reference< XStatusListener >& xControl,
306 const URL& aURL )
307 throw( RuntimeException )
308 {
309 // Ready for multithreading
310 ResetableGuard aGuard( m_aLock );
311 // Safe impossible cases
312 // Add listener to container.
313 m_aListenerContainer.removeInterface( aURL.Complete, xControl );
314 }
315
316 //*****************************************************************************************************************
317 // XFrameActionListener
318 //*****************************************************************************************************************
319
320 void
frameAction(const FrameActionEvent & aEvent)321 SAL_CALL PopupMenuDispatcher::frameAction(
322 const FrameActionEvent& aEvent )
323 throw ( RuntimeException )
324 {
325 ResetableGuard aGuard( m_aLock );
326
327 if (( aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING ) ||
328 ( aEvent.Action == css::frame::FrameAction_COMPONENT_ATTACHED ))
329 {
330 // Reset query reference to requery it again next time
331 m_xPopupCtrlQuery.clear();
332 }
333 }
334
335 //*****************************************************************************************************************
336 // XEventListener
337 //*****************************************************************************************************************
338 void
disposing(const EventObject &)339 SAL_CALL PopupMenuDispatcher::disposing( const EventObject& ) throw( RuntimeException )
340 {
341 // Ready for multithreading
342 ResetableGuard aGuard( m_aLock );
343 // Safe impossible cases
344 LOG_ASSERT( !(m_bAlreadyDisposed==sal_True), "MenuDispatcher::disposing()\nObject already disposed .. don't call it again!\n" )
345
346 if( m_bAlreadyDisposed == sal_False )
347 {
348 m_bAlreadyDisposed = sal_True;
349
350 if ( m_bActivateListener )
351 {
352 uno::Reference< XFrame > xFrame( m_xWeakFrame.get(), UNO_QUERY );
353 if ( xFrame.is() )
354 {
355 xFrame->removeFrameActionListener( uno::Reference< XFrameActionListener >( (OWeakObject *)this, UNO_QUERY ));
356 m_bActivateListener = sal_False;
357 }
358 }
359
360 // Forget our factory.
361 m_xFactory = uno::Reference< XMultiServiceFactory >();
362 }
363 }
364
impl_RetrievePopupControllerQuery()365 void PopupMenuDispatcher::impl_RetrievePopupControllerQuery()
366 {
367 if ( !m_xPopupCtrlQuery.is() )
368 {
369 css::uno::Reference< css::frame::XLayoutManager > xLayoutManager;
370 css::uno::Reference< css::frame::XFrame > xFrame( m_xWeakFrame );
371
372 if ( xFrame.is() )
373 {
374 css::uno::Reference< css::beans::XPropertySet > xPropSet( xFrame, css::uno::UNO_QUERY );
375 if ( xPropSet.is() )
376 {
377 try
378 {
379 xPropSet->getPropertyValue( FRAME_PROPNAME_LAYOUTMANAGER ) >>= xLayoutManager;
380
381 if ( xLayoutManager.is() )
382 {
383 css::uno::Reference< css::ui::XUIElement > xMenuBar;
384 rtl::OUString aMenuBar( RTL_CONSTASCII_USTRINGPARAM( "private:resource/menubar/menubar" ));
385 xMenuBar = xLayoutManager->getElement( aMenuBar );
386
387 m_xPopupCtrlQuery = css::uno::Reference< css::container::XNameAccess >(
388 xMenuBar, css::uno::UNO_QUERY );
389 }
390 }
391 catch ( css::uno::RuntimeException& )
392 {
393 throw;
394 }
395 catch ( css::uno::Exception& )
396 {
397 }
398 }
399 }
400 }
401 }
402
impl_CreateUriRefFactory()403 void PopupMenuDispatcher::impl_CreateUriRefFactory()
404 {
405 if ( !m_xUriRefFactory.is() )
406 {
407 rtl::OUString aUriRefFactoryService(
408 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.uri.UriReferenceFactory" ));
409
410 m_xUriRefFactory = css::uno::Reference< css::uri::XUriReferenceFactory >(
411 m_xFactory->createInstance( aUriRefFactoryService ),
412 css::uno::UNO_QUERY);
413
414 }
415 }
416
417 } // namespace framework
418