xref: /AOO41X/main/framework/source/dispatch/menudispatcher.cxx (revision 6d739b60ff8f4ed2134ae1442e284f9da90334b4)
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 #include <dispatch/menudispatcher.hxx>
31 #include <general.h>
32 #include <framework/menuconfiguration.hxx>
33 #include <framework/addonmenu.hxx>
34 #include <services.h>
35 
36 //_________________________________________________________________________________________________________________
37 //  interface includes
38 //_________________________________________________________________________________________________________________
39 #include <com/sun/star/frame/FrameSearchFlag.hpp>
40 #include <com/sun/star/awt/XToolkit.hpp>
41 #include <com/sun/star/awt/WindowAttribute.hpp>
42 #include <com/sun/star/awt/WindowDescriptor.hpp>
43 #include <com/sun/star/awt/PosSize.hpp>
44 #include <com/sun/star/awt/XWindowPeer.hpp>
45 #include <com/sun/star/beans/UnknownPropertyException.hpp>
46 #include <com/sun/star/lang/WrappedTargetException.hpp>
47 #include <com/sun/star/beans/XPropertySet.hpp>
48 #include <com/sun/star/container/XEnumeration.hpp>
49 #include <com/sun/star/util/XURLTransformer.hpp>
50 
51 #include <vcl/window.hxx>
52 #include <vcl/syswin.hxx>
53 #include <vcl/menu.hxx>
54 #include <vcl/svapp.hxx>
55 #include <tools/resmgr.hxx>
56 #include <tools/rcid.h>
57 #include <vos/mutex.hxx>
58 #include <toolkit/helper/vclunohelper.hxx>
59 #include <rtl/logfile.hxx>
60 
61 //_________________________________________________________________________________________________________________
62 //  includes of other projects
63 //_________________________________________________________________________________________________________________
64 
65 #include <ucbhelper/content.hxx>
66 
67 //_________________________________________________________________________________________________________________
68 //  namespace
69 //_________________________________________________________________________________________________________________
70 
71 namespace framework{
72 
73 using namespace ::com::sun::star                ;
74 using namespace ::com::sun::star::awt           ;
75 using namespace ::com::sun::star::beans         ;
76 using namespace ::com::sun::star::container     ;
77 using namespace ::com::sun::star::frame         ;
78 using namespace ::com::sun::star::lang          ;
79 using namespace ::com::sun::star::uno           ;
80 using namespace ::com::sun::star::util          ;
81 using namespace ::cppu                          ;
82 using namespace ::osl                           ;
83 using namespace ::rtl                           ;
84 using namespace ::vos                           ;
85 
86 //_________________________________________________________________________________________________________________
87 //  non exported const
88 //_________________________________________________________________________________________________________________
89 
90 const sal_uInt16 SLOTID_MDIWINDOWLIST = 5610;
91 
92 //_________________________________________________________________________________________________________________
93 //  non exported definitions
94 //_________________________________________________________________________________________________________________
95 
96 //_________________________________________________________________________________________________________________
97 //  declarations
98 //_________________________________________________________________________________________________________________
99 
100 //*****************************************************************************************************************
101 //  constructor
102 //*****************************************************************************************************************
MenuDispatcher(const uno::Reference<XMultiServiceFactory> & xFactory,const uno::Reference<XFrame> & xOwner)103 MenuDispatcher::MenuDispatcher(   const   uno::Reference< XMultiServiceFactory >&  xFactory    ,
104                                     const   uno::Reference< XFrame >&               xOwner      )
105         //  Init baseclasses first
106         :   ThreadHelpBase          ( &Application::GetSolarMutex()  )
107         ,   OWeakObject             (                                )
108         // Init member
109         ,   m_xOwnerWeak            ( xOwner                         )
110         ,   m_xFactory              ( xFactory                       )
111         ,   m_aListenerContainer    ( m_aLock.getShareableOslMutex() )
112         ,   m_bAlreadyDisposed      ( sal_False                      )
113         ,   m_bActivateListener     ( sal_False                      )
114         ,   m_pMenuManager          ( NULL                           )
115 {
116     // Safe impossible cases
117     // We need valid informations about ouer ownerfor work.
118     LOG_ASSERT( impldbg_checkParameter_MenuDispatcher( xFactory, xOwner ), "MenuDispatcher::MenuDispatcher()\nInvalid parameter detected!\n" )
119 
120     m_bActivateListener = sal_True;
121     xOwner->addFrameActionListener( uno::Reference< XFrameActionListener >( (OWeakObject *)this, UNO_QUERY ));
122 }
123 
124 //*****************************************************************************************************************
125 //  destructor
126 //*****************************************************************************************************************
~MenuDispatcher()127 MenuDispatcher::~MenuDispatcher()
128 {
129     // Warn programmer if he forgot to dispose this instance.
130     // We must release all our references ...
131     // and a dtor isn't the best place to do that!
132 }
133 
134 //*****************************************************************************************************************
135 //  XInterface, XTypeProvider
136 //*****************************************************************************************************************
DEFINE_XINTERFACE_4(MenuDispatcher,OWeakObject,DIRECT_INTERFACE (XTypeProvider),DIRECT_INTERFACE (XDispatch),DIRECT_INTERFACE (XEventListener),DERIVED_INTERFACE (XFrameActionListener,XEventListener))137 DEFINE_XINTERFACE_4     (   MenuDispatcher                     ,
138                             OWeakObject                         ,
139                             DIRECT_INTERFACE(   XTypeProvider   ),
140                             DIRECT_INTERFACE(   XDispatch       ),
141                             DIRECT_INTERFACE(   XEventListener  ),
142                             DERIVED_INTERFACE(  XFrameActionListener, XEventListener )
143                         )
144 
145 DEFINE_XTYPEPROVIDER_4  (   MenuDispatcher     ,
146                             XTypeProvider       ,
147                             XDispatch           ,
148                             XEventListener      ,
149                             XFrameActionListener
150                         )
151 
152 
153 //*****************************************************************************************************************
154 //  XDispatch
155 //*****************************************************************************************************************
156 void SAL_CALL MenuDispatcher::dispatch(    const   URL&                        /*aURL*/            ,
157                                             const   Sequence< PropertyValue >&  /*seqProperties*/   ) throw( RuntimeException )
158 {
159 }
160 
161 //*****************************************************************************************************************
162 //  XDispatch
163 //*****************************************************************************************************************
addStatusListener(const uno::Reference<XStatusListener> & xControl,const URL & aURL)164 void SAL_CALL MenuDispatcher::addStatusListener(   const   uno::Reference< XStatusListener >&   xControl,
165                                                     const   URL&                            aURL    ) throw( RuntimeException )
166 {
167     // Ready for multithreading
168     ResetableGuard aGuard( m_aLock );
169     // Safe impossible cases
170     // Method not defined for all incoming parameter
171     LOG_ASSERT( impldbg_checkParameter_addStatusListener( xControl, aURL ), "MenuDispatcher::addStatusListener()\nInvalid parameter detected.\n" )
172     // Add listener to container.
173     m_aListenerContainer.addInterface( aURL.Complete, xControl );
174 }
175 
176 //*****************************************************************************************************************
177 //  XDispatch
178 //*****************************************************************************************************************
removeStatusListener(const uno::Reference<XStatusListener> & xControl,const URL & aURL)179 void SAL_CALL MenuDispatcher::removeStatusListener(    const   uno::Reference< XStatusListener >&   xControl,
180                                                         const   URL&                            aURL    ) throw( RuntimeException )
181 {
182     // Ready for multithreading
183     ResetableGuard aGuard( m_aLock );
184     // Safe impossible cases
185     // Method not defined for all incoming parameter
186     LOG_ASSERT( impldbg_checkParameter_removeStatusListener( xControl, aURL ), "MenuDispatcher::removeStatusListener()\nInvalid parameter detected.\n" )
187     // Add listener to container.
188     m_aListenerContainer.removeInterface( aURL.Complete, xControl );
189 }
190 
191 //*****************************************************************************************************************
192 //   XFrameActionListener
193 //*****************************************************************************************************************
194 
frameAction(const FrameActionEvent & aEvent)195 void SAL_CALL MenuDispatcher::frameAction( const FrameActionEvent& aEvent ) throw ( RuntimeException )
196 {
197     ResetableGuard aGuard( m_aLock );
198 
199     if ( m_pMenuManager && aEvent.Action == FrameAction_FRAME_UI_ACTIVATED )
200     {
201         MenuBar* pMenuBar = (MenuBar *)m_pMenuManager->GetMenu();
202         uno::Reference< XFrame > xFrame( m_xOwnerWeak.get(), UNO_QUERY );
203         aGuard.unlock();
204 
205         if ( xFrame.is() && pMenuBar )
206         {
207             uno::Reference< ::com::sun::star::awt::XWindow >xContainerWindow = xFrame->getContainerWindow();
208 
209             OGuard aSolarGuard( Application::GetSolarMutex() );
210             {
211                 Window* pWindow = VCLUnoHelper::GetWindow( xContainerWindow );
212                 while ( pWindow && !pWindow->IsSystemWindow() )
213                     pWindow = pWindow->GetParent();
214 
215                 if ( pWindow )
216                 {
217                     SystemWindow* pSysWindow = (SystemWindow *)pWindow;
218                     pSysWindow->SetMenuBar( pMenuBar );
219                 }
220             }
221         }
222     }
223     else if ( m_pMenuManager && aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING )
224     {
225         if ( m_pMenuManager )
226             impl_setMenuBar( NULL );
227     }
228 }
229 
230 //*****************************************************************************************************************
231 //   XEventListener
232 //*****************************************************************************************************************
disposing(const EventObject &)233 void SAL_CALL MenuDispatcher::disposing( const EventObject& ) throw( RuntimeException )
234 {
235     // Ready for multithreading
236     ResetableGuard aGuard( m_aLock );
237     // Safe impossible cases
238     LOG_ASSERT( !(m_bAlreadyDisposed==sal_True), "MenuDispatcher::disposing()\nObject already disposed .. don't call it again!\n" )
239 
240     if( m_bAlreadyDisposed == sal_False )
241     {
242         m_bAlreadyDisposed = sal_True;
243 
244         if ( m_bActivateListener )
245         {
246             uno::Reference< XFrame > xFrame( m_xOwnerWeak.get(), UNO_QUERY );
247             if ( xFrame.is() )
248             {
249                 xFrame->removeFrameActionListener( uno::Reference< XFrameActionListener >( (OWeakObject *)this, UNO_QUERY ));
250                 m_bActivateListener = sal_False;
251                 if ( m_pMenuManager )
252                 {
253                     EventObject aEventObj;
254                     aEventObj.Source = xFrame;
255                     m_pMenuManager->disposing( aEventObj );
256                 }
257             }
258         }
259 
260         // Forget our factory.
261         m_xFactory = uno::Reference< XMultiServiceFactory >();
262 
263         // Remove our menu from system window if it is still there!
264         if ( m_pMenuManager )
265             impl_setMenuBar( NULL );
266     }
267 }
268 
269 //*****************************************************************************************************************
270 //  private method
271 //
272 //
273 //*****************************************************************************************************************
impl_setAccelerators(Menu * pMenu,const Accelerator & aAccel)274 void MenuDispatcher::impl_setAccelerators( Menu* pMenu, const Accelerator& aAccel )
275 {
276     for ( sal_uInt16 nPos = 0; nPos < pMenu->GetItemCount(); ++nPos )
277     {
278         sal_uInt16     nId    = pMenu->GetItemId(nPos);
279         PopupMenu* pPopup = pMenu->GetPopupMenu(nId);
280         if ( pPopup )
281             impl_setAccelerators( (Menu *)pPopup, aAccel );
282         else if ( nId && !pMenu->GetPopupMenu(nId))
283         {
284             KeyCode aCode = aAccel.GetKeyCode( nId );
285             if ( aCode.GetCode() )
286                 pMenu->SetAccelKey( nId, aCode );
287         }
288     }
289 }
290 
291 //*****************************************************************************************************************
292 //  private method
293 //
294 //
295 //*****************************************************************************************************************
impl_setMenuBar(MenuBar * pMenuBar,sal_Bool bMenuFromResource)296 sal_Bool MenuDispatcher::impl_setMenuBar( MenuBar* pMenuBar, sal_Bool bMenuFromResource )
297 {
298     uno::Reference< XFrame > xFrame( m_xOwnerWeak.get(), UNO_QUERY );
299     if ( xFrame.is() )
300     {
301         uno::Reference< ::com::sun::star::awt::XWindow >xContainerWindow = xFrame->getContainerWindow();
302         Window* pWindow = NULL;
303 
304         // Use SolarMutex for threadsafe code too!
305         OGuard aSolarGuard( Application::GetSolarMutex() );
306         {
307             pWindow = VCLUnoHelper::GetWindow( xContainerWindow );
308             while ( pWindow && !pWindow->IsSystemWindow() )
309                 pWindow = pWindow->GetParent();
310         }
311 
312         if ( pWindow )
313         {
314             // Ready for multithreading
315             ResetableGuard aGuard( m_aLock );
316 
317             SystemWindow* pSysWindow = (SystemWindow *)pWindow;
318 
319             if ( m_pMenuManager )
320             {
321                 // remove old menu from our system window if it was set before
322                 if ( m_pMenuManager->GetMenu() == (Menu *)pSysWindow->GetMenuBar() )
323                     pSysWindow->SetMenuBar( NULL );
324 
325                 // remove listener before we destruct ourself, so we cannot be called back afterwards
326                 m_pMenuManager->RemoveListener();
327 
328                 SAL_STATIC_CAST( ::com::sun::star::uno::XInterface*, (OWeakObject*)m_pMenuManager )->release();
329 
330                 m_pMenuManager = 0;
331             }
332 
333             if ( pMenuBar != NULL )
334             {
335                 sal_uInt16 nPos = pMenuBar->GetItemPos( SLOTID_MDIWINDOWLIST );
336                 if ( nPos != MENU_ITEM_NOTFOUND )
337                 {
338                     OUString aNoContext;
339 
340                     uno::Reference< XModel >            xModel;
341                     uno::Reference< XController >   xController( xFrame->getController(), UNO_QUERY );
342 
343                     if ( xController.is() )
344                         xModel = uno::Reference< XModel >( xController->getModel(), UNO_QUERY );
345 
346                     // retrieve addon popup menus and add them to our menu bar
347                     AddonMenuManager::MergeAddonPopupMenus( xFrame, xModel, nPos, pMenuBar );
348 
349                     // retrieve addon help menu items and add them to our help menu
350                     AddonMenuManager::MergeAddonHelpMenu( xFrame, pMenuBar );
351                 }
352 
353                 // set new menu on our system window and create new menu manager
354                 if ( bMenuFromResource )
355                 {
356                     // #110897#
357                     // m_pMenuManager = new MenuManager( xFrame, pMenuBar, sal_True, sal_False );
358                     m_pMenuManager = new MenuManager( m_xFactory, xFrame, pMenuBar, sal_True, sal_False );
359                 }
360                 else
361                 {
362                     // #110897#
363                     // m_pMenuManager = new MenuManager( xFrame, pMenuBar, sal_True, sal_True );
364                     m_pMenuManager = new MenuManager( m_xFactory, xFrame, pMenuBar, sal_True, sal_True );
365                 }
366 
367                 pSysWindow->SetMenuBar( pMenuBar );
368             }
369 
370             return sal_True;
371         }
372     }
373 
374     return sal_False;
375 }
376 
IMPL_LINK(MenuDispatcher,Close_Impl,void *,EMPTYARG)377 IMPL_LINK( MenuDispatcher, Close_Impl, void*, EMPTYARG )
378 {
379     css::uno::Reference < css::frame::XFrame > xFrame( m_xOwnerWeak.get(), css::uno::UNO_QUERY );
380     if ( !xFrame.is() )
381         return 0;
382 
383     css::util::URL aURL;
384     aURL.Complete = ::rtl::OUString::createFromAscii(".uno:CloseWin");
385     css::uno::Reference< css::util::XURLTransformer >  xTrans ( m_xFactory->createInstance(
386                         SERVICENAME_URLTRANSFORMER ), css::uno::UNO_QUERY );
387     if( xTrans.is() )
388     {
389         // Datei laden
390         xTrans->parseStrict( aURL );
391         uno::Reference< XDispatchProvider > xProv( xFrame, UNO_QUERY );
392         if ( xProv.is() )
393         {
394             css::uno::Reference < css::frame::XDispatch > aDisp = xProv->queryDispatch( aURL, ::rtl::OUString(), 0 );
395             if ( aDisp.is() )
396                 aDisp->dispatch( aURL, css::uno::Sequence < css::beans::PropertyValue>() );
397         }
398     }
399 
400     return 0;
401 }
402 
403 
404 //_________________________________________________________________________________________________________________
405 //  debug methods
406 //_________________________________________________________________________________________________________________
407 
408 /*-----------------------------------------------------------------------------------------------------------------
409     The follow methods checks the parameter for other functions. If a parameter or his value is non valid,
410     we return "sal_False". (else sal_True) This mechanism is used to throw an ASSERT!
411 
412     ATTENTION
413 
414         If you miss a test for one of this parameters, contact the autor or add it himself !(?)
415         But ... look for right testing! See using of this methods!
416 -----------------------------------------------------------------------------------------------------------------*/
417 
418 #ifdef ENABLE_ASSERTIONS
419 
420 //*****************************************************************************************************************
impldbg_checkParameter_MenuDispatcher(const uno::Reference<XMultiServiceFactory> & xFactory,const uno::Reference<XFrame> & xOwner)421 sal_Bool MenuDispatcher::impldbg_checkParameter_MenuDispatcher(   const   uno::Reference< XMultiServiceFactory >&  xFactory    ,
422                                                                         const   uno::Reference< XFrame >&               xOwner      )
423 {
424     // Set default return value.
425     sal_Bool bOK = sal_True;
426     // Check parameter.
427     if  (
428             ( &xFactory     ==  NULL        )   ||
429             ( &xOwner       ==  NULL        )   ||
430             ( xFactory.is() ==  sal_False   )   ||
431             ( xOwner.is()   ==  sal_False   )
432         )
433     {
434         bOK = sal_False ;
435     }
436     // Return result of check.
437     return bOK ;
438 }
439 
440 //*****************************************************************************************************************
441 // We need a valid URL. What is meaning with "register for nothing"?!
442 // xControl must correct to - nobody can advised otherwise!
impldbg_checkParameter_addStatusListener(const uno::Reference<XStatusListener> & xControl,const URL & aURL)443 sal_Bool MenuDispatcher::impldbg_checkParameter_addStatusListener( const   uno::Reference< XStatusListener >&   xControl,
444                                                                         const   URL&                            aURL    )
445 {
446     // Set default return value.
447     sal_Bool bOK = sal_True;
448     // Check parameter.
449     if  (
450             ( &xControl                 ==  NULL    )   ||
451             ( &aURL                     ==  NULL    )   ||
452             ( aURL.Complete.getLength() <   1       )
453         )
454     {
455         bOK = sal_False ;
456     }
457     // Return result of check.
458     return bOK ;
459 }
460 
461 //*****************************************************************************************************************
462 // The same goes for these case! We have added valid listener for correct URL only.
463 // We can't remove invalid listener for nothing!
impldbg_checkParameter_removeStatusListener(const uno::Reference<XStatusListener> & xControl,const URL & aURL)464 sal_Bool MenuDispatcher::impldbg_checkParameter_removeStatusListener(  const   uno::Reference< XStatusListener >&   xControl,
465                                                                             const   URL&                            aURL    )
466 {
467     // Set default return value.
468     sal_Bool bOK = sal_True;
469     // Check parameter.
470     if  (
471             ( &xControl                 ==  NULL    )   ||
472             ( &aURL                     ==  NULL    )   ||
473             ( aURL.Complete.getLength() <   1       )
474         )
475     {
476         bOK = sal_False ;
477     }
478     // Return result of check.
479     return bOK ;
480 }
481 
482 #endif  //  #ifdef ENABLE_ASSERTIONS
483 
484 }       //  namespace framework
485