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