1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_chart2.hxx"
30 #include "DataSeries.hxx"
31 #include "DataSeriesProperties.hxx"
32 #include "DataPointProperties.hxx"
33 #include "CharacterProperties.hxx"
34 #include "UserDefinedProperties.hxx"
35 #include "DataPoint.hxx"
37 #include "DataSeriesHelper.hxx"
38 #include "ContainerHelper.hxx"
39 #include "CloneHelper.hxx"
40 #include "ModifyListenerHelper.hxx"
41 #include "EventListenerHelper.hxx"
45 using namespace ::com::sun::star
;
47 using ::com::sun::star::beans::Property
;
48 using ::com::sun::star::uno::Sequence
;
49 using ::com::sun::star::uno::Reference
;
50 using ::com::sun::star::uno::Any
;
51 using ::rtl::OUString
;
52 using ::osl::MutexGuard
;
54 // ----------------------------------------
58 const uno::Sequence
< Property
> & lcl_GetPropertySequence()
60 static uno::Sequence
< Property
> aPropSeq
;
63 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
64 if( 0 == aPropSeq
.getLength() )
67 ::std::vector
< ::com::sun::star::beans::Property
> aProperties
;
68 ::chart::DataSeriesProperties::AddPropertiesToVector( aProperties
);
69 ::chart::CharacterProperties::AddPropertiesToVector( aProperties
);
70 ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties
);
72 // and sort them for access via bsearch
73 ::std::sort( aProperties
.begin(), aProperties
.end(),
74 ::chart::PropertyNameLess() );
76 // transfer result to static Sequence
77 aPropSeq
= ::chart::ContainerHelper::ContainerToSequence( aProperties
);
84 const uno::Reference
< uno::XInterface
> & xChildInterface
,
85 const uno::Reference
< uno::XInterface
> & xParentInterface
)
87 uno::Reference
< container::XChild
> xChild( xChildInterface
, uno::UNO_QUERY
);
89 xChild
->setParent( xParentInterface
);
92 typedef ::std::map
< sal_Int32
, ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertySet
> >
95 void lcl_CloneAttributedDataPoints(
96 const lcl_tDataPointMap
& rSource
, lcl_tDataPointMap
& rDestination
,
97 const uno::Reference
< uno::XInterface
> & xSeries
)
99 for( lcl_tDataPointMap::const_iterator
aIt( rSource
.begin());
100 aIt
!= rSource
.end(); ++aIt
)
102 Reference
< beans::XPropertySet
> xPoint( (*aIt
).second
);
105 Reference
< util::XCloneable
> xCloneable( xPoint
, uno::UNO_QUERY
);
108 xPoint
.set( xCloneable
->createClone(), uno::UNO_QUERY
);
111 lcl_SetParent( xPoint
, xSeries
);
112 rDestination
.insert( lcl_tDataPointMap::value_type( (*aIt
).first
, xPoint
));
119 } // anonymous namespace
121 // ----------------------------------------
126 DataSeries::DataSeries( const uno::Reference
< uno::XComponentContext
> & xContext
) :
127 ::property::OPropertySet( m_aMutex
),
128 m_xContext( xContext
),
129 m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder())
133 DataSeries::DataSeries( const DataSeries
& rOther
) :
135 impl::DataSeries_Base(),
136 ::property::OPropertySet( rOther
, m_aMutex
),
137 m_xContext( rOther
.m_xContext
),
138 m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder())
140 if( ! rOther
.m_aDataSequences
.empty())
142 CloneHelper::CloneRefVector
< tDataSequenceContainer::value_type
>(
143 rOther
.m_aDataSequences
, m_aDataSequences
);
144 ModifyListenerHelper::addListenerToAllElements( m_aDataSequences
, m_xModifyEventForwarder
);
147 CloneHelper::CloneRefVector
< Reference
< chart2::XRegressionCurve
> >( rOther
.m_aRegressionCurves
, m_aRegressionCurves
);
148 ModifyListenerHelper::addListenerToAllElements( m_aRegressionCurves
, m_xModifyEventForwarder
);
150 // add as listener to XPropertySet properties
151 Reference
< beans::XPropertySet
> xPropertySet
;
154 getFastPropertyValue( aValue
, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X
);
155 if( ( aValue
>>= xPropertySet
)
156 && xPropertySet
.is())
157 ModifyListenerHelper::addListener( xPropertySet
, m_xModifyEventForwarder
);
159 getFastPropertyValue( aValue
, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y
);
160 if( ( aValue
>>= xPropertySet
)
161 && xPropertySet
.is())
162 ModifyListenerHelper::addListener( xPropertySet
, m_xModifyEventForwarder
);
165 // late initialization to call after copy-constructing
166 void DataSeries::Init( const DataSeries
& rOther
)
168 if( ! rOther
.m_aDataSequences
.empty())
169 EventListenerHelper::addListenerToAllElements( m_aDataSequences
, this );
171 Reference
< uno::XInterface
> xThisInterface( static_cast< ::cppu::OWeakObject
* >( this ));
172 if( ! rOther
.m_aAttributedDataPoints
.empty())
174 lcl_CloneAttributedDataPoints(
175 rOther
.m_aAttributedDataPoints
, m_aAttributedDataPoints
, xThisInterface
);
176 ModifyListenerHelper::addListenerToAllMapElements( m_aAttributedDataPoints
, m_xModifyEventForwarder
);
179 // add as parent to error bars
180 Reference
< beans::XPropertySet
> xPropertySet
;
183 getFastPropertyValue( aValue
, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X
);
184 if( ( aValue
>>= xPropertySet
)
185 && xPropertySet
.is())
186 lcl_SetParent( xPropertySet
, xThisInterface
);
188 getFastPropertyValue( aValue
, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y
);
189 if( ( aValue
>>= xPropertySet
)
190 && xPropertySet
.is())
191 lcl_SetParent( xPropertySet
, xThisInterface
);
194 DataSeries::~DataSeries()
198 ModifyListenerHelper::removeListenerFromAllMapElements( m_aAttributedDataPoints
, m_xModifyEventForwarder
);
199 ModifyListenerHelper::removeListenerFromAllElements( m_aRegressionCurves
, m_xModifyEventForwarder
);
200 ModifyListenerHelper::removeListenerFromAllElements( m_aDataSequences
, m_xModifyEventForwarder
);
202 // remove listener from XPropertySet properties
203 Reference
< beans::XPropertySet
> xPropertySet
;
206 getFastPropertyValue( aValue
, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X
);
207 if( ( aValue
>>= xPropertySet
)
208 && xPropertySet
.is())
209 ModifyListenerHelper::removeListener( xPropertySet
, m_xModifyEventForwarder
);
211 getFastPropertyValue( aValue
, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y
);
212 if( ( aValue
>>= xPropertySet
)
213 && xPropertySet
.is())
214 ModifyListenerHelper::removeListener( xPropertySet
, m_xModifyEventForwarder
);
216 catch( const uno::Exception
& ex
)
218 ASSERT_EXCEPTION( ex
);
222 // ____ XCloneable ____
223 uno::Reference
< util::XCloneable
> SAL_CALL
DataSeries::createClone()
224 throw (uno::RuntimeException
)
226 DataSeries
* pNewSeries( new DataSeries( *this ));
227 // hold a reference to the clone
228 uno::Reference
< util::XCloneable
> xResult( pNewSeries
);
229 // do initialization that uses uno references to the clone
230 pNewSeries
->Init( *this );
235 Sequence
< OUString
> DataSeries::getSupportedServiceNames_Static()
237 Sequence
< OUString
> aServices( 3 );
238 aServices
[ 0 ] = C2U( "com.sun.star.chart2.DataSeries" );
239 aServices
[ 1 ] = C2U( "com.sun.star.chart2.DataPointProperties" );
240 aServices
[ 2 ] = C2U( "com.sun.star.beans.PropertySet" );
244 // ____ OPropertySet ____
245 uno::Any
DataSeries::GetDefaultValue( sal_Int32 nHandle
) const
246 throw(beans::UnknownPropertyException
)
248 static tPropertyValueMap aStaticDefaults
;
251 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
252 if( 0 == aStaticDefaults
.size() )
254 // initialize defaults
255 DataSeriesProperties::AddDefaultsToMap( aStaticDefaults
);
256 CharacterProperties::AddDefaultsToMap( aStaticDefaults
);
258 float fDefaultCharHeight
= 10.0;
259 ::chart::PropertyHelper::setPropertyValue( aStaticDefaults
, ::chart::CharacterProperties::PROP_CHAR_CHAR_HEIGHT
, fDefaultCharHeight
);
260 ::chart::PropertyHelper::setPropertyValue( aStaticDefaults
, ::chart::CharacterProperties::PROP_CHAR_ASIAN_CHAR_HEIGHT
, fDefaultCharHeight
);
261 ::chart::PropertyHelper::setPropertyValue( aStaticDefaults
, ::chart::CharacterProperties::PROP_CHAR_COMPLEX_CHAR_HEIGHT
, fDefaultCharHeight
);
264 tPropertyValueMap::const_iterator
aFound(
265 aStaticDefaults
.find( nHandle
));
267 if( aFound
== aStaticDefaults
.end())
268 throw beans::UnknownPropertyException();
270 return (*aFound
).second
;
274 // ____ OPropertySet ____
275 ::cppu::IPropertyArrayHelper
& SAL_CALL
DataSeries::getInfoHelper()
277 static ::cppu::OPropertyArrayHelper
aArrayHelper(
278 lcl_GetPropertySequence(),
279 /* bSorted = */ sal_True
);
285 // ____ XPropertySet ____
286 uno::Reference
< beans::XPropertySetInfo
> SAL_CALL
287 DataSeries::getPropertySetInfo()
288 throw (uno::RuntimeException
)
290 static uno::Reference
< beans::XPropertySetInfo
> xInfo
;
293 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
296 xInfo
= ::cppu::OPropertySetHelper::createPropertySetInfo(
304 void SAL_CALL
DataSeries::getFastPropertyValue
306 sal_Int32 nHandle
) const
308 // special handling for get. set is not possible for this property
309 if( nHandle
== DataSeriesProperties::PROP_DATASERIES_ATTRIBUTED_DATA_POINTS
)
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();
316 for( tDataPointAttributeContainer::const_iterator
aIt( m_aAttributedDataPoints
.begin());
317 aIt
!= m_aAttributedDataPoints
.end(); ++aIt
)
319 pIndexArray
[ i
] = (*aIt
).first
;
326 OPropertySet::getFastPropertyValue( rValue
, nHandle
);
329 void SAL_CALL
DataSeries::setFastPropertyValue_NoBroadcast(
330 sal_Int32 nHandle
, const uno::Any
& rValue
)
331 throw (uno::Exception
)
333 if( nHandle
== DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y
334 || nHandle
== DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X
)
337 Reference
< util::XModifyBroadcaster
> xBroadcaster
;
338 this->getFastPropertyValue( aOldValue
, nHandle
);
339 if( aOldValue
.hasValue() &&
340 (aOldValue
>>= xBroadcaster
) &&
343 ModifyListenerHelper::removeListener( xBroadcaster
, m_xModifyEventForwarder
);
346 OSL_ASSERT( rValue
.getValueType().getTypeClass() == uno::TypeClass_INTERFACE
);
347 if( rValue
.hasValue() &&
348 (rValue
>>= xBroadcaster
) &&
351 ModifyListenerHelper::addListener( xBroadcaster
, m_xModifyEventForwarder
);
355 ::property::OPropertySet::setFastPropertyValue_NoBroadcast( nHandle
, rValue
);
358 Reference
< beans::XPropertySet
>
359 SAL_CALL
DataSeries::getDataPointByIndex( sal_Int32 nIndex
)
360 throw (lang::IndexOutOfBoundsException
,
361 uno::RuntimeException
)
363 Reference
< beans::XPropertySet
> xResult
;
365 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aSequences
;
367 MutexGuard
aGuard( GetMutex() );
368 aSequences
= ContainerHelper::ContainerToSequence( m_aDataSequences
);
371 ::std::vector
< Reference
< chart2::data::XLabeledDataSequence
> > aValuesSeries(
372 DataSeriesHelper::getAllDataSequencesByRole( aSequences
, C2U("values"), true ) );
373 if( !aValuesSeries
.empty() )
375 Reference
< chart2::data::XDataSequence
> xSeq( aValuesSeries
.front()->getValues() );
376 if( 0 <= nIndex
&& nIndex
< xSeq
->getData().getLength() )
379 MutexGuard
aGuard( GetMutex() );
380 tDataPointAttributeContainer::iterator
aIt( m_aAttributedDataPoints
.find( nIndex
) );
381 if( aIt
!= m_aAttributedDataPoints
.end() )
382 xResult
= (*aIt
).second
;
386 Reference
< beans::XPropertySet
> xParentProperties
;
387 Reference
< util::XModifyListener
> xModifyEventForwarder
;
389 MutexGuard
aGuard( GetMutex() );
390 xParentProperties
= this;
391 xModifyEventForwarder
= m_xModifyEventForwarder
;
394 // create a new XPropertySet for this data point
395 xResult
.set( new DataPoint( xParentProperties
) );
397 MutexGuard
aGuard( GetMutex() );
398 m_aAttributedDataPoints
[ nIndex
] = xResult
;
400 ModifyListenerHelper::addListener( xResult
, xModifyEventForwarder
);
406 throw lang::IndexOutOfBoundsException();
412 void SAL_CALL
DataSeries::resetDataPoint( sal_Int32 nIndex
)
413 throw (uno::RuntimeException
)
415 Reference
< beans::XPropertySet
> xDataPointProp
;
416 Reference
< util::XModifyListener
> xModifyEventForwarder
;
418 MutexGuard
aGuard( GetMutex() );
419 xModifyEventForwarder
= m_xModifyEventForwarder
;
420 tDataPointAttributeContainer::iterator
aIt( m_aAttributedDataPoints
.find( nIndex
));
421 if( aIt
!= m_aAttributedDataPoints
.end())
423 xDataPointProp
= (*aIt
).second
;
424 m_aAttributedDataPoints
.erase(aIt
);
428 if( xDataPointProp
.is() )
430 Reference
< util::XModifyBroadcaster
> xBroadcaster( xDataPointProp
, uno::UNO_QUERY
);
431 if( xBroadcaster
.is() && xModifyEventForwarder
.is())
432 xBroadcaster
->removeModifyListener( xModifyEventForwarder
);
437 void SAL_CALL
DataSeries::resetAllDataPoints()
438 throw (uno::RuntimeException
)
440 tDataPointAttributeContainer aOldAttributedDataPoints
;
441 Reference
< util::XModifyListener
> xModifyEventForwarder
;
443 MutexGuard
aGuard( GetMutex() );
444 xModifyEventForwarder
= m_xModifyEventForwarder
;
445 std::swap( aOldAttributedDataPoints
, m_aAttributedDataPoints
);
447 ModifyListenerHelper::removeListenerFromAllMapElements( aOldAttributedDataPoints
, xModifyEventForwarder
);
448 aOldAttributedDataPoints
.clear();
452 // ____ XDataSink ____
453 void SAL_CALL
DataSeries::setData( const uno::Sequence
< Reference
< chart2::data::XLabeledDataSequence
> >& aData
)
454 throw (uno::RuntimeException
)
456 tDataSequenceContainer aOldDataSequences
;
457 tDataSequenceContainer aNewDataSequences
;
458 Reference
< util::XModifyListener
> xModifyEventForwarder
;
459 Reference
< lang::XEventListener
> xListener
;
461 MutexGuard
aGuard( GetMutex() );
462 xModifyEventForwarder
= m_xModifyEventForwarder
;
464 std::swap( aOldDataSequences
, m_aDataSequences
);
465 aNewDataSequences
= ContainerHelper::SequenceToVector( aData
);
466 m_aDataSequences
= aNewDataSequences
;
468 ModifyListenerHelper::removeListenerFromAllElements( aOldDataSequences
, xModifyEventForwarder
);
469 EventListenerHelper::removeListenerFromAllElements( aOldDataSequences
, xListener
);
470 EventListenerHelper::addListenerToAllElements( aNewDataSequences
, xListener
);
471 ModifyListenerHelper::addListenerToAllElements( aNewDataSequences
, xModifyEventForwarder
);
475 // ____ XDataSource ____
476 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > SAL_CALL
DataSeries::getDataSequences()
477 throw (uno::RuntimeException
)
479 MutexGuard
aGuard( GetMutex() );
480 return ContainerHelper::ContainerToSequence( m_aDataSequences
);
484 // ____ XRegressionCurveContainer ____
485 void SAL_CALL
DataSeries::addRegressionCurve(
486 const uno::Reference
< chart2::XRegressionCurve
>& xRegressionCurve
)
487 throw (lang::IllegalArgumentException
,
488 uno::RuntimeException
)
490 Reference
< util::XModifyListener
> xModifyEventForwarder
;
492 MutexGuard
aGuard( GetMutex() );
493 xModifyEventForwarder
= m_xModifyEventForwarder
;
494 if( ::std::find( m_aRegressionCurves
.begin(), m_aRegressionCurves
.end(), xRegressionCurve
)
495 != m_aRegressionCurves
.end())
496 throw lang::IllegalArgumentException();
497 m_aRegressionCurves
.push_back( xRegressionCurve
);
499 ModifyListenerHelper::addListener( xRegressionCurve
, xModifyEventForwarder
);
503 void SAL_CALL
DataSeries::removeRegressionCurve(
504 const uno::Reference
< chart2::XRegressionCurve
>& xRegressionCurve
)
505 throw (container::NoSuchElementException
,
506 uno::RuntimeException
)
508 if( !xRegressionCurve
.is() )
509 throw container::NoSuchElementException();
511 Reference
< util::XModifyListener
> xModifyEventForwarder
;
513 MutexGuard
aGuard( GetMutex() );
514 xModifyEventForwarder
= m_xModifyEventForwarder
;
515 tRegressionCurveContainerType::iterator
aIt(
516 ::std::find( m_aRegressionCurves
.begin(), m_aRegressionCurves
.end(), xRegressionCurve
) );
517 if( aIt
== m_aRegressionCurves
.end())
518 throw container::NoSuchElementException(
519 C2U( "The given regression curve is no element of this series" ),
520 static_cast< uno::XWeak
* >( this ));
521 m_aRegressionCurves
.erase( aIt
);
524 ModifyListenerHelper::removeListener( xRegressionCurve
, xModifyEventForwarder
);
528 uno::Sequence
< uno::Reference
< chart2::XRegressionCurve
> > SAL_CALL
DataSeries::getRegressionCurves()
529 throw (uno::RuntimeException
)
531 MutexGuard
aGuard( GetMutex() );
532 return ContainerHelper::ContainerToSequence( m_aRegressionCurves
);
535 void SAL_CALL
DataSeries::setRegressionCurves(
536 const Sequence
< Reference
< chart2::XRegressionCurve
> >& aRegressionCurves
)
537 throw (uno::RuntimeException
)
539 tRegressionCurveContainerType aOldCurves
;
540 tRegressionCurveContainerType
aNewCurves( ContainerHelper::SequenceToVector( aRegressionCurves
) );
541 Reference
< util::XModifyListener
> xModifyEventForwarder
;
543 MutexGuard
aGuard( GetMutex() );
544 xModifyEventForwarder
= m_xModifyEventForwarder
;
545 std::swap( aOldCurves
, m_aRegressionCurves
);
546 m_aRegressionCurves
= aNewCurves
;
548 ModifyListenerHelper::removeListenerFromAllElements( aOldCurves
, xModifyEventForwarder
);
549 ModifyListenerHelper::addListenerToAllElements( aNewCurves
, xModifyEventForwarder
);
553 // ____ XModifyBroadcaster ____
554 void SAL_CALL
DataSeries::addModifyListener( const Reference
< util::XModifyListener
>& aListener
)
555 throw (uno::RuntimeException
)
559 Reference
< util::XModifyBroadcaster
> xBroadcaster( m_xModifyEventForwarder
, uno::UNO_QUERY_THROW
);
560 xBroadcaster
->addModifyListener( aListener
);
562 catch( const uno::Exception
& ex
)
564 ASSERT_EXCEPTION( ex
);
568 void SAL_CALL
DataSeries::removeModifyListener( const Reference
< util::XModifyListener
>& aListener
)
569 throw (uno::RuntimeException
)
573 Reference
< util::XModifyBroadcaster
> xBroadcaster( m_xModifyEventForwarder
, uno::UNO_QUERY_THROW
);
574 xBroadcaster
->removeModifyListener( aListener
);
576 catch( const uno::Exception
& ex
)
578 ASSERT_EXCEPTION( ex
);
582 // ____ XModifyListener ____
583 void SAL_CALL
DataSeries::modified( const lang::EventObject
& aEvent
)
584 throw (uno::RuntimeException
)
586 m_xModifyEventForwarder
->modified( aEvent
);
589 // ____ XEventListener (base of XModifyListener) ____
590 void SAL_CALL
DataSeries::disposing( const lang::EventObject
& rEventObject
)
591 throw (uno::RuntimeException
)
593 // forget disposed data sequences
594 tDataSequenceContainer::iterator
aIt(
595 ::std::find( m_aDataSequences
.begin(), m_aDataSequences
.end(), rEventObject
.Source
));
596 if( aIt
!= m_aDataSequences
.end())
597 m_aDataSequences
.erase( aIt
);
600 // ____ OPropertySet ____
601 void DataSeries::firePropertyChangeEvent()
606 void DataSeries::fireModifyEvent()
608 m_xModifyEventForwarder
->modified( lang::EventObject( static_cast< uno::XWeak
* >( this )));
612 // ================================================================================
614 using impl::DataSeries_Base
;
615 using ::property::OPropertySet
;
617 IMPLEMENT_FORWARD_XINTERFACE2( DataSeries
, DataSeries_Base
, OPropertySet
)
618 IMPLEMENT_FORWARD_XTYPEPROVIDER2( DataSeries
, DataSeries_Base
, OPropertySet
)
620 // implement XServiceInfo methods basing upon getSupportedServiceNames_Static
621 APPHELPER_XSERVICEINFO_IMPL( DataSeries
,
622 C2U( "com.sun.star.comp.chart.DataSeries" ));