1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: InternalDataProvider.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
32 // MARKER(update_precomp.py): autogen include statement, do not remove
33 #include "precompiled_chart2.hxx"
34 #include <rtl/math.hxx>
38 #include "InternalDataProvider.hxx"
39 #include "LabeledDataSequence.hxx"
40 #include "DataSource.hxx"
41 #include "PropertyHelper.hxx"
43 #include "XMLRangeHelper.hxx"
44 #include "ContainerHelper.hxx"
45 #include "CommonConverters.hxx"
46 #include "CommonFunctors.hxx"
47 #include "UncachedDataSequence.hxx"
48 #include "DataSourceHelper.hxx"
49 #include "ChartModelHelper.hxx"
50 #include "DiagramHelper.hxx"
52 #include "Strings.hrc"
53 #include <com/sun/star/chart2/XChartDocument.hpp>
54 #include <com/sun/star/chart2/data/XDataSequence.hpp>
55 #include <com/sun/star/chart/ChartDataRowSource.hpp>
56 #include <rtl/ustrbuf.hxx>
57 #include <unotools/charclass.hxx>
58 #include <comphelper/sequenceashashmap.hxx>
63 using namespace ::com::sun::star
;
64 using namespace ::std
;
66 using ::com::sun::star::uno::Reference
;
67 using ::com::sun::star::uno::Sequence
;
68 using ::rtl::OUString
;
69 using ::rtl::OUStringBuffer
;
77 struct OUStringBufferAppend
: public unary_function
< OUString
, void >
79 OUStringBufferAppend( OUStringBuffer
& rBuffer
, const OUString
& rSeparator
) :
83 void operator() ( const OUString
& rStr
)
85 m_rBuffer
.append( m_aSep
);
86 m_rBuffer
.append( rStr
);
89 OUStringBuffer m_rBuffer
;
93 OUString
FlattenStringSequence( const Sequence
< OUString
> & aSeq
)
95 if( aSeq
.getLength() == 0 )
97 OUStringBuffer
aBuf( aSeq
[0] );
98 for_each( aSeq
.getConstArray() + 1, aSeq
.getConstArray() + aSeq
.getLength(),
99 OUStringBufferAppend( aBuf
, OUString(RTL_CONSTASCII_USTRINGPARAM(" "))));
100 return aBuf
.makeStringAndClear();
108 void createDefaultData();
110 void setData( const Sequence
< Sequence
< double > > & rNewData
, bool bDataInColumns
);
111 Sequence
< Sequence
< double > > getData( bool bDataInColumns
) const;
112 Sequence
< double > getDataAt( sal_Int32 nIndex
, bool bDataInColumns
) const;
113 void setDataAt( sal_Int32 nIndex
, bool bDataInColumns
, const ::std::vector
< double > & rNewData
);
114 void swapAllDataAtIndexWithNext( sal_Int32 nAtIndex
, bool bDataInColumns
);
116 /** resizes the data if at least one of the given dimensions is larger than
117 before. The data is never becoming smaller only larger.
119 @return </TRUE>, if the data was enlarged
121 bool enlargeData( sal_Int32 nColumnCount
, sal_Int32 nRowCount
);
123 void insertColumn( sal_Int32 nAfterIndex
);
124 void insertRow( sal_Int32 nAfterIndex
);
125 void deleteColumn( sal_Int32 nAtIndex
);
126 void deleteRow( sal_Int32 nAtIndex
);
128 /// @return the index of the newly appended column
129 sal_Int32
appendColumn();
130 /// @return the index of the newly appended row
131 sal_Int32
appendRow();
133 sal_Int32
getRowCount() const;
134 sal_Int32
getColumnCount() const;
136 void setRowLabels( const ::std::vector
< OUString
> & rNewRowLabels
);
137 ::std::vector
< OUString
> getRowLabels() const;
138 void setColumnLabels( const ::std::vector
< OUString
> & rNewColumnLabels
);
139 ::std::vector
< OUString
> getColumnLabels() const;
141 #if OSL_DEBUG_LEVEL > 2
142 void traceData() const;
146 sal_Int32 m_nColumnCount
;
147 sal_Int32 m_nRowCount
;
149 typedef ::std::valarray
< double > tDataType
;
150 typedef ::std::vector
< OUString
> tLabelType
;
153 tLabelType m_aRowLabels
;
154 tLabelType m_aColumnLabels
;
157 // ----------------------------------------
160 struct lcl_NumberedStringGenerator
162 lcl_NumberedStringGenerator( const OUString
& rStub
, const OUString
& rWildcard
) :
165 m_nStubStartIndex( rStub
.indexOf( rWildcard
)),
166 m_nWildcardLength( rWildcard
.getLength())
169 OUString
operator()() {
170 return m_aStub
.replaceAt( m_nStubStartIndex
, m_nWildcardLength
, OUString::valueOf( ++m_nCounter
));
174 sal_Int32 m_nCounter
;
175 const sal_Int32 m_nStubStartIndex
;
176 const sal_Int32 m_nWildcardLength
;
179 template< typename T
>
180 Sequence
< T
> lcl_ValarrayToSequence( const ::std::valarray
< T
> & rValarray
)
182 // is there a more elegant way of conversion?
183 Sequence
< T
> aResult( rValarray
.size());
184 for( size_t i
= 0; i
< rValarray
.size(); ++i
)
185 aResult
[i
] = rValarray
[i
];
189 struct lcl_ValuesOfLabeledSequence
:
190 public unary_function
< Reference
< chart2::data::XLabeledDataSequence
>, Sequence
< double > >
192 Sequence
< double > operator() ( const Reference
< chart2::data::XLabeledDataSequence
> & xLSeq
)
195 return Sequence
< double >();
196 return DataSequenceToDoubleSequence( xLSeq
->getValues());
200 struct lcl_LabelsOfLabeledSequence
:
201 public unary_function
< Reference
< chart2::data::XLabeledDataSequence
>, Sequence
< OUString
> >
203 Sequence
< OUString
> operator() ( const Reference
< chart2::data::XLabeledDataSequence
> & xLSeq
)
206 return Sequence
< OUString
>();
207 return DataSequenceToStringSequence( xLSeq
->getLabel());
211 struct lcl_LabelOfLabeledSequence
:
212 public unary_function
< Reference
< chart2::data::XLabeledDataSequence
>, OUString
>
214 OUString
operator() ( const Reference
< chart2::data::XLabeledDataSequence
> & xLSeq
)
218 return FlattenStringSequence( DataSequenceToStringSequence( xLSeq
->getLabel()));
222 } // anonymous namespace
223 // ----------------------------------------
225 InternalData::InternalData() :
230 void InternalData::createDefaultData()
232 const sal_Int32 nNumRows
= 4;
233 const sal_Int32 nNumColumns
= 3;
234 const sal_Int32 nSize
= nNumColumns
* nNumRows
;
235 // @todo: localize this!
236 const OUString
aRowName( ::chart::SchResId::getResString( STR_ROW_LABEL
));
237 const OUString
aColName( ::chart::SchResId::getResString( STR_COLUMN_LABEL
));
239 const double fDefaultData
[ nSize
] =
245 m_aData
.resize( nSize
);
246 for( sal_Int32 i
=0; i
<nSize
; ++i
)
247 m_aData
[i
] = fDefaultData
[i
];
248 m_nRowCount
= nNumRows
;
249 m_nColumnCount
= nNumColumns
;
251 vector
< OUString
> aRowLabels
;
252 aRowLabels
.reserve( nNumRows
);
253 generate_n( back_inserter( aRowLabels
), nNumRows
,
254 lcl_NumberedStringGenerator( aRowName
, C2U("%ROWNUMBER") ));
255 setRowLabels( aRowLabels
);
257 vector
< OUString
> aColumnLabels
;
258 aColumnLabels
.reserve( nNumColumns
);
259 generate_n( back_inserter( aColumnLabels
), nNumColumns
,
260 lcl_NumberedStringGenerator( aColName
, C2U("%COLUMNNUMBER") ));
261 setColumnLabels( aColumnLabels
);
264 void InternalData::setData( const Sequence
< Sequence
< double > > & rNewData
, bool bDataInColumns
)
266 sal_Int32 nOuterSize
= rNewData
.getLength();
267 sal_Int32 nInnerSize
= (nOuterSize
? rNewData
[0].getLength() : 0);
269 m_nRowCount
= (bDataInColumns
? nInnerSize
: nOuterSize
);
270 m_nColumnCount
= (bDataInColumns
? nOuterSize
: nInnerSize
);
272 if( m_aRowLabels
.size() != static_cast< sal_uInt32
>( m_nRowCount
))
273 m_aRowLabels
.resize( m_nRowCount
);
274 if( m_aColumnLabels
.size() != static_cast< sal_uInt32
>( m_nColumnCount
))
275 m_aColumnLabels
.resize( m_nColumnCount
);
277 m_aData
.resize( m_nRowCount
* m_nColumnCount
);
279 ::rtl::math::setNan( & fNan
);
280 // set all values to Nan
283 for( sal_Int32 nOuterIdx
=0; nOuterIdx
<nOuterSize
; ++nOuterIdx
)
285 int nDataIdx
= (bDataInColumns
? nOuterIdx
: nOuterIdx
*nInnerSize
);
286 const sal_Int32 nMax
= ::std::min( rNewData
[nOuterIdx
].getLength(), nInnerSize
);
287 sal_Int32 nInnerIdx
=0;
288 for( ; nInnerIdx
< nMax
; ++nInnerIdx
)
290 m_aData
[nDataIdx
] = rNewData
[nOuterIdx
][nInnerIdx
];
291 nDataIdx
+= (bDataInColumns
? m_nColumnCount
: 1);
296 Sequence
< Sequence
< double > > InternalData::getData( bool bDataInColumns
) const
298 Sequence
< Sequence
< double > > aResult( bDataInColumns
? m_nColumnCount
: m_nRowCount
);
302 for( sal_Int32 i
=0; i
<m_nColumnCount
; ++i
)
303 aResult
[i
] = lcl_ValarrayToSequence
< tDataType::value_type
>(
304 m_aData
[ ::std::slice( i
, m_nRowCount
, m_nColumnCount
) ] );
308 for( sal_Int32 i
=0; i
<m_nRowCount
; ++i
)
309 aResult
[i
] = lcl_ValarrayToSequence
< tDataType::value_type
>(
310 m_aData
[ ::std::slice( i
*m_nColumnCount
, m_nColumnCount
, 1 ) ] );
316 Sequence
< double > InternalData::getDataAt( sal_Int32 nIndex
, bool bDataInColumns
) const
318 Sequence
< double > aResult( bDataInColumns
? m_nRowCount
: m_nColumnCount
);
322 if( nIndex
< m_nColumnCount
)
323 return lcl_ValarrayToSequence
< tDataType::value_type
>(
324 m_aData
[ ::std::slice( nIndex
, m_nRowCount
, m_nColumnCount
) ] );
328 if( nIndex
< m_nRowCount
)
329 return lcl_ValarrayToSequence
< tDataType::value_type
>(
330 m_aData
[ ::std::slice( nIndex
*m_nColumnCount
, m_nColumnCount
, 1 ) ] );
333 return Sequence
< double >();
336 void InternalData::setDataAt( sal_Int32 nIndex
, bool bDataInColumns
, const ::std::vector
< double > & rNewData
)
340 if( nIndex
< m_nColumnCount
)
342 tDataType aSlice
= m_aData
[ ::std::slice( nIndex
, m_nRowCount
, m_nColumnCount
) ];
343 for( ::std::vector
< double >::size_type i
= 0; i
< rNewData
.size(); ++i
)
344 aSlice
[i
] = rNewData
[i
];
345 m_aData
[ ::std::slice( nIndex
, m_nRowCount
, m_nColumnCount
) ] = aSlice
;
350 if( nIndex
< m_nRowCount
)
352 tDataType aSlice
= m_aData
[ ::std::slice( nIndex
*m_nColumnCount
, m_nColumnCount
, 1 ) ];
353 for( ::std::vector
< double >::size_type i
= 0; i
< rNewData
.size(); ++i
)
354 aSlice
[i
] = rNewData
[i
];
355 m_aData
[ ::std::slice( nIndex
*m_nColumnCount
, m_nColumnCount
, 1 ) ]= aSlice
;
360 void InternalData::swapAllDataAtIndexWithNext( sal_Int32 nAtIndex
, bool bDataInColumns
)
362 if( bDataInColumns
&& nAtIndex
< m_nRowCount
- 1 )
364 const sal_Int32 nMax
= m_nColumnCount
;
365 for( sal_Int32 nColIdx
=0; nColIdx
<nMax
; ++nColIdx
)
367 size_t nIndex1
= nColIdx
+ nAtIndex
*m_nColumnCount
;
368 size_t nIndex2
= nIndex1
+ m_nColumnCount
;
369 double fTemp
= m_aData
[nIndex1
];
370 m_aData
[nIndex1
] = m_aData
[nIndex2
];
371 m_aData
[nIndex2
] = fTemp
;
373 OUString
sTemp( m_aRowLabels
[nAtIndex
] );
374 m_aRowLabels
[nAtIndex
] = m_aRowLabels
[nAtIndex
+ 1];
375 m_aRowLabels
[nAtIndex
+ 1] = sTemp
;
377 else if( nAtIndex
< m_nColumnCount
- 1 )
379 const sal_Int32 nMax
= m_nRowCount
;
380 for( sal_Int32 nRowIdx
=0; nRowIdx
<nMax
; ++nRowIdx
)
382 size_t nIndex1
= nAtIndex
+ nRowIdx
*m_nColumnCount
;
383 size_t nIndex2
= nIndex1
+ 1;
384 double fTemp
= m_aData
[nIndex1
];
385 m_aData
[nIndex1
] = m_aData
[nIndex2
];
386 m_aData
[nIndex2
] = fTemp
;
388 OUString
sTemp( m_aColumnLabels
[nAtIndex
] );
389 m_aColumnLabels
[nAtIndex
] = m_aColumnLabels
[nAtIndex
+ 1];
390 m_aColumnLabels
[nAtIndex
+ 1] = sTemp
;
394 bool InternalData::enlargeData( sal_Int32 nColumnCount
, sal_Int32 nRowCount
)
396 sal_Int32
nNewColumnCount( ::std::max
<sal_Int32
>( m_nColumnCount
, nColumnCount
) );
397 sal_Int32
nNewRowCount( ::std::max
<sal_Int32
>( m_nRowCount
, nRowCount
) );
398 sal_Int32
nNewSize( nNewColumnCount
*nNewRowCount
);
400 bool bGrow
= (nNewSize
> m_nColumnCount
*m_nRowCount
);
405 ::rtl::math::setNan( &fNan
);
406 tDataType
aNewData( fNan
, nNewSize
);
408 for( int nCol
=0; nCol
<m_nColumnCount
; ++nCol
)
409 static_cast< tDataType
>(
410 aNewData
[ ::std::slice( nCol
, m_nRowCount
, nNewColumnCount
) ] ) =
411 m_aData
[ ::std::slice( nCol
, m_nRowCount
, m_nColumnCount
) ];
413 m_aData
.resize( nNewSize
);
416 m_nColumnCount
= nNewColumnCount
;
417 m_nRowCount
= nNewRowCount
;
421 void InternalData::insertColumn( sal_Int32 nAfterIndex
)
423 // note: -1 is allowed, as we insert after the given index
424 OSL_ASSERT( nAfterIndex
< m_nColumnCount
&& nAfterIndex
>= -1 );
425 if( nAfterIndex
>= m_nColumnCount
|| nAfterIndex
< -1 )
427 sal_Int32 nNewColumnCount
= m_nColumnCount
+ 1;
428 sal_Int32
nNewSize( nNewColumnCount
* m_nRowCount
);
431 ::rtl::math::setNan( &fNan
);
432 tDataType
aNewData( fNan
, nNewSize
);
436 for( ; nCol
<=nAfterIndex
; ++nCol
)
437 aNewData
[ ::std::slice( nCol
, m_nRowCount
, nNewColumnCount
) ] =
438 static_cast< tDataType
>(
439 m_aData
[ ::std::slice( nCol
, m_nRowCount
, m_nColumnCount
) ] );
440 for( ++nCol
; nCol
<nNewColumnCount
; ++nCol
)
441 aNewData
[ ::std::slice( nCol
, m_nRowCount
, nNewColumnCount
) ] =
442 static_cast< tDataType
>(
443 m_aData
[ ::std::slice( nCol
- 1, m_nRowCount
, m_nColumnCount
) ] );
445 m_nColumnCount
= nNewColumnCount
;
446 m_aData
.resize( nNewSize
);
450 if( nAfterIndex
< static_cast< sal_Int32
>( m_aColumnLabels
.size()))
451 m_aColumnLabels
.insert( m_aColumnLabels
.begin() + (nAfterIndex
+ 1), OUString());
453 #if OSL_DEBUG_LEVEL > 2
458 sal_Int32
InternalData::appendColumn()
460 insertColumn( getColumnCount() - 1 );
461 return getColumnCount() - 1;
464 sal_Int32
InternalData::appendRow()
466 insertRow( getRowCount() - 1 );
467 return getRowCount() - 1;
470 void InternalData::insertRow( sal_Int32 nAfterIndex
)
472 // note: -1 is allowed, as we insert after the given index
473 OSL_ASSERT( nAfterIndex
< m_nRowCount
&& nAfterIndex
>= -1 );
474 if( nAfterIndex
>= m_nRowCount
|| nAfterIndex
< -1 )
476 sal_Int32 nNewRowCount
= m_nRowCount
+ 1;
477 sal_Int32
nNewSize( m_nColumnCount
* nNewRowCount
);
480 ::rtl::math::setNan( &fNan
);
481 tDataType
aNewData( fNan
, nNewSize
);
484 sal_Int32 nIndex
= nAfterIndex
+ 1;
485 aNewData
[ ::std::slice( 0, nIndex
* m_nColumnCount
, 1 ) ] =
486 static_cast< tDataType
>(
487 m_aData
[ ::std::slice( 0, nIndex
* m_nColumnCount
, 1 ) ] );
489 if( nIndex
< m_nRowCount
)
491 sal_Int32 nRemainingCount
= m_nColumnCount
* (m_nRowCount
- nIndex
);
492 aNewData
[ ::std::slice( (nIndex
+ 1) * m_nColumnCount
, nRemainingCount
, 1 ) ] =
493 static_cast< tDataType
>(
494 m_aData
[ ::std::slice( nIndex
* m_nColumnCount
, nRemainingCount
, 1 ) ] );
497 m_nRowCount
= nNewRowCount
;
498 m_aData
.resize( nNewSize
);
502 if( nAfterIndex
< static_cast< sal_Int32
>( m_aRowLabels
.size()))
503 m_aRowLabels
.insert( m_aRowLabels
.begin() + nIndex
, OUString());
505 #if OSL_DEBUG_LEVEL > 2
510 void InternalData::deleteColumn( sal_Int32 nAtIndex
)
512 OSL_ASSERT( nAtIndex
< m_nColumnCount
&& nAtIndex
>= 0 );
513 if( nAtIndex
>= m_nColumnCount
|| m_nColumnCount
< 1 || nAtIndex
< 0 )
515 sal_Int32 nNewColumnCount
= m_nColumnCount
- 1;
516 sal_Int32
nNewSize( nNewColumnCount
* m_nRowCount
);
519 ::rtl::math::setNan( &fNan
);
520 tDataType
aNewData( fNan
, nNewSize
);
524 for( ; nCol
<nAtIndex
; ++nCol
)
525 aNewData
[ ::std::slice( nCol
, m_nRowCount
, nNewColumnCount
) ] =
526 static_cast< tDataType
>(
527 m_aData
[ ::std::slice( nCol
, m_nRowCount
, m_nColumnCount
) ] );
528 for( ; nCol
<nNewColumnCount
; ++nCol
)
529 aNewData
[ ::std::slice( nCol
, m_nRowCount
, nNewColumnCount
) ] =
530 static_cast< tDataType
>(
531 m_aData
[ ::std::slice( nCol
+ 1, m_nRowCount
, m_nColumnCount
) ] );
533 m_nColumnCount
= nNewColumnCount
;
534 m_aData
.resize( nNewSize
);
538 if( nAtIndex
< static_cast< sal_Int32
>( m_aColumnLabels
.size()))
539 m_aColumnLabels
.erase( m_aColumnLabels
.begin() + nAtIndex
);
541 #if OSL_DEBUG_LEVEL > 2
546 void InternalData::deleteRow( sal_Int32 nAtIndex
)
548 OSL_ASSERT( nAtIndex
< m_nRowCount
&& nAtIndex
>= 0 );
549 if( nAtIndex
>= m_nRowCount
|| m_nRowCount
< 1 || nAtIndex
< 0 )
551 sal_Int32 nNewRowCount
= m_nRowCount
- 1;
552 sal_Int32
nNewSize( m_nColumnCount
* nNewRowCount
);
555 ::rtl::math::setNan( &fNan
);
556 tDataType
aNewData( fNan
, nNewSize
);
559 sal_Int32 nIndex
= nAtIndex
;
561 aNewData
[ ::std::slice( 0, nIndex
* m_nColumnCount
, 1 ) ] =
562 static_cast< tDataType
>(
563 m_aData
[ ::std::slice( 0, nIndex
* m_nColumnCount
, 1 ) ] );
565 if( nIndex
< nNewRowCount
)
567 sal_Int32 nRemainingCount
= m_nColumnCount
* (nNewRowCount
- nIndex
);
568 aNewData
[ ::std::slice( nIndex
* m_nColumnCount
, nRemainingCount
, 1 ) ] =
569 static_cast< tDataType
>(
570 m_aData
[ ::std::slice( (nIndex
+ 1) * m_nColumnCount
, nRemainingCount
, 1 ) ] );
573 m_nRowCount
= nNewRowCount
;
574 m_aData
.resize( nNewSize
);
578 if( nAtIndex
< static_cast< sal_Int32
>( m_aRowLabels
.size()))
579 m_aRowLabels
.erase( m_aRowLabels
.begin() + nAtIndex
);
581 #if OSL_DEBUG_LEVEL > 2
586 sal_Int32
InternalData::getRowCount() const
591 sal_Int32
InternalData::getColumnCount() const
593 return m_nColumnCount
;
596 void InternalData::setRowLabels( const ::std::vector
< OUString
> & rNewRowLabels
)
598 m_aRowLabels
= rNewRowLabels
;
599 if( m_aRowLabels
.size() < static_cast< ::std::vector
< OUString
>::size_type
>( m_nRowCount
))
600 m_aRowLabels
.resize( m_nRowCount
);
602 enlargeData( 0, static_cast< sal_Int32
>( m_aRowLabels
.size() ));
605 ::std::vector
< OUString
> InternalData::getRowLabels() const
610 void InternalData::setColumnLabels( const ::std::vector
< OUString
> & rNewColumnLabels
)
612 m_aColumnLabels
= rNewColumnLabels
;
613 if( m_aColumnLabels
.size() < static_cast< ::std::vector
< OUString
>::size_type
>( m_nColumnCount
))
614 m_aColumnLabels
.resize( m_nColumnCount
);
616 enlargeData( static_cast< sal_Int32
>( m_aColumnLabels
.size()), 0 );
619 ::std::vector
< OUString
> InternalData::getColumnLabels() const
621 return m_aColumnLabels
;
624 #if OSL_DEBUG_LEVEL > 2
625 void InternalData::traceData() const
627 OSL_TRACE( "InternalData: Data in rows\n" );
629 for( sal_Int32 i
=0; i
<m_nRowCount
; ++i
)
631 tDataType
aSlice( m_aData
[ ::std::slice( i
*m_nColumnCount
, m_nColumnCount
, 1 ) ] );
632 for( sal_Int32 j
=0; j
<m_nColumnCount
; ++j
)
633 OSL_TRACE( "%lf ", aSlice
[j
] );
642 // ================================================================================
647 // note: in xmloff this name is used to indicate usage of own data
648 static const ::rtl::OUString
lcl_aServiceName(
649 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart.InternalDataProvider" ));
651 static const ::rtl::OUString
lcl_aCategoriesRangeName(
652 RTL_CONSTASCII_USTRINGPARAM( "categories" ));
653 static const ::rtl::OUString
lcl_aCategoriesRoleName(
654 RTL_CONSTASCII_USTRINGPARAM( "categories" ));
655 static const ::rtl::OUString
lcl_aLabelRangePrefix(
656 RTL_CONSTASCII_USTRINGPARAM( "label " ));
657 static const ::rtl::OUString
lcl_aCompleteRange(
658 RTL_CONSTASCII_USTRINGPARAM( "all" ));
661 struct lcl_DataProviderRangeCreator
: public unary_function
< OUString
, Reference
< chart2::data::XLabeledDataSequence
> >
663 lcl_DataProviderRangeCreator( const Reference
< chart2::data::XDataProvider
> & xDataProvider
) :
664 m_xDataProvider( xDataProvider
)
667 Reference
< chart2::data::XLabeledDataSequence
> operator() ( const OUString
& rRange
)
669 Reference
< chart2::data::XLabeledDataSequence
> xResult
;
670 if( m_xDataProvider
.is())
673 xResult
.set( new ::chart::LabeledDataSequence(
674 m_xDataProvider
->createDataSequenceByRangeRepresentation( rRange
)));
676 catch( const lang::IllegalArgumentException
& ex
)
678 // data provider cannot create single data sequences, but then
679 // detectArguments should work also with an empty data source
682 catch( const uno::Exception
& ex
)
684 ASSERT_EXCEPTION( ex
);
690 Reference
< chart2::data::XDataProvider
> m_xDataProvider
;
693 typedef ::std::multimap
< OUString
, uno::WeakReference
< chart2::data::XDataSequence
> >
696 struct lcl_modifySeqMapValue
: public ::std::unary_function
< lcl_tSequenceMap
, void >
698 void operator() ( const lcl_tSequenceMap::value_type
& rMapEntry
)
700 // convert weak reference to reference
701 Reference
< chart2::data::XDataSequence
> xSeq( rMapEntry
.second
);
704 Reference
< util::XModifiable
> xMod( xSeq
, uno::UNO_QUERY
);
706 xMod
->setModified( sal_True
);
711 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> >
713 const Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > & rDataSeq
,
714 impl::InternalData
& rInternalData
,
715 InternalDataProvider
& rProvider
)
717 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aResult( rDataSeq
.getLength());
718 for( sal_Int32 i
=0; i
<rDataSeq
.getLength(); ++i
)
720 sal_Int32
nNewIndex( rInternalData
.appendColumn());
721 OUString
aIdentifier( OUString::valueOf( nNewIndex
));
722 //@todo: deal also with genericXDataSequence
723 Reference
< chart2::data::XNumericalDataSequence
> xValues( rDataSeq
[i
]->getValues(), uno::UNO_QUERY
);
724 Reference
< chart2::data::XTextualDataSequence
> xLabel( rDataSeq
[i
]->getLabel(), uno::UNO_QUERY
);
725 Reference
< chart2::data::XDataSequence
> xNewValues
;
729 ::std::vector
< double > aValues( ContainerHelper::SequenceToVector( xValues
->getNumericalData()));
730 rInternalData
.enlargeData( nNewIndex
+ 1, aValues
.size());
731 rInternalData
.setDataAt( nNewIndex
, true, aValues
);
732 xNewValues
.set( rProvider
.createDataSequenceByRangeRepresentation( aIdentifier
));
733 comphelper::copyProperties(
734 Reference
< beans::XPropertySet
>( xValues
, uno::UNO_QUERY
),
735 Reference
< beans::XPropertySet
>( xNewValues
, uno::UNO_QUERY
));
740 ::std::vector
< OUString
> aLabels( rInternalData
.getColumnLabels());
741 OSL_ASSERT( static_cast< size_t >( nNewIndex
) < aLabels
.size());
742 if( aLabels
.size() <= static_cast< size_t >( nNewIndex
) )
743 aLabels
.resize( nNewIndex
+1 );
744 aLabels
[nNewIndex
] = impl::FlattenStringSequence( xLabel
->getTextualData());
745 rInternalData
.setColumnLabels( aLabels
);
746 Reference
< chart2::data::XDataSequence
> xNewLabel(
747 rProvider
.createDataSequenceByRangeRepresentation( lcl_aLabelRangePrefix
+ aIdentifier
));
748 comphelper::copyProperties(
749 Reference
< beans::XPropertySet
>( xLabel
, uno::UNO_QUERY
),
750 Reference
< beans::XPropertySet
>( xNewLabel
, uno::UNO_QUERY
));
752 Reference
< chart2::data::XLabeledDataSequence
>(
753 new LabeledDataSequence( xNewValues
, xNewLabel
));
758 Reference
< chart2::data::XLabeledDataSequence
>(
759 new LabeledDataSequence( xNewValues
));
765 struct lcl_internalizeSeries
: public ::std::unary_function
< Reference
< chart2::XDataSeries
>, void >
767 lcl_internalizeSeries( impl::InternalData
& rInternalData
,
768 InternalDataProvider
& rProvider
) :
769 m_rInternalData( rInternalData
),
770 m_rProvider( rProvider
)
772 void operator() ( const Reference
< chart2::XDataSeries
> & xSeries
)
774 Reference
< chart2::data::XDataSource
> xSource( xSeries
, uno::UNO_QUERY
);
775 Reference
< chart2::data::XDataSink
> xSink( xSeries
, uno::UNO_QUERY
);
776 if( xSource
.is() && xSink
.is())
777 xSink
->setData( lcl_internalizeData( xSource
->getDataSequences(), m_rInternalData
, m_rProvider
));
781 impl::InternalData
& m_rInternalData
;
782 InternalDataProvider
& m_rProvider
;
785 } // anonymous namespace
786 InternalDataProvider::InternalDataProvider(const Reference
< uno::XComponentContext
> & /*_xContext*/) :
787 m_bDataInColumns( true )
790 // ================================================================================
792 InternalDataProvider::InternalDataProvider() :
793 m_bDataInColumns( true )
796 InternalDataProvider::InternalDataProvider(
797 const Reference
< ::com::sun::star::chart::XChartDataArray
> & xDataToCopy
) :
798 m_bDataInColumns( true )
800 if( xDataToCopy
.is())
802 setData( xDataToCopy
->getData() );
803 setColumnDescriptions( xDataToCopy
->getColumnDescriptions() );
804 setRowDescriptions( xDataToCopy
->getRowDescriptions() );
808 InternalDataProvider::InternalDataProvider(
809 const Reference
< chart2::XChartDocument
> & xChartDoc
) :
810 m_bDataInColumns( true )
814 Reference
< chart2::XDiagram
> xDiagram( ChartModelHelper::findDiagram( xChartDoc
) );
817 impl::InternalData
& rData( getInternalData());
819 Reference
< chart2::data::XLabeledDataSequence
> xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram
));
820 if( xCategories
.is())
822 // @todo: be able to deal with XDataSequence, too
823 Reference
< chart2::data::XTextualDataSequence
> xSeq( xCategories
->getValues(), uno::UNO_QUERY
);
825 rData
.setRowLabels( ContainerHelper::SequenceToVector( xSeq
->getTextualData()));
826 DiagramHelper::setCategoriesToDiagram(
827 new LabeledDataSequence(
828 createDataSequenceByRangeRepresentation( lcl_aCategoriesRangeName
)),
833 ::std::vector
< Reference
< chart2::XDataSeries
> > aSeriesVector( ChartModelHelper::getDataSeries( xChartDoc
));
834 ::std::for_each( aSeriesVector
.begin(), aSeriesVector
.end(),
835 lcl_internalizeSeries( rData
, *this ));
838 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aUnusedData( xDiagram
->getUnusedData());
839 aUnusedData
= lcl_internalizeData( aUnusedData
, rData
, *this );
840 xDiagram
->setUnusedData( aUnusedData
);
843 catch( const uno::Exception
& ex
)
845 ASSERT_EXCEPTION( ex
);
850 InternalDataProvider::InternalDataProvider( const InternalDataProvider
& rOther
) :
851 impl::InternalDataProvider_Base(),
852 m_aSequenceMap( rOther
.m_aSequenceMap
),
853 m_apData( new impl::InternalData( rOther
.getInternalData())),
854 m_bDataInColumns( rOther
.m_bDataInColumns
)
857 InternalDataProvider::~InternalDataProvider()
860 void InternalDataProvider::addDataSequenceToMap(
861 const OUString
& rRangeRepresentation
,
862 const Reference
< chart2::data::XDataSequence
> & xSequence
)
864 m_aSequenceMap
.insert(
865 tSequenceMap::value_type(
866 rRangeRepresentation
,
867 uno::WeakReference
< chart2::data::XDataSequence
>( xSequence
)));
870 void InternalDataProvider::deleteMapReferences( const OUString
& rRangeRepresentation
)
872 // set sequence to deleted by setting its range to an empty string
873 tSequenceMapRange
aRange( m_aSequenceMap
.equal_range( rRangeRepresentation
));
874 for( tSequenceMap::iterator
aIt( aRange
.first
); aIt
!= aRange
.second
; ++aIt
)
876 Reference
< chart2::data::XDataSequence
> xSeq( aIt
->second
);
879 Reference
< container::XNamed
> xNamed( xSeq
, uno::UNO_QUERY
);
881 xNamed
->setName( OUString());
885 m_aSequenceMap
.erase( aRange
.first
, aRange
.second
);
888 void InternalDataProvider::adaptMapReferences(
889 const OUString
& rOldRangeRepresentation
,
890 const OUString
& rNewRangeRepresentation
)
892 tSequenceMapRange
aRange( m_aSequenceMap
.equal_range( rOldRangeRepresentation
));
893 tSequenceMap aNewElements
;
894 for( tSequenceMap::iterator
aIt( aRange
.first
); aIt
!= aRange
.second
; ++aIt
)
896 Reference
< chart2::data::XDataSequence
> xSeq( aIt
->second
);
899 Reference
< container::XNamed
> xNamed( xSeq
, uno::UNO_QUERY
);
901 xNamed
->setName( rNewRangeRepresentation
);
903 aNewElements
.insert( tSequenceMap::value_type( rNewRangeRepresentation
, aIt
->second
));
905 // erase map values for old index
906 m_aSequenceMap
.erase( aRange
.first
, aRange
.second
);
907 // add new entries for values with new index
908 ::std::copy( aNewElements
.begin(), aNewElements
.end(),
909 ::std::inserter( m_aSequenceMap
,
910 m_aSequenceMap
.upper_bound( rNewRangeRepresentation
)));
913 void InternalDataProvider::increaseMapReferences(
914 sal_Int32 nBegin
, sal_Int32 nEnd
)
916 for( sal_Int32 nIndex
= nEnd
- 1; nIndex
>= nBegin
; --nIndex
)
918 adaptMapReferences( OUString::valueOf( nIndex
),
919 OUString::valueOf( nIndex
+ 1 ));
920 adaptMapReferences( lcl_aLabelRangePrefix
+ OUString::valueOf( nIndex
),
921 lcl_aLabelRangePrefix
+ OUString::valueOf( nIndex
+ 1 ));
925 void InternalDataProvider::decreaseMapReferences(
926 sal_Int32 nBegin
, sal_Int32 nEnd
)
928 for( sal_Int32 nIndex
= nBegin
; nIndex
< nEnd
; ++nIndex
)
930 adaptMapReferences( OUString::valueOf( nIndex
),
931 OUString::valueOf( nIndex
- 1 ));
932 adaptMapReferences( lcl_aLabelRangePrefix
+ OUString::valueOf( nIndex
),
933 lcl_aLabelRangePrefix
+ OUString::valueOf( nIndex
- 1 ));
937 Reference
< chart2::data::XDataSequence
> InternalDataProvider::createDataSequenceAndAddToMap(
938 const OUString
& rRangeRepresentation
)
940 Reference
< chart2::data::XDataSequence
> xSeq(
941 new UncachedDataSequence( this, rRangeRepresentation
));
942 addDataSequenceToMap( rRangeRepresentation
, xSeq
);
946 Reference
< chart2::data::XDataSequence
> InternalDataProvider::createDataSequenceAndAddToMap(
947 const OUString
& rRangeRepresentation
,
948 const OUString
& rRole
)
950 Reference
< chart2::data::XDataSequence
> xSeq(
951 new UncachedDataSequence( this, rRangeRepresentation
, rRole
));
952 addDataSequenceToMap( rRangeRepresentation
, xSeq
);
956 const impl::InternalData
& InternalDataProvider::getInternalData() const
959 return *(m_apData
.get());
961 m_apData
.reset( new impl::InternalData());
962 return *(m_apData
.get());
965 impl::InternalData
& InternalDataProvider::getInternalData()
968 return *(m_apData
.get());
970 m_apData
.reset( new impl::InternalData());
971 return *(m_apData
.get());
974 void InternalDataProvider::createDefaultData()
976 getInternalData().createDefaultData();
979 // ____ XDataProvider ____
980 ::sal_Bool SAL_CALL
InternalDataProvider::createDataSourcePossible( const Sequence
< beans::PropertyValue
>& /* aArguments */ )
981 throw (uno::RuntimeException
)
986 Reference
< chart2::data::XDataSource
> SAL_CALL
InternalDataProvider::createDataSource(
987 const Sequence
< beans::PropertyValue
>& aArguments
)
988 throw (lang::IllegalArgumentException
,
989 uno::RuntimeException
)
991 OUString aRangeRepresentation
;
992 bool bUseColumns
= true;
993 bool bFirstCellAsLabel
= true;
994 bool bHasCategories
= true;
995 uno::Sequence
< sal_Int32
> aSequenceMapping
;
996 DataSourceHelper::readArguments( aArguments
, aRangeRepresentation
, aSequenceMapping
, bUseColumns
, bFirstCellAsLabel
, bHasCategories
);
998 OSL_ASSERT( aRangeRepresentation
.equals( lcl_aCompleteRange
));
1000 ::std::vector
< Reference
< chart2::data::XLabeledDataSequence
> > aResultLSeqVec
;
1001 impl::InternalData
& rData( getInternalData());
1004 if ( bHasCategories
)
1005 aResultLSeqVec
.push_back(
1006 new LabeledDataSequence( createDataSequenceAndAddToMap( lcl_aCategoriesRangeName
, lcl_aCategoriesRoleName
)));
1009 ::std::vector
< Reference
< chart2::data::XLabeledDataSequence
> > aDataVec
;
1010 const sal_Int32 nCount
= (bUseColumns
? rData
.getColumnCount() : rData
.getRowCount());
1011 for( sal_Int32 nIdx
=0; nIdx
<nCount
; ++nIdx
)
1014 new LabeledDataSequence(
1015 createDataSequenceAndAddToMap( OUString::valueOf( nIdx
)),
1016 createDataSequenceAndAddToMap( lcl_aLabelRangePrefix
+ OUString::valueOf( nIdx
))));
1019 // attention: this data provider has the limitation that it stores
1020 // internally if data comes from columns or rows. It is intended for
1021 // creating only one used data source.
1022 // @todo: add this information in the range representation strings
1023 m_bDataInColumns
= bUseColumns
;
1025 //reorder labeled sequences according to aSequenceMapping; ignore categories
1026 for( sal_Int32 nNewIndex
= 0; nNewIndex
< aSequenceMapping
.getLength(); nNewIndex
++ )
1028 std::vector
< LabeledDataSequence
* >::size_type nOldIndex
= aSequenceMapping
[nNewIndex
];
1029 if( nOldIndex
< aDataVec
.size() )
1031 if( aDataVec
[nOldIndex
].is() )
1033 aResultLSeqVec
.push_back( aDataVec
[nOldIndex
] );
1034 aDataVec
[nOldIndex
] = 0;
1039 //add left over data sequences to result
1040 ::std::vector
< Reference
< chart2::data::XLabeledDataSequence
> >::iterator
aIt(aDataVec
.begin());
1041 const ::std::vector
< Reference
< chart2::data::XLabeledDataSequence
> >::const_iterator
aEndIt(aDataVec
.end());
1042 for( ;aIt
!=aEndIt
; ++aIt
)
1045 aResultLSeqVec
.push_back( *aIt
);
1048 return new DataSource( ContainerHelper::ContainerToSequence(aResultLSeqVec
) );
1051 Sequence
< beans::PropertyValue
> SAL_CALL
InternalDataProvider::detectArguments(
1052 const Reference
< chart2::data::XDataSource
>& /* xDataSource */ )
1053 throw (uno::RuntimeException
)
1055 Sequence
< beans::PropertyValue
> aArguments( 4 );
1056 aArguments
[0] = beans::PropertyValue(
1057 C2U("CellRangeRepresentation"), -1, uno::makeAny( lcl_aCompleteRange
),
1058 beans::PropertyState_DIRECT_VALUE
);
1059 aArguments
[1] = beans::PropertyValue(
1060 C2U("DataRowSource"), -1, uno::makeAny(
1062 ? ::com::sun::star::chart::ChartDataRowSource_COLUMNS
1063 : ::com::sun::star::chart::ChartDataRowSource_ROWS
),
1064 beans::PropertyState_DIRECT_VALUE
);
1065 // internal data always contains labels and categories
1066 aArguments
[2] = beans::PropertyValue(
1067 C2U("FirstCellAsLabel"), -1, uno::makeAny( true ), beans::PropertyState_DIRECT_VALUE
);
1068 aArguments
[3] = beans::PropertyValue(
1069 C2U("HasCategories"), -1, uno::makeAny( true ), beans::PropertyState_DIRECT_VALUE
);
1071 // #i85913# Sequence Mapping is not needed for internal data, as it is
1072 // applied to the data when the data source is created.
1077 ::sal_Bool SAL_CALL
InternalDataProvider::createDataSequenceByRangeRepresentationPossible( const OUString
& /* aRangeRepresentation */ )
1078 throw (uno::RuntimeException
)
1083 Reference
< chart2::data::XDataSequence
> SAL_CALL
InternalDataProvider::createDataSequenceByRangeRepresentation(
1084 const OUString
& aRangeRepresentation
)
1085 throw (lang::IllegalArgumentException
,
1086 uno::RuntimeException
)
1088 if( aRangeRepresentation
.equals( lcl_aCategoriesRangeName
))
1091 return createDataSequenceAndAddToMap( lcl_aCategoriesRangeName
, lcl_aCategoriesRoleName
);
1093 else if( aRangeRepresentation
.match( lcl_aLabelRangePrefix
))
1096 sal_Int32 nIndex
= aRangeRepresentation
.copy( lcl_aLabelRangePrefix
.getLength()).toInt32();
1097 return createDataSequenceAndAddToMap( lcl_aLabelRangePrefix
+ OUString::valueOf( nIndex
));
1099 else if( aRangeRepresentation
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "last" )))
1101 sal_Int32 nIndex
= (m_bDataInColumns
1102 ? getInternalData().getColumnCount()
1103 : getInternalData().getRowCount()) - 1;
1104 return createDataSequenceAndAddToMap( OUString::valueOf( nIndex
));
1106 else if( aRangeRepresentation
.getLength())
1109 sal_Int32 nIndex
= aRangeRepresentation
.toInt32();
1110 return createDataSequenceAndAddToMap( OUString::valueOf( nIndex
));
1113 return Reference
< chart2::data::XDataSequence
>();
1116 Reference
< sheet::XRangeSelection
> SAL_CALL
InternalDataProvider::getRangeSelection()
1117 throw (uno::RuntimeException
)
1119 // there is no range selection component
1120 return Reference
< sheet::XRangeSelection
>();
1123 // ____ XInternalDataProvider ____
1124 ::sal_Bool SAL_CALL
InternalDataProvider::hasDataByRangeRepresentation( const OUString
& aRange
)
1125 throw (uno::RuntimeException
)
1127 sal_Bool bResult
= false;
1128 const impl::InternalData
& rData( getInternalData());
1130 if( aRange
.equals( lcl_aCategoriesRangeName
))
1134 else if( aRange
.match( lcl_aLabelRangePrefix
))
1136 sal_Int32 nIndex
= aRange
.copy( lcl_aLabelRangePrefix
.getLength()).toInt32();
1137 bResult
= (nIndex
< (m_bDataInColumns
? rData
.getColumnCount(): rData
.getRowCount()));
1141 sal_Int32 nIndex
= aRange
.toInt32();
1142 bResult
= (nIndex
< (m_bDataInColumns
? rData
.getColumnCount(): rData
.getRowCount()));
1148 Sequence
< uno::Any
> SAL_CALL
InternalDataProvider::getDataByRangeRepresentation( const OUString
& aRange
)
1149 throw (uno::RuntimeException
)
1151 Sequence
< uno::Any
> aResult
;
1152 const impl::InternalData
& rData( getInternalData());
1154 if( aRange
.equals( lcl_aCategoriesRangeName
))
1156 vector
< OUString
> aCategories( m_bDataInColumns
? rData
.getRowLabels() : rData
.getColumnLabels());
1157 aResult
.realloc( aCategories
.size());
1158 transform( aCategories
.begin(), aCategories
.end(),
1159 aResult
.getArray(), CommonFunctors::makeAny
< OUString
>());
1161 else if( aRange
.match( lcl_aLabelRangePrefix
))
1163 sal_Int32 nIndex
= aRange
.copy( lcl_aLabelRangePrefix
.getLength()).toInt32();
1164 vector
< OUString
> aLabels( m_bDataInColumns
? rData
.getColumnLabels() : rData
.getRowLabels());
1165 if( nIndex
< static_cast< sal_Int32
>( aLabels
.size()))
1167 aResult
.realloc( 1 );
1168 aResult
[0] = uno::makeAny( aLabels
[ nIndex
] );
1173 sal_Int32 nIndex
= aRange
.toInt32();
1174 if( nIndex
< (m_bDataInColumns
? rData
.getColumnCount() : rData
.getRowCount()))
1176 Sequence
< double > aData( rData
.getDataAt( nIndex
, m_bDataInColumns
));
1177 aResult
.realloc( aData
.getLength());
1178 transform( aData
.getConstArray(), aData
.getConstArray() + aData
.getLength(),
1179 aResult
.getArray(), CommonFunctors::makeAny
< double >());
1186 void SAL_CALL
InternalDataProvider::setDataByRangeRepresentation(
1187 const OUString
& aRange
, const Sequence
< uno::Any
>& aNewData
)
1188 throw (uno::RuntimeException
)
1190 impl::InternalData
& rData( getInternalData());
1192 if( aRange
.equals( lcl_aCategoriesRangeName
))
1194 vector
< OUString
> aCategories
;
1195 transform( aNewData
.getConstArray(), aNewData
.getConstArray() + aNewData
.getLength(),
1196 back_inserter( aCategories
), CommonFunctors::AnyToString());
1198 if( m_bDataInColumns
)
1199 rData
.setRowLabels( aCategories
);
1201 rData
.setColumnLabels( aCategories
);
1203 else if( aRange
.match( lcl_aLabelRangePrefix
))
1205 sal_uInt32 nIndex
= aRange
.copy( lcl_aLabelRangePrefix
.getLength()).toInt32();
1207 if( aNewData
.getLength() &&
1208 (aNewData
[0] >>= aNewLabel
))
1210 if( m_bDataInColumns
)
1212 vector
< OUString
> aLabels( rData
.getColumnLabels());
1213 if ( aLabels
.size() <= nIndex
)
1214 aLabels
.push_back(aNewLabel
);
1216 aLabels
[ nIndex
] = aNewLabel
;
1217 rData
.setColumnLabels( aLabels
);
1221 vector
< OUString
> aLabels( rData
.getRowLabels());
1222 if ( aLabels
.size() <= nIndex
)
1223 aLabels
.push_back(aNewLabel
);
1225 aLabels
[ nIndex
] = aNewLabel
;
1226 rData
.setRowLabels( aLabels
);
1232 sal_Int32 nIndex
= aRange
.toInt32();
1233 // ensure that the data is large enough
1234 if( m_bDataInColumns
)
1235 rData
.enlargeData( nIndex
, 0 );
1237 rData
.enlargeData( 0, nIndex
);
1239 if( nIndex
< (m_bDataInColumns
? rData
.getColumnCount() : rData
.getRowCount()))
1241 vector
< double > aNewDataVec
;
1242 transform( aNewData
.getConstArray(), aNewData
.getConstArray() + aNewData
.getLength(),
1243 back_inserter( aNewDataVec
), CommonFunctors::AnyToDouble());
1244 rData
.setDataAt( nIndex
, m_bDataInColumns
, aNewDataVec
);
1249 void SAL_CALL
InternalDataProvider::insertSequence( ::sal_Int32 nAfterIndex
)
1250 throw (uno::RuntimeException
)
1252 if( m_bDataInColumns
)
1254 increaseMapReferences( nAfterIndex
+ 1, getInternalData().getColumnCount());
1255 getInternalData().insertColumn( nAfterIndex
);
1259 increaseMapReferences( nAfterIndex
+ 1, getInternalData().getRowCount());
1260 getInternalData().insertRow( nAfterIndex
);
1264 void SAL_CALL
InternalDataProvider::deleteSequence( ::sal_Int32 nAtIndex
)
1265 throw (uno::RuntimeException
)
1267 deleteMapReferences( OUString::valueOf( nAtIndex
));
1268 deleteMapReferences( lcl_aLabelRangePrefix
+ OUString::valueOf( nAtIndex
));
1269 if( m_bDataInColumns
)
1271 decreaseMapReferences( nAtIndex
+ 1, getInternalData().getColumnCount());
1272 getInternalData().deleteColumn( nAtIndex
);
1276 decreaseMapReferences( nAtIndex
+ 1, getInternalData().getRowCount());
1277 getInternalData().deleteRow( nAtIndex
);
1281 void SAL_CALL
InternalDataProvider::appendSequence()
1282 throw (uno::RuntimeException
)
1284 if( m_bDataInColumns
)
1285 getInternalData().appendColumn();
1287 getInternalData().appendRow();
1290 void SAL_CALL
InternalDataProvider::insertDataPointForAllSequences( ::sal_Int32 nAfterIndex
)
1291 throw (uno::RuntimeException
)
1293 sal_Int32 nMaxRep
= 0;
1294 if( m_bDataInColumns
)
1296 getInternalData().insertRow( nAfterIndex
);
1297 nMaxRep
= getInternalData().getColumnCount();
1301 getInternalData().insertColumn( nAfterIndex
);
1302 nMaxRep
= getInternalData().getRowCount();
1305 // notify change to all affected ranges
1306 tSequenceMap::const_iterator
aBegin( m_aSequenceMap
.lower_bound( C2U("0")));
1307 tSequenceMap::const_iterator
aEnd( m_aSequenceMap
.upper_bound( OUString::valueOf( nMaxRep
)));
1308 ::std::for_each( aBegin
, aEnd
, lcl_modifySeqMapValue());
1310 tSequenceMapRange
aRange( m_aSequenceMap
.equal_range( lcl_aCategoriesRangeName
));
1311 ::std::for_each( aRange
.first
, aRange
.second
, lcl_modifySeqMapValue());
1314 void SAL_CALL
InternalDataProvider::deleteDataPointForAllSequences( ::sal_Int32 nAtIndex
)
1315 throw (uno::RuntimeException
)
1317 sal_Int32 nMaxRep
= 0;
1318 if( m_bDataInColumns
)
1320 getInternalData().deleteRow( nAtIndex
);
1321 nMaxRep
= getInternalData().getColumnCount();
1325 getInternalData().deleteColumn( nAtIndex
);
1326 nMaxRep
= getInternalData().getRowCount();
1329 // notify change to all affected ranges
1330 tSequenceMap::const_iterator
aBegin( m_aSequenceMap
.lower_bound( C2U("0")));
1331 tSequenceMap::const_iterator
aEnd( m_aSequenceMap
.upper_bound( OUString::valueOf( nMaxRep
)));
1332 ::std::for_each( aBegin
, aEnd
, lcl_modifySeqMapValue());
1334 tSequenceMapRange
aRange( m_aSequenceMap
.equal_range( lcl_aCategoriesRangeName
));
1335 ::std::for_each( aRange
.first
, aRange
.second
, lcl_modifySeqMapValue());
1338 void SAL_CALL
InternalDataProvider::swapDataPointWithNextOneForAllSequences( ::sal_Int32 nAtIndex
)
1339 throw (uno::RuntimeException
)
1341 getInternalData().swapAllDataAtIndexWithNext( nAtIndex
, m_bDataInColumns
);
1342 sal_Int32 nMaxRep
= (m_bDataInColumns
1343 ? getInternalData().getColumnCount()
1344 : getInternalData().getRowCount());
1346 // notify change to all affected ranges
1347 tSequenceMap::const_iterator
aBegin( m_aSequenceMap
.lower_bound( C2U("0")));
1348 tSequenceMap::const_iterator
aEnd( m_aSequenceMap
.upper_bound( OUString::valueOf( nMaxRep
)));
1349 ::std::for_each( aBegin
, aEnd
, lcl_modifySeqMapValue());
1351 tSequenceMapRange
aRange( m_aSequenceMap
.equal_range( lcl_aCategoriesRangeName
));
1352 ::std::for_each( aRange
.first
, aRange
.second
, lcl_modifySeqMapValue());
1355 void SAL_CALL
InternalDataProvider::registerDataSequenceForChanges( const Reference
< chart2::data::XDataSequence
>& xSeq
)
1356 throw (uno::RuntimeException
)
1359 addDataSequenceToMap( xSeq
->getSourceRangeRepresentation(), xSeq
);
1363 // ____ XRangeXMLConversion ____
1364 OUString SAL_CALL
InternalDataProvider::convertRangeToXML( const OUString
& aRangeRepresentation
)
1365 throw (lang::IllegalArgumentException
,
1366 uno::RuntimeException
)
1368 XMLRangeHelper::CellRange aRange
;
1369 aRange
.aTableName
= OUString(RTL_CONSTASCII_USTRINGPARAM("local-table"));
1370 impl::InternalData
& rData( getInternalData());
1372 // attention: this data provider has the limitation that it stores
1373 // internally if data comes from columns or rows. It is intended for
1374 // creating only one used data source.
1375 // @todo: add this information in the range representation strings
1376 if( aRangeRepresentation
.equals( lcl_aCategoriesRangeName
))
1378 aRange
.aUpperLeft
.bIsEmpty
= false;
1379 if( m_bDataInColumns
)
1381 aRange
.aUpperLeft
.nColumn
= 0;
1382 aRange
.aUpperLeft
.nRow
= 1;
1383 aRange
.aLowerRight
= aRange
.aUpperLeft
;
1384 aRange
.aLowerRight
.nRow
= rData
.getRowCount();
1388 aRange
.aUpperLeft
.nColumn
= 1;
1389 aRange
.aUpperLeft
.nRow
= 0;
1390 aRange
.aLowerRight
= aRange
.aUpperLeft
;
1391 aRange
.aLowerRight
.nColumn
= rData
.getColumnCount();
1394 else if( aRangeRepresentation
.match( lcl_aLabelRangePrefix
))
1396 sal_Int32 nIndex
= aRangeRepresentation
.copy( lcl_aLabelRangePrefix
.getLength()).toInt32();
1397 aRange
.aUpperLeft
.bIsEmpty
= false;
1398 aRange
.aLowerRight
.bIsEmpty
= true;
1399 if( m_bDataInColumns
)
1401 aRange
.aUpperLeft
.nColumn
= nIndex
+ 1;
1402 aRange
.aUpperLeft
.nRow
= 0;
1406 aRange
.aUpperLeft
.nColumn
= 0;
1407 aRange
.aUpperLeft
.nRow
= nIndex
+ 1;
1410 else if( aRangeRepresentation
.equals( lcl_aCompleteRange
))
1412 aRange
.aUpperLeft
.bIsEmpty
= false;
1413 aRange
.aLowerRight
.bIsEmpty
= false;
1414 aRange
.aUpperLeft
.nColumn
= 0;
1415 aRange
.aUpperLeft
.nRow
= 0;
1416 aRange
.aLowerRight
.nColumn
= rData
.getColumnCount();
1417 aRange
.aLowerRight
.nRow
= rData
.getRowCount();
1421 sal_Int32 nIndex
= aRangeRepresentation
.toInt32();
1422 aRange
.aUpperLeft
.bIsEmpty
= false;
1423 if( m_bDataInColumns
)
1425 aRange
.aUpperLeft
.nColumn
= nIndex
+ 1;
1426 aRange
.aUpperLeft
.nRow
= 1;
1427 aRange
.aLowerRight
= aRange
.aUpperLeft
;
1428 aRange
.aLowerRight
.nRow
= rData
.getRowCount();
1432 aRange
.aUpperLeft
.nColumn
= 1;
1433 aRange
.aUpperLeft
.nRow
= nIndex
+ 1;
1434 aRange
.aLowerRight
= aRange
.aUpperLeft
;
1435 aRange
.aLowerRight
.nColumn
= rData
.getColumnCount();
1439 return XMLRangeHelper::getXMLStringFromCellRange( aRange
);
1442 OUString SAL_CALL
InternalDataProvider::convertRangeFromXML( const OUString
& aXMLRange
)
1443 throw (lang::IllegalArgumentException
,
1444 uno::RuntimeException
)
1446 XMLRangeHelper::CellRange
aRange( XMLRangeHelper::getCellRangeFromXMLString( aXMLRange
));
1447 if( aRange
.aUpperLeft
.bIsEmpty
)
1449 OSL_ENSURE( aRange
.aLowerRight
.bIsEmpty
, "Weird Range" );
1454 if( !aRange
.aLowerRight
.bIsEmpty
&&
1455 ( aRange
.aUpperLeft
.nColumn
!= aRange
.aLowerRight
.nColumn
) &&
1456 ( aRange
.aUpperLeft
.nRow
!= aRange
.aLowerRight
.nRow
) )
1457 return lcl_aCompleteRange
;
1459 // attention: this data provider has the limitation that it stores
1460 // internally if data comes from columns or rows. It is intended for
1461 // creating only one used data source.
1462 // @todo: add this information in the range representation strings
1465 if( m_bDataInColumns
)
1467 if( aRange
.aUpperLeft
.nColumn
== 0 )
1468 return lcl_aCategoriesRangeName
;
1469 if( aRange
.aUpperLeft
.nRow
== 0 )
1470 return lcl_aLabelRangePrefix
+ OUString::valueOf( aRange
.aUpperLeft
.nColumn
- 1 );
1472 return OUString::valueOf( aRange
.aUpperLeft
.nColumn
- 1 );
1476 if( aRange
.aUpperLeft
.nRow
== 0 )
1477 return lcl_aCategoriesRangeName
;
1478 if( aRange
.aUpperLeft
.nColumn
== 0 )
1479 return lcl_aLabelRangePrefix
+ OUString::valueOf( aRange
.aUpperLeft
.nRow
- 1 );
1481 return OUString::valueOf( aRange
.aUpperLeft
.nRow
- 1 );
1484 // ____ XChartDataArray ____
1485 // note: do not use m_bDataInColumns for all XChartDataArray-specific code
1486 // the chart-API assumes data is always in rows
1487 Sequence
< Sequence
< double > > SAL_CALL
InternalDataProvider::getData()
1488 throw (uno::RuntimeException
)
1490 return getInternalData().getData( false );
1493 void SAL_CALL
InternalDataProvider::setData( const Sequence
< Sequence
< double > >& aData
)
1494 throw (uno::RuntimeException
)
1496 return getInternalData().setData( aData
, false );
1499 Sequence
< OUString
> SAL_CALL
InternalDataProvider::getRowDescriptions()
1500 throw (uno::RuntimeException
)
1502 return ContainerHelper::ContainerToSequence( getInternalData().getRowLabels());
1505 void SAL_CALL
InternalDataProvider::setRowDescriptions( const Sequence
< OUString
>& aRowDescriptions
)
1506 throw (uno::RuntimeException
)
1508 getInternalData().setRowLabels( ContainerHelper::SequenceToVector( aRowDescriptions
));
1511 Sequence
< OUString
> SAL_CALL
InternalDataProvider::getColumnDescriptions()
1512 throw (uno::RuntimeException
)
1514 return ContainerHelper::ContainerToSequence( getInternalData().getColumnLabels());
1517 void SAL_CALL
InternalDataProvider::setColumnDescriptions( const Sequence
< OUString
>& aColumnDescriptions
)
1518 throw (uno::RuntimeException
)
1520 getInternalData().setColumnLabels( ContainerHelper::SequenceToVector( aColumnDescriptions
));
1524 // ____ XChartData (base of XChartDataArray) ____
1525 void SAL_CALL
InternalDataProvider::addChartDataChangeEventListener(
1526 const Reference
< ::com::sun::star::chart::XChartDataChangeEventListener
>& )
1527 throw (uno::RuntimeException
)
1531 void SAL_CALL
InternalDataProvider::removeChartDataChangeEventListener(
1532 const Reference
< ::com::sun::star::chart::XChartDataChangeEventListener
>& )
1533 throw (uno::RuntimeException
)
1537 double SAL_CALL
InternalDataProvider::getNotANumber()
1538 throw (uno::RuntimeException
)
1541 ::rtl::math::setNan( & fNan
);
1545 ::sal_Bool SAL_CALL
InternalDataProvider::isNotANumber( double nNumber
)
1546 throw (uno::RuntimeException
)
1548 return ::rtl::math::isNan( nNumber
)
1549 || ::rtl::math::isInf( nNumber
);
1551 // lang::XInitialization:
1552 void SAL_CALL
InternalDataProvider::initialize(const uno::Sequence
< uno::Any
> & _aArguments
) throw (uno::RuntimeException
, uno::Exception
)
1554 comphelper::SequenceAsHashMap
aArgs(_aArguments
);
1555 if ( aArgs
.getUnpackedValueOrDefault(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CreateDefaultData")),sal_False
) )
1556 createDefaultData();
1558 // ____ XCloneable ____
1559 Reference
< util::XCloneable
> SAL_CALL
InternalDataProvider::createClone()
1560 throw (uno::RuntimeException
)
1562 return Reference
< util::XCloneable
>( new InternalDataProvider( *this ));
1566 // ================================================================================
1568 Sequence
< OUString
> InternalDataProvider::getSupportedServiceNames_Static()
1570 Sequence
< OUString
> aServices( 1 );
1571 aServices
[ 0 ] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.data.DataProvider" ));
1575 // ================================================================================
1577 APPHELPER_XSERVICEINFO_IMPL( InternalDataProvider
, lcl_aServiceName
);
1579 } // namespace chart