summaryrefslogtreecommitdiff
path: root/chart2/source/tools/ExplicitCategoriesProvider.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'chart2/source/tools/ExplicitCategoriesProvider.cxx')
-rw-r--r--chart2/source/tools/ExplicitCategoriesProvider.cxx367
1 files changed, 346 insertions, 21 deletions
diff --git a/chart2/source/tools/ExplicitCategoriesProvider.cxx b/chart2/source/tools/ExplicitCategoriesProvider.cxx
index cd4b0334f117..bd1c1bb79813 100644
--- a/chart2/source/tools/ExplicitCategoriesProvider.cxx
+++ b/chart2/source/tools/ExplicitCategoriesProvider.cxx
@@ -31,6 +31,10 @@
#include "ExplicitCategoriesProvider.hxx"
#include "DiagramHelper.hxx"
#include "CommonConverters.hxx"
+#include "DataSourceHelper.hxx"
+#include "ChartModelHelper.hxx"
+#include "ContainerHelper.hxx"
+#include "macros.hxx"
//.............................................................................
namespace chart
@@ -41,18 +45,88 @@ using namespace ::com::sun::star;
using namespace ::com::sun::star::chart2;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
-using rtl::OUString;
+using ::rtl::OUString;
+using ::std::vector;
-ExplicitCategoriesProvider::ExplicitCategoriesProvider( const Reference< chart2::XCoordinateSystem >& xCooSysModel )
+
+ExplicitCategoriesProvider::ExplicitCategoriesProvider( const Reference< chart2::XCoordinateSystem >& xCooSysModel
+ , const uno::Reference< frame::XModel >& xChartModel )
: m_bDirty(true)
, m_xCooSysModel( xCooSysModel )
- , m_xCategories()
+ , m_xOriginalCategories()
{
- if( xCooSysModel.is() )
+ try
+ {
+ if( xCooSysModel.is() )
+ {
+ uno::Reference< XAxis > xAxis( xCooSysModel->getAxisByDimension(0,0) );
+ if( xAxis.is() )
+ m_xOriginalCategories = xAxis->getScaleData().Categories;
+ }
+
+ if( m_xOriginalCategories.is() )
+ {
+ Reference< chart2::XChartDocument > xChartDoc( xChartModel, uno::UNO_QUERY );
+ if( xChartDoc.is() )
+ {
+ uno::Reference< data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() );
+
+ if( xDataProvider.is() )
+ {
+ OUString aCatgoriesRange( DataSourceHelper::getRangeFromValues( m_xOriginalCategories ) );
+ const bool bFirstCellAsLabel = false;
+ const bool bHasCategories = false;
+ const uno::Sequence< sal_Int32 > aSequenceMapping;
+
+ uno::Reference< data::XDataSource > xColumnCategoriesSource( xDataProvider->createDataSource(
+ DataSourceHelper::createArguments( aCatgoriesRange, aSequenceMapping, true /*bUseColumns*/
+ , bFirstCellAsLabel, bHasCategories ) ) );
+
+ uno::Reference< data::XDataSource > xRowCategoriesSource( xDataProvider->createDataSource(
+ DataSourceHelper::createArguments( aCatgoriesRange, aSequenceMapping, false /*bUseColumns*/
+ , bFirstCellAsLabel, bHasCategories ) ) );
+
+ if( xColumnCategoriesSource.is() && xRowCategoriesSource.is() )
+ {
+ Sequence< Reference< data::XLabeledDataSequence> > aColumns = xColumnCategoriesSource->getDataSequences();
+ Sequence< Reference< data::XLabeledDataSequence> > aRows = xRowCategoriesSource->getDataSequences();
+
+ sal_Int32 nColumnCount = aColumns.getLength();
+ sal_Int32 nRowCount = aRows.getLength();
+ if( nColumnCount>1 && nRowCount>1 )
+ {
+ //we have complex categories
+ //->split them in the direction of the first series
+ //detect whether the first series is a row or a column
+ bool bSeriesUsesColumns = true;
+ ::std::vector< Reference< XDataSeries > > aSeries( ChartModelHelper::getDataSeries( xChartModel ) );
+ if( !aSeries.empty() )
+ {
+ uno::Reference< data::XDataSource > xSeriesSource( aSeries.front(), uno::UNO_QUERY );
+ ::rtl::OUString aStringDummy;
+ bool bDummy;
+ uno::Sequence< sal_Int32 > aSeqDummy;
+ DataSourceHelper::readArguments( xDataProvider->detectArguments( xSeriesSource),
+ aStringDummy, aSeqDummy, bSeriesUsesColumns, bDummy, bDummy );
+ }
+ if( bSeriesUsesColumns )
+ m_aSplitCategoriesList=aColumns;
+ else
+ m_aSplitCategoriesList=aRows;
+ }
+ }
+ }
+ }
+ if( !m_aSplitCategoriesList.getLength() )
+ {
+ m_aSplitCategoriesList.realloc(1);
+ m_aSplitCategoriesList[0]=m_xOriginalCategories;
+ }
+ }
+ }
+ catch( const uno::Exception & ex )
{
- uno::Reference< XAxis > xAxis( xCooSysModel->getAxisByDimension(0,0) );
- if( xAxis.is() )
- m_xCategories = xAxis->getScaleData().Categories;
+ ASSERT_EXCEPTION( ex );
}
}
@@ -60,34 +134,285 @@ ExplicitCategoriesProvider::~ExplicitCategoriesProvider()
{
}
-//XTextualDataSequence
-Sequence< ::rtl::OUString > SAL_CALL ExplicitCategoriesProvider::getTextualData() throw( uno::RuntimeException)
+const Sequence< Reference< data::XLabeledDataSequence> >& ExplicitCategoriesProvider::getSplitCategoriesList()
+{
+ return m_aSplitCategoriesList;
+}
+
+bool ExplicitCategoriesProvider::hasComplexCategories() const
+{
+ return m_aSplitCategoriesList.getLength() > 1;
+}
+
+sal_Int32 ExplicitCategoriesProvider::getCategoryLevelCount() const
+{
+ sal_Int32 nCount = m_aSplitCategoriesList.getLength();
+ if(!nCount)
+ nCount = 1;
+ return nCount;
+}
+
+std::vector<sal_Int32> lcl_getLimitingBorders( const std::vector< ComplexCategory >& rComplexCategories )
+{
+ std::vector<sal_Int32> aLimitingBorders;
+ std::vector< ComplexCategory >::const_iterator aIt( rComplexCategories.begin() );
+ std::vector< ComplexCategory >::const_iterator aEnd( rComplexCategories.end() );
+ sal_Int32 nBorderIndex = 0; /*border below the index*/
+ for( ; aIt != aEnd; ++aIt )
+ {
+ ComplexCategory aComplexCategory(*aIt);
+ nBorderIndex += aComplexCategory.Count;
+ aLimitingBorders.push_back(nBorderIndex);
+ }
+ return aLimitingBorders;
+}
+
+uno::Sequence< rtl::OUString > lcl_DataToStringSequence( const uno::Reference< data::XDataSequence >& xDataSequence )
+{
+ uno::Sequence< rtl::OUString > aStrings;
+
+ OSL_ASSERT( xDataSequence.is());
+ if( !xDataSequence.is() )
+ return aStrings;
+
+
+ uno::Reference< data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY );
+ if( xTextualDataSequence.is() )
+ {
+ aStrings = xTextualDataSequence->getTextualData();
+ }
+ else
+ {
+ uno::Sequence< uno::Any > aValues = xDataSequence->getData();
+ aStrings.realloc(aValues.getLength());
+
+ for(sal_Int32 nN=aValues.getLength();nN--;)
+ aValues[nN] >>= aStrings[nN];
+ }
+
+ return aStrings;
+}
+
+SplitCategoriesProvider::~SplitCategoriesProvider()
+{
+}
+
+class SplitCategoriesProvider_ForLabeledDataSequences : public SplitCategoriesProvider
+{
+public:
+
+ explicit SplitCategoriesProvider_ForLabeledDataSequences( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::data::XLabeledDataSequence> >& rSplitCategoriesList )
+ : m_rSplitCategoriesList( rSplitCategoriesList )
+ {}
+ virtual ~SplitCategoriesProvider_ForLabeledDataSequences()
+ {}
+
+ virtual sal_Int32 getLevelCount() const;
+ virtual uno::Sequence< rtl::OUString > getStringsForLevel( sal_Int32 nIndex ) const;
+
+private:
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::data::XLabeledDataSequence> >& m_rSplitCategoriesList;
+};
+
+sal_Int32 SplitCategoriesProvider_ForLabeledDataSequences::getLevelCount() const
+{
+ return m_rSplitCategoriesList.getLength();
+}
+uno::Sequence< rtl::OUString > SplitCategoriesProvider_ForLabeledDataSequences::getStringsForLevel( sal_Int32 nLevel ) const
+{
+ uno::Sequence< rtl::OUString > aRet;
+ Reference< data::XLabeledDataSequence > xLabeledDataSequence( m_rSplitCategoriesList[nLevel] );
+ if( xLabeledDataSequence.is() )
+ aRet = lcl_DataToStringSequence( xLabeledDataSequence->getValues() );
+ return aRet;
+}
+
+std::vector< ComplexCategory > lcl_DataSequenceToComplexCategoryVector(
+ const uno::Sequence< rtl::OUString >& rStrings
+ , const std::vector<sal_Int32>& rLimitingBorders, bool bCreateSingleCategories )
+{
+ std::vector< ComplexCategory > aResult;
+
+ sal_Int32 nMaxCount = rStrings.getLength();
+ OUString aPrevious;
+ sal_Int32 nCurrentCount=0;
+ for( sal_Int32 nN=0; nN<nMaxCount; nN++ )
+ {
+ OUString aCurrent = rStrings[nN];
+ if( bCreateSingleCategories || ::std::find( rLimitingBorders.begin(), rLimitingBorders.end(), nN ) != rLimitingBorders.end() )
+ {
+ aResult.push_back( ComplexCategory(aPrevious,nCurrentCount) );
+ nCurrentCount=1;
+ aPrevious = aCurrent;
+ }
+ else
+ {
+ if( aCurrent.getLength() && aPrevious != aCurrent )
+ {
+ aResult.push_back( ComplexCategory(aPrevious,nCurrentCount) );
+ nCurrentCount=1;
+ aPrevious = aCurrent;
+ }
+ else
+ nCurrentCount++;
+ }
+ }
+ if( nCurrentCount )
+ aResult.push_back( ComplexCategory(aPrevious,nCurrentCount) );
+
+ return aResult;
+}
+
+sal_Int32 lcl_getCategoryCount( std::vector< ComplexCategory >& rComplexCategories )
+{
+ sal_Int32 nCount = 0;
+ std::vector< ComplexCategory >::iterator aIt( rComplexCategories.begin() );
+ std::vector< ComplexCategory >::const_iterator aEnd( rComplexCategories.end() );
+ for( ; aIt != aEnd; ++aIt )
+ nCount+=aIt->Count;
+ return nCount;
+}
+
+Sequence< OUString > lcl_getExplicitSimpleCategories(
+ const SplitCategoriesProvider& rSplitCategoriesProvider,
+ ::std::vector< ::std::vector< ComplexCategory > >& rComplexCats )
+{
+ Sequence< OUString > aRet;
+
+ rComplexCats.clear();
+ sal_Int32 nLCount = rSplitCategoriesProvider.getLevelCount();
+ for( sal_Int32 nL = 0; nL < nLCount; nL++ )
+ {
+ std::vector<sal_Int32> aLimitingBorders;
+ if(nL>0)
+ aLimitingBorders = lcl_getLimitingBorders( rComplexCats.back() );
+ rComplexCats.push_back( lcl_DataSequenceToComplexCategoryVector(
+ rSplitCategoriesProvider.getStringsForLevel(nL), aLimitingBorders, nL==(nLCount-1) ) );
+ }
+
+ std::vector< std::vector< ComplexCategory > >::iterator aOuterIt( rComplexCats.begin() );
+ std::vector< std::vector< ComplexCategory > >::const_iterator aOuterEnd( rComplexCats.end() );
+
+ //ensure that the category count is the same on each level
+ sal_Int32 nMaxCategoryCount = 0;
+ {
+ for( aOuterIt=rComplexCats.begin(); aOuterIt != aOuterEnd; ++aOuterIt )
+ {
+ sal_Int32 nCurrentCount = lcl_getCategoryCount( *aOuterIt );
+ nMaxCategoryCount = std::max( nCurrentCount, nMaxCategoryCount );
+ }
+ for( aOuterIt=rComplexCats.begin(); aOuterIt != aOuterEnd; ++aOuterIt )
+ {
+ sal_Int32 nCurrentCount = lcl_getCategoryCount( *aOuterIt );
+ if( nCurrentCount< nMaxCategoryCount )
+ {
+ ComplexCategory& rComplexCategory = aOuterIt->back();
+ rComplexCategory.Count += (nMaxCategoryCount-nCurrentCount);
+ }
+ }
+ }
+
+ //create a list with an element for every index
+ std::vector< std::vector< ComplexCategory > > aComplexCatsPerIndex;
+ for( aOuterIt=rComplexCats.begin() ; aOuterIt != aOuterEnd; ++aOuterIt )
+ {
+ std::vector< ComplexCategory > aSingleLevel;
+ std::vector< ComplexCategory >::iterator aIt( aOuterIt->begin() );
+ std::vector< ComplexCategory >::const_iterator aEnd( aOuterIt->end() );
+ for( ; aIt != aEnd; ++aIt )
+ {
+ ComplexCategory aComplexCategory( *aIt );
+ sal_Int32 nCount = aComplexCategory.Count;
+ while( nCount-- )
+ aSingleLevel.push_back(aComplexCategory);
+ }
+ aComplexCatsPerIndex.push_back( aSingleLevel );
+ }
+
+ if(nMaxCategoryCount)
+ {
+ aRet.realloc(nMaxCategoryCount);
+ aOuterEnd = aComplexCatsPerIndex.end();
+ OUString aSpace(C2U(" "));
+ for(sal_Int32 nN=0; nN<nMaxCategoryCount; nN++)
+ {
+ OUString aText;
+ for( aOuterIt=aComplexCatsPerIndex.begin() ; aOuterIt != aOuterEnd; ++aOuterIt )
+ {
+ OUString aAddText = (*aOuterIt)[nN].Text;
+ if( aAddText.getLength() )
+ {
+ if(aText.getLength())
+ aText += aSpace;
+ aText += aAddText;
+ }
+ }
+ aRet[nN]=aText;
+ }
+ }
+ return aRet;
+}
+
+//static
+Sequence< OUString > ExplicitCategoriesProvider::getExplicitSimpleCategories(
+ const SplitCategoriesProvider& rSplitCategoriesProvider )
+{
+ vector< vector< ComplexCategory > > aComplexCats;
+ return lcl_getExplicitSimpleCategories( rSplitCategoriesProvider, aComplexCats );
+}
+
+void ExplicitCategoriesProvider::init()
{
if( m_bDirty )
{
- if( m_xCategories.is() )
- m_aExplicitCategories = DataSequenceToStringSequence(m_xCategories->getValues());
+ m_aExplicitCategories.realloc(0);
+ m_aComplexCats.clear();//not one per index
+
+ if( m_xOriginalCategories.is() )
+ {
+ if( !hasComplexCategories() )
+ m_aExplicitCategories = DataSequenceToStringSequence(m_xOriginalCategories->getValues());
+ else
+ m_aExplicitCategories = lcl_getExplicitSimpleCategories(
+ SplitCategoriesProvider_ForLabeledDataSequences( m_aSplitCategoriesList ), m_aComplexCats );
+ }
if(!m_aExplicitCategories.getLength())
- m_aExplicitCategories = DiagramHelper::generateAutomaticCategories( uno::Reference< chart2::XCoordinateSystem >( m_xCooSysModel.get(), uno::UNO_QUERY ) );
+ m_aExplicitCategories = DiagramHelper::generateAutomaticCategoriesFromCooSys( m_xCooSysModel );
m_bDirty = false;
}
+}
+
+
+Sequence< ::rtl::OUString > ExplicitCategoriesProvider::getSimpleCategories()
+{
+ init();
return m_aExplicitCategories;
}
+std::vector< ComplexCategory > ExplicitCategoriesProvider::getCategoriesByLevel( sal_Int32 nLevel )
+{
+ std::vector< ComplexCategory > aRet;
+ init();
+ sal_Int32 nMaxIndex = m_aComplexCats.size()-1;
+ if( nLevel >= 0 && nLevel <= nMaxIndex )
+ aRet = m_aComplexCats[nMaxIndex-nLevel];
+ return aRet;
+}
+
// static
OUString ExplicitCategoriesProvider::getCategoryByIndex(
- const Reference< XCoordinateSystem >& xCooSysModel,
- sal_Int32 nIndex )
+ const Reference< XCoordinateSystem >& xCooSysModel
+ , const uno::Reference< frame::XModel >& xChartModel
+ , sal_Int32 nIndex )
{
if( xCooSysModel.is())
{
- Reference< XTextualDataSequence > xTemp( new ExplicitCategoriesProvider( xCooSysModel ));
- if( xTemp.is())
- {
- Sequence< OUString > aCategories( xTemp->getTextualData());
- if( nIndex < aCategories.getLength())
- return aCategories[ nIndex ];
- }
+ ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSysModel, xChartModel );
+ Sequence< OUString > aCategories( aExplicitCategoriesProvider.getSimpleCategories());
+ if( nIndex < aCategories.getLength())
+ return aCategories[ nIndex ];
}
return OUString();
}