24#include <com/sun/star/frame/XFrame.hpp>
25#include <com/sun/star/frame/XModel.hpp>
26#include <com/sun/star/frame/XModel2.hpp>
27#include <com/sun/star/util/XCloseable.hpp>
28#include <com/sun/star/awt/XTopWindow.hpp>
29#include <com/sun/star/embed/XComponentSupplier.hpp>
30#include <com/sun/star/ucb/XCommandProcessor.hpp>
31#include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
32#include <com/sun/star/beans/XPropertySet.hpp>
38#include <osl/mutex.hxx>
45 using ::com::sun::star::uno::Reference;
46 using ::com::sun::star::uno::UNO_QUERY;
47 using ::com::sun::star::uno::UNO_QUERY_THROW;
48 using ::com::sun::star::uno::UNO_SET_THROW;
49 using ::com::sun::star::uno::Exception;
50 using ::com::sun::star::uno::RuntimeException;
51 using ::com::sun::star::uno::Any;
52 using ::com::sun::star::uno::Sequence;
53 using ::com::sun::star::frame::XFrame;
54 using ::com::sun::star::frame::XController;
55 using ::com::sun::star::frame::XModel;
56 using ::com::sun::star::lang::EventObject;
57 using ::com::sun::star::lang::XComponent;
58 using ::com::sun::star::frame::XModel2;
59 using ::com::sun::star::container::XEnumeration;
60 using ::com::sun::star::util::XCloseable;
61 using ::com::sun::star::awt::XTopWindow;
62 using ::com::sun::star::embed::XComponentSupplier;
63 using ::com::sun::star::ucb::XCommandProcessor;
64 using ::com::sun::star::ucb::Command;
65 using ::com::sun::star::document::XDocumentEventBroadcaster;
66 using ::com::sun::star::beans::XPropertySet;
67 using ::com::sun::star::beans::PropertyChangeEvent;
72 struct SubComponentDescriptor
98 const ElementOpenMode i_eOpenMode,
const Reference< XComponent >& i_rComponent )
103 if ( !impl_constructFrom( i_rComponent ) )
107 Reference< XComponentSupplier > xCompSupp( i_rComponent, UNO_QUERY_THROW );
108 Reference< XComponent > xComponent( xCompSupp->getComponent(), UNO_QUERY_THROW );
109 if ( !impl_constructFrom( xComponent ) )
116 bool is()
const {
return xFrame.is(); }
119 bool impl_constructFrom(
const Reference< XComponent >& _rxComponent )
122 xModel.set( _rxComponent, UNO_QUERY );
140 xFrame.set( _rxComponent, UNO_QUERY );
156 struct SelectSubComponent
158 Reference< XComponent > operator()(
const SubComponentDescriptor &_desc )
const
160 if ( _desc.xModel.is() )
162 OSL_ENSURE( _desc.xController.is(),
"SelectSubComponent::operator(): illegal component!" );
163 return _desc.xController;
167 typedef std::vector< SubComponentDescriptor > SubComponents;
169 struct SubComponentMatch
172 SubComponentMatch( OUString i_sName,
const sal_Int32 i_nComponentType,
180 bool operator()(
const SubComponentDescriptor& i_rCompareWith )
const
182 return (
m_sName == i_rCompareWith.sName )
221 ::osl::MutexGuard aGuard(
m_pData->getMutex() );
222 m_pData->m_aComponents.clear();
230 OSL_PRECOND( _rCompDesc.xModel.is(),
"lcl_fallbackToAnotherController: illegal call!" );
231 if ( !_rCompDesc.xModel.is() )
234 xFallback.set( _rCompDesc.xModel->getCurrentController() );
235 if ( xFallback == _rCompDesc.xController )
239 if ( !xFallback.is() )
245 xControllerEnum = xModel2->getControllers();
246 while ( xControllerEnum.is() && xControllerEnum->hasMoreElements() )
248 xFallback.set( xControllerEnum->nextElement(), UNO_QUERY );
249 if ( xFallback == _rCompDesc.xController )
254 if ( xFallback.is() )
256 _rCompDesc.xController = xFallback;
257 _rCompDesc.xFrame.set( xFallback->getFrame(), UNO_SET_THROW );
264 bool lcl_closeComponent(
const Reference< XCommandProcessor >& _rxCommandProcessor )
266 bool bSuccess =
false;
269 sal_Int32 nCommandIdentifier = _rxCommandProcessor->createCommandIdentifier();
273 _rxCommandProcessor->execute( aCommand, nCommandIdentifier,
nullptr );
276 catch(
const Exception& )
283 bool lcl_closeComponent(
const SubComponentDescriptor& _rComponent )
285 if ( _rComponent.xComponentCommandProcessor.is() )
286 return lcl_closeComponent( _rComponent.xComponentCommandProcessor );
288 Reference< XController >
xController( _rComponent.xController );
289 OSL_ENSURE(
xController.is(),
"lcl_closeComponent: invalid controller!" );
296 bool bSuccess =
false;
299 Reference< XCloseable > xCloseable( _rComponent.xFrame, UNO_QUERY_THROW );
300 xCloseable->close(
true );
303 catch(
const Exception& )
310 void lcl_notifySubComponentEvent(
const SubComponentManager_Data& _rData,
const char* _pAsciiEventName,
311 const SubComponentDescriptor& _rComponent )
316 xBroadcaster->notifyDocumentEvent(
317 OUString::createFromAscii( _pAsciiEventName ),
318 &_rData.m_rController,
319 Any( _rComponent.xFrame )
322 catch(
const Exception& )
336 for (
auto & component :
m_pData->m_aComponents)
338 if ( component.xDocumentDefinitionProperties != i_rEvent.Source )
342 OSL_VERIFY( i_rEvent.NewValue >>= sNewName );
344 #if OSL_DEBUG_LEVEL > 0
345 OUString sOldKnownName( component.sName );
347 OSL_VERIFY( i_rEvent.OldValue >>= sOldName );
348 OSL_ENSURE( sOldName == sOldKnownName,
"SubComponentManager::propertyChange: inconsistency in the old names!" );
351 component.sName = sNewName;
358 ::osl::ClearableMutexGuard aGuard(
m_pData->getMutex() );
362 for ( SubComponents::iterator comp =
m_pData->m_aComponents.begin();
363 comp !=
m_pData->m_aComponents.end();
367 bool bRemove =
false;
369 if (
comp->xController == _rSource.Source )
371 if ( !
comp->xModel.is() )
378 if ( !lcl_fallbackToAnotherController( *comp ) )
384 else if (
comp->xModel == _rSource.Source )
391 aClosedComponent = *
comp;
392 m_pData->m_aComponents.erase( comp );
397 if ( aClosedComponent.is() )
400 lcl_notifySubComponentEvent( *
m_pData,
"OnSubComponentClosed", aClosedComponent );
406 ::osl::MutexGuard aGuard(
m_pData->getMutex() );
410 m_pData->m_aComponents.begin(),
412 aComponents.getArray(),
421 ::osl::MutexGuard aGuard(
m_pData->getMutex() );
425 SubComponents aWorkingCopy(
m_pData->m_aComponents );
426 for (
auto const& elem : aWorkingCopy)
428 lcl_closeComponent(elem);
441 ::osl::MutexGuard aGuard(
m_pData->getMutex() );
442 return m_pData->m_aComponents.empty();
448 ::osl::ClearableMutexGuard aGuard(
m_pData->getMutex() );
450#if OSL_DEBUG_LEVEL > 0
451 if ( !_rName.isEmpty() )
454 auto subComponentNotExists = std::none_of(
455 m_pData->m_aComponents.begin(),
457 SubComponentMatch( _rName, _nComponentType, _eOpenMode )
459 OSL_ENSURE( subComponentNotExists,
"already existent!" );
463 ENSURE_OR_THROW( aElement.xModel.is() || aElement.xController.is(),
"illegal component" );
465 m_pData->m_aComponents.push_back( aElement );
468 if ( aElement.xController.is() )
469 aElement.xController->addEventListener(
this );
470 if ( aElement.xModel.is() )
471 aElement.xModel->addEventListener(
this );
472 if ( aElement.xDocumentDefinitionProperties.is() )
473 aElement.xDocumentDefinitionProperties->addPropertyChangeListener(
PROPERTY_NAME,
this );
477 lcl_notifySubComponentEvent( *
m_pData,
"OnSubComponentOpened", aElement );
483 ::osl::MutexGuard aGuard(
m_pData->getMutex() );
485 SubComponents::const_iterator
pos = std::find_if(
486 m_pData->m_aComponents.begin(),
488 SubComponentMatch( _rName, _nComponentType, _eOpenMode )
496 xTopWindow->toFront();
498 if (
pos->xModel.is() )
499 o_rComponent =
pos->xModel.get();
500 else if (
pos->xController.is() )
501 o_rComponent =
pos->xController.get();
503 o_rComponent =
pos->xFrame.get();
510 ::osl::MutexGuard aGuard(
m_pData->getMutex() );
513 SubComponents aWorkingCopy(
m_pData->m_aComponents );
514 for (
auto const& elem : aWorkingCopy)
516 if ( ( elem.sName != i_rName ) || ( elem.nComponentType != _nComponentType ) )
519 if ( !lcl_closeComponent(elem) )
527 OUString& o_rName, sal_Int32& o_rComponentType )
529 for (
auto const& component :
m_pData->m_aComponents)
531 if ( ( component.xModel.is()
532 && ( component.xModel == i_rComponent )
534 || ( component.xController.is()
535 && ( component.xController == i_rComponent )
537 || ( component.xFrame.is()
538 && ( component.xFrame == i_rComponent )
542 o_rName = component.sName;
543 o_rComponentType = component.nComponentType;
bool closeSubFrames(std::u16string_view _rName, const sal_Int32 _nComponentType)
closes all frames of the given component
bool lookupSubComponent(const css::uno::Reference< css::lang::XComponent > &i_rComponent, OUString &o_rName, sal_Int32 &o_rComponentType)
searches for the given sub component
void onSubComponentOpened(const OUString &_rName, const sal_Int32 _nComponentType, const ElementOpenMode _eOpenMode, const css::uno::Reference< css::lang::XComponent > &_rxComponent)
bool closeSubComponents()
std::unique_ptr< SubComponentManager_Data > m_pData
virtual ~SubComponentManager() override
bool activateSubFrame(const OUString &_rName, const sal_Int32 _nComponentType, const ElementOpenMode _eOpenMode, css::uno::Reference< css::lang::XComponent > &o_rComponent) const
activates (i.e.
virtual void SAL_CALL propertyChange(const css::beans::PropertyChangeEvent &evt) override
SubComponentManager(OApplicationController &_rController, const ::comphelper::SharedMutex &_rMutex)
css::uno::Sequence< css::uno::Reference< css::lang::XComponent > > getSubComponents() const
ControllerFrame_Data * m_pData
#define ENSURE_OR_RETURN_FALSE(c, m)
#define ENSURE_OR_THROW(c, m)
#define DBG_UNHANDLED_EXCEPTION(...)
constexpr OUStringLiteral PROPERTY_NAME(u"Name")
SubComponents m_aComponents
SubComponentManager_Data(OApplicationController &_rController, ::comphelper::SharedMutex _aMutex)
OApplicationController & m_rController
::osl::Mutex & getMutex() const
mutable::comphelper::SharedMutex m_aMutex
Reference< XController > xController
the controller of the sub component. Must not be <NULL>
const ElementOpenMode m_eOpenMode
sal_Int32 nComponentType
type of the component - an ElementType value, except for relation design
const sal_Int32 m_nComponentType
ElementOpenMode eOpenMode
the mode in which the sub component has been opened
Reference< XPropertySet > xDocumentDefinitionProperties
the document definition which holds the component, if any; as PropertySet
Reference< XFrame > xFrame
the frame which the component resides in. Must not be <NULL>
Reference< XModel > xModel
the model of the sub component. Might be <NULL>
Reference< XCommandProcessor > xComponentCommandProcessor
the document definition which holds the component, if any; as CommandProcessor