update dev300-m58
[ooovba.git] / framework / source / helper / popupmenucontrollerbase.cxx
blobe8215ecccaaccbbb7983fbb84f49faa372a2e9cd
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: popupmenucontrollerbase.cxx,v $
10 * $Revision: 1.8.82.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_framework.hxx"
33 #include <helper/popupmenucontrollerbase.hxx>
35 //_________________________________________________________________________________________________________________
36 // my own includes
37 //_________________________________________________________________________________________________________________
38 #include <threadhelp/resetableguard.hxx>
39 #include "services.h"
41 //_________________________________________________________________________________________________________________
42 // interface includes
43 //_________________________________________________________________________________________________________________
44 #include <com/sun/star/awt/XDevice.hpp>
45 #include <com/sun/star/beans/PropertyValue.hpp>
46 #include <com/sun/star/awt/MenuItemStyle.hpp>
47 #include <com/sun/star/frame/XDispatchProvider.hpp>
48 #include <com/sun/star/lang/DisposedException.hpp>
50 //_________________________________________________________________________________________________________________
51 // includes of other projects
52 //_________________________________________________________________________________________________________________
54 #ifndef _VCL_MENU_HXX_
55 #include <vcl/menu.hxx>
56 #endif
57 #include <vcl/svapp.hxx>
58 #include <rtl/ustrbuf.hxx>
59 #include <rtl/logfile.hxx>
60 //_________________________________________________________________________________________________________________
61 // Defines
62 //_________________________________________________________________________________________________________________
63 //
65 using namespace com::sun::star::uno;
66 using namespace com::sun::star::lang;
67 using namespace com::sun::star::frame;
68 using namespace com::sun::star::beans;
69 using namespace com::sun::star::util;
71 namespace framework
74 //*****************************************************************************************************************
75 // XInterface, XTypeProvider, XServiceInfo
76 //*****************************************************************************************************************
77 DEFINE_XINTERFACE_11 ( PopupMenuControllerBase ,
78 OWeakObject ,
79 DIRECT_INTERFACE( css::lang::XTypeProvider ),
80 DIRECT_INTERFACE( css::lang::XServiceInfo ),
81 DIRECT_INTERFACE( ::com::sun::star::frame::XPopupMenuController ),
82 DIRECT_INTERFACE( css::lang::XInitialization ),
83 DIRECT_INTERFACE( css::frame::XStatusListener ),
84 DIRECT_INTERFACE( css::awt::XMenuListener ),
85 DIRECT_INTERFACE( css::frame::XDispatchProvider ),
86 DIRECT_INTERFACE( css::frame::XDispatch ),
87 DIRECT_INTERFACE( css::lang::XComponent ),
88 DERIVED_INTERFACE( css::lang::XEventListener, css::frame::XStatusListener ),
89 DERIVED_INTERFACE( css::lang::XEventListener, css::awt::XMenuListener )
92 DEFINE_XTYPEPROVIDER_10 ( PopupMenuControllerBase ,
93 css::lang::XTypeProvider ,
94 css::lang::XServiceInfo ,
95 ::com::sun::star::frame::XPopupMenuController ,
96 css::lang::XInitialization ,
97 css::frame::XStatusListener ,
98 css::awt::XMenuListener ,
99 css::lang::XEventListener ,
100 css::frame::XDispatchProvider ,
101 css::frame::XDispatch ,
102 css::lang::XComponent
105 PopupMenuControllerBase::PopupMenuControllerBase( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ) :
106 ThreadHelpBase(),
107 ::cppu::OBroadcastHelperVar< ::cppu::OMultiTypeInterfaceContainerHelper, ::cppu::OMultiTypeInterfaceContainerHelper::keyType >( m_aLock.getShareableOslMutex() ),
108 m_bInitialized( false ),
109 m_bDisposed( false ),
110 m_xServiceManager( xServiceManager ),
111 m_aListenerContainer( m_aLock.getShareableOslMutex() )
113 if ( m_xServiceManager.is() )
114 m_xURLTransformer.set( m_xServiceManager->createInstance(
115 SERVICENAME_URLTRANSFORMER),
116 UNO_QUERY );
119 PopupMenuControllerBase::~PopupMenuControllerBase()
123 // protected function
124 void PopupMenuControllerBase::resetPopupMenu( com::sun::star::uno::Reference< com::sun::star::awt::XPopupMenu >& rPopupMenu )
126 VCLXPopupMenu* pPopupMenu = 0;
127 if ( rPopupMenu.is() && rPopupMenu->getItemCount() > 0 )
129 pPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( rPopupMenu );
130 if ( pPopupMenu )
132 vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
134 PopupMenu* pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu();
135 pVCLPopupMenu->Clear();
140 void SAL_CALL PopupMenuControllerBase::dispose()
141 throw (::com::sun::star::uno::RuntimeException)
143 css::uno::Reference< css::lang::XComponent > xThis( static_cast< ::cppu::OWeakObject* >(this), UNO_QUERY );
145 // Send message to all listener and forget their references.
146 css::lang::EventObject aEvent( xThis );
147 m_aListenerContainer.disposeAndClear( aEvent );
149 // Reset our members and set disposed flag
150 ResetableGuard aLock( m_aLock );
151 m_xFrame.clear();
152 m_xDispatch.clear();
153 m_xPopupMenu.clear();
154 m_xServiceManager.clear();
155 m_bDisposed = true;
158 void SAL_CALL PopupMenuControllerBase::addEventListener(
159 const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& xListener )
160 throw (::com::sun::star::uno::RuntimeException)
162 m_aListenerContainer.addInterface( ::getCppuType( (const css::uno::Reference< css::lang::XEventListener >*)NULL ), xListener );
165 void SAL_CALL PopupMenuControllerBase::removeEventListener(
166 const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& xListener )
167 throw (::com::sun::star::uno::RuntimeException)
169 m_aListenerContainer.removeInterface( ::getCppuType( (const css::uno::Reference< css::lang::XEventListener >*)NULL ), xListener );
172 // XEventListener
173 void SAL_CALL PopupMenuControllerBase::disposing( const EventObject& ) throw ( RuntimeException )
175 ResetableGuard aLock( m_aLock );
176 m_xFrame.clear();
177 m_xDispatch.clear();
178 m_xPopupMenu.clear();
181 // XMenuListener
182 void SAL_CALL PopupMenuControllerBase::highlight( const css::awt::MenuEvent& ) throw (RuntimeException)
186 void PopupMenuControllerBase::impl_select(const Reference< XDispatch >& _xDispatch,const ::com::sun::star::util::URL& aURL)
188 Sequence<PropertyValue> aArgs;
189 _xDispatch->dispatch( aURL, aArgs );
192 void SAL_CALL PopupMenuControllerBase::select( const css::awt::MenuEvent& rEvent ) throw (RuntimeException)
194 Reference< css::awt::XPopupMenu > xPopupMenu;
195 Reference< XDispatch > xDispatch;
196 Reference< XMultiServiceFactory > xServiceManager;
198 if ( m_bDisposed )
199 throw DisposedException();
201 ResetableGuard aLock( m_aLock );
202 xPopupMenu = m_xPopupMenu;
203 xDispatch = m_xDispatch;
204 xServiceManager = m_xServiceManager;
205 aLock.unlock();
207 if ( xPopupMenu.is() && xDispatch.is() )
209 VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXPopupMenu::GetImplementation( xPopupMenu );
210 if ( pPopupMenu )
212 css::util::URL aTargetURL;
214 vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
215 PopupMenu* pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu();
216 aTargetURL.Complete = pVCLPopupMenu->GetItemCommand( rEvent.MenuId );
219 m_xURLTransformer->parseStrict( aTargetURL );
220 impl_select(xDispatch,aTargetURL);
225 void SAL_CALL PopupMenuControllerBase::activate( const css::awt::MenuEvent& ) throw (RuntimeException)
229 void SAL_CALL PopupMenuControllerBase::deactivate( const css::awt::MenuEvent& ) throw (RuntimeException)
233 void SAL_CALL PopupMenuControllerBase::updatePopupMenu() throw ( ::com::sun::star::uno::RuntimeException )
235 ResetableGuard aLock( m_aLock );
237 if ( m_bDisposed )
238 throw DisposedException();
240 Reference< XStatusListener > xStatusListener( static_cast< OWeakObject* >( this ), UNO_QUERY );
241 Reference< XDispatch > xDispatch( m_xDispatch );
242 com::sun::star::util::URL aTargetURL;
243 aTargetURL.Complete = m_aCommandURL;
244 m_xURLTransformer->parseStrict( aTargetURL );
245 aLock.unlock();
247 // Add/remove status listener to get a status update once
248 if ( xDispatch.is() )
250 xDispatch->addStatusListener( xStatusListener, aTargetURL );
251 xDispatch->removeStatusListener( xStatusListener, aTargetURL );
255 // XDispatchProvider
256 Reference< XDispatch > SAL_CALL
257 PopupMenuControllerBase::queryDispatch(
258 const URL& /*aURL*/,
259 const rtl::OUString& /*sTarget*/,
260 sal_Int32 /*nFlags*/ )
261 throw( RuntimeException )
263 // must be implemented by subclass
264 ResetableGuard aLock( m_aLock );
265 if ( m_bDisposed )
266 throw DisposedException();
268 return Reference< XDispatch >();
271 Sequence< Reference< XDispatch > > SAL_CALL PopupMenuControllerBase::queryDispatches( const Sequence< DispatchDescriptor >& lDescriptor ) throw( RuntimeException )
273 // Create return list - which must have same size then the given descriptor
274 // It's not allowed to pack it!
275 ResetableGuard aLock( m_aLock );
276 if ( m_bDisposed )
277 throw DisposedException();
278 aLock.unlock();
280 sal_Int32 nCount = lDescriptor.getLength();
281 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatcher( nCount );
283 // Step over all descriptors and try to get any dispatcher for it.
284 for( sal_Int32 i=0; i<nCount; ++i )
286 lDispatcher[i] = queryDispatch( lDescriptor[i].FeatureURL ,
287 lDescriptor[i].FrameName ,
288 lDescriptor[i].SearchFlags );
291 return lDispatcher;
294 // XDispatch
295 void SAL_CALL
296 PopupMenuControllerBase::dispatch(
297 const URL& /*aURL*/,
298 const Sequence< PropertyValue >& /*seqProperties*/ )
299 throw( ::com::sun::star::uno::RuntimeException )
301 // must be implemented by subclass
302 ResetableGuard aLock( m_aLock );
303 if ( m_bDisposed )
304 throw DisposedException();
307 void SAL_CALL
308 PopupMenuControllerBase::addStatusListener(
309 const Reference< XStatusListener >& xControl,
310 const URL& aURL )
311 throw( ::com::sun::star::uno::RuntimeException )
313 ResetableGuard aLock( m_aLock );
314 if ( m_bDisposed )
315 throw DisposedException();
316 aLock.unlock();
318 bool bStatusUpdate( false );
319 m_aListenerContainer.addInterface( ::getCppuType( (const css::uno::Reference< css::frame::XStatusListener >*)NULL ), xControl );
321 aLock.lock();
322 if ( aURL.Complete.indexOf( m_aBaseURL ) == 0 )
323 bStatusUpdate = true;
324 aLock.unlock();
326 if ( bStatusUpdate )
328 // Dummy update for popup menu controllers
329 FeatureStateEvent aEvent;
330 aEvent.FeatureURL = aURL;
331 aEvent.IsEnabled = sal_True;
332 aEvent.Requery = sal_False;
333 aEvent.State = Any();
334 xControl->statusChanged( aEvent );
338 void SAL_CALL PopupMenuControllerBase::removeStatusListener(
339 const Reference< XStatusListener >& xControl,
340 const URL& /*aURL*/ )
341 throw( ::com::sun::star::uno::RuntimeException )
343 m_aListenerContainer.removeInterface( ::getCppuType( (const css::uno::Reference< css::frame::XStatusListener >*)NULL ), xControl );
346 ::rtl::OUString PopupMenuControllerBase::determineBaseURL( const ::rtl::OUString& aURL )
348 // Just use the main part of the URL for popup menu controllers
349 sal_Int32 nQueryPart( 0 );
350 sal_Int32 nSchemePart( 0 );
351 rtl::OUString aMainURL( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.popup:" ));
353 nSchemePart = aURL.indexOf( ':' );
354 if (( nSchemePart > 0 ) &&
355 ( aURL.getLength() > ( nSchemePart+1 )))
357 nQueryPart = aURL.indexOf( '?', nSchemePart );
358 if ( nQueryPart > 0 )
359 aMainURL += aURL.copy( nSchemePart, nQueryPart-nSchemePart );
360 else if ( nQueryPart == -1 )
361 aMainURL += aURL.copy( nSchemePart+1 );
364 return aMainURL;
367 // XInitialization
368 void SAL_CALL PopupMenuControllerBase::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException )
370 ResetableGuard aLock( m_aLock );
372 sal_Bool bInitalized( m_bInitialized );
373 if ( !bInitalized )
375 PropertyValue aPropValue;
376 rtl::OUString aCommandURL;
377 Reference< XFrame > xFrame;
379 for ( int i = 0; i < aArguments.getLength(); i++ )
381 if ( aArguments[i] >>= aPropValue )
383 if ( aPropValue.Name.equalsAscii( "Frame" ))
384 aPropValue.Value >>= xFrame;
385 else if ( aPropValue.Name.equalsAscii( "CommandURL" ))
386 aPropValue.Value >>= aCommandURL;
390 if ( xFrame.is() && aCommandURL.getLength() )
392 m_xFrame = xFrame;
393 m_aCommandURL = aCommandURL;
394 m_aBaseURL = determineBaseURL( aCommandURL );
395 m_bInitialized = true;
399 // XPopupMenuController
400 void SAL_CALL PopupMenuControllerBase::setPopupMenu( const Reference< css::awt::XPopupMenu >& xPopupMenu ) throw ( RuntimeException )
402 ResetableGuard aLock( m_aLock );
404 if ( m_bDisposed )
405 throw DisposedException();
407 if ( m_xFrame.is() && !m_xPopupMenu.is() )
409 // Create popup menu on demand
410 vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
412 m_xPopupMenu = xPopupMenu;
413 m_xPopupMenu->addMenuListener( Reference< css::awt::XMenuListener >( (OWeakObject*)this, UNO_QUERY ));
415 Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
417 com::sun::star::util::URL aTargetURL;
418 aTargetURL.Complete = m_aCommandURL;
419 m_xURLTransformer->parseStrict( aTargetURL );
420 m_xDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 );
422 impl_setPopupMenu();
424 updatePopupMenu();
427 void PopupMenuControllerBase::impl_setPopupMenu()