1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_chart2.hxx"
26 #include "DataSeries.hxx"
27 #include "DataSeriesProperties.hxx"
28 #include "DataPointProperties.hxx"
29 #include "CharacterProperties.hxx"
30 #include "UserDefinedProperties.hxx"
31 #include "DataPoint.hxx"
32 #include "macros.hxx"
33 #include "DataSeriesHelper.hxx"
34 #include "ContainerHelper.hxx"
35 #include "CloneHelper.hxx"
36 #include "ModifyListenerHelper.hxx"
37 #include "EventListenerHelper.hxx"
38 
39 #include <algorithm>
40 
41 using namespace ::com::sun::star;
42 
43 using ::com::sun::star::beans::Property;
44 using ::com::sun::star::uno::Sequence;
45 using ::com::sun::star::uno::Reference;
46 using ::com::sun::star::uno::Any;
47 using ::rtl::OUString;
48 using ::osl::MutexGuard;
49 
50 // ----------------------------------------
51 
52 namespace
53 {
54 
55 struct StaticDataSeriesDefaults_Initializer
56 {
operator ()__anon6cb3ece40111::StaticDataSeriesDefaults_Initializer57     ::chart::tPropertyValueMap* operator()()
58     {
59         static ::chart::tPropertyValueMap aStaticDefaults;
60         lcl_AddDefaultsToMap( aStaticDefaults );
61         return &aStaticDefaults;
62     }
63 private:
lcl_AddDefaultsToMap__anon6cb3ece40111::StaticDataSeriesDefaults_Initializer64     void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap )
65     {
66         ::chart::DataSeriesProperties::AddDefaultsToMap( rOutMap );
67         ::chart::CharacterProperties::AddDefaultsToMap( rOutMap );
68 
69         float fDefaultCharHeight = 10.0;
70         ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::CharacterProperties::PROP_CHAR_CHAR_HEIGHT, fDefaultCharHeight );
71         ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::CharacterProperties::PROP_CHAR_ASIAN_CHAR_HEIGHT, fDefaultCharHeight );
72         ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::CharacterProperties::PROP_CHAR_COMPLEX_CHAR_HEIGHT, fDefaultCharHeight );
73     }
74 };
75 
76 struct StaticDataSeriesDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticDataSeriesDefaults_Initializer >
77 {
78 };
79 
80 struct StaticDataSeriesInfoHelper_Initializer
81 {
operator ()__anon6cb3ece40111::StaticDataSeriesInfoHelper_Initializer82     ::cppu::OPropertyArrayHelper* operator()()
83     {
84         static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() );
85         return &aPropHelper;
86     }
87 
88 private:
lcl_GetPropertySequence__anon6cb3ece40111::StaticDataSeriesInfoHelper_Initializer89     uno::Sequence< Property > lcl_GetPropertySequence()
90     {
91         ::std::vector< ::com::sun::star::beans::Property > aProperties;
92         ::chart::DataSeriesProperties::AddPropertiesToVector( aProperties );
93         ::chart::CharacterProperties::AddPropertiesToVector( aProperties );
94         ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
95 
96         ::std::sort( aProperties.begin(), aProperties.end(),
97                      ::chart::PropertyNameLess() );
98 
99         return ::chart::ContainerHelper::ContainerToSequence( aProperties );
100     }
101 
102 };
103 
104 struct StaticDataSeriesInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticDataSeriesInfoHelper_Initializer >
105 {
106 };
107 
108 struct StaticDataSeriesInfo_Initializer
109 {
operator ()__anon6cb3ece40111::StaticDataSeriesInfo_Initializer110     uno::Reference< beans::XPropertySetInfo >* operator()()
111     {
112         static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
113             ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticDataSeriesInfoHelper::get() ) );
114         return &xPropertySetInfo;
115     }
116 };
117 
118 struct StaticDataSeriesInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticDataSeriesInfo_Initializer >
119 {
120 };
121 
lcl_SetParent(const uno::Reference<uno::XInterface> & xChildInterface,const uno::Reference<uno::XInterface> & xParentInterface)122 void lcl_SetParent(
123     const uno::Reference< uno::XInterface > & xChildInterface,
124     const uno::Reference< uno::XInterface > & xParentInterface )
125 {
126     uno::Reference< container::XChild > xChild( xChildInterface, uno::UNO_QUERY );
127     if( xChild.is())
128         xChild->setParent( xParentInterface );
129 }
130 
131 typedef ::std::map< sal_Int32, ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > >
132     lcl_tDataPointMap;
133 
lcl_CloneAttributedDataPoints(const lcl_tDataPointMap & rSource,lcl_tDataPointMap & rDestination,const uno::Reference<uno::XInterface> & xSeries)134 void lcl_CloneAttributedDataPoints(
135     const lcl_tDataPointMap & rSource, lcl_tDataPointMap & rDestination,
136     const uno::Reference< uno::XInterface > & xSeries )
137 {
138     for( lcl_tDataPointMap::const_iterator aIt( rSource.begin());
139          aIt != rSource.end(); ++aIt )
140     {
141         Reference< beans::XPropertySet > xPoint( (*aIt).second );
142         if( xPoint.is())
143         {
144             Reference< util::XCloneable > xCloneable( xPoint, uno::UNO_QUERY );
145             if( xCloneable.is())
146             {
147                 xPoint.set( xCloneable->createClone(), uno::UNO_QUERY );
148                 if( xPoint.is())
149                 {
150                     lcl_SetParent( xPoint, xSeries );
151                     rDestination.insert( lcl_tDataPointMap::value_type( (*aIt).first, xPoint ));
152                 }
153             }
154         }
155     }
156 }
157 
158 } // anonymous namespace
159 
160 // ----------------------------------------
161 
162 namespace chart
163 {
164 
DataSeries(const uno::Reference<uno::XComponentContext> & xContext)165 DataSeries::DataSeries( const uno::Reference< uno::XComponentContext > & xContext ) :
166         ::property::OPropertySet( m_aMutex ),
167         m_xContext( xContext ),
168         m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder())
169 {
170 }
171 
DataSeries(const DataSeries & rOther)172 DataSeries::DataSeries( const DataSeries & rOther ) :
173         MutexContainer(),
174         impl::DataSeries_Base(),
175         ::property::OPropertySet( rOther, m_aMutex ),
176     m_xContext( rOther.m_xContext ),
177     m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder())
178 {
179     if( ! rOther.m_aDataSequences.empty())
180     {
181         CloneHelper::CloneRefVector< tDataSequenceContainer::value_type >(
182             rOther.m_aDataSequences, m_aDataSequences );
183         ModifyListenerHelper::addListenerToAllElements( m_aDataSequences, m_xModifyEventForwarder );
184     }
185 
186     CloneHelper::CloneRefVector< Reference< chart2::XRegressionCurve > >( rOther.m_aRegressionCurves, m_aRegressionCurves );
187     ModifyListenerHelper::addListenerToAllElements( m_aRegressionCurves, m_xModifyEventForwarder );
188 
189     // add as listener to XPropertySet properties
190     Reference< beans::XPropertySet > xPropertySet;
191     uno::Any aValue;
192 
193     getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X );
194     if( ( aValue >>= xPropertySet )
195         && xPropertySet.is())
196         ModifyListenerHelper::addListener( xPropertySet, m_xModifyEventForwarder );
197 
198     getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y );
199     if( ( aValue >>= xPropertySet )
200         && xPropertySet.is())
201         ModifyListenerHelper::addListener( xPropertySet, m_xModifyEventForwarder );
202 }
203 
204 // late initialization to call after copy-constructing
Init(const DataSeries & rOther)205 void DataSeries::Init( const DataSeries & rOther )
206 {
207     if( ! rOther.m_aDataSequences.empty())
208         EventListenerHelper::addListenerToAllElements( m_aDataSequences, this );
209 
210     Reference< uno::XInterface > xThisInterface( static_cast< ::cppu::OWeakObject * >( this ));
211     if( ! rOther.m_aAttributedDataPoints.empty())
212     {
213         lcl_CloneAttributedDataPoints(
214             rOther.m_aAttributedDataPoints, m_aAttributedDataPoints, xThisInterface );
215         ModifyListenerHelper::addListenerToAllMapElements( m_aAttributedDataPoints, m_xModifyEventForwarder );
216     }
217 
218     // add as parent to error bars
219     Reference< beans::XPropertySet > xPropertySet;
220     uno::Any aValue;
221 
222     getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X );
223     if( ( aValue >>= xPropertySet )
224         && xPropertySet.is())
225         lcl_SetParent( xPropertySet, xThisInterface );
226 
227     getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y );
228     if( ( aValue >>= xPropertySet )
229         && xPropertySet.is())
230         lcl_SetParent( xPropertySet, xThisInterface );
231 }
232 
~DataSeries()233 DataSeries::~DataSeries()
234 {
235     try
236     {
237         ModifyListenerHelper::removeListenerFromAllMapElements( m_aAttributedDataPoints, m_xModifyEventForwarder );
238         ModifyListenerHelper::removeListenerFromAllElements( m_aRegressionCurves, m_xModifyEventForwarder );
239         ModifyListenerHelper::removeListenerFromAllElements( m_aDataSequences, m_xModifyEventForwarder );
240 
241         // remove listener from XPropertySet properties
242         Reference< beans::XPropertySet > xPropertySet;
243         uno::Any aValue;
244 
245         getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X );
246         if( ( aValue >>= xPropertySet )
247             && xPropertySet.is())
248             ModifyListenerHelper::removeListener( xPropertySet, m_xModifyEventForwarder );
249 
250         getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y );
251         if( ( aValue >>= xPropertySet )
252             && xPropertySet.is())
253             ModifyListenerHelper::removeListener( xPropertySet, m_xModifyEventForwarder );
254     }
255     catch( const uno::Exception & ex )
256     {
257         ASSERT_EXCEPTION( ex );
258     }
259 }
260 
261 // ____ XCloneable ____
createClone()262 uno::Reference< util::XCloneable > SAL_CALL DataSeries::createClone()
263     throw (uno::RuntimeException)
264 {
265     DataSeries * pNewSeries( new DataSeries( *this ));
266     // hold a reference to the clone
267     uno::Reference< util::XCloneable > xResult( pNewSeries );
268     // do initialization that uses uno references to the clone
269     pNewSeries->Init( *this );
270 
271     return xResult;
272 }
273 
getSupportedServiceNames_Static()274 Sequence< OUString > DataSeries::getSupportedServiceNames_Static()
275 {
276     Sequence< OUString > aServices( 3 );
277     aServices[ 0 ] = C2U( "com.sun.star.chart2.DataSeries" );
278     aServices[ 1 ] = C2U( "com.sun.star.chart2.DataPointProperties" );
279     aServices[ 2 ] = C2U( "com.sun.star.beans.PropertySet" );
280     return aServices;
281 }
282 
283 // ____ OPropertySet ____
GetDefaultValue(sal_Int32 nHandle) const284 uno::Any DataSeries::GetDefaultValue( sal_Int32 nHandle ) const
285     throw(beans::UnknownPropertyException)
286 {
287     const tPropertyValueMap& rStaticDefaults = *StaticDataSeriesDefaults::get();
288     tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
289     if( aFound == rStaticDefaults.end() )
290         return uno::Any();
291     return (*aFound).second;
292 }
293 
294 // ____ OPropertySet ____
getInfoHelper()295 ::cppu::IPropertyArrayHelper & SAL_CALL DataSeries::getInfoHelper()
296 {
297     return *StaticDataSeriesInfoHelper::get();
298 }
299 
300 // ____ XPropertySet ____
getPropertySetInfo()301 uno::Reference< beans::XPropertySetInfo > SAL_CALL DataSeries::getPropertySetInfo()
302     throw (uno::RuntimeException)
303 {
304     return *StaticDataSeriesInfo::get();
305 }
306 
getFastPropertyValue(uno::Any & rValue,sal_Int32 nHandle) const307 void SAL_CALL DataSeries::getFastPropertyValue
308     ( uno::Any& rValue,
309       sal_Int32 nHandle ) const
310 {
311     // special handling for get.  set is not possible for this property
312     if( nHandle == DataSeriesProperties::PROP_DATASERIES_ATTRIBUTED_DATA_POINTS )
313     {
314         // ToDo: only add those property sets that are really modified
315         uno::Sequence< sal_Int32 > aSeq( m_aAttributedDataPoints.size());
316         sal_Int32 * pIndexArray = aSeq.getArray();
317         sal_Int32 i = 0;
318 
319         for( tDataPointAttributeContainer::const_iterator aIt( m_aAttributedDataPoints.begin());
320              aIt != m_aAttributedDataPoints.end(); ++aIt )
321         {
322             pIndexArray[ i ] = (*aIt).first;
323             ++i;
324         }
325 
326         rValue <<= aSeq;
327     }
328     else
329         OPropertySet::getFastPropertyValue( rValue, nHandle );
330 }
331 
setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const uno::Any & rValue)332 void SAL_CALL DataSeries::setFastPropertyValue_NoBroadcast(
333     sal_Int32 nHandle, const uno::Any& rValue )
334     throw (uno::Exception)
335 {
336     if(    nHandle == DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y
337         || nHandle == DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X )
338     {
339         uno::Any aOldValue;
340         Reference< util::XModifyBroadcaster > xBroadcaster;
341         this->getFastPropertyValue( aOldValue, nHandle );
342         if( aOldValue.hasValue() &&
343             (aOldValue >>= xBroadcaster) &&
344             xBroadcaster.is())
345         {
346             ModifyListenerHelper::removeListener( xBroadcaster, m_xModifyEventForwarder );
347         }
348 
349         OSL_ASSERT( rValue.getValueType().getTypeClass() == uno::TypeClass_INTERFACE );
350         if( rValue.hasValue() &&
351             (rValue >>= xBroadcaster) &&
352             xBroadcaster.is())
353         {
354             ModifyListenerHelper::addListener( xBroadcaster, m_xModifyEventForwarder );
355         }
356     }
357 
358     ::property::OPropertySet::setFastPropertyValue_NoBroadcast( nHandle, rValue );
359 }
360 
361 Reference< beans::XPropertySet >
getDataPointByIndex(sal_Int32 nIndex)362     SAL_CALL DataSeries::getDataPointByIndex( sal_Int32 nIndex )
363     throw (lang::IndexOutOfBoundsException,
364            uno::RuntimeException)
365 {
366     Reference< beans::XPropertySet > xResult;
367 
368     Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences;
369     {
370         MutexGuard aGuard( GetMutex() );
371         aSequences = ContainerHelper::ContainerToSequence( m_aDataSequences );
372     }
373 
374     ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aValuesSeries(
375         DataSeriesHelper::getAllDataSequencesByRole( aSequences , C2U("values"), true ) );
376     if( !aValuesSeries.empty() )
377     {
378         Reference< chart2::data::XDataSequence > xSeq( aValuesSeries.front()->getValues() );
379         if( 0 <= nIndex && nIndex < xSeq->getData().getLength() )
380         {
381             {
382                 MutexGuard aGuard( GetMutex() );
383                 tDataPointAttributeContainer::iterator aIt( m_aAttributedDataPoints.find( nIndex ) );
384                 if( aIt != m_aAttributedDataPoints.end() )
385                     xResult = (*aIt).second;
386             }
387             if( !xResult.is() )
388             {
389                 Reference< beans::XPropertySet > xParentProperties;
390                 Reference< util::XModifyListener > xModifyEventForwarder;
391                 {
392                     MutexGuard aGuard( GetMutex() );
393                     xParentProperties = this;
394                     xModifyEventForwarder = m_xModifyEventForwarder;
395                 }
396 
397                 // create a new XPropertySet for this data point
398                 xResult.set( new DataPoint( xParentProperties ) );
399                 {
400                     MutexGuard aGuard( GetMutex() );
401                     m_aAttributedDataPoints[ nIndex ] = xResult;
402                 }
403                 ModifyListenerHelper::addListener( xResult, xModifyEventForwarder );
404             }
405         }
406     }
407     else
408     {
409         throw lang::IndexOutOfBoundsException();
410     }
411 
412     return xResult;
413 }
414 
resetDataPoint(sal_Int32 nIndex)415 void SAL_CALL DataSeries::resetDataPoint( sal_Int32 nIndex )
416         throw (uno::RuntimeException)
417 {
418     Reference< beans::XPropertySet > xDataPointProp;
419     Reference< util::XModifyListener > xModifyEventForwarder;
420     {
421         MutexGuard aGuard( GetMutex() );
422         xModifyEventForwarder = m_xModifyEventForwarder;
423         tDataPointAttributeContainer::iterator aIt( m_aAttributedDataPoints.find( nIndex ));
424         if( aIt != m_aAttributedDataPoints.end())
425         {
426             xDataPointProp = (*aIt).second;
427             m_aAttributedDataPoints.erase(aIt);
428         }
429 
430     }
431     if( xDataPointProp.is() )
432     {
433         Reference< util::XModifyBroadcaster > xBroadcaster( xDataPointProp, uno::UNO_QUERY );
434         if( xBroadcaster.is() && xModifyEventForwarder.is())
435             xBroadcaster->removeModifyListener( xModifyEventForwarder );
436         fireModifyEvent();
437     }
438 }
439 
resetAllDataPoints()440 void SAL_CALL DataSeries::resetAllDataPoints()
441         throw (uno::RuntimeException)
442 {
443     tDataPointAttributeContainer  aOldAttributedDataPoints;
444     Reference< util::XModifyListener > xModifyEventForwarder;
445     {
446         MutexGuard aGuard( GetMutex() );
447         xModifyEventForwarder = m_xModifyEventForwarder;
448         std::swap( aOldAttributedDataPoints, m_aAttributedDataPoints );
449     }
450     ModifyListenerHelper::removeListenerFromAllMapElements( aOldAttributedDataPoints, xModifyEventForwarder );
451     aOldAttributedDataPoints.clear();
452     fireModifyEvent();
453 }
454 
455 // ____ XDataSink ____
setData(const uno::Sequence<Reference<chart2::data::XLabeledDataSequence>> & aData)456 void SAL_CALL DataSeries::setData( const uno::Sequence< Reference< chart2::data::XLabeledDataSequence > >& aData )
457     throw (uno::RuntimeException)
458 {
459     tDataSequenceContainer aOldDataSequences;
460     tDataSequenceContainer aNewDataSequences;
461     Reference< util::XModifyListener > xModifyEventForwarder;
462     Reference< lang::XEventListener > xListener;
463     {
464         MutexGuard aGuard( GetMutex() );
465         xModifyEventForwarder = m_xModifyEventForwarder;
466         xListener = this;
467         std::swap( aOldDataSequences, m_aDataSequences );
468         aNewDataSequences = ContainerHelper::SequenceToVector( aData );
469         m_aDataSequences = aNewDataSequences;
470     }
471     ModifyListenerHelper::removeListenerFromAllElements( aOldDataSequences, xModifyEventForwarder );
472     EventListenerHelper::removeListenerFromAllElements( aOldDataSequences, xListener );
473     EventListenerHelper::addListenerToAllElements( aNewDataSequences, xListener );
474     ModifyListenerHelper::addListenerToAllElements( aNewDataSequences, xModifyEventForwarder );
475     fireModifyEvent();
476 }
477 
478 // ____ XDataSource ____
getDataSequences()479 Sequence< Reference< chart2::data::XLabeledDataSequence > > SAL_CALL DataSeries::getDataSequences()
480     throw (uno::RuntimeException)
481 {
482     MutexGuard aGuard( GetMutex() );
483     return ContainerHelper::ContainerToSequence( m_aDataSequences );
484 }
485 
486 
487 // ____ XRegressionCurveContainer ____
addRegressionCurve(const uno::Reference<chart2::XRegressionCurve> & xRegressionCurve)488 void SAL_CALL DataSeries::addRegressionCurve(
489     const uno::Reference< chart2::XRegressionCurve >& xRegressionCurve )
490     throw (lang::IllegalArgumentException,
491            uno::RuntimeException)
492 {
493     Reference< util::XModifyListener > xModifyEventForwarder;
494     {
495         MutexGuard aGuard( GetMutex() );
496         xModifyEventForwarder = m_xModifyEventForwarder;
497         if( ::std::find( m_aRegressionCurves.begin(), m_aRegressionCurves.end(), xRegressionCurve )
498             != m_aRegressionCurves.end())
499             throw lang::IllegalArgumentException();
500         m_aRegressionCurves.push_back( xRegressionCurve );
501     }
502     ModifyListenerHelper::addListener( xRegressionCurve, xModifyEventForwarder );
503     fireModifyEvent();
504 }
505 
removeRegressionCurve(const uno::Reference<chart2::XRegressionCurve> & xRegressionCurve)506 void SAL_CALL DataSeries::removeRegressionCurve(
507     const uno::Reference< chart2::XRegressionCurve >& xRegressionCurve )
508     throw (container::NoSuchElementException,
509            uno::RuntimeException)
510 {
511     if( !xRegressionCurve.is() )
512         throw container::NoSuchElementException();
513 
514     Reference< util::XModifyListener > xModifyEventForwarder;
515     {
516         MutexGuard aGuard( GetMutex() );
517         xModifyEventForwarder = m_xModifyEventForwarder;
518         tRegressionCurveContainerType::iterator aIt(
519             ::std::find( m_aRegressionCurves.begin(), m_aRegressionCurves.end(), xRegressionCurve ) );
520         if( aIt == m_aRegressionCurves.end())
521             throw container::NoSuchElementException(
522                 C2U( "The given regression curve is no element of this series" ),
523                 static_cast< uno::XWeak * >( this ));
524         m_aRegressionCurves.erase( aIt );
525     }
526 
527     ModifyListenerHelper::removeListener( xRegressionCurve, xModifyEventForwarder );
528     fireModifyEvent();
529 }
530 
getRegressionCurves()531 uno::Sequence< uno::Reference< chart2::XRegressionCurve > > SAL_CALL DataSeries::getRegressionCurves()
532     throw (uno::RuntimeException)
533 {
534     MutexGuard aGuard( GetMutex() );
535     return ContainerHelper::ContainerToSequence( m_aRegressionCurves );
536 }
537 
setRegressionCurves(const Sequence<Reference<chart2::XRegressionCurve>> & aRegressionCurves)538 void SAL_CALL DataSeries::setRegressionCurves(
539     const Sequence< Reference< chart2::XRegressionCurve > >& aRegressionCurves )
540     throw (uno::RuntimeException)
541 {
542     tRegressionCurveContainerType aOldCurves;
543     tRegressionCurveContainerType aNewCurves( ContainerHelper::SequenceToVector( aRegressionCurves ) );
544     Reference< util::XModifyListener > xModifyEventForwarder;
545     {
546         MutexGuard aGuard( GetMutex() );
547         xModifyEventForwarder = m_xModifyEventForwarder;
548         std::swap( aOldCurves, m_aRegressionCurves );
549         m_aRegressionCurves = aNewCurves;
550     }
551     ModifyListenerHelper::removeListenerFromAllElements( aOldCurves, xModifyEventForwarder );
552     ModifyListenerHelper::addListenerToAllElements( aNewCurves, xModifyEventForwarder );
553     fireModifyEvent();
554 }
555 
556 // ____ XModifyBroadcaster ____
addModifyListener(const Reference<util::XModifyListener> & aListener)557 void SAL_CALL DataSeries::addModifyListener( const Reference< util::XModifyListener >& aListener )
558     throw (uno::RuntimeException)
559 {
560     try
561     {
562         Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW );
563         xBroadcaster->addModifyListener( aListener );
564     }
565     catch( const uno::Exception & ex )
566     {
567         ASSERT_EXCEPTION( ex );
568     }
569 }
570 
removeModifyListener(const Reference<util::XModifyListener> & aListener)571 void SAL_CALL DataSeries::removeModifyListener( const Reference< util::XModifyListener >& aListener )
572     throw (uno::RuntimeException)
573 {
574     try
575     {
576         Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW );
577         xBroadcaster->removeModifyListener( aListener );
578     }
579     catch( const uno::Exception & ex )
580     {
581         ASSERT_EXCEPTION( ex );
582     }
583 }
584 
585 // ____ XModifyListener ____
modified(const lang::EventObject & aEvent)586 void SAL_CALL DataSeries::modified( const lang::EventObject& aEvent )
587     throw (uno::RuntimeException)
588 {
589     m_xModifyEventForwarder->modified( aEvent );
590 }
591 
592 // ____ XEventListener (base of XModifyListener) ____
disposing(const lang::EventObject & rEventObject)593 void SAL_CALL DataSeries::disposing( const lang::EventObject& rEventObject )
594     throw (uno::RuntimeException)
595 {
596     // forget disposed data sequences
597     tDataSequenceContainer::iterator aIt(
598         ::std::find( m_aDataSequences.begin(), m_aDataSequences.end(), rEventObject.Source ));
599     if( aIt != m_aDataSequences.end())
600         m_aDataSequences.erase( aIt );
601 }
602 
603 // ____ OPropertySet ____
firePropertyChangeEvent()604 void DataSeries::firePropertyChangeEvent()
605 {
606     fireModifyEvent();
607 }
608 
fireModifyEvent()609 void DataSeries::fireModifyEvent()
610 {
611     m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
612 }
613 
614 
615 // ================================================================================
616 
617 using impl::DataSeries_Base;
618 using ::property::OPropertySet;
619 
620 IMPLEMENT_FORWARD_XINTERFACE2( DataSeries, DataSeries_Base, OPropertySet )
621 IMPLEMENT_FORWARD_XTYPEPROVIDER2( DataSeries, DataSeries_Base, OPropertySet )
622 
623 // implement XServiceInfo methods basing upon getSupportedServiceNames_Static
624 APPHELPER_XSERVICEINFO_IMPL( DataSeries,
625                              C2U( "com.sun.star.comp.chart.DataSeries" ));
626 
627 }  // namespace chart
628