19#include <UndoActions.hxx>
27#include <com/sun/star/container/XChild.hpp>
28#include <com/sun/star/beans/theIntrospection.hpp>
29#include <com/sun/star/beans/PropertyAttribute.hpp>
30#include <com/sun/star/util/XModifyBroadcaster.hpp>
31#include <com/sun/star/beans/XIntrospectionAccess.hpp>
32#include <com/sun/star/beans/XIntrospection.hpp>
39#include <osl/mutex.hxx>
41#include <unordered_map>
49 using namespace beans;
52 using namespace container;
53 using namespace report;
61 explicit PropertyInfo(
const bool i_bIsTransientOrReadOnly )
96 ::std::vector< uno::Reference< container::XChild> >
m_aSections;
108 ,m_aFormatNormalizer( _rModel )
129 OSL_ENSURE(
m_refCount,
"Illegal call to dead object!");
130 osl_atomic_increment( &
m_pImpl->m_nLocks );
134 OSL_ENSURE(
m_refCount,
"Illegal call to dead object!");
136 osl_atomic_decrement( &
m_pImpl->m_nLocks );
154 m_pImpl->m_aPropertySetCache.clear();
191 if (rHint.
GetId() == SfxHintId::ModeChanged )
201 if ( xSourceSet.is() )
203 uno::Reference< report::XSection> xSection(xSourceSet,uno::UNO_QUERY);
216 ::osl::ClearableMutexGuard aGuard(
m_pImpl->m_aMutex );
231 PropertySetInfoCache::iterator objectPos =
m_pImpl->m_aPropertySetCache.find(xSet);
232 if (objectPos ==
m_pImpl->m_aPropertySetCache.end())
234 objectPos =
m_pImpl->m_aPropertySetCache.emplace( xSet, ObjectInfo() ).first;
235 DBG_ASSERT(objectPos !=
m_pImpl->m_aPropertySetCache.end(),
"OXUndoEnvironment::propertyChange : just inserted it... why it's not there?");
237 if ( objectPos ==
m_pImpl->m_aPropertySetCache.end() )
242 ObjectInfo& rObjectInfo = objectPos->second;
243 PropertiesInfo::const_iterator aPropertyPos = rObjectInfo.aProperties.find( _rEvent.PropertyName );
244 if ( aPropertyPos == rObjectInfo.aProperties.end() )
248 sal_Int32 nPropertyAttributes = 0;
251 if ( xPSI->hasPropertyByName( _rEvent.PropertyName ) )
253 nPropertyAttributes = xPSI->getPropertyByName( _rEvent.PropertyName ).Attributes;
259 if ( !rObjectInfo.xPropertyIntrospection.is() )
261 if ( !
m_pImpl->m_xIntrospection.is() )
263 m_pImpl->m_xIntrospection = theIntrospection::get(
m_pImpl->m_rModel.getController()->getORB() );
266 m_pImpl->m_xIntrospection->inspect(
Any( _rEvent.Source ) ),
271 if ( rObjectInfo.xPropertyIntrospection.is() )
273 xPSI.set( rObjectInfo.xPropertyIntrospection->getPropertySetInfo(), UNO_SET_THROW );
274 nPropertyAttributes = xPSI->getPropertyByName( _rEvent.PropertyName ).Attributes;
282 const bool bTransReadOnly =
283 ( ( nPropertyAttributes & PropertyAttribute::READONLY ) != 0 )
284 || ( ( nPropertyAttributes & PropertyAttribute::TRANSIENT ) != 0 );
287 aPropertyPos = rObjectInfo.aProperties.emplace(
288 _rEvent.PropertyName,
291 DBG_ASSERT(aPropertyPos != rObjectInfo.aProperties.end(),
"OXUndoEnvironment::propertyChange : just inserted it ... why it's not there ?");
300 if ( aPropertyPos->second.bIsReadonlyOrTransient )
304 m_pImpl->m_aFormatNormalizer.notifyPropertyChange( _rEvent );
305 m_pImpl->m_aConditionUpdater.notifyPropertyChange( _rEvent );
312 std::unique_ptr<ORptUndoPropertyAction> pUndo;
315 uno::Reference< report::XSection> xSection( xSet, uno::UNO_QUERY );
318 uno::Reference< report::XGroup> xGroup = xSection->getGroup();
330 if ( pUndo ==
nullptr )
333 m_pImpl->m_rModel.GetSdrUndoManager()->AddUndoAction( std::move(pUndo) );
334 pController->InvalidateAll();
339 ::std::vector< uno::Reference< container::XChild> >::const_iterator aFind =
m_pImpl->m_aSections.end();
340 if ( _xContainer.is() )
342 aFind = ::std::find(
m_pImpl->m_aSections.begin(),
m_pImpl->m_aSections.end(),_xContainer);
344 if ( aFind ==
m_pImpl->m_aSections.end() )
357 ::osl::MutexGuard aGuard(
m_pImpl->m_aMutex );
364 if ( xReportComponent.is() )
368 ::std::vector< uno::Reference< container::XChild> >::const_iterator aFind =
getSection(xContainer);
370 if ( aFind !=
m_pImpl->m_aSections.end() )
375 OReportPage* pPage =
m_pImpl->m_rModel.getPage(uno::Reference< report::XSection>(*aFind,uno::UNO_QUERY));
376 OSL_ENSURE(pPage,
"No page could be found for section!");
380 catch(uno::Exception&)
389 uno::Reference< report::XFunctions> xContainer(evt.Source,uno::UNO_QUERY);
390 if ( xContainer.is() )
392 m_pImpl->m_rModel.GetSdrUndoManager()->AddUndoAction(
394 xIface, RID_STR_UNDO_ADDFUNCTION ) );
407 m_pImpl->m_rModel.SetModified(
true );
414 ::osl::MutexGuard aGuard(
m_pImpl->m_aMutex );
417 OSL_ENSURE(xIface.is(),
"OXUndoEnvironment::elementReplaced: invalid container notification!");
420 xIface.set(evt.Element,uno::UNO_QUERY);
430 ::osl::MutexGuard aGuard(
m_pImpl->m_aMutex );
436 ::std::vector< uno::Reference< container::XChild> >::const_iterator aFind =
getSection(xContainer);
439 if ( aFind !=
m_pImpl->m_aSections.end() && xReportComponent.is() )
444 OReportPage* pPage =
m_pImpl->m_rModel.getPage(uno::Reference< report::XSection >( *aFind, uno::UNO_QUERY_THROW ) );
445 OSL_ENSURE( pPage,
"OXUndoEnvironment::elementRemoved: no page for the section!" );
449 catch(
const uno::Exception&)
456 uno::Reference< report::XFunctions> xFunctions(evt.Source,uno::UNO_QUERY);
457 if ( xFunctions.is() )
459 m_pImpl->m_rModel.GetSdrUndoManager()->AddUndoAction( std::make_unique<OUndoContainerAction>(
483 uno::Reference<container::XChild> xChild = _xSection;
484 m_pImpl->m_aSections.push_back(xChild);
488 catch(
const uno::Exception&)
497 OUndoEnvLock aLock(*
this);
500 uno::Reference<container::XChild> xChild(_xSection);
502 xChild),
m_pImpl->m_aSections.end());
506 catch(uno::Exception&){}
512 OSL_PRECOND( _rxContainer.is(),
"OXUndoEnvironment::switchListening: invalid container!" );
513 if ( !_rxContainer.is() )
519 Reference< XInterface > xInterface;
520 sal_Int32
nCount = _rxContainer->getCount();
521 for(sal_Int32 i = 0;
i !=
nCount;++
i)
523 xInterface.set(_rxContainer->getByIndex( i ),uno::UNO_QUERY);
524 if ( _bStartListening )
531 Reference< XContainer > xSimpleContainer( _rxContainer, UNO_QUERY );
532 if ( xSimpleContainer.is() )
534 if ( _bStartListening )
535 xSimpleContainer->addContainerListener(
this );
537 xSimpleContainer->removeContainerListener(
this );
540 catch(
const Exception& )
549 OSL_PRECOND( _rxObject.is(),
"OXUndoEnvironment::switchListening: how should I listen at a NULL object?" );
555 Reference< XPropertySet > xProps( _rxObject, UNO_QUERY );
558 if ( _bStartListening )
559 xProps->addPropertyChangeListener( OUString(),
this );
561 xProps->removePropertyChangeListener( OUString(),
this );
565 Reference< XModifyBroadcaster > xBroadcaster( _rxObject, UNO_QUERY );
566 if ( xBroadcaster.is() )
568 if ( _bStartListening )
569 xBroadcaster->addModifyListener(
this );
571 xBroadcaster->removeModifyListener(
this );
574 catch(
const Exception& )
583 m_pImpl->m_aFormatNormalizer.notifyElementInserted( _rxElement );
587 if ( xContainer.is() )
596 uno::Reference<beans::XPropertySet> xProp(_rxElement,uno::UNO_QUERY);
597 if (!
m_pImpl->m_aPropertySetCache.empty())
598 m_pImpl->m_aPropertySetCache.erase(xProp);
602 if ( xContainer.is() )
PropertiesInfo aProperties
Reference< XPropertySet > xPropertyIntrospection
bool bIsReadonlyOrTransient
void StartListening(SfxBroadcaster &rBroadcaster, DuplicateHandling eDuplicateHanding=DuplicateHandling::Unexpected)
bool IsListening(SfxBroadcaster &rBroadcaster) const
void EndListening(SfxBroadcaster &rBroadcaster, bool bRemoveAllDuplicates=false)
static ::std::function< css::uno::Reference< css::report::XSection >(OGroupHelper *)> getMemberFunction(const css::uno::Reference< css::report::XSection > &_xSection)
static ::std::function< css::uno::Reference< css::report::XSection >(OReportHelper *)> getMemberFunction(const css::uno::Reference< css::report::XSection > &_xSection)
void removeSdrObject(const css::uno::Reference< css::report::XReportComponent > &_xObject)
removes the SdrObject which belongs to the report component.
const css::uno::Reference< css::report::XSection > & getSection() const
void insertObject(const css::uno::Reference< css::report::XReportComponent > &_xObject)
insert a new SdrObject which belongs to the report component.
OXUndoEnvironmentImpl(const OXUndoEnvironmentImpl &)=delete
FormatNormalizer m_aFormatNormalizer
oslInterlockedCount m_nLocks
OXUndoEnvironmentImpl & operator=(const OXUndoEnvironmentImpl &)=delete
OXUndoEnvironmentImpl(OReportModel &_rModel)
PropertySetInfoCache m_aPropertySetCache
Reference< XIntrospection > m_xIntrospection
::std::vector< uno::Reference< container::XChild > > m_aSections
ConditionUpdater m_aConditionUpdater
Create an object ob OUndoEnvLock locks the undo possibility As long as in the OUndoEnvLock scope,...
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
void switchListening(const css::uno::Reference< css::container::XIndexAccess > &_rxContainer, bool _bStartListening)
void SetUndoMode(bool _bUndo)
virtual void SAL_CALL propertyChange(const css::beans::PropertyChangeEvent &evt) override
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
void RemoveSection(const css::uno::Reference< css::report::XSection > &_xSection)
OXUndoEnvironment(const OXUndoEnvironment &)=delete
::std::vector< css::uno::Reference< css::container::XChild > >::const_iterator getSection(const css::uno::Reference< css::container::XChild > &_xContainer) const
virtual void SAL_CALL elementInserted(const css::container::ContainerEvent &rEvent) override
void Clear(const Accessor &_r)
virtual void SAL_CALL modified(const css::lang::EventObject &aEvent) override
virtual void SAL_CALL elementRemoved(const css::container::ContainerEvent &rEvent) override
void RemoveElement(const css::uno::Reference< css::uno::XInterface > &Element)
virtual void SAL_CALL elementReplaced(const css::container::ContainerEvent &rEvent) override
const ::std::unique_ptr< OXUndoEnvironmentImpl > m_pImpl
virtual ~OXUndoEnvironment() override
void AddElement(const css::uno::Reference< css::uno::XInterface > &Element)
void AddSection(const css::uno::Reference< css::report::XSection > &_xSection)
#define DBG_ASSERT(sCon, aError)
#define DBG_UNHANDLED_EXCEPTION(...)
Reference< XIntrospection > xIntrospection
constexpr OUStringLiteral first
::std::map< Reference< XPropertySet >, ObjectInfo > PropertySetInfoCache
std::unordered_map< OUString, PropertyInfo > PropertiesInfo
PropertyInfo(OUString const &aName, sal_Int32 nHandle, css::uno::Type const &aType, sal_Int16 nAttributes)