1 /*************************************************************************
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * Copyright 2008 by Sun Microsystems, Inc.
6 * OpenOffice.org - a multi-platform office productivity suite
8 * $RCSfile: subcomponentmanager.cxx,v $
10 * $Revision: 1.1.2.2 $
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.
28 ************************************************************************/
30 #include "subcomponentmanager.hxx"
31 #include "AppController.hxx"
33 /** === begin UNO includes === **/
34 #include <com/sun/star/frame/XFrame.hpp>
35 #include <com/sun/star/frame/XModel.hpp>
36 #include <com/sun/star/frame/XModel2.hpp>
37 #include <com/sun/star/util/XCloseable.hpp>
38 #include <com/sun/star/awt/XTopWindow.hpp>
39 #include <com/sun/star/embed/XComponentSupplier.hpp>
40 #include <com/sun/star/ucb/XCommandProcessor.hpp>
41 #include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
42 /** === end UNO includes === **/
44 #include <tools/diagnose_ex.h>
45 #include <vcl/svapp.hxx>
46 #include <vos/mutex.hxx>
52 //........................................................................
55 //........................................................................
57 /** === begin UNO using === **/
58 using ::com::sun::star::uno::Reference
;
59 using ::com::sun::star::uno::XInterface
;
60 using ::com::sun::star::uno::UNO_QUERY
;
61 using ::com::sun::star::uno::UNO_QUERY_THROW
;
62 using ::com::sun::star::uno::UNO_SET_THROW
;
63 using ::com::sun::star::uno::Exception
;
64 using ::com::sun::star::uno::RuntimeException
;
65 using ::com::sun::star::uno::Any
;
66 using ::com::sun::star::uno::makeAny
;
67 using ::com::sun::star::uno::Sequence
;
68 using ::com::sun::star::uno::Type
;
69 using ::com::sun::star::frame::XFrame
;
70 using ::com::sun::star::frame::XController
;
71 using ::com::sun::star::frame::XModel
;
72 using ::com::sun::star::lang::EventObject
;
73 using ::com::sun::star::lang::XComponent
;
74 using ::com::sun::star::frame::XModel2
;
75 using ::com::sun::star::container::XEnumeration
;
76 using ::com::sun::star::util::XCloseable
;
77 using ::com::sun::star::awt::XTopWindow
;
78 using ::com::sun::star::embed::XComponentSupplier
;
79 using ::com::sun::star::ucb::XCommandProcessor
;
80 using ::com::sun::star::ucb::Command
;
81 using ::com::sun::star::document::XDocumentEventBroadcaster
;
82 /** === end UNO using === **/
84 //==============================================================================
86 //==============================================================================
89 struct SubComponentDescriptor
91 /// the frame which the component resides in. Must not be <NULL/>
92 Reference
< XFrame
> xFrame
;
93 /// the controller of the sub component. Must not be <NULL/>
94 Reference
< XController
> xController
;
95 /// the model of the sub component. Might be <NULL/>
96 Reference
< XModel
> xModel
;
97 /// the document definition which holds the component, if any
98 Reference
< XCommandProcessor
> xComponentCommandProcessor
;
100 SubComponentDescriptor()
107 SubComponentDescriptor( const Reference
< XComponent
>& _rxComponent
)
109 if ( !impl_constructFrom( _rxComponent
) )
111 Reference
< XComponentSupplier
> xCompSupp( _rxComponent
, UNO_QUERY_THROW
);
112 Reference
< XComponent
> xComponent( xCompSupp
->getComponent(), UNO_QUERY_THROW
);
113 if ( !impl_constructFrom( xComponent
) )
114 throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Illegal component type." ) ), NULL
);
115 xComponentCommandProcessor
.set( _rxComponent
, UNO_QUERY_THROW
);
119 inline bool is() const { return xFrame
.is(); }
122 bool impl_constructFrom( const Reference
< XComponent
>& _rxComponent
)
125 xModel
.set( _rxComponent
, UNO_QUERY
);
128 xController
.set( xModel
->getCurrentController(), UNO_SET_THROW
);
129 xFrame
.set( xController
->getFrame(), UNO_SET_THROW
);
133 // is it a controller?
134 xController
.set( _rxComponent
, UNO_QUERY
);
135 if ( xController
.is() )
137 xFrame
.set( xController
->getFrame(), UNO_SET_THROW
);
142 xFrame
.set( _rxComponent
, UNO_QUERY
);
146 // ensure we have a controller
147 xController
.set( xFrame
->getController(), UNO_SET_THROW
);
150 // check wether there is a model (not required)
151 xModel
.set( xController
->getModel() );
158 struct SelectSubComponent
: public ::std::unary_function
< SubComponentDescriptor
, Reference
< XComponent
> >
160 Reference
< XComponent
> operator()( const SubComponentDescriptor _desc
) const
162 if ( _desc
.xModel
.is() )
163 return _desc
.xModel
.get();
164 OSL_ENSURE( _desc
.xController
.is(), "SelectSubComponent::operator(): illegal component!" );
165 return _desc
.xController
.get();
169 struct SubComponentAccessor
171 /// the name of the sub component
172 ::rtl::OUString sName
;
173 /// type of the component - usually an ElementType value
174 sal_Int32 nComponentType
;
175 /// the mode in which the sub component has been opened
176 ElementOpenMode eOpenMode
;
178 SubComponentAccessor()
180 ,nComponentType( sal_Int32( E_NONE
) )
181 ,eOpenMode( E_OPEN_NORMAL
)
185 SubComponentAccessor( const ::rtl::OUString
& _rName
, const sal_Int32 _nCompType
, const ElementOpenMode _eMode
)
187 ,nComponentType( _nCompType
)
193 struct SubComponentAccessorHash
: public ::std::unary_function
< SubComponentAccessor
, size_t >
195 size_t operator()( const SubComponentAccessor
& _lhs
) const
197 return _lhs
.sName
.hashCode() + _lhs
.nComponentType
+ size_t( _lhs
.eOpenMode
);
200 struct SubComponentAccessorEqual
: public ::std::binary_function
< SubComponentAccessor
, SubComponentAccessor
, bool >
202 bool operator()( const SubComponentAccessor
& _lhs
, const SubComponentAccessor
& _rhs
) const
204 return ( _lhs
.sName
== _rhs
.sName
)
205 && ( _lhs
.nComponentType
== _rhs
.nComponentType
)
206 && ( _lhs
.eOpenMode
== _rhs
.eOpenMode
);
210 typedef ::std::hash_map
< SubComponentAccessor
, SubComponentDescriptor
, SubComponentAccessorHash
, SubComponentAccessorEqual
>
215 //==============================================================================
216 //= SubComponentManager_Data
217 //==============================================================================
218 struct SubComponentManager_Data
220 SubComponentManager_Data( OApplicationController
& _rController
, const ::comphelper::SharedMutex
& _rMutex
)
221 :m_rController( _rController
)
226 OApplicationController
& m_rController
;
227 mutable ::comphelper::SharedMutex m_aMutex
;
228 SubComponentMap m_aComponents
;
230 ::osl::Mutex
& getMutex() const { return m_aMutex
; }
233 //====================================================================
234 //= SubComponentManager
235 //====================================================================
236 //--------------------------------------------------------------------
237 SubComponentManager::SubComponentManager( OApplicationController
& _rController
, const ::comphelper::SharedMutex
& _rMutex
)
238 :m_pData( new SubComponentManager_Data( _rController
, _rMutex
) )
242 //--------------------------------------------------------------------
243 SubComponentManager::~SubComponentManager()
247 //--------------------------------------------------------------------
248 void SubComponentManager::disposing()
250 ::osl::MutexGuard
aGuard( m_pData
->getMutex() );
251 m_pData
->m_aComponents
.clear();
254 //--------------------------------------------------------------------
257 bool lcl_fallbackToAnotherController( SubComponentDescriptor
& _rCompDesc
)
259 Reference
< XController
> xFallback
;
260 OSL_PRECOND( _rCompDesc
.xModel
.is(), "lcl_fallbackToAnotherController: illegal call!" );
261 if ( !_rCompDesc
.xModel
.is() )
264 xFallback
.set( _rCompDesc
.xModel
->getCurrentController() );
265 if ( xFallback
== _rCompDesc
.xController
)
266 // don't accept the very same controller as fallback
269 if ( !xFallback
.is() )
271 // perhaps XModel2 can be of help here
272 Reference
< XModel2
> xModel2( _rCompDesc
.xModel
, UNO_QUERY
);
273 Reference
< XEnumeration
> xControllerEnum
;
275 xControllerEnum
= xModel2
->getControllers();
276 while ( xControllerEnum
.is() && xControllerEnum
->hasMoreElements() )
278 xFallback
.set( xControllerEnum
->nextElement(), UNO_QUERY
);
279 if ( xFallback
== _rCompDesc
.xController
)
284 if ( xFallback
.is() )
286 _rCompDesc
.xController
= xFallback
;
287 _rCompDesc
.xFrame
.set( xFallback
->getFrame(), UNO_SET_THROW
);
294 //----------------------------------------------------------------
295 bool lcl_closeComponent( const Reference
< XCommandProcessor
>& _rxCommandProcessor
)
297 bool bSuccess
= false;
300 Reference
< XCommandProcessor
> xCommandProcessor( _rxCommandProcessor
, UNO_SET_THROW
);
301 sal_Int32 nCommandIdentifier
= xCommandProcessor
->createCommandIdentifier();
304 aCommand
.Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "close" ) );
305 xCommandProcessor
->execute( aCommand
, nCommandIdentifier
, NULL
);
308 catch( const Exception
& )
310 DBG_UNHANDLED_EXCEPTION();
315 //----------------------------------------------------------------
316 bool lcl_closeComponent( const SubComponentDescriptor
& _rComponent
)
318 if ( _rComponent
.xComponentCommandProcessor
.is() )
319 return lcl_closeComponent( _rComponent
.xComponentCommandProcessor
);
321 Reference
< XController
> xController( _rComponent
.xController
);
322 OSL_ENSURE( xController
.is(), "lcl_closeComponent: invalid controller!" );
324 // suspend the controller in the document
325 if ( xController
.is() )
326 if ( !xController
->suspend( sal_True
) )
329 bool bSuccess
= false;
332 Reference
< XCloseable
> xCloseable( _rComponent
.xFrame
, UNO_QUERY_THROW
);
333 xCloseable
->close( sal_True
);
336 catch( const Exception
& )
338 DBG_UNHANDLED_EXCEPTION();
343 // -----------------------------------------------------------------------------
344 void lcl_notifySubComponentEvent( const SubComponentManager_Data
& _rData
, const sal_Char
* _pAsciiEventName
,
345 const SubComponentDescriptor
& _rComponent
)
349 Reference
< XDocumentEventBroadcaster
> xBroadcaster( _rData
.m_rController
.getModel(), UNO_QUERY_THROW
);
350 xBroadcaster
->notifyDocumentEvent(
351 ::rtl::OUString::createFromAscii( _pAsciiEventName
),
352 &_rData
.m_rController
,
353 makeAny( _rComponent
.xFrame
)
356 catch( const Exception
& )
358 DBG_UNHANDLED_EXCEPTION();
363 //--------------------------------------------------------------------
364 void SAL_CALL
SubComponentManager::disposing( const EventObject
& _rSource
) throw (RuntimeException
)
366 ::osl::ClearableMutexGuard
aGuard( m_pData
->getMutex() );
368 SubComponentDescriptor aClosedComponent
;
370 for ( SubComponentMap::iterator comp
= m_pData
->m_aComponents
.begin();
371 comp
!= m_pData
->m_aComponents
.end();
375 bool bRemove
= false;
377 if ( comp
->second
.xController
== _rSource
.Source
)
379 if ( !comp
->second
.xModel
.is() )
385 // maybe this is just one view to the sub document, and only this view is closed
386 if ( !lcl_fallbackToAnotherController( comp
->second
) )
392 else if ( comp
->second
.xModel
== _rSource
.Source
)
399 aClosedComponent
= comp
->second
;
400 m_pData
->m_aComponents
.erase( comp
);
405 if ( aClosedComponent
.is() )
408 lcl_notifySubComponentEvent( *m_pData
, "OnSubComponentClosed", aClosedComponent
);
412 //--------------------------------------------------------------------
413 Sequence
< Reference
< XComponent
> > SubComponentManager::getSubComponents() const
415 ::osl::MutexGuard
aGuard( m_pData
->getMutex() );
417 Sequence
< Reference
< XComponent
> > aComponents( m_pData
->m_aComponents
.size() );
419 m_pData
->m_aComponents
.begin(),
420 m_pData
->m_aComponents
.end(),
421 aComponents
.getArray(),
422 ::std::compose1( SelectSubComponent(), ::std::select2nd
< SubComponentMap::value_type
>() )
427 // -----------------------------------------------------------------------------
428 sal_Bool
SubComponentManager::closeSubComponents()
430 ::vos::OGuard
aSolarGuard( Application::GetSolarMutex() );
431 ::osl::MutexGuard
aGuard( m_pData
->getMutex() );
435 typedef ::std::vector
< SubComponentAccessor
> ComponentAccessors
;
436 ComponentAccessors aClosedComponents
;
438 SubComponentMap
aComponents( m_pData
->m_aComponents
);
439 for ( SubComponentMap::const_iterator comp
= aComponents
.begin();
440 comp
!= aComponents
.end();
444 lcl_closeComponent( comp
->second
);
447 catch ( const Exception
& )
449 DBG_UNHANDLED_EXCEPTION();
455 // -----------------------------------------------------------------------------
456 bool SubComponentManager::empty() const
458 ::osl::MutexGuard
aGuard( m_pData
->getMutex() );
459 return m_pData
->m_aComponents
.empty();
462 // -----------------------------------------------------------------------------
463 void SubComponentManager::onSubComponentOpened( const ::rtl::OUString
& _rName
, const sal_Int32 _nComponentType
,
464 const ElementOpenMode _eOpenMode
, const Reference
< XComponent
>& _rxComponent
)
466 ::osl::ClearableMutexGuard
aGuard( m_pData
->getMutex() );
469 SubComponentAccessor
aKey( _rName
, _nComponentType
, _eOpenMode
);
470 SubComponentDescriptor
aElement( _rxComponent
);
472 m_pData
->m_aComponents
.insert( SubComponentMap::value_type(
477 aElement
.xController
->addEventListener( this );
478 if ( aElement
.xModel
.is() )
479 aElement
.xModel
->addEventListener( this );
481 // notify this to interested parties
483 lcl_notifySubComponentEvent( *m_pData
, "OnSubComponentOpened", aElement
);
486 // -----------------------------------------------------------------------------
487 bool SubComponentManager::activateSubFrame( const ::rtl::OUString
& _rName
, const sal_Int32 _nComponentType
, const ElementOpenMode _eOpenMode
) const
489 ::osl::MutexGuard
aGuard( m_pData
->getMutex() );
491 SubComponentAccessor
aKey( _rName
, _nComponentType
, _eOpenMode
);
492 SubComponentMap::const_iterator pos
= m_pData
->m_aComponents
.find( aKey
);
493 if ( pos
== m_pData
->m_aComponents
.end() )
494 // no component with this name/type/open mode
497 const Reference
< XFrame
> xFrame( pos
->second
.xFrame
, UNO_SET_THROW
);
498 const Reference
< XTopWindow
> xTopWindow( xFrame
->getContainerWindow(), UNO_QUERY_THROW
);
499 xTopWindow
->toFront();
504 // -----------------------------------------------------------------------------
505 bool SubComponentManager::closeSubFrames( const ::rtl::OUString
& _rName
, const sal_Int32 _nComponentType
)
507 ::osl::MutexGuard
aGuard( m_pData
->getMutex() );
509 SubComponentMap
aWorkingCopy( m_pData
->m_aComponents
);
510 for ( SubComponentMap::const_iterator comp
= aWorkingCopy
.begin();
511 comp
!= aWorkingCopy
.end();
515 if ( ( comp
->first
.sName
!= _rName
) || ( comp
->first
.nComponentType
!= _nComponentType
) )
518 if ( !lcl_closeComponent( comp
->second
) )
525 //........................................................................
527 //........................................................................