Bump version to 5.0-14
[LibreOffice.git] / svtools / source / uno / statusbarcontroller.cxx
blob88f10265e99e772514557ed533e2b754db7faf1f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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;
46 namespace svt
49 StatusbarController::StatusbarController(
50 const Reference< XComponentContext >& rxContext,
51 const Reference< XFrame >& xFrame,
52 const OUString& aCommandURL,
53 unsigned short nID ) :
54 OWeakObject()
55 , m_bInitialized( false )
56 , m_bDisposed( false )
57 , m_nID( nID )
58 , m_xFrame( xFrame )
59 , m_xContext( rxContext )
60 , m_aCommandURL( aCommandURL )
61 , m_aListenerContainer( m_aMutex )
65 StatusbarController::StatusbarController() :
66 OWeakObject()
67 , m_bInitialized( false )
68 , m_bDisposed( false )
69 , m_nID( 0 )
70 , m_aListenerContainer( m_aMutex )
74 StatusbarController::~StatusbarController()
78 Reference< XFrame > StatusbarController::getFrameInterface() const
80 SolarMutexGuard aSolarMutexGuard;
81 return m_xFrame;
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;
95 // XInterface
96 Any SAL_CALL StatusbarController::queryInterface( const Type& rType )
97 throw ( RuntimeException, std::exception )
99 Any a = ::cppu::queryInterface(
100 rType ,
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 ));
108 if ( a.hasValue() )
109 return a;
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;
132 if ( m_bDisposed )
133 throw DisposedException();
135 bInitialized = m_bInitialized;
138 if ( !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;
156 if( xMSF.is() )
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;
178 if ( m_bDisposed )
179 throw DisposedException();
182 // Bind all registered listeners to their dispatch objects
183 bindListener();
186 // XComponent
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;
194 if ( m_bDisposed )
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 );
217 catch ( Exception& )
221 ++pIter;
224 // clear hash map
225 m_aListenerMap.clear();
227 // release references
228 m_xURLTransformer.clear();
229 m_xContext.clear();
230 m_xFrame.clear();
231 m_xParentWindow.clear();
232 m_xStatusbarItem.clear();
234 m_bDisposed = true;
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 );
249 // XEventListener
250 void SAL_CALL StatusbarController::disposing( const EventObject& Source )
251 throw ( RuntimeException, std::exception )
253 SolarMutexGuard aSolarMutexGuard;
255 if ( m_bDisposed )
256 return;
258 Reference< XFrame > xFrame( Source.Source, UNO_QUERY );
259 if ( xFrame.is() )
261 if ( xFrame == m_xFrame )
262 m_xFrame.clear();
263 return;
266 Reference< XDispatch > xDispatch( Source.Source, UNO_QUERY );
267 if ( !xDispatch.is() )
268 return;
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();
276 ++pIter;
280 // XStatusListener
281 void SAL_CALL StatusbarController::statusChanged( const FeatureStateEvent& Event )
282 throw ( RuntimeException, std::exception )
284 SolarMutexGuard aSolarMutexGuard;
286 if ( m_bDisposed )
287 return;
289 vcl::Window* pWindow = VCLUnoHelper::GetWindow( m_xParentWindow );
290 if ( pWindow && pWindow->GetType() == WINDOW_STATUSBAR && m_nID != 0 )
292 OUString aStrValue;
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)
307 return sal_False;
310 sal_Bool SAL_CALL StatusbarController::mouseMove(
311 const ::com::sun::star::awt::MouseEvent& )
312 throw (::com::sun::star::uno::RuntimeException, std::exception)
314 return sal_False;
317 sal_Bool SAL_CALL StatusbarController::mouseButtonUp(
318 const ::com::sun::star::awt::MouseEvent& )
319 throw (::com::sun::star::uno::RuntimeException, std::exception)
321 return sal_False;
324 void SAL_CALL StatusbarController::command(
325 const ::com::sun::star::awt::Point&,
326 ::sal_Int32,
327 sal_Bool,
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&,
336 ::sal_Int32 )
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;
350 if ( m_bDisposed )
351 return;
353 Sequence< PropertyValue > aArgs;
354 execute( 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() )
369 return;
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 >() ));
377 return;
379 else
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 );
402 catch ( Exception& )
406 else
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 );
418 catch ( Exception& )
423 void StatusbarController::bindListener()
425 std::vector< Listener > aDispatchVector;
426 Reference< XStatusListener > xStatusListener;
429 SolarMutexGuard aSolarMutexGuard;
431 if ( !m_bInitialized )
432 return;
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 );
456 catch ( Exception& )
461 pIter->second.clear();
462 xDispatch.clear();
464 // Query for dispatch object. Old dispatch will be released with this, too.
467 xDispatch = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
469 catch ( Exception& )
472 pIter->second = xDispatch;
474 Listener aListener( aTargetURL, xDispatch );
475 aDispatchVector.push_back( aListener );
476 ++pIter;
481 // Call without locked mutex as we are called back from dispatch implementation
482 if ( !xStatusListener.is() )
483 return;
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 );
504 catch ( ... ){}
508 ::Rectangle StatusbarController::getControlRect() const
510 ::Rectangle aRect;
513 SolarMutexGuard aSolarMutexGuard;
515 if ( m_bDisposed )
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 );
526 return aRect;
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;
538 if ( m_bDisposed )
539 throw DisposedException();
541 if ( m_bInitialized &&
542 m_xFrame.is() &&
543 m_xContext.is() &&
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;
580 if ( m_bDisposed )
581 throw DisposedException();
583 if ( m_bInitialized &&
584 m_xFrame.is() &&
585 m_xContext.is() &&
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;
595 else
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& )
617 } // svt
619 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */