merged tag ooo/OOO330_m14
[LibreOffice.git] / chart2 / source / tools / DataSeriesHelper.cxx
blobacff332d4229b5d8d8e1e6bf7da409a4c5dd7501
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_chart2.hxx"
30 #include "DataSeriesHelper.hxx"
31 #include "DiagramHelper.hxx"
32 #include "DataSource.hxx"
33 #include "macros.hxx"
34 #include "ContainerHelper.hxx"
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/chart2/DataPointLabel.hpp>
37 #include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
38 #include <com/sun/star/chart2/StackingDirection.hpp>
39 #include <com/sun/star/chart2/data/LabelOrigin.hpp>
40 #include <com/sun/star/chart2/AxisType.hpp>
41 #include <com/sun/star/chart2/SymbolStyle.hpp>
42 #include <com/sun/star/chart2/Symbol.hpp>
43 #include <com/sun/star/drawing/LineStyle.hpp>
46 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
47 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
48 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
49 #include <rtl/ustrbuf.hxx>
51 #include <functional>
52 #include <algorithm>
53 #include <iterator>
54 #include <vector>
55 #include <set>
57 using namespace ::com::sun::star;
58 using namespace ::com::sun::star::chart2;
60 using ::com::sun::star::uno::Reference;
61 using ::com::sun::star::uno::Sequence;
62 using ::rtl::OUString;
63 using ::rtl::OUStringBuffer;
65 // ----------------------------------------
66 namespace
69 class lcl_MatchesRole : public ::std::unary_function< Reference< chart2::data::XLabeledDataSequence >, bool >
71 public:
72 explicit lcl_MatchesRole( const OUString & aRole, bool bMatchPrefix ) :
73 m_aRole( aRole ),
74 m_bMatchPrefix( bMatchPrefix )
77 bool operator () ( const Reference< chart2::data::XLabeledDataSequence > & xSeq ) const
79 if(!xSeq.is())
80 return false;
81 Reference< beans::XPropertySet > xProp( xSeq->getValues(), uno::UNO_QUERY );
82 OUString aRole;
84 if( m_bMatchPrefix )
85 return ( xProp.is() &&
86 (xProp->getPropertyValue(
87 OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )) ) >>= aRole ) &&
88 aRole.match( m_aRole ));
90 return ( xProp.is() &&
91 (xProp->getPropertyValue(
92 OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )) ) >>= aRole ) &&
93 m_aRole.equals( aRole ));
96 private:
97 OUString m_aRole;
98 bool m_bMatchPrefix;
101 Reference< chart2::data::XLabeledDataSequence > lcl_findLSequenceWithOnlyLabel(
102 const Reference< chart2::data::XDataSource > & xDataSource )
104 Reference< chart2::data::XLabeledDataSequence > xResult;
105 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( xDataSource->getDataSequences());
107 for( sal_Int32 i=0; i<aSequences.getLength(); ++i )
109 OSL_ENSURE( aSequences[i].is(), "empty LabeledDataSequence" );
110 // no values are set but a label exists
111 if( aSequences[i].is() &&
112 ( ! aSequences[i]->getValues().is() &&
113 aSequences[i]->getLabel().is()))
115 xResult.set( aSequences[i] );
116 break;
120 return xResult;
123 void lcl_getCooSysAndChartTypeOfSeries(
124 const Reference< chart2::XDataSeries > & xSeries,
125 const Reference< chart2::XDiagram > & xDiagram,
126 Reference< chart2::XCoordinateSystem > & xOutCooSys,
127 Reference< chart2::XChartType > & xOutChartType )
129 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY );
130 if( xCooSysCnt.is())
132 Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems());
133 for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
135 Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
136 Sequence< Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes());
137 for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx )
139 Reference< chart2::XDataSeriesContainer > xSeriesCnt( aChartTypes[nCTIdx], uno::UNO_QUERY );
140 if( xSeriesCnt.is())
142 Sequence< Reference< chart2::XDataSeries > > aSeries( xSeriesCnt->getDataSeries());
143 for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeries.getLength(); ++nSeriesIdx )
145 if( aSeries[nSeriesIdx] == xSeries )
147 xOutCooSys.set( aCooSysSeq[nCooSysIdx] );
148 xOutChartType.set( aChartTypes[nCTIdx] );
157 void lcl_insertOrDeleteDataLabelsToSeriesAndAllPoints( const Reference< chart2::XDataSeries >& xSeries, bool bInsert )
161 Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY );
162 if( xSeriesProperties.is() )
164 DataPointLabel aLabelAtSeries;
165 xSeriesProperties->getPropertyValue( C2U( "Label" ) ) >>= aLabelAtSeries;
166 aLabelAtSeries.ShowNumber = bInsert;
167 if( !bInsert )
169 aLabelAtSeries.ShowNumberInPercent = false;
170 aLabelAtSeries.ShowCategoryName = false;
172 xSeriesProperties->setPropertyValue( C2U( "Label" ), uno::makeAny( aLabelAtSeries ) );
173 uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
174 if( xSeriesProperties->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList )
176 for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
178 Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) );
179 if( xPointProp.is() )
181 DataPointLabel aLabel;
182 xPointProp->getPropertyValue( C2U( "Label" ) ) >>= aLabel;
183 aLabel.ShowNumber = bInsert;
184 if( !bInsert )
186 aLabel.ShowNumberInPercent = false;
187 aLabel.ShowCategoryName = false;
189 xPointProp->setPropertyValue( C2U( "Label" ), uno::makeAny( aLabel ) );
195 catch( uno::Exception &e)
197 ASSERT_EXCEPTION( e );
201 } // anonymous namespace
202 // ----------------------------------------
204 namespace chart
207 namespace DataSeriesHelper
210 OUString GetRole( const uno::Reference< chart2::data::XLabeledDataSequence >& xLabeledDataSequence )
212 OUString aRet;
213 if( xLabeledDataSequence.is() )
215 Reference< beans::XPropertySet > xProp( xLabeledDataSequence->getValues(), uno::UNO_QUERY );
216 if( xProp.is() )
217 xProp->getPropertyValue( C2U("Role") ) >>= aRet;
219 return aRet;
222 Reference< chart2::data::XLabeledDataSequence >
223 getDataSequenceByRole(
224 const Reference< chart2::data::XDataSource > & xSource, OUString aRole,
225 bool bMatchPrefix /* = false */ )
227 Reference< chart2::data::XLabeledDataSequence > aNoResult;
228 if( ! xSource.is())
229 return aNoResult;
230 Sequence< Reference< chart2::data::XLabeledDataSequence > > aLabeledSeq( xSource->getDataSequences());
232 const Reference< chart2::data::XLabeledDataSequence > * pBegin = aLabeledSeq.getConstArray();
233 const Reference< chart2::data::XLabeledDataSequence > * pEnd = pBegin + aLabeledSeq.getLength();
234 const Reference< chart2::data::XLabeledDataSequence > * pMatch =
235 ::std::find_if( pBegin, pEnd, lcl_MatchesRole( aRole, bMatchPrefix ));
237 if( pMatch != pEnd )
238 return *pMatch;
240 return aNoResult;
243 ::std::vector< Reference< chart2::data::XLabeledDataSequence > >
244 getAllDataSequencesByRole( const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aDataSequences,
245 OUString aRole, bool bMatchPrefix /* = false */ )
247 ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aResultVec;
248 ::std::remove_copy_if( aDataSequences.getConstArray(), aDataSequences.getConstArray() + aDataSequences.getLength(),
249 ::std::back_inserter( aResultVec ),
250 ::std::not1( lcl_MatchesRole( aRole, bMatchPrefix )));
251 return aResultVec;
254 Reference< chart2::data::XDataSource >
255 getDataSource( const Sequence< Reference< chart2::XDataSeries > > & aSeries )
257 ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aSeqVec;
259 for( sal_Int32 i = 0; i < aSeries.getLength(); ++i )
261 Reference< chart2::data::XDataSource > xSource( aSeries[ i ], uno::UNO_QUERY );
262 if( xSource.is())
264 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeq( xSource->getDataSequences());
265 ::std::copy( aSeq.getConstArray(), aSeq.getConstArray() + aSeq.getLength(),
266 ::std::back_inserter( aSeqVec ));
270 return Reference< chart2::data::XDataSource >(
271 new DataSource( ContainerHelper::ContainerToSequence( aSeqVec )));
274 namespace
276 OUString lcl_getDataSequenceLabel( const Reference< chart2::data::XDataSequence > & xSequence )
278 OUString aResult;
280 Reference< chart2::data::XTextualDataSequence > xTextSeq( xSequence, uno::UNO_QUERY );
281 if( xTextSeq.is())
283 Sequence< OUString > aSeq( xTextSeq->getTextualData());
285 const sal_Int32 nMax = aSeq.getLength() - 1;
286 OUString aVal;
287 OUStringBuffer aBuf;
289 for( sal_Int32 i = 0; i <= nMax; ++i )
291 aBuf.append( aSeq[i] );
292 if( i < nMax )
293 aBuf.append( sal_Unicode( ' ' ));
295 aResult = aBuf.makeStringAndClear();
297 else if( xSequence.is())
299 Sequence< uno::Any > aSeq( xSequence->getData());
301 const sal_Int32 nMax = aSeq.getLength() - 1;
302 OUString aVal;
303 OUStringBuffer aBuf;
304 double fNum = 0;
306 for( sal_Int32 i = 0; i <= nMax; ++i )
308 if( aSeq[i] >>= aVal )
310 aBuf.append( aVal );
311 if( i < nMax )
312 aBuf.append( sal_Unicode( ' ' ));
314 else if( aSeq[ i ] >>= fNum )
316 aBuf.append( fNum );
317 if( i < nMax )
318 aBuf.append( sal_Unicode( ' ' ));
321 aResult = aBuf.makeStringAndClear();
324 return aResult;
328 OUString getLabelForLabeledDataSequence(
329 const Reference< chart2::data::XLabeledDataSequence > & xLabeledSeq )
331 OUString aResult;
332 if( xLabeledSeq.is())
334 Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getLabel());
335 if( xSeq.is() )
336 aResult = lcl_getDataSequenceLabel( xSeq );
337 if( !xSeq.is() || !aResult.getLength() )
339 // no label set or label content is empty -> use auto-generated one
340 Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues() );
341 if( xValueSeq.is() )
343 Sequence< OUString > aLabels( xValueSeq->generateLabel(
344 chart2::data::LabelOrigin_SHORT_SIDE ) );
345 // no labels returned is interpreted as: auto-generation not
346 // supported by sequence
347 if( aLabels.getLength() )
348 aResult=aLabels[0];
349 else
351 //todo?: maybe use the index of the series as name
352 //but as the index may change it would be better to have such a name persistent
353 //what is not possible at the moment
354 //--> maybe use the identifier as part of the name ...
355 aResult = lcl_getDataSequenceLabel( xValueSeq );
360 return aResult;
363 OUString getDataSeriesLabel(
364 const Reference< chart2::XDataSeries > & xSeries,
365 const OUString & rLabelSequenceRole )
367 OUString aResult;
369 Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
370 if( xSource.is())
372 Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
373 ::chart::DataSeriesHelper::getDataSequenceByRole( xSource, rLabelSequenceRole ));
374 if( xLabeledSeq.is())
375 aResult = getLabelForLabeledDataSequence( xLabeledSeq );
376 else
378 // special case: labeled data series with only a label and no values may
379 // serve as label
380 xLabeledSeq.set( lcl_findLSequenceWithOnlyLabel( xSource ));
381 if( xLabeledSeq.is())
383 Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getLabel());
384 if( xSeq.is())
385 aResult = lcl_getDataSequenceLabel( xSeq );
391 return aResult;
394 void setStackModeAtSeries(
395 const Sequence< Reference< chart2::XDataSeries > > & aSeries,
396 const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem,
397 StackMode eStackMode )
399 if( eStackMode == StackMode_AMBIGUOUS )
400 return;
402 const OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( "StackingDirection" ));
403 const uno::Any aPropValue = uno::makeAny(
404 ( (eStackMode == StackMode_Y_STACKED) ||
405 (eStackMode == StackMode_Y_STACKED_PERCENT) )
406 ? chart2::StackingDirection_Y_STACKING
407 : (eStackMode == StackMode_Z_STACKED )
408 ? chart2::StackingDirection_Z_STACKING
409 : chart2::StackingDirection_NO_STACKING );
411 std::set< sal_Int32 > aAxisIndexSet;
412 for( sal_Int32 i=0; i<aSeries.getLength(); ++i )
416 Reference< beans::XPropertySet > xProp( aSeries[i], uno::UNO_QUERY );
417 if( xProp.is() )
419 xProp->setPropertyValue( aPropName, aPropValue );
421 sal_Int32 nAxisIndex;
422 xProp->getPropertyValue( C2U("AttachedAxisIndex") ) >>= nAxisIndex;
423 aAxisIndexSet.insert(nAxisIndex);
426 catch( uno::Exception & ex )
428 ASSERT_EXCEPTION( ex );
432 if( xCorrespondingCoordinateSystem.is() &&
433 1 < xCorrespondingCoordinateSystem->getDimension() )
435 sal_Int32 nAxisIndexCount = aAxisIndexSet.size();
436 if( !nAxisIndexCount )
438 aAxisIndexSet.insert(0);
439 nAxisIndexCount = aAxisIndexSet.size();
442 for( ::std::set< sal_Int32 >::const_iterator aIt = aAxisIndexSet.begin();
443 aIt != aAxisIndexSet.end(); ++aIt )
445 sal_Int32 nAxisIndex = *aIt;
446 Reference< chart2::XAxis > xAxis(
447 xCorrespondingCoordinateSystem->getAxisByDimension( 1, nAxisIndex ));
448 if( xAxis.is())
450 sal_Bool bPercent = (eStackMode == StackMode_Y_STACKED_PERCENT);
451 chart2::ScaleData aScaleData = xAxis->getScaleData();
453 if( bPercent != (aScaleData.AxisType==chart2::AxisType::PERCENT) )
455 if( bPercent )
456 aScaleData.AxisType = chart2::AxisType::PERCENT;
457 else
458 aScaleData.AxisType = chart2::AxisType::REALNUMBER;
459 xAxis->setScaleData( aScaleData );
466 sal_Int32 getAttachedAxisIndex( const Reference< chart2::XDataSeries > & xSeries )
468 sal_Int32 nRet = 0;
471 Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY );
472 if( xProp.is() )
474 xProp->getPropertyValue( C2U("AttachedAxisIndex") ) >>= nRet;
477 catch( uno::Exception & ex )
479 ASSERT_EXCEPTION( ex );
481 return nRet;
484 sal_Int32 getNumberFormatKeyFromAxis(
485 const Reference< chart2::XDataSeries > & xSeries,
486 const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem,
487 sal_Int32 nDimensionIndex,
488 sal_Int32 nAxisIndex /* = -1 */ )
490 sal_Int32 nResult = 0;
491 if( nAxisIndex == -1 )
492 nAxisIndex = getAttachedAxisIndex( xSeries );
495 Reference< beans::XPropertySet > xAxisProp(
496 xCorrespondingCoordinateSystem->getAxisByDimension( nDimensionIndex, nAxisIndex ), uno::UNO_QUERY );
497 if( xAxisProp.is())
498 xAxisProp->getPropertyValue( C2U("NumberFormat")) >>= nResult;
500 catch( const uno::Exception & ex )
502 ASSERT_EXCEPTION( ex );
505 return nResult;
508 Reference< chart2::XCoordinateSystem > getCoordinateSystemOfSeries(
509 const Reference< chart2::XDataSeries > & xSeries,
510 const Reference< chart2::XDiagram > & xDiagram )
512 Reference< chart2::XCoordinateSystem > xResult;
513 Reference< chart2::XChartType > xDummy;
514 lcl_getCooSysAndChartTypeOfSeries( xSeries, xDiagram, xResult, xDummy );
516 return xResult;
519 Reference< chart2::XChartType > getChartTypeOfSeries(
520 const Reference< chart2::XDataSeries > & xSeries,
521 const Reference< chart2::XDiagram > & xDiagram )
523 Reference< chart2::XChartType > xResult;
524 Reference< chart2::XCoordinateSystem > xDummy;
525 lcl_getCooSysAndChartTypeOfSeries( xSeries, xDiagram, xDummy, xResult );
527 return xResult;
530 void deleteSeries(
531 const Reference< chart2::XDataSeries > & xSeries,
532 const Reference< chart2::XChartType > & xChartType )
536 Reference< chart2::XDataSeriesContainer > xSeriesCnt( xChartType, uno::UNO_QUERY_THROW );
537 ::std::vector< Reference< chart2::XDataSeries > > aSeries(
538 ContainerHelper::SequenceToVector( xSeriesCnt->getDataSeries()));
539 ::std::vector< Reference< chart2::XDataSeries > >::iterator aIt =
540 ::std::find( aSeries.begin(), aSeries.end(), xSeries );
541 if( aIt != aSeries.end())
543 aSeries.erase( aIt );
544 xSeriesCnt->setDataSeries( ContainerHelper::ContainerToSequence( aSeries ));
547 catch( uno::Exception & ex )
549 ASSERT_EXCEPTION( ex );
553 void switchSymbolsOnOrOff( const Reference< beans::XPropertySet > & xSeriesProperties,
554 bool bSymbolsOn, sal_Int32 nSeriesIndex )
556 if( !xSeriesProperties.is() )
557 return;
559 chart2::Symbol aSymbProp;
560 if( (xSeriesProperties->getPropertyValue( C2U( "Symbol" )) >>= aSymbProp ) )
562 if( !bSymbolsOn )
563 aSymbProp.Style = chart2::SymbolStyle_NONE;
564 else if( aSymbProp.Style == chart2::SymbolStyle_NONE )
566 aSymbProp.Style = chart2::SymbolStyle_STANDARD;
567 aSymbProp.StandardSymbol = nSeriesIndex;
569 xSeriesProperties->setPropertyValue( C2U( "Symbol" ), uno::makeAny( aSymbProp ));
571 //todo: check attributed data points
574 void switchLinesOnOrOff( const Reference< beans::XPropertySet > & xSeriesProperties, bool bLinesOn )
576 if( !xSeriesProperties.is() )
577 return;
579 if( bLinesOn )
581 // keep line-styles that are not NONE
582 drawing::LineStyle eLineStyle;
583 if( (xSeriesProperties->getPropertyValue( C2U( "LineStyle" )) >>= eLineStyle ) &&
584 eLineStyle == drawing::LineStyle_NONE )
586 xSeriesProperties->setPropertyValue( C2U( "LineStyle" ), uno::makeAny( drawing::LineStyle_SOLID ) );
589 else
590 xSeriesProperties->setPropertyValue( C2U( "LineStyle" ), uno::makeAny( drawing::LineStyle_NONE ) );
593 void makeLinesThickOrThin( const Reference< beans::XPropertySet > & xSeriesProperties, bool bThick )
595 if( !xSeriesProperties.is() )
596 return;
598 sal_Int32 nNewValue = bThick ? 80 : 0;
599 sal_Int32 nOldValue = 0;
600 if( (xSeriesProperties->getPropertyValue( C2U( "LineWidth" )) >>= nOldValue ) &&
601 nOldValue != nNewValue )
603 if( !(bThick && nOldValue>0))
604 xSeriesProperties->setPropertyValue( C2U( "LineWidth" ), uno::makeAny( nNewValue ) );
608 void setPropertyAlsoToAllAttributedDataPoints( const Reference< chart2::XDataSeries >& xSeries,
609 const OUString& rPropertyName, const uno::Any& rPropertyValue )
611 Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY );
612 if( !xSeriesProperties.is() )
613 return;
615 xSeriesProperties->setPropertyValue( rPropertyName, rPropertyValue );
616 uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
617 if( xSeriesProperties->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList )
619 for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
621 Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) );
622 if(!xPointProp.is())
623 continue;
624 xPointProp->setPropertyValue( rPropertyName, rPropertyValue );
629 bool hasAttributedDataPointDifferentValue( const Reference< chart2::XDataSeries >& xSeries,
630 const OUString& rPropertyName, const uno::Any& rPropertyValue )
632 Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY );
633 if( !xSeriesProperties.is() )
634 return false;
636 uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
637 if( xSeriesProperties->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList )
639 for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
641 Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) );
642 if(!xPointProp.is())
643 continue;
644 uno::Any aPointValue( xPointProp->getPropertyValue( rPropertyName ) );
645 if( !( rPropertyValue==aPointValue ) )
646 return true;
649 return false;
652 bool areAllSeriesAttachedToSameAxis( const uno::Reference< chart2::XChartType >& xChartType, sal_Int32 & rOutAxisIndex )
656 uno::Reference< chart2::XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY_THROW );
657 uno::Sequence< uno::Reference< chart2::XDataSeries > > aSeriesSeq( xDataSeriesContainer->getDataSeries());
659 const sal_Int32 nSeriesCount( aSeriesSeq.getLength());
660 // AxisIndex can only be 0 or 1
661 sal_Int32 nSeriesAtFirstAxis = 0;
662 sal_Int32 nSeriesAtSecondAxis = 0;
664 for( sal_Int32 nI = 0; nI < nSeriesCount; ++nI )
666 uno::Reference< chart2::XDataSeries > xSeries( aSeriesSeq[nI], uno::UNO_QUERY );
667 sal_Int32 nAxisIndex = DataSeriesHelper::getAttachedAxisIndex( xSeries );
668 if( nAxisIndex == 0 )
669 ++nSeriesAtFirstAxis;
670 else if( nAxisIndex == 1 )
671 ++nSeriesAtSecondAxis;
673 OSL_ENSURE( nSeriesAtFirstAxis + nSeriesAtSecondAxis == nSeriesCount, "Invalid axis index found" );
675 if( nSeriesAtFirstAxis == nSeriesCount )
676 rOutAxisIndex = 0;
677 else if( nSeriesAtSecondAxis == nSeriesCount )
678 rOutAxisIndex = 1;
680 return ( nSeriesAtFirstAxis == nSeriesCount ||
681 nSeriesAtSecondAxis == nSeriesCount );
683 catch( const uno::Exception & ex )
685 ASSERT_EXCEPTION( ex );
686 return false;
690 namespace
693 bool lcl_SequenceHasUnhiddenData( const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
695 if( !xDataSequence.is() )
696 return false;
697 uno::Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY );
698 if( xProp.is() )
700 uno::Sequence< sal_Int32 > aHiddenValues;
703 xProp->getPropertyValue( C2U( "HiddenValues" ) ) >>= aHiddenValues;
704 if( !aHiddenValues.getLength() )
705 return true;
707 catch( uno::Exception& e )
709 (void)e; // avoid warning
710 return true;
713 if( xDataSequence->getData().getLength() )
714 return true;
715 return false;
720 bool hasUnhiddenData( const uno::Reference< chart2::XDataSeries >& xSeries )
722 uno::Reference< chart2::data::XDataSource > xDataSource =
723 uno::Reference< chart2::data::XDataSource >( xSeries, uno::UNO_QUERY );
725 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aDataSequences = xDataSource->getDataSequences();
727 for(sal_Int32 nN = aDataSequences.getLength();nN--;)
729 if( !aDataSequences[nN].is() )
730 continue;
731 if( lcl_SequenceHasUnhiddenData( aDataSequences[nN]->getValues() ) )
732 return true;
733 if( lcl_SequenceHasUnhiddenData( aDataSequences[nN]->getLabel() ) )
734 return true;
736 return false;
739 struct lcl_LessIndex
741 inline bool operator() ( const sal_Int32& first, const sal_Int32& second )
743 return ( first < second );
747 sal_Int32 translateIndexFromHiddenToFullSequence( sal_Int32 nIndex, const Reference< chart2::data::XDataSequence >& xDataSequence, bool bTranslate )
749 if( !bTranslate )
750 return nIndex;
754 uno::Reference<beans::XPropertySet> xProp( xDataSequence, uno::UNO_QUERY );
755 if( xProp.is())
757 Sequence<sal_Int32> aHiddenIndicesSeq;
758 xProp->getPropertyValue( C2U("HiddenValues") ) >>= aHiddenIndicesSeq;
759 if( aHiddenIndicesSeq.getLength() )
761 ::std::vector< sal_Int32 > aHiddenIndices( ContainerHelper::SequenceToVector( aHiddenIndicesSeq ) );
762 ::std::sort( aHiddenIndices.begin(), aHiddenIndices.end(), lcl_LessIndex() );
764 sal_Int32 nHiddenCount = static_cast<sal_Int32>(aHiddenIndices.size());
765 for( sal_Int32 nN = 0; nN < nHiddenCount; ++nN)
767 if( aHiddenIndices[nN] <= nIndex )
768 nIndex += 1;
769 else
770 break;
775 catch (const beans::UnknownPropertyException&)
778 return nIndex;
781 bool hasDataLabelsAtSeries( const Reference< chart2::XDataSeries >& xSeries )
783 bool bRet = false;
786 Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY );
787 if( xProp.is() )
789 DataPointLabel aLabel;
790 if( (xProp->getPropertyValue( C2U( "Label" ) ) >>= aLabel) )
791 bRet = aLabel.ShowNumber || aLabel.ShowNumberInPercent || aLabel.ShowCategoryName;
794 catch( uno::Exception &e)
796 ASSERT_EXCEPTION( e );
798 return bRet;
801 bool hasDataLabelsAtPoints( const Reference< chart2::XDataSeries >& xSeries )
803 bool bRet = false;
806 Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY );
807 if( xSeriesProperties.is() )
809 uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
810 if( xSeriesProperties->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList )
812 for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
814 Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) );
815 if( xPointProp.is() )
817 DataPointLabel aLabel;
818 if( (xPointProp->getPropertyValue( C2U( "Label" ) ) >>= aLabel) )
819 bRet = aLabel.ShowNumber || aLabel.ShowNumberInPercent || aLabel.ShowCategoryName;
820 if( bRet )
821 break;
827 catch( uno::Exception &e)
829 ASSERT_EXCEPTION( e );
831 return bRet;
834 bool hasDataLabelAtPoint( const Reference< chart2::XDataSeries >& xSeries, sal_Int32 nPointIndex )
836 bool bRet = false;
839 Reference< beans::XPropertySet > xProp;
840 Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY );
841 if( xSeriesProperties.is() )
843 uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
844 if( xSeriesProperties->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList )
846 ::std::vector< sal_Int32 > aIndices( ContainerHelper::SequenceToVector( aAttributedDataPointIndexList ) );
847 ::std::vector< sal_Int32 >::iterator aIt = ::std::find( aIndices.begin(), aIndices.end(), nPointIndex );
848 if( aIt != aIndices.end())
849 xProp = xSeries->getDataPointByIndex(nPointIndex);
850 else
851 xProp = xSeriesProperties;
853 if( xProp.is() )
855 DataPointLabel aLabel;
856 if( (xProp->getPropertyValue( C2U( "Label" ) ) >>= aLabel) )
857 bRet = aLabel.ShowNumber || aLabel.ShowNumberInPercent || aLabel.ShowCategoryName;
861 catch( uno::Exception &e)
863 ASSERT_EXCEPTION( e );
865 return bRet;
868 void insertDataLabelsToSeriesAndAllPoints( const Reference< chart2::XDataSeries >& xSeries )
870 lcl_insertOrDeleteDataLabelsToSeriesAndAllPoints( xSeries, true /*bInsert*/ );
873 void deleteDataLabelsFromSeriesAndAllPoints( const Reference< chart2::XDataSeries >& xSeries )
875 lcl_insertOrDeleteDataLabelsToSeriesAndAllPoints( xSeries, false /*bInsert*/ );
879 void insertDataLabelToPoint( const Reference< beans::XPropertySet >& xPointProp )
883 if( xPointProp.is() )
885 DataPointLabel aLabel;
886 xPointProp->getPropertyValue( C2U( "Label" ) ) >>= aLabel;
887 aLabel.ShowNumber = true;
888 xPointProp->setPropertyValue( C2U( "Label" ), uno::makeAny( aLabel ) );
891 catch( uno::Exception &e)
893 ASSERT_EXCEPTION( e );
897 void deleteDataLabelsFromPoint( const Reference< beans::XPropertySet >& xPointProp )
901 if( xPointProp.is() )
903 DataPointLabel aLabel;
904 xPointProp->getPropertyValue( C2U( "Label" ) ) >>= aLabel;
905 aLabel.ShowNumber = false;
906 aLabel.ShowNumberInPercent = false;
907 aLabel.ShowCategoryName = false;
908 xPointProp->setPropertyValue( C2U( "Label" ), uno::makeAny( aLabel ) );
911 catch( uno::Exception &e)
913 ASSERT_EXCEPTION( e );
917 } // namespace DataSeriesHelper
918 } // namespace chart