1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
23 #include "Strings.hrc"
25 #include <rtl/math.hxx>
29 using ::com::sun::star::uno::Sequence
;
31 using namespace ::com::sun::star
;
32 using namespace ::std
;
37 // ----------------------------------------
40 struct lcl_NumberedStringGenerator
42 lcl_NumberedStringGenerator( const OUString
& rStub
, const OUString
& rWildcard
) :
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
)) );
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
];
72 } // anonymous namespace
73 // ----------------------------------------
75 InternalData::InternalData()
79 , m_aColumnLabels( 0 )
82 static const double fDefaultData
[] = {
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
] )
130 void InternalData::clearDefaultData()
132 if( isDefaultData() )
134 m_nRowCount
= m_nColumnCount
= 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
);
153 ::rtl::math::setNan( & fNan
);
154 // set all values to Nan
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
];
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 ) ] );
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 )
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
)
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 )
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
)
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
];
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
];
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
);
309 ::rtl::math::setNan( &fNan
);
310 tDataType
aNewData( fNan
, nNewSize
);
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
);
320 m_nColumnCount
= nNewColumnCount
;
321 m_nRowCount
= nNewRowCount
;
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 )
331 sal_Int32 nNewColumnCount
= m_nColumnCount
+ 1;
332 sal_Int32
nNewSize( nNewColumnCount
* m_nRowCount
);
335 ::rtl::math::setNan( &fNan
);
336 tDataType
aNewData( fNan
, nNewSize
);
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
);
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
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 )
380 sal_Int32 nNewRowCount
= m_nRowCount
+ 1;
381 sal_Int32
nNewSize( m_nColumnCount
* nNewRowCount
);
384 ::rtl::math::setNan( &fNan
);
385 tDataType
aNewData( fNan
, nNewSize
);
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
);
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
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 )
419 sal_Int32 nNewColumnCount
= m_nColumnCount
- 1;
420 sal_Int32
nNewSize( nNewColumnCount
* m_nRowCount
);
423 ::rtl::math::setNan( &fNan
);
424 tDataType
aNewData( fNan
, nNewSize
);
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
);
442 if( nAtIndex
< static_cast< sal_Int32
>( m_aColumnLabels
.size()))
443 m_aColumnLabels
.erase( m_aColumnLabels
.begin() + nAtIndex
);
445 #if OSL_DEBUG_LEVEL > 1
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 )
455 sal_Int32 nNewRowCount
= m_nRowCount
- 1;
456 sal_Int32
nNewSize( m_nColumnCount
* nNewRowCount
);
459 ::rtl::math::setNan( &fNan
);
460 tDataType
aNewData( fNan
, nNewSize
);
463 sal_Int32 nIndex
= nAtIndex
;
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
);
482 if( nAtIndex
< static_cast< sal_Int32
>( m_aRowLabels
.size()))
483 m_aRowLabels
.erase( m_aRowLabels
.begin() + nAtIndex
);
485 #if OSL_DEBUG_LEVEL > 1
490 sal_Int32
InternalData::getRowCount() const
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
);
507 enlargeData( 0, nNewRowCount
);
510 vector
< vector
< uno::Any
> > InternalData::getComplexRowLabels() const
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
);
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
] );
548 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */