sw: fix SolarMutex asserts from SwXCellRange dtor
Happened when loading a report from the attachment of tdf#97033,
but that bug is apparently about a different crash.
Deploy the sw::UnoImplPtr, which is clearly the best way to avoid such
problems. Also another silly weak pointer this, for tdf#72695.
Change-Id: Ice8db95ca3eecc638bd4a4ef7fa8967d180bd525
diff --git a/sw/inc/unotbl.hxx b/sw/inc/unotbl.hxx
index f79598e..ef5c42b 100644
--- a/sw/inc/unotbl.hxx
+++ b/sw/inc/unotbl.hxx
@@ -33,7 +33,6 @@
#include <com/sun/star/table/XAutoFormattable.hpp>
#include <cppuhelper/implbase.hxx>
#include <comphelper/interfacecontainer2.hxx>
#include <comphelper/uno3.hxx>
@@ -447,28 +446,31 @@ class SwXCellRange : public cppu::WeakImplHelper
css::chart::XChartDataArray,
css::util::XSortable,
css::sheet::XCellRangeData
>,
public SwClient
>
{
::osl::Mutex m_Mutex;
::comphelper::OInterfaceContainerHelper2 m_ChartListeners;
private:
class Impl;
::sw::UnoImplPtr<Impl> m_pImpl;
SwRangeDescriptor aRgDesc;
const SfxItemPropertySet* m_pPropSet;
sw::UnoCursorPointer m_pTableCursor;
bool m_bFirstRowAsLabel;
bool m_bFirstColumnAsLabel;
std::tuple<sal_uInt32, sal_uInt32, sal_uInt32, sal_uInt32> getLabelCoordinates(bool bRow);
css::uno::Sequence<OUString> getLabelDescriptions(bool bRow);
void setLabelDescriptions(const css::uno::Sequence<OUString>& rDesc, bool bRow);
public:
SwXCellRange(sw::UnoCursorPointer pCursor, SwFrameFormat& rFrameFormat, SwRangeDescriptor& rDesc);
virtual ~SwXCellRange();
public:
static ::rtl::Reference<SwXCellRange> CreateXCellRange(
sw::UnoCursorPointer pCursor, SwFrameFormat& rFrameFormat,
SwRangeDescriptor& rDesc);
void SetLabels(bool bFirstRowAsLabel, bool bFirstColumnAsLabel)
{ m_bFirstRowAsLabel = bFirstRowAsLabel, m_bFirstColumnAsLabel = bFirstColumnAsLabel; }
virtual ~SwXCellRange() {};
std::vector< css::uno::Reference< css::table::XCell > > GetCells();
@@ -533,10 +535,6 @@ public:
virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw( css::uno::RuntimeException, std::exception ) override;
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() throw( css::uno::RuntimeException, std::exception ) override;
//SwClient
virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew) override;
SwFrameFormat* GetFrameFormat() const { return const_cast<SwFrameFormat*>(static_cast<const SwFrameFormat*>(GetRegisteredIn())); }
sal_uInt16 getRowCount();
sal_uInt16 getColumnCount();
diff --git a/sw/source/core/unocore/unochart.cxx b/sw/source/core/unocore/unochart.cxx
index a22b4da..bb13239 100644
--- a/sw/source/core/unocore/unochart.cxx
+++ b/sw/source/core/unocore/unochart.cxx
@@ -2146,7 +2146,7 @@ std::vector< css::uno::Reference< css::table::XCell > > SwChartDataSequence::Get
SwRangeDescriptor aDesc;
if(!FillRangeDescriptor(aDesc, GetCellRangeName(*pTableFormat, *m_pTableCursor)))
return std::vector< css::uno::Reference< css::table::XCell > >();
return SwXCellRange(m_pTableCursor, *pTableFormat, aDesc).GetCells();
return SwXCellRange::CreateXCellRange(m_pTableCursor, *pTableFormat, aDesc)->GetCells();
}
uno::Sequence< OUString > SAL_CALL SwChartDataSequence::getTextualData()
diff --git a/sw/source/core/unocore/unotbl.cxx b/sw/source/core/unocore/unotbl.cxx
index e20b35b..29d1b14 100644
--- a/sw/source/core/unocore/unotbl.cxx
+++ b/sw/source/core/unocore/unotbl.cxx
@@ -99,6 +99,7 @@
#include <rtl/math.hxx>
#include <editeng/frmdiritem.hxx>
#include <calbck.hxx>
#include <comphelper/interfacecontainer2.hxx>
#include <comphelper/servicehelper.hxx>
#include <comphelper/string.hxx>
#include <cppuhelper/supportsservice.hxx>
@@ -151,14 +152,14 @@ static void lcl_SendChartEvent(::cppu::OWeakObject & rSource,
& chart::XChartDataChangeEventListener::chartDataChanged, event);
}
static void lcl_SendChartEvent(::cppu::OWeakObject & rSource,
static void lcl_SendChartEvent(uno::Reference<uno::XInterface> const& xSource,
::comphelper::OInterfaceContainerHelper2 & rListeners)
{
if (!rListeners.getLength())
return;
//TODO: find appropriate settings of the Event
chart::ChartDataChangeEvent event;
event.Source = & rSource;
event.Source = xSource;
event.Type = chart::ChartDataChangeType_ALL;
event.StartColumn = 0;
event.EndColumn = 1;
@@ -169,6 +170,12 @@ static void lcl_SendChartEvent(::cppu::OWeakObject & rSource,
}
static void lcl_SendChartEvent(::cppu::OWeakObject & rSource,
::comphelper::OInterfaceContainerHelper2 & rListeners)
{
return lcl_SendChartEvent(&rSource, rListeners);
}
static void lcl_SendChartEvent(::cppu::OWeakObject & rSource,
::cppu::OMultiTypeInterfaceContainerHelper & rListeners)
{
::cppu::OInterfaceContainerHelper *const pContainer(rListeners.getContainer(
@@ -2255,7 +2262,7 @@ uno::Reference<table::XCellRange> SwXTextTable::GetRangeByName(SwFrameFormat* p
UnoActionRemoveContext aRemoveContext(*pCursor);
pCursor->MakeBoxSels();
// pUnoCursor will be provided and will not be deleted
return new SwXCellRange(pUnoCursor, *pFormat, rDesc);
return SwXCellRange::CreateXCellRange(pUnoCursor, *pFormat, rDesc).get();
}
uno::Reference<table::XCellRange> SwXTextTable::getCellRangeByPosition(sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom)
@@ -3137,6 +3144,36 @@ uno::Sequence<OUString> SwXTextTable::getSupportedServiceNames() throw(uno::Runt
"com.sun.star.text.TextSortable" };
}
class SwXCellRange::Impl
: public SwClient
{
private:
::osl::Mutex m_Mutex; // just for OInterfaceContainerHelper2
public:
uno::WeakReference<uno::XInterface> m_wThis;
::comphelper::OInterfaceContainerHelper2 m_ChartListeners;
sw::UnoCursorPointer m_pTableCursor;
Impl(sw::UnoCursorPointer const pCursor, SwFrameFormat& rFrameFormat)
: SwClient(&rFrameFormat)
, m_ChartListeners(m_Mutex)
, m_pTableCursor(pCursor)
{
}
SwFrameFormat* GetFrameFormat()
{
return static_cast<SwFrameFormat*>(GetRegisteredIn());
}
// SwClient
virtual void Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew) override;
};
namespace
{
class theSwXCellRangeUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSwXCellRangeUnoTunnelId > {};
@@ -3180,20 +3217,33 @@ uno::Sequence<OUString> SwXCellRange::getSupportedServiceNames() throw( uno::Run
SwXCellRange::SwXCellRange(sw::UnoCursorPointer pCursor, SwFrameFormat& rFrameFormat,
SwRangeDescriptor& rDesc)
: SwClient(&rFrameFormat)
, m_ChartListeners(m_Mutex)
: m_pImpl(new Impl(pCursor, rFrameFormat))
, aRgDesc(rDesc)
, m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TABLE_RANGE))
, m_pTableCursor(pCursor)
, m_bFirstRowAsLabel(false)
, m_bFirstColumnAsLabel(false)
{
aRgDesc.Normalize();
}
SwXCellRange::~SwXCellRange()
{
}
rtl::Reference<SwXCellRange> SwXCellRange::CreateXCellRange(
sw::UnoCursorPointer const pCursor, SwFrameFormat& rFrameFormat,
SwRangeDescriptor& rDesc)
{
SwXCellRange *const pCellRange(new SwXCellRange(pCursor, rFrameFormat, rDesc));
uno::Reference<table::XCellRange> xCellRange(pCellRange);
// need a permanent Reference to initialize m_wThis
pCellRange->m_pImpl->m_wThis = xCellRange;
return pCellRange;
}
std::vector< uno::Reference< table::XCell > > SwXCellRange::GetCells()
{
SwFrameFormat* const pFormat = GetFrameFormat();
SwFrameFormat *const pFormat = m_pImpl->GetFrameFormat();
const sal_Int32 nRowCount(getRowCount());
const sal_Int32 nColCount(getColumnCount());
std::vector< uno::Reference< table::XCell > > vResult;
@@ -3209,7 +3259,7 @@ uno::Reference< table::XCell > SwXCellRange::getCellByPosition(sal_Int32 nColum
{
SolarMutexGuard aGuard;
uno::Reference< table::XCell > aRet;
SwFrameFormat* pFormat = GetFrameFormat();
SwFrameFormat *const pFormat = m_pImpl->GetFrameFormat();
if(pFormat)
{
if(nColumn >= 0 && nRow >= 0 &&
@@ -3233,7 +3283,7 @@ uno::Reference< table::XCellRange > SwXCellRange::getCellRangeByPosition(
{
SolarMutexGuard aGuard;
uno::Reference< table::XCellRange > aRet;
SwFrameFormat* pFormat = GetFrameFormat();
SwFrameFormat *const pFormat = m_pImpl->GetFrameFormat();
if(pFormat && getColumnCount() > nRight && getRowCount() > nBottom &&
nLeft <= nRight && nTop <= nBottom
&& nLeft >= 0 && nRight >= 0 && nTop >= 0 && nBottom >= 0 )
@@ -3269,8 +3319,7 @@ uno::Reference< table::XCellRange > SwXCellRange::getCellRangeByPosition(
UnoActionRemoveContext aRemoveContext(*pCursor);
pCursor->MakeBoxSels();
// pUnoCursor will be provided and will not be deleted
SwXCellRange* pCellRange = new SwXCellRange(pUnoCursor, *pFormat, aNewDesc);
aRet = pCellRange;
aRet = SwXCellRange::CreateXCellRange(pUnoCursor, *pFormat, aNewDesc).get();
}
}
}
@@ -3313,7 +3362,7 @@ void SwXCellRange::setPropertyValue(const OUString& rPropertyName, const uno::An
std::exception)
{
SolarMutexGuard aGuard;
SwFrameFormat* pFormat = GetFrameFormat();
SwFrameFormat *const pFormat = m_pImpl->GetFrameFormat();
if(pFormat)
{
const SfxItemPropertySimpleEntry* pEntry =
@@ -3323,8 +3372,8 @@ void SwXCellRange::setPropertyValue(const OUString& rPropertyName, const uno::An
if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
throw beans::PropertyVetoException("Property is read-only: " + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
SwDoc* pDoc = m_pTableCursor->GetDoc();
SwUnoTableCursor& rCursor = dynamic_cast<SwUnoTableCursor&>(*m_pTableCursor);
SwDoc *const pDoc = m_pImpl->m_pTableCursor->GetDoc();
SwUnoTableCursor& rCursor = dynamic_cast<SwUnoTableCursor&>(*m_pImpl->m_pTableCursor);
{
// HACK: remove pending actions for selecting old style tables
UnoActionRemoveContext aRemoveContext(rCursor);
@@ -3335,9 +3384,9 @@ void SwXCellRange::setPropertyValue(const OUString& rPropertyName, const uno::An
case FN_UNO_TABLE_CELL_BACKGROUND:
{
SvxBrushItem aBrush( RES_BACKGROUND );
SwDoc::GetBoxAttr( *m_pTableCursor, aBrush );
SwDoc::GetBoxAttr(*m_pImpl->m_pTableCursor, aBrush);
((SfxPoolItem&)aBrush).PutValue(aValue, pEntry->nMemberId);
pDoc->SetBoxAttr( *m_pTableCursor, aBrush );
pDoc->SetBoxAttr(*m_pImpl->m_pTableCursor, aBrush);
}
break;
@@ -3372,7 +3421,7 @@ void SwXCellRange::setPropertyValue(const OUString& rPropertyName, const uno::An
SvxBoxItem aBoxItem(static_cast<const SvxBoxItem&>(aSet.Get(RES_BOX)));
((SfxPoolItem&)aBoxItem).PutValue(aValue, pEntry->nMemberId);
aSet.Put(aBoxItem);
pDoc->SetTabBorders( *m_pTableCursor, aSet );
pDoc->SetTabBorders(*m_pImpl->m_pTableCursor, aSet);
}
break;
case RES_BOXATR_FORMAT:
@@ -3387,7 +3436,7 @@ void SwXCellRange::setPropertyValue(const OUString& rPropertyName, const uno::An
bool bTmp = *static_cast<sal_Bool const *>(aValue.getValue());
if(m_bFirstRowAsLabel != bTmp)
{
lcl_SendChartEvent(*this, m_ChartListeners);
lcl_SendChartEvent(*this, m_pImpl->m_ChartListeners);
m_bFirstRowAsLabel = bTmp;
}
}
@@ -3397,7 +3446,7 @@ void SwXCellRange::setPropertyValue(const OUString& rPropertyName, const uno::An
bool bTmp = *static_cast<sal_Bool const *>(aValue.getValue());
if(m_bFirstColumnAsLabel != bTmp)
{
lcl_SendChartEvent(*this, m_ChartListeners);
lcl_SendChartEvent(*this, m_pImpl->m_ChartListeners);
m_bFirstColumnAsLabel = bTmp;
}
}
@@ -3439,7 +3488,7 @@ uno::Any SwXCellRange::getPropertyValue(const OUString& rPropertyName)
{
SolarMutexGuard aGuard;
uno::Any aRet;
SwFrameFormat* pFormat = GetFrameFormat();
SwFrameFormat *const pFormat = m_pImpl->GetFrameFormat();
if(pFormat)
{
const SfxItemPropertySimpleEntry* pEntry =
@@ -3451,20 +3500,20 @@ uno::Any SwXCellRange::getPropertyValue(const OUString& rPropertyName)
case FN_UNO_TABLE_CELL_BACKGROUND:
{
SvxBrushItem aBrush( RES_BACKGROUND );
if(SwDoc::GetBoxAttr( *m_pTableCursor, aBrush ))
if (SwDoc::GetBoxAttr(*m_pImpl->m_pTableCursor, aBrush))
aBrush.QueryValue(aRet, pEntry->nMemberId);
}
break;
case RES_BOX :
{
SwDoc* pDoc = m_pTableCursor->GetDoc();
SwDoc *const pDoc = m_pImpl->m_pTableCursor->GetDoc();
SfxItemSet aSet(pDoc->GetAttrPool(),
RES_BOX, RES_BOX,
SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER,
0);
aSet.Put(SvxBoxInfoItem( SID_ATTR_BORDER_INNER ));
SwDoc::GetTabBorders(*m_pTableCursor, aSet);
SwDoc::GetTabBorders(*m_pImpl->m_pTableCursor, aSet);
const SvxBoxItem& rBoxItem = static_cast<const SvxBoxItem&>(aSet.Get(RES_BOX));
rBoxItem.QueryValue(aRet, pEntry->nMemberId);
}
@@ -3475,7 +3524,7 @@ uno::Any SwXCellRange::getPropertyValue(const OUString& rPropertyName)
case FN_UNO_PARA_STYLE:
{
SwFormatColl *const pTmpFormat =
SwUnoCursorHelper::GetCurTextFormatColl(*m_pTableCursor, false);
SwUnoCursorHelper::GetCurTextFormatColl(*m_pImpl->m_pTableCursor, false);
OUString sRet;
if(pFormat)
sRet = pTmpFormat->GetName();
@@ -3491,7 +3540,7 @@ uno::Any SwXCellRange::getPropertyValue(const OUString& rPropertyName)
case RES_VERT_ORIENT:
{
SwFormatVertOrient aVertOrient;
if( SwDoc::GetBoxAttr( *m_pTableCursor, aVertOrient ) )
if (SwDoc::GetBoxAttr(*m_pImpl->m_pTableCursor, aVertOrient))
{
aVertOrient.QueryValue( aRet, pEntry->nMemberId );
}
@@ -3499,13 +3548,14 @@ uno::Any SwXCellRange::getPropertyValue(const OUString& rPropertyName)
break;
default:
{
SfxItemSet aSet(m_pTableCursor->GetDoc()->GetAttrPool(),
SfxItemSet aSet(m_pImpl->m_pTableCursor->GetDoc()->GetAttrPool(),
RES_CHRATR_BEGIN, RES_FRMATR_END -1,
RES_TXTATR_UNKNOWN_CONTAINER, RES_TXTATR_UNKNOWN_CONTAINER,
RES_UNKNOWNATR_CONTAINER, RES_UNKNOWNATR_CONTAINER,
0L);
// first look at the attributes of the cursor
SwUnoTableCursor* pCursor = dynamic_cast<SwUnoTableCursor*>(&(*m_pTableCursor));
SwUnoTableCursor *const pCursor =
dynamic_cast<SwUnoTableCursor*>(&(*m_pImpl->m_pTableCursor));
SwUnoCursorHelper::GetCursorAttr(pCursor->GetSelRing(), aSet);
m_pPropSet->getPropertyValue(*pEntry, aSet, aRet);
}
@@ -3538,7 +3588,7 @@ uno::Sequence< uno::Sequence< uno::Any > > SAL_CALL SwXCellRange::getDataArray()
const sal_Int32 nColCount = getColumnCount();
if(!nRowCount || !nColCount)
throw uno::RuntimeException("Table too complex", static_cast<cppu::OWeakObject*>(this));
lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject*>(this));
lcl_EnsureCoreConnected(m_pImpl->GetFrameFormat(), static_cast<cppu::OWeakObject*>(this));
uno::Sequence< uno::Sequence< uno::Any > > aRowSeq(nRowCount);
auto vCells(GetCells());
auto pCurrentCell(vCells.begin());
@@ -3565,7 +3615,7 @@ void SAL_CALL SwXCellRange::setDataArray(const uno::Sequence< uno::Sequence< uno
const sal_Int32 nColCount = getColumnCount();
if(!nRowCount || !nColCount)
throw uno::RuntimeException("Table too complex", static_cast<cppu::OWeakObject*>(this));
SwFrameFormat* pFormat = GetFrameFormat();
SwFrameFormat *const pFormat = m_pImpl->GetFrameFormat();
if(!pFormat)
return;
if(rArray.getLength() != nRowCount)
@@ -3634,7 +3684,7 @@ void SwXCellRange::setData(const uno::Sequence< uno::Sequence< double > >& rData
nColCount-1, nRowCount-1), uno::UNO_QUERY);
return xDataRange->setData(rData);
}
lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject*>(this));
lcl_EnsureCoreConnected(m_pImpl->GetFrameFormat(), static_cast<cppu::OWeakObject*>(this));
if(rData.getLength() != nRowCount)
throw uno::RuntimeException("Row count mismatch. expected: " + OUString::number(nRowCount) + " got: " + OUString::number(rData.getLength()), static_cast<cppu::OWeakObject*>(this));
auto vCells(GetCells());
@@ -3675,7 +3725,7 @@ uno::Sequence<OUString> SwXCellRange::getLabelDescriptions(bool bRow)
std::tie(nLeft, nTop, nRight, nBottom) = getLabelCoordinates(bRow);
if(!nRight && !nBottom)
throw uno::RuntimeException("Table too complex", static_cast<cppu::OWeakObject*>(this));
lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject*>(this));
lcl_EnsureCoreConnected(m_pImpl->GetFrameFormat(), static_cast<cppu::OWeakObject*>(this));
if(!(bRow ? m_bFirstColumnAsLabel : m_bFirstRowAsLabel))
return {}; // without labels we have no descriptions
auto xLabelRange(getCellRangeByPosition(nLeft, nTop, nRight, nBottom));
@@ -3697,7 +3747,7 @@ uno::Sequence<OUString> SwXCellRange::getColumnDescriptions()
void SwXCellRange::setLabelDescriptions(const uno::Sequence<OUString>& rDesc, bool bRow)
{
SolarMutexGuard aGuard;
lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject*>(this));
lcl_EnsureCoreConnected(m_pImpl->GetFrameFormat(), static_cast<cppu::OWeakObject*>(this));
if(!(bRow ? m_bFirstColumnAsLabel : m_bFirstRowAsLabel))
return; // if there are no labels we cannot set descriptions
sal_uInt32 nLeft, nTop, nRight, nBottom;
@@ -3725,7 +3775,7 @@ void SAL_CALL SwXCellRange::addChartDataChangeEventListener(
throw (uno::RuntimeException, std::exception)
{
// no need to lock here as m_pImpl is const and container threadsafe
m_ChartListeners.addInterface(xListener);
m_pImpl->m_ChartListeners.addInterface(xListener);
}
void SAL_CALL SwXCellRange::removeChartDataChangeEventListener(
@@ -3733,7 +3783,7 @@ void SAL_CALL SwXCellRange::removeChartDataChangeEventListener(
throw (uno::RuntimeException, std::exception)
{
// no need to lock here as m_pImpl is const and container threadsafe
m_ChartListeners.removeInterface(xListener);
m_pImpl->m_ChartListeners.removeInterface(xListener);
}
sal_Bool SwXCellRange::isNotANumber(double /*fNumber*/) throw( uno::RuntimeException, std::exception )
@@ -3754,10 +3804,10 @@ void SAL_CALL SwXCellRange::sort(const uno::Sequence< beans::PropertyValue >& rD
{
SolarMutexGuard aGuard;
SwSortOptions aSortOpt;
SwFrameFormat* pFormat(GetFrameFormat());
SwFrameFormat *const pFormat = m_pImpl->GetFrameFormat();
if(pFormat && SwUnoCursorHelper::ConvertSortProperties(rDescriptor, aSortOpt))
{
SwUnoTableCursor& rTableCursor = dynamic_cast<SwUnoTableCursor&>(*m_pTableCursor);
SwUnoTableCursor& rTableCursor = dynamic_cast<SwUnoTableCursor&>(*m_pImpl->m_pTableCursor);
rTableCursor.MakeBoxSels();
UnoActionContext aContext(pFormat->GetDoc());
pFormat->GetDoc()->SortTable(rTableCursor.GetSelectedBoxes(), aSortOpt);
@@ -3772,22 +3822,28 @@ sal_uInt16 SwXCellRange::getRowCount()
const SwUnoCursor* SwXCellRange::GetTableCursor() const
{
SwFrameFormat* pFormat = GetFrameFormat();
return pFormat ? &(*m_pTableCursor) : nullptr;
SwFrameFormat *const pFormat = m_pImpl->GetFrameFormat();
return pFormat ? &(*m_pImpl->m_pTableCursor) : nullptr;
}
void SwXCellRange::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
void SwXCellRange::Impl::Modify(
SfxPoolItem const*const pOld, SfxPoolItem const*const pNew)
{
ClientModify(this, pOld, pNew );
ClientModify(this, pOld, pNew);
uno::Reference<uno::XInterface> const xThis(m_wThis);
if (!xThis.is())
{ // fdo#72695: if UNO object is already dead, don't revive it with event
return;
}
if(!GetRegisteredIn() || !m_pTableCursor)
{
m_pTableCursor.reset(nullptr);
lang::EventObject const ev(static_cast< ::cppu::OWeakObject&>(*this));
lang::EventObject const ev(xThis);
m_ChartListeners.disposeAndClear(ev);
}
else
{
lcl_SendChartEvent(*this, m_ChartListeners);
lcl_SendChartEvent(xThis.get(), m_ChartListeners);
}
}