1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <svtools/statusbarcontroller.hxx>
21 #include <com/sun/star/beans/PropertyValue.hpp>
22 #include <com/sun/star/beans/XPropertySet.hpp>
23 #include <com/sun/star/frame/XDispatchProvider.hpp>
24 #include <com/sun/star/lang/DisposedException.hpp>
25 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
26 #include <com/sun/star/frame/XLayoutManager.hpp>
27 #include <com/sun/star/util/URLTransformer.hpp>
28 #include <cppuhelper/queryinterface.hxx>
29 #include <osl/mutex.hxx>
30 #include <vcl/svapp.hxx>
31 #include <vcl/window.hxx>
32 #include <vcl/status.hxx>
33 #include <svtools/imgdef.hxx>
34 #include <svtools/miscopt.hxx>
35 #include <toolkit/helper/vclunohelper.hxx>
36 #include <comphelper/processfactory.hxx>
38 using namespace ::cppu
;
39 using namespace ::com::sun::star::awt
;
40 using namespace ::com::sun::star::uno
;
41 using namespace ::com::sun::star::util
;
42 using namespace ::com::sun::star::beans
;
43 using namespace ::com::sun::star::lang
;
44 using namespace ::com::sun::star::frame
;
49 StatusbarController::StatusbarController(
50 const Reference
< XComponentContext
>& rxContext
,
51 const Reference
< XFrame
>& xFrame
,
52 const OUString
& aCommandURL
,
53 unsigned short nID
) :
55 , m_bInitialized( false )
56 , m_bDisposed( false )
59 , m_xContext( rxContext
)
60 , m_aCommandURL( aCommandURL
)
61 , m_aListenerContainer( m_aMutex
)
65 StatusbarController::StatusbarController() :
67 , m_bInitialized( false )
68 , m_bDisposed( false )
70 , m_aListenerContainer( m_aMutex
)
74 StatusbarController::~StatusbarController()
78 Reference
< XFrame
> StatusbarController::getFrameInterface() const
80 SolarMutexGuard aSolarMutexGuard
;
84 Reference
< XURLTransformer
> StatusbarController::getURLTransformer() const
86 SolarMutexGuard aSolarMutexGuard
;
87 if ( !m_xURLTransformer
.is() && m_xContext
.is() )
89 m_xURLTransformer
= com::sun::star::util::URLTransformer::create( m_xContext
);
92 return m_xURLTransformer
;
96 Any SAL_CALL
StatusbarController::queryInterface( const Type
& rType
)
97 throw ( RuntimeException
, std::exception
)
99 Any a
= ::cppu::queryInterface(
101 static_cast< XStatusbarController
* >( this ),
102 static_cast< XStatusListener
* >( this ),
103 static_cast< XEventListener
* >( this ),
104 static_cast< XInitialization
* >( this ),
105 static_cast< XComponent
* >( this ),
106 static_cast< XUpdatable
* >( this ));
111 return OWeakObject::queryInterface( rType
);
114 void SAL_CALL
StatusbarController::acquire() throw ()
116 OWeakObject::acquire();
119 void SAL_CALL
StatusbarController::release() throw ()
121 OWeakObject::release();
124 void SAL_CALL
StatusbarController::initialize( const Sequence
< Any
>& aArguments
)
125 throw ( Exception
, RuntimeException
, std::exception
)
127 bool bInitialized( true );
130 SolarMutexGuard aSolarMutexGuard
;
133 throw DisposedException();
135 bInitialized
= m_bInitialized
;
140 SolarMutexGuard aSolarMutexGuard
;
141 m_bInitialized
= true;
143 PropertyValue aPropValue
;
144 for ( int i
= 0; i
< aArguments
.getLength(); i
++ )
146 if ( aArguments
[i
] >>= aPropValue
)
148 if ( aPropValue
.Name
== "Frame" )
149 aPropValue
.Value
>>= m_xFrame
;
150 else if ( aPropValue
.Name
== "CommandURL" )
151 aPropValue
.Value
>>= m_aCommandURL
;
152 else if ( aPropValue
.Name
== "ServiceManager" )
154 Reference
<XMultiServiceFactory
> xMSF
;
155 aPropValue
.Value
>>= xMSF
;
157 m_xContext
= comphelper::getComponentContext(xMSF
);
159 else if ( aPropValue
.Name
== "ParentWindow" )
160 aPropValue
.Value
>>= m_xParentWindow
;
161 else if ( aPropValue
.Name
== "Identifier" )
162 aPropValue
.Value
>>= m_nID
;
163 else if ( aPropValue
.Name
== "StatusbarItem" )
164 aPropValue
.Value
>>= m_xStatusbarItem
;
168 if ( !m_aCommandURL
.isEmpty() )
169 m_aListenerMap
.insert( URLToDispatchMap::value_type( m_aCommandURL
, Reference
< XDispatch
>() ));
173 void SAL_CALL
StatusbarController::update()
174 throw ( RuntimeException
, std::exception
)
177 SolarMutexGuard aSolarMutexGuard
;
179 throw DisposedException();
182 // Bind all registered listeners to their dispatch objects
187 void SAL_CALL
StatusbarController::dispose()
188 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
190 Reference
< XComponent
> xThis( static_cast< OWeakObject
* >(this), UNO_QUERY
);
193 SolarMutexGuard aSolarMutexGuard
;
195 throw DisposedException();
198 com::sun::star::lang::EventObject
aEvent( xThis
);
199 m_aListenerContainer
.disposeAndClear( aEvent
);
201 SolarMutexGuard aSolarMutexGuard
;
202 Reference
< XStatusListener
> xStatusListener( static_cast< OWeakObject
* >( this ), UNO_QUERY
);
203 Reference
< XURLTransformer
> xURLTransformer
= getURLTransformer();
204 URLToDispatchMap::iterator pIter
= m_aListenerMap
.begin();
205 com::sun::star::util::URL aTargetURL
;
206 while ( pIter
!= m_aListenerMap
.end() )
210 Reference
< XDispatch
> xDispatch( pIter
->second
);
211 aTargetURL
.Complete
= pIter
->first
;
212 xURLTransformer
->parseStrict( aTargetURL
);
214 if ( xDispatch
.is() && xStatusListener
.is() )
215 xDispatch
->removeStatusListener( xStatusListener
, aTargetURL
);
225 m_aListenerMap
.clear();
227 // release references
228 m_xURLTransformer
.clear();
231 m_xParentWindow
.clear();
232 m_xStatusbarItem
.clear();
237 void SAL_CALL
StatusbarController::addEventListener( const Reference
< XEventListener
>& xListener
)
238 throw ( RuntimeException
, std::exception
)
240 m_aListenerContainer
.addInterface( cppu::UnoType
<XEventListener
>::get(), xListener
);
243 void SAL_CALL
StatusbarController::removeEventListener( const Reference
< XEventListener
>& aListener
)
244 throw ( RuntimeException
, std::exception
)
246 m_aListenerContainer
.removeInterface( cppu::UnoType
<XEventListener
>::get(), aListener
);
250 void SAL_CALL
StatusbarController::disposing( const EventObject
& Source
)
251 throw ( RuntimeException
, std::exception
)
253 SolarMutexGuard aSolarMutexGuard
;
258 Reference
< XFrame
> xFrame( Source
.Source
, UNO_QUERY
);
261 if ( xFrame
== m_xFrame
)
266 Reference
< XDispatch
> xDispatch( Source
.Source
, UNO_QUERY
);
267 if ( !xDispatch
.is() )
270 URLToDispatchMap::iterator pIter
= m_aListenerMap
.begin();
271 while ( pIter
!= m_aListenerMap
.end() )
273 // Compare references and release dispatch references if they are equal.
274 if ( xDispatch
== pIter
->second
)
275 pIter
->second
.clear();
281 void SAL_CALL
StatusbarController::statusChanged( const FeatureStateEvent
& Event
)
282 throw ( RuntimeException
, std::exception
)
284 SolarMutexGuard aSolarMutexGuard
;
289 vcl::Window
* pWindow
= VCLUnoHelper::GetWindow( m_xParentWindow
);
290 if ( pWindow
&& pWindow
->GetType() == WINDOW_STATUSBAR
&& m_nID
!= 0 )
293 StatusBar
* pStatusBar
= static_cast<StatusBar
*>(pWindow
);
295 if ( Event
.State
>>= aStrValue
)
296 pStatusBar
->SetItemText( m_nID
, aStrValue
);
297 else if ( !Event
.State
.hasValue() )
298 pStatusBar
->SetItemText( m_nID
, "" );
302 // XStatusbarController
303 sal_Bool SAL_CALL
StatusbarController::mouseButtonDown(
304 const ::com::sun::star::awt::MouseEvent
& )
305 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
310 sal_Bool SAL_CALL
StatusbarController::mouseMove(
311 const ::com::sun::star::awt::MouseEvent
& )
312 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
317 sal_Bool SAL_CALL
StatusbarController::mouseButtonUp(
318 const ::com::sun::star::awt::MouseEvent
& )
319 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
324 void SAL_CALL
StatusbarController::command(
325 const ::com::sun::star::awt::Point
&,
328 const ::com::sun::star::uno::Any
& )
329 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
333 void SAL_CALL
StatusbarController::paint(
334 const ::com::sun::star::uno::Reference
< ::com::sun::star::awt::XGraphics
>&,
335 const ::com::sun::star::awt::Rectangle
&,
337 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
341 void SAL_CALL
StatusbarController::click( const ::com::sun::star::awt::Point
& )
342 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
346 void SAL_CALL
StatusbarController::doubleClick( const ::com::sun::star::awt::Point
& ) throw (::com::sun::star::uno::RuntimeException
, std::exception
)
348 SolarMutexGuard aSolarMutexGuard
;
353 Sequence
< PropertyValue
> aArgs
;
357 void StatusbarController::addStatusListener( const OUString
& aCommandURL
)
359 Reference
< XDispatch
> xDispatch
;
360 Reference
< XStatusListener
> xStatusListener
;
361 com::sun::star::util::URL aTargetURL
;
364 SolarMutexGuard aSolarMutexGuard
;
365 URLToDispatchMap::iterator pIter
= m_aListenerMap
.find( aCommandURL
);
367 // Already in the list of status listener. Do nothing.
368 if ( pIter
!= m_aListenerMap
.end() )
371 // Check if we are already initialized. Implementation starts adding itself as status listener when
372 // intialize is called.
373 if ( !m_bInitialized
)
375 // Put into the unordered_map of status listener. Will be activated when initialized is called
376 m_aListenerMap
.insert( URLToDispatchMap::value_type( aCommandURL
, Reference
< XDispatch
>() ));
381 // Add status listener directly as intialize has already been called.
382 Reference
< XDispatchProvider
> xDispatchProvider( m_xFrame
, UNO_QUERY
);
383 if ( m_xContext
.is() && xDispatchProvider
.is() )
385 Reference
< XURLTransformer
> xURLTransformer
= getURLTransformer();
386 aTargetURL
.Complete
= aCommandURL
;
387 xURLTransformer
->parseStrict( aTargetURL
);
388 xDispatch
= xDispatchProvider
->queryDispatch( aTargetURL
, OUString(), 0 );
390 xStatusListener
= Reference
< XStatusListener
>( static_cast< OWeakObject
* >( this ), UNO_QUERY
);
391 URLToDispatchMap::iterator aIter
= m_aListenerMap
.find( aCommandURL
);
392 if ( aIter
!= m_aListenerMap
.end() )
394 Reference
< XDispatch
> xOldDispatch( aIter
->second
);
395 aIter
->second
= xDispatch
;
399 if ( xOldDispatch
.is() )
400 xOldDispatch
->removeStatusListener( xStatusListener
, aTargetURL
);
407 m_aListenerMap
.insert( URLToDispatchMap::value_type( aCommandURL
, xDispatch
));
412 // Call without locked mutex as we are called back from dispatch implementation
415 if ( xDispatch
.is() )
416 xDispatch
->addStatusListener( xStatusListener
, aTargetURL
);
423 void StatusbarController::bindListener()
425 std::vector
< Listener
> aDispatchVector
;
426 Reference
< XStatusListener
> xStatusListener
;
429 SolarMutexGuard aSolarMutexGuard
;
431 if ( !m_bInitialized
)
434 // Collect all registered command URL's and store them temporary
435 Reference
< XDispatchProvider
> xDispatchProvider( m_xFrame
, UNO_QUERY
);
436 if ( m_xContext
.is() && xDispatchProvider
.is() )
438 xStatusListener
= Reference
< XStatusListener
>( static_cast< OWeakObject
* >( this ), UNO_QUERY
);
439 URLToDispatchMap::iterator pIter
= m_aListenerMap
.begin();
440 while ( pIter
!= m_aListenerMap
.end() )
442 Reference
< XURLTransformer
> xURLTransformer
= getURLTransformer();
443 com::sun::star::util::URL aTargetURL
;
444 aTargetURL
.Complete
= pIter
->first
;
445 xURLTransformer
->parseStrict( aTargetURL
);
447 Reference
< XDispatch
> xDispatch( pIter
->second
);
448 if ( xDispatch
.is() )
450 // We already have a dispatch object => we have to requery.
451 // Release old dispatch object and remove it as listener
454 xDispatch
->removeStatusListener( xStatusListener
, aTargetURL
);
461 pIter
->second
.clear();
464 // Query for dispatch object. Old dispatch will be released with this, too.
467 xDispatch
= xDispatchProvider
->queryDispatch( aTargetURL
, OUString(), 0 );
472 pIter
->second
= xDispatch
;
474 Listener
aListener( aTargetURL
, xDispatch
);
475 aDispatchVector
.push_back( aListener
);
481 // Call without locked mutex as we are called back from dispatch implementation
482 if ( !xStatusListener
.is() )
485 for ( sal_uInt32 i
= 0; i
< aDispatchVector
.size(); i
++ )
489 Listener
& rListener
= aDispatchVector
[i
];
490 if ( rListener
.xDispatch
.is() )
491 rListener
.xDispatch
->addStatusListener( xStatusListener
, rListener
.aURL
);
492 else if ( rListener
.aURL
.Complete
== m_aCommandURL
)
494 // Send status changed for the main URL, if we cannot get a valid dispatch object.
495 // UI disables the button. Catch exception as we release our mutex, it is possible
496 // that someone else already disposed this instance!
497 FeatureStateEvent aFeatureStateEvent
;
498 aFeatureStateEvent
.IsEnabled
= sal_False
;
499 aFeatureStateEvent
.FeatureURL
= rListener
.aURL
;
500 aFeatureStateEvent
.State
= Any();
501 xStatusListener
->statusChanged( aFeatureStateEvent
);
508 ::Rectangle
StatusbarController::getControlRect() const
513 SolarMutexGuard aSolarMutexGuard
;
516 throw DisposedException();
518 if ( m_xParentWindow
.is() )
520 VclPtr
< StatusBar
> pStatusBar
= dynamic_cast< StatusBar
* >( VCLUnoHelper::GetWindow( m_xParentWindow
).get() );
521 if ( pStatusBar
&& pStatusBar
->GetType() == WINDOW_STATUSBAR
)
522 aRect
= pStatusBar
->GetItemRect( m_nID
);
529 void StatusbarController::execute( const ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::PropertyValue
>& aArgs
)
531 Reference
< XDispatch
> xDispatch
;
532 Reference
< XURLTransformer
> xURLTransformer
;
533 OUString aCommandURL
;
536 SolarMutexGuard aSolarMutexGuard
;
539 throw DisposedException();
541 if ( m_bInitialized
&&
544 !m_aCommandURL
.isEmpty() )
546 xURLTransformer
= getURLTransformer();
547 aCommandURL
= m_aCommandURL
;
548 URLToDispatchMap::iterator pIter
= m_aListenerMap
.find( m_aCommandURL
);
549 if ( pIter
!= m_aListenerMap
.end() )
550 xDispatch
= pIter
->second
;
554 if ( xDispatch
.is() && xURLTransformer
.is() )
558 com::sun::star::util::URL aTargetURL
;
560 aTargetURL
.Complete
= aCommandURL
;
561 xURLTransformer
->parseStrict( aTargetURL
);
562 xDispatch
->dispatch( aTargetURL
, aArgs
);
564 catch ( DisposedException
& )
570 void StatusbarController::execute(
571 const OUString
& aCommandURL
,
572 const Sequence
< ::com::sun::star::beans::PropertyValue
>& aArgs
)
574 Reference
< XDispatch
> xDispatch
;
575 com::sun::star::util::URL aTargetURL
;
578 SolarMutexGuard aSolarMutexGuard
;
581 throw DisposedException();
583 if ( m_bInitialized
&&
586 !m_aCommandURL
.isEmpty() )
588 Reference
< XURLTransformer
> xURLTransformer( getURLTransformer() );
589 aTargetURL
.Complete
= aCommandURL
;
590 xURLTransformer
->parseStrict( aTargetURL
);
592 URLToDispatchMap::iterator pIter
= m_aListenerMap
.find( aCommandURL
);
593 if ( pIter
!= m_aListenerMap
.end() )
594 xDispatch
= pIter
->second
;
597 Reference
< ::com::sun::star::frame::XDispatchProvider
> xDispatchProvider(
598 m_xFrame
->getController(), UNO_QUERY
);
599 if ( xDispatchProvider
.is() )
600 xDispatch
= xDispatchProvider
->queryDispatch( aTargetURL
, OUString(), 0 );
605 if ( xDispatch
.is() )
609 xDispatch
->dispatch( aTargetURL
, aArgs
);
611 catch ( DisposedException
& )
619 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */