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