1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <DataSeries.hxx>
21 #include "DataSeriesProperties.hxx"
22 #include "DataPointProperties.hxx"
23 #include <CharacterProperties.hxx>
24 #include <UserDefinedProperties.hxx>
25 #include "DataPoint.hxx"
26 #include <DataSeriesHelper.hxx>
27 #include <CloneHelper.hxx>
28 #include <ModifyListenerHelper.hxx>
29 #include <EventListenerHelper.hxx>
30 #include <com/sun/star/container/NoSuchElementException.hpp>
31 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
32 #include <cppuhelper/supportsservice.hxx>
33 #include <tools/diagnose_ex.h>
37 namespace com
{ namespace sun
{ namespace star
{ namespace uno
{ class XComponentContext
; } } } }
39 using namespace ::com::sun::star
;
41 using ::com::sun::star::beans::Property
;
42 using ::com::sun::star::uno::Sequence
;
43 using ::com::sun::star::uno::Reference
;
44 using ::osl::MutexGuard
;
49 struct StaticDataSeriesDefaults
: public rtl::StaticWithInit
< ::chart::tPropertyValueMap
, StaticDataSeriesDefaults
>
51 ::chart::tPropertyValueMap
operator()()
53 ::chart::tPropertyValueMap aStaticDefaults
;
54 ::chart::DataSeriesProperties::AddDefaultsToMap( aStaticDefaults
);
55 ::chart::CharacterProperties::AddDefaultsToMap( aStaticDefaults
);
56 float fDefaultCharHeight
= 10.0;
57 ::chart::PropertyHelper::setPropertyValue( aStaticDefaults
, ::chart::CharacterProperties::PROP_CHAR_CHAR_HEIGHT
, fDefaultCharHeight
);
58 ::chart::PropertyHelper::setPropertyValue( aStaticDefaults
, ::chart::CharacterProperties::PROP_CHAR_ASIAN_CHAR_HEIGHT
, fDefaultCharHeight
);
59 ::chart::PropertyHelper::setPropertyValue( aStaticDefaults
, ::chart::CharacterProperties::PROP_CHAR_COMPLEX_CHAR_HEIGHT
, fDefaultCharHeight
);
60 return aStaticDefaults
;
64 struct StaticDataSeriesInfoHelper
: public rtl::StaticWithInit
< ::cppu::OPropertyArrayHelper
, StaticDataSeriesInfoHelper
, StaticDataSeriesInfoHelper
, uno::Sequence
< Property
> >
66 uno::Sequence
< Property
> operator()()
68 std::vector
< css::beans::Property
> aProperties
;
69 ::chart::DataSeriesProperties::AddPropertiesToVector( aProperties
);
70 ::chart::CharacterProperties::AddPropertiesToVector( aProperties
);
71 ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties
);
73 std::sort( aProperties
.begin(), aProperties
.end(),
74 ::chart::PropertyNameLess() );
76 return comphelper::containerToSequence( aProperties
);
80 struct StaticDataSeriesInfo
: public rtl::StaticWithInit
< uno::Reference
< beans::XPropertySetInfo
>, StaticDataSeriesInfo
>
82 uno::Reference
< beans::XPropertySetInfo
> operator()()
84 return ::cppu::OPropertySetHelper::createPropertySetInfo(StaticDataSeriesInfoHelper::get() );
89 const uno::Reference
< uno::XInterface
> & xChildInterface
,
90 const uno::Reference
< uno::XInterface
> & xParentInterface
)
92 uno::Reference
< container::XChild
> xChild( xChildInterface
, uno::UNO_QUERY
);
94 xChild
->setParent( xParentInterface
);
97 typedef std::map
< sal_Int32
, css::uno::Reference
< css::beans::XPropertySet
> >
100 void lcl_CloneAttributedDataPoints(
101 const lcl_tDataPointMap
& rSource
, lcl_tDataPointMap
& rDestination
,
102 const uno::Reference
< uno::XInterface
> & xSeries
)
104 for (auto const& elem
: rSource
)
106 Reference
< beans::XPropertySet
> xPoint( elem
.second
);
109 Reference
< util::XCloneable
> xCloneable( xPoint
, uno::UNO_QUERY
);
112 xPoint
.set( xCloneable
->createClone(), uno::UNO_QUERY
);
115 lcl_SetParent( xPoint
, xSeries
);
116 rDestination
.emplace( elem
.first
, xPoint
);
123 } // anonymous namespace
128 DataSeries::DataSeries() :
129 ::property::OPropertySet( m_aMutex
),
130 m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder())
134 DataSeries::DataSeries( const DataSeries
& rOther
) :
135 impl::DataSeries_Base(rOther
),
136 ::property::OPropertySet( rOther
, m_aMutex
),
137 m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder())
139 if( ! rOther
.m_aDataSequences
.empty())
141 CloneHelper::CloneRefVector
<css::chart2::data::XLabeledDataSequence
>(
142 rOther
.m_aDataSequences
, m_aDataSequences
);
143 ModifyListenerHelper::addListenerToAllElements( m_aDataSequences
, m_xModifyEventForwarder
);
146 CloneHelper::CloneRefVector
< chart2::XRegressionCurve
>( rOther
.m_aRegressionCurves
, m_aRegressionCurves
);
147 ModifyListenerHelper::addListenerToAllElements( m_aRegressionCurves
, m_xModifyEventForwarder
);
149 // add as listener to XPropertySet properties
150 Reference
< beans::XPropertySet
> xPropertySet
;
153 getFastPropertyValue( aValue
, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X
);
154 if( ( aValue
>>= xPropertySet
)
155 && xPropertySet
.is())
156 ModifyListenerHelper::addListener( xPropertySet
, m_xModifyEventForwarder
);
158 getFastPropertyValue( aValue
, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y
);
159 if( ( aValue
>>= xPropertySet
)
160 && xPropertySet
.is())
161 ModifyListenerHelper::addListener( xPropertySet
, m_xModifyEventForwarder
);
164 // late initialization to call after copy-constructing
165 void DataSeries::Init( const DataSeries
& rOther
)
167 if( ! rOther
.m_aDataSequences
.empty())
168 EventListenerHelper::addListenerToAllElements( m_aDataSequences
, this );
170 Reference
< uno::XInterface
> xThisInterface( static_cast< ::cppu::OWeakObject
* >( this ));
171 if( ! rOther
.m_aAttributedDataPoints
.empty())
173 lcl_CloneAttributedDataPoints(
174 rOther
.m_aAttributedDataPoints
, m_aAttributedDataPoints
, xThisInterface
);
175 ModifyListenerHelper::addListenerToAllMapElements( m_aAttributedDataPoints
, m_xModifyEventForwarder
);
178 // add as parent to error bars
179 Reference
< beans::XPropertySet
> xPropertySet
;
182 getFastPropertyValue( aValue
, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X
);
183 if( ( aValue
>>= xPropertySet
)
184 && xPropertySet
.is())
185 lcl_SetParent( xPropertySet
, xThisInterface
);
187 getFastPropertyValue( aValue
, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y
);
188 if( ( aValue
>>= xPropertySet
)
189 && xPropertySet
.is())
190 lcl_SetParent( xPropertySet
, xThisInterface
);
193 DataSeries::~DataSeries()
197 ModifyListenerHelper::removeListenerFromAllMapElements( m_aAttributedDataPoints
, m_xModifyEventForwarder
);
198 ModifyListenerHelper::removeListenerFromAllElements( m_aRegressionCurves
, m_xModifyEventForwarder
);
199 ModifyListenerHelper::removeListenerFromAllElements( m_aDataSequences
, m_xModifyEventForwarder
);
201 // remove listener from XPropertySet properties
202 Reference
< beans::XPropertySet
> xPropertySet
;
205 getFastPropertyValue( aValue
, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X
);
206 if( ( aValue
>>= xPropertySet
)
207 && xPropertySet
.is())
208 ModifyListenerHelper::removeListener( xPropertySet
, m_xModifyEventForwarder
);
210 getFastPropertyValue( aValue
, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y
);
211 if( ( aValue
>>= xPropertySet
)
212 && xPropertySet
.is())
213 ModifyListenerHelper::removeListener( xPropertySet
, m_xModifyEventForwarder
);
215 catch( const uno::Exception
& )
217 DBG_UNHANDLED_EXCEPTION("chart2");
221 // ____ XCloneable ____
222 uno::Reference
< util::XCloneable
> SAL_CALL
DataSeries::createClone()
224 DataSeries
* pNewSeries( new DataSeries( *this ));
225 // hold a reference to the clone
226 uno::Reference
< util::XCloneable
> xResult( pNewSeries
);
227 // do initialization that uses uno references to the clone
228 pNewSeries
->Init( *this );
233 // ____ OPropertySet ____
234 uno::Any
DataSeries::GetDefaultValue( sal_Int32 nHandle
) const
236 const tPropertyValueMap
& rStaticDefaults
= StaticDataSeriesDefaults::get();
237 tPropertyValueMap::const_iterator
aFound( rStaticDefaults
.find( nHandle
) );
238 if( aFound
== rStaticDefaults
.end() )
240 return (*aFound
).second
;
243 // ____ OPropertySet ____
244 ::cppu::IPropertyArrayHelper
& SAL_CALL
DataSeries::getInfoHelper()
246 return StaticDataSeriesInfoHelper::get();
249 // ____ XPropertySet ____
250 uno::Reference
< beans::XPropertySetInfo
> SAL_CALL
DataSeries::getPropertySetInfo()
252 return StaticDataSeriesInfo::get();
255 void SAL_CALL
DataSeries::getFastPropertyValue
257 sal_Int32 nHandle
) const
259 // special handling for get. set is not possible for this property
260 if( nHandle
== DataSeriesProperties::PROP_DATASERIES_ATTRIBUTED_DATA_POINTS
)
262 // TODO: only add those property sets that are really modified
264 rValue
<<= comphelper::mapKeysToSequence(m_aAttributedDataPoints
);
267 OPropertySet::getFastPropertyValue( rValue
, nHandle
);
270 void SAL_CALL
DataSeries::setFastPropertyValue_NoBroadcast(
271 sal_Int32 nHandle
, const uno::Any
& rValue
)
273 if( nHandle
== DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y
274 || nHandle
== DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X
)
277 Reference
< util::XModifyBroadcaster
> xBroadcaster
;
278 getFastPropertyValue( aOldValue
, nHandle
);
279 if( aOldValue
.hasValue() &&
280 (aOldValue
>>= xBroadcaster
) &&
283 ModifyListenerHelper::removeListener( xBroadcaster
, m_xModifyEventForwarder
);
286 OSL_ASSERT( rValue
.getValueType().getTypeClass() == uno::TypeClass_INTERFACE
);
287 if( rValue
.hasValue() &&
288 (rValue
>>= xBroadcaster
) &&
291 ModifyListenerHelper::addListener( xBroadcaster
, m_xModifyEventForwarder
);
295 ::property::OPropertySet::setFastPropertyValue_NoBroadcast( nHandle
, rValue
);
298 Reference
< beans::XPropertySet
>
299 SAL_CALL
DataSeries::getDataPointByIndex( sal_Int32 nIndex
)
301 Reference
< beans::XPropertySet
> xResult
;
303 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aSequences
;
305 MutexGuard
aGuard( m_aMutex
);
306 aSequences
= comphelper::containerToSequence( m_aDataSequences
);
309 std::vector
< Reference
< chart2::data::XLabeledDataSequence
> > aValuesSeries(
310 DataSeriesHelper::getAllDataSequencesByRole( aSequences
, "values" ) );
312 if (aValuesSeries
.empty())
313 throw lang::IndexOutOfBoundsException();
315 Reference
< chart2::data::XDataSequence
> xSeq( aValuesSeries
.front()->getValues() );
316 if( 0 <= nIndex
&& nIndex
< xSeq
->getData().getLength() )
319 MutexGuard
aGuard( m_aMutex
);
320 tDataPointAttributeContainer::iterator
aIt( m_aAttributedDataPoints
.find( nIndex
) );
321 if( aIt
!= m_aAttributedDataPoints
.end() )
322 xResult
= (*aIt
).second
;
326 Reference
< beans::XPropertySet
> xParentProperties
;
327 Reference
< util::XModifyListener
> xModifyEventForwarder
;
329 MutexGuard
aGuard( m_aMutex
);
330 xParentProperties
= this;
331 xModifyEventForwarder
= m_xModifyEventForwarder
;
334 // create a new XPropertySet for this data point
335 xResult
.set( new DataPoint( xParentProperties
) );
337 MutexGuard
aGuard( m_aMutex
);
338 m_aAttributedDataPoints
[ nIndex
] = xResult
;
340 ModifyListenerHelper::addListener( xResult
, xModifyEventForwarder
);
347 void SAL_CALL
DataSeries::resetDataPoint( sal_Int32 nIndex
)
349 Reference
< beans::XPropertySet
> xDataPointProp
;
350 Reference
< util::XModifyListener
> xModifyEventForwarder
;
352 MutexGuard
aGuard( m_aMutex
);
353 xModifyEventForwarder
= m_xModifyEventForwarder
;
354 tDataPointAttributeContainer::iterator
aIt( m_aAttributedDataPoints
.find( nIndex
));
355 if( aIt
!= m_aAttributedDataPoints
.end())
357 xDataPointProp
= (*aIt
).second
;
358 m_aAttributedDataPoints
.erase(aIt
);
362 if( xDataPointProp
.is() )
364 Reference
< util::XModifyBroadcaster
> xBroadcaster( xDataPointProp
, uno::UNO_QUERY
);
365 if( xBroadcaster
.is() && xModifyEventForwarder
.is())
366 xBroadcaster
->removeModifyListener( xModifyEventForwarder
);
371 void SAL_CALL
DataSeries::resetAllDataPoints()
373 tDataPointAttributeContainer aOldAttributedDataPoints
;
374 Reference
< util::XModifyListener
> xModifyEventForwarder
;
376 MutexGuard
aGuard( m_aMutex
);
377 xModifyEventForwarder
= m_xModifyEventForwarder
;
378 std::swap( aOldAttributedDataPoints
, m_aAttributedDataPoints
);
380 ModifyListenerHelper::removeListenerFromAllMapElements( aOldAttributedDataPoints
, xModifyEventForwarder
);
381 aOldAttributedDataPoints
.clear();
385 // ____ XDataSink ____
386 void SAL_CALL
DataSeries::setData( const uno::Sequence
< Reference
< chart2::data::XLabeledDataSequence
> >& aData
)
388 tDataSequenceContainer aOldDataSequences
;
389 tDataSequenceContainer aNewDataSequences
;
390 Reference
< util::XModifyListener
> xModifyEventForwarder
;
391 Reference
< lang::XEventListener
> xListener
;
393 MutexGuard
aGuard( m_aMutex
);
394 xModifyEventForwarder
= m_xModifyEventForwarder
;
396 std::swap( aOldDataSequences
, m_aDataSequences
);
397 aNewDataSequences
= comphelper::sequenceToContainer
<tDataSequenceContainer
>( aData
);
398 m_aDataSequences
= aNewDataSequences
;
400 ModifyListenerHelper::removeListenerFromAllElements( aOldDataSequences
, xModifyEventForwarder
);
401 EventListenerHelper::removeListenerFromAllElements( aOldDataSequences
, xListener
);
402 EventListenerHelper::addListenerToAllElements( aNewDataSequences
, xListener
);
403 ModifyListenerHelper::addListenerToAllElements( aNewDataSequences
, xModifyEventForwarder
);
407 // ____ XDataSource ____
408 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > SAL_CALL
DataSeries::getDataSequences()
410 MutexGuard
aGuard( m_aMutex
);
411 return comphelper::containerToSequence( m_aDataSequences
);
414 // ____ XRegressionCurveContainer ____
415 void SAL_CALL
DataSeries::addRegressionCurve(
416 const uno::Reference
< chart2::XRegressionCurve
>& xRegressionCurve
)
418 Reference
< util::XModifyListener
> xModifyEventForwarder
;
420 MutexGuard
aGuard( m_aMutex
);
421 xModifyEventForwarder
= m_xModifyEventForwarder
;
422 if( std::find( m_aRegressionCurves
.begin(), m_aRegressionCurves
.end(), xRegressionCurve
)
423 != m_aRegressionCurves
.end())
424 throw lang::IllegalArgumentException();
425 m_aRegressionCurves
.push_back( xRegressionCurve
);
427 ModifyListenerHelper::addListener( xRegressionCurve
, xModifyEventForwarder
);
431 void SAL_CALL
DataSeries::removeRegressionCurve(
432 const uno::Reference
< chart2::XRegressionCurve
>& xRegressionCurve
)
434 if( !xRegressionCurve
.is() )
435 throw container::NoSuchElementException();
437 Reference
< util::XModifyListener
> xModifyEventForwarder
;
439 MutexGuard
aGuard( m_aMutex
);
440 xModifyEventForwarder
= m_xModifyEventForwarder
;
441 tRegressionCurveContainerType::iterator
aIt(
442 std::find( m_aRegressionCurves
.begin(), m_aRegressionCurves
.end(), xRegressionCurve
) );
443 if( aIt
== m_aRegressionCurves
.end())
444 throw container::NoSuchElementException(
445 "The given regression curve is no element of this series",
446 static_cast< uno::XWeak
* >( this ));
447 m_aRegressionCurves
.erase( aIt
);
450 ModifyListenerHelper::removeListener( xRegressionCurve
, xModifyEventForwarder
);
454 uno::Sequence
< uno::Reference
< chart2::XRegressionCurve
> > SAL_CALL
DataSeries::getRegressionCurves()
456 MutexGuard
aGuard( m_aMutex
);
457 return comphelper::containerToSequence( m_aRegressionCurves
);
460 void SAL_CALL
DataSeries::setRegressionCurves(
461 const Sequence
< Reference
< chart2::XRegressionCurve
> >& aRegressionCurves
)
463 tRegressionCurveContainerType aOldCurves
;
464 auto aNewCurves( comphelper::sequenceToContainer
<tRegressionCurveContainerType
>( aRegressionCurves
) );
465 Reference
< util::XModifyListener
> xModifyEventForwarder
;
467 MutexGuard
aGuard( m_aMutex
);
468 xModifyEventForwarder
= m_xModifyEventForwarder
;
469 std::swap( aOldCurves
, m_aRegressionCurves
);
470 m_aRegressionCurves
= aNewCurves
;
472 ModifyListenerHelper::removeListenerFromAllElements( aOldCurves
, xModifyEventForwarder
);
473 ModifyListenerHelper::addListenerToAllElements( aNewCurves
, xModifyEventForwarder
);
477 // ____ XModifyBroadcaster ____
478 void SAL_CALL
DataSeries::addModifyListener( const Reference
< util::XModifyListener
>& aListener
)
482 Reference
< util::XModifyBroadcaster
> xBroadcaster( m_xModifyEventForwarder
, uno::UNO_QUERY_THROW
);
483 xBroadcaster
->addModifyListener( aListener
);
485 catch( const uno::Exception
& )
487 DBG_UNHANDLED_EXCEPTION("chart2");
491 void SAL_CALL
DataSeries::removeModifyListener( const Reference
< util::XModifyListener
>& aListener
)
495 Reference
< util::XModifyBroadcaster
> xBroadcaster( m_xModifyEventForwarder
, uno::UNO_QUERY_THROW
);
496 xBroadcaster
->removeModifyListener( aListener
);
498 catch( const uno::Exception
& )
500 DBG_UNHANDLED_EXCEPTION("chart2");
504 // ____ XModifyListener ____
505 void SAL_CALL
DataSeries::modified( const lang::EventObject
& aEvent
)
507 m_xModifyEventForwarder
->modified( aEvent
);
510 // ____ XEventListener (base of XModifyListener) ____
511 void SAL_CALL
DataSeries::disposing( const lang::EventObject
& rEventObject
)
513 // forget disposed data sequences
514 tDataSequenceContainer::iterator
aIt(
515 std::find( m_aDataSequences
.begin(), m_aDataSequences
.end(), rEventObject
.Source
));
516 if( aIt
!= m_aDataSequences
.end())
517 m_aDataSequences
.erase( aIt
);
520 // ____ OPropertySet ____
521 void DataSeries::firePropertyChangeEvent()
526 void DataSeries::fireModifyEvent()
528 m_xModifyEventForwarder
->modified( lang::EventObject( static_cast< uno::XWeak
* >( this )));
531 using impl::DataSeries_Base
;
532 using ::property::OPropertySet
;
534 IMPLEMENT_FORWARD_XINTERFACE2( DataSeries
, DataSeries_Base
, OPropertySet
)
535 IMPLEMENT_FORWARD_XTYPEPROVIDER2( DataSeries
, DataSeries_Base
, OPropertySet
)
537 // implement XServiceInfo methods basing upon getSupportedServiceNames_Static
538 OUString SAL_CALL
DataSeries::getImplementationName()
540 return "com.sun.star.comp.chart.DataSeries";
543 sal_Bool SAL_CALL
DataSeries::supportsService( const OUString
& rServiceName
)
545 return cppu::supportsService(this, rServiceName
);
548 css::uno::Sequence
< OUString
> SAL_CALL
DataSeries::getSupportedServiceNames()
551 "com.sun.star.chart2.DataSeries",
552 "com.sun.star.chart2.DataPointProperties",
553 "com.sun.star.beans.PropertySet" };
558 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
559 com_sun_star_comp_chart_DataSeries_get_implementation(css::uno::XComponentContext
*,
560 css::uno::Sequence
<css::uno::Any
> const &)
562 return cppu::acquire(new ::chart::DataSeries
);
565 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */