Version 3.6.0.2, tag libreoffice-3.6.0.2
[LibreOffice.git] / dbaccess / source / ui / app / subcomponentmanager.cxx
blob428f2ef8840149c15fa02720db7027a2a2d7407f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 #include "subcomponentmanager.hxx"
29 #include "AppController.hxx"
30 #include "dbustrings.hrc"
32 /** === begin UNO includes === **/
33 #include <com/sun/star/frame/XFrame.hpp>
34 #include <com/sun/star/frame/XModel.hpp>
35 #include <com/sun/star/frame/XModel2.hpp>
36 #include <com/sun/star/util/XCloseable.hpp>
37 #include <com/sun/star/awt/XTopWindow.hpp>
38 #include <com/sun/star/embed/XComponentSupplier.hpp>
39 #include <com/sun/star/ucb/XCommandProcessor.hpp>
40 #include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
41 #include <com/sun/star/beans/XPropertySet.hpp>
42 /** === end UNO includes === **/
44 #include <tools/diagnose_ex.h>
45 #include <vcl/svapp.hxx>
46 #include <osl/mutex.hxx>
48 #include <algorithm>
49 #include <functional>
51 //......................................................................................................................
52 namespace dbaui
54 //......................................................................................................................
56 /** === begin UNO using === **/
57 using ::com::sun::star::uno::Reference;
58 using ::com::sun::star::uno::XInterface;
59 using ::com::sun::star::uno::UNO_QUERY;
60 using ::com::sun::star::uno::UNO_QUERY_THROW;
61 using ::com::sun::star::uno::UNO_SET_THROW;
62 using ::com::sun::star::uno::Exception;
63 using ::com::sun::star::uno::RuntimeException;
64 using ::com::sun::star::uno::Any;
65 using ::com::sun::star::uno::makeAny;
66 using ::com::sun::star::uno::Sequence;
67 using ::com::sun::star::uno::Type;
68 using ::com::sun::star::frame::XFrame;
69 using ::com::sun::star::frame::XController;
70 using ::com::sun::star::frame::XModel;
71 using ::com::sun::star::lang::EventObject;
72 using ::com::sun::star::lang::XComponent;
73 using ::com::sun::star::frame::XModel2;
74 using ::com::sun::star::container::XEnumeration;
75 using ::com::sun::star::util::XCloseable;
76 using ::com::sun::star::awt::XTopWindow;
77 using ::com::sun::star::embed::XComponentSupplier;
78 using ::com::sun::star::ucb::XCommandProcessor;
79 using ::com::sun::star::ucb::Command;
80 using ::com::sun::star::document::XDocumentEventBroadcaster;
81 using ::com::sun::star::beans::XPropertySet;
82 using ::com::sun::star::beans::PropertyChangeEvent;
83 /** === end UNO using === **/
85 //==================================================================================================================
86 //= helper structs
87 //==================================================================================================================
88 namespace
90 //..............................................................................................................
91 struct SubComponentDescriptor
93 /// the name of the sub component, empty if it is yet unsaved
94 ::rtl::OUString sName;
95 /// type of the component - an ElementType value, except for relation design
96 sal_Int32 nComponentType;
97 /// the mode in which the sub component has been opened
98 ElementOpenMode eOpenMode;
99 /// the frame which the component resides in. Must not be <NULL/>
100 Reference< XFrame > xFrame;
101 /// the controller of the sub component. Must not be <NULL/>
102 Reference< XController > xController;
103 /// the model of the sub component. Might be <NULL/>
104 Reference< XModel > xModel;
105 /// the document definition which holds the component, if any; as CommandProcessor
106 Reference< XCommandProcessor > xComponentCommandProcessor;
107 /// the document definition which holds the component, if any; as PropertySet
108 Reference< XPropertySet > xDocumentDefinitionProperties;
110 SubComponentDescriptor()
111 :sName()
112 ,nComponentType( -1 )
113 ,eOpenMode( E_OPEN_NORMAL )
114 ,xFrame()
115 ,xController()
116 ,xModel()
120 SubComponentDescriptor( const ::rtl::OUString& i_rName, const sal_Int32 i_nComponentType,
121 const ElementOpenMode i_eOpenMode, const Reference< XComponent >& i_rComponent )
122 :sName( i_rName )
123 ,nComponentType( i_nComponentType )
124 ,eOpenMode( i_eOpenMode )
126 if ( !impl_constructFrom( i_rComponent ) )
128 // i_rComponent is neither a model, nor a controller, nor a frame
129 // => it must be a css.sdb.DocumentDefinition
130 Reference< XComponentSupplier > xCompSupp( i_rComponent, UNO_QUERY_THROW );
131 Reference< XComponent > xComponent( xCompSupp->getComponent(), UNO_QUERY_THROW );
132 if ( !impl_constructFrom( xComponent ) )
133 throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Illegal component type." ) ), NULL );
134 xComponentCommandProcessor.set( i_rComponent, UNO_QUERY_THROW );
135 xDocumentDefinitionProperties.set( i_rComponent, UNO_QUERY_THROW );
139 inline bool is() const { return xFrame.is(); }
141 private:
142 bool impl_constructFrom( const Reference< XComponent >& _rxComponent )
144 // is it a model?
145 xModel.set( _rxComponent, UNO_QUERY );
146 if ( xModel.is() )
148 xController.set( xModel->getCurrentController() );
149 if ( xController.is() )
150 xFrame.set( xController->getFrame(), UNO_SET_THROW );
152 else
154 // is it a controller?
155 xController.set( _rxComponent, UNO_QUERY );
156 if ( xController.is() )
158 xFrame.set( xController->getFrame(), UNO_SET_THROW );
160 else
162 // is it a frame?
163 xFrame.set( _rxComponent, UNO_QUERY );
164 if ( !xFrame.is() )
165 return false;
167 // ensure we have a controller
168 xController.set( xFrame->getController(), UNO_SET_THROW );
171 // check whether there is a model (not required)
172 xModel.set( xController->getModel() );
175 return true;
179 //..............................................................................................................
180 struct SelectSubComponent : public ::std::unary_function< SubComponentDescriptor, Reference< XComponent > >
182 Reference< XComponent > operator()( const SubComponentDescriptor &_desc ) const
184 if ( _desc.xModel.is() )
185 return _desc.xModel.get();
186 OSL_ENSURE( _desc.xController.is(), "SelectSubComponent::operator(): illegal component!" );
187 return _desc.xController.get();
191 //..............................................................................................................
192 typedef ::std::vector< SubComponentDescriptor > SubComponents;
194 //..............................................................................................................
195 struct SubComponentMatch : public ::std::unary_function< SubComponentDescriptor, bool >
197 public:
198 SubComponentMatch( const ::rtl::OUString& i_rName, const sal_Int32 i_nComponentType,
199 const ElementOpenMode i_eOpenMode )
200 :m_sName( i_rName )
201 ,m_nComponentType( i_nComponentType )
202 ,m_eOpenMode( i_eOpenMode )
206 bool operator()( const SubComponentDescriptor& i_rCompareWith ) const
208 return ( m_sName == i_rCompareWith.sName )
209 && ( m_nComponentType == i_rCompareWith.nComponentType )
210 && ( m_eOpenMode == i_rCompareWith.eOpenMode );
212 private:
213 const ::rtl::OUString m_sName;
214 const sal_Int32 m_nComponentType;
215 const ElementOpenMode m_eOpenMode;
219 //==================================================================================================================
220 //= SubComponentManager_Data
221 //==================================================================================================================
222 struct SubComponentManager_Data
224 SubComponentManager_Data( OApplicationController& _rController, const ::comphelper::SharedMutex& _rMutex )
225 :m_rController( _rController )
226 ,m_aMutex( _rMutex )
230 OApplicationController& m_rController;
231 mutable ::comphelper::SharedMutex m_aMutex;
232 SubComponents m_aComponents;
234 ::osl::Mutex& getMutex() const { return m_aMutex; }
237 //==================================================================================================================
238 //= SubComponentManager
239 //==================================================================================================================
240 //------------------------------------------------------------------------------------------------------------------
241 SubComponentManager::SubComponentManager( OApplicationController& _rController, const ::comphelper::SharedMutex& _rMutex )
242 :m_pData( new SubComponentManager_Data( _rController, _rMutex ) )
246 //------------------------------------------------------------------------------------------------------------------
247 SubComponentManager::~SubComponentManager()
251 //------------------------------------------------------------------------------------------------------------------
252 void SubComponentManager::disposing()
254 ::osl::MutexGuard aGuard( m_pData->getMutex() );
255 m_pData->m_aComponents.clear();
258 //------------------------------------------------------------------------------------------------------------------
259 namespace
261 //..............................................................................................................
262 bool lcl_fallbackToAnotherController( SubComponentDescriptor& _rCompDesc )
264 Reference< XController > xFallback;
265 OSL_PRECOND( _rCompDesc.xModel.is(), "lcl_fallbackToAnotherController: illegal call!" );
266 if ( !_rCompDesc.xModel.is() )
267 return false;
269 xFallback.set( _rCompDesc.xModel->getCurrentController() );
270 if ( xFallback == _rCompDesc.xController )
271 // don't accept the very same controller as fallback
272 xFallback.clear();
274 if ( !xFallback.is() )
276 // perhaps XModel2 can be of help here
277 Reference< XModel2 > xModel2( _rCompDesc.xModel, UNO_QUERY );
278 Reference< XEnumeration > xControllerEnum;
279 if ( xModel2.is() )
280 xControllerEnum = xModel2->getControllers();
281 while ( xControllerEnum.is() && xControllerEnum->hasMoreElements() )
283 xFallback.set( xControllerEnum->nextElement(), UNO_QUERY );
284 if ( xFallback == _rCompDesc.xController )
285 xFallback.clear();
289 if ( xFallback.is() )
291 _rCompDesc.xController = xFallback;
292 _rCompDesc.xFrame.set( xFallback->getFrame(), UNO_SET_THROW );
293 return true;
296 return false;
299 //..............................................................................................................
300 bool lcl_closeComponent( const Reference< XCommandProcessor >& _rxCommandProcessor )
302 bool bSuccess = false;
305 Reference< XCommandProcessor > xCommandProcessor( _rxCommandProcessor, UNO_SET_THROW );
306 sal_Int32 nCommandIdentifier = xCommandProcessor->createCommandIdentifier();
308 Command aCommand;
309 aCommand.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "close" ) );
310 xCommandProcessor->execute( aCommand, nCommandIdentifier, NULL );
311 bSuccess = true;
313 catch( const Exception& )
315 DBG_UNHANDLED_EXCEPTION();
317 return bSuccess;
320 //..............................................................................................................
321 bool lcl_closeComponent( const SubComponentDescriptor& _rComponent )
323 if ( _rComponent.xComponentCommandProcessor.is() )
324 return lcl_closeComponent( _rComponent.xComponentCommandProcessor );
326 Reference< XController > xController( _rComponent.xController );
327 OSL_ENSURE( xController.is(), "lcl_closeComponent: invalid controller!" );
329 // suspend the controller in the document
330 if ( xController.is() )
331 if ( !xController->suspend( sal_True ) )
332 return false;
334 bool bSuccess = false;
337 Reference< XCloseable > xCloseable( _rComponent.xFrame, UNO_QUERY_THROW );
338 xCloseable->close( sal_True );
339 bSuccess = true;
341 catch( const Exception& )
343 DBG_UNHANDLED_EXCEPTION();
345 return bSuccess;
348 //..............................................................................................................
349 void lcl_notifySubComponentEvent( const SubComponentManager_Data& _rData, const sal_Char* _pAsciiEventName,
350 const SubComponentDescriptor& _rComponent )
354 Reference< XDocumentEventBroadcaster > xBroadcaster( _rData.m_rController.getModel(), UNO_QUERY_THROW );
355 xBroadcaster->notifyDocumentEvent(
356 ::rtl::OUString::createFromAscii( _pAsciiEventName ),
357 &_rData.m_rController,
358 makeAny( _rComponent.xFrame )
361 catch( const Exception& )
363 DBG_UNHANDLED_EXCEPTION();
368 //------------------------------------------------------------------------------------------------------------------
369 void SAL_CALL SubComponentManager::propertyChange( const PropertyChangeEvent& i_rEvent ) throw (RuntimeException)
371 if ( i_rEvent.PropertyName != PROPERTY_NAME )
372 // by definition, it's allowed to broadcast more than what we've registered for
373 return;
375 // find the sub component whose name changed
376 for ( SubComponents::iterator comp = m_pData->m_aComponents.begin();
377 comp != m_pData->m_aComponents.end();
378 ++comp
381 if ( comp->xDocumentDefinitionProperties != i_rEvent.Source )
382 continue;
384 ::rtl::OUString sNewName;
385 OSL_VERIFY( i_rEvent.NewValue >>= sNewName );
387 #if OSL_DEBUG_LEVEL > 0
388 ::rtl::OUString sOldKnownName( comp->sName );
389 ::rtl::OUString sOldName;
390 OSL_VERIFY( i_rEvent.OldValue >>= sOldName );
391 OSL_ENSURE( sOldName == sOldKnownName, "SubComponentManager::propertyChange: inconsistency in the old names!" );
392 #endif
394 comp->sName = sNewName;
395 break;
399 //------------------------------------------------------------------------------------------------------------------
400 void SAL_CALL SubComponentManager::disposing( const EventObject& _rSource ) throw (RuntimeException)
402 ::osl::ClearableMutexGuard aGuard( m_pData->getMutex() );
404 SubComponentDescriptor aClosedComponent;
406 for ( SubComponents::iterator comp = m_pData->m_aComponents.begin();
407 comp != m_pData->m_aComponents.end();
408 ++comp
411 bool bRemove = false;
413 if ( comp->xController == _rSource.Source )
415 if ( !comp->xModel.is() )
417 bRemove = true;
419 else
421 // maybe this is just one view to the sub document, and only this view is closed
422 if ( !lcl_fallbackToAnotherController( *comp ) )
424 bRemove = true;
428 else if ( comp->xModel == _rSource.Source )
430 bRemove = true;
433 if ( bRemove )
435 aClosedComponent = *comp;
436 m_pData->m_aComponents.erase( comp );
437 break;
441 if ( aClosedComponent.is() )
443 aGuard.clear();
444 lcl_notifySubComponentEvent( *m_pData, "OnSubComponentClosed", aClosedComponent );
448 //------------------------------------------------------------------------------------------------------------------
449 Sequence< Reference< XComponent> > SubComponentManager::getSubComponents() const
451 ::osl::MutexGuard aGuard( m_pData->getMutex() );
453 Sequence< Reference< XComponent > > aComponents( m_pData->m_aComponents.size() );
454 ::std::transform(
455 m_pData->m_aComponents.begin(),
456 m_pData->m_aComponents.end(),
457 aComponents.getArray(),
458 SelectSubComponent()
460 return aComponents;
463 //------------------------------------------------------------------------------------------------------------------
464 sal_Bool SubComponentManager::closeSubComponents()
466 SolarMutexGuard aSolarGuard;
467 ::osl::MutexGuard aGuard( m_pData->getMutex() );
471 SubComponents aWorkingCopy( m_pData->m_aComponents );
472 for ( SubComponents::const_iterator comp = aWorkingCopy.begin();
473 comp != aWorkingCopy.end();
474 ++comp
477 lcl_closeComponent( *comp );
480 catch ( const Exception& )
482 DBG_UNHANDLED_EXCEPTION();
485 return empty();
488 //------------------------------------------------------------------------------------------------------------------
489 bool SubComponentManager::empty() const
491 ::osl::MutexGuard aGuard( m_pData->getMutex() );
492 return m_pData->m_aComponents.empty();
495 //------------------------------------------------------------------------------------------------------------------
496 void SubComponentManager::onSubComponentOpened( const ::rtl::OUString& _rName, const sal_Int32 _nComponentType,
497 const ElementOpenMode _eOpenMode, const Reference< XComponent >& _rxComponent )
499 ::osl::ClearableMutexGuard aGuard( m_pData->getMutex() );
501 #if OSL_DEBUG_LEVEL > 0
502 if ( !_rName.isEmpty() )
504 // check there does not already exist such a component
505 SubComponents::const_iterator existentPos = ::std::find_if(
506 m_pData->m_aComponents.begin(),
507 m_pData->m_aComponents.end(),
508 SubComponentMatch( _rName, _nComponentType, _eOpenMode )
510 OSL_ENSURE( existentPos == m_pData->m_aComponents.end(), "already existent!" );
512 #endif
513 SubComponentDescriptor aElement( _rName, _nComponentType, _eOpenMode, _rxComponent );
514 ENSURE_OR_THROW( aElement.xModel.is() || aElement.xController.is(), "illegal component" );
516 m_pData->m_aComponents.push_back( aElement );
518 // add as listener
519 if ( aElement.xController.is() )
520 aElement.xController->addEventListener( this );
521 if ( aElement.xModel.is() )
522 aElement.xModel->addEventListener( this );
523 if ( aElement.xDocumentDefinitionProperties.is() )
524 aElement.xDocumentDefinitionProperties->addPropertyChangeListener( PROPERTY_NAME, this );
526 // notify this to interested parties
527 aGuard.clear();
528 lcl_notifySubComponentEvent( *m_pData, "OnSubComponentOpened", aElement );
531 //------------------------------------------------------------------------------------------------------------------
532 bool SubComponentManager::activateSubFrame( const ::rtl::OUString& _rName, const sal_Int32 _nComponentType,
533 const ElementOpenMode _eOpenMode, Reference< XComponent >& o_rComponent ) const
535 ::osl::MutexGuard aGuard( m_pData->getMutex() );
537 SubComponents::const_iterator pos = ::std::find_if(
538 m_pData->m_aComponents.begin(),
539 m_pData->m_aComponents.end(),
540 SubComponentMatch( _rName, _nComponentType, _eOpenMode )
542 if ( pos == m_pData->m_aComponents.end() )
543 // no component with this name/type/open mode
544 return false;
546 const Reference< XFrame > xFrame( pos->xFrame, UNO_SET_THROW );
547 const Reference< XTopWindow > xTopWindow( xFrame->getContainerWindow(), UNO_QUERY_THROW );
548 xTopWindow->toFront();
550 if ( pos->xModel.is() )
551 o_rComponent = pos->xModel.get();
552 else if ( pos->xController.is() )
553 o_rComponent = pos->xController.get();
554 else
555 o_rComponent = pos->xFrame.get();
557 return true;
560 //------------------------------------------------------------------------------------------------------------------
561 bool SubComponentManager::closeSubFrames( const ::rtl::OUString& i_rName, const sal_Int32 _nComponentType )
563 ::osl::MutexGuard aGuard( m_pData->getMutex() );
564 ENSURE_OR_RETURN_FALSE( !i_rName.isEmpty(), "SubComponentManager::closeSubFrames: illegal name!" );
566 SubComponents aWorkingCopy( m_pData->m_aComponents );
567 for ( SubComponents::const_iterator comp = aWorkingCopy.begin();
568 comp != aWorkingCopy.end();
569 ++comp
572 if ( ( comp->sName != i_rName ) || ( comp->nComponentType != _nComponentType ) )
573 continue;
575 if ( !lcl_closeComponent( *comp ) )
576 return false;
579 return true;
582 //------------------------------------------------------------------------------------------------------------------
583 bool SubComponentManager::lookupSubComponent( const Reference< XComponent >& i_rComponent,
584 ::rtl::OUString& o_rName, sal_Int32& o_rComponentType )
586 for ( SubComponents::const_iterator comp = m_pData->m_aComponents.begin();
587 comp != m_pData->m_aComponents.end();
588 ++comp
591 if ( ( comp->xModel.is()
592 && ( comp->xModel == i_rComponent )
594 || ( comp->xController.is()
595 && ( comp->xController == i_rComponent )
597 || ( comp->xFrame.is()
598 && ( comp->xFrame == i_rComponent )
602 o_rName = comp->sName;
603 o_rComponentType = comp->nComponentType;
604 return true;
607 return false;
610 //......................................................................................................................
611 } // namespace dbaui
612 //......................................................................................................................
614 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */