diff options
Diffstat (limited to 'chart2/source/model/main/DataSeries.cxx')
-rw-r--r-- | chart2/source/model/main/DataSeries.cxx | 700 |
1 files changed, 594 insertions, 106 deletions
diff --git a/chart2/source/model/main/DataSeries.cxx b/chart2/source/model/main/DataSeries.cxx index b873c19650b9..a9843f1d423d 100644 --- a/chart2/source/model/main/DataSeries.cxx +++ b/chart2/source/model/main/DataSeries.cxx @@ -18,20 +18,26 @@ */ #include <DataSeries.hxx> -#include "DataSeriesProperties.hxx" +#include <DataSeriesProperties.hxx> #include "DataPointProperties.hxx" #include <CharacterProperties.hxx> #include <UserDefinedProperties.hxx> #include "DataPoint.hxx" #include <DataSeriesHelper.hxx> #include <CloneHelper.hxx> +#include <RegressionCurveModel.hxx> #include <ModifyListenerHelper.hxx> -#include <EventListenerHelper.hxx> +#include <unonames.hxx> +#include <com/sun/star/chart2/DataPointLabel.hpp> +#include <com/sun/star/chart2/Symbol.hpp> +#include <com/sun/star/chart2/data/XTextualDataSequence.hpp> #include <com/sun/star/container/NoSuchElementException.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> #include <com/sun/star/lang/IndexOutOfBoundsException.hpp> #include <cppuhelper/supportsservice.hxx> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <rtl/ref.hxx> +#include <rtl/ustrbuf.hxx> #include <algorithm> @@ -44,46 +50,43 @@ using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::Reference; using ::osl::MutexGuard; -namespace +namespace chart { - -struct StaticDataSeriesDefaults : public rtl::StaticWithInit< ::chart::tPropertyValueMap, StaticDataSeriesDefaults > +const ::chart::tPropertyValueMap & StaticDataSeriesDefaults() { - ::chart::tPropertyValueMap operator()() - { - ::chart::tPropertyValueMap aStaticDefaults; - ::chart::DataSeriesProperties::AddDefaultsToMap( aStaticDefaults ); - ::chart::CharacterProperties::AddDefaultsToMap( aStaticDefaults ); - float fDefaultCharHeight = 10.0; - ::chart::PropertyHelper::setPropertyValue( aStaticDefaults, ::chart::CharacterProperties::PROP_CHAR_CHAR_HEIGHT, fDefaultCharHeight ); - ::chart::PropertyHelper::setPropertyValue( aStaticDefaults, ::chart::CharacterProperties::PROP_CHAR_ASIAN_CHAR_HEIGHT, fDefaultCharHeight ); - ::chart::PropertyHelper::setPropertyValue( aStaticDefaults, ::chart::CharacterProperties::PROP_CHAR_COMPLEX_CHAR_HEIGHT, fDefaultCharHeight ); - return aStaticDefaults; - } + static const ::chart::tPropertyValueMap aStaticDefaults = []() + { + ::chart::tPropertyValueMap aMap; + ::chart::DataSeriesProperties::AddDefaultsToMap( aMap ); + ::chart::CharacterProperties::AddDefaultsToMap( aMap ); + float fDefaultCharHeight = 10.0; + ::chart::PropertyHelper::setPropertyValue( aMap, ::chart::CharacterProperties::PROP_CHAR_CHAR_HEIGHT, fDefaultCharHeight ); + ::chart::PropertyHelper::setPropertyValue( aMap, ::chart::CharacterProperties::PROP_CHAR_ASIAN_CHAR_HEIGHT, fDefaultCharHeight ); + ::chart::PropertyHelper::setPropertyValue( aMap, ::chart::CharacterProperties::PROP_CHAR_COMPLEX_CHAR_HEIGHT, fDefaultCharHeight ); + return aMap; + }(); + return aStaticDefaults; }; +} // namespace chart -struct StaticDataSeriesInfoHelper : public rtl::StaticWithInit< ::cppu::OPropertyArrayHelper, StaticDataSeriesInfoHelper, StaticDataSeriesInfoHelper, uno::Sequence< Property > > +namespace { - uno::Sequence< Property > operator()() - { - std::vector< css::beans::Property > aProperties; - ::chart::DataSeriesProperties::AddPropertiesToVector( aProperties ); - ::chart::CharacterProperties::AddPropertiesToVector( aProperties ); - ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties ); - std::sort( aProperties.begin(), aProperties.end(), - ::chart::PropertyNameLess() ); +::cppu::OPropertyArrayHelper& StaticDataSeriesInfoHelper() +{ + static ::cppu::OPropertyArrayHelper oHelper = []() + { + std::vector< css::beans::Property > aProperties; + ::chart::DataSeriesProperties::AddPropertiesToVector( aProperties ); + ::chart::CharacterProperties::AddPropertiesToVector( aProperties ); + ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties ); - return comphelper::containerToSequence( aProperties ); - } -}; + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); -struct StaticDataSeriesInfo : public rtl::StaticWithInit< uno::Reference< beans::XPropertySetInfo >, StaticDataSeriesInfo > -{ - uno::Reference< beans::XPropertySetInfo > operator()() - { - return ::cppu::OPropertySetHelper::createPropertySetInfo(StaticDataSeriesInfoHelper::get() ); - } + return comphelper::containerToSequence( aProperties ); + }(); + return oHelper; }; void lcl_SetParent( @@ -127,24 +130,22 @@ namespace chart { DataSeries::DataSeries() : - ::property::OPropertySet( m_aMutex ), - m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) + m_xModifyEventForwarder( new ModifyEventForwarder() ) { } DataSeries::DataSeries( const DataSeries & rOther ) : impl::DataSeries_Base(rOther), - ::property::OPropertySet( rOther, m_aMutex ), - m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) + ::property::OPropertySet( rOther ), + m_xModifyEventForwarder( new ModifyEventForwarder() ) { if( ! rOther.m_aDataSequences.empty()) { - CloneHelper::CloneRefVector<css::chart2::data::XLabeledDataSequence>( - rOther.m_aDataSequences, m_aDataSequences ); + CloneHelper::CloneRefVector(rOther.m_aDataSequences, m_aDataSequences ); ModifyListenerHelper::addListenerToAllElements( m_aDataSequences, m_xModifyEventForwarder ); } - CloneHelper::CloneRefVector< chart2::XRegressionCurve >( rOther.m_aRegressionCurves, m_aRegressionCurves ); + CloneHelper::CloneRefVector( rOther.m_aRegressionCurves, m_aRegressionCurves ); ModifyListenerHelper::addListenerToAllElements( m_aRegressionCurves, m_xModifyEventForwarder ); // add as listener to XPropertySet properties @@ -165,9 +166,6 @@ DataSeries::DataSeries( const DataSeries & rOther ) : // late initialization to call after copy-constructing void DataSeries::Init( const DataSeries & rOther ) { - if( ! rOther.m_aDataSequences.empty()) - EventListenerHelper::addListenerToAllElements( m_aDataSequences, this ); - Reference< uno::XInterface > xThisInterface( static_cast< ::cppu::OWeakObject * >( this )); if( ! rOther.m_aAttributedDataPoints.empty()) { @@ -230,25 +228,28 @@ uno::Reference< util::XCloneable > SAL_CALL DataSeries::createClone() } // ____ OPropertySet ____ -uno::Any DataSeries::GetDefaultValue( sal_Int32 nHandle ) const +void DataSeries::GetDefaultValue( sal_Int32 nHandle, uno::Any& rDest ) const { - const tPropertyValueMap& rStaticDefaults = StaticDataSeriesDefaults::get(); + const tPropertyValueMap& rStaticDefaults = StaticDataSeriesDefaults(); tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); if( aFound == rStaticDefaults.end() ) - return uno::Any(); - return (*aFound).second; + rDest.clear(); + else + rDest = (*aFound).second; } // ____ OPropertySet ____ ::cppu::IPropertyArrayHelper & SAL_CALL DataSeries::getInfoHelper() { - return StaticDataSeriesInfoHelper::get(); + return StaticDataSeriesInfoHelper(); } // ____ XPropertySet ____ uno::Reference< beans::XPropertySetInfo > SAL_CALL DataSeries::getPropertySetInfo() { - return StaticDataSeriesInfo::get(); + static uno::Reference< beans::XPropertySetInfo > xPropSetInfo = + ::cppu::OPropertySetHelper::createPropertySetInfo(StaticDataSeriesInfoHelper() ); + return xPropSetInfo; } void SAL_CALL DataSeries::getFastPropertyValue @@ -282,7 +283,7 @@ void SAL_CALL DataSeries::setFastPropertyValue_NoBroadcast( ModifyListenerHelper::removeListener( xBroadcaster, m_xModifyEventForwarder ); } - OSL_ASSERT( rValue.getValueType().getTypeClass() == uno::TypeClass_INTERFACE ); + OSL_ASSERT( rValue.getValueTypeClass() == uno::TypeClass_INTERFACE ); if( rValue.hasValue() && (rValue >>= xBroadcaster) && xBroadcaster.is()) @@ -299,14 +300,14 @@ Reference< beans::XPropertySet > { Reference< beans::XPropertySet > xResult; - Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences; + std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences; { MutexGuard aGuard( m_aMutex ); - aSequences = comphelper::containerToSequence( m_aDataSequences ); + aSequences = m_aDataSequences; } - std::vector< Reference< chart2::data::XLabeledDataSequence > > aValuesSeries( - DataSeriesHelper::getAllDataSequencesByRole( aSequences , "values" ) ); + std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aValuesSeries( + DataSeriesHelper::getAllDataSequencesByRole( aSequences , u"values"_ustr ) ); if (aValuesSeries.empty()) throw lang::IndexOutOfBoundsException(); @@ -323,7 +324,7 @@ Reference< beans::XPropertySet > if( !xResult.is() ) { Reference< beans::XPropertySet > xParentProperties; - Reference< util::XModifyListener > xModifyEventForwarder; + rtl::Reference< ModifyEventForwarder > xModifyEventForwarder; { MutexGuard aGuard( m_aMutex ); xParentProperties = this; @@ -346,7 +347,7 @@ Reference< beans::XPropertySet > void SAL_CALL DataSeries::resetDataPoint( sal_Int32 nIndex ) { Reference< beans::XPropertySet > xDataPointProp; - Reference< util::XModifyListener > xModifyEventForwarder; + rtl::Reference< ModifyEventForwarder > xModifyEventForwarder; { MutexGuard aGuard( m_aMutex ); xModifyEventForwarder = m_xModifyEventForwarder; @@ -370,7 +371,7 @@ void SAL_CALL DataSeries::resetDataPoint( sal_Int32 nIndex ) void SAL_CALL DataSeries::resetAllDataPoints() { tDataPointAttributeContainer aOldAttributedDataPoints; - Reference< util::XModifyListener > xModifyEventForwarder; + rtl::Reference< ModifyEventForwarder > xModifyEventForwarder; { MutexGuard aGuard( m_aMutex ); xModifyEventForwarder = m_xModifyEventForwarder; @@ -386,44 +387,67 @@ void SAL_CALL DataSeries::setData( const uno::Sequence< Reference< chart2::data: { tDataSequenceContainer aOldDataSequences; tDataSequenceContainer aNewDataSequences; - Reference< util::XModifyListener > xModifyEventForwarder; - Reference< lang::XEventListener > xListener; + rtl::Reference< ModifyEventForwarder > xModifyEventForwarder; + { + MutexGuard aGuard( m_aMutex ); + xModifyEventForwarder = m_xModifyEventForwarder; + std::swap( aOldDataSequences, m_aDataSequences ); + for (const auto & i : aData) + { + aNewDataSequences.push_back(i); + } + m_aDataSequences = aNewDataSequences; + } + ModifyListenerHelper::removeListenerFromAllElements( aOldDataSequences, xModifyEventForwarder ); + ModifyListenerHelper::addListenerToAllElements( aNewDataSequences, xModifyEventForwarder ); + fireModifyEvent(); +} + +void DataSeries::setData( const std::vector< uno::Reference< chart2::data::XLabeledDataSequence > >& aData ) +{ + tDataSequenceContainer aOldDataSequences; + tDataSequenceContainer aNewDataSequences; + rtl::Reference< ModifyEventForwarder > xModifyEventForwarder; { MutexGuard aGuard( m_aMutex ); xModifyEventForwarder = m_xModifyEventForwarder; - xListener = this; std::swap( aOldDataSequences, m_aDataSequences ); - aNewDataSequences = comphelper::sequenceToContainer<tDataSequenceContainer>( aData ); + aNewDataSequences = aData; m_aDataSequences = aNewDataSequences; } ModifyListenerHelper::removeListenerFromAllElements( aOldDataSequences, xModifyEventForwarder ); - EventListenerHelper::removeListenerFromAllElements( aOldDataSequences, xListener ); - EventListenerHelper::addListenerToAllElements( aNewDataSequences, xListener ); ModifyListenerHelper::addListenerToAllElements( aNewDataSequences, xModifyEventForwarder ); fireModifyEvent(); } +void DataSeries::addDataSequence(css::uno::Reference<css::chart2::data::XLabeledDataSequence> const& rSequence) +{ + m_aDataSequences.push_back(rSequence); +} + // ____ XDataSource ____ Sequence< Reference< chart2::data::XLabeledDataSequence > > SAL_CALL DataSeries::getDataSequences() { MutexGuard aGuard( m_aMutex ); - return comphelper::containerToSequence( m_aDataSequences ); + return comphelper::containerToSequence<Reference< chart2::data::XLabeledDataSequence >>( m_aDataSequences ); } // ____ XRegressionCurveContainer ____ void SAL_CALL DataSeries::addRegressionCurve( const uno::Reference< chart2::XRegressionCurve >& xRegressionCurve ) { - Reference< util::XModifyListener > xModifyEventForwarder; + auto pRegressionCurve = dynamic_cast<RegressionCurveModel*>(xRegressionCurve.get()); + assert(pRegressionCurve); + rtl::Reference< ModifyEventForwarder > xModifyEventForwarder; { MutexGuard aGuard( m_aMutex ); xModifyEventForwarder = m_xModifyEventForwarder; - if( std::find( m_aRegressionCurves.begin(), m_aRegressionCurves.end(), xRegressionCurve ) + if( std::find( m_aRegressionCurves.begin(), m_aRegressionCurves.end(), pRegressionCurve ) != m_aRegressionCurves.end()) - throw lang::IllegalArgumentException("curve not found", static_cast<cppu::OWeakObject*>(this), 1); - m_aRegressionCurves.push_back( xRegressionCurve ); + throw lang::IllegalArgumentException(u"curve not found"_ustr, static_cast<cppu::OWeakObject*>(this), 1); + m_aRegressionCurves.push_back( pRegressionCurve ); } - ModifyListenerHelper::addListener( xRegressionCurve, xModifyEventForwarder ); + ModifyListenerHelper::addListener( rtl::Reference<RegressionCurveModel>(pRegressionCurve), xModifyEventForwarder ); fireModifyEvent(); } @@ -432,36 +456,44 @@ void SAL_CALL DataSeries::removeRegressionCurve( { if( !xRegressionCurve.is() ) throw container::NoSuchElementException(); + auto pRegressionCurve = dynamic_cast<RegressionCurveModel*>(xRegressionCurve.get()); + assert(pRegressionCurve); - Reference< util::XModifyListener > xModifyEventForwarder; + rtl::Reference< ModifyEventForwarder > xModifyEventForwarder; { MutexGuard aGuard( m_aMutex ); xModifyEventForwarder = m_xModifyEventForwarder; tRegressionCurveContainerType::iterator aIt( - std::find( m_aRegressionCurves.begin(), m_aRegressionCurves.end(), xRegressionCurve ) ); + std::find( m_aRegressionCurves.begin(), m_aRegressionCurves.end(), pRegressionCurve ) ); if( aIt == m_aRegressionCurves.end()) throw container::NoSuchElementException( - "The given regression curve is no element of this series", + u"The given regression curve is no element of this series"_ustr, static_cast< uno::XWeak * >( this )); m_aRegressionCurves.erase( aIt ); } - ModifyListenerHelper::removeListener( xRegressionCurve, xModifyEventForwarder ); + ModifyListenerHelper::removeListener( rtl::Reference<RegressionCurveModel>(pRegressionCurve), xModifyEventForwarder ); fireModifyEvent(); } uno::Sequence< uno::Reference< chart2::XRegressionCurve > > SAL_CALL DataSeries::getRegressionCurves() { MutexGuard aGuard( m_aMutex ); - return comphelper::containerToSequence( m_aRegressionCurves ); + return comphelper::containerToSequence<uno::Reference< chart2::XRegressionCurve >>( m_aRegressionCurves ); } void SAL_CALL DataSeries::setRegressionCurves( const Sequence< Reference< chart2::XRegressionCurve > >& aRegressionCurves ) { tRegressionCurveContainerType aOldCurves; - auto aNewCurves( comphelper::sequenceToContainer<tRegressionCurveContainerType>( aRegressionCurves ) ); - Reference< util::XModifyListener > xModifyEventForwarder; + tRegressionCurveContainerType aNewCurves; + for (const auto & i : aRegressionCurves) + { + auto pRegressionCurve = dynamic_cast<RegressionCurveModel*>(i.get()); + assert(pRegressionCurve); + aNewCurves.push_back(pRegressionCurve); + } + rtl::Reference< ModifyEventForwarder > xModifyEventForwarder; { MutexGuard aGuard( m_aMutex ); xModifyEventForwarder = m_xModifyEventForwarder; @@ -476,28 +508,12 @@ void SAL_CALL DataSeries::setRegressionCurves( // ____ XModifyBroadcaster ____ void SAL_CALL DataSeries::addModifyListener( const Reference< util::XModifyListener >& aListener ) { - try - { - Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); - xBroadcaster->addModifyListener( aListener ); - } - catch( const uno::Exception & ) - { - DBG_UNHANDLED_EXCEPTION("chart2"); - } + m_xModifyEventForwarder->addModifyListener( aListener ); } void SAL_CALL DataSeries::removeModifyListener( const Reference< util::XModifyListener >& aListener ) { - try - { - Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); - xBroadcaster->removeModifyListener( aListener ); - } - catch( const uno::Exception & ) - { - DBG_UNHANDLED_EXCEPTION("chart2"); - } + m_xModifyEventForwarder->removeModifyListener( aListener ); } // ____ XModifyListener ____ @@ -507,13 +523,8 @@ void SAL_CALL DataSeries::modified( const lang::EventObject& aEvent ) } // ____ XEventListener (base of XModifyListener) ____ -void SAL_CALL DataSeries::disposing( const lang::EventObject& rEventObject ) +void SAL_CALL DataSeries::disposing( const lang::EventObject& ) { - // forget disposed data sequences - tDataSequenceContainer::iterator aIt( - std::find( m_aDataSequences.begin(), m_aDataSequences.end(), rEventObject.Source )); - if( aIt != m_aDataSequences.end()) - m_aDataSequences.erase( aIt ); } // ____ OPropertySet ____ @@ -536,7 +547,7 @@ IMPLEMENT_FORWARD_XTYPEPROVIDER2( DataSeries, DataSeries_Base, OPropertySet ) // implement XServiceInfo methods basing upon getSupportedServiceNames_Static OUString SAL_CALL DataSeries::getImplementationName() { - return "com.sun.star.comp.chart.DataSeries"; + return u"com.sun.star.comp.chart.DataSeries"_ustr; } sal_Bool SAL_CALL DataSeries::supportsService( const OUString& rServiceName ) @@ -547,9 +558,486 @@ sal_Bool SAL_CALL DataSeries::supportsService( const OUString& rServiceName ) css::uno::Sequence< OUString > SAL_CALL DataSeries::getSupportedServiceNames() { return { - "com.sun.star.chart2.DataSeries", - "com.sun.star.chart2.DataPointProperties", - "com.sun.star.beans.PropertySet" }; + u"com.sun.star.chart2.DataSeries"_ustr, + u"com.sun.star.chart2.DataPointProperties"_ustr, + u"com.sun.star.beans.PropertySet"_ustr }; +} + +static Reference< chart2::data::XLabeledDataSequence > lcl_findLSequenceWithOnlyLabel( + const Sequence< Reference< chart2::data::XLabeledDataSequence > > & rDataSequences ) +{ + Reference< chart2::data::XLabeledDataSequence > xResult; + + for( auto const & labeledData : rDataSequences ) + { + OSL_ENSURE( labeledData.is(), "empty LabeledDataSequence" ); + // no values are set but a label exists + if( labeledData.is() && + ( ! labeledData->getValues().is() && + labeledData->getLabel().is())) + { + xResult.set( labeledData ); + break; + } + } + + return xResult; +} + +static OUString lcl_getDataSequenceLabel( const Reference< chart2::data::XDataSequence > & xSequence ) +{ + OUString aResult; + + Reference< chart2::data::XTextualDataSequence > xTextSeq( xSequence, uno::UNO_QUERY ); + if( xTextSeq.is()) + { + Sequence< OUString > aSeq( xTextSeq->getTextualData()); + + const sal_Int32 nMax = aSeq.getLength() - 1; + OUStringBuffer aBuf; + + for( sal_Int32 i = 0; i <= nMax; ++i ) + { + aBuf.append( aSeq[i] ); + if( i < nMax ) + aBuf.append( ' '); + } + aResult = aBuf.makeStringAndClear(); + } + else if( xSequence.is()) + { + Sequence< uno::Any > aSeq( xSequence->getData()); + + const sal_Int32 nMax = aSeq.getLength() - 1; + OUString aVal; + OUStringBuffer aBuf; + double fNum = 0; + + for( sal_Int32 i = 0; i <= nMax; ++i ) + { + if( aSeq[i] >>= aVal ) + { + aBuf.append( aVal ); + if( i < nMax ) + aBuf.append( ' '); + } + else if( aSeq[ i ] >>= fNum ) + { + aBuf.append( fNum ); + if( i < nMax ) + aBuf.append( ' '); + } + } + aResult = aBuf.makeStringAndClear(); + } + + return aResult; +} + +static OUString getLabelForLabeledDataSequence( + const Reference< chart2::data::XLabeledDataSequence > & xLabeledSeq ) +{ + OUString aResult; + if( xLabeledSeq.is()) + { + Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getLabel()); + if( xSeq.is() ) + aResult = lcl_getDataSequenceLabel( xSeq ); + if( !xSeq.is() || aResult.isEmpty() ) + { + // no label set or label content is empty -> use auto-generated one + Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues() ); + if( xValueSeq.is() ) + { + Sequence< OUString > aLabels( xValueSeq->generateLabel( + chart2::data::LabelOrigin_SHORT_SIDE ) ); + // no labels returned is interpreted as: auto-generation not + // supported by sequence + if( aLabels.hasElements() ) + aResult=aLabels[0]; + else + { + //todo?: maybe use the index of the series as name + //but as the index may change it would be better to have such a name persistent + //what is not possible at the moment + //--> maybe use the identifier as part of the name ... + aResult = lcl_getDataSequenceLabel( xValueSeq ); + } + } + } + } + return aResult; +} + +OUString DataSeries::getLabelForRole( const OUString & rLabelSequenceRole ) +{ + OUString aResult; + + Reference< chart2::data::XLabeledDataSequence > xLabeledSeq( + ::chart::DataSeriesHelper::getDataSequenceByRole( this, rLabelSequenceRole )); + if( xLabeledSeq.is()) + aResult = getLabelForLabeledDataSequence( xLabeledSeq ); + else + { + // special case: labeled data series with only a label and no values may + // serve as label + xLabeledSeq.set( lcl_findLSequenceWithOnlyLabel( getDataSequences() )); + if( xLabeledSeq.is()) + { + Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getLabel()); + if( xSeq.is()) + aResult = lcl_getDataSequenceLabel( xSeq ); + } + } + + return aResult; +} + +static bool lcl_SequenceHasUnhiddenData( const uno::Reference< chart2::data::XDataSequence >& xDataSequence ) +{ + if (!xDataSequence.is()) + return false; + uno::Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY ); + if( xProp.is() ) + { + uno::Sequence< sal_Int32 > aHiddenValues; + try + { + xProp->getPropertyValue( u"HiddenValues"_ustr ) >>= aHiddenValues; + if( !aHiddenValues.hasElements() ) + return true; + } + catch( const uno::Exception& ) + { + return true; + } + } + return xDataSequence->getData().hasElements(); +} + +bool DataSeries::hasUnhiddenData() +{ + MutexGuard aGuard( m_aMutex ); + + for(uno::Reference< chart2::data::XLabeledDataSequence > const & rDataSequence : m_aDataSequences) + { + if( !rDataSequence.is() ) + continue; + if( lcl_SequenceHasUnhiddenData( rDataSequence->getValues() ) ) + return true; + } + return false; +} + +bool DataSeries::hasPointOwnColor( + sal_Int32 nPointIndex + , const css::uno::Reference< css::beans::XPropertySet >& xDataPointProperties //may be NULL this is just for performance + ) +{ + if( hasPointOwnProperties( nPointIndex )) + { + uno::Reference< beans::XPropertyState > xPointState( xDataPointProperties, uno::UNO_QUERY ); + if( !xPointState.is() ) + { + xPointState.set( getDataPointByIndex( nPointIndex ), uno::UNO_QUERY ); + } + if( !xPointState.is() ) + return false; + + return (xPointState->getPropertyState( u"Color"_ustr) != beans::PropertyState_DEFAULT_VALUE ); + } + + return false; +} + +bool DataSeries::hasPointOwnProperties( sal_Int32 nPointIndex ) +{ + MutexGuard aGuard( m_aMutex ); + return m_aAttributedDataPoints.find(nPointIndex) != m_aAttributedDataPoints.end(); +} + +sal_Int32 DataSeries::getAttachedAxisIndex() +{ + sal_Int32 nRet = 0; + try + { + getFastPropertyValue( ::chart::DataSeriesProperties::PROP_DATASERIES_ATTACHED_AXIS_INDEX ) >>= nRet; + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return nRet; +} + +void DataSeries::switchSymbolsOnOrOff( bool bSymbolsOn, sal_Int32 nSeriesIndex ) +{ + css::chart2::Symbol aSymbProp; + if( getPropertyValue( u"Symbol"_ustr) >>= aSymbProp ) + { + if( !bSymbolsOn ) + aSymbProp.Style = chart2::SymbolStyle_NONE; + else if( aSymbProp.Style == chart2::SymbolStyle_NONE ) + { + aSymbProp.Style = chart2::SymbolStyle_STANDARD; + aSymbProp.StandardSymbol = nSeriesIndex; + } + setPropertyValue( u"Symbol"_ustr, uno::Any( aSymbProp )); + } + //todo: check attributed data points +} + +void DataSeries::switchLinesOnOrOff( bool bLinesOn ) +{ + if( bLinesOn ) + { + // keep line-styles that are not NONE + css::drawing::LineStyle eLineStyle; + if( (getPropertyValue( u"LineStyle"_ustr) >>= eLineStyle ) && + eLineStyle == drawing::LineStyle_NONE ) + { + setPropertyValue( u"LineStyle"_ustr, uno::Any( drawing::LineStyle_SOLID ) ); + } + } + else + setPropertyValue( u"LineStyle"_ustr, uno::Any( drawing::LineStyle_NONE ) ); +} + +void DataSeries::makeLinesThickOrThin( bool bThick ) +{ + sal_Int32 nNewValue = bThick ? 80 : 0; + sal_Int32 nOldValue = 0; + if( (getPropertyValue( u"LineWidth"_ustr) >>= nOldValue ) && + nOldValue != nNewValue ) + { + if( !(bThick && nOldValue>0)) + setPropertyValue( u"LineWidth"_ustr, uno::Any( nNewValue ) ); + } +} + +void DataSeries::setPropertyAlsoToAllAttributedDataPoints( const OUString& rPropertyName, const uno::Any& rPropertyValue ) +{ + setPropertyValue( rPropertyName, rPropertyValue ); + + std::vector<sal_Int32> aAttributedDataPointIndexList; + { + MutexGuard aGuard( m_aMutex ); + aAttributedDataPointIndexList.reserve(m_aAttributedDataPoints.size()); + for (const auto & rPair : m_aAttributedDataPoints) + aAttributedDataPointIndexList.push_back(rPair.first); + } + + for(sal_Int32 nIdx : aAttributedDataPointIndexList) + { + Reference< beans::XPropertySet > xPointProp( getDataPointByIndex(nIdx) ); + if(!xPointProp.is()) + continue; + xPointProp->setPropertyValue( rPropertyName, rPropertyValue ); + if( rPropertyName == "LabelPlacement" ) + { + xPointProp->setPropertyValue(u"CustomLabelPosition"_ustr, uno::Any()); + xPointProp->setPropertyValue(u"CustomLabelSize"_ustr, uno::Any()); + } + } +} + +bool DataSeries::hasAttributedDataPointDifferentValue( + const OUString& rPropertyName, const uno::Any& rPropertyValue ) +{ + std::vector<sal_Int32> aAttributedDataPointIndexList; + { + MutexGuard aGuard( m_aMutex ); + aAttributedDataPointIndexList.reserve(m_aAttributedDataPoints.size()); + for (const auto & rPair : m_aAttributedDataPoints) + aAttributedDataPointIndexList.push_back(rPair.first); + } + + for(sal_Int32 nIdx : aAttributedDataPointIndexList) + { + Reference< beans::XPropertySet > xPointProp( getDataPointByIndex(nIdx) ); + if(!xPointProp.is()) + continue; + uno::Any aPointValue( xPointProp->getPropertyValue( rPropertyName ) ); + if( rPropertyValue != aPointValue ) + return true; + } + + return false; +} + +bool DataSeries::hasDataLabelsAtSeries() +{ + bool bRet = false; + try + { + chart2::DataPointLabel aLabel; + if( getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel ) + bRet = aLabel.ShowNumber || aLabel.ShowNumberInPercent || aLabel.ShowCategoryName + || aLabel.ShowSeriesName; + } + catch(const uno::Exception &) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + return bRet; +} + +bool DataSeries::hasDataLabelsAtPoints() +{ + bool bRet = false; + try + { + std::vector<sal_Int32> aAttributedDataPointIndexList; + { + MutexGuard aGuard( m_aMutex ); + aAttributedDataPointIndexList.reserve(m_aAttributedDataPoints.size()); + for (const auto & rPair : m_aAttributedDataPoints) + aAttributedDataPointIndexList.push_back(rPair.first); + } + for(sal_Int32 nIdx : aAttributedDataPointIndexList) + { + Reference< beans::XPropertySet > xPointProp( getDataPointByIndex(nIdx) ); + if( xPointProp.is() ) + { + chart2::DataPointLabel aLabel; + if( xPointProp->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel ) + bRet = aLabel.ShowNumber || aLabel.ShowNumberInPercent + || aLabel.ShowCategoryName || aLabel.ShowCustomLabel + || aLabel.ShowSeriesName; + if( bRet ) + break; + } + } + } + catch(const uno::Exception &) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + return bRet; +} + +bool DataSeries::hasDataLabelAtPoint( sal_Int32 nPointIndex ) +{ + bool bRet = false; + try + { + Reference< beans::XPropertySet > xProp; + bool bFound = false; + { + MutexGuard aGuard( m_aMutex ); + bFound = m_aAttributedDataPoints.find(nPointIndex) != m_aAttributedDataPoints.end(); + } + if (bFound) + xProp = getDataPointByIndex(nPointIndex); + else + xProp = this; + if( xProp.is() ) + { + chart2::DataPointLabel aLabel; + if( xProp->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel ) + bRet = aLabel.ShowNumber || aLabel.ShowNumberInPercent + || aLabel.ShowCategoryName || aLabel.ShowCustomLabel + || aLabel.ShowSeriesName; + } + } + catch(const uno::Exception &) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + return bRet; +} + +void DataSeries::insertDataLabelsToSeriesAndAllPoints() +{ + impl_insertOrDeleteDataLabelsToSeriesAndAllPoints( true /*bInsert*/ ); +} + +void DataSeries::deleteDataLabelsFromSeriesAndAllPoints() +{ + impl_insertOrDeleteDataLabelsToSeriesAndAllPoints( false /*bInsert*/ ); +} + +void DataSeries::impl_insertOrDeleteDataLabelsToSeriesAndAllPoints( bool bInsert ) +{ + try + { + chart2::DataPointLabel aLabelAtSeries; + getPropertyValue(CHART_UNONAME_LABEL) >>= aLabelAtSeries; + aLabelAtSeries.ShowNumber = bInsert; + if( !bInsert ) + { + aLabelAtSeries.ShowNumberInPercent = false; + aLabelAtSeries.ShowCategoryName = false; + } + setPropertyValue(CHART_UNONAME_LABEL, uno::Any(aLabelAtSeries)); + std::vector<sal_Int32> aAttributedDataPointIndexList; + { + MutexGuard aGuard( m_aMutex ); + aAttributedDataPointIndexList.reserve(m_aAttributedDataPoints.size()); + for (const auto & rPair : m_aAttributedDataPoints) + aAttributedDataPointIndexList.push_back(rPair.first); + } + for(sal_Int32 nIdx : aAttributedDataPointIndexList) + { + Reference< beans::XPropertySet > xPointProp( getDataPointByIndex(nIdx) ); + if( xPointProp.is() ) + { + chart2::DataPointLabel aLabel; + xPointProp->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel; + aLabel.ShowNumber = bInsert; + if( !bInsert ) + { + aLabel.ShowNumberInPercent = false; + aLabel.ShowCategoryName = false; + aLabel.ShowCustomLabel = false; + aLabel.ShowSeriesName = false; + } + xPointProp->setPropertyValue(CHART_UNONAME_LABEL, uno::Any(aLabel)); + xPointProp->setPropertyValue(CHART_UNONAME_CUSTOM_LABEL_FIELDS, uno::Any()); + } + } + } + catch(const uno::Exception &) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } +} + +sal_Int32 DataSeries::getExplicitNumberFormatKeyForDataLabel() +{ + sal_Int32 nFormat = 0; + try + { + bool bLinkToSource = true; + getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT) >>= bLinkToSource; + getPropertyValue(CHART_UNONAME_NUMFMT) >>= nFormat; + + if (bLinkToSource) + { + MutexGuard aGuard( m_aMutex ); + + if (!m_aDataSequences.empty()) + { + Reference<chart2::data::XLabeledDataSequence> xLabeledSeq(m_aDataSequences[0]); + if( xLabeledSeq.is() ) + { + Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getValues()); + if( xSeq.is() ) + { + nFormat = xSeq->getNumberFormatKeyByIndex( -1 ); + } + } + } + } + } + catch (const beans::UnknownPropertyException&) + { + } + + if (nFormat < 0) + nFormat = 0; + return nFormat; + } } // namespace chart |