LibreOffice Module chart2 (master) 1
VDataSeries.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <limits>
21#include <memory>
22#include <VDataSeries.hxx>
23#include <DataSeries.hxx>
25#include <ObjectIdentifier.hxx>
26#include <CommonConverters.hxx>
28#include <ChartType.hxx>
29#include <ChartTypeHelper.hxx>
32#include <unonames.hxx>
33
34#include <com/sun/star/chart/MissingValueTreatment.hpp>
35#include <com/sun/star/chart2/DataPointLabel.hpp>
36#include <com/sun/star/chart2/Symbol.hpp>
37#include <com/sun/star/chart2/XRegressionCurveCalculator.hpp>
38#include <com/sun/star/chart2/RelativePosition.hpp>
39
40#include <osl/diagnose.h>
41#include <tools/color.hxx>
43#include <com/sun/star/beans/XPropertySet.hpp>
44#include <com/sun/star/beans/XPropertyState.hpp>
45
46namespace chart {
47
48using namespace ::com::sun::star;
49using namespace ::com::sun::star::chart2;
50using ::com::sun::star::uno::Reference;
51using namespace ::chart::DataSeriesProperties;
52
54{
57}
58
60{
61 return m_xModel.is();
62}
64{
65 m_xModel = nullptr;
66 m_aValues.realloc(0);
67}
68
69double VDataSequence::getValue( sal_Int32 index ) const
70{
71 if( 0<=index && index<m_aValues.getLength() )
72 return m_aValues[index];
73 return std::numeric_limits<double>::quiet_NaN();
74}
75
76sal_Int32 VDataSequence::detectNumberFormatKey( sal_Int32 index ) const
77{
78 sal_Int32 nNumberFormatKey = -1;
79
80 // -1 is allowed and means a key for the whole sequence
81 if( -1<=index && index<m_aValues.getLength() && m_xModel.is())
82 {
83 nNumberFormatKey = m_xModel->getNumberFormatKeyByIndex( index );
84 }
85
86 return nNumberFormatKey;
87}
88
89sal_Int32 VDataSequence::getLength() const
90{
91 return m_aValues.getLength();
92}
93
94namespace
95{
96struct lcl_LessXOfPoint
97{
98 bool operator() ( const std::vector< double >& first,
99 const std::vector< double >& second )
100 {
101 if( !first.empty() && !second.empty() )
102 {
103 return first[0]<second[0];
104 }
105 return false;
106 }
107};
108
109void lcl_clearIfNoValuesButTextIsContained( VDataSequence& rData, const uno::Reference<data::XDataSequence>& xDataSequence )
110{
111 //#i71686#, #i101968#, #i102428#
112 sal_Int32 nCount = rData.m_aValues.getLength();
113 for( sal_Int32 i = 0; i < nCount; ++i )
114 {
115 if( !std::isnan( rData.m_aValues[i] ) )
116 return;
117 }
118 //no double value is contained
119 //is there any text?
120 uno::Sequence< OUString > aStrings( DataSequenceToStringSequence( xDataSequence ) );
121 sal_Int32 nTextCount = aStrings.getLength();
122 for( sal_Int32 j = 0; j < nTextCount; ++j )
123 {
124 if( !aStrings[j].isEmpty() )
125 {
126 rData.clear();
127 return;
128 }
129 }
130 //no content at all
131}
132
133void lcl_maybeReplaceNanWithZero( double& rfValue, sal_Int32 nMissingValueTreatment )
134{
135 if( nMissingValueTreatment == css::chart::MissingValueTreatment::USE_ZERO
136 && (std::isnan(rfValue) || std::isinf(rfValue)) )
137 rfValue = 0.0;
138}
139
140}
141
143 : m_nPolygonIndex(0)
144 , m_fLogicMinX(0.0)
145 , m_fLogicMaxX(0.0)
146 , m_fLogicZPos(0.0)
147 , m_xDataSeries(xDataSeries)
148 , m_nPointCount(0)
149 , m_pValueSequenceForDataLabelNumberFormatDetection(&m_aValues_Y)
150 , m_fXMeanValue(std::numeric_limits<double>::quiet_NaN())
151 , m_fYMeanValue(std::numeric_limits<double>::quiet_NaN())
152 , m_eStackingDirection(StackingDirection_NO_STACKING)
153 , m_nAxisIndex(0)
154 , m_bConnectBars(false)
155 , m_bGroupBarsPerAxis(true)
156 , m_nStartingAngle(90)
157 , m_nGlobalSeriesIndex(0)
158 , m_nCurrentAttributedPoint(-1)
159 , m_nMissingValueTreatment(css::chart::MissingValueTreatment::LEAVE_GAP)
160 , m_bAllowPercentValueInDataLabel(false)
161 , mpOldSeries(nullptr)
162 , mnPercent(0.0)
163{
164 m_xDataSeriesProps = m_xDataSeries;
165
166 const std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > & aDataSequences =
167 m_xDataSeries->getDataSequences2();
168
169 for(sal_Int32 nN = aDataSequences.size();nN--;)
170 {
171 uno::Reference<data::XDataSequence> xDataSequence( aDataSequences[nN]->getValues());
172 uno::Reference<beans::XPropertySet> xProp(xDataSequence, uno::UNO_QUERY );
173 if( xProp.is())
174 {
175 try
176 {
177 uno::Any aARole = xProp->getPropertyValue("Role");
178 OUString aRole;
179 aARole >>= aRole;
180
181 if (aRole == "values-x")
182 {
183 m_aValues_X.init( xDataSequence );
184 lcl_clearIfNoValuesButTextIsContained( m_aValues_X, xDataSequence );
185 }
186 else if (aRole =="values-y")
187 m_aValues_Y.init( xDataSequence );
188 else if (aRole == "values-min")
189 m_aValues_Y_Min.init( xDataSequence );
190 else if (aRole == "values-max")
191 m_aValues_Y_Max.init( xDataSequence );
192 else if (aRole == "values-first")
193 m_aValues_Y_First.init( xDataSequence );
194 else if (aRole == "values-last")
195 m_aValues_Y_Last.init( xDataSequence );
196 else if (aRole == "values-size")
197 m_aValues_Bubble_Size.init( xDataSequence );
198 else
199 {
200 VDataSequence aSequence;
201 aSequence.init(xDataSequence);
202 m_PropertyMap.insert(std::make_pair(aRole, aSequence));
203 }
204 }
205 catch( const uno::Exception& )
206 {
207 TOOLS_WARN_EXCEPTION("chart2", "" );
208 }
209 }
210 }
211
212 //determine the point count
213 m_nPointCount = m_aValues_Y.getLength();
214 {
215 if( m_nPointCount < m_aValues_Bubble_Size.getLength() )
216 m_nPointCount = m_aValues_Bubble_Size.getLength();
217 if( m_nPointCount < m_aValues_Y_Min.getLength() )
218 m_nPointCount = m_aValues_Y_Min.getLength();
219 if( m_nPointCount < m_aValues_Y_Max.getLength() )
220 m_nPointCount = m_aValues_Y_Max.getLength();
221 if( m_nPointCount < m_aValues_Y_First.getLength() )
222 m_nPointCount = m_aValues_Y_First.getLength();
223 if( m_nPointCount < m_aValues_Y_Last.getLength() )
224 m_nPointCount = m_aValues_Y_Last.getLength();
225 }
226
227 if( !xDataSeries.is())
228 return;
229
230 try
231 {
232 // "AttributedDataPoints"
233 xDataSeries->getFastPropertyValue(PROP_DATASERIES_ATTRIBUTED_DATA_POINTS) >>= m_aAttributedDataPointIndexList;
234
235 xDataSeries->getFastPropertyValue(PROP_DATASERIES_STACKING_DIRECTION) >>= m_eStackingDirection; // "StackingDirection"
236
237 xDataSeries->getFastPropertyValue(PROP_DATASERIES_ATTACHED_AXIS_INDEX) >>= m_nAxisIndex; // "AttachedAxisIndex"
238 if(m_nAxisIndex<0)
239 m_nAxisIndex=0;
240 }
241 catch( const uno::Exception& )
242 {
243 TOOLS_WARN_EXCEPTION("chart2", "" );
244 }
245}
246
248{
249}
250
252{
253 if( !(m_aValues_X.is() && m_aValues_X.m_aValues.hasElements()) )
254 return;
255
256 //prepare a vector for sorting
257 std::vector< std::vector< double > > aTmp;//outer vector are points, inner vector are the different values of the point
258 sal_Int32 nPointIndex = 0;
259 for( nPointIndex=0; nPointIndex < m_nPointCount; nPointIndex++ )
260 {
261 aTmp.push_back(
262 { ((nPointIndex < m_aValues_X.m_aValues.getLength()) ? m_aValues_X.m_aValues[nPointIndex]
263 : std::numeric_limits<double>::quiet_NaN()),
264 ((nPointIndex < m_aValues_Y.m_aValues.getLength()) ? m_aValues_Y.m_aValues[nPointIndex]
265 : std::numeric_limits<double>::quiet_NaN())
266 }
267 );
268 }
269
270 //do sort
271 std::stable_sort( aTmp.begin(), aTmp.end(), lcl_LessXOfPoint() );
272
273 //fill the sorted points back to the members
275 auto pDoublesX = m_aValues_X.m_aValues.getArray();
277 auto pDoublesY = m_aValues_Y.m_aValues.getArray();
278
279 for( nPointIndex=0; nPointIndex < m_nPointCount; nPointIndex++ )
280 {
281 pDoublesX[nPointIndex]=aTmp[nPointIndex][0];
282 pDoublesY[nPointIndex]=aTmp[nPointIndex][1];
283 }
284}
285
287{
288 m_xGroupShape.set(nullptr);
289 m_xLabelsGroupShape.set(nullptr);
290 m_xErrorXBarsGroupShape.set(nullptr);
291 m_xErrorYBarsGroupShape.set(nullptr);
292 m_xFrontSubGroupShape.set(nullptr);
293 m_xBackSubGroupShape.set(nullptr);
294
295 m_aPolyPolygonShape3D.clear();
296 m_nPolygonIndex = 0;
297}
298
300{
301 return m_xDataSeries;
302}
303
305{
308}
309
311{
313 m_aValues_X.init( xValues );
315}
316
318{
319 if( m_aValues_X.is() )
320 return;
321
322 m_aValues_X.init( xValues );
323 lcl_clearIfNoValuesButTextIsContained( m_aValues_X, xValues );
324}
325
326void VDataSeries::setGlobalSeriesIndex( sal_Int32 nGlobalSeriesIndex )
327{
328 m_nGlobalSeriesIndex = nGlobalSeriesIndex;
329}
330
331void VDataSeries::setParticle( const OUString& rSeriesParticle )
332{
333 m_aSeriesParticle = rSeriesParticle;
334
335 //get CID
338
341}
342OUString VDataSeries::getErrorBarsCID(bool bYError) const
343{
344 OUString aChildParticle( ObjectIdentifier::getStringForType(
346 + "=" );
347
349 m_aSeriesParticle, aChildParticle );
350}
352{
353 OUString aChildParticle( ObjectIdentifier::getStringForType( OBJECTTYPE_DATA_LABELS ) + "=" );
354
356 m_aSeriesParticle, aChildParticle );
357}
358OUString VDataSeries::getDataCurveCID( sal_Int32 nCurveIndex, bool bAverageLine ) const
359{
360 return ObjectIdentifier::createDataCurveCID( m_aSeriesParticle, nCurveIndex, bAverageLine );
361}
362
363OUString VDataSeries::getDataCurveEquationCID( sal_Int32 nCurveIndex ) const
364{
366}
367void VDataSeries::setPageReferenceSize( const awt::Size & rPageRefSize )
368{
369 m_aReferenceSize = rPageRefSize;
370}
371
372void VDataSeries::setConnectBars( bool bConnectBars )
373{
374 m_bConnectBars = bConnectBars;
375}
376
378{
379 return m_bConnectBars;
380}
381
382void VDataSeries::setGroupBarsPerAxis( bool bGroupBarsPerAxis )
383{
384 m_bGroupBarsPerAxis = bGroupBarsPerAxis;
385}
386
388{
389 return m_bGroupBarsPerAxis;
390}
391
392void VDataSeries::setStartingAngle( sal_Int32 nStartingAngle )
393{
394 m_nStartingAngle = nStartingAngle;
395}
396
398{
399 return m_nStartingAngle;
400}
401
402chart2::StackingDirection VDataSeries::getStackingDirection() const
403{
405}
406
408{
409 return m_nAxisIndex;
410}
411
412void VDataSeries::setAttachedAxisIndex( sal_Int32 nAttachedAxisIndex )
413{
414 if( nAttachedAxisIndex < 0 )
415 nAttachedAxisIndex = 0;
416 m_nAxisIndex = nAttachedAxisIndex;
417}
418
419double VDataSeries::getXValue( sal_Int32 index ) const
420{
421 double fRet = std::numeric_limits<double>::quiet_NaN();
422 if(m_aValues_X.is())
423 {
424 if( 0<=index && index<m_aValues_X.getLength() )
425 {
427 if(mpOldSeries && index < mpOldSeries->m_aValues_X.getLength())
428 {
429 double nOldVal = mpOldSeries->m_aValues_X.m_aValues[index];
430 fRet = nOldVal + (fRet - nOldVal) * mnPercent;
431 }
432 }
433 }
434 else
435 {
436 // #i70133# always return correct X position - needed for short data series
437 if( 0<=index /*&& index < m_nPointCount*/ )
438 fRet = index+1;//first category (index 0) matches with real number 1.0
439 }
440 lcl_maybeReplaceNanWithZero( fRet, getMissingValueTreatment() );
441 return fRet;
442}
443
444double VDataSeries::getYValue( sal_Int32 index ) const
445{
446 double fRet = std::numeric_limits<double>::quiet_NaN();
447 if(m_aValues_Y.is())
448 {
449 if( 0<=index && index<m_aValues_Y.getLength() )
450 {
452 if(mpOldSeries && index < mpOldSeries->m_aValues_Y.getLength())
453 {
454 double nOldVal = mpOldSeries->m_aValues_Y.m_aValues[index];
455 fRet = nOldVal + (fRet - nOldVal) * mnPercent;
456 }
457 }
458 }
459 else
460 {
461 // #i70133# always return correct X position - needed for short data series
462 if( 0<=index /*&& index < m_nPointCount*/ )
463 fRet = index+1;//first category (index 0) matches with real number 1.0
464 }
465 lcl_maybeReplaceNanWithZero( fRet, getMissingValueTreatment() );
466 return fRet;
467}
468
469void VDataSeries::getMinMaxXValue(double& fMin, double& fMax) const
470{
471 fMax = std::numeric_limits<double>::quiet_NaN();
472 fMin = std::numeric_limits<double>::quiet_NaN();
473
474 uno::Sequence< double > aValuesX = getAllX();
475
476 if(!aValuesX.hasElements())
477 return;
478
479 sal_Int32 i = 0;
480 while ( i < aValuesX.getLength() && std::isnan(aValuesX[i]) )
481 i++;
482 if ( i < aValuesX.getLength() )
483 fMax = fMin = aValuesX[i++];
484
485 for ( ; i < aValuesX.getLength(); i++)
486 {
487 const double aValue = aValuesX[i];
488 if ( aValue > fMax)
489 {
490 fMax = aValue;
491 }
492 else if ( aValue < fMin)
493 {
494 fMin = aValue;
495 }
496 }
497}
498double VDataSeries::getY_Min( sal_Int32 index ) const
499{
501}
502double VDataSeries::getY_Max( sal_Int32 index ) const
503{
505}
506double VDataSeries::getY_First( sal_Int32 index ) const
507{
509}
510double VDataSeries::getY_Last( sal_Int32 index ) const
511{
513}
514double VDataSeries::getBubble_Size( sal_Int32 index ) const
515{
516 double nNewVal = m_aValues_Bubble_Size.getValue( index );
517 if(mpOldSeries && index < mpOldSeries->m_aValues_Bubble_Size.getLength())
518 {
519 double nOldVal = mpOldSeries->m_aValues_Bubble_Size.getValue( index );
520 nNewVal = nOldVal + (nNewVal - nOldVal) * mnPercent;
521 }
522
523 return nNewVal;
524}
525
526bool VDataSeries::hasExplicitNumberFormat( sal_Int32 nPointIndex, bool bForPercentage ) const
527{
528 OUString aPropName = bForPercentage ? OUString("PercentageNumberFormat") : OUString(CHART_UNONAME_NUMFMT);
529 bool bHasNumberFormat = false;
530 bool bLinkToSource = true;
532 if( xPointProp.is() && (xPointProp->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT) >>= bLinkToSource))
533 {
534 sal_Int32 nNumberFormat = -1;
535 if( !bLinkToSource && (xPointProp->getPropertyValue(aPropName) >>= nNumberFormat))
536 bHasNumberFormat = true;
537 }
538 return bHasNumberFormat;
539}
540sal_Int32 VDataSeries::getExplicitNumberFormat( sal_Int32 nPointIndex, bool bForPercentage ) const
541{
542 OUString aPropName = bForPercentage ? OUString("PercentageNumberFormat") : OUString(CHART_UNONAME_NUMFMT);
543 sal_Int32 nNumberFormat = -1;
545 if( xPointProp.is() )
546 xPointProp->getPropertyValue(aPropName) >>= nNumberFormat;
547 return nNumberFormat;
548}
550{
551 if (rRole == u"values-y")
553 else if (rRole == u"values-size")
555 else if (rRole == u"values-min")
557 else if (rRole == u"values-max")
559 else if (rRole == u"values-first")
561 else if (rRole == u"values-last")
563 else if (rRole == u"values-x")
565}
566sal_Int32 VDataSeries::detectNumberFormatKey( sal_Int32 index ) const
567{
568 sal_Int32 nRet = 0;
571 return nRet;
572}
573
574sal_Int32 VDataSeries::getLabelPlacement( sal_Int32 nPointIndex, const rtl::Reference< ChartType >& xChartType, bool bSwapXAndY ) const
575{
576 sal_Int32 nLabelPlacement=0;
577 try
578 {
580 if( xPointProps.is() )
581 xPointProps->getPropertyValue("LabelPlacement") >>= nLabelPlacement;
582
584 xChartType, bSwapXAndY, m_xDataSeries ) );
585
586 for( sal_Int32 n : aAvailablePlacements )
587 if( n == nLabelPlacement )
588 return nLabelPlacement; //ok
589
590 //otherwise use the first supported one
591 if( aAvailablePlacements.hasElements() )
592 {
593 nLabelPlacement = aAvailablePlacements[0];
594 if( xPointProps.is() )
595 xPointProps->setPropertyValue("LabelPlacement", uno::Any(nLabelPlacement));
596 return nLabelPlacement;
597 }
598
599 OSL_FAIL("no label placement supported");
600 }
601 catch( const uno::Exception& )
602 {
603 TOOLS_WARN_EXCEPTION("chart2", "" );
604 }
605 return nLabelPlacement;
606}
607
608awt::Point VDataSeries::getLabelPosition( awt::Point aTextShapePos, sal_Int32 nPointIndex ) const
609{
610 awt::Point aPos(-1, -1);
611 try
612 {
613 RelativePosition aCustomLabelPosition;
615 if( xPointProps.is() && (xPointProps->getPropertyValue("CustomLabelPosition") >>= aCustomLabelPosition))
616 {
617 aPos.X = static_cast<sal_Int32>(aCustomLabelPosition.Primary * m_aReferenceSize.Width) + aTextShapePos.X;
618 aPos.Y = static_cast<sal_Int32>(aCustomLabelPosition.Secondary * m_aReferenceSize.Height) + aTextShapePos.Y;
619 }
620 }
621 catch (const uno::Exception&)
622 {
623 TOOLS_WARN_EXCEPTION("chart2", "");
624 }
625 return aPos;
626}
627
628bool VDataSeries::isLabelCustomPos(sal_Int32 nPointIndex) const
629{
630 bool bCustom = false;
631 try
632 {
633 if( isAttributedDataPoint(nPointIndex) )
634 {
635 uno::Reference< beans::XPropertySet > xPointProps(m_xDataSeries->getDataPointByIndex(nPointIndex));
636 RelativePosition aCustomLabelPosition;
637 if( xPointProps.is() && (xPointProps->getPropertyValue("CustomLabelPosition") >>= aCustomLabelPosition) )
638 bCustom = true;
639 }
640 }
641 catch (const uno::Exception&)
642 {
643 TOOLS_WARN_EXCEPTION("chart2", "");
644 }
645 return bCustom;
646}
647
648double VDataSeries::getMinimumofAllDifferentYValues( sal_Int32 index ) const
649{
650 double fMin = std::numeric_limits<double>::infinity();
651
652 if( !m_aValues_Y.is() &&
655 {
656 double fY_Min = getY_Min( index );
657 double fY_Max = getY_Max( index );
658 double fY_First = getY_First( index );
659 double fY_Last = getY_Last( index );
660
661 if(fMin>fY_First)
662 fMin=fY_First;
663 if(fMin>fY_Last)
664 fMin=fY_Last;
665 if(fMin>fY_Min)
666 fMin=fY_Min;
667 if(fMin>fY_Max)
668 fMin=fY_Max;
669 }
670 else
671 {
672 double fY = getYValue( index );
673 if(fMin>fY)
674 fMin=fY;
675 }
676
677 if( std::isinf(fMin) )
678 return std::numeric_limits<double>::quiet_NaN();
679
680 return fMin;
681}
682
683double VDataSeries::getMaximumofAllDifferentYValues( sal_Int32 index ) const
684{
685 double fMax = -std::numeric_limits<double>::infinity();
686
687 if( !m_aValues_Y.is() &&
690 {
691 double fY_Min = getY_Min( index );
692 double fY_Max = getY_Max( index );
693 double fY_First = getY_First( index );
694 double fY_Last = getY_Last( index );
695
696 if(fMax<fY_First)
697 fMax=fY_First;
698 if(fMax<fY_Last)
699 fMax=fY_Last;
700 if(fMax<fY_Min)
701 fMax=fY_Min;
702 if(fMax<fY_Max)
703 fMax=fY_Max;
704 }
705 else
706 {
707 double fY = getYValue( index );
708 if(fMax<fY)
709 fMax=fY;
710 }
711
712 if( std::isinf(fMax) )
713 return std::numeric_limits<double>::quiet_NaN();
714
715 return fMax;
716}
717
719{
721 {
722 //init x values from category indexes
723 //first category (index 0) matches with real number 1.0
725 auto pDoubles = m_aValues_X.m_aValues.getArray();
726 for(sal_Int32 nN=m_aValues_X.getLength();nN--;)
727 pDoubles[nN] = nN+1;
728 }
729 return m_aValues_X.m_aValues;
730}
731
733{
735 {
736 //init y values from indexes
737 //first y-value (index 0) matches with real number 1.0
739 auto pDoubles = m_aValues_Y.m_aValues.getArray();
740 for(sal_Int32 nN=m_aValues_Y.getLength();nN--;)
741 pDoubles[nN] = nN+1;
742 }
743 return m_aValues_Y.m_aValues;
744}
745
747{
748 if( std::isnan( m_fXMeanValue ) )
749 {
751 uno::Sequence< double > aXValuesDummy;
752 xCalculator->recalculateRegression( aXValuesDummy, getAllX() );
753 m_fXMeanValue = xCalculator->getCurveValue( 1.0 );
754 }
755 return m_fXMeanValue;
756}
757
759{
760 if( std::isnan( m_fYMeanValue ) )
761 {
763 RegressionCurveHelper::createRegressionCurveCalculatorByServiceName(u"com.sun.star.chart2.MeanValueRegressionCurve"));
764 uno::Sequence< double > aXValuesDummy;
765 xCalculator->recalculateRegression( aXValuesDummy, getAllY() );
766 m_fYMeanValue = xCalculator->getCurveValue( 1.0 );
767 }
768 return m_fYMeanValue;
769}
770
772{
773 Symbol aSymbolProps;
774 try
775 {
776 if( xProp->getPropertyValue("Symbol") >>= aSymbolProps )
777 {
778 //use main color to fill symbols
779 xProp->getPropertyValue("Color") >>= aSymbolProps.FillColor;
780 // border of symbols always same as fill color
781 aSymbolProps.BorderColor = aSymbolProps.FillColor;
782 }
783 else
784 return std::nullopt;
785 }
786 catch(const uno::Exception &)
787 {
788 TOOLS_WARN_EXCEPTION("chart2", "" );
789 }
790 return aSymbolProps;
791}
792
794{
795 Symbol* pRet=nullptr;
797 {
803 //if a single data point does not have symbols but the dataseries itself has symbols
804 //we create an invisible symbol shape to enable selection of that point
805 if( !pRet || pRet->Style == SymbolStyle_NONE )
806 {
810 if( m_oSymbolProperties_Series && m_oSymbolProperties_Series->Style != SymbolStyle_NONE )
811 {
813 {
815 m_oSymbolProperties_InvisibleSymbolForSelection->Style = SymbolStyle_STANDARD;
816 m_oSymbolProperties_InvisibleSymbolForSelection->StandardSymbol = 0;//square
817 m_oSymbolProperties_InvisibleSymbolForSelection->Size = com::sun::star::awt::Size(0, 0);//tdf#126033
818 m_oSymbolProperties_InvisibleSymbolForSelection->BorderColor = 0xff000000;//invisible
819 m_oSymbolProperties_InvisibleSymbolForSelection->FillColor = 0xff000000;//invisible
820 }
822 }
823 }
824 }
825 else
826 {
831 }
832
833 if( pRet && pRet->Style == SymbolStyle_AUTO )
834 {
835 pRet->Style = SymbolStyle_STANDARD;
836
837 sal_Int32 nIndex = m_nGlobalSeriesIndex;
838 if(m_aValues_X.is())
839 nIndex++;
840 pRet->StandardSymbol = nIndex;
841 }
842
843 return pRet;
844}
845
847{
849
851 if( xPointProp.is() )
852 xPointProp->getPropertyValue(CHART_UNONAME_ERRORBAR_X) >>= xErrorBarProp;
853 return xErrorBarProp;
854}
855
857{
859
861 if( xPointProp.is() )
862 xPointProp->getPropertyValue(CHART_UNONAME_ERRORBAR_Y) >>= xErrorBarProp;
863 return xErrorBarProp;
864}
865
866bool VDataSeries::hasPointOwnColor( sal_Int32 index ) const
867{
869 return false;
870
871 try
872 {
873 uno::Reference< beans::XPropertyState > xPointState( getPropertiesOfPoint(index), uno::UNO_QUERY_THROW );
874 return (xPointState->getPropertyState("Color") != beans::PropertyState_DEFAULT_VALUE );
875 }
876 catch(const uno::Exception&)
877 {
878 TOOLS_WARN_EXCEPTION("chart2", "" );
879 }
880 return false;
881}
882
883bool VDataSeries::isAttributedDataPoint( sal_Int32 index ) const
884{
885 //returns true if the data point assigned by the given index has set its own properties
887 return false;
888 for(sal_Int32 n : m_aAttributedDataPointIndexList)
889 {
890 if(index == n)
891 return true;
892 }
893 return false;
894}
895
897{
898 bool bVaryColorsByPoint = false;
899 if( m_xDataSeries )
900 m_xDataSeries->getFastPropertyValue(PROP_DATASERIES_VARY_COLORS_BY_POINT) >>= bVaryColorsByPoint; // "VaryColorsByPoint"
901 return bVaryColorsByPoint;
902}
903
905{
907 return m_xDataSeries->getDataPointByIndex(index);
908 return getPropertiesOfSeries();
909}
910
912{
913 return m_xDataSeriesProps;
914}
915
916static std::optional<DataPointLabel> getDataPointLabelFromPropertySet( const uno::Reference< beans::XPropertySet >& xProp )
917{
918 std::optional< DataPointLabel > apLabel( std::in_place );
919 try
920 {
921 if( !(xProp->getPropertyValue(CHART_UNONAME_LABEL) >>= *apLabel) )
922 apLabel.reset();
923 }
924 catch(const uno::Exception &)
925 {
926 TOOLS_WARN_EXCEPTION("chart2", "" );
927 }
928 return apLabel;
929}
930
931void VDataSeries::adaptPointCache( sal_Int32 nNewPointIndex ) const
932{
933 if( m_nCurrentAttributedPoint != nNewPointIndex )
934 {
939 m_nCurrentAttributedPoint = nNewPointIndex;
940 }
941}
942
943DataPointLabel* VDataSeries::getDataPointLabel( sal_Int32 index ) const
944{
945 DataPointLabel* pRet = nullptr;
947 {
954 }
955 else
956 {
957 if (!m_oLabel_Series)
960 if (m_oLabel_Series)
961 pRet = &*m_oLabel_Series;
962 }
964 {
965 if( pRet )
966 pRet->ShowNumberInPercent = false;
967 }
968 return pRet;
969}
970
971DataPointLabel* VDataSeries::getDataPointLabelIfLabel( sal_Int32 index ) const
972{
973 DataPointLabel* pLabel = getDataPointLabel( index );
974 if( !pLabel || (!pLabel->ShowNumber && !pLabel->ShowNumberInPercent
975 && !pLabel->ShowCategoryName && !pLabel->ShowCustomLabel && !pLabel->ShowSeriesName ) )
976 return nullptr;
977 return pLabel;
978}
979
981 , tNameSequence*& pPropNames
982 , tAnySequence*& pPropValues ) const
983{
984 pPropNames = nullptr; pPropValues = nullptr;
986 bool bDoDynamicFontResize = false;
988 {
991 {
992 // Cache these properties for this point.
995 xTextProp.set( getPropertiesOfPoint( index ));
998 bDoDynamicFontResize = true;
999 }
1000 pPropNames = m_apLabelPropNames_AttributedPoint.get();
1001 pPropValues = m_apLabelPropValues_AttributedPoint.get();
1002 }
1003 else
1004 {
1006 {
1007 // Cache these properties for the whole series.
1008 m_oLabelPropNames_Series.emplace();
1009 m_oLabelPropValues_Series.emplace();
1010 xTextProp.set( getPropertiesOfPoint( index ));
1013 bDoDynamicFontResize = true;
1014 }
1015 pPropNames = &*m_oLabelPropNames_Series;
1016 pPropValues = &*m_oLabelPropValues_Series;
1017 }
1018
1019 if( bDoDynamicFontResize &&
1020 pPropNames && pPropValues &&
1021 xTextProp.is())
1022 {
1023 LabelPositionHelper::doDynamicFontResize( *pPropValues, *pPropNames, xTextProp, m_aReferenceSize );
1024 }
1025
1026 return (pPropNames && pPropValues);
1027}
1028
1029void VDataSeries::setMissingValueTreatment( sal_Int32 nMissingValueTreatment )
1030{
1031 m_nMissingValueTreatment = nMissingValueTreatment;
1032}
1033
1035{
1037}
1038
1040 : m_nPolygonIndex(0)
1041 , m_fLogicMinX(0)
1042 , m_fLogicMaxX(0)
1043 , m_fLogicZPos(0)
1044 , m_nPointCount(0)
1045 , m_pValueSequenceForDataLabelNumberFormatDetection(nullptr)
1046 , m_fXMeanValue(0)
1047 , m_fYMeanValue(0)
1048 , m_eStackingDirection(chart2::StackingDirection_NO_STACKING)
1049 , m_nAxisIndex(0)
1050 , m_bConnectBars(false)
1051 , m_bGroupBarsPerAxis(false)
1052 , m_nStartingAngle(0)
1053 , m_nGlobalSeriesIndex(0)
1054 , m_nCurrentAttributedPoint(0)
1055 , m_nMissingValueTreatment(0)
1056 , m_bAllowPercentValueInDataLabel(false)
1057 , mpOldSeries(nullptr)
1058 , mnPercent(0)
1059{
1060}
1061
1062void VDataSeries::setOldTimeBased( VDataSeries* pOldSeries, double nPercent )
1063{
1064 mnPercent = nPercent;
1065 mpOldSeries = pOldSeries;
1066 mpOldSeries->mpOldSeries = nullptr;
1067}
1068
1070{
1071 VDataSeries* pNew = new VDataSeries();
1072 pNew->m_aValues_X = m_aValues_X;
1073 pNew->m_aValues_Y = m_aValues_Y;
1074 pNew->m_aValues_Z = m_aValues_Z;
1081
1083
1084 return pNew;
1085}
1086
1087double VDataSeries::getValueByProperty( sal_Int32 nIndex, const OUString& rPropName ) const
1088{
1089 auto const itr = m_PropertyMap.find(rPropName);
1090 if (itr == m_PropertyMap.end())
1091 return std::numeric_limits<double>::quiet_NaN();
1092
1093 const VDataSequence* pData = &itr->second;
1094 double fValue = pData->getValue(nIndex);
1095 if(mpOldSeries && mpOldSeries->hasPropertyMapping(rPropName))
1096 {
1097 double fOldValue = mpOldSeries->getValueByProperty( nIndex, rPropName );
1098 if(rPropName.endsWith("Color"))
1099 {
1100 //optimized interpolation for color values
1101 Color aColor(ColorTransparency, static_cast<sal_uInt32>(fValue));
1102 Color aOldColor(ColorTransparency, static_cast<sal_uInt32>(fOldValue));
1103 sal_uInt8 r = aOldColor.GetRed() + (aColor.GetRed() - aOldColor.GetRed()) * mnPercent;
1104 sal_uInt8 g = aOldColor.GetGreen() + (aColor.GetGreen() - aOldColor.GetGreen()) * mnPercent;
1105 sal_uInt8 b = aOldColor.GetBlue() + (aColor.GetBlue() - aOldColor.GetBlue()) * mnPercent;
1106 sal_uInt8 a = aOldColor.GetAlpha() + (aColor.GetAlpha() - aOldColor.GetAlpha()) * mnPercent;
1107 Color aRet(ColorAlpha, a, r, g, b);
1108 return sal_uInt32(aRet);
1109 }
1110 return fOldValue + (fValue - fOldValue) * mnPercent;
1111 }
1112 return fValue;
1113}
1114
1115bool VDataSeries::hasPropertyMapping(const OUString& rPropName ) const
1116{
1117 return m_PropertyMap.find(rPropName) != m_PropertyMap.end();
1118}
1119
1120} //namespace chart
1121
1122/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_uInt8 GetBlue() const
sal_uInt8 GetAlpha() const
sal_uInt8 GetRed() const
sal_uInt8 GetGreen() const
static css::uno::Sequence< sal_Int32 > getSupportedLabelPlacements(const rtl::Reference< ::chart::ChartType > &xChartType, bool bSwapXAndY, const rtl::Reference< ::chart::DataSeries > &xSeries)
static void doDynamicFontResize(tAnySequence &rPropValues, const tNameSequence &rPropNames, const css::uno::Reference< css::beans::XPropertySet > &xAxisModelProps, const css::awt::Size &rNewReferenceSize)
static OUString createClassifiedIdentifierForParticle(std::u16string_view rParticle)
static OUString createDataCurveEquationCID(std::u16string_view rSeriesParticle, sal_Int32 nCurveIndex)
static OUString getStringForType(ObjectType eObjectType)
static OUString createDataCurveCID(std::u16string_view rSeriesParticle, sal_Int32 nCurveIndex, bool bAverageLine)
static OUString createClassifiedIdentifierForParticles(std::u16string_view rParentParticle, std::u16string_view rChildParticle, std::u16string_view rDragMethodServiceName=std::u16string_view(), std::u16string_view rDragParameterString=std::u16string_view())
static OUString createSeriesSubObjectStub(ObjectType eSubObjectType, std::u16string_view rSeriesParticle, std::u16string_view rDragMethodServiceName=std::u16string_view(), std::u16string_view rDragParameterString=std::u16string_view())
static OUString createClassifiedIdentifierWithParent(enum ObjectType, std::u16string_view rParticleID, std::u16string_view rParentPartical, std::u16string_view rDragMethodServiceName=std::u16string_view(), std::u16string_view rDragParameterString=std::u16string_view())
static void getTextLabelMultiPropertyLists(const css::uno::Reference< css::beans::XPropertySet > &xSourceProp, tNameSequence &rPropNames, tAnySequence &rPropValues, bool bName=true, sal_Int32 nLimitedSpace=-1, bool bLimitedHeight=false, bool bSupportsLabelBorder=true)
css::uno::Reference< css::chart2::data::XDataSequence > m_xModel
Definition: VDataSeries.hxx:56
sal_Int32 getLength() const
Definition: VDataSeries.cxx:89
void init(const css::uno::Reference< css::chart2::data::XDataSequence > &xModel)
Definition: VDataSeries.cxx:53
double getValue(sal_Int32 index) const
Definition: VDataSeries.cxx:69
css::uno::Sequence< double > m_aValues
Definition: VDataSeries.hxx:57
sal_Int32 detectNumberFormatKey(sal_Int32 index) const
Definition: VDataSeries.cxx:76
rtl::Reference< SvxShapeGroupAnyD > m_xGroupShape
bool hasExplicitNumberFormat(sal_Int32 nPointIndex, bool bForPercentage) const
css::awt::Point getLabelPosition(css::awt::Point aTextShapePos, sal_Int32 nPointIndex) const
sal_Int32 getExplicitNumberFormat(sal_Int32 nPointIndex, bool bForPercentage) const
css::chart2::StackingDirection getStackingDirection() const
OUString getDataCurveCID(sal_Int32 nCurveIndex, bool bAverageLine) const
void setOldTimeBased(VDataSeries *pOldSeries, double nPercent)
sal_Int32 getAttachedAxisIndex() const
void getMinMaxXValue(double &fMin, double &fMax) const
double getYMeanValue() const
rtl::Reference< SvxShapeGroupAnyD > m_xErrorYBarsGroupShape
OUString m_aSeriesParticle
void adaptPointCache(sal_Int32 nNewPointIndex) const
bool getGroupBarsPerAxis() const
std::vector< std::vector< css::drawing::Position3D > > m_aPolyPolygonShape3D
bool isVaryColorsByPoint() const
VDataSequence m_aValues_X
css::chart2::Symbol * getSymbolProperties(sal_Int32 index) const
const css::uno::Reference< css::beans::XPropertySet > & getPropertiesOfSeries() const
css::uno::Sequence< double > const & getAllX() const
css::uno::Reference< css::beans::XPropertySet > getPropertiesOfPoint(sal_Int32 index) const
double getYValue(sal_Int32 index) const
css::chart2::StackingDirection m_eStackingDirection
rtl::Reference< SvxShapeGroup > m_xLabelsGroupShape
double getValueByProperty(sal_Int32 index, const OUString &rPropName) const
std::optional< tNameSequence > m_oLabelPropNames_Series
rtl::Reference< SvxShapeGroupAnyD > m_xErrorXBarsGroupShape
std::optional< css::chart2::Symbol > m_oSymbolProperties_Series
sal_Int32 m_nStartingAngle
void setXValuesIfNone(const css::uno::Reference< css::chart2::data::XDataSequence > &xValues)
VDataSequence m_aValues_Bubble_Size
css::chart2::DataPointLabel * getDataPointLabelIfLabel(sal_Int32 index) const
sal_Int32 getStartingAngle() const
void setXValues(const css::uno::Reference< css::chart2::data::XDataSequence > &xValues)
double getY_First(sal_Int32 index) const
css::uno::Reference< css::beans::XPropertySet > m_xDataSeriesProps
css::uno::Reference< css::beans::XPropertySet > getXErrorBarProperties(sal_Int32 index) const
sal_Int32 m_nPolygonIndex
std::unique_ptr< tAnySequence > m_apLabelPropValues_AttributedPoint
std::optional< css::chart2::DataPointLabel > m_oLabel_AttributedPoint
const rtl::Reference<::chart::DataSeries > & getModel() const
css::uno::Sequence< sal_Int32 > m_aAttributedDataPointIndexList
double getY_Max(sal_Int32 index) const
rtl::Reference< SvxShapeGroupAnyD > m_xBackSubGroupShape
VDataSequence m_aValues_Y_Max
VDataSeries * createCopyForTimeBased() const
double getMinimumofAllDifferentYValues(sal_Int32 index) const
css::chart2::DataPointLabel * getDataPointLabel(sal_Int32 index) const
std::map< OUString, VDataSequence > m_PropertyMap
OUString getErrorBarsCID(bool bYError) const
VDataSequence m_aValues_Y_Min
std::optional< css::chart2::Symbol > m_oSymbolProperties_InvisibleSymbolForSelection
VDataSeries * mpOldSeries
bool isAttributedDataPoint(sal_Int32 index) const
VDataSequence m_aValues_Y_First
std::optional< css::chart2::DataPointLabel > m_oLabel_Series
void setConnectBars(bool bConnectBars)
OUString m_aPointCID_Stub
sal_Int32 m_nAxisIndex
VDataSequence m_aValues_Y_Last
sal_Int32 m_nGlobalSeriesIndex
sal_Int32 detectNumberFormatKey(sal_Int32 nPointIndex) const
bool hasPropertyMapping(const OUString &rPropName) const
sal_Int32 getLabelPlacement(sal_Int32 nPointIndex, const rtl::Reference<::chart::ChartType > &xChartType, bool bSwapXAndY) const
double getMaximumofAllDifferentYValues(sal_Int32 index) const
VDataSequence m_aValues_Y
std::optional< css::chart2::Symbol > m_oSymbolProperties_AttributedPoint
VDataSequence * m_pValueSequenceForDataLabelNumberFormatDetection
double getBubble_Size(sal_Int32 index) const
bool getConnectBars() const
void setGroupBarsPerAxis(bool bGroupBarsPerAxis)
double getXValue(sal_Int32 index) const
void setAttachedAxisIndex(sal_Int32 nAttachedAxisIndex)
void setGlobalSeriesIndex(sal_Int32 nGlobalSeriesIndex)
bool hasPointOwnColor(sal_Int32 index) const
double getXMeanValue() const
double getY_Last(sal_Int32 index) const
void setMissingValueTreatment(sal_Int32 nMissingValueTreatment)
double getY_Min(sal_Int32 index) const
sal_Int32 m_nMissingValueTreatment
OUString getDataCurveEquationCID(sal_Int32 nCurveIndex) const
css::awt::Size m_aReferenceSize
css::uno::Sequence< double > const & getAllY() const
OUString m_aLabelCID_Stub
std::optional< tAnySequence > m_oLabelPropValues_Series
css::uno::Reference< css::beans::XPropertySet > getYErrorBarProperties(sal_Int32 index) const
bool getTextLabelMultiPropertyLists(sal_Int32 index, tNameSequence *&pPropNames, tAnySequence *&pPropValues) const
void setStartingAngle(sal_Int32 nStartingAngle)
bool isLabelCustomPos(sal_Int32 nPointIndex) const
rtl::Reference<::chart::DataSeries > m_xDataSeries
void setParticle(const OUString &rSeriesParticle)
rtl::Reference< SvxShapeGroupAnyD > m_xFrontSubGroupShape
VDataSequence m_aValues_Z
OUString getLabelsCID() const
sal_Int32 m_nPointCount
std::unique_ptr< tNameSequence > m_apLabelPropNames_AttributedPoint
void setRoleOfSequenceForDataLabelNumberFormatDetection(std::u16string_view rRole)
bool m_bAllowPercentValueInDataLabel
void setPageReferenceSize(const css::awt::Size &rPageRefSize)
sal_Int32 getMissingValueTreatment() const
sal_Int32 m_nCurrentAttributedPoint
ColorAlpha
ColorTransparency
int nCount
#define TOOLS_WARN_EXCEPTION(area, stream)
float u
sal_Int32 nIndex
sal_Int64 n
uno_Any a
std::unique_ptr< sal_Int32[]> pData
OOO_DLLPUBLIC_CHARTTOOLS rtl::Reference<::chart::RegressionCurveCalculator > createRegressionCurveCalculatorByServiceName(std::u16string_view aServiceName)
returns a calculator object for regression curves (used by the view)
@ OBJECTTYPE_DATA_LABELS
@ OBJECTTYPE_DATA_ERRORS_X
@ OBJECTTYPE_DATA_POINT
@ OBJECTTYPE_DATA_ERRORS_Y
@ OBJECTTYPE_DATA_LABEL
css::uno::Sequence< OUString > tNameSequence
css::uno::Sequence< css::uno::Any > tAnySequence
OOO_DLLPUBLIC_CHARTTOOLS css::uno::Sequence< double > DataSequenceToDoubleSequence(const css::uno::Reference< css::chart2::data::XDataSequence > &xDataSequence)
chart2::XDataSequence -> uno::Sequence< double >
static std::optional< Symbol > getSymbolPropertiesFromPropertySet(const uno::Reference< beans::XPropertySet > &xProp)
OOO_DLLPUBLIC_CHARTTOOLS css::uno::Sequence< OUString > DataSequenceToStringSequence(const css::uno::Reference< css::chart2::data::XDataSequence > &xDataSequence)
static std::optional< DataPointLabel > getDataPointLabelFromPropertySet(const uno::Reference< beans::XPropertySet > &xProp)
int i
constexpr OUStringLiteral first
index
OUString aPropName
Reference< XModel > xModel
unsigned char sal_uInt8
constexpr OUStringLiteral CHART_UNONAME_ERRORBAR_Y
Definition: unonames.hxx:23
constexpr OUStringLiteral CHART_UNONAME_LINK_TO_SRC_NUMFMT
Definition: unonames.hxx:21
constexpr OUStringLiteral CHART_UNONAME_NUMFMT
Definition: unonames.hxx:20
constexpr OUStringLiteral CHART_UNONAME_ERRORBAR_X
Definition: unonames.hxx:22
constexpr OUStringLiteral CHART_UNONAME_LABEL
Definition: unonames.hxx:24