bump product version to 4.1.6.2
[LibreOffice.git] / chart2 / source / tools / DataSeriesHelper.cxx
blobd7ec4ac688db47c188ae4958035ab9d06d797f83
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "DataSeriesHelper.hxx"
21 #include "DiagramHelper.hxx"
22 #include "DataSource.hxx"
23 #include "macros.hxx"
24 #include "ContainerHelper.hxx"
25 #include <com/sun/star/beans/XPropertySet.hpp>
26 #include <com/sun/star/chart2/DataPointLabel.hpp>
27 #include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
28 #include <com/sun/star/chart2/StackingDirection.hpp>
29 #include <com/sun/star/chart2/data/LabelOrigin.hpp>
30 #include <com/sun/star/chart2/AxisType.hpp>
31 #include <com/sun/star/chart2/SymbolStyle.hpp>
32 #include <com/sun/star/chart2/Symbol.hpp>
33 #include <com/sun/star/drawing/LineStyle.hpp>
36 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
37 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
38 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
39 #include <rtl/ustrbuf.hxx>
41 #include <functional>
42 #include <algorithm>
43 #include <iterator>
44 #include <vector>
45 #include <set>
47 using namespace ::com::sun::star;
48 using namespace ::com::sun::star::chart2;
50 using ::com::sun::star::uno::Reference;
51 using ::com::sun::star::uno::Sequence;
53 // ----------------------------------------
54 namespace
57 class lcl_MatchesRole : public ::std::unary_function< Reference< chart2::data::XLabeledDataSequence >, bool >
59 public:
60 explicit lcl_MatchesRole( const OUString & aRole, bool bMatchPrefix ) :
61 m_aRole( aRole ),
62 m_bMatchPrefix( bMatchPrefix )
65 bool operator () ( const Reference< chart2::data::XLabeledDataSequence > & xSeq ) const
67 if(!xSeq.is())
68 return false;
69 Reference< beans::XPropertySet > xProp( xSeq->getValues(), uno::UNO_QUERY );
70 OUString aRole;
72 if( m_bMatchPrefix )
73 return ( xProp.is() &&
74 (xProp->getPropertyValue( "Role" ) >>= aRole ) &&
75 aRole.match( m_aRole ));
77 return ( xProp.is() &&
78 (xProp->getPropertyValue( "Role" ) >>= aRole ) &&
79 m_aRole.equals( aRole ));
82 private:
83 OUString m_aRole;
84 bool m_bMatchPrefix;
87 Reference< chart2::data::XLabeledDataSequence > lcl_findLSequenceWithOnlyLabel(
88 const Reference< chart2::data::XDataSource > & xDataSource )
90 Reference< chart2::data::XLabeledDataSequence > xResult;
91 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( xDataSource->getDataSequences());
93 for( sal_Int32 i=0; i<aSequences.getLength(); ++i )
95 OSL_ENSURE( aSequences[i].is(), "empty LabeledDataSequence" );
96 // no values are set but a label exists
97 if( aSequences[i].is() &&
98 ( ! aSequences[i]->getValues().is() &&
99 aSequences[i]->getLabel().is()))
101 xResult.set( aSequences[i] );
102 break;
106 return xResult;
109 void lcl_getCooSysAndChartTypeOfSeries(
110 const Reference< chart2::XDataSeries > & xSeries,
111 const Reference< chart2::XDiagram > & xDiagram,
112 Reference< chart2::XCoordinateSystem > & xOutCooSys,
113 Reference< chart2::XChartType > & xOutChartType )
115 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY );
116 if( xCooSysCnt.is())
118 Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems());
119 for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
121 Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
122 Sequence< Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes());
123 for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx )
125 Reference< chart2::XDataSeriesContainer > xSeriesCnt( aChartTypes[nCTIdx], uno::UNO_QUERY );
126 if( xSeriesCnt.is())
128 Sequence< Reference< chart2::XDataSeries > > aSeries( xSeriesCnt->getDataSeries());
129 for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeries.getLength(); ++nSeriesIdx )
131 if( aSeries[nSeriesIdx] == xSeries )
133 xOutCooSys.set( aCooSysSeq[nCooSysIdx] );
134 xOutChartType.set( aChartTypes[nCTIdx] );
143 void lcl_insertOrDeleteDataLabelsToSeriesAndAllPoints( const Reference< chart2::XDataSeries >& xSeries, bool bInsert )
147 Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY );
148 if( xSeriesProperties.is() )
150 DataPointLabel aLabelAtSeries;
151 xSeriesProperties->getPropertyValue( "Label" ) >>= aLabelAtSeries;
152 aLabelAtSeries.ShowNumber = bInsert;
153 if( !bInsert )
155 aLabelAtSeries.ShowNumberInPercent = false;
156 aLabelAtSeries.ShowCategoryName = false;
158 xSeriesProperties->setPropertyValue( "Label", uno::makeAny( aLabelAtSeries ) );
159 uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
160 if( xSeriesProperties->getPropertyValue( "AttributedDataPoints" ) >>= aAttributedDataPointIndexList )
162 for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
164 Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) );
165 if( xPointProp.is() )
167 DataPointLabel aLabel;
168 xPointProp->getPropertyValue( "Label" ) >>= aLabel;
169 aLabel.ShowNumber = bInsert;
170 if( !bInsert )
172 aLabel.ShowNumberInPercent = false;
173 aLabel.ShowCategoryName = false;
175 xPointProp->setPropertyValue( "Label", uno::makeAny( aLabel ) );
181 catch(const uno::Exception &e)
183 ASSERT_EXCEPTION( e );
187 } // anonymous namespace
188 // ----------------------------------------
190 namespace chart
193 namespace DataSeriesHelper
196 OUString GetRole( const uno::Reference< chart2::data::XLabeledDataSequence >& xLabeledDataSequence )
198 OUString aRet;
199 if( xLabeledDataSequence.is() )
201 Reference< beans::XPropertySet > xProp( xLabeledDataSequence->getValues(), uno::UNO_QUERY );
202 if( xProp.is() )
203 xProp->getPropertyValue( "Role" ) >>= aRet;
205 return aRet;
208 Reference< chart2::data::XLabeledDataSequence >
209 getDataSequenceByRole(
210 const Reference< chart2::data::XDataSource > & xSource, OUString aRole,
211 bool bMatchPrefix /* = false */ )
213 Reference< chart2::data::XLabeledDataSequence > aNoResult;
214 if( ! xSource.is())
215 return aNoResult;
216 Sequence< Reference< chart2::data::XLabeledDataSequence > > aLabeledSeq( xSource->getDataSequences());
218 const Reference< chart2::data::XLabeledDataSequence > * pBegin = aLabeledSeq.getConstArray();
219 const Reference< chart2::data::XLabeledDataSequence > * pEnd = pBegin + aLabeledSeq.getLength();
220 const Reference< chart2::data::XLabeledDataSequence > * pMatch =
221 ::std::find_if( pBegin, pEnd, lcl_MatchesRole( aRole, bMatchPrefix ));
223 if( pMatch != pEnd )
224 return *pMatch;
226 return aNoResult;
229 ::std::vector< Reference< chart2::data::XLabeledDataSequence > >
230 getAllDataSequencesByRole( const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aDataSequences,
231 OUString aRole, bool bMatchPrefix /* = false */ )
233 ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aResultVec;
234 ::std::remove_copy_if( aDataSequences.getConstArray(), aDataSequences.getConstArray() + aDataSequences.getLength(),
235 ::std::back_inserter( aResultVec ),
236 ::std::not1( lcl_MatchesRole( aRole, bMatchPrefix )));
237 return aResultVec;
240 Reference< chart2::data::XDataSource >
241 getDataSource( const Sequence< Reference< chart2::XDataSeries > > & aSeries )
243 ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aSeqVec;
245 for( sal_Int32 i = 0; i < aSeries.getLength(); ++i )
247 Reference< chart2::data::XDataSource > xSource( aSeries[ i ], uno::UNO_QUERY );
248 if( xSource.is())
250 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeq( xSource->getDataSequences());
251 ::std::copy( aSeq.getConstArray(), aSeq.getConstArray() + aSeq.getLength(),
252 ::std::back_inserter( aSeqVec ));
256 return Reference< chart2::data::XDataSource >(
257 new DataSource( ContainerHelper::ContainerToSequence( aSeqVec )));
260 namespace
262 OUString lcl_getDataSequenceLabel( const Reference< chart2::data::XDataSequence > & xSequence )
264 OUString aResult;
266 Reference< chart2::data::XTextualDataSequence > xTextSeq( xSequence, uno::UNO_QUERY );
267 if( xTextSeq.is())
269 Sequence< OUString > aSeq( xTextSeq->getTextualData());
271 const sal_Int32 nMax = aSeq.getLength() - 1;
272 OUStringBuffer aBuf;
274 for( sal_Int32 i = 0; i <= nMax; ++i )
276 aBuf.append( aSeq[i] );
277 if( i < nMax )
278 aBuf.append( sal_Unicode( ' ' ));
280 aResult = aBuf.makeStringAndClear();
282 else if( xSequence.is())
284 Sequence< uno::Any > aSeq( xSequence->getData());
286 const sal_Int32 nMax = aSeq.getLength() - 1;
287 OUString aVal;
288 OUStringBuffer aBuf;
289 double fNum = 0;
291 for( sal_Int32 i = 0; i <= nMax; ++i )
293 if( aSeq[i] >>= aVal )
295 aBuf.append( aVal );
296 if( i < nMax )
297 aBuf.append( sal_Unicode( ' ' ));
299 else if( aSeq[ i ] >>= fNum )
301 aBuf.append( fNum );
302 if( i < nMax )
303 aBuf.append( sal_Unicode( ' ' ));
306 aResult = aBuf.makeStringAndClear();
309 return aResult;
313 OUString getLabelForLabeledDataSequence(
314 const Reference< chart2::data::XLabeledDataSequence > & xLabeledSeq )
316 OUString aResult;
317 if( xLabeledSeq.is())
319 Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getLabel());
320 if( xSeq.is() )
321 aResult = lcl_getDataSequenceLabel( xSeq );
322 if( !xSeq.is() || aResult.isEmpty() )
324 // no label set or label content is empty -> use auto-generated one
325 Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues() );
326 if( xValueSeq.is() )
328 Sequence< OUString > aLabels( xValueSeq->generateLabel(
329 chart2::data::LabelOrigin_SHORT_SIDE ) );
330 // no labels returned is interpreted as: auto-generation not
331 // supported by sequence
332 if( aLabels.getLength() )
333 aResult=aLabels[0];
334 else
336 //todo?: maybe use the index of the series as name
337 //but as the index may change it would be better to have such a name persistent
338 //what is not possible at the moment
339 //--> maybe use the identifier as part of the name ...
340 aResult = lcl_getDataSequenceLabel( xValueSeq );
345 return aResult;
348 OUString getDataSeriesLabel(
349 const Reference< chart2::XDataSeries > & xSeries,
350 const OUString & rLabelSequenceRole )
352 OUString aResult;
354 Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
355 if( xSource.is())
357 Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
358 ::chart::DataSeriesHelper::getDataSequenceByRole( xSource, rLabelSequenceRole ));
359 if( xLabeledSeq.is())
360 aResult = getLabelForLabeledDataSequence( xLabeledSeq );
361 else
363 // special case: labeled data series with only a label and no values may
364 // serve as label
365 xLabeledSeq.set( lcl_findLSequenceWithOnlyLabel( xSource ));
366 if( xLabeledSeq.is())
368 Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getLabel());
369 if( xSeq.is())
370 aResult = lcl_getDataSequenceLabel( xSeq );
376 return aResult;
379 void setStackModeAtSeries(
380 const Sequence< Reference< chart2::XDataSeries > > & aSeries,
381 const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem,
382 StackMode eStackMode )
384 if( eStackMode == StackMode_AMBIGUOUS )
385 return;
387 const OUString aPropName( "StackingDirection" );
388 const uno::Any aPropValue = uno::makeAny(
389 ( (eStackMode == StackMode_Y_STACKED) ||
390 (eStackMode == StackMode_Y_STACKED_PERCENT) )
391 ? chart2::StackingDirection_Y_STACKING
392 : (eStackMode == StackMode_Z_STACKED )
393 ? chart2::StackingDirection_Z_STACKING
394 : chart2::StackingDirection_NO_STACKING );
396 std::set< sal_Int32 > aAxisIndexSet;
397 for( sal_Int32 i=0; i<aSeries.getLength(); ++i )
401 Reference< beans::XPropertySet > xProp( aSeries[i], uno::UNO_QUERY );
402 if( xProp.is() )
404 xProp->setPropertyValue( aPropName, aPropValue );
406 sal_Int32 nAxisIndex;
407 xProp->getPropertyValue( "AttachedAxisIndex" ) >>= nAxisIndex;
408 aAxisIndexSet.insert(nAxisIndex);
411 catch( const uno::Exception & ex )
413 ASSERT_EXCEPTION( ex );
417 if( xCorrespondingCoordinateSystem.is() &&
418 1 < xCorrespondingCoordinateSystem->getDimension() )
420 sal_Int32 nAxisIndexCount = aAxisIndexSet.size();
421 if( !nAxisIndexCount )
423 aAxisIndexSet.insert(0);
424 nAxisIndexCount = aAxisIndexSet.size();
427 for( ::std::set< sal_Int32 >::const_iterator aIt = aAxisIndexSet.begin();
428 aIt != aAxisIndexSet.end(); ++aIt )
430 sal_Int32 nAxisIndex = *aIt;
431 Reference< chart2::XAxis > xAxis(
432 xCorrespondingCoordinateSystem->getAxisByDimension( 1, nAxisIndex ));
433 if( xAxis.is())
435 sal_Bool bPercent = (eStackMode == StackMode_Y_STACKED_PERCENT);
436 chart2::ScaleData aScaleData = xAxis->getScaleData();
438 if( bPercent != (aScaleData.AxisType==chart2::AxisType::PERCENT) )
440 if( bPercent )
441 aScaleData.AxisType = chart2::AxisType::PERCENT;
442 else
443 aScaleData.AxisType = chart2::AxisType::REALNUMBER;
444 xAxis->setScaleData( aScaleData );
451 sal_Int32 getAttachedAxisIndex( const Reference< chart2::XDataSeries > & xSeries )
453 sal_Int32 nRet = 0;
456 Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY );
457 if( xProp.is() )
459 xProp->getPropertyValue( "AttachedAxisIndex" ) >>= nRet;
462 catch( const uno::Exception & ex )
464 ASSERT_EXCEPTION( ex );
466 return nRet;
469 sal_Int32 getNumberFormatKeyFromAxis(
470 const Reference< chart2::XDataSeries > & xSeries,
471 const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem,
472 sal_Int32 nDimensionIndex,
473 sal_Int32 nAxisIndex /* = -1 */ )
475 sal_Int32 nResult = 0;
476 if( nAxisIndex == -1 )
477 nAxisIndex = getAttachedAxisIndex( xSeries );
480 Reference< beans::XPropertySet > xAxisProp(
481 xCorrespondingCoordinateSystem->getAxisByDimension( nDimensionIndex, nAxisIndex ), uno::UNO_QUERY );
482 if( xAxisProp.is())
483 xAxisProp->getPropertyValue( "NumberFormat") >>= nResult;
485 catch( const uno::Exception & ex )
487 ASSERT_EXCEPTION( ex );
490 return nResult;
493 Reference< chart2::XCoordinateSystem > getCoordinateSystemOfSeries(
494 const Reference< chart2::XDataSeries > & xSeries,
495 const Reference< chart2::XDiagram > & xDiagram )
497 Reference< chart2::XCoordinateSystem > xResult;
498 Reference< chart2::XChartType > xDummy;
499 lcl_getCooSysAndChartTypeOfSeries( xSeries, xDiagram, xResult, xDummy );
501 return xResult;
504 Reference< chart2::XChartType > getChartTypeOfSeries(
505 const Reference< chart2::XDataSeries > & xSeries,
506 const Reference< chart2::XDiagram > & xDiagram )
508 Reference< chart2::XChartType > xResult;
509 Reference< chart2::XCoordinateSystem > xDummy;
510 lcl_getCooSysAndChartTypeOfSeries( xSeries, xDiagram, xDummy, xResult );
512 return xResult;
515 void deleteSeries(
516 const Reference< chart2::XDataSeries > & xSeries,
517 const Reference< chart2::XChartType > & xChartType )
521 Reference< chart2::XDataSeriesContainer > xSeriesCnt( xChartType, uno::UNO_QUERY_THROW );
522 ::std::vector< Reference< chart2::XDataSeries > > aSeries(
523 ContainerHelper::SequenceToVector( xSeriesCnt->getDataSeries()));
524 ::std::vector< Reference< chart2::XDataSeries > >::iterator aIt =
525 ::std::find( aSeries.begin(), aSeries.end(), xSeries );
526 if( aIt != aSeries.end())
528 aSeries.erase( aIt );
529 xSeriesCnt->setDataSeries( ContainerHelper::ContainerToSequence( aSeries ));
532 catch( const uno::Exception & ex )
534 ASSERT_EXCEPTION( ex );
538 void switchSymbolsOnOrOff( const Reference< beans::XPropertySet > & xSeriesProperties,
539 bool bSymbolsOn, sal_Int32 nSeriesIndex )
541 if( !xSeriesProperties.is() )
542 return;
544 chart2::Symbol aSymbProp;
545 if( (xSeriesProperties->getPropertyValue( "Symbol") >>= aSymbProp ) )
547 if( !bSymbolsOn )
548 aSymbProp.Style = chart2::SymbolStyle_NONE;
549 else if( aSymbProp.Style == chart2::SymbolStyle_NONE )
551 aSymbProp.Style = chart2::SymbolStyle_STANDARD;
552 aSymbProp.StandardSymbol = nSeriesIndex;
554 xSeriesProperties->setPropertyValue( "Symbol", uno::makeAny( aSymbProp ));
556 //todo: check attributed data points
559 void switchLinesOnOrOff( const Reference< beans::XPropertySet > & xSeriesProperties, bool bLinesOn )
561 if( !xSeriesProperties.is() )
562 return;
564 if( bLinesOn )
566 // keep line-styles that are not NONE
567 drawing::LineStyle eLineStyle;
568 if( (xSeriesProperties->getPropertyValue( "LineStyle") >>= eLineStyle ) &&
569 eLineStyle == drawing::LineStyle_NONE )
571 xSeriesProperties->setPropertyValue( "LineStyle", uno::makeAny( drawing::LineStyle_SOLID ) );
574 else
575 xSeriesProperties->setPropertyValue( "LineStyle", uno::makeAny( drawing::LineStyle_NONE ) );
578 void makeLinesThickOrThin( const Reference< beans::XPropertySet > & xSeriesProperties, bool bThick )
580 if( !xSeriesProperties.is() )
581 return;
583 sal_Int32 nNewValue = bThick ? 80 : 0;
584 sal_Int32 nOldValue = 0;
585 if( (xSeriesProperties->getPropertyValue( "LineWidth") >>= nOldValue ) &&
586 nOldValue != nNewValue )
588 if( !(bThick && nOldValue>0))
589 xSeriesProperties->setPropertyValue( "LineWidth", uno::makeAny( nNewValue ) );
593 void setPropertyAlsoToAllAttributedDataPoints( const Reference< chart2::XDataSeries >& xSeries,
594 const OUString& rPropertyName, const uno::Any& rPropertyValue )
596 Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY );
597 if( !xSeriesProperties.is() )
598 return;
600 xSeriesProperties->setPropertyValue( rPropertyName, rPropertyValue );
601 uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
602 if( xSeriesProperties->getPropertyValue( "AttributedDataPoints" ) >>= aAttributedDataPointIndexList )
604 for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
606 Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) );
607 if(!xPointProp.is())
608 continue;
609 xPointProp->setPropertyValue( rPropertyName, rPropertyValue );
614 bool hasAttributedDataPointDifferentValue( const Reference< chart2::XDataSeries >& xSeries,
615 const OUString& rPropertyName, const uno::Any& rPropertyValue )
617 Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY );
618 if( !xSeriesProperties.is() )
619 return false;
621 uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
622 if( xSeriesProperties->getPropertyValue( "AttributedDataPoints" ) >>= aAttributedDataPointIndexList )
624 for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
626 Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) );
627 if(!xPointProp.is())
628 continue;
629 uno::Any aPointValue( xPointProp->getPropertyValue( rPropertyName ) );
630 if( !( rPropertyValue==aPointValue ) )
631 return true;
634 return false;
637 bool areAllSeriesAttachedToSameAxis( const uno::Reference< chart2::XChartType >& xChartType, sal_Int32 & rOutAxisIndex )
641 uno::Reference< chart2::XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY_THROW );
642 uno::Sequence< uno::Reference< chart2::XDataSeries > > aSeriesSeq( xDataSeriesContainer->getDataSeries());
644 const sal_Int32 nSeriesCount( aSeriesSeq.getLength());
645 // AxisIndex can only be 0 or 1
646 sal_Int32 nSeriesAtFirstAxis = 0;
647 sal_Int32 nSeriesAtSecondAxis = 0;
649 for( sal_Int32 nI = 0; nI < nSeriesCount; ++nI )
651 uno::Reference< chart2::XDataSeries > xSeries( aSeriesSeq[nI], uno::UNO_QUERY );
652 sal_Int32 nAxisIndex = DataSeriesHelper::getAttachedAxisIndex( xSeries );
653 if( nAxisIndex == 0 )
654 ++nSeriesAtFirstAxis;
655 else if( nAxisIndex == 1 )
656 ++nSeriesAtSecondAxis;
658 OSL_ENSURE( nSeriesAtFirstAxis + nSeriesAtSecondAxis == nSeriesCount, "Invalid axis index found" );
660 if( nSeriesAtFirstAxis == nSeriesCount )
661 rOutAxisIndex = 0;
662 else if( nSeriesAtSecondAxis == nSeriesCount )
663 rOutAxisIndex = 1;
665 return ( nSeriesAtFirstAxis == nSeriesCount ||
666 nSeriesAtSecondAxis == nSeriesCount );
668 catch( const uno::Exception & ex )
670 ASSERT_EXCEPTION( ex );
671 return false;
675 namespace
678 bool lcl_SequenceHasUnhiddenData( const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
680 if( !xDataSequence.is() )
681 return false;
682 uno::Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY );
683 if( xProp.is() )
685 uno::Sequence< sal_Int32 > aHiddenValues;
688 xProp->getPropertyValue( "HiddenValues" ) >>= aHiddenValues;
689 if( !aHiddenValues.getLength() )
690 return true;
692 catch( const uno::Exception& )
694 return true;
697 if( xDataSequence->getData().getLength() )
698 return true;
699 return false;
704 bool hasUnhiddenData( const uno::Reference< chart2::XDataSeries >& xSeries )
706 uno::Reference< chart2::data::XDataSource > xDataSource =
707 uno::Reference< chart2::data::XDataSource >( xSeries, uno::UNO_QUERY );
709 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aDataSequences = xDataSource->getDataSequences();
711 for(sal_Int32 nN = aDataSequences.getLength();nN--;)
713 if( !aDataSequences[nN].is() )
714 continue;
715 if( lcl_SequenceHasUnhiddenData( aDataSequences[nN]->getValues() ) )
716 return true;
717 if( lcl_SequenceHasUnhiddenData( aDataSequences[nN]->getLabel() ) )
718 return true;
720 return false;
723 struct lcl_LessIndex
725 inline bool operator() ( const sal_Int32& first, const sal_Int32& second ) const
727 return ( first < second );
731 sal_Int32 translateIndexFromHiddenToFullSequence( sal_Int32 nIndex, const Reference< chart2::data::XDataSequence >& xDataSequence, bool bTranslate )
733 if( !bTranslate )
734 return nIndex;
738 uno::Reference<beans::XPropertySet> xProp( xDataSequence, uno::UNO_QUERY );
739 if( xProp.is())
741 Sequence<sal_Int32> aHiddenIndicesSeq;
742 xProp->getPropertyValue( "HiddenValues" ) >>= aHiddenIndicesSeq;
743 if( aHiddenIndicesSeq.getLength() )
745 ::std::vector< sal_Int32 > aHiddenIndices( ContainerHelper::SequenceToVector( aHiddenIndicesSeq ) );
746 ::std::sort( aHiddenIndices.begin(), aHiddenIndices.end(), lcl_LessIndex() );
748 sal_Int32 nHiddenCount = static_cast<sal_Int32>(aHiddenIndices.size());
749 for( sal_Int32 nN = 0; nN < nHiddenCount; ++nN)
751 if( aHiddenIndices[nN] <= nIndex )
752 nIndex += 1;
753 else
754 break;
759 catch (const beans::UnknownPropertyException&)
762 return nIndex;
765 bool hasDataLabelsAtSeries( const Reference< chart2::XDataSeries >& xSeries )
767 bool bRet = false;
770 Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY );
771 if( xProp.is() )
773 DataPointLabel aLabel;
774 if( (xProp->getPropertyValue( "Label" ) >>= aLabel) )
775 bRet = aLabel.ShowNumber || aLabel.ShowNumberInPercent || aLabel.ShowCategoryName;
778 catch(const uno::Exception &e)
780 ASSERT_EXCEPTION( e );
782 return bRet;
785 bool hasDataLabelsAtPoints( const Reference< chart2::XDataSeries >& xSeries )
787 bool bRet = false;
790 Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY );
791 if( xSeriesProperties.is() )
793 uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
794 if( xSeriesProperties->getPropertyValue( "AttributedDataPoints" ) >>= aAttributedDataPointIndexList )
796 for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
798 Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) );
799 if( xPointProp.is() )
801 DataPointLabel aLabel;
802 if( (xPointProp->getPropertyValue( "Label" ) >>= aLabel) )
803 bRet = aLabel.ShowNumber || aLabel.ShowNumberInPercent || aLabel.ShowCategoryName;
804 if( bRet )
805 break;
811 catch(const uno::Exception &e)
813 ASSERT_EXCEPTION( e );
815 return bRet;
818 bool hasDataLabelAtPoint( const Reference< chart2::XDataSeries >& xSeries, sal_Int32 nPointIndex )
820 bool bRet = false;
823 Reference< beans::XPropertySet > xProp;
824 Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY );
825 if( xSeriesProperties.is() )
827 uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
828 if( xSeriesProperties->getPropertyValue( "AttributedDataPoints" ) >>= aAttributedDataPointIndexList )
830 ::std::vector< sal_Int32 > aIndices( ContainerHelper::SequenceToVector( aAttributedDataPointIndexList ) );
831 ::std::vector< sal_Int32 >::iterator aIt = ::std::find( aIndices.begin(), aIndices.end(), nPointIndex );
832 if( aIt != aIndices.end())
833 xProp = xSeries->getDataPointByIndex(nPointIndex);
834 else
835 xProp = xSeriesProperties;
837 if( xProp.is() )
839 DataPointLabel aLabel;
840 if( (xProp->getPropertyValue( "Label" ) >>= aLabel) )
841 bRet = aLabel.ShowNumber || aLabel.ShowNumberInPercent || aLabel.ShowCategoryName;
845 catch(const uno::Exception &e)
847 ASSERT_EXCEPTION( e );
849 return bRet;
852 void insertDataLabelsToSeriesAndAllPoints( const Reference< chart2::XDataSeries >& xSeries )
854 lcl_insertOrDeleteDataLabelsToSeriesAndAllPoints( xSeries, true /*bInsert*/ );
857 void deleteDataLabelsFromSeriesAndAllPoints( const Reference< chart2::XDataSeries >& xSeries )
859 lcl_insertOrDeleteDataLabelsToSeriesAndAllPoints( xSeries, false /*bInsert*/ );
863 void insertDataLabelToPoint( const Reference< beans::XPropertySet >& xPointProp )
867 if( xPointProp.is() )
869 DataPointLabel aLabel;
870 xPointProp->getPropertyValue( "Label" ) >>= aLabel;
871 aLabel.ShowNumber = true;
872 xPointProp->setPropertyValue( "Label", uno::makeAny( aLabel ) );
875 catch(const uno::Exception &e)
877 ASSERT_EXCEPTION( e );
881 void deleteDataLabelsFromPoint( const Reference< beans::XPropertySet >& xPointProp )
885 if( xPointProp.is() )
887 DataPointLabel aLabel;
888 xPointProp->getPropertyValue( "Label" ) >>= aLabel;
889 aLabel.ShowNumber = false;
890 aLabel.ShowNumberInPercent = false;
891 aLabel.ShowCategoryName = false;
892 xPointProp->setPropertyValue( "Label", uno::makeAny( aLabel ) );
895 catch(const uno::Exception &e)
897 ASSERT_EXCEPTION( e );
901 } // namespace DataSeriesHelper
902 } // namespace chart
904 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */