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(); 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(); 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(); 787 pNewRowTable.reset(); 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 2180 // #118840# Only interpret range string when the ScDocument is not just used 2181 // temporary (e.g. for transporting a chart over the clipboard). In that case, the local 2182 // cell data would be invalid; despite the fact that a 'Sheet1' exists (just because 2183 // it's the default) 2184 if(!m_pDocument->IsTemporary()) 2185 { 2186 ScRangeStringConverter::GetStringFromXMLRangeString(aRet, sXMLRange, m_pDocument); 2187 } 2188 2189 return aRet; 2190 } 2191 2192 // DataProvider XPropertySet ------------------------------------------------- 2193 2194 uno::Reference< beans::XPropertySetInfo> SAL_CALL 2195 ScChart2DataProvider::getPropertySetInfo() throw( uno::RuntimeException) 2196 { 2197 ScUnoGuard aGuard; 2198 static uno::Reference<beans::XPropertySetInfo> aRef = 2199 new SfxItemPropertySetInfo( m_aPropSet.getPropertyMap() ); 2200 return aRef; 2201 } 2202 2203 2204 void SAL_CALL ScChart2DataProvider::setPropertyValue( 2205 const ::rtl::OUString& rPropertyName, const uno::Any& rValue) 2206 throw( beans::UnknownPropertyException, 2207 beans::PropertyVetoException, 2208 lang::IllegalArgumentException, 2209 lang::WrappedTargetException, uno::RuntimeException) 2210 { 2211 if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS))) 2212 { 2213 if ( !(rValue >>= m_bIncludeHiddenCells)) 2214 throw lang::IllegalArgumentException(); 2215 } 2216 else 2217 throw beans::UnknownPropertyException(); 2218 } 2219 2220 2221 uno::Any SAL_CALL ScChart2DataProvider::getPropertyValue( 2222 const ::rtl::OUString& rPropertyName) 2223 throw( beans::UnknownPropertyException, 2224 lang::WrappedTargetException, uno::RuntimeException) 2225 { 2226 uno::Any aRet; 2227 if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS))) 2228 aRet <<= m_bIncludeHiddenCells; 2229 else 2230 throw beans::UnknownPropertyException(); 2231 return aRet; 2232 } 2233 2234 2235 void SAL_CALL ScChart2DataProvider::addPropertyChangeListener( 2236 const ::rtl::OUString& /*rPropertyName*/, 2237 const uno::Reference< beans::XPropertyChangeListener>& /*xListener*/) 2238 throw( beans::UnknownPropertyException, 2239 lang::WrappedTargetException, uno::RuntimeException) 2240 { 2241 OSL_ENSURE( false, "Not yet implemented" ); 2242 } 2243 2244 2245 void SAL_CALL ScChart2DataProvider::removePropertyChangeListener( 2246 const ::rtl::OUString& /*rPropertyName*/, 2247 const uno::Reference< beans::XPropertyChangeListener>& /*rListener*/) 2248 throw( beans::UnknownPropertyException, 2249 lang::WrappedTargetException, uno::RuntimeException) 2250 { 2251 OSL_ENSURE( false, "Not yet implemented" ); 2252 } 2253 2254 2255 void SAL_CALL ScChart2DataProvider::addVetoableChangeListener( 2256 const ::rtl::OUString& /*rPropertyName*/, 2257 const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/) 2258 throw( beans::UnknownPropertyException, 2259 lang::WrappedTargetException, uno::RuntimeException) 2260 { 2261 OSL_ENSURE( false, "Not yet implemented" ); 2262 } 2263 2264 2265 void SAL_CALL ScChart2DataProvider::removeVetoableChangeListener( 2266 const ::rtl::OUString& /*rPropertyName*/, 2267 const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/ ) 2268 throw( beans::UnknownPropertyException, 2269 lang::WrappedTargetException, uno::RuntimeException) 2270 { 2271 OSL_ENSURE( false, "Not yet implemented" ); 2272 } 2273 2274 // DataSource ================================================================ 2275 2276 ScChart2DataSource::ScChart2DataSource( ScDocument* pDoc) 2277 : m_pDocument( pDoc) 2278 { 2279 if ( m_pDocument ) 2280 m_pDocument->AddUnoObject( *this); 2281 } 2282 2283 2284 ScChart2DataSource::~ScChart2DataSource() 2285 { 2286 if ( m_pDocument ) 2287 m_pDocument->RemoveUnoObject( *this); 2288 } 2289 2290 2291 void ScChart2DataSource::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint) 2292 { 2293 if ( rHint.ISA( SfxSimpleHint ) && 2294 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) 2295 { 2296 m_pDocument = NULL; 2297 } 2298 } 2299 2300 2301 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence> > SAL_CALL 2302 ScChart2DataSource::getDataSequences() throw ( uno::RuntimeException) 2303 { 2304 ScUnoGuard aGuard; 2305 2306 LabeledList::const_iterator aItr(m_aLabeledSequences.begin()); 2307 LabeledList::const_iterator aEndItr(m_aLabeledSequences.end()); 2308 2309 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aRet(m_aLabeledSequences.size()); 2310 2311 sal_Int32 i = 0; 2312 while (aItr != aEndItr) 2313 { 2314 aRet[i] = *aItr; 2315 ++i; 2316 ++aItr; 2317 } 2318 2319 return aRet; 2320 2321 /* typedef ::std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > tVec; 2322 tVec aVec; 2323 bool bSeries = false; 2324 // split into columns - FIXME: different if GlueState() is used 2325 for ( ScRangePtr p = m_xRanges->First(); p; p = m_xRanges->Next()) 2326 { 2327 for ( SCCOL nCol = p->aStart.Col(); nCol <= p->aEnd.Col(); ++nCol) 2328 { 2329 uno::Reference< chart2::data::XLabeledDataSequence > xLabeledSeq( 2330 new ScChart2LabeledDataSequence( m_pDocument)); 2331 if( xLabeledSeq.is()) 2332 { 2333 aVec.push_back( xLabeledSeq ); 2334 if( bSeries ) 2335 { 2336 ScRangeListRef aColRanges = new ScRangeList; 2337 // one single sheet selected assumed for now 2338 aColRanges->Append( ScRange( nCol, p->aStart.Row(), 2339 p->aStart.Tab(), nCol, p->aStart.Row(), 2340 p->aStart.Tab())); 2341 // TEST: add range two times, once as label, once as data 2342 // TODO: create pure Numerical and Text sequences if possible 2343 uno::Reference< chart2::data::XDataSequence > xLabel( 2344 new ScChart2DataSequence( m_pDocument, aColRanges)); 2345 2346 // set role 2347 uno::Reference< beans::XPropertySet > xProp( xLabel, uno::UNO_QUERY ); 2348 if( xProp.is()) 2349 xProp->setPropertyValue( 2350 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )), 2351 ::uno::makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "label" )))); 2352 2353 xLabeledSeq->setLabel( xLabel ); 2354 } 2355 2356 ScRangeListRef aColRanges = new ScRangeList; 2357 2358 // one single sheet selected assumed for now 2359 aColRanges->Append( ScRange( nCol, p->aStart.Row() + 1, 2360 p->aStart.Tab(), nCol, p->aEnd.Row(), 2361 p->aStart.Tab())); 2362 uno::Reference< chart2::data::XDataSequence > xData( 2363 new ScChart2DataSequence( m_pDocument, aColRanges)); 2364 2365 // set role 2366 uno::Reference< beans::XPropertySet > xProp( xData, uno::UNO_QUERY ); 2367 if( xProp.is()) 2368 xProp->setPropertyValue( 2369 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )), 2370 ::uno::makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "values" )))); 2371 2372 xLabeledSeq->setValues( xData ); 2373 2374 bSeries = true; 2375 } 2376 } 2377 } 2378 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence> > aSequences( 2379 aVec.size()); 2380 uno::Reference< chart2::data::XLabeledDataSequence> * pArr = aSequences.getArray(); 2381 sal_Int32 j = 0; 2382 for ( tVec::const_iterator iSeq = aVec.begin(); iSeq != aVec.end(); 2383 ++iSeq, ++j) 2384 { 2385 pArr[j] = *iSeq; 2386 } 2387 return aSequences;*/ 2388 } 2389 2390 void ScChart2DataSource::AddLabeledSequence(const uno::Reference < chart2::data::XLabeledDataSequence >& xNew) 2391 { 2392 m_aLabeledSequences.push_back(xNew); 2393 } 2394 2395 2396 // DataSequence ============================================================== 2397 2398 ScChart2DataSequence::Item::Item() : 2399 mfValue(0.0), mbIsValue(false) 2400 { 2401 ::rtl::math::setNan(&mfValue); 2402 } 2403 2404 ScChart2DataSequence::HiddenRangeListener::HiddenRangeListener(ScChart2DataSequence& rParent) : 2405 mrParent(rParent) 2406 { 2407 } 2408 2409 ScChart2DataSequence::HiddenRangeListener::~HiddenRangeListener() 2410 { 2411 } 2412 2413 void ScChart2DataSequence::HiddenRangeListener::notify() 2414 { 2415 mrParent.setDataChangedHint(true); 2416 } 2417 2418 ScChart2DataSequence::ScChart2DataSequence( ScDocument* pDoc, 2419 const uno::Reference < chart2::data::XDataProvider >& xDP, 2420 vector<ScSharedTokenRef>* pTokens, 2421 bool bIncludeHiddenCells ) 2422 : m_bIncludeHiddenCells( bIncludeHiddenCells) 2423 , m_nObjectId( 0 ) 2424 , m_pDocument( pDoc) 2425 , m_pTokens(pTokens) 2426 , m_pRangeIndices(NULL) 2427 , m_pExtRefListener(NULL) 2428 , m_xDataProvider( xDP) 2429 , m_aPropSet(lcl_GetDataSequencePropertyMap()) 2430 , m_pHiddenListener(NULL) 2431 , m_pValueListener( NULL ) 2432 , m_bGotDataChangedHint(false) 2433 , m_bExtDataRebuildQueued(false) 2434 { 2435 DBG_ASSERT(pTokens, "reference token list is null"); 2436 2437 if ( m_pDocument ) 2438 { 2439 m_pDocument->AddUnoObject( *this); 2440 m_nObjectId = m_pDocument->GetNewUnoId(); 2441 } 2442 // FIXME: real implementation of identifier and it's mapping to ranges. 2443 // Reuse ScChartListener? 2444 2445 // BM: don't use names of named ranges but the UI range strings 2446 // String aStr; 2447 // rRangeList->Format( aStr, SCR_ABS_3D, m_pDocument ); 2448 // m_aIdentifier = ::rtl::OUString( aStr ); 2449 2450 // m_aIdentifier = ::rtl::OUString::createFromAscii( "ID_"); 2451 // static sal_Int32 nID = 0; 2452 // m_aIdentifier += ::rtl::OUString::valueOf( ++nID); 2453 } 2454 2455 ScChart2DataSequence::~ScChart2DataSequence() 2456 { 2457 if ( m_pDocument ) 2458 { 2459 m_pDocument->RemoveUnoObject( *this); 2460 if (m_pHiddenListener.get()) 2461 { 2462 ScChartListenerCollection* pCLC = m_pDocument->GetChartListenerCollection(); 2463 if (pCLC) 2464 pCLC->EndListeningHiddenRange(m_pHiddenListener.get()); 2465 } 2466 StopListeningToAllExternalRefs(); 2467 } 2468 2469 delete m_pValueListener; 2470 } 2471 2472 void ScChart2DataSequence::RefChanged() 2473 { 2474 if( m_pValueListener && m_aValueListeners.Count() != 0 ) 2475 { 2476 m_pValueListener->EndListeningAll(); 2477 2478 if( m_pDocument ) 2479 { 2480 ScChartListenerCollection* pCLC = NULL; 2481 if (m_pHiddenListener.get()) 2482 { 2483 pCLC = m_pDocument->GetChartListenerCollection(); 2484 if (pCLC) 2485 pCLC->EndListeningHiddenRange(m_pHiddenListener.get()); 2486 } 2487 2488 vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end(); 2489 for (; itr != itrEnd; ++itr) 2490 { 2491 ScRange aRange; 2492 if (!ScRefTokenHelper::getRangeFromToken(aRange, *itr)) 2493 continue; 2494 2495 m_pDocument->StartListeningArea(aRange, m_pValueListener); 2496 if (pCLC) 2497 pCLC->StartListeningHiddenRange(aRange, m_pHiddenListener.get()); 2498 } 2499 } 2500 } 2501 } 2502 2503 void ScChart2DataSequence::BuildDataCache() 2504 { 2505 m_bExtDataRebuildQueued = false; 2506 2507 if (!m_aDataArray.empty()) 2508 return; 2509 2510 if (!m_pTokens.get()) 2511 { 2512 DBG_ERROR("m_pTokens == NULL! Something is wrong."); 2513 return; 2514 } 2515 2516 StopListeningToAllExternalRefs(); 2517 2518 ::std::list<sal_Int32> aHiddenValues; 2519 sal_Int32 nDataCount = 0; 2520 sal_Int32 nHiddenValueCount = 0; 2521 2522 for (vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end(); 2523 itr != itrEnd; ++itr) 2524 { 2525 if (ScRefTokenHelper::isExternalRef(*itr)) 2526 { 2527 nDataCount += FillCacheFromExternalRef(*itr); 2528 } 2529 else 2530 { 2531 ScRange aRange; 2532 if (!ScRefTokenHelper::getRangeFromToken(aRange, *itr)) 2533 continue; 2534 2535 SCCOL nLastCol = -1; 2536 SCROW nLastRow = -1; 2537 2538 for (SCTAB nTab = aRange.aStart.Tab(); nTab <= aRange.aEnd.Tab(); ++nTab) 2539 { 2540 for (SCCOL nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol) 2541 { 2542 for (SCROW nRow = aRange.aStart.Row(); nRow <= aRange.aEnd.Row(); ++nRow) 2543 { 2544 bool bColHidden = m_pDocument->ColHidden(nCol, nTab, nLastCol); 2545 bool bRowHidden = m_pDocument->RowHidden(nRow, nTab, nLastRow); 2546 2547 if (bColHidden || bRowHidden) 2548 { 2549 // hidden cell 2550 ++nHiddenValueCount; 2551 aHiddenValues.push_back(nDataCount-1); 2552 2553 if( !m_bIncludeHiddenCells ) 2554 continue; 2555 } 2556 2557 m_aDataArray.push_back(Item()); 2558 Item& rItem = m_aDataArray.back(); 2559 ++nDataCount; 2560 2561 ScAddress aAdr(nCol, nRow, nTab); 2562 ScBaseCell* pCell = m_pDocument->GetCell(aAdr); 2563 if (!pCell) 2564 continue; 2565 2566 if (pCell->HasStringData()) 2567 2568 rItem.maString = pCell->GetStringData(); 2569 else 2570 { 2571 String aStr; 2572 m_pDocument->GetString(nCol, nRow, nTab, aStr); 2573 rItem.maString = aStr; 2574 } 2575 2576 switch (pCell->GetCellType()) 2577 { 2578 case CELLTYPE_VALUE: 2579 rItem.mfValue = static_cast< ScValueCell*>(pCell)->GetValue(); 2580 rItem.mbIsValue = true; 2581 break; 2582 case CELLTYPE_FORMULA: 2583 { 2584 ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell); 2585 sal_uInt16 nErr = pFCell->GetErrCode(); 2586 if (nErr) 2587 break; 2588 2589 if (pFCell->HasValueData()) 2590 { 2591 rItem.mfValue = pFCell->GetValue(); 2592 rItem.mbIsValue = true; 2593 } 2594 } 2595 break; 2596 #if DBG_UTIL 2597 case CELLTYPE_DESTROYED: 2598 #endif 2599 case CELLTYPE_EDIT: 2600 case CELLTYPE_NONE: 2601 case CELLTYPE_NOTE: 2602 case CELLTYPE_STRING: 2603 case CELLTYPE_SYMBOLS: 2604 default: 2605 ; // do nothing 2606 } 2607 } 2608 } 2609 } 2610 } 2611 } 2612 2613 // convert the hidden cell list to sequence. 2614 m_aHiddenValues.realloc(nHiddenValueCount); 2615 sal_Int32* pArr = m_aHiddenValues.getArray(); 2616 ::std::list<sal_Int32>::const_iterator itr = aHiddenValues.begin(), itrEnd = aHiddenValues.end(); 2617 for (;itr != itrEnd; ++itr, ++pArr) 2618 *pArr = *itr; 2619 2620 // Clear the data series cache when the array is re-built. 2621 m_aMixedDataCache.realloc(0); 2622 } 2623 2624 void ScChart2DataSequence::RebuildDataCache() 2625 { 2626 if (!m_bExtDataRebuildQueued) 2627 { 2628 m_aDataArray.clear(); 2629 m_pDocument->BroadcastUno(ScHint(SC_HINT_DATACHANGED, ScAddress(), NULL)); 2630 m_bExtDataRebuildQueued = true; 2631 m_bGotDataChangedHint = true; 2632 } 2633 } 2634 2635 sal_Int32 ScChart2DataSequence::FillCacheFromExternalRef(const ScSharedTokenRef& pToken) 2636 { 2637 ScExternalRefManager* pRefMgr = m_pDocument->GetExternalRefManager(); 2638 ScRange aRange; 2639 if (!ScRefTokenHelper::getRangeFromToken(aRange, pToken, true)) 2640 return 0; 2641 2642 sal_uInt16 nFileId = pToken->GetIndex(); 2643 const String& rTabName = pToken->GetString(); 2644 ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(nFileId, rTabName, aRange, NULL); 2645 if (!pArray) 2646 // no external data exists for this range. 2647 return 0; 2648 2649 // Start listening for this external document. 2650 ExternalRefListener* pExtRefListener = GetExtRefListener(); 2651 pRefMgr->addLinkListener(nFileId, pExtRefListener); 2652 pExtRefListener->addFileId(nFileId); 2653 2654 ScExternalRefCache::TableTypeRef pTable = pRefMgr->getCacheTable(nFileId, rTabName, false, NULL); 2655 sal_Int32 nDataCount = 0; 2656 for (FormulaToken* p = pArray->First(); p; p = pArray->Next()) 2657 { 2658 // Cached external range is always represented as a single 2659 // matrix token, although that might change in the future when 2660 // we introduce a new token type to store multi-table range 2661 // data. 2662 2663 if (p->GetType() != svMatrix) 2664 { 2665 DBG_ERROR("Cached array is not a matrix token."); 2666 continue; 2667 } 2668 2669 const ScMatrix* pMat = static_cast<ScToken*>(p)->GetMatrix(); 2670 SCSIZE nCSize, nRSize; 2671 pMat->GetDimensions(nCSize, nRSize); 2672 for (SCSIZE nC = 0; nC < nCSize; ++nC) 2673 { 2674 for (SCSIZE nR = 0; nR < nRSize; ++nR) 2675 { 2676 if (pMat->IsValue(nC, nR) || pMat->IsBoolean(nC, nR)) 2677 { 2678 m_aDataArray.push_back(Item()); 2679 Item& rItem = m_aDataArray.back(); 2680 ++nDataCount; 2681 2682 rItem.mbIsValue = true; 2683 rItem.mfValue = pMat->GetDouble(nC, nR); 2684 2685 SvNumberFormatter* pFormatter = m_pDocument->GetFormatTable(); 2686 if (pFormatter) 2687 { 2688 String aStr; 2689 const double fVal = rItem.mfValue; 2690 Color* pColor = NULL; 2691 sal_uInt32 nFmt = 0; 2692 if (pTable) 2693 { 2694 // Get the correct format index from the cache. 2695 SCCOL nCol = aRange.aStart.Col() + static_cast<SCCOL>(nC); 2696 SCROW nRow = aRange.aStart.Row() + static_cast<SCROW>(nR); 2697 pTable->getCell(nCol, nRow, &nFmt); 2698 } 2699 pFormatter->GetOutputString(fVal, nFmt, aStr, &pColor); 2700 rItem.maString = aStr; 2701 } 2702 } 2703 else if (pMat->IsString(nC, nR)) 2704 { 2705 m_aDataArray.push_back(Item()); 2706 Item& rItem = m_aDataArray.back(); 2707 ++nDataCount; 2708 2709 rItem.mbIsValue = false; 2710 rItem.maString = pMat->GetString(nC, nR); 2711 } 2712 } 2713 } 2714 } 2715 return nDataCount; 2716 } 2717 2718 void ScChart2DataSequence::UpdateTokensFromRanges(const ScRangeList& rRanges) 2719 { 2720 if (!m_pRangeIndices.get()) 2721 return; 2722 2723 sal_uInt32 nCount = rRanges.Count(); 2724 for (sal_uInt32 i = 0; i < nCount; ++i) 2725 { 2726 ScSharedTokenRef pToken; 2727 ScRange* pRange = static_cast<ScRange*>(rRanges.GetObject(i)); 2728 DBG_ASSERT(pRange, "range object is NULL."); 2729 2730 ScRefTokenHelper::getTokenFromRange(pToken, *pRange); 2731 sal_uInt32 nOrigPos = (*m_pRangeIndices)[i]; 2732 (*m_pTokens)[nOrigPos] = pToken; 2733 } 2734 2735 RefChanged(); 2736 2737 // any change of the range address is broadcast to value (modify) listeners 2738 if ( m_aValueListeners.Count() ) 2739 m_bGotDataChangedHint = true; 2740 } 2741 2742 ScChart2DataSequence::ExternalRefListener* ScChart2DataSequence::GetExtRefListener() 2743 { 2744 if (!m_pExtRefListener.get()) 2745 m_pExtRefListener.reset(new ExternalRefListener(*this, m_pDocument)); 2746 2747 return m_pExtRefListener.get(); 2748 } 2749 2750 void ScChart2DataSequence::StopListeningToAllExternalRefs() 2751 { 2752 if (!m_pExtRefListener.get()) 2753 return; 2754 2755 const hash_set<sal_uInt16>& rFileIds = m_pExtRefListener->getAllFileIds(); 2756 hash_set<sal_uInt16>::const_iterator itr = rFileIds.begin(), itrEnd = rFileIds.end(); 2757 ScExternalRefManager* pRefMgr = m_pDocument->GetExternalRefManager(); 2758 for (; itr != itrEnd; ++itr) 2759 pRefMgr->removeLinkListener(*itr, m_pExtRefListener.get()); 2760 2761 m_pExtRefListener.reset(); 2762 } 2763 2764 void ScChart2DataSequence::CopyData(const ScChart2DataSequence& r) 2765 { 2766 if (!m_pDocument) 2767 { 2768 DBG_ERROR("document instance is NULL!?"); 2769 return; 2770 } 2771 2772 list<Item> aDataArray(r.m_aDataArray); 2773 m_aDataArray.swap(aDataArray); 2774 2775 m_aHiddenValues = r.m_aHiddenValues; 2776 m_aRole = r.m_aRole; 2777 2778 if (r.m_pRangeIndices.get()) 2779 m_pRangeIndices.reset(new vector<sal_uInt32>(*r.m_pRangeIndices)); 2780 2781 if (r.m_pExtRefListener.get()) 2782 { 2783 // Re-register all external files that the old instance was 2784 // listening to. 2785 2786 ScExternalRefManager* pRefMgr = m_pDocument->GetExternalRefManager(); 2787 m_pExtRefListener.reset(new ExternalRefListener(*this, m_pDocument)); 2788 const hash_set<sal_uInt16>& rFileIds = r.m_pExtRefListener->getAllFileIds(); 2789 hash_set<sal_uInt16>::const_iterator itr = rFileIds.begin(), itrEnd = rFileIds.end(); 2790 for (; itr != itrEnd; ++itr) 2791 { 2792 pRefMgr->addLinkListener(*itr, m_pExtRefListener.get()); 2793 m_pExtRefListener->addFileId(*itr); 2794 } 2795 } 2796 } 2797 2798 void ScChart2DataSequence::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint) 2799 { 2800 if ( rHint.ISA( SfxSimpleHint ) ) 2801 { 2802 sal_uLong nId = static_cast<const SfxSimpleHint&>(rHint).GetId(); 2803 if ( nId ==SFX_HINT_DYING ) 2804 { 2805 m_pDocument = NULL; 2806 } 2807 else if ( nId == SFX_HINT_DATACHANGED ) 2808 { 2809 // delayed broadcast as in ScCellRangesBase 2810 2811 if ( m_bGotDataChangedHint && m_pDocument ) 2812 { 2813 m_aDataArray.clear(); 2814 lang::EventObject aEvent; 2815 aEvent.Source.set((cppu::OWeakObject*)this); 2816 2817 if( m_pDocument ) 2818 { 2819 for ( sal_uInt16 n=0; n<m_aValueListeners.Count(); n++ ) 2820 m_pDocument->AddUnoListenerCall( *m_aValueListeners[n], aEvent ); 2821 } 2822 2823 m_bGotDataChangedHint = false; 2824 } 2825 } 2826 else if ( nId == SC_HINT_CALCALL ) 2827 { 2828 // broadcast from DoHardRecalc - set m_bGotDataChangedHint 2829 // (SFX_HINT_DATACHANGED follows separately) 2830 2831 if ( m_aValueListeners.Count() ) 2832 m_bGotDataChangedHint = true; 2833 } 2834 } 2835 else if ( rHint.ISA( ScUpdateRefHint ) ) 2836 { 2837 // Create a range list from the token list, have the range list 2838 // updated, and bring the change back to the token list. 2839 2840 ScRangeList aRanges; 2841 m_pRangeIndices.reset(new vector<sal_uInt32>()); 2842 vector<ScSharedTokenRef>::const_iterator itrBeg = m_pTokens->begin(), itrEnd = m_pTokens->end(); 2843 for (vector<ScSharedTokenRef>::const_iterator itr = itrBeg ;itr != itrEnd; ++itr) 2844 { 2845 if (!ScRefTokenHelper::isExternalRef(*itr)) 2846 { 2847 ScRange aRange; 2848 ScRefTokenHelper::getRangeFromToken(aRange, *itr); 2849 aRanges.Append(aRange); 2850 sal_uInt32 nPos = distance(itrBeg, itr); 2851 m_pRangeIndices->push_back(nPos); 2852 } 2853 } 2854 2855 DBG_ASSERT(m_pRangeIndices->size() == static_cast<size_t>(aRanges.Count()), 2856 "range list and range index list have different sizes."); 2857 2858 auto_ptr<ScRangeList> pUndoRanges; 2859 if ( m_pDocument->HasUnoRefUndo() ) 2860 pUndoRanges.reset(new ScRangeList(aRanges)); 2861 2862 const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint; 2863 bool bChanged = aRanges.UpdateReference( 2864 rRef.GetMode(), m_pDocument, rRef.GetRange(), rRef.GetDx(), rRef.GetDy(), rRef.GetDz()); 2865 2866 if (bChanged) 2867 { 2868 DBG_ASSERT(m_pRangeIndices->size() == static_cast<size_t>(aRanges.Count()), 2869 "range list and range index list have different sizes after the reference update."); 2870 2871 // Bring the change back from the range list to the token list. 2872 UpdateTokensFromRanges(aRanges); 2873 2874 if (pUndoRanges.get()) 2875 m_pDocument->AddUnoRefChange(m_nObjectId, *pUndoRanges); 2876 } 2877 } 2878 else if ( rHint.ISA( ScUnoRefUndoHint ) ) 2879 { 2880 const ScUnoRefUndoHint& rUndoHint = static_cast<const ScUnoRefUndoHint&>(rHint); 2881 2882 do 2883 { 2884 if (rUndoHint.GetObjectId() != m_nObjectId) 2885 break; 2886 2887 // The hint object provides the old ranges. Restore the old state 2888 // from these ranges. 2889 2890 if (!m_pRangeIndices.get() || m_pRangeIndices->empty()) 2891 { 2892 DBG_ERROR(" faulty range indices"); 2893 break; 2894 } 2895 2896 const ScRangeList& rRanges = rUndoHint.GetRanges(); 2897 2898 sal_uInt32 nCount = rRanges.Count(); 2899 if (nCount != m_pRangeIndices->size()) 2900 { 2901 DBG_ERROR("range count and range index count differ."); 2902 break; 2903 } 2904 2905 UpdateTokensFromRanges(rRanges); 2906 } 2907 while (false); 2908 } 2909 } 2910 2911 2912 IMPL_LINK( ScChart2DataSequence, ValueListenerHdl, SfxHint*, pHint ) 2913 { 2914 if ( m_pDocument && pHint && pHint->ISA( SfxSimpleHint ) && 2915 ((const SfxSimpleHint*)pHint)->GetId() & (SC_HINT_DATACHANGED | SC_HINT_DYING) ) 2916 { 2917 // This may be called several times for a single change, if several formulas 2918 // in the range are notified. So only a flag is set that is checked when 2919 // SFX_HINT_DATACHANGED is received. 2920 2921 setDataChangedHint(true); 2922 } 2923 return 0; 2924 } 2925 2926 // ---------------------------------------------------------------------------- 2927 2928 ScChart2DataSequence::ExternalRefListener::ExternalRefListener( 2929 ScChart2DataSequence& rParent, ScDocument* pDoc) : 2930 ScExternalRefManager::LinkListener(), 2931 mrParent(rParent), 2932 mpDoc(pDoc) 2933 { 2934 } 2935 2936 ScChart2DataSequence::ExternalRefListener::~ExternalRefListener() 2937 { 2938 if (!mpDoc || mpDoc->IsInDtorClear()) 2939 // The document is being destroyed. Do nothing. 2940 return; 2941 2942 // Make sure to remove all pointers to this object. 2943 mpDoc->GetExternalRefManager()->removeLinkListener(this); 2944 } 2945 2946 void ScChart2DataSequence::ExternalRefListener::notify(sal_uInt16 nFileId, ScExternalRefManager::LinkUpdateType eType) 2947 { 2948 switch (eType) 2949 { 2950 case ScExternalRefManager::LINK_MODIFIED: 2951 { 2952 if (maFileIds.count(nFileId)) 2953 // We are listening to this external document. 2954 mrParent.RebuildDataCache(); 2955 } 2956 break; 2957 case ScExternalRefManager::LINK_BROKEN: 2958 removeFileId(nFileId); 2959 break; 2960 } 2961 } 2962 2963 void ScChart2DataSequence::ExternalRefListener::addFileId(sal_uInt16 nFileId) 2964 { 2965 maFileIds.insert(nFileId); 2966 } 2967 2968 void ScChart2DataSequence::ExternalRefListener::removeFileId(sal_uInt16 nFileId) 2969 { 2970 maFileIds.erase(nFileId); 2971 } 2972 2973 const hash_set<sal_uInt16>& ScChart2DataSequence::ExternalRefListener::getAllFileIds() 2974 { 2975 return maFileIds; 2976 } 2977 2978 // ---------------------------------------------------------------------------- 2979 2980 uno::Sequence< uno::Any> SAL_CALL ScChart2DataSequence::getData() 2981 throw ( uno::RuntimeException) 2982 { 2983 ScUnoGuard aGuard; 2984 if ( !m_pDocument) 2985 throw uno::RuntimeException(); 2986 2987 BuildDataCache(); 2988 2989 if (!m_aMixedDataCache.getLength()) 2990 { 2991 // Build a cache for the 1st time... 2992 2993 sal_Int32 nCount = m_aDataArray.size(); 2994 m_aMixedDataCache.realloc(nCount); 2995 uno::Any* pArr = m_aMixedDataCache.getArray(); 2996 ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end(); 2997 for (; itr != itrEnd; ++itr, ++pArr) 2998 { 2999 if (itr->mbIsValue) 3000 *pArr <<= itr->mfValue; 3001 else 3002 *pArr <<= itr->maString; 3003 } 3004 } 3005 return m_aMixedDataCache; 3006 } 3007 3008 // XNumericalDataSequence -------------------------------------------------- 3009 3010 uno::Sequence< double > SAL_CALL ScChart2DataSequence::getNumericalData() 3011 throw ( uno::RuntimeException) 3012 { 3013 ScUnoGuard aGuard; 3014 if ( !m_pDocument) 3015 throw uno::RuntimeException(); 3016 3017 BuildDataCache(); 3018 3019 double fNAN; 3020 ::rtl::math::setNan(&fNAN); 3021 3022 sal_Int32 nCount = m_aDataArray.size(); 3023 uno::Sequence<double> aSeq(nCount); 3024 double* pArr = aSeq.getArray(); 3025 ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end(); 3026 for (; itr != itrEnd; ++itr, ++pArr) 3027 *pArr = itr->mbIsValue ? itr->mfValue : fNAN; 3028 3029 return aSeq; 3030 } 3031 3032 // XTextualDataSequence -------------------------------------------------- 3033 3034 uno::Sequence< rtl::OUString > SAL_CALL ScChart2DataSequence::getTextualData( ) throw (uno::RuntimeException) 3035 { 3036 ScUnoGuard aGuard; 3037 if ( !m_pDocument) 3038 throw uno::RuntimeException(); 3039 3040 BuildDataCache(); 3041 3042 sal_Int32 nCount = m_aDataArray.size(); 3043 uno::Sequence<rtl::OUString> aSeq(nCount); 3044 rtl::OUString* pArr = aSeq.getArray(); 3045 ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end(); 3046 for (; itr != itrEnd; ++itr, ++pArr) 3047 *pArr = itr->maString; 3048 3049 return aSeq; 3050 } 3051 3052 ::rtl::OUString SAL_CALL ScChart2DataSequence::getSourceRangeRepresentation() 3053 throw ( uno::RuntimeException) 3054 { 3055 ScUnoGuard aGuard; 3056 OUString aStr; 3057 DBG_ASSERT( m_pDocument, "No Document -> no SourceRangeRepresentation" ); 3058 if (m_pDocument && m_pTokens.get()) 3059 lcl_convertTokensToString(aStr, *m_pTokens, m_pDocument); 3060 3061 return aStr; 3062 } 3063 3064 namespace { 3065 3066 /** 3067 * This function object is used to accumulatively count the numbers of 3068 * columns and rows in all reference tokens. 3069 */ 3070 class AccumulateRangeSize : public unary_function<ScSharedTokenRef, void> 3071 { 3072 public: 3073 AccumulateRangeSize() : 3074 mnCols(0), mnRows(0) {} 3075 3076 AccumulateRangeSize(const AccumulateRangeSize& r) : 3077 mnCols(r.mnCols), mnRows(r.mnRows) {} 3078 3079 void operator() (const ScSharedTokenRef& pToken) 3080 { 3081 ScRange r; 3082 bool bExternal = ScRefTokenHelper::isExternalRef(pToken); 3083 ScRefTokenHelper::getRangeFromToken(r, pToken, bExternal); 3084 r.Justify(); 3085 mnCols += r.aEnd.Col() - r.aStart.Col() + 1; 3086 mnRows += r.aEnd.Row() - r.aStart.Row() + 1; 3087 } 3088 3089 SCCOL getCols() const { return mnCols; } 3090 SCROW getRows() const { return mnRows; } 3091 private: 3092 SCCOL mnCols; 3093 SCROW mnRows; 3094 }; 3095 3096 /** 3097 * This function object is used to generate label strings from a list of 3098 * reference tokens. 3099 */ 3100 class GenerateLabelStrings : public unary_function<ScSharedTokenRef, void> 3101 { 3102 public: 3103 GenerateLabelStrings(sal_Int32 nSize, chart2::data::LabelOrigin eOrigin, bool bColumn) : 3104 mpLabels(new Sequence<OUString>(nSize)), 3105 meOrigin(eOrigin), 3106 mnCount(0), 3107 mbColumn(bColumn) {} 3108 3109 GenerateLabelStrings(const GenerateLabelStrings& r) : 3110 mpLabels(r.mpLabels), 3111 meOrigin(r.meOrigin), 3112 mnCount(r.mnCount), 3113 mbColumn(r.mbColumn) {} 3114 3115 void operator() (const ScSharedTokenRef& pToken) 3116 { 3117 bool bExternal = ScRefTokenHelper::isExternalRef(pToken); 3118 ScRange aRange; 3119 ScRefTokenHelper::getRangeFromToken(aRange, pToken, bExternal); 3120 OUString* pArr = mpLabels->getArray(); 3121 if (mbColumn) 3122 { 3123 for (SCCOL nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol) 3124 { 3125 if ( meOrigin != chart2::data::LabelOrigin_LONG_SIDE) 3126 { 3127 String aString = ScGlobal::GetRscString(STR_COLUMN); 3128 aString += ' '; 3129 ScAddress aPos( nCol, 0, 0 ); 3130 String aColStr; 3131 aPos.Format( aColStr, SCA_VALID_COL, NULL ); 3132 aString += aColStr; 3133 pArr[mnCount] = aString; 3134 } 3135 else //only indices for categories 3136 pArr[mnCount] = String::CreateFromInt32( mnCount+1 ); 3137 ++mnCount; 3138 } 3139 } 3140 else 3141 { 3142 for (sal_Int32 nRow = aRange.aStart.Row(); nRow <= aRange.aEnd.Row(); ++nRow) 3143 { 3144 if (meOrigin != chart2::data::LabelOrigin_LONG_SIDE) 3145 { 3146 String aString = ScGlobal::GetRscString(STR_ROW); 3147 aString += ' '; 3148 aString += String::CreateFromInt32( nRow+1 ); 3149 pArr[mnCount] = aString; 3150 } 3151 else //only indices for categories 3152 pArr[mnCount] = String::CreateFromInt32( mnCount+1 ); 3153 ++mnCount; 3154 } 3155 } 3156 } 3157 3158 Sequence<OUString> getLabels() const { return *mpLabels; } 3159 3160 private: 3161 GenerateLabelStrings(); // disabled 3162 3163 shared_ptr< Sequence<OUString> > mpLabels; 3164 chart2::data::LabelOrigin meOrigin; 3165 sal_Int32 mnCount; 3166 bool mbColumn; 3167 }; 3168 3169 } 3170 3171 uno::Sequence< ::rtl::OUString > SAL_CALL ScChart2DataSequence::generateLabel(chart2::data::LabelOrigin eOrigin) 3172 throw (uno::RuntimeException) 3173 { 3174 ScUnoGuard aGuard; 3175 if ( !m_pDocument) 3176 throw uno::RuntimeException(); 3177 3178 if (!m_pTokens.get()) 3179 return Sequence<OUString>(); 3180 3181 // Determine the total size of all ranges. 3182 AccumulateRangeSize func; 3183 func = for_each(m_pTokens->begin(), m_pTokens->end(), func); 3184 SCCOL nCols = func.getCols(); 3185 SCROW nRows = func.getRows(); 3186 3187 // Detemine whether this is column-major or row-major. 3188 bool bColumn = true; 3189 if ((eOrigin == chart2::data::LabelOrigin_SHORT_SIDE) || 3190 (eOrigin == chart2::data::LabelOrigin_LONG_SIDE)) 3191 { 3192 if (nRows > nCols) 3193 { 3194 if (eOrigin == chart2::data::LabelOrigin_SHORT_SIDE) 3195 bColumn = true; 3196 else 3197 bColumn = false; 3198 } 3199 else if (nCols > nRows) 3200 { 3201 if (eOrigin == chart2::data::LabelOrigin_SHORT_SIDE) 3202 bColumn = false; 3203 else 3204 bColumn = true; 3205 } 3206 else 3207 return Sequence<OUString>(); 3208 } 3209 3210 // Generate label strings based on the info so far. 3211 sal_Int32 nCount = bColumn ? nCols : nRows; 3212 GenerateLabelStrings genLabels(nCount, eOrigin, bColumn); 3213 genLabels = for_each(m_pTokens->begin(), m_pTokens->end(), genLabels); 3214 Sequence<OUString> aSeq = genLabels.getLabels(); 3215 3216 return aSeq; 3217 } 3218 3219 ::sal_Int32 SAL_CALL ScChart2DataSequence::getNumberFormatKeyByIndex( ::sal_Int32 nIndex ) 3220 throw (lang::IndexOutOfBoundsException, 3221 uno::RuntimeException) 3222 { 3223 // index -1 means a heuristic value for the entire sequence 3224 bool bGetSeriesFormat = (nIndex == -1); 3225 sal_Int32 nResult = 0; 3226 3227 ScUnoGuard aGuard; 3228 if ( !m_pDocument || !m_pTokens.get()) 3229 return nResult; 3230 3231 sal_Int32 nCount = 0; 3232 bool bFound = false; 3233 ScRangePtr p; 3234 3235 uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( lcl_GetSpreadSheetDocument( m_pDocument )); 3236 if (!xSpreadDoc.is()) 3237 return nResult; 3238 3239 uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY ); 3240 if (!xIndex.is()) 3241 return nResult; 3242 3243 ScRangeList aRanges; 3244 ScRefTokenHelper::getRangeListFromTokens(aRanges, *m_pTokens); 3245 uno::Reference< table::XCellRange > xSheet; 3246 for ( p = aRanges.First(); p && !bFound; p = aRanges.Next()) 3247 { 3248 // TODO: use DocIter? 3249 table::CellAddress aStart, aEnd; 3250 ScUnoConversion::FillApiAddress( aStart, p->aStart ); 3251 ScUnoConversion::FillApiAddress( aEnd, p->aEnd ); 3252 for ( sal_Int16 nSheet = aStart.Sheet; nSheet <= aEnd.Sheet && !bFound; ++nSheet) 3253 { 3254 xSheet.set(xIndex->getByIndex(nSheet), uno::UNO_QUERY); 3255 for ( sal_Int32 nCol = aStart.Column; nCol <= aEnd.Column && !bFound; ++nCol) 3256 { 3257 for ( sal_Int32 nRow = aStart.Row; nRow <= aEnd.Row && !bFound; ++nRow) 3258 { 3259 if( bGetSeriesFormat ) 3260 { 3261 // TODO: use nicer heuristic 3262 // return format of first non-empty cell 3263 uno::Reference< text::XText > xText( 3264 xSheet->getCellByPosition(nCol, nRow), uno::UNO_QUERY); 3265 if (xText.is() && xText->getString().getLength()) 3266 { 3267 uno::Reference< beans::XPropertySet > xProp(xText, uno::UNO_QUERY); 3268 if( xProp.is()) 3269 xProp->getPropertyValue( 3270 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NumberFormat"))) >>= nResult; 3271 bFound = true; 3272 break; 3273 } 3274 } 3275 else if( nCount == nIndex ) 3276 { 3277 uno::Reference< beans::XPropertySet > xProp( 3278 xSheet->getCellByPosition(nCol, nRow), uno::UNO_QUERY); 3279 if( xProp.is()) 3280 xProp->getPropertyValue( 3281 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NumberFormat"))) >>= nResult; 3282 bFound = true; 3283 break; 3284 } 3285 ++nCount; 3286 } 3287 } 3288 } 3289 } 3290 3291 return nResult; 3292 } 3293 3294 // XCloneable ================================================================ 3295 3296 uno::Reference< util::XCloneable > SAL_CALL ScChart2DataSequence::createClone() 3297 throw (uno::RuntimeException) 3298 { 3299 ScUnoGuard aGuard; 3300 3301 auto_ptr< vector<ScSharedTokenRef> > pTokensNew; 3302 if (m_pTokens.get()) 3303 { 3304 // Clone tokens. 3305 pTokensNew.reset(new vector<ScSharedTokenRef>); 3306 pTokensNew->reserve(m_pTokens->size()); 3307 vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end(); 3308 for (; itr != itrEnd; ++itr) 3309 { 3310 ScSharedTokenRef p(static_cast<ScToken*>((*itr)->Clone())); 3311 pTokensNew->push_back(p); 3312 } 3313 } 3314 3315 auto_ptr<ScChart2DataSequence> p(new ScChart2DataSequence(m_pDocument, m_xDataProvider, pTokensNew.release(), m_bIncludeHiddenCells)); 3316 p->CopyData(*this); 3317 Reference< util::XCloneable > xClone(p.release()); 3318 3319 return xClone; 3320 } 3321 3322 // XModifyBroadcaster ======================================================== 3323 3324 void SAL_CALL ScChart2DataSequence::addModifyListener( const uno::Reference< util::XModifyListener >& aListener ) 3325 throw (uno::RuntimeException) 3326 { 3327 // like ScCellRangesBase::addModifyListener 3328 ScUnoGuard aGuard; 3329 if (!m_pTokens.get() || m_pTokens->empty()) 3330 return; 3331 3332 ScRangeList aRanges; 3333 ScRefTokenHelper::getRangeListFromTokens(aRanges, *m_pTokens); 3334 uno::Reference<util::XModifyListener> *pObj = 3335 new uno::Reference<util::XModifyListener>( aListener ); 3336 m_aValueListeners.Insert( pObj, m_aValueListeners.Count() ); 3337 3338 if ( m_aValueListeners.Count() == 1 ) 3339 { 3340 if (!m_pValueListener) 3341 m_pValueListener = new ScLinkListener( LINK( this, ScChart2DataSequence, ValueListenerHdl ) ); 3342 3343 if (!m_pHiddenListener.get()) 3344 m_pHiddenListener.reset(new HiddenRangeListener(*this)); 3345 3346 if( m_pDocument ) 3347 { 3348 ScChartListenerCollection* pCLC = m_pDocument->GetChartListenerCollection(); 3349 vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end(); 3350 for (; itr != itrEnd; ++itr) 3351 { 3352 ScRange aRange; 3353 if (!ScRefTokenHelper::getRangeFromToken(aRange, *itr)) 3354 continue; 3355 3356 m_pDocument->StartListeningArea( aRange, m_pValueListener ); 3357 if (pCLC) 3358 pCLC->StartListeningHiddenRange(aRange, m_pHiddenListener.get()); 3359 } 3360 } 3361 3362 acquire(); // don't lose this object (one ref for all listeners) 3363 } 3364 } 3365 3366 void SAL_CALL ScChart2DataSequence::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) 3367 throw (uno::RuntimeException) 3368 { 3369 // like ScCellRangesBase::removeModifyListener 3370 3371 ScUnoGuard aGuard; 3372 if (!m_pTokens.get() || m_pTokens->empty()) 3373 return; 3374 3375 acquire(); // in case the listeners have the last ref - released below 3376 3377 sal_uInt16 nCount = m_aValueListeners.Count(); 3378 for ( sal_uInt16 n=nCount; n--; ) 3379 { 3380 uno::Reference<util::XModifyListener> *pObj = m_aValueListeners[n]; 3381 if ( *pObj == aListener ) 3382 { 3383 m_aValueListeners.DeleteAndDestroy( n ); 3384 3385 if ( m_aValueListeners.Count() == 0 ) 3386 { 3387 if (m_pValueListener) 3388 m_pValueListener->EndListeningAll(); 3389 3390 if (m_pHiddenListener.get() && m_pDocument) 3391 { 3392 ScChartListenerCollection* pCLC = m_pDocument->GetChartListenerCollection(); 3393 if (pCLC) 3394 pCLC->EndListeningHiddenRange(m_pHiddenListener.get()); 3395 } 3396 3397 release(); // release the ref for the listeners 3398 } 3399 3400 break; 3401 } 3402 } 3403 3404 release(); // might delete this object 3405 } 3406 3407 // DataSequence XPropertySet ------------------------------------------------- 3408 3409 uno::Reference< beans::XPropertySetInfo> SAL_CALL 3410 ScChart2DataSequence::getPropertySetInfo() throw( uno::RuntimeException) 3411 { 3412 ScUnoGuard aGuard; 3413 static uno::Reference<beans::XPropertySetInfo> aRef = 3414 new SfxItemPropertySetInfo( m_aPropSet.getPropertyMap() ); 3415 return aRef; 3416 } 3417 3418 3419 void SAL_CALL ScChart2DataSequence::setPropertyValue( 3420 const ::rtl::OUString& rPropertyName, const uno::Any& rValue) 3421 throw( beans::UnknownPropertyException, 3422 beans::PropertyVetoException, 3423 lang::IllegalArgumentException, 3424 lang::WrappedTargetException, uno::RuntimeException) 3425 { 3426 if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE))) 3427 { 3428 if ( !(rValue >>= m_aRole)) 3429 throw lang::IllegalArgumentException(); 3430 } 3431 else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS))) 3432 { 3433 sal_Bool bOldValue = m_bIncludeHiddenCells; 3434 if ( !(rValue >>= m_bIncludeHiddenCells)) 3435 throw lang::IllegalArgumentException(); 3436 if( bOldValue != m_bIncludeHiddenCells ) 3437 m_aDataArray.clear();//data array is dirty now 3438 } 3439 else 3440 throw beans::UnknownPropertyException(); 3441 // TODO: support optional properties 3442 } 3443 3444 3445 uno::Any SAL_CALL ScChart2DataSequence::getPropertyValue( 3446 const ::rtl::OUString& rPropertyName) 3447 throw( beans::UnknownPropertyException, 3448 lang::WrappedTargetException, uno::RuntimeException) 3449 { 3450 uno::Any aRet; 3451 if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE))) 3452 aRet <<= m_aRole; 3453 else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS))) 3454 aRet <<= m_bIncludeHiddenCells; 3455 else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(SC_UNONAME_HIDDENVALUES))) 3456 { 3457 // This property is read-only thus cannot be set externally via 3458 // setPropertyValue(...). 3459 BuildDataCache(); 3460 aRet <<= m_aHiddenValues; 3461 } 3462 else 3463 throw beans::UnknownPropertyException(); 3464 // TODO: support optional properties 3465 return aRet; 3466 } 3467 3468 3469 void SAL_CALL ScChart2DataSequence::addPropertyChangeListener( 3470 const ::rtl::OUString& /*rPropertyName*/, 3471 const uno::Reference< beans::XPropertyChangeListener>& /*xListener*/) 3472 throw( beans::UnknownPropertyException, 3473 lang::WrappedTargetException, uno::RuntimeException) 3474 { 3475 // FIXME: real implementation 3476 // throw uno::RuntimeException(); 3477 OSL_ENSURE( false, "Not yet implemented" ); 3478 } 3479 3480 3481 void SAL_CALL ScChart2DataSequence::removePropertyChangeListener( 3482 const ::rtl::OUString& /*rPropertyName*/, 3483 const uno::Reference< beans::XPropertyChangeListener>& /*rListener*/) 3484 throw( beans::UnknownPropertyException, 3485 lang::WrappedTargetException, uno::RuntimeException) 3486 { 3487 // FIXME: real implementation 3488 // throw uno::RuntimeException(); 3489 OSL_ENSURE( false, "Not yet implemented" ); 3490 } 3491 3492 3493 void SAL_CALL ScChart2DataSequence::addVetoableChangeListener( 3494 const ::rtl::OUString& /*rPropertyName*/, 3495 const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/) 3496 throw( beans::UnknownPropertyException, 3497 lang::WrappedTargetException, uno::RuntimeException) 3498 { 3499 // FIXME: real implementation 3500 // throw uno::RuntimeException(); 3501 OSL_ENSURE( false, "Not yet implemented" ); 3502 } 3503 3504 3505 void SAL_CALL ScChart2DataSequence::removeVetoableChangeListener( 3506 const ::rtl::OUString& /*rPropertyName*/, 3507 const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/) 3508 throw( beans::UnknownPropertyException, 3509 lang::WrappedTargetException, uno::RuntimeException) 3510 { 3511 // FIXME: real implementation 3512 // throw uno::RuntimeException(); 3513 OSL_ENSURE( false, "Not yet implemented" ); 3514 } 3515 3516 void ScChart2DataSequence::setDataChangedHint(bool b) 3517 { 3518 m_bGotDataChangedHint = b; 3519 } 3520 3521 // XUnoTunnel 3522 3523 // sal_Int64 SAL_CALL ScChart2DataSequence::getSomething( 3524 // const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) 3525 // { 3526 // if ( rId.getLength() == 16 && 3527 // 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), 3528 // rId.getConstArray(), 16 ) ) 3529 // { 3530 // return (sal_Int64)this; 3531 // } 3532 // return 0; 3533 // } 3534 3535 // // static 3536 // const uno::Sequence<sal_Int8>& ScChart2DataSequence::getUnoTunnelId() 3537 // { 3538 // static uno::Sequence<sal_Int8> * pSeq = 0; 3539 // if( !pSeq ) 3540 // { 3541 // osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); 3542 // if( !pSeq ) 3543 // { 3544 // static uno::Sequence< sal_Int8 > aSeq( 16 ); 3545 // rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); 3546 // pSeq = &aSeq; 3547 // } 3548 // } 3549 // return *pSeq; 3550 // } 3551 3552 // // static 3553 // ScChart2DataSequence* ScChart2DataSequence::getImplementation( const uno::Reference<uno::XInterface> xObj ) 3554 // { 3555 // ScChart2DataSequence* pRet = NULL; 3556 // uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); 3557 // if (xUT.is()) 3558 // pRet = (ScChart2DataSequence*) xUT->getSomething( getUnoTunnelId() ); 3559 // return pRet; 3560 // } 3561 3562 #if USE_CHART2_EMPTYDATASEQUENCE 3563 // DataSequence ============================================================== 3564 3565 ScChart2EmptyDataSequence::ScChart2EmptyDataSequence( ScDocument* pDoc, 3566 const uno::Reference < chart2::data::XDataProvider >& xDP, 3567 const ScRangeListRef& rRangeList, 3568 sal_Bool bColumn) 3569 : m_bIncludeHiddenCells( sal_True) 3570 , m_xRanges( rRangeList) 3571 , m_pDocument( pDoc) 3572 , m_xDataProvider( xDP) 3573 , m_aPropSet(lcl_GetDataSequencePropertyMap()) 3574 , m_bColumn(bColumn) 3575 { 3576 if ( m_pDocument ) 3577 m_pDocument->AddUnoObject( *this); 3578 // FIXME: real implementation of identifier and it's mapping to ranges. 3579 // Reuse ScChartListener? 3580 3581 // BM: don't use names of named ranges but the UI range strings 3582 // String aStr; 3583 // rRangeList->Format( aStr, SCR_ABS_3D, m_pDocument ); 3584 // m_aIdentifier = ::rtl::OUString( aStr ); 3585 3586 // m_aIdentifier = ::rtl::OUString::createFromAscii( "ID_"); 3587 // static sal_Int32 nID = 0; 3588 // m_aIdentifier += ::rtl::OUString::valueOf( ++nID); 3589 } 3590 3591 3592 ScChart2EmptyDataSequence::~ScChart2EmptyDataSequence() 3593 { 3594 if ( m_pDocument ) 3595 m_pDocument->RemoveUnoObject( *this); 3596 } 3597 3598 3599 void ScChart2EmptyDataSequence::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint) 3600 { 3601 if ( rHint.ISA( SfxSimpleHint ) && 3602 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) 3603 { 3604 m_pDocument = NULL; 3605 } 3606 } 3607 3608 3609 uno::Sequence< uno::Any> SAL_CALL ScChart2EmptyDataSequence::getData() 3610 throw ( uno::RuntimeException) 3611 { 3612 ScUnoGuard aGuard; 3613 if ( !m_pDocument) 3614 throw uno::RuntimeException(); 3615 return uno::Sequence< uno::Any>(); 3616 } 3617 3618 // XTextualDataSequence -------------------------------------------------- 3619 3620 uno::Sequence< rtl::OUString > SAL_CALL ScChart2EmptyDataSequence::getTextualData( ) throw (uno::RuntimeException) 3621 { 3622 ScUnoGuard aGuard; 3623 if ( !m_pDocument) 3624 throw uno::RuntimeException(); 3625 3626 sal_Int32 nCount = 0; 3627 ScRangePtr p; 3628 3629 DBG_ASSERT(m_xRanges->Count() == 1, "not handled count of ranges"); 3630 3631 for ( p = m_xRanges->First(); p; p = m_xRanges->Next()) 3632 { 3633 p->Justify(); 3634 // TODO: handle overlaping ranges? 3635 nCount += m_bColumn ? p->aEnd.Col() - p->aStart.Col() + 1 : p->aEnd.Row() - p->aStart.Row() + 1; 3636 } 3637 uno::Sequence< rtl::OUString > aSeq( nCount); 3638 rtl::OUString* pArr = aSeq.getArray(); 3639 nCount = 0; 3640 for ( p = m_xRanges->First(); p; p = m_xRanges->Next()) 3641 { 3642 if (m_bColumn) 3643 { 3644 for (SCCOL nCol = p->aStart.Col(); nCol <= p->aEnd.Col(); ++nCol) 3645 { 3646 String aString = ScGlobal::GetRscString(STR_COLUMN); 3647 aString += ' '; 3648 ScAddress aPos( nCol, 0, 0 ); 3649 String aColStr; 3650 aPos.Format( aColStr, SCA_VALID_COL, NULL ); 3651 aString += aColStr; 3652 pArr[nCount] = aString; 3653 ++nCount; 3654 } 3655 } 3656 else 3657 { 3658 for (sal_Int32 nRow = p->aStart.Row(); nRow <= p->aEnd.Row(); ++nRow) 3659 { 3660 String aString = ScGlobal::GetRscString(STR_ROW); 3661 aString += ' '; 3662 aString += String::CreateFromInt32( nRow+1 ); 3663 pArr[nCount] = aString; 3664 ++nCount; 3665 } 3666 } 3667 } 3668 return aSeq; 3669 } 3670 3671 ::rtl::OUString SAL_CALL ScChart2EmptyDataSequence::getSourceRangeRepresentation() 3672 throw ( uno::RuntimeException) 3673 { 3674 ScUnoGuard aGuard; 3675 String aStr; 3676 DBG_ASSERT( m_pDocument, "No Document -> no SourceRangeRepresentation" ); 3677 if( m_pDocument ) 3678 m_xRanges->Format( aStr, SCR_ABS_3D, m_pDocument, m_pDocument->GetAddressConvention() ); 3679 return aStr; 3680 } 3681 3682 uno::Sequence< ::rtl::OUString > SAL_CALL ScChart2EmptyDataSequence::generateLabel(chart2::data::LabelOrigin /*nOrigin*/) 3683 throw (uno::RuntimeException) 3684 { 3685 ScUnoGuard aGuard; 3686 uno::Sequence< ::rtl::OUString > aRet; 3687 return aRet; 3688 } 3689 3690 ::sal_Int32 SAL_CALL ScChart2EmptyDataSequence::getNumberFormatKeyByIndex( ::sal_Int32 /*nIndex*/ ) 3691 throw (lang::IndexOutOfBoundsException, 3692 uno::RuntimeException) 3693 { 3694 sal_Int32 nResult = 0; 3695 3696 ScUnoGuard aGuard; 3697 if ( !m_pDocument) 3698 return nResult; 3699 3700 return nResult; 3701 } 3702 3703 // XCloneable ================================================================ 3704 3705 uno::Reference< util::XCloneable > SAL_CALL ScChart2EmptyDataSequence::createClone() 3706 throw (uno::RuntimeException) 3707 { 3708 ScUnoGuard aGuard; 3709 if (m_xDataProvider.is()) 3710 { 3711 // copy properties 3712 uno::Reference < util::XCloneable > xClone(new ScChart2EmptyDataSequence(m_pDocument, m_xDataProvider, new ScRangeList(*m_xRanges), m_bColumn)); 3713 uno::Reference< beans::XPropertySet > xProp( xClone, uno::UNO_QUERY ); 3714 if( xProp.is()) 3715 { 3716 xProp->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_ROLE )), 3717 uno::makeAny( m_aRole )); 3718 xProp->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS )), 3719 uno::makeAny( m_bIncludeHiddenCells )); 3720 } 3721 return xClone; 3722 } 3723 return uno::Reference< util::XCloneable >(); 3724 } 3725 3726 // XModifyBroadcaster ======================================================== 3727 3728 void SAL_CALL ScChart2EmptyDataSequence::addModifyListener( const uno::Reference< util::XModifyListener >& /*aListener*/ ) 3729 throw (uno::RuntimeException) 3730 { 3731 // TODO: Implement 3732 } 3733 3734 void SAL_CALL ScChart2EmptyDataSequence::removeModifyListener( const uno::Reference< util::XModifyListener >& /*aListener*/ ) 3735 throw (uno::RuntimeException) 3736 { 3737 // TODO: Implement 3738 } 3739 3740 // DataSequence XPropertySet ------------------------------------------------- 3741 3742 uno::Reference< beans::XPropertySetInfo> SAL_CALL 3743 ScChart2EmptyDataSequence::getPropertySetInfo() throw( uno::RuntimeException) 3744 { 3745 ScUnoGuard aGuard; 3746 static uno::Reference<beans::XPropertySetInfo> aRef = 3747 new SfxItemPropertySetInfo( m_aPropSet.getPropertyMap() ); 3748 return aRef; 3749 } 3750 3751 3752 void SAL_CALL ScChart2EmptyDataSequence::setPropertyValue( 3753 const ::rtl::OUString& rPropertyName, const uno::Any& rValue) 3754 throw( beans::UnknownPropertyException, 3755 beans::PropertyVetoException, 3756 lang::IllegalArgumentException, 3757 lang::WrappedTargetException, uno::RuntimeException) 3758 { 3759 if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE))) 3760 { 3761 if ( !(rValue >>= m_aRole)) 3762 throw lang::IllegalArgumentException(); 3763 } 3764 else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS))) 3765 { 3766 if ( !(rValue >>= m_bIncludeHiddenCells)) 3767 throw lang::IllegalArgumentException(); 3768 } 3769 else 3770 throw beans::UnknownPropertyException(); 3771 // TODO: support optional properties 3772 } 3773 3774 3775 uno::Any SAL_CALL ScChart2EmptyDataSequence::getPropertyValue( 3776 const ::rtl::OUString& rPropertyName) 3777 throw( beans::UnknownPropertyException, 3778 lang::WrappedTargetException, uno::RuntimeException) 3779 { 3780 uno::Any aRet; 3781 if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE))) 3782 aRet <<= m_aRole; 3783 else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS))) 3784 aRet <<= m_bIncludeHiddenCells; 3785 else 3786 throw beans::UnknownPropertyException(); 3787 // TODO: support optional properties 3788 return aRet; 3789 } 3790 3791 3792 void SAL_CALL ScChart2EmptyDataSequence::addPropertyChangeListener( 3793 const ::rtl::OUString& /*rPropertyName*/, 3794 const uno::Reference< beans::XPropertyChangeListener>& /*xListener*/) 3795 throw( beans::UnknownPropertyException, 3796 lang::WrappedTargetException, uno::RuntimeException) 3797 { 3798 // FIXME: real implementation 3799 // throw uno::RuntimeException(); 3800 OSL_ENSURE( false, "Not yet implemented" ); 3801 } 3802 3803 3804 void SAL_CALL ScChart2EmptyDataSequence::removePropertyChangeListener( 3805 const ::rtl::OUString& /*rPropertyName*/, 3806 const uno::Reference< beans::XPropertyChangeListener>& /*rListener*/) 3807 throw( beans::UnknownPropertyException, 3808 lang::WrappedTargetException, uno::RuntimeException) 3809 { 3810 // FIXME: real implementation 3811 // throw uno::RuntimeException(); 3812 OSL_ENSURE( false, "Not yet implemented" ); 3813 } 3814 3815 3816 void SAL_CALL ScChart2EmptyDataSequence::addVetoableChangeListener( 3817 const ::rtl::OUString& /*rPropertyName*/, 3818 const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/) 3819 throw( beans::UnknownPropertyException, 3820 lang::WrappedTargetException, uno::RuntimeException) 3821 { 3822 // FIXME: real implementation 3823 // throw uno::RuntimeException(); 3824 OSL_ENSURE( false, "Not yet implemented" ); 3825 } 3826 3827 3828 void SAL_CALL ScChart2EmptyDataSequence::removeVetoableChangeListener( 3829 const ::rtl::OUString& /*rPropertyName*/, 3830 const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/ ) 3831 throw( beans::UnknownPropertyException, 3832 lang::WrappedTargetException, uno::RuntimeException) 3833 { 3834 // FIXME: real implementation 3835 // throw uno::RuntimeException(); 3836 OSL_ENSURE( false, "Not yet implemented" ); 3837 } 3838 3839 // XUnoTunnel 3840 3841 // sal_Int64 SAL_CALL ScChart2EmptyDataSequence::getSomething( 3842 // const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) 3843 // { 3844 // if ( rId.getLength() == 16 && 3845 // 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), 3846 // rId.getConstArray(), 16 ) ) 3847 // { 3848 // return (sal_Int64)this; 3849 // } 3850 // return 0; 3851 // } 3852 3853 // // static 3854 // const uno::Sequence<sal_Int8>& ScChart2EmptyDataSequence::getUnoTunnelId() 3855 // { 3856 // static uno::Sequence<sal_Int8> * pSeq = 0; 3857 // if( !pSeq ) 3858 // { 3859 // osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); 3860 // if( !pSeq ) 3861 // { 3862 // static uno::Sequence< sal_Int8 > aSeq( 16 ); 3863 // rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); 3864 // pSeq = &aSeq; 3865 // } 3866 // } 3867 // return *pSeq; 3868 // } 3869 3870 // // static 3871 // ScChart2DataSequence* ScChart2EmptyDataSequence::getImplementation( const uno::Reference<uno::XInterface> xObj ) 3872 // { 3873 // ScChart2DataSequence* pRet = NULL; 3874 // uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); 3875 // if (xUT.is()) 3876 // pRet = (ScChart2EmptyDataSequence*) xUT->getSomething( getUnoTunnelId() ); 3877 // return pRet; 3878 // } 3879 #endif 3880