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 <uielement/menubarwrapper.hxx>
21 
22 #include <com/sun/star/beans/XPropertySet.hpp>
23 #include <com/sun/star/container/XNameAccess.hpp>
24 #include <com/sun/star/ui/UIElementType.hpp>
25 #include <com/sun/star/frame/ModuleManager.hpp>
26 #include <com/sun/star/util/URLTransformer.hpp>
27 
28 #include <comphelper/sequence.hxx>
29 #include <cppuhelper/typeprovider.hxx>
30 #include <cppuhelper/queryinterface.hxx>
31 #include <toolkit/awt/vclxmenu.hxx>
32 #include <vcl/svapp.hxx>
33 
34 using namespace com::sun::star;
35 using namespace com::sun::star::uno;
36 using namespace com::sun::star::beans;
37 using namespace com::sun::star::frame;
38 using namespace com::sun::star::lang;
39 using namespace com::sun::star::container;
40 using namespace com::sun::star::awt;
41 using namespace com::sun::star::util;
42 using namespace ::com::sun::star::ui;
43 
44 namespace framework
45 {
46 
acquire()47 void SAL_CALL MenuBarWrapper::acquire() noexcept                                                                          \
48 {                                                                                                                                                       \
49     /* Don't use mutex in methods of XInterface! */                                                                                                     \
50     UIConfigElementWrapperBase::acquire();                                                                                                                               \
51 }                                                                                                                                                       \
52                                                                                                                                                         \
release()53 void SAL_CALL MenuBarWrapper::release() noexcept                                                                          \
54 {                                                                                                                                                       \
55     /* Don't use mutex in methods of XInterface! */                                                                                                     \
56     UIConfigElementWrapperBase::release();                                                                                                                               \
57 }
58 
queryInterface(const css::uno::Type & aType)59 css::uno::Any SAL_CALL MenuBarWrapper::queryInterface( const css::uno::Type& aType )
60 {
61     /* Attention: Don't use mutex or guard in this method!!! Is a method of XInterface. */
62     /* Ask for my own supported interfaces ...                                          */
63     css::uno::Any aReturn  = ::cppu::queryInterface( aType,
64                         static_cast< css::lang::XTypeProvider* >( this ),
65                         static_cast< css::ui::XUIElement* >( this ),
66                         static_cast< css::ui::XUIElementSettings* >( this ),
67                         static_cast< css::beans::XMultiPropertySet* >( this ),
68                         static_cast< css::beans::XFastPropertySet* >( this ),
69                         static_cast< css::beans::XPropertySet* >( this ),
70                         static_cast< css::lang::XInitialization* >( this ),
71                         static_cast< css::lang::XComponent* >( this ),
72                         static_cast< css::util::XUpdatable* >( this ),
73                         static_cast< css::ui::XUIConfigurationListener* >( this ),
74                         static_cast< css::container::XNameAccess* >( static_cast< css::container::XElementAccess* >( this ) )
75                                         );
76     /* If searched interface not supported by this class ... */
77     if ( !aReturn.hasValue() )
78     {
79         /* ... ask baseclass for interfaces! */
80         aReturn = UIConfigElementWrapperBase::queryInterface( aType );
81     }
82     /* Return result of this search. */
83     return aReturn;
84 }
85 
getImplementationId()86 css::uno::Sequence< sal_Int8 > SAL_CALL MenuBarWrapper::getImplementationId()
87 {
88     return css::uno::Sequence<sal_Int8>();
89 }
90 
getTypes()91 css::uno::Sequence< css::uno::Type > SAL_CALL MenuBarWrapper::getTypes()
92 {
93     /* Attention: "TYPES" will expand to "(...)"!   */
94     static cppu::OTypeCollection ourTypeCollection {
95                         cppu::UnoType<css::lang::XTypeProvider>::get()           ,
96                         cppu::UnoType<css::ui::XUIElement>::get()                ,
97                         cppu::UnoType<css::ui::XUIElementSettings>::get()        ,
98                         cppu::UnoType<css::beans::XMultiPropertySet>::get()      ,
99                         cppu::UnoType<css::beans::XFastPropertySet>::get()       ,
100                         cppu::UnoType<css::beans::XPropertySet>::get()           ,
101                         cppu::UnoType<css::lang::XInitialization>::get()         ,
102                         cppu::UnoType<css::lang::XComponent>::get()              ,
103                         cppu::UnoType<css::util::XUpdatable>::get()              ,
104                         cppu::UnoType<css::ui::XUIConfigurationListener>::get()  ,
105                     cppu::UnoType<css::container::XNameAccess>::get() };
106     return ourTypeCollection.getTypes();
107 }
108 
MenuBarWrapper(const css::uno::Reference<css::uno::XComponentContext> & rxContext)109 MenuBarWrapper::MenuBarWrapper(
110     const css::uno::Reference< css::uno::XComponentContext >& rxContext
111     )
112 :    UIConfigElementWrapperBase( UIElementType::MENUBAR ),
113      m_bRefreshPopupControllerCache( true ),
114      m_xContext( rxContext )
115 {
116 }
117 
~MenuBarWrapper()118 MenuBarWrapper::~MenuBarWrapper()
119 {
120 }
121 
dispose()122 void SAL_CALL MenuBarWrapper::dispose()
123 {
124     Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY );
125 
126     css::lang::EventObject aEvent( xThis );
127     m_aListenerContainer.disposeAndClear( aEvent );
128 
129     SolarMutexGuard g;
130 
131     m_xMenuBarManager->dispose();
132     m_xMenuBarManager.clear();
133     m_xConfigSource.clear();
134     m_xConfigData.clear();
135 
136     m_xMenuBar.clear();
137     m_bDisposed = true;
138 }
139 
140 // XInitialization
initialize(const Sequence<Any> & aArguments)141 void SAL_CALL MenuBarWrapper::initialize( const Sequence< Any >& aArguments )
142 {
143     SolarMutexGuard g;
144 
145     if ( m_bDisposed )
146         throw DisposedException();
147 
148     if ( m_bInitialized )
149         return;
150 
151     OUString aModuleIdentifier;
152     UIConfigElementWrapperBase::initialize( aArguments );
153 
154     Reference< XFrame > xFrame( m_xWeakFrame );
155     if ( !(xFrame.is() && m_xConfigSource.is()) )
156         return;
157 
158     // Create VCL menubar which will be filled with settings data
159     VclPtr<MenuBar> pVCLMenuBar;
160     {
161         SolarMutexGuard aSolarMutexGuard;
162         pVCLMenuBar = VclPtr<MenuBar>::Create();
163     }
164 
165     Reference< XModuleManager2 > xModuleManager = ModuleManager::create( m_xContext );
166 
167     try
168     {
169         aModuleIdentifier = xModuleManager->identify( xFrame );
170     }
171     catch( const Exception& )
172     {
173     }
174 
175     Reference< XURLTransformer > xTrans;
176     try
177     {
178         xTrans.set( URLTransformer::create(m_xContext) );
179         m_xConfigData = m_xConfigSource->getSettings( m_aResourceURL, false );
180         if ( m_xConfigData.is() )
181         {
182             // Fill menubar with container contents
183             sal_uInt16 nId = 1;
184             MenuBarManager::FillMenuWithConfiguration( nId, pVCLMenuBar, aModuleIdentifier, m_xConfigData, xTrans );
185         }
186     }
187     catch ( const NoSuchElementException& )
188     {
189     }
190 
191     bool bMenuOnly( false );
192     for ( const Any& rArg : aArguments )
193     {
194         PropertyValue aPropValue;
195         if ( rArg >>= aPropValue )
196         {
197             if ( aPropValue.Name == "MenuOnly" )
198                 aPropValue.Value >>= bMenuOnly;
199         }
200     }
201 
202     if ( !bMenuOnly )
203     {
204         // Initialize menubar manager with our vcl menu bar. There are some situations where we only want to get the menu without any
205         // interaction which is done by the menu bar manager. This must be requested by a special property called "MenuOnly". Be careful
206         // a menu bar created with this property is not fully supported. It must be attached to a real menu bar manager to have full
207         // support. This feature is currently used for "Inplace editing"!
208         Reference< XDispatchProvider > xDispatchProvider;
209 
210         m_xMenuBarManager = new MenuBarManager( m_xContext,
211                                                               xFrame,
212                                                               xTrans,
213                                                               xDispatchProvider,
214                                                               aModuleIdentifier,
215                                                               pVCLMenuBar,
216                                                               false );
217     }
218 
219     // Initialize toolkit menu bar implementation to have awt::XMenuBar for data exchange.
220     // Don't use this toolkit menu bar or one of its functions. It is only used as a data container!
221     m_xMenuBar = new VCLXMenuBar( pVCLMenuBar );
222 }
223 
224 // XUIElementSettings
updateSettings()225 void SAL_CALL MenuBarWrapper::updateSettings()
226 {
227     SolarMutexGuard g;
228 
229     if ( m_bDisposed )
230         throw DisposedException();
231 
232     if ( !m_xMenuBarManager.is() )
233         return;
234 
235     if ( m_xConfigSource.is() && m_bPersistent )
236     {
237         try
238         {
239             MenuBarManager* pMenuBarManager = static_cast< MenuBarManager *>( m_xMenuBarManager.get() );
240 
241             m_xConfigData = m_xConfigSource->getSettings( m_aResourceURL, false );
242             if ( m_xConfigData.is() )
243                 pMenuBarManager->SetItemContainer( m_xConfigData );
244         }
245         catch ( const NoSuchElementException& )
246         {
247         }
248     }
249     else if ( !m_bPersistent )
250     {
251         // Transient menubar: do nothing
252     }
253 }
impl_fillNewData()254 void MenuBarWrapper::impl_fillNewData()
255 {
256     // Transient menubar => Fill menubar with new data
257     MenuBarManager* pMenuBarManager = static_cast< MenuBarManager *>( m_xMenuBarManager.get() );
258 
259     if ( pMenuBarManager )
260         pMenuBarManager->SetItemContainer( m_xConfigData );
261 }
262 
fillPopupControllerCache()263 void MenuBarWrapper::fillPopupControllerCache()
264 {
265     if ( m_bRefreshPopupControllerCache )
266     {
267         MenuBarManager* pMenuBarManager = static_cast< MenuBarManager *>( m_xMenuBarManager.get() );
268         if ( pMenuBarManager )
269             pMenuBarManager->GetPopupController( m_aPopupControllerCache );
270         if ( !m_aPopupControllerCache.empty() )
271             m_bRefreshPopupControllerCache = false;
272     }
273 }
274 
275 // XElementAccess
getElementType()276 Type SAL_CALL MenuBarWrapper::getElementType()
277 {
278     return cppu::UnoType<XDispatchProvider>::get();
279 }
280 
hasElements()281 sal_Bool SAL_CALL MenuBarWrapper::hasElements()
282 {
283     SolarMutexGuard g;
284 
285     if ( m_bDisposed )
286         throw DisposedException();
287 
288     fillPopupControllerCache();
289     return ( !m_aPopupControllerCache.empty() );
290 }
291 
292 // XNameAccess
getByName(const OUString & aName)293 Any SAL_CALL MenuBarWrapper::getByName(
294     const OUString& aName )
295 {
296     SolarMutexGuard g;
297 
298     if ( m_bDisposed )
299         throw DisposedException();
300 
301     fillPopupControllerCache();
302 
303     PopupControllerCache::const_iterator pIter = m_aPopupControllerCache.find( aName );
304     if ( pIter == m_aPopupControllerCache.end() )
305         throw container::NoSuchElementException();
306 
307     uno::Reference< frame::XDispatchProvider > xDispatchProvider = pIter->second.m_xDispatchProvider;
308     return uno::makeAny( xDispatchProvider );
309 }
310 
getElementNames()311 Sequence< OUString > SAL_CALL MenuBarWrapper::getElementNames()
312 {
313     SolarMutexGuard g;
314 
315     if ( m_bDisposed )
316         throw DisposedException();
317 
318     fillPopupControllerCache();
319 
320     return comphelper::mapKeysToSequence( m_aPopupControllerCache );
321 }
322 
hasByName(const OUString & aName)323 sal_Bool SAL_CALL MenuBarWrapper::hasByName(
324     const OUString& aName )
325 {
326     SolarMutexGuard g;
327 
328     if ( m_bDisposed )
329         throw DisposedException();
330 
331     fillPopupControllerCache();
332 
333     PopupControllerCache::const_iterator pIter = m_aPopupControllerCache.find( aName );
334     if ( pIter != m_aPopupControllerCache.end() )
335         return true;
336     else
337         return false;
338 }
339 
340 // XUIElement
getRealInterface()341 Reference< XInterface > SAL_CALL MenuBarWrapper::getRealInterface()
342 {
343     if ( m_bDisposed )
344         throw DisposedException();
345 
346     return Reference< XInterface >( m_xMenuBarManager, UNO_QUERY );
347 }
348 
349 } // namespace framework
350 
351 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
352