merge the formfield patch from ooo-build
[ooovba.git] / chart2 / source / view / main / VDataSeries.cxx
blob6acb0379b09935afba4275817b1702dbff77a8f3
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: 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"
35 #include "macros.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 //.............................................................................
58 namespace chart
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 )
67 Model = xModel;
68 Doubles = DataSequenceToDoubleSequence( xModel );
71 bool VDataSequence::is() const
73 return Model.is();
75 void VDataSequence::clear()
77 Model = NULL;
78 Doubles.realloc(0);
81 double VDataSequence::getValue( sal_Int32 index ) const
83 if( 0<=index && index<Doubles.getLength() )
84 return Doubles[index];
85 else
87 double fNan;
88 ::rtl::math::setNan( & fNan );
89 return 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() &&
99 Model.is())
101 nNumberFormatKey = Model->getNumberFormatKeyByIndex( index );
104 return nNumberFormatKey;
107 sal_Int32 VDataSequence::getLength() const
109 return Doubles.getLength();
112 namespace
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];
123 return false;
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] ) )
134 return;
136 //no double value is countained
137 //is there any text?
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() )
144 rData.clear();
145 return;
148 //no content at all
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)) )
155 rfValue = 0.0;
160 VDataSeries::VDataSeries( const uno::Reference< XDataSeries >& xDataSeries )
161 : m_nPolygonIndex(0)
162 , m_fLogicMinX(0.0)
163 , m_fLogicMaxX(0.0)
164 , m_fLogicZPos(0.0)
165 , m_xGroupShape(NULL)
166 , m_xLabelsGroupShape(NULL)
167 , m_xErrorBarsGroupShape(NULL)
168 , m_xFrontSubGroupShape(NULL)
169 , m_xBackSubGroupShape(NULL)
170 , m_xDataSeries(xDataSeries)
171 , m_aDataSequences()
172 , m_nPointCount(0)
174 , m_aValues_X()
175 , m_aValues_Y()
176 , m_aValues_Z()
177 , m_aValues_Y_Min()
178 , m_aValues_Y_Max()
179 , m_aValues_Y_First()
180 , m_aValues_Y_Last()
181 , m_aValues_Bubble_Size()
182 , m_pValueSequenceForDataLabelNumberFormatDetection(&m_aValues_Y)
184 , m_fYMeanValue(1.0)
186 , m_aAttributedDataPointIndexList()
188 , m_eStackingDirection(StackingDirection_NO_STACKING)
189 , m_nAxisIndex(0)
190 , m_bConnectBars(sal_False)
191 , m_bGroupBarsPerAxis(sal_True)
192 , m_nStartingAngle(90)
194 , m_aSeriesParticle()
195 , m_aCID()
196 , m_aPointCID_Stub()
197 , m_aLabelCID_Stub()
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())
225 continue;
226 uno::Reference<data::XDataSequence> xDataSequence( m_aDataSequences[nN]->getValues());
227 uno::Reference<beans::XPropertySet> xProp(xDataSequence, uno::UNO_QUERY );
228 if( xProp.is())
232 uno::Any aARole = xProp->getPropertyValue( C2U( "Role" ) );
233 rtl::OUString aRole;
234 aARole >>= aRole;
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 );
277 if( xProp.is())
281 //get AttributedDataPoints
282 xProp->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= m_aAttributedDataPointIndexList;
284 xProp->getPropertyValue( C2U( "StackingDirection" ) ) >>= m_eStackingDirection;
286 xProp->getPropertyValue( C2U( "AttachedAxisIndex" ) ) >>= m_nAxisIndex;
287 if(m_nAxisIndex<0)
288 m_nAxisIndex=0;
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
307 double fNan;
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 );
318 //do sort
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);
349 m_nPolygonIndex = 0;
352 void VDataSeries::setCategoryXAxis()
354 m_aValues_X.clear();
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;
367 //get CID
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
380 return m_aCID;
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
408 rtl::OUString aRet;
409 aRet = ObjectIdentifier::createDataCurveCID( m_aSeriesParticle, nCurveIndex, bAverageLine );
410 return aRet;
413 rtl::OUString VDataSeries::getDataCurveEquationCID( sal_Int32 nCurveIndex ) const
415 rtl::OUString aRet;
416 aRet = ObjectIdentifier::createDataCurveEquationCID( m_aSeriesParticle, nCurveIndex );
417 return aRet;
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
430 return m_nAxisIndex;
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
472 double fRet = 0.0;
473 if(m_aValues_X.is())
475 if( 0<=index && index<m_aValues_X.getLength() )
476 fRet = m_aValues_X.Doubles[index];
477 else
478 ::rtl::math::setNan( &fRet );
480 else
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
485 else
486 ::rtl::math::setNan( &fRet );
488 lcl_maybeReplaceNanWithZero( fRet, getMissingValueTreatment() );
489 return fRet;
492 double VDataSeries::getYValue( sal_Int32 index ) const
494 double fRet = 0.0;
495 if(m_aValues_Y.is())
497 if( 0<=index && index<m_aValues_Y.getLength() )
498 fRet = m_aValues_Y.Doubles[index];
499 else
500 ::rtl::math::setNan( &fRet );
502 else
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
507 else
508 ::rtl::math::setNan( &fRet );
510 lcl_maybeReplaceNanWithZero( fRet, getMissingValueTreatment() );
511 return fRet;
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 )
574 return false;
575 else if( m_pValueSequenceForDataLabelNumberFormatDetection == &m_aValues_X )
576 return false;
577 return true;
579 sal_Int32 VDataSeries::detectNumberFormatKey( sal_Int32 index ) const
581 sal_Int32 nRet = 0;
582 if( m_pValueSequenceForDataLabelNumberFormatDetection )
583 nRet = m_pValueSequenceForDataLabelNumberFormatDetection->detectNumberFormatKey( index );
584 return nRet;
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
623 double fMin=0.0;
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 );
635 if(fMin>fY_First)
636 fMin=fY_First;
637 if(fMin>fY_Last)
638 fMin=fY_Last;
639 if(fMin>fY_Min)
640 fMin=fY_Min;
641 if(fMin>fY_Max)
642 fMin=fY_Max;
644 else
646 double fY = getYValue( index );
647 if(fMin>fY)
648 fMin=fY;
651 if( ::rtl::math::isInf(fMin) )
652 ::rtl::math::setNan(&fMin);
654 return fMin;
657 double VDataSeries::getMaximumofAllDifferentYValues( sal_Int32 index ) const
659 double fMax=0.0;
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 );
671 if(fMax<fY_First)
672 fMax=fY_First;
673 if(fMax<fY_Last)
674 fMax=fY_Last;
675 if(fMax<fY_Min)
676 fMax=fY_Min;
677 if(fMax<fY_Max)
678 fMax=fY_Max;
680 else
682 double fY = getYValue( index );
683 if(fMax<fY)
684 fMax=fY;
687 if( ::rtl::math::isInf(fMax) )
688 ::rtl::math::setNan(&fMax);
690 return 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;
745 else
746 apSymbolProps.reset();
748 catch( uno::Exception &e)
750 ASSERT_EXCEPTION( e );
752 return apSymbolProps;
755 Symbol* VDataSeries::getSymbolProperties( sal_Int32 index ) const
757 Symbol* pRet=NULL;
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();
785 else
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;
797 if(m_aValues_X.is())
798 nIndex++;
799 pRet->StandardSymbol = nIndex;
802 return pRet;
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) )
818 return false;
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 );
829 return false;
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)
836 return false;
837 for(sal_Int32 nN=m_aAttributedDataPointIndexList.getLength();nN--;)
839 if(index==m_aAttributedDataPointIndexList[nN])
840 return true;
842 return false;
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) )
873 apLabel.reset();
875 catch( uno::Exception &e)
877 ASSERT_EXCEPTION( e );
879 return apLabel;
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();
904 else
906 if(!m_apLabel_Series.get())
907 m_apLabel_Series = getDataPointLabelFromPropertySet( this->getPropertiesOfPoint( index ) );
908 pRet = m_apLabel_Series.get();
910 if( !m_bAllowPercentValueInDataLabel )
912 if( pRet )
913 pRet->ShowNumberInPercent = false;
915 return pRet;
918 DataPointLabel* VDataSeries::getDataPointLabelIfLabel( sal_Int32 index ) const
920 DataPointLabel* pLabel = this->getDataPointLabel( index );
921 if( !pLabel || (!pLabel->ShowNumber && !pLabel->ShowNumberInPercent
922 && !pLabel->ShowCategoryName ) )
923 return 0;
924 return pLabel;
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();
950 else
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 &&
968 xTextProp.is())
970 LabelPositionHelper::doDynamicFontResize( *pPropValues, *pPropNames, xTextProp, m_aReferenceSize );
972 if(pPropNames&&pPropValues)
973 return true;
974 return false;
977 void VDataSeries::setMissingValueTreatment( sal_Int32 nMissingValueTreatment )
979 m_nMissingValueTreatment = nMissingValueTreatment;
982 sal_Int32 VDataSeries::getMissingValueTreatment() const
984 return m_nMissingValueTreatment;
987 //.............................................................................
988 } //namespace chart
989 //.............................................................................