update dev300-m58
[ooovba.git] / chart2 / source / tools / DataSeriesHelper.cxx
blob5d27ec144a84b13331bfe20e9086cd1455a7d48f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: DataSeriesHelper.cxx,v $
10 * $Revision: 1.11.24.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_chart2.hxx"
33 #include "DataSeriesHelper.hxx"
34 #include "DiagramHelper.hxx"
35 #include "DataSource.hxx"
36 #include "macros.hxx"
37 #include "ContainerHelper.hxx"
38 #include <com/sun/star/beans/XPropertySet.hpp>
39 #include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
40 #include <com/sun/star/chart2/StackingDirection.hpp>
41 #include <com/sun/star/chart2/data/LabelOrigin.hpp>
42 #include <com/sun/star/chart2/AxisType.hpp>
43 #include <com/sun/star/chart2/SymbolStyle.hpp>
44 #include <com/sun/star/chart2/Symbol.hpp>
45 #include <com/sun/star/drawing/LineStyle.hpp>
48 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
49 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
50 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
51 #include <rtl/ustrbuf.hxx>
53 #include <functional>
54 #include <algorithm>
55 #include <iterator>
56 #include <vector>
57 #include <set>
59 using namespace ::com::sun::star;
61 using ::com::sun::star::uno::Reference;
62 using ::com::sun::star::uno::Sequence;
63 using ::rtl::OUString;
64 using ::rtl::OUStringBuffer;
66 // ----------------------------------------
67 namespace
70 class lcl_MatchesRole : public ::std::unary_function< Reference< chart2::data::XLabeledDataSequence >, bool >
72 public:
73 explicit lcl_MatchesRole( const OUString & aRole, bool bMatchPrefix ) :
74 m_aRole( aRole ),
75 m_bMatchPrefix( bMatchPrefix )
78 bool operator () ( const Reference< chart2::data::XLabeledDataSequence > & xSeq ) const
80 if(!xSeq.is())
81 return false;
82 Reference< beans::XPropertySet > xProp( xSeq->getValues(), uno::UNO_QUERY );
83 OUString aRole;
85 if( m_bMatchPrefix )
86 return ( xProp.is() &&
87 (xProp->getPropertyValue(
88 OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )) ) >>= aRole ) &&
89 aRole.match( m_aRole ));
91 return ( xProp.is() &&
92 (xProp->getPropertyValue(
93 OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )) ) >>= aRole ) &&
94 m_aRole.equals( aRole ));
97 private:
98 OUString m_aRole;
99 bool m_bMatchPrefix;
102 Reference< chart2::data::XLabeledDataSequence > lcl_findLSequenceWithOnlyLabel(
103 const Reference< chart2::data::XDataSource > & xDataSource )
105 Reference< chart2::data::XLabeledDataSequence > xResult;
106 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( xDataSource->getDataSequences());
108 for( sal_Int32 i=0; i<aSequences.getLength(); ++i )
110 OSL_ENSURE( aSequences[i].is(), "empty LabeledDataSequence" );
111 // no values are set but a label exists
112 if( aSequences[i].is() &&
113 ( ! aSequences[i]->getValues().is() &&
114 aSequences[i]->getLabel().is()))
116 xResult.set( aSequences[i] );
117 break;
121 return xResult;
124 void lcl_getCooSysAndChartTypeOfSeries(
125 const Reference< chart2::XDataSeries > & xSeries,
126 const Reference< chart2::XDiagram > & xDiagram,
127 Reference< chart2::XCoordinateSystem > & xOutCooSys,
128 Reference< chart2::XChartType > & xOutChartType )
130 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY );
131 if( xCooSysCnt.is())
133 Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems());
134 for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
136 Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
137 Sequence< Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes());
138 for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx )
140 Reference< chart2::XDataSeriesContainer > xSeriesCnt( aChartTypes[nCTIdx], uno::UNO_QUERY );
141 if( xSeriesCnt.is())
143 Sequence< Reference< chart2::XDataSeries > > aSeries( xSeriesCnt->getDataSeries());
144 for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeries.getLength(); ++nSeriesIdx )
146 if( aSeries[nSeriesIdx] == xSeries )
148 xOutCooSys.set( aCooSysSeq[nCooSysIdx] );
149 xOutChartType.set( aChartTypes[nCTIdx] );
158 } // anonymous namespace
159 // ----------------------------------------
161 namespace chart
164 namespace DataSeriesHelper
167 OUString GetRole( const uno::Reference< chart2::data::XLabeledDataSequence >& xLabeledDataSequence )
169 OUString aRet;
170 if( xLabeledDataSequence.is() )
172 Reference< beans::XPropertySet > xProp( xLabeledDataSequence->getValues(), uno::UNO_QUERY );
173 if( xProp.is() )
174 xProp->getPropertyValue( C2U("Role") ) >>= aRet;
176 return aRet;
179 Reference< chart2::data::XLabeledDataSequence >
180 getDataSequenceByRole(
181 const Reference< chart2::data::XDataSource > & xSource, OUString aRole,
182 bool bMatchPrefix /* = false */ )
184 Reference< chart2::data::XLabeledDataSequence > aNoResult;
185 if( ! xSource.is())
186 return aNoResult;
187 Sequence< Reference< chart2::data::XLabeledDataSequence > > aLabeledSeq( xSource->getDataSequences());
189 const Reference< chart2::data::XLabeledDataSequence > * pBegin = aLabeledSeq.getConstArray();
190 const Reference< chart2::data::XLabeledDataSequence > * pEnd = pBegin + aLabeledSeq.getLength();
191 const Reference< chart2::data::XLabeledDataSequence > * pMatch =
192 ::std::find_if( pBegin, pEnd, lcl_MatchesRole( aRole, bMatchPrefix ));
194 if( pMatch != pEnd )
195 return *pMatch;
197 return aNoResult;
200 ::std::vector< Reference< chart2::data::XLabeledDataSequence > >
201 getAllDataSequencesByRole( const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aDataSequences,
202 OUString aRole, bool bMatchPrefix /* = false */ )
204 ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aResultVec;
205 ::std::remove_copy_if( aDataSequences.getConstArray(), aDataSequences.getConstArray() + aDataSequences.getLength(),
206 ::std::back_inserter( aResultVec ),
207 ::std::not1( lcl_MatchesRole( aRole, bMatchPrefix )));
208 return aResultVec;
211 Reference< chart2::data::XDataSource >
212 getDataSource( const Sequence< Reference< chart2::XDataSeries > > & aSeries )
214 ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aSeqVec;
216 for( sal_Int32 i = 0; i < aSeries.getLength(); ++i )
218 Reference< chart2::data::XDataSource > xSource( aSeries[ i ], uno::UNO_QUERY );
219 if( xSource.is())
221 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeq( xSource->getDataSequences());
222 ::std::copy( aSeq.getConstArray(), aSeq.getConstArray() + aSeq.getLength(),
223 ::std::back_inserter( aSeqVec ));
227 return Reference< chart2::data::XDataSource >(
228 new DataSource( ContainerHelper::ContainerToSequence( aSeqVec )));
231 namespace
233 OUString lcl_getDataSequenceLabel( const Reference< chart2::data::XDataSequence > & xSequence )
235 OUString aResult;
237 Reference< chart2::data::XTextualDataSequence > xTextSeq( xSequence, uno::UNO_QUERY );
238 if( xTextSeq.is())
240 Sequence< OUString > aSeq( xTextSeq->getTextualData());
242 const sal_Int32 nMax = aSeq.getLength() - 1;
243 OUString aVal;
244 OUStringBuffer aBuf;
246 for( sal_Int32 i = 0; i <= nMax; ++i )
248 aBuf.append( aSeq[i] );
249 if( i < nMax )
250 aBuf.append( sal_Unicode( ' ' ));
252 aResult = aBuf.makeStringAndClear();
254 else if( xSequence.is())
256 Sequence< uno::Any > aSeq( xSequence->getData());
258 const sal_Int32 nMax = aSeq.getLength() - 1;
259 OUString aVal;
260 OUStringBuffer aBuf;
261 double fNum = 0;
263 for( sal_Int32 i = 0; i <= nMax; ++i )
265 if( aSeq[i] >>= aVal )
267 aBuf.append( aVal );
268 if( i < nMax )
269 aBuf.append( sal_Unicode( ' ' ));
271 else if( aSeq[ i ] >>= fNum )
273 aBuf.append( fNum );
274 if( i < nMax )
275 aBuf.append( sal_Unicode( ' ' ));
278 aResult = aBuf.makeStringAndClear();
281 return aResult;
285 OUString getLabelForLabeledDataSequence(
286 const Reference< chart2::data::XLabeledDataSequence > & xLabeledSeq )
288 OUString aResult;
289 if( xLabeledSeq.is())
291 Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getLabel());
292 if( xSeq.is() )
293 aResult = lcl_getDataSequenceLabel( xSeq );
294 if( !xSeq.is() || !aResult.getLength() )
296 // no label set or label content is empty -> use auto-generated one
297 Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues() );
298 if( xValueSeq.is() )
300 Sequence< OUString > aLabels( xValueSeq->generateLabel(
301 chart2::data::LabelOrigin_SHORT_SIDE ) );
302 // no labels returned is interpreted as: auto-generation not
303 // supported by sequence
304 if( aLabels.getLength() )
305 aResult=aLabels[0];
306 else
308 //todo?: maybe use the index of the series as name
309 //but as the index may change it would be better to have such a name persistent
310 //what is not possible at the moment
311 //--> maybe use the identifier as part of the name ...
312 aResult = lcl_getDataSequenceLabel( xValueSeq );
317 return aResult;
320 OUString getDataSeriesLabel(
321 const Reference< chart2::XDataSeries > & xSeries,
322 const OUString & rLabelSequenceRole )
324 OUString aResult;
326 Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
327 if( xSource.is())
329 Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
330 ::chart::DataSeriesHelper::getDataSequenceByRole( xSource, rLabelSequenceRole ));
331 if( xLabeledSeq.is())
332 aResult = getLabelForLabeledDataSequence( xLabeledSeq );
333 else
335 // special case: labeled data series with only a label and no values may
336 // serve as label
337 xLabeledSeq.set( lcl_findLSequenceWithOnlyLabel( xSource ));
338 if( xLabeledSeq.is())
340 Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getLabel());
341 if( xSeq.is())
342 aResult = lcl_getDataSequenceLabel( xSeq );
348 return aResult;
351 void setStackModeAtSeries(
352 const Sequence< Reference< chart2::XDataSeries > > & aSeries,
353 const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem,
354 StackMode eStackMode )
356 if( eStackMode == StackMode_AMBIGUOUS )
357 return;
359 const OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( "StackingDirection" ));
360 const uno::Any aPropValue = uno::makeAny(
361 ( (eStackMode == StackMode_Y_STACKED) ||
362 (eStackMode == StackMode_Y_STACKED_PERCENT) )
363 ? chart2::StackingDirection_Y_STACKING
364 : (eStackMode == StackMode_Z_STACKED )
365 ? chart2::StackingDirection_Z_STACKING
366 : chart2::StackingDirection_NO_STACKING );
368 std::set< sal_Int32 > aAxisIndexSet;
369 for( sal_Int32 i=0; i<aSeries.getLength(); ++i )
373 Reference< beans::XPropertySet > xProp( aSeries[i], uno::UNO_QUERY );
374 if( xProp.is() )
376 xProp->setPropertyValue( aPropName, aPropValue );
378 sal_Int32 nAxisIndex;
379 xProp->getPropertyValue( C2U("AttachedAxisIndex") ) >>= nAxisIndex;
380 aAxisIndexSet.insert(nAxisIndex);
383 catch( uno::Exception & ex )
385 ASSERT_EXCEPTION( ex );
389 if( xCorrespondingCoordinateSystem.is() &&
390 1 < xCorrespondingCoordinateSystem->getDimension() )
392 sal_Int32 nAxisIndexCount = aAxisIndexSet.size();
393 if( !nAxisIndexCount )
395 aAxisIndexSet.insert(0);
396 nAxisIndexCount = aAxisIndexSet.size();
399 for( ::std::set< sal_Int32 >::const_iterator aIt = aAxisIndexSet.begin();
400 aIt != aAxisIndexSet.end(); ++aIt )
402 sal_Int32 nAxisIndex = *aIt;
403 Reference< chart2::XAxis > xAxis(
404 xCorrespondingCoordinateSystem->getAxisByDimension( 1, nAxisIndex ));
405 if( xAxis.is())
407 sal_Bool bPercent = (eStackMode == StackMode_Y_STACKED_PERCENT);
408 chart2::ScaleData aScaleData = xAxis->getScaleData();
410 if( bPercent != (aScaleData.AxisType==chart2::AxisType::PERCENT) )
412 if( bPercent )
413 aScaleData.AxisType = chart2::AxisType::PERCENT;
414 else
415 aScaleData.AxisType = chart2::AxisType::REALNUMBER;
416 xAxis->setScaleData( aScaleData );
423 sal_Int32 getAttachedAxisIndex( const Reference< chart2::XDataSeries > & xSeries )
425 sal_Int32 nRet = 0;
428 Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY );
429 if( xProp.is() )
431 xProp->getPropertyValue( C2U("AttachedAxisIndex") ) >>= nRet;
434 catch( uno::Exception & ex )
436 ASSERT_EXCEPTION( ex );
438 return nRet;
441 sal_Int32 getNumberFormatKeyFromAxis(
442 const Reference< chart2::XDataSeries > & xSeries,
443 const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem,
444 sal_Int32 nDimensionIndex,
445 sal_Int32 nAxisIndex /* = -1 */ )
447 sal_Int32 nResult = 0;
448 if( nAxisIndex == -1 )
449 nAxisIndex = getAttachedAxisIndex( xSeries );
452 Reference< beans::XPropertySet > xAxisProp(
453 xCorrespondingCoordinateSystem->getAxisByDimension( nDimensionIndex, nAxisIndex ), uno::UNO_QUERY );
454 if( xAxisProp.is())
455 xAxisProp->getPropertyValue( C2U("NumberFormat")) >>= nResult;
457 catch( const uno::Exception & ex )
459 ASSERT_EXCEPTION( ex );
462 return nResult;
465 Reference< chart2::XCoordinateSystem > getCoordinateSystemOfSeries(
466 const Reference< chart2::XDataSeries > & xSeries,
467 const Reference< chart2::XDiagram > & xDiagram )
469 Reference< chart2::XCoordinateSystem > xResult;
470 Reference< chart2::XChartType > xDummy;
471 lcl_getCooSysAndChartTypeOfSeries( xSeries, xDiagram, xResult, xDummy );
473 return xResult;
476 Reference< chart2::XChartType > getChartTypeOfSeries(
477 const Reference< chart2::XDataSeries > & xSeries,
478 const Reference< chart2::XDiagram > & xDiagram )
480 Reference< chart2::XChartType > xResult;
481 Reference< chart2::XCoordinateSystem > xDummy;
482 lcl_getCooSysAndChartTypeOfSeries( xSeries, xDiagram, xDummy, xResult );
484 return xResult;
487 void deleteSeries(
488 const Reference< chart2::XDataSeries > & xSeries,
489 const Reference< chart2::XChartType > & xChartType )
493 Reference< chart2::XDataSeriesContainer > xSeriesCnt( xChartType, uno::UNO_QUERY_THROW );
494 ::std::vector< Reference< chart2::XDataSeries > > aSeries(
495 ContainerHelper::SequenceToVector( xSeriesCnt->getDataSeries()));
496 ::std::vector< Reference< chart2::XDataSeries > >::iterator aIt =
497 ::std::find( aSeries.begin(), aSeries.end(), xSeries );
498 if( aIt != aSeries.end())
500 aSeries.erase( aIt );
501 xSeriesCnt->setDataSeries( ContainerHelper::ContainerToSequence( aSeries ));
504 catch( uno::Exception & ex )
506 ASSERT_EXCEPTION( ex );
510 void switchSymbolsOnOrOff( const Reference< beans::XPropertySet > & xSeriesProperties,
511 bool bSymbolsOn, sal_Int32 nSeriesIndex )
513 if( !xSeriesProperties.is() )
514 return;
516 chart2::Symbol aSymbProp;
517 if( (xSeriesProperties->getPropertyValue( C2U( "Symbol" )) >>= aSymbProp ) )
519 if( !bSymbolsOn )
520 aSymbProp.Style = chart2::SymbolStyle_NONE;
521 else if( aSymbProp.Style == chart2::SymbolStyle_NONE )
523 aSymbProp.Style = chart2::SymbolStyle_STANDARD;
524 aSymbProp.StandardSymbol = nSeriesIndex;
526 xSeriesProperties->setPropertyValue( C2U( "Symbol" ), uno::makeAny( aSymbProp ));
528 //todo: check attributed data points
531 void switchLinesOnOrOff( const Reference< beans::XPropertySet > & xSeriesProperties, bool bLinesOn )
533 if( !xSeriesProperties.is() )
534 return;
536 if( bLinesOn )
538 // keep line-styles that are not NONE
539 drawing::LineStyle eLineStyle;
540 if( (xSeriesProperties->getPropertyValue( C2U( "LineStyle" )) >>= eLineStyle ) &&
541 eLineStyle == drawing::LineStyle_NONE )
543 xSeriesProperties->setPropertyValue( C2U( "LineStyle" ), uno::makeAny( drawing::LineStyle_SOLID ) );
546 else
547 xSeriesProperties->setPropertyValue( C2U( "LineStyle" ), uno::makeAny( drawing::LineStyle_NONE ) );
550 void makeLinesThickOrThin( const Reference< beans::XPropertySet > & xSeriesProperties, bool bThick )
552 if( !xSeriesProperties.is() )
553 return;
555 sal_Int32 nNewValue = bThick ? 88 : 0;
556 sal_Int32 nOldValue = 0;
557 if( (xSeriesProperties->getPropertyValue( C2U( "LineWidth" )) >>= nOldValue ) &&
558 nOldValue != nNewValue )
560 if( !(bThick && nOldValue>0))
561 xSeriesProperties->setPropertyValue( C2U( "LineWidth" ), uno::makeAny( nNewValue ) );
565 void setPropertyAlsoToAllAttributedDataPoints( const Reference< chart2::XDataSeries >& xSeries,
566 const OUString& rPropertyName, const uno::Any& rPropertyValue )
568 Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY );
569 if( !xSeriesProperties.is() )
570 return;
572 xSeriesProperties->setPropertyValue( rPropertyName, rPropertyValue );
573 uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
574 if( xSeriesProperties->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList )
576 for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
578 Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) );
579 if(!xPointProp.is())
580 continue;
581 xPointProp->setPropertyValue( rPropertyName, rPropertyValue );
586 bool hasAttributedDataPointDifferentValue( const Reference< chart2::XDataSeries >& xSeries,
587 const OUString& rPropertyName, const uno::Any& rPropertyValue )
589 Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY );
590 if( !xSeriesProperties.is() )
591 return false;
593 uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
594 if( xSeriesProperties->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList )
596 for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
598 Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) );
599 if(!xPointProp.is())
600 continue;
601 uno::Any aPointValue( xPointProp->getPropertyValue( rPropertyName ) );
602 if( !( rPropertyValue==aPointValue ) )
603 return true;
606 return false;
609 bool areAllSeriesAttachedToSameAxis( const uno::Reference< chart2::XChartType >& xChartType, sal_Int32 & rOutAxisIndex )
613 uno::Reference< chart2::XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY_THROW );
614 uno::Sequence< uno::Reference< chart2::XDataSeries > > aSeriesSeq( xDataSeriesContainer->getDataSeries());
616 const sal_Int32 nSeriesCount( aSeriesSeq.getLength());
617 // AxisIndex can only be 0 or 1
618 sal_Int32 nSeriesAtFirstAxis = 0;
619 sal_Int32 nSeriesAtSecondAxis = 0;
621 for( sal_Int32 nI = 0; nI < nSeriesCount; ++nI )
623 uno::Reference< chart2::XDataSeries > xSeries( aSeriesSeq[nI], uno::UNO_QUERY );
624 sal_Int32 nAxisIndex = DataSeriesHelper::getAttachedAxisIndex( xSeries );
625 if( nAxisIndex == 0 )
626 ++nSeriesAtFirstAxis;
627 else if( nAxisIndex == 1 )
628 ++nSeriesAtSecondAxis;
630 OSL_ENSURE( nSeriesAtFirstAxis + nSeriesAtSecondAxis == nSeriesCount, "Invalid axis index found" );
632 if( nSeriesAtFirstAxis == nSeriesCount )
633 rOutAxisIndex = 0;
634 else if( nSeriesAtSecondAxis == nSeriesCount )
635 rOutAxisIndex = 1;
637 return ( nSeriesAtFirstAxis == nSeriesCount ||
638 nSeriesAtSecondAxis == nSeriesCount );
640 catch( const uno::Exception & ex )
642 ASSERT_EXCEPTION( ex );
643 return false;
647 namespace
650 bool lcl_SequenceHasUnhiddenData( const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
652 if( !xDataSequence.is() )
653 return false;
654 uno::Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY );
655 if( xProp.is() )
657 uno::Sequence< sal_Int32 > aHiddenValues;
660 xProp->getPropertyValue( C2U( "HiddenValues" ) ) >>= aHiddenValues;
661 if( !aHiddenValues.getLength() )
662 return true;
664 catch( uno::Exception& e )
666 (void)e; // avoid warning
667 return true;
670 if( xDataSequence->getData().getLength() )
671 return true;
672 return false;
677 bool hasUnhiddenData( const uno::Reference< chart2::XDataSeries >& xSeries )
679 uno::Reference< chart2::data::XDataSource > xDataSource =
680 uno::Reference< chart2::data::XDataSource >( xSeries, uno::UNO_QUERY );
682 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aDataSequences = xDataSource->getDataSequences();
684 for(sal_Int32 nN = aDataSequences.getLength();nN--;)
686 if( !aDataSequences[nN].is() )
687 continue;
688 if( lcl_SequenceHasUnhiddenData( aDataSequences[nN]->getValues() ) )
689 return true;
690 if( lcl_SequenceHasUnhiddenData( aDataSequences[nN]->getLabel() ) )
691 return true;
693 return false;
696 struct lcl_LessIndex
698 inline bool operator() ( const sal_Int32& first, const sal_Int32& second )
700 return ( first < second );
704 sal_Int32 translateIndexFromHiddenToFullSequence( sal_Int32 nIndex, const Reference< chart2::data::XDataSequence >& xDataSequence, bool bTranslate )
706 if( !bTranslate )
707 return nIndex;
711 uno::Reference<beans::XPropertySet> xProp( xDataSequence, uno::UNO_QUERY );
712 if( xProp.is())
714 Sequence<sal_Int32> aHiddenIndicesSeq;
715 xProp->getPropertyValue( C2U("HiddenValues") ) >>= aHiddenIndicesSeq;
716 if( aHiddenIndicesSeq.getLength() )
718 ::std::vector< sal_Int32 > aHiddenIndices( ContainerHelper::SequenceToVector( aHiddenIndicesSeq ) );
719 ::std::sort( aHiddenIndices.begin(), aHiddenIndices.end(), lcl_LessIndex() );
721 sal_Int32 nHiddenCount = static_cast<sal_Int32>(aHiddenIndices.size());
722 for( sal_Int32 nN = 0; nN < nHiddenCount; ++nN)
724 if( aHiddenIndices[nN] <= nIndex )
725 nIndex += 1;
726 else
727 break;
732 catch (const beans::UnknownPropertyException&)
735 return nIndex;
738 } // namespace DataSeriesHelper
739 } // namespace chart