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 // ____ XDataSink ____
423 void SAL_CALL
DataSeries::setData( const uno::Sequence
< Reference
< chart2::data::XLabeledDataSequence
> >& aData
)
424 throw (uno::RuntimeException
)
427 MutexGuard
aGuard( GetMutex() );
428 ModifyListenerHelper::removeListenerFromAllElements( m_aDataSequences
, m_xModifyEventForwarder
);
429 EventListenerHelper::removeListenerFromAllElements( m_aDataSequences
, this );
430 m_aDataSequences
= ContainerHelper::SequenceToVector( aData
);
431 EventListenerHelper::addListenerToAllElements( m_aDataSequences
, this );
432 ModifyListenerHelper::addListenerToAllElements( m_aDataSequences
, m_xModifyEventForwarder
);
437 // ____ XDataSource ____
438 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > SAL_CALL
DataSeries::getDataSequences()
439 throw (uno::RuntimeException
)
442 MutexGuard
aGuard( GetMutex() );
443 return ContainerHelper::ContainerToSequence( m_aDataSequences
);
448 // ____ XRegressionCurveContainer ____
449 void SAL_CALL
DataSeries::addRegressionCurve(
450 const uno::Reference
< chart2::XRegressionCurve
>& xRegressionCurve
)
451 throw (lang::IllegalArgumentException
,
452 uno::RuntimeException
)
454 if( ::std::find( m_aRegressionCurves
.begin(), m_aRegressionCurves
.end(), xRegressionCurve
)
455 != m_aRegressionCurves
.end())
456 throw lang::IllegalArgumentException();
458 m_aRegressionCurves
.push_back( xRegressionCurve
);
459 ModifyListenerHelper::addListener( xRegressionCurve
, m_xModifyEventForwarder
);
463 void SAL_CALL
DataSeries::removeRegressionCurve(
464 const uno::Reference
< chart2::XRegressionCurve
>& xRegressionCurve
)
465 throw (container::NoSuchElementException
,
466 uno::RuntimeException
)
468 if( ! xRegressionCurve
.is())
469 throw container::NoSuchElementException();
471 tRegressionCurveContainerType::iterator
aIt(
472 ::std::find( m_aRegressionCurves
.begin(), m_aRegressionCurves
.end(), xRegressionCurve
) );
474 if( aIt
== m_aRegressionCurves
.end())
475 throw container::NoSuchElementException(
476 C2U( "The given regression curve is no element of this series" ),
477 static_cast< uno::XWeak
* >( this ));
479 ModifyListenerHelper::removeListener( xRegressionCurve
, m_xModifyEventForwarder
);
480 m_aRegressionCurves
.erase( aIt
);
484 uno::Sequence
< uno::Reference
< chart2::XRegressionCurve
> > SAL_CALL
DataSeries::getRegressionCurves()
485 throw (uno::RuntimeException
)
487 return ContainerHelper::ContainerToSequence( m_aRegressionCurves
);
490 void SAL_CALL
DataSeries::setRegressionCurves(
491 const Sequence
< Reference
< chart2::XRegressionCurve
> >& aRegressionCurves
)
492 throw (uno::RuntimeException
)
494 ModifyListenerHelper::removeListenerFromAllElements( m_aRegressionCurves
, m_xModifyEventForwarder
);
495 m_aRegressionCurves
.clear();
496 for( sal_Int32 i
=0; i
<aRegressionCurves
.getLength(); ++i
)
497 addRegressionCurve( aRegressionCurves
[i
] );
500 // ____ XModifyBroadcaster ____
501 void SAL_CALL
DataSeries::addModifyListener( const Reference
< util::XModifyListener
>& aListener
)
502 throw (uno::RuntimeException
)
506 Reference
< util::XModifyBroadcaster
> xBroadcaster( m_xModifyEventForwarder
, uno::UNO_QUERY_THROW
);
507 xBroadcaster
->addModifyListener( aListener
);
509 catch( const uno::Exception
& ex
)
511 ASSERT_EXCEPTION( ex
);
515 void SAL_CALL
DataSeries::removeModifyListener( const Reference
< util::XModifyListener
>& aListener
)
516 throw (uno::RuntimeException
)
520 Reference
< util::XModifyBroadcaster
> xBroadcaster( m_xModifyEventForwarder
, uno::UNO_QUERY_THROW
);
521 xBroadcaster
->removeModifyListener( aListener
);
523 catch( const uno::Exception
& ex
)
525 ASSERT_EXCEPTION( ex
);
529 // ____ XModifyListener ____
530 void SAL_CALL
DataSeries::modified( const lang::EventObject
& aEvent
)
531 throw (uno::RuntimeException
)
533 m_xModifyEventForwarder
->modified( aEvent
);
536 // ____ XEventListener (base of XModifyListener) ____
537 void SAL_CALL
DataSeries::disposing( const lang::EventObject
& rEventObject
)
538 throw (uno::RuntimeException
)
540 // forget disposed data sequences
541 tDataSequenceContainer::iterator
aIt(
542 ::std::find( m_aDataSequences
.begin(), m_aDataSequences
.end(), rEventObject
.Source
));
543 if( aIt
!= m_aDataSequences
.end())
544 m_aDataSequences
.erase( aIt
);
547 // ____ OPropertySet ____
548 void DataSeries::firePropertyChangeEvent()
553 void DataSeries::fireModifyEvent()
555 m_xModifyEventForwarder
->modified( lang::EventObject( static_cast< uno::XWeak
* >( this )));
559 // ================================================================================
561 using impl::DataSeries_Base
;
562 using ::property::OPropertySet
;
564 IMPLEMENT_FORWARD_XINTERFACE2( DataSeries
, DataSeries_Base
, OPropertySet
)
565 IMPLEMENT_FORWARD_XTYPEPROVIDER2( DataSeries
, DataSeries_Base
, OPropertySet
)
567 // implement XServiceInfo methods basing upon getSupportedServiceNames_Static
568 APPHELPER_XSERVICEINFO_IMPL( DataSeries
,
569 C2U( "com.sun.star.comp.chart.DataSeries" ));