1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "DataSourceHelper.hxx"
23 #include "ChartModelHelper.hxx"
24 #include "DiagramHelper.hxx"
25 #include "DataSeriesHelper.hxx"
26 #include "DataSource.hxx"
27 #include "ContainerHelper.hxx"
28 #include "ControllerLockGuard.hxx"
29 #include "PropertyHelper.hxx"
30 #include "CachedDataSequence.hxx"
31 #include "LabeledDataSequence.hxx"
33 #include <com/sun/star/chart2/XChartDocument.hpp>
34 #include <com/sun/star/chart2/data/XDataSource.hpp>
35 #include <com/sun/star/chart2/data/XLabeledDataSequence.hpp>
37 #include <com/sun/star/chart/ChartDataRowSource.hpp>
38 #include <com/sun/star/chart/ErrorBarStyle.hpp>
40 //.............................................................................
43 //.............................................................................
44 using namespace ::com::sun::star
;
45 using namespace ::com::sun::star::chart2
;
46 using ::com::sun::star::uno::Reference
;
47 using ::com::sun::star::uno::Sequence
;
51 void lcl_addRanges( ::std::vector
< OUString
> & rOutResult
,
52 const uno::Reference
< data::XLabeledDataSequence
> & xLabeledSeq
)
54 if( ! xLabeledSeq
.is())
56 uno::Reference
< data::XDataSequence
> xSeq( xLabeledSeq
->getLabel());
58 rOutResult
.push_back( xSeq
->getSourceRangeRepresentation());
59 xSeq
.set( xLabeledSeq
->getValues());
61 rOutResult
.push_back( xSeq
->getSourceRangeRepresentation());
64 void lcl_addDataSourceRanges(
65 ::std::vector
< OUString
> & rOutResult
,
66 const uno::Reference
< data::XDataSource
> & xDataSource
)
68 if( xDataSource
.is() )
70 uno::Sequence
< uno::Reference
< data::XLabeledDataSequence
> > aDataSequences( xDataSource
->getDataSequences() );
71 for( sal_Int32 i
=0; i
<aDataSequences
.getLength(); ++i
)
72 lcl_addRanges( rOutResult
, aDataSequences
[i
] );
76 void lcl_addErrorBarRanges(
77 ::std::vector
< OUString
> & rOutResult
,
78 const uno::Reference
< XDataSeries
> & xDataSeries
)
80 uno::Reference
< beans::XPropertySet
> xSeriesProp( xDataSeries
, uno::UNO_QUERY
);
81 if( !xSeriesProp
.is())
86 uno::Reference
< beans::XPropertySet
> xErrorBarProp
;
87 if( ( xSeriesProp
->getPropertyValue( "ErrorBarY") >>= xErrorBarProp
) &&
90 sal_Int32 eStyle
= ::com::sun::star::chart::ErrorBarStyle::NONE
;
91 if( ( xErrorBarProp
->getPropertyValue( "ErrorBarStyle") >>= eStyle
) &&
92 eStyle
== ::com::sun::star::chart::ErrorBarStyle::FROM_DATA
)
94 uno::Reference
< data::XDataSource
> xErrorBarDataSource( xErrorBarProp
, uno::UNO_QUERY
);
95 if( xErrorBarDataSource
.is() )
96 lcl_addDataSourceRanges( rOutResult
, xErrorBarDataSource
);
100 if( ( xSeriesProp
->getPropertyValue("ErrorBarX") >>= xErrorBarProp
) && xErrorBarProp
.is())
102 sal_Int32 eStyle
= ::com::sun::star::chart::ErrorBarStyle::NONE
;
103 if( ( xErrorBarProp
->getPropertyValue("ErrorBarStyle") >>= eStyle
) &&
104 eStyle
== ::com::sun::star::chart::ErrorBarStyle::FROM_DATA
)
106 uno::Reference
< data::XDataSource
> xErrorBarDataSource( xErrorBarProp
, uno::UNO_QUERY
);
107 if( xErrorBarDataSource
.is() )
108 lcl_addDataSourceRanges( rOutResult
, xErrorBarDataSource
);
112 catch( const uno::Exception
& ex
)
114 ASSERT_EXCEPTION( ex
);
118 } // anonymous namespace
120 Reference
< chart2::data::XDataSource
> DataSourceHelper::createDataSource(
121 const Sequence
< Reference
< chart2::data::XLabeledDataSequence
> >& rSequences
)
123 return new DataSource(rSequences
);
126 Reference
< chart2::data::XDataSequence
> DataSourceHelper::createCachedDataSequence()
128 return new ::chart::CachedDataSequence();
131 Reference
< chart2::data::XDataSequence
> DataSourceHelper::createCachedDataSequence( const OUString
& rSingleText
)
133 return new ::chart::CachedDataSequence( rSingleText
);
136 Reference
< chart2::data::XLabeledDataSequence
> DataSourceHelper::createLabeledDataSequence(
137 const Reference
< chart2::data::XDataSequence
>& xValues
,
138 const Reference
< chart2::data::XDataSequence
>& xLabels
)
140 return new ::chart::LabeledDataSequence( xValues
, xLabels
);
143 Reference
< chart2::data::XLabeledDataSequence
> DataSourceHelper::createLabeledDataSequence(
144 const Reference
< chart2::data::XDataSequence
>& xValues
)
146 return new ::chart::LabeledDataSequence( xValues
);
149 Reference
< chart2::data::XLabeledDataSequence
> DataSourceHelper::createLabeledDataSequence(
150 const Reference
< uno::XComponentContext
>& xContext
)
152 return new ::chart::LabeledDataSequence( xContext
);
155 uno::Sequence
< beans::PropertyValue
> DataSourceHelper::createArguments(
156 bool bUseColumns
, bool bFirstCellAsLabel
, bool bHasCategories
)
158 ::com::sun::star::chart::ChartDataRowSource eRowSource
= ::com::sun::star::chart::ChartDataRowSource_ROWS
;
160 eRowSource
= ::com::sun::star::chart::ChartDataRowSource_COLUMNS
;
162 uno::Sequence
< beans::PropertyValue
> aArguments(3);
163 aArguments
[0] = beans::PropertyValue( "DataRowSource"
164 , -1, uno::makeAny( eRowSource
)
165 , beans::PropertyState_DIRECT_VALUE
);
166 aArguments
[1] = beans::PropertyValue( "FirstCellAsLabel"
167 , -1, uno::makeAny( bFirstCellAsLabel
)
168 , beans::PropertyState_DIRECT_VALUE
);
169 aArguments
[2] = beans::PropertyValue( "HasCategories"
170 , -1, uno::makeAny( bHasCategories
)
171 , beans::PropertyState_DIRECT_VALUE
);
176 uno::Sequence
< beans::PropertyValue
> DataSourceHelper::createArguments(
177 const OUString
& rRangeRepresentation
,
178 const uno::Sequence
< sal_Int32
>& rSequenceMapping
,
179 bool bUseColumns
, bool bFirstCellAsLabel
, bool bHasCategories
)
181 uno::Sequence
< beans::PropertyValue
> aArguments( createArguments( bUseColumns
, bFirstCellAsLabel
, bHasCategories
));
182 aArguments
.realloc( aArguments
.getLength() + 1 );
183 aArguments
[aArguments
.getLength() - 1] =
184 beans::PropertyValue( "CellRangeRepresentation"
185 , -1, uno::makeAny( rRangeRepresentation
)
186 , beans::PropertyState_DIRECT_VALUE
);
187 if( rSequenceMapping
.getLength() )
189 aArguments
.realloc( aArguments
.getLength() + 1 );
190 aArguments
[aArguments
.getLength() - 1] =
191 beans::PropertyValue( "SequenceMapping"
192 , -1, uno::makeAny( rSequenceMapping
)
193 , beans::PropertyState_DIRECT_VALUE
);
198 void DataSourceHelper::readArguments( const uno::Sequence
< beans::PropertyValue
>& rArguments
199 , OUString
& rRangeRepresentation
, uno::Sequence
< sal_Int32
>& rSequenceMapping
200 , bool& bUseColumns
, bool& bFirstCellAsLabel
, bool& bHasCategories
)
202 const beans::PropertyValue
* pArguments
= rArguments
.getConstArray();
203 for(sal_Int32 i
=0; i
<rArguments
.getLength(); ++i
, ++pArguments
)
205 const beans::PropertyValue
& aProperty
= *pArguments
;
206 if ( aProperty
.Name
== "DataRowSource" )
208 ::com::sun::star::chart::ChartDataRowSource eRowSource
;
209 if( aProperty
.Value
>>= eRowSource
)
210 bUseColumns
= (eRowSource
==::com::sun::star::chart::ChartDataRowSource_COLUMNS
);
212 else if ( aProperty
.Name
== "FirstCellAsLabel" )
214 aProperty
.Value
>>= bFirstCellAsLabel
;
216 else if ( aProperty
.Name
== "HasCategories" )
218 aProperty
.Value
>>= bHasCategories
;
220 else if ( aProperty
.Name
== "CellRangeRepresentation" )
222 aProperty
.Value
>>= rRangeRepresentation
;
224 else if ( aProperty
.Name
== "SequenceMapping" )
226 aProperty
.Value
>>= rSequenceMapping
;
231 uno::Reference
< chart2::data::XDataSource
> DataSourceHelper::pressUsedDataIntoRectangularFormat(
232 const uno::Reference
< chart2::XChartDocument
>& xChartDoc
, bool bWithCategories
)
234 ::std::vector
< Reference
< chart2::data::XLabeledDataSequence
> > aResultVector
;
236 //categories are always the first sequence
237 Reference
< chart2::XDiagram
> xDiagram( xChartDoc
->getFirstDiagram());
239 if( bWithCategories
)
241 Reference
< chart2::data::XLabeledDataSequence
> xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram
) );
242 if( xCategories
.is() )
243 aResultVector
.push_back( xCategories
);
246 ::std::vector
< Reference
< chart2::XDataSeries
> > xSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram
) );
247 uno::Reference
< chart2::data::XDataSource
> xSeriesSource(
248 DataSeriesHelper::getDataSource( ContainerHelper::ContainerToSequence(xSeriesVector
) ) );
249 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aDataSeqences( xSeriesSource
->getDataSequences() );
251 //the first x-values is always the next sequence //todo ... other x-values get lost for old format
252 Reference
< chart2::data::XLabeledDataSequence
> xXValues(
253 DataSeriesHelper::getDataSequenceByRole( xSeriesSource
, "values-x" ) );
255 aResultVector
.push_back( xXValues
);
257 //add all other sequences now without x-values
258 for( sal_Int32 nN
=0; nN
<aDataSeqences
.getLength(); nN
++ )
260 OUString
aRole( DataSeriesHelper::GetRole( aDataSeqences
[nN
] ) );
261 if( !aRole
.equals("values-x") )
262 aResultVector
.push_back( aDataSeqences
[nN
] );
265 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aResultSequence( aResultVector
.size() );
266 ::std::copy( aResultVector
.begin(), aResultVector
.end(), aResultSequence
.getArray() );
268 return new DataSource( aResultSequence
);
271 uno::Sequence
< OUString
> DataSourceHelper::getUsedDataRanges(
272 const uno::Reference
< chart2::XDiagram
> & xDiagram
)
274 ::std::vector
< OUString
> aResult
;
278 uno::Reference
< data::XLabeledDataSequence
> xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram
) );
279 if( xCategories
.is() )
280 lcl_addRanges( aResult
, xCategories
);
282 ::std::vector
< uno::Reference
< XDataSeries
> > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram
) );
283 for( ::std::vector
< uno::Reference
< XDataSeries
> >::const_iterator
aSeriesIt( aSeriesVector
.begin() )
284 ; aSeriesIt
!= aSeriesVector
.end(); ++aSeriesIt
)
286 uno::Reference
< data::XDataSource
> xDataSource( *aSeriesIt
, uno::UNO_QUERY
);
287 lcl_addDataSourceRanges( aResult
, xDataSource
);
288 lcl_addErrorBarRanges( aResult
, *aSeriesIt
);
292 return ContainerHelper::ContainerToSequence( aResult
);
295 uno::Sequence
< OUString
> DataSourceHelper::getUsedDataRanges( const uno::Reference
< frame::XModel
> & xChartModel
)
297 uno::Reference
< XDiagram
> xDiagram( ChartModelHelper::findDiagram( xChartModel
) );
298 return getUsedDataRanges( xDiagram
);
301 uno::Reference
< chart2::data::XDataSource
> DataSourceHelper::getUsedData(
302 const uno::Reference
< chart2::XChartDocument
>& xChartDoc
)
304 return pressUsedDataIntoRectangularFormat( xChartDoc
);
307 uno::Reference
< chart2::data::XDataSource
> DataSourceHelper::getUsedData(
308 const uno::Reference
< frame::XModel
>& xChartModel
)
310 ::std::vector
< uno::Reference
< chart2::data::XLabeledDataSequence
> > aResult
;
312 uno::Reference
< XDiagram
> xDiagram( ChartModelHelper::findDiagram( xChartModel
) );
313 uno::Reference
< data::XLabeledDataSequence
> xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram
) );
314 if( xCategories
.is() )
315 aResult
.push_back( xCategories
);
317 ::std::vector
< uno::Reference
< XDataSeries
> > aSeriesVector( ChartModelHelper::getDataSeries( xChartModel
) );
318 for( ::std::vector
< uno::Reference
< XDataSeries
> >::const_iterator
aSeriesIt( aSeriesVector
.begin() )
319 ; aSeriesIt
!= aSeriesVector
.end(); ++aSeriesIt
)
321 uno::Reference
< data::XDataSource
> xDataSource( *aSeriesIt
, uno::UNO_QUERY
);
322 if( !xDataSource
.is() )
324 uno::Sequence
< uno::Reference
< data::XLabeledDataSequence
> > aDataSequences( xDataSource
->getDataSequences() );
325 ::std::copy( aDataSequences
.getConstArray(), aDataSequences
.getConstArray() + aDataSequences
.getLength(),
326 ::std::back_inserter( aResult
));
329 return uno::Reference
< chart2::data::XDataSource
>(
330 new DataSource( ContainerHelper::ContainerToSequence( aResult
)));
333 bool DataSourceHelper::detectRangeSegmentation(
334 const uno::Reference
<
335 frame::XModel
>& xChartModel
336 , OUString
& rOutRangeString
337 , ::com::sun::star::uno::Sequence
< sal_Int32
>& rSequenceMapping
338 , bool& rOutUseColumns
339 , bool& rOutFirstCellAsLabel
340 , bool& rOutHasCategories
)
342 bool bSomethingDetected
= false;
344 uno::Reference
< XChartDocument
> xChartDocument( xChartModel
, uno::UNO_QUERY
);
345 if( !xChartDocument
.is() )
346 return bSomethingDetected
;
347 uno::Reference
< data::XDataProvider
> xDataProvider( xChartDocument
->getDataProvider() );
348 if( !xDataProvider
.is() )
349 return bSomethingDetected
;
353 DataSourceHelper::readArguments(
354 xDataProvider
->detectArguments( pressUsedDataIntoRectangularFormat( xChartDocument
) ),
355 rOutRangeString
, rSequenceMapping
, rOutUseColumns
, rOutFirstCellAsLabel
, rOutHasCategories
);
356 bSomethingDetected
= !rOutRangeString
.isEmpty();
358 uno::Reference
< chart2::data::XLabeledDataSequence
> xCategories(
359 DiagramHelper::getCategoriesFromDiagram( xChartDocument
->getFirstDiagram() ));
360 rOutHasCategories
= xCategories
.is();
362 catch( uno::Exception
& ex
)
364 ASSERT_EXCEPTION( ex
);
366 return bSomethingDetected
;
369 bool DataSourceHelper::allArgumentsForRectRangeDetected(
370 const uno::Reference
< chart2::XChartDocument
>& xChartDocument
)
372 bool bHasDataRowSource
= false;
373 bool bHasFirstCellAsLabel
= false;
374 bool bHasCellRangeRepresentation
= false;
376 uno::Reference
< data::XDataProvider
> xDataProvider( xChartDocument
->getDataProvider() );
377 if( !xDataProvider
.is() )
382 const uno::Sequence
< beans::PropertyValue
> aArguments(
383 xDataProvider
->detectArguments( pressUsedDataIntoRectangularFormat( xChartDocument
)));
384 const beans::PropertyValue
* pArguments
= aArguments
.getConstArray();
385 for(sal_Int32 i
=0; i
<aArguments
.getLength(); ++i
, ++pArguments
)
387 const beans::PropertyValue
& aProperty
= *pArguments
;
388 if ( aProperty
.Name
== "DataRowSource" )
391 (aProperty
.Value
.hasValue() && aProperty
.Value
.isExtractableTo(
392 ::getCppuType( reinterpret_cast<
393 const ::com::sun::star::chart::ChartDataRowSource
* >(0))));
395 else if ( aProperty
.Name
== "FirstCellAsLabel" )
397 bHasFirstCellAsLabel
=
398 (aProperty
.Value
.hasValue() && aProperty
.Value
.isExtractableTo(::getBooleanCppuType()));
400 else if ( aProperty
.Name
== "CellRangeRepresentation" )
403 bHasCellRangeRepresentation
=
404 (aProperty
.Value
.hasValue() && (aProperty
.Value
>>= aRange
) && !aRange
.isEmpty());
408 catch( const uno::Exception
& ex
)
410 ASSERT_EXCEPTION( ex
);
413 return (bHasCellRangeRepresentation
&& bHasDataRowSource
&& bHasFirstCellAsLabel
);
416 void DataSourceHelper::setRangeSegmentation(
417 const uno::Reference
< frame::XModel
>& xChartModel
418 , const ::com::sun::star::uno::Sequence
< sal_Int32
>& rSequenceMapping
419 , bool bUseColumns
, bool bFirstCellAsLabel
, bool bUseCategories
)
421 uno::Reference
< XChartDocument
> xChartDocument( xChartModel
, uno::UNO_QUERY
);
422 if( !xChartDocument
.is() )
424 uno::Reference
< data::XDataProvider
> xDataProvider( xChartDocument
->getDataProvider() );
425 if( !xDataProvider
.is() )
427 uno::Reference
< XDiagram
> xDiagram( ChartModelHelper::findDiagram( xChartModel
) );
430 uno::Reference
< chart2::XChartTypeManager
> xChartTypeManager( xChartDocument
->getChartTypeManager() );
431 if( !xChartTypeManager
.is() )
433 uno::Reference
< lang::XMultiServiceFactory
> xTemplateFactory( xChartTypeManager
, uno::UNO_QUERY
);
434 if( !xTemplateFactory
.is() )
437 OUString aRangeString
;
439 uno::Sequence
< sal_Int32
> aDummy
;
440 readArguments( xDataProvider
->detectArguments( pressUsedDataIntoRectangularFormat( xChartDocument
)),
441 aRangeString
, aDummy
, bDummy
, bDummy
, bDummy
);
443 uno::Sequence
< beans::PropertyValue
> aArguments(
444 createArguments( aRangeString
, rSequenceMapping
, bUseColumns
, bFirstCellAsLabel
, bUseCategories
) );
446 uno::Reference
< chart2::data::XDataSource
> xDataSource( xDataProvider
->createDataSource(
448 if( !xDataSource
.is() )
451 ControllerLockGuard
aCtrlLockGuard( xChartModel
);
452 xDiagram
->setDiagramData( xDataSource
, aArguments
);
455 Sequence
< OUString
> DataSourceHelper::getRangesFromLabeledDataSequence(
456 const Reference
< data::XLabeledDataSequence
> & xLSeq
)
458 Sequence
< OUString
> aResult
;
461 Reference
< data::XDataSequence
> xLabel( xLSeq
->getLabel());
462 Reference
< data::XDataSequence
> xValues( xLSeq
->getValues());
468 aResult
.realloc( 2 );
469 aResult
[0] = xLabel
->getSourceRangeRepresentation();
470 aResult
[1] = xValues
->getSourceRangeRepresentation();
474 aResult
.realloc( 1 );
475 aResult
[0] = xLabel
->getSourceRangeRepresentation();
478 else if( xValues
.is())
480 aResult
.realloc( 1 );
481 aResult
[0] = xValues
->getSourceRangeRepresentation();
487 OUString
DataSourceHelper::getRangeFromValues(
488 const Reference
< data::XLabeledDataSequence
> & xLSeq
)
493 Reference
< data::XDataSequence
> xValues( xLSeq
->getValues() );
495 aResult
= xValues
->getSourceRangeRepresentation();
500 Sequence
< OUString
> DataSourceHelper::getRangesFromDataSource( const Reference
< data::XDataSource
> & xSource
)
502 ::std::vector
< OUString
> aResult
;
505 Sequence
< Reference
< data::XLabeledDataSequence
> > aLSeqSeq( xSource
->getDataSequences());
506 for( sal_Int32 i
=0; i
<aLSeqSeq
.getLength(); ++i
)
508 Reference
< data::XDataSequence
> xLabel( aLSeqSeq
[i
]->getLabel());
509 Reference
< data::XDataSequence
> xValues( aLSeqSeq
[i
]->getValues());
512 aResult
.push_back( xLabel
->getSourceRangeRepresentation());
514 aResult
.push_back( xValues
->getSourceRangeRepresentation());
517 return ContainerHelper::ContainerToSequence( aResult
);
520 //.............................................................................
522 //.............................................................................
524 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */