xref: /trunk/main/framework/source/dispatch/popupmenudispatcher.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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