merged tag ooo/OOO330_m14
[LibreOffice.git] / chart2 / source / tools / ExplicitCategoriesProvider.cxx
blobbd1c1bb798130d0987bfbf3dba4032d9952e10ed
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"
37 #include "macros.hxx"
39 //.............................................................................
40 namespace chart
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;
49 using ::std::vector;
52 ExplicitCategoriesProvider::ExplicitCategoriesProvider( const Reference< chart2::XCoordinateSystem >& xCooSysModel
53 , const uno::Reference< frame::XModel >& xChartModel )
54 : m_bDirty(true)
55 , m_xCooSysModel( xCooSysModel )
56 , m_xOriginalCategories()
58 try
60 if( xCooSysModel.is() )
62 uno::Reference< XAxis > xAxis( xCooSysModel->getAxisByDimension(0,0) );
63 if( xAxis.is() )
64 m_xOriginalCategories = xAxis->getScaleData().Categories;
67 if( m_xOriginalCategories.is() )
69 Reference< chart2::XChartDocument > xChartDoc( xChartModel, uno::UNO_QUERY );
70 if( xChartDoc.is() )
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;
107 bool bDummy;
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;
114 else
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();
150 if(!nCount)
151 nCount = 1;
152 return nCount;
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() )
176 return aStrings;
179 uno::Reference< data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY );
180 if( xTextualDataSequence.is() )
182 aStrings = xTextualDataSequence->getTextualData();
184 else
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];
193 return aStrings;
196 SplitCategoriesProvider::~SplitCategoriesProvider()
200 class SplitCategoriesProvider_ForLabeledDataSequences : public SplitCategoriesProvider
202 public:
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;
214 private:
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() );
229 return aRet;
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();
239 OUString aPrevious;
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) );
247 nCurrentCount=1;
248 aPrevious = aCurrent;
250 else
252 if( aCurrent.getLength() && aPrevious != aCurrent )
254 aResult.push_back( ComplexCategory(aPrevious,nCurrentCount) );
255 nCurrentCount=1;
256 aPrevious = aCurrent;
258 else
259 nCurrentCount++;
262 if( nCurrentCount )
263 aResult.push_back( ComplexCategory(aPrevious,nCurrentCount) );
265 return aResult;
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 )
274 nCount+=aIt->Count;
275 return nCount;
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;
289 if(nL>0)
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;
328 while( nCount-- )
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++)
341 OUString aText;
342 for( aOuterIt=aComplexCatsPerIndex.begin() ; aOuterIt != aOuterEnd; ++aOuterIt )
344 OUString aAddText = (*aOuterIt)[nN].Text;
345 if( aAddText.getLength() )
347 if(aText.getLength())
348 aText += aSpace;
349 aText += aAddText;
352 aRet[nN]=aText;
355 return aRet;
358 //static
359 Sequence< OUString > ExplicitCategoriesProvider::getExplicitSimpleCategories(
360 const SplitCategoriesProvider& rSplitCategoriesProvider )
362 vector< vector< ComplexCategory > > aComplexCats;
363 return lcl_getExplicitSimpleCategories( rSplitCategoriesProvider, aComplexCats );
366 void ExplicitCategoriesProvider::init()
368 if( m_bDirty )
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());
377 else
378 m_aExplicitCategories = lcl_getExplicitSimpleCategories(
379 SplitCategoriesProvider_ForLabeledDataSequences( m_aSplitCategoriesList ), m_aComplexCats );
381 if(!m_aExplicitCategories.getLength())
382 m_aExplicitCategories = DiagramHelper::generateAutomaticCategoriesFromCooSys( m_xCooSysModel );
383 m_bDirty = false;
388 Sequence< ::rtl::OUString > ExplicitCategoriesProvider::getSimpleCategories()
390 init();
391 return m_aExplicitCategories;
394 std::vector< ComplexCategory > ExplicitCategoriesProvider::getCategoriesByLevel( sal_Int32 nLevel )
396 std::vector< ComplexCategory > aRet;
397 init();
398 sal_Int32 nMaxIndex = m_aComplexCats.size()-1;
399 if( nLevel >= 0 && nLevel <= nMaxIndex )
400 aRet = m_aComplexCats[nMaxIndex-nLevel];
401 return aRet;
404 // static
405 OUString ExplicitCategoriesProvider::getCategoryByIndex(
406 const Reference< XCoordinateSystem >& xCooSysModel
407 , const uno::Reference< frame::XModel >& xChartModel
408 , sal_Int32 nIndex )
410 if( xCooSysModel.is())
412 ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSysModel, xChartModel );
413 Sequence< OUString > aCategories( aExplicitCategoriesProvider.getSimpleCategories());
414 if( nIndex < aCategories.getLength())
415 return aCategories[ nIndex ];
417 return OUString();
420 //.............................................................................
421 } //namespace chart
422 //.............................................................................