1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: DataSeries.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_chart2.hxx"
33 #include "DataSeries.hxx"
34 #include "DataSeriesProperties.hxx"
35 #include "DataPointProperties.hxx"
36 #include "CharacterProperties.hxx"
37 #include "UserDefinedProperties.hxx"
38 #include "DataPoint.hxx"
40 #include "DataSeriesHelper.hxx"
41 #include "ContainerHelper.hxx"
42 #include "CloneHelper.hxx"
43 #include "ModifyListenerHelper.hxx"
44 #include "EventListenerHelper.hxx"
48 using namespace ::com::sun::star
;
50 using ::com::sun::star::beans::Property
;
51 using ::com::sun::star::uno::Sequence
;
52 using ::com::sun::star::uno::Reference
;
53 using ::com::sun::star::uno::Any
;
54 using ::rtl::OUString
;
55 using ::osl::MutexGuard
;
57 // ----------------------------------------
61 const uno::Sequence
< Property
> & lcl_GetPropertySequence()
63 static uno::Sequence
< Property
> aPropSeq
;
66 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
67 if( 0 == aPropSeq
.getLength() )
70 ::std::vector
< ::com::sun::star::beans::Property
> aProperties
;
71 ::chart::DataSeriesProperties::AddPropertiesToVector( aProperties
);
72 ::chart::CharacterProperties::AddPropertiesToVector( aProperties
);
73 ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties
);
75 // and sort them for access via bsearch
76 ::std::sort( aProperties
.begin(), aProperties
.end(),
77 ::chart::PropertyNameLess() );
79 // transfer result to static Sequence
80 aPropSeq
= ::chart::ContainerHelper::ContainerToSequence( aProperties
);
87 const uno::Reference
< uno::XInterface
> & xChildInterface
,
88 const uno::Reference
< uno::XInterface
> & xParentInterface
)
90 uno::Reference
< container::XChild
> xChild( xChildInterface
, uno::UNO_QUERY
);
92 xChild
->setParent( xParentInterface
);
95 typedef ::std::map
< sal_Int32
, ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertySet
> >
98 void lcl_CloneAttributedDataPoints(
99 const lcl_tDataPointMap
& rSource
, lcl_tDataPointMap
& rDestination
,
100 const uno::Reference
< uno::XInterface
> & xSeries
)
102 for( lcl_tDataPointMap::const_iterator
aIt( rSource
.begin());
103 aIt
!= rSource
.end(); ++aIt
)
105 Reference
< beans::XPropertySet
> xPoint( (*aIt
).second
);
108 Reference
< util::XCloneable
> xCloneable( xPoint
, uno::UNO_QUERY
);
111 xPoint
.set( xCloneable
->createClone(), uno::UNO_QUERY
);
114 lcl_SetParent( xPoint
, xSeries
);
115 rDestination
.insert( lcl_tDataPointMap::value_type( (*aIt
).first
, xPoint
));
122 bool lcl_isInternalData( const Reference
< chart2::data::XLabeledDataSequence
> & xLSeq
)
124 Reference
< lang::XServiceInfo
> xServiceInfo( xLSeq
, uno::UNO_QUERY
);
125 return ( xServiceInfo
.is() && xServiceInfo
->getImplementationName().equalsAsciiL(
126 RTL_CONSTASCII_STRINGPARAM("com.sun.star.comp.chart2.LabeledDataSequence")));
129 } // anonymous namespace
131 // ----------------------------------------
136 DataSeries::DataSeries( const uno::Reference
< uno::XComponentContext
> & xContext
) :
137 ::property::OPropertySet( m_aMutex
),
138 m_xContext( xContext
),
139 m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder())
143 DataSeries::DataSeries( const DataSeries
& rOther
) :
145 impl::DataSeries_Base(),
146 ::property::OPropertySet( rOther
, m_aMutex
),
147 m_xContext( rOther
.m_xContext
),
148 m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder())
150 if( ! rOther
.m_aDataSequences
.empty())
152 if( lcl_isInternalData( rOther
.m_aDataSequences
.front()))
153 CloneHelper::CloneRefVector
< tDataSequenceContainer::value_type
>(
154 rOther
.m_aDataSequences
, m_aDataSequences
);
156 m_aDataSequences
= rOther
.m_aDataSequences
;
157 ModifyListenerHelper::addListenerToAllElements( m_aDataSequences
, m_xModifyEventForwarder
);
160 CloneHelper::CloneRefVector
< Reference
< chart2::XRegressionCurve
> >( rOther
.m_aRegressionCurves
, m_aRegressionCurves
);
161 ModifyListenerHelper::addListenerToAllElements( m_aRegressionCurves
, m_xModifyEventForwarder
);
163 // add as listener to XPropertySet properties
164 Reference
< beans::XPropertySet
> xPropertySet
;
167 getFastPropertyValue( aValue
, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X
);
168 if( ( aValue
>>= xPropertySet
)
169 && xPropertySet
.is())
170 ModifyListenerHelper::addListener( xPropertySet
, m_xModifyEventForwarder
);
172 getFastPropertyValue( aValue
, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y
);
173 if( ( aValue
>>= xPropertySet
)
174 && xPropertySet
.is())
175 ModifyListenerHelper::addListener( xPropertySet
, m_xModifyEventForwarder
);
178 // late initialization to call after copy-constructing
179 void DataSeries::Init( const DataSeries
& rOther
)
181 if( ! rOther
.m_aDataSequences
.empty())
182 EventListenerHelper::addListenerToAllElements( m_aDataSequences
, this );
184 Reference
< uno::XInterface
> xThisInterface( static_cast< ::cppu::OWeakObject
* >( this ));
185 if( ! rOther
.m_aAttributedDataPoints
.empty())
187 lcl_CloneAttributedDataPoints(
188 rOther
.m_aAttributedDataPoints
, m_aAttributedDataPoints
, xThisInterface
);
189 ModifyListenerHelper::addListenerToAllMapElements( m_aAttributedDataPoints
, m_xModifyEventForwarder
);
192 // add as parent to error bars
193 Reference
< beans::XPropertySet
> xPropertySet
;
196 getFastPropertyValue( aValue
, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X
);
197 if( ( aValue
>>= xPropertySet
)
198 && xPropertySet
.is())
199 lcl_SetParent( xPropertySet
, xThisInterface
);
201 getFastPropertyValue( aValue
, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y
);
202 if( ( aValue
>>= xPropertySet
)
203 && xPropertySet
.is())
204 lcl_SetParent( xPropertySet
, xThisInterface
);
207 DataSeries::~DataSeries()
211 ModifyListenerHelper::removeListenerFromAllMapElements( m_aAttributedDataPoints
, m_xModifyEventForwarder
);
212 ModifyListenerHelper::removeListenerFromAllElements( m_aRegressionCurves
, m_xModifyEventForwarder
);
213 ModifyListenerHelper::removeListenerFromAllElements( m_aDataSequences
, m_xModifyEventForwarder
);
215 // remove listener from XPropertySet properties
216 Reference
< beans::XPropertySet
> xPropertySet
;
219 getFastPropertyValue( aValue
, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X
);
220 if( ( aValue
>>= xPropertySet
)
221 && xPropertySet
.is())
222 ModifyListenerHelper::removeListener( xPropertySet
, m_xModifyEventForwarder
);
224 getFastPropertyValue( aValue
, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y
);
225 if( ( aValue
>>= xPropertySet
)
226 && xPropertySet
.is())
227 ModifyListenerHelper::removeListener( xPropertySet
, m_xModifyEventForwarder
);
229 catch( const uno::Exception
& ex
)
231 ASSERT_EXCEPTION( ex
);
235 // ____ XCloneable ____
236 uno::Reference
< util::XCloneable
> SAL_CALL
DataSeries::createClone()
237 throw (uno::RuntimeException
)
239 DataSeries
* pNewSeries( new DataSeries( *this ));
240 // hold a reference to the clone
241 uno::Reference
< util::XCloneable
> xResult( pNewSeries
);
242 // do initialization that uses uno references to the clone
243 pNewSeries
->Init( *this );
248 Sequence
< OUString
> DataSeries::getSupportedServiceNames_Static()
250 Sequence
< OUString
> aServices( 3 );
251 aServices
[ 0 ] = C2U( "com.sun.star.chart2.DataSeries" );
252 aServices
[ 1 ] = C2U( "com.sun.star.chart2.DataPointProperties" );
253 aServices
[ 2 ] = C2U( "com.sun.star.beans.PropertySet" );
257 // ____ OPropertySet ____
258 uno::Any
DataSeries::GetDefaultValue( sal_Int32 nHandle
) const
259 throw(beans::UnknownPropertyException
)
261 static tPropertyValueMap aStaticDefaults
;
264 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
265 if( 0 == aStaticDefaults
.size() )
267 // initialize defaults
268 DataSeriesProperties::AddDefaultsToMap( aStaticDefaults
);
269 CharacterProperties::AddDefaultsToMap( aStaticDefaults
);
271 float fDefaultCharHeight
= 6.0;
272 ::chart::PropertyHelper::setPropertyValue( aStaticDefaults
, ::chart::CharacterProperties::PROP_CHAR_CHAR_HEIGHT
, fDefaultCharHeight
);
273 ::chart::PropertyHelper::setPropertyValue( aStaticDefaults
, ::chart::CharacterProperties::PROP_CHAR_ASIAN_CHAR_HEIGHT
, fDefaultCharHeight
);
274 ::chart::PropertyHelper::setPropertyValue( aStaticDefaults
, ::chart::CharacterProperties::PROP_CHAR_COMPLEX_CHAR_HEIGHT
, fDefaultCharHeight
);
277 tPropertyValueMap::const_iterator
aFound(
278 aStaticDefaults
.find( nHandle
));
280 if( aFound
== aStaticDefaults
.end())
281 throw beans::UnknownPropertyException();
283 return (*aFound
).second
;
287 // ____ OPropertySet ____
288 ::cppu::IPropertyArrayHelper
& SAL_CALL
DataSeries::getInfoHelper()
290 static ::cppu::OPropertyArrayHelper
aArrayHelper(
291 lcl_GetPropertySequence(),
292 /* bSorted = */ sal_True
);
298 // ____ XPropertySet ____
299 uno::Reference
< beans::XPropertySetInfo
> SAL_CALL
300 DataSeries::getPropertySetInfo()
301 throw (uno::RuntimeException
)
303 static uno::Reference
< beans::XPropertySetInfo
> xInfo
;
306 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
309 xInfo
= ::cppu::OPropertySetHelper::createPropertySetInfo(
317 void SAL_CALL
DataSeries::getFastPropertyValue
319 sal_Int32 nHandle
) const
321 // special handling for get. set is not possible for this property
322 if( nHandle
== DataSeriesProperties::PROP_DATASERIES_ATTRIBUTED_DATA_POINTS
)
324 // ToDo: only add those property sets that are really modified
325 uno::Sequence
< sal_Int32
> aSeq( m_aAttributedDataPoints
.size());
326 sal_Int32
* pIndexArray
= aSeq
.getArray();
329 for( tDataPointAttributeContainer::const_iterator
aIt( m_aAttributedDataPoints
.begin());
330 aIt
!= m_aAttributedDataPoints
.end(); ++aIt
)
332 pIndexArray
[ i
] = (*aIt
).first
;
339 OPropertySet::getFastPropertyValue( rValue
, nHandle
);
342 void SAL_CALL
DataSeries::setFastPropertyValue_NoBroadcast(
343 sal_Int32 nHandle
, const uno::Any
& rValue
)
344 throw (uno::Exception
)
346 if( nHandle
== DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y
347 || nHandle
== DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X
)
350 Reference
< util::XModifyBroadcaster
> xBroadcaster
;
351 this->getFastPropertyValue( aOldValue
, nHandle
);
352 if( aOldValue
.hasValue() &&
353 (aOldValue
>>= xBroadcaster
) &&
356 ModifyListenerHelper::removeListener( xBroadcaster
, m_xModifyEventForwarder
);
359 OSL_ASSERT( rValue
.getValueType().getTypeClass() == uno::TypeClass_INTERFACE
);
360 if( rValue
.hasValue() &&
361 (rValue
>>= xBroadcaster
) &&
364 ModifyListenerHelper::addListener( xBroadcaster
, m_xModifyEventForwarder
);
368 ::property::OPropertySet::setFastPropertyValue_NoBroadcast( nHandle
, rValue
);
371 Reference
< beans::XPropertySet
>
372 SAL_CALL
DataSeries::getDataPointByIndex( sal_Int32 nIndex
)
373 throw (lang::IndexOutOfBoundsException
,
374 uno::RuntimeException
)
376 Reference
< beans::XPropertySet
> aResult
;
379 MutexGuard
aGuard( GetMutex() );
381 if( ! m_aDataSequences
.empty() )
383 ::std::vector
< Reference
< chart2::data::XLabeledDataSequence
> > aValuesSeries(
384 DataSeriesHelper::getAllDataSequencesByRole(
385 ContainerHelper::ContainerToSequence( m_aDataSequences
),
386 C2U("values"), true ));
387 if( ! aValuesSeries
.empty())
389 Reference
< chart2::data::XDataSequence
> xSeq( aValuesSeries
.front()->getValues());
390 if( 0 <= nIndex
&& nIndex
< xSeq
->getData().getLength())
392 tDataPointAttributeContainer::iterator
aIt(
393 m_aAttributedDataPoints
.find( nIndex
));
395 if( aIt
== m_aAttributedDataPoints
.end())
397 // create a new XPropertySet for this data point
398 aResult
.set( new DataPoint( this ));
399 ModifyListenerHelper::addListener( aResult
, m_xModifyEventForwarder
);
400 m_aAttributedDataPoints
[ nIndex
] = aResult
;
404 aResult
= (*aIt
).second
;
410 throw lang::IndexOutOfBoundsException();
415 throw lang::IndexOutOfBoundsException();
422 void SAL_CALL
DataSeries::resetDataPoint( sal_Int32 nIndex
)
423 throw (uno::RuntimeException
)
425 MutexGuard
aGuard( GetMutex() );
426 tDataPointAttributeContainer::iterator
aIt( m_aAttributedDataPoints
.find( nIndex
));
427 if( aIt
!= m_aAttributedDataPoints
.end())
429 Reference
< beans::XPropertySet
> xDataPointProp( (*aIt
).second
);
430 Reference
< util::XModifyBroadcaster
> xBroadcaster( xDataPointProp
, uno::UNO_QUERY
);
431 if( xBroadcaster
.is() && m_xModifyEventForwarder
.is())
432 xBroadcaster
->removeModifyListener( m_xModifyEventForwarder
);
433 m_aAttributedDataPoints
.erase(aIt
);
438 void SAL_CALL
DataSeries::resetAllDataPoints()
439 throw (uno::RuntimeException
)
441 MutexGuard
aGuard( GetMutex() );
442 ModifyListenerHelper::removeListenerFromAllMapElements( m_aAttributedDataPoints
, m_xModifyEventForwarder
);
443 m_aAttributedDataPoints
.clear();
447 // ____ XDataSink ____
448 void SAL_CALL
DataSeries::setData( const uno::Sequence
< Reference
< chart2::data::XLabeledDataSequence
> >& aData
)
449 throw (uno::RuntimeException
)
452 MutexGuard
aGuard( GetMutex() );
453 ModifyListenerHelper::removeListenerFromAllElements( m_aDataSequences
, m_xModifyEventForwarder
);
454 EventListenerHelper::removeListenerFromAllElements( m_aDataSequences
, this );
455 m_aDataSequences
= ContainerHelper::SequenceToVector( aData
);
456 EventListenerHelper::addListenerToAllElements( m_aDataSequences
, this );
457 ModifyListenerHelper::addListenerToAllElements( m_aDataSequences
, m_xModifyEventForwarder
);
462 // ____ XDataSource ____
463 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > SAL_CALL
DataSeries::getDataSequences()
464 throw (uno::RuntimeException
)
467 MutexGuard
aGuard( GetMutex() );
468 return ContainerHelper::ContainerToSequence( m_aDataSequences
);
473 // ____ XRegressionCurveContainer ____
474 void SAL_CALL
DataSeries::addRegressionCurve(
475 const uno::Reference
< chart2::XRegressionCurve
>& xRegressionCurve
)
476 throw (lang::IllegalArgumentException
,
477 uno::RuntimeException
)
479 if( ::std::find( m_aRegressionCurves
.begin(), m_aRegressionCurves
.end(), xRegressionCurve
)
480 != m_aRegressionCurves
.end())
481 throw lang::IllegalArgumentException();
483 m_aRegressionCurves
.push_back( xRegressionCurve
);
484 ModifyListenerHelper::addListener( xRegressionCurve
, m_xModifyEventForwarder
);
488 void SAL_CALL
DataSeries::removeRegressionCurve(
489 const uno::Reference
< chart2::XRegressionCurve
>& xRegressionCurve
)
490 throw (container::NoSuchElementException
,
491 uno::RuntimeException
)
493 if( ! xRegressionCurve
.is())
494 throw container::NoSuchElementException();
496 tRegressionCurveContainerType::iterator
aIt(
497 ::std::find( m_aRegressionCurves
.begin(), m_aRegressionCurves
.end(), xRegressionCurve
) );
499 if( aIt
== m_aRegressionCurves
.end())
500 throw container::NoSuchElementException(
501 C2U( "The given regression curve is no element of this series" ),
502 static_cast< uno::XWeak
* >( this ));
504 ModifyListenerHelper::removeListener( xRegressionCurve
, m_xModifyEventForwarder
);
505 m_aRegressionCurves
.erase( aIt
);
509 uno::Sequence
< uno::Reference
< chart2::XRegressionCurve
> > SAL_CALL
DataSeries::getRegressionCurves()
510 throw (uno::RuntimeException
)
512 return ContainerHelper::ContainerToSequence( m_aRegressionCurves
);
515 void SAL_CALL
DataSeries::setRegressionCurves(
516 const Sequence
< Reference
< chart2::XRegressionCurve
> >& aRegressionCurves
)
517 throw (uno::RuntimeException
)
519 ModifyListenerHelper::removeListenerFromAllElements( m_aRegressionCurves
, m_xModifyEventForwarder
);
520 m_aRegressionCurves
.clear();
521 for( sal_Int32 i
=0; i
<aRegressionCurves
.getLength(); ++i
)
522 addRegressionCurve( aRegressionCurves
[i
] );
525 // ____ XModifyBroadcaster ____
526 void SAL_CALL
DataSeries::addModifyListener( const Reference
< util::XModifyListener
>& aListener
)
527 throw (uno::RuntimeException
)
531 Reference
< util::XModifyBroadcaster
> xBroadcaster( m_xModifyEventForwarder
, uno::UNO_QUERY_THROW
);
532 xBroadcaster
->addModifyListener( aListener
);
534 catch( const uno::Exception
& ex
)
536 ASSERT_EXCEPTION( ex
);
540 void SAL_CALL
DataSeries::removeModifyListener( const Reference
< util::XModifyListener
>& aListener
)
541 throw (uno::RuntimeException
)
545 Reference
< util::XModifyBroadcaster
> xBroadcaster( m_xModifyEventForwarder
, uno::UNO_QUERY_THROW
);
546 xBroadcaster
->removeModifyListener( aListener
);
548 catch( const uno::Exception
& ex
)
550 ASSERT_EXCEPTION( ex
);
554 // ____ XModifyListener ____
555 void SAL_CALL
DataSeries::modified( const lang::EventObject
& aEvent
)
556 throw (uno::RuntimeException
)
558 m_xModifyEventForwarder
->modified( aEvent
);
561 // ____ XEventListener (base of XModifyListener) ____
562 void SAL_CALL
DataSeries::disposing( const lang::EventObject
& rEventObject
)
563 throw (uno::RuntimeException
)
565 // forget disposed data sequences
566 tDataSequenceContainer::iterator
aIt(
567 ::std::find( m_aDataSequences
.begin(), m_aDataSequences
.end(), rEventObject
.Source
));
568 if( aIt
!= m_aDataSequences
.end())
569 m_aDataSequences
.erase( aIt
);
572 // ____ OPropertySet ____
573 void DataSeries::firePropertyChangeEvent()
578 void DataSeries::fireModifyEvent()
580 m_xModifyEventForwarder
->modified( lang::EventObject( static_cast< uno::XWeak
* >( this )));
584 // ================================================================================
586 using impl::DataSeries_Base
;
587 using ::property::OPropertySet
;
589 IMPLEMENT_FORWARD_XINTERFACE2( DataSeries
, DataSeries_Base
, OPropertySet
)
590 IMPLEMENT_FORWARD_XTYPEPROVIDER2( DataSeries
, DataSeries_Base
, OPropertySet
)
592 // implement XServiceInfo methods basing upon getSupportedServiceNames_Static
593 APPHELPER_XSERVICEINFO_IMPL( DataSeries
,
594 C2U( "com.sun.star.comp.chart.DataSeries" ));