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