xref: /trunk/main/chart2/source/model/main/DataSeries.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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_chartmodel.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 ()__anond0609b030111::StaticDataSeriesDefaults_Initializer57     ::chart::tPropertyValueMap* operator()()
58     {
59         static ::chart::tPropertyValueMap aStaticDefaults;
60         lcl_AddDefaultsToMap( aStaticDefaults );
61         return &aStaticDefaults;
62     }
63 private:
lcl_AddDefaultsToMap__anond0609b030111::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 ()__anond0609b030111::StaticDataSeriesInfoHelper_Initializer82     ::cppu::OPropertyArrayHelper* operator()()
83     {
84         static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() );
85         return &aPropHelper;
86     }
87 
88 private:
lcl_GetPropertySequence__anond0609b030111::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 ()__anond0609b030111::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 {
264     DataSeries * pNewSeries( new DataSeries( *this ));
265     // hold a reference to the clone
266     uno::Reference< util::XCloneable > xResult( pNewSeries );
267     // do initialization that uses uno references to the clone
268     pNewSeries->Init( *this );
269 
270     return xResult;
271 }
272 
getSupportedServiceNames_Static()273 Sequence< OUString > DataSeries::getSupportedServiceNames_Static()
274 {
275     Sequence< OUString > aServices( 3 );
276     aServices[ 0 ] = C2U( "com.sun.star.chart2.DataSeries" );
277     aServices[ 1 ] = C2U( "com.sun.star.chart2.DataPointProperties" );
278     aServices[ 2 ] = C2U( "com.sun.star.beans.PropertySet" );
279     return aServices;
280 }
281 
282 // ____ OPropertySet ____
GetDefaultValue(sal_Int32 nHandle) const283 uno::Any DataSeries::GetDefaultValue( sal_Int32 nHandle ) const
284 {
285     const tPropertyValueMap& rStaticDefaults = *StaticDataSeriesDefaults::get();
286     tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
287     if( aFound == rStaticDefaults.end() )
288         return uno::Any();
289     return (*aFound).second;
290 }
291 
292 // ____ OPropertySet ____
getInfoHelper()293 ::cppu::IPropertyArrayHelper & SAL_CALL DataSeries::getInfoHelper()
294 {
295     return *StaticDataSeriesInfoHelper::get();
296 }
297 
298 // ____ XPropertySet ____
getPropertySetInfo()299 uno::Reference< beans::XPropertySetInfo > SAL_CALL DataSeries::getPropertySetInfo()
300 {
301     return *StaticDataSeriesInfo::get();
302 }
303 
getFastPropertyValue(uno::Any & rValue,sal_Int32 nHandle) const304 void SAL_CALL DataSeries::getFastPropertyValue
305     ( uno::Any& rValue,
306       sal_Int32 nHandle ) const
307 {
308     // special handling for get.  set is not possible for this property
309     if( nHandle == DataSeriesProperties::PROP_DATASERIES_ATTRIBUTED_DATA_POINTS )
310     {
311         // ToDo: only add those property sets that are really modified
312         uno::Sequence< sal_Int32 > aSeq( m_aAttributedDataPoints.size());
313         sal_Int32 * pIndexArray = aSeq.getArray();
314         sal_Int32 i = 0;
315 
316         for( tDataPointAttributeContainer::const_iterator aIt( m_aAttributedDataPoints.begin());
317              aIt != m_aAttributedDataPoints.end(); ++aIt )
318         {
319             pIndexArray[ i ] = (*aIt).first;
320             ++i;
321         }
322 
323         rValue <<= aSeq;
324     }
325     else
326         OPropertySet::getFastPropertyValue( rValue, nHandle );
327 }
328 
setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const uno::Any & rValue)329 void SAL_CALL DataSeries::setFastPropertyValue_NoBroadcast(
330     sal_Int32 nHandle, const uno::Any& rValue )
331 {
332     if(    nHandle == DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y
333         || nHandle == DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X )
334     {
335         uno::Any aOldValue;
336         Reference< util::XModifyBroadcaster > xBroadcaster;
337         this->getFastPropertyValue( aOldValue, nHandle );
338         if( aOldValue.hasValue() &&
339             (aOldValue >>= xBroadcaster) &&
340             xBroadcaster.is())
341         {
342             ModifyListenerHelper::removeListener( xBroadcaster, m_xModifyEventForwarder );
343         }
344 
345         OSL_ASSERT( rValue.getValueType().getTypeClass() == uno::TypeClass_INTERFACE );
346         if( rValue.hasValue() &&
347             (rValue >>= xBroadcaster) &&
348             xBroadcaster.is())
349         {
350             ModifyListenerHelper::addListener( xBroadcaster, m_xModifyEventForwarder );
351         }
352     }
353 
354     ::property::OPropertySet::setFastPropertyValue_NoBroadcast( nHandle, rValue );
355 }
356 
357 Reference< beans::XPropertySet >
getDataPointByIndex(sal_Int32 nIndex)358     SAL_CALL DataSeries::getDataPointByIndex( sal_Int32 nIndex )
359 {
360     Reference< beans::XPropertySet > xResult;
361 
362     Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences;
363     {
364         MutexGuard aGuard( GetMutex() );
365         aSequences = ContainerHelper::ContainerToSequence( m_aDataSequences );
366     }
367 
368     ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aValuesSeries(
369         DataSeriesHelper::getAllDataSequencesByRole( aSequences , C2U("values"), true ) );
370     if( !aValuesSeries.empty() )
371     {
372         Reference< chart2::data::XDataSequence > xSeq( aValuesSeries.front()->getValues() );
373         if( 0 <= nIndex && nIndex < xSeq->getData().getLength() )
374         {
375             {
376                 MutexGuard aGuard( GetMutex() );
377                 tDataPointAttributeContainer::iterator aIt( m_aAttributedDataPoints.find( nIndex ) );
378                 if( aIt != m_aAttributedDataPoints.end() )
379                     xResult = (*aIt).second;
380             }
381             if( !xResult.is() )
382             {
383                 Reference< beans::XPropertySet > xParentProperties;
384                 Reference< util::XModifyListener > xModifyEventForwarder;
385                 {
386                     MutexGuard aGuard( GetMutex() );
387                     xParentProperties = this;
388                     xModifyEventForwarder = m_xModifyEventForwarder;
389                 }
390 
391                 // create a new XPropertySet for this data point
392                 xResult.set( new DataPoint( xParentProperties ) );
393                 {
394                     MutexGuard aGuard( GetMutex() );
395                     m_aAttributedDataPoints[ nIndex ] = xResult;
396                 }
397                 ModifyListenerHelper::addListener( xResult, xModifyEventForwarder );
398             }
399         }
400     }
401     else
402     {
403         throw lang::IndexOutOfBoundsException();
404     }
405 
406     return xResult;
407 }
408 
resetDataPoint(sal_Int32 nIndex)409 void SAL_CALL DataSeries::resetDataPoint( sal_Int32 nIndex )
410 {
411     Reference< beans::XPropertySet > xDataPointProp;
412     Reference< util::XModifyListener > xModifyEventForwarder;
413     {
414         MutexGuard aGuard( GetMutex() );
415         xModifyEventForwarder = m_xModifyEventForwarder;
416         tDataPointAttributeContainer::iterator aIt( m_aAttributedDataPoints.find( nIndex ));
417         if( aIt != m_aAttributedDataPoints.end())
418         {
419             xDataPointProp = (*aIt).second;
420             m_aAttributedDataPoints.erase(aIt);
421         }
422 
423     }
424     if( xDataPointProp.is() )
425     {
426         Reference< util::XModifyBroadcaster > xBroadcaster( xDataPointProp, uno::UNO_QUERY );
427         if( xBroadcaster.is() && xModifyEventForwarder.is())
428             xBroadcaster->removeModifyListener( xModifyEventForwarder );
429         fireModifyEvent();
430     }
431 }
432 
resetAllDataPoints()433 void SAL_CALL DataSeries::resetAllDataPoints()
434 {
435     tDataPointAttributeContainer  aOldAttributedDataPoints;
436     Reference< util::XModifyListener > xModifyEventForwarder;
437     {
438         MutexGuard aGuard( GetMutex() );
439         xModifyEventForwarder = m_xModifyEventForwarder;
440         std::swap( aOldAttributedDataPoints, m_aAttributedDataPoints );
441     }
442     ModifyListenerHelper::removeListenerFromAllMapElements( aOldAttributedDataPoints, xModifyEventForwarder );
443     aOldAttributedDataPoints.clear();
444     fireModifyEvent();
445 }
446 
447 // ____ XDataSink ____
setData(const uno::Sequence<Reference<chart2::data::XLabeledDataSequence>> & aData)448 void SAL_CALL DataSeries::setData( const uno::Sequence< Reference< chart2::data::XLabeledDataSequence > >& aData )
449 {
450     tDataSequenceContainer aOldDataSequences;
451     tDataSequenceContainer aNewDataSequences;
452     Reference< util::XModifyListener > xModifyEventForwarder;
453     Reference< lang::XEventListener > xListener;
454     {
455         MutexGuard aGuard( GetMutex() );
456         xModifyEventForwarder = m_xModifyEventForwarder;
457         xListener = this;
458         std::swap( aOldDataSequences, m_aDataSequences );
459         aNewDataSequences = ContainerHelper::SequenceToVector( aData );
460         m_aDataSequences = aNewDataSequences;
461     }
462     ModifyListenerHelper::removeListenerFromAllElements( aOldDataSequences, xModifyEventForwarder );
463     EventListenerHelper::removeListenerFromAllElements( aOldDataSequences, xListener );
464     EventListenerHelper::addListenerToAllElements( aNewDataSequences, xListener );
465     ModifyListenerHelper::addListenerToAllElements( aNewDataSequences, xModifyEventForwarder );
466     fireModifyEvent();
467 }
468 
469 // ____ XDataSource ____
getDataSequences()470 Sequence< Reference< chart2::data::XLabeledDataSequence > > SAL_CALL DataSeries::getDataSequences()
471 {
472     MutexGuard aGuard( GetMutex() );
473     return ContainerHelper::ContainerToSequence( m_aDataSequences );
474 }
475 
476 
477 // ____ XRegressionCurveContainer ____
addRegressionCurve(const uno::Reference<chart2::XRegressionCurve> & xRegressionCurve)478 void SAL_CALL DataSeries::addRegressionCurve(
479     const uno::Reference< chart2::XRegressionCurve >& xRegressionCurve )
480 {
481     Reference< util::XModifyListener > xModifyEventForwarder;
482     {
483         MutexGuard aGuard( GetMutex() );
484         xModifyEventForwarder = m_xModifyEventForwarder;
485         if( ::std::find( m_aRegressionCurves.begin(), m_aRegressionCurves.end(), xRegressionCurve )
486             != m_aRegressionCurves.end())
487             throw lang::IllegalArgumentException();
488         m_aRegressionCurves.push_back( xRegressionCurve );
489     }
490     ModifyListenerHelper::addListener( xRegressionCurve, xModifyEventForwarder );
491     fireModifyEvent();
492 }
493 
removeRegressionCurve(const uno::Reference<chart2::XRegressionCurve> & xRegressionCurve)494 void SAL_CALL DataSeries::removeRegressionCurve(
495     const uno::Reference< chart2::XRegressionCurve >& xRegressionCurve )
496 {
497     if( !xRegressionCurve.is() )
498         throw container::NoSuchElementException();
499 
500     Reference< util::XModifyListener > xModifyEventForwarder;
501     {
502         MutexGuard aGuard( GetMutex() );
503         xModifyEventForwarder = m_xModifyEventForwarder;
504         tRegressionCurveContainerType::iterator aIt(
505             ::std::find( m_aRegressionCurves.begin(), m_aRegressionCurves.end(), xRegressionCurve ) );
506         if( aIt == m_aRegressionCurves.end())
507             throw container::NoSuchElementException(
508                 C2U( "The given regression curve is no element of this series" ),
509                 static_cast< uno::XWeak * >( this ));
510         m_aRegressionCurves.erase( aIt );
511     }
512 
513     ModifyListenerHelper::removeListener( xRegressionCurve, xModifyEventForwarder );
514     fireModifyEvent();
515 }
516 
getRegressionCurves()517 uno::Sequence< uno::Reference< chart2::XRegressionCurve > > SAL_CALL DataSeries::getRegressionCurves()
518 {
519     MutexGuard aGuard( GetMutex() );
520     return ContainerHelper::ContainerToSequence( m_aRegressionCurves );
521 }
522 
setRegressionCurves(const Sequence<Reference<chart2::XRegressionCurve>> & aRegressionCurves)523 void SAL_CALL DataSeries::setRegressionCurves(
524     const Sequence< Reference< chart2::XRegressionCurve > >& aRegressionCurves )
525 {
526     tRegressionCurveContainerType aOldCurves;
527     tRegressionCurveContainerType aNewCurves( ContainerHelper::SequenceToVector( aRegressionCurves ) );
528     Reference< util::XModifyListener > xModifyEventForwarder;
529     {
530         MutexGuard aGuard( GetMutex() );
531         xModifyEventForwarder = m_xModifyEventForwarder;
532         std::swap( aOldCurves, m_aRegressionCurves );
533         m_aRegressionCurves = aNewCurves;
534     }
535     ModifyListenerHelper::removeListenerFromAllElements( aOldCurves, xModifyEventForwarder );
536     ModifyListenerHelper::addListenerToAllElements( aNewCurves, xModifyEventForwarder );
537     fireModifyEvent();
538 }
539 
540 // ____ XModifyBroadcaster ____
addModifyListener(const Reference<util::XModifyListener> & aListener)541 void SAL_CALL DataSeries::addModifyListener( const Reference< util::XModifyListener >& aListener )
542 {
543     try
544     {
545         Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW );
546         xBroadcaster->addModifyListener( aListener );
547     }
548     catch( const uno::Exception & ex )
549     {
550         ASSERT_EXCEPTION( ex );
551     }
552 }
553 
removeModifyListener(const Reference<util::XModifyListener> & aListener)554 void SAL_CALL DataSeries::removeModifyListener( const Reference< util::XModifyListener >& aListener )
555 {
556     try
557     {
558         Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW );
559         xBroadcaster->removeModifyListener( aListener );
560     }
561     catch( const uno::Exception & ex )
562     {
563         ASSERT_EXCEPTION( ex );
564     }
565 }
566 
567 // ____ XModifyListener ____
modified(const lang::EventObject & aEvent)568 void SAL_CALL DataSeries::modified( const lang::EventObject& aEvent )
569 {
570     m_xModifyEventForwarder->modified( aEvent );
571 }
572 
573 // ____ XEventListener (base of XModifyListener) ____
disposing(const lang::EventObject & rEventObject)574 void SAL_CALL DataSeries::disposing( const lang::EventObject& rEventObject )
575 {
576     // forget disposed data sequences
577     tDataSequenceContainer::iterator aIt(
578         ::std::find( m_aDataSequences.begin(), m_aDataSequences.end(), rEventObject.Source ));
579     if( aIt != m_aDataSequences.end())
580         m_aDataSequences.erase( aIt );
581 }
582 
583 // ____ OPropertySet ____
firePropertyChangeEvent()584 void DataSeries::firePropertyChangeEvent()
585 {
586     fireModifyEvent();
587 }
588 
fireModifyEvent()589 void DataSeries::fireModifyEvent()
590 {
591     m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
592 }
593 
594 
595 // ================================================================================
596 
597 using impl::DataSeries_Base;
598 using ::property::OPropertySet;
599 
600 IMPLEMENT_FORWARD_XINTERFACE2( DataSeries, DataSeries_Base, OPropertySet )
601 IMPLEMENT_FORWARD_XTYPEPROVIDER2( DataSeries, DataSeries_Base, OPropertySet )
602 
603 // implement XServiceInfo methods basing upon getSupportedServiceNames_Static
604 APPHELPER_XSERVICEINFO_IMPL( DataSeries,
605                              C2U( "com.sun.star.comp.chart.DataSeries" ));
606 
607 }  // namespace chart
608