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"
31 #include "ExplicitCategoriesProvider.hxx"
32 #include "DiagramHelper.hxx"
33 #include "CommonConverters.hxx"
34 #include "DataSourceHelper.hxx"
35 #include "ChartModelHelper.hxx"
36 #include "ContainerHelper.hxx"
39 //.............................................................................
42 //.............................................................................
44 using namespace ::com::sun::star
;
45 using namespace ::com::sun::star::chart2
;
46 using ::com::sun::star::uno::Reference
;
47 using ::com::sun::star::uno::Sequence
;
48 using ::rtl::OUString
;
52 ExplicitCategoriesProvider::ExplicitCategoriesProvider( const Reference
< chart2::XCoordinateSystem
>& xCooSysModel
53 , const uno::Reference
< frame::XModel
>& xChartModel
)
55 , m_xCooSysModel( xCooSysModel
)
56 , m_xOriginalCategories()
60 if( xCooSysModel
.is() )
62 uno::Reference
< XAxis
> xAxis( xCooSysModel
->getAxisByDimension(0,0) );
64 m_xOriginalCategories
= xAxis
->getScaleData().Categories
;
67 if( m_xOriginalCategories
.is() )
69 Reference
< chart2::XChartDocument
> xChartDoc( xChartModel
, uno::UNO_QUERY
);
72 uno::Reference
< data::XDataProvider
> xDataProvider( xChartDoc
->getDataProvider() );
74 if( xDataProvider
.is() )
76 OUString
aCatgoriesRange( DataSourceHelper::getRangeFromValues( m_xOriginalCategories
) );
77 const bool bFirstCellAsLabel
= false;
78 const bool bHasCategories
= false;
79 const uno::Sequence
< sal_Int32
> aSequenceMapping
;
81 uno::Reference
< data::XDataSource
> xColumnCategoriesSource( xDataProvider
->createDataSource(
82 DataSourceHelper::createArguments( aCatgoriesRange
, aSequenceMapping
, true /*bUseColumns*/
83 , bFirstCellAsLabel
, bHasCategories
) ) );
85 uno::Reference
< data::XDataSource
> xRowCategoriesSource( xDataProvider
->createDataSource(
86 DataSourceHelper::createArguments( aCatgoriesRange
, aSequenceMapping
, false /*bUseColumns*/
87 , bFirstCellAsLabel
, bHasCategories
) ) );
89 if( xColumnCategoriesSource
.is() && xRowCategoriesSource
.is() )
91 Sequence
< Reference
< data::XLabeledDataSequence
> > aColumns
= xColumnCategoriesSource
->getDataSequences();
92 Sequence
< Reference
< data::XLabeledDataSequence
> > aRows
= xRowCategoriesSource
->getDataSequences();
94 sal_Int32 nColumnCount
= aColumns
.getLength();
95 sal_Int32 nRowCount
= aRows
.getLength();
96 if( nColumnCount
>1 && nRowCount
>1 )
98 //we have complex categories
99 //->split them in the direction of the first series
100 //detect whether the first series is a row or a column
101 bool bSeriesUsesColumns
= true;
102 ::std::vector
< Reference
< XDataSeries
> > aSeries( ChartModelHelper::getDataSeries( xChartModel
) );
103 if( !aSeries
.empty() )
105 uno::Reference
< data::XDataSource
> xSeriesSource( aSeries
.front(), uno::UNO_QUERY
);
106 ::rtl::OUString aStringDummy
;
108 uno::Sequence
< sal_Int32
> aSeqDummy
;
109 DataSourceHelper::readArguments( xDataProvider
->detectArguments( xSeriesSource
),
110 aStringDummy
, aSeqDummy
, bSeriesUsesColumns
, bDummy
, bDummy
);
112 if( bSeriesUsesColumns
)
113 m_aSplitCategoriesList
=aColumns
;
115 m_aSplitCategoriesList
=aRows
;
120 if( !m_aSplitCategoriesList
.getLength() )
122 m_aSplitCategoriesList
.realloc(1);
123 m_aSplitCategoriesList
[0]=m_xOriginalCategories
;
127 catch( const uno::Exception
& ex
)
129 ASSERT_EXCEPTION( ex
);
133 ExplicitCategoriesProvider::~ExplicitCategoriesProvider()
137 const Sequence
< Reference
< data::XLabeledDataSequence
> >& ExplicitCategoriesProvider::getSplitCategoriesList()
139 return m_aSplitCategoriesList
;
142 bool ExplicitCategoriesProvider::hasComplexCategories() const
144 return m_aSplitCategoriesList
.getLength() > 1;
147 sal_Int32
ExplicitCategoriesProvider::getCategoryLevelCount() const
149 sal_Int32 nCount
= m_aSplitCategoriesList
.getLength();
155 std::vector
<sal_Int32
> lcl_getLimitingBorders( const std::vector
< ComplexCategory
>& rComplexCategories
)
157 std::vector
<sal_Int32
> aLimitingBorders
;
158 std::vector
< ComplexCategory
>::const_iterator
aIt( rComplexCategories
.begin() );
159 std::vector
< ComplexCategory
>::const_iterator
aEnd( rComplexCategories
.end() );
160 sal_Int32 nBorderIndex
= 0; /*border below the index*/
161 for( ; aIt
!= aEnd
; ++aIt
)
163 ComplexCategory
aComplexCategory(*aIt
);
164 nBorderIndex
+= aComplexCategory
.Count
;
165 aLimitingBorders
.push_back(nBorderIndex
);
167 return aLimitingBorders
;
170 uno::Sequence
< rtl::OUString
> lcl_DataToStringSequence( const uno::Reference
< data::XDataSequence
>& xDataSequence
)
172 uno::Sequence
< rtl::OUString
> aStrings
;
174 OSL_ASSERT( xDataSequence
.is());
175 if( !xDataSequence
.is() )
179 uno::Reference
< data::XTextualDataSequence
> xTextualDataSequence( xDataSequence
, uno::UNO_QUERY
);
180 if( xTextualDataSequence
.is() )
182 aStrings
= xTextualDataSequence
->getTextualData();
186 uno::Sequence
< uno::Any
> aValues
= xDataSequence
->getData();
187 aStrings
.realloc(aValues
.getLength());
189 for(sal_Int32 nN
=aValues
.getLength();nN
--;)
190 aValues
[nN
] >>= aStrings
[nN
];
196 SplitCategoriesProvider::~SplitCategoriesProvider()
200 class SplitCategoriesProvider_ForLabeledDataSequences
: public SplitCategoriesProvider
204 explicit SplitCategoriesProvider_ForLabeledDataSequences( const ::com::sun::star::uno::Sequence
< ::com::sun::star::uno::Reference
<
205 ::com::sun::star::chart2::data::XLabeledDataSequence
> >& rSplitCategoriesList
)
206 : m_rSplitCategoriesList( rSplitCategoriesList
)
208 virtual ~SplitCategoriesProvider_ForLabeledDataSequences()
211 virtual sal_Int32
getLevelCount() const;
212 virtual uno::Sequence
< rtl::OUString
> getStringsForLevel( sal_Int32 nIndex
) const;
215 const ::com::sun::star::uno::Sequence
< ::com::sun::star::uno::Reference
<
216 ::com::sun::star::chart2::data::XLabeledDataSequence
> >& m_rSplitCategoriesList
;
219 sal_Int32
SplitCategoriesProvider_ForLabeledDataSequences::getLevelCount() const
221 return m_rSplitCategoriesList
.getLength();
223 uno::Sequence
< rtl::OUString
> SplitCategoriesProvider_ForLabeledDataSequences::getStringsForLevel( sal_Int32 nLevel
) const
225 uno::Sequence
< rtl::OUString
> aRet
;
226 Reference
< data::XLabeledDataSequence
> xLabeledDataSequence( m_rSplitCategoriesList
[nLevel
] );
227 if( xLabeledDataSequence
.is() )
228 aRet
= lcl_DataToStringSequence( xLabeledDataSequence
->getValues() );
232 std::vector
< ComplexCategory
> lcl_DataSequenceToComplexCategoryVector(
233 const uno::Sequence
< rtl::OUString
>& rStrings
234 , const std::vector
<sal_Int32
>& rLimitingBorders
, bool bCreateSingleCategories
)
236 std::vector
< ComplexCategory
> aResult
;
238 sal_Int32 nMaxCount
= rStrings
.getLength();
240 sal_Int32 nCurrentCount
=0;
241 for( sal_Int32 nN
=0; nN
<nMaxCount
; nN
++ )
243 OUString aCurrent
= rStrings
[nN
];
244 if( bCreateSingleCategories
|| ::std::find( rLimitingBorders
.begin(), rLimitingBorders
.end(), nN
) != rLimitingBorders
.end() )
246 aResult
.push_back( ComplexCategory(aPrevious
,nCurrentCount
) );
248 aPrevious
= aCurrent
;
252 if( aCurrent
.getLength() && aPrevious
!= aCurrent
)
254 aResult
.push_back( ComplexCategory(aPrevious
,nCurrentCount
) );
256 aPrevious
= aCurrent
;
263 aResult
.push_back( ComplexCategory(aPrevious
,nCurrentCount
) );
268 sal_Int32
lcl_getCategoryCount( std::vector
< ComplexCategory
>& rComplexCategories
)
270 sal_Int32 nCount
= 0;
271 std::vector
< ComplexCategory
>::iterator
aIt( rComplexCategories
.begin() );
272 std::vector
< ComplexCategory
>::const_iterator
aEnd( rComplexCategories
.end() );
273 for( ; aIt
!= aEnd
; ++aIt
)
278 Sequence
< OUString
> lcl_getExplicitSimpleCategories(
279 const SplitCategoriesProvider
& rSplitCategoriesProvider
,
280 ::std::vector
< ::std::vector
< ComplexCategory
> >& rComplexCats
)
282 Sequence
< OUString
> aRet
;
284 rComplexCats
.clear();
285 sal_Int32 nLCount
= rSplitCategoriesProvider
.getLevelCount();
286 for( sal_Int32 nL
= 0; nL
< nLCount
; nL
++ )
288 std::vector
<sal_Int32
> aLimitingBorders
;
290 aLimitingBorders
= lcl_getLimitingBorders( rComplexCats
.back() );
291 rComplexCats
.push_back( lcl_DataSequenceToComplexCategoryVector(
292 rSplitCategoriesProvider
.getStringsForLevel(nL
), aLimitingBorders
, nL
==(nLCount
-1) ) );
295 std::vector
< std::vector
< ComplexCategory
> >::iterator
aOuterIt( rComplexCats
.begin() );
296 std::vector
< std::vector
< ComplexCategory
> >::const_iterator
aOuterEnd( rComplexCats
.end() );
298 //ensure that the category count is the same on each level
299 sal_Int32 nMaxCategoryCount
= 0;
301 for( aOuterIt
=rComplexCats
.begin(); aOuterIt
!= aOuterEnd
; ++aOuterIt
)
303 sal_Int32 nCurrentCount
= lcl_getCategoryCount( *aOuterIt
);
304 nMaxCategoryCount
= std::max( nCurrentCount
, nMaxCategoryCount
);
306 for( aOuterIt
=rComplexCats
.begin(); aOuterIt
!= aOuterEnd
; ++aOuterIt
)
308 sal_Int32 nCurrentCount
= lcl_getCategoryCount( *aOuterIt
);
309 if( nCurrentCount
< nMaxCategoryCount
)
311 ComplexCategory
& rComplexCategory
= aOuterIt
->back();
312 rComplexCategory
.Count
+= (nMaxCategoryCount
-nCurrentCount
);
317 //create a list with an element for every index
318 std::vector
< std::vector
< ComplexCategory
> > aComplexCatsPerIndex
;
319 for( aOuterIt
=rComplexCats
.begin() ; aOuterIt
!= aOuterEnd
; ++aOuterIt
)
321 std::vector
< ComplexCategory
> aSingleLevel
;
322 std::vector
< ComplexCategory
>::iterator
aIt( aOuterIt
->begin() );
323 std::vector
< ComplexCategory
>::const_iterator
aEnd( aOuterIt
->end() );
324 for( ; aIt
!= aEnd
; ++aIt
)
326 ComplexCategory
aComplexCategory( *aIt
);
327 sal_Int32 nCount
= aComplexCategory
.Count
;
329 aSingleLevel
.push_back(aComplexCategory
);
331 aComplexCatsPerIndex
.push_back( aSingleLevel
);
334 if(nMaxCategoryCount
)
336 aRet
.realloc(nMaxCategoryCount
);
337 aOuterEnd
= aComplexCatsPerIndex
.end();
338 OUString
aSpace(C2U(" "));
339 for(sal_Int32 nN
=0; nN
<nMaxCategoryCount
; nN
++)
342 for( aOuterIt
=aComplexCatsPerIndex
.begin() ; aOuterIt
!= aOuterEnd
; ++aOuterIt
)
344 OUString aAddText
= (*aOuterIt
)[nN
].Text
;
345 if( aAddText
.getLength() )
347 if(aText
.getLength())
359 Sequence
< OUString
> ExplicitCategoriesProvider::getExplicitSimpleCategories(
360 const SplitCategoriesProvider
& rSplitCategoriesProvider
)
362 vector
< vector
< ComplexCategory
> > aComplexCats
;
363 return lcl_getExplicitSimpleCategories( rSplitCategoriesProvider
, aComplexCats
);
366 void ExplicitCategoriesProvider::init()
370 m_aExplicitCategories
.realloc(0);
371 m_aComplexCats
.clear();//not one per index
373 if( m_xOriginalCategories
.is() )
375 if( !hasComplexCategories() )
376 m_aExplicitCategories
= DataSequenceToStringSequence(m_xOriginalCategories
->getValues());
378 m_aExplicitCategories
= lcl_getExplicitSimpleCategories(
379 SplitCategoriesProvider_ForLabeledDataSequences( m_aSplitCategoriesList
), m_aComplexCats
);
381 if(!m_aExplicitCategories
.getLength())
382 m_aExplicitCategories
= DiagramHelper::generateAutomaticCategoriesFromCooSys( m_xCooSysModel
);
388 Sequence
< ::rtl::OUString
> ExplicitCategoriesProvider::getSimpleCategories()
391 return m_aExplicitCategories
;
394 std::vector
< ComplexCategory
> ExplicitCategoriesProvider::getCategoriesByLevel( sal_Int32 nLevel
)
396 std::vector
< ComplexCategory
> aRet
;
398 sal_Int32 nMaxIndex
= m_aComplexCats
.size()-1;
399 if( nLevel
>= 0 && nLevel
<= nMaxIndex
)
400 aRet
= m_aComplexCats
[nMaxIndex
-nLevel
];
405 OUString
ExplicitCategoriesProvider::getCategoryByIndex(
406 const Reference
< XCoordinateSystem
>& xCooSysModel
407 , const uno::Reference
< frame::XModel
>& xChartModel
410 if( xCooSysModel
.is())
412 ExplicitCategoriesProvider
aExplicitCategoriesProvider( xCooSysModel
, xChartModel
);
413 Sequence
< OUString
> aCategories( aExplicitCategoriesProvider
.getSimpleCategories());
414 if( nIndex
< aCategories
.getLength())
415 return aCategories
[ nIndex
];
420 //.............................................................................
422 //.............................................................................