1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_chart2.hxx"
26 
27 #include "InternalData.hxx"
28 #include "ResId.hxx"
29 #include "Strings.hrc"
30 #include "macros.hxx"
31 
32 #include <rtl/math.hxx>
33 #include <algorithm>
34 
35 using ::com::sun::star::uno::Sequence;
36 using ::rtl::OUString;
37 
38 using namespace ::com::sun::star;
39 using namespace ::std;
40 
41 namespace chart
42 {
43 
44 // ----------------------------------------
45 namespace
46 {
47 struct lcl_NumberedStringGenerator
48 {
lcl_NumberedStringGeneratorchart::__anonfac9888a0111::lcl_NumberedStringGenerator49     lcl_NumberedStringGenerator( const OUString & rStub, const OUString & rWildcard ) :
50             m_aStub( rStub ),
51             m_nCounter( 0 ),
52             m_nStubStartIndex( rStub.indexOf( rWildcard )),
53             m_nWildcardLength( rWildcard.getLength())
54     {
55     }
operator ()chart::__anonfac9888a0111::lcl_NumberedStringGenerator56     vector< uno::Any > operator()()
57     {
58         vector< uno::Any > aRet(1);
59         aRet[0] = uno::makeAny( m_aStub.replaceAt( m_nStubStartIndex, m_nWildcardLength, OUString::valueOf( ++m_nCounter )) );
60         return aRet;
61     }
62 private:
63     OUString m_aStub;
64     sal_Int32 m_nCounter;
65     const sal_Int32 m_nStubStartIndex;
66     const sal_Int32 m_nWildcardLength;
67 };
68 
69 template< typename T >
lcl_ValarrayToSequence(const::std::valarray<T> & rValarray)70     Sequence< T > lcl_ValarrayToSequence( const ::std::valarray< T > & rValarray )
71 {
72     // is there a more elegant way of conversion?
73     Sequence< T > aResult( rValarray.size());
74     for( size_t i = 0; i < rValarray.size(); ++i )
75         aResult[i] = rValarray[i];
76     return aResult;
77 }
78 
79 } // anonymous namespace
80 // ----------------------------------------
81 
InternalData()82 InternalData::InternalData()
83     : m_nColumnCount( 0 )
84     , m_nRowCount( 0 )
85     , m_aRowLabels( 0 )
86     , m_aColumnLabels( 0 )
87 {}
88 
createDefaultData()89 void InternalData::createDefaultData()
90 {
91     const sal_Int32 nRowCount = 4;
92     const sal_Int32 nColumnCount = 3;
93 
94     m_nRowCount = nRowCount;
95     m_nColumnCount = nColumnCount;
96     const sal_Int32 nSize = nColumnCount * nRowCount;
97     // @todo: localize this!
98     const OUString aRowName( ::chart::SchResId::getResString( STR_ROW_LABEL ));
99     const OUString aColName( ::chart::SchResId::getResString( STR_COLUMN_LABEL ));
100 
101     const double fDefaultData[ nSize ] =
102         { 9.10, 3.20, 4.54,
103           2.40, 8.80, 9.65,
104           3.10, 1.50, 3.70,
105           4.30, 9.02, 6.20 };
106 
107     m_aData.resize( nSize );
108     for( sal_Int32 i=0; i<nSize; ++i )
109         m_aData[i] = fDefaultData[i];
110 
111     m_aRowLabels.clear();
112     m_aRowLabels.reserve( m_nRowCount );
113     generate_n( back_inserter( m_aRowLabels ), m_nRowCount,
114         lcl_NumberedStringGenerator( aRowName, C2U("%ROWNUMBER") ));
115 
116     m_aColumnLabels.clear();
117     m_aColumnLabels.reserve( m_nColumnCount );
118     generate_n( back_inserter( m_aColumnLabels ), m_nColumnCount,
119         lcl_NumberedStringGenerator( aColName, C2U("%COLUMNNUMBER") ));
120 }
121 
setData(const Sequence<Sequence<double>> & rDataInRows)122 void InternalData::setData( const Sequence< Sequence< double > >& rDataInRows )
123 {
124     m_nRowCount = rDataInRows.getLength();
125     m_nColumnCount = (m_nRowCount ? rDataInRows[0].getLength() : 0);
126 
127     if( m_aRowLabels.size() != static_cast< sal_uInt32 >( m_nRowCount ))
128         m_aRowLabels.resize( m_nRowCount );
129     if( m_aColumnLabels.size() != static_cast< sal_uInt32 >( m_nColumnCount ))
130         m_aColumnLabels.resize( m_nColumnCount );
131 
132     m_aData.resize( m_nRowCount * m_nColumnCount );
133     double fNan;
134     ::rtl::math::setNan( & fNan );
135     // set all values to Nan
136     m_aData = fNan;
137 
138     for( sal_Int32 nRow=0; nRow<m_nRowCount; ++nRow )
139     {
140         int nDataIdx = nRow*m_nColumnCount;
141         const sal_Int32 nMax = ::std::min( rDataInRows[nRow].getLength(), m_nColumnCount );
142         for( sal_Int32 nCol=0; nCol < nMax; ++nCol )
143         {
144             m_aData[nDataIdx] = rDataInRows[nRow][nCol];
145             nDataIdx += 1;
146         }
147     }
148 }
149 
getData() const150 Sequence< Sequence< double > > InternalData::getData() const
151 {
152     Sequence< Sequence< double > > aResult( m_nRowCount );
153 
154     for( sal_Int32 i=0; i<m_nRowCount; ++i )
155         aResult[i] = lcl_ValarrayToSequence< tDataType::value_type >(
156             m_aData[ ::std::slice( i*m_nColumnCount, m_nColumnCount, 1 ) ] );
157 
158     return aResult;
159 }
160 
getColumnValues(sal_Int32 nColumnIndex) const161 Sequence< double > InternalData::getColumnValues( sal_Int32 nColumnIndex ) const
162 {
163     if( nColumnIndex >= 0 && nColumnIndex < m_nColumnCount )
164         return lcl_ValarrayToSequence< tDataType::value_type >(
165             m_aData[ ::std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ] );
166     return Sequence< double >();
167 }
getRowValues(sal_Int32 nRowIndex) const168 Sequence< double > InternalData::getRowValues( sal_Int32 nRowIndex ) const
169 {
170     if( nRowIndex >= 0 && nRowIndex < m_nRowCount )
171         return lcl_ValarrayToSequence< tDataType::value_type >(
172             m_aData[ ::std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ] );
173     return Sequence< double >();
174 }
175 
setColumnValues(sal_Int32 nColumnIndex,const vector<double> & rNewData)176 void InternalData::setColumnValues( sal_Int32 nColumnIndex, const vector< double > & rNewData )
177 {
178     if( nColumnIndex < 0 )
179         return;
180     enlargeData( nColumnIndex + 1, rNewData.size() );
181 
182     tDataType aSlice = m_aData[ ::std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ];
183     for( vector< double >::size_type i = 0; i < rNewData.size(); ++i )
184         aSlice[i] = rNewData[i];
185     m_aData[ ::std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ] = aSlice;
186 }
187 
setRowValues(sal_Int32 nRowIndex,const vector<double> & rNewData)188 void InternalData::setRowValues( sal_Int32 nRowIndex, const vector< double > & rNewData )
189 {
190     if( nRowIndex < 0 )
191         return;
192     enlargeData( rNewData.size(), nRowIndex+1 );
193 
194     tDataType aSlice = m_aData[ ::std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ];
195     for( vector< double >::size_type i = 0; i < rNewData.size(); ++i )
196         aSlice[i] = rNewData[i];
197     m_aData[ ::std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ]= aSlice;
198 }
199 
setComplexColumnLabel(sal_Int32 nColumnIndex,const vector<uno::Any> & rComplexLabel)200 void InternalData::setComplexColumnLabel( sal_Int32 nColumnIndex, const vector< uno::Any >& rComplexLabel )
201 {
202     if( nColumnIndex < 0 )
203         return;
204     if( nColumnIndex >= static_cast< sal_Int32 >( m_aColumnLabels.size() ) )
205     {
206         m_aColumnLabels.resize(nColumnIndex+1);
207         enlargeData( nColumnIndex+1, 0 );
208     }
209     m_aColumnLabels[nColumnIndex]=rComplexLabel;
210 }
211 
setComplexRowLabel(sal_Int32 nRowIndex,const vector<uno::Any> & rComplexLabel)212 void InternalData::setComplexRowLabel( sal_Int32 nRowIndex, const vector< uno::Any >& rComplexLabel )
213 {
214     if( nRowIndex < 0 )
215         return;
216     if( nRowIndex >= static_cast< sal_Int32 >( m_aRowLabels.size() ) )
217     {
218         m_aRowLabels.resize(nRowIndex+1);
219         enlargeData( 0, nRowIndex+1 );
220     }
221     m_aRowLabels[nRowIndex] = rComplexLabel;
222 }
223 
getComplexColumnLabel(sal_Int32 nColumnIndex) const224 vector< uno::Any > InternalData::getComplexColumnLabel( sal_Int32 nColumnIndex ) const
225 {
226     if( nColumnIndex < static_cast< sal_Int32 >( m_aColumnLabels.size() ) )
227         return m_aColumnLabels[nColumnIndex];
228     else
229         return vector< uno::Any >();
230 }
getComplexRowLabel(sal_Int32 nRowIndex) const231 vector< uno::Any > InternalData::getComplexRowLabel( sal_Int32 nRowIndex ) const
232 {
233     if( nRowIndex < static_cast< sal_Int32 >( m_aRowLabels.size() ) )
234         return m_aRowLabels[nRowIndex];
235     else
236         return vector< uno::Any >();
237 }
238 
swapRowWithNext(sal_Int32 nRowIndex)239 void InternalData::swapRowWithNext( sal_Int32 nRowIndex )
240 {
241     if( nRowIndex < m_nRowCount - 1 )
242     {
243         const sal_Int32 nMax = m_nColumnCount;
244         for( sal_Int32 nColIdx=0; nColIdx<nMax; ++nColIdx )
245         {
246             size_t nIndex1 = nColIdx + nRowIndex*m_nColumnCount;
247             size_t nIndex2 = nIndex1 + m_nColumnCount;
248             double fTemp = m_aData[nIndex1];
249             m_aData[nIndex1] = m_aData[nIndex2];
250             m_aData[nIndex2] = fTemp;
251         }
252 
253         vector< uno::Any > aTemp( m_aRowLabels[nRowIndex] );
254         m_aRowLabels[nRowIndex] = m_aRowLabels[nRowIndex + 1];
255         m_aRowLabels[nRowIndex + 1] = aTemp;
256     }
257 }
258 
swapColumnWithNext(sal_Int32 nColumnIndex)259 void InternalData::swapColumnWithNext( sal_Int32 nColumnIndex )
260 {
261     if( nColumnIndex < m_nColumnCount - 1 )
262     {
263         const sal_Int32 nMax = m_nRowCount;
264         for( sal_Int32 nRowIdx=0; nRowIdx<nMax; ++nRowIdx )
265         {
266             size_t nIndex1 = nColumnIndex + nRowIdx*m_nColumnCount;
267             size_t nIndex2 = nIndex1 + 1;
268             double fTemp = m_aData[nIndex1];
269             m_aData[nIndex1] = m_aData[nIndex2];
270             m_aData[nIndex2] = fTemp;
271         }
272 
273         vector< uno::Any > aTemp( m_aColumnLabels[nColumnIndex] );
274         m_aColumnLabels[nColumnIndex] = m_aColumnLabels[nColumnIndex + 1];
275         m_aColumnLabels[nColumnIndex + 1] = aTemp;
276     }
277 }
278 
enlargeData(sal_Int32 nColumnCount,sal_Int32 nRowCount)279 bool InternalData::enlargeData( sal_Int32 nColumnCount, sal_Int32 nRowCount )
280 {
281     sal_Int32 nNewColumnCount( ::std::max<sal_Int32>( m_nColumnCount, nColumnCount ) );
282     sal_Int32 nNewRowCount( ::std::max<sal_Int32>( m_nRowCount, nRowCount ) );
283     sal_Int32 nNewSize( nNewColumnCount*nNewRowCount );
284 
285     bool bGrow = (nNewSize > m_nColumnCount*m_nRowCount);
286 
287     if( bGrow )
288     {
289         double fNan;
290         ::rtl::math::setNan( &fNan );
291         tDataType aNewData( fNan, nNewSize );
292         // copy old data
293         for( int nCol=0; nCol<m_nColumnCount; ++nCol )
294             static_cast< tDataType >(
295                 aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] ) =
296                 m_aData[ ::std::slice( nCol, m_nRowCount, m_nColumnCount ) ];
297 
298         m_aData.resize( nNewSize );
299         m_aData = aNewData;
300     }
301     m_nColumnCount = nNewColumnCount;
302     m_nRowCount = nNewRowCount;
303     return bGrow;
304 }
305 
insertColumn(sal_Int32 nAfterIndex)306 void InternalData::insertColumn( sal_Int32 nAfterIndex )
307 {
308     // note: -1 is allowed, as we insert after the given index
309     OSL_ASSERT( nAfterIndex < m_nColumnCount && nAfterIndex >= -1 );
310     if( nAfterIndex >= m_nColumnCount || nAfterIndex < -1 )
311         return;
312     sal_Int32 nNewColumnCount = m_nColumnCount + 1;
313     sal_Int32 nNewSize( nNewColumnCount * m_nRowCount );
314 
315     double fNan;
316     ::rtl::math::setNan( &fNan );
317     tDataType aNewData( fNan, nNewSize );
318 
319     // copy old data
320     int nCol=0;
321     for( ; nCol<=nAfterIndex; ++nCol )
322         aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] =
323             static_cast< tDataType >(
324                 m_aData[ ::std::slice( nCol, m_nRowCount, m_nColumnCount ) ] );
325     for( ++nCol; nCol<nNewColumnCount; ++nCol )
326         aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] =
327             static_cast< tDataType >(
328                 m_aData[ ::std::slice( nCol - 1, m_nRowCount, m_nColumnCount ) ] );
329 
330     m_nColumnCount = nNewColumnCount;
331     m_aData.resize( nNewSize );
332     m_aData = aNewData;
333 
334     // labels
335     if( nAfterIndex < static_cast< sal_Int32 >( m_aColumnLabels.size()))
336         m_aColumnLabels.insert( m_aColumnLabels.begin() + (nAfterIndex + 1), vector< uno::Any >(1) );
337 
338 #if OSL_DEBUG_LEVEL > 2
339     traceData();
340 #endif
341 }
342 
appendColumn()343 sal_Int32 InternalData::appendColumn()
344 {
345     insertColumn( getColumnCount() - 1 );
346     return getColumnCount() - 1;
347 }
348 
appendRow()349 sal_Int32 InternalData::appendRow()
350 {
351     insertRow( getRowCount() - 1 );
352     return getRowCount() - 1;
353 }
354 
insertRow(sal_Int32 nAfterIndex)355 void InternalData::insertRow( sal_Int32 nAfterIndex )
356 {
357     // note: -1 is allowed, as we insert after the given index
358     OSL_ASSERT( nAfterIndex < m_nRowCount && nAfterIndex >= -1 );
359     if( nAfterIndex >= m_nRowCount || nAfterIndex < -1 )
360         return;
361     sal_Int32 nNewRowCount = m_nRowCount + 1;
362     sal_Int32 nNewSize( m_nColumnCount * nNewRowCount );
363 
364     double fNan;
365     ::rtl::math::setNan( &fNan );
366     tDataType aNewData( fNan, nNewSize );
367 
368     // copy old data
369     sal_Int32 nIndex = nAfterIndex + 1;
370     aNewData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] =
371         static_cast< tDataType >(
372             m_aData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] );
373 
374     if( nIndex < m_nRowCount )
375     {
376         sal_Int32 nRemainingCount = m_nColumnCount * (m_nRowCount - nIndex);
377         aNewData[ ::std::slice( (nIndex + 1) * m_nColumnCount, nRemainingCount, 1 ) ] =
378             static_cast< tDataType >(
379                 m_aData[ ::std::slice( nIndex * m_nColumnCount, nRemainingCount, 1 ) ] );
380     }
381 
382     m_nRowCount = nNewRowCount;
383     m_aData.resize( nNewSize );
384     m_aData = aNewData;
385 
386     // labels
387     if( nAfterIndex < static_cast< sal_Int32 >( m_aRowLabels.size()))
388         m_aRowLabels.insert( m_aRowLabels.begin() + nIndex, vector< uno::Any > (1));
389 
390 #if OSL_DEBUG_LEVEL > 2
391     traceData();
392 #endif
393 }
394 
deleteColumn(sal_Int32 nAtIndex)395 void InternalData::deleteColumn( sal_Int32 nAtIndex )
396 {
397     OSL_ASSERT( nAtIndex < m_nColumnCount && nAtIndex >= 0 );
398     if( nAtIndex >= m_nColumnCount || m_nColumnCount < 1 || nAtIndex < 0 )
399         return;
400     sal_Int32 nNewColumnCount = m_nColumnCount - 1;
401     sal_Int32 nNewSize( nNewColumnCount * m_nRowCount );
402 
403     double fNan;
404     ::rtl::math::setNan( &fNan );
405     tDataType aNewData( fNan, nNewSize );
406 
407     // copy old data
408     int nCol=0;
409     for( ; nCol<nAtIndex; ++nCol )
410         aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] =
411             static_cast< tDataType >(
412                 m_aData[ ::std::slice( nCol, m_nRowCount, m_nColumnCount ) ] );
413     for( ; nCol<nNewColumnCount; ++nCol )
414         aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] =
415             static_cast< tDataType >(
416                 m_aData[ ::std::slice( nCol + 1, m_nRowCount, m_nColumnCount ) ] );
417 
418     m_nColumnCount = nNewColumnCount;
419     m_aData.resize( nNewSize );
420     m_aData = aNewData;
421 
422     // labels
423     if( nAtIndex < static_cast< sal_Int32 >( m_aColumnLabels.size()))
424         m_aColumnLabels.erase( m_aColumnLabels.begin() + nAtIndex );
425 
426 #if OSL_DEBUG_LEVEL > 2
427     traceData();
428 #endif
429 }
430 
deleteRow(sal_Int32 nAtIndex)431 void InternalData::deleteRow( sal_Int32 nAtIndex )
432 {
433     OSL_ASSERT( nAtIndex < m_nRowCount && nAtIndex >= 0 );
434     if( nAtIndex >= m_nRowCount || m_nRowCount < 1 || nAtIndex < 0 )
435         return;
436     sal_Int32 nNewRowCount = m_nRowCount - 1;
437     sal_Int32 nNewSize( m_nColumnCount * nNewRowCount );
438 
439     double fNan;
440     ::rtl::math::setNan( &fNan );
441     tDataType aNewData( fNan, nNewSize );
442 
443     // copy old data
444     sal_Int32 nIndex = nAtIndex;
445     if( nIndex )
446         aNewData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] =
447             static_cast< tDataType >(
448                 m_aData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] );
449 
450     if( nIndex < nNewRowCount )
451     {
452         sal_Int32 nRemainingCount = m_nColumnCount * (nNewRowCount - nIndex);
453         aNewData[ ::std::slice( nIndex * m_nColumnCount, nRemainingCount, 1 ) ] =
454             static_cast< tDataType >(
455                 m_aData[ ::std::slice( (nIndex + 1) * m_nColumnCount, nRemainingCount, 1 ) ] );
456     }
457 
458     m_nRowCount = nNewRowCount;
459     m_aData.resize( nNewSize );
460     m_aData = aNewData;
461 
462     // labels
463     if( nAtIndex < static_cast< sal_Int32 >( m_aRowLabels.size()))
464         m_aRowLabels.erase( m_aRowLabels.begin() + nAtIndex );
465 
466 #if OSL_DEBUG_LEVEL > 2
467     traceData();
468 #endif
469 }
470 
getRowCount() const471 sal_Int32 InternalData::getRowCount() const
472 {
473     return m_nRowCount;
474 }
475 
getColumnCount() const476 sal_Int32 InternalData::getColumnCount() const
477 {
478     return m_nColumnCount;
479 }
480 
setComplexRowLabels(const vector<vector<uno::Any>> & rNewRowLabels)481 void InternalData::setComplexRowLabels( const vector< vector< uno::Any > >& rNewRowLabels )
482 {
483     m_aRowLabels = rNewRowLabels;
484     sal_Int32 nNewRowCount = static_cast< sal_Int32 >( m_aRowLabels.size() );
485     if( nNewRowCount < m_nRowCount )
486         m_aRowLabels.resize( m_nRowCount );
487     else
488         enlargeData( 0, nNewRowCount );
489 }
490 
getComplexRowLabels() const491 vector< vector< uno::Any > > InternalData::getComplexRowLabels() const
492 {
493     return m_aRowLabels;
494 }
495 
setComplexColumnLabels(const vector<vector<uno::Any>> & rNewColumnLabels)496 void InternalData::setComplexColumnLabels( const vector< vector< uno::Any > >& rNewColumnLabels )
497 {
498     m_aColumnLabels = rNewColumnLabels;
499     sal_Int32 nNewColumnCount = static_cast< sal_Int32 >( m_aColumnLabels.size() );
500     if( nNewColumnCount < m_nColumnCount )
501         m_aColumnLabels.resize( m_nColumnCount );
502     else
503         enlargeData( nNewColumnCount, 0 );
504 }
505 
getComplexColumnLabels() const506 vector< vector< uno::Any > > InternalData::getComplexColumnLabels() const
507 {
508     return m_aColumnLabels;
509 }
510 
511 #if OSL_DEBUG_LEVEL > 2
traceData() const512 void InternalData::traceData() const
513 {
514     OSL_TRACE( "InternalData: Data in rows\n" );
515 
516     for( sal_Int32 i=0; i<m_nRowCount; ++i )
517     {
518         tDataType aSlice( m_aData[ ::std::slice( i*m_nColumnCount, m_nColumnCount, 1 ) ] );
519         for( sal_Int32 j=0; j<m_nColumnCount; ++j )
520             OSL_TRACE( "%lf ", aSlice[j] );
521         OSL_TRACE( "\n" );
522     }
523     OSL_TRACE( "\n" );
524 }
525 #endif
526 
527 } //  namespace chart
528