1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_chart2.hxx"
31 #include "DataSourceHelper.hxx"
33 #include "ChartModelHelper.hxx"
34 #include "DiagramHelper.hxx"
35 #include "DataSeriesHelper.hxx"
36 #include "DataSource.hxx"
37 #include "ContainerHelper.hxx"
38 #include "ControllerLockGuard.hxx"
39 #include "PropertyHelper.hxx"
40 #include "CachedDataSequence.hxx"
41 #include "LabeledDataSequence.hxx"
43 #include <com/sun/star/chart2/XChartDocument.hpp>
44 #include <com/sun/star/chart2/data/XDataSource.hpp>
45 #include <com/sun/star/chart2/data/XLabeledDataSequence.hpp>
47 #include <com/sun/star/chart/ChartDataRowSource.hpp>
48 #include <com/sun/star/chart/ErrorBarStyle.hpp>
50 //.............................................................................
53 //.............................................................................
54 using namespace ::com::sun::star
;
55 using namespace ::com::sun::star::chart2
;
56 using ::com::sun::star::uno::Reference
;
57 using ::com::sun::star::uno::Sequence
;
58 using ::rtl::OUString
;
62 void lcl_addRanges( ::std::vector
< ::rtl::OUString
> & rOutResult
,
63 const uno::Reference
< data::XLabeledDataSequence
> & xLabeledSeq
)
65 if( ! xLabeledSeq
.is())
67 uno::Reference
< data::XDataSequence
> xSeq( xLabeledSeq
->getLabel());
69 rOutResult
.push_back( xSeq
->getSourceRangeRepresentation());
70 xSeq
.set( xLabeledSeq
->getValues());
72 rOutResult
.push_back( xSeq
->getSourceRangeRepresentation());
75 void lcl_addDataSourceRanges(
76 ::std::vector
< ::rtl::OUString
> & rOutResult
,
77 const uno::Reference
< data::XDataSource
> & xDataSource
)
79 if( xDataSource
.is() )
81 uno::Sequence
< uno::Reference
< data::XLabeledDataSequence
> > aDataSequences( xDataSource
->getDataSequences() );
82 for( sal_Int32 i
=0; i
<aDataSequences
.getLength(); ++i
)
83 lcl_addRanges( rOutResult
, aDataSequences
[i
] );
87 void lcl_addErrorBarRanges(
88 ::std::vector
< ::rtl::OUString
> & rOutResult
,
89 const uno::Reference
< XDataSeries
> & xDataSeries
)
91 uno::Reference
< beans::XPropertySet
> xSeriesProp( xDataSeries
, uno::UNO_QUERY
);
92 if( !xSeriesProp
.is())
97 uno::Reference
< beans::XPropertySet
> xErrorBarProp
;
98 if( ( xSeriesProp
->getPropertyValue( C2U("ErrorBarY")) >>= xErrorBarProp
) &&
101 sal_Int32 eStyle
= ::com::sun::star::chart::ErrorBarStyle::NONE
;
102 if( ( xErrorBarProp
->getPropertyValue( C2U("ErrorBarStyle")) >>= eStyle
) &&
103 eStyle
== ::com::sun::star::chart::ErrorBarStyle::FROM_DATA
)
105 uno::Reference
< data::XDataSource
> xErrorBarDataSource( xErrorBarProp
, uno::UNO_QUERY
);
106 if( xErrorBarDataSource
.is() )
107 lcl_addDataSourceRanges( rOutResult
, xErrorBarDataSource
);
111 catch( const uno::Exception
& ex
)
113 ASSERT_EXCEPTION( ex
);
117 } // anonymous namespace
119 Reference
< chart2::data::XDataSource
> DataSourceHelper::createDataSource(
120 const Sequence
< Reference
< chart2::data::XLabeledDataSequence
> >& rSequences
)
122 return new DataSource(rSequences
);
125 Reference
< chart2::data::XDataSequence
> DataSourceHelper::createCachedDataSequence()
127 return new ::chart::CachedDataSequence();
130 Reference
< chart2::data::XDataSequence
> DataSourceHelper::createCachedDataSequence( const ::rtl::OUString
& rSingleText
)
132 return new ::chart::CachedDataSequence( rSingleText
);
135 Reference
< chart2::data::XLabeledDataSequence
> DataSourceHelper::createLabeledDataSequence(
136 const Reference
< chart2::data::XDataSequence
>& xValues
,
137 const Reference
< chart2::data::XDataSequence
>& xLabels
)
139 return new ::chart::LabeledDataSequence( xValues
, xLabels
);
142 Reference
< chart2::data::XLabeledDataSequence
> DataSourceHelper::createLabeledDataSequence(
143 const Reference
< chart2::data::XDataSequence
>& xValues
)
145 return new ::chart::LabeledDataSequence( xValues
);
148 Reference
< chart2::data::XLabeledDataSequence
> DataSourceHelper::createLabeledDataSequence(
149 const Reference
< uno::XComponentContext
>& xContext
)
151 return new ::chart::LabeledDataSequence( xContext
);
154 uno::Sequence
< beans::PropertyValue
> DataSourceHelper::createArguments(
155 bool bUseColumns
, bool bFirstCellAsLabel
, bool bHasCategories
)
157 ::com::sun::star::chart::ChartDataRowSource eRowSource
= ::com::sun::star::chart::ChartDataRowSource_ROWS
;
159 eRowSource
= ::com::sun::star::chart::ChartDataRowSource_COLUMNS
;
161 uno::Sequence
< beans::PropertyValue
> aArguments(3);
162 aArguments
[0] = beans::PropertyValue( C2U("DataRowSource")
163 , -1, uno::makeAny( eRowSource
)
164 , beans::PropertyState_DIRECT_VALUE
);
165 aArguments
[1] = beans::PropertyValue( C2U("FirstCellAsLabel")
166 , -1, uno::makeAny( bFirstCellAsLabel
)
167 , beans::PropertyState_DIRECT_VALUE
);
168 aArguments
[2] = beans::PropertyValue( C2U("HasCategories")
169 , -1, uno::makeAny( bHasCategories
)
170 , beans::PropertyState_DIRECT_VALUE
);
175 uno::Sequence
< beans::PropertyValue
> DataSourceHelper::createArguments(
176 const ::rtl::OUString
& rRangeRepresentation
,
177 const uno::Sequence
< sal_Int32
>& rSequenceMapping
,
178 bool bUseColumns
, bool bFirstCellAsLabel
, bool bHasCategories
)
180 uno::Sequence
< beans::PropertyValue
> aArguments( createArguments( bUseColumns
, bFirstCellAsLabel
, bHasCategories
));
181 aArguments
.realloc( aArguments
.getLength() + 1 );
182 aArguments
[aArguments
.getLength() - 1] =
183 beans::PropertyValue( C2U("CellRangeRepresentation")
184 , -1, uno::makeAny( rRangeRepresentation
)
185 , beans::PropertyState_DIRECT_VALUE
);
186 if( rSequenceMapping
.getLength() )
188 aArguments
.realloc( aArguments
.getLength() + 1 );
189 aArguments
[aArguments
.getLength() - 1] =
190 beans::PropertyValue( C2U("SequenceMapping")
191 , -1, uno::makeAny( rSequenceMapping
)
192 , beans::PropertyState_DIRECT_VALUE
);
197 void DataSourceHelper::readArguments( const uno::Sequence
< beans::PropertyValue
>& rArguments
198 , ::rtl::OUString
& rRangeRepresentation
, uno::Sequence
< sal_Int32
>& rSequenceMapping
199 , bool& bUseColumns
, bool& bFirstCellAsLabel
, bool& bHasCategories
)
201 const beans::PropertyValue
* pArguments
= rArguments
.getConstArray();
202 for(sal_Int32 i
=0; i
<rArguments
.getLength(); ++i
, ++pArguments
)
204 const beans::PropertyValue
& aProperty
= *pArguments
;
205 if( aProperty
.Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "DataRowSource" ) ))
207 ::com::sun::star::chart::ChartDataRowSource eRowSource
;
208 if( aProperty
.Value
>>= eRowSource
)
209 bUseColumns
= (eRowSource
==::com::sun::star::chart::ChartDataRowSource_COLUMNS
);
211 else if( aProperty
.Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "FirstCellAsLabel" ) ))
213 aProperty
.Value
>>= bFirstCellAsLabel
;
215 else if( aProperty
.Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "HasCategories" ) ))
217 aProperty
.Value
>>= bHasCategories
;
219 else if( aProperty
.Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CellRangeRepresentation" ) ))
221 aProperty
.Value
>>= rRangeRepresentation
;
223 else if( aProperty
.Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "SequenceMapping" ) ))
225 aProperty
.Value
>>= rSequenceMapping
;
230 uno::Reference
< chart2::data::XDataSource
> DataSourceHelper::pressUsedDataIntoRectangularFormat(
231 const uno::Reference
< chart2::XChartDocument
>& xChartDoc
, bool bWithCategories
)
233 ::std::vector
< Reference
< chart2::data::XLabeledDataSequence
> > aResultVector
;
235 //categories are always the first sequence
236 Reference
< chart2::XDiagram
> xDiagram( xChartDoc
->getFirstDiagram());
238 if( bWithCategories
)
240 Reference
< chart2::data::XLabeledDataSequence
> xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram
) );
241 if( xCategories
.is() )
242 aResultVector
.push_back( xCategories
);
245 ::std::vector
< Reference
< chart2::XDataSeries
> > xSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram
) );
246 uno::Reference
< chart2::data::XDataSource
> xSeriesSource(
247 DataSeriesHelper::getDataSource( ContainerHelper::ContainerToSequence(xSeriesVector
) ) );
248 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aDataSeqences( xSeriesSource
->getDataSequences() );
250 //the first x-values is always the next sequence //todo ... other x-values get lost for old format
251 Reference
< chart2::data::XLabeledDataSequence
> xXValues(
252 DataSeriesHelper::getDataSequenceByRole( xSeriesSource
, C2U("values-x") ) );
254 aResultVector
.push_back( xXValues
);
256 //add all other sequences now without x-values
257 for( sal_Int32 nN
=0; nN
<aDataSeqences
.getLength(); nN
++ )
259 OUString
aRole( DataSeriesHelper::GetRole( aDataSeqences
[nN
] ) );
260 if( !aRole
.equals(C2U("values-x")) )
261 aResultVector
.push_back( aDataSeqences
[nN
] );
264 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aResultSequence( aResultVector
.size() );
265 ::std::copy( aResultVector
.begin(), aResultVector
.end(), aResultSequence
.getArray() );
267 return new DataSource( aResultSequence
);
270 uno::Sequence
< ::rtl::OUString
> DataSourceHelper::getUsedDataRanges(
271 const uno::Reference
< chart2::XDiagram
> & xDiagram
)
273 ::std::vector
< ::rtl::OUString
> aResult
;
277 uno::Reference
< data::XLabeledDataSequence
> xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram
) );
278 if( xCategories
.is() )
279 lcl_addRanges( aResult
, xCategories
);
281 ::std::vector
< uno::Reference
< XDataSeries
> > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram
) );
282 for( ::std::vector
< uno::Reference
< XDataSeries
> >::const_iterator
aSeriesIt( aSeriesVector
.begin() )
283 ; aSeriesIt
!= aSeriesVector
.end(); ++aSeriesIt
)
285 uno::Reference
< data::XDataSource
> xDataSource( *aSeriesIt
, uno::UNO_QUERY
);
286 lcl_addDataSourceRanges( aResult
, xDataSource
);
287 lcl_addErrorBarRanges( aResult
, *aSeriesIt
);
291 return ContainerHelper::ContainerToSequence( aResult
);
294 uno::Sequence
< ::rtl::OUString
> DataSourceHelper::getUsedDataRanges( const uno::Reference
< frame::XModel
> & xChartModel
)
296 uno::Reference
< XDiagram
> xDiagram( ChartModelHelper::findDiagram( xChartModel
) );
297 return getUsedDataRanges( xDiagram
);
300 uno::Reference
< chart2::data::XDataSource
> DataSourceHelper::getUsedData(
301 const uno::Reference
< chart2::XChartDocument
>& xChartDoc
)
303 return pressUsedDataIntoRectangularFormat( xChartDoc
);
306 uno::Reference
< chart2::data::XDataSource
> DataSourceHelper::getUsedData(
307 const uno::Reference
< frame::XModel
>& xChartModel
)
309 ::std::vector
< uno::Reference
< chart2::data::XLabeledDataSequence
> > aResult
;
311 uno::Reference
< XDiagram
> xDiagram( ChartModelHelper::findDiagram( xChartModel
) );
312 uno::Reference
< data::XLabeledDataSequence
> xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram
) );
313 if( xCategories
.is() )
314 aResult
.push_back( xCategories
);
316 ::std::vector
< uno::Reference
< XDataSeries
> > aSeriesVector( ChartModelHelper::getDataSeries( xChartModel
) );
317 for( ::std::vector
< uno::Reference
< XDataSeries
> >::const_iterator
aSeriesIt( aSeriesVector
.begin() )
318 ; aSeriesIt
!= aSeriesVector
.end(); ++aSeriesIt
)
320 uno::Reference
< data::XDataSource
> xDataSource( *aSeriesIt
, uno::UNO_QUERY
);
321 if( !xDataSource
.is() )
323 uno::Sequence
< uno::Reference
< data::XLabeledDataSequence
> > aDataSequences( xDataSource
->getDataSequences() );
324 ::std::copy( aDataSequences
.getConstArray(), aDataSequences
.getConstArray() + aDataSequences
.getLength(),
325 ::std::back_inserter( aResult
));
328 return uno::Reference
< chart2::data::XDataSource
>(
329 new DataSource( ContainerHelper::ContainerToSequence( aResult
)));
332 bool DataSourceHelper::detectRangeSegmentation(
333 const uno::Reference
<
334 frame::XModel
>& xChartModel
335 , ::rtl::OUString
& rOutRangeString
336 , ::com::sun::star::uno::Sequence
< sal_Int32
>& rSequenceMapping
337 , bool& rOutUseColumns
338 , bool& rOutFirstCellAsLabel
339 , bool& rOutHasCategories
)
341 bool bSomethingDetected
= false;
343 uno::Reference
< XChartDocument
> xChartDocument( xChartModel
, uno::UNO_QUERY
);
344 if( !xChartDocument
.is() )
345 return bSomethingDetected
;
346 uno::Reference
< data::XDataProvider
> xDataProvider( xChartDocument
->getDataProvider() );
347 if( !xDataProvider
.is() )
348 return bSomethingDetected
;
352 DataSourceHelper::readArguments(
353 xDataProvider
->detectArguments( pressUsedDataIntoRectangularFormat( xChartDocument
) ),
354 rOutRangeString
, rSequenceMapping
, rOutUseColumns
, rOutFirstCellAsLabel
, rOutHasCategories
);
355 bSomethingDetected
= (rOutRangeString
.getLength() > 0);
357 uno::Reference
< chart2::data::XLabeledDataSequence
> xCategories(
358 DiagramHelper::getCategoriesFromDiagram( xChartDocument
->getFirstDiagram() ));
359 rOutHasCategories
= xCategories
.is();
361 catch( uno::Exception
& ex
)
363 ASSERT_EXCEPTION( ex
);
365 return bSomethingDetected
;
368 bool DataSourceHelper::allArgumentsForRectRangeDetected(
369 const uno::Reference
< chart2::XChartDocument
>& xChartDocument
)
371 bool bHasDataRowSource
= false;
372 bool bHasFirstCellAsLabel
= false;
373 // bool bHasHasCategories = false;
374 bool bHasCellRangeRepresentation
= false;
375 // bool bHasSequenceMapping = false;
377 uno::Reference
< data::XDataProvider
> xDataProvider( xChartDocument
->getDataProvider() );
378 if( !xDataProvider
.is() )
383 const uno::Sequence
< beans::PropertyValue
> aArguments(
384 xDataProvider
->detectArguments( pressUsedDataIntoRectangularFormat( xChartDocument
)));
385 const beans::PropertyValue
* pArguments
= aArguments
.getConstArray();
386 for(sal_Int32 i
=0; i
<aArguments
.getLength(); ++i
, ++pArguments
)
388 const beans::PropertyValue
& aProperty
= *pArguments
;
389 if( aProperty
.Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "DataRowSource" ) ))
392 (aProperty
.Value
.hasValue() && aProperty
.Value
.isExtractableTo(
393 ::getCppuType( reinterpret_cast<
394 const ::com::sun::star::chart::ChartDataRowSource
* >(0))));
396 else if( aProperty
.Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "FirstCellAsLabel" ) ))
398 bHasFirstCellAsLabel
=
399 (aProperty
.Value
.hasValue() && aProperty
.Value
.isExtractableTo(::getBooleanCppuType()));
401 // else if( aProperty.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "HasCategories" ) ))
403 // bHasHasCategories =
404 // (aProperty.Value.hasValue() && aProperty.Value.isExtractableTo(::getBooleanCppuType()));
406 else if( aProperty
.Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CellRangeRepresentation" ) ))
408 ::rtl::OUString aRange
;
409 bHasCellRangeRepresentation
=
410 (aProperty
.Value
.hasValue() && (aProperty
.Value
>>= aRange
) && aRange
.getLength() > 0);
412 // else if( aProperty.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "SequenceMapping" ) ))
414 // bHasSequenceMapping =
415 // (aProperty.Value.hasValue() && aProperty.Value.isExtractableTo(
416 // ::getCppuType( reinterpret_cast<
417 // const uno::Sequence< sal_Int32 > * >(0))));
421 catch( const uno::Exception
& ex
)
423 ASSERT_EXCEPTION( ex
);
426 return (bHasCellRangeRepresentation
&& bHasDataRowSource
&& bHasFirstCellAsLabel
);
429 void DataSourceHelper::setRangeSegmentation(
430 const uno::Reference
< frame::XModel
>& xChartModel
431 , const ::com::sun::star::uno::Sequence
< sal_Int32
>& rSequenceMapping
432 , bool bUseColumns
, bool bFirstCellAsLabel
, bool bUseCategories
)
434 uno::Reference
< XChartDocument
> xChartDocument( xChartModel
, uno::UNO_QUERY
);
435 if( !xChartDocument
.is() )
437 uno::Reference
< data::XDataProvider
> xDataProvider( xChartDocument
->getDataProvider() );
438 if( !xDataProvider
.is() )
440 uno::Reference
< XDiagram
> xDiagram( ChartModelHelper::findDiagram( xChartModel
) );
443 uno::Reference
< chart2::XChartTypeManager
> xChartTypeManager( xChartDocument
->getChartTypeManager() );
444 if( !xChartTypeManager
.is() )
446 uno::Reference
< lang::XMultiServiceFactory
> xTemplateFactory( xChartTypeManager
, uno::UNO_QUERY
);
447 if( !xTemplateFactory
.is() )
450 ::rtl::OUString aRangeString
;
452 uno::Sequence
< sal_Int32
> aDummy
;
453 readArguments( xDataProvider
->detectArguments( pressUsedDataIntoRectangularFormat( xChartDocument
)),
454 aRangeString
, aDummy
, bDummy
, bDummy
, bDummy
);
456 uno::Sequence
< beans::PropertyValue
> aArguments(
457 createArguments( aRangeString
, rSequenceMapping
, bUseColumns
, bFirstCellAsLabel
, bUseCategories
) );
459 uno::Reference
< chart2::data::XDataSource
> xDataSource( xDataProvider
->createDataSource(
461 if( !xDataSource
.is() )
464 DiagramHelper::tTemplateWithServiceName aTemplateAndService
=
465 DiagramHelper::getTemplateForDiagram( xDiagram
, xTemplateFactory
);
467 rtl::OUString
aServiceName( aTemplateAndService
.second
);
468 uno::Reference
< chart2::XChartTypeTemplate
> xTemplate
= aTemplateAndService
.first
;
470 if( !xTemplate
.is() )
472 if( aServiceName
.getLength() == 0 )
473 aServiceName
= C2U("com.sun.star.chart2.template.Column");
474 xTemplate
.set( xTemplateFactory
->createInstance( aServiceName
), uno::UNO_QUERY
);
476 if( !xTemplate
.is() )
479 // /-- locked controllers
480 ControllerLockGuard
aCtrlLockGuard( xChartModel
);
481 xTemplate
->changeDiagramData( xDiagram
, xDataSource
, aArguments
);
482 // \-- locked controllers
485 Sequence
< OUString
> DataSourceHelper::getRangesFromLabeledDataSequence(
486 const Reference
< data::XLabeledDataSequence
> & xLSeq
)
488 Sequence
< OUString
> aResult
;
491 Reference
< data::XDataSequence
> xLabel( xLSeq
->getLabel());
492 Reference
< data::XDataSequence
> xValues( xLSeq
->getValues());
498 aResult
.realloc( 2 );
499 aResult
[0] = xLabel
->getSourceRangeRepresentation();
500 aResult
[1] = xValues
->getSourceRangeRepresentation();
504 aResult
.realloc( 1 );
505 aResult
[0] = xLabel
->getSourceRangeRepresentation();
508 else if( xValues
.is())
510 aResult
.realloc( 1 );
511 aResult
[0] = xValues
->getSourceRangeRepresentation();
517 OUString
DataSourceHelper::getRangeFromValues(
518 const Reference
< data::XLabeledDataSequence
> & xLSeq
)
523 Reference
< data::XDataSequence
> xValues( xLSeq
->getValues() );
525 aResult
= xValues
->getSourceRangeRepresentation();
530 Sequence
< OUString
> DataSourceHelper::getRangesFromDataSource( const Reference
< data::XDataSource
> & xSource
)
532 ::std::vector
< OUString
> aResult
;
535 Sequence
< Reference
< data::XLabeledDataSequence
> > aLSeqSeq( xSource
->getDataSequences());
536 for( sal_Int32 i
=0; i
<aLSeqSeq
.getLength(); ++i
)
538 Reference
< data::XDataSequence
> xLabel( aLSeqSeq
[i
]->getLabel());
539 Reference
< data::XDataSequence
> xValues( aLSeqSeq
[i
]->getValues());
542 aResult
.push_back( xLabel
->getSourceRangeRepresentation());
544 aResult
.push_back( xValues
->getSourceRangeRepresentation());
547 return ContainerHelper::ContainerToSequence( aResult
);
550 //.............................................................................
552 //.............................................................................