update dev300-m58
[ooovba.git] / dbaccess / source / ui / app / subcomponentmanager.cxx
blob8541879c6921dccf1787efa4190338feac26cf9e
1 /*************************************************************************
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
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>
48 #include <hash_map>
49 #include <algorithm>
50 #include <functional>
52 //........................................................................
53 namespace dbaui
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 //==============================================================================
85 //= helper structs
86 //==============================================================================
87 namespace
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()
101 :xFrame()
102 ,xController()
103 ,xModel()
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(); }
121 private:
122 bool impl_constructFrom( const Reference< XComponent >& _rxComponent )
124 // is it a model?
125 xModel.set( _rxComponent, UNO_QUERY );
126 if ( xModel.is() )
128 xController.set( xModel->getCurrentController(), UNO_SET_THROW );
129 xFrame.set( xController->getFrame(), UNO_SET_THROW );
131 else
133 // is it a controller?
134 xController.set( _rxComponent, UNO_QUERY );
135 if ( xController.is() )
137 xFrame.set( xController->getFrame(), UNO_SET_THROW );
139 else
141 // is it a frame?
142 xFrame.set( _rxComponent, UNO_QUERY );
143 if ( !xFrame.is() )
144 return false;
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() );
154 return true;
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()
179 :sName()
180 ,nComponentType( sal_Int32( E_NONE ) )
181 ,eOpenMode( E_OPEN_NORMAL )
185 SubComponentAccessor( const ::rtl::OUString& _rName, const sal_Int32 _nCompType, const ElementOpenMode _eMode )
186 :sName( _rName )
187 ,nComponentType( _nCompType )
188 ,eOpenMode( _eMode )
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 >
211 SubComponentMap;
215 //==============================================================================
216 //= SubComponentManager_Data
217 //==============================================================================
218 struct SubComponentManager_Data
220 SubComponentManager_Data( OApplicationController& _rController, const ::comphelper::SharedMutex& _rMutex )
221 :m_rController( _rController )
222 ,m_aMutex( _rMutex )
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 //--------------------------------------------------------------------
255 namespace
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() )
262 return false;
264 xFallback.set( _rCompDesc.xModel->getCurrentController() );
265 if ( xFallback == _rCompDesc.xController )
266 // don't accept the very same controller as fallback
267 xFallback.clear();
269 if ( !xFallback.is() )
271 // perhaps XModel2 can be of help here
272 Reference< XModel2 > xModel2( _rCompDesc.xModel, UNO_QUERY );
273 Reference< XEnumeration > xControllerEnum;
274 if ( xModel2.is() )
275 xControllerEnum = xModel2->getControllers();
276 while ( xControllerEnum.is() && xControllerEnum->hasMoreElements() )
278 xFallback.set( xControllerEnum->nextElement(), UNO_QUERY );
279 if ( xFallback == _rCompDesc.xController )
280 xFallback.clear();
284 if ( xFallback.is() )
286 _rCompDesc.xController = xFallback;
287 _rCompDesc.xFrame.set( xFallback->getFrame(), UNO_SET_THROW );
288 return true;
291 return false;
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();
303 Command aCommand;
304 aCommand.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "close" ) );
305 xCommandProcessor->execute( aCommand, nCommandIdentifier, NULL );
306 bSuccess = true;
308 catch( const Exception& )
310 DBG_UNHANDLED_EXCEPTION();
312 return bSuccess;
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 ) )
327 return false;
329 bool bSuccess = false;
332 Reference< XCloseable > xCloseable( _rComponent.xFrame, UNO_QUERY_THROW );
333 xCloseable->close( sal_True );
334 bSuccess = true;
336 catch( const Exception& )
338 DBG_UNHANDLED_EXCEPTION();
340 return bSuccess;
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();
372 ++comp
375 bool bRemove = false;
377 if ( comp->second.xController == _rSource.Source )
379 if ( !comp->second.xModel.is() )
381 bRemove = true;
383 else
385 // maybe this is just one view to the sub document, and only this view is closed
386 if ( !lcl_fallbackToAnotherController( comp->second ) )
388 bRemove = true;
392 else if ( comp->second.xModel == _rSource.Source )
394 bRemove = true;
397 if ( bRemove )
399 aClosedComponent = comp->second;
400 m_pData->m_aComponents.erase( comp );
401 break;
405 if ( aClosedComponent.is() )
407 aGuard.clear();
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() );
418 ::std::transform(
419 m_pData->m_aComponents.begin(),
420 m_pData->m_aComponents.end(),
421 aComponents.getArray(),
422 ::std::compose1( SelectSubComponent(), ::std::select2nd< SubComponentMap::value_type >() )
424 return aComponents;
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();
441 ++comp
444 lcl_closeComponent( comp->second );
447 catch ( const Exception& )
449 DBG_UNHANDLED_EXCEPTION();
452 return empty();
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() );
468 // put into map
469 SubComponentAccessor aKey( _rName, _nComponentType, _eOpenMode );
470 SubComponentDescriptor aElement( _rxComponent );
472 m_pData->m_aComponents.insert( SubComponentMap::value_type(
473 aKey, aElement
474 ) ) ;
476 // add as listener
477 aElement.xController->addEventListener( this );
478 if ( aElement.xModel.is() )
479 aElement.xModel->addEventListener( this );
481 // notify this to interested parties
482 aGuard.clear();
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
495 return false;
497 const Reference< XFrame > xFrame( pos->second.xFrame, UNO_SET_THROW );
498 const Reference< XTopWindow > xTopWindow( xFrame->getContainerWindow(), UNO_QUERY_THROW );
499 xTopWindow->toFront();
501 return true;
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();
512 ++comp
515 if ( ( comp->first.sName != _rName ) || ( comp->first.nComponentType != _nComponentType ) )
516 continue;
518 if ( !lcl_closeComponent( comp->second ) )
519 return false;
522 return true;
525 //........................................................................
526 } // namespace dbaui
527 //........................................................................