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: VDataSeries.cxx,v $
10 * $Revision: 1.32.8.2 $
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 "VDataSeries.hxx"
34 #include "ObjectIdentifier.hxx"
36 #include "CommonConverters.hxx"
37 #include "LabelPositionHelper.hxx"
38 #include "ChartTypeHelper.hxx"
39 #include "ContainerHelper.hxx"
40 #include "DataSeriesHelper.hxx"
41 #include "RegressionCurveHelper.hxx"
43 #include <com/sun/star/chart/MissingValueTreatment.hpp>
44 #include <com/sun/star/chart2/Symbol.hpp>
46 //#include "CommonConverters.hxx"
47 #include <rtl/math.hxx>
48 #include <tools/debug.hxx>
49 #include <com/sun/star/beans/XPropertySet.hpp>
50 #include <com/sun/star/beans/XPropertyState.hpp>
51 #include <com/sun/star/drawing/LineStyle.hpp>
52 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
53 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
54 #include <com/sun/star/text/WritingMode.hpp>
55 #include <com/sun/star/chart2/data/XDataSource.hpp>
57 //.............................................................................
60 //.............................................................................
61 using namespace ::com::sun::star
;
62 using namespace ::com::sun::star::chart2
;
63 using ::com::sun::star::uno::Reference
;
65 void VDataSequence::init( const uno::Reference
< data::XDataSequence
>& xModel
)
68 Doubles
= DataSequenceToDoubleSequence( xModel
);
71 bool VDataSequence::is() const
75 void VDataSequence::clear()
81 double VDataSequence::getValue( sal_Int32 index
) const
83 if( 0<=index
&& index
<Doubles
.getLength() )
84 return Doubles
[index
];
88 ::rtl::math::setNan( & fNan
);
93 sal_Int32
VDataSequence::detectNumberFormatKey( sal_Int32 index
) const
95 sal_Int32 nNumberFormatKey
= -1;
97 // -1 is allowed and means a key for the whole sequence
98 if( -1<=index
&& index
<Doubles
.getLength() &&
101 nNumberFormatKey
= Model
->getNumberFormatKeyByIndex( index
);
104 return nNumberFormatKey
;
107 sal_Int32
VDataSequence::getLength() const
109 return Doubles
.getLength();
114 struct lcl_LessXOfPoint
116 inline bool operator() ( const std::vector
< double >& first
,
117 const std::vector
< double >& second
)
119 if( first
.size() > 0 && second
.size() > 0 )
121 return first
[0]<second
[0];
127 void lcl_clearIfNoValuesButTextIsContained( VDataSequence
& rData
, const uno::Reference
<data::XDataSequence
>& xDataSequence
)
129 //#i71686#, #i101968#, #i102428#
130 sal_Int32 nCount
= rData
.Doubles
.getLength();
131 for( sal_Int32 i
= 0; i
< nCount
; ++i
)
133 if( !::rtl::math::isNan( rData
.Doubles
[i
] ) )
136 //no double value is countained
138 uno::Sequence
< rtl::OUString
> aStrings( DataSequenceToStringSequence( xDataSequence
) );
139 sal_Int32 nTextCount
= aStrings
.getLength();
140 for( sal_Int32 j
= 0; j
< nTextCount
; ++j
)
142 if( aStrings
[j
].getLength() )
151 void lcl_maybeReplaceNanWithZero( double& rfValue
, sal_Int32 nMissingValueTreatment
)
153 if( nMissingValueTreatment
== ::com::sun::star::chart::MissingValueTreatment::USE_ZERO
154 && (::rtl::math::isNan(rfValue
) || ::rtl::math::isInf(rfValue
)) )
160 VDataSeries::VDataSeries( const uno::Reference
< XDataSeries
>& xDataSeries
)
165 , m_xGroupShape(NULL
)
166 , m_xLabelsGroupShape(NULL
)
167 , m_xErrorBarsGroupShape(NULL
)
168 , m_xFrontSubGroupShape(NULL
)
169 , m_xBackSubGroupShape(NULL
)
170 , m_xDataSeries(xDataSeries
)
179 , m_aValues_Y_First()
181 , m_aValues_Bubble_Size()
182 , m_pValueSequenceForDataLabelNumberFormatDetection(&m_aValues_Y
)
186 , m_aAttributedDataPointIndexList()
188 , m_eStackingDirection(StackingDirection_NO_STACKING
)
190 , m_bConnectBars(sal_False
)
191 , m_bGroupBarsPerAxis(sal_True
)
192 , m_nStartingAngle(90)
194 , m_aSeriesParticle()
199 , m_nGlobalSeriesIndex(0)
201 , m_apLabel_Series(NULL
)
202 , m_apLabelPropNames_Series(NULL
)
203 , m_apLabelPropValues_Series(NULL
)
204 , m_apSymbolProperties_Series(NULL
)
206 , m_apLabel_AttributedPoint(NULL
)
207 , m_apLabelPropNames_AttributedPoint(NULL
)
208 , m_apLabelPropValues_AttributedPoint(NULL
)
209 , m_apSymbolProperties_AttributedPoint(NULL
)
210 , m_apSymbolProperties_InvisibleSymbolForSelection(NULL
)
211 , m_nCurrentAttributedPoint(-1)
212 , m_nMissingValueTreatment(::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP
)
213 , m_bAllowPercentValueInDataLabel(false)
215 ::rtl::math::setNan( & m_fYMeanValue
);
217 uno::Reference
<data::XDataSource
> xDataSource
=
218 uno::Reference
<data::XDataSource
>( xDataSeries
, uno::UNO_QUERY
);
220 m_aDataSequences
= xDataSource
->getDataSequences();
222 for(sal_Int32 nN
= m_aDataSequences
.getLength();nN
--;)
224 if(!m_aDataSequences
[nN
].is())
226 uno::Reference
<data::XDataSequence
> xDataSequence( m_aDataSequences
[nN
]->getValues());
227 uno::Reference
<beans::XPropertySet
> xProp(xDataSequence
, uno::UNO_QUERY
);
232 uno::Any aARole
= xProp
->getPropertyValue( C2U( "Role" ) );
236 if( aRole
.equals(C2U("values-x")) )
238 m_aValues_X
.init( xDataSequence
);
239 lcl_clearIfNoValuesButTextIsContained( m_aValues_X
, xDataSequence
);
241 else if( aRole
.equals(C2U("values-y")) )
242 m_aValues_Y
.init( xDataSequence
);
243 else if( aRole
.equals(C2U("values-min")) )
244 m_aValues_Y_Min
.init( xDataSequence
);
245 else if( aRole
.equals(C2U("values-max")) )
246 m_aValues_Y_Max
.init( xDataSequence
);
247 else if( aRole
.equals(C2U("values-first")) )
248 m_aValues_Y_First
.init( xDataSequence
);
249 else if( aRole
.equals(C2U("values-last")) )
250 m_aValues_Y_Last
.init( xDataSequence
);
251 else if( aRole
.equals(C2U("values-size")) )
252 m_aValues_Bubble_Size
.init( xDataSequence
);
254 catch( uno::Exception
& e
)
256 ASSERT_EXCEPTION( e
);
261 //determine the point count
262 m_nPointCount
= m_aValues_Y
.getLength();
264 if( m_nPointCount
< m_aValues_Bubble_Size
.getLength() )
265 m_nPointCount
= m_aValues_Bubble_Size
.getLength();
266 if( m_nPointCount
< m_aValues_Y_Min
.getLength() )
267 m_nPointCount
= m_aValues_Y_Min
.getLength();
268 if( m_nPointCount
< m_aValues_Y_Max
.getLength() )
269 m_nPointCount
= m_aValues_Y_Max
.getLength();
270 if( m_nPointCount
< m_aValues_Y_First
.getLength() )
271 m_nPointCount
= m_aValues_Y_First
.getLength();
272 if( m_nPointCount
< m_aValues_Y_Last
.getLength() )
273 m_nPointCount
= m_aValues_Y_Last
.getLength();
276 uno::Reference
<beans::XPropertySet
> xProp(xDataSeries
, uno::UNO_QUERY
);
281 //get AttributedDataPoints
282 xProp
->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= m_aAttributedDataPointIndexList
;
284 xProp
->getPropertyValue( C2U( "StackingDirection" ) ) >>= m_eStackingDirection
;
286 xProp
->getPropertyValue( C2U( "AttachedAxisIndex" ) ) >>= m_nAxisIndex
;
290 catch( uno::Exception
& e
)
292 ASSERT_EXCEPTION( e
);
297 VDataSeries::~VDataSeries()
301 void VDataSeries::doSortByXValues()
303 if( m_aValues_X
.is() && m_aValues_X
.Doubles
.getLength() )
305 //prepare a vector vor sorting
306 std::vector
< ::std::vector
< double > > aTmp
;//outer vector are points, inner vector are the different values of athe point
308 ::rtl::math::setNan( & fNan
);
309 sal_Int32 nPointIndex
= 0;
310 for( nPointIndex
=0; nPointIndex
< m_nPointCount
; nPointIndex
++ )
312 std::vector
< double > aSinglePoint
;
313 aSinglePoint
.push_back( (nPointIndex
< m_aValues_X
.Doubles
.getLength()) ? m_aValues_X
.Doubles
[nPointIndex
] : fNan
);
314 aSinglePoint
.push_back( (nPointIndex
< m_aValues_Y
.Doubles
.getLength()) ? m_aValues_Y
.Doubles
[nPointIndex
] : fNan
);
315 aTmp
.push_back( aSinglePoint
);
319 std::sort( aTmp
.begin(), aTmp
.end(), lcl_LessXOfPoint() );
321 //fill the sorted points back to the mambers
322 m_aValues_X
.Doubles
.realloc( m_nPointCount
);
323 m_aValues_Y
.Doubles
.realloc( m_nPointCount
);
325 for( nPointIndex
=0; nPointIndex
< m_nPointCount
; nPointIndex
++ )
327 m_aValues_X
.Doubles
[nPointIndex
]=aTmp
[nPointIndex
][0];
328 m_aValues_Y
.Doubles
[nPointIndex
]=aTmp
[nPointIndex
][1];
333 uno::Reference
< XDataSeries
> VDataSeries::getModel() const
335 return m_xDataSeries
;
338 void VDataSeries::releaseShapes()
340 m_xGroupShape
.set(0);
341 m_xLabelsGroupShape
.set(0);
342 m_xErrorBarsGroupShape
.set(0);
343 m_xFrontSubGroupShape
.set(0);
344 m_xBackSubGroupShape
.set(0);
346 m_aPolyPolygonShape3D
.SequenceX
.realloc(0);
347 m_aPolyPolygonShape3D
.SequenceY
.realloc(0);
348 m_aPolyPolygonShape3D
.SequenceZ
.realloc(0);
352 void VDataSeries::setCategoryXAxis()
355 m_bAllowPercentValueInDataLabel
= true;
358 void VDataSeries::setGlobalSeriesIndex( sal_Int32 nGlobalSeriesIndex
)
360 m_nGlobalSeriesIndex
= nGlobalSeriesIndex
;
363 void VDataSeries::setParticle( const rtl::OUString
& rSeriesParticle
)
365 m_aSeriesParticle
= rSeriesParticle
;
368 m_aCID
= ObjectIdentifier::createClassifiedIdentifierForParticle( m_aSeriesParticle
);
369 m_aPointCID_Stub
= ObjectIdentifier::createSeriesSubObjectStub( OBJECTTYPE_DATA_POINT
, m_aSeriesParticle
);
371 m_aLabelCID_Stub
= ObjectIdentifier::createClassifiedIdentifierWithParent(
372 OBJECTTYPE_DATA_LABEL
, ::rtl::OUString(), getLabelsCID() );
374 rtl::OUString
VDataSeries::getSeriesParticle() const
376 return m_aSeriesParticle
;
378 rtl::OUString
VDataSeries::getCID() const
382 rtl::OUString
VDataSeries::getPointCID_Stub() const
384 return m_aPointCID_Stub
;
386 rtl::OUString
VDataSeries::getErrorBarsCID() const
388 rtl::OUString
aChildParticle( ObjectIdentifier::getStringForType( OBJECTTYPE_DATA_ERRORS
) );
389 aChildParticle
+=(C2U("="));
391 return ObjectIdentifier::createClassifiedIdentifierForParticles(
392 m_aSeriesParticle
, aChildParticle
);
394 rtl::OUString
VDataSeries::getLabelsCID() const
396 rtl::OUString
aChildParticle( ObjectIdentifier::getStringForType( OBJECTTYPE_DATA_LABELS
) );
397 aChildParticle
+=(C2U("="));
399 return ObjectIdentifier::createClassifiedIdentifierForParticles(
400 m_aSeriesParticle
, aChildParticle
);
402 rtl::OUString
VDataSeries::getLabelCID_Stub() const
404 return m_aLabelCID_Stub
;
406 rtl::OUString
VDataSeries::getDataCurveCID( sal_Int32 nCurveIndex
, bool bAverageLine
) const
409 aRet
= ObjectIdentifier::createDataCurveCID( m_aSeriesParticle
, nCurveIndex
, bAverageLine
);
413 rtl::OUString
VDataSeries::getDataCurveEquationCID( sal_Int32 nCurveIndex
) const
416 aRet
= ObjectIdentifier::createDataCurveEquationCID( m_aSeriesParticle
, nCurveIndex
);
419 void VDataSeries::setPageReferenceSize( const awt::Size
& rPageRefSize
)
421 m_aReferenceSize
= rPageRefSize
;
424 StackingDirection
VDataSeries::getStackingDirection() const
426 return m_eStackingDirection
;
428 sal_Int32
VDataSeries::getAttachedAxisIndex() const
432 void VDataSeries::setConnectBars( sal_Bool bConnectBars
)
434 m_bConnectBars
= bConnectBars
;
436 sal_Bool
VDataSeries::getConnectBars() const
438 return m_bConnectBars
;
440 void VDataSeries::setGroupBarsPerAxis( sal_Bool bGroupBarsPerAxis
)
442 m_bGroupBarsPerAxis
= bGroupBarsPerAxis
;
444 sal_Bool
VDataSeries::getGroupBarsPerAxis() const
446 return m_bGroupBarsPerAxis
;
449 void VDataSeries::setStartingAngle( sal_Int32 nStartingAngle
)
451 m_nStartingAngle
= nStartingAngle
;
453 sal_Int32
VDataSeries::getStartingAngle() const
455 return m_nStartingAngle
;
458 void VDataSeries::setAttachedAxisIndex( sal_Int32 nAttachedAxisIndex
)
460 if( nAttachedAxisIndex
< 0 )
461 nAttachedAxisIndex
= 0;
462 m_nAxisIndex
= nAttachedAxisIndex
;
465 sal_Int32
VDataSeries::getTotalPointCount() const
467 return m_nPointCount
;
470 double VDataSeries::getXValue( sal_Int32 index
) const
475 if( 0<=index
&& index
<m_aValues_X
.getLength() )
476 fRet
= m_aValues_X
.Doubles
[index
];
478 ::rtl::math::setNan( &fRet
);
482 // #i70133# always return correct X position - needed for short data series
483 if( 0<=index
/*&& index < m_nPointCount*/ )
484 fRet
= index
+1;//first category (index 0) matches with real number 1.0
486 ::rtl::math::setNan( &fRet
);
488 lcl_maybeReplaceNanWithZero( fRet
, getMissingValueTreatment() );
492 double VDataSeries::getYValue( sal_Int32 index
) const
497 if( 0<=index
&& index
<m_aValues_Y
.getLength() )
498 fRet
= m_aValues_Y
.Doubles
[index
];
500 ::rtl::math::setNan( &fRet
);
504 // #i70133# always return correct X position - needed for short data series
505 if( 0<=index
/*&& index < m_nPointCount*/ )
506 fRet
= index
+1;//first category (index 0) matches with real number 1.0
508 ::rtl::math::setNan( &fRet
);
510 lcl_maybeReplaceNanWithZero( fRet
, getMissingValueTreatment() );
514 double VDataSeries::getY_Min( sal_Int32 index
) const
516 return m_aValues_Y_Min
.getValue( index
);
518 double VDataSeries::getY_Max( sal_Int32 index
) const
520 return m_aValues_Y_Max
.getValue( index
);
522 double VDataSeries::getY_First( sal_Int32 index
) const
524 return m_aValues_Y_First
.getValue( index
);
526 double VDataSeries::getY_Last( sal_Int32 index
) const
528 return m_aValues_Y_Last
.getValue( index
);
530 double VDataSeries::getBubble_Size( sal_Int32 index
) const
532 return m_aValues_Bubble_Size
.getValue( index
);
535 bool VDataSeries::hasExplicitNumberFormat( sal_Int32 nPointIndex
, bool bForPercentage
) const
537 rtl::OUString
aPropName( bForPercentage
? C2U( "PercentageNumberFormat" ) : C2U( "NumberFormat" ) );
538 bool bHasNumberFormat
= false;
539 uno::Reference
< beans::XPropertySet
> xPointProp( this->getPropertiesOfPoint( nPointIndex
));
540 sal_Int32 nNumberFormat
= -1;
541 if( xPointProp
.is() && (xPointProp
->getPropertyValue(aPropName
) >>= nNumberFormat
) )
542 bHasNumberFormat
= true;
543 return bHasNumberFormat
;
545 sal_Int32
VDataSeries::getExplicitNumberFormat( sal_Int32 nPointIndex
, bool bForPercentage
) const
547 rtl::OUString
aPropName( bForPercentage
? C2U( "PercentageNumberFormat" ) : C2U( "NumberFormat" ) );
548 sal_Int32 nNumberFormat
= -1;
549 uno::Reference
< beans::XPropertySet
> xPointProp( this->getPropertiesOfPoint( nPointIndex
));
550 if( xPointProp
.is() )
551 xPointProp
->getPropertyValue(aPropName
) >>= nNumberFormat
;
552 return nNumberFormat
;
554 void VDataSeries::setRoleOfSequenceForDataLabelNumberFormatDetection( const rtl::OUString
& rRole
)
556 if( rRole
.equals(C2U("values-y")) )
557 m_pValueSequenceForDataLabelNumberFormatDetection
= &m_aValues_Y
;
558 else if( rRole
.equals(C2U("values-size")) )
559 m_pValueSequenceForDataLabelNumberFormatDetection
= &m_aValues_Bubble_Size
;
560 else if( rRole
.equals(C2U("values-min")) )
561 m_pValueSequenceForDataLabelNumberFormatDetection
= &m_aValues_Y_Min
;
562 else if( rRole
.equals(C2U("values-max")) )
563 m_pValueSequenceForDataLabelNumberFormatDetection
= &m_aValues_Y_Max
;
564 else if( rRole
.equals(C2U("values-first")) )
565 m_pValueSequenceForDataLabelNumberFormatDetection
= &m_aValues_Y_First
;
566 else if( rRole
.equals(C2U("values-last")) )
567 m_pValueSequenceForDataLabelNumberFormatDetection
= &m_aValues_Y_Last
;
568 else if( rRole
.equals(C2U("values-x")) )
569 m_pValueSequenceForDataLabelNumberFormatDetection
= &m_aValues_X
;
571 bool VDataSeries::shouldLabelNumberFormatKeyBeDetectedFromYAxis() const
573 if( m_pValueSequenceForDataLabelNumberFormatDetection
== &m_aValues_Bubble_Size
)
575 else if( m_pValueSequenceForDataLabelNumberFormatDetection
== &m_aValues_X
)
579 sal_Int32
VDataSeries::detectNumberFormatKey( sal_Int32 index
) const
582 if( m_pValueSequenceForDataLabelNumberFormatDetection
)
583 nRet
= m_pValueSequenceForDataLabelNumberFormatDetection
->detectNumberFormatKey( index
);
587 sal_Int32
VDataSeries::getLabelPlacement( sal_Int32 nPointIndex
, const uno::Reference
< chart2::XChartType
>& xChartType
, sal_Int32 nDimensionCount
, sal_Bool bSwapXAndY
) const
589 sal_Int32 nLabelPlacement
=0;
592 uno::Reference
< beans::XPropertySet
> xPointProps( this->getPropertiesOfPoint( nPointIndex
) );
593 if( xPointProps
.is() )
594 xPointProps
->getPropertyValue( C2U( "LabelPlacement" ) ) >>= nLabelPlacement
;
596 //ensure that the set label placement is supported by this charttype
598 uno::Sequence
< sal_Int32
> aAvailablePlacements( ChartTypeHelper::getSupportedLabelPlacements(
599 xChartType
, nDimensionCount
, bSwapXAndY
, m_xDataSeries
) );
601 for( sal_Int32 nN
= 0; nN
< aAvailablePlacements
.getLength(); nN
++ )
602 if( aAvailablePlacements
[nN
] == nLabelPlacement
)
603 return nLabelPlacement
; //ok
605 //otherwise use the first supported one
606 if( aAvailablePlacements
.getLength() )
608 nLabelPlacement
= aAvailablePlacements
[0];
609 return nLabelPlacement
;
612 DBG_ERROR("no label placement supported");
614 catch( uno::Exception
& e
)
616 ASSERT_EXCEPTION( e
);
618 return nLabelPlacement
;
621 double VDataSeries::getMinimumofAllDifferentYValues( sal_Int32 index
) const
624 ::rtl::math::setInf(&fMin
, false);
626 if( !m_aValues_Y
.is() &&
627 (m_aValues_Y_Min
.is() || m_aValues_Y_Max
.is()
628 || m_aValues_Y_First
.is() || m_aValues_Y_Last
.is() ) )
630 double fY_Min
= getY_Min( index
);
631 double fY_Max
= getY_Max( index
);
632 double fY_First
= getY_First( index
);
633 double fY_Last
= getY_Last( index
);
646 double fY
= getYValue( index
);
651 if( ::rtl::math::isInf(fMin
) )
652 ::rtl::math::setNan(&fMin
);
657 double VDataSeries::getMaximumofAllDifferentYValues( sal_Int32 index
) const
660 ::rtl::math::setInf(&fMax
, true);
662 if( !m_aValues_Y
.is() &&
663 (m_aValues_Y_Min
.is() || m_aValues_Y_Max
.is()
664 || m_aValues_Y_First
.is() || m_aValues_Y_Last
.is() ) )
666 double fY_Min
= getY_Min( index
);
667 double fY_Max
= getY_Max( index
);
668 double fY_First
= getY_First( index
);
669 double fY_Last
= getY_Last( index
);
682 double fY
= getYValue( index
);
687 if( ::rtl::math::isInf(fMax
) )
688 ::rtl::math::setNan(&fMax
);
693 uno::Sequence
< double > VDataSeries::getAllX() const
695 if(!m_aValues_X
.is() && !m_aValues_X
.getLength() && m_nPointCount
)
697 //init x values from category indexes
698 //first category (index 0) matches with real number 1.0
699 m_aValues_X
.Doubles
.realloc( m_nPointCount
);
700 for(sal_Int32 nN
=m_aValues_X
.getLength();nN
--;)
701 m_aValues_X
.Doubles
[nN
] = nN
+1;
703 return m_aValues_X
.Doubles
;
706 uno::Sequence
< double > VDataSeries::getAllY() const
708 if(!m_aValues_Y
.is() && !m_aValues_Y
.getLength() && m_nPointCount
)
710 //init y values from indexes
711 //first y-value (index 0) matches with real number 1.0
712 m_aValues_Y
.Doubles
.realloc( m_nPointCount
);
713 for(sal_Int32 nN
=m_aValues_Y
.getLength();nN
--;)
714 m_aValues_Y
.Doubles
[nN
] = nN
+1;
716 return m_aValues_Y
.Doubles
;
719 double VDataSeries::getYMeanValue() const
721 if( ::rtl::math::isNan( m_fYMeanValue
) )
723 uno::Reference
< XRegressionCurveCalculator
> xCalculator( RegressionCurveHelper::createRegressionCurveCalculatorByServiceName( C2U("com.sun.star.chart2.MeanValueRegressionCurve") ) );
724 uno::Sequence
< double > aXValuesDummy
;
725 xCalculator
->recalculateRegression( aXValuesDummy
, getAllY() );
726 double fXDummy
= 1.0;
727 m_fYMeanValue
= xCalculator
->getCurveValue( fXDummy
);
729 return m_fYMeanValue
;
732 ::std::auto_ptr
< Symbol
> getSymbolPropertiesFromPropertySet(
733 const uno::Reference
< beans::XPropertySet
>& xProp
)
735 ::std::auto_ptr
< Symbol
> apSymbolProps( new Symbol() );
738 if( xProp
->getPropertyValue( C2U( "Symbol" ) ) >>= *apSymbolProps
)
740 // border of symbols always black
741 apSymbolProps
->BorderColor
= 0x000000;
742 //use main color to fill symbols
743 xProp
->getPropertyValue( C2U( "Color" ) ) >>= apSymbolProps
->FillColor
;
746 apSymbolProps
.reset();
748 catch( uno::Exception
&e
)
750 ASSERT_EXCEPTION( e
);
752 return apSymbolProps
;
755 Symbol
* VDataSeries::getSymbolProperties( sal_Int32 index
) const
758 if( isAttributedDataPoint( index
) )
760 adaptPointCache( index
);
761 if(!m_apSymbolProperties_AttributedPoint
.get())
762 m_apSymbolProperties_AttributedPoint
= getSymbolPropertiesFromPropertySet( this->getPropertiesOfPoint( index
) );
763 pRet
= m_apSymbolProperties_AttributedPoint
.get();
764 //if a single data point does not have symbols but the dataseries itself has symbols
765 //we create an invisible symbol shape to enable selection of that point
766 if( !pRet
|| pRet
->Style
== SymbolStyle_NONE
)
768 if(!m_apSymbolProperties_Series
.get())
769 m_apSymbolProperties_Series
= getSymbolPropertiesFromPropertySet( this->getPropertiesOfSeries() );
770 if( m_apSymbolProperties_Series
.get() && m_apSymbolProperties_Series
->Style
!= SymbolStyle_NONE
)
772 if(!m_apSymbolProperties_InvisibleSymbolForSelection
.get())
774 m_apSymbolProperties_InvisibleSymbolForSelection
= ::std::auto_ptr
< Symbol
>( new Symbol() );
775 m_apSymbolProperties_InvisibleSymbolForSelection
->Style
= SymbolStyle_STANDARD
;
776 m_apSymbolProperties_InvisibleSymbolForSelection
->StandardSymbol
= 0;//square
777 m_apSymbolProperties_InvisibleSymbolForSelection
->Size
= m_apSymbolProperties_Series
->Size
;
778 m_apSymbolProperties_InvisibleSymbolForSelection
->BorderColor
= 0xff000000;//invisible
779 m_apSymbolProperties_InvisibleSymbolForSelection
->FillColor
= 0xff000000;//invisible
781 pRet
= m_apSymbolProperties_InvisibleSymbolForSelection
.get();
787 if(!m_apSymbolProperties_Series
.get())
788 m_apSymbolProperties_Series
= getSymbolPropertiesFromPropertySet( this->getPropertiesOfSeries() );
789 pRet
= m_apSymbolProperties_Series
.get();
792 if( pRet
&& pRet
->Style
== SymbolStyle_AUTO
)
794 pRet
->Style
= SymbolStyle_STANDARD
;
796 sal_Int32 nIndex
= m_nGlobalSeriesIndex
;
799 pRet
->StandardSymbol
= nIndex
;
805 uno::Reference
< beans::XPropertySet
> VDataSeries::getYErrorBarProperties( sal_Int32 index
) const
807 uno::Reference
< beans::XPropertySet
> xErrorBarProp
;
809 uno::Reference
< beans::XPropertySet
> xPointProp( this->getPropertiesOfPoint( index
));
810 if( xPointProp
.is() )
811 xPointProp
->getPropertyValue( C2U( "ErrorBarY" )) >>= xErrorBarProp
;
812 return xErrorBarProp
;
815 bool VDataSeries::hasPointOwnColor( sal_Int32 index
) const
817 if( !isAttributedDataPoint(index
) )
822 uno::Reference
< beans::XPropertyState
> xPointState( this->getPropertiesOfPoint(index
), uno::UNO_QUERY_THROW
);
823 return (xPointState
->getPropertyState( C2U("Color")) != beans::PropertyState_DEFAULT_VALUE
);
825 catch( uno::Exception
& e
)
827 ASSERT_EXCEPTION( e
);
832 bool VDataSeries::isAttributedDataPoint( sal_Int32 index
) const
834 //returns true if the data point assigned by the given index has set it's own properties
835 if( index
>=m_nPointCount
|| m_nPointCount
==0)
837 for(sal_Int32 nN
=m_aAttributedDataPointIndexList
.getLength();nN
--;)
839 if(index
==m_aAttributedDataPointIndexList
[nN
])
845 bool VDataSeries::isVaryColorsByPoint() const
847 bool bVaryColorsByPoint
= false;
848 Reference
< beans::XPropertySet
> xSeriesProp( this->getPropertiesOfSeries() );
849 if( xSeriesProp
.is() )
850 xSeriesProp
->getPropertyValue( C2U("VaryColorsByPoint") ) >>= bVaryColorsByPoint
;
851 return bVaryColorsByPoint
;
854 uno::Reference
< beans::XPropertySet
> VDataSeries::getPropertiesOfPoint( sal_Int32 index
) const
856 if( isAttributedDataPoint( index
) )
857 return m_xDataSeries
->getDataPointByIndex(index
);
858 return this->getPropertiesOfSeries();
861 uno::Reference
< beans::XPropertySet
> VDataSeries::getPropertiesOfSeries() const
863 return uno::Reference
<beans::XPropertySet
>(m_xDataSeries
, uno::UNO_QUERY
);
866 ::std::auto_ptr
< DataPointLabel
> getDataPointLabelFromPropertySet(
867 const uno::Reference
< beans::XPropertySet
>& xProp
)
869 ::std::auto_ptr
< DataPointLabel
> apLabel( new DataPointLabel() );
872 if( !(xProp
->getPropertyValue( C2U( "Label" ) ) >>= *apLabel
) )
875 catch( uno::Exception
&e
)
877 ASSERT_EXCEPTION( e
);
882 void VDataSeries::adaptPointCache( sal_Int32 nNewPointIndex
) const
884 if( m_nCurrentAttributedPoint
!= nNewPointIndex
)
886 m_apLabel_AttributedPoint
.reset();
887 m_apLabelPropNames_AttributedPoint
.reset();
888 m_apLabelPropValues_AttributedPoint
.reset();
889 m_apSymbolProperties_AttributedPoint
.reset();
890 m_nCurrentAttributedPoint
= nNewPointIndex
;
894 DataPointLabel
* VDataSeries::getDataPointLabel( sal_Int32 index
) const
896 DataPointLabel
* pRet
= NULL
;
897 if( isAttributedDataPoint( index
) )
899 adaptPointCache( index
);
900 if( !m_apLabel_AttributedPoint
.get() )
901 m_apLabel_AttributedPoint
= getDataPointLabelFromPropertySet( this->getPropertiesOfPoint( index
) );
902 pRet
= m_apLabel_AttributedPoint
.get();
906 if(!m_apLabel_Series
.get())
907 m_apLabel_Series
= getDataPointLabelFromPropertySet( this->getPropertiesOfPoint( index
) );
908 pRet
= m_apLabel_Series
.get();
910 if( !m_bAllowPercentValueInDataLabel
)
913 pRet
->ShowNumberInPercent
= false;
918 DataPointLabel
* VDataSeries::getDataPointLabelIfLabel( sal_Int32 index
) const
920 DataPointLabel
* pLabel
= this->getDataPointLabel( index
);
921 if( !pLabel
|| (!pLabel
->ShowNumber
&& !pLabel
->ShowNumberInPercent
922 && !pLabel
->ShowCategoryName
) )
927 bool VDataSeries::getTextLabelMultiPropertyLists( sal_Int32 index
928 , tNameSequence
*& pPropNames
929 , tAnySequence
*& pPropValues
) const
931 pPropNames
= NULL
; pPropValues
= NULL
;
932 uno::Reference
< beans::XPropertySet
> xTextProp
;
933 bool bDoDynamicFontResize
= false;
934 if( isAttributedDataPoint( index
) )
936 adaptPointCache( index
);
937 if(!m_apLabelPropValues_AttributedPoint
.get())
939 pPropNames
= new tNameSequence();
940 pPropValues
= new tAnySequence();
941 xTextProp
.set( this->getPropertiesOfPoint( index
));
942 PropertyMapper::getTextLabelMultiPropertyLists( xTextProp
, *pPropNames
, *pPropValues
);
943 m_apLabelPropNames_AttributedPoint
= ::std::auto_ptr
< tNameSequence
>(pPropNames
);
944 m_apLabelPropValues_AttributedPoint
= ::std::auto_ptr
< tAnySequence
>(pPropValues
);
945 bDoDynamicFontResize
= true;
947 pPropNames
= m_apLabelPropNames_AttributedPoint
.get();
948 pPropValues
= m_apLabelPropValues_AttributedPoint
.get();
952 if(!m_apLabelPropValues_Series
.get())
954 pPropNames
= new tNameSequence();
955 pPropValues
= new tAnySequence();
956 xTextProp
.set( this->getPropertiesOfPoint( index
));
957 PropertyMapper::getTextLabelMultiPropertyLists( xTextProp
, *pPropNames
, *pPropValues
);
958 m_apLabelPropNames_Series
= ::std::auto_ptr
< tNameSequence
>(pPropNames
);
959 m_apLabelPropValues_Series
= ::std::auto_ptr
< tAnySequence
>(pPropValues
);
960 bDoDynamicFontResize
= true;
962 pPropNames
= m_apLabelPropNames_Series
.get();
963 pPropValues
= m_apLabelPropValues_Series
.get();
966 if( bDoDynamicFontResize
&&
967 pPropNames
&& pPropValues
&&
970 LabelPositionHelper::doDynamicFontResize( *pPropValues
, *pPropNames
, xTextProp
, m_aReferenceSize
);
972 if(pPropNames
&&pPropValues
)
977 void VDataSeries::setMissingValueTreatment( sal_Int32 nMissingValueTreatment
)
979 m_nMissingValueTreatment
= nMissingValueTreatment
;
982 sal_Int32
VDataSeries::getMissingValueTreatment() const
984 return m_nMissingValueTreatment
;
987 //.............................................................................
989 //.............................................................................