1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
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.
14  *
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).
20  *
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.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_chart2.hxx"
30 
31 #include "InternalData.hxx"
32 #include "ResId.hxx"
33 #include "Strings.hrc"
34 #include "macros.hxx"
35 
36 #include <rtl/math.hxx>
37 
38 using ::com::sun::star::uno::Sequence;
39 using ::rtl::OUString;
40 
41 using namespace ::com::sun::star;
42 using namespace ::std;
43 
44 namespace chart
45 {
46 
47 // ----------------------------------------
48 namespace
49 {
50 struct lcl_NumberedStringGenerator
51 {
52     lcl_NumberedStringGenerator( const OUString & rStub, const OUString & rWildcard ) :
53             m_aStub( rStub ),
54             m_nCounter( 0 ),
55             m_nStubStartIndex( rStub.indexOf( rWildcard )),
56             m_nWildcardLength( rWildcard.getLength())
57     {
58     }
59     vector< uno::Any > operator()()
60     {
61         vector< uno::Any > aRet(1);
62         aRet[0] = uno::makeAny( m_aStub.replaceAt( m_nStubStartIndex, m_nWildcardLength, OUString::valueOf( ++m_nCounter )) );
63         return aRet;
64     }
65 private:
66     OUString m_aStub;
67     sal_Int32 m_nCounter;
68     const sal_Int32 m_nStubStartIndex;
69     const sal_Int32 m_nWildcardLength;
70 };
71 
72 template< typename T >
73     Sequence< T > lcl_ValarrayToSequence( const ::std::valarray< T > & rValarray )
74 {
75     // is there a more elegant way of conversion?
76     Sequence< T > aResult( rValarray.size());
77     for( size_t i = 0; i < rValarray.size(); ++i )
78         aResult[i] = rValarray[i];
79     return aResult;
80 }
81 
82 } // anonymous namespace
83 // ----------------------------------------
84 
85 InternalData::InternalData()
86     : m_nColumnCount( 0 )
87     , m_nRowCount( 0 )
88     , m_aRowLabels( 0 )
89     , m_aColumnLabels( 0 )
90 {}
91 
92 void InternalData::createDefaultData()
93 {
94     const sal_Int32 nRowCount = 4;
95     const sal_Int32 nColumnCount = 3;
96 
97     m_nRowCount = nRowCount;
98     m_nColumnCount = nColumnCount;
99     const sal_Int32 nSize = nColumnCount * nRowCount;
100     // @todo: localize this!
101     const OUString aRowName( ::chart::SchResId::getResString( STR_ROW_LABEL ));
102     const OUString aColName( ::chart::SchResId::getResString( STR_COLUMN_LABEL ));
103 
104     const double fDefaultData[ nSize ] =
105         { 9.10, 3.20, 4.54,
106           2.40, 8.80, 9.65,
107           3.10, 1.50, 3.70,
108           4.30, 9.02, 6.20 };
109 
110     m_aData.resize( nSize );
111     for( sal_Int32 i=0; i<nSize; ++i )
112         m_aData[i] = fDefaultData[i];
113 
114     m_aRowLabels.clear();
115     m_aRowLabels.reserve( m_nRowCount );
116     generate_n( back_inserter( m_aRowLabels ), m_nRowCount,
117         lcl_NumberedStringGenerator( aRowName, C2U("%ROWNUMBER") ));
118 
119     m_aColumnLabels.clear();
120     m_aColumnLabels.reserve( m_nColumnCount );
121     generate_n( back_inserter( m_aColumnLabels ), m_nColumnCount,
122         lcl_NumberedStringGenerator( aColName, C2U("%COLUMNNUMBER") ));
123 }
124 
125 void InternalData::setData( const Sequence< Sequence< double > >& rDataInRows )
126 {
127     m_nRowCount = rDataInRows.getLength();
128     m_nColumnCount = (m_nRowCount ? rDataInRows[0].getLength() : 0);
129 
130     if( m_aRowLabels.size() != static_cast< sal_uInt32 >( m_nRowCount ))
131         m_aRowLabels.resize( m_nRowCount );
132     if( m_aColumnLabels.size() != static_cast< sal_uInt32 >( m_nColumnCount ))
133         m_aColumnLabels.resize( m_nColumnCount );
134 
135     m_aData.resize( m_nRowCount * m_nColumnCount );
136     double fNan;
137     ::rtl::math::setNan( & fNan );
138     // set all values to Nan
139     m_aData = fNan;
140 
141     for( sal_Int32 nRow=0; nRow<m_nRowCount; ++nRow )
142     {
143         int nDataIdx = nRow*m_nColumnCount;
144         const sal_Int32 nMax = ::std::min( rDataInRows[nRow].getLength(), m_nColumnCount );
145         for( sal_Int32 nCol=0; nCol < nMax; ++nCol )
146         {
147             m_aData[nDataIdx] = rDataInRows[nRow][nCol];
148             nDataIdx += 1;
149         }
150     }
151 }
152 
153 Sequence< Sequence< double > > InternalData::getData() const
154 {
155     Sequence< Sequence< double > > aResult( m_nRowCount );
156 
157     for( sal_Int32 i=0; i<m_nRowCount; ++i )
158         aResult[i] = lcl_ValarrayToSequence< tDataType::value_type >(
159             m_aData[ ::std::slice( i*m_nColumnCount, m_nColumnCount, 1 ) ] );
160 
161     return aResult;
162 }
163 
164 Sequence< double > InternalData::getColumnValues( sal_Int32 nColumnIndex ) const
165 {
166     if( nColumnIndex >= 0 && nColumnIndex < m_nColumnCount )
167         return lcl_ValarrayToSequence< tDataType::value_type >(
168             m_aData[ ::std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ] );
169     return Sequence< double >();
170 }
171 Sequence< double > InternalData::getRowValues( sal_Int32 nRowIndex ) const
172 {
173     if( nRowIndex >= 0 && nRowIndex < m_nRowCount )
174         return lcl_ValarrayToSequence< tDataType::value_type >(
175             m_aData[ ::std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ] );
176     return Sequence< double >();
177 }
178 
179 void InternalData::setColumnValues( sal_Int32 nColumnIndex, const vector< double > & rNewData )
180 {
181     if( nColumnIndex < 0 )
182         return;
183     enlargeData( nColumnIndex + 1, rNewData.size() );
184 
185     tDataType aSlice = m_aData[ ::std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ];
186     for( vector< double >::size_type i = 0; i < rNewData.size(); ++i )
187         aSlice[i] = rNewData[i];
188     m_aData[ ::std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ] = aSlice;
189 }
190 
191 void InternalData::setRowValues( sal_Int32 nRowIndex, const vector< double > & rNewData )
192 {
193     if( nRowIndex < 0 )
194         return;
195     enlargeData( rNewData.size(), nRowIndex+1 );
196 
197     tDataType aSlice = m_aData[ ::std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ];
198     for( vector< double >::size_type i = 0; i < rNewData.size(); ++i )
199         aSlice[i] = rNewData[i];
200     m_aData[ ::std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ]= aSlice;
201 }
202 
203 void InternalData::setComplexColumnLabel( sal_Int32 nColumnIndex, const vector< uno::Any >& rComplexLabel )
204 {
205     if( nColumnIndex < 0 )
206         return;
207     if( nColumnIndex >= static_cast< sal_Int32 >( m_aColumnLabels.size() ) )
208     {
209         m_aColumnLabels.resize(nColumnIndex+1);
210         enlargeData( nColumnIndex+1, 0 );
211     }
212     m_aColumnLabels[nColumnIndex]=rComplexLabel;
213 }
214 
215 void InternalData::setComplexRowLabel( sal_Int32 nRowIndex, const vector< uno::Any >& rComplexLabel )
216 {
217     if( nRowIndex < 0 )
218         return;
219     if( nRowIndex >= static_cast< sal_Int32 >( m_aRowLabels.size() ) )
220     {
221         m_aRowLabels.resize(nRowIndex+1);
222         enlargeData( 0, nRowIndex+1 );
223     }
224     m_aRowLabels[nRowIndex] = rComplexLabel;
225 }
226 
227 vector< uno::Any > InternalData::getComplexColumnLabel( sal_Int32 nColumnIndex ) const
228 {
229     if( nColumnIndex < static_cast< sal_Int32 >( m_aColumnLabels.size() ) )
230         return m_aColumnLabels[nColumnIndex];
231     else
232         return vector< uno::Any >();
233 }
234 vector< uno::Any > InternalData::getComplexRowLabel( sal_Int32 nRowIndex ) const
235 {
236     if( nRowIndex < static_cast< sal_Int32 >( m_aRowLabels.size() ) )
237         return m_aRowLabels[nRowIndex];
238     else
239         return vector< uno::Any >();
240 }
241 
242 void InternalData::swapRowWithNext( sal_Int32 nRowIndex )
243 {
244     if( nRowIndex < m_nRowCount - 1 )
245     {
246         const sal_Int32 nMax = m_nColumnCount;
247         for( sal_Int32 nColIdx=0; nColIdx<nMax; ++nColIdx )
248         {
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;
254         }
255 
256         vector< uno::Any > aTemp( m_aRowLabels[nRowIndex] );
257         m_aRowLabels[nRowIndex] = m_aRowLabels[nRowIndex + 1];
258         m_aRowLabels[nRowIndex + 1] = aTemp;
259     }
260 }
261 
262 void InternalData::swapColumnWithNext( sal_Int32 nColumnIndex )
263 {
264     if( nColumnIndex < m_nColumnCount - 1 )
265     {
266         const sal_Int32 nMax = m_nRowCount;
267         for( sal_Int32 nRowIdx=0; nRowIdx<nMax; ++nRowIdx )
268         {
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;
274         }
275 
276         vector< uno::Any > aTemp( m_aColumnLabels[nColumnIndex] );
277         m_aColumnLabels[nColumnIndex] = m_aColumnLabels[nColumnIndex + 1];
278         m_aColumnLabels[nColumnIndex + 1] = aTemp;
279     }
280 }
281 
282 bool InternalData::enlargeData( sal_Int32 nColumnCount, sal_Int32 nRowCount )
283 {
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 );
287 
288     bool bGrow = (nNewSize > m_nColumnCount*m_nRowCount);
289 
290     if( bGrow )
291     {
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 ) ];
300 
301         m_aData.resize( nNewSize );
302         m_aData = aNewData;
303     }
304     m_nColumnCount = nNewColumnCount;
305     m_nRowCount = nNewRowCount;
306     return bGrow;
307 }
308 
309 void InternalData::insertColumn( sal_Int32 nAfterIndex )
310 {
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 );
317 
318     double fNan;
319     ::rtl::math::setNan( &fNan );
320     tDataType aNewData( fNan, nNewSize );
321 
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 ) ] );
332 
333     m_nColumnCount = nNewColumnCount;
334     m_aData.resize( nNewSize );
335     m_aData = aNewData;
336 
337     // labels
338     if( nAfterIndex < static_cast< sal_Int32 >( m_aColumnLabels.size()))
339         m_aColumnLabels.insert( m_aColumnLabels.begin() + (nAfterIndex + 1), vector< uno::Any >(1) );
340 
341 #if OSL_DEBUG_LEVEL > 2
342     traceData();
343 #endif
344 }
345 
346 sal_Int32 InternalData::appendColumn()
347 {
348     insertColumn( getColumnCount() - 1 );
349     return getColumnCount() - 1;
350 }
351 
352 sal_Int32 InternalData::appendRow()
353 {
354     insertRow( getRowCount() - 1 );
355     return getRowCount() - 1;
356 }
357 
358 void InternalData::insertRow( sal_Int32 nAfterIndex )
359 {
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 );
366 
367     double fNan;
368     ::rtl::math::setNan( &fNan );
369     tDataType aNewData( fNan, nNewSize );
370 
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 ) ] );
376 
377     if( nIndex < m_nRowCount )
378     {
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 ) ] );
383     }
384 
385     m_nRowCount = nNewRowCount;
386     m_aData.resize( nNewSize );
387     m_aData = aNewData;
388 
389     // labels
390     if( nAfterIndex < static_cast< sal_Int32 >( m_aRowLabels.size()))
391         m_aRowLabels.insert( m_aRowLabels.begin() + nIndex, vector< uno::Any > (1));
392 
393 #if OSL_DEBUG_LEVEL > 2
394     traceData();
395 #endif
396 }
397 
398 void InternalData::deleteColumn( sal_Int32 nAtIndex )
399 {
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 );
405 
406     double fNan;
407     ::rtl::math::setNan( &fNan );
408     tDataType aNewData( fNan, nNewSize );
409 
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 ) ] );
420 
421     m_nColumnCount = nNewColumnCount;
422     m_aData.resize( nNewSize );
423     m_aData = aNewData;
424 
425     // labels
426     if( nAtIndex < static_cast< sal_Int32 >( m_aColumnLabels.size()))
427         m_aColumnLabels.erase( m_aColumnLabels.begin() + nAtIndex );
428 
429 #if OSL_DEBUG_LEVEL > 2
430     traceData();
431 #endif
432 }
433 
434 void InternalData::deleteRow( sal_Int32 nAtIndex )
435 {
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 );
441 
442     double fNan;
443     ::rtl::math::setNan( &fNan );
444     tDataType aNewData( fNan, nNewSize );
445 
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 ) ] );
452 
453     if( nIndex < nNewRowCount )
454     {
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 ) ] );
459     }
460 
461     m_nRowCount = nNewRowCount;
462     m_aData.resize( nNewSize );
463     m_aData = aNewData;
464 
465     // labels
466     if( nAtIndex < static_cast< sal_Int32 >( m_aRowLabels.size()))
467         m_aRowLabels.erase( m_aRowLabels.begin() + nAtIndex );
468 
469 #if OSL_DEBUG_LEVEL > 2
470     traceData();
471 #endif
472 }
473 
474 sal_Int32 InternalData::getRowCount() const
475 {
476     return m_nRowCount;
477 }
478 
479 sal_Int32 InternalData::getColumnCount() const
480 {
481     return m_nColumnCount;
482 }
483 
484 void InternalData::setComplexRowLabels( const vector< vector< uno::Any > >& rNewRowLabels )
485 {
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 );
492 }
493 
494 vector< vector< uno::Any > > InternalData::getComplexRowLabels() const
495 {
496     return m_aRowLabels;
497 }
498 
499 void InternalData::setComplexColumnLabels( const vector< vector< uno::Any > >& rNewColumnLabels )
500 {
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 );
507 }
508 
509 vector< vector< uno::Any > > InternalData::getComplexColumnLabels() const
510 {
511     return m_aColumnLabels;
512 }
513 
514 #if OSL_DEBUG_LEVEL > 2
515 void InternalData::traceData() const
516 {
517     OSL_TRACE( "InternalData: Data in rows\n" );
518 
519     for( sal_Int32 i=0; i<m_nRowCount; ++i )
520     {
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" );
525     }
526     OSL_TRACE( "\n" );
527 }
528 #endif
529 
530 } //  namespace chart
531