merge the formfield patch from ooo-build
[ooovba.git] / chart2 / source / model / main / DataSeries.cxx
blobab6d1bcea978d6b011d88765b6665190e3027233
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: DataSeries.cxx,v $
10 * $Revision: 1.11 $
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"
39 #include "macros.hxx"
40 #include "DataSeriesHelper.hxx"
41 #include "ContainerHelper.hxx"
42 #include "CloneHelper.hxx"
43 #include "ModifyListenerHelper.hxx"
44 #include "EventListenerHelper.hxx"
46 #include <algorithm>
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 // ----------------------------------------
59 namespace
61 const uno::Sequence< Property > & lcl_GetPropertySequence()
63 static uno::Sequence< Property > aPropSeq;
65 // /--
66 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
67 if( 0 == aPropSeq.getLength() )
69 // get properties
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 );
83 return aPropSeq;
86 void lcl_SetParent(
87 const uno::Reference< uno::XInterface > & xChildInterface,
88 const uno::Reference< uno::XInterface > & xParentInterface )
90 uno::Reference< container::XChild > xChild( xChildInterface, uno::UNO_QUERY );
91 if( xChild.is())
92 xChild->setParent( xParentInterface );
95 typedef ::std::map< sal_Int32, ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > >
96 lcl_tDataPointMap;
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 );
106 if( xPoint.is())
108 Reference< util::XCloneable > xCloneable( xPoint, uno::UNO_QUERY );
109 if( xCloneable.is())
111 xPoint.set( xCloneable->createClone(), uno::UNO_QUERY );
112 if( xPoint.is())
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 // ----------------------------------------
133 namespace chart
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 ) :
144 MutexContainer(),
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 );
155 else
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;
165 uno::Any aValue;
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;
194 uno::Any aValue;
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;
217 uno::Any aValue;
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 );
245 return xResult;
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" );
254 return aServices;
257 // ____ OPropertySet ____
258 uno::Any DataSeries::GetDefaultValue( sal_Int32 nHandle ) const
259 throw(beans::UnknownPropertyException)
261 static tPropertyValueMap aStaticDefaults;
263 // /--
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;
284 // \--
287 // ____ OPropertySet ____
288 ::cppu::IPropertyArrayHelper & SAL_CALL DataSeries::getInfoHelper()
290 static ::cppu::OPropertyArrayHelper aArrayHelper(
291 lcl_GetPropertySequence(),
292 /* bSorted = */ sal_True );
294 return aArrayHelper;
298 // ____ XPropertySet ____
299 uno::Reference< beans::XPropertySetInfo > SAL_CALL
300 DataSeries::getPropertySetInfo()
301 throw (uno::RuntimeException)
303 static uno::Reference< beans::XPropertySetInfo > xInfo;
305 // /--
306 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
307 if( !xInfo.is())
309 xInfo = ::cppu::OPropertySetHelper::createPropertySetInfo(
310 getInfoHelper());
313 return xInfo;
314 // \--
317 void SAL_CALL DataSeries::getFastPropertyValue
318 ( uno::Any& rValue,
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();
327 sal_Int32 i = 0;
329 for( tDataPointAttributeContainer::const_iterator aIt( m_aAttributedDataPoints.begin());
330 aIt != m_aAttributedDataPoints.end(); ++aIt )
332 pIndexArray[ i ] = (*aIt).first;
333 ++i;
336 rValue <<= aSeq;
338 else
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 )
349 uno::Any aOldValue;
350 Reference< util::XModifyBroadcaster > xBroadcaster;
351 this->getFastPropertyValue( aOldValue, nHandle );
352 if( aOldValue.hasValue() &&
353 (aOldValue >>= xBroadcaster) &&
354 xBroadcaster.is())
356 ModifyListenerHelper::removeListener( xBroadcaster, m_xModifyEventForwarder );
359 OSL_ASSERT( rValue.getValueType().getTypeClass() == uno::TypeClass_INTERFACE );
360 if( rValue.hasValue() &&
361 (rValue >>= xBroadcaster) &&
362 xBroadcaster.is())
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;
378 // /--
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;
402 else
404 aResult = (*aIt).second;
408 else
410 throw lang::IndexOutOfBoundsException();
413 else
415 throw lang::IndexOutOfBoundsException();
418 return aResult;
419 // \--
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);
434 fireModifyEvent();
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();
444 fireModifyEvent();
447 // ____ XDataSink ____
448 void SAL_CALL DataSeries::setData( const uno::Sequence< Reference< chart2::data::XLabeledDataSequence > >& aData )
449 throw (uno::RuntimeException)
451 // /--
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 );
458 fireModifyEvent();
459 // \--
462 // ____ XDataSource ____
463 Sequence< Reference< chart2::data::XLabeledDataSequence > > SAL_CALL DataSeries::getDataSequences()
464 throw (uno::RuntimeException)
466 // /--
467 MutexGuard aGuard( GetMutex() );
468 return ContainerHelper::ContainerToSequence( m_aDataSequences );
469 // \--
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 );
485 fireModifyEvent();
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 );
506 fireModifyEvent();
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()
575 fireModifyEvent();
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" ));
596 } // namespace chart