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 our owner for 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, nPos, pMenuBar, m_xFactory );
348
349 // retrieve addon help menu items and add them to our help menu
350 AddonMenuManager::MergeAddonHelpMenu( xFrame, pMenuBar, m_xFactory );
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 author 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