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 
ExplicitCategoriesProvider(const Reference<chart2::XCoordinateSystem> & xCooSysModel,const uno::Reference<frame::XModel> & xChartModel)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 ) );
87*9ec58d04SHerbert Dürr                 if( xDataProvider.is() && !aCatgoriesRange.isEmpty() )
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 
~ExplicitCategoriesProvider()145cdf0e10cSrcweir ExplicitCategoriesProvider::~ExplicitCategoriesProvider()
146cdf0e10cSrcweir {
147cdf0e10cSrcweir }
148cdf0e10cSrcweir 
getOriginalCategories()149cdf0e10cSrcweir Reference< chart2::data::XDataSequence > ExplicitCategoriesProvider::getOriginalCategories()
150cdf0e10cSrcweir {
151cdf0e10cSrcweir     if( m_xOriginalCategories.is() )
152cdf0e10cSrcweir         return m_xOriginalCategories->getValues();
153cdf0e10cSrcweir     return 0;
154cdf0e10cSrcweir }
155cdf0e10cSrcweir 
getSplitCategoriesList()156cdf0e10cSrcweir const Sequence< Reference< data::XLabeledDataSequence> >& ExplicitCategoriesProvider::getSplitCategoriesList()
157cdf0e10cSrcweir {
158cdf0e10cSrcweir     return m_aSplitCategoriesList;
159cdf0e10cSrcweir }
160cdf0e10cSrcweir 
hasComplexCategories() const161cdf0e10cSrcweir bool ExplicitCategoriesProvider::hasComplexCategories() const
162cdf0e10cSrcweir {
163cdf0e10cSrcweir     return m_aSplitCategoriesList.getLength() > 1;
164cdf0e10cSrcweir }
165cdf0e10cSrcweir 
getCategoryLevelCount() const166cdf0e10cSrcweir sal_Int32 ExplicitCategoriesProvider::getCategoryLevelCount() const
167cdf0e10cSrcweir {
168cdf0e10cSrcweir     sal_Int32 nCount = m_aSplitCategoriesList.getLength();
169cdf0e10cSrcweir     if(!nCount)
170cdf0e10cSrcweir         nCount = 1;
171cdf0e10cSrcweir     return nCount;
172cdf0e10cSrcweir }
173cdf0e10cSrcweir 
lcl_getLimitingBorders(const std::vector<ComplexCategory> & rComplexCategories)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 
convertCategoryAnysToText(uno::Sequence<rtl::OUString> & rOutTexts,const uno::Sequence<uno::Any> & rInAnys,Reference<frame::XModel> xChartModel)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 
~SplitCategoriesProvider()236cdf0e10cSrcweir SplitCategoriesProvider::~SplitCategoriesProvider()
237cdf0e10cSrcweir {
238cdf0e10cSrcweir }
239cdf0e10cSrcweir 
240cdf0e10cSrcweir class SplitCategoriesProvider_ForLabeledDataSequences : public SplitCategoriesProvider
241cdf0e10cSrcweir {
242cdf0e10cSrcweir public:
243cdf0e10cSrcweir 
SplitCategoriesProvider_ForLabeledDataSequences(const::com::sun::star::uno::Sequence<::com::sun::star::uno::Reference<::com::sun::star::chart2::data::XLabeledDataSequence>> & rSplitCategoriesList,const Reference<frame::XModel> & xChartModel)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     {}
~SplitCategoriesProvider_ForLabeledDataSequences()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 
getLevelCount() const265cdf0e10cSrcweir sal_Int32 SplitCategoriesProvider_ForLabeledDataSequences::getLevelCount() const
266cdf0e10cSrcweir {
267cdf0e10cSrcweir     return m_rSplitCategoriesList.getLength();
268cdf0e10cSrcweir }
getStringsForLevel(sal_Int32 nLevel) const269cdf0e10cSrcweir 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 
lcl_DataSequenceToComplexCategoryVector(const uno::Sequence<rtl::OUString> & rStrings,const std::vector<sal_Int32> & rLimitingBorders,bool bCreateSingleCategories)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         {
302*9ec58d04SHerbert Dürr             if( !aCurrent.isEmpty() && 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 
lcl_getCategoryCount(std::vector<ComplexCategory> & rComplexCategories)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 
lcl_getExplicitSimpleCategories(const SplitCategoriesProvider & rSplitCategoriesProvider,::std::vector<::std::vector<ComplexCategory>> & rComplexCats)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             {
361703594c7SArmin Le Grand                 if(!aOuterIt->empty()) // #121277# Caution, aOuterIt may be empty (!)
362703594c7SArmin Le Grand                 {
363703594c7SArmin Le Grand                     ComplexCategory& rComplexCategory = aOuterIt->back();
364703594c7SArmin Le Grand                     rComplexCategory.Count += (nMaxCategoryCount-nCurrentCount);
365703594c7SArmin 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             {
397703594c7SArmin Le Grand                 OUString aAddText;
398703594c7SArmin Le Grand 
399703594c7SArmin Le Grand                 if(!aOuterIt->empty()) // #121277# Caution, aOuterIt may be empty (!)
400cdf0e10cSrcweir                 {
401703594c7SArmin Le Grand                     aAddText = (*aOuterIt)[nN].Text;
402*9ec58d04SHerbert Dürr                     if( !aAddText.isEmpty() )
403703594c7SArmin Le Grand                     {
404*9ec58d04SHerbert Dürr                         if( !aText.isEmpty() )
405703594c7SArmin Le Grand                             aText += aSpace;
406703594c7SArmin Le Grand                         aText += aAddText;
407703594c7SArmin Le Grand                     }
408cdf0e10cSrcweir                 }
409cdf0e10cSrcweir             }
410cdf0e10cSrcweir             aRet[nN]=aText;
411cdf0e10cSrcweir         }
412cdf0e10cSrcweir     }
413cdf0e10cSrcweir     return aRet;
414cdf0e10cSrcweir }
415cdf0e10cSrcweir 
getExplicitSimpleCategories(const SplitCategoriesProvider & rSplitCategoriesProvider)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 {
operator ()chart::DatePlusIndexComparator425cdf0e10cSrcweir     inline bool operator() ( const DatePlusIndex& aFirst,
426cdf0e10cSrcweir                              const DatePlusIndex& aSecond )
427cdf0e10cSrcweir     {
428cdf0e10cSrcweir         return ( aFirst.fValue < aSecond.fValue );
429cdf0e10cSrcweir     }
430cdf0e10cSrcweir };
431cdf0e10cSrcweir 
lcl_fillDateCategories(const uno::Reference<data::XDataSequence> & xDataSequence,std::vector<DatePlusIndex> & rDateCategories,bool bIsAutoDate,Reference<util::XNumberFormatsSupplier> xNumberFormatsSupplier)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;
486*9ec58d04SHerbert Dürr                 if( (aAny>>=aTest) && aTest.isEmpty() ) //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 
init()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 
getSimpleCategories()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 
getCategoriesByLevel(sal_Int32 nLevel)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 
getCategoryByIndex(const Reference<XCoordinateSystem> & xCooSysModel,const uno::Reference<frame::XModel> & xChartModel,sal_Int32 nIndex)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 
isDateAxis()594cdf0e10cSrcweir bool ExplicitCategoriesProvider::isDateAxis()
595cdf0e10cSrcweir {
596cdf0e10cSrcweir     init();
597cdf0e10cSrcweir     return m_bIsDateAxis;
598cdf0e10cSrcweir }
599cdf0e10cSrcweir 
getDateCategories()600cdf0e10cSrcweir const std::vector< DatePlusIndex >&  ExplicitCategoriesProvider::getDateCategories()
601cdf0e10cSrcweir {
602cdf0e10cSrcweir     init();
603cdf0e10cSrcweir     return m_aDateCategories;
604cdf0e10cSrcweir }
605cdf0e10cSrcweir 
606cdf0e10cSrcweir //.............................................................................
607cdf0e10cSrcweir } //namespace chart
608cdf0e10cSrcweir //.............................................................................
609