/src/libreoffice/chart2/source/tools/InternalData.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
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/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
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 . |
18 | | */ |
19 | | |
20 | | #include <InternalData.hxx> |
21 | | #include <ResId.hxx> |
22 | | #include <strings.hrc> |
23 | | |
24 | | #include <comphelper/sequence.hxx> |
25 | | #include <o3tl/safeint.hxx> |
26 | | #include <osl/diagnose.h> |
27 | | |
28 | | #ifdef DEBUG_CHART2_TOOLS |
29 | | #define DEBUG_INTERNAL_DATA 1 |
30 | | #endif |
31 | | |
32 | | #ifdef DEBUG_INTERNAL_DATA |
33 | | #include <svl/gridprinter.hxx> |
34 | | #endif |
35 | | |
36 | | #include <algorithm> |
37 | | #include <iterator> |
38 | | #include <limits> |
39 | | |
40 | | using ::com::sun::star::uno::Sequence; |
41 | | |
42 | | using namespace ::com::sun::star; |
43 | | |
44 | | namespace chart |
45 | | { |
46 | | |
47 | | namespace |
48 | | { |
49 | | struct lcl_NumberedStringGenerator |
50 | | { |
51 | | lcl_NumberedStringGenerator( const OUString & rStub, std::u16string_view rWildcard ) : |
52 | 0 | m_aStub( rStub ), |
53 | 0 | m_nCounter( 0 ), |
54 | 0 | m_nStubStartIndex( rStub.indexOf( rWildcard )), |
55 | 0 | m_nWildcardLength( rWildcard.size()) |
56 | 0 | { |
57 | 0 | } |
58 | | std::vector< uno::Any > operator()() |
59 | 0 | { |
60 | 0 | return { uno::Any(m_aStub.replaceAt( m_nStubStartIndex, m_nWildcardLength, OUString::number( ++m_nCounter ))) }; |
61 | 0 | } |
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 > |
70 | | Sequence< T > lcl_ValarrayToSequence( const std::valarray< T > & rValarray ) |
71 | 0 | { |
72 | | #if defined __GLIBCXX__ && (!defined _GLIBCXX_RELEASE || _GLIBCXX_RELEASE < 12) |
73 | | // workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103022 |
74 | | if (!size(rValarray)) |
75 | | return Sequence<T>(); |
76 | | #endif |
77 | |
|
78 | 0 | return comphelper::containerToSequence(rValarray); |
79 | 0 | } |
80 | | |
81 | | } // anonymous namespace |
82 | | |
83 | | InternalData::InternalData() |
84 | 0 | : m_nColumnCount( 0 ) |
85 | 0 | , m_nRowCount( 0 ) |
86 | 0 | , m_aRowLabels( 0 ) |
87 | 0 | , m_aColumnLabels( 0 ) |
88 | 0 | {} |
89 | | |
90 | | const double fDefaultData[] = { |
91 | | 9.10, 3.20, 4.54, |
92 | | 2.40, 8.80, 9.65, |
93 | | 3.10, 1.50, 3.70, |
94 | | 4.30, 9.02, 6.20 |
95 | | }; |
96 | | |
97 | | void InternalData::createDefaultData() |
98 | 0 | { |
99 | 0 | const sal_Int32 nRowCount = 4; |
100 | 0 | const sal_Int32 nColumnCount = 3; |
101 | |
|
102 | 0 | m_nRowCount = nRowCount; |
103 | 0 | m_nColumnCount = nColumnCount; |
104 | 0 | const sal_Int32 nSize = nColumnCount * nRowCount; |
105 | | // @todo: localize this! |
106 | 0 | const OUString aRowName(SchResId(STR_ROW_LABEL)); |
107 | 0 | const OUString aColName(SchResId(STR_COLUMN_LABEL)); |
108 | |
|
109 | 0 | m_aData.resize( nSize ); |
110 | 0 | for( sal_Int32 i=0; i<nSize; ++i ) |
111 | 0 | m_aData[i] = fDefaultData[i]; |
112 | |
|
113 | 0 | m_aRowLabels.clear(); |
114 | 0 | m_aRowLabels.reserve( m_nRowCount ); |
115 | 0 | generate_n( back_inserter( m_aRowLabels ), m_nRowCount, |
116 | 0 | lcl_NumberedStringGenerator( aRowName, u"%ROWNUMBER" )); |
117 | |
|
118 | 0 | m_aColumnLabels.clear(); |
119 | 0 | m_aColumnLabels.reserve( m_nColumnCount ); |
120 | 0 | generate_n( back_inserter( m_aColumnLabels ), m_nColumnCount, |
121 | 0 | lcl_NumberedStringGenerator( aColName, u"%COLUMNNUMBER" )); |
122 | 0 | } |
123 | | |
124 | | void InternalData::setData( const Sequence< Sequence< double > >& rDataInRows ) |
125 | 0 | { |
126 | 0 | m_nRowCount = rDataInRows.getLength(); |
127 | 0 | m_nColumnCount = (m_nRowCount ? rDataInRows[0].getLength() : 0); |
128 | |
|
129 | 0 | if( m_aRowLabels.size() != static_cast< sal_uInt32 >( m_nRowCount )) |
130 | 0 | m_aRowLabels.resize( m_nRowCount ); |
131 | 0 | if( m_aColumnLabels.size() != static_cast< sal_uInt32 >( m_nColumnCount )) |
132 | 0 | m_aColumnLabels.resize( m_nColumnCount ); |
133 | |
|
134 | 0 | m_aData.resize( m_nRowCount * m_nColumnCount ); |
135 | | // set all values to Nan |
136 | 0 | m_aData = std::numeric_limits<double>::quiet_NaN(); |
137 | |
|
138 | 0 | for( sal_Int32 nRow=0; nRow<m_nRowCount; ++nRow ) |
139 | 0 | { |
140 | 0 | int nDataIdx = nRow*m_nColumnCount; |
141 | 0 | const sal_Int32 nMax = std::min( rDataInRows[nRow].getLength(), m_nColumnCount ); |
142 | 0 | for( sal_Int32 nCol=0; nCol < nMax; ++nCol ) |
143 | 0 | { |
144 | 0 | m_aData[nDataIdx] = rDataInRows[nRow][nCol]; |
145 | 0 | nDataIdx += 1; |
146 | 0 | } |
147 | 0 | } |
148 | 0 | } |
149 | | |
150 | | Sequence< Sequence< double > > InternalData::getData() const |
151 | 0 | { |
152 | 0 | Sequence< Sequence< double > > aResult( m_nRowCount ); |
153 | 0 | auto aResultRange = asNonConstRange(aResult); |
154 | |
|
155 | 0 | for( sal_Int32 i=0; i<m_nRowCount; ++i ) |
156 | 0 | aResultRange[i] = lcl_ValarrayToSequence< tDataType::value_type >( |
157 | 0 | m_aData[ std::slice( i*m_nColumnCount, m_nColumnCount, 1 ) ] ); |
158 | |
|
159 | 0 | return aResult; |
160 | 0 | } |
161 | | |
162 | | Sequence< double > InternalData::getColumnValues( sal_Int32 nColumnIndex ) const |
163 | 0 | { |
164 | 0 | if( nColumnIndex >= 0 && nColumnIndex < m_nColumnCount ) |
165 | 0 | return lcl_ValarrayToSequence< tDataType::value_type >( |
166 | 0 | m_aData[ std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ] ); |
167 | 0 | return Sequence< double >(); |
168 | 0 | } |
169 | | Sequence< double > InternalData::getRowValues( sal_Int32 nRowIndex ) const |
170 | 0 | { |
171 | 0 | if( nRowIndex >= 0 && nRowIndex < m_nRowCount ) |
172 | 0 | return lcl_ValarrayToSequence< tDataType::value_type >( |
173 | 0 | m_aData[ std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ] ); |
174 | 0 | return Sequence< double >(); |
175 | 0 | } |
176 | | |
177 | | void InternalData::setColumnValues( sal_Int32 nColumnIndex, const std::vector< double > & rNewData ) |
178 | 0 | { |
179 | 0 | if( nColumnIndex < 0 ) |
180 | 0 | return; |
181 | 0 | enlargeData( nColumnIndex + 1, rNewData.size() ); |
182 | |
|
183 | 0 | tDataType aSlice = m_aData[ std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ]; |
184 | 0 | for( std::vector< double >::size_type i = 0; i < rNewData.size(); ++i ) |
185 | 0 | aSlice[i] = rNewData[i]; |
186 | 0 | m_aData[ std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ] = aSlice; |
187 | 0 | } |
188 | | |
189 | | void InternalData::setRowValues( sal_Int32 nRowIndex, const std::vector< double > & rNewData ) |
190 | 0 | { |
191 | 0 | if( nRowIndex < 0 ) |
192 | 0 | return; |
193 | 0 | enlargeData( rNewData.size(), nRowIndex+1 ); |
194 | |
|
195 | 0 | tDataType aSlice = m_aData[ std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ]; |
196 | 0 | for( std::vector< double >::size_type i = 0; i < rNewData.size(); ++i ) |
197 | 0 | aSlice[i] = rNewData[i]; |
198 | 0 | m_aData[ std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ]= aSlice; |
199 | 0 | } |
200 | | |
201 | | void InternalData::setComplexColumnLabel( sal_Int32 nColumnIndex, std::vector< uno::Any >&& rComplexLabel ) |
202 | 0 | { |
203 | 0 | if( nColumnIndex < 0 ) |
204 | 0 | return; |
205 | 0 | if( o3tl::make_unsigned(nColumnIndex) >= m_aColumnLabels.size() ) |
206 | 0 | { |
207 | 0 | m_aColumnLabels.resize(nColumnIndex+1); |
208 | 0 | enlargeData( nColumnIndex+1, 0 ); |
209 | 0 | } |
210 | 0 | m_aColumnLabels[nColumnIndex] = std::move(rComplexLabel); |
211 | |
|
212 | 0 | dump(); |
213 | 0 | } |
214 | | |
215 | | void InternalData::setComplexRowLabel( sal_Int32 nRowIndex, std::vector< uno::Any >&& rComplexLabel ) |
216 | 0 | { |
217 | 0 | if( nRowIndex < 0 ) |
218 | 0 | return; |
219 | 0 | if( o3tl::make_unsigned(nRowIndex) >= m_aRowLabels.size() ) |
220 | 0 | { |
221 | 0 | m_aRowLabels.resize(nRowIndex+1); |
222 | 0 | enlargeData( 0, nRowIndex+1 ); |
223 | 0 | } |
224 | 0 | m_aRowLabels[nRowIndex] = std::move(rComplexLabel); |
225 | |
|
226 | 0 | dump(); |
227 | 0 | } |
228 | | |
229 | | void InternalData::setComplexCategoryLabel(sal_Int32 nRowIndex, std::vector< uno::Any >&& rComplexLabel) |
230 | 0 | { |
231 | 0 | if (nRowIndex < 0) |
232 | 0 | return; |
233 | 0 | if (o3tl::make_unsigned(nRowIndex) >= m_aRowLabels.size()) |
234 | 0 | { |
235 | 0 | m_aRowLabels.resize(nRowIndex + 1); |
236 | 0 | enlargeData(0, nRowIndex + 1); |
237 | 0 | } |
238 | 0 | sal_Int32 nSize = static_cast<sal_Int32>(m_aRowLabels[nRowIndex].size()); |
239 | 0 | if (nSize >= 1 && !rComplexLabel.empty()) |
240 | 0 | { |
241 | 0 | m_aRowLabels[nRowIndex].resize(nSize + 1); |
242 | 0 | m_aRowLabels[nRowIndex][nSize] = rComplexLabel[0]; |
243 | 0 | } |
244 | 0 | else |
245 | 0 | { |
246 | 0 | m_aRowLabels[nRowIndex] = std::move(rComplexLabel); |
247 | 0 | } |
248 | 0 | } |
249 | | |
250 | | std::vector< uno::Any > InternalData::getComplexColumnLabel( sal_Int32 nColumnIndex ) const |
251 | 0 | { |
252 | 0 | if( nColumnIndex < static_cast< sal_Int32 >( m_aColumnLabels.size() ) ) |
253 | 0 | return m_aColumnLabels[nColumnIndex]; |
254 | 0 | else |
255 | 0 | return std::vector< uno::Any >(); |
256 | 0 | } |
257 | | std::vector< uno::Any > InternalData::getComplexRowLabel( sal_Int32 nRowIndex ) const |
258 | 0 | { |
259 | 0 | if( nRowIndex < static_cast< sal_Int32 >( m_aRowLabels.size() ) ) |
260 | 0 | return m_aRowLabels[nRowIndex]; |
261 | 0 | else |
262 | 0 | return std::vector< uno::Any >(); |
263 | 0 | } |
264 | | |
265 | | void InternalData::swapRowWithNext( sal_Int32 nRowIndex ) |
266 | 0 | { |
267 | 0 | if( nRowIndex >= m_nRowCount - 1 ) |
268 | 0 | return; |
269 | | |
270 | 0 | const sal_Int32 nMax = m_nColumnCount; |
271 | 0 | for( sal_Int32 nColIdx=0; nColIdx<nMax; ++nColIdx ) |
272 | 0 | { |
273 | 0 | size_t nIndex1 = nColIdx + nRowIndex*m_nColumnCount; |
274 | 0 | size_t nIndex2 = nIndex1 + m_nColumnCount; |
275 | 0 | std::swap(m_aData[nIndex1], m_aData[nIndex2]); |
276 | 0 | } |
277 | |
|
278 | 0 | std::swap(m_aRowLabels[nRowIndex], m_aRowLabels[nRowIndex + 1]); |
279 | 0 | } |
280 | | |
281 | | void InternalData::swapColumnWithNext( sal_Int32 nColumnIndex ) |
282 | 0 | { |
283 | 0 | if( nColumnIndex >= m_nColumnCount - 1 ) |
284 | 0 | return; |
285 | | |
286 | 0 | const sal_Int32 nMax = m_nRowCount; |
287 | 0 | for( sal_Int32 nRowIdx=0; nRowIdx<nMax; ++nRowIdx ) |
288 | 0 | { |
289 | 0 | size_t nIndex1 = nColumnIndex + nRowIdx*m_nColumnCount; |
290 | 0 | size_t nIndex2 = nIndex1 + 1; |
291 | 0 | std::swap(m_aData[nIndex1], m_aData[nIndex2]); |
292 | 0 | } |
293 | |
|
294 | 0 | std::swap(m_aColumnLabels[nColumnIndex], m_aColumnLabels[nColumnIndex + 1]); |
295 | 0 | } |
296 | | |
297 | | bool InternalData::enlargeData( sal_Int32 nColumnCount, sal_Int32 nRowCount ) |
298 | 0 | { |
299 | 0 | sal_Int32 nNewColumnCount( std::max<sal_Int32>( m_nColumnCount, nColumnCount ) ); |
300 | 0 | sal_Int32 nNewRowCount( std::max<sal_Int32>( m_nRowCount, nRowCount ) ); |
301 | 0 | sal_Int32 nNewSize( nNewColumnCount*nNewRowCount ); |
302 | |
|
303 | 0 | bool bGrow = (nNewSize > m_nColumnCount*m_nRowCount); |
304 | |
|
305 | 0 | if( bGrow ) |
306 | 0 | { |
307 | 0 | tDataType aNewData( std::numeric_limits<double>::quiet_NaN(), nNewSize ); |
308 | | // copy old data |
309 | 0 | for( int nCol=0; nCol<m_nColumnCount; ++nCol ) |
310 | 0 | static_cast< tDataType >( |
311 | 0 | aNewData[ std::slice( nCol, m_nRowCount, nNewColumnCount ) ] ) = |
312 | 0 | m_aData[ std::slice( nCol, m_nRowCount, m_nColumnCount ) ]; |
313 | |
|
314 | 0 | m_aData = std::move(aNewData); |
315 | 0 | } |
316 | 0 | m_nColumnCount = nNewColumnCount; |
317 | 0 | m_nRowCount = nNewRowCount; |
318 | 0 | return bGrow; |
319 | 0 | } |
320 | | |
321 | | void InternalData::insertColumn( sal_Int32 nAfterIndex ) |
322 | 0 | { |
323 | | // note: -1 is allowed, as we insert after the given index |
324 | 0 | OSL_ASSERT( nAfterIndex < m_nColumnCount && nAfterIndex >= -1 ); |
325 | 0 | if( nAfterIndex >= m_nColumnCount || nAfterIndex < -1 ) |
326 | 0 | return; |
327 | 0 | sal_Int32 nNewColumnCount = m_nColumnCount + 1; |
328 | 0 | sal_Int32 nNewSize( nNewColumnCount * m_nRowCount ); |
329 | |
|
330 | 0 | tDataType aNewData( std::numeric_limits<double>::quiet_NaN(), nNewSize ); |
331 | | |
332 | | // copy old data |
333 | 0 | int nCol=0; |
334 | 0 | for( ; nCol<=nAfterIndex; ++nCol ) |
335 | 0 | aNewData[ std::slice( nCol, m_nRowCount, nNewColumnCount ) ] = |
336 | 0 | static_cast< tDataType >( |
337 | 0 | m_aData[ std::slice( nCol, m_nRowCount, m_nColumnCount ) ] ); |
338 | 0 | for( ++nCol; nCol<nNewColumnCount; ++nCol ) |
339 | 0 | aNewData[ std::slice( nCol, m_nRowCount, nNewColumnCount ) ] = |
340 | 0 | static_cast< tDataType >( |
341 | 0 | m_aData[ std::slice( nCol - 1, m_nRowCount, m_nColumnCount ) ] ); |
342 | |
|
343 | 0 | m_nColumnCount = nNewColumnCount; |
344 | 0 | m_aData = std::move(aNewData); |
345 | | |
346 | | // labels |
347 | 0 | if( nAfterIndex < static_cast< sal_Int32 >( m_aColumnLabels.size())) |
348 | 0 | m_aColumnLabels.insert( m_aColumnLabels.begin() + (nAfterIndex + 1), std::vector< uno::Any >(1) ); |
349 | |
|
350 | 0 | dump(); |
351 | 0 | } |
352 | | |
353 | | sal_Int32 InternalData::appendColumn() |
354 | 0 | { |
355 | 0 | insertColumn( getColumnCount() - 1 ); |
356 | 0 | return getColumnCount() - 1; |
357 | 0 | } |
358 | | |
359 | | sal_Int32 InternalData::appendRow() |
360 | 0 | { |
361 | 0 | insertRow( getRowCount() - 1 ); |
362 | 0 | return getRowCount() - 1; |
363 | 0 | } |
364 | | |
365 | | sal_Int32 InternalData::getRowCount() const |
366 | 0 | { |
367 | 0 | return m_nRowCount; |
368 | 0 | } |
369 | | |
370 | | sal_Int32 InternalData::getColumnCount() const |
371 | 0 | { |
372 | 0 | return m_nColumnCount; |
373 | 0 | } |
374 | | |
375 | | void InternalData::insertRow( sal_Int32 nAfterIndex ) |
376 | 0 | { |
377 | | // note: -1 is allowed, as we insert after the given index |
378 | 0 | OSL_ASSERT( nAfterIndex < m_nRowCount && nAfterIndex >= -1 ); |
379 | 0 | if( nAfterIndex >= m_nRowCount || nAfterIndex < -1 ) |
380 | 0 | return; |
381 | 0 | sal_Int32 nNewRowCount = m_nRowCount + 1; |
382 | 0 | sal_Int32 nNewSize( m_nColumnCount * nNewRowCount ); |
383 | |
|
384 | 0 | tDataType aNewData( std::numeric_limits<double>::quiet_NaN(), nNewSize ); |
385 | | |
386 | | // copy old data |
387 | 0 | sal_Int32 nIndex = nAfterIndex + 1; |
388 | 0 | aNewData[ std::slice( 0, nIndex * m_nColumnCount, 1 ) ] = |
389 | 0 | static_cast< tDataType >( |
390 | 0 | m_aData[ std::slice( 0, nIndex * m_nColumnCount, 1 ) ] ); |
391 | |
|
392 | 0 | if( nIndex < m_nRowCount ) |
393 | 0 | { |
394 | 0 | sal_Int32 nRemainingCount = m_nColumnCount * (m_nRowCount - nIndex); |
395 | 0 | aNewData[ std::slice( (nIndex + 1) * m_nColumnCount, nRemainingCount, 1 ) ] = |
396 | 0 | static_cast< tDataType >( |
397 | 0 | m_aData[ std::slice( nIndex * m_nColumnCount, nRemainingCount, 1 ) ] ); |
398 | 0 | } |
399 | |
|
400 | 0 | m_nRowCount = nNewRowCount; |
401 | 0 | m_aData = std::move(aNewData); |
402 | | |
403 | | // labels |
404 | 0 | if( nAfterIndex < static_cast< sal_Int32 >( m_aRowLabels.size())) |
405 | 0 | m_aRowLabels.insert( m_aRowLabels.begin() + nIndex, std::vector< uno::Any > (1)); |
406 | |
|
407 | 0 | dump(); |
408 | 0 | } |
409 | | |
410 | | void InternalData::deleteColumn( sal_Int32 nAtIndex ) |
411 | 0 | { |
412 | 0 | OSL_ASSERT( nAtIndex < m_nColumnCount && nAtIndex >= 0 ); |
413 | 0 | if( nAtIndex >= m_nColumnCount || m_nColumnCount < 1 || nAtIndex < 0 ) |
414 | 0 | return; |
415 | 0 | sal_Int32 nNewColumnCount = m_nColumnCount - 1; |
416 | 0 | sal_Int32 nNewSize( nNewColumnCount * m_nRowCount ); |
417 | |
|
418 | 0 | tDataType aNewData( std::numeric_limits<double>::quiet_NaN(), nNewSize ); |
419 | | |
420 | | // copy old data |
421 | 0 | int nCol=0; |
422 | 0 | for( ; nCol<nAtIndex; ++nCol ) |
423 | 0 | aNewData[ std::slice( nCol, m_nRowCount, nNewColumnCount ) ] = |
424 | 0 | static_cast< tDataType >( |
425 | 0 | m_aData[ std::slice( nCol, m_nRowCount, m_nColumnCount ) ] ); |
426 | 0 | for( ; nCol<nNewColumnCount; ++nCol ) |
427 | 0 | aNewData[ std::slice( nCol, m_nRowCount, nNewColumnCount ) ] = |
428 | 0 | static_cast< tDataType >( |
429 | 0 | m_aData[ std::slice( nCol + 1, m_nRowCount, m_nColumnCount ) ] ); |
430 | |
|
431 | 0 | m_nColumnCount = nNewColumnCount; |
432 | 0 | m_aData = std::move(aNewData); |
433 | | |
434 | | // labels |
435 | 0 | if( nAtIndex < static_cast< sal_Int32 >( m_aColumnLabels.size())) |
436 | 0 | m_aColumnLabels.erase( m_aColumnLabels.begin() + nAtIndex ); |
437 | |
|
438 | 0 | dump(); |
439 | 0 | } |
440 | | |
441 | | void InternalData::deleteRow( sal_Int32 nAtIndex ) |
442 | 0 | { |
443 | 0 | OSL_ASSERT( nAtIndex < m_nRowCount && nAtIndex >= 0 ); |
444 | 0 | if( nAtIndex >= m_nRowCount || m_nRowCount < 1 || nAtIndex < 0 ) |
445 | 0 | return; |
446 | 0 | sal_Int32 nNewRowCount = m_nRowCount - 1; |
447 | 0 | sal_Int32 nNewSize( m_nColumnCount * nNewRowCount ); |
448 | |
|
449 | 0 | tDataType aNewData( std::numeric_limits<double>::quiet_NaN(), nNewSize ); |
450 | | |
451 | | // copy old data |
452 | 0 | sal_Int32 nIndex = nAtIndex; |
453 | 0 | if( nIndex ) |
454 | 0 | aNewData[ std::slice( 0, nIndex * m_nColumnCount, 1 ) ] = |
455 | 0 | static_cast< tDataType >( |
456 | 0 | m_aData[ std::slice( 0, nIndex * m_nColumnCount, 1 ) ] ); |
457 | |
|
458 | 0 | if( nIndex < nNewRowCount ) |
459 | 0 | { |
460 | 0 | sal_Int32 nRemainingCount = m_nColumnCount * (nNewRowCount - nIndex); |
461 | 0 | aNewData[ std::slice( nIndex * m_nColumnCount, nRemainingCount, 1 ) ] = |
462 | 0 | static_cast< tDataType >( |
463 | 0 | m_aData[ std::slice( (nIndex + 1) * m_nColumnCount, nRemainingCount, 1 ) ] ); |
464 | 0 | } |
465 | |
|
466 | 0 | m_nRowCount = nNewRowCount; |
467 | 0 | m_aData = std::move(aNewData); |
468 | | |
469 | | // labels |
470 | 0 | if( nAtIndex < static_cast< sal_Int32 >( m_aRowLabels.size())) |
471 | 0 | m_aRowLabels.erase( m_aRowLabels.begin() + nAtIndex ); |
472 | |
|
473 | 0 | dump(); |
474 | 0 | } |
475 | | |
476 | | void InternalData::setComplexRowLabels( tVecVecAny&& rNewRowLabels ) |
477 | 0 | { |
478 | 0 | m_aRowLabels = std::move(rNewRowLabels); |
479 | 0 | sal_Int32 nNewRowCount = static_cast< sal_Int32 >( m_aRowLabels.size() ); |
480 | 0 | if( nNewRowCount < m_nRowCount ) |
481 | 0 | m_aRowLabels.resize( m_nRowCount ); |
482 | 0 | else |
483 | 0 | enlargeData( 0, nNewRowCount ); |
484 | 0 | } |
485 | | |
486 | | const InternalData::tVecVecAny& InternalData::getComplexRowLabels() const |
487 | 0 | { |
488 | 0 | return m_aRowLabels; |
489 | 0 | } |
490 | | |
491 | | void InternalData::setComplexColumnLabels( tVecVecAny&& rNewColumnLabels ) |
492 | 0 | { |
493 | 0 | m_aColumnLabels = std::move(rNewColumnLabels); |
494 | 0 | sal_Int32 nNewColumnCount = static_cast< sal_Int32 >( m_aColumnLabels.size() ); |
495 | 0 | if( nNewColumnCount < m_nColumnCount ) |
496 | 0 | m_aColumnLabels.resize( m_nColumnCount ); |
497 | 0 | else |
498 | 0 | enlargeData( nNewColumnCount, 0 ); |
499 | 0 | } |
500 | | |
501 | | const InternalData::tVecVecAny& InternalData::getComplexColumnLabels() const |
502 | 0 | { |
503 | 0 | return m_aColumnLabels; |
504 | 0 | } |
505 | | |
506 | | #ifdef DEBUG_INTERNAL_DATA |
507 | | void InternalData::dump() const |
508 | | { |
509 | | // Header |
510 | | if (!m_aColumnLabels.empty()) |
511 | | { |
512 | | svl::GridPrinter aPrinter(m_aColumnLabels[0].size(), m_aColumnLabels.size(), true); |
513 | | for (size_t nCol = 0; nCol < m_aColumnLabels.size(); ++nCol) |
514 | | { |
515 | | for (size_t nRow = 0; nRow < m_aColumnLabels[nCol].size(); ++nRow) |
516 | | { |
517 | | OUString aStr; |
518 | | if (m_aColumnLabels[nCol].at(nRow) >>= aStr) |
519 | | aPrinter.set(nRow, nCol, aStr); |
520 | | } |
521 | | } |
522 | | aPrinter.print("Header"); |
523 | | } |
524 | | |
525 | | if (!m_aRowLabels.empty()) |
526 | | { |
527 | | svl::GridPrinter aPrinter(m_aRowLabels.size(), m_aRowLabels[0].size(), true); |
528 | | for (size_t nRow = 0; nRow < m_aRowLabels.size(); ++nRow) |
529 | | { |
530 | | for (size_t nCol = 0; nCol < m_aRowLabels[nRow].size(); ++nCol) |
531 | | { |
532 | | OUString aStr; |
533 | | if (m_aRowLabels[nRow].at(nCol) >>= aStr) |
534 | | aPrinter.set(nRow, nCol, aStr); |
535 | | } |
536 | | } |
537 | | aPrinter.print("Row labels"); |
538 | | } |
539 | | |
540 | | svl::GridPrinter aPrinter(m_nRowCount, m_nColumnCount, true); |
541 | | |
542 | | for (sal_Int32 nRow = 0; nRow < m_nRowCount; ++nRow) |
543 | | { |
544 | | tDataType aSlice( m_aData[ std::slice( nRow*m_nColumnCount, m_nColumnCount, 1 ) ] ); |
545 | | for (sal_Int32 nCol = 0; nCol < m_nColumnCount; ++nCol) |
546 | | aPrinter.set(nRow, nCol, OUString::number(aSlice[nCol])); |
547 | | } |
548 | | |
549 | | aPrinter.print("Column data"); |
550 | | } |
551 | | #else |
552 | 0 | void InternalData::dump() const {} |
553 | | #endif |
554 | | |
555 | | } // namespace chart |
556 | | |
557 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |