1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_framework.hxx"
30 
31 //_________________________________________________________________________________________________________________
32 //	my own includes
33 //_________________________________________________________________________________________________________________
34 #include <uielement/menubarwrapper.hxx>
35 #include <threadhelp/resetableguard.hxx>
36 #include <framework/actiontriggerhelper.hxx>
37 #include <services.h>
38 
39 //_________________________________________________________________________________________________________________
40 //	interface includes
41 //_________________________________________________________________________________________________________________
42 #include <com/sun/star/lang/XServiceInfo.hpp>
43 #include <com/sun/star/beans/XPropertySet.hpp>
44 #include <com/sun/star/awt/XSystemDependentMenuPeer.hpp>
45 #include <com/sun/star/awt/XMenuBar.hpp>
46 #include <com/sun/star/container/XIndexContainer.hpp>
47 #include <com/sun/star/container/XNameAccess.hpp>
48 #include <com/sun/star/ui/UIElementType.hpp>
49 #include <com/sun/star/frame/XModuleManager.hpp>
50 
51 //_________________________________________________________________________________________________________________
52 //	other includes
53 //_________________________________________________________________________________________________________________
54 #include <comphelper/processfactory.hxx>
55 #include <tools/solar.h>
56 #include <vcl/svapp.hxx>
57 #include <rtl/logfile.hxx>
58 
59 using namespace com::sun::star;
60 using namespace com::sun::star::uno;
61 using namespace com::sun::star::beans;
62 using namespace com::sun::star::frame;
63 using namespace com::sun::star::lang;
64 using namespace com::sun::star::container;
65 using namespace com::sun::star::awt;
66 using namespace com::sun::star::util;
67 using namespace ::com::sun::star::ui;
68 
69 namespace framework
70 {
71 
72 //*****************************************************************************************************************
73 //	XInterface, XTypeProvider
74 //*****************************************************************************************************************
75 DEFINE_XINTERFACE_11    (   MenuBarWrapper                                                    ,
76                             UIConfigElementWrapperBase                                        ,
77                             DIRECT_INTERFACE( ::com::sun::star::lang::XTypeProvider          ),
78                             DIRECT_INTERFACE( ::com::sun::star::ui::XUIElement               ),
79                             DIRECT_INTERFACE( ::com::sun::star::ui::XUIElementSettings       ),
80                             DIRECT_INTERFACE( ::com::sun::star::beans::XMultiPropertySet     ),
81                             DIRECT_INTERFACE( ::com::sun::star::beans::XFastPropertySet      ),
82                             DIRECT_INTERFACE( ::com::sun::star::beans::XPropertySet          ),
83                             DIRECT_INTERFACE( ::com::sun::star::lang::XInitialization        ),
84                             DIRECT_INTERFACE( ::com::sun::star::lang::XComponent             ),
85                             DIRECT_INTERFACE( ::com::sun::star::util::XUpdatable             ),
86                             DIRECT_INTERFACE( ::com::sun::star::ui::XUIConfigurationListener ),
87                             DERIVED_INTERFACE( ::com::sun::star::container::XNameAccess, ::com::sun::star::container::XElementAccess )
88 						)
89 
90 DEFINE_XTYPEPROVIDER_11 (   MenuBarWrapper                                  ,
91                             ::com::sun::star::lang::XTypeProvider           ,
92                             ::com::sun::star::ui::XUIElement                ,
93                             ::com::sun::star::ui::XUIElementSettings        ,
94                             ::com::sun::star::beans::XMultiPropertySet      ,
95                             ::com::sun::star::beans::XFastPropertySet       ,
96                             ::com::sun::star::beans::XPropertySet           ,
97                             ::com::sun::star::lang::XInitialization         ,
98                             ::com::sun::star::lang::XComponent              ,
99                             ::com::sun::star::util::XUpdatable              ,
100                             ::com::sun::star::ui::XUIConfigurationListener  ,
101                             ::com::sun::star::container::XNameAccess
102 						)
103 
104 // #110897#
105 MenuBarWrapper::MenuBarWrapper(
106 	const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& xServiceManager
107 	)
108 :    UIConfigElementWrapperBase( UIElementType::MENUBAR,xServiceManager ),
109      m_bRefreshPopupControllerCache( sal_True )
110 {
111 }
112 
113 MenuBarWrapper::~MenuBarWrapper()
114 {
115 }
116 
117 void SAL_CALL MenuBarWrapper::dispose() throw (::com::sun::star::uno::RuntimeException)
118 {
119     Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY );
120 
121     com::sun::star::lang::EventObject aEvent( xThis );
122     m_aListenerContainer.disposeAndClear( aEvent );
123 
124     ResetableGuard aLock( m_aLock );
125 
126     m_xMenuBarManager->dispose();
127     m_xMenuBarManager.clear();
128     m_xConfigSource.clear();
129     m_xConfigData.clear();
130 
131     m_xMenuBar.clear();
132     m_bDisposed = sal_True;
133 }
134 
135 // XInitialization
136 void SAL_CALL MenuBarWrapper::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException )
137 {
138     RTL_LOGFILE_CONTEXT( aLog, "framework (cd100003) ::MenuBarWrapper::initialize" );
139 
140     ResetableGuard aLock( m_aLock );
141 
142     if ( m_bDisposed )
143         throw DisposedException();
144 
145     if ( !m_bInitialized )
146     {
147         rtl::OUString aModuleIdentifier;
148         UIConfigElementWrapperBase::initialize( aArguments );
149 
150         Reference< XFrame > xFrame( m_xWeakFrame );
151         if ( xFrame.is() && m_xConfigSource.is() )
152         {
153             // Create VCL menubar which will be filled with settings data
154             MenuBar*        pVCLMenuBar = 0;
155             VCLXMenuBar*    pAwtMenuBar = 0;
156             {
157                 vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
158                 pVCLMenuBar = new MenuBar();
159             }
160 
161             Reference< XModuleManager > xModuleManager;
162             xModuleManager = Reference< XModuleManager >(
163                 m_xServiceFactory->createInstance(
164                     SERVICENAME_MODULEMANAGER ), UNO_QUERY_THROW );
165 
166             try
167             {
168                 aModuleIdentifier = xModuleManager->identify( xFrame );
169             }
170             catch( Exception& )
171             {
172             }
173 
174             Reference< XURLTransformer > xTrans;
175             try
176             {
177                 xTrans.set( m_xServiceFactory->createInstance(
178                                                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
179                                                     "com.sun.star.util.URLTransformer" ))), UNO_QUERY );
180                 m_xConfigData = m_xConfigSource->getSettings( m_aResourceURL, sal_False );
181                 if ( m_xConfigData.is() )
182                 {
183                     // Fill menubar with container contents
184                     sal_uInt16 nId = 1;
185                     MenuBarManager::FillMenuWithConfiguration( nId, pVCLMenuBar, aModuleIdentifier, m_xConfigData, xTrans );
186                 }
187             }
188             catch ( NoSuchElementException& )
189             {
190             }
191 
192             sal_Bool bMenuOnly( sal_False );
193             for ( sal_Int32 n = 0; n < aArguments.getLength(); n++ )
194             {
195                 PropertyValue aPropValue;
196                 if ( aArguments[n] >>= aPropValue )
197                 {
198                     if ( aPropValue.Name.equalsAscii( "MenuOnly" ))
199                         aPropValue.Value >>= bMenuOnly;
200                 }
201             }
202 
203             if ( !bMenuOnly )
204             {
205                 // Initialize menubar manager with our vcl menu bar. There are some situations where we only want to get the menu without any
206                 // interaction which is done by the menu bar manager. This must be requested by a special property called "MenuOnly". Be careful
207                 // a menu bar created with this property is not fully supported. It must be attached to a real menu bar manager to have full
208                 // support. This feature is currently used for "Inplace editing"!
209                 Reference< XDispatchProvider > xDispatchProvider;
210 
211                 // #110897#
212                 MenuBarManager* pMenuBarManager = new MenuBarManager( m_xServiceFactory,
213                                                                       xFrame,
214                                                                       xTrans,
215                                                                       xDispatchProvider,
216                                                                       aModuleIdentifier,
217                                                                       pVCLMenuBar,
218                                                                       sal_False,
219                                                                       sal_True );
220 
221 				m_xMenuBarManager = Reference< XComponent >( static_cast< OWeakObject *>( pMenuBarManager ), UNO_QUERY );
222             }
223 
224             // Initialize toolkit menu bar implementation to have awt::XMenuBar for data exchange.
225             // Don't use this toolkit menu bar or one of its functions. It is only used as a data container!
226             pAwtMenuBar = new VCLXMenuBar( pVCLMenuBar );
227             m_xMenuBar = Reference< XMenuBar >( static_cast< OWeakObject *>( pAwtMenuBar ), UNO_QUERY );
228         }
229     }
230 }
231 
232 // XUIElementSettings
233 void SAL_CALL MenuBarWrapper::updateSettings() throw ( RuntimeException )
234 {
235     ResetableGuard aLock( m_aLock );
236 
237     if ( m_bDisposed )
238         throw DisposedException();
239 
240     if ( m_xMenuBarManager.is() )
241     {
242         if ( m_xConfigSource.is() && m_bPersistent )
243         {
244             try
245             {
246                 MenuBarManager* pMenuBarManager = static_cast< MenuBarManager *>( m_xMenuBarManager.get() );
247 
248                 m_xConfigData = m_xConfigSource->getSettings( m_aResourceURL, sal_False );
249                 if ( m_xConfigData.is() )
250                     pMenuBarManager->SetItemContainer( m_xConfigData );
251             }
252             catch ( NoSuchElementException& )
253             {
254             }
255         }
256         else if ( !m_bPersistent )
257         {
258             // Transient menubar: do nothing
259         }
260     }
261 }
262 void MenuBarWrapper::impl_fillNewData()
263 {
264     // Transient menubar => Fill menubar with new data
265     MenuBarManager* pMenuBarManager = static_cast< MenuBarManager *>( m_xMenuBarManager.get() );
266 
267     if ( pMenuBarManager )
268         pMenuBarManager->SetItemContainer( m_xConfigData );
269 }
270 
271 
272 void MenuBarWrapper::fillPopupControllerCache()
273 {
274     if ( m_bRefreshPopupControllerCache )
275     {
276         MenuBarManager* pMenuBarManager = static_cast< MenuBarManager *>( m_xMenuBarManager.get() );
277         if ( pMenuBarManager )
278             pMenuBarManager->GetPopupController( m_aPopupControllerCache );
279         if ( !m_aPopupControllerCache.empty() )
280             m_bRefreshPopupControllerCache = sal_False;
281     }
282 }
283 
284 // XElementAccess
285 Type SAL_CALL MenuBarWrapper::getElementType()
286 throw (::com::sun::star::uno::RuntimeException)
287 {
288     return ::getCppuType(( Reference< XDispatchProvider >*)0);
289 }
290 
291 ::sal_Bool SAL_CALL MenuBarWrapper::hasElements()
292 throw (::com::sun::star::uno::RuntimeException)
293 {
294     ResetableGuard aLock( m_aLock );
295 
296     if ( m_bDisposed )
297         throw DisposedException();
298 
299     fillPopupControllerCache();
300     return ( !m_aPopupControllerCache.empty() );
301 }
302 
303 // XNameAccess
304 Any SAL_CALL MenuBarWrapper::getByName(
305     const ::rtl::OUString& aName )
306 throw ( container::NoSuchElementException,
307         lang::WrappedTargetException,
308         uno::RuntimeException)
309 {
310     ResetableGuard aLock( m_aLock );
311 
312     if ( m_bDisposed )
313         throw DisposedException();
314 
315     fillPopupControllerCache();
316 
317     PopupControllerCache::const_iterator pIter = m_aPopupControllerCache.find( aName );
318     if ( pIter != m_aPopupControllerCache.end() )
319     {
320         uno::Reference< frame::XDispatchProvider > xDispatchProvider;
321         xDispatchProvider = pIter->second.m_xDispatchProvider;
322         return uno::makeAny( xDispatchProvider );
323     }
324     else
325         throw container::NoSuchElementException();
326 }
327 
328 Sequence< ::rtl::OUString > SAL_CALL MenuBarWrapper::getElementNames()
329 throw (::com::sun::star::uno::RuntimeException)
330 {
331     ResetableGuard aLock( m_aLock );
332 
333     if ( m_bDisposed )
334         throw DisposedException();
335 
336     fillPopupControllerCache();
337 
338     Sequence< rtl::OUString > aSeq( m_aPopupControllerCache.size() );
339 
340     sal_Int32 i( 0 );
341     PopupControllerCache::const_iterator pIter = m_aPopupControllerCache.begin();
342     while ( pIter != m_aPopupControllerCache.end() )
343     {
344         aSeq[i++] = pIter->first;
345         ++pIter;
346     }
347 
348     return aSeq;
349 }
350 
351 ::sal_Bool SAL_CALL MenuBarWrapper::hasByName(
352     const ::rtl::OUString& aName )
353 throw (::com::sun::star::uno::RuntimeException)
354 {
355     ResetableGuard aLock( m_aLock );
356 
357     if ( m_bDisposed )
358         throw DisposedException();
359 
360     fillPopupControllerCache();
361 
362     PopupControllerCache::const_iterator pIter = m_aPopupControllerCache.find( aName );
363     if ( pIter != m_aPopupControllerCache.end() )
364         return sal_True;
365     else
366         return sal_False;
367 }
368 
369 // XUIElement
370 Reference< XInterface > SAL_CALL MenuBarWrapper::getRealInterface() throw ( RuntimeException )
371 {
372     if ( m_bDisposed )
373         throw DisposedException();
374 
375     return Reference< XInterface >( m_xMenuBarManager, UNO_QUERY );
376 }
377 
378 } // namespace framework
379 
380