bump product version to 4.1.6.2
[LibreOffice.git] / chart2 / source / tools / InternalData.cxx
blob61dfaa96598f44e65d70b839ef451bb002168ca6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "InternalData.hxx"
22 #include "ResId.hxx"
23 #include "Strings.hrc"
25 #include <rtl/math.hxx>
26 #include <algorithm>
27 #include <iterator>
29 using ::com::sun::star::uno::Sequence;
31 using namespace ::com::sun::star;
32 using namespace ::std;
34 namespace chart
37 // ----------------------------------------
38 namespace
40 struct lcl_NumberedStringGenerator
42 lcl_NumberedStringGenerator( const OUString & rStub, const OUString & rWildcard ) :
43 m_aStub( rStub ),
44 m_nCounter( 0 ),
45 m_nStubStartIndex( rStub.indexOf( rWildcard )),
46 m_nWildcardLength( rWildcard.getLength())
49 vector< uno::Any > operator()()
51 vector< uno::Any > aRet(1);
52 aRet[0] = uno::makeAny( m_aStub.replaceAt( m_nStubStartIndex, m_nWildcardLength, OUString::valueOf( ++m_nCounter )) );
53 return aRet;
55 private:
56 OUString m_aStub;
57 sal_Int32 m_nCounter;
58 const sal_Int32 m_nStubStartIndex;
59 const sal_Int32 m_nWildcardLength;
62 template< typename T >
63 Sequence< T > lcl_ValarrayToSequence( const ::std::valarray< T > & rValarray )
65 // is there a more elegant way of conversion?
66 Sequence< T > aResult( rValarray.size());
67 for( size_t i = 0; i < rValarray.size(); ++i )
68 aResult[i] = rValarray[i];
69 return aResult;
72 } // anonymous namespace
73 // ----------------------------------------
75 InternalData::InternalData()
76 : m_nColumnCount( 0 )
77 , m_nRowCount( 0 )
78 , m_aRowLabels( 0 )
79 , m_aColumnLabels( 0 )
82 static const double fDefaultData[] = {
83 9.10, 3.20, 4.54,
84 2.40, 8.80, 9.65,
85 3.10, 1.50, 3.70,
86 4.30, 9.02, 6.20
89 void InternalData::createDefaultData()
91 const sal_Int32 nRowCount = 4;
92 const sal_Int32 nColumnCount = 3;
94 m_nRowCount = nRowCount;
95 m_nColumnCount = nColumnCount;
96 const sal_Int32 nSize = nColumnCount * nRowCount;
97 // @todo: localize this!
98 const OUString aRowName(SCH_RESSTR(STR_ROW_LABEL));
99 const OUString aColName(SCH_RESSTR(STR_COLUMN_LABEL));
101 m_aData.resize( nSize );
102 for( sal_Int32 i=0; i<nSize; ++i )
103 m_aData[i] = fDefaultData[i];
105 m_aRowLabels.clear();
106 m_aRowLabels.reserve( m_nRowCount );
107 generate_n( back_inserter( m_aRowLabels ), m_nRowCount,
108 lcl_NumberedStringGenerator( aRowName, "%ROWNUMBER" ));
110 m_aColumnLabels.clear();
111 m_aColumnLabels.reserve( m_nColumnCount );
112 generate_n( back_inserter( m_aColumnLabels ), m_nColumnCount,
113 lcl_NumberedStringGenerator( aColName, "%COLUMNNUMBER" ));
116 bool InternalData::isDefaultData()
119 if( m_nRowCount == 4 && m_nColumnCount == 3 )
121 for( sal_Int32 i=0; i<(4*3); ++i )
122 if( m_aData[i] != fDefaultData[i] )
123 return false;
125 return true;
127 return false;
130 void InternalData::clearDefaultData()
132 if( isDefaultData() )
134 m_nRowCount = m_nColumnCount = 1;
135 m_aData.resize( 1 );
136 m_aRowLabels.clear();
137 m_aColumnLabels.clear();
141 void InternalData::setData( const Sequence< Sequence< double > >& rDataInRows )
143 m_nRowCount = rDataInRows.getLength();
144 m_nColumnCount = (m_nRowCount ? rDataInRows[0].getLength() : 0);
146 if( m_aRowLabels.size() != static_cast< sal_uInt32 >( m_nRowCount ))
147 m_aRowLabels.resize( m_nRowCount );
148 if( m_aColumnLabels.size() != static_cast< sal_uInt32 >( m_nColumnCount ))
149 m_aColumnLabels.resize( m_nColumnCount );
151 m_aData.resize( m_nRowCount * m_nColumnCount );
152 double fNan;
153 ::rtl::math::setNan( & fNan );
154 // set all values to Nan
155 m_aData = fNan;
157 for( sal_Int32 nRow=0; nRow<m_nRowCount; ++nRow )
159 int nDataIdx = nRow*m_nColumnCount;
160 const sal_Int32 nMax = ::std::min( rDataInRows[nRow].getLength(), m_nColumnCount );
161 for( sal_Int32 nCol=0; nCol < nMax; ++nCol )
163 m_aData[nDataIdx] = rDataInRows[nRow][nCol];
164 nDataIdx += 1;
169 Sequence< Sequence< double > > InternalData::getData() const
171 Sequence< Sequence< double > > aResult( m_nRowCount );
173 for( sal_Int32 i=0; i<m_nRowCount; ++i )
174 aResult[i] = lcl_ValarrayToSequence< tDataType::value_type >(
175 m_aData[ ::std::slice( i*m_nColumnCount, m_nColumnCount, 1 ) ] );
177 return aResult;
180 Sequence< double > InternalData::getColumnValues( sal_Int32 nColumnIndex ) const
182 if( nColumnIndex >= 0 && nColumnIndex < m_nColumnCount )
183 return lcl_ValarrayToSequence< tDataType::value_type >(
184 m_aData[ ::std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ] );
185 return Sequence< double >();
187 Sequence< double > InternalData::getRowValues( sal_Int32 nRowIndex ) const
189 if( nRowIndex >= 0 && nRowIndex < m_nRowCount )
190 return lcl_ValarrayToSequence< tDataType::value_type >(
191 m_aData[ ::std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ] );
192 return Sequence< double >();
195 void InternalData::setColumnValues( sal_Int32 nColumnIndex, const vector< double > & rNewData )
197 if( nColumnIndex < 0 )
198 return;
199 enlargeData( nColumnIndex + 1, rNewData.size() );
201 tDataType aSlice = m_aData[ ::std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ];
202 for( vector< double >::size_type i = 0; i < rNewData.size(); ++i )
203 aSlice[i] = rNewData[i];
204 m_aData[ ::std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ] = aSlice;
207 void InternalData::setRowValues( sal_Int32 nRowIndex, const vector< double > & rNewData )
209 if( nRowIndex < 0 )
210 return;
211 enlargeData( rNewData.size(), nRowIndex+1 );
213 tDataType aSlice = m_aData[ ::std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ];
214 for( vector< double >::size_type i = 0; i < rNewData.size(); ++i )
215 aSlice[i] = rNewData[i];
216 m_aData[ ::std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ]= aSlice;
219 void InternalData::setComplexColumnLabel( sal_Int32 nColumnIndex, const vector< uno::Any >& rComplexLabel )
221 if( nColumnIndex < 0 )
222 return;
223 if( nColumnIndex >= static_cast< sal_Int32 >( m_aColumnLabels.size() ) )
225 m_aColumnLabels.resize(nColumnIndex+1);
226 enlargeData( nColumnIndex+1, 0 );
228 m_aColumnLabels[nColumnIndex]=rComplexLabel;
231 void InternalData::setComplexRowLabel( sal_Int32 nRowIndex, const vector< uno::Any >& rComplexLabel )
233 if( nRowIndex < 0 )
234 return;
235 if( nRowIndex >= static_cast< sal_Int32 >( m_aRowLabels.size() ) )
237 m_aRowLabels.resize(nRowIndex+1);
238 enlargeData( 0, nRowIndex+1 );
240 m_aRowLabels[nRowIndex] = rComplexLabel;
243 vector< uno::Any > InternalData::getComplexColumnLabel( sal_Int32 nColumnIndex ) const
245 if( nColumnIndex < static_cast< sal_Int32 >( m_aColumnLabels.size() ) )
246 return m_aColumnLabels[nColumnIndex];
247 else
248 return vector< uno::Any >();
250 vector< uno::Any > InternalData::getComplexRowLabel( sal_Int32 nRowIndex ) const
252 if( nRowIndex < static_cast< sal_Int32 >( m_aRowLabels.size() ) )
253 return m_aRowLabels[nRowIndex];
254 else
255 return vector< uno::Any >();
258 void InternalData::swapRowWithNext( sal_Int32 nRowIndex )
260 if( nRowIndex < m_nRowCount - 1 )
262 const sal_Int32 nMax = m_nColumnCount;
263 for( sal_Int32 nColIdx=0; nColIdx<nMax; ++nColIdx )
265 size_t nIndex1 = nColIdx + nRowIndex*m_nColumnCount;
266 size_t nIndex2 = nIndex1 + m_nColumnCount;
267 double fTemp = m_aData[nIndex1];
268 m_aData[nIndex1] = m_aData[nIndex2];
269 m_aData[nIndex2] = fTemp;
272 vector< uno::Any > aTemp( m_aRowLabels[nRowIndex] );
273 m_aRowLabels[nRowIndex] = m_aRowLabels[nRowIndex + 1];
274 m_aRowLabels[nRowIndex + 1] = aTemp;
278 void InternalData::swapColumnWithNext( sal_Int32 nColumnIndex )
280 if( nColumnIndex < m_nColumnCount - 1 )
282 const sal_Int32 nMax = m_nRowCount;
283 for( sal_Int32 nRowIdx=0; nRowIdx<nMax; ++nRowIdx )
285 size_t nIndex1 = nColumnIndex + nRowIdx*m_nColumnCount;
286 size_t nIndex2 = nIndex1 + 1;
287 double fTemp = m_aData[nIndex1];
288 m_aData[nIndex1] = m_aData[nIndex2];
289 m_aData[nIndex2] = fTemp;
292 vector< uno::Any > aTemp( m_aColumnLabels[nColumnIndex] );
293 m_aColumnLabels[nColumnIndex] = m_aColumnLabels[nColumnIndex + 1];
294 m_aColumnLabels[nColumnIndex + 1] = aTemp;
298 bool InternalData::enlargeData( sal_Int32 nColumnCount, sal_Int32 nRowCount )
300 sal_Int32 nNewColumnCount( ::std::max<sal_Int32>( m_nColumnCount, nColumnCount ) );
301 sal_Int32 nNewRowCount( ::std::max<sal_Int32>( m_nRowCount, nRowCount ) );
302 sal_Int32 nNewSize( nNewColumnCount*nNewRowCount );
304 bool bGrow = (nNewSize > m_nColumnCount*m_nRowCount);
306 if( bGrow )
308 double fNan;
309 ::rtl::math::setNan( &fNan );
310 tDataType aNewData( fNan, nNewSize );
311 // copy old data
312 for( int nCol=0; nCol<m_nColumnCount; ++nCol )
313 static_cast< tDataType >(
314 aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] ) =
315 m_aData[ ::std::slice( nCol, m_nRowCount, m_nColumnCount ) ];
317 m_aData.resize( nNewSize );
318 m_aData = aNewData;
320 m_nColumnCount = nNewColumnCount;
321 m_nRowCount = nNewRowCount;
322 return bGrow;
325 void InternalData::insertColumn( sal_Int32 nAfterIndex )
327 // note: -1 is allowed, as we insert after the given index
328 OSL_ASSERT( nAfterIndex < m_nColumnCount && nAfterIndex >= -1 );
329 if( nAfterIndex >= m_nColumnCount || nAfterIndex < -1 )
330 return;
331 sal_Int32 nNewColumnCount = m_nColumnCount + 1;
332 sal_Int32 nNewSize( nNewColumnCount * m_nRowCount );
334 double fNan;
335 ::rtl::math::setNan( &fNan );
336 tDataType aNewData( fNan, nNewSize );
338 // copy old data
339 int nCol=0;
340 for( ; nCol<=nAfterIndex; ++nCol )
341 aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] =
342 static_cast< tDataType >(
343 m_aData[ ::std::slice( nCol, m_nRowCount, m_nColumnCount ) ] );
344 for( ++nCol; nCol<nNewColumnCount; ++nCol )
345 aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] =
346 static_cast< tDataType >(
347 m_aData[ ::std::slice( nCol - 1, m_nRowCount, m_nColumnCount ) ] );
349 m_nColumnCount = nNewColumnCount;
350 m_aData.resize( nNewSize );
351 m_aData = aNewData;
353 // labels
354 if( nAfterIndex < static_cast< sal_Int32 >( m_aColumnLabels.size()))
355 m_aColumnLabels.insert( m_aColumnLabels.begin() + (nAfterIndex + 1), vector< uno::Any >(1) );
357 #if OSL_DEBUG_LEVEL > 1
358 traceData();
359 #endif
362 sal_Int32 InternalData::appendColumn()
364 insertColumn( getColumnCount() - 1 );
365 return getColumnCount() - 1;
368 sal_Int32 InternalData::appendRow()
370 insertRow( getRowCount() - 1 );
371 return getRowCount() - 1;
374 void InternalData::insertRow( sal_Int32 nAfterIndex )
376 // note: -1 is allowed, as we insert after the given index
377 OSL_ASSERT( nAfterIndex < m_nRowCount && nAfterIndex >= -1 );
378 if( nAfterIndex >= m_nRowCount || nAfterIndex < -1 )
379 return;
380 sal_Int32 nNewRowCount = m_nRowCount + 1;
381 sal_Int32 nNewSize( m_nColumnCount * nNewRowCount );
383 double fNan;
384 ::rtl::math::setNan( &fNan );
385 tDataType aNewData( fNan, nNewSize );
387 // copy old data
388 sal_Int32 nIndex = nAfterIndex + 1;
389 aNewData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] =
390 static_cast< tDataType >(
391 m_aData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] );
393 if( nIndex < m_nRowCount )
395 sal_Int32 nRemainingCount = m_nColumnCount * (m_nRowCount - nIndex);
396 aNewData[ ::std::slice( (nIndex + 1) * m_nColumnCount, nRemainingCount, 1 ) ] =
397 static_cast< tDataType >(
398 m_aData[ ::std::slice( nIndex * m_nColumnCount, nRemainingCount, 1 ) ] );
401 m_nRowCount = nNewRowCount;
402 m_aData.resize( nNewSize );
403 m_aData = aNewData;
405 // labels
406 if( nAfterIndex < static_cast< sal_Int32 >( m_aRowLabels.size()))
407 m_aRowLabels.insert( m_aRowLabels.begin() + nIndex, vector< uno::Any > (1));
409 #if OSL_DEBUG_LEVEL > 1
410 traceData();
411 #endif
414 void InternalData::deleteColumn( sal_Int32 nAtIndex )
416 OSL_ASSERT( nAtIndex < m_nColumnCount && nAtIndex >= 0 );
417 if( nAtIndex >= m_nColumnCount || m_nColumnCount < 1 || nAtIndex < 0 )
418 return;
419 sal_Int32 nNewColumnCount = m_nColumnCount - 1;
420 sal_Int32 nNewSize( nNewColumnCount * m_nRowCount );
422 double fNan;
423 ::rtl::math::setNan( &fNan );
424 tDataType aNewData( fNan, nNewSize );
426 // copy old data
427 int nCol=0;
428 for( ; nCol<nAtIndex; ++nCol )
429 aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] =
430 static_cast< tDataType >(
431 m_aData[ ::std::slice( nCol, m_nRowCount, m_nColumnCount ) ] );
432 for( ; nCol<nNewColumnCount; ++nCol )
433 aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] =
434 static_cast< tDataType >(
435 m_aData[ ::std::slice( nCol + 1, m_nRowCount, m_nColumnCount ) ] );
437 m_nColumnCount = nNewColumnCount;
438 m_aData.resize( nNewSize );
439 m_aData = aNewData;
441 // labels
442 if( nAtIndex < static_cast< sal_Int32 >( m_aColumnLabels.size()))
443 m_aColumnLabels.erase( m_aColumnLabels.begin() + nAtIndex );
445 #if OSL_DEBUG_LEVEL > 1
446 traceData();
447 #endif
450 void InternalData::deleteRow( sal_Int32 nAtIndex )
452 OSL_ASSERT( nAtIndex < m_nRowCount && nAtIndex >= 0 );
453 if( nAtIndex >= m_nRowCount || m_nRowCount < 1 || nAtIndex < 0 )
454 return;
455 sal_Int32 nNewRowCount = m_nRowCount - 1;
456 sal_Int32 nNewSize( m_nColumnCount * nNewRowCount );
458 double fNan;
459 ::rtl::math::setNan( &fNan );
460 tDataType aNewData( fNan, nNewSize );
462 // copy old data
463 sal_Int32 nIndex = nAtIndex;
464 if( nIndex )
465 aNewData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] =
466 static_cast< tDataType >(
467 m_aData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] );
469 if( nIndex < nNewRowCount )
471 sal_Int32 nRemainingCount = m_nColumnCount * (nNewRowCount - nIndex);
472 aNewData[ ::std::slice( nIndex * m_nColumnCount, nRemainingCount, 1 ) ] =
473 static_cast< tDataType >(
474 m_aData[ ::std::slice( (nIndex + 1) * m_nColumnCount, nRemainingCount, 1 ) ] );
477 m_nRowCount = nNewRowCount;
478 m_aData.resize( nNewSize );
479 m_aData = aNewData;
481 // labels
482 if( nAtIndex < static_cast< sal_Int32 >( m_aRowLabels.size()))
483 m_aRowLabels.erase( m_aRowLabels.begin() + nAtIndex );
485 #if OSL_DEBUG_LEVEL > 1
486 traceData();
487 #endif
490 sal_Int32 InternalData::getRowCount() const
492 return m_nRowCount;
495 sal_Int32 InternalData::getColumnCount() const
497 return m_nColumnCount;
500 void InternalData::setComplexRowLabels( const vector< vector< uno::Any > >& rNewRowLabels )
502 m_aRowLabels = rNewRowLabels;
503 sal_Int32 nNewRowCount = static_cast< sal_Int32 >( m_aRowLabels.size() );
504 if( nNewRowCount < m_nRowCount )
505 m_aRowLabels.resize( m_nRowCount );
506 else
507 enlargeData( 0, nNewRowCount );
510 vector< vector< uno::Any > > InternalData::getComplexRowLabels() const
512 return m_aRowLabels;
515 void InternalData::setComplexColumnLabels( const vector< vector< uno::Any > >& rNewColumnLabels )
517 m_aColumnLabels = rNewColumnLabels;
518 sal_Int32 nNewColumnCount = static_cast< sal_Int32 >( m_aColumnLabels.size() );
519 if( nNewColumnCount < m_nColumnCount )
520 m_aColumnLabels.resize( m_nColumnCount );
521 else
522 enlargeData( nNewColumnCount, 0 );
525 vector< vector< uno::Any > > InternalData::getComplexColumnLabels() const
527 return m_aColumnLabels;
530 #if OSL_DEBUG_LEVEL > 1
531 void InternalData::traceData() const
533 OSL_TRACE( "InternalData: Data in rows" );
535 for( sal_Int32 i=0; i<m_nRowCount; ++i )
537 tDataType aSlice( m_aData[ ::std::slice( i*m_nColumnCount, m_nColumnCount, 1 ) ] );
538 for( sal_Int32 j=0; j<m_nColumnCount; ++j )
539 OSL_TRACE( "%lf ", aSlice[j] );
540 OSL_TRACE( "\n" );
542 OSL_TRACE( "\n" );
544 #endif
546 } // namespace chart
548 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */