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 ComplexCategory& rComplexCategory = aOuterIt->back(); 362 rComplexCategory.Count += (nMaxCategoryCount-nCurrentCount); 363 } 364 } 365 } 366 367 //create a list with an element for every index 368 std::vector< std::vector< ComplexCategory > > aComplexCatsPerIndex; 369 for( aOuterIt=rComplexCats.begin() ; aOuterIt != aOuterEnd; ++aOuterIt ) 370 { 371 std::vector< ComplexCategory > aSingleLevel; 372 std::vector< ComplexCategory >::iterator aIt( aOuterIt->begin() ); 373 std::vector< ComplexCategory >::const_iterator aEnd( aOuterIt->end() ); 374 for( ; aIt != aEnd; ++aIt ) 375 { 376 ComplexCategory aComplexCategory( *aIt ); 377 sal_Int32 nCount = aComplexCategory.Count; 378 while( nCount-- ) 379 aSingleLevel.push_back(aComplexCategory); 380 } 381 aComplexCatsPerIndex.push_back( aSingleLevel ); 382 } 383 384 if(nMaxCategoryCount) 385 { 386 aRet.realloc(nMaxCategoryCount); 387 aOuterEnd = aComplexCatsPerIndex.end(); 388 OUString aSpace(C2U(" ")); 389 for(sal_Int32 nN=0; nN<nMaxCategoryCount; nN++) 390 { 391 OUString aText; 392 for( aOuterIt=aComplexCatsPerIndex.begin() ; aOuterIt != aOuterEnd; ++aOuterIt ) 393 { 394 OUString aAddText = (*aOuterIt)[nN].Text; 395 if( aAddText.getLength() ) 396 { 397 if(aText.getLength()) 398 aText += aSpace; 399 aText += aAddText; 400 } 401 } 402 aRet[nN]=aText; 403 } 404 } 405 return aRet; 406 } 407 408 Sequence< OUString > ExplicitCategoriesProvider::getExplicitSimpleCategories( 409 const SplitCategoriesProvider& rSplitCategoriesProvider ) 410 { 411 vector< vector< ComplexCategory > > aComplexCats; 412 return lcl_getExplicitSimpleCategories( rSplitCategoriesProvider, aComplexCats ); 413 } 414 415 struct DatePlusIndexComparator 416 { 417 inline bool operator() ( const DatePlusIndex& aFirst, 418 const DatePlusIndex& aSecond ) 419 { 420 return ( aFirst.fValue < aSecond.fValue ); 421 } 422 }; 423 424 bool lcl_fillDateCategories( const uno::Reference< data::XDataSequence >& xDataSequence, std::vector< DatePlusIndex >& rDateCategories, bool bIsAutoDate, Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier ) 425 { 426 bool bOnlyDatesFound = true; 427 bool bAnyDataFound = false; 428 429 if( xDataSequence.is() ) 430 { 431 uno::Sequence< uno::Any > aValues = xDataSequence->getData(); 432 sal_Int32 nCount = aValues.getLength(); 433 rDateCategories.reserve(nCount); 434 Reference< util::XNumberFormats > xNumberFormats; 435 if( xNumberFormatsSupplier.is() ) 436 xNumberFormats = Reference< util::XNumberFormats >( xNumberFormatsSupplier->getNumberFormats() ); 437 438 bool bOwnData = false; 439 bool bOwnDataAnddAxisHasAnyFormat = false; 440 bool bOwnDataAnddAxisHasDateFormat = false; 441 Reference< chart2::XChartDocument > xChartDoc( xNumberFormatsSupplier, uno::UNO_QUERY ); 442 Reference< XCoordinateSystem > xCooSysModel( ChartModelHelper::getFirstCoordinateSystem( Reference< frame::XModel >( xChartDoc, uno::UNO_QUERY ) ) ); 443 if( xChartDoc.is() && xCooSysModel.is() ) 444 { 445 if( xChartDoc->hasInternalDataProvider() ) 446 { 447 bOwnData = true; 448 Reference< beans::XPropertySet > xAxisProps( xCooSysModel->getAxisByDimension(0,0), uno::UNO_QUERY ); 449 sal_Int32 nAxisNumberFormat = 0; 450 if( xAxisProps.is() && (xAxisProps->getPropertyValue( C2U("NumberFormat") ) >>= nAxisNumberFormat) ) 451 { 452 bOwnDataAnddAxisHasAnyFormat = true; 453 bOwnDataAnddAxisHasDateFormat = DiagramHelper::isDateNumberFormat( nAxisNumberFormat, xNumberFormats ); 454 } 455 } 456 } 457 458 for(sal_Int32 nN=0;nN<nCount;nN++) 459 { 460 bool bIsDate = false; 461 if( bIsAutoDate ) 462 { 463 if( bOwnData ) 464 bIsDate = bOwnDataAnddAxisHasAnyFormat ? bOwnDataAnddAxisHasDateFormat : true; 465 else 466 bIsDate = DiagramHelper::isDateNumberFormat( xDataSequence->getNumberFormatKeyByIndex( nN ), xNumberFormats ); 467 } 468 else 469 bIsDate = true; 470 471 bool bContainsEmptyString = false; 472 bool bContainsNan = false; 473 uno::Any aAny = aValues[nN]; 474 if( aAny.hasValue() ) 475 { 476 OUString aTest; 477 double fTest = 0; 478 if( (aAny>>=aTest) && !aTest.getLength() ) //empty String 479 bContainsEmptyString = true; 480 else if( (aAny>>=fTest) && ::rtl::math::isNan(fTest) ) 481 bContainsNan = true; 482 483 if( !bContainsEmptyString && !bContainsNan ) 484 bAnyDataFound = true; 485 } 486 DatePlusIndex aDatePlusIndex( 1.0, nN ); 487 if( bIsDate && (aAny >>= aDatePlusIndex.fValue) ) 488 rDateCategories.push_back( aDatePlusIndex ); 489 else 490 { 491 if( aAny.hasValue() && !bContainsEmptyString )//empty string does not count as non date value! 492 bOnlyDatesFound=false; 493 ::rtl::math::setNan( &aDatePlusIndex.fValue ); 494 rDateCategories.push_back( aDatePlusIndex ); 495 } 496 } 497 ::std::sort( rDateCategories.begin(), rDateCategories.end(), DatePlusIndexComparator() ); 498 } 499 500 return bAnyDataFound && bOnlyDatesFound; 501 } 502 503 void ExplicitCategoriesProvider::init() 504 { 505 if( m_bDirty ) 506 { 507 m_aComplexCats.clear();//not one per index 508 m_aDateCategories.clear(); 509 510 if( m_xOriginalCategories.is() ) 511 { 512 if( !hasComplexCategories() ) 513 { 514 if(m_bIsDateAxis) 515 { 516 if( ChartTypeHelper::isSupportingDateAxis( AxisHelper::getChartTypeByIndex( m_xCooSysModel, 0 ), 2, 0 ) ) 517 m_bIsDateAxis = lcl_fillDateCategories( m_xOriginalCategories->getValues(), m_aDateCategories, m_bIsAutoDate, Reference< util::XNumberFormatsSupplier >( m_xChartModel.get(), uno::UNO_QUERY ) ); 518 else 519 m_bIsDateAxis = false; 520 } 521 } 522 else 523 { 524 m_bIsDateAxis = false; 525 } 526 } 527 else 528 m_bIsDateAxis=false; 529 m_bDirty = false; 530 } 531 } 532 533 534 Sequence< ::rtl::OUString > ExplicitCategoriesProvider::getSimpleCategories() 535 { 536 if( !m_bIsExplicitCategoriesInited ) 537 { 538 init(); 539 m_aExplicitCategories.realloc(0); 540 if( m_xOriginalCategories.is() ) 541 { 542 if( !hasComplexCategories() ) 543 { 544 uno::Reference< data::XDataSequence > xDataSequence( m_xOriginalCategories->getValues() ); 545 if( xDataSequence.is() ) 546 ExplicitCategoriesProvider::convertCategoryAnysToText( m_aExplicitCategories, xDataSequence->getData(), m_xChartModel ); 547 } 548 else 549 { 550 m_aExplicitCategories = lcl_getExplicitSimpleCategories( 551 SplitCategoriesProvider_ForLabeledDataSequences( m_aSplitCategoriesList, m_xChartModel ), m_aComplexCats ); 552 } 553 } 554 if(!m_aExplicitCategories.getLength()) 555 m_aExplicitCategories = DiagramHelper::generateAutomaticCategoriesFromCooSys( m_xCooSysModel ); 556 m_bIsExplicitCategoriesInited = true; 557 } 558 return m_aExplicitCategories; 559 } 560 561 std::vector< ComplexCategory > ExplicitCategoriesProvider::getCategoriesByLevel( sal_Int32 nLevel ) 562 { 563 std::vector< ComplexCategory > aRet; 564 init(); 565 sal_Int32 nMaxIndex = m_aComplexCats.size()-1; 566 if( nLevel >= 0 && nLevel <= nMaxIndex ) 567 aRet = m_aComplexCats[nMaxIndex-nLevel]; 568 return aRet; 569 } 570 571 OUString ExplicitCategoriesProvider::getCategoryByIndex( 572 const Reference< XCoordinateSystem >& xCooSysModel 573 , const uno::Reference< frame::XModel >& xChartModel 574 , sal_Int32 nIndex ) 575 { 576 if( xCooSysModel.is()) 577 { 578 ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSysModel, xChartModel ); 579 Sequence< OUString > aCategories( aExplicitCategoriesProvider.getSimpleCategories()); 580 if( nIndex < aCategories.getLength()) 581 return aCategories[ nIndex ]; 582 } 583 return OUString(); 584 } 585 586 bool ExplicitCategoriesProvider::isDateAxis() 587 { 588 init(); 589 return m_bIsDateAxis; 590 } 591 592 const std::vector< DatePlusIndex >& ExplicitCategoriesProvider::getDateCategories() 593 { 594 init(); 595 return m_aDateCategories; 596 } 597 598 //............................................................................. 599 } //namespace chart 600 //............................................................................. 601