merged tag ooo/OOO330_m14
[LibreOffice.git] / chart2 / source / tools / InternalData.cxx
blob65fc97a04b3891d2e0db9eef67289f561f4cbcc0
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_chart2.hxx"
31 #include "InternalData.hxx"
32 #include "ResId.hxx"
33 #include "Strings.hrc"
34 #include "macros.hxx"
36 #include <rtl/math.hxx>
38 using ::com::sun::star::uno::Sequence;
39 using ::rtl::OUString;
41 using namespace ::std;
43 namespace chart
46 // ----------------------------------------
47 namespace
49 struct lcl_NumberedStringGenerator
51 lcl_NumberedStringGenerator( const OUString & rStub, const OUString & rWildcard ) :
52 m_aStub( rStub ),
53 m_nCounter( 0 ),
54 m_nStubStartIndex( rStub.indexOf( rWildcard )),
55 m_nWildcardLength( rWildcard.getLength())
58 vector< OUString > operator()()
60 vector< OUString > aRet(1);
61 aRet[0] = m_aStub.replaceAt( m_nStubStartIndex, m_nWildcardLength, OUString::valueOf( ++m_nCounter ));
62 return aRet;
64 private:
65 OUString m_aStub;
66 sal_Int32 m_nCounter;
67 const sal_Int32 m_nStubStartIndex;
68 const sal_Int32 m_nWildcardLength;
71 template< typename T >
72 Sequence< T > lcl_ValarrayToSequence( const ::std::valarray< T > & rValarray )
74 // is there a more elegant way of conversion?
75 Sequence< T > aResult( rValarray.size());
76 for( size_t i = 0; i < rValarray.size(); ++i )
77 aResult[i] = rValarray[i];
78 return aResult;
81 } // anonymous namespace
82 // ----------------------------------------
84 InternalData::InternalData()
85 : m_nColumnCount( 0 )
86 , m_nRowCount( 0 )
87 , m_aRowLabels( 0 )
88 , m_aColumnLabels( 0 )
91 void InternalData::createDefaultData()
93 const sal_Int32 nRowCount = 4;
94 const sal_Int32 nColumnCount = 3;
96 m_nRowCount = nRowCount;
97 m_nColumnCount = nColumnCount;
98 const sal_Int32 nSize = nColumnCount * nRowCount;
99 // @todo: localize this!
100 const OUString aRowName( ::chart::SchResId::getResString( STR_ROW_LABEL ));
101 const OUString aColName( ::chart::SchResId::getResString( STR_COLUMN_LABEL ));
103 const double fDefaultData[ nSize ] =
104 { 9.10, 3.20, 4.54,
105 2.40, 8.80, 9.65,
106 3.10, 1.50, 3.70,
107 4.30, 9.02, 6.20 };
109 m_aData.resize( nSize );
110 for( sal_Int32 i=0; i<nSize; ++i )
111 m_aData[i] = fDefaultData[i];
113 m_aRowLabels.clear();
114 m_aRowLabels.reserve( m_nRowCount );
115 generate_n( back_inserter( m_aRowLabels ), m_nRowCount,
116 lcl_NumberedStringGenerator( aRowName, C2U("%ROWNUMBER") ));
118 m_aColumnLabels.clear();
119 m_aColumnLabels.reserve( m_nColumnCount );
120 generate_n( back_inserter( m_aColumnLabels ), m_nColumnCount,
121 lcl_NumberedStringGenerator( aColName, C2U("%COLUMNNUMBER") ));
124 void InternalData::setData( const Sequence< Sequence< double > >& rDataInRows )
126 m_nRowCount = rDataInRows.getLength();
127 m_nColumnCount = (m_nRowCount ? rDataInRows[0].getLength() : 0);
129 if( m_aRowLabels.size() != static_cast< sal_uInt32 >( m_nRowCount ))
130 m_aRowLabels.resize( m_nRowCount );
131 if( m_aColumnLabels.size() != static_cast< sal_uInt32 >( m_nColumnCount ))
132 m_aColumnLabels.resize( m_nColumnCount );
134 m_aData.resize( m_nRowCount * m_nColumnCount );
135 double fNan;
136 ::rtl::math::setNan( & fNan );
137 // set all values to Nan
138 m_aData = fNan;
140 for( sal_Int32 nRow=0; nRow<m_nRowCount; ++nRow )
142 int nDataIdx = nRow*m_nColumnCount;
143 const sal_Int32 nMax = ::std::min( rDataInRows[nRow].getLength(), m_nColumnCount );
144 for( sal_Int32 nCol=0; nCol < nMax; ++nCol )
146 m_aData[nDataIdx] = rDataInRows[nRow][nCol];
147 nDataIdx += 1;
152 Sequence< Sequence< double > > InternalData::getData() const
154 Sequence< Sequence< double > > aResult( m_nRowCount );
156 for( sal_Int32 i=0; i<m_nRowCount; ++i )
157 aResult[i] = lcl_ValarrayToSequence< tDataType::value_type >(
158 m_aData[ ::std::slice( i*m_nColumnCount, m_nColumnCount, 1 ) ] );
160 return aResult;
163 Sequence< double > InternalData::getColumnValues( sal_Int32 nColumnIndex ) const
165 if( nColumnIndex >= 0 && nColumnIndex < m_nColumnCount )
166 return lcl_ValarrayToSequence< tDataType::value_type >(
167 m_aData[ ::std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ] );
168 return Sequence< double >();
170 Sequence< double > InternalData::getRowValues( sal_Int32 nRowIndex ) const
172 if( nRowIndex >= 0 && nRowIndex < m_nRowCount )
173 return lcl_ValarrayToSequence< tDataType::value_type >(
174 m_aData[ ::std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ] );
175 return Sequence< double >();
178 void InternalData::setColumnValues( sal_Int32 nColumnIndex, const vector< double > & rNewData )
180 if( nColumnIndex < 0 )
181 return;
182 enlargeData( nColumnIndex + 1, rNewData.size() );
184 tDataType aSlice = m_aData[ ::std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ];
185 for( vector< double >::size_type i = 0; i < rNewData.size(); ++i )
186 aSlice[i] = rNewData[i];
187 m_aData[ ::std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ] = aSlice;
190 void InternalData::setRowValues( sal_Int32 nRowIndex, const vector< double > & rNewData )
192 if( nRowIndex < 0 )
193 return;
194 enlargeData( rNewData.size(), nRowIndex+1 );
196 tDataType aSlice = m_aData[ ::std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ];
197 for( vector< double >::size_type i = 0; i < rNewData.size(); ++i )
198 aSlice[i] = rNewData[i];
199 m_aData[ ::std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ]= aSlice;
202 void InternalData::setComplexColumnLabel( sal_Int32 nColumnIndex, const vector< OUString >& rComplexLabel )
204 if( nColumnIndex < 0 )
205 return;
206 if( nColumnIndex >= static_cast< sal_Int32 >( m_aColumnLabels.size() ) )
208 m_aColumnLabels.resize(nColumnIndex+1);
209 enlargeData( nColumnIndex+1, 0 );
212 m_aColumnLabels[nColumnIndex]=rComplexLabel;
214 void InternalData::setComplexRowLabel( sal_Int32 nRowIndex, const vector< OUString >& rComplexLabel )
216 if( nRowIndex < 0 )
217 return;
218 if( nRowIndex >= static_cast< sal_Int32 >( m_aRowLabels.size() ) )
220 m_aRowLabels.resize(nRowIndex+1);
221 enlargeData( 0, nRowIndex+1 );
224 m_aRowLabels[nRowIndex] = rComplexLabel;
227 vector< OUString > InternalData::getComplexColumnLabel( sal_Int32 nColumnIndex ) const
229 if( nColumnIndex < static_cast< sal_Int32 >( m_aColumnLabels.size() ) )
230 return m_aColumnLabels[nColumnIndex];
231 else
232 return vector< OUString >();
234 vector< OUString > InternalData::getComplexRowLabel( sal_Int32 nRowIndex ) const
236 if( nRowIndex < static_cast< sal_Int32 >( m_aRowLabels.size() ) )
237 return m_aRowLabels[nRowIndex];
238 else
239 return vector< OUString >();
242 void InternalData::swapRowWithNext( sal_Int32 nRowIndex )
244 if( nRowIndex < m_nRowCount - 1 )
246 const sal_Int32 nMax = m_nColumnCount;
247 for( sal_Int32 nColIdx=0; nColIdx<nMax; ++nColIdx )
249 size_t nIndex1 = nColIdx + nRowIndex*m_nColumnCount;
250 size_t nIndex2 = nIndex1 + m_nColumnCount;
251 double fTemp = m_aData[nIndex1];
252 m_aData[nIndex1] = m_aData[nIndex2];
253 m_aData[nIndex2] = fTemp;
256 vector< OUString > aTemp( m_aRowLabels[nRowIndex] );
257 m_aRowLabels[nRowIndex] = m_aRowLabels[nRowIndex + 1];
258 m_aRowLabels[nRowIndex + 1] = aTemp;
262 void InternalData::swapColumnWithNext( sal_Int32 nColumnIndex )
264 if( nColumnIndex < m_nColumnCount - 1 )
266 const sal_Int32 nMax = m_nRowCount;
267 for( sal_Int32 nRowIdx=0; nRowIdx<nMax; ++nRowIdx )
269 size_t nIndex1 = nColumnIndex + nRowIdx*m_nColumnCount;
270 size_t nIndex2 = nIndex1 + 1;
271 double fTemp = m_aData[nIndex1];
272 m_aData[nIndex1] = m_aData[nIndex2];
273 m_aData[nIndex2] = fTemp;
276 vector< OUString > aTemp( m_aColumnLabels[nColumnIndex] );
277 m_aColumnLabels[nColumnIndex] = m_aColumnLabels[nColumnIndex + 1];
278 m_aColumnLabels[nColumnIndex + 1] = aTemp;
282 bool InternalData::enlargeData( sal_Int32 nColumnCount, sal_Int32 nRowCount )
284 sal_Int32 nNewColumnCount( ::std::max<sal_Int32>( m_nColumnCount, nColumnCount ) );
285 sal_Int32 nNewRowCount( ::std::max<sal_Int32>( m_nRowCount, nRowCount ) );
286 sal_Int32 nNewSize( nNewColumnCount*nNewRowCount );
288 bool bGrow = (nNewSize > m_nColumnCount*m_nRowCount);
290 if( bGrow )
292 double fNan;
293 ::rtl::math::setNan( &fNan );
294 tDataType aNewData( fNan, nNewSize );
295 // copy old data
296 for( int nCol=0; nCol<m_nColumnCount; ++nCol )
297 static_cast< tDataType >(
298 aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] ) =
299 m_aData[ ::std::slice( nCol, m_nRowCount, m_nColumnCount ) ];
301 m_aData.resize( nNewSize );
302 m_aData = aNewData;
304 m_nColumnCount = nNewColumnCount;
305 m_nRowCount = nNewRowCount;
306 return bGrow;
309 void InternalData::insertColumn( sal_Int32 nAfterIndex )
311 // note: -1 is allowed, as we insert after the given index
312 OSL_ASSERT( nAfterIndex < m_nColumnCount && nAfterIndex >= -1 );
313 if( nAfterIndex >= m_nColumnCount || nAfterIndex < -1 )
314 return;
315 sal_Int32 nNewColumnCount = m_nColumnCount + 1;
316 sal_Int32 nNewSize( nNewColumnCount * m_nRowCount );
318 double fNan;
319 ::rtl::math::setNan( &fNan );
320 tDataType aNewData( fNan, nNewSize );
322 // copy old data
323 int nCol=0;
324 for( ; nCol<=nAfterIndex; ++nCol )
325 aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] =
326 static_cast< tDataType >(
327 m_aData[ ::std::slice( nCol, m_nRowCount, m_nColumnCount ) ] );
328 for( ++nCol; nCol<nNewColumnCount; ++nCol )
329 aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] =
330 static_cast< tDataType >(
331 m_aData[ ::std::slice( nCol - 1, m_nRowCount, m_nColumnCount ) ] );
333 m_nColumnCount = nNewColumnCount;
334 m_aData.resize( nNewSize );
335 m_aData = aNewData;
337 // labels
338 if( nAfterIndex < static_cast< sal_Int32 >( m_aColumnLabels.size()))
339 m_aColumnLabels.insert( m_aColumnLabels.begin() + (nAfterIndex + 1), vector< OUString >(1) );
341 #if OSL_DEBUG_LEVEL > 2
342 traceData();
343 #endif
346 sal_Int32 InternalData::appendColumn()
348 insertColumn( getColumnCount() - 1 );
349 return getColumnCount() - 1;
352 sal_Int32 InternalData::appendRow()
354 insertRow( getRowCount() - 1 );
355 return getRowCount() - 1;
358 void InternalData::insertRow( sal_Int32 nAfterIndex )
360 // note: -1 is allowed, as we insert after the given index
361 OSL_ASSERT( nAfterIndex < m_nRowCount && nAfterIndex >= -1 );
362 if( nAfterIndex >= m_nRowCount || nAfterIndex < -1 )
363 return;
364 sal_Int32 nNewRowCount = m_nRowCount + 1;
365 sal_Int32 nNewSize( m_nColumnCount * nNewRowCount );
367 double fNan;
368 ::rtl::math::setNan( &fNan );
369 tDataType aNewData( fNan, nNewSize );
371 // copy old data
372 sal_Int32 nIndex = nAfterIndex + 1;
373 aNewData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] =
374 static_cast< tDataType >(
375 m_aData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] );
377 if( nIndex < m_nRowCount )
379 sal_Int32 nRemainingCount = m_nColumnCount * (m_nRowCount - nIndex);
380 aNewData[ ::std::slice( (nIndex + 1) * m_nColumnCount, nRemainingCount, 1 ) ] =
381 static_cast< tDataType >(
382 m_aData[ ::std::slice( nIndex * m_nColumnCount, nRemainingCount, 1 ) ] );
385 m_nRowCount = nNewRowCount;
386 m_aData.resize( nNewSize );
387 m_aData = aNewData;
389 // labels
390 if( nAfterIndex < static_cast< sal_Int32 >( m_aRowLabels.size()))
391 m_aRowLabels.insert( m_aRowLabels.begin() + nIndex, vector< OUString> (1));
393 #if OSL_DEBUG_LEVEL > 2
394 traceData();
395 #endif
398 void InternalData::deleteColumn( sal_Int32 nAtIndex )
400 OSL_ASSERT( nAtIndex < m_nColumnCount && nAtIndex >= 0 );
401 if( nAtIndex >= m_nColumnCount || m_nColumnCount < 1 || nAtIndex < 0 )
402 return;
403 sal_Int32 nNewColumnCount = m_nColumnCount - 1;
404 sal_Int32 nNewSize( nNewColumnCount * m_nRowCount );
406 double fNan;
407 ::rtl::math::setNan( &fNan );
408 tDataType aNewData( fNan, nNewSize );
410 // copy old data
411 int nCol=0;
412 for( ; nCol<nAtIndex; ++nCol )
413 aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] =
414 static_cast< tDataType >(
415 m_aData[ ::std::slice( nCol, m_nRowCount, m_nColumnCount ) ] );
416 for( ; nCol<nNewColumnCount; ++nCol )
417 aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] =
418 static_cast< tDataType >(
419 m_aData[ ::std::slice( nCol + 1, m_nRowCount, m_nColumnCount ) ] );
421 m_nColumnCount = nNewColumnCount;
422 m_aData.resize( nNewSize );
423 m_aData = aNewData;
425 // labels
426 if( nAtIndex < static_cast< sal_Int32 >( m_aColumnLabels.size()))
427 m_aColumnLabels.erase( m_aColumnLabels.begin() + nAtIndex );
429 #if OSL_DEBUG_LEVEL > 2
430 traceData();
431 #endif
434 void InternalData::deleteRow( sal_Int32 nAtIndex )
436 OSL_ASSERT( nAtIndex < m_nRowCount && nAtIndex >= 0 );
437 if( nAtIndex >= m_nRowCount || m_nRowCount < 1 || nAtIndex < 0 )
438 return;
439 sal_Int32 nNewRowCount = m_nRowCount - 1;
440 sal_Int32 nNewSize( m_nColumnCount * nNewRowCount );
442 double fNan;
443 ::rtl::math::setNan( &fNan );
444 tDataType aNewData( fNan, nNewSize );
446 // copy old data
447 sal_Int32 nIndex = nAtIndex;
448 if( nIndex )
449 aNewData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] =
450 static_cast< tDataType >(
451 m_aData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] );
453 if( nIndex < nNewRowCount )
455 sal_Int32 nRemainingCount = m_nColumnCount * (nNewRowCount - nIndex);
456 aNewData[ ::std::slice( nIndex * m_nColumnCount, nRemainingCount, 1 ) ] =
457 static_cast< tDataType >(
458 m_aData[ ::std::slice( (nIndex + 1) * m_nColumnCount, nRemainingCount, 1 ) ] );
461 m_nRowCount = nNewRowCount;
462 m_aData.resize( nNewSize );
463 m_aData = aNewData;
465 // labels
466 if( nAtIndex < static_cast< sal_Int32 >( m_aRowLabels.size()))
467 m_aRowLabels.erase( m_aRowLabels.begin() + nAtIndex );
469 #if OSL_DEBUG_LEVEL > 2
470 traceData();
471 #endif
474 sal_Int32 InternalData::getRowCount() const
476 return m_nRowCount;
479 sal_Int32 InternalData::getColumnCount() const
481 return m_nColumnCount;
484 void InternalData::setComplexRowLabels( const vector< vector< OUString > >& rNewRowLabels )
486 m_aRowLabels = rNewRowLabels;
487 sal_Int32 nNewRowCount = static_cast< sal_Int32 >( m_aRowLabels.size() );
488 if( nNewRowCount < m_nRowCount )
489 m_aRowLabels.resize( m_nRowCount );
490 else
491 enlargeData( 0, nNewRowCount );
494 vector< vector< OUString > > InternalData::getComplexRowLabels() const
496 return m_aRowLabels;
499 void InternalData::setComplexColumnLabels( const vector< vector< OUString > >& rNewColumnLabels )
501 m_aColumnLabels = rNewColumnLabels;
502 sal_Int32 nNewColumnCount = static_cast< sal_Int32 >( m_aColumnLabels.size() );
503 if( nNewColumnCount < m_nColumnCount )
504 m_aColumnLabels.resize( m_nColumnCount );
505 else
506 enlargeData( nNewColumnCount, 0 );
509 vector< vector< OUString > > InternalData::getComplexColumnLabels() const
511 return m_aColumnLabels;
514 #if OSL_DEBUG_LEVEL > 2
515 void InternalData::traceData() const
517 OSL_TRACE( "InternalData: Data in rows\n" );
519 for( sal_Int32 i=0; i<m_nRowCount; ++i )
521 tDataType aSlice( m_aData[ ::std::slice( i*m_nColumnCount, m_nColumnCount, 1 ) ] );
522 for( sal_Int32 j=0; j<m_nColumnCount; ++j )
523 OSL_TRACE( "%lf ", aSlice[j] );
524 OSL_TRACE( "\n" );
526 OSL_TRACE( "\n" );
528 #endif
530 } // namespace chart