1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: menudispatcher.cxx,v $
10 * $Revision: 1.23.82.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_framework.hxx"
34 //_________________________________________________________________________________________________________________
36 //_________________________________________________________________________________________________________________
37 #include <dispatch/menudispatcher.hxx>
39 #include <xml/menuconfiguration.hxx>
40 #include <classes/addonmenu.hxx>
43 //_________________________________________________________________________________________________________________
45 //_________________________________________________________________________________________________________________
46 #include <com/sun/star/frame/FrameSearchFlag.hpp>
47 #include <com/sun/star/awt/XToolkit.hpp>
48 #include <com/sun/star/awt/WindowAttribute.hpp>
49 #include <com/sun/star/awt/WindowDescriptor.hpp>
50 #include <com/sun/star/awt/PosSize.hpp>
51 #include <com/sun/star/awt/XWindowPeer.hpp>
52 #include <com/sun/star/beans/UnknownPropertyException.hpp>
53 #include <com/sun/star/lang/WrappedTargetException.hpp>
54 #include <com/sun/star/beans/XPropertySet.hpp>
55 #include <com/sun/star/container/XEnumeration.hpp>
56 #include <com/sun/star/util/XURLTransformer.hpp>
58 #include <vcl/window.hxx>
59 #include <vcl/syswin.hxx>
60 #include <vcl/menu.hxx>
61 #include <vcl/svapp.hxx>
62 #include <tools/resmgr.hxx>
63 #include <tools/rcid.h>
64 #include <vos/mutex.hxx>
65 #include <toolkit/helper/vclunohelper.hxx>
66 #include <rtl/logfile.hxx>
68 //_________________________________________________________________________________________________________________
69 // includes of other projects
70 //_________________________________________________________________________________________________________________
72 #include <ucbhelper/content.hxx>
74 //_________________________________________________________________________________________________________________
76 //_________________________________________________________________________________________________________________
80 using namespace ::com::sun::star
;
81 using namespace ::com::sun::star::awt
;
82 using namespace ::com::sun::star::beans
;
83 using namespace ::com::sun::star::container
;
84 using namespace ::com::sun::star::frame
;
85 using namespace ::com::sun::star::lang
;
86 using namespace ::com::sun::star::uno
;
87 using namespace ::com::sun::star::util
;
88 using namespace ::cppu
;
89 using namespace ::osl
;
90 using namespace ::rtl
;
91 using namespace ::vos
;
93 //_________________________________________________________________________________________________________________
95 //_________________________________________________________________________________________________________________
97 const USHORT SLOTID_MDIWINDOWLIST
= 5610;
99 //_________________________________________________________________________________________________________________
100 // non exported definitions
101 //_________________________________________________________________________________________________________________
103 //_________________________________________________________________________________________________________________
105 //_________________________________________________________________________________________________________________
107 //*****************************************************************************************************************
109 //*****************************************************************************************************************
110 MenuDispatcher::MenuDispatcher( const uno::Reference
< XMultiServiceFactory
>& xFactory
,
111 const uno::Reference
< XFrame
>& xOwner
)
112 // Init baseclasses first
113 : ThreadHelpBase ( &Application::GetSolarMutex() )
116 , m_xOwnerWeak ( xOwner
)
117 , m_xFactory ( xFactory
)
118 , m_aListenerContainer ( m_aLock
.getShareableOslMutex() )
119 , m_bAlreadyDisposed ( sal_False
)
120 , m_bActivateListener ( sal_False
)
121 , m_pMenuManager ( NULL
)
123 // Safe impossible cases
124 // We need valid informations about ouer ownerfor work.
125 LOG_ASSERT( impldbg_checkParameter_MenuDispatcher( xFactory
, xOwner
), "MenuDispatcher::MenuDispatcher()\nInvalid parameter detected!\n" )
127 m_bActivateListener
= sal_True
;
128 xOwner
->addFrameActionListener( uno::Reference
< XFrameActionListener
>( (OWeakObject
*)this, UNO_QUERY
));
131 //*****************************************************************************************************************
133 //*****************************************************************************************************************
134 MenuDispatcher::~MenuDispatcher()
136 // Warn programmer if he forgot to dispose this instance.
137 // We must release all our references ...
138 // and a dtor isn't the best place to do that!
141 //*****************************************************************************************************************
142 // XInterface, XTypeProvider
143 //*****************************************************************************************************************
144 DEFINE_XINTERFACE_4 ( MenuDispatcher
,
146 DIRECT_INTERFACE( XTypeProvider
),
147 DIRECT_INTERFACE( XDispatch
),
148 DIRECT_INTERFACE( XEventListener
),
149 DERIVED_INTERFACE( XFrameActionListener
, XEventListener
)
152 DEFINE_XTYPEPROVIDER_4 ( MenuDispatcher
,
160 //*****************************************************************************************************************
162 //*****************************************************************************************************************
163 void SAL_CALL
MenuDispatcher::dispatch( const URL
& /*aURL*/ ,
164 const Sequence
< PropertyValue
>& /*seqProperties*/ ) throw( RuntimeException
)
168 //*****************************************************************************************************************
170 //*****************************************************************************************************************
171 void SAL_CALL
MenuDispatcher::addStatusListener( const uno::Reference
< XStatusListener
>& xControl
,
172 const URL
& aURL
) throw( RuntimeException
)
174 // Ready for multithreading
175 ResetableGuard
aGuard( m_aLock
);
176 // Safe impossible cases
177 // Method not defined for all incoming parameter
178 LOG_ASSERT( impldbg_checkParameter_addStatusListener( xControl
, aURL
), "MenuDispatcher::addStatusListener()\nInvalid parameter detected.\n" )
179 // Add listener to container.
180 m_aListenerContainer
.addInterface( aURL
.Complete
, xControl
);
183 //*****************************************************************************************************************
185 //*****************************************************************************************************************
186 void SAL_CALL
MenuDispatcher::removeStatusListener( const uno::Reference
< XStatusListener
>& xControl
,
187 const URL
& aURL
) throw( RuntimeException
)
189 // Ready for multithreading
190 ResetableGuard
aGuard( m_aLock
);
191 // Safe impossible cases
192 // Method not defined for all incoming parameter
193 LOG_ASSERT( impldbg_checkParameter_removeStatusListener( xControl
, aURL
), "MenuDispatcher::removeStatusListener()\nInvalid parameter detected.\n" )
194 // Add listener to container.
195 m_aListenerContainer
.removeInterface( aURL
.Complete
, xControl
);
198 //*****************************************************************************************************************
199 // XFrameActionListener
200 //*****************************************************************************************************************
202 void SAL_CALL
MenuDispatcher::frameAction( const FrameActionEvent
& aEvent
) throw ( RuntimeException
)
204 ResetableGuard
aGuard( m_aLock
);
206 if ( m_pMenuManager
&& aEvent
.Action
== FrameAction_FRAME_UI_ACTIVATED
)
208 MenuBar
* pMenuBar
= (MenuBar
*)m_pMenuManager
->GetMenu();
209 uno::Reference
< XFrame
> xFrame( m_xOwnerWeak
.get(), UNO_QUERY
);
212 if ( xFrame
.is() && pMenuBar
)
214 uno::Reference
< ::com::sun::star::awt::XWindow
>xContainerWindow
= xFrame
->getContainerWindow();
216 OGuard
aSolarGuard( Application::GetSolarMutex() );
218 Window
* pWindow
= VCLUnoHelper::GetWindow( xContainerWindow
);
219 while ( pWindow
&& !pWindow
->IsSystemWindow() )
220 pWindow
= pWindow
->GetParent();
224 SystemWindow
* pSysWindow
= (SystemWindow
*)pWindow
;
225 pSysWindow
->SetMenuBar( pMenuBar
);
230 else if ( m_pMenuManager
&& aEvent
.Action
== css::frame::FrameAction_COMPONENT_DETACHING
)
232 if ( m_pMenuManager
)
233 impl_setMenuBar( NULL
);
237 //*****************************************************************************************************************
239 //*****************************************************************************************************************
240 void SAL_CALL
MenuDispatcher::disposing( const EventObject
& ) throw( RuntimeException
)
242 // Ready for multithreading
243 ResetableGuard
aGuard( m_aLock
);
244 // Safe impossible cases
245 LOG_ASSERT( !(m_bAlreadyDisposed
==sal_True
), "MenuDispatcher::disposing()\nObject already disposed .. don't call it again!\n" )
247 if( m_bAlreadyDisposed
== sal_False
)
249 m_bAlreadyDisposed
= sal_True
;
251 if ( m_bActivateListener
)
253 uno::Reference
< XFrame
> xFrame( m_xOwnerWeak
.get(), UNO_QUERY
);
256 xFrame
->removeFrameActionListener( uno::Reference
< XFrameActionListener
>( (OWeakObject
*)this, UNO_QUERY
));
257 m_bActivateListener
= sal_False
;
258 if ( m_pMenuManager
)
260 EventObject aEventObj
;
261 aEventObj
.Source
= xFrame
;
262 m_pMenuManager
->disposing( aEventObj
);
267 // Forget our factory.
268 m_xFactory
= uno::Reference
< XMultiServiceFactory
>();
270 // Remove our menu from system window if it is still there!
271 if ( m_pMenuManager
)
272 impl_setMenuBar( NULL
);
276 //*****************************************************************************************************************
280 //*****************************************************************************************************************
281 void MenuDispatcher::impl_setAccelerators( Menu
* pMenu
, const Accelerator
& aAccel
)
283 for ( USHORT nPos
= 0; nPos
< pMenu
->GetItemCount(); ++nPos
)
285 USHORT nId
= pMenu
->GetItemId(nPos
);
286 PopupMenu
* pPopup
= pMenu
->GetPopupMenu(nId
);
288 impl_setAccelerators( (Menu
*)pPopup
, aAccel
);
289 else if ( nId
&& !pMenu
->GetPopupMenu(nId
))
291 KeyCode aCode
= aAccel
.GetKeyCode( nId
);
292 if ( aCode
.GetCode() )
293 pMenu
->SetAccelKey( nId
, aCode
);
298 //*****************************************************************************************************************
302 //*****************************************************************************************************************
303 sal_Bool
MenuDispatcher::impl_setMenuBar( MenuBar
* pMenuBar
, sal_Bool bMenuFromResource
)
305 uno::Reference
< XFrame
> xFrame( m_xOwnerWeak
.get(), UNO_QUERY
);
308 uno::Reference
< ::com::sun::star::awt::XWindow
>xContainerWindow
= xFrame
->getContainerWindow();
309 Window
* pWindow
= NULL
;
311 // Use SolarMutex for threadsafe code too!
312 OGuard
aSolarGuard( Application::GetSolarMutex() );
314 pWindow
= VCLUnoHelper::GetWindow( xContainerWindow
);
315 while ( pWindow
&& !pWindow
->IsSystemWindow() )
316 pWindow
= pWindow
->GetParent();
321 // Ready for multithreading
322 ResetableGuard
aGuard( m_aLock
);
324 SystemWindow
* pSysWindow
= (SystemWindow
*)pWindow
;
326 if ( m_pMenuManager
)
328 // remove old menu from our system window if it was set before
329 if ( m_pMenuManager
->GetMenu() == (Menu
*)pSysWindow
->GetMenuBar() )
330 pSysWindow
->SetMenuBar( NULL
);
332 // remove listener before we destruct ourself, so we cannot be called back afterwards
333 m_pMenuManager
->RemoveListener();
335 SAL_STATIC_CAST( ::com::sun::star::uno::XInterface
*, (OWeakObject
*)m_pMenuManager
)->release();
340 if ( pMenuBar
!= NULL
)
342 USHORT nPos
= pMenuBar
->GetItemPos( SLOTID_MDIWINDOWLIST
);
343 if ( nPos
!= MENU_ITEM_NOTFOUND
)
347 uno::Reference
< XModel
> xModel
;
348 uno::Reference
< XController
> xController( xFrame
->getController(), UNO_QUERY
);
350 if ( xController
.is() )
351 xModel
= uno::Reference
< XModel
>( xController
->getModel(), UNO_QUERY
);
353 // retrieve addon popup menus and add them to our menu bar
354 AddonMenuManager::MergeAddonPopupMenus( xFrame
, xModel
, nPos
, pMenuBar
);
356 // retrieve addon help menu items and add them to our help menu
357 AddonMenuManager::MergeAddonHelpMenu( xFrame
, pMenuBar
);
360 // set new menu on our system window and create new menu manager
361 if ( bMenuFromResource
)
364 // m_pMenuManager = new MenuManager( xFrame, pMenuBar, sal_True, sal_False );
365 m_pMenuManager
= new MenuManager( m_xFactory
, xFrame
, pMenuBar
, sal_True
, sal_False
);
370 // m_pMenuManager = new MenuManager( xFrame, pMenuBar, sal_True, sal_True );
371 m_pMenuManager
= new MenuManager( m_xFactory
, xFrame
, pMenuBar
, sal_True
, sal_True
);
374 pSysWindow
->SetMenuBar( pMenuBar
);
384 IMPL_LINK( MenuDispatcher
, Close_Impl
, void*, EMPTYARG
)
386 css::uno::Reference
< css::frame::XFrame
> xFrame( m_xOwnerWeak
.get(), css::uno::UNO_QUERY
);
391 aURL
.Complete
= ::rtl::OUString::createFromAscii(".uno:CloseWin");
392 css::uno::Reference
< css::util::XURLTransformer
> xTrans ( m_xFactory
->createInstance(
393 SERVICENAME_URLTRANSFORMER
), css::uno::UNO_QUERY
);
397 xTrans
->parseStrict( aURL
);
398 uno::Reference
< XDispatchProvider
> xProv( xFrame
, UNO_QUERY
);
401 css::uno::Reference
< css::frame::XDispatch
> aDisp
= xProv
->queryDispatch( aURL
, ::rtl::OUString(), 0 );
403 aDisp
->dispatch( aURL
, css::uno::Sequence
< css::beans::PropertyValue
>() );
411 //_________________________________________________________________________________________________________________
413 //_________________________________________________________________________________________________________________
415 /*-----------------------------------------------------------------------------------------------------------------
416 The follow methods checks the parameter for other functions. If a parameter or his value is non valid,
417 we return "sal_False". (else sal_True) This mechanism is used to throw an ASSERT!
421 If you miss a test for one of this parameters, contact the autor or add it himself !(?)
422 But ... look for right testing! See using of this methods!
423 -----------------------------------------------------------------------------------------------------------------*/
425 #ifdef ENABLE_ASSERTIONS
427 //*****************************************************************************************************************
428 sal_Bool
MenuDispatcher::impldbg_checkParameter_MenuDispatcher( const uno::Reference
< XMultiServiceFactory
>& xFactory
,
429 const uno::Reference
< XFrame
>& xOwner
)
431 // Set default return value.
432 sal_Bool bOK
= sal_True
;
435 ( &xFactory
== NULL
) ||
436 ( &xOwner
== NULL
) ||
437 ( xFactory
.is() == sal_False
) ||
438 ( xOwner
.is() == sal_False
)
443 // Return result of check.
447 //*****************************************************************************************************************
448 // We don't know anything about right values of aURL and seqArguments!
449 // Check valid references only.
450 sal_Bool
MenuDispatcher::impldbg_checkParameter_dispatch( const URL
& aURL
,
451 const Sequence
< PropertyValue
>& seqArguments
)
453 // Set default return value.
454 sal_Bool bOK
= sal_True
;
458 ( &seqArguments
== NULL
)
463 // Return result of check.
467 //*****************************************************************************************************************
468 // We need a valid URL. What is meaning with "register for nothing"?!
469 // xControl must correct to - nobody can advised otherwise!
470 sal_Bool
MenuDispatcher::impldbg_checkParameter_addStatusListener( const uno::Reference
< XStatusListener
>& xControl
,
473 // Set default return value.
474 sal_Bool bOK
= sal_True
;
477 ( &xControl
== NULL
) ||
479 ( aURL
.Complete
.getLength() < 1 )
484 // Return result of check.
488 //*****************************************************************************************************************
489 // The same goes for these case! We have added valid listener for correct URL only.
490 // We can't remove invalid listener for nothing!
491 sal_Bool
MenuDispatcher::impldbg_checkParameter_removeStatusListener( const uno::Reference
< XStatusListener
>& xControl
,
494 // Set default return value.
495 sal_Bool bOK
= sal_True
;
498 ( &xControl
== NULL
) ||
500 ( aURL
.Complete
.getLength() < 1 )
505 // Return result of check.
509 #endif // #ifdef ENABLE_ASSERTIONS
511 } // namespace framework