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