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