1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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 //_________________________________________________________________________________________________________________
37 //_________________________________________________________________________________________________________________
38 #include <threadhelp/resetableguard.hxx>
41 //_________________________________________________________________________________________________________________
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>
57 #include <vcl/svapp.hxx>
58 #include <rtl/ustrbuf.hxx>
59 #include <rtl/logfile.hxx>
60 //_________________________________________________________________________________________________________________
62 //_________________________________________________________________________________________________________________
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
;
74 //*****************************************************************************************************************
75 // XInterface, XTypeProvider, XServiceInfo
76 //*****************************************************************************************************************
77 DEFINE_XINTERFACE_11 ( PopupMenuControllerBase
,
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
) :
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
),
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
);
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
);
153 m_xPopupMenu
.clear();
154 m_xServiceManager
.clear();
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
);
173 void SAL_CALL
PopupMenuControllerBase::disposing( const EventObject
& ) throw ( RuntimeException
)
175 ResetableGuard
aLock( m_aLock
);
178 m_xPopupMenu
.clear();
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
;
199 throw DisposedException();
201 ResetableGuard
aLock( m_aLock
);
202 xPopupMenu
= m_xPopupMenu
;
203 xDispatch
= m_xDispatch
;
204 xServiceManager
= m_xServiceManager
;
207 if ( xPopupMenu
.is() && xDispatch
.is() )
209 VCLXPopupMenu
* pPopupMenu
= (VCLXPopupMenu
*)VCLXPopupMenu::GetImplementation( xPopupMenu
);
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
);
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
);
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
);
256 Reference
< XDispatch
> SAL_CALL
257 PopupMenuControllerBase::queryDispatch(
259 const rtl::OUString
& /*sTarget*/,
260 sal_Int32
/*nFlags*/ )
261 throw( RuntimeException
)
263 // must be implemented by subclass
264 ResetableGuard
aLock( m_aLock
);
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
);
277 throw DisposedException();
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
);
296 PopupMenuControllerBase::dispatch(
298 const Sequence
< PropertyValue
>& /*seqProperties*/ )
299 throw( ::com::sun::star::uno::RuntimeException
)
301 // must be implemented by subclass
302 ResetableGuard
aLock( m_aLock
);
304 throw DisposedException();
308 PopupMenuControllerBase::addStatusListener(
309 const Reference
< XStatusListener
>& xControl
,
311 throw( ::com::sun::star::uno::RuntimeException
)
313 ResetableGuard
aLock( m_aLock
);
315 throw DisposedException();
318 bool bStatusUpdate( false );
319 m_aListenerContainer
.addInterface( ::getCppuType( (const css::uno::Reference
< css::frame::XStatusListener
>*)NULL
), xControl
);
322 if ( aURL
.Complete
.indexOf( m_aBaseURL
) == 0 )
323 bStatusUpdate
= true;
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 );
368 void SAL_CALL
PopupMenuControllerBase::initialize( const Sequence
< Any
>& aArguments
) throw ( Exception
, RuntimeException
)
370 ResetableGuard
aLock( m_aLock
);
372 sal_Bool
bInitalized( m_bInitialized
);
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() )
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
);
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 );
427 void PopupMenuControllerBase::impl_setPopupMenu()