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: framestatuslistener.cxx,v $
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_svtools.hxx"
33 #include <framestatuslistener.hxx>
34 #include <com/sun/star/frame/XDispatchProvider.hpp>
35 #include <com/sun/star/lang/DisposedException.hpp>
36 #include <vos/mutex.hxx>
37 #include <vcl/svapp.hxx>
39 using namespace ::cppu
;
40 using namespace ::com::sun::star::awt
;
41 using namespace ::com::sun::star::uno
;
42 using namespace ::com::sun::star::util
;
43 using namespace ::com::sun::star::beans
;
44 using namespace ::com::sun::star::lang
;
45 using namespace ::com::sun::star::frame
;
50 FrameStatusListener::FrameStatusListener(
51 const Reference
< XMultiServiceFactory
>& rServiceManager
,
52 const Reference
< XFrame
>& xFrame
) :
54 , m_bInitialized( sal_True
)
55 , m_bDisposed( sal_False
)
57 , m_xServiceManager( rServiceManager
)
61 FrameStatusListener::~FrameStatusListener()
65 Reference
< XFrame
> FrameStatusListener::getFrameInterface() const
67 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
71 Reference
< XMultiServiceFactory
> FrameStatusListener::getServiceManager() const
73 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
74 return m_xServiceManager
;
78 Any SAL_CALL
FrameStatusListener::queryInterface( const Type
& rType
)
79 throw ( RuntimeException
)
81 Any a
= ::cppu::queryInterface(
83 static_cast< XComponent
* >( this ),
84 static_cast< XFrameActionListener
* >( this ),
85 static_cast< XStatusListener
* >( this ),
86 static_cast< XEventListener
* >( static_cast< XStatusListener
* >( this )),
87 static_cast< XEventListener
* >( static_cast< XFrameActionListener
* >( this )));
92 return OWeakObject::queryInterface( rType
);
95 void SAL_CALL
FrameStatusListener::acquire() throw ()
97 OWeakObject::acquire();
100 void SAL_CALL
FrameStatusListener::release() throw ()
102 OWeakObject::release();
106 void SAL_CALL
FrameStatusListener::dispose()
107 throw (::com::sun::star::uno::RuntimeException
)
109 Reference
< XComponent
> xThis( static_cast< OWeakObject
* >(this), UNO_QUERY
);
111 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
113 throw DisposedException();
115 Reference
< XStatusListener
> xStatusListener( static_cast< OWeakObject
* >( this ), UNO_QUERY
);
116 URLToDispatchMap::iterator pIter
= m_aListenerMap
.begin();
117 while ( pIter
!= m_aListenerMap
.end() )
121 Reference
< XDispatch
> xDispatch( pIter
->second
);
122 Reference
< XURLTransformer
> xURLTransformer( m_xServiceManager
->createInstance(
123 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
124 "com.sun.star.util.URLTransformer" ))),
126 com::sun::star::util::URL aTargetURL
;
127 aTargetURL
.Complete
= pIter
->first
;
128 xURLTransformer
->parseStrict( aTargetURL
);
130 if ( xDispatch
.is() && xStatusListener
.is() )
131 xDispatch
->removeStatusListener( xStatusListener
, aTargetURL
);
140 m_bDisposed
= sal_True
;
143 void SAL_CALL
FrameStatusListener::addEventListener( const Reference
< XEventListener
>& )
144 throw ( RuntimeException
)
146 // helper class for status updates - no need to support listener
149 void SAL_CALL
FrameStatusListener::removeEventListener( const Reference
< XEventListener
>& )
150 throw ( RuntimeException
)
152 // helper class for status updates - no need to support listener
156 void SAL_CALL
FrameStatusListener::disposing( const EventObject
& Source
)
157 throw ( RuntimeException
)
159 Reference
< XInterface
> xSource( Source
.Source
);
161 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
163 URLToDispatchMap::iterator pIter
= m_aListenerMap
.begin();
164 while ( pIter
!= m_aListenerMap
.end() )
166 // Compare references and release dispatch references if they are equal.
167 Reference
< XInterface
> xIfac( pIter
->second
, UNO_QUERY
);
168 if ( xSource
== xIfac
)
169 pIter
->second
.clear();
172 Reference
< XInterface
> xIfac( m_xFrame
, UNO_QUERY
);
173 if ( xIfac
== xSource
)
178 void SAL_CALL
FrameStatusListener::statusChanged( const FeatureStateEvent
& )
179 throw ( RuntimeException
)
181 // must be implemented by sub class
184 void FrameStatusListener::frameAction( const FrameActionEvent
& Action
)
185 throw ( RuntimeException
)
187 if ( Action
.Action
== FrameAction_CONTEXT_CHANGED
)
191 void FrameStatusListener::addStatusListener( const rtl::OUString
& aCommandURL
)
193 Reference
< XDispatch
> xDispatch
;
194 Reference
< XStatusListener
> xStatusListener
;
195 com::sun::star::util::URL aTargetURL
;
198 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
199 URLToDispatchMap::iterator pIter
= m_aListenerMap
.find( aCommandURL
);
201 // Already in the list of status listener. Do nothing.
202 if ( pIter
!= m_aListenerMap
.end() )
205 // Check if we are already initialized. Implementation starts adding itself as status listener when
206 // intialize is called.
207 if ( !m_bInitialized
)
209 // Put into the hash_map of status listener. Will be activated when initialized is called
210 m_aListenerMap
.insert( URLToDispatchMap::value_type( aCommandURL
, Reference
< XDispatch
>() ));
215 // Add status listener directly as intialize has already been called.
216 Reference
< XDispatchProvider
> xDispatchProvider( m_xFrame
, UNO_QUERY
);
217 if ( m_xServiceManager
.is() && xDispatchProvider
.is() )
219 Reference
< XURLTransformer
> xURLTransformer( m_xServiceManager
->createInstance(
220 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.URLTransformer" ))),
222 aTargetURL
.Complete
= aCommandURL
;
223 xURLTransformer
->parseStrict( aTargetURL
);
224 xDispatch
= xDispatchProvider
->queryDispatch( aTargetURL
, ::rtl::OUString(), 0 );
226 xStatusListener
= Reference
< XStatusListener
>( static_cast< OWeakObject
* >( this ), UNO_QUERY
);
227 URLToDispatchMap::iterator aIter
= m_aListenerMap
.find( aCommandURL
);
228 if ( aIter
!= m_aListenerMap
.end() )
230 Reference
< XDispatch
> xOldDispatch( aIter
->second
);
231 aIter
->second
= xDispatch
;
235 if ( xOldDispatch
.is() )
236 xOldDispatch
->removeStatusListener( xStatusListener
, aTargetURL
);
243 m_aListenerMap
.insert( URLToDispatchMap::value_type( aCommandURL
, xDispatch
));
248 // Call without locked mutex as we are called back from dispatch implementation
251 if ( xDispatch
.is() )
252 xDispatch
->addStatusListener( xStatusListener
, aTargetURL
);
259 void FrameStatusListener::removeStatusListener( const rtl::OUString
& aCommandURL
)
261 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
263 URLToDispatchMap::iterator pIter
= m_aListenerMap
.find( aCommandURL
);
264 if ( pIter
!= m_aListenerMap
.end() )
266 Reference
< XDispatch
> xDispatch( pIter
->second
);
267 Reference
< XStatusListener
> xStatusListener( static_cast< OWeakObject
* >( this ), UNO_QUERY
);
268 m_aListenerMap
.erase( pIter
);
272 Reference
< XURLTransformer
> xURLTransformer( m_xServiceManager
->createInstance(
273 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.URLTransformer" ))),
275 com::sun::star::util::URL aTargetURL
;
276 aTargetURL
.Complete
= aCommandURL
;
277 xURLTransformer
->parseStrict( aTargetURL
);
279 if ( xDispatch
.is() && xStatusListener
.is() )
280 xDispatch
->removeStatusListener( xStatusListener
, aTargetURL
);
288 void FrameStatusListener::bindListener()
290 std::vector
< Listener
> aDispatchVector
;
291 Reference
< XStatusListener
> xStatusListener
;
294 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
296 if ( !m_bInitialized
)
299 // Collect all registered command URL's and store them temporary
300 Reference
< XDispatchProvider
> xDispatchProvider( m_xFrame
, UNO_QUERY
);
301 if ( m_xServiceManager
.is() && xDispatchProvider
.is() )
303 xStatusListener
= Reference
< XStatusListener
>( static_cast< OWeakObject
* >( this ), UNO_QUERY
);
304 URLToDispatchMap::iterator pIter
= m_aListenerMap
.begin();
305 while ( pIter
!= m_aListenerMap
.end() )
307 Reference
< XURLTransformer
> xURLTransformer( m_xServiceManager
->createInstance(
308 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.URLTransformer" ))),
310 com::sun::star::util::URL aTargetURL
;
311 aTargetURL
.Complete
= pIter
->first
;
312 xURLTransformer
->parseStrict( aTargetURL
);
314 Reference
< XDispatch
> xDispatch( pIter
->second
);
315 if ( xDispatch
.is() )
317 // We already have a dispatch object => we have to requery.
318 // Release old dispatch object and remove it as listener
321 xDispatch
->removeStatusListener( xStatusListener
, aTargetURL
);
328 // Query for dispatch object. Old dispatch will be released with this, too.
331 xDispatch
= xDispatchProvider
->queryDispatch( aTargetURL
, ::rtl::OUString(), 0 );
336 pIter
->second
= xDispatch
;
338 Listener
aListener( aTargetURL
, xDispatch
);
339 aDispatchVector
.push_back( aListener
);
345 // Call without locked mutex as we are called back from dispatch implementation
346 if ( xStatusListener
.is() )
350 for ( sal_uInt32 i
= 0; i
< aDispatchVector
.size(); i
++ )
352 Listener
& rListener
= aDispatchVector
[i
];
353 if ( rListener
.xDispatch
.is() )
354 rListener
.xDispatch
->addStatusListener( xStatusListener
, rListener
.aURL
);
363 void FrameStatusListener::unbindListener()
365 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
367 if ( !m_bInitialized
)
370 // Collect all registered command URL's and store them temporary
371 Reference
< XDispatchProvider
> xDispatchProvider( m_xFrame
, UNO_QUERY
);
372 if ( m_xServiceManager
.is() && xDispatchProvider
.is() )
374 Reference
< XStatusListener
> xStatusListener( static_cast< OWeakObject
* >( this ), UNO_QUERY
);
375 URLToDispatchMap::iterator pIter
= m_aListenerMap
.begin();
376 while ( pIter
!= m_aListenerMap
.end() )
378 Reference
< XURLTransformer
> xURLTransformer( m_xServiceManager
->createInstance(
379 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.URLTransformer" ))),
381 com::sun::star::util::URL aTargetURL
;
382 aTargetURL
.Complete
= pIter
->first
;
383 xURLTransformer
->parseStrict( aTargetURL
);
385 Reference
< XDispatch
> xDispatch( pIter
->second
);
386 if ( xDispatch
.is() )
388 // We already have a dispatch object => we have to requery.
389 // Release old dispatch object and remove it as listener
392 xDispatch
->removeStatusListener( xStatusListener
, aTargetURL
);
398 pIter
->second
.clear();
404 void FrameStatusListener::updateStatus( const rtl::OUString aCommandURL
)
406 Reference
< XDispatch
> xDispatch
;
407 Reference
< XStatusListener
> xStatusListener
;
408 com::sun::star::util::URL aTargetURL
;
411 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
413 if ( !m_bInitialized
)
416 // Try to find a dispatch object for the requested command URL
417 Reference
< XDispatchProvider
> xDispatchProvider( m_xFrame
, UNO_QUERY
);
418 xStatusListener
= Reference
< XStatusListener
>( static_cast< OWeakObject
* >( this ), UNO_QUERY
);
419 if ( m_xServiceManager
.is() && xDispatchProvider
.is() )
421 Reference
< XURLTransformer
> xURLTransformer( m_xServiceManager
->createInstance(
422 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.URLTransformer" ))),
424 aTargetURL
.Complete
= aCommandURL
;
425 xURLTransformer
->parseStrict( aTargetURL
);
426 xDispatch
= xDispatchProvider
->queryDispatch( aTargetURL
, rtl::OUString(), 0 );
430 if ( xDispatch
.is() && xStatusListener
.is() )
432 // Catch exception as we release our mutex, it is possible that someone else
433 // has already disposed this instance!
434 // Add/remove status listener to get a update status information from the
435 // requested command.
438 xDispatch
->addStatusListener( xStatusListener
, aTargetURL
);
439 xDispatch
->removeStatusListener( xStatusListener
, aTargetURL
);