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 // MARKER(update_precomp.py): autogen include statement, do not remove 23 #include "precompiled_sc.hxx" 24 25 #include "chart2uno.hxx" 26 #include "miscuno.hxx" 27 #include "document.hxx" 28 #include "unoguard.hxx" 29 #include "cell.hxx" 30 #include "chartpos.hxx" 31 #include "unonames.hxx" 32 #include "globstr.hrc" 33 #include "convuno.hxx" 34 #include "rangeutl.hxx" 35 #include "hints.hxx" 36 #include "unoreflist.hxx" 37 #include "compiler.hxx" 38 #include "reftokenhelper.hxx" 39 #include "chartlis.hxx" 40 #include "rangenam.hxx" 41 42 #include <sfx2/objsh.hxx> 43 #include <tools/table.hxx> 44 45 #include <com/sun/star/beans/UnknownPropertyException.hpp> 46 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp> 47 #include <com/sun/star/table/XCellRange.hpp> 48 #include <com/sun/star/table/CellAddress.hpp> 49 #include <com/sun/star/text/XText.hpp> 50 #include <comphelper/extract.hxx> 51 #include <comphelper/processfactory.hxx> 52 53 #include <vector> 54 #include <list> 55 #include <rtl/math.hxx> 56 57 SC_SIMPLE_SERVICE_INFO( ScChart2DataProvider, "ScChart2DataProvider", 58 "com.sun.star.chart2.data.DataProvider") 59 SC_SIMPLE_SERVICE_INFO( ScChart2DataSource, "ScChart2DataSource", 60 "com.sun.star.chart2.data.DataSource") 61 SC_SIMPLE_SERVICE_INFO( ScChart2DataSequence, "ScChart2DataSequence", 62 "com.sun.star.chart2.data.DataSequence") 63 #if USE_CHART2_EMPTYDATASEQUENCE 64 SC_SIMPLE_SERVICE_INFO( ScChart2EmptyDataSequence, "ScChart2EmptyDataSequence", 65 "com.sun.star.chart2.data.DataSequence") 66 #endif 67 68 using namespace ::com::sun::star; 69 using namespace ::formula; 70 using ::rtl::OUString; 71 using ::rtl::OUStringBuffer; 72 using ::com::sun::star::uno::Sequence; 73 using ::com::sun::star::uno::Reference; 74 using ::std::auto_ptr; 75 using ::std::vector; 76 using ::std::list; 77 using ::std::distance; 78 using ::std::unary_function; 79 using ::std::hash_set; 80 using ::boost::shared_ptr; 81 82 namespace 83 { 84 const SfxItemPropertyMapEntry* lcl_GetDataProviderPropertyMap() 85 { 86 static SfxItemPropertyMapEntry aDataProviderPropertyMap_Impl[] = 87 { 88 {MAP_CHAR_LEN(SC_UNONAME_INCLUDEHIDDENCELLS), 0, &getBooleanCppuType(), 0, 0 }, 89 {0,0,0,0,0,0} 90 }; 91 return aDataProviderPropertyMap_Impl; 92 } 93 94 const SfxItemPropertyMapEntry* lcl_GetDataSequencePropertyMap() 95 { 96 static SfxItemPropertyMapEntry aDataSequencePropertyMap_Impl[] = 97 { 98 {MAP_CHAR_LEN(SC_UNONAME_HIDDENVALUES), 0, &getCppuType((uno::Sequence<sal_Int32>*)0 ), 0, 0 }, 99 {MAP_CHAR_LEN(SC_UNONAME_ROLE), 0, &getCppuType((::com::sun::star::chart2::data::DataSequenceRole*)0), 0, 0 }, 100 {MAP_CHAR_LEN(SC_UNONAME_INCLUDEHIDDENCELLS), 0, &getBooleanCppuType(), 0, 0 }, 101 {0,0,0,0,0,0} 102 }; 103 return aDataSequencePropertyMap_Impl; 104 } 105 106 template< typename T > 107 ::com::sun::star::uno::Sequence< T > lcl_VectorToSequence( 108 const ::std::vector< T > & rCont ) 109 { 110 ::com::sun::star::uno::Sequence< T > aResult( rCont.size()); 111 ::std::copy( rCont.begin(), rCont.end(), aResult.getArray()); 112 return aResult; 113 } 114 115 struct lcl_appendTableNumber : public ::std::unary_function< SCTAB, void > 116 { 117 lcl_appendTableNumber( ::rtl::OUStringBuffer & rBuffer ) : 118 m_rBuffer( rBuffer ) 119 {} 120 void operator() ( SCTAB nTab ) 121 { 122 // there is no append with SCTAB or sal_Int16 123 m_rBuffer.append( static_cast< sal_Int32 >( nTab )); 124 m_rBuffer.append( sal_Unicode( ' ' )); 125 } 126 private: 127 ::rtl::OUStringBuffer & m_rBuffer; 128 }; 129 130 ::rtl::OUString lcl_createTableNumberList( const ::std::list< SCTAB > & rTableList ) 131 { 132 ::rtl::OUStringBuffer aBuffer; 133 ::std::for_each( rTableList.begin(), rTableList.end(), lcl_appendTableNumber( aBuffer )); 134 // remove last trailing ' ' 135 if( aBuffer.getLength() > 0 ) 136 aBuffer.setLength( aBuffer.getLength() - 1 ); 137 return aBuffer.makeStringAndClear(); 138 } 139 140 uno::Reference< frame::XModel > lcl_GetXModel( ScDocument * pDoc ) 141 { 142 uno::Reference< frame::XModel > xModel; 143 SfxObjectShell * pObjSh( pDoc ? pDoc->GetDocumentShell() : 0 ); 144 if( pObjSh ) 145 xModel.set( pObjSh->GetModel()); 146 return xModel; 147 } 148 149 uno::Reference< sheet::XSpreadsheetDocument > lcl_GetSpreadSheetDocument( ScDocument * pDoc ) 150 { 151 return uno::Reference< sheet::XSpreadsheetDocument >( lcl_GetXModel( pDoc ), uno::UNO_QUERY ); 152 } 153 154 // ============================================================================ 155 156 namespace { 157 158 struct DeleteInstance : public unary_function<FormulaToken*, void> 159 { 160 void operator() (FormulaToken* p) const 161 { 162 delete p; 163 } 164 }; 165 166 } 167 168 struct TokenTable 169 { 170 SCROW mnRowCount; 171 SCCOL mnColCount; 172 vector<FormulaToken*> maTokens; 173 174 void init( SCCOL nColCount, SCROW nRowCount ) 175 { 176 mnColCount = nColCount; 177 mnRowCount = nRowCount; 178 maTokens.reserve(mnColCount*mnRowCount); 179 } 180 void clear() 181 { 182 for_each(maTokens.begin(), maTokens.end(), DeleteInstance()); 183 } 184 185 void push_back( FormulaToken* pToken ) 186 { 187 maTokens.push_back( pToken ); 188 DBG_ASSERT( maTokens.size()<= static_cast<sal_uInt32>( mnColCount*mnRowCount ), "too much tokens" ); 189 } 190 191 sal_uInt32 getIndex(SCCOL nCol, SCROW nRow) const 192 { 193 DBG_ASSERT( nCol<mnColCount, "wrong column index" ); 194 DBG_ASSERT( nRow<mnRowCount, "wrong row index" ); 195 sal_uInt32 nRet = static_cast<sal_uInt32>(nCol*mnRowCount + nRow); 196 DBG_ASSERT( maTokens.size()>= static_cast<sal_uInt32>( mnColCount*mnRowCount ), "too few tokens" ); 197 return nRet; 198 } 199 200 vector<ScSharedTokenRef>* getColRanges(SCCOL nCol) const; 201 vector<ScSharedTokenRef>* getRowRanges(SCROW nRow) const; 202 vector<ScSharedTokenRef>* getAllRanges() const; 203 }; 204 205 vector<ScSharedTokenRef>* TokenTable::getColRanges(SCCOL nCol) const 206 { 207 if (nCol >= mnColCount) 208 return NULL; 209 if( mnRowCount<=0 ) 210 return NULL; 211 212 auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>); 213 sal_uInt32 nLast = getIndex(nCol, mnRowCount-1); 214 for (sal_uInt32 i = getIndex(nCol, 0); i <= nLast; ++i) 215 { 216 FormulaToken* p = maTokens[i]; 217 if (!p) 218 continue; 219 220 ScSharedTokenRef pCopy(static_cast<ScToken*>(p->Clone())); 221 ScRefTokenHelper::join(*pTokens, pCopy); 222 } 223 return pTokens.release(); 224 } 225 226 vector<ScSharedTokenRef>* TokenTable::getRowRanges(SCROW nRow) const 227 { 228 if (nRow >= mnRowCount) 229 return NULL; 230 if( mnColCount<=0 ) 231 return NULL; 232 233 auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>); 234 sal_uInt32 nLast = getIndex(mnColCount-1, nRow); 235 for (sal_uInt32 i = getIndex(0, nRow); i <= nLast; i += mnRowCount) 236 { 237 FormulaToken* p = maTokens[i]; 238 if (!p) 239 continue; 240 241 ScSharedTokenRef p2(static_cast<ScToken*>(p->Clone())); 242 ScRefTokenHelper::join(*pTokens, p2); 243 } 244 return pTokens.release(); 245 } 246 247 vector<ScSharedTokenRef>* TokenTable::getAllRanges() const 248 { 249 auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>); 250 sal_uInt32 nStop = mnColCount*mnRowCount; 251 for (sal_uInt32 i = 0; i < nStop; i++) 252 { 253 FormulaToken* p = maTokens[i]; 254 if (!p) 255 continue; 256 257 ScSharedTokenRef p2(static_cast<ScToken*>(p->Clone())); 258 ScRefTokenHelper::join(*pTokens, p2); 259 } 260 return pTokens.release(); 261 } 262 263 // ============================================================================ 264 265 class Chart2PositionMap 266 { 267 public: 268 Chart2PositionMap(SCCOL nColCount, SCROW nRowCount, 269 bool bFillRowHeader, bool bFillColumnHeader, Table& rCols, 270 ScDocument* pDoc ); 271 ~Chart2PositionMap(); 272 273 SCCOL getDataColCount() const { return mnDataColCount; } 274 SCROW getDataRowCount() const { return mnDataRowCount; } 275 276 vector<ScSharedTokenRef>* getLeftUpperCornerRanges() const; 277 vector<ScSharedTokenRef>* getAllColHeaderRanges() const; 278 vector<ScSharedTokenRef>* getAllRowHeaderRanges() const; 279 280 vector<ScSharedTokenRef>* getColHeaderRanges(SCCOL nChartCol) const; 281 vector<ScSharedTokenRef>* getRowHeaderRanges(SCROW nChartRow) const; 282 283 vector<ScSharedTokenRef>* getDataColRanges(SCCOL nCol) const; 284 vector<ScSharedTokenRef>* getDataRowRanges(SCROW nRow) const; 285 286 private: 287 SCCOL mnDataColCount; 288 SCROW mnDataRowCount; 289 290 TokenTable maLeftUpperCorner; //nHeaderColCount*nHeaderRowCount 291 TokenTable maColHeaders; //mnDataColCount*nHeaderRowCount 292 TokenTable maRowHeaders; //nHeaderColCount*mnDataRowCount 293 TokenTable maData;//mnDataColCount*mnDataRowCount 294 }; 295 296 Chart2PositionMap::Chart2PositionMap(SCCOL nAllColCount, SCROW nAllRowCount, 297 bool bFillRowHeader, bool bFillColumnHeader, Table& rCols, ScDocument* pDoc) 298 { 299 // if bFillRowHeader is true, at least the first column serves as a row header. 300 // If more than one column is pure text all the first pure text columns are used as header. 301 // Likewise, if bFillColumnHeader is true, at least the first row serves as a column header. 302 // If more than one row is pure text all the first pure text rows are used as header. 303 304 SCROW nHeaderRowCount = (bFillColumnHeader && nAllColCount && nAllRowCount) ? 1 : 0; 305 SCCOL nHeaderColCount = (bFillRowHeader && nAllColCount && nAllRowCount) ? 1 : 0; 306 307 if( nHeaderColCount || nHeaderRowCount ) 308 { 309 const SCCOL nInitialHeaderColCount = nHeaderColCount; 310 //check whether there is more than one text column or row that should be added to the headers 311 SCROW nSmallestValueRowIndex = nAllRowCount; 312 bool bFoundValues = false; 313 bool bFoundAnything = false; 314 Table* pCol = static_cast<Table*>(rCols.First()); 315 for (SCCOL nCol = 0; !bFoundValues && nCol < nAllColCount; ++nCol) 316 { 317 if (pCol && nCol>=nHeaderColCount) 318 { 319 ScToken* pToken = static_cast<ScToken*>(pCol->First()); 320 for (SCROW nRow = 0; !bFoundValues && nRow < nSmallestValueRowIndex; ++nRow) 321 { 322 if (pToken && nRow>=nHeaderRowCount) 323 { 324 ScRange aRange; 325 bool bExternal = false; 326 StackVar eType = pToken->GetType(); 327 if( eType==svExternal || eType==svExternalSingleRef || eType==svExternalDoubleRef || eType==svExternalName ) 328 bExternal = true;//lllll todo correct? 329 ScSharedTokenRef pSharedToken(static_cast<ScToken*>(pToken->Clone())); 330 ScRefTokenHelper::getRangeFromToken(aRange, pSharedToken, bExternal ); 331 SCCOL nCol1=0, nCol2=0; 332 SCROW nRow1=0, nRow2=0; 333 SCTAB nTab1=0, nTab2=0; 334 aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); 335 if (pDoc && pDoc->HasValueData( nCol1, nRow1, nTab1 )) 336 { 337 bFoundValues = bFoundAnything = true; 338 nSmallestValueRowIndex = std::min( nSmallestValueRowIndex, nRow ); 339 } 340 if( !bFoundAnything ) 341 { 342 if (pDoc && pDoc->HasData( nCol1, nRow1, nTab1 ) ) 343 bFoundAnything = true; 344 } 345 } 346 pToken = static_cast<ScToken*>(pCol->Next()); 347 } 348 if(!bFoundValues && nHeaderColCount>0) 349 nHeaderColCount++; 350 } 351 pCol = static_cast<Table*>(rCols.Next()); 352 } 353 if( bFoundAnything ) 354 { 355 if(nHeaderRowCount>0) 356 { 357 if( bFoundValues ) 358 nHeaderRowCount = nSmallestValueRowIndex; 359 else if( nAllRowCount>1 ) 360 nHeaderRowCount = nAllRowCount-1; 361 } 362 } 363 else //if the cells are completely empty, just use single header rows and columns 364 nHeaderColCount = nInitialHeaderColCount; 365 } 366 367 mnDataColCount = nAllColCount - nHeaderColCount; 368 mnDataRowCount = nAllRowCount - nHeaderRowCount; 369 370 maLeftUpperCorner.init(nHeaderColCount,nHeaderRowCount); 371 maColHeaders.init(mnDataColCount,nHeaderRowCount); 372 maRowHeaders.init(nHeaderColCount,mnDataRowCount); 373 maData.init(mnDataColCount,mnDataRowCount); 374 375 Table* pCol = static_cast<Table*>(rCols.First()); 376 FormulaToken* pToken = static_cast<FormulaToken*>(pCol->First()); 377 for (SCCOL nCol = 0; nCol < nAllColCount; ++nCol) 378 { 379 if (pCol) 380 { 381 pToken = static_cast<FormulaToken*>(pCol->First()); 382 for (SCROW nRow = 0; nRow < nAllRowCount; ++nRow) 383 { 384 if( nCol < nHeaderColCount ) 385 { 386 if( nRow < nHeaderRowCount ) 387 maLeftUpperCorner.push_back(pToken); 388 else 389 maRowHeaders.push_back(pToken); 390 } 391 else if( nRow < nHeaderRowCount ) 392 maColHeaders.push_back(pToken); 393 else 394 maData.push_back(pToken); 395 396 pToken = static_cast<FormulaToken*>(pCol->Next()); 397 } 398 } 399 pCol = static_cast<Table*>(rCols.Next()); 400 } 401 } 402 403 Chart2PositionMap::~Chart2PositionMap() 404 { 405 maLeftUpperCorner.clear(); 406 maColHeaders.clear(); 407 maRowHeaders.clear(); 408 maData.clear(); 409 } 410 411 vector<ScSharedTokenRef>* Chart2PositionMap::getLeftUpperCornerRanges() const 412 { 413 return maLeftUpperCorner.getAllRanges(); 414 } 415 vector<ScSharedTokenRef>* Chart2PositionMap::getAllColHeaderRanges() const 416 { 417 return maColHeaders.getAllRanges(); 418 } 419 vector<ScSharedTokenRef>* Chart2PositionMap::getAllRowHeaderRanges() const 420 { 421 return maRowHeaders.getAllRanges(); 422 } 423 vector<ScSharedTokenRef>* Chart2PositionMap::getColHeaderRanges(SCCOL nCol) const 424 { 425 return maColHeaders.getColRanges( nCol); 426 } 427 vector<ScSharedTokenRef>* Chart2PositionMap::getRowHeaderRanges(SCROW nRow) const 428 { 429 return maRowHeaders.getRowRanges( nRow); 430 } 431 432 vector<ScSharedTokenRef>* Chart2PositionMap::getDataColRanges(SCCOL nCol) const 433 { 434 return maData.getColRanges( nCol); 435 } 436 437 vector<ScSharedTokenRef>* Chart2PositionMap::getDataRowRanges(SCROW nRow) const 438 { 439 return maData.getRowRanges( nRow); 440 } 441 442 // ---------------------------------------------------------------------------- 443 444 /** 445 * Designed to be a drop-in replacement for ScChartPositioner, in order to 446 * handle external references. 447 */ 448 class Chart2Positioner 449 { 450 enum GlueType 451 { 452 GLUETYPE_NA, 453 GLUETYPE_NONE, 454 GLUETYPE_COLS, 455 GLUETYPE_ROWS, 456 GLUETYPE_BOTH 457 }; 458 459 public: 460 Chart2Positioner(ScDocument* pDoc, const vector<ScSharedTokenRef>& rRefTokens) : 461 mpRefTokens(new vector<ScSharedTokenRef>(rRefTokens)), 462 mpPositionMap(NULL), 463 meGlue(GLUETYPE_NA), 464 mpDoc(pDoc), 465 mbColHeaders(false), 466 mbRowHeaders(false), 467 mbDummyUpperLeft(false) 468 { 469 } 470 471 ~Chart2Positioner() 472 { 473 } 474 475 void setHeaders(bool bColHeaders, bool bRowHeaders) 476 { 477 mbColHeaders = bColHeaders; 478 mbRowHeaders = bRowHeaders; 479 } 480 481 bool hasColHeaders() const { return mbColHeaders; } 482 bool hasRowHeaders() const { return mbRowHeaders; } 483 484 Chart2PositionMap* getPositionMap() 485 { 486 createPositionMap(); 487 return mpPositionMap.get(); 488 } 489 490 private: 491 Chart2Positioner(); // disabled 492 493 void invalidateGlue(); 494 void glueState(); 495 void createPositionMap(); 496 497 private: 498 shared_ptr< vector<ScSharedTokenRef> > mpRefTokens; 499 auto_ptr<Chart2PositionMap> mpPositionMap; 500 GlueType meGlue; 501 SCCOL mnStartCol; 502 SCROW mnStartRow; 503 ScDocument* mpDoc; 504 bool mbColHeaders:1; 505 bool mbRowHeaders:1; 506 bool mbDummyUpperLeft:1; 507 }; 508 509 void Chart2Positioner::invalidateGlue() 510 { 511 meGlue = GLUETYPE_NA; 512 mpPositionMap.reset(NULL); 513 } 514 515 void Chart2Positioner::glueState() 516 { 517 if (meGlue != GLUETYPE_NA) 518 return; 519 520 mbDummyUpperLeft = false; 521 if (mpRefTokens->size() <= 1) 522 { 523 const ScSharedTokenRef& p = mpRefTokens->front(); 524 ScComplexRefData aData; 525 if (ScRefTokenHelper::getDoubleRefDataFromToken(aData, p)) 526 { 527 if (aData.Ref1.nTab == aData.Ref2.nTab) 528 meGlue = GLUETYPE_NONE; 529 else 530 meGlue = GLUETYPE_COLS; 531 mnStartCol = aData.Ref1.nCol; 532 mnStartRow = aData.Ref1.nRow; 533 } 534 else 535 { 536 invalidateGlue(); 537 mnStartCol = 0; 538 mnStartRow = 0; 539 } 540 return; 541 } 542 543 ScComplexRefData aData; 544 ScRefTokenHelper::getDoubleRefDataFromToken(aData, mpRefTokens->front()); 545 mnStartCol = aData.Ref1.nCol; 546 mnStartRow = aData.Ref1.nRow; 547 548 SCCOL nMaxCols = 0, nEndCol = 0; 549 SCROW nMaxRows = 0, nEndRow = 0; 550 for (vector<ScSharedTokenRef>::const_iterator itr = mpRefTokens->begin(), itrEnd = mpRefTokens->end() 551 ; itr != itrEnd; ++itr) 552 { 553 ScRefTokenHelper::getDoubleRefDataFromToken(aData, *itr); 554 SCCOLROW n1 = aData.Ref1.nCol; 555 SCCOLROW n2 = aData.Ref2.nCol; 556 if (n1 > MAXCOL) 557 n1 = MAXCOL; 558 if (n2 > MAXCOL) 559 n2 = MAXCOL; 560 SCCOLROW nTmp = n2 - n1 + 1; 561 if (n1 < mnStartCol) 562 mnStartCol = static_cast<SCCOL>(n1); 563 if (n2 > nEndCol) 564 nEndCol = static_cast<SCCOL>(n2); 565 if (nTmp > nMaxCols) 566 nMaxCols = static_cast<SCCOL>(nTmp); 567 568 n1 = aData.Ref1.nRow; 569 n2 = aData.Ref2.nRow; 570 if (n1 > MAXROW) 571 n1 = MAXROW; 572 if (n2 > MAXROW) 573 n2 = MAXROW; 574 nTmp = n2 - n1 + 1; 575 576 if (n1 < mnStartRow) 577 mnStartRow = static_cast<SCROW>(n1); 578 if (n2 > nEndRow) 579 nEndRow = static_cast<SCROW>(n2); 580 if (nTmp > nMaxRows) 581 nMaxRows = static_cast<SCROW>(nTmp); 582 } 583 584 // total column size ? 585 SCCOL nC = nEndCol - mnStartCol + 1; 586 if (nC == 1) 587 { 588 meGlue = GLUETYPE_ROWS; 589 return; 590 } 591 // total row size ? 592 SCROW nR = nEndRow - mnStartRow + 1; 593 if (nR == 1) 594 { 595 meGlue = GLUETYPE_COLS; 596 return; 597 } 598 // #i103540# prevent invalid vector size 599 if ((nC <= 0) || (nR <= 0)) 600 { 601 invalidateGlue(); 602 mnStartCol = 0; 603 mnStartRow = 0; 604 return; 605 } 606 sal_uInt32 nCR = static_cast<sal_uInt32>(nC*nR); 607 608 const sal_uInt8 nHole = 0; 609 const sal_uInt8 nOccu = 1; 610 const sal_uInt8 nFree = 2; 611 const sal_uInt8 nGlue = 3; 612 613 vector<sal_uInt8> aCellStates(nCR); 614 for (vector<ScSharedTokenRef>::const_iterator itr = mpRefTokens->begin(), itrEnd = mpRefTokens->end(); 615 itr != itrEnd; ++itr) 616 { 617 ScRefTokenHelper::getDoubleRefDataFromToken(aData, *itr); 618 SCCOL nCol1 = static_cast<SCCOL>(aData.Ref1.nCol) - mnStartCol; 619 SCCOL nCol2 = static_cast<SCCOL>(aData.Ref2.nCol) - mnStartCol; 620 SCROW nRow1 = static_cast<SCROW>(aData.Ref1.nRow) - mnStartRow; 621 SCROW nRow2 = static_cast<SCROW>(aData.Ref2.nRow) - mnStartRow; 622 for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) 623 for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow) 624 { 625 size_t i = nCol*nR + nRow; 626 aCellStates[i] = nOccu; 627 } 628 } 629 bool bGlue = true; 630 631 size_t i = 0; 632 bool bGlueCols = false; 633 for (SCCOL nCol = 0; bGlue && nCol < nC; ++nCol) 634 { 635 for (SCROW nRow = 0; bGlue && nRow < nR; ++nRow) 636 { 637 i = nCol*nR + nRow; 638 if (aCellStates[i] == nOccu) 639 { 640 if (nRow > 0 && nRow > 0) 641 bGlue = false; 642 else 643 nRow = nR; 644 } 645 else 646 aCellStates[i] = nFree; 647 } 648 i = (nCol+1)*nR - 1; // index for the last cell in the column. 649 if (bGlue && (aCellStates[i] == nFree)) 650 { 651 aCellStates[i] = nGlue; 652 bGlueCols = true; 653 } 654 } 655 656 bool bGlueRows = false; 657 for (SCROW nRow = 0; bGlue && nRow < nR; ++nRow) 658 { 659 i = nRow; 660 for (SCCOL nCol = 0; bGlue && nCol < nC; ++nCol, i += nR) 661 { 662 if (aCellStates[i] == nOccu) 663 { 664 if (nCol > 0 && nRow > 0) 665 bGlue = false; 666 else 667 nCol = nC; 668 } 669 else 670 aCellStates[i] = nFree; 671 } 672 i = (nC-1)*nR + nRow; // index for the row position in the last column. 673 if (bGlue && aCellStates[i] == nFree) 674 { 675 aCellStates[i] = nGlue; 676 bGlueRows = true; 677 } 678 } 679 680 i = 1; 681 for (sal_uInt32 n = 1; bGlue && n < nCR; ++n, ++i) 682 if (aCellStates[i] == nHole) 683 bGlue = false; 684 685 if (bGlue) 686 { 687 if (bGlueCols && bGlueRows) 688 meGlue = GLUETYPE_BOTH; 689 else if (bGlueRows) 690 meGlue = GLUETYPE_ROWS; 691 else 692 meGlue = GLUETYPE_COLS; 693 if (aCellStates.front() != nOccu) 694 mbDummyUpperLeft = true; 695 } 696 else 697 meGlue = GLUETYPE_NONE; 698 } 699 700 void Chart2Positioner::createPositionMap() 701 { 702 if (meGlue == GLUETYPE_NA && mpPositionMap.get()) 703 mpPositionMap.reset(NULL); 704 705 if (mpPositionMap.get()) 706 return; 707 708 glueState(); 709 710 bool bNoGlue = (meGlue == GLUETYPE_NONE); 711 auto_ptr<Table> pCols(new Table); 712 auto_ptr<FormulaToken> pNewAddress; 713 auto_ptr<Table> pNewRowTable(new Table); 714 Table* pCol = NULL; 715 SCROW nNoGlueRow = 0; 716 for (vector<ScSharedTokenRef>::const_iterator itr = mpRefTokens->begin(), itrEnd = mpRefTokens->end(); 717 itr != itrEnd; ++itr) 718 { 719 const ScSharedTokenRef& pToken = *itr; 720 721 bool bExternal = ScRefTokenHelper::isExternalRef(pToken); 722 sal_uInt16 nFileId = bExternal ? pToken->GetIndex() : 0; 723 String aTabName = bExternal ? pToken->GetString() : String(); 724 725 ScComplexRefData aData; 726 ScRefTokenHelper::getDoubleRefDataFromToken(aData, *itr); 727 const ScSingleRefData& s = aData.Ref1; 728 const ScSingleRefData& e = aData.Ref2; 729 SCCOL nCol1 = s.nCol, nCol2 = e.nCol; 730 SCROW nRow1 = s.nRow, nRow2 = e.nRow; 731 SCTAB nTab1 = s.nTab, nTab2 = e.nTab; 732 733 for (SCTAB nTab = nTab1; nTab <= nTab2; ++nTab) 734 { 735 // What's this for ??? 736 sal_uInt32 nInsCol = (static_cast<sal_uInt32>(nTab) << 16) | 737 (bNoGlue ? 0 : static_cast<sal_uInt32>(nCol1)); 738 for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol, ++nInsCol) 739 { 740 if (bNoGlue || meGlue == GLUETYPE_ROWS) 741 { 742 pCol = static_cast<Table*>(pCols->Get(nInsCol)); 743 if (!pCol) 744 { 745 pCol = pNewRowTable.get(); 746 pCols->Insert(nInsCol, pNewRowTable.release()); 747 pNewRowTable.reset(new Table); 748 } 749 } 750 else 751 { 752 if (pCols->Insert(nInsCol, pNewRowTable.get())) 753 { 754 pCol = pNewRowTable.release(); 755 pNewRowTable.reset(new Table); 756 } 757 else 758 pCol = static_cast<Table*>(pCols->Get(nInsCol)); 759 } 760 761 sal_uInt32 nInsRow = static_cast<sal_uInt32>(bNoGlue ? nNoGlueRow : nRow1); 762 for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow, ++nInsRow) 763 { 764 ScSingleRefData aCellData; 765 aCellData.InitFlags(); 766 aCellData.SetFlag3D(true); 767 aCellData.SetColRel(false); 768 aCellData.SetRowRel(false); 769 aCellData.SetTabRel(false); 770 aCellData.nCol = nCol; 771 aCellData.nRow = nRow; 772 aCellData.nTab = nTab; 773 774 if (bExternal) 775 pNewAddress.reset(new ScExternalSingleRefToken(nFileId, aTabName, aCellData)); 776 else 777 pNewAddress.reset(new ScSingleRefToken(aCellData)); 778 779 if (pCol->Insert(nInsRow, pNewAddress.get())) 780 pNewAddress.release(); // To prevent the instance from being destroyed. 781 } 782 } 783 } 784 nNoGlueRow += nRow2 - nRow1 + 1; 785 } 786 pNewAddress.reset(NULL); 787 pNewRowTable.reset(NULL); 788 789 bool bFillRowHeader = mbRowHeaders; 790 bool bFillColumnHeader = mbColHeaders; 791 792 SCSIZE nAllColCount = static_cast<SCSIZE>(pCols->Count()); 793 SCSIZE nAllRowCount = 0; 794 pCol = static_cast<Table*>(pCols->First()); 795 if (pCol) 796 { 797 if (mbDummyUpperLeft) 798 pCol->Insert(0, NULL); // Dummy fuer Beschriftung 799 nAllRowCount = static_cast<SCSIZE>(pCol->Count()); 800 } 801 802 if( nAllColCount!=0 && nAllRowCount!=0 ) 803 { 804 if (bNoGlue) 805 { 806 Table* pFirstCol = static_cast<Table*>(pCols->First()); 807 sal_uInt32 nCount = pFirstCol->Count(); 808 pFirstCol->First(); 809 for (sal_uInt32 n = 0; n < nCount; ++n, pFirstCol->Next()) 810 { 811 sal_uInt32 nKey = pFirstCol->GetCurKey(); 812 pCols->First(); 813 for (pCol = static_cast<Table*>(pCols->Next()); pCol; pCol = static_cast<Table*>(pCols->Next())) 814 pCol->Insert(nKey, NULL); 815 } 816 } 817 } 818 mpPositionMap.reset( 819 new Chart2PositionMap( 820 static_cast<SCCOL>(nAllColCount), static_cast<SCROW>(nAllRowCount), 821 bFillRowHeader, bFillColumnHeader, *pCols, mpDoc)); 822 823 // Destroy all column instances. 824 for (pCol = static_cast<Table*>(pCols->First()); pCol; pCol = static_cast<Table*>(pCols->Next())) 825 delete pCol; 826 } 827 828 // ============================================================================ 829 830 /** 831 * Function object to create a range string from a token list. 832 */ 833 class Tokens2RangeString : public unary_function<ScSharedTokenRef, void> 834 { 835 public: 836 Tokens2RangeString(ScDocument* pDoc, FormulaGrammar::Grammar eGram, sal_Unicode cRangeSep) : 837 mpRangeStr(new OUStringBuffer), 838 mpDoc(pDoc), 839 meGrammar(eGram), 840 mcRangeSep(cRangeSep), 841 mbFirst(true) 842 { 843 } 844 845 Tokens2RangeString(const Tokens2RangeString& r) : 846 mpRangeStr(r.mpRangeStr), 847 mpDoc(r.mpDoc), 848 meGrammar(r.meGrammar), 849 mcRangeSep(r.mcRangeSep), 850 mbFirst(r.mbFirst) 851 { 852 } 853 854 void operator() (const ScSharedTokenRef& rToken) 855 { 856 ScCompiler aCompiler(mpDoc, ScAddress(0,0,0)); 857 aCompiler.SetGrammar(meGrammar); 858 String aStr; 859 aCompiler.CreateStringFromToken(aStr, rToken.get()); 860 if (mbFirst) 861 mbFirst = false; 862 else 863 mpRangeStr->append(mcRangeSep); 864 mpRangeStr->append(aStr); 865 } 866 867 void getString(OUString& rStr) 868 { 869 rStr = mpRangeStr->makeStringAndClear(); 870 } 871 872 private: 873 Tokens2RangeString(); // disabled 874 875 private: 876 shared_ptr<OUStringBuffer> mpRangeStr; 877 ScDocument* mpDoc; 878 FormulaGrammar::Grammar meGrammar; 879 sal_Unicode mcRangeSep; 880 bool mbFirst; 881 }; 882 883 /** 884 * Function object to convert a list of tokens into a string form suitable 885 * for ODF export. In ODF, a range is expressed as 886 * 887 * (start cell address):(end cell address) 888 * 889 * and each address doesn't include any '$' symbols. 890 */ 891 class Tokens2RangeStringXML : public unary_function<ScSharedTokenRef, void> 892 { 893 public: 894 Tokens2RangeStringXML(ScDocument* pDoc) : 895 mpRangeStr(new OUStringBuffer), 896 mpDoc(pDoc), 897 mcRangeSep(' '), 898 mcAddrSep(':'), 899 mbFirst(true) 900 { 901 } 902 903 Tokens2RangeStringXML(const Tokens2RangeStringXML& r) : 904 mpRangeStr(r.mpRangeStr), 905 mpDoc(r.mpDoc), 906 mcRangeSep(r.mcRangeSep), 907 mcAddrSep(r.mcAddrSep), 908 mbFirst(r.mbFirst) 909 { 910 } 911 912 void operator() (const ScSharedTokenRef& rToken) 913 { 914 if (mbFirst) 915 mbFirst = false; 916 else 917 mpRangeStr->append(mcRangeSep); 918 919 ScSharedTokenRef aStart, aEnd; 920 splitRangeToken(rToken, aStart, aEnd); 921 ScCompiler aCompiler(mpDoc, ScAddress(0,0,0)); 922 aCompiler.SetGrammar(FormulaGrammar::GRAM_ENGLISH); 923 { 924 String aStr; 925 aCompiler.CreateStringFromToken(aStr, aStart.get()); 926 mpRangeStr->append(aStr); 927 } 928 mpRangeStr->append(mcAddrSep); 929 { 930 String aStr; 931 aCompiler.CreateStringFromToken(aStr, aEnd.get()); 932 mpRangeStr->append(aStr); 933 } 934 } 935 936 void getString(OUString& rStr) 937 { 938 rStr = mpRangeStr->makeStringAndClear(); 939 } 940 941 private: 942 Tokens2RangeStringXML(); // disabled 943 944 void splitRangeToken(const ScSharedTokenRef& pToken, ScSharedTokenRef& rStart, ScSharedTokenRef& rEnd) const 945 { 946 ScComplexRefData aData; 947 ScRefTokenHelper::getDoubleRefDataFromToken(aData, pToken); 948 bool bExternal = ScRefTokenHelper::isExternalRef(pToken); 949 sal_uInt16 nFileId = bExternal ? pToken->GetIndex() : 0; 950 String aTabName = bExternal ? pToken->GetString() : String(); 951 952 // In saving to XML, we don't prepend address with '$'. 953 setRelative(aData.Ref1); 954 setRelative(aData.Ref2); 955 956 // In XML, the end range must explicitly specify sheet name. 957 aData.Ref2.SetFlag3D(true); 958 959 if (bExternal) 960 rStart.reset(new ScExternalSingleRefToken(nFileId, aTabName, aData.Ref1)); 961 else 962 rStart.reset(new ScSingleRefToken(aData.Ref1)); 963 964 if (bExternal) 965 rEnd.reset(new ScExternalSingleRefToken(nFileId, aTabName, aData.Ref2)); 966 else 967 rEnd.reset(new ScSingleRefToken(aData.Ref2)); 968 } 969 970 void setRelative(ScSingleRefData& rData) const 971 { 972 rData.SetColRel(true); 973 rData.SetRowRel(true); 974 rData.SetTabRel(true); 975 } 976 977 private: 978 shared_ptr<OUStringBuffer> mpRangeStr; 979 ScDocument* mpDoc; 980 sal_Unicode mcRangeSep; 981 sal_Unicode mcAddrSep; 982 bool mbFirst; 983 }; 984 985 void lcl_convertTokensToString(OUString& rStr, const vector<ScSharedTokenRef>& rTokens, ScDocument* pDoc) 986 { 987 const sal_Unicode cRangeSep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0); 988 FormulaGrammar::Grammar eGrammar = pDoc->GetGrammar(); 989 Tokens2RangeString func(pDoc, eGrammar, cRangeSep); 990 func = for_each(rTokens.begin(), rTokens.end(), func); 991 func.getString(rStr); 992 } 993 994 } // anonymous namespace 995 996 // DataProvider ============================================================== 997 998 ScChart2DataProvider::ScChart2DataProvider( ScDocument* pDoc ) 999 : m_pDocument( pDoc) 1000 , m_aPropSet(lcl_GetDataProviderPropertyMap()) 1001 , m_bIncludeHiddenCells( sal_True) 1002 { 1003 if ( m_pDocument ) 1004 m_pDocument->AddUnoObject( *this); 1005 } 1006 1007 ScChart2DataProvider::~ScChart2DataProvider() 1008 { 1009 if ( m_pDocument ) 1010 m_pDocument->RemoveUnoObject( *this); 1011 } 1012 1013 1014 void ScChart2DataProvider::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint) 1015 { 1016 if ( rHint.ISA( SfxSimpleHint ) && 1017 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) 1018 { 1019 m_pDocument = NULL; 1020 } 1021 } 1022 1023 ::sal_Bool SAL_CALL ScChart2DataProvider::createDataSourcePossible( const uno::Sequence< beans::PropertyValue >& aArguments ) 1024 throw (uno::RuntimeException) 1025 { 1026 ScUnoGuard aGuard; 1027 if( ! m_pDocument ) 1028 return false; 1029 1030 rtl::OUString aRangeRepresentation; 1031 for(sal_Int32 i = 0; i < aArguments.getLength(); ++i) 1032 { 1033 rtl::OUString sName(aArguments[i].Name); 1034 if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CellRangeRepresentation"))) 1035 { 1036 aArguments[i].Value >>= aRangeRepresentation; 1037 } 1038 } 1039 1040 vector<ScSharedTokenRef> aTokens; 1041 ScRefTokenHelper::compileRangeRepresentation(aTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar()); 1042 return !aTokens.empty(); 1043 } 1044 1045 namespace 1046 { 1047 1048 Reference< chart2::data::XLabeledDataSequence > lcl_createLabeledDataSequenceFromTokens( 1049 auto_ptr< vector< ScSharedTokenRef > > pValueTokens, auto_ptr< vector< ScSharedTokenRef > > pLabelTokens, 1050 ScDocument* pDoc, const Reference< chart2::data::XDataProvider >& xDP, bool bIncludeHiddenCells ) 1051 { 1052 Reference< chart2::data::XLabeledDataSequence > xResult; 1053 bool bHasValues = pValueTokens.get() && !pValueTokens->empty(); 1054 bool bHasLabel = pLabelTokens.get() && !pLabelTokens->empty(); 1055 if( bHasValues || bHasLabel ) 1056 { 1057 try 1058 { 1059 Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); 1060 if ( xContext.is() ) 1061 { 1062 xResult.set( xContext->getServiceManager()->createInstanceWithContext( 1063 ::rtl::OUString::createFromAscii( "com.sun.star.chart2.data.LabeledDataSequence" ), 1064 xContext ), uno::UNO_QUERY_THROW ); 1065 } 1066 if ( bHasValues ) 1067 { 1068 Reference< chart2::data::XDataSequence > xSeq( new ScChart2DataSequence( pDoc, xDP, pValueTokens.release(), bIncludeHiddenCells ) ); 1069 xResult->setValues( xSeq ); 1070 } 1071 if ( bHasLabel ) 1072 { 1073 Reference< chart2::data::XDataSequence > xLabelSeq( new ScChart2DataSequence( pDoc, xDP, pLabelTokens.release(), bIncludeHiddenCells ) ); 1074 xResult->setLabel( xLabelSeq ); 1075 } 1076 } 1077 catch( const uno::Exception& ) 1078 { 1079 } 1080 } 1081 return xResult; 1082 } 1083 1084 //---------------------------------------------------- 1085 /** 1086 * Check the current list of reference tokens, and add the upper left 1087 * corner of the minimum range that encloses all ranges if certain 1088 * conditions are met. 1089 * 1090 * @param rRefTokens list of reference tokens 1091 * 1092 * @return true if the corner was added, false otherwise. 1093 */ 1094 bool lcl_addUpperLeftCornerIfMissing(vector<ScSharedTokenRef>& rRefTokens, 1095 SCROW nCornerRowCount=1, SCCOL nCornerColumnCount=1) 1096 { 1097 using ::std::max; 1098 using ::std::min; 1099 1100 if (rRefTokens.empty()) 1101 return false; 1102 1103 SCCOL nMinCol = MAXCOLCOUNT; 1104 SCROW nMinRow = MAXROWCOUNT; 1105 SCCOL nMaxCol = 0; 1106 SCROW nMaxRow = 0; 1107 SCTAB nTab = 0; 1108 1109 sal_uInt16 nFileId = 0; 1110 String aExtTabName; 1111 bool bExternal = false; 1112 1113 vector<ScSharedTokenRef>::const_iterator itr = rRefTokens.begin(), itrEnd = rRefTokens.end(); 1114 1115 // Get the first ref token. 1116 ScSharedTokenRef pToken = *itr; 1117 switch (pToken->GetType()) 1118 { 1119 case svSingleRef: 1120 { 1121 const ScSingleRefData& rData = pToken->GetSingleRef(); 1122 nMinCol = rData.nCol; 1123 nMinRow = rData.nRow; 1124 nMaxCol = rData.nCol; 1125 nMaxRow = rData.nRow; 1126 nTab = rData.nTab; 1127 } 1128 break; 1129 case svDoubleRef: 1130 { 1131 const ScComplexRefData& rData = pToken->GetDoubleRef(); 1132 nMinCol = min(rData.Ref1.nCol, rData.Ref2.nCol); 1133 nMinRow = min(rData.Ref1.nRow, rData.Ref2.nRow); 1134 nMaxCol = max(rData.Ref1.nCol, rData.Ref2.nCol); 1135 nMaxRow = max(rData.Ref1.nRow, rData.Ref2.nRow); 1136 nTab = rData.Ref1.nTab; 1137 } 1138 break; 1139 case svExternalSingleRef: 1140 { 1141 const ScSingleRefData& rData = pToken->GetSingleRef(); 1142 nMinCol = rData.nCol; 1143 nMinRow = rData.nRow; 1144 nMaxCol = rData.nCol; 1145 nMaxRow = rData.nRow; 1146 nTab = rData.nTab; 1147 nFileId = pToken->GetIndex(); 1148 aExtTabName = pToken->GetString(); 1149 bExternal = true; 1150 } 1151 break; 1152 case svExternalDoubleRef: 1153 { 1154 const ScComplexRefData& rData = pToken->GetDoubleRef(); 1155 nMinCol = min(rData.Ref1.nCol, rData.Ref2.nCol); 1156 nMinRow = min(rData.Ref1.nRow, rData.Ref2.nRow); 1157 nMaxCol = max(rData.Ref1.nCol, rData.Ref2.nCol); 1158 nMaxRow = max(rData.Ref1.nRow, rData.Ref2.nRow); 1159 nTab = rData.Ref1.nTab; 1160 nFileId = pToken->GetIndex(); 1161 aExtTabName = pToken->GetString(); 1162 bExternal = true; 1163 } 1164 break; 1165 default: 1166 ; 1167 } 1168 1169 // Determine the minimum range enclosing all data ranges. Also make sure 1170 // that they are all on the same table. 1171 1172 for (++itr; itr != itrEnd; ++itr) 1173 { 1174 pToken = *itr; 1175 switch (pToken->GetType()) 1176 { 1177 case svSingleRef: 1178 { 1179 const ScSingleRefData& rData = pToken->GetSingleRef(); 1180 1181 nMinCol = min(nMinCol, rData.nCol); 1182 nMinRow = min(nMinRow, rData.nRow); 1183 nMaxCol = max(nMaxCol, rData.nCol); 1184 nMaxRow = max(nMaxRow, rData.nRow); 1185 if (nTab != rData.nTab || bExternal) 1186 return false; 1187 } 1188 break; 1189 case svDoubleRef: 1190 { 1191 const ScComplexRefData& rData = pToken->GetDoubleRef(); 1192 1193 nMinCol = min(nMinCol, rData.Ref1.nCol); 1194 nMinCol = min(nMinCol, rData.Ref2.nCol); 1195 nMinRow = min(nMinRow, rData.Ref1.nRow); 1196 nMinRow = min(nMinRow, rData.Ref2.nRow); 1197 1198 nMaxCol = max(nMaxCol, rData.Ref1.nCol); 1199 nMaxCol = max(nMaxCol, rData.Ref2.nCol); 1200 nMaxRow = max(nMaxRow, rData.Ref1.nRow); 1201 nMaxRow = max(nMaxRow, rData.Ref2.nRow); 1202 1203 if (nTab != rData.Ref1.nTab || bExternal) 1204 return false; 1205 } 1206 break; 1207 case svExternalSingleRef: 1208 { 1209 if (!bExternal) 1210 return false; 1211 1212 if (nFileId != pToken->GetIndex() || aExtTabName != pToken->GetString()) 1213 return false; 1214 1215 const ScSingleRefData& rData = pToken->GetSingleRef(); 1216 1217 nMinCol = min(nMinCol, rData.nCol); 1218 nMinRow = min(nMinRow, rData.nRow); 1219 nMaxCol = max(nMaxCol, rData.nCol); 1220 nMaxRow = max(nMaxRow, rData.nRow); 1221 } 1222 break; 1223 case svExternalDoubleRef: 1224 { 1225 if (!bExternal) 1226 return false; 1227 1228 if (nFileId != pToken->GetIndex() || aExtTabName != pToken->GetString()) 1229 return false; 1230 1231 const ScComplexRefData& rData = pToken->GetDoubleRef(); 1232 1233 nMinCol = min(nMinCol, rData.Ref1.nCol); 1234 nMinCol = min(nMinCol, rData.Ref2.nCol); 1235 nMinRow = min(nMinRow, rData.Ref1.nRow); 1236 nMinRow = min(nMinRow, rData.Ref2.nRow); 1237 1238 nMaxCol = max(nMaxCol, rData.Ref1.nCol); 1239 nMaxCol = max(nMaxCol, rData.Ref2.nCol); 1240 nMaxRow = max(nMaxRow, rData.Ref1.nRow); 1241 nMaxRow = max(nMaxRow, rData.Ref2.nRow); 1242 } 1243 break; 1244 default: 1245 ; 1246 } 1247 } 1248 1249 if (nMinRow >= nMaxRow || nMinCol >= nMaxCol || 1250 nMinRow >= MAXROWCOUNT || nMinCol >= MAXCOLCOUNT || 1251 nMaxRow >= MAXROWCOUNT || nMaxCol >= MAXCOLCOUNT) 1252 { 1253 // Invalid range. Bail out. 1254 return false; 1255 } 1256 1257 // Check if the following conditions are met: 1258 // 1259 // 1) The upper-left corner cell is not included. 1260 // 2) The three adjacent cells of that corner cell are included. 1261 1262 bool bRight = false, bBottom = false, bDiagonal = false; 1263 for (itr = rRefTokens.begin(); itr != itrEnd; ++itr) 1264 { 1265 pToken = *itr; 1266 switch (pToken->GetType()) 1267 { 1268 case svSingleRef: 1269 case svExternalSingleRef: 1270 { 1271 const ScSingleRefData& rData = pToken->GetSingleRef(); 1272 if (rData.nCol == nMinCol && rData.nRow == nMinRow) 1273 // The corner cell is contained. 1274 return false; 1275 1276 if (rData.nCol == nMinCol+nCornerColumnCount && rData.nRow == nMinRow) 1277 bRight = true; 1278 1279 if (rData.nCol == nMinCol && rData.nRow == nMinRow+nCornerRowCount) 1280 bBottom = true; 1281 1282 if (rData.nCol == nMinCol+nCornerColumnCount && rData.nRow == nMinRow+nCornerRowCount) 1283 bDiagonal = true; 1284 } 1285 break; 1286 case svDoubleRef: 1287 case svExternalDoubleRef: 1288 { 1289 const ScComplexRefData& rData = pToken->GetDoubleRef(); 1290 const ScSingleRefData& r1 = rData.Ref1; 1291 const ScSingleRefData& r2 = rData.Ref2; 1292 if (r1.nCol <= nMinCol && nMinCol <= r2.nCol && 1293 r1.nRow <= nMinRow && nMinRow <= r2.nRow) 1294 // The corner cell is contained. 1295 return false; 1296 1297 if (r1.nCol <= nMinCol+nCornerColumnCount && nMinCol+nCornerColumnCount <= r2.nCol && 1298 r1.nRow <= nMinRow && nMinRow <= r2.nRow) 1299 bRight = true; 1300 1301 if (r1.nCol <= nMinCol && nMinCol <= r2.nCol && 1302 r1.nRow <= nMinRow+nCornerRowCount && nMinRow+nCornerRowCount <= r2.nRow) 1303 bBottom = true; 1304 1305 if (r1.nCol <= nMinCol+nCornerColumnCount && nMinCol+nCornerColumnCount <= r2.nCol && 1306 r1.nRow <= nMinRow+nCornerRowCount && nMinRow+nCornerRowCount <= r2.nRow) 1307 bDiagonal = true; 1308 } 1309 break; 1310 default: 1311 ; 1312 } 1313 } 1314 1315 if (!bRight || !bBottom || !bDiagonal) 1316 // Not all the adjacent cells are included. Bail out. 1317 return false; 1318 1319 #if 0 // Do we really need to do this ??? 1320 if (rRefTokens.size() == 2) 1321 { 1322 // Make a simple rectangular range if possible. 1323 ScRange aRightPart(ScAddress(nMinCol+1, nMinRow, nTab), ScAddress(nMaxCol, nMaxRow, nTab)); 1324 ScRange aBottomPart(ScAddress(nMinCol, nMinRow+1, nTab), ScAddress(nMaxCol, nMaxRow, nTab)); 1325 vector<ScRange> aRanges; 1326 aRanges.reserve(2); 1327 aRanges.push_back(aRightPart); 1328 aRanges.push_back(aBottomPart); 1329 if (lcl_isRangeContained(rRefTokens, aRanges)) 1330 { 1331 // Consolidate them into a single rectangle. 1332 ScComplexRefData aData; 1333 aData.InitFlags(); 1334 aData.Ref1.SetFlag3D(true); 1335 aData.Ref1.SetColRel(false); 1336 aData.Ref1.SetRowRel(false); 1337 aData.Ref1.SetTabRel(false); 1338 aData.Ref2.SetColRel(false); 1339 aData.Ref2.SetRowRel(false); 1340 aData.Ref2.SetTabRel(false); 1341 aData.Ref1.nCol = nMinCol; 1342 aData.Ref1.nRow = nMinRow; 1343 aData.Ref1.nTab = nTab; 1344 aData.Ref2.nCol = nMaxCol; 1345 aData.Ref2.nRow = nMaxRow; 1346 aData.Ref2.nTab = nTab; 1347 vector<ScSharedTokenRef> aNewTokens; 1348 aNewTokens.reserve(1); 1349 if (bExternal) 1350 { 1351 ScSharedTokenRef p( 1352 new ScExternalDoubleRefToken(nFileId, aExtTabName, aData)); 1353 aNewTokens.push_back(p); 1354 } 1355 else 1356 { 1357 ScSharedTokenRef p(new ScDoubleRefToken(aData)); 1358 aNewTokens.push_back(p); 1359 } 1360 rRefTokens.swap(aNewTokens); 1361 return true; 1362 } 1363 } 1364 #endif 1365 1366 ScSingleRefData aData; 1367 aData.InitFlags(); 1368 aData.SetFlag3D(true); 1369 aData.SetColRel(false); 1370 aData.SetRowRel(false); 1371 aData.SetTabRel(false); 1372 aData.nCol = nMinCol; 1373 aData.nRow = nMinRow; 1374 aData.nTab = nTab; 1375 1376 if( nCornerRowCount==1 && nCornerColumnCount==1 ) 1377 { 1378 if (bExternal) 1379 { 1380 ScSharedTokenRef pCorner( 1381 new ScExternalSingleRefToken(nFileId, aExtTabName, aData)); 1382 ScRefTokenHelper::join(rRefTokens, pCorner); 1383 } 1384 else 1385 { 1386 ScSharedTokenRef pCorner(new ScSingleRefToken(aData)); 1387 ScRefTokenHelper::join(rRefTokens, pCorner); 1388 } 1389 } 1390 else 1391 { 1392 ScSingleRefData aDataEnd(aData); 1393 aDataEnd.nCol += (nCornerColumnCount-1); 1394 aDataEnd.nRow += (nCornerRowCount-1); 1395 ScComplexRefData r; 1396 r.Ref1=aData; 1397 r.Ref2=aDataEnd; 1398 if (bExternal) 1399 { 1400 ScSharedTokenRef pCorner( 1401 new ScExternalDoubleRefToken(nFileId, aExtTabName, r)); 1402 ScRefTokenHelper::join(rRefTokens, pCorner); 1403 } 1404 else 1405 { 1406 ScSharedTokenRef pCorner(new ScDoubleRefToken(r)); 1407 ScRefTokenHelper::join(rRefTokens, pCorner); 1408 } 1409 } 1410 1411 return true; 1412 } 1413 1414 } 1415 1416 uno::Reference< chart2::data::XDataSource> SAL_CALL 1417 ScChart2DataProvider::createDataSource( 1418 const uno::Sequence< beans::PropertyValue >& aArguments ) 1419 throw( lang::IllegalArgumentException, uno::RuntimeException) 1420 { 1421 ScUnoGuard aGuard; 1422 if ( ! m_pDocument ) 1423 throw uno::RuntimeException(); 1424 1425 uno::Reference< chart2::data::XDataSource> xResult; 1426 bool bLabel = true; 1427 bool bCategories = false; 1428 bool bOrientCol = true; 1429 ::rtl::OUString aRangeRepresentation; 1430 uno::Sequence< sal_Int32 > aSequenceMapping; 1431 for(sal_Int32 i = 0; i < aArguments.getLength(); ++i) 1432 { 1433 rtl::OUString sName(aArguments[i].Name); 1434 if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataRowSource"))) 1435 { 1436 chart::ChartDataRowSource eSource = chart::ChartDataRowSource_COLUMNS; 1437 if( ! (aArguments[i].Value >>= eSource)) 1438 { 1439 sal_Int32 nSource(0); 1440 if( aArguments[i].Value >>= nSource ) 1441 eSource = (static_cast< chart::ChartDataRowSource >( nSource )); 1442 } 1443 bOrientCol = (eSource == chart::ChartDataRowSource_COLUMNS); 1444 } 1445 else if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FirstCellAsLabel"))) 1446 { 1447 bLabel = ::cppu::any2bool(aArguments[i].Value); 1448 } 1449 else if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HasCategories"))) 1450 { 1451 bCategories = ::cppu::any2bool(aArguments[i].Value); 1452 } 1453 else if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CellRangeRepresentation"))) 1454 { 1455 aArguments[i].Value >>= aRangeRepresentation; 1456 } 1457 else if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("SequenceMapping"))) 1458 { 1459 aArguments[i].Value >>= aSequenceMapping; 1460 } 1461 } 1462 1463 vector<ScSharedTokenRef> aRefTokens; 1464 ScRefTokenHelper::compileRangeRepresentation(aRefTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar()); 1465 if (aRefTokens.empty()) 1466 // Invalid range representation. Bail out. 1467 throw lang::IllegalArgumentException(); 1468 1469 if (bLabel) 1470 lcl_addUpperLeftCornerIfMissing(aRefTokens); //#i90669# 1471 1472 bool bColHeaders = (bOrientCol ? bLabel : bCategories ); 1473 bool bRowHeaders = (bOrientCol ? bCategories : bLabel ); 1474 1475 Chart2Positioner aChPositioner(m_pDocument, aRefTokens); 1476 aChPositioner.setHeaders(bColHeaders, bRowHeaders); 1477 1478 const Chart2PositionMap* pChartMap = aChPositioner.getPositionMap(); 1479 if (!pChartMap) 1480 // No chart position map instance. Bail out. 1481 return xResult; 1482 1483 ScChart2DataSource* pDS = NULL; 1484 ::std::list< Reference< chart2::data::XLabeledDataSequence > > aSeqs; 1485 1486 // Fill Categories 1487 if( bCategories ) 1488 { 1489 auto_ptr< vector<ScSharedTokenRef> > pValueTokens(NULL); 1490 if (bOrientCol) 1491 pValueTokens.reset(pChartMap->getAllRowHeaderRanges()); 1492 else 1493 pValueTokens.reset(pChartMap->getAllColHeaderRanges()); 1494 1495 auto_ptr< vector<ScSharedTokenRef> > pLabelTokens(NULL); 1496 pLabelTokens.reset(pChartMap->getLeftUpperCornerRanges()); 1497 1498 Reference< chart2::data::XLabeledDataSequence > xCategories = lcl_createLabeledDataSequenceFromTokens( 1499 pValueTokens, pLabelTokens, m_pDocument, this, m_bIncludeHiddenCells ); //ownership of pointers is transfered! 1500 if ( xCategories.is() ) 1501 { 1502 aSeqs.push_back( xCategories ); 1503 } 1504 } 1505 1506 // Fill Serieses (values and label) 1507 sal_Int32 nCount = bOrientCol ? pChartMap->getDataColCount() : pChartMap->getDataRowCount(); 1508 for (sal_Int32 i = 0; i < nCount; ++i) 1509 { 1510 auto_ptr< vector<ScSharedTokenRef> > pValueTokens(NULL); 1511 auto_ptr< vector<ScSharedTokenRef> > pLabelTokens(NULL); 1512 if (bOrientCol) 1513 { 1514 pValueTokens.reset(pChartMap->getDataColRanges(static_cast<SCCOL>(i))); 1515 pLabelTokens.reset(pChartMap->getColHeaderRanges(static_cast<SCCOL>(i))); 1516 } 1517 else 1518 { 1519 pValueTokens.reset(pChartMap->getDataRowRanges(static_cast<SCROW>(i))); 1520 pLabelTokens.reset(pChartMap->getRowHeaderRanges(static_cast<SCROW>(i))); 1521 } 1522 Reference< chart2::data::XLabeledDataSequence > xChartSeries = lcl_createLabeledDataSequenceFromTokens( 1523 pValueTokens, pLabelTokens, m_pDocument, this, m_bIncludeHiddenCells ); //ownership of pointers is transfered! 1524 if ( xChartSeries.is() ) 1525 { 1526 aSeqs.push_back( xChartSeries ); 1527 } 1528 } 1529 1530 pDS = new ScChart2DataSource(m_pDocument); 1531 ::std::list< Reference< chart2::data::XLabeledDataSequence > >::iterator aItr( aSeqs.begin() ); 1532 ::std::list< Reference< chart2::data::XLabeledDataSequence > >::iterator aEndItr( aSeqs.end() ); 1533 1534 //reorder labeled sequences according to aSequenceMapping 1535 ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aSeqVector; 1536 while(aItr != aEndItr) 1537 { 1538 aSeqVector.push_back(*aItr); 1539 ++aItr; 1540 } 1541 1542 ::std::map< sal_Int32, Reference< chart2::data::XLabeledDataSequence > > aSequenceMap; 1543 for( sal_Int32 nNewIndex = 0; nNewIndex < aSequenceMapping.getLength(); nNewIndex++ ) 1544 { 1545 // note: assuming that the values in the sequence mapping are always non-negative 1546 ::std::vector< Reference< chart2::data::XLabeledDataSequence > >::size_type nOldIndex( static_cast< sal_uInt32 >( aSequenceMapping[nNewIndex] ) ); 1547 if( nOldIndex < aSeqVector.size() ) 1548 { 1549 pDS->AddLabeledSequence( aSeqVector[nOldIndex] ); 1550 aSeqVector[nOldIndex] = 0; 1551 } 1552 } 1553 1554 ::std::vector< Reference< chart2::data::XLabeledDataSequence > >::iterator aVectorItr( aSeqVector.begin() ); 1555 ::std::vector< Reference< chart2::data::XLabeledDataSequence > >::iterator aVectorEndItr( aSeqVector.end() ); 1556 while(aVectorItr != aVectorEndItr) 1557 { 1558 Reference< chart2::data::XLabeledDataSequence > xSeq( *aVectorItr ); 1559 if ( xSeq.is() ) 1560 { 1561 pDS->AddLabeledSequence( xSeq ); 1562 } 1563 ++aVectorItr; 1564 } 1565 1566 xResult.set( pDS ); 1567 return xResult; 1568 } 1569 1570 namespace 1571 { 1572 1573 /** 1574 * Function object to create a list of table numbers from a token list. 1575 */ 1576 class InsertTabNumber : public unary_function<ScSharedTokenRef, void> 1577 { 1578 public: 1579 InsertTabNumber() : 1580 mpTabNumList(new list<SCTAB>()) 1581 { 1582 } 1583 1584 InsertTabNumber(const InsertTabNumber& r) : 1585 mpTabNumList(r.mpTabNumList) 1586 { 1587 } 1588 1589 void operator() (const ScSharedTokenRef& pToken) const 1590 { 1591 if (!ScRefTokenHelper::isRef(pToken)) 1592 return; 1593 1594 const ScSingleRefData& r = pToken->GetSingleRef(); 1595 mpTabNumList->push_back(r.nTab); 1596 } 1597 1598 void getList(list<SCTAB>& rList) 1599 { 1600 mpTabNumList->swap(rList); 1601 } 1602 private: 1603 shared_ptr< list<SCTAB> > mpTabNumList; 1604 }; 1605 1606 class RangeAnalyzer 1607 { 1608 public: 1609 RangeAnalyzer(); 1610 void initRangeAnalyzer( const vector<ScSharedTokenRef>& rTokens ); 1611 void analyzeRange( sal_Int32& rnDataInRows, sal_Int32& rnDataInCols, 1612 bool& rbRowSourceAmbiguous ) const; 1613 bool inSameSingleRow( RangeAnalyzer& rOther ); 1614 bool inSameSingleColumn( RangeAnalyzer& rOther ); 1615 SCROW getRowCount() { return mnRowCount; } 1616 SCCOL getColumnCount() { return mnColumnCount; } 1617 1618 private: 1619 bool mbEmpty; 1620 bool mbAmbiguous; 1621 SCROW mnRowCount; 1622 SCCOL mnColumnCount; 1623 1624 SCCOL mnStartColumn; 1625 SCROW mnStartRow; 1626 }; 1627 1628 RangeAnalyzer::RangeAnalyzer() 1629 : mbEmpty(true) 1630 , mbAmbiguous(false) 1631 , mnRowCount(0) 1632 , mnColumnCount(0) 1633 , mnStartColumn(-1) 1634 , mnStartRow(-1) 1635 { 1636 } 1637 1638 void RangeAnalyzer::initRangeAnalyzer( const vector<ScSharedTokenRef>& rTokens ) 1639 { 1640 mnRowCount=0; 1641 mnColumnCount=0; 1642 mnStartColumn = -1; 1643 mnStartRow = -1; 1644 mbAmbiguous=false; 1645 if( rTokens.empty() ) 1646 { 1647 mbEmpty=true; 1648 return; 1649 } 1650 mbEmpty=false; 1651 1652 vector<ScSharedTokenRef>::const_iterator itr = rTokens.begin(), itrEnd = rTokens.end(); 1653 for (; itr != itrEnd ; ++itr) 1654 { 1655 ScSharedTokenRef aRefToken = *itr; 1656 StackVar eVar = aRefToken->GetType(); 1657 if (eVar == svDoubleRef || eVar == svExternalDoubleRef) 1658 { 1659 const ScComplexRefData& r = aRefToken->GetDoubleRef(); 1660 if (r.Ref1.nTab == r.Ref2.nTab) 1661 { 1662 mnColumnCount = std::max<SCCOL>( mnColumnCount, static_cast<SCCOL>(abs(r.Ref2.nCol - r.Ref1.nCol)+1) ); 1663 mnRowCount = std::max<SCROW>( mnRowCount, static_cast<SCROW>(abs(r.Ref2.nRow - r.Ref1.nRow)+1) ); 1664 if( mnStartColumn == -1 ) 1665 { 1666 mnStartColumn = r.Ref1.nCol; 1667 mnStartRow = r.Ref1.nRow; 1668 } 1669 else 1670 { 1671 if( mnStartColumn != r.Ref1.nCol && mnStartRow != r.Ref1.nRow ) 1672 mbAmbiguous=true; 1673 } 1674 } 1675 else 1676 mbAmbiguous=true; 1677 } 1678 else if (eVar == svSingleRef || eVar == svExternalSingleRef) 1679 { 1680 const ScSingleRefData& r = aRefToken->GetSingleRef(); 1681 mnColumnCount = std::max<SCCOL>( mnColumnCount, 1); 1682 mnRowCount = std::max<SCROW>( mnRowCount, 1); 1683 if( mnStartColumn == -1 ) 1684 { 1685 mnStartColumn = r.nCol; 1686 mnStartRow = r.nRow; 1687 } 1688 else 1689 { 1690 if( mnStartColumn != r.nCol && mnStartRow != r.nRow ) 1691 mbAmbiguous=true; 1692 } 1693 } 1694 else 1695 mbAmbiguous=true; 1696 } 1697 } 1698 1699 void RangeAnalyzer::analyzeRange( sal_Int32& rnDataInRows, 1700 sal_Int32& rnDataInCols, 1701 bool& rbRowSourceAmbiguous ) const 1702 { 1703 if(!mbEmpty && !mbAmbiguous) 1704 { 1705 if( mnRowCount==1 && mnColumnCount>1 ) 1706 ++rnDataInRows; 1707 else if( mnColumnCount==1 && mnRowCount>1 ) 1708 ++rnDataInCols; 1709 else if( mnRowCount>1 && mnColumnCount>1 ) 1710 rbRowSourceAmbiguous = true; 1711 } 1712 else if( !mbEmpty ) 1713 rbRowSourceAmbiguous = true; 1714 } 1715 1716 bool RangeAnalyzer::inSameSingleRow( RangeAnalyzer& rOther ) 1717 { 1718 if( mnStartRow==rOther.mnStartRow && 1719 mnRowCount==1 && rOther.mnRowCount==1 ) 1720 return true; 1721 return false; 1722 } 1723 1724 bool RangeAnalyzer::inSameSingleColumn( RangeAnalyzer& rOther ) 1725 { 1726 if( mnStartColumn==rOther.mnStartColumn && 1727 mnColumnCount==1 && rOther.mnColumnCount==1 ) 1728 return true; 1729 return false; 1730 } 1731 1732 } //end anonymous namespace 1733 1734 uno::Sequence< beans::PropertyValue > SAL_CALL ScChart2DataProvider::detectArguments( 1735 const uno::Reference< chart2::data::XDataSource >& xDataSource ) 1736 throw (uno::RuntimeException) 1737 { 1738 ::std::vector< beans::PropertyValue > aResult; 1739 bool bRowSourceDetected = false; 1740 bool bFirstCellAsLabel = false; 1741 bool bHasCategories = false; 1742 ::rtl::OUString sRangeRep; 1743 1744 bool bHasCategoriesLabels = false; 1745 vector<ScSharedTokenRef> aAllCategoriesValuesTokens; 1746 vector<ScSharedTokenRef> aAllSeriesLabelTokens; 1747 1748 chart::ChartDataRowSource eRowSource = chart::ChartDataRowSource_COLUMNS; 1749 1750 vector<ScSharedTokenRef> aAllTokens; 1751 1752 // parse given data source and collect infos 1753 { 1754 ScUnoGuard aGuard; 1755 DBG_ASSERT( m_pDocument, "No Document -> no detectArguments" ); 1756 if(!m_pDocument ||!xDataSource.is()) 1757 return lcl_VectorToSequence( aResult ); 1758 1759 sal_Int32 nDataInRows = 0; 1760 sal_Int32 nDataInCols = 0; 1761 bool bRowSourceAmbiguous = false; 1762 1763 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( xDataSource->getDataSequences()); 1764 const sal_Int32 nCount( aSequences.getLength()); 1765 RangeAnalyzer aPrevLabel,aPrevValues; 1766 for( sal_Int32 nIdx=0; nIdx<nCount; ++nIdx ) 1767 { 1768 Reference< chart2::data::XLabeledDataSequence > xLS(aSequences[nIdx]); 1769 if( xLS.is() ) 1770 { 1771 bool bThisIsCategories = false; 1772 if(!bHasCategories) 1773 { 1774 Reference< beans::XPropertySet > xSeqProp( xLS->getValues(), uno::UNO_QUERY ); 1775 ::rtl::OUString aRole; 1776 if( xSeqProp.is() && (xSeqProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Role"))) >>= aRole) && 1777 aRole.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("categories")) ) 1778 bThisIsCategories = bHasCategories = true; 1779 } 1780 1781 RangeAnalyzer aLabel,aValues; 1782 // label 1783 Reference< chart2::data::XDataSequence > xLabel( xLS->getLabel()); 1784 if( xLabel.is()) 1785 { 1786 bFirstCellAsLabel = true; 1787 vector<ScSharedTokenRef> aTokens; 1788 ScRefTokenHelper::compileRangeRepresentation( aTokens, xLabel->getSourceRangeRepresentation(), m_pDocument, m_pDocument->GetGrammar() ); 1789 aLabel.initRangeAnalyzer(aTokens); 1790 vector<ScSharedTokenRef>::const_iterator itr = aTokens.begin(), itrEnd = aTokens.end(); 1791 for (; itr != itrEnd; ++itr) 1792 { 1793 ScRefTokenHelper::join(aAllTokens, *itr); 1794 if(!bThisIsCategories) 1795 ScRefTokenHelper::join(aAllSeriesLabelTokens, *itr); 1796 } 1797 if(bThisIsCategories) 1798 bHasCategoriesLabels=true; 1799 } 1800 // values 1801 Reference< chart2::data::XDataSequence > xValues( xLS->getValues()); 1802 if( xValues.is()) 1803 { 1804 vector<ScSharedTokenRef> aTokens; 1805 ScRefTokenHelper::compileRangeRepresentation( aTokens, xValues->getSourceRangeRepresentation(), m_pDocument, m_pDocument->GetGrammar() ); 1806 aValues.initRangeAnalyzer(aTokens); 1807 vector<ScSharedTokenRef>::const_iterator itr = aTokens.begin(), itrEnd = aTokens.end(); 1808 for (; itr != itrEnd; ++itr) 1809 { 1810 ScRefTokenHelper::join(aAllTokens, *itr); 1811 if(bThisIsCategories) 1812 ScRefTokenHelper::join(aAllCategoriesValuesTokens, *itr); 1813 } 1814 } 1815 //detect row source 1816 if(!bThisIsCategories || nCount==1) //categories might span multiple rows *and* columns, so they should be used for detection only if nothing else is available 1817 { 1818 if (!bRowSourceAmbiguous) 1819 { 1820 aValues.analyzeRange(nDataInRows,nDataInCols,bRowSourceAmbiguous); 1821 aLabel.analyzeRange(nDataInRows,nDataInCols,bRowSourceAmbiguous); 1822 if (nDataInRows > 1 && nDataInCols > 1) 1823 bRowSourceAmbiguous = true; 1824 else if( !bRowSourceAmbiguous && !nDataInRows && !nDataInCols ) 1825 { 1826 if( aValues.inSameSingleColumn( aLabel ) ) 1827 nDataInCols++; 1828 else if( aValues.inSameSingleRow( aLabel ) ) 1829 nDataInRows++; 1830 else 1831 { 1832 //#i86188# also detect a single column split into rows correctly 1833 if( aValues.inSameSingleColumn( aPrevValues ) ) 1834 nDataInRows++; 1835 else if( aValues.inSameSingleRow( aPrevValues ) ) 1836 nDataInCols++; 1837 else if( aLabel.inSameSingleColumn( aPrevLabel ) ) 1838 nDataInRows++; 1839 else if( aLabel.inSameSingleRow( aPrevLabel ) ) 1840 nDataInCols++; 1841 } 1842 } 1843 } 1844 } 1845 aPrevValues=aValues; 1846 aPrevLabel=aLabel; 1847 } 1848 } 1849 1850 if (!bRowSourceAmbiguous) 1851 { 1852 bRowSourceDetected = true; 1853 eRowSource = ( nDataInRows > 0 1854 ? chart::ChartDataRowSource_ROWS 1855 : chart::ChartDataRowSource_COLUMNS ); 1856 } 1857 else 1858 { 1859 // set DataRowSource to the better of the two ambiguities 1860 eRowSource = ( nDataInRows > nDataInCols 1861 ? chart::ChartDataRowSource_ROWS 1862 : chart::ChartDataRowSource_COLUMNS ); 1863 } 1864 1865 } 1866 1867 // TableNumberList 1868 { 1869 list<SCTAB> aTableNumList; 1870 InsertTabNumber func; 1871 func = for_each(aAllTokens.begin(), aAllTokens.end(), func); 1872 func.getList(aTableNumList); 1873 aResult.push_back( 1874 beans::PropertyValue( ::rtl::OUString::createFromAscii("TableNumberList"), -1, 1875 uno::makeAny( lcl_createTableNumberList( aTableNumList ) ), 1876 beans::PropertyState_DIRECT_VALUE )); 1877 } 1878 1879 // DataRowSource (calculated before) 1880 if( bRowSourceDetected ) 1881 { 1882 aResult.push_back( 1883 beans::PropertyValue( ::rtl::OUString::createFromAscii("DataRowSource"), -1, 1884 uno::makeAny( eRowSource ), beans::PropertyState_DIRECT_VALUE )); 1885 } 1886 1887 // HasCategories 1888 if( bRowSourceDetected ) 1889 { 1890 aResult.push_back( 1891 beans::PropertyValue( ::rtl::OUString::createFromAscii("HasCategories"), -1, 1892 uno::makeAny( bHasCategories ), beans::PropertyState_DIRECT_VALUE )); 1893 } 1894 1895 // FirstCellAsLabel 1896 if( bRowSourceDetected ) 1897 { 1898 aResult.push_back( 1899 beans::PropertyValue( ::rtl::OUString::createFromAscii("FirstCellAsLabel"), -1, 1900 uno::makeAny( bFirstCellAsLabel ), beans::PropertyState_DIRECT_VALUE )); 1901 } 1902 1903 // Add the left upper corner to the range if it is missing. 1904 if (bRowSourceDetected && bFirstCellAsLabel && bHasCategories && !bHasCategoriesLabels ) 1905 { 1906 RangeAnalyzer aTop,aLeft; 1907 if( eRowSource==chart::ChartDataRowSource_COLUMNS ) 1908 { 1909 aTop.initRangeAnalyzer(aAllSeriesLabelTokens); 1910 aLeft.initRangeAnalyzer(aAllCategoriesValuesTokens); 1911 } 1912 else 1913 { 1914 aTop.initRangeAnalyzer(aAllCategoriesValuesTokens); 1915 aLeft.initRangeAnalyzer(aAllSeriesLabelTokens); 1916 } 1917 lcl_addUpperLeftCornerIfMissing(aAllTokens, aTop.getRowCount(), aLeft.getColumnCount());//e.g. #i91212# 1918 } 1919 1920 // Get range string. 1921 lcl_convertTokensToString(sRangeRep, aAllTokens, m_pDocument); 1922 1923 // add cell range property 1924 aResult.push_back( 1925 beans::PropertyValue( ::rtl::OUString::createFromAscii("CellRangeRepresentation"), -1, 1926 uno::makeAny( sRangeRep ), beans::PropertyState_DIRECT_VALUE )); 1927 1928 //Sequence Mapping 1929 bool bSequencesReordered = true;//todo detect this above or detect this sequence mapping cheaper ... 1930 if( bSequencesReordered && bRowSourceDetected ) 1931 { 1932 bool bDifferentIndexes = false; 1933 1934 std::vector< sal_Int32 > aSequenceMappingVector; 1935 1936 uno::Reference< chart2::data::XDataSource > xCompareDataSource; 1937 try 1938 { 1939 xCompareDataSource.set( this->createDataSource( lcl_VectorToSequence( aResult ) ) ); 1940 } 1941 catch( const lang::IllegalArgumentException & ) 1942 { 1943 // creation of data source to compare didn't work, so we cannot 1944 // create a sequence mapping 1945 } 1946 1947 if( xDataSource.is() && xCompareDataSource.is() ) 1948 { 1949 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence> > aOldSequences( 1950 xCompareDataSource->getDataSequences() ); 1951 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aNewSequences( 1952 xDataSource->getDataSequences()); 1953 1954 rtl::OUString aOldLabel; 1955 rtl::OUString aNewLabel; 1956 rtl::OUString aOldValues; 1957 rtl::OUString aNewValues; 1958 rtl::OUString aEmpty; 1959 1960 for( sal_Int32 nNewIndex = 0; nNewIndex < aNewSequences.getLength(); nNewIndex++ ) 1961 { 1962 uno::Reference< chart2::data::XLabeledDataSequence> xNew( aNewSequences[nNewIndex] ); 1963 for( sal_Int32 nOldIndex = 0; nOldIndex < aOldSequences.getLength(); nOldIndex++ ) 1964 { 1965 uno::Reference< chart2::data::XLabeledDataSequence> xOld( aOldSequences[nOldIndex] ); 1966 1967 if( xOld.is() && xNew.is() ) 1968 { 1969 aOldLabel = aNewLabel = aOldValues = aNewValues = aEmpty; 1970 if( xOld.is() && xOld->getLabel().is() ) 1971 aOldLabel = xOld->getLabel()->getSourceRangeRepresentation(); 1972 if( xNew.is() && xNew->getLabel().is() ) 1973 aNewLabel = xNew->getLabel()->getSourceRangeRepresentation(); 1974 if( xOld.is() && xOld->getValues().is() ) 1975 aOldValues = xOld->getValues()->getSourceRangeRepresentation(); 1976 if( xNew.is() && xNew->getValues().is() ) 1977 aNewValues = xNew->getValues()->getSourceRangeRepresentation(); 1978 1979 if( aOldLabel.equals(aNewLabel) 1980 && ( aOldValues.equals(aNewValues) ) ) 1981 { 1982 if( nOldIndex!=nNewIndex ) 1983 bDifferentIndexes = true; 1984 aSequenceMappingVector.push_back(nOldIndex); 1985 break; 1986 } 1987 } 1988 } 1989 } 1990 } 1991 1992 if( bDifferentIndexes && aSequenceMappingVector.size() ) 1993 { 1994 aResult.push_back( 1995 beans::PropertyValue( ::rtl::OUString::createFromAscii("SequenceMapping"), -1, 1996 uno::makeAny( lcl_VectorToSequence(aSequenceMappingVector) ) 1997 , beans::PropertyState_DIRECT_VALUE )); 1998 } 1999 } 2000 2001 return lcl_VectorToSequence( aResult ); 2002 } 2003 2004 ::sal_Bool SAL_CALL ScChart2DataProvider::createDataSequenceByRangeRepresentationPossible( const ::rtl::OUString& aRangeRepresentation ) 2005 throw (uno::RuntimeException) 2006 { 2007 ScUnoGuard aGuard; 2008 if( ! m_pDocument ) 2009 return false; 2010 2011 vector<ScSharedTokenRef> aTokens; 2012 ScRefTokenHelper::compileRangeRepresentation(aTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar()); 2013 return !aTokens.empty(); 2014 } 2015 2016 uno::Reference< chart2::data::XDataSequence > SAL_CALL 2017 ScChart2DataProvider::createDataSequenceByRangeRepresentation( 2018 const ::rtl::OUString& aRangeRepresentation ) 2019 throw (lang::IllegalArgumentException, 2020 uno::RuntimeException) 2021 { 2022 ScUnoGuard aGuard; 2023 uno::Reference< chart2::data::XDataSequence > xResult; 2024 2025 DBG_ASSERT( m_pDocument, "No Document -> no createDataSequenceByRangeRepresentation" ); 2026 if(!m_pDocument || (aRangeRepresentation.getLength() == 0)) 2027 return xResult; 2028 2029 // Note: the range representation must be in Calc A1 format. The import 2030 // filters use this method to pass data ranges, and they have no idea what 2031 // the current formula syntax is. In the future we should add another 2032 // method to allow the client code to directly pass tokens representing 2033 // ranges. 2034 2035 vector<ScSharedTokenRef> aRefTokens; 2036 ScRefTokenHelper::compileRangeRepresentation(aRefTokens, aRangeRepresentation, m_pDocument); 2037 if (aRefTokens.empty()) // i120962: If haven't get reference, that means aRangeRepresentation is not a simple address, then try formulas 2038 { 2039 ScRangeName aLocalRangeName(*(m_pDocument->GetRangeName())); 2040 sal_uInt16 nCurPos = 0; 2041 sal_Bool bFindName = aLocalRangeName.SearchName(aRangeRepresentation, nCurPos); // Find global name first 2042 2043 for (SCTAB Scope = 0; Scope < MAXTABCOUNT && !bFindName; Scope++ ) // Find name in sheet scope 2044 bFindName = aLocalRangeName.SearchName(aRangeRepresentation, nCurPos, Scope); 2045 2046 if (bFindName) 2047 { 2048 ScRangeData* pData =(ScRangeData*)(aLocalRangeName.At(nCurPos)); 2049 ScTokenArray* pArray = pData->GetCode(); 2050 sal_uInt16 nLen = pArray->GetLen(); 2051 if (!nLen) 2052 ; 2053 else if (nLen == 1) // range names 2054 { 2055 pArray->Reset(); 2056 const FormulaToken* p = pArray->GetNextReference(); 2057 if (p) 2058 aRefTokens.push_back( 2059 ScSharedTokenRef(static_cast<ScToken*>(p->Clone()))); 2060 } 2061 else // formulas 2062 { 2063 String aSymbol; 2064 pData->GetSymbol(aSymbol, FormulaGrammar::GRAM_ENGLISH); 2065 2066 String aFormulaStr('='); 2067 aFormulaStr += aSymbol; 2068 2069 ScAddress aAddr; 2070 ScFormulaCell* pCell = new ScFormulaCell(m_pDocument, aAddr, aFormulaStr, FormulaGrammar::GRAM_ENGLISH); 2071 pCell->Interpret(); 2072 2073 if (pCell->GetValidRefToken()) 2074 { 2075 aRefTokens.push_back( 2076 ScSharedTokenRef(static_cast<ScToken*>(pCell->GetValidRefToken()->Clone()))); 2077 } 2078 2079 DELETEZ( pCell ); 2080 } 2081 } 2082 } 2083 2084 if (aRefTokens.empty()) 2085 return xResult; 2086 2087 // ScChart2DataSequence manages the life cycle of pRefTokens. 2088 vector<ScSharedTokenRef>* pRefTokens = new vector<ScSharedTokenRef>(); 2089 pRefTokens->swap(aRefTokens); 2090 xResult.set(new ScChart2DataSequence(m_pDocument, this, pRefTokens, m_bIncludeHiddenCells)); 2091 2092 return xResult; 2093 } 2094 2095 uno::Reference< sheet::XRangeSelection > SAL_CALL ScChart2DataProvider::getRangeSelection() 2096 throw (uno::RuntimeException) 2097 { 2098 uno::Reference< sheet::XRangeSelection > xResult; 2099 2100 uno::Reference< frame::XModel > xModel( lcl_GetXModel( m_pDocument )); 2101 if( xModel.is()) 2102 xResult.set( xModel->getCurrentController(), uno::UNO_QUERY ); 2103 2104 return xResult; 2105 } 2106 2107 /*uno::Reference< util::XNumberFormatsSupplier > SAL_CALL ScChart2DataProvider::getNumberFormatsSupplier() 2108 throw (uno::RuntimeException) 2109 { 2110 return uno::Reference< util::XNumberFormatsSupplier >( lcl_GetXModel( m_pDocument ), uno::UNO_QUERY ); 2111 }*/ 2112 2113 // XRangeXMLConversion --------------------------------------------------- 2114 2115 rtl::OUString SAL_CALL ScChart2DataProvider::convertRangeToXML( const rtl::OUString& sRangeRepresentation ) 2116 throw ( uno::RuntimeException, lang::IllegalArgumentException ) 2117 { 2118 OUString aRet; 2119 if (!m_pDocument) 2120 return aRet; 2121 2122 if (!sRangeRepresentation.getLength()) 2123 // Empty data range is allowed. 2124 return aRet; 2125 2126 vector<ScSharedTokenRef> aRefTokens; 2127 ScRefTokenHelper::compileRangeRepresentation(aRefTokens, sRangeRepresentation, m_pDocument, m_pDocument->GetGrammar()); 2128 if (aRefTokens.empty()) 2129 throw lang::IllegalArgumentException(); 2130 2131 Tokens2RangeStringXML converter(m_pDocument); 2132 converter = for_each(aRefTokens.begin(), aRefTokens.end(), converter); 2133 converter.getString(aRet); 2134 2135 return aRet; 2136 } 2137 2138 rtl::OUString SAL_CALL ScChart2DataProvider::convertRangeFromXML( const rtl::OUString& sXMLRange ) 2139 throw ( uno::RuntimeException, lang::IllegalArgumentException ) 2140 { 2141 const sal_Unicode cSep = ' '; 2142 const sal_Unicode cQuote = '\''; 2143 2144 if (!m_pDocument) 2145 { 2146 // #i74062# When loading flat XML, this is called before the referenced sheets are in the document, 2147 // so the conversion has to take place directly with the strings, without looking up the sheets. 2148 2149 rtl::OUStringBuffer sRet; 2150 sal_Int32 nOffset = 0; 2151 while( nOffset >= 0 ) 2152 { 2153 rtl::OUString sToken; 2154 ScRangeStringConverter::GetTokenByOffset( sToken, sXMLRange, nOffset, cSep, cQuote ); 2155 if( nOffset >= 0 ) 2156 { 2157 // convert one address (remove dots) 2158 2159 String aUIString(sToken); 2160 2161 sal_Int32 nIndex = ScRangeStringConverter::IndexOf( sToken, ':', 0, cQuote ); 2162 if ( nIndex >= 0 && nIndex < aUIString.Len() - 1 && 2163 aUIString.GetChar((xub_StrLen)nIndex + 1) == (sal_Unicode) '.' ) 2164 aUIString.Erase( (xub_StrLen)nIndex + 1, 1 ); 2165 2166 if ( aUIString.GetChar(0) == (sal_Unicode) '.' ) 2167 aUIString.Erase( 0, 1 ); 2168 2169 if( sRet.getLength() ) 2170 sRet.append( (sal_Unicode) ';' ); 2171 sRet.append( aUIString ); 2172 } 2173 } 2174 2175 return sRet.makeStringAndClear(); 2176 } 2177 2178 OUString aRet; 2179 ScRangeStringConverter::GetStringFromXMLRangeString(aRet, sXMLRange, m_pDocument); 2180 return aRet; 2181 } 2182 2183 // DataProvider XPropertySet ------------------------------------------------- 2184 2185 uno::Reference< beans::XPropertySetInfo> SAL_CALL 2186 ScChart2DataProvider::getPropertySetInfo() throw( uno::RuntimeException) 2187 { 2188 ScUnoGuard aGuard; 2189 static uno::Reference<beans::XPropertySetInfo> aRef = 2190 new SfxItemPropertySetInfo( m_aPropSet.getPropertyMap() ); 2191 return aRef; 2192 } 2193 2194 2195 void SAL_CALL ScChart2DataProvider::setPropertyValue( 2196 const ::rtl::OUString& rPropertyName, const uno::Any& rValue) 2197 throw( beans::UnknownPropertyException, 2198 beans::PropertyVetoException, 2199 lang::IllegalArgumentException, 2200 lang::WrappedTargetException, uno::RuntimeException) 2201 { 2202 if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS))) 2203 { 2204 if ( !(rValue >>= m_bIncludeHiddenCells)) 2205 throw lang::IllegalArgumentException(); 2206 } 2207 else 2208 throw beans::UnknownPropertyException(); 2209 } 2210 2211 2212 uno::Any SAL_CALL ScChart2DataProvider::getPropertyValue( 2213 const ::rtl::OUString& rPropertyName) 2214 throw( beans::UnknownPropertyException, 2215 lang::WrappedTargetException, uno::RuntimeException) 2216 { 2217 uno::Any aRet; 2218 if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS))) 2219 aRet <<= m_bIncludeHiddenCells; 2220 else 2221 throw beans::UnknownPropertyException(); 2222 return aRet; 2223 } 2224 2225 2226 void SAL_CALL ScChart2DataProvider::addPropertyChangeListener( 2227 const ::rtl::OUString& /*rPropertyName*/, 2228 const uno::Reference< beans::XPropertyChangeListener>& /*xListener*/) 2229 throw( beans::UnknownPropertyException, 2230 lang::WrappedTargetException, uno::RuntimeException) 2231 { 2232 OSL_ENSURE( false, "Not yet implemented" ); 2233 } 2234 2235 2236 void SAL_CALL ScChart2DataProvider::removePropertyChangeListener( 2237 const ::rtl::OUString& /*rPropertyName*/, 2238 const uno::Reference< beans::XPropertyChangeListener>& /*rListener*/) 2239 throw( beans::UnknownPropertyException, 2240 lang::WrappedTargetException, uno::RuntimeException) 2241 { 2242 OSL_ENSURE( false, "Not yet implemented" ); 2243 } 2244 2245 2246 void SAL_CALL ScChart2DataProvider::addVetoableChangeListener( 2247 const ::rtl::OUString& /*rPropertyName*/, 2248 const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/) 2249 throw( beans::UnknownPropertyException, 2250 lang::WrappedTargetException, uno::RuntimeException) 2251 { 2252 OSL_ENSURE( false, "Not yet implemented" ); 2253 } 2254 2255 2256 void SAL_CALL ScChart2DataProvider::removeVetoableChangeListener( 2257 const ::rtl::OUString& /*rPropertyName*/, 2258 const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/ ) 2259 throw( beans::UnknownPropertyException, 2260 lang::WrappedTargetException, uno::RuntimeException) 2261 { 2262 OSL_ENSURE( false, "Not yet implemented" ); 2263 } 2264 2265 // DataSource ================================================================ 2266 2267 ScChart2DataSource::ScChart2DataSource( ScDocument* pDoc) 2268 : m_pDocument( pDoc) 2269 { 2270 if ( m_pDocument ) 2271 m_pDocument->AddUnoObject( *this); 2272 } 2273 2274 2275 ScChart2DataSource::~ScChart2DataSource() 2276 { 2277 if ( m_pDocument ) 2278 m_pDocument->RemoveUnoObject( *this); 2279 } 2280 2281 2282 void ScChart2DataSource::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint) 2283 { 2284 if ( rHint.ISA( SfxSimpleHint ) && 2285 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) 2286 { 2287 m_pDocument = NULL; 2288 } 2289 } 2290 2291 2292 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence> > SAL_CALL 2293 ScChart2DataSource::getDataSequences() throw ( uno::RuntimeException) 2294 { 2295 ScUnoGuard aGuard; 2296 2297 LabeledList::const_iterator aItr(m_aLabeledSequences.begin()); 2298 LabeledList::const_iterator aEndItr(m_aLabeledSequences.end()); 2299 2300 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aRet(m_aLabeledSequences.size()); 2301 2302 sal_Int32 i = 0; 2303 while (aItr != aEndItr) 2304 { 2305 aRet[i] = *aItr; 2306 ++i; 2307 ++aItr; 2308 } 2309 2310 return aRet; 2311 2312 /* typedef ::std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > tVec; 2313 tVec aVec; 2314 bool bSeries = false; 2315 // split into columns - FIXME: different if GlueState() is used 2316 for ( ScRangePtr p = m_xRanges->First(); p; p = m_xRanges->Next()) 2317 { 2318 for ( SCCOL nCol = p->aStart.Col(); nCol <= p->aEnd.Col(); ++nCol) 2319 { 2320 uno::Reference< chart2::data::XLabeledDataSequence > xLabeledSeq( 2321 new ScChart2LabeledDataSequence( m_pDocument)); 2322 if( xLabeledSeq.is()) 2323 { 2324 aVec.push_back( xLabeledSeq ); 2325 if( bSeries ) 2326 { 2327 ScRangeListRef aColRanges = new ScRangeList; 2328 // one single sheet selected assumed for now 2329 aColRanges->Append( ScRange( nCol, p->aStart.Row(), 2330 p->aStart.Tab(), nCol, p->aStart.Row(), 2331 p->aStart.Tab())); 2332 // TEST: add range two times, once as label, once as data 2333 // TODO: create pure Numerical and Text sequences if possible 2334 uno::Reference< chart2::data::XDataSequence > xLabel( 2335 new ScChart2DataSequence( m_pDocument, aColRanges)); 2336 2337 // set role 2338 uno::Reference< beans::XPropertySet > xProp( xLabel, uno::UNO_QUERY ); 2339 if( xProp.is()) 2340 xProp->setPropertyValue( 2341 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )), 2342 ::uno::makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "label" )))); 2343 2344 xLabeledSeq->setLabel( xLabel ); 2345 } 2346 2347 ScRangeListRef aColRanges = new ScRangeList; 2348 2349 // one single sheet selected assumed for now 2350 aColRanges->Append( ScRange( nCol, p->aStart.Row() + 1, 2351 p->aStart.Tab(), nCol, p->aEnd.Row(), 2352 p->aStart.Tab())); 2353 uno::Reference< chart2::data::XDataSequence > xData( 2354 new ScChart2DataSequence( m_pDocument, aColRanges)); 2355 2356 // set role 2357 uno::Reference< beans::XPropertySet > xProp( xData, uno::UNO_QUERY ); 2358 if( xProp.is()) 2359 xProp->setPropertyValue( 2360 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )), 2361 ::uno::makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "values" )))); 2362 2363 xLabeledSeq->setValues( xData ); 2364 2365 bSeries = true; 2366 } 2367 } 2368 } 2369 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence> > aSequences( 2370 aVec.size()); 2371 uno::Reference< chart2::data::XLabeledDataSequence> * pArr = aSequences.getArray(); 2372 sal_Int32 j = 0; 2373 for ( tVec::const_iterator iSeq = aVec.begin(); iSeq != aVec.end(); 2374 ++iSeq, ++j) 2375 { 2376 pArr[j] = *iSeq; 2377 } 2378 return aSequences;*/ 2379 } 2380 2381 void ScChart2DataSource::AddLabeledSequence(const uno::Reference < chart2::data::XLabeledDataSequence >& xNew) 2382 { 2383 m_aLabeledSequences.push_back(xNew); 2384 } 2385 2386 2387 // DataSequence ============================================================== 2388 2389 ScChart2DataSequence::Item::Item() : 2390 mfValue(0.0), mbIsValue(false) 2391 { 2392 ::rtl::math::setNan(&mfValue); 2393 } 2394 2395 ScChart2DataSequence::HiddenRangeListener::HiddenRangeListener(ScChart2DataSequence& rParent) : 2396 mrParent(rParent) 2397 { 2398 } 2399 2400 ScChart2DataSequence::HiddenRangeListener::~HiddenRangeListener() 2401 { 2402 } 2403 2404 void ScChart2DataSequence::HiddenRangeListener::notify() 2405 { 2406 mrParent.setDataChangedHint(true); 2407 } 2408 2409 ScChart2DataSequence::ScChart2DataSequence( ScDocument* pDoc, 2410 const uno::Reference < chart2::data::XDataProvider >& xDP, 2411 vector<ScSharedTokenRef>* pTokens, 2412 bool bIncludeHiddenCells ) 2413 : m_bIncludeHiddenCells( bIncludeHiddenCells) 2414 , m_nObjectId( 0 ) 2415 , m_pDocument( pDoc) 2416 , m_pTokens(pTokens) 2417 , m_pRangeIndices(NULL) 2418 , m_pExtRefListener(NULL) 2419 , m_xDataProvider( xDP) 2420 , m_aPropSet(lcl_GetDataSequencePropertyMap()) 2421 , m_pHiddenListener(NULL) 2422 , m_pValueListener( NULL ) 2423 , m_bGotDataChangedHint(false) 2424 , m_bExtDataRebuildQueued(false) 2425 { 2426 DBG_ASSERT(pTokens, "reference token list is null"); 2427 2428 if ( m_pDocument ) 2429 { 2430 m_pDocument->AddUnoObject( *this); 2431 m_nObjectId = m_pDocument->GetNewUnoId(); 2432 } 2433 // FIXME: real implementation of identifier and it's mapping to ranges. 2434 // Reuse ScChartListener? 2435 2436 // BM: don't use names of named ranges but the UI range strings 2437 // String aStr; 2438 // rRangeList->Format( aStr, SCR_ABS_3D, m_pDocument ); 2439 // m_aIdentifier = ::rtl::OUString( aStr ); 2440 2441 // m_aIdentifier = ::rtl::OUString::createFromAscii( "ID_"); 2442 // static sal_Int32 nID = 0; 2443 // m_aIdentifier += ::rtl::OUString::valueOf( ++nID); 2444 } 2445 2446 ScChart2DataSequence::~ScChart2DataSequence() 2447 { 2448 if ( m_pDocument ) 2449 { 2450 m_pDocument->RemoveUnoObject( *this); 2451 if (m_pHiddenListener.get()) 2452 { 2453 ScChartListenerCollection* pCLC = m_pDocument->GetChartListenerCollection(); 2454 if (pCLC) 2455 pCLC->EndListeningHiddenRange(m_pHiddenListener.get()); 2456 } 2457 StopListeningToAllExternalRefs(); 2458 } 2459 2460 delete m_pValueListener; 2461 } 2462 2463 void ScChart2DataSequence::RefChanged() 2464 { 2465 if( m_pValueListener && m_aValueListeners.Count() != 0 ) 2466 { 2467 m_pValueListener->EndListeningAll(); 2468 2469 if( m_pDocument ) 2470 { 2471 ScChartListenerCollection* pCLC = NULL; 2472 if (m_pHiddenListener.get()) 2473 { 2474 pCLC = m_pDocument->GetChartListenerCollection(); 2475 if (pCLC) 2476 pCLC->EndListeningHiddenRange(m_pHiddenListener.get()); 2477 } 2478 2479 vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end(); 2480 for (; itr != itrEnd; ++itr) 2481 { 2482 ScRange aRange; 2483 if (!ScRefTokenHelper::getRangeFromToken(aRange, *itr)) 2484 continue; 2485 2486 m_pDocument->StartListeningArea(aRange, m_pValueListener); 2487 if (pCLC) 2488 pCLC->StartListeningHiddenRange(aRange, m_pHiddenListener.get()); 2489 } 2490 } 2491 } 2492 } 2493 2494 void ScChart2DataSequence::BuildDataCache() 2495 { 2496 m_bExtDataRebuildQueued = false; 2497 2498 if (!m_aDataArray.empty()) 2499 return; 2500 2501 if (!m_pTokens.get()) 2502 { 2503 DBG_ERROR("m_pTokens == NULL! Something is wrong."); 2504 return; 2505 } 2506 2507 StopListeningToAllExternalRefs(); 2508 2509 ::std::list<sal_Int32> aHiddenValues; 2510 sal_Int32 nDataCount = 0; 2511 sal_Int32 nHiddenValueCount = 0; 2512 2513 for (vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end(); 2514 itr != itrEnd; ++itr) 2515 { 2516 if (ScRefTokenHelper::isExternalRef(*itr)) 2517 { 2518 nDataCount += FillCacheFromExternalRef(*itr); 2519 } 2520 else 2521 { 2522 ScRange aRange; 2523 if (!ScRefTokenHelper::getRangeFromToken(aRange, *itr)) 2524 continue; 2525 2526 SCCOL nLastCol = -1; 2527 SCROW nLastRow = -1; 2528 for (SCTAB nTab = aRange.aStart.Tab(); nTab <= aRange.aEnd.Tab(); ++nTab) 2529 { 2530 for (SCCOL nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol) 2531 { 2532 for (SCROW nRow = aRange.aStart.Row(); nRow <= aRange.aEnd.Row(); ++nRow) 2533 { 2534 bool bColHidden = m_pDocument->ColHidden(nCol, nTab, nLastCol); 2535 bool bRowHidden = m_pDocument->RowHidden(nRow, nTab, nLastRow); 2536 2537 if (bColHidden || bRowHidden) 2538 { 2539 // hidden cell 2540 ++nHiddenValueCount; 2541 aHiddenValues.push_back(nDataCount-1); 2542 2543 if( !m_bIncludeHiddenCells ) 2544 continue; 2545 } 2546 2547 m_aDataArray.push_back(Item()); 2548 Item& rItem = m_aDataArray.back(); 2549 ++nDataCount; 2550 2551 ScAddress aAdr(nCol, nRow, nTab); 2552 ScBaseCell* pCell = m_pDocument->GetCell(aAdr); 2553 if (!pCell) 2554 continue; 2555 2556 if (pCell->HasStringData()) 2557 rItem.maString = pCell->GetStringData(); 2558 else 2559 { 2560 String aStr; 2561 m_pDocument->GetString(nCol, nRow, nTab, aStr); 2562 rItem.maString = aStr; 2563 } 2564 2565 switch (pCell->GetCellType()) 2566 { 2567 case CELLTYPE_VALUE: 2568 rItem.mfValue = static_cast< ScValueCell*>(pCell)->GetValue(); 2569 rItem.mbIsValue = true; 2570 break; 2571 case CELLTYPE_FORMULA: 2572 { 2573 ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell); 2574 sal_uInt16 nErr = pFCell->GetErrCode(); 2575 if (nErr) 2576 break; 2577 2578 if (pFCell->HasValueData()) 2579 { 2580 rItem.mfValue = pFCell->GetValue(); 2581 rItem.mbIsValue = true; 2582 } 2583 } 2584 break; 2585 #if DBG_UTIL 2586 case CELLTYPE_DESTROYED: 2587 #endif 2588 case CELLTYPE_EDIT: 2589 case CELLTYPE_NONE: 2590 case CELLTYPE_NOTE: 2591 case CELLTYPE_STRING: 2592 case CELLTYPE_SYMBOLS: 2593 default: 2594 ; // do nothing 2595 } 2596 } 2597 } 2598 } 2599 } 2600 } 2601 2602 // convert the hidden cell list to sequence. 2603 m_aHiddenValues.realloc(nHiddenValueCount); 2604 sal_Int32* pArr = m_aHiddenValues.getArray(); 2605 ::std::list<sal_Int32>::const_iterator itr = aHiddenValues.begin(), itrEnd = aHiddenValues.end(); 2606 for (;itr != itrEnd; ++itr, ++pArr) 2607 *pArr = *itr; 2608 2609 // Clear the data series cache when the array is re-built. 2610 m_aMixedDataCache.realloc(0); 2611 } 2612 2613 void ScChart2DataSequence::RebuildDataCache() 2614 { 2615 if (!m_bExtDataRebuildQueued) 2616 { 2617 m_aDataArray.clear(); 2618 m_pDocument->BroadcastUno(ScHint(SC_HINT_DATACHANGED, ScAddress(), NULL)); 2619 m_bExtDataRebuildQueued = true; 2620 m_bGotDataChangedHint = true; 2621 } 2622 } 2623 2624 sal_Int32 ScChart2DataSequence::FillCacheFromExternalRef(const ScSharedTokenRef& pToken) 2625 { 2626 ScExternalRefManager* pRefMgr = m_pDocument->GetExternalRefManager(); 2627 ScRange aRange; 2628 if (!ScRefTokenHelper::getRangeFromToken(aRange, pToken, true)) 2629 return 0; 2630 2631 sal_uInt16 nFileId = pToken->GetIndex(); 2632 const String& rTabName = pToken->GetString(); 2633 ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(nFileId, rTabName, aRange, NULL); 2634 if (!pArray) 2635 // no external data exists for this range. 2636 return 0; 2637 2638 // Start listening for this external document. 2639 ExternalRefListener* pExtRefListener = GetExtRefListener(); 2640 pRefMgr->addLinkListener(nFileId, pExtRefListener); 2641 pExtRefListener->addFileId(nFileId); 2642 2643 ScExternalRefCache::TableTypeRef pTable = pRefMgr->getCacheTable(nFileId, rTabName, false, NULL); 2644 sal_Int32 nDataCount = 0; 2645 for (FormulaToken* p = pArray->First(); p; p = pArray->Next()) 2646 { 2647 // Cached external range is always represented as a single 2648 // matrix token, although that might change in the future when 2649 // we introduce a new token type to store multi-table range 2650 // data. 2651 2652 if (p->GetType() != svMatrix) 2653 { 2654 DBG_ERROR("Cached array is not a matrix token."); 2655 continue; 2656 } 2657 2658 const ScMatrix* pMat = static_cast<ScToken*>(p)->GetMatrix(); 2659 SCSIZE nCSize, nRSize; 2660 pMat->GetDimensions(nCSize, nRSize); 2661 for (SCSIZE nC = 0; nC < nCSize; ++nC) 2662 { 2663 for (SCSIZE nR = 0; nR < nRSize; ++nR) 2664 { 2665 if (pMat->IsValue(nC, nR) || pMat->IsBoolean(nC, nR)) 2666 { 2667 m_aDataArray.push_back(Item()); 2668 Item& rItem = m_aDataArray.back(); 2669 ++nDataCount; 2670 2671 rItem.mbIsValue = true; 2672 rItem.mfValue = pMat->GetDouble(nC, nR); 2673 2674 SvNumberFormatter* pFormatter = m_pDocument->GetFormatTable(); 2675 if (pFormatter) 2676 { 2677 String aStr; 2678 const double fVal = rItem.mfValue; 2679 Color* pColor = NULL; 2680 sal_uInt32 nFmt = 0; 2681 if (pTable) 2682 { 2683 // Get the correct format index from the cache. 2684 SCCOL nCol = aRange.aStart.Col() + static_cast<SCCOL>(nC); 2685 SCROW nRow = aRange.aStart.Row() + static_cast<SCROW>(nR); 2686 pTable->getCell(nCol, nRow, &nFmt); 2687 } 2688 pFormatter->GetOutputString(fVal, nFmt, aStr, &pColor); 2689 rItem.maString = aStr; 2690 } 2691 } 2692 else if (pMat->IsString(nC, nR)) 2693 { 2694 m_aDataArray.push_back(Item()); 2695 Item& rItem = m_aDataArray.back(); 2696 ++nDataCount; 2697 2698 rItem.mbIsValue = false; 2699 rItem.maString = pMat->GetString(nC, nR); 2700 } 2701 } 2702 } 2703 } 2704 return nDataCount; 2705 } 2706 2707 void ScChart2DataSequence::UpdateTokensFromRanges(const ScRangeList& rRanges) 2708 { 2709 if (!m_pRangeIndices.get()) 2710 return; 2711 2712 sal_uInt32 nCount = rRanges.Count(); 2713 for (sal_uInt32 i = 0; i < nCount; ++i) 2714 { 2715 ScSharedTokenRef pToken; 2716 ScRange* pRange = static_cast<ScRange*>(rRanges.GetObject(i)); 2717 DBG_ASSERT(pRange, "range object is NULL."); 2718 2719 ScRefTokenHelper::getTokenFromRange(pToken, *pRange); 2720 sal_uInt32 nOrigPos = (*m_pRangeIndices)[i]; 2721 (*m_pTokens)[nOrigPos] = pToken; 2722 } 2723 2724 RefChanged(); 2725 2726 // any change of the range address is broadcast to value (modify) listeners 2727 if ( m_aValueListeners.Count() ) 2728 m_bGotDataChangedHint = true; 2729 } 2730 2731 ScChart2DataSequence::ExternalRefListener* ScChart2DataSequence::GetExtRefListener() 2732 { 2733 if (!m_pExtRefListener.get()) 2734 m_pExtRefListener.reset(new ExternalRefListener(*this, m_pDocument)); 2735 2736 return m_pExtRefListener.get(); 2737 } 2738 2739 void ScChart2DataSequence::StopListeningToAllExternalRefs() 2740 { 2741 if (!m_pExtRefListener.get()) 2742 return; 2743 2744 const hash_set<sal_uInt16>& rFileIds = m_pExtRefListener->getAllFileIds(); 2745 hash_set<sal_uInt16>::const_iterator itr = rFileIds.begin(), itrEnd = rFileIds.end(); 2746 ScExternalRefManager* pRefMgr = m_pDocument->GetExternalRefManager(); 2747 for (; itr != itrEnd; ++itr) 2748 pRefMgr->removeLinkListener(*itr, m_pExtRefListener.get()); 2749 2750 m_pExtRefListener.reset(NULL); 2751 } 2752 2753 void ScChart2DataSequence::CopyData(const ScChart2DataSequence& r) 2754 { 2755 if (!m_pDocument) 2756 { 2757 DBG_ERROR("document instance is NULL!?"); 2758 return; 2759 } 2760 2761 list<Item> aDataArray(r.m_aDataArray); 2762 m_aDataArray.swap(aDataArray); 2763 2764 m_aHiddenValues = r.m_aHiddenValues; 2765 m_aRole = r.m_aRole; 2766 2767 if (r.m_pRangeIndices.get()) 2768 m_pRangeIndices.reset(new vector<sal_uInt32>(*r.m_pRangeIndices)); 2769 2770 if (r.m_pExtRefListener.get()) 2771 { 2772 // Re-register all external files that the old instance was 2773 // listening to. 2774 2775 ScExternalRefManager* pRefMgr = m_pDocument->GetExternalRefManager(); 2776 m_pExtRefListener.reset(new ExternalRefListener(*this, m_pDocument)); 2777 const hash_set<sal_uInt16>& rFileIds = r.m_pExtRefListener->getAllFileIds(); 2778 hash_set<sal_uInt16>::const_iterator itr = rFileIds.begin(), itrEnd = rFileIds.end(); 2779 for (; itr != itrEnd; ++itr) 2780 { 2781 pRefMgr->addLinkListener(*itr, m_pExtRefListener.get()); 2782 m_pExtRefListener->addFileId(*itr); 2783 } 2784 } 2785 } 2786 2787 void ScChart2DataSequence::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint) 2788 { 2789 if ( rHint.ISA( SfxSimpleHint ) ) 2790 { 2791 sal_uLong nId = static_cast<const SfxSimpleHint&>(rHint).GetId(); 2792 if ( nId ==SFX_HINT_DYING ) 2793 { 2794 m_pDocument = NULL; 2795 } 2796 else if ( nId == SFX_HINT_DATACHANGED ) 2797 { 2798 // delayed broadcast as in ScCellRangesBase 2799 2800 if ( m_bGotDataChangedHint && m_pDocument ) 2801 { 2802 m_aDataArray.clear(); 2803 lang::EventObject aEvent; 2804 aEvent.Source.set((cppu::OWeakObject*)this); 2805 2806 if( m_pDocument ) 2807 { 2808 for ( sal_uInt16 n=0; n<m_aValueListeners.Count(); n++ ) 2809 m_pDocument->AddUnoListenerCall( *m_aValueListeners[n], aEvent ); 2810 } 2811 2812 m_bGotDataChangedHint = false; 2813 } 2814 } 2815 else if ( nId == SC_HINT_CALCALL ) 2816 { 2817 // broadcast from DoHardRecalc - set m_bGotDataChangedHint 2818 // (SFX_HINT_DATACHANGED follows separately) 2819 2820 if ( m_aValueListeners.Count() ) 2821 m_bGotDataChangedHint = true; 2822 } 2823 } 2824 else if ( rHint.ISA( ScUpdateRefHint ) ) 2825 { 2826 // Create a range list from the token list, have the range list 2827 // updated, and bring the change back to the token list. 2828 2829 ScRangeList aRanges; 2830 m_pRangeIndices.reset(new vector<sal_uInt32>()); 2831 vector<ScSharedTokenRef>::const_iterator itrBeg = m_pTokens->begin(), itrEnd = m_pTokens->end(); 2832 for (vector<ScSharedTokenRef>::const_iterator itr = itrBeg ;itr != itrEnd; ++itr) 2833 { 2834 if (!ScRefTokenHelper::isExternalRef(*itr)) 2835 { 2836 ScRange aRange; 2837 ScRefTokenHelper::getRangeFromToken(aRange, *itr); 2838 aRanges.Append(aRange); 2839 sal_uInt32 nPos = distance(itrBeg, itr); 2840 m_pRangeIndices->push_back(nPos); 2841 } 2842 } 2843 2844 DBG_ASSERT(m_pRangeIndices->size() == static_cast<size_t>(aRanges.Count()), 2845 "range list and range index list have different sizes."); 2846 2847 auto_ptr<ScRangeList> pUndoRanges; 2848 if ( m_pDocument->HasUnoRefUndo() ) 2849 pUndoRanges.reset(new ScRangeList(aRanges)); 2850 2851 const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint; 2852 bool bChanged = aRanges.UpdateReference( 2853 rRef.GetMode(), m_pDocument, rRef.GetRange(), rRef.GetDx(), rRef.GetDy(), rRef.GetDz()); 2854 2855 if (bChanged) 2856 { 2857 DBG_ASSERT(m_pRangeIndices->size() == static_cast<size_t>(aRanges.Count()), 2858 "range list and range index list have different sizes after the reference update."); 2859 2860 // Bring the change back from the range list to the token list. 2861 UpdateTokensFromRanges(aRanges); 2862 2863 if (pUndoRanges.get()) 2864 m_pDocument->AddUnoRefChange(m_nObjectId, *pUndoRanges); 2865 } 2866 } 2867 else if ( rHint.ISA( ScUnoRefUndoHint ) ) 2868 { 2869 const ScUnoRefUndoHint& rUndoHint = static_cast<const ScUnoRefUndoHint&>(rHint); 2870 2871 do 2872 { 2873 if (rUndoHint.GetObjectId() != m_nObjectId) 2874 break; 2875 2876 // The hint object provides the old ranges. Restore the old state 2877 // from these ranges. 2878 2879 if (!m_pRangeIndices.get() || m_pRangeIndices->empty()) 2880 { 2881 DBG_ERROR(" faulty range indices"); 2882 break; 2883 } 2884 2885 const ScRangeList& rRanges = rUndoHint.GetRanges(); 2886 2887 sal_uInt32 nCount = rRanges.Count(); 2888 if (nCount != m_pRangeIndices->size()) 2889 { 2890 DBG_ERROR("range count and range index count differ."); 2891 break; 2892 } 2893 2894 UpdateTokensFromRanges(rRanges); 2895 } 2896 while (false); 2897 } 2898 } 2899 2900 2901 IMPL_LINK( ScChart2DataSequence, ValueListenerHdl, SfxHint*, pHint ) 2902 { 2903 if ( m_pDocument && pHint && pHint->ISA( SfxSimpleHint ) && 2904 ((const SfxSimpleHint*)pHint)->GetId() & (SC_HINT_DATACHANGED | SC_HINT_DYING) ) 2905 { 2906 // This may be called several times for a single change, if several formulas 2907 // in the range are notified. So only a flag is set that is checked when 2908 // SFX_HINT_DATACHANGED is received. 2909 2910 setDataChangedHint(true); 2911 } 2912 return 0; 2913 } 2914 2915 // ---------------------------------------------------------------------------- 2916 2917 ScChart2DataSequence::ExternalRefListener::ExternalRefListener( 2918 ScChart2DataSequence& rParent, ScDocument* pDoc) : 2919 ScExternalRefManager::LinkListener(), 2920 mrParent(rParent), 2921 mpDoc(pDoc) 2922 { 2923 } 2924 2925 ScChart2DataSequence::ExternalRefListener::~ExternalRefListener() 2926 { 2927 if (!mpDoc || mpDoc->IsInDtorClear()) 2928 // The document is being destroyed. Do nothing. 2929 return; 2930 2931 // Make sure to remove all pointers to this object. 2932 mpDoc->GetExternalRefManager()->removeLinkListener(this); 2933 } 2934 2935 void ScChart2DataSequence::ExternalRefListener::notify(sal_uInt16 nFileId, ScExternalRefManager::LinkUpdateType eType) 2936 { 2937 switch (eType) 2938 { 2939 case ScExternalRefManager::LINK_MODIFIED: 2940 { 2941 if (maFileIds.count(nFileId)) 2942 // We are listening to this external document. 2943 mrParent.RebuildDataCache(); 2944 } 2945 break; 2946 case ScExternalRefManager::LINK_BROKEN: 2947 removeFileId(nFileId); 2948 break; 2949 } 2950 } 2951 2952 void ScChart2DataSequence::ExternalRefListener::addFileId(sal_uInt16 nFileId) 2953 { 2954 maFileIds.insert(nFileId); 2955 } 2956 2957 void ScChart2DataSequence::ExternalRefListener::removeFileId(sal_uInt16 nFileId) 2958 { 2959 maFileIds.erase(nFileId); 2960 } 2961 2962 const hash_set<sal_uInt16>& ScChart2DataSequence::ExternalRefListener::getAllFileIds() 2963 { 2964 return maFileIds; 2965 } 2966 2967 // ---------------------------------------------------------------------------- 2968 2969 uno::Sequence< uno::Any> SAL_CALL ScChart2DataSequence::getData() 2970 throw ( uno::RuntimeException) 2971 { 2972 ScUnoGuard aGuard; 2973 if ( !m_pDocument) 2974 throw uno::RuntimeException(); 2975 2976 BuildDataCache(); 2977 2978 if (!m_aMixedDataCache.getLength()) 2979 { 2980 // Build a cache for the 1st time... 2981 2982 sal_Int32 nCount = m_aDataArray.size(); 2983 m_aMixedDataCache.realloc(nCount); 2984 uno::Any* pArr = m_aMixedDataCache.getArray(); 2985 ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end(); 2986 for (; itr != itrEnd; ++itr, ++pArr) 2987 { 2988 if (itr->mbIsValue) 2989 *pArr <<= itr->mfValue; 2990 else 2991 *pArr <<= itr->maString; 2992 } 2993 } 2994 return m_aMixedDataCache; 2995 } 2996 2997 // XNumericalDataSequence -------------------------------------------------- 2998 2999 uno::Sequence< double > SAL_CALL ScChart2DataSequence::getNumericalData() 3000 throw ( uno::RuntimeException) 3001 { 3002 ScUnoGuard aGuard; 3003 if ( !m_pDocument) 3004 throw uno::RuntimeException(); 3005 3006 BuildDataCache(); 3007 3008 double fNAN; 3009 ::rtl::math::setNan(&fNAN); 3010 3011 sal_Int32 nCount = m_aDataArray.size(); 3012 // i121058: if there's too many points need to be painted, it doens't need to get all points for performance consideration 3013 // and so many points are not useful for users to understand the chart. So only picked some points to paint 3014 sal_Int32 nStep = nCount >= 10000 ? 50 : 1; 3015 nCount = nCount >= 10000 ? ((nCount - nCount % nStep) / nStep) : nCount; 3016 sal_Int32 nRealCount = nStep == 1 ? nCount : nCount * 2; 3017 uno::Sequence<double> aSeq(nRealCount); 3018 double* pArr = aSeq.getArray(); 3019 ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end(); 3020 for (sal_Int32 i = 0; i < nCount; i++) 3021 { 3022 if (nStep == 1) 3023 { 3024 *pArr++ = itr->mbIsValue ? itr->mfValue : fNAN; 3025 itr++; 3026 } 3027 else 3028 { 3029 sal_Int32 nMax = 0, nMin = 0, nMaxStep = 0, nMinStep = 0; 3030 for (sal_Int32 j = 0; j < nStep; j++) 3031 { 3032 sal_Int32 nValue = itr->mbIsValue ? itr->mfValue : fNAN; 3033 if (nValue > nMax) 3034 { 3035 nMax = nValue; 3036 nMaxStep = j; 3037 } 3038 if (nValue < nMin) 3039 { 3040 nMin = nValue; 3041 nMinStep = j; 3042 } 3043 itr++; 3044 } 3045 if (nMaxStep > nMinStep) 3046 { 3047 *pArr++ = nMin; 3048 *pArr++ = nMax; 3049 } 3050 else 3051 { 3052 *pArr++ = nMax; 3053 *pArr++ = nMin; 3054 } 3055 } 3056 } 3057 return aSeq; 3058 } 3059 3060 // XTextualDataSequence -------------------------------------------------- 3061 3062 uno::Sequence< rtl::OUString > SAL_CALL ScChart2DataSequence::getTextualData( ) throw (uno::RuntimeException) 3063 { 3064 ScUnoGuard aGuard; 3065 if ( !m_pDocument) 3066 throw uno::RuntimeException(); 3067 3068 BuildDataCache(); 3069 3070 sal_Int32 nCount = m_aDataArray.size(); 3071 uno::Sequence<rtl::OUString> aSeq(nCount); 3072 rtl::OUString* pArr = aSeq.getArray(); 3073 ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end(); 3074 for (; itr != itrEnd; ++itr, ++pArr) 3075 *pArr = itr->maString; 3076 3077 return aSeq; 3078 } 3079 3080 ::rtl::OUString SAL_CALL ScChart2DataSequence::getSourceRangeRepresentation() 3081 throw ( uno::RuntimeException) 3082 { 3083 ScUnoGuard aGuard; 3084 OUString aStr; 3085 DBG_ASSERT( m_pDocument, "No Document -> no SourceRangeRepresentation" ); 3086 if (m_pDocument && m_pTokens.get()) 3087 lcl_convertTokensToString(aStr, *m_pTokens, m_pDocument); 3088 3089 return aStr; 3090 } 3091 3092 namespace { 3093 3094 /** 3095 * This function object is used to accumulatively count the numbers of 3096 * columns and rows in all reference tokens. 3097 */ 3098 class AccumulateRangeSize : public unary_function<ScSharedTokenRef, void> 3099 { 3100 public: 3101 AccumulateRangeSize() : 3102 mnCols(0), mnRows(0) {} 3103 3104 AccumulateRangeSize(const AccumulateRangeSize& r) : 3105 mnCols(r.mnCols), mnRows(r.mnRows) {} 3106 3107 void operator() (const ScSharedTokenRef& pToken) 3108 { 3109 ScRange r; 3110 bool bExternal = ScRefTokenHelper::isExternalRef(pToken); 3111 ScRefTokenHelper::getRangeFromToken(r, pToken, bExternal); 3112 r.Justify(); 3113 mnCols += r.aEnd.Col() - r.aStart.Col() + 1; 3114 mnRows += r.aEnd.Row() - r.aStart.Row() + 1; 3115 } 3116 3117 SCCOL getCols() const { return mnCols; } 3118 SCROW getRows() const { return mnRows; } 3119 private: 3120 SCCOL mnCols; 3121 SCROW mnRows; 3122 }; 3123 3124 /** 3125 * This function object is used to generate label strings from a list of 3126 * reference tokens. 3127 */ 3128 class GenerateLabelStrings : public unary_function<ScSharedTokenRef, void> 3129 { 3130 public: 3131 GenerateLabelStrings(sal_Int32 nSize, chart2::data::LabelOrigin eOrigin, bool bColumn) : 3132 mpLabels(new Sequence<OUString>(nSize)), 3133 meOrigin(eOrigin), 3134 mnCount(0), 3135 mbColumn(bColumn) {} 3136 3137 GenerateLabelStrings(const GenerateLabelStrings& r) : 3138 mpLabels(r.mpLabels), 3139 meOrigin(r.meOrigin), 3140 mnCount(r.mnCount), 3141 mbColumn(r.mbColumn) {} 3142 3143 void operator() (const ScSharedTokenRef& pToken) 3144 { 3145 bool bExternal = ScRefTokenHelper::isExternalRef(pToken); 3146 ScRange aRange; 3147 ScRefTokenHelper::getRangeFromToken(aRange, pToken, bExternal); 3148 OUString* pArr = mpLabels->getArray(); 3149 if (mbColumn) 3150 { 3151 for (SCCOL nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol) 3152 { 3153 if ( meOrigin != chart2::data::LabelOrigin_LONG_SIDE) 3154 { 3155 String aString = ScGlobal::GetRscString(STR_COLUMN); 3156 aString += ' '; 3157 ScAddress aPos( nCol, 0, 0 ); 3158 String aColStr; 3159 aPos.Format( aColStr, SCA_VALID_COL, NULL ); 3160 aString += aColStr; 3161 pArr[mnCount] = aString; 3162 } 3163 else //only indices for categories 3164 pArr[mnCount] = String::CreateFromInt32( mnCount+1 ); 3165 ++mnCount; 3166 } 3167 } 3168 else 3169 { 3170 for (sal_Int32 nRow = aRange.aStart.Row(); nRow <= aRange.aEnd.Row(); ++nRow) 3171 { 3172 if (meOrigin != chart2::data::LabelOrigin_LONG_SIDE) 3173 { 3174 String aString = ScGlobal::GetRscString(STR_ROW); 3175 aString += ' '; 3176 aString += String::CreateFromInt32( nRow+1 ); 3177 pArr[mnCount] = aString; 3178 } 3179 else //only indices for categories 3180 pArr[mnCount] = String::CreateFromInt32( mnCount+1 ); 3181 ++mnCount; 3182 } 3183 } 3184 } 3185 3186 Sequence<OUString> getLabels() const { return *mpLabels; } 3187 3188 private: 3189 GenerateLabelStrings(); // disabled 3190 3191 shared_ptr< Sequence<OUString> > mpLabels; 3192 chart2::data::LabelOrigin meOrigin; 3193 sal_Int32 mnCount; 3194 bool mbColumn; 3195 }; 3196 3197 } 3198 3199 uno::Sequence< ::rtl::OUString > SAL_CALL ScChart2DataSequence::generateLabel(chart2::data::LabelOrigin eOrigin) 3200 throw (uno::RuntimeException) 3201 { 3202 ScUnoGuard aGuard; 3203 if ( !m_pDocument) 3204 throw uno::RuntimeException(); 3205 3206 if (!m_pTokens.get()) 3207 return Sequence<OUString>(); 3208 3209 // Determine the total size of all ranges. 3210 AccumulateRangeSize func; 3211 func = for_each(m_pTokens->begin(), m_pTokens->end(), func); 3212 SCCOL nCols = func.getCols(); 3213 SCROW nRows = func.getRows(); 3214 3215 // Detemine whether this is column-major or row-major. 3216 bool bColumn = true; 3217 if ((eOrigin == chart2::data::LabelOrigin_SHORT_SIDE) || 3218 (eOrigin == chart2::data::LabelOrigin_LONG_SIDE)) 3219 { 3220 if (nRows > nCols) 3221 { 3222 if (eOrigin == chart2::data::LabelOrigin_SHORT_SIDE) 3223 bColumn = true; 3224 else 3225 bColumn = false; 3226 } 3227 else if (nCols > nRows) 3228 { 3229 if (eOrigin == chart2::data::LabelOrigin_SHORT_SIDE) 3230 bColumn = false; 3231 else 3232 bColumn = true; 3233 } 3234 else 3235 return Sequence<OUString>(); 3236 } 3237 3238 // Generate label strings based on the info so far. 3239 sal_Int32 nCount = bColumn ? nCols : nRows; 3240 GenerateLabelStrings genLabels(nCount, eOrigin, bColumn); 3241 genLabels = for_each(m_pTokens->begin(), m_pTokens->end(), genLabels); 3242 Sequence<OUString> aSeq = genLabels.getLabels(); 3243 3244 return aSeq; 3245 } 3246 3247 ::sal_Int32 SAL_CALL ScChart2DataSequence::getNumberFormatKeyByIndex( ::sal_Int32 nIndex ) 3248 throw (lang::IndexOutOfBoundsException, 3249 uno::RuntimeException) 3250 { 3251 // index -1 means a heuristic value for the entire sequence 3252 bool bGetSeriesFormat = (nIndex == -1); 3253 sal_Int32 nResult = 0; 3254 3255 ScUnoGuard aGuard; 3256 if ( !m_pDocument || !m_pTokens.get()) 3257 return nResult; 3258 3259 sal_Int32 nCount = 0; 3260 bool bFound = false; 3261 ScRangePtr p; 3262 3263 uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( lcl_GetSpreadSheetDocument( m_pDocument )); 3264 if (!xSpreadDoc.is()) 3265 return nResult; 3266 3267 uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY ); 3268 if (!xIndex.is()) 3269 return nResult; 3270 3271 ScRangeList aRanges; 3272 ScRefTokenHelper::getRangeListFromTokens(aRanges, *m_pTokens); 3273 uno::Reference< table::XCellRange > xSheet; 3274 for ( p = aRanges.First(); p && !bFound; p = aRanges.Next()) 3275 { 3276 // TODO: use DocIter? 3277 table::CellAddress aStart, aEnd; 3278 ScUnoConversion::FillApiAddress( aStart, p->aStart ); 3279 ScUnoConversion::FillApiAddress( aEnd, p->aEnd ); 3280 for ( sal_Int16 nSheet = aStart.Sheet; nSheet <= aEnd.Sheet && !bFound; ++nSheet) 3281 { 3282 xSheet.set(xIndex->getByIndex(nSheet), uno::UNO_QUERY); 3283 for ( sal_Int32 nCol = aStart.Column; nCol <= aEnd.Column && !bFound; ++nCol) 3284 { 3285 for ( sal_Int32 nRow = aStart.Row; nRow <= aEnd.Row && !bFound; ++nRow) 3286 { 3287 if( bGetSeriesFormat ) 3288 { 3289 // TODO: use nicer heuristic 3290 // return format of first non-empty cell 3291 uno::Reference< text::XText > xText( 3292 xSheet->getCellByPosition(nCol, nRow), uno::UNO_QUERY); 3293 if (xText.is() && xText->getString().getLength()) 3294 { 3295 uno::Reference< beans::XPropertySet > xProp(xText, uno::UNO_QUERY); 3296 if( xProp.is()) 3297 xProp->getPropertyValue( 3298 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NumberFormat"))) >>= nResult; 3299 bFound = true; 3300 break; 3301 } 3302 } 3303 else if( nCount == nIndex ) 3304 { 3305 uno::Reference< beans::XPropertySet > xProp( 3306 xSheet->getCellByPosition(nCol, nRow), uno::UNO_QUERY); 3307 if( xProp.is()) 3308 xProp->getPropertyValue( 3309 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NumberFormat"))) >>= nResult; 3310 bFound = true; 3311 break; 3312 } 3313 ++nCount; 3314 } 3315 } 3316 } 3317 } 3318 3319 return nResult; 3320 } 3321 3322 // XCloneable ================================================================ 3323 3324 uno::Reference< util::XCloneable > SAL_CALL ScChart2DataSequence::createClone() 3325 throw (uno::RuntimeException) 3326 { 3327 ScUnoGuard aGuard; 3328 3329 auto_ptr< vector<ScSharedTokenRef> > pTokensNew; 3330 if (m_pTokens.get()) 3331 { 3332 // Clone tokens. 3333 pTokensNew.reset(new vector<ScSharedTokenRef>); 3334 pTokensNew->reserve(m_pTokens->size()); 3335 vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end(); 3336 for (; itr != itrEnd; ++itr) 3337 { 3338 ScSharedTokenRef p(static_cast<ScToken*>((*itr)->Clone())); 3339 pTokensNew->push_back(p); 3340 } 3341 } 3342 3343 auto_ptr<ScChart2DataSequence> p(new ScChart2DataSequence(m_pDocument, m_xDataProvider, pTokensNew.release(), m_bIncludeHiddenCells)); 3344 p->CopyData(*this); 3345 Reference< util::XCloneable > xClone(p.release()); 3346 3347 return xClone; 3348 } 3349 3350 // XModifyBroadcaster ======================================================== 3351 3352 void SAL_CALL ScChart2DataSequence::addModifyListener( const uno::Reference< util::XModifyListener >& aListener ) 3353 throw (uno::RuntimeException) 3354 { 3355 // like ScCellRangesBase::addModifyListener 3356 ScUnoGuard aGuard; 3357 if (!m_pTokens.get() || m_pTokens->empty()) 3358 return; 3359 3360 ScRangeList aRanges; 3361 ScRefTokenHelper::getRangeListFromTokens(aRanges, *m_pTokens); 3362 uno::Reference<util::XModifyListener> *pObj = 3363 new uno::Reference<util::XModifyListener>( aListener ); 3364 m_aValueListeners.Insert( pObj, m_aValueListeners.Count() ); 3365 3366 if ( m_aValueListeners.Count() == 1 ) 3367 { 3368 if (!m_pValueListener) 3369 m_pValueListener = new ScLinkListener( LINK( this, ScChart2DataSequence, ValueListenerHdl ) ); 3370 3371 if (!m_pHiddenListener.get()) 3372 m_pHiddenListener.reset(new HiddenRangeListener(*this)); 3373 3374 if( m_pDocument ) 3375 { 3376 ScChartListenerCollection* pCLC = m_pDocument->GetChartListenerCollection(); 3377 vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end(); 3378 for (; itr != itrEnd; ++itr) 3379 { 3380 ScRange aRange; 3381 if (!ScRefTokenHelper::getRangeFromToken(aRange, *itr)) 3382 continue; 3383 3384 m_pDocument->StartListeningArea( aRange, m_pValueListener ); 3385 if (pCLC) 3386 pCLC->StartListeningHiddenRange(aRange, m_pHiddenListener.get()); 3387 } 3388 } 3389 3390 acquire(); // don't lose this object (one ref for all listeners) 3391 } 3392 } 3393 3394 void SAL_CALL ScChart2DataSequence::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) 3395 throw (uno::RuntimeException) 3396 { 3397 // like ScCellRangesBase::removeModifyListener 3398 3399 ScUnoGuard aGuard; 3400 if (!m_pTokens.get() || m_pTokens->empty()) 3401 return; 3402 3403 acquire(); // in case the listeners have the last ref - released below 3404 3405 sal_uInt16 nCount = m_aValueListeners.Count(); 3406 for ( sal_uInt16 n=nCount; n--; ) 3407 { 3408 uno::Reference<util::XModifyListener> *pObj = m_aValueListeners[n]; 3409 if ( *pObj == aListener ) 3410 { 3411 m_aValueListeners.DeleteAndDestroy( n ); 3412 3413 if ( m_aValueListeners.Count() == 0 ) 3414 { 3415 if (m_pValueListener) 3416 m_pValueListener->EndListeningAll(); 3417 3418 if (m_pHiddenListener.get() && m_pDocument) 3419 { 3420 ScChartListenerCollection* pCLC = m_pDocument->GetChartListenerCollection(); 3421 if (pCLC) 3422 pCLC->EndListeningHiddenRange(m_pHiddenListener.get()); 3423 } 3424 3425 release(); // release the ref for the listeners 3426 } 3427 3428 break; 3429 } 3430 } 3431 3432 release(); // might delete this object 3433 } 3434 3435 // DataSequence XPropertySet ------------------------------------------------- 3436 3437 uno::Reference< beans::XPropertySetInfo> SAL_CALL 3438 ScChart2DataSequence::getPropertySetInfo() throw( uno::RuntimeException) 3439 { 3440 ScUnoGuard aGuard; 3441 static uno::Reference<beans::XPropertySetInfo> aRef = 3442 new SfxItemPropertySetInfo( m_aPropSet.getPropertyMap() ); 3443 return aRef; 3444 } 3445 3446 3447 void SAL_CALL ScChart2DataSequence::setPropertyValue( 3448 const ::rtl::OUString& rPropertyName, const uno::Any& rValue) 3449 throw( beans::UnknownPropertyException, 3450 beans::PropertyVetoException, 3451 lang::IllegalArgumentException, 3452 lang::WrappedTargetException, uno::RuntimeException) 3453 { 3454 if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE))) 3455 { 3456 if ( !(rValue >>= m_aRole)) 3457 throw lang::IllegalArgumentException(); 3458 } 3459 else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS))) 3460 { 3461 sal_Bool bOldValue = m_bIncludeHiddenCells; 3462 if ( !(rValue >>= m_bIncludeHiddenCells)) 3463 throw lang::IllegalArgumentException(); 3464 if( bOldValue != m_bIncludeHiddenCells ) 3465 m_aDataArray.clear();//data array is dirty now 3466 } 3467 else 3468 throw beans::UnknownPropertyException(); 3469 // TODO: support optional properties 3470 } 3471 3472 3473 uno::Any SAL_CALL ScChart2DataSequence::getPropertyValue( 3474 const ::rtl::OUString& rPropertyName) 3475 throw( beans::UnknownPropertyException, 3476 lang::WrappedTargetException, uno::RuntimeException) 3477 { 3478 uno::Any aRet; 3479 if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE))) 3480 aRet <<= m_aRole; 3481 else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS))) 3482 aRet <<= m_bIncludeHiddenCells; 3483 else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(SC_UNONAME_HIDDENVALUES))) 3484 { 3485 // This property is read-only thus cannot be set externally via 3486 // setPropertyValue(...). 3487 BuildDataCache(); 3488 aRet <<= m_aHiddenValues; 3489 } 3490 else 3491 throw beans::UnknownPropertyException(); 3492 // TODO: support optional properties 3493 return aRet; 3494 } 3495 3496 3497 void SAL_CALL ScChart2DataSequence::addPropertyChangeListener( 3498 const ::rtl::OUString& /*rPropertyName*/, 3499 const uno::Reference< beans::XPropertyChangeListener>& /*xListener*/) 3500 throw( beans::UnknownPropertyException, 3501 lang::WrappedTargetException, uno::RuntimeException) 3502 { 3503 // FIXME: real implementation 3504 // throw uno::RuntimeException(); 3505 OSL_ENSURE( false, "Not yet implemented" ); 3506 } 3507 3508 3509 void SAL_CALL ScChart2DataSequence::removePropertyChangeListener( 3510 const ::rtl::OUString& /*rPropertyName*/, 3511 const uno::Reference< beans::XPropertyChangeListener>& /*rListener*/) 3512 throw( beans::UnknownPropertyException, 3513 lang::WrappedTargetException, uno::RuntimeException) 3514 { 3515 // FIXME: real implementation 3516 // throw uno::RuntimeException(); 3517 OSL_ENSURE( false, "Not yet implemented" ); 3518 } 3519 3520 3521 void SAL_CALL ScChart2DataSequence::addVetoableChangeListener( 3522 const ::rtl::OUString& /*rPropertyName*/, 3523 const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/) 3524 throw( beans::UnknownPropertyException, 3525 lang::WrappedTargetException, uno::RuntimeException) 3526 { 3527 // FIXME: real implementation 3528 // throw uno::RuntimeException(); 3529 OSL_ENSURE( false, "Not yet implemented" ); 3530 } 3531 3532 3533 void SAL_CALL ScChart2DataSequence::removeVetoableChangeListener( 3534 const ::rtl::OUString& /*rPropertyName*/, 3535 const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/) 3536 throw( beans::UnknownPropertyException, 3537 lang::WrappedTargetException, uno::RuntimeException) 3538 { 3539 // FIXME: real implementation 3540 // throw uno::RuntimeException(); 3541 OSL_ENSURE( false, "Not yet implemented" ); 3542 } 3543 3544 void ScChart2DataSequence::setDataChangedHint(bool b) 3545 { 3546 m_bGotDataChangedHint = b; 3547 } 3548 3549 // XUnoTunnel 3550 3551 // sal_Int64 SAL_CALL ScChart2DataSequence::getSomething( 3552 // const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) 3553 // { 3554 // if ( rId.getLength() == 16 && 3555 // 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), 3556 // rId.getConstArray(), 16 ) ) 3557 // { 3558 // return (sal_Int64)this; 3559 // } 3560 // return 0; 3561 // } 3562 3563 // // static 3564 // const uno::Sequence<sal_Int8>& ScChart2DataSequence::getUnoTunnelId() 3565 // { 3566 // static uno::Sequence<sal_Int8> * pSeq = 0; 3567 // if( !pSeq ) 3568 // { 3569 // osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); 3570 // if( !pSeq ) 3571 // { 3572 // static uno::Sequence< sal_Int8 > aSeq( 16 ); 3573 // rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); 3574 // pSeq = &aSeq; 3575 // } 3576 // } 3577 // return *pSeq; 3578 // } 3579 3580 // // static 3581 // ScChart2DataSequence* ScChart2DataSequence::getImplementation( const uno::Reference<uno::XInterface> xObj ) 3582 // { 3583 // ScChart2DataSequence* pRet = NULL; 3584 // uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); 3585 // if (xUT.is()) 3586 // pRet = (ScChart2DataSequence*) xUT->getSomething( getUnoTunnelId() ); 3587 // return pRet; 3588 // } 3589 3590 #if USE_CHART2_EMPTYDATASEQUENCE 3591 // DataSequence ============================================================== 3592 3593 ScChart2EmptyDataSequence::ScChart2EmptyDataSequence( ScDocument* pDoc, 3594 const uno::Reference < chart2::data::XDataProvider >& xDP, 3595 const ScRangeListRef& rRangeList, 3596 sal_Bool bColumn) 3597 : m_bIncludeHiddenCells( sal_True) 3598 , m_xRanges( rRangeList) 3599 , m_pDocument( pDoc) 3600 , m_xDataProvider( xDP) 3601 , m_aPropSet(lcl_GetDataSequencePropertyMap()) 3602 , m_bColumn(bColumn) 3603 { 3604 if ( m_pDocument ) 3605 m_pDocument->AddUnoObject( *this); 3606 // FIXME: real implementation of identifier and it's mapping to ranges. 3607 // Reuse ScChartListener? 3608 3609 // BM: don't use names of named ranges but the UI range strings 3610 // String aStr; 3611 // rRangeList->Format( aStr, SCR_ABS_3D, m_pDocument ); 3612 // m_aIdentifier = ::rtl::OUString( aStr ); 3613 3614 // m_aIdentifier = ::rtl::OUString::createFromAscii( "ID_"); 3615 // static sal_Int32 nID = 0; 3616 // m_aIdentifier += ::rtl::OUString::valueOf( ++nID); 3617 } 3618 3619 3620 ScChart2EmptyDataSequence::~ScChart2EmptyDataSequence() 3621 { 3622 if ( m_pDocument ) 3623 m_pDocument->RemoveUnoObject( *this); 3624 } 3625 3626 3627 void ScChart2EmptyDataSequence::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint) 3628 { 3629 if ( rHint.ISA( SfxSimpleHint ) && 3630 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) 3631 { 3632 m_pDocument = NULL; 3633 } 3634 } 3635 3636 3637 uno::Sequence< uno::Any> SAL_CALL ScChart2EmptyDataSequence::getData() 3638 throw ( uno::RuntimeException) 3639 { 3640 ScUnoGuard aGuard; 3641 if ( !m_pDocument) 3642 throw uno::RuntimeException(); 3643 return uno::Sequence< uno::Any>(); 3644 } 3645 3646 // XTextualDataSequence -------------------------------------------------- 3647 3648 uno::Sequence< rtl::OUString > SAL_CALL ScChart2EmptyDataSequence::getTextualData( ) throw (uno::RuntimeException) 3649 { 3650 ScUnoGuard aGuard; 3651 if ( !m_pDocument) 3652 throw uno::RuntimeException(); 3653 3654 sal_Int32 nCount = 0; 3655 ScRangePtr p; 3656 3657 DBG_ASSERT(m_xRanges->Count() == 1, "not handled count of ranges"); 3658 3659 for ( p = m_xRanges->First(); p; p = m_xRanges->Next()) 3660 { 3661 p->Justify(); 3662 // TODO: handle overlaping ranges? 3663 nCount += m_bColumn ? p->aEnd.Col() - p->aStart.Col() + 1 : p->aEnd.Row() - p->aStart.Row() + 1; 3664 } 3665 uno::Sequence< rtl::OUString > aSeq( nCount); 3666 rtl::OUString* pArr = aSeq.getArray(); 3667 nCount = 0; 3668 for ( p = m_xRanges->First(); p; p = m_xRanges->Next()) 3669 { 3670 if (m_bColumn) 3671 { 3672 for (SCCOL nCol = p->aStart.Col(); nCol <= p->aEnd.Col(); ++nCol) 3673 { 3674 String aString = ScGlobal::GetRscString(STR_COLUMN); 3675 aString += ' '; 3676 ScAddress aPos( nCol, 0, 0 ); 3677 String aColStr; 3678 aPos.Format( aColStr, SCA_VALID_COL, NULL ); 3679 aString += aColStr; 3680 pArr[nCount] = aString; 3681 ++nCount; 3682 } 3683 } 3684 else 3685 { 3686 for (sal_Int32 nRow = p->aStart.Row(); nRow <= p->aEnd.Row(); ++nRow) 3687 { 3688 String aString = ScGlobal::GetRscString(STR_ROW); 3689 aString += ' '; 3690 aString += String::CreateFromInt32( nRow+1 ); 3691 pArr[nCount] = aString; 3692 ++nCount; 3693 } 3694 } 3695 } 3696 return aSeq; 3697 } 3698 3699 ::rtl::OUString SAL_CALL ScChart2EmptyDataSequence::getSourceRangeRepresentation() 3700 throw ( uno::RuntimeException) 3701 { 3702 ScUnoGuard aGuard; 3703 String aStr; 3704 DBG_ASSERT( m_pDocument, "No Document -> no SourceRangeRepresentation" ); 3705 if( m_pDocument ) 3706 m_xRanges->Format( aStr, SCR_ABS_3D, m_pDocument, m_pDocument->GetAddressConvention() ); 3707 return aStr; 3708 } 3709 3710 uno::Sequence< ::rtl::OUString > SAL_CALL ScChart2EmptyDataSequence::generateLabel(chart2::data::LabelOrigin /*nOrigin*/) 3711 throw (uno::RuntimeException) 3712 { 3713 ScUnoGuard aGuard; 3714 uno::Sequence< ::rtl::OUString > aRet; 3715 return aRet; 3716 } 3717 3718 ::sal_Int32 SAL_CALL ScChart2EmptyDataSequence::getNumberFormatKeyByIndex( ::sal_Int32 /*nIndex*/ ) 3719 throw (lang::IndexOutOfBoundsException, 3720 uno::RuntimeException) 3721 { 3722 sal_Int32 nResult = 0; 3723 3724 ScUnoGuard aGuard; 3725 if ( !m_pDocument) 3726 return nResult; 3727 3728 return nResult; 3729 } 3730 3731 // XCloneable ================================================================ 3732 3733 uno::Reference< util::XCloneable > SAL_CALL ScChart2EmptyDataSequence::createClone() 3734 throw (uno::RuntimeException) 3735 { 3736 ScUnoGuard aGuard; 3737 if (m_xDataProvider.is()) 3738 { 3739 // copy properties 3740 uno::Reference < util::XCloneable > xClone(new ScChart2EmptyDataSequence(m_pDocument, m_xDataProvider, new ScRangeList(*m_xRanges), m_bColumn)); 3741 uno::Reference< beans::XPropertySet > xProp( xClone, uno::UNO_QUERY ); 3742 if( xProp.is()) 3743 { 3744 xProp->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_ROLE )), 3745 uno::makeAny( m_aRole )); 3746 xProp->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS )), 3747 uno::makeAny( m_bIncludeHiddenCells )); 3748 } 3749 return xClone; 3750 } 3751 return uno::Reference< util::XCloneable >(); 3752 } 3753 3754 // XModifyBroadcaster ======================================================== 3755 3756 void SAL_CALL ScChart2EmptyDataSequence::addModifyListener( const uno::Reference< util::XModifyListener >& /*aListener*/ ) 3757 throw (uno::RuntimeException) 3758 { 3759 // TODO: Implement 3760 } 3761 3762 void SAL_CALL ScChart2EmptyDataSequence::removeModifyListener( const uno::Reference< util::XModifyListener >& /*aListener*/ ) 3763 throw (uno::RuntimeException) 3764 { 3765 // TODO: Implement 3766 } 3767 3768 // DataSequence XPropertySet ------------------------------------------------- 3769 3770 uno::Reference< beans::XPropertySetInfo> SAL_CALL 3771 ScChart2EmptyDataSequence::getPropertySetInfo() throw( uno::RuntimeException) 3772 { 3773 ScUnoGuard aGuard; 3774 static uno::Reference<beans::XPropertySetInfo> aRef = 3775 new SfxItemPropertySetInfo( m_aPropSet.getPropertyMap() ); 3776 return aRef; 3777 } 3778 3779 3780 void SAL_CALL ScChart2EmptyDataSequence::setPropertyValue( 3781 const ::rtl::OUString& rPropertyName, const uno::Any& rValue) 3782 throw( beans::UnknownPropertyException, 3783 beans::PropertyVetoException, 3784 lang::IllegalArgumentException, 3785 lang::WrappedTargetException, uno::RuntimeException) 3786 { 3787 if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE))) 3788 { 3789 if ( !(rValue >>= m_aRole)) 3790 throw lang::IllegalArgumentException(); 3791 } 3792 else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS))) 3793 { 3794 if ( !(rValue >>= m_bIncludeHiddenCells)) 3795 throw lang::IllegalArgumentException(); 3796 } 3797 else 3798 throw beans::UnknownPropertyException(); 3799 // TODO: support optional properties 3800 } 3801 3802 3803 uno::Any SAL_CALL ScChart2EmptyDataSequence::getPropertyValue( 3804 const ::rtl::OUString& rPropertyName) 3805 throw( beans::UnknownPropertyException, 3806 lang::WrappedTargetException, uno::RuntimeException) 3807 { 3808 uno::Any aRet; 3809 if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE))) 3810 aRet <<= m_aRole; 3811 else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS))) 3812 aRet <<= m_bIncludeHiddenCells; 3813 else 3814 throw beans::UnknownPropertyException(); 3815 // TODO: support optional properties 3816 return aRet; 3817 } 3818 3819 3820 void SAL_CALL ScChart2EmptyDataSequence::addPropertyChangeListener( 3821 const ::rtl::OUString& /*rPropertyName*/, 3822 const uno::Reference< beans::XPropertyChangeListener>& /*xListener*/) 3823 throw( beans::UnknownPropertyException, 3824 lang::WrappedTargetException, uno::RuntimeException) 3825 { 3826 // FIXME: real implementation 3827 // throw uno::RuntimeException(); 3828 OSL_ENSURE( false, "Not yet implemented" ); 3829 } 3830 3831 3832 void SAL_CALL ScChart2EmptyDataSequence::removePropertyChangeListener( 3833 const ::rtl::OUString& /*rPropertyName*/, 3834 const uno::Reference< beans::XPropertyChangeListener>& /*rListener*/) 3835 throw( beans::UnknownPropertyException, 3836 lang::WrappedTargetException, uno::RuntimeException) 3837 { 3838 // FIXME: real implementation 3839 // throw uno::RuntimeException(); 3840 OSL_ENSURE( false, "Not yet implemented" ); 3841 } 3842 3843 3844 void SAL_CALL ScChart2EmptyDataSequence::addVetoableChangeListener( 3845 const ::rtl::OUString& /*rPropertyName*/, 3846 const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/) 3847 throw( beans::UnknownPropertyException, 3848 lang::WrappedTargetException, uno::RuntimeException) 3849 { 3850 // FIXME: real implementation 3851 // throw uno::RuntimeException(); 3852 OSL_ENSURE( false, "Not yet implemented" ); 3853 } 3854 3855 3856 void SAL_CALL ScChart2EmptyDataSequence::removeVetoableChangeListener( 3857 const ::rtl::OUString& /*rPropertyName*/, 3858 const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/ ) 3859 throw( beans::UnknownPropertyException, 3860 lang::WrappedTargetException, uno::RuntimeException) 3861 { 3862 // FIXME: real implementation 3863 // throw uno::RuntimeException(); 3864 OSL_ENSURE( false, "Not yet implemented" ); 3865 } 3866 3867 // XUnoTunnel 3868 3869 // sal_Int64 SAL_CALL ScChart2EmptyDataSequence::getSomething( 3870 // const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) 3871 // { 3872 // if ( rId.getLength() == 16 && 3873 // 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), 3874 // rId.getConstArray(), 16 ) ) 3875 // { 3876 // return (sal_Int64)this; 3877 // } 3878 // return 0; 3879 // } 3880 3881 // // static 3882 // const uno::Sequence<sal_Int8>& ScChart2EmptyDataSequence::getUnoTunnelId() 3883 // { 3884 // static uno::Sequence<sal_Int8> * pSeq = 0; 3885 // if( !pSeq ) 3886 // { 3887 // osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); 3888 // if( !pSeq ) 3889 // { 3890 // static uno::Sequence< sal_Int8 > aSeq( 16 ); 3891 // rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); 3892 // pSeq = &aSeq; 3893 // } 3894 // } 3895 // return *pSeq; 3896 // } 3897 3898 // // static 3899 // ScChart2DataSequence* ScChart2EmptyDataSequence::getImplementation( const uno::Reference<uno::XInterface> xObj ) 3900 // { 3901 // ScChart2DataSequence* pRet = NULL; 3902 // uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); 3903 // if (xUT.is()) 3904 // pRet = (ScChart2EmptyDataSequence*) xUT->getSomething( getUnoTunnelId() ); 3905 // return pRet; 3906 // } 3907 #endif 3908