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: toolboxcontroller.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 <svtools/toolboxcontroller.hxx>
34 #include <com/sun/star/beans/PropertyValue.hpp>
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/frame/XDispatchProvider.hpp>
37 #include <com/sun/star/lang/DisposedException.hpp>
38 #include <com/sun/star/frame/XLayoutManager.hpp>
39 #include <vos/mutex.hxx>
40 #include <vcl/svapp.hxx>
42 #include <svtools/miscopt.hxx>
44 #ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_
45 #include <toolkit/unohlp.hxx>
47 #include <vcl/toolbox.hxx>
49 using namespace ::cppu
;
50 using namespace ::com::sun::star::awt
;
51 using namespace ::com::sun::star::uno
;
52 using namespace ::com::sun::star::util
;
53 using namespace ::com::sun::star::beans
;
54 using namespace ::com::sun::star::lang
;
55 using namespace ::com::sun::star::frame
;
56 using namespace ::com::sun::star::frame
;
60 struct ToolboxController_Impl
62 ::com::sun::star::uno::Reference
< ::com::sun::star::awt::XWindow
> m_xParentWindow
;
63 ::com::sun::star::uno::Reference
< ::com::sun::star::util::XURLTransformer
> m_xUrlTransformer
;
66 ToolboxController::ToolboxController(
67 const Reference
< XMultiServiceFactory
>& rServiceManager
,
68 const Reference
< XFrame
>& xFrame
,
69 const ::rtl::OUString
& aCommandURL
) :
71 , m_bInitialized( sal_False
)
72 , m_bDisposed( sal_False
)
74 , m_xServiceManager( rServiceManager
)
75 , m_aCommandURL( aCommandURL
)
76 , m_aListenerContainer( m_aMutex
)
78 m_pImpl
= new ToolboxController_Impl
;
82 m_pImpl
->m_xUrlTransformer
.set( m_xServiceManager
->createInstance(
83 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.URLTransformer" ))),
86 catch(const Exception
&)
91 ToolboxController::ToolboxController() :
93 , m_bInitialized( sal_False
)
94 , m_bDisposed( sal_False
)
95 , m_aListenerContainer( m_aMutex
)
97 m_pImpl
= new ToolboxController_Impl
;
100 ToolboxController::~ToolboxController()
105 Reference
< XFrame
> ToolboxController::getFrameInterface() const
107 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
111 Reference
< XMultiServiceFactory
> ToolboxController::getServiceManager() const
113 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
114 return m_xServiceManager
;
117 Reference
< XLayoutManager
> ToolboxController::getLayoutManager() const
119 Reference
< XLayoutManager
> xLayoutManager
;
120 Reference
< XPropertySet
> xPropSet
;
122 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
123 xPropSet
= Reference
< XPropertySet
>( m_xFrame
, UNO_QUERY
);
130 xLayoutManager
.set(xPropSet
->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" ))),UNO_QUERY
);
137 return xLayoutManager
;
141 Any SAL_CALL
ToolboxController::queryInterface( const Type
& rType
)
142 throw ( RuntimeException
)
144 Any a
= ::cppu::queryInterface(
146 static_cast< XToolbarController
* >( this ),
147 static_cast< XStatusListener
* >( this ),
148 static_cast< XEventListener
* >( this ),
149 static_cast< XInitialization
* >( this ),
150 static_cast< XComponent
* >( this ),
151 static_cast< XUpdatable
* >( this ));
156 return OWeakObject::queryInterface( rType
);
159 void SAL_CALL
ToolboxController::acquire() throw ()
161 OWeakObject::acquire();
164 void SAL_CALL
ToolboxController::release() throw ()
166 OWeakObject::release();
169 void SAL_CALL
ToolboxController::initialize( const Sequence
< Any
>& aArguments
)
170 throw ( Exception
, RuntimeException
)
172 const rtl::OUString
aFrameName( RTL_CONSTASCII_USTRINGPARAM( "Frame" ));
173 const rtl::OUString
aCommandURLName( RTL_CONSTASCII_USTRINGPARAM( "CommandURL" ));
174 const rtl::OUString
aServiceManagerName( RTL_CONSTASCII_USTRINGPARAM( "ServiceManager" ));
175 const rtl::OUString
aParentWindow( RTL_CONSTASCII_USTRINGPARAM( "ParentWindow" ));
177 bool bInitialized( true );
180 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
183 throw DisposedException();
185 bInitialized
= m_bInitialized
;
190 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
191 m_bInitialized
= sal_True
;
193 PropertyValue aPropValue
;
194 for ( int i
= 0; i
< aArguments
.getLength(); i
++ )
196 if ( aArguments
[i
] >>= aPropValue
)
198 if ( aPropValue
.Name
.equalsAscii( "Frame" ))
199 m_xFrame
.set(aPropValue
.Value
,UNO_QUERY
);
200 else if ( aPropValue
.Name
.equalsAscii( "CommandURL" ))
201 aPropValue
.Value
>>= m_aCommandURL
;
202 else if ( aPropValue
.Name
.equalsAscii( "ServiceManager" ))
203 m_xServiceManager
.set(aPropValue
.Value
,UNO_QUERY
);
204 else if ( aPropValue
.Name
.equalsAscii( "ParentWindow" ))
205 m_pImpl
->m_xParentWindow
.set(aPropValue
.Value
,UNO_QUERY
);
211 if ( !m_pImpl
->m_xUrlTransformer
.is() && m_xServiceManager
.is() )
212 m_pImpl
->m_xUrlTransformer
.set( m_xServiceManager
->createInstance(
213 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.URLTransformer" ))),
216 catch(const Exception
&)
220 if ( m_aCommandURL
.getLength() )
221 m_aListenerMap
.insert( URLToDispatchMap::value_type( m_aCommandURL
, Reference
< XDispatch
>() ));
225 void SAL_CALL
ToolboxController::update()
226 throw ( RuntimeException
)
229 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
231 throw DisposedException();
234 // Bind all registered listeners to their dispatch objects
239 void SAL_CALL
ToolboxController::dispose()
240 throw (::com::sun::star::uno::RuntimeException
)
242 Reference
< XComponent
> xThis( static_cast< OWeakObject
* >(this), UNO_QUERY
);
245 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
247 throw DisposedException();
250 com::sun::star::lang::EventObject
aEvent( xThis
);
251 m_aListenerContainer
.disposeAndClear( aEvent
);
253 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
254 Reference
< XStatusListener
> xStatusListener( static_cast< OWeakObject
* >( this ), UNO_QUERY
);
255 URLToDispatchMap::iterator pIter
= m_aListenerMap
.begin();
256 while ( pIter
!= m_aListenerMap
.end() )
260 Reference
< XDispatch
> xDispatch( pIter
->second
);
262 com::sun::star::util::URL aTargetURL
;
263 aTargetURL
.Complete
= pIter
->first
;
264 if ( m_pImpl
->m_xUrlTransformer
.is() )
265 m_pImpl
->m_xUrlTransformer
->parseStrict( aTargetURL
);
267 if ( xDispatch
.is() && xStatusListener
.is() )
268 xDispatch
->removeStatusListener( xStatusListener
, aTargetURL
);
277 m_bDisposed
= sal_True
;
280 void SAL_CALL
ToolboxController::addEventListener( const Reference
< XEventListener
>& xListener
)
281 throw ( RuntimeException
)
283 m_aListenerContainer
.addInterface( ::getCppuType( ( const Reference
< XEventListener
>* ) NULL
), xListener
);
286 void SAL_CALL
ToolboxController::removeEventListener( const Reference
< XEventListener
>& aListener
)
287 throw ( RuntimeException
)
289 m_aListenerContainer
.removeInterface( ::getCppuType( ( const Reference
< XEventListener
>* ) NULL
), aListener
);
293 void SAL_CALL
ToolboxController::disposing( const EventObject
& Source
)
294 throw ( RuntimeException
)
296 Reference
< XInterface
> xSource( Source
.Source
);
298 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
303 URLToDispatchMap::iterator pIter
= m_aListenerMap
.begin();
304 while ( pIter
!= m_aListenerMap
.end() )
306 // Compare references and release dispatch references if they are equal.
307 Reference
< XInterface
> xIfac( pIter
->second
, UNO_QUERY
);
308 if ( xSource
== xIfac
)
309 pIter
->second
.clear();
313 Reference
< XInterface
> xIfac( m_xFrame
, UNO_QUERY
);
314 if ( xIfac
== xSource
)
319 void SAL_CALL
ToolboxController::statusChanged( const FeatureStateEvent
& )
320 throw ( RuntimeException
)
322 // must be implemented by sub class
325 // XToolbarController
326 void SAL_CALL
ToolboxController::execute( sal_Int16 KeyModifier
)
327 throw (::com::sun::star::uno::RuntimeException
)
329 Reference
< XDispatch
> xDispatch
;
330 ::rtl::OUString aCommandURL
;
333 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
336 throw DisposedException();
338 if ( m_bInitialized
&&
340 m_xServiceManager
.is() &&
341 m_aCommandURL
.getLength() )
344 aCommandURL
= m_aCommandURL
;
345 URLToDispatchMap::iterator pIter
= m_aListenerMap
.find( m_aCommandURL
);
346 if ( pIter
!= m_aListenerMap
.end() )
347 xDispatch
= pIter
->second
;
351 if ( xDispatch
.is() )
355 com::sun::star::util::URL aTargetURL
;
356 Sequence
<PropertyValue
> aArgs( 1 );
358 // Provide key modifier information to dispatch function
359 aArgs
[0].Name
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "KeyModifier" ));
360 aArgs
[0].Value
= makeAny( KeyModifier
);
362 aTargetURL
.Complete
= aCommandURL
;
363 if ( m_pImpl
->m_xUrlTransformer
.is() )
364 m_pImpl
->m_xUrlTransformer
->parseStrict( aTargetURL
);
365 xDispatch
->dispatch( aTargetURL
, aArgs
);
367 catch ( DisposedException
& )
373 void SAL_CALL
ToolboxController::click()
374 throw (::com::sun::star::uno::RuntimeException
)
378 void SAL_CALL
ToolboxController::doubleClick()
379 throw (::com::sun::star::uno::RuntimeException
)
383 Reference
< XWindow
> SAL_CALL
ToolboxController::createPopupWindow()
384 throw (::com::sun::star::uno::RuntimeException
)
386 return Reference
< XWindow
>();
389 Reference
< XWindow
> SAL_CALL
ToolboxController::createItemWindow( const Reference
< XWindow
>& )
390 throw (::com::sun::star::uno::RuntimeException
)
392 return Reference
< XWindow
>();
395 void ToolboxController::addStatusListener( const rtl::OUString
& aCommandURL
)
397 Reference
< XDispatch
> xDispatch
;
398 Reference
< XStatusListener
> xStatusListener
;
399 com::sun::star::util::URL aTargetURL
;
402 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
403 URLToDispatchMap::iterator pIter
= m_aListenerMap
.find( aCommandURL
);
405 // Already in the list of status listener. Do nothing.
406 if ( pIter
!= m_aListenerMap
.end() )
409 // Check if we are already initialized. Implementation starts adding itself as status listener when
410 // intialize is called.
411 if ( !m_bInitialized
)
413 // Put into the hash_map of status listener. Will be activated when initialized is called
414 m_aListenerMap
.insert( URLToDispatchMap::value_type( aCommandURL
, Reference
< XDispatch
>() ));
419 // Add status listener directly as intialize has already been called.
420 Reference
< XDispatchProvider
> xDispatchProvider( m_xFrame
, UNO_QUERY
);
421 if ( m_xServiceManager
.is() && xDispatchProvider
.is() )
423 aTargetURL
.Complete
= aCommandURL
;
424 if ( m_pImpl
->m_xUrlTransformer
.is() )
425 m_pImpl
->m_xUrlTransformer
->parseStrict( aTargetURL
);
426 xDispatch
= xDispatchProvider
->queryDispatch( aTargetURL
, ::rtl::OUString(), 0 );
428 xStatusListener
= Reference
< XStatusListener
>( static_cast< OWeakObject
* >( this ), UNO_QUERY
);
429 URLToDispatchMap::iterator aIter
= m_aListenerMap
.find( aCommandURL
);
430 if ( aIter
!= m_aListenerMap
.end() )
432 Reference
< XDispatch
> xOldDispatch( aIter
->second
);
433 aIter
->second
= xDispatch
;
437 if ( xOldDispatch
.is() )
438 xOldDispatch
->removeStatusListener( xStatusListener
, aTargetURL
);
445 m_aListenerMap
.insert( URLToDispatchMap::value_type( aCommandURL
, xDispatch
));
450 // Call without locked mutex as we are called back from dispatch implementation
453 if ( xDispatch
.is() )
454 xDispatch
->addStatusListener( xStatusListener
, aTargetURL
);
461 void ToolboxController::removeStatusListener( const rtl::OUString
& aCommandURL
)
463 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
465 URLToDispatchMap::iterator pIter
= m_aListenerMap
.find( aCommandURL
);
466 if ( pIter
!= m_aListenerMap
.end() )
468 Reference
< XDispatch
> xDispatch( pIter
->second
);
469 Reference
< XStatusListener
> xStatusListener( static_cast< OWeakObject
* >( this ), UNO_QUERY
);
470 m_aListenerMap
.erase( pIter
);
474 com::sun::star::util::URL aTargetURL
;
475 aTargetURL
.Complete
= aCommandURL
;
476 if ( m_pImpl
->m_xUrlTransformer
.is() )
477 m_pImpl
->m_xUrlTransformer
->parseStrict( aTargetURL
);
479 if ( xDispatch
.is() && xStatusListener
.is() )
480 xDispatch
->removeStatusListener( xStatusListener
, aTargetURL
);
488 void ToolboxController::bindListener()
490 std::vector
< Listener
> aDispatchVector
;
491 Reference
< XStatusListener
> xStatusListener
;
494 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
496 if ( !m_bInitialized
)
499 // Collect all registered command URL's and store them temporary
500 Reference
< XDispatchProvider
> xDispatchProvider( m_xFrame
, UNO_QUERY
);
501 if ( m_xServiceManager
.is() && xDispatchProvider
.is() )
503 xStatusListener
= Reference
< XStatusListener
>( static_cast< OWeakObject
* >( this ), UNO_QUERY
);
504 URLToDispatchMap::iterator pIter
= m_aListenerMap
.begin();
505 while ( pIter
!= m_aListenerMap
.end() )
507 com::sun::star::util::URL aTargetURL
;
508 aTargetURL
.Complete
= pIter
->first
;
509 if ( m_pImpl
->m_xUrlTransformer
.is() )
510 m_pImpl
->m_xUrlTransformer
->parseStrict( aTargetURL
);
512 Reference
< XDispatch
> xDispatch( pIter
->second
);
513 if ( xDispatch
.is() )
515 // We already have a dispatch object => we have to requery.
516 // Release old dispatch object and remove it as listener
519 xDispatch
->removeStatusListener( xStatusListener
, aTargetURL
);
526 pIter
->second
.clear();
529 // Query for dispatch object. Old dispatch will be released with this, too.
532 xDispatch
= xDispatchProvider
->queryDispatch( aTargetURL
, ::rtl::OUString(), 0 );
537 pIter
->second
= xDispatch
;
539 Listener
aListener( aTargetURL
, xDispatch
);
540 aDispatchVector
.push_back( aListener
);
546 // Call without locked mutex as we are called back from dispatch implementation
547 if ( xStatusListener
.is() )
551 for ( sal_uInt32 i
= 0; i
< aDispatchVector
.size(); i
++ )
553 Listener
& rListener
= aDispatchVector
[i
];
554 if ( rListener
.xDispatch
.is() )
555 rListener
.xDispatch
->addStatusListener( xStatusListener
, rListener
.aURL
);
556 else if ( rListener
.aURL
.Complete
== m_aCommandURL
)
560 // Send status changed for the main URL, if we cannot get a valid dispatch object.
561 // UI disables the button. Catch exception as we release our mutex, it is possible
562 // that someone else already disposed this instance!
563 FeatureStateEvent aFeatureStateEvent
;
564 aFeatureStateEvent
.IsEnabled
= sal_False
;
565 aFeatureStateEvent
.FeatureURL
= rListener
.aURL
;
566 aFeatureStateEvent
.State
= Any();
567 xStatusListener
->statusChanged( aFeatureStateEvent
);
581 void ToolboxController::unbindListener()
583 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
585 if ( !m_bInitialized
)
588 // Collect all registered command URL's and store them temporary
589 Reference
< XDispatchProvider
> xDispatchProvider( m_xFrame
, UNO_QUERY
);
590 if ( m_xServiceManager
.is() && xDispatchProvider
.is() )
592 Reference
< XStatusListener
> xStatusListener( static_cast< OWeakObject
* >( this ), UNO_QUERY
);
593 URLToDispatchMap::iterator pIter
= m_aListenerMap
.begin();
594 while ( pIter
!= m_aListenerMap
.end() )
596 com::sun::star::util::URL aTargetURL
;
597 aTargetURL
.Complete
= pIter
->first
;
598 if ( m_pImpl
->m_xUrlTransformer
.is() )
599 m_pImpl
->m_xUrlTransformer
->parseStrict( aTargetURL
);
601 Reference
< XDispatch
> xDispatch( pIter
->second
);
602 if ( xDispatch
.is() )
604 // We already have a dispatch object => we have to requery.
605 // Release old dispatch object and remove it as listener
608 xDispatch
->removeStatusListener( xStatusListener
, aTargetURL
);
614 pIter
->second
.clear();
620 sal_Bool
ToolboxController::isBound() const
622 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
624 if ( !m_bInitialized
)
627 URLToDispatchMap::const_iterator pIter
= m_aListenerMap
.find( m_aCommandURL
);
628 if ( pIter
!= m_aListenerMap
.end() )
629 return ( pIter
->second
.is() );
634 sal_Bool
ToolboxController::hasBigImages() const
636 return SvtMiscOptions().AreCurrentSymbolsLarge();
639 sal_Bool
ToolboxController::isHighContrast() const
641 sal_Bool
bHighContrast( sal_False
);
643 Reference
< XWindow
> xWindow
= m_pImpl
->m_xParentWindow
;
646 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
647 Window
* pWindow
= VCLUnoHelper::GetWindow( xWindow
);
649 bHighContrast
= ( ((ToolBox
*)pWindow
)->GetBackground().GetColor().IsDark() );
652 return bHighContrast
;
655 void ToolboxController::updateStatus()
660 void ToolboxController::updateStatus( const rtl::OUString aCommandURL
)
662 Reference
< XDispatch
> xDispatch
;
663 Reference
< XStatusListener
> xStatusListener
;
664 com::sun::star::util::URL aTargetURL
;
667 vos::OGuard
aSolarMutexGuard( Application::GetSolarMutex() );
669 if ( !m_bInitialized
)
672 // Try to find a dispatch object for the requested command URL
673 Reference
< XDispatchProvider
> xDispatchProvider( m_xFrame
, UNO_QUERY
);
674 xStatusListener
= Reference
< XStatusListener
>( static_cast< OWeakObject
* >( this ), UNO_QUERY
);
675 if ( m_xServiceManager
.is() && xDispatchProvider
.is() )
677 aTargetURL
.Complete
= aCommandURL
;
678 if ( m_pImpl
->m_xUrlTransformer
.is() )
679 m_pImpl
->m_xUrlTransformer
->parseStrict( aTargetURL
);
680 xDispatch
= xDispatchProvider
->queryDispatch( aTargetURL
, rtl::OUString(), 0 );
684 if ( xDispatch
.is() && xStatusListener
.is() )
686 // Catch exception as we release our mutex, it is possible that someone else
687 // has already disposed this instance!
688 // Add/remove status listener to get a update status information from the
689 // requested command.
692 xDispatch
->addStatusListener( xStatusListener
, aTargetURL
);
693 xDispatch
->removeStatusListener( xStatusListener
, aTargetURL
);
701 Reference
< XURLTransformer
> ToolboxController::getURLTransformer() const
703 return m_pImpl
->m_xUrlTransformer
;
706 Reference
< ::com::sun::star::awt::XWindow
> ToolboxController::getParent() const
708 return m_pImpl
->m_xParentWindow
;