merge the formfield patch from ooo-build
[ooovba.git] / chart2 / source / tools / InternalDataProvider.cxx
blobdb64dc832930d945c9c37c7fa092d3c29794a8fa
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: InternalDataProvider.cxx,v $
10 * $Revision: 1.7 $
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>
36 #include <valarray>
38 #include "InternalDataProvider.hxx"
39 #include "LabeledDataSequence.hxx"
40 #include "DataSource.hxx"
41 #include "PropertyHelper.hxx"
42 #include "macros.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"
51 #include "ResId.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>
60 #include <vector>
61 #include <algorithm>
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;
71 namespace chart
73 namespace impl
77 struct OUStringBufferAppend : public unary_function< OUString, void >
79 OUStringBufferAppend( OUStringBuffer & rBuffer, const OUString & rSeparator ) :
80 m_rBuffer( rBuffer ),
81 m_aSep( rSeparator )
83 void operator() ( const OUString & rStr )
85 m_rBuffer.append( m_aSep );
86 m_rBuffer.append( rStr );
88 private:
89 OUStringBuffer m_rBuffer;
90 OUString m_aSep;
93 OUString FlattenStringSequence( const Sequence< OUString > & aSeq )
95 if( aSeq.getLength() == 0 )
96 return OUString();
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();
103 class InternalData
105 public:
106 InternalData();
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;
143 #endif
145 private:
146 sal_Int32 m_nColumnCount;
147 sal_Int32 m_nRowCount;
149 typedef ::std::valarray< double > tDataType;
150 typedef ::std::vector< OUString > tLabelType;
152 tDataType m_aData;
153 tLabelType m_aRowLabels;
154 tLabelType m_aColumnLabels;
157 // ----------------------------------------
158 namespace
160 struct lcl_NumberedStringGenerator
162 lcl_NumberedStringGenerator( const OUString & rStub, const OUString & rWildcard ) :
163 m_aStub( rStub ),
164 m_nCounter( 0 ),
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 ));
172 private:
173 OUString m_aStub;
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];
186 return aResult;
189 struct lcl_ValuesOfLabeledSequence :
190 public unary_function< Reference< chart2::data::XLabeledDataSequence >, Sequence< double > >
192 Sequence< double > operator() ( const Reference< chart2::data::XLabeledDataSequence > & xLSeq )
194 if( ! xLSeq.is())
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 )
205 if( ! xLSeq.is())
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 )
216 if( ! xLSeq.is())
217 return OUString();
218 return FlattenStringSequence( DataSequenceToStringSequence( xLSeq->getLabel()));
222 } // anonymous namespace
223 // ----------------------------------------
225 InternalData::InternalData() :
226 m_nColumnCount( 0 ),
227 m_nRowCount( 0 )
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 ] =
240 { 9.10, 3.20, 4.54,
241 2.40, 8.80, 9.65,
242 3.10, 1.50, 3.70,
243 4.30, 9.02, 6.20 };
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 );
278 double fNan;
279 ::rtl::math::setNan( & fNan );
280 // set all values to Nan
281 m_aData = fNan;
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 );
300 if( bDataInColumns )
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 ) ] );
306 else
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 ) ] );
313 return aResult;
316 Sequence< double > InternalData::getDataAt( sal_Int32 nIndex, bool bDataInColumns ) const
318 Sequence< double > aResult( bDataInColumns ? m_nRowCount : m_nColumnCount );
320 if( bDataInColumns )
322 if( nIndex < m_nColumnCount )
323 return lcl_ValarrayToSequence< tDataType::value_type >(
324 m_aData[ ::std::slice( nIndex, m_nRowCount, m_nColumnCount ) ] );
326 else
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 )
338 if( bDataInColumns )
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;
348 else
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);
402 if( bGrow )
404 double fNan;
405 ::rtl::math::setNan( &fNan );
406 tDataType aNewData( fNan, nNewSize );
407 // copy old data
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 );
414 m_aData = aNewData;
416 m_nColumnCount = nNewColumnCount;
417 m_nRowCount = nNewRowCount;
418 return bGrow;
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 )
426 return;
427 sal_Int32 nNewColumnCount = m_nColumnCount + 1;
428 sal_Int32 nNewSize( nNewColumnCount * m_nRowCount );
430 double fNan;
431 ::rtl::math::setNan( &fNan );
432 tDataType aNewData( fNan, nNewSize );
434 // copy old data
435 int nCol=0;
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 );
447 m_aData = aNewData;
449 // labels
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
454 traceData();
455 #endif
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 )
475 return;
476 sal_Int32 nNewRowCount = m_nRowCount + 1;
477 sal_Int32 nNewSize( m_nColumnCount * nNewRowCount );
479 double fNan;
480 ::rtl::math::setNan( &fNan );
481 tDataType aNewData( fNan, nNewSize );
483 // copy old data
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 );
499 m_aData = aNewData;
501 // labels
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
506 traceData();
507 #endif
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 )
514 return;
515 sal_Int32 nNewColumnCount = m_nColumnCount - 1;
516 sal_Int32 nNewSize( nNewColumnCount * m_nRowCount );
518 double fNan;
519 ::rtl::math::setNan( &fNan );
520 tDataType aNewData( fNan, nNewSize );
522 // copy old data
523 int nCol=0;
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 );
535 m_aData = aNewData;
537 // labels
538 if( nAtIndex < static_cast< sal_Int32 >( m_aColumnLabels.size()))
539 m_aColumnLabels.erase( m_aColumnLabels.begin() + nAtIndex );
541 #if OSL_DEBUG_LEVEL > 2
542 traceData();
543 #endif
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 )
550 return;
551 sal_Int32 nNewRowCount = m_nRowCount - 1;
552 sal_Int32 nNewSize( m_nColumnCount * nNewRowCount );
554 double fNan;
555 ::rtl::math::setNan( &fNan );
556 tDataType aNewData( fNan, nNewSize );
558 // copy old data
559 sal_Int32 nIndex = nAtIndex;
560 if( nIndex )
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 );
575 m_aData = aNewData;
577 // labels
578 if( nAtIndex < static_cast< sal_Int32 >( m_aRowLabels.size()))
579 m_aRowLabels.erase( m_aRowLabels.begin() + nAtIndex );
581 #if OSL_DEBUG_LEVEL > 2
582 traceData();
583 #endif
586 sal_Int32 InternalData::getRowCount() const
588 return m_nRowCount;
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 );
601 else
602 enlargeData( 0, static_cast< sal_Int32 >( m_aRowLabels.size() ));
605 ::std::vector< OUString > InternalData::getRowLabels() const
607 return m_aRowLabels;
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 );
615 else
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] );
634 OSL_TRACE( "\n" );
636 OSL_TRACE( "\n" );
638 #endif
640 } // namespace impl
642 // ================================================================================
644 namespace
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
680 (void)(ex);
682 catch( const uno::Exception & ex )
684 ASSERT_EXCEPTION( ex );
686 return xResult;
689 private:
690 Reference< chart2::data::XDataProvider > m_xDataProvider;
693 typedef ::std::multimap< OUString, uno::WeakReference< chart2::data::XDataSequence > >
694 lcl_tSequenceMap;
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 );
702 if( xSeq.is())
704 Reference< util::XModifiable > xMod( xSeq, uno::UNO_QUERY );
705 if( xMod.is())
706 xMod->setModified( sal_True );
711 Sequence< Reference< chart2::data::XLabeledDataSequence > >
712 lcl_internalizeData(
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;
727 if( xValues.is())
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 ));
738 if( xLabel.is())
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 ));
751 aResult[i] =
752 Reference< chart2::data::XLabeledDataSequence >(
753 new LabeledDataSequence( xNewValues, xNewLabel ));
755 else
757 aResult[i] =
758 Reference< chart2::data::XLabeledDataSequence >(
759 new LabeledDataSequence( xNewValues ));
762 return aResult;
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 ));
780 private:
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 ) );
815 if( xDiagram.is())
817 impl::InternalData & rData( getInternalData());
818 // categories
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 );
824 if( xSeq.is())
825 rData.setRowLabels( ContainerHelper::SequenceToVector( xSeq->getTextualData()));
826 DiagramHelper::setCategoriesToDiagram(
827 new LabeledDataSequence(
828 createDataSequenceByRangeRepresentation( lcl_aCategoriesRangeName )),
829 xDiagram );
832 // data series
833 ::std::vector< Reference< chart2::XDataSeries > > aSeriesVector( ChartModelHelper::getDataSeries( xChartDoc ));
834 ::std::for_each( aSeriesVector.begin(), aSeriesVector.end(),
835 lcl_internalizeSeries( rData, *this ));
837 // unused data
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 );
849 // copy-CTOR
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 );
877 if( xSeq.is())
879 Reference< container::XNamed > xNamed( xSeq, uno::UNO_QUERY );
880 if( xNamed.is())
881 xNamed->setName( OUString());
884 // remove from map
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 );
897 if( xSeq.is())
899 Reference< container::XNamed > xNamed( xSeq, uno::UNO_QUERY );
900 if( xNamed.is())
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 );
943 return 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 );
953 return xSeq;
956 const impl::InternalData & InternalDataProvider::getInternalData() const
958 if( m_apData.get())
959 return *(m_apData.get());
961 m_apData.reset( new impl::InternalData());
962 return *(m_apData.get());
965 impl::InternalData & InternalDataProvider::getInternalData()
967 if( m_apData.get())
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)
983 return true;
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());
1003 // categories
1004 if ( bHasCategories )
1005 aResultLSeqVec.push_back(
1006 new LabeledDataSequence( createDataSequenceAndAddToMap( lcl_aCategoriesRangeName, lcl_aCategoriesRoleName )));
1008 // data with labels
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 )
1013 aDataVec.push_back(
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)
1044 if( aIt->is() )
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(
1061 m_bDataInColumns
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.
1074 return aArguments;
1077 ::sal_Bool SAL_CALL InternalDataProvider::createDataSequenceByRangeRepresentationPossible( const OUString& /* aRangeRepresentation */ )
1078 throw (uno::RuntimeException)
1080 return true;
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 ))
1090 // categories
1091 return createDataSequenceAndAddToMap( lcl_aCategoriesRangeName, lcl_aCategoriesRoleName );
1093 else if( aRangeRepresentation.match( lcl_aLabelRangePrefix ))
1095 // label
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())
1108 // data
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 ))
1132 bResult = true;
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()));
1139 else
1141 sal_Int32 nIndex = aRange.toInt32();
1142 bResult = (nIndex < (m_bDataInColumns ? rData.getColumnCount(): rData.getRowCount()));
1145 return bResult;
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 ] );
1171 else
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 >());
1183 return aResult;
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 );
1200 else
1201 rData.setColumnLabels( aCategories );
1203 else if( aRange.match( lcl_aLabelRangePrefix ))
1205 sal_uInt32 nIndex = aRange.copy( lcl_aLabelRangePrefix.getLength()).toInt32();
1206 OUString aNewLabel;
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);
1215 else
1216 aLabels[ nIndex ] = aNewLabel;
1217 rData.setColumnLabels( aLabels );
1219 else
1221 vector< OUString > aLabels( rData.getRowLabels());
1222 if ( aLabels.size() <= nIndex )
1223 aLabels.push_back(aNewLabel);
1224 else
1225 aLabels[ nIndex ] = aNewLabel;
1226 rData.setRowLabels( aLabels );
1230 else
1232 sal_Int32 nIndex = aRange.toInt32();
1233 // ensure that the data is large enough
1234 if( m_bDataInColumns )
1235 rData.enlargeData( nIndex, 0 );
1236 else
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 );
1257 else
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 );
1274 else
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();
1286 else
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();
1299 else
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();
1323 else
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)
1358 if( xSeq.is())
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();
1386 else
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;
1404 else
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();
1419 else
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();
1430 else
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" );
1450 return OUString();
1453 // "all"
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
1464 // data in columns
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 );
1475 // data in rows
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)
1540 double fNan;
1541 ::rtl::math::setNan( & fNan );
1542 return 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" ));
1572 return aServices;
1575 // ================================================================================
1577 APPHELPER_XSERVICEINFO_IMPL( InternalDataProvider, lcl_aServiceName );
1579 } // namespace chart