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 "svtools/popupmenucontrollerbase.hxx"
30 : :
31 : : #include <com/sun/star/awt/XDevice.hpp>
32 : : #include <com/sun/star/beans/PropertyValue.hpp>
33 : : #include <com/sun/star/awt/MenuItemStyle.hpp>
34 : : #include <com/sun/star/frame/XDispatchProvider.hpp>
35 : : #include <com/sun/star/lang/DisposedException.hpp>
36 : : #include <com/sun/star/awt/XMenuExtended.hpp>
37 : : #include <com/sun/star/util/URLTransformer.hpp>
38 : :
39 : : #include <vcl/menu.hxx>
40 : : #include <vcl/svapp.hxx>
41 : : #include <rtl/ustrbuf.hxx>
42 : : #include <rtl/logfile.hxx>
43 : : #include <osl/mutex.hxx>
44 : : #include <comphelper/componentcontext.hxx>
45 : :
46 : : //_________________________________________________________________________________________________________________
47 : : // Defines
48 : : //_________________________________________________________________________________________________________________
49 : : //
50 : :
51 : : using ::rtl::OUString;
52 : :
53 : : using namespace com::sun::star;
54 : : using namespace com::sun::star::uno;
55 : : using namespace com::sun::star::lang;
56 : : using namespace com::sun::star::frame;
57 : : using namespace com::sun::star::beans;
58 : : using namespace com::sun::star::util;
59 : :
60 : : namespace svt
61 : : {
62 : :
63 [ # # ]: 0 : struct PopupMenuControllerBaseDispatchInfo
64 : : {
65 : : Reference< XDispatch > mxDispatch;
66 : : const URL maURL;
67 : : const Sequence< PropertyValue > maArgs;
68 : :
69 : 0 : PopupMenuControllerBaseDispatchInfo( const Reference< XDispatch >& xDispatch, const URL& rURL, const Sequence< PropertyValue >& rArgs )
70 [ # # ]: 0 : : mxDispatch( xDispatch ), maURL( rURL ), maArgs( rArgs ) {}
71 : : };
72 : :
73 : 38 : PopupMenuControllerBase::PopupMenuControllerBase( const Reference< XMultiServiceFactory >& xServiceManager ) :
74 : : ::comphelper::OBaseMutex(),
75 : : PopupMenuControllerBaseType(m_aMutex),
76 : : m_bInitialized( false ),
77 : 38 : m_xServiceManager( xServiceManager )
78 : : {
79 [ + - ]: 38 : if ( m_xServiceManager.is() )
80 [ + - ][ + - ]: 38 : m_xURLTransformer.set( util::URLTransformer::create( ::comphelper::ComponentContext(m_xServiceManager).getUNOContext() ) );
[ + - ][ + - ]
[ + - ]
81 : 38 : }
82 : :
83 [ + - ]: 38 : PopupMenuControllerBase::~PopupMenuControllerBase()
84 : : {
85 [ - + ]: 38 : }
86 : :
87 : : // protected function
88 : 58 : void PopupMenuControllerBase::throwIfDisposed() throw ( RuntimeException )
89 : : {
90 [ + - ][ - + ]: 58 : if (rBHelper.bDisposed || rBHelper.bInDispose)
91 [ # # ]: 0 : throw com::sun::star::lang::DisposedException();
92 : 58 : }
93 : :
94 : : // protected function
95 : 2 : void PopupMenuControllerBase::resetPopupMenu( com::sun::star::uno::Reference< com::sun::star::awt::XPopupMenu >& rPopupMenu )
96 : : {
97 : 2 : VCLXPopupMenu* pPopupMenu = 0;
98 [ + - ][ - + ]: 2 : if ( rPopupMenu.is() && rPopupMenu->getItemCount() > 0 )
[ - + ]
99 : : {
100 : 0 : pPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( rPopupMenu );
101 [ # # ]: 0 : if ( pPopupMenu )
102 : : {
103 [ # # ]: 0 : SolarMutexGuard aSolarMutexGuard;
104 : :
105 : 0 : PopupMenu* pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu();
106 [ # # ][ # # ]: 0 : pVCLPopupMenu->Clear();
107 : : }
108 : : }
109 : 2 : }
110 : :
111 : 38 : void SAL_CALL PopupMenuControllerBase::disposing()
112 : : {
113 : : // Reset our members and set disposed flag
114 [ + - ]: 38 : osl::MutexGuard aLock( m_aMutex );
115 : 38 : m_xFrame.clear();
116 : 38 : m_xDispatch.clear();
117 : 38 : m_xPopupMenu.clear();
118 [ + - ]: 38 : m_xServiceManager.clear();
119 : 38 : }
120 : :
121 : : // XServiceInfo
122 : :
123 : 0 : sal_Bool SAL_CALL PopupMenuControllerBase::supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException)
124 : : {
125 [ # # ]: 0 : const Sequence< rtl::OUString > aSNL( getSupportedServiceNames() );
126 : 0 : const rtl::OUString * pArray = aSNL.getConstArray();
127 : :
128 [ # # ]: 0 : for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
129 [ # # ]: 0 : if( pArray[i] == ServiceName )
130 : 0 : return true;
131 : :
132 [ # # ]: 0 : return false;
133 : : }
134 : :
135 : : // XEventListener
136 : 0 : void SAL_CALL PopupMenuControllerBase::disposing( const EventObject& ) throw ( RuntimeException )
137 : : {
138 [ # # ]: 0 : osl::MutexGuard aLock( m_aMutex );
139 : 0 : m_xFrame.clear();
140 : 0 : m_xDispatch.clear();
141 [ # # ]: 0 : m_xPopupMenu.clear();
142 : 0 : }
143 : :
144 : : // XMenuListener
145 : 0 : void SAL_CALL PopupMenuControllerBase::highlight( const awt::MenuEvent& ) throw (RuntimeException)
146 : : {
147 : 0 : }
148 : :
149 : 0 : void PopupMenuControllerBase::impl_select(const Reference< XDispatch >& _xDispatch,const URL& aURL)
150 : : {
151 [ # # ]: 0 : Sequence<PropertyValue> aArgs;
152 : : OSL_ENSURE(_xDispatch.is(),"PopupMenuControllerBase::impl_select: No dispatch");
153 [ # # ]: 0 : if ( _xDispatch.is() )
154 [ # # ][ # # ]: 0 : _xDispatch->dispatch( aURL, aArgs );
[ # # ]
155 : 0 : }
156 : :
157 : 0 : void SAL_CALL PopupMenuControllerBase::select( const awt::MenuEvent& rEvent ) throw (RuntimeException)
158 : : {
159 [ # # ]: 0 : throwIfDisposed();
160 : :
161 [ # # ]: 0 : osl::MutexGuard aLock( m_aMutex );
162 : :
163 [ # # ]: 0 : Reference< awt::XMenuExtended > xExtMenu( m_xPopupMenu, UNO_QUERY );
164 [ # # ]: 0 : if( xExtMenu.is() )
165 : : {
166 [ # # ]: 0 : Sequence<PropertyValue> aArgs;
167 [ # # ][ # # ]: 0 : dispatchCommand( xExtMenu->getCommand( rEvent.MenuId ), aArgs );
[ # # ][ # # ]
168 [ # # ]: 0 : }
169 : 0 : }
170 : :
171 : 0 : void PopupMenuControllerBase::dispatchCommand( const ::rtl::OUString& sCommandURL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rArgs )
172 : : {
173 [ # # ]: 0 : osl::MutexGuard aLock( m_aMutex );
174 : :
175 [ # # ]: 0 : throwIfDisposed();
176 : :
177 : : try
178 : : {
179 [ # # ]: 0 : Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY_THROW );
180 : 0 : URL aURL;
181 : 0 : aURL.Complete = sCommandURL;
182 [ # # ][ # # ]: 0 : m_xURLTransformer->parseStrict( aURL );
183 : :
184 [ # # ][ # # ]: 0 : Reference< XDispatch > xDispatch( xDispatchProvider->queryDispatch( aURL, OUString(), 0 ), UNO_QUERY_THROW );
[ # # ]
185 : :
186 [ # # ][ # # ]: 0 : Application::PostUserEvent( STATIC_LINK(0, PopupMenuControllerBase, ExecuteHdl_Impl), new PopupMenuControllerBaseDispatchInfo( xDispatch, aURL, rArgs ) );
[ # # ][ # # ]
[ # # ]
187 : :
188 : : }
189 [ # # ]: 0 : catch( Exception& )
190 : : {
191 [ # # ]: 0 : }
192 : :
193 : 0 : }
194 : :
195 : 0 : IMPL_STATIC_LINK_NOINSTANCE( PopupMenuControllerBase, ExecuteHdl_Impl, PopupMenuControllerBaseDispatchInfo*, pDispatchInfo )
196 : : {
197 : 0 : pDispatchInfo->mxDispatch->dispatch( pDispatchInfo->maURL, pDispatchInfo->maArgs );
198 [ # # ]: 0 : delete pDispatchInfo;
199 : 0 : return 0;
200 : : }
201 : :
202 : 0 : void SAL_CALL PopupMenuControllerBase::activate( const awt::MenuEvent& ) throw (RuntimeException)
203 : : {
204 : 0 : }
205 : :
206 : 0 : void SAL_CALL PopupMenuControllerBase::deactivate( const awt::MenuEvent& ) throw (RuntimeException)
207 : : {
208 : 0 : }
209 : :
210 : 28 : void SAL_CALL PopupMenuControllerBase::updatePopupMenu() throw ( ::com::sun::star::uno::RuntimeException )
211 : : {
212 [ + - ]: 28 : osl::ClearableMutexGuard aLock( m_aMutex );
213 [ + - ]: 28 : throwIfDisposed();
214 [ + - ]: 28 : aLock.clear();
215 : :
216 [ + - ][ + - ]: 28 : updateCommand( m_aCommandURL );
217 : 28 : }
218 : :
219 : 28 : void SAL_CALL PopupMenuControllerBase::updateCommand( const rtl::OUString& rCommandURL )
220 : : {
221 [ + - ]: 28 : osl::ClearableMutexGuard aLock( m_aMutex );
222 [ + - ]: 28 : Reference< XStatusListener > xStatusListener( static_cast< OWeakObject* >( this ), UNO_QUERY );
223 : 28 : Reference< XDispatch > xDispatch( m_xDispatch );
224 : 28 : URL aTargetURL;
225 : 28 : aTargetURL.Complete = rCommandURL;
226 [ + - ][ + - ]: 28 : m_xURLTransformer->parseStrict( aTargetURL );
227 [ + - ]: 28 : aLock.clear();
228 : :
229 : : // Add/remove status listener to get a status update once
230 [ + + ]: 28 : if ( xDispatch.is() )
231 : : {
232 [ + - ][ + - ]: 10 : xDispatch->addStatusListener( xStatusListener, aTargetURL );
233 [ + - ][ + - ]: 10 : xDispatch->removeStatusListener( xStatusListener, aTargetURL );
234 [ + - ]: 28 : }
235 : 28 : }
236 : :
237 : :
238 : : // XDispatchProvider
239 : : Reference< XDispatch > SAL_CALL
240 : 0 : PopupMenuControllerBase::queryDispatch(
241 : : const URL& /*aURL*/,
242 : : const rtl::OUString& /*sTarget*/,
243 : : sal_Int32 /*nFlags*/ )
244 : : throw( RuntimeException )
245 : : {
246 : : // must be implemented by subclass
247 [ # # ]: 0 : osl::MutexGuard aLock( m_aMutex );
248 [ # # ]: 0 : throwIfDisposed();
249 : :
250 [ # # ]: 0 : return Reference< XDispatch >();
251 : : }
252 : :
253 : 0 : Sequence< Reference< XDispatch > > SAL_CALL PopupMenuControllerBase::queryDispatches( const Sequence< DispatchDescriptor >& lDescriptor ) throw( RuntimeException )
254 : : {
255 : : // Create return list - which must have same size then the given descriptor
256 : : // It's not allowed to pack it!
257 [ # # ]: 0 : osl::ClearableMutexGuard aLock( m_aMutex );
258 [ # # ]: 0 : throwIfDisposed();
259 [ # # ]: 0 : aLock.clear();
260 : :
261 : 0 : sal_Int32 nCount = lDescriptor.getLength();
262 [ # # ]: 0 : uno::Sequence< uno::Reference< frame::XDispatch > > lDispatcher( nCount );
263 : :
264 : : // Step over all descriptors and try to get any dispatcher for it.
265 [ # # ]: 0 : for( sal_Int32 i=0; i<nCount; ++i )
266 : : {
267 [ # # ]: 0 : lDispatcher[i] = queryDispatch( lDescriptor[i].FeatureURL ,
268 : 0 : lDescriptor[i].FrameName ,
269 [ # # ][ # # ]: 0 : lDescriptor[i].SearchFlags );
270 : : }
271 : :
272 [ # # ]: 0 : return lDispatcher;
273 : : }
274 : :
275 : : // XDispatch
276 : : void SAL_CALL
277 : 0 : PopupMenuControllerBase::dispatch(
278 : : const URL& /*aURL*/,
279 : : const Sequence< PropertyValue >& /*seqProperties*/ )
280 : : throw( ::com::sun::star::uno::RuntimeException )
281 : : {
282 : : // must be implemented by subclass
283 [ # # ]: 0 : osl::MutexGuard aLock( m_aMutex );
284 [ # # ][ # # ]: 0 : throwIfDisposed();
285 : 0 : }
286 : :
287 : : void SAL_CALL
288 : 0 : PopupMenuControllerBase::addStatusListener(
289 : : const Reference< XStatusListener >& xControl,
290 : : const URL& aURL )
291 : : throw( ::com::sun::star::uno::RuntimeException )
292 : : {
293 [ # # ]: 0 : osl::ResettableMutexGuard aLock( m_aMutex );
294 [ # # ]: 0 : throwIfDisposed();
295 [ # # ]: 0 : aLock.clear();
296 : :
297 : 0 : bool bStatusUpdate( false );
298 [ # # ][ # # ]: 0 : rBHelper.addListener( ::getCppuType( &xControl ), xControl );
299 : :
300 [ # # ]: 0 : aLock.reset();
301 [ # # ]: 0 : if ( aURL.Complete.indexOf( m_aBaseURL ) == 0 )
302 : 0 : bStatusUpdate = true;
303 [ # # ]: 0 : aLock.clear();
304 : :
305 [ # # ]: 0 : if ( bStatusUpdate )
306 : : {
307 : : // Dummy update for popup menu controllers
308 [ # # ]: 0 : FeatureStateEvent aEvent;
309 : 0 : aEvent.FeatureURL = aURL;
310 : 0 : aEvent.IsEnabled = sal_True;
311 : 0 : aEvent.Requery = sal_False;
312 : 0 : aEvent.State = Any();
313 [ # # ][ # # ]: 0 : xControl->statusChanged( aEvent );
[ # # ]
314 [ # # ]: 0 : }
315 : 0 : }
316 : :
317 : 0 : void SAL_CALL PopupMenuControllerBase::removeStatusListener(
318 : : const Reference< XStatusListener >& xControl,
319 : : const URL& /*aURL*/ )
320 : : throw( ::com::sun::star::uno::RuntimeException )
321 : : {
322 : 0 : rBHelper.removeListener( ::getCppuType( &xControl ), xControl );
323 : 0 : }
324 : :
325 : 6 : ::rtl::OUString PopupMenuControllerBase::determineBaseURL( const ::rtl::OUString& aURL )
326 : : {
327 : : // Just use the main part of the URL for popup menu controllers
328 : 6 : sal_Int32 nQueryPart( 0 );
329 : 6 : sal_Int32 nSchemePart( 0 );
330 : 6 : rtl::OUString aMainURL( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.popup:" ));
331 : :
332 : 6 : nSchemePart = aURL.indexOf( ':' );
333 [ + - ]: 12 : if (( nSchemePart > 0 ) &&
[ + - + - ]
334 : 6 : ( aURL.getLength() > ( nSchemePart+1 )))
335 : : {
336 : 6 : nQueryPart = aURL.indexOf( '?', nSchemePart );
337 [ - + ]: 6 : if ( nQueryPart > 0 )
338 : 0 : aMainURL += aURL.copy( nSchemePart, nQueryPart-nSchemePart );
339 [ + - ]: 6 : else if ( nQueryPart == -1 )
340 : 6 : aMainURL += aURL.copy( nSchemePart+1 );
341 : : }
342 : :
343 : 6 : return aMainURL;
344 : : }
345 : :
346 : : // XInitialization
347 : 22 : void SAL_CALL PopupMenuControllerBase::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException )
348 : : {
349 [ + - ]: 22 : osl::MutexGuard aLock( m_aMutex );
350 : :
351 : 22 : sal_Bool bInitalized( m_bInitialized );
352 [ + - ]: 22 : if ( !bInitalized )
353 : : {
354 : 22 : PropertyValue aPropValue;
355 : 22 : rtl::OUString aCommandURL;
356 : 22 : Reference< XFrame > xFrame;
357 : :
358 [ + + ]: 40 : for ( int i = 0; i < aArguments.getLength(); i++ )
359 : : {
360 [ + - ][ + - ]: 18 : if ( aArguments[i] >>= aPropValue )
361 : : {
362 [ + + ]: 18 : if ( aPropValue.Name == "Frame" )
363 [ + - ]: 6 : aPropValue.Value >>= xFrame;
364 [ + + ]: 12 : else if ( aPropValue.Name == "CommandURL" )
365 : 6 : aPropValue.Value >>= aCommandURL;
366 [ + - ]: 6 : else if ( aPropValue.Name == "ModuleName" )
367 : 6 : aPropValue.Value >>= m_aModuleName;
368 : : }
369 : : }
370 : :
371 [ + + ][ + - ]: 22 : if ( xFrame.is() && !aCommandURL.isEmpty() )
[ + + ]
372 : : {
373 [ + - ]: 6 : m_xFrame = xFrame;
374 : 6 : m_aCommandURL = aCommandURL;
375 [ + - ]: 6 : m_aBaseURL = determineBaseURL( aCommandURL );
376 : 6 : m_bInitialized = true;
377 : 22 : }
378 [ + - ]: 22 : }
379 : 22 : }
380 : : // XPopupMenuController
381 : 18 : void SAL_CALL PopupMenuControllerBase::setPopupMenu( const Reference< awt::XPopupMenu >& xPopupMenu ) throw ( RuntimeException )
382 : : {
383 [ + - ]: 18 : osl::MutexGuard aLock( m_aMutex );
384 [ + - ]: 18 : throwIfDisposed();
385 : :
386 [ + + ][ + - ]: 18 : if ( m_xFrame.is() && !m_xPopupMenu.is() )
[ + + ]
387 : : {
388 : : // Create popup menu on demand
389 [ + - ]: 4 : SolarMutexGuard aSolarMutexGuard;
390 : :
391 [ + - ]: 4 : m_xPopupMenu = xPopupMenu;
392 [ + - ][ + - ]: 4 : m_xPopupMenu->addMenuListener( Reference< awt::XMenuListener >( (OWeakObject*)this, UNO_QUERY ));
[ + - ]
393 : :
394 [ + - ]: 4 : Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
395 : :
396 : 4 : URL aTargetURL;
397 : 4 : aTargetURL.Complete = m_aCommandURL;
398 [ + - ][ + - ]: 4 : m_xURLTransformer->parseStrict( aTargetURL );
399 [ + - ][ + - ]: 4 : m_xDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 );
[ + - ]
400 : :
401 [ + - ]: 4 : impl_setPopupMenu();
402 : :
403 [ + - ][ + - ]: 4 : updatePopupMenu();
404 [ + - ]: 18 : }
405 : 18 : }
406 : 4 : void PopupMenuControllerBase::impl_setPopupMenu()
407 : : {
408 : 4 : }
409 : : }
410 : :
411 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|