1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_charttools.hxx" 26 27 #include "InternalData.hxx" 28 #include "ResId.hxx" 29 #include "Strings.hrc" 30 #include "macros.hxx" 31 32 #include <rtl/math.hxx> 33 #include <algorithm> 34 35 36 // std::back_inserter lives in <iterator>. VC9's headers pulled it in 37 // transitively, a modern one does not. 38 #include <iterator> 39 using ::com::sun::star::uno::Sequence; 40 using ::rtl::OUString; 41 42 using namespace ::com::sun::star; 43 using namespace ::std; 44 45 namespace chart 46 { 47 48 // ---------------------------------------- 49 namespace 50 { 51 struct lcl_NumberedStringGenerator 52 { 53 lcl_NumberedStringGenerator( const OUString & rStub, const OUString & rWildcard ) : 54 m_aStub( rStub ), 55 m_nCounter( 0 ), 56 m_nStubStartIndex( rStub.indexOf( rWildcard )), 57 m_nWildcardLength( rWildcard.getLength()) 58 { 59 } 60 vector< uno::Any > operator()() 61 { 62 vector< uno::Any > aRet(1); 63 aRet[0] = uno::makeAny( m_aStub.replaceAt( m_nStubStartIndex, m_nWildcardLength, OUString::valueOf( ++m_nCounter )) ); 64 return aRet; 65 } 66 private: 67 OUString m_aStub; 68 sal_Int32 m_nCounter; 69 const sal_Int32 m_nStubStartIndex; 70 const sal_Int32 m_nWildcardLength; 71 }; 72 73 template< typename T > 74 Sequence< T > lcl_ValarrayToSequence( const ::std::valarray< T > & rValarray ) 75 { 76 // is there a more elegant way of conversion? 77 Sequence< T > aResult( rValarray.size()); 78 for( size_t i = 0; i < rValarray.size(); ++i ) 79 aResult[i] = rValarray[i]; 80 return aResult; 81 } 82 83 } // anonymous namespace 84 // ---------------------------------------- 85 86 InternalData::InternalData() 87 : m_nColumnCount( 0 ) 88 , m_nRowCount( 0 ) 89 , m_aRowLabels( 0 ) 90 , m_aColumnLabels( 0 ) 91 {} 92 93 void InternalData::createDefaultData() 94 { 95 const sal_Int32 nRowCount = 4; 96 const sal_Int32 nColumnCount = 3; 97 98 m_nRowCount = nRowCount; 99 m_nColumnCount = nColumnCount; 100 const sal_Int32 nSize = nColumnCount * nRowCount; 101 // @todo: localize this! 102 const OUString aRowName( ::chart::SchResId::getResString( STR_ROW_LABEL )); 103 const OUString aColName( ::chart::SchResId::getResString( STR_COLUMN_LABEL )); 104 105 const double fDefaultData[ nSize ] = 106 { 9.10, 3.20, 4.54, 107 2.40, 8.80, 9.65, 108 3.10, 1.50, 3.70, 109 4.30, 9.02, 6.20 }; 110 111 m_aData.resize( nSize ); 112 for( sal_Int32 i=0; i<nSize; ++i ) 113 m_aData[i] = fDefaultData[i]; 114 115 m_aRowLabels.clear(); 116 m_aRowLabels.reserve( m_nRowCount ); 117 generate_n( back_inserter( m_aRowLabels ), m_nRowCount, 118 lcl_NumberedStringGenerator( aRowName, C2U("%ROWNUMBER") )); 119 120 m_aColumnLabels.clear(); 121 m_aColumnLabels.reserve( m_nColumnCount ); 122 generate_n( back_inserter( m_aColumnLabels ), m_nColumnCount, 123 lcl_NumberedStringGenerator( aColName, C2U("%COLUMNNUMBER") )); 124 } 125 126 void InternalData::setData( const Sequence< Sequence< double > >& rDataInRows ) 127 { 128 m_nRowCount = rDataInRows.getLength(); 129 m_nColumnCount = (m_nRowCount ? rDataInRows[0].getLength() : 0); 130 131 if( m_aRowLabels.size() != static_cast< sal_uInt32 >( m_nRowCount )) 132 m_aRowLabels.resize( m_nRowCount ); 133 if( m_aColumnLabels.size() != static_cast< sal_uInt32 >( m_nColumnCount )) 134 m_aColumnLabels.resize( m_nColumnCount ); 135 136 m_aData.resize( m_nRowCount * m_nColumnCount ); 137 double fNan; 138 ::rtl::math::setNan( & fNan ); 139 // set all values to Nan 140 m_aData = fNan; 141 142 for( sal_Int32 nRow=0; nRow<m_nRowCount; ++nRow ) 143 { 144 int nDataIdx = nRow*m_nColumnCount; 145 const sal_Int32 nMax = ::std::min( rDataInRows[nRow].getLength(), m_nColumnCount ); 146 for( sal_Int32 nCol=0; nCol < nMax; ++nCol ) 147 { 148 m_aData[nDataIdx] = rDataInRows[nRow][nCol]; 149 nDataIdx += 1; 150 } 151 } 152 } 153 154 Sequence< Sequence< double > > InternalData::getData() const 155 { 156 Sequence< Sequence< double > > aResult( m_nRowCount ); 157 158 for( sal_Int32 i=0; i<m_nRowCount; ++i ) 159 aResult[i] = lcl_ValarrayToSequence< tDataType::value_type >( 160 m_aData[ ::std::slice( i*m_nColumnCount, m_nColumnCount, 1 ) ] ); 161 162 return aResult; 163 } 164 165 Sequence< double > InternalData::getColumnValues( sal_Int32 nColumnIndex ) const 166 { 167 if( nColumnIndex >= 0 && nColumnIndex < m_nColumnCount ) 168 return lcl_ValarrayToSequence< tDataType::value_type >( 169 m_aData[ ::std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ] ); 170 return Sequence< double >(); 171 } 172 Sequence< double > InternalData::getRowValues( sal_Int32 nRowIndex ) const 173 { 174 if( nRowIndex >= 0 && nRowIndex < m_nRowCount ) 175 return lcl_ValarrayToSequence< tDataType::value_type >( 176 m_aData[ ::std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ] ); 177 return Sequence< double >(); 178 } 179 180 void InternalData::setColumnValues( sal_Int32 nColumnIndex, const vector< double > & rNewData ) 181 { 182 if( nColumnIndex < 0 ) 183 return; 184 enlargeData( nColumnIndex + 1, rNewData.size() ); 185 186 tDataType aSlice = m_aData[ ::std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ]; 187 for( vector< double >::size_type i = 0; i < rNewData.size(); ++i ) 188 aSlice[i] = rNewData[i]; 189 m_aData[ ::std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ] = aSlice; 190 } 191 192 void InternalData::setRowValues( sal_Int32 nRowIndex, const vector< double > & rNewData ) 193 { 194 if( nRowIndex < 0 ) 195 return; 196 enlargeData( rNewData.size(), nRowIndex+1 ); 197 198 tDataType aSlice = m_aData[ ::std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ]; 199 for( vector< double >::size_type i = 0; i < rNewData.size(); ++i ) 200 aSlice[i] = rNewData[i]; 201 m_aData[ ::std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ]= aSlice; 202 } 203 204 void InternalData::setComplexColumnLabel( sal_Int32 nColumnIndex, const vector< uno::Any >& rComplexLabel ) 205 { 206 if( nColumnIndex < 0 ) 207 return; 208 if( nColumnIndex >= static_cast< sal_Int32 >( m_aColumnLabels.size() ) ) 209 { 210 m_aColumnLabels.resize(nColumnIndex+1); 211 enlargeData( nColumnIndex+1, 0 ); 212 } 213 m_aColumnLabels[nColumnIndex]=rComplexLabel; 214 } 215 216 void InternalData::setComplexRowLabel( sal_Int32 nRowIndex, const vector< uno::Any >& rComplexLabel ) 217 { 218 if( nRowIndex < 0 ) 219 return; 220 if( nRowIndex >= static_cast< sal_Int32 >( m_aRowLabels.size() ) ) 221 { 222 m_aRowLabels.resize(nRowIndex+1); 223 enlargeData( 0, nRowIndex+1 ); 224 } 225 m_aRowLabels[nRowIndex] = rComplexLabel; 226 } 227 228 vector< uno::Any > InternalData::getComplexColumnLabel( sal_Int32 nColumnIndex ) const 229 { 230 if( nColumnIndex < static_cast< sal_Int32 >( m_aColumnLabels.size() ) ) 231 return m_aColumnLabels[nColumnIndex]; 232 else 233 return vector< uno::Any >(); 234 } 235 vector< uno::Any > InternalData::getComplexRowLabel( sal_Int32 nRowIndex ) const 236 { 237 if( nRowIndex < static_cast< sal_Int32 >( m_aRowLabels.size() ) ) 238 return m_aRowLabels[nRowIndex]; 239 else 240 return vector< uno::Any >(); 241 } 242 243 void InternalData::swapRowWithNext( sal_Int32 nRowIndex ) 244 { 245 if( nRowIndex < m_nRowCount - 1 ) 246 { 247 const sal_Int32 nMax = m_nColumnCount; 248 for( sal_Int32 nColIdx=0; nColIdx<nMax; ++nColIdx ) 249 { 250 size_t nIndex1 = nColIdx + nRowIndex*m_nColumnCount; 251 size_t nIndex2 = nIndex1 + m_nColumnCount; 252 double fTemp = m_aData[nIndex1]; 253 m_aData[nIndex1] = m_aData[nIndex2]; 254 m_aData[nIndex2] = fTemp; 255 } 256 257 vector< uno::Any > aTemp( m_aRowLabels[nRowIndex] ); 258 m_aRowLabels[nRowIndex] = m_aRowLabels[nRowIndex + 1]; 259 m_aRowLabels[nRowIndex + 1] = aTemp; 260 } 261 } 262 263 void InternalData::swapColumnWithNext( sal_Int32 nColumnIndex ) 264 { 265 if( nColumnIndex < m_nColumnCount - 1 ) 266 { 267 const sal_Int32 nMax = m_nRowCount; 268 for( sal_Int32 nRowIdx=0; nRowIdx<nMax; ++nRowIdx ) 269 { 270 size_t nIndex1 = nColumnIndex + nRowIdx*m_nColumnCount; 271 size_t nIndex2 = nIndex1 + 1; 272 double fTemp = m_aData[nIndex1]; 273 m_aData[nIndex1] = m_aData[nIndex2]; 274 m_aData[nIndex2] = fTemp; 275 } 276 277 vector< uno::Any > aTemp( m_aColumnLabels[nColumnIndex] ); 278 m_aColumnLabels[nColumnIndex] = m_aColumnLabels[nColumnIndex + 1]; 279 m_aColumnLabels[nColumnIndex + 1] = aTemp; 280 } 281 } 282 283 bool InternalData::enlargeData( sal_Int32 nColumnCount, sal_Int32 nRowCount ) 284 { 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 ); 288 289 bool bGrow = (nNewSize > m_nColumnCount*m_nRowCount); 290 291 if( bGrow ) 292 { 293 double fNan; 294 ::rtl::math::setNan( &fNan ); 295 tDataType aNewData( fNan, nNewSize ); 296 // copy old data 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 ) ]; 301 302 m_aData.resize( nNewSize ); 303 m_aData = aNewData; 304 } 305 m_nColumnCount = nNewColumnCount; 306 m_nRowCount = nNewRowCount; 307 return bGrow; 308 } 309 310 void InternalData::insertColumn( sal_Int32 nAfterIndex ) 311 { 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 ) 315 return; 316 sal_Int32 nNewColumnCount = m_nColumnCount + 1; 317 sal_Int32 nNewSize( nNewColumnCount * m_nRowCount ); 318 319 double fNan; 320 ::rtl::math::setNan( &fNan ); 321 tDataType aNewData( fNan, nNewSize ); 322 323 // copy old data 324 int nCol=0; 325 for( ; nCol<=nAfterIndex; ++nCol ) 326 aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] = 327 static_cast< tDataType >( 328 m_aData[ ::std::slice( nCol, m_nRowCount, m_nColumnCount ) ] ); 329 for( ++nCol; nCol<nNewColumnCount; ++nCol ) 330 aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] = 331 static_cast< tDataType >( 332 m_aData[ ::std::slice( nCol - 1, m_nRowCount, m_nColumnCount ) ] ); 333 334 m_nColumnCount = nNewColumnCount; 335 m_aData.resize( nNewSize ); 336 m_aData = aNewData; 337 338 // labels 339 if( nAfterIndex < static_cast< sal_Int32 >( m_aColumnLabels.size())) 340 m_aColumnLabels.insert( m_aColumnLabels.begin() + (nAfterIndex + 1), vector< uno::Any >(1) ); 341 342 #if OSL_DEBUG_LEVEL > 2 343 traceData(); 344 #endif 345 } 346 347 sal_Int32 InternalData::appendColumn() 348 { 349 insertColumn( getColumnCount() - 1 ); 350 return getColumnCount() - 1; 351 } 352 353 sal_Int32 InternalData::appendRow() 354 { 355 insertRow( getRowCount() - 1 ); 356 return getRowCount() - 1; 357 } 358 359 void InternalData::insertRow( sal_Int32 nAfterIndex ) 360 { 361 // note: -1 is allowed, as we insert after the given index 362 OSL_ASSERT( nAfterIndex < m_nRowCount && nAfterIndex >= -1 ); 363 if( nAfterIndex >= m_nRowCount || nAfterIndex < -1 ) 364 return; 365 sal_Int32 nNewRowCount = m_nRowCount + 1; 366 sal_Int32 nNewSize( m_nColumnCount * nNewRowCount ); 367 368 double fNan; 369 ::rtl::math::setNan( &fNan ); 370 tDataType aNewData( fNan, nNewSize ); 371 372 // copy old data 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 ) ] ); 377 378 if( nIndex < m_nRowCount ) 379 { 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 ) ] ); 384 } 385 386 m_nRowCount = nNewRowCount; 387 m_aData.resize( nNewSize ); 388 m_aData = aNewData; 389 390 // labels 391 if( nAfterIndex < static_cast< sal_Int32 >( m_aRowLabels.size())) 392 m_aRowLabels.insert( m_aRowLabels.begin() + nIndex, vector< uno::Any > (1)); 393 394 #if OSL_DEBUG_LEVEL > 2 395 traceData(); 396 #endif 397 } 398 399 void InternalData::deleteColumn( sal_Int32 nAtIndex ) 400 { 401 OSL_ASSERT( nAtIndex < m_nColumnCount && nAtIndex >= 0 ); 402 if( nAtIndex >= m_nColumnCount || m_nColumnCount < 1 || nAtIndex < 0 ) 403 return; 404 sal_Int32 nNewColumnCount = m_nColumnCount - 1; 405 sal_Int32 nNewSize( nNewColumnCount * m_nRowCount ); 406 407 double fNan; 408 ::rtl::math::setNan( &fNan ); 409 tDataType aNewData( fNan, nNewSize ); 410 411 // copy old data 412 int nCol=0; 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 ) ] ); 421 422 m_nColumnCount = nNewColumnCount; 423 m_aData.resize( nNewSize ); 424 m_aData = aNewData; 425 426 // labels 427 if( nAtIndex < static_cast< sal_Int32 >( m_aColumnLabels.size())) 428 m_aColumnLabels.erase( m_aColumnLabels.begin() + nAtIndex ); 429 430 #if OSL_DEBUG_LEVEL > 2 431 traceData(); 432 #endif 433 } 434 435 void InternalData::deleteRow( sal_Int32 nAtIndex ) 436 { 437 OSL_ASSERT( nAtIndex < m_nRowCount && nAtIndex >= 0 ); 438 if( nAtIndex >= m_nRowCount || m_nRowCount < 1 || nAtIndex < 0 ) 439 return; 440 sal_Int32 nNewRowCount = m_nRowCount - 1; 441 sal_Int32 nNewSize( m_nColumnCount * nNewRowCount ); 442 443 double fNan; 444 ::rtl::math::setNan( &fNan ); 445 tDataType aNewData( fNan, nNewSize ); 446 447 // copy old data 448 sal_Int32 nIndex = nAtIndex; 449 if( nIndex ) 450 aNewData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] = 451 static_cast< tDataType >( 452 m_aData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] ); 453 454 if( nIndex < nNewRowCount ) 455 { 456 sal_Int32 nRemainingCount = m_nColumnCount * (nNewRowCount - nIndex); 457 aNewData[ ::std::slice( nIndex * m_nColumnCount, nRemainingCount, 1 ) ] = 458 static_cast< tDataType >( 459 m_aData[ ::std::slice( (nIndex + 1) * m_nColumnCount, nRemainingCount, 1 ) ] ); 460 } 461 462 m_nRowCount = nNewRowCount; 463 m_aData.resize( nNewSize ); 464 m_aData = aNewData; 465 466 // labels 467 if( nAtIndex < static_cast< sal_Int32 >( m_aRowLabels.size())) 468 m_aRowLabels.erase( m_aRowLabels.begin() + nAtIndex ); 469 470 #if OSL_DEBUG_LEVEL > 2 471 traceData(); 472 #endif 473 } 474 475 sal_Int32 InternalData::getRowCount() const 476 { 477 return m_nRowCount; 478 } 479 480 sal_Int32 InternalData::getColumnCount() const 481 { 482 return m_nColumnCount; 483 } 484 485 void InternalData::setComplexRowLabels( const vector< vector< uno::Any > >& rNewRowLabels ) 486 { 487 m_aRowLabels = rNewRowLabels; 488 sal_Int32 nNewRowCount = static_cast< sal_Int32 >( m_aRowLabels.size() ); 489 if( nNewRowCount < m_nRowCount ) 490 m_aRowLabels.resize( m_nRowCount ); 491 else 492 enlargeData( 0, nNewRowCount ); 493 } 494 495 vector< vector< uno::Any > > InternalData::getComplexRowLabels() const 496 { 497 return m_aRowLabels; 498 } 499 500 void InternalData::setComplexColumnLabels( const vector< vector< uno::Any > >& rNewColumnLabels ) 501 { 502 m_aColumnLabels = rNewColumnLabels; 503 sal_Int32 nNewColumnCount = static_cast< sal_Int32 >( m_aColumnLabels.size() ); 504 if( nNewColumnCount < m_nColumnCount ) 505 m_aColumnLabels.resize( m_nColumnCount ); 506 else 507 enlargeData( nNewColumnCount, 0 ); 508 } 509 510 vector< vector< uno::Any > > InternalData::getComplexColumnLabels() const 511 { 512 return m_aColumnLabels; 513 } 514 515 #if OSL_DEBUG_LEVEL > 2 516 void InternalData::traceData() const 517 { 518 OSL_TRACE( "InternalData: Data in rows\n" ); 519 520 for( sal_Int32 i=0; i<m_nRowCount; ++i ) 521 { 522 tDataType aSlice( m_aData[ ::std::slice( i*m_nColumnCount, m_nColumnCount, 1 ) ] ); 523 for( sal_Int32 j=0; j<m_nColumnCount; ++j ) 524 OSL_TRACE( "%lf ", aSlice[j] ); 525 OSL_TRACE( "\n" ); 526 } 527 OSL_TRACE( "\n" ); 528 } 529 #endif 530 531 } // namespace chart 532