Updated core
[LibreOffice.git] / svtools / source / uno / statusbarcontroller.cxx
blobd93feed5ff78f152eaeafe92d3d08fc222503e7e
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/frame/XLayoutManager.hpp>
26 #include <com/sun/star/util/URLTransformer.hpp>
27 #include <osl/mutex.hxx>
28 #include <vcl/svapp.hxx>
29 #include <vcl/window.hxx>
30 #include <vcl/status.hxx>
31 #include <svtools/imgdef.hxx>
32 #include <svtools/miscopt.hxx>
33 #include <toolkit/helper/vclunohelper.hxx>
34 #include <comphelper/processfactory.hxx>
36 using namespace ::cppu;
37 using namespace ::com::sun::star::awt;
38 using namespace ::com::sun::star::uno;
39 using namespace ::com::sun::star::util;
40 using namespace ::com::sun::star::beans;
41 using namespace ::com::sun::star::lang;
42 using namespace ::com::sun::star::frame;
44 namespace svt
47 StatusbarController::StatusbarController(
48 const Reference< XMultiServiceFactory >& rServiceManager,
49 const Reference< XFrame >& xFrame,
50 const OUString& aCommandURL,
51 unsigned short nID ) :
52 OWeakObject()
53 , m_bInitialized( sal_False )
54 , m_bDisposed( sal_False )
55 , m_nID( nID )
56 , m_xFrame( xFrame )
57 , m_xServiceManager( rServiceManager )
58 , m_aCommandURL( aCommandURL )
59 , m_aListenerContainer( m_aMutex )
63 StatusbarController::StatusbarController() :
64 OWeakObject()
65 , m_bInitialized( sal_False )
66 , m_bDisposed( sal_False )
67 , m_nID( 0 )
68 , m_aListenerContainer( m_aMutex )
72 StatusbarController::~StatusbarController()
76 Reference< XFrame > StatusbarController::getFrameInterface() const
78 SolarMutexGuard aSolarMutexGuard;
79 return m_xFrame;
82 Reference< XURLTransformer > StatusbarController::getURLTransformer() const
84 SolarMutexGuard aSolarMutexGuard;
85 if ( !m_xURLTransformer.is() && m_xServiceManager.is() )
87 m_xURLTransformer = com::sun::star::util::URLTransformer::create( ::comphelper::getComponentContext(m_xServiceManager) );
90 return m_xURLTransformer;
93 // XInterface
94 Any SAL_CALL StatusbarController::queryInterface( const Type& rType )
95 throw ( RuntimeException )
97 Any a = ::cppu::queryInterface(
98 rType ,
99 static_cast< XStatusbarController* >( this ),
100 static_cast< XStatusListener* >( this ),
101 static_cast< XEventListener* >( this ),
102 static_cast< XInitialization* >( this ),
103 static_cast< XComponent* >( this ),
104 static_cast< XUpdatable* >( this ));
106 if ( a.hasValue() )
107 return a;
109 return OWeakObject::queryInterface( rType );
112 void SAL_CALL StatusbarController::acquire() throw ()
114 OWeakObject::acquire();
117 void SAL_CALL StatusbarController::release() throw ()
119 OWeakObject::release();
122 void SAL_CALL StatusbarController::initialize( const Sequence< Any >& aArguments )
123 throw ( Exception, RuntimeException )
125 bool bInitialized( true );
128 SolarMutexGuard aSolarMutexGuard;
130 if ( m_bDisposed )
131 throw DisposedException();
133 bInitialized = m_bInitialized;
136 if ( !bInitialized )
138 SolarMutexGuard aSolarMutexGuard;
139 m_bInitialized = sal_True;
141 PropertyValue aPropValue;
142 for ( int i = 0; i < aArguments.getLength(); i++ )
144 if ( aArguments[i] >>= aPropValue )
146 if ( aPropValue.Name == "Frame" )
147 aPropValue.Value >>= m_xFrame;
148 else if ( aPropValue.Name == "CommandURL" )
149 aPropValue.Value >>= m_aCommandURL;
150 else if ( aPropValue.Name == "ServiceManager" )
151 aPropValue.Value >>= m_xServiceManager;
152 else if ( aPropValue.Name == "ParentWindow" )
153 aPropValue.Value >>= m_xParentWindow;
154 else if ( aPropValue.Name == "Identifier" )
155 aPropValue.Value >>= m_nID;
156 else if ( aPropValue.Name == "StatusbarItem" )
157 aPropValue.Value >>= m_xStatusbarItem;
161 if ( !m_aCommandURL.isEmpty() )
162 m_aListenerMap.insert( URLToDispatchMap::value_type( m_aCommandURL, Reference< XDispatch >() ));
166 void SAL_CALL StatusbarController::update()
167 throw ( RuntimeException )
170 SolarMutexGuard aSolarMutexGuard;
171 if ( m_bDisposed )
172 throw DisposedException();
175 // Bind all registered listeners to their dispatch objects
176 bindListener();
179 // XComponent
180 void SAL_CALL StatusbarController::dispose()
181 throw (::com::sun::star::uno::RuntimeException)
183 Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY );
186 SolarMutexGuard aSolarMutexGuard;
187 if ( m_bDisposed )
188 throw DisposedException();
191 com::sun::star::lang::EventObject aEvent( xThis );
192 m_aListenerContainer.disposeAndClear( aEvent );
194 SolarMutexGuard aSolarMutexGuard;
195 Reference< XStatusListener > xStatusListener( static_cast< OWeakObject* >( this ), UNO_QUERY );
196 Reference< XURLTransformer > xURLTransformer = getURLTransformer();
197 URLToDispatchMap::iterator pIter = m_aListenerMap.begin();
198 com::sun::star::util::URL aTargetURL;
199 while ( pIter != m_aListenerMap.end() )
203 Reference< XDispatch > xDispatch( pIter->second );
204 aTargetURL.Complete = pIter->first;
205 xURLTransformer->parseStrict( aTargetURL );
207 if ( xDispatch.is() && xStatusListener.is() )
208 xDispatch->removeStatusListener( xStatusListener, aTargetURL );
210 catch ( Exception& )
214 ++pIter;
217 // clear hash map
218 m_aListenerMap.clear();
220 // release references
221 m_xURLTransformer.clear();
222 m_xServiceManager.clear();
223 m_xFrame.clear();
224 m_xParentWindow.clear();
225 m_xStatusbarItem.clear();
227 m_bDisposed = sal_True;
230 void SAL_CALL StatusbarController::addEventListener( const Reference< XEventListener >& xListener )
231 throw ( RuntimeException )
233 m_aListenerContainer.addInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), xListener );
236 void SAL_CALL StatusbarController::removeEventListener( const Reference< XEventListener >& aListener )
237 throw ( RuntimeException )
239 m_aListenerContainer.removeInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), aListener );
242 // XEventListener
243 void SAL_CALL StatusbarController::disposing( const EventObject& Source )
244 throw ( RuntimeException )
246 SolarMutexGuard aSolarMutexGuard;
248 if ( m_bDisposed )
249 return;
251 Reference< XFrame > xFrame( Source.Source, UNO_QUERY );
252 if ( xFrame.is() )
254 if ( xFrame == m_xFrame )
255 m_xFrame.clear();
256 return;
259 Reference< XDispatch > xDispatch( Source.Source, UNO_QUERY );
260 if ( !xDispatch.is() )
261 return;
263 URLToDispatchMap::iterator pIter = m_aListenerMap.begin();
264 while ( pIter != m_aListenerMap.end() )
266 // Compare references and release dispatch references if they are equal.
267 if ( xDispatch == pIter->second )
268 pIter->second.clear();
269 ++pIter;
273 // XStatusListener
274 void SAL_CALL StatusbarController::statusChanged( const FeatureStateEvent& Event )
275 throw ( RuntimeException )
277 SolarMutexGuard aSolarMutexGuard;
279 if ( m_bDisposed )
280 return;
282 Window* pWindow = VCLUnoHelper::GetWindow( m_xParentWindow );
283 if ( pWindow && pWindow->GetType() == WINDOW_STATUSBAR && m_nID != 0 )
285 OUString aStrValue;
286 StatusBar* pStatusBar = (StatusBar *)pWindow;
288 if ( Event.State >>= aStrValue )
289 pStatusBar->SetItemText( m_nID, aStrValue );
290 else if ( !Event.State.hasValue() )
291 pStatusBar->SetItemText( m_nID, String() );
295 // XStatusbarController
296 ::sal_Bool SAL_CALL StatusbarController::mouseButtonDown(
297 const ::com::sun::star::awt::MouseEvent& )
298 throw (::com::sun::star::uno::RuntimeException)
300 return sal_False;
303 ::sal_Bool SAL_CALL StatusbarController::mouseMove(
304 const ::com::sun::star::awt::MouseEvent& )
305 throw (::com::sun::star::uno::RuntimeException)
307 return sal_False;
310 ::sal_Bool SAL_CALL StatusbarController::mouseButtonUp(
311 const ::com::sun::star::awt::MouseEvent& )
312 throw (::com::sun::star::uno::RuntimeException)
314 return sal_False;
317 void SAL_CALL StatusbarController::command(
318 const ::com::sun::star::awt::Point&,
319 ::sal_Int32,
320 ::sal_Bool,
321 const ::com::sun::star::uno::Any& )
322 throw (::com::sun::star::uno::RuntimeException)
326 void SAL_CALL StatusbarController::paint(
327 const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics >&,
328 const ::com::sun::star::awt::Rectangle&,
329 ::sal_Int32 )
330 throw (::com::sun::star::uno::RuntimeException)
334 void SAL_CALL StatusbarController::click( const ::com::sun::star::awt::Point& )
335 throw (::com::sun::star::uno::RuntimeException)
339 void SAL_CALL StatusbarController::doubleClick( const ::com::sun::star::awt::Point& ) throw (::com::sun::star::uno::RuntimeException)
341 SolarMutexGuard aSolarMutexGuard;
343 if ( m_bDisposed )
344 return;
346 Sequence< PropertyValue > aArgs;
347 execute( aArgs );
350 void StatusbarController::addStatusListener( const OUString& aCommandURL )
352 Reference< XDispatch > xDispatch;
353 Reference< XStatusListener > xStatusListener;
354 com::sun::star::util::URL aTargetURL;
357 SolarMutexGuard aSolarMutexGuard;
358 URLToDispatchMap::iterator pIter = m_aListenerMap.find( aCommandURL );
360 // Already in the list of status listener. Do nothing.
361 if ( pIter != m_aListenerMap.end() )
362 return;
364 // Check if we are already initialized. Implementation starts adding itself as status listener when
365 // intialize is called.
366 if ( !m_bInitialized )
368 // Put into the boost::unordered_map of status listener. Will be activated when initialized is called
369 m_aListenerMap.insert( URLToDispatchMap::value_type( aCommandURL, Reference< XDispatch >() ));
370 return;
372 else
374 // Add status listener directly as intialize has already been called.
375 Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
376 if ( m_xServiceManager.is() && xDispatchProvider.is() )
378 Reference< XURLTransformer > xURLTransformer = getURLTransformer();
379 aTargetURL.Complete = aCommandURL;
380 xURLTransformer->parseStrict( aTargetURL );
381 xDispatch = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
383 xStatusListener = Reference< XStatusListener >( static_cast< OWeakObject* >( this ), UNO_QUERY );
384 URLToDispatchMap::iterator aIter = m_aListenerMap.find( aCommandURL );
385 if ( aIter != m_aListenerMap.end() )
387 Reference< XDispatch > xOldDispatch( aIter->second );
388 aIter->second = xDispatch;
392 if ( xOldDispatch.is() )
393 xOldDispatch->removeStatusListener( xStatusListener, aTargetURL );
395 catch ( Exception& )
399 else
400 m_aListenerMap.insert( URLToDispatchMap::value_type( aCommandURL, xDispatch ));
405 // Call without locked mutex as we are called back from dispatch implementation
408 if ( xDispatch.is() )
409 xDispatch->addStatusListener( xStatusListener, aTargetURL );
411 catch ( Exception& )
416 void StatusbarController::bindListener()
418 std::vector< Listener > aDispatchVector;
419 Reference< XStatusListener > xStatusListener;
422 SolarMutexGuard aSolarMutexGuard;
424 if ( !m_bInitialized )
425 return;
427 // Collect all registered command URL's and store them temporary
428 Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
429 if ( m_xServiceManager.is() && xDispatchProvider.is() )
431 xStatusListener = Reference< XStatusListener >( static_cast< OWeakObject* >( this ), UNO_QUERY );
432 URLToDispatchMap::iterator pIter = m_aListenerMap.begin();
433 while ( pIter != m_aListenerMap.end() )
435 Reference< XURLTransformer > xURLTransformer = getURLTransformer();
436 com::sun::star::util::URL aTargetURL;
437 aTargetURL.Complete = pIter->first;
438 xURLTransformer->parseStrict( aTargetURL );
440 Reference< XDispatch > xDispatch( pIter->second );
441 if ( xDispatch.is() )
443 // We already have a dispatch object => we have to requery.
444 // Release old dispatch object and remove it as listener
447 xDispatch->removeStatusListener( xStatusListener, aTargetURL );
449 catch ( Exception& )
454 pIter->second.clear();
455 xDispatch.clear();
457 // Query for dispatch object. Old dispatch will be released with this, too.
460 xDispatch = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
462 catch ( Exception& )
465 pIter->second = xDispatch;
467 Listener aListener( aTargetURL, xDispatch );
468 aDispatchVector.push_back( aListener );
469 ++pIter;
474 // Call without locked mutex as we are called back from dispatch implementation
475 if ( !xStatusListener.is() )
476 return;
478 for ( sal_uInt32 i = 0; i < aDispatchVector.size(); i++ )
482 Listener& rListener = aDispatchVector[i];
483 if ( rListener.xDispatch.is() )
484 rListener.xDispatch->addStatusListener( xStatusListener, rListener.aURL );
485 else if ( rListener.aURL.Complete == m_aCommandURL )
487 // Send status changed for the main URL, if we cannot get a valid dispatch object.
488 // UI disables the button. Catch exception as we release our mutex, it is possible
489 // that someone else already disposed this instance!
490 FeatureStateEvent aFeatureStateEvent;
491 aFeatureStateEvent.IsEnabled = sal_False;
492 aFeatureStateEvent.FeatureURL = rListener.aURL;
493 aFeatureStateEvent.State = Any();
494 xStatusListener->statusChanged( aFeatureStateEvent );
497 catch ( ... ){}
501 ::Rectangle StatusbarController::getControlRect() const
503 ::Rectangle aRect;
506 SolarMutexGuard aSolarMutexGuard;
508 if ( m_bDisposed )
509 throw DisposedException();
511 if ( m_xParentWindow.is() )
513 StatusBar* pStatusBar = dynamic_cast< StatusBar* >( VCLUnoHelper::GetWindow( m_xParentWindow ));
514 if ( pStatusBar && pStatusBar->GetType() == WINDOW_STATUSBAR )
515 aRect = pStatusBar->GetItemRect( m_nID );
519 return aRect;
522 void StatusbarController::execute( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArgs )
524 Reference< XDispatch > xDispatch;
525 Reference< XURLTransformer > xURLTransformer;
526 OUString aCommandURL;
529 SolarMutexGuard aSolarMutexGuard;
531 if ( m_bDisposed )
532 throw DisposedException();
534 if ( m_bInitialized &&
535 m_xFrame.is() &&
536 m_xServiceManager.is() &&
537 !m_aCommandURL.isEmpty() )
539 xURLTransformer = getURLTransformer();
540 aCommandURL = m_aCommandURL;
541 URLToDispatchMap::iterator pIter = m_aListenerMap.find( m_aCommandURL );
542 if ( pIter != m_aListenerMap.end() )
543 xDispatch = pIter->second;
547 if ( xDispatch.is() && xURLTransformer.is() )
551 com::sun::star::util::URL aTargetURL;
553 aTargetURL.Complete = aCommandURL;
554 xURLTransformer->parseStrict( aTargetURL );
555 xDispatch->dispatch( aTargetURL, aArgs );
557 catch ( DisposedException& )
563 void StatusbarController::execute(
564 const OUString& aCommandURL,
565 const Sequence< ::com::sun::star::beans::PropertyValue >& aArgs )
567 Reference< XDispatch > xDispatch;
568 com::sun::star::util::URL aTargetURL;
571 SolarMutexGuard aSolarMutexGuard;
573 if ( m_bDisposed )
574 throw DisposedException();
576 if ( m_bInitialized &&
577 m_xFrame.is() &&
578 m_xServiceManager.is() &&
579 !m_aCommandURL.isEmpty() )
581 Reference< XURLTransformer > xURLTransformer( getURLTransformer() );
582 aTargetURL.Complete = aCommandURL;
583 xURLTransformer->parseStrict( aTargetURL );
585 URLToDispatchMap::iterator pIter = m_aListenerMap.find( aCommandURL );
586 if ( pIter != m_aListenerMap.end() )
587 xDispatch = pIter->second;
588 else
590 Reference< ::com::sun::star::frame::XDispatchProvider > xDispatchProvider(
591 m_xFrame->getController(), UNO_QUERY );
592 if ( xDispatchProvider.is() )
593 xDispatch = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
598 if ( xDispatch.is() )
602 xDispatch->dispatch( aTargetURL, aArgs );
604 catch ( DisposedException& )
610 } // svt
612 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */