Line data Source code
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 "VDataSeries.hxx"
21 : #include "ObjectIdentifier.hxx"
22 : #include "macros.hxx"
23 : #include "CommonConverters.hxx"
24 : #include "LabelPositionHelper.hxx"
25 : #include "ChartTypeHelper.hxx"
26 : #include "ContainerHelper.hxx"
27 : #include "DataSeriesHelper.hxx"
28 : #include "RegressionCurveHelper.hxx"
29 : #include <unonames.hxx>
30 :
31 : #include <com/sun/star/chart/MissingValueTreatment.hpp>
32 : #include <com/sun/star/chart2/Symbol.hpp>
33 :
34 : #include <rtl/math.hxx>
35 : #include <com/sun/star/beans/XPropertySet.hpp>
36 : #include <com/sun/star/beans/XPropertyState.hpp>
37 : #include <com/sun/star/drawing/LineStyle.hpp>
38 : #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
39 : #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
40 : #include <com/sun/star/text/WritingMode.hpp>
41 : #include <com/sun/star/chart2/data/XDataSource.hpp>
42 :
43 : namespace chart {
44 :
45 : using namespace ::com::sun::star;
46 : using namespace ::com::sun::star::chart2;
47 : using ::com::sun::star::uno::Reference;
48 :
49 3253 : void VDataSequence::init( const uno::Reference< data::XDataSequence >& xModel )
50 : {
51 3253 : Model = xModel;
52 3253 : Doubles = DataSequenceToDoubleSequence( xModel );
53 3253 : }
54 :
55 135815 : bool VDataSequence::is() const
56 : {
57 135815 : return Model.is();
58 : }
59 3038 : void VDataSequence::clear()
60 : {
61 3038 : Model = NULL;
62 3038 : Doubles.realloc(0);
63 3038 : }
64 :
65 618 : double VDataSequence::getValue( sal_Int32 index ) const
66 : {
67 618 : if( 0<=index && index<Doubles.getLength() )
68 486 : return Doubles[index];
69 : else
70 : {
71 : double fNan;
72 132 : ::rtl::math::setNan( & fNan );
73 132 : return fNan;
74 : }
75 : }
76 :
77 1104 : sal_Int32 VDataSequence::detectNumberFormatKey( sal_Int32 index ) const
78 : {
79 1104 : sal_Int32 nNumberFormatKey = -1;
80 :
81 : // -1 is allowed and means a key for the whole sequence
82 2208 : if( -1<=index && index<Doubles.getLength() &&
83 1104 : Model.is())
84 : {
85 1104 : nNumberFormatKey = Model->getNumberFormatKeyByIndex( index );
86 : }
87 :
88 1104 : return nNumberFormatKey;
89 : }
90 :
91 63056 : sal_Int32 VDataSequence::getLength() const
92 : {
93 63056 : return Doubles.getLength();
94 : }
95 :
96 : namespace
97 : {
98 : struct lcl_LessXOfPoint
99 : {
100 0 : inline bool operator() ( const std::vector< double >& first,
101 : const std::vector< double >& second )
102 : {
103 0 : if( !first.empty() && !second.empty() )
104 : {
105 0 : return first[0]<second[0];
106 : }
107 0 : return false;
108 : }
109 : };
110 :
111 121 : void lcl_clearIfNoValuesButTextIsContained( VDataSequence& rData, const uno::Reference<data::XDataSequence>& xDataSequence )
112 : {
113 : //#i71686#, #i101968#, #i102428#
114 121 : sal_Int32 nCount = rData.Doubles.getLength();
115 297 : for( sal_Int32 i = 0; i < nCount; ++i )
116 : {
117 227 : if( !::rtl::math::isNan( rData.Doubles[i] ) )
118 147 : return;
119 : }
120 : //no double value is countained
121 : //is there any text?
122 70 : uno::Sequence< OUString > aStrings( DataSequenceToStringSequence( xDataSequence ) );
123 70 : sal_Int32 nTextCount = aStrings.getLength();
124 70 : for( sal_Int32 j = 0; j < nTextCount; ++j )
125 : {
126 45 : if( !aStrings[j].isEmpty() )
127 : {
128 45 : rData.clear();
129 45 : return;
130 : }
131 25 : }
132 : //no content at all
133 : }
134 :
135 110335 : void lcl_maybeReplaceNanWithZero( double& rfValue, sal_Int32 nMissingValueTreatment )
136 : {
137 110335 : if( nMissingValueTreatment == ::com::sun::star::chart::MissingValueTreatment::USE_ZERO
138 110335 : && (::rtl::math::isNan(rfValue) || ::rtl::math::isInf(rfValue)) )
139 12 : rfValue = 0.0;
140 110335 : }
141 :
142 : }
143 :
144 3098 : VDataSeries::VDataSeries( const uno::Reference< XDataSeries >& xDataSeries )
145 : : m_nPolygonIndex(0)
146 : , m_fLogicMinX(0.0)
147 : , m_fLogicMaxX(0.0)
148 : , m_fLogicZPos(0.0)
149 : , m_xGroupShape(NULL)
150 : , m_xLabelsGroupShape(NULL)
151 : , m_xErrorXBarsGroupShape(NULL)
152 : , m_xErrorYBarsGroupShape(NULL)
153 : , m_xFrontSubGroupShape(NULL)
154 : , m_xBackSubGroupShape(NULL)
155 : , m_xDataSeries(xDataSeries)
156 : , m_nPointCount(0)
157 :
158 : , m_pValueSequenceForDataLabelNumberFormatDetection(&m_aValues_Y)
159 :
160 : , m_fXMeanValue(1.0)
161 : , m_fYMeanValue(1.0)
162 :
163 : , m_aAttributedDataPointIndexList()
164 :
165 : , m_eStackingDirection(StackingDirection_NO_STACKING)
166 : , m_nAxisIndex(0)
167 : , m_bConnectBars(false)
168 : , m_bGroupBarsPerAxis(true)
169 : , m_nStartingAngle(90)
170 :
171 : , m_nGlobalSeriesIndex(0)
172 :
173 : , m_apLabel_Series(NULL)
174 : , m_apLabelPropNames_Series(NULL)
175 : , m_apLabelPropValues_Series(NULL)
176 : , m_apSymbolProperties_Series(NULL)
177 :
178 : , m_apLabel_AttributedPoint(NULL)
179 : , m_apLabelPropNames_AttributedPoint(NULL)
180 : , m_apLabelPropValues_AttributedPoint(NULL)
181 : , m_apSymbolProperties_AttributedPoint(NULL)
182 : , m_apSymbolProperties_InvisibleSymbolForSelection(NULL)
183 : , m_nCurrentAttributedPoint(-1)
184 : , m_nMissingValueTreatment(::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP)
185 : , m_bAllowPercentValueInDataLabel(false)
186 : , mpOldSeries(NULL)
187 3098 : , mnPercent(0.0)
188 : {
189 3098 : ::rtl::math::setNan( & m_fXMeanValue );
190 3098 : ::rtl::math::setNan( & m_fYMeanValue );
191 :
192 : uno::Reference<data::XDataSource> xDataSource =
193 3098 : uno::Reference<data::XDataSource>( xDataSeries, uno::UNO_QUERY );
194 :
195 : uno::Sequence< uno::Reference<
196 : chart2::data::XLabeledDataSequence > > aDataSequences =
197 6196 : xDataSource->getDataSequences();
198 :
199 9395 : for(sal_Int32 nN = aDataSequences.getLength();nN--;)
200 : {
201 3199 : if(!aDataSequences[nN].is())
202 0 : continue;
203 3199 : uno::Reference<data::XDataSequence> xDataSequence( aDataSequences[nN]->getValues());
204 6398 : uno::Reference<beans::XPropertySet> xProp(xDataSequence, uno::UNO_QUERY );
205 3199 : if( xProp.is())
206 : {
207 : try
208 : {
209 3199 : uno::Any aARole = xProp->getPropertyValue("Role");
210 6398 : OUString aRole;
211 3199 : aARole >>= aRole;
212 :
213 3199 : if (aRole == "values-x")
214 : {
215 67 : m_aValues_X.init( xDataSequence );
216 67 : lcl_clearIfNoValuesButTextIsContained( m_aValues_X, xDataSequence );
217 : }
218 3132 : else if (aRole =="values-y")
219 3084 : m_aValues_Y.init( xDataSequence );
220 48 : else if (aRole == "values-min")
221 14 : m_aValues_Y_Min.init( xDataSequence );
222 34 : else if (aRole == "values-max")
223 12 : m_aValues_Y_Max.init( xDataSequence );
224 22 : else if (aRole == "values-first")
225 4 : m_aValues_Y_First.init( xDataSequence );
226 18 : else if (aRole == "values-last")
227 12 : m_aValues_Y_Last.init( xDataSequence );
228 6 : else if (aRole == "values-size")
229 6 : m_aValues_Bubble_Size.init( xDataSequence );
230 : else
231 : {
232 0 : VDataSequence* pSequence = new VDataSequence();
233 0 : pSequence->init( xDataSequence );
234 0 : maPropertyMap.insert(aRole, pSequence);
235 3199 : }
236 : }
237 0 : catch( const uno::Exception& e )
238 : {
239 : ASSERT_EXCEPTION( e );
240 : }
241 : }
242 3199 : }
243 :
244 : //determine the point count
245 3098 : m_nPointCount = m_aValues_Y.getLength();
246 : {
247 3098 : if( m_nPointCount < m_aValues_Bubble_Size.getLength() )
248 0 : m_nPointCount = m_aValues_Bubble_Size.getLength();
249 3098 : if( m_nPointCount < m_aValues_Y_Min.getLength() )
250 14 : m_nPointCount = m_aValues_Y_Min.getLength();
251 3098 : if( m_nPointCount < m_aValues_Y_Max.getLength() )
252 0 : m_nPointCount = m_aValues_Y_Max.getLength();
253 3098 : if( m_nPointCount < m_aValues_Y_First.getLength() )
254 0 : m_nPointCount = m_aValues_Y_First.getLength();
255 3098 : if( m_nPointCount < m_aValues_Y_Last.getLength() )
256 0 : m_nPointCount = m_aValues_Y_Last.getLength();
257 : }
258 :
259 6196 : uno::Reference<beans::XPropertySet> xProp(xDataSeries, uno::UNO_QUERY );
260 3098 : if( xProp.is())
261 : {
262 : try
263 : {
264 : //get AttributedDataPoints
265 3098 : xProp->getPropertyValue("AttributedDataPoints") >>= m_aAttributedDataPointIndexList;
266 :
267 3098 : xProp->getPropertyValue("StackingDirection") >>= m_eStackingDirection;
268 :
269 3098 : xProp->getPropertyValue("AttachedAxisIndex") >>= m_nAxisIndex;
270 3098 : if(m_nAxisIndex<0)
271 0 : m_nAxisIndex=0;
272 : }
273 0 : catch( const uno::Exception& e )
274 : {
275 : ASSERT_EXCEPTION( e );
276 : }
277 3098 : }
278 3098 : }
279 :
280 3098 : VDataSeries::~VDataSeries()
281 : {
282 3098 : }
283 :
284 0 : void VDataSeries::doSortByXValues()
285 : {
286 0 : if( m_aValues_X.is() && m_aValues_X.Doubles.getLength() )
287 : {
288 : //prepare a vector for sorting
289 0 : std::vector< ::std::vector< double > > aTmp;//outer vector are points, inner vector are the different values of athe point
290 : double fNan;
291 0 : ::rtl::math::setNan( & fNan );
292 0 : sal_Int32 nPointIndex = 0;
293 0 : for( nPointIndex=0; nPointIndex < m_nPointCount; nPointIndex++ )
294 : {
295 0 : std::vector< double > aSinglePoint;
296 0 : aSinglePoint.push_back( (nPointIndex < m_aValues_X.Doubles.getLength()) ? m_aValues_X.Doubles[nPointIndex] : fNan );
297 0 : aSinglePoint.push_back( (nPointIndex < m_aValues_Y.Doubles.getLength()) ? m_aValues_Y.Doubles[nPointIndex] : fNan );
298 0 : aTmp.push_back( aSinglePoint );
299 0 : }
300 :
301 : //do sort
302 0 : std::stable_sort( aTmp.begin(), aTmp.end(), lcl_LessXOfPoint() );
303 :
304 : //fill the sorted points back to the members
305 0 : m_aValues_X.Doubles.realloc( m_nPointCount );
306 0 : m_aValues_Y.Doubles.realloc( m_nPointCount );
307 :
308 0 : for( nPointIndex=0; nPointIndex < m_nPointCount; nPointIndex++ )
309 : {
310 0 : m_aValues_X.Doubles[nPointIndex]=aTmp[nPointIndex][0];
311 0 : m_aValues_Y.Doubles[nPointIndex]=aTmp[nPointIndex][1];
312 0 : }
313 : }
314 0 : }
315 :
316 66 : void VDataSeries::releaseShapes()
317 : {
318 66 : m_xGroupShape.set(0);
319 66 : m_xLabelsGroupShape.set(0);
320 66 : m_xErrorXBarsGroupShape.set(0);
321 66 : m_xErrorYBarsGroupShape.set(0);
322 66 : m_xFrontSubGroupShape.set(0);
323 66 : m_xBackSubGroupShape.set(0);
324 :
325 66 : m_aPolyPolygonShape3D.SequenceX.realloc(0);
326 66 : m_aPolyPolygonShape3D.SequenceY.realloc(0);
327 66 : m_aPolyPolygonShape3D.SequenceZ.realloc(0);
328 66 : m_nPolygonIndex = 0;
329 66 : }
330 :
331 10414 : uno::Reference<css::chart2::XDataSeries> VDataSeries::getModel() const
332 : {
333 10414 : return m_xDataSeries;
334 : }
335 :
336 2993 : void VDataSeries::setCategoryXAxis()
337 : {
338 2993 : m_aValues_X.clear();
339 2993 : m_bAllowPercentValueInDataLabel = true;
340 2993 : }
341 :
342 0 : void VDataSeries::setXValues( const Reference< chart2::data::XDataSequence >& xValues )
343 : {
344 0 : m_aValues_X.clear();
345 0 : m_aValues_X.init( xValues );
346 0 : m_bAllowPercentValueInDataLabel = true;
347 0 : }
348 :
349 105 : void VDataSeries::setXValuesIfNone( const Reference< chart2::data::XDataSequence >& xValues )
350 : {
351 105 : if( m_aValues_X.is() )
352 156 : return;
353 :
354 54 : m_aValues_X.init( xValues );
355 54 : lcl_clearIfNoValuesButTextIsContained( m_aValues_X, xValues );
356 : }
357 :
358 3098 : void VDataSeries::setGlobalSeriesIndex( sal_Int32 nGlobalSeriesIndex )
359 : {
360 3098 : m_nGlobalSeriesIndex = nGlobalSeriesIndex;
361 3098 : }
362 :
363 3098 : void VDataSeries::setParticle( const OUString& rSeriesParticle )
364 : {
365 3098 : m_aSeriesParticle = rSeriesParticle;
366 :
367 : //get CID
368 3098 : m_aCID = ObjectIdentifier::createClassifiedIdentifierForParticle( m_aSeriesParticle );
369 3098 : m_aPointCID_Stub = ObjectIdentifier::createSeriesSubObjectStub( OBJECTTYPE_DATA_POINT, m_aSeriesParticle );
370 :
371 6196 : m_aLabelCID_Stub = ObjectIdentifier::createClassifiedIdentifierWithParent(
372 3098 : OBJECTTYPE_DATA_LABEL, OUString(), getLabelsCID() );
373 3098 : }
374 880 : OUString VDataSeries::getErrorBarsCID(bool bYError) const
375 : {
376 : OUString aChildParticle( ObjectIdentifier::getStringForType(
377 880 : bYError ? OBJECTTYPE_DATA_ERRORS_Y : OBJECTTYPE_DATA_ERRORS_X ) );
378 880 : aChildParticle += "=";
379 :
380 : return ObjectIdentifier::createClassifiedIdentifierForParticles(
381 880 : m_aSeriesParticle, aChildParticle );
382 : }
383 3473 : OUString VDataSeries::getLabelsCID() const
384 : {
385 3473 : OUString aChildParticle( ObjectIdentifier::getStringForType( OBJECTTYPE_DATA_LABELS ) );
386 3473 : aChildParticle += "=";
387 :
388 : return ObjectIdentifier::createClassifiedIdentifierForParticles(
389 3473 : m_aSeriesParticle, aChildParticle );
390 : }
391 54 : OUString VDataSeries::getDataCurveCID( sal_Int32 nCurveIndex, bool bAverageLine ) const
392 : {
393 54 : OUString aRet;
394 54 : aRet = ObjectIdentifier::createDataCurveCID( m_aSeriesParticle, nCurveIndex, bAverageLine );
395 54 : return aRet;
396 : }
397 :
398 60 : OUString VDataSeries::getDataCurveEquationCID( sal_Int32 nCurveIndex ) const
399 : {
400 60 : OUString aRet;
401 60 : aRet = ObjectIdentifier::createDataCurveEquationCID( m_aSeriesParticle, nCurveIndex );
402 60 : return aRet;
403 : }
404 3098 : void VDataSeries::setPageReferenceSize( const awt::Size & rPageRefSize )
405 : {
406 3098 : m_aReferenceSize = rPageRefSize;
407 3098 : }
408 :
409 3098 : void VDataSeries::setConnectBars( bool bConnectBars )
410 : {
411 3098 : m_bConnectBars = bConnectBars;
412 3098 : }
413 :
414 883 : bool VDataSeries::getConnectBars() const
415 : {
416 883 : return m_bConnectBars;
417 : }
418 :
419 3098 : void VDataSeries::setGroupBarsPerAxis( bool bGroupBarsPerAxis )
420 : {
421 3098 : m_bGroupBarsPerAxis = bGroupBarsPerAxis;
422 3098 : }
423 :
424 3436 : bool VDataSeries::getGroupBarsPerAxis() const
425 : {
426 3436 : return m_bGroupBarsPerAxis;
427 : }
428 :
429 3098 : void VDataSeries::setStartingAngle( sal_Int32 nStartingAngle )
430 : {
431 3098 : m_nStartingAngle = nStartingAngle;
432 3098 : }
433 :
434 74 : sal_Int32 VDataSeries::getStartingAngle() const
435 : {
436 74 : return m_nStartingAngle;
437 : }
438 :
439 5619 : chart2::StackingDirection VDataSeries::getStackingDirection() const
440 : {
441 5619 : return m_eStackingDirection;
442 : }
443 :
444 45567 : sal_Int32 VDataSeries::getAttachedAxisIndex() const
445 : {
446 45567 : return m_nAxisIndex;
447 : }
448 :
449 0 : void VDataSeries::setAttachedAxisIndex( sal_Int32 nAttachedAxisIndex )
450 : {
451 0 : if( nAttachedAxisIndex < 0 )
452 0 : nAttachedAxisIndex = 0;
453 0 : m_nAxisIndex = nAttachedAxisIndex;
454 0 : }
455 :
456 68121 : double VDataSeries::getXValue( sal_Int32 index ) const
457 : {
458 68121 : double fRet = 0.0;
459 68121 : if(m_aValues_X.is())
460 : {
461 2166 : if( 0<=index && index<m_aValues_X.getLength() )
462 : {
463 2166 : fRet = m_aValues_X.Doubles[index];
464 2166 : if(mpOldSeries && index < mpOldSeries->m_aValues_X.getLength())
465 : {
466 0 : double nOldVal = mpOldSeries->m_aValues_X.Doubles[index];
467 0 : fRet = nOldVal + (fRet - nOldVal) * mnPercent;
468 : }
469 : }
470 : else
471 0 : ::rtl::math::setNan( &fRet );
472 : }
473 : else
474 : {
475 : // #i70133# always return correct X position - needed for short data series
476 65955 : if( 0<=index /*&& index < m_nPointCount*/ )
477 65955 : fRet = index+1;//first category (index 0) matches with real number 1.0
478 : else
479 0 : ::rtl::math::setNan( &fRet );
480 : }
481 68121 : lcl_maybeReplaceNanWithZero( fRet, getMissingValueTreatment() );
482 68121 : return fRet;
483 : }
484 :
485 42214 : double VDataSeries::getYValue( sal_Int32 index ) const
486 : {
487 42214 : double fRet = 0.0;
488 42214 : if(m_aValues_Y.is())
489 : {
490 42214 : if( 0<=index && index<m_aValues_Y.getLength() )
491 : {
492 42214 : fRet = m_aValues_Y.Doubles[index];
493 42214 : if(mpOldSeries && index < mpOldSeries->m_aValues_Y.getLength())
494 : {
495 0 : double nOldVal = mpOldSeries->m_aValues_Y.Doubles[index];
496 0 : fRet = nOldVal + (fRet - nOldVal) * mnPercent;
497 : }
498 : }
499 : else
500 0 : ::rtl::math::setNan( &fRet );
501 : }
502 : else
503 : {
504 : // #i70133# always return correct X position - needed for short data series
505 0 : if( 0<=index /*&& index < m_nPointCount*/ )
506 0 : fRet = index+1;//first category (index 0) matches with real number 1.0
507 : else
508 0 : ::rtl::math::setNan( &fRet );
509 : }
510 42214 : lcl_maybeReplaceNanWithZero( fRet, getMissingValueTreatment() );
511 42214 : return fRet;
512 : }
513 :
514 23 : void VDataSeries::getMinMaxXValue(double& fMin, double& fMax) const
515 : {
516 23 : rtl::math::setNan( &fMax );
517 23 : rtl::math::setNan( &fMin );
518 :
519 23 : uno::Sequence< double > aValuesX = getAllX();
520 :
521 23 : if(aValuesX.getLength() > 0)
522 : {
523 23 : fMax = fMin = aValuesX[0];
524 :
525 155 : for (sal_Int32 i = 1; i < aValuesX.getLength(); i++)
526 : {
527 132 : const double aValue = aValuesX[i];
528 132 : if ( aValue > fMax)
529 : {
530 132 : fMax = aValue;
531 : }
532 0 : else if ( aValue < fMin)
533 : {
534 0 : fMin = aValue;
535 : }
536 : }
537 23 : }
538 23 : }
539 150 : double VDataSeries::getY_Min( sal_Int32 index ) const
540 : {
541 150 : return m_aValues_Y_Min.getValue( index );
542 : }
543 150 : double VDataSeries::getY_Max( sal_Int32 index ) const
544 : {
545 150 : return m_aValues_Y_Max.getValue( index );
546 : }
547 150 : double VDataSeries::getY_First( sal_Int32 index ) const
548 : {
549 150 : return m_aValues_Y_First.getValue( index );
550 : }
551 150 : double VDataSeries::getY_Last( sal_Int32 index ) const
552 : {
553 150 : return m_aValues_Y_Last.getValue( index );
554 : }
555 18 : double VDataSeries::getBubble_Size( sal_Int32 index ) const
556 : {
557 18 : double nNewVal = m_aValues_Bubble_Size.getValue( index );
558 18 : if(mpOldSeries && index < mpOldSeries->m_aValues_Bubble_Size.getLength())
559 : {
560 0 : double nOldVal = mpOldSeries->m_aValues_Bubble_Size.getValue( index );
561 0 : nNewVal = nOldVal + (nNewVal - nOldVal) * mnPercent;
562 : }
563 :
564 18 : return nNewVal;
565 : }
566 :
567 1700 : bool VDataSeries::hasExplicitNumberFormat( sal_Int32 nPointIndex, bool bForPercentage ) const
568 : {
569 1700 : OUString aPropName = bForPercentage ? OUString("PercentageNumberFormat") : OUString(CHART_UNONAME_NUMFMT);
570 1700 : bool bHasNumberFormat = false;
571 3400 : uno::Reference< beans::XPropertySet > xPointProp( this->getPropertiesOfPoint( nPointIndex ));
572 1700 : sal_Int32 nNumberFormat = -1;
573 1700 : if( xPointProp.is() && (xPointProp->getPropertyValue(aPropName) >>= nNumberFormat) )
574 297 : bHasNumberFormat = true;
575 3400 : return bHasNumberFormat;
576 : }
577 297 : sal_Int32 VDataSeries::getExplicitNumberFormat( sal_Int32 nPointIndex, bool bForPercentage ) const
578 : {
579 297 : OUString aPropName = bForPercentage ? OUString("PercentageNumberFormat") : OUString(CHART_UNONAME_NUMFMT);
580 297 : sal_Int32 nNumberFormat = -1;
581 594 : uno::Reference< beans::XPropertySet > xPointProp( this->getPropertiesOfPoint( nPointIndex ));
582 297 : if( xPointProp.is() )
583 297 : xPointProp->getPropertyValue(aPropName) >>= nNumberFormat;
584 594 : return nNumberFormat;
585 : }
586 3098 : void VDataSeries::setRoleOfSequenceForDataLabelNumberFormatDetection( const OUString& rRole )
587 : {
588 3098 : if (rRole == "values-y")
589 3075 : m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y;
590 23 : else if (rRole == "values-size")
591 9 : m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Bubble_Size;
592 14 : else if (rRole == "values-min")
593 0 : m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_Min;
594 14 : else if (rRole == "values-max")
595 0 : m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_Max;
596 14 : else if (rRole == "values-first")
597 0 : m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_First;
598 14 : else if (rRole == "values-last")
599 14 : m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_Last;
600 0 : else if (rRole == "values-x")
601 0 : m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_X;
602 3098 : }
603 1260 : bool VDataSeries::shouldLabelNumberFormatKeyBeDetectedFromYAxis() const
604 : {
605 1260 : if( m_pValueSequenceForDataLabelNumberFormatDetection == &m_aValues_Bubble_Size )
606 0 : return false;
607 1260 : else if( m_pValueSequenceForDataLabelNumberFormatDetection == &m_aValues_X )
608 0 : return false;
609 1260 : return true;
610 : }
611 1104 : sal_Int32 VDataSeries::detectNumberFormatKey( sal_Int32 index ) const
612 : {
613 1104 : sal_Int32 nRet = 0;
614 1104 : if( m_pValueSequenceForDataLabelNumberFormatDetection )
615 1104 : nRet = m_pValueSequenceForDataLabelNumberFormatDetection->detectNumberFormatKey( index );
616 1104 : return nRet;
617 : }
618 :
619 1674 : sal_Int32 VDataSeries::getLabelPlacement( sal_Int32 nPointIndex, const uno::Reference< chart2::XChartType >& xChartType, sal_Int32 nDimensionCount, bool bSwapXAndY ) const
620 : {
621 1674 : sal_Int32 nLabelPlacement=0;
622 : try
623 : {
624 1674 : uno::Reference< beans::XPropertySet > xPointProps( this->getPropertiesOfPoint( nPointIndex ) );
625 1674 : if( xPointProps.is() )
626 1674 : xPointProps->getPropertyValue("LabelPlacement") >>= nLabelPlacement;
627 :
628 : //ensure that the set label placement is supported by this charttype
629 :
630 : uno::Sequence < sal_Int32 > aAvailablePlacements( ChartTypeHelper::getSupportedLabelPlacements(
631 1674 : xChartType, nDimensionCount, bSwapXAndY, m_xDataSeries ) );
632 :
633 9195 : for( sal_Int32 nN = 0; nN < aAvailablePlacements.getLength(); nN++ )
634 7700 : if( aAvailablePlacements[nN] == nLabelPlacement )
635 179 : return nLabelPlacement; //ok
636 :
637 : //otherwise use the first supported one
638 1495 : if( aAvailablePlacements.getLength() )
639 : {
640 1495 : nLabelPlacement = aAvailablePlacements[0];
641 1495 : return nLabelPlacement;
642 : }
643 :
644 0 : OSL_FAIL("no label placement supported");
645 : }
646 0 : catch( const uno::Exception& e )
647 : {
648 : ASSERT_EXCEPTION( e );
649 : }
650 0 : return nLabelPlacement;
651 : }
652 :
653 12434 : double VDataSeries::getMinimumofAllDifferentYValues( sal_Int32 index ) const
654 : {
655 12434 : double fMin=0.0;
656 12434 : ::rtl::math::setInf(&fMin, false);
657 :
658 12534 : if( !m_aValues_Y.is() &&
659 50 : (m_aValues_Y_Min.is() || m_aValues_Y_Max.is()
660 0 : || m_aValues_Y_First.is() || m_aValues_Y_Last.is() ) )
661 : {
662 50 : double fY_Min = getY_Min( index );
663 50 : double fY_Max = getY_Max( index );
664 50 : double fY_First = getY_First( index );
665 50 : double fY_Last = getY_Last( index );
666 :
667 50 : if(fMin>fY_First)
668 20 : fMin=fY_First;
669 50 : if(fMin>fY_Last)
670 32 : fMin=fY_Last;
671 50 : if(fMin>fY_Min)
672 30 : fMin=fY_Min;
673 50 : if(fMin>fY_Max)
674 18 : fMin=fY_Max;
675 : }
676 : else
677 : {
678 12384 : double fY = getYValue( index );
679 12384 : if(fMin>fY)
680 12353 : fMin=fY;
681 : }
682 :
683 12434 : if( ::rtl::math::isInf(fMin) )
684 31 : ::rtl::math::setNan(&fMin);
685 :
686 12434 : return fMin;
687 : }
688 :
689 12434 : double VDataSeries::getMaximumofAllDifferentYValues( sal_Int32 index ) const
690 : {
691 12434 : double fMax=0.0;
692 12434 : ::rtl::math::setInf(&fMax, true);
693 :
694 12534 : if( !m_aValues_Y.is() &&
695 50 : (m_aValues_Y_Min.is() || m_aValues_Y_Max.is()
696 0 : || m_aValues_Y_First.is() || m_aValues_Y_Last.is() ) )
697 : {
698 50 : double fY_Min = getY_Min( index );
699 50 : double fY_Max = getY_Max( index );
700 50 : double fY_First = getY_First( index );
701 50 : double fY_Last = getY_Last( index );
702 :
703 50 : if(fMax<fY_First)
704 20 : fMax=fY_First;
705 50 : if(fMax<fY_Last)
706 36 : fMax=fY_Last;
707 50 : if(fMax<fY_Min)
708 26 : fMax=fY_Min;
709 50 : if(fMax<fY_Max)
710 18 : fMax=fY_Max;
711 : }
712 : else
713 : {
714 12384 : double fY = getYValue( index );
715 12384 : if(fMax<fY)
716 12353 : fMax=fY;
717 : }
718 :
719 12434 : if( ::rtl::math::isInf(fMax) )
720 31 : ::rtl::math::setNan(&fMax);
721 :
722 12434 : return fMax;
723 : }
724 :
725 83 : uno::Sequence< double > VDataSeries::getAllX() const
726 : {
727 83 : if(!m_aValues_X.is() && !m_aValues_X.getLength() && m_nPointCount)
728 : {
729 : //init x values from category indexes
730 : //first category (index 0) matches with real number 1.0
731 37 : m_aValues_X.Doubles.realloc( m_nPointCount );
732 501 : for(sal_Int32 nN=m_aValues_X.getLength();nN--;)
733 427 : m_aValues_X.Doubles[nN] = nN+1;
734 : }
735 83 : return m_aValues_X.Doubles;
736 : }
737 :
738 309 : uno::Sequence< double > VDataSeries::getAllY() const
739 : {
740 309 : if(!m_aValues_Y.is() && !m_aValues_Y.getLength() && m_nPointCount)
741 : {
742 : //init y values from indexes
743 : //first y-value (index 0) matches with real number 1.0
744 0 : m_aValues_Y.Doubles.realloc( m_nPointCount );
745 0 : for(sal_Int32 nN=m_aValues_Y.getLength();nN--;)
746 0 : m_aValues_Y.Doubles[nN] = nN+1;
747 : }
748 309 : return m_aValues_Y.Doubles;
749 : }
750 :
751 0 : double VDataSeries::getXMeanValue() const
752 : {
753 0 : if( ::rtl::math::isNan( m_fXMeanValue ) )
754 : {
755 0 : uno::Reference< XRegressionCurveCalculator > xCalculator( RegressionCurveHelper::createRegressionCurveCalculatorByServiceName( "com.sun.star.chart2.MeanValueRegressionCurve" ) );
756 0 : uno::Sequence< double > aXValuesDummy;
757 0 : xCalculator->recalculateRegression( aXValuesDummy, getAllX() );
758 0 : double fXDummy = 1.0;
759 0 : m_fXMeanValue = xCalculator->getCurveValue( fXDummy );
760 : }
761 0 : return m_fXMeanValue;
762 : }
763 :
764 0 : double VDataSeries::getYMeanValue() const
765 : {
766 0 : if( ::rtl::math::isNan( m_fYMeanValue ) )
767 : {
768 : uno::Reference< XRegressionCurveCalculator > xCalculator(
769 0 : RegressionCurveHelper::createRegressionCurveCalculatorByServiceName("com.sun.star.chart2.MeanValueRegressionCurve"));
770 0 : uno::Sequence< double > aXValuesDummy;
771 0 : xCalculator->recalculateRegression( aXValuesDummy, getAllY() );
772 0 : double fXDummy = 1.0;
773 0 : m_fYMeanValue = xCalculator->getCurveValue( fXDummy );
774 : }
775 0 : return m_fYMeanValue;
776 : }
777 :
778 305 : Symbol* getSymbolPropertiesFromPropertySet( const uno::Reference< beans::XPropertySet >& xProp )
779 : {
780 305 : ::std::unique_ptr< Symbol > apSymbolProps( new Symbol() );
781 : try
782 : {
783 305 : if( xProp->getPropertyValue("Symbol") >>= *apSymbolProps )
784 : {
785 : //use main color to fill symbols
786 305 : xProp->getPropertyValue("Color") >>= apSymbolProps->FillColor;
787 : // border of symbols always same as fill color
788 305 : apSymbolProps->BorderColor = apSymbolProps->FillColor;
789 : }
790 : else
791 0 : apSymbolProps.reset();
792 : }
793 0 : catch(const uno::Exception &e)
794 : {
795 : ASSERT_EXCEPTION( e );
796 : }
797 305 : return apSymbolProps.release();
798 : }
799 :
800 1959 : Symbol* VDataSeries::getSymbolProperties( sal_Int32 index ) const
801 : {
802 1959 : Symbol* pRet=NULL;
803 1959 : if( isAttributedDataPoint( index ) )
804 : {
805 0 : adaptPointCache( index );
806 0 : if (!m_apSymbolProperties_AttributedPoint)
807 : m_apSymbolProperties_AttributedPoint.reset(
808 0 : getSymbolPropertiesFromPropertySet(this->getPropertiesOfPoint(index)));
809 0 : pRet = m_apSymbolProperties_AttributedPoint.get();
810 : //if a single data point does not have symbols but the dataseries itself has symbols
811 : //we create an invisible symbol shape to enable selection of that point
812 0 : if( !pRet || pRet->Style == SymbolStyle_NONE )
813 : {
814 0 : if (!m_apSymbolProperties_Series)
815 : m_apSymbolProperties_Series.reset(
816 0 : getSymbolPropertiesFromPropertySet(this->getPropertiesOfSeries()));
817 0 : if( m_apSymbolProperties_Series.get() && m_apSymbolProperties_Series->Style != SymbolStyle_NONE )
818 : {
819 0 : if (!m_apSymbolProperties_InvisibleSymbolForSelection)
820 : {
821 0 : m_apSymbolProperties_InvisibleSymbolForSelection.reset(new Symbol);
822 0 : m_apSymbolProperties_InvisibleSymbolForSelection->Style = SymbolStyle_STANDARD;
823 0 : m_apSymbolProperties_InvisibleSymbolForSelection->StandardSymbol = 0;//square
824 0 : m_apSymbolProperties_InvisibleSymbolForSelection->Size = m_apSymbolProperties_Series->Size;
825 0 : m_apSymbolProperties_InvisibleSymbolForSelection->BorderColor = 0xff000000;//invisible
826 0 : m_apSymbolProperties_InvisibleSymbolForSelection->FillColor = 0xff000000;//invisible
827 : }
828 0 : pRet = m_apSymbolProperties_InvisibleSymbolForSelection.get();
829 : }
830 : }
831 : }
832 : else
833 : {
834 1959 : if (!m_apSymbolProperties_Series)
835 : m_apSymbolProperties_Series.reset(
836 305 : getSymbolPropertiesFromPropertySet(this->getPropertiesOfSeries()));
837 1959 : pRet = m_apSymbolProperties_Series.get();
838 : }
839 :
840 1959 : if( pRet && pRet->Style == SymbolStyle_AUTO )
841 : {
842 15 : pRet->Style = SymbolStyle_STANDARD;
843 :
844 15 : sal_Int32 nIndex = m_nGlobalSeriesIndex;
845 15 : if(m_aValues_X.is())
846 3 : nIndex++;
847 15 : pRet->StandardSymbol = nIndex;
848 : }
849 :
850 1959 : return pRet;
851 : }
852 :
853 2084 : uno::Reference< beans::XPropertySet > VDataSeries::getXErrorBarProperties( sal_Int32 index ) const
854 : {
855 2084 : uno::Reference< beans::XPropertySet > xErrorBarProp;
856 :
857 4168 : uno::Reference< beans::XPropertySet > xPointProp( this->getPropertiesOfPoint( index ));
858 2084 : if( xPointProp.is() )
859 2084 : xPointProp->getPropertyValue(CHART_UNONAME_ERRORBAR_X) >>= xErrorBarProp;
860 4168 : return xErrorBarProp;
861 : }
862 :
863 12311 : uno::Reference< beans::XPropertySet > VDataSeries::getYErrorBarProperties( sal_Int32 index ) const
864 : {
865 12311 : uno::Reference< beans::XPropertySet > xErrorBarProp;
866 :
867 24622 : uno::Reference< beans::XPropertySet > xPointProp( this->getPropertiesOfPoint( index ));
868 12311 : if( xPointProp.is() )
869 12311 : xPointProp->getPropertyValue(CHART_UNONAME_ERRORBAR_Y) >>= xErrorBarProp;
870 24622 : return xErrorBarProp;
871 : }
872 :
873 460 : bool VDataSeries::hasPointOwnColor( sal_Int32 index ) const
874 : {
875 460 : if( !isAttributedDataPoint(index) )
876 140 : return false;
877 :
878 : try
879 : {
880 320 : uno::Reference< beans::XPropertyState > xPointState( this->getPropertiesOfPoint(index), uno::UNO_QUERY_THROW );
881 320 : return (xPointState->getPropertyState("Color") != beans::PropertyState_DEFAULT_VALUE );
882 : }
883 0 : catch(const uno::Exception& e)
884 : {
885 : ASSERT_EXCEPTION( e );
886 : }
887 0 : return false;
888 : }
889 :
890 69632 : bool VDataSeries::isAttributedDataPoint( sal_Int32 index ) const
891 : {
892 : //returns true if the data point assigned by the given index has set it's own properties
893 69632 : if( index>=m_nPointCount || m_nPointCount==0)
894 0 : return false;
895 151187 : for(sal_Int32 nN=m_aAttributedDataPointIndexList.getLength();nN--;)
896 : {
897 17815 : if(index==m_aAttributedDataPointIndexList[nN])
898 5892 : return true;
899 : }
900 63740 : return false;
901 : }
902 :
903 3563 : bool VDataSeries::isVaryColorsByPoint() const
904 : {
905 3563 : bool bVaryColorsByPoint = false;
906 3563 : Reference< beans::XPropertySet > xSeriesProp( this->getPropertiesOfSeries() );
907 3563 : if( xSeriesProp.is() )
908 3563 : xSeriesProp->getPropertyValue("VaryColorsByPoint") >>= bVaryColorsByPoint;
909 3563 : return bVaryColorsByPoint;
910 : }
911 :
912 37161 : uno::Reference< beans::XPropertySet > VDataSeries::getPropertiesOfPoint( sal_Int32 index ) const
913 : {
914 37161 : if( isAttributedDataPoint( index ) )
915 3974 : return m_xDataSeries->getDataPointByIndex(index);
916 33187 : return this->getPropertiesOfSeries();
917 : }
918 :
919 40572 : uno::Reference<beans::XPropertySet> VDataSeries::getPropertiesOfSeries() const
920 : {
921 40572 : return uno::Reference<css::beans::XPropertySet>(m_xDataSeries, css::uno::UNO_QUERY);
922 : }
923 :
924 3518 : DataPointLabel* getDataPointLabelFromPropertySet( const uno::Reference< beans::XPropertySet >& xProp )
925 : {
926 3518 : ::std::unique_ptr< DataPointLabel > apLabel( new DataPointLabel() );
927 : try
928 : {
929 3518 : if( !(xProp->getPropertyValue(CHART_UNONAME_LABEL) >>= *apLabel) )
930 0 : apLabel.reset();
931 : }
932 0 : catch(const uno::Exception &e)
933 : {
934 : ASSERT_EXCEPTION( e );
935 : }
936 3518 : return apLabel.release();
937 : }
938 :
939 1224 : void VDataSeries::adaptPointCache( sal_Int32 nNewPointIndex ) const
940 : {
941 1224 : if( m_nCurrentAttributedPoint != nNewPointIndex )
942 : {
943 502 : m_apLabel_AttributedPoint.reset();
944 502 : m_apLabelPropNames_AttributedPoint.reset();
945 502 : m_apLabelPropValues_AttributedPoint.reset();
946 502 : m_apSymbolProperties_AttributedPoint.reset();
947 502 : m_nCurrentAttributedPoint = nNewPointIndex;
948 : }
949 1224 : }
950 :
951 15628 : DataPointLabel* VDataSeries::getDataPointLabel( sal_Int32 index ) const
952 : {
953 15628 : DataPointLabel* pRet = NULL;
954 15628 : if( isAttributedDataPoint( index ) )
955 : {
956 863 : adaptPointCache( index );
957 863 : if( !m_apLabel_AttributedPoint.get() )
958 : m_apLabel_AttributedPoint.reset(
959 502 : getDataPointLabelFromPropertySet(this->getPropertiesOfPoint(index)));
960 863 : pRet = m_apLabel_AttributedPoint.get();
961 : }
962 : else
963 : {
964 14765 : if (!m_apLabel_Series)
965 : m_apLabel_Series.reset(
966 3016 : getDataPointLabelFromPropertySet(this->getPropertiesOfPoint(index)));
967 14765 : pRet = m_apLabel_Series.get();
968 : }
969 15628 : if( !m_bAllowPercentValueInDataLabel )
970 : {
971 360 : if( pRet )
972 360 : pRet->ShowNumberInPercent = false;
973 : }
974 15628 : return pRet;
975 : }
976 :
977 15628 : DataPointLabel* VDataSeries::getDataPointLabelIfLabel( sal_Int32 index ) const
978 : {
979 15628 : DataPointLabel* pLabel = this->getDataPointLabel( index );
980 15628 : if( !pLabel || (!pLabel->ShowNumber && !pLabel->ShowNumberInPercent
981 11406 : && !pLabel->ShowCategoryName ) )
982 11320 : return 0;
983 4308 : return pLabel;
984 : }
985 :
986 1674 : bool VDataSeries::getTextLabelMultiPropertyLists( sal_Int32 index
987 : , tNameSequence*& pPropNames
988 : , tAnySequence*& pPropValues ) const
989 : {
990 1674 : pPropNames = NULL; pPropValues = NULL;
991 1674 : uno::Reference< beans::XPropertySet > xTextProp;
992 1674 : bool bDoDynamicFontResize = false;
993 1674 : if( isAttributedDataPoint( index ) )
994 : {
995 361 : adaptPointCache( index );
996 361 : if (!m_apLabelPropValues_AttributedPoint)
997 : {
998 : // Cache these properties for this point.
999 361 : m_apLabelPropNames_AttributedPoint.reset(new tNameSequence);
1000 361 : m_apLabelPropValues_AttributedPoint.reset(new tAnySequence);
1001 361 : xTextProp.set( this->getPropertiesOfPoint( index ));
1002 : PropertyMapper::getTextLabelMultiPropertyLists(
1003 361 : xTextProp, *m_apLabelPropNames_AttributedPoint, *m_apLabelPropValues_AttributedPoint);
1004 361 : bDoDynamicFontResize = true;
1005 : }
1006 361 : pPropNames = m_apLabelPropNames_AttributedPoint.get();
1007 361 : pPropValues = m_apLabelPropValues_AttributedPoint.get();
1008 : }
1009 : else
1010 : {
1011 1313 : if (!m_apLabelPropValues_Series)
1012 : {
1013 : // Cache these properties for the whole series.
1014 139 : m_apLabelPropNames_Series.reset(new tNameSequence);
1015 139 : m_apLabelPropValues_Series.reset(new tAnySequence);
1016 139 : xTextProp.set( this->getPropertiesOfPoint( index ));
1017 : PropertyMapper::getTextLabelMultiPropertyLists(
1018 139 : xTextProp, *m_apLabelPropNames_Series, *m_apLabelPropValues_Series);
1019 139 : bDoDynamicFontResize = true;
1020 : }
1021 1313 : pPropNames = m_apLabelPropNames_Series.get();
1022 1313 : pPropValues = m_apLabelPropValues_Series.get();
1023 : }
1024 :
1025 2174 : if( bDoDynamicFontResize &&
1026 2674 : pPropNames && pPropValues &&
1027 500 : xTextProp.is())
1028 : {
1029 500 : LabelPositionHelper::doDynamicFontResize( *pPropValues, *pPropNames, xTextProp, m_aReferenceSize );
1030 : }
1031 :
1032 1674 : return (pPropNames && pPropValues);
1033 : }
1034 :
1035 3098 : void VDataSeries::setMissingValueTreatment( sal_Int32 nMissingValueTreatment )
1036 : {
1037 3098 : m_nMissingValueTreatment = nMissingValueTreatment;
1038 3098 : }
1039 :
1040 110404 : sal_Int32 VDataSeries::getMissingValueTreatment() const
1041 : {
1042 110404 : return m_nMissingValueTreatment;
1043 : }
1044 :
1045 0 : VDataSeries::VDataSeries()
1046 : : m_nPolygonIndex(0)
1047 : , m_fLogicMinX(0)
1048 : , m_fLogicMaxX(0)
1049 : , m_fLogicZPos(0)
1050 : , m_nPointCount(0)
1051 : , m_pValueSequenceForDataLabelNumberFormatDetection(NULL)
1052 : , m_fXMeanValue(0)
1053 : , m_fYMeanValue(0)
1054 : , m_eStackingDirection(chart2::StackingDirection_NO_STACKING)
1055 : , m_nAxisIndex(0)
1056 : , m_bConnectBars(false)
1057 : , m_bGroupBarsPerAxis(false)
1058 : , m_nStartingAngle(0)
1059 : , m_nGlobalSeriesIndex(0)
1060 : , m_nCurrentAttributedPoint(0)
1061 : , m_nMissingValueTreatment(0)
1062 : , m_bAllowPercentValueInDataLabel(false)
1063 : , mpOldSeries(NULL)
1064 0 : , mnPercent(0)
1065 : {
1066 0 : }
1067 :
1068 0 : void VDataSeries::setOldTimeBased( VDataSeries* pOldSeries, double nPercent )
1069 : {
1070 0 : mnPercent = nPercent;
1071 0 : mpOldSeries = pOldSeries;
1072 0 : mpOldSeries->mpOldSeries = NULL;
1073 0 : }
1074 :
1075 0 : VDataSeries* VDataSeries::createCopyForTimeBased() const
1076 : {
1077 0 : VDataSeries* pNew = new VDataSeries();
1078 0 : pNew->m_aValues_X = m_aValues_X;
1079 0 : pNew->m_aValues_Y = m_aValues_Y;
1080 0 : pNew->m_aValues_Z = m_aValues_Z;
1081 0 : pNew->m_aValues_Y_Min = m_aValues_Y_Min;
1082 0 : pNew->m_aValues_Y_Max = m_aValues_Y_Max;
1083 0 : pNew->m_aValues_Y_First = m_aValues_Y_First;
1084 0 : pNew->m_aValues_Y_Last = m_aValues_Y_Last;
1085 0 : pNew->m_aValues_Bubble_Size = m_aValues_Bubble_Size;
1086 0 : pNew->maPropertyMap = maPropertyMap;
1087 :
1088 0 : pNew->m_nPointCount = m_nPointCount;
1089 :
1090 0 : return pNew;
1091 : }
1092 :
1093 0 : double VDataSeries::getValueByProperty( sal_Int32 nIndex, const OUString& rPropName ) const
1094 : {
1095 : boost::ptr_map<OUString, VDataSequence>::const_iterator itr =
1096 0 : maPropertyMap.find(rPropName);
1097 0 : if(itr == maPropertyMap.end())
1098 : {
1099 : double fNan;
1100 0 : ::rtl::math::setNan( &fNan );
1101 0 : return fNan;
1102 : }
1103 :
1104 0 : const VDataSequence* pData = itr->second;
1105 0 : double fValue = pData->getValue(nIndex);
1106 0 : if(mpOldSeries && mpOldSeries->hasPropertyMapping(rPropName))
1107 : {
1108 0 : double fOldValue = mpOldSeries->getValueByProperty( nIndex, rPropName );
1109 0 : if(rPropName.endsWith("Color"))
1110 : {
1111 : //optimized interpolation for color values
1112 0 : Color aColor(static_cast<sal_uInt32>(fValue));
1113 0 : Color aOldColor(static_cast<sal_uInt32>(fOldValue));
1114 0 : sal_uInt8 r = aOldColor.GetRed() + (aColor.GetRed() - aOldColor.GetRed()) * mnPercent;
1115 0 : sal_uInt8 g = aOldColor.GetGreen() + (aColor.GetGreen() - aOldColor.GetGreen()) * mnPercent;
1116 0 : sal_uInt8 b = aOldColor.GetBlue() + (aColor.GetBlue() - aOldColor.GetBlue()) * mnPercent;
1117 0 : sal_uInt8 t = aOldColor.GetTransparency() + (aColor.GetTransparency() - aOldColor.GetTransparency()) * mnPercent;
1118 0 : Color aRet(t, r, g, b);
1119 0 : return aRet.GetColor();
1120 : }
1121 0 : return fOldValue + (fValue - fOldValue) * mnPercent;
1122 : }
1123 0 : return fValue;
1124 : }
1125 :
1126 10705 : bool VDataSeries::hasPropertyMapping(const OUString& rPropName ) const
1127 : {
1128 10705 : return maPropertyMap.find(rPropName) != maPropertyMap.end();
1129 : }
1130 :
1131 : } //namespace chart
1132 :
1133 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|