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 {
165 css::uno::Reference< css::frame::XFrame > xFrame;
166
167 /* SAFE { */
168 WriteGuard aWriteLock(m_aLock);
169
170 for (int a=0; a<lArguments.getLength(); ++a)
171 {
172 if (a==0)
173 {
174 lArguments[a] >>= xFrame;
175 m_xWeakFrame = xFrame;
176
177 m_bActivateListener = sal_True;
178 uno::Reference< css::frame::XFrameActionListener > xFrameActionListener(
179 (OWeakObject *)this, css::uno::UNO_QUERY );
180 xFrame->addFrameActionListener( xFrameActionListener );
181 }
182 }
183
184 aWriteLock.unlock();
185 /* } SAFE */
186 }
187
188 //*****************************************************************************************************************
189 // XDispatchProvider
190 //*****************************************************************************************************************
191 css::uno::Reference< css::frame::XDispatch >
queryDispatch(const css::util::URL & rURL,const::rtl::OUString & sTarget,sal_Int32 nFlags)192 SAL_CALL PopupMenuDispatcher::queryDispatch(
193 const css::util::URL& rURL ,
194 const ::rtl::OUString& sTarget ,
195 sal_Int32 nFlags )
196 {
197 css::uno::Reference< css::frame::XDispatch > xDispatch;
198
199 if ( rURL.Complete.compareToAscii( PROTOCOL_VALUE, PROTOCOL_LENGTH ) == 0 )
200 {
201 // --- SAFE ---
202 ResetableGuard aGuard( m_aLock );
203 impl_RetrievePopupControllerQuery();
204 impl_CreateUriRefFactory();
205
206 css::uno::Reference< css::container::XNameAccess > xPopupCtrlQuery( m_xPopupCtrlQuery );
207 css::uno::Reference< css::uri::XUriReferenceFactory > xUriRefFactory( m_xUriRefFactory );
208 aGuard.unlock();
209 // --- SAFE ---
210
211 if ( xPopupCtrlQuery.is() )
212 {
213 try
214 {
215 // Just use the main part of the URL for popup menu controllers
216 sal_Int32 nQueryPart( 0 );
217 sal_Int32 nSchemePart( 0 );
218 rtl::OUString aBaseURL( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.popup:" ));
219 rtl::OUString aURL( rURL.Complete );
220
221 nSchemePart = aURL.indexOf( ':' );
222 if (( nSchemePart > 0 ) &&
223 ( aURL.getLength() > ( nSchemePart+1 )))
224 {
225 nQueryPart = aURL.indexOf( '?', nSchemePart );
226 if ( nQueryPart > 0 )
227 aBaseURL += aURL.copy( nSchemePart+1, nQueryPart-(nSchemePart+1) );
228 else if ( nQueryPart == -1 )
229 aBaseURL += aURL.copy( nSchemePart+1 );
230 }
231
232 css::uno::Reference< css::frame::XDispatchProvider > xDispatchProvider;
233
234 // Find popup menu controller using the base URL
235 xPopupCtrlQuery->getByName( aBaseURL ) >>= xDispatchProvider;
236 aGuard.unlock();
237
238 // Ask popup menu dispatch provider for dispatch object
239 if ( xDispatchProvider.is() )
240 xDispatch = xDispatchProvider->queryDispatch( rURL, sTarget, nFlags );
241 }
242 catch ( RuntimeException& )
243 {
244 throw;
245 }
246 catch ( Exception& )
247 {
248 }
249 }
250 }
251 return xDispatch;
252 }
253
254 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL
queryDispatches(const css::uno::Sequence<css::frame::DispatchDescriptor> & lDescriptor)255 PopupMenuDispatcher::queryDispatches(
256 const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor )
257 {
258 sal_Int32 nCount = lDescriptor.getLength();
259 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatcher( nCount );
260 for( sal_Int32 i=0; i<nCount; ++i )
261 {
262 lDispatcher[i] = this->queryDispatch(
263 lDescriptor[i].FeatureURL,
264 lDescriptor[i].FrameName,
265 lDescriptor[i].SearchFlags);
266 }
267 return lDispatcher;
268 }
269
270 //*****************************************************************************************************************
271 // XDispatch
272 //*****************************************************************************************************************
273 void
dispatch(const URL &,const Sequence<PropertyValue> &)274 SAL_CALL PopupMenuDispatcher::dispatch(
275 const URL& /*aURL*/ ,
276 const Sequence< PropertyValue >& /*seqProperties*/ )
277 {
278 }
279
280 //*****************************************************************************************************************
281 // XDispatch
282 //*****************************************************************************************************************
283 void
addStatusListener(const uno::Reference<XStatusListener> & xControl,const URL & aURL)284 SAL_CALL PopupMenuDispatcher::addStatusListener(
285 const uno::Reference< XStatusListener >& xControl,
286 const URL& aURL )
287 {
288 // Ready for multithreading
289 ResetableGuard aGuard( m_aLock );
290 // Safe impossible cases
291 // Add listener to container.
292 m_aListenerContainer.addInterface( aURL.Complete, xControl );
293 }
294
295 //*****************************************************************************************************************
296 // XDispatch
297 //*****************************************************************************************************************
298 void
removeStatusListener(const uno::Reference<XStatusListener> & xControl,const URL & aURL)299 SAL_CALL PopupMenuDispatcher::removeStatusListener(
300 const uno::Reference< XStatusListener >& xControl,
301 const URL& aURL )
302 {
303 // Ready for multithreading
304 ResetableGuard aGuard( m_aLock );
305 // Safe impossible cases
306 // Add listener to container.
307 m_aListenerContainer.removeInterface( aURL.Complete, xControl );
308 }
309
310 //*****************************************************************************************************************
311 // XFrameActionListener
312 //*****************************************************************************************************************
313
314 void
frameAction(const FrameActionEvent & aEvent)315 SAL_CALL PopupMenuDispatcher::frameAction(
316 const FrameActionEvent& aEvent )
317 {
318 ResetableGuard aGuard( m_aLock );
319
320 if (( aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING ) ||
321 ( aEvent.Action == css::frame::FrameAction_COMPONENT_ATTACHED ))
322 {
323 // Reset query reference to requery it again next time
324 m_xPopupCtrlQuery.clear();
325 }
326 }
327
328 //*****************************************************************************************************************
329 // XEventListener
330 //*****************************************************************************************************************
331 void
disposing(const EventObject &)332 SAL_CALL PopupMenuDispatcher::disposing( const EventObject& )
333 {
334 // Ready for multithreading
335 ResetableGuard aGuard( m_aLock );
336 // Safe impossible cases
337 LOG_ASSERT( !(m_bAlreadyDisposed==sal_True), "MenuDispatcher::disposing()\nObject already disposed .. don't call it again!\n" )
338
339 if( m_bAlreadyDisposed == sal_False )
340 {
341 m_bAlreadyDisposed = sal_True;
342
343 if ( m_bActivateListener )
344 {
345 uno::Reference< XFrame > xFrame( m_xWeakFrame.get(), UNO_QUERY );
346 if ( xFrame.is() )
347 {
348 xFrame->removeFrameActionListener( uno::Reference< XFrameActionListener >( (OWeakObject *)this, UNO_QUERY ));
349 m_bActivateListener = sal_False;
350 }
351 }
352
353 // Forget our factory.
354 m_xFactory = uno::Reference< XMultiServiceFactory >();
355 }
356 }
357
impl_RetrievePopupControllerQuery()358 void PopupMenuDispatcher::impl_RetrievePopupControllerQuery()
359 {
360 if ( !m_xPopupCtrlQuery.is() )
361 {
362 css::uno::Reference< css::frame::XLayoutManager > xLayoutManager;
363 css::uno::Reference< css::frame::XFrame > xFrame( m_xWeakFrame );
364
365 if ( xFrame.is() )
366 {
367 css::uno::Reference< css::beans::XPropertySet > xPropSet( xFrame, css::uno::UNO_QUERY );
368 if ( xPropSet.is() )
369 {
370 try
371 {
372 xPropSet->getPropertyValue( FRAME_PROPNAME_LAYOUTMANAGER ) >>= xLayoutManager;
373
374 if ( xLayoutManager.is() )
375 {
376 css::uno::Reference< css::ui::XUIElement > xMenuBar;
377 rtl::OUString aMenuBar( RTL_CONSTASCII_USTRINGPARAM( "private:resource/menubar/menubar" ));
378 xMenuBar = xLayoutManager->getElement( aMenuBar );
379
380 m_xPopupCtrlQuery = css::uno::Reference< css::container::XNameAccess >(
381 xMenuBar, css::uno::UNO_QUERY );
382 }
383 }
384 catch ( css::uno::RuntimeException& )
385 {
386 throw;
387 }
388 catch ( css::uno::Exception& )
389 {
390 }
391 }
392 }
393 }
394 }
395
impl_CreateUriRefFactory()396 void PopupMenuDispatcher::impl_CreateUriRefFactory()
397 {
398 if ( !m_xUriRefFactory.is() )
399 {
400 rtl::OUString aUriRefFactoryService(
401 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.uri.UriReferenceFactory" ));
402
403 m_xUriRefFactory = css::uno::Reference< css::uri::XUriReferenceFactory >(
404 m_xFactory->createInstance( aUriRefFactoryService ),
405 css::uno::UNO_QUERY);
406
407 }
408 }
409
410 } // namespace framework
411