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 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.getLength() ) 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 145 ExplicitCategoriesProvider::~ExplicitCategoriesProvider() 146 { 147 } 148 149 Reference< chart2::data::XDataSequence > ExplicitCategoriesProvider::getOriginalCategories() 150 { 151 if( m_xOriginalCategories.is() ) 152 return m_xOriginalCategories->getValues(); 153 return 0; 154 } 155 156 const Sequence< Reference< data::XLabeledDataSequence> >& ExplicitCategoriesProvider::getSplitCategoriesList() 157 { 158 return m_aSplitCategoriesList; 159 } 160 161 bool ExplicitCategoriesProvider::hasComplexCategories() const 162 { 163 return m_aSplitCategoriesList.getLength() > 1; 164 } 165 166 sal_Int32 ExplicitCategoriesProvider::getCategoryLevelCount() const 167 { 168 sal_Int32 nCount = m_aSplitCategoriesList.getLength(); 169 if(!nCount) 170 nCount = 1; 171 return nCount; 172 } 173 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 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 236 SplitCategoriesProvider::~SplitCategoriesProvider() 237 { 238 } 239 240 class SplitCategoriesProvider_ForLabeledDataSequences : public SplitCategoriesProvider 241 { 242 public: 243 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 {} 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 265 sal_Int32 SplitCategoriesProvider_ForLabeledDataSequences::getLevelCount() const 266 { 267 return m_rSplitCategoriesList.getLength(); 268 } 269 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 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.getLength() && 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 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 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.getLength() ) 403 { 404 if(aText.getLength()) 405 aText += aSpace; 406 aText += aAddText; 407 } 408 } 409 } 410 aRet[nN]=aText; 411 } 412 } 413 return aRet; 414 } 415 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 { 425 inline bool operator() ( const DatePlusIndex& aFirst, 426 const DatePlusIndex& aSecond ) 427 { 428 return ( aFirst.fValue < aSecond.fValue ); 429 } 430 }; 431 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.getLength() ) //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 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 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 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 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 594 bool ExplicitCategoriesProvider::isDateAxis() 595 { 596 init(); 597 return m_bIsDateAxis; 598 } 599 600 const std::vector< DatePlusIndex >& ExplicitCategoriesProvider::getDateCategories() 601 { 602 init(); 603 return m_aDateCategories; 604 } 605 606 //............................................................................. 607 } //namespace chart 608 //............................................................................. 609