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::vector
< uno::Any
> aTemp( m_aColumnLabels
[nColumnIndex
] );
281 m_aColumnLabels
[nColumnIndex
] = m_aColumnLabels
[nColumnIndex
+ 1];
282 m_aColumnLabels
[nColumnIndex
+ 1] = aTemp
;
285 bool InternalData::enlargeData( sal_Int32 nColumnCount
, sal_Int32 nRowCount
)
287 sal_Int32
nNewColumnCount( std::max
<sal_Int32
>( m_nColumnCount
, nColumnCount
) );
288 sal_Int32
nNewRowCount( std::max
<sal_Int32
>( m_nRowCount
, nRowCount
) );
289 sal_Int32
nNewSize( nNewColumnCount
*nNewRowCount
);
291 bool bGrow
= (nNewSize
> m_nColumnCount
*m_nRowCount
);
295 tDataType
aNewData( std::numeric_limits
<double>::quiet_NaN(), nNewSize
);
297 for( int nCol
=0; nCol
<m_nColumnCount
; ++nCol
)
298 static_cast< tDataType
>(
299 aNewData
[ std::slice( nCol
, m_nRowCount
, nNewColumnCount
) ] ) =
300 m_aData
[ std::slice( nCol
, m_nRowCount
, m_nColumnCount
) ];
302 m_aData
.resize( nNewSize
);
305 m_nColumnCount
= nNewColumnCount
;
306 m_nRowCount
= nNewRowCount
;
310 void InternalData::insertColumn( sal_Int32 nAfterIndex
)
312 // note: -1 is allowed, as we insert after the given index
313 OSL_ASSERT( nAfterIndex
< m_nColumnCount
&& nAfterIndex
>= -1 );
314 if( nAfterIndex
>= m_nColumnCount
|| nAfterIndex
< -1 )
316 sal_Int32 nNewColumnCount
= m_nColumnCount
+ 1;
317 sal_Int32
nNewSize( nNewColumnCount
* m_nRowCount
);
319 tDataType
aNewData( std::numeric_limits
<double>::quiet_NaN(), nNewSize
);
323 for( ; nCol
<=nAfterIndex
; ++nCol
)
324 aNewData
[ std::slice( nCol
, m_nRowCount
, nNewColumnCount
) ] =
325 static_cast< tDataType
>(
326 m_aData
[ std::slice( nCol
, m_nRowCount
, m_nColumnCount
) ] );
327 for( ++nCol
; nCol
<nNewColumnCount
; ++nCol
)
328 aNewData
[ std::slice( nCol
, m_nRowCount
, nNewColumnCount
) ] =
329 static_cast< tDataType
>(
330 m_aData
[ std::slice( nCol
- 1, m_nRowCount
, m_nColumnCount
) ] );
332 m_nColumnCount
= nNewColumnCount
;
333 m_aData
.resize( nNewSize
);
337 if( nAfterIndex
< static_cast< sal_Int32
>( m_aColumnLabels
.size()))
338 m_aColumnLabels
.insert( m_aColumnLabels
.begin() + (nAfterIndex
+ 1), std::vector
< uno::Any
>(1) );
343 sal_Int32
InternalData::appendColumn()
345 insertColumn( getColumnCount() - 1 );
346 return getColumnCount() - 1;
349 sal_Int32
InternalData::appendRow()
351 insertRow( getRowCount() - 1 );
352 return getRowCount() - 1;
355 sal_Int32
InternalData::getRowCount() const
360 sal_Int32
InternalData::getColumnCount() const
362 return m_nColumnCount
;
365 void InternalData::insertRow( sal_Int32 nAfterIndex
)
367 // note: -1 is allowed, as we insert after the given index
368 OSL_ASSERT( nAfterIndex
< m_nRowCount
&& nAfterIndex
>= -1 );
369 if( nAfterIndex
>= m_nRowCount
|| nAfterIndex
< -1 )
371 sal_Int32 nNewRowCount
= m_nRowCount
+ 1;
372 sal_Int32
nNewSize( m_nColumnCount
* nNewRowCount
);
374 tDataType
aNewData( std::numeric_limits
<double>::quiet_NaN(), nNewSize
);
377 sal_Int32 nIndex
= nAfterIndex
+ 1;
378 aNewData
[ std::slice( 0, nIndex
* m_nColumnCount
, 1 ) ] =
379 static_cast< tDataType
>(
380 m_aData
[ std::slice( 0, nIndex
* m_nColumnCount
, 1 ) ] );
382 if( nIndex
< m_nRowCount
)
384 sal_Int32 nRemainingCount
= m_nColumnCount
* (m_nRowCount
- nIndex
);
385 aNewData
[ std::slice( (nIndex
+ 1) * m_nColumnCount
, nRemainingCount
, 1 ) ] =
386 static_cast< tDataType
>(
387 m_aData
[ std::slice( nIndex
* m_nColumnCount
, nRemainingCount
, 1 ) ] );
390 m_nRowCount
= nNewRowCount
;
391 m_aData
.resize( nNewSize
);
395 if( nAfterIndex
< static_cast< sal_Int32
>( m_aRowLabels
.size()))
396 m_aRowLabels
.insert( m_aRowLabels
.begin() + nIndex
, std::vector
< uno::Any
> (1));
401 void InternalData::deleteColumn( sal_Int32 nAtIndex
)
403 OSL_ASSERT( nAtIndex
< m_nColumnCount
&& nAtIndex
>= 0 );
404 if( nAtIndex
>= m_nColumnCount
|| m_nColumnCount
< 1 || nAtIndex
< 0 )
406 sal_Int32 nNewColumnCount
= m_nColumnCount
- 1;
407 sal_Int32
nNewSize( nNewColumnCount
* m_nRowCount
);
409 tDataType
aNewData( std::numeric_limits
<double>::quiet_NaN(), nNewSize
);
413 for( ; nCol
<nAtIndex
; ++nCol
)
414 aNewData
[ std::slice( nCol
, m_nRowCount
, nNewColumnCount
) ] =
415 static_cast< tDataType
>(
416 m_aData
[ std::slice( nCol
, m_nRowCount
, m_nColumnCount
) ] );
417 for( ; nCol
<nNewColumnCount
; ++nCol
)
418 aNewData
[ std::slice( nCol
, m_nRowCount
, nNewColumnCount
) ] =
419 static_cast< tDataType
>(
420 m_aData
[ std::slice( nCol
+ 1, m_nRowCount
, m_nColumnCount
) ] );
422 m_nColumnCount
= nNewColumnCount
;
423 m_aData
.resize( nNewSize
);
427 if( nAtIndex
< static_cast< sal_Int32
>( m_aColumnLabels
.size()))
428 m_aColumnLabels
.erase( m_aColumnLabels
.begin() + nAtIndex
);
433 void InternalData::deleteRow( sal_Int32 nAtIndex
)
435 OSL_ASSERT( nAtIndex
< m_nRowCount
&& nAtIndex
>= 0 );
436 if( nAtIndex
>= m_nRowCount
|| m_nRowCount
< 1 || nAtIndex
< 0 )
438 sal_Int32 nNewRowCount
= m_nRowCount
- 1;
439 sal_Int32
nNewSize( m_nColumnCount
* nNewRowCount
);
441 tDataType
aNewData( std::numeric_limits
<double>::quiet_NaN(), nNewSize
);
444 sal_Int32 nIndex
= nAtIndex
;
446 aNewData
[ std::slice( 0, nIndex
* m_nColumnCount
, 1 ) ] =
447 static_cast< tDataType
>(
448 m_aData
[ std::slice( 0, nIndex
* m_nColumnCount
, 1 ) ] );
450 if( nIndex
< nNewRowCount
)
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 ) ] );
458 m_nRowCount
= nNewRowCount
;
459 m_aData
.resize( nNewSize
);
463 if( nAtIndex
< static_cast< sal_Int32
>( m_aRowLabels
.size()))
464 m_aRowLabels
.erase( m_aRowLabels
.begin() + nAtIndex
);
469 void InternalData::setComplexRowLabels( tVecVecAny
&& rNewRowLabels
)
471 m_aRowLabels
= std::move(rNewRowLabels
);
472 sal_Int32 nNewRowCount
= static_cast< sal_Int32
>( m_aRowLabels
.size() );
473 if( nNewRowCount
< m_nRowCount
)
474 m_aRowLabels
.resize( m_nRowCount
);
476 enlargeData( 0, nNewRowCount
);
479 const InternalData::tVecVecAny
& InternalData::getComplexRowLabels() const
484 void InternalData::setComplexColumnLabels( tVecVecAny
&& rNewColumnLabels
)
486 m_aColumnLabels
= std::move(rNewColumnLabels
);
487 sal_Int32 nNewColumnCount
= static_cast< sal_Int32
>( m_aColumnLabels
.size() );
488 if( nNewColumnCount
< m_nColumnCount
)
489 m_aColumnLabels
.resize( m_nColumnCount
);
491 enlargeData( nNewColumnCount
, 0 );
494 const InternalData::tVecVecAny
& InternalData::getComplexColumnLabels() const
496 return m_aColumnLabels
;
499 #ifdef DEBUG_INTERNAL_DATA
500 void InternalData::dump() const
503 if (!m_aColumnLabels
.empty())
505 svl::GridPrinter
aPrinter(m_aColumnLabels
[0].size(), m_aColumnLabels
.size(), true);
506 for (size_t nCol
= 0; nCol
< m_aColumnLabels
.size(); ++nCol
)
508 for (size_t nRow
= 0; nRow
< m_aColumnLabels
[nCol
].size(); ++nRow
)
511 if (m_aColumnLabels
[nCol
].at(nRow
) >>= aStr
)
512 aPrinter
.set(nRow
, nCol
, aStr
);
515 aPrinter
.print("Header");
518 if (!m_aRowLabels
.empty())
520 svl::GridPrinter
aPrinter(m_aRowLabels
.size(), m_aRowLabels
[0].size(), true);
521 for (size_t nRow
= 0; nRow
< m_aRowLabels
.size(); ++nRow
)
523 for (size_t nCol
= 0; nCol
< m_aRowLabels
[nRow
].size(); ++nCol
)
526 if (m_aRowLabels
[nRow
].at(nCol
) >>= aStr
)
527 aPrinter
.set(nRow
, nCol
, aStr
);
530 aPrinter
.print("Row labels");
533 svl::GridPrinter
aPrinter(m_nRowCount
, m_nColumnCount
, true);
535 for (sal_Int32 nRow
= 0; nRow
< m_nRowCount
; ++nRow
)
537 tDataType
aSlice( m_aData
[ std::slice( nRow
*m_nColumnCount
, m_nColumnCount
, 1 ) ] );
538 for (sal_Int32 nCol
= 0; nCol
< m_nColumnCount
; ++nCol
)
539 aPrinter
.set(nRow
, nCol
, OUString::number(aSlice
[nCol
]));
542 aPrinter
.print("Column data");
545 void InternalData::dump() const {}
550 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */