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