update dev300-m58
[ooovba.git] / chart2 / source / tools / InternalDataProvider.cxx
blob1673908b07ea35a1cdc3637a71bf2673fe27b4bb
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>(1, ::std::max<sal_Int32>( m_nColumnCount, nColumnCount )));
397 sal_Int32 nNewRowCount( ::std::max<sal_Int32>(1, ::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;
415 m_nColumnCount = nNewColumnCount;
416 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 aLabels[nNewIndex] = impl::FlattenStringSequence( xLabel->getTextualData());
743 rInternalData.setColumnLabels( aLabels );
744 Reference< chart2::data::XDataSequence > xNewLabel(
745 rProvider.createDataSequenceByRangeRepresentation( lcl_aLabelRangePrefix + aIdentifier ));
746 comphelper::copyProperties(
747 Reference< beans::XPropertySet >( xLabel, uno::UNO_QUERY ),
748 Reference< beans::XPropertySet >( xNewLabel, uno::UNO_QUERY ));
749 aResult[i] =
750 Reference< chart2::data::XLabeledDataSequence >(
751 new LabeledDataSequence( xNewValues, xNewLabel ));
753 else
755 aResult[i] =
756 Reference< chart2::data::XLabeledDataSequence >(
757 new LabeledDataSequence( xNewValues ));
760 return aResult;
763 struct lcl_internalizeSeries : public ::std::unary_function< Reference< chart2::XDataSeries >, void >
765 lcl_internalizeSeries( impl::InternalData & rInternalData,
766 InternalDataProvider & rProvider ) :
767 m_rInternalData( rInternalData ),
768 m_rProvider( rProvider )
770 void operator() ( const Reference< chart2::XDataSeries > & xSeries )
772 Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
773 Reference< chart2::data::XDataSink > xSink( xSeries, uno::UNO_QUERY );
774 if( xSource.is() && xSink.is())
775 xSink->setData( lcl_internalizeData( xSource->getDataSequences(), m_rInternalData, m_rProvider ));
778 private:
779 impl::InternalData & m_rInternalData;
780 InternalDataProvider & m_rProvider;
783 } // anonymous namespace
784 InternalDataProvider::InternalDataProvider(const Reference< uno::XComponentContext > & /*_xContext*/) :
785 m_bDataInColumns( true )
788 // ================================================================================
790 InternalDataProvider::InternalDataProvider() :
791 m_bDataInColumns( true )
794 InternalDataProvider::InternalDataProvider(
795 const Reference< ::com::sun::star::chart::XChartDataArray > & xDataToCopy ) :
796 m_bDataInColumns( true )
798 if( xDataToCopy.is())
800 setData( xDataToCopy->getData() );
801 setColumnDescriptions( xDataToCopy->getColumnDescriptions() );
802 setRowDescriptions( xDataToCopy->getRowDescriptions() );
806 InternalDataProvider::InternalDataProvider(
807 const Reference< chart2::XChartDocument > & xChartDoc ) :
808 m_bDataInColumns( true )
812 Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartDoc ) );
813 if( xDiagram.is())
815 impl::InternalData & rData( getInternalData());
816 // categories
817 Reference< chart2::data::XLabeledDataSequence > xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram ));
818 if( xCategories.is())
820 // @todo: be able to deal with XDataSequence, too
821 Reference< chart2::data::XTextualDataSequence > xSeq( xCategories->getValues(), uno::UNO_QUERY );
822 if( xSeq.is())
823 rData.setRowLabels( ContainerHelper::SequenceToVector( xSeq->getTextualData()));
824 DiagramHelper::setCategoriesToDiagram(
825 new LabeledDataSequence(
826 createDataSequenceByRangeRepresentation( lcl_aCategoriesRangeName )),
827 xDiagram );
830 // data series
831 ::std::vector< Reference< chart2::XDataSeries > > aSeriesVector( ChartModelHelper::getDataSeries( xChartDoc ));
832 ::std::for_each( aSeriesVector.begin(), aSeriesVector.end(),
833 lcl_internalizeSeries( rData, *this ));
835 // unused data
836 Sequence< Reference< chart2::data::XLabeledDataSequence > > aUnusedData( xDiagram->getUnusedData());
837 aUnusedData = lcl_internalizeData( aUnusedData, rData, *this );
838 xDiagram->setUnusedData( aUnusedData );
841 catch( const uno::Exception & ex )
843 ASSERT_EXCEPTION( ex );
847 // copy-CTOR
848 InternalDataProvider::InternalDataProvider( const InternalDataProvider & rOther ) :
849 impl::InternalDataProvider_Base(),
850 m_aSequenceMap( rOther.m_aSequenceMap ),
851 m_apData( new impl::InternalData( rOther.getInternalData())),
852 m_bDataInColumns( rOther.m_bDataInColumns )
855 InternalDataProvider::~InternalDataProvider()
858 void InternalDataProvider::addDataSequenceToMap(
859 const OUString & rRangeRepresentation,
860 const Reference< chart2::data::XDataSequence > & xSequence )
862 m_aSequenceMap.insert(
863 tSequenceMap::value_type(
864 rRangeRepresentation,
865 uno::WeakReference< chart2::data::XDataSequence >( xSequence )));
868 void InternalDataProvider::deleteMapReferences( const OUString & rRangeRepresentation )
870 // set sequence to deleted by setting its range to an empty string
871 tSequenceMapRange aRange( m_aSequenceMap.equal_range( rRangeRepresentation ));
872 for( tSequenceMap::iterator aIt( aRange.first ); aIt != aRange.second; ++aIt )
874 Reference< chart2::data::XDataSequence > xSeq( aIt->second );
875 if( xSeq.is())
877 Reference< container::XNamed > xNamed( xSeq, uno::UNO_QUERY );
878 if( xNamed.is())
879 xNamed->setName( OUString());
882 // remove from map
883 m_aSequenceMap.erase( aRange.first, aRange.second );
886 void InternalDataProvider::adaptMapReferences(
887 const OUString & rOldRangeRepresentation,
888 const OUString & rNewRangeRepresentation )
890 tSequenceMapRange aRange( m_aSequenceMap.equal_range( rOldRangeRepresentation ));
891 tSequenceMap aNewElements;
892 for( tSequenceMap::iterator aIt( aRange.first ); aIt != aRange.second; ++aIt )
894 Reference< chart2::data::XDataSequence > xSeq( aIt->second );
895 if( xSeq.is())
897 Reference< container::XNamed > xNamed( xSeq, uno::UNO_QUERY );
898 if( xNamed.is())
899 xNamed->setName( rNewRangeRepresentation );
901 aNewElements.insert( tSequenceMap::value_type( rNewRangeRepresentation, aIt->second ));
903 // erase map values for old index
904 m_aSequenceMap.erase( aRange.first, aRange.second );
905 // add new entries for values with new index
906 ::std::copy( aNewElements.begin(), aNewElements.end(),
907 ::std::inserter( m_aSequenceMap,
908 m_aSequenceMap.upper_bound( rNewRangeRepresentation )));
911 void InternalDataProvider::increaseMapReferences(
912 sal_Int32 nBegin, sal_Int32 nEnd )
914 for( sal_Int32 nIndex = nEnd - 1; nIndex >= nBegin; --nIndex )
916 adaptMapReferences( OUString::valueOf( nIndex ),
917 OUString::valueOf( nIndex + 1 ));
918 adaptMapReferences( lcl_aLabelRangePrefix + OUString::valueOf( nIndex ),
919 lcl_aLabelRangePrefix + OUString::valueOf( nIndex + 1 ));
923 void InternalDataProvider::decreaseMapReferences(
924 sal_Int32 nBegin, sal_Int32 nEnd )
926 for( sal_Int32 nIndex = nBegin; nIndex < nEnd; ++nIndex )
928 adaptMapReferences( OUString::valueOf( nIndex ),
929 OUString::valueOf( nIndex - 1 ));
930 adaptMapReferences( lcl_aLabelRangePrefix + OUString::valueOf( nIndex ),
931 lcl_aLabelRangePrefix + OUString::valueOf( nIndex - 1 ));
935 Reference< chart2::data::XDataSequence > InternalDataProvider::createDataSequenceAndAddToMap(
936 const OUString & rRangeRepresentation )
938 Reference< chart2::data::XDataSequence > xSeq(
939 new UncachedDataSequence( this, rRangeRepresentation ));
940 addDataSequenceToMap( rRangeRepresentation, xSeq );
941 return xSeq;
944 Reference< chart2::data::XDataSequence > InternalDataProvider::createDataSequenceAndAddToMap(
945 const OUString & rRangeRepresentation,
946 const OUString & rRole )
948 Reference< chart2::data::XDataSequence > xSeq(
949 new UncachedDataSequence( this, rRangeRepresentation, rRole ));
950 addDataSequenceToMap( rRangeRepresentation, xSeq );
951 return xSeq;
954 const impl::InternalData & InternalDataProvider::getInternalData() const
956 if( m_apData.get())
957 return *(m_apData.get());
959 m_apData.reset( new impl::InternalData());
960 return *(m_apData.get());
963 impl::InternalData & InternalDataProvider::getInternalData()
965 if( m_apData.get())
966 return *(m_apData.get());
968 m_apData.reset( new impl::InternalData());
969 return *(m_apData.get());
972 void InternalDataProvider::createDefaultData()
974 getInternalData().createDefaultData();
977 // ____ XDataProvider ____
978 ::sal_Bool SAL_CALL InternalDataProvider::createDataSourcePossible( const Sequence< beans::PropertyValue >& /* aArguments */ )
979 throw (uno::RuntimeException)
981 return true;
984 Reference< chart2::data::XDataSource > SAL_CALL InternalDataProvider::createDataSource(
985 const Sequence< beans::PropertyValue >& aArguments )
986 throw (lang::IllegalArgumentException,
987 uno::RuntimeException)
989 OUString aRangeRepresentation;
990 bool bUseColumns = true;
991 bool bFirstCellAsLabel = true;
992 bool bHasCategories = true;
993 uno::Sequence< sal_Int32 > aSequenceMapping;
994 DataSourceHelper::readArguments( aArguments, aRangeRepresentation, aSequenceMapping, bUseColumns, bFirstCellAsLabel, bHasCategories );
996 OSL_ASSERT( aRangeRepresentation.equals( lcl_aCompleteRange ));
998 ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aResultLSeqVec;
999 impl::InternalData & rData( getInternalData());
1001 // categories
1002 if ( bHasCategories )
1003 aResultLSeqVec.push_back(
1004 new LabeledDataSequence( createDataSequenceAndAddToMap( lcl_aCategoriesRangeName, lcl_aCategoriesRoleName )));
1006 // data with labels
1007 ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aDataVec;
1008 const sal_Int32 nCount = (bUseColumns ? rData.getColumnCount() : rData.getRowCount());
1009 for( sal_Int32 nIdx=0; nIdx<nCount; ++nIdx )
1011 aDataVec.push_back(
1012 new LabeledDataSequence(
1013 createDataSequenceAndAddToMap( OUString::valueOf( nIdx )),
1014 createDataSequenceAndAddToMap( lcl_aLabelRangePrefix + OUString::valueOf( nIdx ))));
1017 // attention: this data provider has the limitation that it stores
1018 // internally if data comes from columns or rows. It is intended for
1019 // creating only one used data source.
1020 // @todo: add this information in the range representation strings
1021 m_bDataInColumns = bUseColumns;
1023 //reorder labeled sequences according to aSequenceMapping; ignore categories
1024 for( sal_Int32 nNewIndex = 0; nNewIndex < aSequenceMapping.getLength(); nNewIndex++ )
1026 std::vector< LabeledDataSequence* >::size_type nOldIndex = aSequenceMapping[nNewIndex];
1027 if( nOldIndex < aDataVec.size() )
1029 if( aDataVec[nOldIndex].is() )
1031 aResultLSeqVec.push_back( aDataVec[nOldIndex] );
1032 aDataVec[nOldIndex] = 0;
1037 //add left over data sequences to result
1038 ::std::vector< Reference< chart2::data::XLabeledDataSequence > >::iterator aIt(aDataVec.begin());
1039 const ::std::vector< Reference< chart2::data::XLabeledDataSequence > >::const_iterator aEndIt(aDataVec.end());
1040 for( ;aIt!=aEndIt; ++aIt)
1042 if( aIt->is() )
1043 aResultLSeqVec.push_back( *aIt );
1046 return new DataSource( ContainerHelper::ContainerToSequence(aResultLSeqVec) );
1049 Sequence< beans::PropertyValue > SAL_CALL InternalDataProvider::detectArguments(
1050 const Reference< chart2::data::XDataSource >& /* xDataSource */ )
1051 throw (uno::RuntimeException)
1053 Sequence< beans::PropertyValue > aArguments( 4 );
1054 aArguments[0] = beans::PropertyValue(
1055 C2U("CellRangeRepresentation"), -1, uno::makeAny( lcl_aCompleteRange ),
1056 beans::PropertyState_DIRECT_VALUE );
1057 aArguments[1] = beans::PropertyValue(
1058 C2U("DataRowSource"), -1, uno::makeAny(
1059 m_bDataInColumns
1060 ? ::com::sun::star::chart::ChartDataRowSource_COLUMNS
1061 : ::com::sun::star::chart::ChartDataRowSource_ROWS ),
1062 beans::PropertyState_DIRECT_VALUE );
1063 // internal data always contains labels and categories
1064 aArguments[2] = beans::PropertyValue(
1065 C2U("FirstCellAsLabel"), -1, uno::makeAny( true ), beans::PropertyState_DIRECT_VALUE );
1066 aArguments[3] = beans::PropertyValue(
1067 C2U("HasCategories"), -1, uno::makeAny( true ), beans::PropertyState_DIRECT_VALUE );
1069 // #i85913# Sequence Mapping is not needed for internal data, as it is
1070 // applied to the data when the data source is created.
1072 return aArguments;
1075 ::sal_Bool SAL_CALL InternalDataProvider::createDataSequenceByRangeRepresentationPossible( const OUString& /* aRangeRepresentation */ )
1076 throw (uno::RuntimeException)
1078 return true;
1081 Reference< chart2::data::XDataSequence > SAL_CALL InternalDataProvider::createDataSequenceByRangeRepresentation(
1082 const OUString& aRangeRepresentation )
1083 throw (lang::IllegalArgumentException,
1084 uno::RuntimeException)
1086 if( aRangeRepresentation.equals( lcl_aCategoriesRangeName ))
1088 // categories
1089 return createDataSequenceAndAddToMap( lcl_aCategoriesRangeName, lcl_aCategoriesRoleName );
1091 else if( aRangeRepresentation.match( lcl_aLabelRangePrefix ))
1093 // label
1094 sal_Int32 nIndex = aRangeRepresentation.copy( lcl_aLabelRangePrefix.getLength()).toInt32();
1095 return createDataSequenceAndAddToMap( lcl_aLabelRangePrefix + OUString::valueOf( nIndex ));
1097 else if( aRangeRepresentation.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "last" )))
1099 sal_Int32 nIndex = (m_bDataInColumns
1100 ? getInternalData().getColumnCount()
1101 : getInternalData().getRowCount()) - 1;
1102 return createDataSequenceAndAddToMap( OUString::valueOf( nIndex ));
1104 else if( aRangeRepresentation.getLength())
1106 // data
1107 sal_Int32 nIndex = aRangeRepresentation.toInt32();
1108 return createDataSequenceAndAddToMap( OUString::valueOf( nIndex ));
1111 return Reference< chart2::data::XDataSequence >();
1114 Reference< sheet::XRangeSelection > SAL_CALL InternalDataProvider::getRangeSelection()
1115 throw (uno::RuntimeException)
1117 // there is no range selection component
1118 return Reference< sheet::XRangeSelection >();
1121 // ____ XInternalDataProvider ____
1122 ::sal_Bool SAL_CALL InternalDataProvider::hasDataByRangeRepresentation( const OUString& aRange )
1123 throw (uno::RuntimeException)
1125 sal_Bool bResult = false;
1126 const impl::InternalData & rData( getInternalData());
1128 if( aRange.equals( lcl_aCategoriesRangeName ))
1130 bResult = true;
1132 else if( aRange.match( lcl_aLabelRangePrefix ))
1134 sal_Int32 nIndex = aRange.copy( lcl_aLabelRangePrefix.getLength()).toInt32();
1135 bResult = (nIndex < (m_bDataInColumns ? rData.getColumnCount(): rData.getRowCount()));
1137 else
1139 sal_Int32 nIndex = aRange.toInt32();
1140 bResult = (nIndex < (m_bDataInColumns ? rData.getColumnCount(): rData.getRowCount()));
1143 return bResult;
1146 Sequence< uno::Any > SAL_CALL InternalDataProvider::getDataByRangeRepresentation( const OUString& aRange )
1147 throw (uno::RuntimeException)
1149 Sequence< uno::Any > aResult;
1150 const impl::InternalData & rData( getInternalData());
1152 if( aRange.equals( lcl_aCategoriesRangeName ))
1154 vector< OUString > aCategories( m_bDataInColumns ? rData.getRowLabels() : rData.getColumnLabels());
1155 aResult.realloc( aCategories.size());
1156 transform( aCategories.begin(), aCategories.end(),
1157 aResult.getArray(), CommonFunctors::makeAny< OUString >());
1159 else if( aRange.match( lcl_aLabelRangePrefix ))
1161 sal_Int32 nIndex = aRange.copy( lcl_aLabelRangePrefix.getLength()).toInt32();
1162 vector< OUString > aLabels( m_bDataInColumns ? rData.getColumnLabels() : rData.getRowLabels());
1163 if( nIndex < static_cast< sal_Int32 >( aLabels.size()))
1165 aResult.realloc( 1 );
1166 aResult[0] = uno::makeAny( aLabels[ nIndex ] );
1169 else
1171 sal_Int32 nIndex = aRange.toInt32();
1172 if( nIndex < (m_bDataInColumns ? rData.getColumnCount() : rData.getRowCount()))
1174 Sequence< double > aData( rData.getDataAt( nIndex, m_bDataInColumns ));
1175 aResult.realloc( aData.getLength());
1176 transform( aData.getConstArray(), aData.getConstArray() + aData.getLength(),
1177 aResult.getArray(), CommonFunctors::makeAny< double >());
1181 return aResult;
1184 void SAL_CALL InternalDataProvider::setDataByRangeRepresentation(
1185 const OUString& aRange, const Sequence< uno::Any >& aNewData )
1186 throw (uno::RuntimeException)
1188 impl::InternalData & rData( getInternalData());
1190 if( aRange.equals( lcl_aCategoriesRangeName ))
1192 vector< OUString > aCategories;
1193 transform( aNewData.getConstArray(), aNewData.getConstArray() + aNewData.getLength(),
1194 back_inserter( aCategories ), CommonFunctors::AnyToString());
1196 if( m_bDataInColumns )
1197 rData.setRowLabels( aCategories );
1198 else
1199 rData.setColumnLabels( aCategories );
1201 else if( aRange.match( lcl_aLabelRangePrefix ))
1203 sal_uInt32 nIndex = aRange.copy( lcl_aLabelRangePrefix.getLength()).toInt32();
1204 OUString aNewLabel;
1205 if( aNewData.getLength() &&
1206 (aNewData[0] >>= aNewLabel))
1208 if( m_bDataInColumns )
1210 vector< OUString > aLabels( rData.getColumnLabels());
1211 if ( aLabels.size() <= nIndex )
1212 aLabels.push_back(aNewLabel);
1213 else
1214 aLabels[ nIndex ] = aNewLabel;
1215 rData.setColumnLabels( aLabels );
1217 else
1219 vector< OUString > aLabels( rData.getRowLabels());
1220 if ( aLabels.size() <= nIndex )
1221 aLabels.push_back(aNewLabel);
1222 else
1223 aLabels[ nIndex ] = aNewLabel;
1224 rData.setRowLabels( aLabels );
1228 else
1230 sal_Int32 nIndex = aRange.toInt32();
1231 // ensure that the data is large enough
1232 if( m_bDataInColumns )
1233 rData.enlargeData( nIndex, 0 );
1234 else
1235 rData.enlargeData( 0, nIndex );
1237 if( nIndex < (m_bDataInColumns ? rData.getColumnCount() : rData.getRowCount()))
1239 vector< double > aNewDataVec;
1240 transform( aNewData.getConstArray(), aNewData.getConstArray() + aNewData.getLength(),
1241 back_inserter( aNewDataVec ), CommonFunctors::AnyToDouble());
1242 rData.setDataAt( nIndex, m_bDataInColumns, aNewDataVec );
1247 void SAL_CALL InternalDataProvider::insertSequence( ::sal_Int32 nAfterIndex )
1248 throw (uno::RuntimeException)
1250 if( m_bDataInColumns )
1252 increaseMapReferences( nAfterIndex + 1, getInternalData().getColumnCount());
1253 getInternalData().insertColumn( nAfterIndex );
1255 else
1257 increaseMapReferences( nAfterIndex + 1, getInternalData().getRowCount());
1258 getInternalData().insertRow( nAfterIndex );
1262 void SAL_CALL InternalDataProvider::deleteSequence( ::sal_Int32 nAtIndex )
1263 throw (uno::RuntimeException)
1265 deleteMapReferences( OUString::valueOf( nAtIndex ));
1266 deleteMapReferences( lcl_aLabelRangePrefix + OUString::valueOf( nAtIndex ));
1267 if( m_bDataInColumns )
1269 decreaseMapReferences( nAtIndex + 1, getInternalData().getColumnCount());
1270 getInternalData().deleteColumn( nAtIndex );
1272 else
1274 decreaseMapReferences( nAtIndex + 1, getInternalData().getRowCount());
1275 getInternalData().deleteRow( nAtIndex );
1279 void SAL_CALL InternalDataProvider::appendSequence()
1280 throw (uno::RuntimeException)
1282 if( m_bDataInColumns )
1283 getInternalData().appendColumn();
1284 else
1285 getInternalData().appendRow();
1288 void SAL_CALL InternalDataProvider::insertDataPointForAllSequences( ::sal_Int32 nAfterIndex )
1289 throw (uno::RuntimeException)
1291 sal_Int32 nMaxRep = 0;
1292 if( m_bDataInColumns )
1294 getInternalData().insertRow( nAfterIndex );
1295 nMaxRep = getInternalData().getColumnCount();
1297 else
1299 getInternalData().insertColumn( nAfterIndex );
1300 nMaxRep = getInternalData().getRowCount();
1303 // notify change to all affected ranges
1304 tSequenceMap::const_iterator aBegin( m_aSequenceMap.lower_bound( C2U("0")));
1305 tSequenceMap::const_iterator aEnd( m_aSequenceMap.upper_bound( OUString::valueOf( nMaxRep )));
1306 ::std::for_each( aBegin, aEnd, lcl_modifySeqMapValue());
1308 tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
1309 ::std::for_each( aRange.first, aRange.second, lcl_modifySeqMapValue());
1312 void SAL_CALL InternalDataProvider::deleteDataPointForAllSequences( ::sal_Int32 nAtIndex )
1313 throw (uno::RuntimeException)
1315 sal_Int32 nMaxRep = 0;
1316 if( m_bDataInColumns )
1318 getInternalData().deleteRow( nAtIndex );
1319 nMaxRep = getInternalData().getColumnCount();
1321 else
1323 getInternalData().deleteColumn( nAtIndex );
1324 nMaxRep = getInternalData().getRowCount();
1327 // notify change to all affected ranges
1328 tSequenceMap::const_iterator aBegin( m_aSequenceMap.lower_bound( C2U("0")));
1329 tSequenceMap::const_iterator aEnd( m_aSequenceMap.upper_bound( OUString::valueOf( nMaxRep )));
1330 ::std::for_each( aBegin, aEnd, lcl_modifySeqMapValue());
1332 tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
1333 ::std::for_each( aRange.first, aRange.second, lcl_modifySeqMapValue());
1336 void SAL_CALL InternalDataProvider::swapDataPointWithNextOneForAllSequences( ::sal_Int32 nAtIndex )
1337 throw (uno::RuntimeException)
1339 getInternalData().swapAllDataAtIndexWithNext( nAtIndex, m_bDataInColumns );
1340 sal_Int32 nMaxRep = (m_bDataInColumns
1341 ? getInternalData().getColumnCount()
1342 : getInternalData().getRowCount());
1344 // notify change to all affected ranges
1345 tSequenceMap::const_iterator aBegin( m_aSequenceMap.lower_bound( C2U("0")));
1346 tSequenceMap::const_iterator aEnd( m_aSequenceMap.upper_bound( OUString::valueOf( nMaxRep )));
1347 ::std::for_each( aBegin, aEnd, lcl_modifySeqMapValue());
1349 tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
1350 ::std::for_each( aRange.first, aRange.second, lcl_modifySeqMapValue());
1353 void SAL_CALL InternalDataProvider::registerDataSequenceForChanges( const Reference< chart2::data::XDataSequence >& xSeq )
1354 throw (uno::RuntimeException)
1356 if( xSeq.is())
1357 addDataSequenceToMap( xSeq->getSourceRangeRepresentation(), xSeq );
1361 // ____ XRangeXMLConversion ____
1362 OUString SAL_CALL InternalDataProvider::convertRangeToXML( const OUString& aRangeRepresentation )
1363 throw (lang::IllegalArgumentException,
1364 uno::RuntimeException)
1366 XMLRangeHelper::CellRange aRange;
1367 aRange.aTableName = OUString(RTL_CONSTASCII_USTRINGPARAM("local-table"));
1368 impl::InternalData & rData( getInternalData());
1370 // attention: this data provider has the limitation that it stores
1371 // internally if data comes from columns or rows. It is intended for
1372 // creating only one used data source.
1373 // @todo: add this information in the range representation strings
1374 if( aRangeRepresentation.equals( lcl_aCategoriesRangeName ))
1376 aRange.aUpperLeft.bIsEmpty = false;
1377 if( m_bDataInColumns )
1379 aRange.aUpperLeft.nColumn = 0;
1380 aRange.aUpperLeft.nRow = 1;
1381 aRange.aLowerRight = aRange.aUpperLeft;
1382 aRange.aLowerRight.nRow = rData.getRowCount();
1384 else
1386 aRange.aUpperLeft.nColumn = 1;
1387 aRange.aUpperLeft.nRow = 0;
1388 aRange.aLowerRight = aRange.aUpperLeft;
1389 aRange.aLowerRight.nColumn = rData.getColumnCount();
1392 else if( aRangeRepresentation.match( lcl_aLabelRangePrefix ))
1394 sal_Int32 nIndex = aRangeRepresentation.copy( lcl_aLabelRangePrefix.getLength()).toInt32();
1395 aRange.aUpperLeft.bIsEmpty = false;
1396 aRange.aLowerRight.bIsEmpty = true;
1397 if( m_bDataInColumns )
1399 aRange.aUpperLeft.nColumn = nIndex + 1;
1400 aRange.aUpperLeft.nRow = 0;
1402 else
1404 aRange.aUpperLeft.nColumn = 0;
1405 aRange.aUpperLeft.nRow = nIndex + 1;
1408 else if( aRangeRepresentation.equals( lcl_aCompleteRange ))
1410 aRange.aUpperLeft.bIsEmpty = false;
1411 aRange.aLowerRight.bIsEmpty = false;
1412 aRange.aUpperLeft.nColumn = 0;
1413 aRange.aUpperLeft.nRow = 0;
1414 aRange.aLowerRight.nColumn = rData.getColumnCount();
1415 aRange.aLowerRight.nRow = rData.getRowCount();
1417 else
1419 sal_Int32 nIndex = aRangeRepresentation.toInt32();
1420 aRange.aUpperLeft.bIsEmpty = false;
1421 if( m_bDataInColumns )
1423 aRange.aUpperLeft.nColumn = nIndex + 1;
1424 aRange.aUpperLeft.nRow = 1;
1425 aRange.aLowerRight = aRange.aUpperLeft;
1426 aRange.aLowerRight.nRow = rData.getRowCount();
1428 else
1430 aRange.aUpperLeft.nColumn = 1;
1431 aRange.aUpperLeft.nRow = nIndex + 1;
1432 aRange.aLowerRight = aRange.aUpperLeft;
1433 aRange.aLowerRight.nColumn = rData.getColumnCount();
1437 return XMLRangeHelper::getXMLStringFromCellRange( aRange );
1440 OUString SAL_CALL InternalDataProvider::convertRangeFromXML( const OUString& aXMLRange )
1441 throw (lang::IllegalArgumentException,
1442 uno::RuntimeException)
1444 XMLRangeHelper::CellRange aRange( XMLRangeHelper::getCellRangeFromXMLString( aXMLRange ));
1445 if( aRange.aUpperLeft.bIsEmpty )
1447 OSL_ENSURE( aRange.aLowerRight.bIsEmpty, "Weird Range" );
1448 return OUString();
1451 // "all"
1452 if( !aRange.aLowerRight.bIsEmpty &&
1453 ( aRange.aUpperLeft.nColumn != aRange.aLowerRight.nColumn ) &&
1454 ( aRange.aUpperLeft.nRow != aRange.aLowerRight.nRow ) )
1455 return lcl_aCompleteRange;
1457 // attention: this data provider has the limitation that it stores
1458 // internally if data comes from columns or rows. It is intended for
1459 // creating only one used data source.
1460 // @todo: add this information in the range representation strings
1462 // data in columns
1463 if( m_bDataInColumns )
1465 if( aRange.aUpperLeft.nColumn == 0 )
1466 return lcl_aCategoriesRangeName;
1467 if( aRange.aUpperLeft.nRow == 0 )
1468 return lcl_aLabelRangePrefix + OUString::valueOf( aRange.aUpperLeft.nColumn - 1 );
1470 return OUString::valueOf( aRange.aUpperLeft.nColumn - 1 );
1473 // data in rows
1474 if( aRange.aUpperLeft.nRow == 0 )
1475 return lcl_aCategoriesRangeName;
1476 if( aRange.aUpperLeft.nColumn == 0 )
1477 return lcl_aLabelRangePrefix + OUString::valueOf( aRange.aUpperLeft.nRow - 1 );
1479 return OUString::valueOf( aRange.aUpperLeft.nRow - 1 );
1482 // ____ XChartDataArray ____
1483 // note: do not use m_bDataInColumns for all XChartDataArray-specific code
1484 // the chart-API assumes data is always in rows
1485 Sequence< Sequence< double > > SAL_CALL InternalDataProvider::getData()
1486 throw (uno::RuntimeException)
1488 return getInternalData().getData( false );
1491 void SAL_CALL InternalDataProvider::setData( const Sequence< Sequence< double > >& aData )
1492 throw (uno::RuntimeException)
1494 return getInternalData().setData( aData, false );
1497 Sequence< OUString > SAL_CALL InternalDataProvider::getRowDescriptions()
1498 throw (uno::RuntimeException)
1500 return ContainerHelper::ContainerToSequence( getInternalData().getRowLabels());
1503 void SAL_CALL InternalDataProvider::setRowDescriptions( const Sequence< OUString >& aRowDescriptions )
1504 throw (uno::RuntimeException)
1506 getInternalData().setRowLabels( ContainerHelper::SequenceToVector( aRowDescriptions ));
1509 Sequence< OUString > SAL_CALL InternalDataProvider::getColumnDescriptions()
1510 throw (uno::RuntimeException)
1512 return ContainerHelper::ContainerToSequence( getInternalData().getColumnLabels());
1515 void SAL_CALL InternalDataProvider::setColumnDescriptions( const Sequence< OUString >& aColumnDescriptions )
1516 throw (uno::RuntimeException)
1518 getInternalData().setColumnLabels( ContainerHelper::SequenceToVector( aColumnDescriptions ));
1522 // ____ XChartData (base of XChartDataArray) ____
1523 void SAL_CALL InternalDataProvider::addChartDataChangeEventListener(
1524 const Reference< ::com::sun::star::chart::XChartDataChangeEventListener >& )
1525 throw (uno::RuntimeException)
1529 void SAL_CALL InternalDataProvider::removeChartDataChangeEventListener(
1530 const Reference< ::com::sun::star::chart::XChartDataChangeEventListener >& )
1531 throw (uno::RuntimeException)
1535 double SAL_CALL InternalDataProvider::getNotANumber()
1536 throw (uno::RuntimeException)
1538 double fNan;
1539 ::rtl::math::setNan( & fNan );
1540 return fNan;
1543 ::sal_Bool SAL_CALL InternalDataProvider::isNotANumber( double nNumber )
1544 throw (uno::RuntimeException)
1546 return ::rtl::math::isNan( nNumber )
1547 || ::rtl::math::isInf( nNumber );
1549 // lang::XInitialization:
1550 void SAL_CALL InternalDataProvider::initialize(const uno::Sequence< uno::Any > & _aArguments) throw (uno::RuntimeException, uno::Exception)
1552 comphelper::SequenceAsHashMap aArgs(_aArguments);
1553 if ( aArgs.getUnpackedValueOrDefault(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CreateDefaultData")),sal_False) )
1554 createDefaultData();
1556 // ____ XCloneable ____
1557 Reference< util::XCloneable > SAL_CALL InternalDataProvider::createClone()
1558 throw (uno::RuntimeException)
1560 return Reference< util::XCloneable >( new InternalDataProvider( *this ));
1564 // ================================================================================
1566 Sequence< OUString > InternalDataProvider::getSupportedServiceNames_Static()
1568 Sequence< OUString > aServices( 1 );
1569 aServices[ 0 ] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.data.DataProvider" ));
1570 return aServices;
1573 // ================================================================================
1575 APPHELPER_XSERVICEINFO_IMPL( InternalDataProvider, lcl_aServiceName );
1577 } // namespace chart