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"
33 #include "Strings.hrc"
36 #include <rtl/math.hxx>
38 using ::com::sun::star::uno::Sequence
;
39 using ::rtl::OUString
;
41 using namespace ::std
;
46 // ----------------------------------------
49 struct lcl_NumberedStringGenerator
51 lcl_NumberedStringGenerator( const OUString
& rStub
, const OUString
& rWildcard
) :
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
));
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
];
81 } // anonymous namespace
82 // ----------------------------------------
84 InternalData::InternalData()
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
] =
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
);
136 ::rtl::math::setNan( & fNan
);
137 // set all values to Nan
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
];
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 ) ] );
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 )
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
)
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 )
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
)
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
];
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
];
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
);
293 ::rtl::math::setNan( &fNan
);
294 tDataType
aNewData( fNan
, nNewSize
);
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
);
304 m_nColumnCount
= nNewColumnCount
;
305 m_nRowCount
= nNewRowCount
;
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 )
315 sal_Int32 nNewColumnCount
= m_nColumnCount
+ 1;
316 sal_Int32
nNewSize( nNewColumnCount
* m_nRowCount
);
319 ::rtl::math::setNan( &fNan
);
320 tDataType
aNewData( fNan
, nNewSize
);
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
);
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
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 )
364 sal_Int32 nNewRowCount
= m_nRowCount
+ 1;
365 sal_Int32
nNewSize( m_nColumnCount
* nNewRowCount
);
368 ::rtl::math::setNan( &fNan
);
369 tDataType
aNewData( fNan
, nNewSize
);
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
);
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
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 )
403 sal_Int32 nNewColumnCount
= m_nColumnCount
- 1;
404 sal_Int32
nNewSize( nNewColumnCount
* m_nRowCount
);
407 ::rtl::math::setNan( &fNan
);
408 tDataType
aNewData( fNan
, nNewSize
);
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
);
426 if( nAtIndex
< static_cast< sal_Int32
>( m_aColumnLabels
.size()))
427 m_aColumnLabels
.erase( m_aColumnLabels
.begin() + nAtIndex
);
429 #if OSL_DEBUG_LEVEL > 2
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 )
439 sal_Int32 nNewRowCount
= m_nRowCount
- 1;
440 sal_Int32
nNewSize( m_nColumnCount
* nNewRowCount
);
443 ::rtl::math::setNan( &fNan
);
444 tDataType
aNewData( fNan
, nNewSize
);
447 sal_Int32 nIndex
= nAtIndex
;
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
);
466 if( nAtIndex
< static_cast< sal_Int32
>( m_aRowLabels
.size()))
467 m_aRowLabels
.erase( m_aRowLabels
.begin() + nAtIndex
);
469 #if OSL_DEBUG_LEVEL > 2
474 sal_Int32
InternalData::getRowCount() const
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
);
491 enlargeData( 0, nNewRowCount
);
494 vector
< vector
< OUString
> > InternalData::getComplexRowLabels() const
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
);
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
] );