1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 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. 14 * 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). 20 * 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. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_chart2.hxx" 30 31 #include "InternalData.hxx" 32 #include "ResId.hxx" 33 #include "Strings.hrc" 34 #include "macros.hxx" 35 36 #include <rtl/math.hxx> 37 38 using ::com::sun::star::uno::Sequence; 39 using ::rtl::OUString; 40 41 using namespace ::com::sun::star; 42 using namespace ::std; 43 44 namespace chart 45 { 46 47 // ---------------------------------------- 48 namespace 49 { 50 struct lcl_NumberedStringGenerator 51 { 52 lcl_NumberedStringGenerator( const OUString & rStub, const OUString & rWildcard ) : 53 m_aStub( rStub ), 54 m_nCounter( 0 ), 55 m_nStubStartIndex( rStub.indexOf( rWildcard )), 56 m_nWildcardLength( rWildcard.getLength()) 57 { 58 } 59 vector< uno::Any > operator()() 60 { 61 vector< uno::Any > aRet(1); 62 aRet[0] = uno::makeAny( m_aStub.replaceAt( m_nStubStartIndex, m_nWildcardLength, OUString::valueOf( ++m_nCounter )) ); 63 return aRet; 64 } 65 private: 66 OUString m_aStub; 67 sal_Int32 m_nCounter; 68 const sal_Int32 m_nStubStartIndex; 69 const sal_Int32 m_nWildcardLength; 70 }; 71 72 template< typename T > 73 Sequence< T > lcl_ValarrayToSequence( const ::std::valarray< T > & rValarray ) 74 { 75 // is there a more elegant way of conversion? 76 Sequence< T > aResult( rValarray.size()); 77 for( size_t i = 0; i < rValarray.size(); ++i ) 78 aResult[i] = rValarray[i]; 79 return aResult; 80 } 81 82 } // anonymous namespace 83 // ---------------------------------------- 84 85 InternalData::InternalData() 86 : m_nColumnCount( 0 ) 87 , m_nRowCount( 0 ) 88 , m_aRowLabels( 0 ) 89 , m_aColumnLabels( 0 ) 90 {} 91 92 void InternalData::createDefaultData() 93 { 94 const sal_Int32 nRowCount = 4; 95 const sal_Int32 nColumnCount = 3; 96 97 m_nRowCount = nRowCount; 98 m_nColumnCount = nColumnCount; 99 const sal_Int32 nSize = nColumnCount * nRowCount; 100 // @todo: localize this! 101 const OUString aRowName( ::chart::SchResId::getResString( STR_ROW_LABEL )); 102 const OUString aColName( ::chart::SchResId::getResString( STR_COLUMN_LABEL )); 103 104 const double fDefaultData[ nSize ] = 105 { 9.10, 3.20, 4.54, 106 2.40, 8.80, 9.65, 107 3.10, 1.50, 3.70, 108 4.30, 9.02, 6.20 }; 109 110 m_aData.resize( nSize ); 111 for( sal_Int32 i=0; i<nSize; ++i ) 112 m_aData[i] = fDefaultData[i]; 113 114 m_aRowLabels.clear(); 115 m_aRowLabels.reserve( m_nRowCount ); 116 generate_n( back_inserter( m_aRowLabels ), m_nRowCount, 117 lcl_NumberedStringGenerator( aRowName, C2U("%ROWNUMBER") )); 118 119 m_aColumnLabels.clear(); 120 m_aColumnLabels.reserve( m_nColumnCount ); 121 generate_n( back_inserter( m_aColumnLabels ), m_nColumnCount, 122 lcl_NumberedStringGenerator( aColName, C2U("%COLUMNNUMBER") )); 123 } 124 125 void InternalData::setData( const Sequence< Sequence< double > >& rDataInRows ) 126 { 127 m_nRowCount = rDataInRows.getLength(); 128 m_nColumnCount = (m_nRowCount ? rDataInRows[0].getLength() : 0); 129 130 if( m_aRowLabels.size() != static_cast< sal_uInt32 >( m_nRowCount )) 131 m_aRowLabels.resize( m_nRowCount ); 132 if( m_aColumnLabels.size() != static_cast< sal_uInt32 >( m_nColumnCount )) 133 m_aColumnLabels.resize( m_nColumnCount ); 134 135 m_aData.resize( m_nRowCount * m_nColumnCount ); 136 double fNan; 137 ::rtl::math::setNan( & fNan ); 138 // set all values to Nan 139 m_aData = fNan; 140 141 for( sal_Int32 nRow=0; nRow<m_nRowCount; ++nRow ) 142 { 143 int nDataIdx = nRow*m_nColumnCount; 144 const sal_Int32 nMax = ::std::min( rDataInRows[nRow].getLength(), m_nColumnCount ); 145 for( sal_Int32 nCol=0; nCol < nMax; ++nCol ) 146 { 147 m_aData[nDataIdx] = rDataInRows[nRow][nCol]; 148 nDataIdx += 1; 149 } 150 } 151 } 152 153 Sequence< Sequence< double > > InternalData::getData() const 154 { 155 Sequence< Sequence< double > > aResult( m_nRowCount ); 156 157 for( sal_Int32 i=0; i<m_nRowCount; ++i ) 158 aResult[i] = lcl_ValarrayToSequence< tDataType::value_type >( 159 m_aData[ ::std::slice( i*m_nColumnCount, m_nColumnCount, 1 ) ] ); 160 161 return aResult; 162 } 163 164 Sequence< double > InternalData::getColumnValues( sal_Int32 nColumnIndex ) const 165 { 166 if( nColumnIndex >= 0 && nColumnIndex < m_nColumnCount ) 167 return lcl_ValarrayToSequence< tDataType::value_type >( 168 m_aData[ ::std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ] ); 169 return Sequence< double >(); 170 } 171 Sequence< double > InternalData::getRowValues( sal_Int32 nRowIndex ) const 172 { 173 if( nRowIndex >= 0 && nRowIndex < m_nRowCount ) 174 return lcl_ValarrayToSequence< tDataType::value_type >( 175 m_aData[ ::std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ] ); 176 return Sequence< double >(); 177 } 178 179 void InternalData::setColumnValues( sal_Int32 nColumnIndex, const vector< double > & rNewData ) 180 { 181 if( nColumnIndex < 0 ) 182 return; 183 enlargeData( nColumnIndex + 1, rNewData.size() ); 184 185 tDataType aSlice = m_aData[ ::std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ]; 186 for( vector< double >::size_type i = 0; i < rNewData.size(); ++i ) 187 aSlice[i] = rNewData[i]; 188 m_aData[ ::std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ] = aSlice; 189 } 190 191 void InternalData::setRowValues( sal_Int32 nRowIndex, const vector< double > & rNewData ) 192 { 193 if( nRowIndex < 0 ) 194 return; 195 enlargeData( rNewData.size(), nRowIndex+1 ); 196 197 tDataType aSlice = m_aData[ ::std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ]; 198 for( vector< double >::size_type i = 0; i < rNewData.size(); ++i ) 199 aSlice[i] = rNewData[i]; 200 m_aData[ ::std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ]= aSlice; 201 } 202 203 void InternalData::setComplexColumnLabel( sal_Int32 nColumnIndex, const vector< uno::Any >& rComplexLabel ) 204 { 205 if( nColumnIndex < 0 ) 206 return; 207 if( nColumnIndex >= static_cast< sal_Int32 >( m_aColumnLabels.size() ) ) 208 { 209 m_aColumnLabels.resize(nColumnIndex+1); 210 enlargeData( nColumnIndex+1, 0 ); 211 } 212 m_aColumnLabels[nColumnIndex]=rComplexLabel; 213 } 214 215 void InternalData::setComplexRowLabel( sal_Int32 nRowIndex, const vector< uno::Any >& rComplexLabel ) 216 { 217 if( nRowIndex < 0 ) 218 return; 219 if( nRowIndex >= static_cast< sal_Int32 >( m_aRowLabels.size() ) ) 220 { 221 m_aRowLabels.resize(nRowIndex+1); 222 enlargeData( 0, nRowIndex+1 ); 223 } 224 m_aRowLabels[nRowIndex] = rComplexLabel; 225 } 226 227 vector< uno::Any > InternalData::getComplexColumnLabel( sal_Int32 nColumnIndex ) const 228 { 229 if( nColumnIndex < static_cast< sal_Int32 >( m_aColumnLabels.size() ) ) 230 return m_aColumnLabels[nColumnIndex]; 231 else 232 return vector< uno::Any >(); 233 } 234 vector< uno::Any > InternalData::getComplexRowLabel( sal_Int32 nRowIndex ) const 235 { 236 if( nRowIndex < static_cast< sal_Int32 >( m_aRowLabels.size() ) ) 237 return m_aRowLabels[nRowIndex]; 238 else 239 return vector< uno::Any >(); 240 } 241 242 void InternalData::swapRowWithNext( sal_Int32 nRowIndex ) 243 { 244 if( nRowIndex < m_nRowCount - 1 ) 245 { 246 const sal_Int32 nMax = m_nColumnCount; 247 for( sal_Int32 nColIdx=0; nColIdx<nMax; ++nColIdx ) 248 { 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; 254 } 255 256 vector< uno::Any > aTemp( m_aRowLabels[nRowIndex] ); 257 m_aRowLabels[nRowIndex] = m_aRowLabels[nRowIndex + 1]; 258 m_aRowLabels[nRowIndex + 1] = aTemp; 259 } 260 } 261 262 void InternalData::swapColumnWithNext( sal_Int32 nColumnIndex ) 263 { 264 if( nColumnIndex < m_nColumnCount - 1 ) 265 { 266 const sal_Int32 nMax = m_nRowCount; 267 for( sal_Int32 nRowIdx=0; nRowIdx<nMax; ++nRowIdx ) 268 { 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; 274 } 275 276 vector< uno::Any > aTemp( m_aColumnLabels[nColumnIndex] ); 277 m_aColumnLabels[nColumnIndex] = m_aColumnLabels[nColumnIndex + 1]; 278 m_aColumnLabels[nColumnIndex + 1] = aTemp; 279 } 280 } 281 282 bool InternalData::enlargeData( sal_Int32 nColumnCount, sal_Int32 nRowCount ) 283 { 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 ); 287 288 bool bGrow = (nNewSize > m_nColumnCount*m_nRowCount); 289 290 if( bGrow ) 291 { 292 double fNan; 293 ::rtl::math::setNan( &fNan ); 294 tDataType aNewData( fNan, nNewSize ); 295 // copy old data 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 ) ]; 300 301 m_aData.resize( nNewSize ); 302 m_aData = aNewData; 303 } 304 m_nColumnCount = nNewColumnCount; 305 m_nRowCount = nNewRowCount; 306 return bGrow; 307 } 308 309 void InternalData::insertColumn( sal_Int32 nAfterIndex ) 310 { 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 ) 314 return; 315 sal_Int32 nNewColumnCount = m_nColumnCount + 1; 316 sal_Int32 nNewSize( nNewColumnCount * m_nRowCount ); 317 318 double fNan; 319 ::rtl::math::setNan( &fNan ); 320 tDataType aNewData( fNan, nNewSize ); 321 322 // copy old data 323 int nCol=0; 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 ) ] ); 332 333 m_nColumnCount = nNewColumnCount; 334 m_aData.resize( nNewSize ); 335 m_aData = aNewData; 336 337 // labels 338 if( nAfterIndex < static_cast< sal_Int32 >( m_aColumnLabels.size())) 339 m_aColumnLabels.insert( m_aColumnLabels.begin() + (nAfterIndex + 1), vector< uno::Any >(1) ); 340 341 #if OSL_DEBUG_LEVEL > 2 342 traceData(); 343 #endif 344 } 345 346 sal_Int32 InternalData::appendColumn() 347 { 348 insertColumn( getColumnCount() - 1 ); 349 return getColumnCount() - 1; 350 } 351 352 sal_Int32 InternalData::appendRow() 353 { 354 insertRow( getRowCount() - 1 ); 355 return getRowCount() - 1; 356 } 357 358 void InternalData::insertRow( sal_Int32 nAfterIndex ) 359 { 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 ) 363 return; 364 sal_Int32 nNewRowCount = m_nRowCount + 1; 365 sal_Int32 nNewSize( m_nColumnCount * nNewRowCount ); 366 367 double fNan; 368 ::rtl::math::setNan( &fNan ); 369 tDataType aNewData( fNan, nNewSize ); 370 371 // copy old data 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 ) ] ); 376 377 if( nIndex < m_nRowCount ) 378 { 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 ) ] ); 383 } 384 385 m_nRowCount = nNewRowCount; 386 m_aData.resize( nNewSize ); 387 m_aData = aNewData; 388 389 // labels 390 if( nAfterIndex < static_cast< sal_Int32 >( m_aRowLabels.size())) 391 m_aRowLabels.insert( m_aRowLabels.begin() + nIndex, vector< uno::Any > (1)); 392 393 #if OSL_DEBUG_LEVEL > 2 394 traceData(); 395 #endif 396 } 397 398 void InternalData::deleteColumn( sal_Int32 nAtIndex ) 399 { 400 OSL_ASSERT( nAtIndex < m_nColumnCount && nAtIndex >= 0 ); 401 if( nAtIndex >= m_nColumnCount || m_nColumnCount < 1 || nAtIndex < 0 ) 402 return; 403 sal_Int32 nNewColumnCount = m_nColumnCount - 1; 404 sal_Int32 nNewSize( nNewColumnCount * m_nRowCount ); 405 406 double fNan; 407 ::rtl::math::setNan( &fNan ); 408 tDataType aNewData( fNan, nNewSize ); 409 410 // copy old data 411 int nCol=0; 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 ) ] ); 420 421 m_nColumnCount = nNewColumnCount; 422 m_aData.resize( nNewSize ); 423 m_aData = aNewData; 424 425 // labels 426 if( nAtIndex < static_cast< sal_Int32 >( m_aColumnLabels.size())) 427 m_aColumnLabels.erase( m_aColumnLabels.begin() + nAtIndex ); 428 429 #if OSL_DEBUG_LEVEL > 2 430 traceData(); 431 #endif 432 } 433 434 void InternalData::deleteRow( sal_Int32 nAtIndex ) 435 { 436 OSL_ASSERT( nAtIndex < m_nRowCount && nAtIndex >= 0 ); 437 if( nAtIndex >= m_nRowCount || m_nRowCount < 1 || nAtIndex < 0 ) 438 return; 439 sal_Int32 nNewRowCount = m_nRowCount - 1; 440 sal_Int32 nNewSize( m_nColumnCount * nNewRowCount ); 441 442 double fNan; 443 ::rtl::math::setNan( &fNan ); 444 tDataType aNewData( fNan, nNewSize ); 445 446 // copy old data 447 sal_Int32 nIndex = nAtIndex; 448 if( nIndex ) 449 aNewData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] = 450 static_cast< tDataType >( 451 m_aData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] ); 452 453 if( nIndex < nNewRowCount ) 454 { 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 ) ] ); 459 } 460 461 m_nRowCount = nNewRowCount; 462 m_aData.resize( nNewSize ); 463 m_aData = aNewData; 464 465 // labels 466 if( nAtIndex < static_cast< sal_Int32 >( m_aRowLabels.size())) 467 m_aRowLabels.erase( m_aRowLabels.begin() + nAtIndex ); 468 469 #if OSL_DEBUG_LEVEL > 2 470 traceData(); 471 #endif 472 } 473 474 sal_Int32 InternalData::getRowCount() const 475 { 476 return m_nRowCount; 477 } 478 479 sal_Int32 InternalData::getColumnCount() const 480 { 481 return m_nColumnCount; 482 } 483 484 void InternalData::setComplexRowLabels( const vector< vector< uno::Any > >& rNewRowLabels ) 485 { 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 ); 490 else 491 enlargeData( 0, nNewRowCount ); 492 } 493 494 vector< vector< uno::Any > > InternalData::getComplexRowLabels() const 495 { 496 return m_aRowLabels; 497 } 498 499 void InternalData::setComplexColumnLabels( const vector< vector< uno::Any > >& rNewColumnLabels ) 500 { 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 ); 505 else 506 enlargeData( nNewColumnCount, 0 ); 507 } 508 509 vector< vector< uno::Any > > InternalData::getComplexColumnLabels() const 510 { 511 return m_aColumnLabels; 512 } 513 514 #if OSL_DEBUG_LEVEL > 2 515 void InternalData::traceData() const 516 { 517 OSL_TRACE( "InternalData: Data in rows\n" ); 518 519 for( sal_Int32 i=0; i<m_nRowCount; ++i ) 520 { 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] ); 524 OSL_TRACE( "\n" ); 525 } 526 OSL_TRACE( "\n" ); 527 } 528 #endif 529 530 } // namespace chart 531