Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <dispatch/menudispatcher.hxx>
30 : : #include <general.h>
31 : : #include <framework/menuconfiguration.hxx>
32 : : #include <framework/addonmenu.hxx>
33 : : #include <services.h>
34 : :
35 : : #include <com/sun/star/frame/FrameSearchFlag.hpp>
36 : : #include <com/sun/star/awt/XToolkit.hpp>
37 : : #include <com/sun/star/awt/WindowAttribute.hpp>
38 : : #include <com/sun/star/awt/WindowDescriptor.hpp>
39 : : #include <com/sun/star/awt/PosSize.hpp>
40 : : #include <com/sun/star/awt/XWindowPeer.hpp>
41 : : #include <com/sun/star/beans/UnknownPropertyException.hpp>
42 : : #include <com/sun/star/lang/WrappedTargetException.hpp>
43 : : #include <com/sun/star/beans/XPropertySet.hpp>
44 : : #include <com/sun/star/container/XEnumeration.hpp>
45 : : #include <com/sun/star/util/XURLTransformer.hpp>
46 : :
47 : : #include <vcl/window.hxx>
48 : : #include <vcl/syswin.hxx>
49 : : #include <vcl/menu.hxx>
50 : : #include <vcl/svapp.hxx>
51 : : #include <tools/rcid.h>
52 : : #include <osl/mutex.hxx>
53 : : #include <toolkit/helper/vclunohelper.hxx>
54 : : #include <rtl/logfile.hxx>
55 : :
56 : : #include <ucbhelper/content.hxx>
57 : :
58 : : namespace framework{
59 : :
60 : : using namespace ::com::sun::star ;
61 : : using namespace ::com::sun::star::awt ;
62 : : using namespace ::com::sun::star::beans ;
63 : : using namespace ::com::sun::star::container ;
64 : : using namespace ::com::sun::star::frame ;
65 : : using namespace ::com::sun::star::lang ;
66 : : using namespace ::com::sun::star::uno ;
67 : : using namespace ::com::sun::star::util ;
68 : : using namespace ::cppu ;
69 : : using ::rtl::OUString;
70 : :
71 : : const sal_uInt16 SLOTID_MDIWINDOWLIST = 5610;
72 : :
73 : : //*****************************************************************************************************************
74 : : // constructor
75 : : //*****************************************************************************************************************
76 : 2 : MenuDispatcher::MenuDispatcher( const uno::Reference< XMultiServiceFactory >& xFactory ,
77 : : const uno::Reference< XFrame >& xOwner )
78 : : // Init baseclasses first
79 [ + - ]: 2 : : ThreadHelpBase ( &Application::GetSolarMutex() )
80 : : , OWeakObject ( )
81 : : // Init member
82 : : , m_xOwnerWeak ( xOwner )
83 : : , m_xFactory ( xFactory )
84 [ + - ]: 2 : , m_aListenerContainer ( m_aLock.getShareableOslMutex() )
85 : : , m_bAlreadyDisposed ( sal_False )
86 : : , m_bActivateListener ( sal_False )
87 [ + - ][ + - ]: 6 : , m_pMenuManager ( NULL )
[ + - ]
88 : : {
89 : : // Safe impossible cases
90 : : // We need valid informations about ouer ownerfor work.
91 : : LOG_ASSERT( impldbg_checkParameter_MenuDispatcher( xFactory, xOwner ), "MenuDispatcher::MenuDispatcher()\nInvalid parameter detected!\n" )
92 : :
93 : 2 : m_bActivateListener = sal_True;
94 [ + - ][ + - ]: 2 : xOwner->addFrameActionListener( uno::Reference< XFrameActionListener >( (OWeakObject *)this, UNO_QUERY ));
[ + - ]
95 : 2 : }
96 : :
97 : : //*****************************************************************************************************************
98 : : // destructor
99 : : //*****************************************************************************************************************
100 [ + - ][ + - ]: 2 : MenuDispatcher::~MenuDispatcher()
[ + - ][ + - ]
101 : : {
102 : : // Warn programmer if he forgot to dispose this instance.
103 : : // We must release all our references ...
104 : : // and a dtor isn't the best place to do that!
105 [ - + ]: 4 : }
106 : :
107 : : //*****************************************************************************************************************
108 : : // XInterface, XTypeProvider
109 : : //*****************************************************************************************************************
110 [ - + ][ # # ]: 52 : DEFINE_XINTERFACE_4 ( MenuDispatcher ,
111 : : OWeakObject ,
112 : : DIRECT_INTERFACE( XTypeProvider ),
113 : : DIRECT_INTERFACE( XDispatch ),
114 : : DIRECT_INTERFACE( XEventListener ),
115 : : DERIVED_INTERFACE( XFrameActionListener, XEventListener )
116 : : )
117 : :
118 [ # # ][ # # ]: 0 : DEFINE_XTYPEPROVIDER_4 ( MenuDispatcher ,
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
119 : : XTypeProvider ,
120 : : XDispatch ,
121 : : XEventListener ,
122 : : XFrameActionListener
123 : : )
124 : :
125 : :
126 : : //*****************************************************************************************************************
127 : : // XDispatch
128 : : //*****************************************************************************************************************
129 : 2 : void SAL_CALL MenuDispatcher::dispatch( const URL& /*aURL*/ ,
130 : : const Sequence< PropertyValue >& /*seqProperties*/ ) throw( RuntimeException )
131 : : {
132 : 2 : }
133 : :
134 : : //*****************************************************************************************************************
135 : : // XDispatch
136 : : //*****************************************************************************************************************
137 : 0 : void SAL_CALL MenuDispatcher::addStatusListener( const uno::Reference< XStatusListener >& xControl,
138 : : const URL& aURL ) throw( RuntimeException )
139 : : {
140 : : // Ready for multithreading
141 [ # # ]: 0 : ResetableGuard aGuard( m_aLock );
142 : : // Safe impossible cases
143 : : // Method not defined for all incoming parameter
144 : : LOG_ASSERT( impldbg_checkParameter_addStatusListener( xControl, aURL ), "MenuDispatcher::addStatusListener()\nInvalid parameter detected.\n" )
145 : : // Add listener to container.
146 [ # # ][ # # ]: 0 : m_aListenerContainer.addInterface( aURL.Complete, xControl );
147 : 0 : }
148 : :
149 : : //*****************************************************************************************************************
150 : : // XDispatch
151 : : //*****************************************************************************************************************
152 : 0 : void SAL_CALL MenuDispatcher::removeStatusListener( const uno::Reference< XStatusListener >& xControl,
153 : : const URL& aURL ) throw( RuntimeException )
154 : : {
155 : : // Ready for multithreading
156 [ # # ]: 0 : ResetableGuard aGuard( m_aLock );
157 : : // Safe impossible cases
158 : : // Method not defined for all incoming parameter
159 : : LOG_ASSERT( impldbg_checkParameter_removeStatusListener( xControl, aURL ), "MenuDispatcher::removeStatusListener()\nInvalid parameter detected.\n" )
160 : : // Add listener to container.
161 [ # # ][ # # ]: 0 : m_aListenerContainer.removeInterface( aURL.Complete, xControl );
162 : 0 : }
163 : :
164 : : //*****************************************************************************************************************
165 : : // XFrameActionListener
166 : : //*****************************************************************************************************************
167 : :
168 : 0 : void SAL_CALL MenuDispatcher::frameAction( const FrameActionEvent& aEvent ) throw ( RuntimeException )
169 : : {
170 [ # # ]: 0 : ResetableGuard aGuard( m_aLock );
171 : :
172 [ # # ][ # # ]: 0 : if ( m_pMenuManager && aEvent.Action == FrameAction_FRAME_UI_ACTIVATED )
173 : : {
174 : 0 : MenuBar* pMenuBar = (MenuBar *)m_pMenuManager->GetMenu();
175 [ # # ][ # # ]: 0 : uno::Reference< XFrame > xFrame( m_xOwnerWeak.get(), UNO_QUERY );
176 [ # # ]: 0 : aGuard.unlock();
177 : :
178 [ # # ][ # # ]: 0 : if ( xFrame.is() && pMenuBar )
[ # # ]
179 : : {
180 [ # # ][ # # ]: 0 : uno::Reference< ::com::sun::star::awt::XWindow >xContainerWindow = xFrame->getContainerWindow();
181 : :
182 [ # # ]: 0 : SolarMutexGuard aSolarGuard;
183 : : {
184 [ # # ]: 0 : Window* pWindow = VCLUnoHelper::GetWindow( xContainerWindow );
185 [ # # ][ # # ]: 0 : while ( pWindow && !pWindow->IsSystemWindow() )
[ # # ][ # # ]
186 [ # # ]: 0 : pWindow = pWindow->GetParent();
187 : :
188 [ # # ]: 0 : if ( pWindow )
189 : : {
190 : 0 : SystemWindow* pSysWindow = (SystemWindow *)pWindow;
191 [ # # ]: 0 : pSysWindow->SetMenuBar( pMenuBar );
192 : : }
193 [ # # ]: 0 : }
194 : 0 : }
195 : : }
196 [ # # ][ # # ]: 0 : else if ( m_pMenuManager && aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING )
197 : : {
198 [ # # ]: 0 : if ( m_pMenuManager )
199 [ # # ]: 0 : impl_setMenuBar( NULL );
200 [ # # ]: 0 : }
201 : 0 : }
202 : :
203 : : //*****************************************************************************************************************
204 : : // XEventListener
205 : : //*****************************************************************************************************************
206 : 2 : void SAL_CALL MenuDispatcher::disposing( const EventObject& ) throw( RuntimeException )
207 : : {
208 : : // Ready for multithreading
209 [ + - ]: 2 : ResetableGuard aGuard( m_aLock );
210 : : // Safe impossible cases
211 : : LOG_ASSERT( !(m_bAlreadyDisposed==sal_True), "MenuDispatcher::disposing()\nObject already disposed .. don't call it again!\n" )
212 : :
213 [ + - ]: 2 : if( m_bAlreadyDisposed == sal_False )
214 : : {
215 : 2 : m_bAlreadyDisposed = sal_True;
216 : :
217 [ + - ]: 2 : if ( m_bActivateListener )
218 : : {
219 [ + - ][ + - ]: 2 : uno::Reference< XFrame > xFrame( m_xOwnerWeak.get(), UNO_QUERY );
220 [ + - ]: 2 : if ( xFrame.is() )
221 : : {
222 [ + - ][ + - ]: 2 : xFrame->removeFrameActionListener( uno::Reference< XFrameActionListener >( (OWeakObject *)this, UNO_QUERY ));
[ + - ]
223 : 2 : m_bActivateListener = sal_False;
224 [ - + ]: 2 : if ( m_pMenuManager )
225 : : {
226 [ # # ]: 0 : EventObject aEventObj;
227 [ # # ]: 0 : aEventObj.Source = xFrame;
228 [ # # ][ # # ]: 0 : m_pMenuManager->disposing( aEventObj );
229 : : }
230 : 2 : }
231 : : }
232 : :
233 : : // Forget our factory.
234 [ + - ]: 2 : m_xFactory = uno::Reference< XMultiServiceFactory >();
235 : :
236 : : // Remove our menu from system window if it is still there!
237 [ - + ]: 2 : if ( m_pMenuManager )
238 [ # # ]: 0 : impl_setMenuBar( NULL );
239 [ + - ]: 2 : }
240 : 2 : }
241 : :
242 : : //*****************************************************************************************************************
243 : : // private method
244 : : //*****************************************************************************************************************
245 : 0 : void MenuDispatcher::impl_setAccelerators( Menu* pMenu, const Accelerator& aAccel )
246 : : {
247 [ # # ]: 0 : for ( sal_uInt16 nPos = 0; nPos < pMenu->GetItemCount(); ++nPos )
248 : : {
249 : 0 : sal_uInt16 nId = pMenu->GetItemId(nPos);
250 : 0 : PopupMenu* pPopup = pMenu->GetPopupMenu(nId);
251 [ # # ]: 0 : if ( pPopup )
252 : 0 : impl_setAccelerators( (Menu *)pPopup, aAccel );
253 [ # # ][ # # ]: 0 : else if ( nId && !pMenu->GetPopupMenu(nId))
[ # # ]
254 : : {
255 [ # # ]: 0 : KeyCode aCode = aAccel.GetKeyCode( nId );
256 [ # # ]: 0 : if ( aCode.GetCode() )
257 [ # # ]: 0 : pMenu->SetAccelKey( nId, aCode );
258 : : }
259 : : }
260 : 0 : }
261 : :
262 : : //*****************************************************************************************************************
263 : : // private method
264 : : //*****************************************************************************************************************
265 : 0 : sal_Bool MenuDispatcher::impl_setMenuBar( MenuBar* pMenuBar, sal_Bool bMenuFromResource )
266 : : {
267 [ # # ][ # # ]: 0 : uno::Reference< XFrame > xFrame( m_xOwnerWeak.get(), UNO_QUERY );
268 [ # # ]: 0 : if ( xFrame.is() )
269 : : {
270 [ # # ][ # # ]: 0 : uno::Reference< ::com::sun::star::awt::XWindow >xContainerWindow = xFrame->getContainerWindow();
271 : 0 : Window* pWindow = NULL;
272 : :
273 : : // Use SolarMutex for threadsafe code too!
274 [ # # ]: 0 : SolarMutexGuard aSolarGuard;
275 : : {
276 [ # # ]: 0 : pWindow = VCLUnoHelper::GetWindow( xContainerWindow );
277 [ # # ][ # # ]: 0 : while ( pWindow && !pWindow->IsSystemWindow() )
[ # # ][ # # ]
278 [ # # ]: 0 : pWindow = pWindow->GetParent();
279 : : }
280 : :
281 [ # # ]: 0 : if ( pWindow )
282 : : {
283 : : // Ready for multithreading
284 [ # # ]: 0 : ResetableGuard aGuard( m_aLock );
285 : :
286 : 0 : SystemWindow* pSysWindow = (SystemWindow *)pWindow;
287 : :
288 [ # # ]: 0 : if ( m_pMenuManager )
289 : : {
290 : : // remove old menu from our system window if it was set before
291 [ # # ]: 0 : if ( m_pMenuManager->GetMenu() == (Menu *)pSysWindow->GetMenuBar() )
292 [ # # ]: 0 : pSysWindow->SetMenuBar( NULL );
293 : :
294 : : // remove listener before we destruct ourself, so we cannot be called back afterwards
295 [ # # ]: 0 : m_pMenuManager->RemoveListener();
296 : :
297 : 0 : (static_cast< ::com::sun::star::uno::XInterface* >((OWeakObject*)m_pMenuManager))->release();
298 : :
299 : 0 : m_pMenuManager = 0;
300 : : }
301 : :
302 [ # # ]: 0 : if ( pMenuBar != NULL )
303 : : {
304 [ # # ]: 0 : sal_uInt16 nPos = pMenuBar->GetItemPos( SLOTID_MDIWINDOWLIST );
305 [ # # ]: 0 : if ( nPos != MENU_ITEM_NOTFOUND )
306 : : {
307 : 0 : uno::Reference< XModel > xModel;
308 [ # # ][ # # ]: 0 : uno::Reference< XController > xController( xFrame->getController(), UNO_QUERY );
[ # # ]
309 : :
310 [ # # ]: 0 : if ( xController.is() )
311 [ # # ][ # # ]: 0 : xModel = uno::Reference< XModel >( xController->getModel(), UNO_QUERY );
[ # # ][ # # ]
312 : :
313 : : // retrieve addon popup menus and add them to our menu bar
314 [ # # ]: 0 : AddonMenuManager::MergeAddonPopupMenus( xFrame, xModel, nPos, pMenuBar );
315 : :
316 : : // retrieve addon help menu items and add them to our help menu
317 [ # # ]: 0 : AddonMenuManager::MergeAddonHelpMenu( xFrame, pMenuBar );
318 : : }
319 : :
320 : : // set new menu on our system window and create new menu manager
321 [ # # ]: 0 : if ( bMenuFromResource )
322 : : {
323 [ # # ]: 0 : m_pMenuManager = new MenuManager( m_xFactory, xFrame, pMenuBar, sal_True, sal_False );
324 : : }
325 : : else
326 : : {
327 [ # # ]: 0 : m_pMenuManager = new MenuManager( m_xFactory, xFrame, pMenuBar, sal_True, sal_True );
328 : : }
329 : :
330 [ # # ]: 0 : pSysWindow->SetMenuBar( pMenuBar );
331 : : }
332 : :
333 [ # # ]: 0 : return sal_True;
334 [ # # ][ # # ]: 0 : }
[ # # ]
335 : : }
336 : :
337 : 0 : return sal_False;
338 : : }
339 : :
340 : : //_________________________________________________________________________________________________________________
341 : : // debug methods
342 : : //_________________________________________________________________________________________________________________
343 : :
344 : : /*-----------------------------------------------------------------------------------------------------------------
345 : : The follow methods checks the parameter for other functions. If a parameter or his value is non valid,
346 : : we return "sal_False". (else sal_True) This mechanism is used to throw an ASSERT!
347 : :
348 : : ATTENTION
349 : :
350 : : If you miss a test for one of this parameters, contact the autor or add it himself !(?)
351 : : But ... look for right testing! See using of this methods!
352 : : -----------------------------------------------------------------------------------------------------------------*/
353 : :
354 : : #ifdef ENABLE_ASSERTIONS
355 : :
356 : : //*****************************************************************************************************************
357 : : sal_Bool MenuDispatcher::impldbg_checkParameter_MenuDispatcher( const uno::Reference< XMultiServiceFactory >& xFactory ,
358 : : const uno::Reference< XFrame >& xOwner )
359 : : {
360 : : // Set default return value.
361 : : sal_Bool bOK = sal_True;
362 : : // Check parameter.
363 : : if (
364 : : ( &xFactory == NULL ) ||
365 : : ( &xOwner == NULL ) ||
366 : : ( xFactory.is() == sal_False ) ||
367 : : ( xOwner.is() == sal_False )
368 : : )
369 : : {
370 : : bOK = sal_False ;
371 : : }
372 : : // Return result of check.
373 : : return bOK ;
374 : : }
375 : :
376 : : //*****************************************************************************************************************
377 : : // We need a valid URL. What is meaning with "register for nothing"?!
378 : : // xControl must correct to - nobody can advised otherwise!
379 : : sal_Bool MenuDispatcher::impldbg_checkParameter_addStatusListener( const uno::Reference< XStatusListener >& xControl,
380 : : const URL& aURL )
381 : : {
382 : : // Set default return value.
383 : : sal_Bool bOK = sal_True;
384 : : // Check parameter.
385 : : if (
386 : : ( &xControl == NULL ) ||
387 : : ( &aURL == NULL ) ||
388 : : ( aURL.Complete.isEmpty() )
389 : : )
390 : : {
391 : : bOK = sal_False ;
392 : : }
393 : : // Return result of check.
394 : : return bOK ;
395 : : }
396 : :
397 : : //*****************************************************************************************************************
398 : : // The same goes for these case! We have added valid listener for correct URL only.
399 : : // We can't remove invalid listener for nothing!
400 : : sal_Bool MenuDispatcher::impldbg_checkParameter_removeStatusListener( const uno::Reference< XStatusListener >& xControl,
401 : : const URL& aURL )
402 : : {
403 : : // Set default return value.
404 : : sal_Bool bOK = sal_True;
405 : : // Check parameter.
406 : : if (
407 : : ( &xControl == NULL ) ||
408 : : ( &aURL == NULL ) ||
409 : : ( aURL.Complete.isEmpty() )
410 : : )
411 : : {
412 : : bOK = sal_False ;
413 : : }
414 : : // Return result of check.
415 : : return bOK ;
416 : : }
417 : :
418 : : #endif // #ifdef ENABLE_ASSERTIONS
419 : :
420 : : } // namespace framework
421 : :
422 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|