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