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