1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_chart2.hxx"
26 
27 #include "ExplicitCategoriesProvider.hxx"
28 #include "DiagramHelper.hxx"
29 #include "ChartTypeHelper.hxx"
30 #include "AxisHelper.hxx"
31 #include "CommonConverters.hxx"
32 #include "DataSourceHelper.hxx"
33 #include "ChartModelHelper.hxx"
34 #include "ContainerHelper.hxx"
35 #include "macros.hxx"
36 #include "NumberFormatterWrapper.hxx"
37 
38 #include <com/sun/star/chart2/AxisType.hpp>
39 #include <com/sun/star/util/NumberFormat.hpp>
40 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
41 
42 //.............................................................................
43 namespace chart
44 {
45 //.............................................................................
46 
47 using namespace ::com::sun::star;
48 using namespace ::com::sun::star::chart2;
49 using ::com::sun::star::uno::Reference;
50 using ::com::sun::star::uno::Sequence;
51 using ::rtl::OUString;
52 using ::std::vector;
53 
54 
ExplicitCategoriesProvider(const Reference<chart2::XCoordinateSystem> & xCooSysModel,const uno::Reference<frame::XModel> & xChartModel)55 ExplicitCategoriesProvider::ExplicitCategoriesProvider( const Reference< chart2::XCoordinateSystem >& xCooSysModel
56                                                        , const uno::Reference< frame::XModel >& xChartModel )
57     : m_bDirty(true)
58     , m_xCooSysModel( xCooSysModel )
59     , m_xChartModel( xChartModel )
60     , m_xOriginalCategories()
61     , m_bIsExplicitCategoriesInited(false)
62     , m_bIsDateAxis(false)
63     , m_bIsAutoDate(false)
64 {
65     try
66     {
67         if( xCooSysModel.is() )
68         {
69             uno::Reference< XAxis > xAxis( xCooSysModel->getAxisByDimension(0,0) );
70             if( xAxis.is() )
71             {
72                 ScaleData aScale( xAxis->getScaleData() );
73                 m_xOriginalCategories = aScale.Categories;
74                 m_bIsAutoDate = (aScale.AutoDateAxis && aScale.AxisType==chart2::AxisType::CATEGORY);
75                 m_bIsDateAxis = (aScale.AxisType == chart2::AxisType::DATE || m_bIsAutoDate);
76             }
77         }
78 
79         if( m_xOriginalCategories.is() )
80         {
81             Reference< chart2::XChartDocument > xChartDoc( xChartModel, uno::UNO_QUERY );
82             if( xChartDoc.is() )
83             {
84                 uno::Reference< data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() );
85 
86                 OUString aCatgoriesRange( DataSourceHelper::getRangeFromValues( m_xOriginalCategories ) );
87                 if( xDataProvider.is() && !aCatgoriesRange.isEmpty() )
88                 {
89                     const bool bFirstCellAsLabel = false;
90                     const bool bHasCategories = false;
91                     const uno::Sequence< sal_Int32 > aSequenceMapping;
92 
93                     uno::Reference< data::XDataSource > xColumnCategoriesSource( xDataProvider->createDataSource(
94                          DataSourceHelper::createArguments( aCatgoriesRange, aSequenceMapping, true /*bUseColumns*/
95                             , bFirstCellAsLabel, bHasCategories ) ) );
96 
97                     uno::Reference< data::XDataSource > xRowCategoriesSource( xDataProvider->createDataSource(
98                          DataSourceHelper::createArguments( aCatgoriesRange, aSequenceMapping, false /*bUseColumns*/
99                             , bFirstCellAsLabel, bHasCategories ) ) );
100 
101                     if( xColumnCategoriesSource.is() &&  xRowCategoriesSource.is() )
102                     {
103                         Sequence< Reference< data::XLabeledDataSequence> > aColumns = xColumnCategoriesSource->getDataSequences();
104                         Sequence< Reference< data::XLabeledDataSequence> > aRows = xRowCategoriesSource->getDataSequences();
105 
106                         sal_Int32 nColumnCount = aColumns.getLength();
107                         sal_Int32 nRowCount = aRows.getLength();
108                         if( nColumnCount>1 && nRowCount>1 )
109                         {
110                             //we have complex categories
111                             //->split them in the direction of the first series
112                             //detect whether the first series is a row or a column
113                             bool bSeriesUsesColumns = true;
114                             ::std::vector< Reference< XDataSeries > > aSeries( ChartModelHelper::getDataSeries( xChartModel ) );
115                             if( !aSeries.empty() )
116                             {
117                                 uno::Reference< data::XDataSource > xSeriesSource( aSeries.front(), uno::UNO_QUERY );
118                                 ::rtl::OUString aStringDummy;
119                                 bool bDummy;
120                                 uno::Sequence< sal_Int32 > aSeqDummy;
121                                 DataSourceHelper::readArguments( xDataProvider->detectArguments( xSeriesSource),
122                                                aStringDummy, aSeqDummy, bSeriesUsesColumns, bDummy, bDummy );
123                             }
124                             if( bSeriesUsesColumns )
125                                 m_aSplitCategoriesList=aColumns;
126                             else
127                                 m_aSplitCategoriesList=aRows;
128                         }
129                     }
130                 }
131             }
132             if( !m_aSplitCategoriesList.getLength() )
133             {
134                 m_aSplitCategoriesList.realloc(1);
135                 m_aSplitCategoriesList[0]=m_xOriginalCategories;
136             }
137         }
138     }
139     catch( const uno::Exception & ex )
140     {
141         ASSERT_EXCEPTION( ex );
142     }
143 }
144 
~ExplicitCategoriesProvider()145 ExplicitCategoriesProvider::~ExplicitCategoriesProvider()
146 {
147 }
148 
getOriginalCategories()149 Reference< chart2::data::XDataSequence > ExplicitCategoriesProvider::getOriginalCategories()
150 {
151     if( m_xOriginalCategories.is() )
152         return m_xOriginalCategories->getValues();
153     return 0;
154 }
155 
getSplitCategoriesList()156 const Sequence< Reference< data::XLabeledDataSequence> >& ExplicitCategoriesProvider::getSplitCategoriesList()
157 {
158     return m_aSplitCategoriesList;
159 }
160 
hasComplexCategories() const161 bool ExplicitCategoriesProvider::hasComplexCategories() const
162 {
163     return m_aSplitCategoriesList.getLength() > 1;
164 }
165 
getCategoryLevelCount() const166 sal_Int32 ExplicitCategoriesProvider::getCategoryLevelCount() const
167 {
168     sal_Int32 nCount = m_aSplitCategoriesList.getLength();
169     if(!nCount)
170         nCount = 1;
171     return nCount;
172 }
173 
lcl_getLimitingBorders(const std::vector<ComplexCategory> & rComplexCategories)174 std::vector<sal_Int32> lcl_getLimitingBorders( const std::vector< ComplexCategory >& rComplexCategories )
175 {
176     std::vector<sal_Int32> aLimitingBorders;
177     std::vector< ComplexCategory >::const_iterator aIt( rComplexCategories.begin() );
178     std::vector< ComplexCategory >::const_iterator aEnd( rComplexCategories.end() );
179     sal_Int32 nBorderIndex = 0; /*border below the index*/
180     for( ; aIt != aEnd; ++aIt )
181     {
182         ComplexCategory aComplexCategory(*aIt);
183         nBorderIndex += aComplexCategory.Count;
184         aLimitingBorders.push_back(nBorderIndex);
185     }
186     return aLimitingBorders;
187 }
188 
convertCategoryAnysToText(uno::Sequence<rtl::OUString> & rOutTexts,const uno::Sequence<uno::Any> & rInAnys,Reference<frame::XModel> xChartModel)189 void ExplicitCategoriesProvider::convertCategoryAnysToText( uno::Sequence< rtl::OUString >& rOutTexts, const uno::Sequence< uno::Any >& rInAnys, Reference< frame::XModel > xChartModel )
190 {
191     sal_Int32 nCount = rInAnys.getLength();
192     if(!nCount)
193         return;
194     rOutTexts.realloc(nCount);
195     Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( xChartModel, uno::UNO_QUERY );
196     Reference< util::XNumberFormats > xNumberFormats;
197     if( xNumberFormatsSupplier.is() )
198          xNumberFormats = Reference< util::XNumberFormats >( xNumberFormatsSupplier->getNumberFormats() );
199 
200     sal_Int32 nAxisNumberFormat = 0;
201     Reference< XCoordinateSystem > xCooSysModel( ChartModelHelper::getFirstCoordinateSystem( xChartModel ) );
202     if( xCooSysModel.is() )
203     {
204         Reference< chart2::XAxis > xAxis( xCooSysModel->getAxisByDimension(0,0) );
205         nAxisNumberFormat = AxisHelper::getExplicitNumberFormatKeyForAxis(
206                   xAxis, xCooSysModel, xNumberFormatsSupplier, false );
207     }
208 
209     sal_Int32 nLabelColor;
210     bool bColorChanged = false;
211 
212     NumberFormatterWrapper aNumberFormatterWrapper( xNumberFormatsSupplier );
213 
214     for(sal_Int32 nN=0;nN<nCount;nN++)
215     {
216         rtl::OUString aText;
217         uno::Any aAny = rInAnys[nN];
218         if( aAny.hasValue() )
219         {
220             double fDouble = 0;
221             if( aAny>>=fDouble )
222             {
223                 if( !::rtl::math::isNan(fDouble) )
224                     aText = aNumberFormatterWrapper.getFormattedString(
225                         nAxisNumberFormat, fDouble, nLabelColor, bColorChanged );
226             }
227             else
228             {
229                 aAny>>=aText;
230             }
231         }
232         rOutTexts[nN] = aText;
233     }
234 }
235 
~SplitCategoriesProvider()236 SplitCategoriesProvider::~SplitCategoriesProvider()
237 {
238 }
239 
240 class SplitCategoriesProvider_ForLabeledDataSequences : public SplitCategoriesProvider
241 {
242 public:
243 
SplitCategoriesProvider_ForLabeledDataSequences(const::com::sun::star::uno::Sequence<::com::sun::star::uno::Reference<::com::sun::star::chart2::data::XLabeledDataSequence>> & rSplitCategoriesList,const Reference<frame::XModel> & xChartModel)244     explicit SplitCategoriesProvider_ForLabeledDataSequences(
245         const ::com::sun::star::uno::Sequence<
246             ::com::sun::star::uno::Reference<
247                 ::com::sun::star::chart2::data::XLabeledDataSequence> >& rSplitCategoriesList
248         , const Reference< frame::XModel >& xChartModel )
249         : m_rSplitCategoriesList( rSplitCategoriesList )
250         , m_xChartModel( xChartModel )
251     {}
~SplitCategoriesProvider_ForLabeledDataSequences()252     virtual ~SplitCategoriesProvider_ForLabeledDataSequences()
253     {}
254 
255     virtual sal_Int32 getLevelCount() const;
256     virtual uno::Sequence< rtl::OUString > getStringsForLevel( sal_Int32 nIndex ) const;
257 
258 private:
259     const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference<
260         ::com::sun::star::chart2::data::XLabeledDataSequence> >& m_rSplitCategoriesList;
261 
262     Reference< frame::XModel > m_xChartModel;
263 };
264 
getLevelCount() const265 sal_Int32 SplitCategoriesProvider_ForLabeledDataSequences::getLevelCount() const
266 {
267     return m_rSplitCategoriesList.getLength();
268 }
getStringsForLevel(sal_Int32 nLevel) const269 uno::Sequence< rtl::OUString > SplitCategoriesProvider_ForLabeledDataSequences::getStringsForLevel( sal_Int32 nLevel ) const
270 {
271     uno::Sequence< rtl::OUString > aRet;
272     Reference< data::XLabeledDataSequence > xLabeledDataSequence( m_rSplitCategoriesList[nLevel] );
273     if( xLabeledDataSequence.is() )
274     {
275         uno::Reference< data::XDataSequence > xDataSequence( xLabeledDataSequence->getValues() );
276         if( xDataSequence.is() )
277             ExplicitCategoriesProvider::convertCategoryAnysToText( aRet, xDataSequence->getData(), m_xChartModel );
278     }
279     return aRet;
280 }
281 
lcl_DataSequenceToComplexCategoryVector(const uno::Sequence<rtl::OUString> & rStrings,const std::vector<sal_Int32> & rLimitingBorders,bool bCreateSingleCategories)282 std::vector< ComplexCategory > lcl_DataSequenceToComplexCategoryVector(
283     const uno::Sequence< rtl::OUString >& rStrings
284     , const std::vector<sal_Int32>& rLimitingBorders, bool bCreateSingleCategories )
285 {
286     std::vector< ComplexCategory > aResult;
287 
288     sal_Int32 nMaxCount = rStrings.getLength();
289     OUString aPrevious;
290     sal_Int32 nCurrentCount=0;
291     for( sal_Int32 nN=0; nN<nMaxCount; nN++ )
292     {
293         OUString aCurrent = rStrings[nN];
294         if( bCreateSingleCategories || ::std::find( rLimitingBorders.begin(), rLimitingBorders.end(), nN ) != rLimitingBorders.end() )
295         {
296             aResult.push_back( ComplexCategory(aPrevious,nCurrentCount) );
297             nCurrentCount=1;
298             aPrevious = aCurrent;
299         }
300         else
301         {
302             if( !aCurrent.isEmpty() && aPrevious != aCurrent )
303             {
304                 aResult.push_back( ComplexCategory(aPrevious,nCurrentCount) );
305                 nCurrentCount=1;
306                 aPrevious = aCurrent;
307             }
308             else
309                 nCurrentCount++;
310         }
311     }
312     if( nCurrentCount )
313         aResult.push_back( ComplexCategory(aPrevious,nCurrentCount) );
314 
315     return aResult;
316 }
317 
lcl_getCategoryCount(std::vector<ComplexCategory> & rComplexCategories)318 sal_Int32 lcl_getCategoryCount( std::vector< ComplexCategory >& rComplexCategories )
319 {
320     sal_Int32 nCount = 0;
321     std::vector< ComplexCategory >::iterator aIt( rComplexCategories.begin() );
322     std::vector< ComplexCategory >::const_iterator aEnd( rComplexCategories.end() );
323     for( ; aIt != aEnd; ++aIt )
324         nCount+=aIt->Count;
325     return nCount;
326 }
327 
lcl_getExplicitSimpleCategories(const SplitCategoriesProvider & rSplitCategoriesProvider,::std::vector<::std::vector<ComplexCategory>> & rComplexCats)328 Sequence< OUString > lcl_getExplicitSimpleCategories(
329     const SplitCategoriesProvider& rSplitCategoriesProvider,
330     ::std::vector< ::std::vector< ComplexCategory > >& rComplexCats )
331 {
332     Sequence< OUString > aRet;
333 
334     rComplexCats.clear();
335     sal_Int32 nLCount = rSplitCategoriesProvider.getLevelCount();
336     for( sal_Int32 nL = 0; nL < nLCount; nL++ )
337     {
338         std::vector<sal_Int32> aLimitingBorders;
339         if(nL>0)
340             aLimitingBorders = lcl_getLimitingBorders( rComplexCats.back() );
341         rComplexCats.push_back( lcl_DataSequenceToComplexCategoryVector(
342             rSplitCategoriesProvider.getStringsForLevel(nL), aLimitingBorders, nL==(nLCount-1) ) );
343     }
344 
345     std::vector< std::vector< ComplexCategory > >::iterator aOuterIt( rComplexCats.begin() );
346     std::vector< std::vector< ComplexCategory > >::const_iterator aOuterEnd( rComplexCats.end() );
347 
348     //ensure that the category count is the same on each level
349     sal_Int32 nMaxCategoryCount = 0;
350     {
351         for( aOuterIt=rComplexCats.begin(); aOuterIt != aOuterEnd; ++aOuterIt )
352         {
353             sal_Int32 nCurrentCount = lcl_getCategoryCount( *aOuterIt );
354             nMaxCategoryCount = std::max( nCurrentCount, nMaxCategoryCount );
355         }
356         for( aOuterIt=rComplexCats.begin(); aOuterIt != aOuterEnd; ++aOuterIt )
357         {
358             sal_Int32 nCurrentCount = lcl_getCategoryCount( *aOuterIt );
359             if( nCurrentCount< nMaxCategoryCount )
360             {
361                 if(!aOuterIt->empty()) // #121277# Caution, aOuterIt may be empty (!)
362                 {
363                     ComplexCategory& rComplexCategory = aOuterIt->back();
364                     rComplexCategory.Count += (nMaxCategoryCount-nCurrentCount);
365                 }
366             }
367         }
368     }
369 
370     //create a list with an element for every index
371     std::vector< std::vector< ComplexCategory > > aComplexCatsPerIndex;
372     for( aOuterIt=rComplexCats.begin() ; aOuterIt != aOuterEnd; ++aOuterIt )
373     {
374         std::vector< ComplexCategory > aSingleLevel;
375         std::vector< ComplexCategory >::iterator aIt( aOuterIt->begin() );
376         std::vector< ComplexCategory >::const_iterator aEnd( aOuterIt->end() );
377         for( ; aIt != aEnd; ++aIt )
378         {
379             ComplexCategory aComplexCategory( *aIt );
380             sal_Int32 nCount = aComplexCategory.Count;
381             while( nCount-- )
382                 aSingleLevel.push_back(aComplexCategory);
383         }
384         aComplexCatsPerIndex.push_back( aSingleLevel );
385     }
386 
387     if(nMaxCategoryCount)
388     {
389         aRet.realloc(nMaxCategoryCount);
390         aOuterEnd = aComplexCatsPerIndex.end();
391         OUString aSpace(C2U(" "));
392         for(sal_Int32 nN=0; nN<nMaxCategoryCount; nN++)
393         {
394             OUString aText;
395             for( aOuterIt=aComplexCatsPerIndex.begin() ; aOuterIt != aOuterEnd; ++aOuterIt )
396             {
397                 OUString aAddText;
398 
399                 if(!aOuterIt->empty()) // #121277# Caution, aOuterIt may be empty (!)
400                 {
401                     aAddText = (*aOuterIt)[nN].Text;
402                     if( !aAddText.isEmpty() )
403                     {
404                         if( !aText.isEmpty() )
405                             aText += aSpace;
406                         aText += aAddText;
407                     }
408                 }
409             }
410             aRet[nN]=aText;
411         }
412     }
413     return aRet;
414 }
415 
getExplicitSimpleCategories(const SplitCategoriesProvider & rSplitCategoriesProvider)416 Sequence< OUString > ExplicitCategoriesProvider::getExplicitSimpleCategories(
417     const SplitCategoriesProvider& rSplitCategoriesProvider )
418 {
419     vector< vector< ComplexCategory > > aComplexCats;
420     return lcl_getExplicitSimpleCategories( rSplitCategoriesProvider, aComplexCats );
421 }
422 
423 struct DatePlusIndexComparator
424 {
operator ()chart::DatePlusIndexComparator425     inline bool operator() ( const DatePlusIndex& aFirst,
426                              const DatePlusIndex& aSecond )
427     {
428         return ( aFirst.fValue < aSecond.fValue );
429     }
430 };
431 
lcl_fillDateCategories(const uno::Reference<data::XDataSequence> & xDataSequence,std::vector<DatePlusIndex> & rDateCategories,bool bIsAutoDate,Reference<util::XNumberFormatsSupplier> xNumberFormatsSupplier)432 bool lcl_fillDateCategories( const uno::Reference< data::XDataSequence >& xDataSequence, std::vector< DatePlusIndex >& rDateCategories, bool bIsAutoDate, Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier )
433 {
434     bool bOnlyDatesFound = true;
435     bool bAnyDataFound = false;
436 
437     if( xDataSequence.is() )
438     {
439         uno::Sequence< uno::Any > aValues = xDataSequence->getData();
440         sal_Int32 nCount = aValues.getLength();
441         rDateCategories.reserve(nCount);
442         Reference< util::XNumberFormats > xNumberFormats;
443         if( xNumberFormatsSupplier.is() )
444              xNumberFormats = Reference< util::XNumberFormats >( xNumberFormatsSupplier->getNumberFormats() );
445 
446         bool bOwnData = false;
447         bool bOwnDataAnddAxisHasAnyFormat = false;
448         bool bOwnDataAnddAxisHasDateFormat = false;
449         Reference< chart2::XChartDocument > xChartDoc( xNumberFormatsSupplier, uno::UNO_QUERY );
450         Reference< XCoordinateSystem > xCooSysModel( ChartModelHelper::getFirstCoordinateSystem( Reference< frame::XModel >( xChartDoc, uno::UNO_QUERY ) ) );
451         if( xChartDoc.is() && xCooSysModel.is() )
452         {
453             if( xChartDoc->hasInternalDataProvider() )
454             {
455                 bOwnData = true;
456                 Reference< beans::XPropertySet > xAxisProps( xCooSysModel->getAxisByDimension(0,0), uno::UNO_QUERY );
457                 sal_Int32 nAxisNumberFormat = 0;
458                 if( xAxisProps.is() && (xAxisProps->getPropertyValue( C2U("NumberFormat") ) >>= nAxisNumberFormat) )
459                 {
460                     bOwnDataAnddAxisHasAnyFormat = true;
461                     bOwnDataAnddAxisHasDateFormat = DiagramHelper::isDateNumberFormat( nAxisNumberFormat, xNumberFormats );
462                 }
463             }
464         }
465 
466         for(sal_Int32 nN=0;nN<nCount;nN++)
467         {
468             bool bIsDate = false;
469             if( bIsAutoDate )
470             {
471                 if( bOwnData )
472                     bIsDate = bOwnDataAnddAxisHasAnyFormat ? bOwnDataAnddAxisHasDateFormat : true;
473                 else
474                     bIsDate = DiagramHelper::isDateNumberFormat( xDataSequence->getNumberFormatKeyByIndex( nN ), xNumberFormats );
475             }
476             else
477                 bIsDate = true;
478 
479             bool bContainsEmptyString = false;
480             bool bContainsNan = false;
481             uno::Any aAny = aValues[nN];
482             if( aAny.hasValue() )
483             {
484                 OUString aTest;
485                 double fTest = 0;
486                 if( (aAny>>=aTest) && aTest.isEmpty() ) //empty String
487                     bContainsEmptyString = true;
488                 else if( (aAny>>=fTest) &&  ::rtl::math::isNan(fTest) )
489                     bContainsNan = true;
490 
491                 if( !bContainsEmptyString && !bContainsNan )
492                     bAnyDataFound = true;
493             }
494             DatePlusIndex aDatePlusIndex( 1.0, nN );
495             if( bIsDate && (aAny >>= aDatePlusIndex.fValue) )
496                 rDateCategories.push_back( aDatePlusIndex );
497             else
498             {
499                 if( aAny.hasValue() && !bContainsEmptyString )//empty string does not count as non date value!
500                     bOnlyDatesFound=false;
501                 ::rtl::math::setNan( &aDatePlusIndex.fValue );
502                 rDateCategories.push_back( aDatePlusIndex );
503             }
504         }
505         ::std::sort( rDateCategories.begin(), rDateCategories.end(), DatePlusIndexComparator() );
506     }
507 
508     return bAnyDataFound && bOnlyDatesFound;
509 }
510 
init()511 void ExplicitCategoriesProvider::init()
512 {
513     if( m_bDirty )
514     {
515         m_aComplexCats.clear();//not one per index
516         m_aDateCategories.clear();
517 
518         if( m_xOriginalCategories.is() )
519         {
520             if( !hasComplexCategories() )
521             {
522                 if(m_bIsDateAxis)
523                 {
524                     if( ChartTypeHelper::isSupportingDateAxis( AxisHelper::getChartTypeByIndex( m_xCooSysModel, 0 ), 2, 0 ) )
525                         m_bIsDateAxis = lcl_fillDateCategories( m_xOriginalCategories->getValues(), m_aDateCategories, m_bIsAutoDate, Reference< util::XNumberFormatsSupplier >( m_xChartModel.get(), uno::UNO_QUERY ) );
526                     else
527                         m_bIsDateAxis = false;
528                 }
529             }
530             else
531             {
532                 m_bIsDateAxis = false;
533             }
534         }
535         else
536             m_bIsDateAxis=false;
537         m_bDirty = false;
538     }
539 }
540 
541 
getSimpleCategories()542 Sequence< ::rtl::OUString > ExplicitCategoriesProvider::getSimpleCategories()
543 {
544     if( !m_bIsExplicitCategoriesInited )
545     {
546         init();
547         m_aExplicitCategories.realloc(0);
548         if( m_xOriginalCategories.is() )
549         {
550             if( !hasComplexCategories() )
551             {
552                 uno::Reference< data::XDataSequence > xDataSequence( m_xOriginalCategories->getValues() );
553                 if( xDataSequence.is() )
554                     ExplicitCategoriesProvider::convertCategoryAnysToText( m_aExplicitCategories, xDataSequence->getData(), m_xChartModel );
555             }
556             else
557             {
558                 m_aExplicitCategories = lcl_getExplicitSimpleCategories(
559                     SplitCategoriesProvider_ForLabeledDataSequences( m_aSplitCategoriesList, m_xChartModel ), m_aComplexCats );
560             }
561         }
562         if(!m_aExplicitCategories.getLength())
563             m_aExplicitCategories = DiagramHelper::generateAutomaticCategoriesFromCooSys( m_xCooSysModel );
564         m_bIsExplicitCategoriesInited = true;
565     }
566     return m_aExplicitCategories;
567 }
568 
getCategoriesByLevel(sal_Int32 nLevel)569 std::vector< ComplexCategory >  ExplicitCategoriesProvider::getCategoriesByLevel( sal_Int32 nLevel )
570 {
571     std::vector< ComplexCategory > aRet;
572     init();
573     sal_Int32 nMaxIndex = m_aComplexCats.size()-1;
574     if( nLevel >= 0 && nLevel <= nMaxIndex  )
575         aRet = m_aComplexCats[nMaxIndex-nLevel];
576     return aRet;
577 }
578 
getCategoryByIndex(const Reference<XCoordinateSystem> & xCooSysModel,const uno::Reference<frame::XModel> & xChartModel,sal_Int32 nIndex)579 OUString ExplicitCategoriesProvider::getCategoryByIndex(
580           const Reference< XCoordinateSystem >& xCooSysModel
581         , const uno::Reference< frame::XModel >& xChartModel
582         , sal_Int32 nIndex )
583 {
584     if( xCooSysModel.is())
585     {
586         ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSysModel, xChartModel );
587         Sequence< OUString > aCategories( aExplicitCategoriesProvider.getSimpleCategories());
588         if( nIndex < aCategories.getLength())
589             return aCategories[ nIndex ];
590     }
591     return OUString();
592 }
593 
isDateAxis()594 bool ExplicitCategoriesProvider::isDateAxis()
595 {
596     init();
597     return m_bIsDateAxis;
598 }
599 
getDateCategories()600 const std::vector< DatePlusIndex >&  ExplicitCategoriesProvider::getDateCategories()
601 {
602     init();
603     return m_aDateCategories;
604 }
605 
606 //.............................................................................
607 } //namespace chart
608 //.............................................................................
609