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