Bump version to 6.4-15
[LibreOffice.git] / chart2 / source / model / main / DataSeries.cxx
blob26226172bf4339add7e81cead4323966c5206cc4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
35 #include <algorithm>
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;
46 namespace
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() );
88 void lcl_SetParent(
89 const uno::Reference< uno::XInterface > & xChildInterface,
90 const uno::Reference< uno::XInterface > & xParentInterface )
92 uno::Reference< container::XChild > xChild( xChildInterface, uno::UNO_QUERY );
93 if( xChild.is())
94 xChild->setParent( xParentInterface );
97 typedef std::map< sal_Int32, css::uno::Reference< css::beans::XPropertySet > >
98 lcl_tDataPointMap;
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 );
107 if( xPoint.is())
109 Reference< util::XCloneable > xCloneable( xPoint, uno::UNO_QUERY );
110 if( xCloneable.is())
112 xPoint.set( xCloneable->createClone(), uno::UNO_QUERY );
113 if( xPoint.is())
115 lcl_SetParent( xPoint, xSeries );
116 rDestination.emplace( elem.first, xPoint );
123 } // anonymous namespace
125 namespace chart
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;
151 uno::Any aValue;
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;
180 uno::Any aValue;
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;
203 uno::Any aValue;
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 );
230 return xResult;
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() )
239 return uno::Any();
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
256 ( uno::Any& rValue,
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);
266 else
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 )
276 uno::Any aOldValue;
277 Reference< util::XModifyBroadcaster > xBroadcaster;
278 getFastPropertyValue( aOldValue, nHandle );
279 if( aOldValue.hasValue() &&
280 (aOldValue >>= xBroadcaster) &&
281 xBroadcaster.is())
283 ModifyListenerHelper::removeListener( xBroadcaster, m_xModifyEventForwarder );
286 OSL_ASSERT( rValue.getValueType().getTypeClass() == uno::TypeClass_INTERFACE );
287 if( rValue.hasValue() &&
288 (rValue >>= xBroadcaster) &&
289 xBroadcaster.is())
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;
324 if( !xResult.is() )
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 );
344 return xResult;
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 );
367 fireModifyEvent();
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();
382 fireModifyEvent();
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;
395 xListener = this;
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 );
404 fireModifyEvent();
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 );
428 fireModifyEvent();
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 );
451 fireModifyEvent();
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 );
474 fireModifyEvent();
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()
523 fireModifyEvent();
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()
550 return {
551 "com.sun.star.chart2.DataSeries",
552 "com.sun.star.chart2.DataPointProperties",
553 "com.sun.star.beans.PropertySet" };
556 } // namespace chart
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: */