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 .
20 #include <InternalData.hxx>
22 #include <strings.hrc>
24 #include <comphelper/sequence.hxx>
25 #include <o3tl/safeint.hxx>
26 #include <osl/diagnose.h>
28 #ifdef DEBUG_CHART2_TOOLS
29 #define DEBUG_INTERNAL_DATA 1
32 #ifdef DEBUG_INTERNAL_DATA
33 #include <svl/gridprinter.hxx>
40 using ::com::sun::star::uno::Sequence
;
42 using namespace ::com::sun::star
;
49 struct lcl_NumberedStringGenerator
51 lcl_NumberedStringGenerator( const OUString
& rStub
, std::u16string_view rWildcard
) :
54 m_nStubStartIndex( rStub
.indexOf( rWildcard
)),
55 m_nWildcardLength( rWildcard
.size())
58 std::vector
< uno::Any
> operator()()
60 return { uno::Any(m_aStub
.replaceAt( m_nStubStartIndex
, m_nWildcardLength
, OUString::number( ++m_nCounter
))) };
65 const sal_Int32 m_nStubStartIndex
;
66 const sal_Int32 m_nWildcardLength
;
69 template< typename T
>
70 Sequence
< T
> lcl_ValarrayToSequence( const std::valarray
< T
> & rValarray
)
72 #if defined __GLIBCXX__ && (!defined _GLIBCXX_RELEASE || _GLIBCXX_RELEASE < 12)
73 // workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103022
78 return comphelper::containerToSequence(rValarray
);
81 } // anonymous namespace
83 InternalData::InternalData()
87 , m_aColumnLabels( 0 )
90 const double fDefaultData
[] = {
97 void InternalData::createDefaultData()
99 const sal_Int32 nRowCount
= 4;
100 const sal_Int32 nColumnCount
= 3;
102 m_nRowCount
= nRowCount
;
103 m_nColumnCount
= nColumnCount
;
104 const sal_Int32 nSize
= nColumnCount
* nRowCount
;
105 // @todo: localize this!
106 const OUString
aRowName(SchResId(STR_ROW_LABEL
));
107 const OUString
aColName(SchResId(STR_COLUMN_LABEL
));
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
, u
"%ROWNUMBER" ));
118 m_aColumnLabels
.clear();
119 m_aColumnLabels
.reserve( m_nColumnCount
);
120 generate_n( back_inserter( m_aColumnLabels
), m_nColumnCount
,
121 lcl_NumberedStringGenerator( aColName
, u
"%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
);
135 // set all values to Nan
136 m_aData
= std::numeric_limits
<double>::quiet_NaN();
138 for( sal_Int32 nRow
=0; nRow
<m_nRowCount
; ++nRow
)
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
)
144 m_aData
[nDataIdx
] = rDataInRows
[nRow
][nCol
];
150 Sequence
< Sequence
< double > > InternalData::getData() const
152 Sequence
< Sequence
< double > > aResult( m_nRowCount
);
153 auto aResultRange
= asNonConstRange(aResult
);
155 for( sal_Int32 i
=0; i
<m_nRowCount
; ++i
)
156 aResultRange
[i
] = lcl_ValarrayToSequence
< tDataType::value_type
>(
157 m_aData
[ std::slice( i
*m_nColumnCount
, m_nColumnCount
, 1 ) ] );
162 Sequence
< double > InternalData::getColumnValues( sal_Int32 nColumnIndex
) const
164 if( nColumnIndex
>= 0 && nColumnIndex
< m_nColumnCount
)
165 return lcl_ValarrayToSequence
< tDataType::value_type
>(
166 m_aData
[ std::slice( nColumnIndex
, m_nRowCount
, m_nColumnCount
) ] );
167 return Sequence
< double >();
169 Sequence
< double > InternalData::getRowValues( sal_Int32 nRowIndex
) const
171 if( nRowIndex
>= 0 && nRowIndex
< m_nRowCount
)
172 return lcl_ValarrayToSequence
< tDataType::value_type
>(
173 m_aData
[ std::slice( nRowIndex
*m_nColumnCount
, m_nColumnCount
, 1 ) ] );
174 return Sequence
< double >();
177 void InternalData::setColumnValues( sal_Int32 nColumnIndex
, const std::vector
< double > & rNewData
)
179 if( nColumnIndex
< 0 )
181 enlargeData( nColumnIndex
+ 1, rNewData
.size() );
183 tDataType aSlice
= m_aData
[ std::slice( nColumnIndex
, m_nRowCount
, m_nColumnCount
) ];
184 for( std::vector
< double >::size_type i
= 0; i
< rNewData
.size(); ++i
)
185 aSlice
[i
] = rNewData
[i
];
186 m_aData
[ std::slice( nColumnIndex
, m_nRowCount
, m_nColumnCount
) ] = aSlice
;
189 void InternalData::setRowValues( sal_Int32 nRowIndex
, const std::vector
< double > & rNewData
)
193 enlargeData( rNewData
.size(), nRowIndex
+1 );
195 tDataType aSlice
= m_aData
[ std::slice( nRowIndex
*m_nColumnCount
, m_nColumnCount
, 1 ) ];
196 for( std::vector
< double >::size_type i
= 0; i
< rNewData
.size(); ++i
)
197 aSlice
[i
] = rNewData
[i
];
198 m_aData
[ std::slice( nRowIndex
*m_nColumnCount
, m_nColumnCount
, 1 ) ]= aSlice
;
201 void InternalData::setComplexColumnLabel( sal_Int32 nColumnIndex
, std::vector
< uno::Any
>&& rComplexLabel
)
203 if( nColumnIndex
< 0 )
205 if( o3tl::make_unsigned(nColumnIndex
) >= m_aColumnLabels
.size() )
207 m_aColumnLabels
.resize(nColumnIndex
+1);
208 enlargeData( nColumnIndex
+1, 0 );
210 m_aColumnLabels
[nColumnIndex
] = std::move(rComplexLabel
);
215 void InternalData::setComplexRowLabel( sal_Int32 nRowIndex
, std::vector
< uno::Any
>&& rComplexLabel
)
219 if( o3tl::make_unsigned(nRowIndex
) >= m_aRowLabels
.size() )
221 m_aRowLabels
.resize(nRowIndex
+1);
222 enlargeData( 0, nRowIndex
+1 );
224 sal_Int32 nSize
= static_cast<sal_Int32
>( m_aRowLabels
[nRowIndex
].size() );
225 if( nSize
>= 1 && !rComplexLabel
.empty() )
227 m_aRowLabels
[nRowIndex
].resize(nSize
+1);
228 m_aRowLabels
[nRowIndex
][nSize
] = rComplexLabel
[0];
232 m_aRowLabels
[nRowIndex
] = std::move(rComplexLabel
);
236 std::vector
< uno::Any
> InternalData::getComplexColumnLabel( sal_Int32 nColumnIndex
) const
238 if( nColumnIndex
< static_cast< sal_Int32
>( m_aColumnLabels
.size() ) )
239 return m_aColumnLabels
[nColumnIndex
];
241 return std::vector
< uno::Any
>();
243 std::vector
< uno::Any
> InternalData::getComplexRowLabel( sal_Int32 nRowIndex
) const
245 if( nRowIndex
< static_cast< sal_Int32
>( m_aRowLabels
.size() ) )
246 return m_aRowLabels
[nRowIndex
];
248 return std::vector
< uno::Any
>();
251 void InternalData::swapRowWithNext( sal_Int32 nRowIndex
)
253 if( nRowIndex
>= m_nRowCount
- 1 )
256 const sal_Int32 nMax
= m_nColumnCount
;
257 for( sal_Int32 nColIdx
=0; nColIdx
<nMax
; ++nColIdx
)
259 size_t nIndex1
= nColIdx
+ nRowIndex
*m_nColumnCount
;
260 size_t nIndex2
= nIndex1
+ m_nColumnCount
;
261 std::swap(m_aData
[nIndex1
], m_aData
[nIndex2
]);
264 std::swap(m_aRowLabels
[nRowIndex
], m_aRowLabels
[nRowIndex
+ 1]);
267 void InternalData::swapColumnWithNext( sal_Int32 nColumnIndex
)
269 if( nColumnIndex
>= m_nColumnCount
- 1 )
272 const sal_Int32 nMax
= m_nRowCount
;
273 for( sal_Int32 nRowIdx
=0; nRowIdx
<nMax
; ++nRowIdx
)
275 size_t nIndex1
= nColumnIndex
+ nRowIdx
*m_nColumnCount
;
276 size_t nIndex2
= nIndex1
+ 1;
277 std::swap(m_aData
[nIndex1
], m_aData
[nIndex2
]);
280 std::swap(m_aColumnLabels
[nColumnIndex
], m_aColumnLabels
[nColumnIndex
+ 1]);
283 bool InternalData::enlargeData( sal_Int32 nColumnCount
, sal_Int32 nRowCount
)
285 sal_Int32
nNewColumnCount( std::max
<sal_Int32
>( m_nColumnCount
, nColumnCount
) );
286 sal_Int32
nNewRowCount( std::max
<sal_Int32
>( m_nRowCount
, nRowCount
) );
287 sal_Int32
nNewSize( nNewColumnCount
*nNewRowCount
);
289 bool bGrow
= (nNewSize
> m_nColumnCount
*m_nRowCount
);
293 tDataType
aNewData( std::numeric_limits
<double>::quiet_NaN(), nNewSize
);
295 for( int nCol
=0; nCol
<m_nColumnCount
; ++nCol
)
296 static_cast< tDataType
>(
297 aNewData
[ std::slice( nCol
, m_nRowCount
, nNewColumnCount
) ] ) =
298 m_aData
[ std::slice( nCol
, m_nRowCount
, m_nColumnCount
) ];
300 m_aData
= std::move(aNewData
);
302 m_nColumnCount
= nNewColumnCount
;
303 m_nRowCount
= nNewRowCount
;
307 void InternalData::insertColumn( sal_Int32 nAfterIndex
)
309 // note: -1 is allowed, as we insert after the given index
310 OSL_ASSERT( nAfterIndex
< m_nColumnCount
&& nAfterIndex
>= -1 );
311 if( nAfterIndex
>= m_nColumnCount
|| nAfterIndex
< -1 )
313 sal_Int32 nNewColumnCount
= m_nColumnCount
+ 1;
314 sal_Int32
nNewSize( nNewColumnCount
* m_nRowCount
);
316 tDataType
aNewData( std::numeric_limits
<double>::quiet_NaN(), nNewSize
);
320 for( ; nCol
<=nAfterIndex
; ++nCol
)
321 aNewData
[ std::slice( nCol
, m_nRowCount
, nNewColumnCount
) ] =
322 static_cast< tDataType
>(
323 m_aData
[ std::slice( nCol
, m_nRowCount
, m_nColumnCount
) ] );
324 for( ++nCol
; nCol
<nNewColumnCount
; ++nCol
)
325 aNewData
[ std::slice( nCol
, m_nRowCount
, nNewColumnCount
) ] =
326 static_cast< tDataType
>(
327 m_aData
[ std::slice( nCol
- 1, m_nRowCount
, m_nColumnCount
) ] );
329 m_nColumnCount
= nNewColumnCount
;
330 m_aData
= std::move(aNewData
);
333 if( nAfterIndex
< static_cast< sal_Int32
>( m_aColumnLabels
.size()))
334 m_aColumnLabels
.insert( m_aColumnLabels
.begin() + (nAfterIndex
+ 1), std::vector
< uno::Any
>(1) );
339 sal_Int32
InternalData::appendColumn()
341 insertColumn( getColumnCount() - 1 );
342 return getColumnCount() - 1;
345 sal_Int32
InternalData::appendRow()
347 insertRow( getRowCount() - 1 );
348 return getRowCount() - 1;
351 sal_Int32
InternalData::getRowCount() const
356 sal_Int32
InternalData::getColumnCount() const
358 return m_nColumnCount
;
361 void InternalData::insertRow( sal_Int32 nAfterIndex
)
363 // note: -1 is allowed, as we insert after the given index
364 OSL_ASSERT( nAfterIndex
< m_nRowCount
&& nAfterIndex
>= -1 );
365 if( nAfterIndex
>= m_nRowCount
|| nAfterIndex
< -1 )
367 sal_Int32 nNewRowCount
= m_nRowCount
+ 1;
368 sal_Int32
nNewSize( m_nColumnCount
* nNewRowCount
);
370 tDataType
aNewData( std::numeric_limits
<double>::quiet_NaN(), nNewSize
);
373 sal_Int32 nIndex
= nAfterIndex
+ 1;
374 aNewData
[ std::slice( 0, nIndex
* m_nColumnCount
, 1 ) ] =
375 static_cast< tDataType
>(
376 m_aData
[ std::slice( 0, nIndex
* m_nColumnCount
, 1 ) ] );
378 if( nIndex
< m_nRowCount
)
380 sal_Int32 nRemainingCount
= m_nColumnCount
* (m_nRowCount
- nIndex
);
381 aNewData
[ std::slice( (nIndex
+ 1) * m_nColumnCount
, nRemainingCount
, 1 ) ] =
382 static_cast< tDataType
>(
383 m_aData
[ std::slice( nIndex
* m_nColumnCount
, nRemainingCount
, 1 ) ] );
386 m_nRowCount
= nNewRowCount
;
387 m_aData
= std::move(aNewData
);
390 if( nAfterIndex
< static_cast< sal_Int32
>( m_aRowLabels
.size()))
391 m_aRowLabels
.insert( m_aRowLabels
.begin() + nIndex
, std::vector
< uno::Any
> (1));
396 void InternalData::deleteColumn( sal_Int32 nAtIndex
)
398 OSL_ASSERT( nAtIndex
< m_nColumnCount
&& nAtIndex
>= 0 );
399 if( nAtIndex
>= m_nColumnCount
|| m_nColumnCount
< 1 || nAtIndex
< 0 )
401 sal_Int32 nNewColumnCount
= m_nColumnCount
- 1;
402 sal_Int32
nNewSize( nNewColumnCount
* m_nRowCount
);
404 tDataType
aNewData( std::numeric_limits
<double>::quiet_NaN(), nNewSize
);
408 for( ; nCol
<nAtIndex
; ++nCol
)
409 aNewData
[ std::slice( nCol
, m_nRowCount
, nNewColumnCount
) ] =
410 static_cast< tDataType
>(
411 m_aData
[ std::slice( nCol
, m_nRowCount
, m_nColumnCount
) ] );
412 for( ; nCol
<nNewColumnCount
; ++nCol
)
413 aNewData
[ std::slice( nCol
, m_nRowCount
, nNewColumnCount
) ] =
414 static_cast< tDataType
>(
415 m_aData
[ std::slice( nCol
+ 1, m_nRowCount
, m_nColumnCount
) ] );
417 m_nColumnCount
= nNewColumnCount
;
418 m_aData
= std::move(aNewData
);
421 if( nAtIndex
< static_cast< sal_Int32
>( m_aColumnLabels
.size()))
422 m_aColumnLabels
.erase( m_aColumnLabels
.begin() + nAtIndex
);
427 void InternalData::deleteRow( sal_Int32 nAtIndex
)
429 OSL_ASSERT( nAtIndex
< m_nRowCount
&& nAtIndex
>= 0 );
430 if( nAtIndex
>= m_nRowCount
|| m_nRowCount
< 1 || nAtIndex
< 0 )
432 sal_Int32 nNewRowCount
= m_nRowCount
- 1;
433 sal_Int32
nNewSize( m_nColumnCount
* nNewRowCount
);
435 tDataType
aNewData( std::numeric_limits
<double>::quiet_NaN(), nNewSize
);
438 sal_Int32 nIndex
= nAtIndex
;
440 aNewData
[ std::slice( 0, nIndex
* m_nColumnCount
, 1 ) ] =
441 static_cast< tDataType
>(
442 m_aData
[ std::slice( 0, nIndex
* m_nColumnCount
, 1 ) ] );
444 if( nIndex
< nNewRowCount
)
446 sal_Int32 nRemainingCount
= m_nColumnCount
* (nNewRowCount
- nIndex
);
447 aNewData
[ std::slice( nIndex
* m_nColumnCount
, nRemainingCount
, 1 ) ] =
448 static_cast< tDataType
>(
449 m_aData
[ std::slice( (nIndex
+ 1) * m_nColumnCount
, nRemainingCount
, 1 ) ] );
452 m_nRowCount
= nNewRowCount
;
453 m_aData
= std::move(aNewData
);
456 if( nAtIndex
< static_cast< sal_Int32
>( m_aRowLabels
.size()))
457 m_aRowLabels
.erase( m_aRowLabels
.begin() + nAtIndex
);
462 void InternalData::setComplexRowLabels( tVecVecAny
&& rNewRowLabels
)
464 m_aRowLabels
= std::move(rNewRowLabels
);
465 sal_Int32 nNewRowCount
= static_cast< sal_Int32
>( m_aRowLabels
.size() );
466 if( nNewRowCount
< m_nRowCount
)
467 m_aRowLabels
.resize( m_nRowCount
);
469 enlargeData( 0, nNewRowCount
);
472 const InternalData::tVecVecAny
& InternalData::getComplexRowLabels() const
477 void InternalData::setComplexColumnLabels( tVecVecAny
&& rNewColumnLabels
)
479 m_aColumnLabels
= std::move(rNewColumnLabels
);
480 sal_Int32 nNewColumnCount
= static_cast< sal_Int32
>( m_aColumnLabels
.size() );
481 if( nNewColumnCount
< m_nColumnCount
)
482 m_aColumnLabels
.resize( m_nColumnCount
);
484 enlargeData( nNewColumnCount
, 0 );
487 const InternalData::tVecVecAny
& InternalData::getComplexColumnLabels() const
489 return m_aColumnLabels
;
492 #ifdef DEBUG_INTERNAL_DATA
493 void InternalData::dump() const
496 if (!m_aColumnLabels
.empty())
498 svl::GridPrinter
aPrinter(m_aColumnLabels
[0].size(), m_aColumnLabels
.size(), true);
499 for (size_t nCol
= 0; nCol
< m_aColumnLabels
.size(); ++nCol
)
501 for (size_t nRow
= 0; nRow
< m_aColumnLabels
[nCol
].size(); ++nRow
)
504 if (m_aColumnLabels
[nCol
].at(nRow
) >>= aStr
)
505 aPrinter
.set(nRow
, nCol
, aStr
);
508 aPrinter
.print("Header");
511 if (!m_aRowLabels
.empty())
513 svl::GridPrinter
aPrinter(m_aRowLabels
.size(), m_aRowLabels
[0].size(), true);
514 for (size_t nRow
= 0; nRow
< m_aRowLabels
.size(); ++nRow
)
516 for (size_t nCol
= 0; nCol
< m_aRowLabels
[nRow
].size(); ++nCol
)
519 if (m_aRowLabels
[nRow
].at(nCol
) >>= aStr
)
520 aPrinter
.set(nRow
, nCol
, aStr
);
523 aPrinter
.print("Row labels");
526 svl::GridPrinter
aPrinter(m_nRowCount
, m_nColumnCount
, true);
528 for (sal_Int32 nRow
= 0; nRow
< m_nRowCount
; ++nRow
)
530 tDataType
aSlice( m_aData
[ std::slice( nRow
*m_nColumnCount
, m_nColumnCount
, 1 ) ] );
531 for (sal_Int32 nCol
= 0; nCol
< m_nColumnCount
; ++nCol
)
532 aPrinter
.set(nRow
, nCol
, OUString::number(aSlice
[nCol
]));
535 aPrinter
.print("Column data");
538 void InternalData::dump() const {}
543 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */