merge the formfield patch from ooo-build
[ooovba.git] / sc / source / ui / unoobj / chart2uno.cxx
blobd6e6976a7b4cd846f231be7f8d2473a37b472184
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: chart2uno.cxx,v $
10 * $Revision: 1.11 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 #include "chart2uno.hxx"
35 #include "miscuno.hxx"
36 #include "document.hxx"
37 #include "unoguard.hxx"
38 #include "cell.hxx"
39 #include "chartpos.hxx"
40 #include "unonames.hxx"
41 #include "globstr.hrc"
42 #include "convuno.hxx"
43 #include "rangeutl.hxx"
44 #include "hints.hxx"
45 #include "unoreflist.hxx"
46 #include "compiler.hxx"
47 #include "reftokenhelper.hxx"
48 #include "chartlis.hxx"
50 #include <sfx2/objsh.hxx>
51 #include <tools/table.hxx>
53 #include <com/sun/star/beans/UnknownPropertyException.hpp>
54 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
55 #include <com/sun/star/table/XCellRange.hpp>
56 #include <com/sun/star/table/CellAddress.hpp>
57 #include <com/sun/star/text/XText.hpp>
58 #include <comphelper/extract.hxx>
60 #include <vector>
61 #include <list>
62 #include <rtl/math.hxx>
64 SC_SIMPLE_SERVICE_INFO( ScChart2DataProvider, "ScChart2DataProvider",
65 "com.sun.star.chart2.data.DataProvider")
66 SC_SIMPLE_SERVICE_INFO( ScChart2DataSource, "ScChart2DataSource",
67 "com.sun.star.chart2.data.DataSource")
68 SC_SIMPLE_SERVICE_INFO( ScChart2LabeledDataSequence, "ScChart2LabeledDataSequence",
69 "com.sun.star.chart2.data.LabeledDataSequence")
70 SC_SIMPLE_SERVICE_INFO( ScChart2DataSequence, "ScChart2DataSequence",
71 "com.sun.star.chart2.data.DataSequence")
72 #if USE_CHART2_EMPTYDATASEQUENCE
73 SC_SIMPLE_SERVICE_INFO( ScChart2EmptyDataSequence, "ScChart2EmptyDataSequence",
74 "com.sun.star.chart2.data.DataSequence")
75 #endif
77 using namespace ::com::sun::star;
78 using namespace ::formula;
79 using ::rtl::OUString;
80 using ::rtl::OUStringBuffer;
81 using ::com::sun::star::uno::Sequence;
82 using ::com::sun::star::uno::Reference;
83 using ::std::auto_ptr;
84 using ::std::vector;
85 using ::std::list;
86 using ::std::distance;
87 using ::std::unary_function;
88 using ::std::hash_set;
89 using ::boost::shared_ptr;
91 namespace
93 const SfxItemPropertyMapEntry* lcl_GetDataProviderPropertyMap()
95 static SfxItemPropertyMapEntry aDataProviderPropertyMap_Impl[] =
97 {MAP_CHAR_LEN(SC_UNONAME_INCLUDEHIDDENCELLS), 0, &getBooleanCppuType(), 0, 0 },
98 {0,0,0,0,0,0}
100 return aDataProviderPropertyMap_Impl;
103 const SfxItemPropertyMapEntry* lcl_GetDataSequencePropertyMap()
105 static SfxItemPropertyMapEntry aDataSequencePropertyMap_Impl[] =
107 {MAP_CHAR_LEN(SC_UNONAME_HIDDENVALUES), 0, &getCppuType((uno::Sequence<sal_Int32>*)0 ), 0, 0 },
108 {MAP_CHAR_LEN(SC_UNONAME_ROLE), 0, &getCppuType((::com::sun::star::chart2::data::DataSequenceRole*)0), 0, 0 },
109 {MAP_CHAR_LEN(SC_UNONAME_INCLUDEHIDDENCELLS), 0, &getBooleanCppuType(), 0, 0 },
110 {0,0,0,0,0,0}
112 return aDataSequencePropertyMap_Impl;
115 template< typename T >
116 ::com::sun::star::uno::Sequence< T > lcl_VectorToSequence(
117 const ::std::vector< T > & rCont )
119 ::com::sun::star::uno::Sequence< T > aResult( rCont.size());
120 ::std::copy( rCont.begin(), rCont.end(), aResult.getArray());
121 return aResult;
124 ::std::vector< ::rtl::OUString > lcl_getRangeRepresentationsFromDataSource(
125 const uno::Reference< chart2::data::XDataSource > & xDataSource )
127 ::std::vector< ::rtl::OUString > aResult;
128 if( xDataSource.is())
130 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences(
131 xDataSource->getDataSequences());
132 const sal_Int32 nCount( aSequences.getLength());
133 for( sal_Int32 nIdx=0; nIdx<nCount; ++nIdx )
135 if( aSequences[nIdx].is() )
137 // first: label
138 uno::Reference< chart2::data::XDataSequence > xSeq( aSequences[nIdx]->getLabel());
139 if( xSeq.is())
140 aResult.push_back( xSeq->getSourceRangeRepresentation());
141 // then: values
142 xSeq.set( aSequences[nIdx]->getValues());
143 if( xSeq.is())
144 aResult.push_back( xSeq->getSourceRangeRepresentation());
148 return aResult;
151 uno::Reference< chart2::data::XLabeledDataSequence > lcl_getCategoriesFromDataSource(
152 const uno::Reference< chart2::data::XDataSource > & xDataSource )
154 uno::Reference< chart2::data::XLabeledDataSequence > xResult;
155 if( xDataSource.is())
157 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences(
158 xDataSource->getDataSequences());
159 const sal_Int32 nCount( aSequences.getLength());
160 for( sal_Int32 nIdx=0; nIdx<nCount; ++nIdx )
162 if( aSequences[nIdx].is() )
164 uno::Reference< beans::XPropertySet > xSeqProp( aSequences[nIdx]->getValues(), uno::UNO_QUERY );
165 ::rtl::OUString aRole;
166 if( xSeqProp.is() &&
167 (xSeqProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Role"))) >>= aRole) &&
168 aRole.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("categories")) )
170 xResult.set( aSequences[nIdx] );
171 break;
176 return xResult;
179 struct lcl_appendTableNumber : public ::std::unary_function< SCTAB, void >
181 lcl_appendTableNumber( ::rtl::OUStringBuffer & rBuffer ) :
182 m_rBuffer( rBuffer )
184 void operator() ( SCTAB nTab )
186 // there is no append with SCTAB or sal_Int16
187 m_rBuffer.append( static_cast< sal_Int32 >( nTab ));
188 m_rBuffer.append( sal_Unicode( ' ' ));
190 private:
191 ::rtl::OUStringBuffer & m_rBuffer;
194 ::rtl::OUString lcl_createTableNumberList( const ::std::list< SCTAB > & rTableList )
196 ::rtl::OUStringBuffer aBuffer;
197 ::std::for_each( rTableList.begin(), rTableList.end(), lcl_appendTableNumber( aBuffer ));
198 // remove last trailing ' '
199 if( aBuffer.getLength() > 0 )
200 aBuffer.setLength( aBuffer.getLength() - 1 );
201 return aBuffer.makeStringAndClear();
204 uno::Reference< frame::XModel > lcl_GetXModel( ScDocument * pDoc )
206 uno::Reference< frame::XModel > xModel;
207 SfxObjectShell * pObjSh( pDoc ? pDoc->GetDocumentShell() : 0 );
208 if( pObjSh )
209 xModel.set( pObjSh->GetModel());
210 return xModel;
213 uno::Reference< sheet::XSpreadsheetDocument > lcl_GetSpreadSheetDocument( ScDocument * pDoc )
215 return uno::Reference< sheet::XSpreadsheetDocument >( lcl_GetXModel( pDoc ), uno::UNO_QUERY );
218 // ============================================================================
220 class Chart2PositionMap
222 public:
223 Chart2PositionMap(SCCOL nColCount, SCROW nRowCount,
224 bool bColAdd, bool bRowAdd, Table& rCols);
225 ~Chart2PositionMap();
227 SCCOL getColCount() const { return static_cast<SCCOL>(maColHeaders.size()); }
228 SCROW getRowCount() const { return static_cast<SCROW>(maRowHeaders.size()); }
230 const FormulaToken* getColHeaderPosition(SCCOL nChartCol) const;
231 const FormulaToken* getRowHeaderPosition(SCROW nChartRow) const;
233 vector<ScSharedTokenRef>* getColRanges(SCCOL nCol) const;
234 vector<ScSharedTokenRef>* getRowRanges(SCROW nRow) const;
237 private:
238 sal_uInt32 getIndex(SCCOL nCol, SCROW nRow) const
240 return static_cast<sal_uInt32>(nCol*getRowCount() + nRow);
243 private:
244 vector<FormulaToken*> maRowHeaders;
245 vector<FormulaToken*> maColHeaders;
246 vector<FormulaToken*> maData;
249 Chart2PositionMap::Chart2PositionMap(SCCOL nColCount, SCROW nRowCount,
250 bool bColAdd, bool bRowAdd, Table& rCols)
252 // bColAdd is true when the first column serves as a row header. Likewise,
253 // when bRowAdd is true the first row serves as a column header.
255 maColHeaders.reserve(nColCount);
256 maRowHeaders.reserve(nRowCount);
257 maData.reserve(nColCount*nRowCount);
259 Table* pCol = static_cast<Table*>(rCols.First());
260 FormulaToken* pPos = static_cast<FormulaToken*>(pCol->First());
262 if (bRowAdd)
263 pPos = static_cast<FormulaToken*>(pCol->Next());
265 if (bColAdd)
267 // 1st column as a row header.
268 for (SCROW nRow = 0; nRow < nRowCount; ++nRow)
270 maRowHeaders.push_back(pPos);
271 pPos = static_cast<FormulaToken*>(pCol->Next());
273 pCol = static_cast<Table*>(rCols.Next()); // move to the next column.
275 else
277 for (SCROW nRow = 0; nRow < nRowCount; ++nRow)
279 // Make a copy.
280 maRowHeaders.push_back(pPos ? pPos->Clone() : NULL);
281 pPos = static_cast<FormulaToken*>(pCol->Next());
285 // Data in columns and in column headers.
286 for (SCCOL nCol = 0; nCol < nColCount; ++nCol)
288 if (pCol)
290 pPos = static_cast<FormulaToken*>(pCol->First());
291 if (bRowAdd)
293 // 1st row as a column header.
294 maColHeaders.push_back(pPos);
295 pPos = static_cast<FormulaToken*>(pCol->Next());
297 else
298 // Duplicate the 1st cell as a column header.
299 maColHeaders.push_back(pPos ? pPos->Clone() : NULL);
301 for (SCROW nRow = 0; nRow < nRowCount; ++nRow)
303 maData.push_back(pPos);
304 pPos = static_cast<FormulaToken*>(pCol->Next());
307 else
309 // the entire column is empty.
310 maColHeaders.push_back(NULL);
311 for (SCROW nRow = 0; nRow < nRowCount; ++nRow)
312 maData.push_back(NULL);
314 pCol = static_cast<Table*>(rCols.Next());
318 namespace {
320 struct DeleteInstance : public unary_function<FormulaToken*, void>
322 void operator() (FormulaToken* p) const
324 delete p;
330 Chart2PositionMap::~Chart2PositionMap()
332 for_each(maColHeaders.begin(), maColHeaders.end(), DeleteInstance());
333 for_each(maRowHeaders.begin(), maRowHeaders.end(), DeleteInstance());
334 for_each(maData.begin(), maData.end(), DeleteInstance());
337 const FormulaToken* Chart2PositionMap::getColHeaderPosition(SCCOL nCol) const
339 if (nCol < getColCount())
340 return maColHeaders[nCol];
341 return NULL;
343 const FormulaToken* Chart2PositionMap::getRowHeaderPosition(SCROW nRow) const
345 if (nRow < getRowCount())
346 return maRowHeaders[nRow];
347 return NULL;
350 vector<ScSharedTokenRef>* Chart2PositionMap::getColRanges(SCCOL nCol) const
352 if (nCol >= getColCount())
353 return NULL;
355 auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>);
356 sal_uInt32 nStop = getIndex(nCol, getRowCount());
357 for (sal_uInt32 i = getIndex(nCol, 0); i < nStop; ++i)
359 FormulaToken* p = maData[i];
360 if (!p)
361 continue;
363 ScSharedTokenRef pCopy(static_cast<ScToken*>(p->Clone()));
364 ScRefTokenHelper::join(*pTokens, pCopy);
366 return pTokens.release();
369 vector<ScSharedTokenRef>* Chart2PositionMap::getRowRanges(SCROW nRow) const
371 SCROW nRowCount = getRowCount();
372 if (nRow >= nRowCount)
373 return NULL;
375 auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>);
376 sal_uInt32 nStop = getIndex(getColCount(), nRow);
377 for (sal_uInt32 i = getIndex(0, nRow); i < nStop; i += nRowCount)
379 FormulaToken* p = maData[i];
380 if (!p)
381 continue;
383 ScSharedTokenRef p2(static_cast<ScToken*>(p->Clone()));
384 ScRefTokenHelper::join(*pTokens, p2);
386 return pTokens.release();
389 // ----------------------------------------------------------------------------
392 * Designed to be a drop-in replacement for ScChartPositioner, in order to
393 * handle external references.
395 class Chart2Positioner
397 enum GlueType
399 GLUETYPE_NA,
400 GLUETYPE_NONE,
401 GLUETYPE_COLS,
402 GLUETYPE_ROWS,
403 GLUETYPE_BOTH
406 public:
407 Chart2Positioner(ScDocument* pDoc, const vector<ScSharedTokenRef>& rRefTokens) :
408 mpRefTokens(new vector<ScSharedTokenRef>(rRefTokens)),
409 mpPositionMap(NULL),
410 meGlue(GLUETYPE_NA),
411 mpDoc(pDoc),
412 mbColHeaders(false),
413 mbRowHeaders(false),
414 mbDummyUpperLeft(false)
418 ~Chart2Positioner()
422 void setHeaders(bool bColHeaders, bool bRowHeaders)
424 mbColHeaders = bColHeaders;
425 mbRowHeaders = bRowHeaders;
428 bool hasColHeaders() const { return mbColHeaders; }
429 bool hasRowHeaders() const { return mbRowHeaders; }
431 Chart2PositionMap* getPositionMap()
433 createPositionMap();
434 return mpPositionMap.get();
437 private:
438 Chart2Positioner(); // disabled
440 void invalidateGlue();
441 void glueState();
442 void createPositionMap();
444 private:
445 shared_ptr< vector<ScSharedTokenRef> > mpRefTokens;
446 auto_ptr<Chart2PositionMap> mpPositionMap;
447 GlueType meGlue;
448 SCCOL mnStartCol;
449 SCROW mnStartRow;
450 ScDocument* mpDoc;
451 bool mbColHeaders:1;
452 bool mbRowHeaders:1;
453 bool mbDummyUpperLeft:1;
456 void Chart2Positioner::invalidateGlue()
458 meGlue = GLUETYPE_NA;
459 mpPositionMap.reset(NULL);
462 void Chart2Positioner::glueState()
464 if (meGlue != GLUETYPE_NA)
465 return;
467 mbDummyUpperLeft = false;
468 if (mpRefTokens->size() <= 1)
470 const ScSharedTokenRef& p = mpRefTokens->front();
471 ScComplexRefData aData;
472 if (ScRefTokenHelper::getDoubleRefDataFromToken(aData, p))
474 if (aData.Ref1.nTab == aData.Ref2.nTab)
475 meGlue = GLUETYPE_NONE;
476 else
477 meGlue = GLUETYPE_COLS;
478 mnStartCol = aData.Ref1.nCol;
479 mnStartRow = aData.Ref1.nRow;
481 else
483 invalidateGlue();
484 mnStartCol = 0;
485 mnStartRow = 0;
487 return;
490 ScComplexRefData aData;
491 ScRefTokenHelper::getDoubleRefDataFromToken(aData, mpRefTokens->front());
492 mnStartCol = aData.Ref1.nCol;
493 mnStartRow = aData.Ref1.nRow;
495 SCCOL nMaxCols = 0, nEndCol = 0;
496 SCROW nMaxRows = 0, nEndRow = 0;
497 for (vector<ScSharedTokenRef>::const_iterator itr = mpRefTokens->begin(), itrEnd = mpRefTokens->end()
498 ; itr != itrEnd; ++itr)
500 ScRefTokenHelper::getDoubleRefDataFromToken(aData, *itr);
501 SCCOLROW n1 = aData.Ref1.nCol;
502 SCCOLROW n2 = aData.Ref2.nCol;
503 if (n1 > MAXCOL)
504 n1 = MAXCOL;
505 if (n2 > MAXCOL)
506 n2 = MAXCOL;
507 SCCOLROW nTmp = n2 - n1 + 1;
508 if (n1 < mnStartCol)
509 mnStartCol = static_cast<SCCOL>(n1);
510 if (n2 > nEndCol)
511 nEndCol = static_cast<SCCOL>(n2);
512 if (nTmp > nMaxCols)
513 nMaxCols = static_cast<SCCOL>(nTmp);
515 n1 = aData.Ref1.nRow;
516 n2 = aData.Ref2.nRow;
517 if (n1 > MAXROW)
518 n1 = MAXROW;
519 if (n2 > MAXROW)
520 n2 = MAXROW;
521 nTmp = n2 - n1 + 1;
523 if (n1 < mnStartRow)
524 mnStartRow = static_cast<SCROW>(n1);
525 if (n2 > nEndRow)
526 nEndRow = static_cast<SCROW>(n2);
527 if (nTmp > nMaxRows)
528 nMaxRows = static_cast<SCROW>(nTmp);
531 // total column size ?
532 SCCOL nC = nEndCol - mnStartCol + 1;
533 if (nC == 1)
535 meGlue = GLUETYPE_ROWS;
536 return;
538 // total row size ?
539 SCROW nR = nEndRow - mnStartRow + 1;
540 if (nR == 1)
542 meGlue = GLUETYPE_COLS;
543 return;
545 // #i103540# prevent invalid vector size
546 if ((nC <= 0) || (nR <= 0))
548 invalidateGlue();
549 mnStartCol = 0;
550 mnStartRow = 0;
551 return;
553 sal_uInt32 nCR = static_cast<sal_uInt32>(nC*nR);
555 const sal_uInt8 nHole = 0;
556 const sal_uInt8 nOccu = 1;
557 const sal_uInt8 nFree = 2;
558 const sal_uInt8 nGlue = 3;
560 vector<sal_uInt8> aCellStates(nCR);
561 for (vector<ScSharedTokenRef>::const_iterator itr = mpRefTokens->begin(), itrEnd = mpRefTokens->end();
562 itr != itrEnd; ++itr)
564 ScRefTokenHelper::getDoubleRefDataFromToken(aData, *itr);
565 SCCOL nCol1 = static_cast<SCCOL>(aData.Ref1.nCol) - mnStartCol;
566 SCCOL nCol2 = static_cast<SCCOL>(aData.Ref2.nCol) - mnStartCol;
567 SCROW nRow1 = static_cast<SCROW>(aData.Ref1.nRow) - mnStartRow;
568 SCROW nRow2 = static_cast<SCROW>(aData.Ref2.nRow) - mnStartRow;
569 for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
570 for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
572 size_t i = nCol*nR + nRow;
573 aCellStates[i] = nOccu;
576 bool bGlue = true;
578 size_t i = 0;
579 bool bGlueCols = false;
580 for (SCCOL nCol = 0; bGlue && nCol < nC; ++nCol)
582 for (SCROW nRow = 0; bGlue && nRow < nR; ++nRow)
584 i = nCol*nR + nRow;
585 if (aCellStates[i] == nOccu)
587 if (nRow > 0 && nRow > 0)
588 bGlue = false;
589 else
590 nRow = nR;
592 else
593 aCellStates[i] = nFree;
595 i = (nCol+1)*nR - 1; // index for the last cell in the column.
596 if (bGlue && (aCellStates[i] == nFree))
598 aCellStates[i] = nGlue;
599 bGlueCols = true;
603 bool bGlueRows = false;
604 for (SCROW nRow = 0; bGlue && nRow < nR; ++nRow)
606 i = nRow;
607 for (SCCOL nCol = 0; bGlue && nCol < nC; ++nCol, i += nR)
609 if (aCellStates[i] == nOccu)
611 if (nCol > 0 && nRow > 0)
612 bGlue = false;
613 else
614 nCol = nC;
616 else
617 aCellStates[i] = nFree;
619 i = (nC-1)*nR + nRow; // index for the row position in the last column.
620 if (bGlue && aCellStates[i] == nFree)
622 aCellStates[i] = nGlue;
623 bGlueRows = true;
627 i = 1;
628 for (sal_uInt32 n = 1; bGlue && n < nCR; ++n, ++i)
629 if (aCellStates[i] == nHole)
630 bGlue = false;
632 if (bGlue)
634 if (bGlueCols && bGlueRows)
635 meGlue = GLUETYPE_BOTH;
636 else if (bGlueRows)
637 meGlue = GLUETYPE_ROWS;
638 else
639 meGlue = GLUETYPE_COLS;
640 if (aCellStates.front() != nOccu)
641 mbDummyUpperLeft = true;
643 else
644 meGlue = GLUETYPE_NONE;
647 void Chart2Positioner::createPositionMap()
649 if (meGlue == GLUETYPE_NA && mpPositionMap.get())
650 mpPositionMap.reset(NULL);
652 if (mpPositionMap.get())
653 return;
655 glueState();
657 bool bNoGlue = (meGlue == GLUETYPE_NONE);
658 auto_ptr<Table> pCols(new Table);
659 auto_ptr<FormulaToken> pNewAddress;
660 auto_ptr<Table> pNewRowTable(new Table);
661 Table* pCol = NULL;
662 SCROW nNoGlueRow = 0;
663 for (vector<ScSharedTokenRef>::const_iterator itr = mpRefTokens->begin(), itrEnd = mpRefTokens->end();
664 itr != itrEnd; ++itr)
666 const ScSharedTokenRef& pToken = *itr;
668 bool bExternal = ScRefTokenHelper::isExternalRef(pToken);
669 sal_uInt16 nFileId = bExternal ? pToken->GetIndex() : 0;
670 String aTabName = bExternal ? pToken->GetString() : String();
672 ScComplexRefData aData;
673 ScRefTokenHelper::getDoubleRefDataFromToken(aData, *itr);
674 const ScSingleRefData& s = aData.Ref1;
675 const ScSingleRefData& e = aData.Ref2;
676 SCCOL nCol1 = s.nCol, nCol2 = e.nCol;
677 SCROW nRow1 = s.nRow, nRow2 = e.nRow;
678 SCTAB nTab1 = s.nTab, nTab2 = e.nTab;
680 for (SCTAB nTab = nTab1; nTab <= nTab2; ++nTab)
682 // What's this for ???
683 sal_uInt32 nInsCol = (static_cast<sal_uInt32>(nTab) << 16) |
684 (bNoGlue ? 0 : static_cast<sal_uInt32>(nCol1));
685 for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol, ++nInsCol)
687 if (bNoGlue || meGlue == GLUETYPE_ROWS)
689 pCol = static_cast<Table*>(pCols->Get(nInsCol));
690 if (!pCol)
692 pCol = pNewRowTable.get();
693 pCols->Insert(nInsCol, pNewRowTable.release());
694 pNewRowTable.reset(new Table);
697 else
699 if (pCols->Insert(nInsCol, pNewRowTable.get()))
701 pCol = pNewRowTable.release();
702 pNewRowTable.reset(new Table);
704 else
705 pCol = static_cast<Table*>(pCols->Get(nInsCol));
708 sal_uInt32 nInsRow = static_cast<sal_uInt32>(bNoGlue ? nNoGlueRow : nRow1);
709 for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow, ++nInsRow)
711 ScSingleRefData aCellData;
712 aCellData.InitFlags();
713 aCellData.SetFlag3D(true);
714 aCellData.SetColRel(false);
715 aCellData.SetRowRel(false);
716 aCellData.SetTabRel(false);
717 aCellData.nCol = nCol;
718 aCellData.nRow = nRow;
719 aCellData.nTab = nTab;
721 if (bExternal)
722 pNewAddress.reset(new ScExternalSingleRefToken(nFileId, aTabName, aCellData));
723 else
724 pNewAddress.reset(new ScSingleRefToken(aCellData));
726 if (pCol->Insert(nInsRow, pNewAddress.get()))
727 pNewAddress.release(); // To prevent the instance from being destroyed.
731 nNoGlueRow += nRow2 - nRow1 + 1;
733 pNewAddress.reset(NULL);
734 pNewRowTable.reset(NULL);
736 bool bColAdd = mbRowHeaders;
737 bool bRowAdd = mbColHeaders;
739 SCSIZE nColCount = static_cast<SCSIZE>(pCols->Count());
740 SCSIZE nRowCount = 0;
741 pCol = static_cast<Table*>(pCols->First());
742 if (pCol)
744 if (mbDummyUpperLeft)
745 pCol->Insert(0, NULL); // Dummy fuer Beschriftung
746 nRowCount = static_cast<SCSIZE>(pCol->Count());
748 else
749 nRowCount = 0;
751 if (nColCount > 0 && bColAdd)
752 nColCount -= 1;
753 if (nRowCount > 0 && bRowAdd)
754 nRowCount -= 1;
756 if (nColCount == 0 || nRowCount == 0)
758 ScComplexRefData aData;
759 ScRefTokenHelper::getDoubleRefDataFromToken(aData, mpRefTokens->front());
760 if (pCols->Count() > 0)
761 pCol = static_cast<Table*>(pCols->First());
762 else
764 pCol = new Table;
765 pCols->Insert(0, pCol);
767 nColCount = 1;
768 if (pCol->Count() > 0)
770 FormulaToken* pPos = static_cast<FormulaToken*>(pCol->First());
771 if (pPos)
773 delete pPos;
774 pCol->Replace(pCol->GetCurKey(), NULL);
777 else
778 pCol->Insert(0, NULL);
780 nRowCount = 1;
781 bColAdd = false;
782 bRowAdd = false;
784 else
786 if (bNoGlue)
788 Table* pFirstCol = static_cast<Table*>(pCols->First());
789 sal_uInt32 nCount = pFirstCol->Count();
790 pFirstCol->First();
791 for (sal_uInt32 n = 0; n < nCount; ++n, pFirstCol->Next())
793 sal_uInt32 nKey = pFirstCol->GetCurKey();
794 pCols->First();
795 for (pCol = static_cast<Table*>(pCols->Next()); pCol; pCol = static_cast<Table*>(pCols->Next()))
796 pCol->Insert(nKey, NULL);
800 mpPositionMap.reset(
801 new Chart2PositionMap(
802 static_cast<SCCOL>(nColCount), static_cast<SCROW>(nRowCount),
803 bColAdd, bRowAdd, *pCols));
805 // Destroy all column instances.
806 for (pCol = static_cast<Table*>(pCols->First()); pCol; pCol = static_cast<Table*>(pCols->Next()))
807 delete pCol;
810 // ============================================================================
812 /**
813 * Function object to create a range string from a token list.
815 class Tokens2RangeString : public unary_function<ScSharedTokenRef, void>
817 public:
818 Tokens2RangeString(ScDocument* pDoc, FormulaGrammar::Grammar eGram, sal_Unicode cRangeSep) :
819 mpRangeStr(new OUStringBuffer),
820 mpDoc(pDoc),
821 meGrammar(eGram),
822 mcRangeSep(cRangeSep),
823 mbFirst(true)
827 Tokens2RangeString(const Tokens2RangeString& r) :
828 mpRangeStr(r.mpRangeStr),
829 mpDoc(r.mpDoc),
830 meGrammar(r.meGrammar),
831 mcRangeSep(r.mcRangeSep),
832 mbFirst(r.mbFirst)
836 void operator() (const ScSharedTokenRef& rToken)
838 ScCompiler aCompiler(mpDoc, ScAddress(0,0,0));
839 aCompiler.SetGrammar(meGrammar);
840 String aStr;
841 aCompiler.CreateStringFromToken(aStr, rToken.get());
842 if (mbFirst)
843 mbFirst = false;
844 else
845 mpRangeStr->append(mcRangeSep);
846 mpRangeStr->append(aStr);
849 void getString(OUString& rStr)
851 rStr = mpRangeStr->makeStringAndClear();
854 private:
855 Tokens2RangeString(); // disabled
857 private:
858 shared_ptr<OUStringBuffer> mpRangeStr;
859 ScDocument* mpDoc;
860 FormulaGrammar::Grammar meGrammar;
861 sal_Unicode mcRangeSep;
862 bool mbFirst;
865 /**
866 * Function object to convert a list of tokens into a string form suitable
867 * for ODF export. In ODF, a range is expressed as
869 * (start cell address):(end cell address)
871 * and each address doesn't include any '$' symbols.
873 class Tokens2RangeStringXML : public unary_function<ScSharedTokenRef, void>
875 public:
876 Tokens2RangeStringXML(ScDocument* pDoc) :
877 mpRangeStr(new OUStringBuffer),
878 mpDoc(pDoc),
879 mcRangeSep(' '),
880 mcAddrSep(':'),
881 mbFirst(true)
885 Tokens2RangeStringXML(const Tokens2RangeStringXML& r) :
886 mpRangeStr(r.mpRangeStr),
887 mpDoc(r.mpDoc),
888 mcRangeSep(r.mcRangeSep),
889 mcAddrSep(r.mcAddrSep),
890 mbFirst(r.mbFirst)
894 void operator() (const ScSharedTokenRef& rToken)
896 if (mbFirst)
897 mbFirst = false;
898 else
899 mpRangeStr->append(mcRangeSep);
901 ScSharedTokenRef aStart, aEnd;
902 splitRangeToken(rToken, aStart, aEnd);
903 ScCompiler aCompiler(mpDoc, ScAddress(0,0,0));
904 aCompiler.SetGrammar(FormulaGrammar::GRAM_ENGLISH);
906 String aStr;
907 aCompiler.CreateStringFromToken(aStr, aStart.get());
908 mpRangeStr->append(aStr);
910 mpRangeStr->append(mcAddrSep);
912 String aStr;
913 aCompiler.CreateStringFromToken(aStr, aEnd.get());
914 mpRangeStr->append(aStr);
918 void getString(OUString& rStr)
920 rStr = mpRangeStr->makeStringAndClear();
923 private:
924 Tokens2RangeStringXML(); // disabled
926 void splitRangeToken(const ScSharedTokenRef& pToken, ScSharedTokenRef& rStart, ScSharedTokenRef& rEnd) const
928 ScComplexRefData aData;
929 ScRefTokenHelper::getDoubleRefDataFromToken(aData, pToken);
930 bool bExternal = ScRefTokenHelper::isExternalRef(pToken);
931 sal_uInt16 nFileId = bExternal ? pToken->GetIndex() : 0;
932 String aTabName = bExternal ? pToken->GetString() : String();
934 // In saving to XML, we don't prepend address with '$'.
935 setRelative(aData.Ref1);
936 setRelative(aData.Ref2);
938 // In XML, the end range must explicitly specify sheet name.
939 aData.Ref2.SetFlag3D(true);
941 if (bExternal)
942 rStart.reset(new ScExternalSingleRefToken(nFileId, aTabName, aData.Ref1));
943 else
944 rStart.reset(new ScSingleRefToken(aData.Ref1));
946 if (bExternal)
947 rEnd.reset(new ScExternalSingleRefToken(nFileId, aTabName, aData.Ref2));
948 else
949 rEnd.reset(new ScSingleRefToken(aData.Ref2));
952 void setRelative(ScSingleRefData& rData) const
954 rData.SetColRel(true);
955 rData.SetRowRel(true);
956 rData.SetTabRel(true);
959 private:
960 shared_ptr<OUStringBuffer> mpRangeStr;
961 ScDocument* mpDoc;
962 sal_Unicode mcRangeSep;
963 sal_Unicode mcAddrSep;
964 bool mbFirst;
967 void lcl_convertTokensToString(OUString& rStr, const vector<ScSharedTokenRef>& rTokens, ScDocument* pDoc)
969 const sal_Unicode cRangeSep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
970 FormulaGrammar::Grammar eGrammar = pDoc->GetGrammar();
971 Tokens2RangeString func(pDoc, eGrammar, cRangeSep);
972 func = for_each(rTokens.begin(), rTokens.end(), func);
973 func.getString(rStr);
976 } // anonymous namespace
978 // DataProvider ==============================================================
980 ScChart2DataProvider::ScChart2DataProvider( ScDocument* pDoc )
981 : m_pDocument( pDoc)
982 , m_aPropSet(lcl_GetDataProviderPropertyMap())
983 , m_bIncludeHiddenCells( sal_True)
985 if ( m_pDocument )
986 m_pDocument->AddUnoObject( *this);
989 ScChart2DataProvider::~ScChart2DataProvider()
991 if ( m_pDocument )
992 m_pDocument->RemoveUnoObject( *this);
996 void ScChart2DataProvider::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
998 if ( rHint.ISA( SfxSimpleHint ) &&
999 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
1001 m_pDocument = NULL;
1005 ::sal_Bool SAL_CALL ScChart2DataProvider::createDataSourcePossible( const uno::Sequence< beans::PropertyValue >& aArguments )
1006 throw (uno::RuntimeException)
1008 ScUnoGuard aGuard;
1009 if( ! m_pDocument )
1010 return false;
1012 rtl::OUString aRangeRepresentation;
1013 for(sal_Int32 i = 0; i < aArguments.getLength(); ++i)
1015 rtl::OUString sName(aArguments[i].Name);
1016 if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CellRangeRepresentation")))
1018 aArguments[i].Value >>= aRangeRepresentation;
1022 vector<ScSharedTokenRef> aTokens;
1023 ScRefTokenHelper::compileRangeRepresentation(aTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar());
1024 return !aTokens.empty();
1027 namespace {
1029 class RemoveHeaderFromRanges : public unary_function<ScSharedTokenRef, void>
1031 public:
1032 RemoveHeaderFromRanges(const ScSharedTokenRef& rHeaderCell, bool bOrientCol) :
1033 mpTokens(new vector<ScSharedTokenRef>),
1034 mpHeaderCell(rHeaderCell),
1035 mbOrientCol(bOrientCol)
1039 RemoveHeaderFromRanges(const RemoveHeaderFromRanges& r) :
1040 mpTokens(r.mpTokens),
1041 mpHeaderCell(r.mpHeaderCell),
1042 mbOrientCol(r.mbOrientCol)
1046 void operator() (const ScSharedTokenRef& pRange)
1048 if (!isContained(pRange))
1050 // header cell is not part of this range. Just add it to the
1051 // range list and move on.
1052 ScRefTokenHelper::join(*mpTokens, pRange);
1053 return;
1056 // This range contains the header cell.
1058 ScComplexRefData aRange;
1059 ScRefTokenHelper::getDoubleRefDataFromToken(aRange, pRange);
1060 const ScSingleRefData& s = aRange.Ref1;
1061 const ScSingleRefData& e = aRange.Ref2;
1062 const ScSingleRefData& h = mpHeaderCell->GetSingleRef();
1064 if (equals(s, e))
1065 // This range *only* contains the header cell. Skip it.
1066 return;
1068 if (s.nTab != e.nTab)
1069 // 3D range has no business being here....
1070 return;
1072 if (mbOrientCol)
1074 // column major
1076 if (s.nCol == e.nCol)
1078 // single column range.
1079 splitSingleColRange(pRange, s, e);
1081 else
1083 if (s.nCol == h.nCol)
1085 // header cell is in the first column.
1088 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1089 ScComplexRefData& r = pNew->GetDoubleRef();
1090 r.Ref2.InitAddress(s.nCol, e.nRow, s.nTab);
1091 splitSingleColRange(pNew, r.Ref1, r.Ref2);
1095 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1096 ScComplexRefData& r = pNew->GetDoubleRef();
1097 r.Ref1.InitAddress(s.nCol + 1, s.nRow, s.nTab);
1098 ScRefTokenHelper::join(*mpTokens, pNew);
1101 else if (e.nCol == h.nCol)
1103 // header cell is in the last column.
1106 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1107 ScComplexRefData& r = pNew->GetDoubleRef();
1108 r.Ref1.InitAddress(e.nCol, s.nRow, s.nTab);
1109 splitSingleColRange(pNew, r.Ref1, r.Ref2);
1113 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1114 ScComplexRefData& r = pNew->GetDoubleRef();
1115 r.Ref2.InitAddress(e.nCol - 1, e.nRow, e.nTab);
1116 ScRefTokenHelper::join(*mpTokens, pNew);
1119 else
1121 // header cell is somewhere between the first and last columns.
1124 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1125 ScComplexRefData& r = pNew->GetDoubleRef();
1126 r.Ref2.InitAddress(h.nCol - 1, e.nRow, h.nTab);
1127 ScRefTokenHelper::join(*mpTokens, pNew);
1131 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1132 ScComplexRefData& r = pNew->GetDoubleRef();
1133 r.Ref1.InitAddress(h.nCol, s.nRow, s.nTab);
1134 r.Ref2.InitAddress(h.nCol, e.nRow, e.nTab);
1135 splitSingleColRange(pNew, r.Ref1, r.Ref2);
1139 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1140 ScComplexRefData& r = pNew->GetDoubleRef();
1141 r.Ref1.InitAddress(h.nCol + 1, s.nRow, h.nTab);
1142 ScRefTokenHelper::join(*mpTokens, pNew);
1147 else
1149 // row major
1151 if (s.nRow == e.nRow)
1153 // Single row range.
1154 splitSingleRowRange(pRange, s, e);
1156 else
1158 if (s.nRow == h.nRow)
1160 // header cell is in the first row.
1163 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1164 ScComplexRefData& r = pNew->GetDoubleRef();
1165 r.Ref2.InitAddress(e.nCol, s.nRow, s.nTab);
1166 splitSingleRowRange(pNew, r.Ref1, r.Ref2);
1170 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1171 ScComplexRefData& r = pNew->GetDoubleRef();
1172 r.Ref1.InitAddress(s.nCol, s.nRow + 1, s.nTab);
1173 ScRefTokenHelper::join(*mpTokens, pNew);
1176 else if (e.nRow == h.nRow)
1178 // header cell is in the last row.
1181 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1182 ScComplexRefData& r = pNew->GetDoubleRef();
1183 r.Ref1.InitAddress(s.nCol, e.nRow, s.nTab);
1184 splitSingleRowRange(pNew, r.Ref1, r.Ref2);
1188 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1189 ScComplexRefData& r = pNew->GetDoubleRef();
1190 r.Ref2.InitAddress(e.nCol, e.nRow - 1, e.nTab);
1191 ScRefTokenHelper::join(*mpTokens, pNew);
1194 else
1196 // header cell is somewhere between the 1st and last rows.
1199 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1200 ScComplexRefData& r = pNew->GetDoubleRef();
1201 r.Ref2.InitAddress(e.nCol, h.nRow - 1, h.nTab);
1202 ScRefTokenHelper::join(*mpTokens, pNew);
1206 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1207 ScComplexRefData& r = pNew->GetDoubleRef();
1208 r.Ref1.InitAddress(s.nCol, h.nRow, s.nTab);
1209 r.Ref2.InitAddress(e.nCol, h.nRow, e.nTab);
1210 splitSingleRowRange(pNew, r.Ref1, r.Ref2);
1214 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1215 ScComplexRefData& r = pNew->GetDoubleRef();
1216 r.Ref1.InitAddress(s.nCol, h.nRow + 1, h.nTab);
1217 ScRefTokenHelper::join(*mpTokens, pNew);
1224 void getNewTokens(vector<ScSharedTokenRef>& rTokens)
1226 mpTokens->swap(rTokens);
1229 private:
1231 void splitSingleColRange(const ScSharedTokenRef& pRange, const ScSingleRefData& s, const ScSingleRefData& e)
1233 const ScSingleRefData& h = mpHeaderCell->GetSingleRef();
1235 if (equals(s, h))
1237 // header is at the top.
1239 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1240 ScComplexRefData& r = pNew->GetDoubleRef();
1241 r.Ref1.nRow += 1;
1242 ScRefTokenHelper::join(*mpTokens, pNew);
1244 else if (equals(e, h))
1246 // header is at the bottom.
1248 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1249 ScComplexRefData& r = pNew->GetDoubleRef();
1250 r.Ref2.nRow -= 1;
1251 ScRefTokenHelper::join(*mpTokens, pNew);
1253 else
1255 // header is somewhere in the middle.
1258 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1259 ScComplexRefData& r = pNew->GetDoubleRef();
1260 r.Ref2.InitAddress(h.nCol, h.nRow - 1, h.nTab);
1261 ScRefTokenHelper::join(*mpTokens, pNew);
1265 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1266 ScComplexRefData& r = pNew->GetDoubleRef();
1267 r.Ref1.InitAddress(h.nCol, h.nRow + 1, h.nTab);
1268 ScRefTokenHelper::join(*mpTokens, pNew);
1273 void splitSingleRowRange(const ScSharedTokenRef& pRange, const ScSingleRefData& s, const ScSingleRefData& e)
1275 const ScSingleRefData& h = mpHeaderCell->GetSingleRef();
1277 if (equals(s, h))
1279 // header is at the top.
1281 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1282 ScComplexRefData& r = pNew->GetDoubleRef();
1283 r.Ref1.nCol += 1;
1284 ScRefTokenHelper::join(*mpTokens, pNew);
1286 else if (equals(e, h))
1288 // header is at the bottom.
1290 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1291 ScComplexRefData& r = pNew->GetDoubleRef();
1292 r.Ref2.nCol -= 1;
1293 ScRefTokenHelper::join(*mpTokens, pNew);
1295 else
1297 // header is somewhere in the middle.
1300 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1301 ScComplexRefData& r = pNew->GetDoubleRef();
1302 r.Ref2.InitAddress(h.nCol - 1, h.nRow, h.nTab);
1303 ScRefTokenHelper::join(*mpTokens, pNew);
1307 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1308 ScComplexRefData& r = pNew->GetDoubleRef();
1309 r.Ref1.InitAddress(h.nCol + 1, h.nRow, h.nTab);
1310 ScRefTokenHelper::join(*mpTokens, pNew);
1315 /**
1316 * Compare two single ref data for equality, but only compare their
1317 * absolute cell addresses while ignoring flags and relative addresses.
1319 bool equals(const ScSingleRefData& r1, const ScSingleRefData& r2) const
1321 return (r1.nCol == r2.nCol) && (r1.nRow == r2.nRow) && (r1.nTab == r2.nTab);
1324 bool isContained(const ScSharedTokenRef& pRange)
1326 bool bExternal = ScRefTokenHelper::isExternalRef(mpHeaderCell);
1327 if (bExternal != ScRefTokenHelper::isExternalRef(pRange))
1328 // internal vs external.
1329 return false;
1331 if (bExternal)
1333 if (pRange->GetIndex() != mpHeaderCell->GetIndex())
1334 // different external files.
1335 return false;
1337 if (pRange->GetString() != mpHeaderCell->GetString())
1338 // different table.
1339 return false;
1342 ScComplexRefData aRange;
1343 ScRefTokenHelper::getDoubleRefDataFromToken(aRange, pRange);
1344 const ScSingleRefData& rCell = mpHeaderCell->GetSingleRef();
1346 bool bRowContained = (aRange.Ref1.nRow <= rCell.nRow) && (rCell.nRow <= aRange.Ref2.nRow);
1347 bool bColContained = (aRange.Ref1.nCol <= rCell.nCol) && (rCell.nCol <= aRange.Ref2.nCol);
1348 bool bTabContained = (aRange.Ref1.nTab <= rCell.nTab) && (rCell.nTab <= aRange.Ref2.nTab);
1350 return (bRowContained && bColContained && bTabContained);
1353 private:
1354 shared_ptr< vector<ScSharedTokenRef> > mpTokens;
1356 /**
1357 * Stores header cell position. Must be a single ref token i.e. either
1358 * ScSingleRefToken or ScExternalSingleRefToken.
1360 ScSharedTokenRef mpHeaderCell;
1362 bool mbOrientCol;
1367 static void lcl_removeHeaderFromRanges(vector<ScSharedTokenRef>& rTokens, const ScSharedTokenRef& rHeaderCell, bool bOrientCol)
1369 RemoveHeaderFromRanges func(rHeaderCell, bOrientCol);
1370 func = for_each(rTokens.begin(), rTokens.end(), func);
1371 func.getNewTokens(rTokens);
1374 uno::Reference< chart2::data::XDataSource> SAL_CALL
1375 ScChart2DataProvider::createDataSource(
1376 const uno::Sequence< beans::PropertyValue >& aArguments )
1377 throw( lang::IllegalArgumentException, uno::RuntimeException)
1379 ScUnoGuard aGuard;
1380 if ( ! m_pDocument )
1381 throw uno::RuntimeException();
1383 uno::Reference< chart2::data::XDataSource> xResult;
1384 bool bLabel = true;
1385 bool bOrientCol = true;
1386 ::rtl::OUString aRangeRepresentation;
1387 uno::Sequence< sal_Int32 > aSequenceMapping;
1388 for(sal_Int32 i = 0; i < aArguments.getLength(); ++i)
1390 rtl::OUString sName(aArguments[i].Name);
1391 if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataRowSource")))
1393 chart::ChartDataRowSource eSource = chart::ChartDataRowSource_COLUMNS;
1394 if( ! (aArguments[i].Value >>= eSource))
1396 sal_Int32 nSource(0);
1397 if( aArguments[i].Value >>= nSource )
1398 eSource = (static_cast< chart::ChartDataRowSource >( nSource ));
1400 bOrientCol = (eSource == chart::ChartDataRowSource_COLUMNS);
1402 else if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FirstCellAsLabel")))
1404 bLabel = ::cppu::any2bool(aArguments[i].Value);
1406 else if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CellRangeRepresentation")))
1408 aArguments[i].Value >>= aRangeRepresentation;
1410 else if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("SequenceMapping")))
1412 aArguments[i].Value >>= aSequenceMapping;
1416 vector<ScSharedTokenRef> aRefTokens;
1417 ScRefTokenHelper::compileRangeRepresentation(aRefTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar());
1418 if (aRefTokens.empty())
1419 // Invalid range representation. Bail out.
1420 throw lang::IllegalArgumentException();
1422 if (bLabel)
1423 addUpperLeftCornerIfMissing(aRefTokens);
1425 bool bColHeaders = (bOrientCol ? bLabel : false );
1426 bool bRowHeaders = (bOrientCol ? false : bLabel );
1428 Chart2Positioner aChPositioner(m_pDocument, aRefTokens);
1429 aChPositioner.setHeaders(bColHeaders, bRowHeaders);
1431 const Chart2PositionMap* pChartMap = aChPositioner.getPositionMap();
1432 if (!pChartMap)
1433 // No chart position map instance. Bail out.
1434 return xResult;
1436 ScChart2DataSource* pDS = NULL;
1437 std::list < ScChart2LabeledDataSequence* > aSeqs;
1439 // Fill Categories
1441 ScChart2LabeledDataSequence* pHeader = NULL;
1442 if (bOrientCol ? aChPositioner.hasRowHeaders() : aChPositioner.hasColHeaders())
1444 pHeader = new ScChart2LabeledDataSequence(m_pDocument);
1445 sal_Int32 nCount = static_cast< sal_Int32 >( bOrientCol ? pChartMap->getRowCount() : pChartMap->getColCount() );
1446 vector<ScSharedTokenRef> aRefTokens2;
1447 ScSharedTokenRef pLabelToken;
1448 for (sal_Int32 i = 0; i < nCount; ++i)
1450 const FormulaToken* pPos = bOrientCol ?
1451 pChartMap->getRowHeaderPosition(static_cast<SCROW>(i)) :
1452 pChartMap->getColHeaderPosition(static_cast<SCCOL>(i));
1453 if (pPos)
1455 ScSharedTokenRef p(static_cast<ScToken*>(pPos->Clone()));
1456 ScRefTokenHelper::join(aRefTokens2, p);
1457 if (!pLabelToken)
1459 pLabelToken = p;
1460 StackVar eType = pLabelToken->GetType();
1461 if (eType == svSingleRef || eType == svExternalSingleRef)
1463 ScSingleRefData& r = pLabelToken->GetSingleRef();
1464 if (bOrientCol)
1465 r.nRow -= 1;
1466 else
1467 r.nCol -= 1;
1472 if (pLabelToken)
1474 if (bLabel)
1476 auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>);
1477 pTokens->push_back(pLabelToken);
1478 Reference < chart2::data::XDataSequence > xLabelSeq(new ScChart2DataSequence(m_pDocument, this, pTokens.release(), m_bIncludeHiddenCells));
1479 Reference< beans::XPropertySet > xLabelProps(xLabelSeq, uno::UNO_QUERY);
1480 if (xLabelProps.is())
1481 xLabelProps->setPropertyValue(
1482 OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_ROLE)),
1483 uno::makeAny(OUString(RTL_CONSTASCII_USTRINGPARAM("label"))));
1484 pHeader->setLabel(xLabelSeq);
1486 else
1487 ScRefTokenHelper::join(aRefTokens2, pLabelToken);
1489 auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>);
1490 pTokens->swap(aRefTokens2);
1491 uno::Reference< chart2::data::XDataSequence > xSeq( new ScChart2DataSequence( m_pDocument, this, pTokens.release(), m_bIncludeHiddenCells) );
1492 pHeader->setValues(xSeq);
1494 if (pHeader)
1495 aSeqs.push_back(pHeader);
1497 // Fill Serieses with Labels
1499 sal_Int32 nCount = bOrientCol ? pChartMap->getColCount() : pChartMap->getRowCount();
1500 for (sal_Int32 i = 0; i < nCount; ++i)
1502 ScChart2LabeledDataSequence* pLabeled = new ScChart2LabeledDataSequence(m_pDocument);
1503 uno::Reference < chart2::data::XDataSequence > xLabelSeq;
1504 auto_ptr< vector<ScSharedTokenRef> > pRanges(NULL);
1505 if (bOrientCol)
1506 pRanges.reset(pChartMap->getColRanges(static_cast<SCCOL>(i)));
1507 else
1508 pRanges.reset(pChartMap->getRowRanges(static_cast<SCROW>(i)));
1510 ScSharedTokenRef pHeaderCell;
1511 if (bOrientCol)
1513 const FormulaToken* p = pChartMap->getColHeaderPosition(static_cast<SCCOL>(i));
1514 if (p)
1515 pHeaderCell.reset(static_cast<ScToken*>(p->Clone()));
1517 else
1519 const FormulaToken* p = pChartMap->getRowHeaderPosition(static_cast<SCROW>(i));
1520 if (p)
1521 pHeaderCell.reset(static_cast<ScToken*>(p->Clone()));
1524 if (bLabel)
1526 if (!pHeaderCell && pRanges.get() && !pRanges->empty())
1528 const ScSharedTokenRef& p = pRanges->front();
1529 if (p && ScRefTokenHelper::isRef(p))
1531 // Take the first cell in the range as the header position.
1532 ScSingleRefData aData = p->GetSingleRef();
1533 bool bExternal = ScRefTokenHelper::isExternalRef(p);
1534 if (bExternal)
1536 sal_uInt16 nFileId = p->GetIndex();
1537 const String& rTabName = p->GetString();
1538 pHeaderCell.reset(new ScExternalSingleRefToken(nFileId, rTabName, aData));
1540 else
1541 pHeaderCell.reset(new ScSingleRefToken(aData));
1544 if (pHeaderCell)
1546 auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>);
1547 pTokens->reserve(1);
1548 pTokens->push_back(pHeaderCell);
1549 xLabelSeq.set(new ScChart2DataSequence(m_pDocument, this, pTokens.release(), m_bIncludeHiddenCells));
1550 uno::Reference< beans::XPropertySet > xLabelProps(xLabelSeq, uno::UNO_QUERY);
1551 if (xLabelProps.is())
1552 xLabelProps->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_ROLE)), uno::makeAny(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("label"))));
1554 // remove Header from Ranges
1555 lcl_removeHeaderFromRanges(*pRanges, pHeaderCell, bOrientCol);
1558 else
1560 if (pHeaderCell)
1561 ScRefTokenHelper::join(*pRanges, pHeaderCell);
1564 // FIXME: if there are no labels the column or row name should be taken
1566 uno::Reference < chart2::data::XDataSequence > xSeq(new ScChart2DataSequence(m_pDocument, this, pRanges.release(), m_bIncludeHiddenCells));
1568 pLabeled->setValues(xSeq);
1569 pLabeled->setLabel(xLabelSeq);
1571 aSeqs.push_back(pLabeled);
1574 pDS = new ScChart2DataSource(m_pDocument);
1575 std::list < ScChart2LabeledDataSequence* >::iterator aItr(aSeqs.begin());
1576 std::list < ScChart2LabeledDataSequence* >::iterator aEndItr(aSeqs.end());
1578 //reorder labeled sequences according to aSequenceMapping
1579 std::vector< ScChart2LabeledDataSequence* > aSeqVector;
1580 while(aItr != aEndItr)
1582 aSeqVector.push_back(*aItr);
1583 ++aItr;
1586 std::map< sal_Int32, ScChart2LabeledDataSequence* > aSequenceMap;
1587 for( sal_Int32 nNewIndex = 0; nNewIndex < aSequenceMapping.getLength(); nNewIndex++ )
1589 // note: assuming that the values in the sequence mapping are always non-negative
1590 std::vector< ScChart2LabeledDataSequence* >::size_type nOldIndex( static_cast< sal_uInt32 >( aSequenceMapping[nNewIndex] ));
1591 if( nOldIndex < aSeqVector.size() )
1593 pDS->AddLabeledSequence( aSeqVector[nOldIndex] );
1594 aSeqVector[nOldIndex] = 0;
1599 std::vector< ScChart2LabeledDataSequence* >::iterator aVectorItr(aSeqVector.begin());
1600 std::vector< ScChart2LabeledDataSequence* >::iterator aVectorEndItr(aSeqVector.end());
1601 while(aVectorItr != aVectorEndItr)
1603 if(*aVectorItr)
1604 pDS->AddLabeledSequence(*aVectorItr);
1605 ++aVectorItr;
1608 xResult.set( pDS );
1609 return xResult;
1612 namespace
1615 bool lcl_HasCategories(
1616 const uno::Reference< chart2::data::XDataSource >& xDataSource,
1617 bool & rOutHasCategories )
1619 bool bResult = false;
1620 uno::Reference< chart2::data::XLabeledDataSequence > xCategories(
1621 lcl_getCategoriesFromDataSource( xDataSource ));
1622 if( xCategories.is())
1624 uno::Reference< lang::XServiceInfo > xValues( xCategories->getValues(), uno::UNO_QUERY );
1625 if (xValues.is())
1627 rOutHasCategories = xValues->getImplementationName().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ScChart2DataSequence"));
1628 bResult = true;
1631 return bResult;
1634 bool lcl_HasFirstCellAsLabel(
1635 const uno::Reference< chart2::data::XDataSource >& xDataSource,
1636 bool & rOutHasFirstCellAsLabel )
1638 bool bResult = false;
1639 if( xDataSource.is())
1641 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences(
1642 xDataSource->getDataSequences());
1643 const sal_Int32 nCount( aSequences.getLength());
1644 if (nCount > 0 && aSequences[nCount - 1].is() )
1646 uno::Reference< lang::XServiceInfo > xLabel( aSequences[nCount - 1]->getLabel(), uno::UNO_QUERY ); // take the last sequence, because the first has no label if it is also created
1647 if (xLabel.is())
1649 rOutHasFirstCellAsLabel = xLabel->getImplementationName().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ScChart2DataSequence"));
1650 bResult = true;
1654 return bResult;
1657 } // anonymous namespace
1659 bool ScChart2DataProvider::addUpperLeftCornerIfMissing(vector<ScSharedTokenRef>& rRefTokens)
1661 using ::std::max;
1662 using ::std::min;
1664 if (rRefTokens.empty())
1665 return false;
1667 SCCOL nMinCol = MAXCOLCOUNT;
1668 SCROW nMinRow = MAXROWCOUNT;
1669 SCCOL nMaxCol = 0;
1670 SCROW nMaxRow = 0;
1671 SCTAB nTab = 0;
1673 USHORT nFileId = 0;
1674 String aExtTabName;
1675 bool bExternal = false;
1677 vector<ScSharedTokenRef>::const_iterator itr = rRefTokens.begin(), itrEnd = rRefTokens.end();
1679 // Get the first ref token.
1680 ScSharedTokenRef pToken = *itr;
1681 switch (pToken->GetType())
1683 case svSingleRef:
1685 const ScSingleRefData& rData = pToken->GetSingleRef();
1686 nMinCol = rData.nCol;
1687 nMinRow = rData.nRow;
1688 nMaxCol = rData.nCol;
1689 nMaxRow = rData.nRow;
1690 nTab = rData.nTab;
1692 break;
1693 case svDoubleRef:
1695 const ScComplexRefData& rData = pToken->GetDoubleRef();
1696 nMinCol = min(rData.Ref1.nCol, rData.Ref2.nCol);
1697 nMinRow = min(rData.Ref1.nRow, rData.Ref2.nRow);
1698 nMaxCol = max(rData.Ref1.nCol, rData.Ref2.nCol);
1699 nMaxRow = max(rData.Ref1.nRow, rData.Ref2.nRow);
1700 nTab = rData.Ref1.nTab;
1702 break;
1703 case svExternalSingleRef:
1705 const ScSingleRefData& rData = pToken->GetSingleRef();
1706 nMinCol = rData.nCol;
1707 nMinRow = rData.nRow;
1708 nMaxCol = rData.nCol;
1709 nMaxRow = rData.nRow;
1710 nTab = rData.nTab;
1711 nFileId = pToken->GetIndex();
1712 aExtTabName = pToken->GetString();
1713 bExternal = true;
1715 break;
1716 case svExternalDoubleRef:
1718 const ScComplexRefData& rData = pToken->GetDoubleRef();
1719 nMinCol = min(rData.Ref1.nCol, rData.Ref2.nCol);
1720 nMinRow = min(rData.Ref1.nRow, rData.Ref2.nRow);
1721 nMaxCol = max(rData.Ref1.nCol, rData.Ref2.nCol);
1722 nMaxRow = max(rData.Ref1.nRow, rData.Ref2.nRow);
1723 nTab = rData.Ref1.nTab;
1724 nFileId = pToken->GetIndex();
1725 aExtTabName = pToken->GetString();
1726 bExternal = true;
1728 break;
1729 default:
1733 // Determine the minimum range enclosing all data ranges. Also make sure
1734 // that they are all on the same table.
1736 for (++itr; itr != itrEnd; ++itr)
1738 pToken = *itr;
1739 switch (pToken->GetType())
1741 case svSingleRef:
1743 const ScSingleRefData& rData = pToken->GetSingleRef();
1745 nMinCol = min(nMinCol, rData.nCol);
1746 nMinRow = min(nMinRow, rData.nRow);
1747 nMaxCol = max(nMaxCol, rData.nCol);
1748 nMaxRow = max(nMaxRow, rData.nRow);
1749 if (nTab != rData.nTab || bExternal)
1750 return false;
1752 break;
1753 case svDoubleRef:
1755 const ScComplexRefData& rData = pToken->GetDoubleRef();
1757 nMinCol = min(nMinCol, rData.Ref1.nCol);
1758 nMinCol = min(nMinCol, rData.Ref2.nCol);
1759 nMinRow = min(nMinRow, rData.Ref1.nRow);
1760 nMinRow = min(nMinRow, rData.Ref2.nRow);
1762 nMaxCol = max(nMaxCol, rData.Ref1.nCol);
1763 nMaxCol = max(nMaxCol, rData.Ref2.nCol);
1764 nMaxRow = max(nMaxRow, rData.Ref1.nRow);
1765 nMaxRow = max(nMaxRow, rData.Ref2.nRow);
1767 if (nTab != rData.Ref1.nTab || bExternal)
1768 return false;
1770 break;
1771 case svExternalSingleRef:
1773 if (!bExternal)
1774 return false;
1776 if (nFileId != pToken->GetIndex() || aExtTabName != pToken->GetString())
1777 return false;
1779 const ScSingleRefData& rData = pToken->GetSingleRef();
1781 nMinCol = min(nMinCol, rData.nCol);
1782 nMinRow = min(nMinRow, rData.nRow);
1783 nMaxCol = max(nMaxCol, rData.nCol);
1784 nMaxRow = max(nMaxRow, rData.nRow);
1786 break;
1787 case svExternalDoubleRef:
1789 if (!bExternal)
1790 return false;
1792 if (nFileId != pToken->GetIndex() || aExtTabName != pToken->GetString())
1793 return false;
1795 const ScComplexRefData& rData = pToken->GetDoubleRef();
1797 nMinCol = min(nMinCol, rData.Ref1.nCol);
1798 nMinCol = min(nMinCol, rData.Ref2.nCol);
1799 nMinRow = min(nMinRow, rData.Ref1.nRow);
1800 nMinRow = min(nMinRow, rData.Ref2.nRow);
1802 nMaxCol = max(nMaxCol, rData.Ref1.nCol);
1803 nMaxCol = max(nMaxCol, rData.Ref2.nCol);
1804 nMaxRow = max(nMaxRow, rData.Ref1.nRow);
1805 nMaxRow = max(nMaxRow, rData.Ref2.nRow);
1807 break;
1808 default:
1813 if (nMinRow >= nMaxRow || nMinCol >= nMaxCol ||
1814 nMinRow >= MAXROWCOUNT || nMinCol >= MAXCOLCOUNT ||
1815 nMaxRow >= MAXROWCOUNT || nMaxCol >= MAXCOLCOUNT)
1817 // Invalid range. Bail out.
1818 return false;
1821 // Check if the following conditions are met:
1823 // 1) The upper-left corner cell is not included.
1824 // 2) The three adjacent cells of that corner cell are included.
1826 bool bRight = false, bBottom = false, bDiagonal = false;
1827 for (itr = rRefTokens.begin(); itr != itrEnd; ++itr)
1829 pToken = *itr;
1830 switch (pToken->GetType())
1832 case svSingleRef:
1833 case svExternalSingleRef:
1835 const ScSingleRefData& rData = pToken->GetSingleRef();
1836 if (rData.nCol == nMinCol && rData.nRow == nMinRow)
1837 // The corner cell is contained.
1838 return false;
1840 if (rData.nCol == nMinCol+1 && rData.nRow == nMinRow)
1841 bRight = true;
1843 if (rData.nCol == nMinCol && rData.nRow == nMinRow+1)
1844 bBottom = true;
1846 if (rData.nCol == nMinCol+1 && rData.nRow == nMinRow+1)
1847 bDiagonal = true;
1849 break;
1850 case svDoubleRef:
1851 case svExternalDoubleRef:
1853 const ScComplexRefData& rData = pToken->GetDoubleRef();
1854 const ScSingleRefData& r1 = rData.Ref1;
1855 const ScSingleRefData& r2 = rData.Ref2;
1856 if (r1.nCol <= nMinCol && nMinCol <= r2.nCol &&
1857 r1.nRow <= nMinRow && nMinRow <= r2.nRow)
1858 // The corner cell is contained.
1859 return false;
1861 if (r1.nCol <= nMinCol+1 && nMinCol+1 <= r2.nCol &&
1862 r1.nRow <= nMinRow && nMinRow <= r2.nRow)
1863 bRight = true;
1865 if (r1.nCol <= nMinCol && nMinCol <= r2.nCol &&
1866 r1.nRow <= nMinRow+1 && nMinRow+1 <= r2.nRow)
1867 bBottom = true;
1869 if (r1.nCol <= nMinCol+1 && nMinCol+1 <= r2.nCol &&
1870 r1.nRow <= nMinRow+1 && nMinRow+1 <= r2.nRow)
1871 bDiagonal = true;
1873 break;
1874 default:
1879 if (!bRight || !bBottom || !bDiagonal)
1880 // Not all the adjacent cells are included. Bail out.
1881 return false;
1883 #if 0 // Do we really need to do this ???
1884 if (rRefTokens.size() == 2)
1886 // Make a simple rectangular range if possible.
1887 ScRange aRightPart(ScAddress(nMinCol+1, nMinRow, nTab), ScAddress(nMaxCol, nMaxRow, nTab));
1888 ScRange aBottomPart(ScAddress(nMinCol, nMinRow+1, nTab), ScAddress(nMaxCol, nMaxRow, nTab));
1889 vector<ScRange> aRanges;
1890 aRanges.reserve(2);
1891 aRanges.push_back(aRightPart);
1892 aRanges.push_back(aBottomPart);
1893 if (lcl_isRangeContained(rRefTokens, aRanges))
1895 // Consolidate them into a single rectangle.
1896 ScComplexRefData aData;
1897 aData.InitFlags();
1898 aData.Ref1.SetFlag3D(true);
1899 aData.Ref1.SetColRel(false);
1900 aData.Ref1.SetRowRel(false);
1901 aData.Ref1.SetTabRel(false);
1902 aData.Ref2.SetColRel(false);
1903 aData.Ref2.SetRowRel(false);
1904 aData.Ref2.SetTabRel(false);
1905 aData.Ref1.nCol = nMinCol;
1906 aData.Ref1.nRow = nMinRow;
1907 aData.Ref1.nTab = nTab;
1908 aData.Ref2.nCol = nMaxCol;
1909 aData.Ref2.nRow = nMaxRow;
1910 aData.Ref2.nTab = nTab;
1911 vector<ScSharedTokenRef> aNewTokens;
1912 aNewTokens.reserve(1);
1913 if (bExternal)
1915 ScSharedTokenRef p(
1916 new ScExternalDoubleRefToken(nFileId, aExtTabName, aData));
1917 aNewTokens.push_back(p);
1919 else
1921 ScSharedTokenRef p(new ScDoubleRefToken(aData));
1922 aNewTokens.push_back(p);
1924 rRefTokens.swap(aNewTokens);
1925 return true;
1928 #endif
1930 ScSingleRefData aData;
1931 aData.InitFlags();
1932 aData.SetFlag3D(true);
1933 aData.SetColRel(false);
1934 aData.SetRowRel(false);
1935 aData.SetTabRel(false);
1936 aData.nCol = nMinCol;
1937 aData.nRow = nMinRow;
1938 aData.nTab = nTab;
1940 if (bExternal)
1942 ScSharedTokenRef pCorner(
1943 new ScExternalSingleRefToken(nFileId, aExtTabName, aData));
1944 ScRefTokenHelper::join(rRefTokens, pCorner);
1946 else
1948 ScSharedTokenRef pCorner(new ScSingleRefToken(aData));
1949 ScRefTokenHelper::join(rRefTokens, pCorner);
1952 return true;
1955 namespace {
1957 /**
1958 * Function object to create a list of table numbers from a token list.
1960 class InsertTabNumber : public unary_function<ScSharedTokenRef, void>
1962 public:
1963 InsertTabNumber() :
1964 mpTabNumList(new list<SCTAB>())
1968 InsertTabNumber(const InsertTabNumber& r) :
1969 mpTabNumList(r.mpTabNumList)
1973 void operator() (const ScSharedTokenRef& pToken) const
1975 if (!ScRefTokenHelper::isRef(pToken))
1976 return;
1978 const ScSingleRefData& r = pToken->GetSingleRef();
1979 mpTabNumList->push_back(r.nTab);
1982 void getList(list<SCTAB>& rList)
1984 mpTabNumList->swap(rList);
1986 private:
1987 shared_ptr< list<SCTAB> > mpTabNumList;
1992 uno::Sequence< beans::PropertyValue > SAL_CALL ScChart2DataProvider::detectArguments(
1993 const uno::Reference< chart2::data::XDataSource >& xDataSource )
1994 throw (uno::RuntimeException)
1996 ::std::vector< beans::PropertyValue > aResult;
1997 bool bRowSourceDetected = false;
1998 bool bFirstCellAsLabel = false;
1999 bool bHasCategories = true;
2000 ::rtl::OUString sRangeRep;
2002 chart::ChartDataRowSource eRowSource = chart::ChartDataRowSource_COLUMNS;
2004 vector<ScSharedTokenRef> aTokens;
2006 // CellRangeRepresentation
2008 ScUnoGuard aGuard;
2009 DBG_ASSERT( m_pDocument, "No Document -> no detectArguments" );
2010 if(!m_pDocument)
2011 return lcl_VectorToSequence( aResult );
2013 detectRangesFromDataSource(aTokens, eRowSource, bRowSourceDetected, xDataSource);
2016 // TableNumberList
2018 list<SCTAB> aTableNumList;
2019 InsertTabNumber func;
2020 func = for_each(aTokens.begin(), aTokens.end(), func);
2021 func.getList(aTableNumList);
2022 aResult.push_back(
2023 beans::PropertyValue( ::rtl::OUString::createFromAscii("TableNumberList"), -1,
2024 uno::makeAny( lcl_createTableNumberList( aTableNumList ) ),
2025 beans::PropertyState_DIRECT_VALUE ));
2028 // DataRowSource (calculated before)
2029 if( bRowSourceDetected )
2031 aResult.push_back(
2032 beans::PropertyValue( ::rtl::OUString::createFromAscii("DataRowSource"), -1,
2033 uno::makeAny( eRowSource ), beans::PropertyState_DIRECT_VALUE ));
2036 // HasCategories
2037 if( bRowSourceDetected )
2039 if( lcl_HasCategories( xDataSource, bHasCategories ))
2041 aResult.push_back(
2042 beans::PropertyValue( ::rtl::OUString::createFromAscii("HasCategories"), -1,
2043 uno::makeAny( bHasCategories ), beans::PropertyState_DIRECT_VALUE ));
2047 // FirstCellAsLabel
2048 if( bRowSourceDetected )
2050 lcl_HasFirstCellAsLabel( xDataSource, bFirstCellAsLabel );
2051 aResult.push_back(
2052 beans::PropertyValue( ::rtl::OUString::createFromAscii("FirstCellAsLabel"), -1,
2053 uno::makeAny( bFirstCellAsLabel ), beans::PropertyState_DIRECT_VALUE ));
2056 // Add the left upper corner to the range if it is missing.
2057 if (bRowSourceDetected && bFirstCellAsLabel && bHasCategories)
2058 addUpperLeftCornerIfMissing(aTokens);
2060 // Get range string.
2061 lcl_convertTokensToString(sRangeRep, aTokens, m_pDocument);
2063 // add cell range property
2064 aResult.push_back(
2065 beans::PropertyValue( ::rtl::OUString::createFromAscii("CellRangeRepresentation"), -1,
2066 uno::makeAny( sRangeRep ), beans::PropertyState_DIRECT_VALUE ));
2068 //Sequence Mapping
2069 bool bSequencesReordered = true;//todo detect this above or detect this sequence mapping cheaper ...
2070 if( bSequencesReordered && bRowSourceDetected )
2072 bool bDifferentIndexes = false;
2074 std::vector< sal_Int32 > aSequenceMappingVector;
2076 uno::Reference< chart2::data::XDataSource > xCompareDataSource;
2079 xCompareDataSource.set( this->createDataSource( lcl_VectorToSequence( aResult ) ) );
2081 catch( const lang::IllegalArgumentException & )
2083 // creation of data source to compare didn't work, so we cannot
2084 // create a sequence mapping
2087 if( xDataSource.is() && xCompareDataSource.is() )
2089 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence> > aOldSequences(
2090 xCompareDataSource->getDataSequences() );
2091 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aNewSequences(
2092 xDataSource->getDataSequences());
2094 rtl::OUString aOldLabel;
2095 rtl::OUString aNewLabel;
2096 rtl::OUString aOldValues;
2097 rtl::OUString aNewValues;
2098 rtl::OUString aEmpty;
2100 for( sal_Int32 nNewIndex = 0; nNewIndex < aNewSequences.getLength(); nNewIndex++ )
2102 uno::Reference< chart2::data::XLabeledDataSequence> xNew( aNewSequences[nNewIndex] );
2103 for( sal_Int32 nOldIndex = 0; nOldIndex < aOldSequences.getLength(); nOldIndex++ )
2105 uno::Reference< chart2::data::XLabeledDataSequence> xOld( aOldSequences[nOldIndex] );
2107 if( xOld.is() && xNew.is() )
2109 aOldLabel = aNewLabel = aOldValues = aNewValues = aEmpty;
2110 if( xOld.is() && xOld->getLabel().is() )
2111 aOldLabel = xOld->getLabel()->getSourceRangeRepresentation();
2112 if( xNew.is() && xNew->getLabel().is() )
2113 aNewLabel = xNew->getLabel()->getSourceRangeRepresentation();
2114 if( xOld.is() && xOld->getValues().is() )
2115 aOldValues = xOld->getValues()->getSourceRangeRepresentation();
2116 if( xNew.is() && xNew->getValues().is() )
2117 aNewValues = xNew->getValues()->getSourceRangeRepresentation();
2119 if( aOldLabel.equals(aNewLabel)
2120 && ( aOldValues.equals(aNewValues) ) )
2122 if( nOldIndex!=nNewIndex )
2123 bDifferentIndexes = true;
2124 aSequenceMappingVector.push_back(nOldIndex);
2125 break;
2132 if( bDifferentIndexes && aSequenceMappingVector.size() )
2134 aResult.push_back(
2135 beans::PropertyValue( ::rtl::OUString::createFromAscii("SequenceMapping"), -1,
2136 uno::makeAny( lcl_VectorToSequence(aSequenceMappingVector) )
2137 , beans::PropertyState_DIRECT_VALUE ));
2141 return lcl_VectorToSequence( aResult );
2144 ::sal_Bool SAL_CALL ScChart2DataProvider::createDataSequenceByRangeRepresentationPossible( const ::rtl::OUString& aRangeRepresentation )
2145 throw (uno::RuntimeException)
2147 ScUnoGuard aGuard;
2148 if( ! m_pDocument )
2149 return false;
2151 vector<ScSharedTokenRef> aTokens;
2152 ScRefTokenHelper::compileRangeRepresentation(aTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar());
2153 return !aTokens.empty();
2156 uno::Reference< chart2::data::XDataSequence > SAL_CALL
2157 ScChart2DataProvider::createDataSequenceByRangeRepresentation(
2158 const ::rtl::OUString& aRangeRepresentation )
2159 throw (lang::IllegalArgumentException,
2160 uno::RuntimeException)
2162 ScUnoGuard aGuard;
2163 uno::Reference< chart2::data::XDataSequence > xResult;
2165 DBG_ASSERT( m_pDocument, "No Document -> no createDataSequenceByRangeRepresentation" );
2166 if(!m_pDocument || (aRangeRepresentation.getLength() == 0))
2167 return xResult;
2169 // Note: the range representation must be in Calc A1 format. The import
2170 // filters use this method to pass data ranges, and they have no idea what
2171 // the current formula syntax is. In the future we should add another
2172 // method to allow the client code to directly pass tokens representing
2173 // ranges.
2175 vector<ScSharedTokenRef> aRefTokens;
2176 ScRefTokenHelper::compileRangeRepresentation(aRefTokens, aRangeRepresentation, m_pDocument);
2177 if (aRefTokens.empty())
2178 return xResult;
2180 // ScChart2DataSequence manages the life cycle of pRefTokens.
2181 vector<ScSharedTokenRef>* pRefTokens = new vector<ScSharedTokenRef>();
2182 pRefTokens->swap(aRefTokens);
2183 xResult.set(new ScChart2DataSequence(m_pDocument, this, pRefTokens, m_bIncludeHiddenCells));
2185 return xResult;
2188 uno::Reference< sheet::XRangeSelection > SAL_CALL ScChart2DataProvider::getRangeSelection()
2189 throw (uno::RuntimeException)
2191 uno::Reference< sheet::XRangeSelection > xResult;
2193 uno::Reference< frame::XModel > xModel( lcl_GetXModel( m_pDocument ));
2194 if( xModel.is())
2195 xResult.set( xModel->getCurrentController(), uno::UNO_QUERY );
2197 return xResult;
2200 /*uno::Reference< util::XNumberFormatsSupplier > SAL_CALL ScChart2DataProvider::getNumberFormatsSupplier()
2201 throw (uno::RuntimeException)
2203 return uno::Reference< util::XNumberFormatsSupplier >( lcl_GetXModel( m_pDocument ), uno::UNO_QUERY );
2206 // XRangeXMLConversion ---------------------------------------------------
2208 rtl::OUString SAL_CALL ScChart2DataProvider::convertRangeToXML( const rtl::OUString& sRangeRepresentation )
2209 throw ( uno::RuntimeException, lang::IllegalArgumentException )
2211 OUString aRet;
2212 if (!m_pDocument)
2213 return aRet;
2215 if (!sRangeRepresentation.getLength())
2216 // Empty data range is allowed.
2217 return aRet;
2219 vector<ScSharedTokenRef> aRefTokens;
2220 ScRefTokenHelper::compileRangeRepresentation(aRefTokens, sRangeRepresentation, m_pDocument, m_pDocument->GetGrammar());
2221 if (aRefTokens.empty())
2222 throw lang::IllegalArgumentException();
2224 Tokens2RangeStringXML converter(m_pDocument);
2225 converter = for_each(aRefTokens.begin(), aRefTokens.end(), converter);
2226 converter.getString(aRet);
2228 return aRet;
2231 rtl::OUString SAL_CALL ScChart2DataProvider::convertRangeFromXML( const rtl::OUString& sXMLRange )
2232 throw ( uno::RuntimeException, lang::IllegalArgumentException )
2234 const sal_Unicode cSep = ' ';
2235 const sal_Unicode cQuote = '\'';
2237 if (!m_pDocument)
2239 // #i74062# When loading flat XML, this is called before the referenced sheets are in the document,
2240 // so the conversion has to take place directly with the strings, without looking up the sheets.
2242 rtl::OUStringBuffer sRet;
2243 sal_Int32 nOffset = 0;
2244 while( nOffset >= 0 )
2246 rtl::OUString sToken;
2247 ScRangeStringConverter::GetTokenByOffset( sToken, sXMLRange, nOffset, cSep, cQuote );
2248 if( nOffset >= 0 )
2250 // convert one address (remove dots)
2252 String aUIString(sToken);
2254 sal_Int32 nIndex = ScRangeStringConverter::IndexOf( sToken, ':', 0, cQuote );
2255 if ( nIndex >= 0 && nIndex < aUIString.Len() - 1 &&
2256 aUIString.GetChar((xub_StrLen)nIndex + 1) == (sal_Unicode) '.' )
2257 aUIString.Erase( (xub_StrLen)nIndex + 1, 1 );
2259 if ( aUIString.GetChar(0) == (sal_Unicode) '.' )
2260 aUIString.Erase( 0, 1 );
2262 if( sRet.getLength() )
2263 sRet.append( (sal_Unicode) ';' );
2264 sRet.append( aUIString );
2268 return sRet.makeStringAndClear();
2271 OUString aRet;
2272 ScRangeStringConverter::GetStringFromXMLRangeString(aRet, sXMLRange, m_pDocument);
2273 return aRet;
2276 namespace {
2278 class CollectRefTokens : public ::std::unary_function<ScSharedTokenRef, void>
2280 public:
2281 CollectRefTokens() :
2282 mpRefTokens(new vector<ScSharedTokenRef>()),
2283 mnDataInRows(0),
2284 mnDataInCols(0),
2285 mbRowSourceAmbiguous(false)
2289 CollectRefTokens(const CollectRefTokens& r) :
2290 mpRefTokens(r.mpRefTokens),
2291 mnDataInRows(r.mnDataInRows),
2292 mnDataInCols(r.mnDataInCols),
2293 mbRowSourceAmbiguous(r.mbRowSourceAmbiguous)
2297 void operator() (const ScSharedTokenRef& rRefToken)
2299 if (!mbRowSourceAmbiguous)
2301 StackVar eVar = rRefToken->GetType();
2302 if (eVar == svDoubleRef || eVar == svExternalDoubleRef)
2304 const ScComplexRefData& r = rRefToken->GetDoubleRef();
2305 mbRowSourceAmbiguous = r.Ref1.nTab != r.Ref2.nTab;
2306 if (!mbRowSourceAmbiguous)
2308 bool bColDiff = (r.Ref2.nCol - r.Ref1.nCol) != 0;
2309 bool bRowDiff = (r.Ref2.nRow - r.Ref1.nRow) != 0;
2311 if (bColDiff && !bRowDiff)
2312 ++mnDataInRows;
2313 else if (bRowDiff && !bColDiff)
2314 ++mnDataInCols;
2315 else if (bRowDiff && bColDiff)
2316 mbRowSourceAmbiguous = true;
2318 if (mnDataInRows > 0 && mnDataInCols > 0)
2319 mbRowSourceAmbiguous = true;
2324 mpRefTokens->push_back(rRefToken);
2327 void appendTokens(vector<ScSharedTokenRef>& rTokens)
2329 vector<ScSharedTokenRef> aNewTokens = rTokens;
2330 vector<ScSharedTokenRef>::const_iterator itr = mpRefTokens->begin(), itrEnd = mpRefTokens->end();
2331 for (; itr != itrEnd; ++itr)
2332 ScRefTokenHelper::join(aNewTokens, *itr);
2334 rTokens.swap(aNewTokens);
2337 bool isRowSourceAmbiguous() const
2339 return mbRowSourceAmbiguous;
2342 sal_uInt32 getDataInRows() const
2344 return mnDataInRows;
2347 sal_uInt32 getDataInCols() const
2349 return mnDataInCols;
2352 private:
2353 shared_ptr< vector<ScSharedTokenRef> > mpRefTokens;
2354 sal_uInt32 mnDataInRows;
2355 sal_uInt32 mnDataInCols;
2356 bool mbRowSourceAmbiguous;
2361 // DataProvider XPropertySet -------------------------------------------------
2363 uno::Reference< beans::XPropertySetInfo> SAL_CALL
2364 ScChart2DataProvider::getPropertySetInfo() throw( uno::RuntimeException)
2366 ScUnoGuard aGuard;
2367 static uno::Reference<beans::XPropertySetInfo> aRef =
2368 new SfxItemPropertySetInfo( m_aPropSet.getPropertyMap() );
2369 return aRef;
2373 void SAL_CALL ScChart2DataProvider::setPropertyValue(
2374 const ::rtl::OUString& rPropertyName, const uno::Any& rValue)
2375 throw( beans::UnknownPropertyException,
2376 beans::PropertyVetoException,
2377 lang::IllegalArgumentException,
2378 lang::WrappedTargetException, uno::RuntimeException)
2380 if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS)))
2382 if ( !(rValue >>= m_bIncludeHiddenCells))
2383 throw lang::IllegalArgumentException();
2385 else
2386 throw beans::UnknownPropertyException();
2390 uno::Any SAL_CALL ScChart2DataProvider::getPropertyValue(
2391 const ::rtl::OUString& rPropertyName)
2392 throw( beans::UnknownPropertyException,
2393 lang::WrappedTargetException, uno::RuntimeException)
2395 uno::Any aRet;
2396 if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS)))
2397 aRet <<= m_bIncludeHiddenCells;
2398 else
2399 throw beans::UnknownPropertyException();
2400 return aRet;
2404 void SAL_CALL ScChart2DataProvider::addPropertyChangeListener(
2405 const ::rtl::OUString& /*rPropertyName*/,
2406 const uno::Reference< beans::XPropertyChangeListener>& /*xListener*/)
2407 throw( beans::UnknownPropertyException,
2408 lang::WrappedTargetException, uno::RuntimeException)
2410 OSL_ENSURE( false, "Not yet implemented" );
2414 void SAL_CALL ScChart2DataProvider::removePropertyChangeListener(
2415 const ::rtl::OUString& /*rPropertyName*/,
2416 const uno::Reference< beans::XPropertyChangeListener>& /*rListener*/)
2417 throw( beans::UnknownPropertyException,
2418 lang::WrappedTargetException, uno::RuntimeException)
2420 OSL_ENSURE( false, "Not yet implemented" );
2424 void SAL_CALL ScChart2DataProvider::addVetoableChangeListener(
2425 const ::rtl::OUString& /*rPropertyName*/,
2426 const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/)
2427 throw( beans::UnknownPropertyException,
2428 lang::WrappedTargetException, uno::RuntimeException)
2430 OSL_ENSURE( false, "Not yet implemented" );
2434 void SAL_CALL ScChart2DataProvider::removeVetoableChangeListener(
2435 const ::rtl::OUString& /*rPropertyName*/,
2436 const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/ )
2437 throw( beans::UnknownPropertyException,
2438 lang::WrappedTargetException, uno::RuntimeException)
2440 OSL_ENSURE( false, "Not yet implemented" );
2443 void ScChart2DataProvider::detectRangesFromDataSource(vector<ScSharedTokenRef>& rRefTokens,
2444 chart::ChartDataRowSource& rRowSource,
2445 bool& rRowSourceDetected,
2446 const Reference<chart2::data::XDataSource>& xDataSource)
2448 if (!m_pDocument)
2449 return;
2451 sal_Int32 nDataInRows = 0;
2452 sal_Int32 nDataInCols = 0;
2453 bool bRowSourceAmbiguous = false;
2455 vector<OUString> aRangeReps = lcl_getRangeRepresentationsFromDataSource(xDataSource);
2456 for (vector<OUString>::const_iterator itr = aRangeReps.begin(), itrEnd = aRangeReps.end();
2457 itr != itrEnd; ++itr)
2459 const OUString& rRangeRep = *itr;
2460 vector<ScSharedTokenRef> aTokens;
2461 ScRefTokenHelper::compileRangeRepresentation(aTokens, rRangeRep, m_pDocument, m_pDocument->GetGrammar());
2463 CollectRefTokens func;
2464 func = for_each(aTokens.begin(), aTokens.end(), func);
2465 func.appendTokens(rRefTokens);
2466 bRowSourceAmbiguous = bRowSourceAmbiguous || func.isRowSourceAmbiguous();
2467 if (!bRowSourceAmbiguous)
2469 nDataInRows += func.getDataInRows();
2470 nDataInCols += func.getDataInCols();
2474 if (!bRowSourceAmbiguous)
2476 rRowSourceDetected = true;
2477 rRowSource = ( nDataInRows > 0
2478 ? chart::ChartDataRowSource_ROWS
2479 : chart::ChartDataRowSource_COLUMNS );
2481 else
2483 // set DataRowSource to the better of the two ambiguities
2484 rRowSource = ( nDataInRows > nDataInCols
2485 ? chart::ChartDataRowSource_ROWS
2486 : chart::ChartDataRowSource_COLUMNS );
2490 // DataSource ================================================================
2492 ScChart2DataSource::ScChart2DataSource( ScDocument* pDoc)
2493 : m_pDocument( pDoc)
2495 if ( m_pDocument )
2496 m_pDocument->AddUnoObject( *this);
2500 ScChart2DataSource::~ScChart2DataSource()
2502 if ( m_pDocument )
2503 m_pDocument->RemoveUnoObject( *this);
2507 void ScChart2DataSource::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
2509 if ( rHint.ISA( SfxSimpleHint ) &&
2510 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
2512 m_pDocument = NULL;
2517 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence> > SAL_CALL
2518 ScChart2DataSource::getDataSequences() throw ( uno::RuntimeException)
2520 ScUnoGuard aGuard;
2522 LabeledList::const_iterator aItr(m_aLabeledSequences.begin());
2523 LabeledList::const_iterator aEndItr(m_aLabeledSequences.end());
2525 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aRet(m_aLabeledSequences.size());
2527 sal_Int32 i = 0;
2528 while (aItr != aEndItr)
2530 aRet[i] = *aItr;
2531 ++i;
2532 ++aItr;
2535 return aRet;
2537 /* typedef ::std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > tVec;
2538 tVec aVec;
2539 bool bSeries = false;
2540 // split into columns - FIXME: different if GlueState() is used
2541 for ( ScRangePtr p = m_xRanges->First(); p; p = m_xRanges->Next())
2543 for ( SCCOL nCol = p->aStart.Col(); nCol <= p->aEnd.Col(); ++nCol)
2545 uno::Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
2546 new ScChart2LabeledDataSequence( m_pDocument));
2547 if( xLabeledSeq.is())
2549 aVec.push_back( xLabeledSeq );
2550 if( bSeries )
2552 ScRangeListRef aColRanges = new ScRangeList;
2553 // one single sheet selected assumed for now
2554 aColRanges->Append( ScRange( nCol, p->aStart.Row(),
2555 p->aStart.Tab(), nCol, p->aStart.Row(),
2556 p->aStart.Tab()));
2557 // TEST: add range two times, once as label, once as data
2558 // TODO: create pure Numerical and Text sequences if possible
2559 uno::Reference< chart2::data::XDataSequence > xLabel(
2560 new ScChart2DataSequence( m_pDocument, aColRanges));
2562 // set role
2563 uno::Reference< beans::XPropertySet > xProp( xLabel, uno::UNO_QUERY );
2564 if( xProp.is())
2565 xProp->setPropertyValue(
2566 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )),
2567 ::uno::makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "label" ))));
2569 xLabeledSeq->setLabel( xLabel );
2572 ScRangeListRef aColRanges = new ScRangeList;
2574 // one single sheet selected assumed for now
2575 aColRanges->Append( ScRange( nCol, p->aStart.Row() + 1,
2576 p->aStart.Tab(), nCol, p->aEnd.Row(),
2577 p->aStart.Tab()));
2578 uno::Reference< chart2::data::XDataSequence > xData(
2579 new ScChart2DataSequence( m_pDocument, aColRanges));
2581 // set role
2582 uno::Reference< beans::XPropertySet > xProp( xData, uno::UNO_QUERY );
2583 if( xProp.is())
2584 xProp->setPropertyValue(
2585 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )),
2586 ::uno::makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "values" ))));
2588 xLabeledSeq->setValues( xData );
2590 bSeries = true;
2594 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence> > aSequences(
2595 aVec.size());
2596 uno::Reference< chart2::data::XLabeledDataSequence> * pArr = aSequences.getArray();
2597 sal_Int32 j = 0;
2598 for ( tVec::const_iterator iSeq = aVec.begin(); iSeq != aVec.end();
2599 ++iSeq, ++j)
2601 pArr[j] = *iSeq;
2603 return aSequences;*/
2606 void ScChart2DataSource::AddLabeledSequence(const uno::Reference < chart2::data::XLabeledDataSequence >& xNew)
2608 m_aLabeledSequences.push_back(xNew);
2611 // LabeledDataSequence =======================================================
2613 ScChart2LabeledDataSequence::ScChart2LabeledDataSequence(
2614 ScDocument* pDoc ) :
2615 m_pDocument( pDoc )
2617 if ( m_pDocument )
2618 m_pDocument->AddUnoObject( *this);
2621 ScChart2LabeledDataSequence::~ScChart2LabeledDataSequence()
2623 if ( m_pDocument )
2624 m_pDocument->RemoveUnoObject( *this);
2627 // SfxListener -----------------------------------------------------------
2629 void ScChart2LabeledDataSequence::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
2631 if ( rHint.ISA( SfxSimpleHint ) &&
2632 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
2634 ScUnoGuard aGuard;
2635 m_pDocument = NULL;
2639 // XLabeledDataSequence --------------------------------------------------
2641 uno::Reference< chart2::data::XDataSequence > SAL_CALL ScChart2LabeledDataSequence::getValues()
2642 throw (uno::RuntimeException)
2644 ScUnoGuard aGuard;
2645 return m_aData;
2648 void SAL_CALL ScChart2LabeledDataSequence::setValues(
2649 const uno::Reference< chart2::data::XDataSequence >& xSequence )
2650 throw (uno::RuntimeException)
2652 ScUnoGuard aGuard;
2653 m_aData = xSequence;
2656 uno::Reference< chart2::data::XDataSequence > SAL_CALL ScChart2LabeledDataSequence::getLabel()
2657 throw (uno::RuntimeException)
2659 ScUnoGuard aGuard;
2660 return m_aLabel;
2663 void SAL_CALL ScChart2LabeledDataSequence::setLabel(
2664 const uno::Reference< chart2::data::XDataSequence >& xSequence )
2665 throw (uno::RuntimeException)
2667 ScUnoGuard aGuard;
2668 m_aLabel = xSequence;
2671 // XCloneable ================================================================
2673 uno::Reference< util::XCloneable > SAL_CALL ScChart2LabeledDataSequence::createClone()
2674 throw (uno::RuntimeException)
2676 ScUnoGuard aGuard;
2677 uno::Reference< util::XCloneable > xToClone(m_aData, uno::UNO_QUERY);
2678 if (xToClone.is())
2680 ScChart2LabeledDataSequence* pRet = new ScChart2LabeledDataSequence(m_pDocument);
2681 uno::Reference< chart2::data::XDataSequence > xSequence(xToClone->createClone(), uno::UNO_QUERY);
2682 pRet->setValues(xSequence);
2683 xToClone.set(m_aLabel, uno::UNO_QUERY);
2684 if(xToClone.is())
2686 xSequence.set(xToClone->createClone(), uno::UNO_QUERY);
2687 pRet->setLabel(xSequence);
2689 return pRet;
2691 return NULL;
2694 // XModifyBroadcaster ========================================================
2696 void SAL_CALL ScChart2LabeledDataSequence::addModifyListener( const uno::Reference< util::XModifyListener >& aListener )
2697 throw (uno::RuntimeException)
2699 // quick'n dirty: just add the listener to each DataSequence
2701 uno::Reference<util::XModifyBroadcaster> xDataBroadcaster( m_aData, uno::UNO_QUERY );
2702 if ( xDataBroadcaster.is() )
2703 xDataBroadcaster->addModifyListener( aListener );
2704 uno::Reference<util::XModifyBroadcaster> xLabelBroadcaster( m_aLabel, uno::UNO_QUERY );
2705 if ( xLabelBroadcaster.is() )
2706 xLabelBroadcaster->addModifyListener( aListener );
2709 void SAL_CALL ScChart2LabeledDataSequence::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener )
2710 throw (uno::RuntimeException)
2712 uno::Reference<util::XModifyBroadcaster> xDataBroadcaster( m_aData, uno::UNO_QUERY );
2713 if ( xDataBroadcaster.is() )
2714 xDataBroadcaster->removeModifyListener( aListener );
2715 uno::Reference<util::XModifyBroadcaster> xLabelBroadcaster( m_aLabel, uno::UNO_QUERY );
2716 if ( xLabelBroadcaster.is() )
2717 xLabelBroadcaster->removeModifyListener( aListener );
2720 // DataSequence ==============================================================
2722 ScChart2DataSequence::Item::Item() :
2723 mfValue(0.0), mbIsValue(false)
2725 ::rtl::math::setNan(&mfValue);
2728 ScChart2DataSequence::HiddenRangeListener::HiddenRangeListener(ScChart2DataSequence& rParent) :
2729 mrParent(rParent)
2733 ScChart2DataSequence::HiddenRangeListener::~HiddenRangeListener()
2737 void ScChart2DataSequence::HiddenRangeListener::notify()
2739 mrParent.setDataChangedHint(true);
2742 ScChart2DataSequence::ScChart2DataSequence( ScDocument* pDoc,
2743 const uno::Reference < chart2::data::XDataProvider >& xDP,
2744 vector<ScSharedTokenRef>* pTokens,
2745 bool bIncludeHiddenCells )
2746 : m_bIncludeHiddenCells( bIncludeHiddenCells)
2747 , m_nObjectId( 0 )
2748 , m_pDocument( pDoc)
2749 , m_pTokens(pTokens)
2750 , m_pRangeIndices(NULL)
2751 , m_pExtRefListener(NULL)
2752 , m_xDataProvider( xDP)
2753 , m_aPropSet(lcl_GetDataSequencePropertyMap())
2754 , m_pHiddenListener(NULL)
2755 , m_pValueListener( NULL )
2756 , m_bGotDataChangedHint(false)
2757 , m_bExtDataRebuildQueued(false)
2759 DBG_ASSERT(pTokens, "reference token list is null");
2761 if ( m_pDocument )
2763 m_pDocument->AddUnoObject( *this);
2764 m_nObjectId = m_pDocument->GetNewUnoId();
2766 // FIXME: real implementation of identifier and it's mapping to ranges.
2767 // Reuse ScChartListener?
2769 // BM: don't use names of named ranges but the UI range strings
2770 // String aStr;
2771 // rRangeList->Format( aStr, SCR_ABS_3D, m_pDocument );
2772 // m_aIdentifier = ::rtl::OUString( aStr );
2774 // m_aIdentifier = ::rtl::OUString::createFromAscii( "ID_");
2775 // static sal_Int32 nID = 0;
2776 // m_aIdentifier += ::rtl::OUString::valueOf( ++nID);
2779 ScChart2DataSequence::~ScChart2DataSequence()
2781 if ( m_pDocument )
2783 m_pDocument->RemoveUnoObject( *this);
2784 if (m_pHiddenListener.get())
2786 ScChartListenerCollection* pCLC = m_pDocument->GetChartListenerCollection();
2787 if (pCLC)
2788 pCLC->EndListeningHiddenRange(m_pHiddenListener.get());
2790 StopListeningToAllExternalRefs();
2793 delete m_pValueListener;
2796 void ScChart2DataSequence::RefChanged()
2798 if( m_pValueListener && m_aValueListeners.Count() != 0 )
2800 m_pValueListener->EndListeningAll();
2802 if( m_pDocument )
2804 ScChartListenerCollection* pCLC = NULL;
2805 if (m_pHiddenListener.get())
2807 pCLC = m_pDocument->GetChartListenerCollection();
2808 if (pCLC)
2809 pCLC->EndListeningHiddenRange(m_pHiddenListener.get());
2812 vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end();
2813 for (; itr != itrEnd; ++itr)
2815 ScRange aRange;
2816 if (!ScRefTokenHelper::getRangeFromToken(aRange, *itr))
2817 continue;
2819 m_pDocument->StartListeningArea(aRange, m_pValueListener);
2820 if (pCLC)
2821 pCLC->StartListeningHiddenRange(aRange, m_pHiddenListener.get());
2827 void ScChart2DataSequence::BuildDataCache()
2829 m_bExtDataRebuildQueued = false;
2831 if (!m_aDataArray.empty())
2832 return;
2834 if (!m_pTokens.get())
2836 DBG_ERROR("m_pTokens == NULL! Something is wrong.");
2837 return;
2840 StopListeningToAllExternalRefs();
2842 ::std::list<sal_Int32> aHiddenValues;
2843 sal_Int32 nDataCount = 0;
2844 sal_Int32 nHiddenValueCount = 0;
2846 for (vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end();
2847 itr != itrEnd; ++itr)
2849 if (ScRefTokenHelper::isExternalRef(*itr))
2851 nDataCount += FillCacheFromExternalRef(*itr);
2853 else
2855 ScRange aRange;
2856 if (!ScRefTokenHelper::getRangeFromToken(aRange, *itr))
2857 continue;
2859 SCCOL nLastCol = -1;
2860 SCROW nLastRow = -1;
2861 for (SCTAB nTab = aRange.aStart.Tab(); nTab <= aRange.aEnd.Tab(); ++nTab)
2863 for (SCCOL nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol)
2865 for (SCROW nRow = aRange.aStart.Row(); nRow <= aRange.aEnd.Row(); ++nRow)
2867 bool bColHidden = m_pDocument->ColHidden(nCol, nTab, nLastCol);
2868 bool bRowHidden = m_pDocument->RowHidden(nRow, nTab, nLastRow);
2870 if (bColHidden || bRowHidden)
2872 // hidden cell
2873 ++nHiddenValueCount;
2874 aHiddenValues.push_back(nDataCount-1);
2876 if( !m_bIncludeHiddenCells )
2877 continue;
2880 m_aDataArray.push_back(Item());
2881 Item& rItem = m_aDataArray.back();
2882 ++nDataCount;
2884 ScAddress aAdr(nCol, nRow, nTab);
2885 ScBaseCell* pCell = m_pDocument->GetCell(aAdr);
2886 if (!pCell)
2887 continue;
2889 if (pCell->HasStringData())
2890 rItem.maString = pCell->GetStringData();
2891 else
2893 String aStr;
2894 m_pDocument->GetString(nCol, nRow, nTab, aStr);
2895 rItem.maString = aStr;
2898 switch (pCell->GetCellType())
2900 case CELLTYPE_VALUE:
2901 rItem.mfValue = static_cast< ScValueCell*>(pCell)->GetValue();
2902 rItem.mbIsValue = true;
2903 break;
2904 case CELLTYPE_FORMULA:
2906 ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
2907 USHORT nErr = pFCell->GetErrCode();
2908 if (nErr)
2909 break;
2911 if (pFCell->HasValueData())
2913 rItem.mfValue = pFCell->GetValue();
2914 rItem.mbIsValue = true;
2917 break;
2918 #if DBG_UTIL
2919 case CELLTYPE_DESTROYED:
2920 #endif
2921 case CELLTYPE_EDIT:
2922 case CELLTYPE_NONE:
2923 case CELLTYPE_NOTE:
2924 case CELLTYPE_STRING:
2925 case CELLTYPE_SYMBOLS:
2926 default:
2927 ; // do nothing
2935 // convert the hidden cell list to sequence.
2936 m_aHiddenValues.realloc(nHiddenValueCount);
2937 sal_Int32* pArr = m_aHiddenValues.getArray();
2938 ::std::list<sal_Int32>::const_iterator itr = aHiddenValues.begin(), itrEnd = aHiddenValues.end();
2939 for (;itr != itrEnd; ++itr, ++pArr)
2940 *pArr = *itr;
2942 // Clear the data series cache when the array is re-built.
2943 m_aMixedDataCache.realloc(0);
2946 void ScChart2DataSequence::RebuildDataCache()
2948 if (!m_bExtDataRebuildQueued)
2950 m_aDataArray.clear();
2951 m_pDocument->BroadcastUno(ScHint(SC_HINT_DATACHANGED, ScAddress(), NULL));
2952 m_bExtDataRebuildQueued = true;
2953 m_bGotDataChangedHint = true;
2957 sal_Int32 ScChart2DataSequence::FillCacheFromExternalRef(const ScSharedTokenRef& pToken)
2959 ScExternalRefManager* pRefMgr = m_pDocument->GetExternalRefManager();
2960 ScRange aRange;
2961 if (!ScRefTokenHelper::getRangeFromToken(aRange, pToken, true))
2962 return 0;
2964 sal_uInt16 nFileId = pToken->GetIndex();
2965 const String& rTabName = pToken->GetString();
2966 ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(nFileId, rTabName, aRange, NULL);
2967 if (!pArray)
2968 // no external data exists for this range.
2969 return 0;
2971 // Start listening for this external document.
2972 ExternalRefListener* pExtRefListener = GetExtRefListener();
2973 pRefMgr->addLinkListener(nFileId, pExtRefListener);
2974 pExtRefListener->addFileId(nFileId);
2976 ScExternalRefCache::TableTypeRef pTable = pRefMgr->getCacheTable(nFileId, rTabName, false, NULL);
2977 sal_Int32 nDataCount = 0;
2978 for (FormulaToken* p = pArray->First(); p; p = pArray->Next())
2980 // Cached external range is always represented as a single
2981 // matrix token, although that might change in the future when
2982 // we introduce a new token type to store multi-table range
2983 // data.
2985 if (p->GetType() != svMatrix)
2987 DBG_ERROR("Cached array is not a matrix token.");
2988 continue;
2991 const ScMatrix* pMat = static_cast<ScToken*>(p)->GetMatrix();
2992 SCSIZE nCSize, nRSize;
2993 pMat->GetDimensions(nCSize, nRSize);
2994 for (SCSIZE nC = 0; nC < nCSize; ++nC)
2996 for (SCSIZE nR = 0; nR < nRSize; ++nR)
2998 if (pMat->IsValue(nC, nR) || pMat->IsBoolean(nC, nR))
3000 m_aDataArray.push_back(Item());
3001 Item& rItem = m_aDataArray.back();
3002 ++nDataCount;
3004 rItem.mbIsValue = true;
3005 rItem.mfValue = pMat->GetDouble(nC, nR);
3007 SvNumberFormatter* pFormatter = m_pDocument->GetFormatTable();
3008 if (pFormatter)
3010 String aStr;
3011 const double fVal = rItem.mfValue;
3012 Color* pColor = NULL;
3013 sal_uInt32 nFmt = 0;
3014 if (pTable)
3016 // Get the correct format index from the cache.
3017 SCCOL nCol = aRange.aStart.Col() + static_cast<SCCOL>(nC);
3018 SCROW nRow = aRange.aStart.Row() + static_cast<SCROW>(nR);
3019 pTable->getCell(nCol, nRow, &nFmt);
3021 pFormatter->GetOutputString(fVal, nFmt, aStr, &pColor);
3022 rItem.maString = aStr;
3025 else if (pMat->IsString(nC, nR))
3027 m_aDataArray.push_back(Item());
3028 Item& rItem = m_aDataArray.back();
3029 ++nDataCount;
3031 rItem.mbIsValue = false;
3032 rItem.maString = pMat->GetString(nC, nR);
3037 return nDataCount;
3040 void ScChart2DataSequence::UpdateTokensFromRanges(const ScRangeList& rRanges)
3042 if (!m_pRangeIndices.get())
3043 return;
3045 sal_uInt32 nCount = rRanges.Count();
3046 for (sal_uInt32 i = 0; i < nCount; ++i)
3048 ScSharedTokenRef pToken;
3049 ScRange* pRange = static_cast<ScRange*>(rRanges.GetObject(i));
3050 DBG_ASSERT(pRange, "range object is NULL.");
3052 ScRefTokenHelper::getTokenFromRange(pToken, *pRange);
3053 sal_uInt32 nOrigPos = (*m_pRangeIndices)[i];
3054 (*m_pTokens)[nOrigPos] = pToken;
3057 RefChanged();
3059 // any change of the range address is broadcast to value (modify) listeners
3060 if ( m_aValueListeners.Count() )
3061 m_bGotDataChangedHint = true;
3064 ScChart2DataSequence::ExternalRefListener* ScChart2DataSequence::GetExtRefListener()
3066 if (!m_pExtRefListener.get())
3067 m_pExtRefListener.reset(new ExternalRefListener(*this, m_pDocument));
3069 return m_pExtRefListener.get();
3072 void ScChart2DataSequence::StopListeningToAllExternalRefs()
3074 if (!m_pExtRefListener.get())
3075 return;
3077 const hash_set<sal_uInt16>& rFileIds = m_pExtRefListener->getAllFileIds();
3078 hash_set<sal_uInt16>::const_iterator itr = rFileIds.begin(), itrEnd = rFileIds.end();
3079 ScExternalRefManager* pRefMgr = m_pDocument->GetExternalRefManager();
3080 for (; itr != itrEnd; ++itr)
3081 pRefMgr->removeLinkListener(*itr, m_pExtRefListener.get());
3083 m_pExtRefListener.reset(NULL);
3086 void ScChart2DataSequence::CopyData(const ScChart2DataSequence& r)
3088 if (!m_pDocument)
3090 DBG_ERROR("document instance is NULL!?");
3091 return;
3094 list<Item> aDataArray(r.m_aDataArray);
3095 m_aDataArray.swap(aDataArray);
3097 m_aHiddenValues = r.m_aHiddenValues;
3098 m_aRole = r.m_aRole;
3100 if (r.m_pRangeIndices.get())
3101 m_pRangeIndices.reset(new vector<sal_uInt32>(*r.m_pRangeIndices));
3103 if (r.m_pExtRefListener.get())
3105 // Re-register all external files that the old instance was
3106 // listening to.
3108 ScExternalRefManager* pRefMgr = m_pDocument->GetExternalRefManager();
3109 m_pExtRefListener.reset(new ExternalRefListener(*this, m_pDocument));
3110 const hash_set<sal_uInt16>& rFileIds = r.m_pExtRefListener->getAllFileIds();
3111 hash_set<sal_uInt16>::const_iterator itr = rFileIds.begin(), itrEnd = rFileIds.end();
3112 for (; itr != itrEnd; ++itr)
3114 pRefMgr->addLinkListener(*itr, m_pExtRefListener.get());
3115 m_pExtRefListener->addFileId(*itr);
3120 void ScChart2DataSequence::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
3122 if ( rHint.ISA( SfxSimpleHint ) )
3124 ULONG nId = static_cast<const SfxSimpleHint&>(rHint).GetId();
3125 if ( nId ==SFX_HINT_DYING )
3127 m_pDocument = NULL;
3129 else if ( nId == SFX_HINT_DATACHANGED )
3131 // delayed broadcast as in ScCellRangesBase
3133 if ( m_bGotDataChangedHint && m_pDocument )
3135 m_aDataArray.clear();
3136 lang::EventObject aEvent;
3137 aEvent.Source.set((cppu::OWeakObject*)this);
3139 if( m_pDocument )
3141 for ( USHORT n=0; n<m_aValueListeners.Count(); n++ )
3142 m_pDocument->AddUnoListenerCall( *m_aValueListeners[n], aEvent );
3145 m_bGotDataChangedHint = false;
3148 else if ( nId == SC_HINT_CALCALL )
3150 // broadcast from DoHardRecalc - set m_bGotDataChangedHint
3151 // (SFX_HINT_DATACHANGED follows separately)
3153 if ( m_aValueListeners.Count() )
3154 m_bGotDataChangedHint = true;
3157 else if ( rHint.ISA( ScUpdateRefHint ) )
3159 // Create a range list from the token list, have the range list
3160 // updated, and bring the change back to the token list.
3162 ScRangeList aRanges;
3163 m_pRangeIndices.reset(new vector<sal_uInt32>());
3164 vector<ScSharedTokenRef>::const_iterator itrBeg = m_pTokens->begin(), itrEnd = m_pTokens->end();
3165 for (vector<ScSharedTokenRef>::const_iterator itr = itrBeg ;itr != itrEnd; ++itr)
3167 if (!ScRefTokenHelper::isExternalRef(*itr))
3169 ScRange aRange;
3170 ScRefTokenHelper::getRangeFromToken(aRange, *itr);
3171 aRanges.Append(aRange);
3172 sal_uInt32 nPos = distance(itrBeg, itr);
3173 m_pRangeIndices->push_back(nPos);
3177 DBG_ASSERT(m_pRangeIndices->size() == static_cast<size_t>(aRanges.Count()),
3178 "range list and range index list have different sizes.");
3180 auto_ptr<ScRangeList> pUndoRanges;
3181 if ( m_pDocument->HasUnoRefUndo() )
3182 pUndoRanges.reset(new ScRangeList(aRanges));
3184 const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint;
3185 bool bChanged = aRanges.UpdateReference(
3186 rRef.GetMode(), m_pDocument, rRef.GetRange(), rRef.GetDx(), rRef.GetDy(), rRef.GetDz());
3188 if (bChanged)
3190 DBG_ASSERT(m_pRangeIndices->size() == static_cast<size_t>(aRanges.Count()),
3191 "range list and range index list have different sizes after the reference update.");
3193 // Bring the change back from the range list to the token list.
3194 UpdateTokensFromRanges(aRanges);
3196 if (pUndoRanges.get())
3197 m_pDocument->AddUnoRefChange(m_nObjectId, *pUndoRanges);
3200 else if ( rHint.ISA( ScUnoRefUndoHint ) )
3202 const ScUnoRefUndoHint& rUndoHint = static_cast<const ScUnoRefUndoHint&>(rHint);
3206 if (rUndoHint.GetObjectId() != m_nObjectId)
3207 break;
3209 // The hint object provides the old ranges. Restore the old state
3210 // from these ranges.
3212 if (!m_pRangeIndices.get() || m_pRangeIndices->empty())
3214 DBG_ERROR(" faulty range indices");
3215 break;
3218 const ScRangeList& rRanges = rUndoHint.GetRanges();
3220 sal_uInt32 nCount = rRanges.Count();
3221 if (nCount != m_pRangeIndices->size())
3223 DBG_ERROR("range count and range index count differ.");
3224 break;
3227 UpdateTokensFromRanges(rRanges);
3229 while (false);
3234 IMPL_LINK( ScChart2DataSequence, ValueListenerHdl, SfxHint*, pHint )
3236 if ( m_pDocument && pHint && pHint->ISA( SfxSimpleHint ) &&
3237 ((const SfxSimpleHint*)pHint)->GetId() & (SC_HINT_DATACHANGED | SC_HINT_DYING) )
3239 // This may be called several times for a single change, if several formulas
3240 // in the range are notified. So only a flag is set that is checked when
3241 // SFX_HINT_DATACHANGED is received.
3243 setDataChangedHint(true);
3245 return 0;
3248 // ----------------------------------------------------------------------------
3250 ScChart2DataSequence::ExternalRefListener::ExternalRefListener(
3251 ScChart2DataSequence& rParent, ScDocument* pDoc) :
3252 ScExternalRefManager::LinkListener(),
3253 mrParent(rParent),
3254 mpDoc(pDoc)
3258 ScChart2DataSequence::ExternalRefListener::~ExternalRefListener()
3260 if (!mpDoc || mpDoc->IsInDtorClear())
3261 // The document is being destroyed. Do nothing.
3262 return;
3264 // Make sure to remove all pointers to this object.
3265 mpDoc->GetExternalRefManager()->removeLinkListener(this);
3268 void ScChart2DataSequence::ExternalRefListener::notify(sal_uInt16 nFileId, ScExternalRefManager::LinkUpdateType eType)
3270 switch (eType)
3272 case ScExternalRefManager::LINK_MODIFIED:
3274 if (maFileIds.count(nFileId))
3275 // We are listening to this external document.
3276 mrParent.RebuildDataCache();
3278 break;
3279 case ScExternalRefManager::LINK_BROKEN:
3280 removeFileId(nFileId);
3281 break;
3285 void ScChart2DataSequence::ExternalRefListener::addFileId(sal_uInt16 nFileId)
3287 maFileIds.insert(nFileId);
3290 void ScChart2DataSequence::ExternalRefListener::removeFileId(sal_uInt16 nFileId)
3292 maFileIds.erase(nFileId);
3295 const hash_set<sal_uInt16>& ScChart2DataSequence::ExternalRefListener::getAllFileIds()
3297 return maFileIds;
3300 // ----------------------------------------------------------------------------
3302 uno::Sequence< uno::Any> SAL_CALL ScChart2DataSequence::getData()
3303 throw ( uno::RuntimeException)
3305 ScUnoGuard aGuard;
3306 if ( !m_pDocument)
3307 throw uno::RuntimeException();
3309 BuildDataCache();
3311 if (!m_aMixedDataCache.getLength())
3313 // Build a cache for the 1st time...
3315 sal_Int32 nCount = m_aDataArray.size();
3316 m_aMixedDataCache.realloc(nCount);
3317 uno::Any* pArr = m_aMixedDataCache.getArray();
3318 ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end();
3319 for (; itr != itrEnd; ++itr, ++pArr)
3321 if (itr->mbIsValue)
3322 *pArr <<= itr->mfValue;
3323 else
3324 *pArr <<= itr->maString;
3327 return m_aMixedDataCache;
3330 // XNumericalDataSequence --------------------------------------------------
3332 uno::Sequence< double > SAL_CALL ScChart2DataSequence::getNumericalData()
3333 throw ( uno::RuntimeException)
3335 ScUnoGuard aGuard;
3336 if ( !m_pDocument)
3337 throw uno::RuntimeException();
3339 BuildDataCache();
3341 double fNAN;
3342 ::rtl::math::setNan(&fNAN);
3344 sal_Int32 nCount = m_aDataArray.size();
3345 uno::Sequence<double> aSeq(nCount);
3346 double* pArr = aSeq.getArray();
3347 ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end();
3348 for (; itr != itrEnd; ++itr, ++pArr)
3349 *pArr = itr->mbIsValue ? itr->mfValue : fNAN;
3351 return aSeq;
3354 // XTextualDataSequence --------------------------------------------------
3356 uno::Sequence< rtl::OUString > SAL_CALL ScChart2DataSequence::getTextualData( ) throw (uno::RuntimeException)
3358 ScUnoGuard aGuard;
3359 if ( !m_pDocument)
3360 throw uno::RuntimeException();
3362 BuildDataCache();
3364 sal_Int32 nCount = m_aDataArray.size();
3365 uno::Sequence<rtl::OUString> aSeq(nCount);
3366 rtl::OUString* pArr = aSeq.getArray();
3367 ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end();
3368 for (; itr != itrEnd; ++itr, ++pArr)
3369 *pArr = itr->maString;
3371 return aSeq;
3374 ::rtl::OUString SAL_CALL ScChart2DataSequence::getSourceRangeRepresentation()
3375 throw ( uno::RuntimeException)
3377 ScUnoGuard aGuard;
3378 OUString aStr;
3379 DBG_ASSERT( m_pDocument, "No Document -> no SourceRangeRepresentation" );
3380 if (m_pDocument && m_pTokens.get())
3381 lcl_convertTokensToString(aStr, *m_pTokens, m_pDocument);
3383 return aStr;
3386 namespace {
3388 /**
3389 * This function object is used to accumulatively count the numbers of
3390 * columns and rows in all reference tokens.
3392 class AccumulateRangeSize : public unary_function<ScSharedTokenRef, void>
3394 public:
3395 AccumulateRangeSize() :
3396 mnCols(0), mnRows(0) {}
3398 AccumulateRangeSize(const AccumulateRangeSize& r) :
3399 mnCols(r.mnCols), mnRows(r.mnRows) {}
3401 void operator() (const ScSharedTokenRef& pToken)
3403 ScRange r;
3404 bool bExternal = ScRefTokenHelper::isExternalRef(pToken);
3405 ScRefTokenHelper::getRangeFromToken(r, pToken, bExternal);
3406 r.Justify();
3407 mnCols += r.aEnd.Col() - r.aStart.Col() + 1;
3408 mnRows += r.aEnd.Row() - r.aStart.Row() + 1;
3411 SCCOL getCols() const { return mnCols; }
3412 SCROW getRows() const { return mnRows; }
3413 private:
3414 SCCOL mnCols;
3415 SCROW mnRows;
3418 /**
3419 * This function object is used to generate label strings from a list of
3420 * reference tokens.
3422 class GenerateLabelStrings : public unary_function<ScSharedTokenRef, void>
3424 public:
3425 GenerateLabelStrings(sal_Int32 nSize, chart2::data::LabelOrigin eOrigin, bool bColumn) :
3426 mpLabels(new Sequence<OUString>(nSize)),
3427 meOrigin(eOrigin),
3428 mnCount(0),
3429 mbColumn(bColumn) {}
3431 GenerateLabelStrings(const GenerateLabelStrings& r) :
3432 mpLabels(r.mpLabels),
3433 meOrigin(r.meOrigin),
3434 mnCount(r.mnCount),
3435 mbColumn(r.mbColumn) {}
3437 void operator() (const ScSharedTokenRef& pToken)
3439 bool bExternal = ScRefTokenHelper::isExternalRef(pToken);
3440 ScRange aRange;
3441 ScRefTokenHelper::getRangeFromToken(aRange, pToken, bExternal);
3442 OUString* pArr = mpLabels->getArray();
3443 if (mbColumn)
3445 for (SCCOL nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol)
3447 if ( meOrigin != chart2::data::LabelOrigin_LONG_SIDE)
3449 String aString = ScGlobal::GetRscString(STR_COLUMN);
3450 aString += ' ';
3451 ScAddress aPos( nCol, 0, 0 );
3452 String aColStr;
3453 aPos.Format( aColStr, SCA_VALID_COL, NULL );
3454 aString += aColStr;
3455 pArr[mnCount] = aString;
3457 else //only indices for categories
3458 pArr[mnCount] = String::CreateFromInt32( mnCount+1 );
3459 ++mnCount;
3462 else
3464 for (sal_Int32 nRow = aRange.aStart.Row(); nRow <= aRange.aEnd.Row(); ++nRow)
3466 if (meOrigin != chart2::data::LabelOrigin_LONG_SIDE)
3468 String aString = ScGlobal::GetRscString(STR_ROW);
3469 aString += ' ';
3470 aString += String::CreateFromInt32( nRow+1 );
3471 pArr[mnCount] = aString;
3473 else //only indices for categories
3474 pArr[mnCount] = String::CreateFromInt32( mnCount+1 );
3475 ++mnCount;
3480 Sequence<OUString> getLabels() const { return *mpLabels; }
3482 private:
3483 GenerateLabelStrings(); // disabled
3485 shared_ptr< Sequence<OUString> > mpLabels;
3486 chart2::data::LabelOrigin meOrigin;
3487 sal_Int32 mnCount;
3488 bool mbColumn;
3493 uno::Sequence< ::rtl::OUString > SAL_CALL ScChart2DataSequence::generateLabel(chart2::data::LabelOrigin eOrigin)
3494 throw (uno::RuntimeException)
3496 ScUnoGuard aGuard;
3497 if ( !m_pDocument)
3498 throw uno::RuntimeException();
3500 if (!m_pTokens.get())
3501 return Sequence<OUString>();
3503 // Determine the total size of all ranges.
3504 AccumulateRangeSize func;
3505 func = for_each(m_pTokens->begin(), m_pTokens->end(), func);
3506 SCCOL nCols = func.getCols();
3507 SCROW nRows = func.getRows();
3509 // Detemine whether this is column-major or row-major.
3510 bool bColumn = true;
3511 if ((eOrigin == chart2::data::LabelOrigin_SHORT_SIDE) ||
3512 (eOrigin == chart2::data::LabelOrigin_LONG_SIDE))
3514 if (nRows > nCols)
3516 if (eOrigin == chart2::data::LabelOrigin_SHORT_SIDE)
3517 bColumn = true;
3518 else
3519 bColumn = false;
3521 else if (nCols > nRows)
3523 if (eOrigin == chart2::data::LabelOrigin_SHORT_SIDE)
3524 bColumn = false;
3525 else
3526 bColumn = true;
3528 else
3529 return Sequence<OUString>();
3532 // Generate label strings based on the info so far.
3533 sal_Int32 nCount = bColumn ? nCols : nRows;
3534 GenerateLabelStrings genLabels(nCount, eOrigin, bColumn);
3535 genLabels = for_each(m_pTokens->begin(), m_pTokens->end(), genLabels);
3536 Sequence<OUString> aSeq = genLabels.getLabels();
3538 return aSeq;
3541 ::sal_Int32 SAL_CALL ScChart2DataSequence::getNumberFormatKeyByIndex( ::sal_Int32 nIndex )
3542 throw (lang::IndexOutOfBoundsException,
3543 uno::RuntimeException)
3545 // index -1 means a heuristic value for the entire sequence
3546 bool bGetSeriesFormat = (nIndex == -1);
3547 sal_Int32 nResult = 0;
3549 ScUnoGuard aGuard;
3550 if ( !m_pDocument || !m_pTokens.get())
3551 return nResult;
3553 sal_Int32 nCount = 0;
3554 bool bFound = false;
3555 ScRangePtr p;
3557 uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( lcl_GetSpreadSheetDocument( m_pDocument ));
3558 if (!xSpreadDoc.is())
3559 return nResult;
3561 uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
3562 if (!xIndex.is())
3563 return nResult;
3565 ScRangeList aRanges;
3566 ScRefTokenHelper::getRangeListFromTokens(aRanges, *m_pTokens);
3567 uno::Reference< table::XCellRange > xSheet;
3568 for ( p = aRanges.First(); p && !bFound; p = aRanges.Next())
3570 // TODO: use DocIter?
3571 table::CellAddress aStart, aEnd;
3572 ScUnoConversion::FillApiAddress( aStart, p->aStart );
3573 ScUnoConversion::FillApiAddress( aEnd, p->aEnd );
3574 for ( sal_Int16 nSheet = aStart.Sheet; nSheet <= aEnd.Sheet && !bFound; ++nSheet)
3576 xSheet.set(xIndex->getByIndex(nSheet), uno::UNO_QUERY);
3577 for ( sal_Int32 nCol = aStart.Column; nCol <= aEnd.Column && !bFound; ++nCol)
3579 for ( sal_Int32 nRow = aStart.Row; nRow <= aEnd.Row && !bFound; ++nRow)
3581 if( bGetSeriesFormat )
3583 // TODO: use nicer heuristic
3584 // return format of first non-empty cell
3585 uno::Reference< text::XText > xText(
3586 xSheet->getCellByPosition(nCol, nRow), uno::UNO_QUERY);
3587 if (xText.is() && xText->getString().getLength())
3589 uno::Reference< beans::XPropertySet > xProp(xText, uno::UNO_QUERY);
3590 if( xProp.is())
3591 xProp->getPropertyValue(
3592 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NumberFormat"))) >>= nResult;
3593 bFound = true;
3594 break;
3597 else if( nCount == nIndex )
3599 uno::Reference< beans::XPropertySet > xProp(
3600 xSheet->getCellByPosition(nCol, nRow), uno::UNO_QUERY);
3601 if( xProp.is())
3602 xProp->getPropertyValue(
3603 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NumberFormat"))) >>= nResult;
3604 bFound = true;
3605 break;
3607 ++nCount;
3613 return nResult;
3616 // XCloneable ================================================================
3618 uno::Reference< util::XCloneable > SAL_CALL ScChart2DataSequence::createClone()
3619 throw (uno::RuntimeException)
3621 ScUnoGuard aGuard;
3623 auto_ptr< vector<ScSharedTokenRef> > pTokensNew;
3624 if (m_pTokens.get())
3626 // Clone tokens.
3627 pTokensNew.reset(new vector<ScSharedTokenRef>);
3628 pTokensNew->reserve(m_pTokens->size());
3629 vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end();
3630 for (; itr != itrEnd; ++itr)
3632 ScSharedTokenRef p(static_cast<ScToken*>((*itr)->Clone()));
3633 pTokensNew->push_back(p);
3637 auto_ptr<ScChart2DataSequence> p(new ScChart2DataSequence(m_pDocument, m_xDataProvider, pTokensNew.release(), m_bIncludeHiddenCells));
3638 p->CopyData(*this);
3639 Reference< util::XCloneable > xClone(p.release());
3641 return xClone;
3644 // XModifyBroadcaster ========================================================
3646 void SAL_CALL ScChart2DataSequence::addModifyListener( const uno::Reference< util::XModifyListener >& aListener )
3647 throw (uno::RuntimeException)
3649 // like ScCellRangesBase::addModifyListener
3650 ScUnoGuard aGuard;
3651 if (!m_pTokens.get() || m_pTokens->empty())
3652 return;
3654 ScRangeList aRanges;
3655 ScRefTokenHelper::getRangeListFromTokens(aRanges, *m_pTokens);
3656 uno::Reference<util::XModifyListener> *pObj =
3657 new uno::Reference<util::XModifyListener>( aListener );
3658 m_aValueListeners.Insert( pObj, m_aValueListeners.Count() );
3660 if ( m_aValueListeners.Count() == 1 )
3662 if (!m_pValueListener)
3663 m_pValueListener = new ScLinkListener( LINK( this, ScChart2DataSequence, ValueListenerHdl ) );
3665 if (!m_pHiddenListener.get())
3666 m_pHiddenListener.reset(new HiddenRangeListener(*this));
3668 if( m_pDocument )
3670 ScChartListenerCollection* pCLC = m_pDocument->GetChartListenerCollection();
3671 vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end();
3672 for (; itr != itrEnd; ++itr)
3674 ScRange aRange;
3675 if (!ScRefTokenHelper::getRangeFromToken(aRange, *itr))
3676 continue;
3678 m_pDocument->StartListeningArea( aRange, m_pValueListener );
3679 if (pCLC)
3680 pCLC->StartListeningHiddenRange(aRange, m_pHiddenListener.get());
3684 acquire(); // don't lose this object (one ref for all listeners)
3688 void SAL_CALL ScChart2DataSequence::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener )
3689 throw (uno::RuntimeException)
3691 // like ScCellRangesBase::removeModifyListener
3693 ScUnoGuard aGuard;
3694 if (!m_pTokens.get() || m_pTokens->empty())
3695 return;
3697 acquire(); // in case the listeners have the last ref - released below
3699 USHORT nCount = m_aValueListeners.Count();
3700 for ( USHORT n=nCount; n--; )
3702 uno::Reference<util::XModifyListener> *pObj = m_aValueListeners[n];
3703 if ( *pObj == aListener )
3705 m_aValueListeners.DeleteAndDestroy( n );
3707 if ( m_aValueListeners.Count() == 0 )
3709 if (m_pValueListener)
3710 m_pValueListener->EndListeningAll();
3712 if (m_pHiddenListener.get() && m_pDocument)
3714 ScChartListenerCollection* pCLC = m_pDocument->GetChartListenerCollection();
3715 if (pCLC)
3716 pCLC->EndListeningHiddenRange(m_pHiddenListener.get());
3719 release(); // release the ref for the listeners
3722 break;
3726 release(); // might delete this object
3729 // DataSequence XPropertySet -------------------------------------------------
3731 uno::Reference< beans::XPropertySetInfo> SAL_CALL
3732 ScChart2DataSequence::getPropertySetInfo() throw( uno::RuntimeException)
3734 ScUnoGuard aGuard;
3735 static uno::Reference<beans::XPropertySetInfo> aRef =
3736 new SfxItemPropertySetInfo( m_aPropSet.getPropertyMap() );
3737 return aRef;
3741 void SAL_CALL ScChart2DataSequence::setPropertyValue(
3742 const ::rtl::OUString& rPropertyName, const uno::Any& rValue)
3743 throw( beans::UnknownPropertyException,
3744 beans::PropertyVetoException,
3745 lang::IllegalArgumentException,
3746 lang::WrappedTargetException, uno::RuntimeException)
3748 if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE)))
3750 if ( !(rValue >>= m_aRole))
3751 throw lang::IllegalArgumentException();
3753 else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS)))
3755 sal_Bool bOldValue = m_bIncludeHiddenCells;
3756 if ( !(rValue >>= m_bIncludeHiddenCells))
3757 throw lang::IllegalArgumentException();
3758 if( bOldValue != m_bIncludeHiddenCells )
3759 m_aDataArray.clear();//data array is dirty now
3761 else
3762 throw beans::UnknownPropertyException();
3763 // TODO: support optional properties
3767 uno::Any SAL_CALL ScChart2DataSequence::getPropertyValue(
3768 const ::rtl::OUString& rPropertyName)
3769 throw( beans::UnknownPropertyException,
3770 lang::WrappedTargetException, uno::RuntimeException)
3772 uno::Any aRet;
3773 if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE)))
3774 aRet <<= m_aRole;
3775 else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS)))
3776 aRet <<= m_bIncludeHiddenCells;
3777 else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(SC_UNONAME_HIDDENVALUES)))
3779 // This property is read-only thus cannot be set externally via
3780 // setPropertyValue(...).
3781 BuildDataCache();
3782 aRet <<= m_aHiddenValues;
3784 else
3785 throw beans::UnknownPropertyException();
3786 // TODO: support optional properties
3787 return aRet;
3791 void SAL_CALL ScChart2DataSequence::addPropertyChangeListener(
3792 const ::rtl::OUString& /*rPropertyName*/,
3793 const uno::Reference< beans::XPropertyChangeListener>& /*xListener*/)
3794 throw( beans::UnknownPropertyException,
3795 lang::WrappedTargetException, uno::RuntimeException)
3797 // FIXME: real implementation
3798 // throw uno::RuntimeException();
3799 OSL_ENSURE( false, "Not yet implemented" );
3803 void SAL_CALL ScChart2DataSequence::removePropertyChangeListener(
3804 const ::rtl::OUString& /*rPropertyName*/,
3805 const uno::Reference< beans::XPropertyChangeListener>& /*rListener*/)
3806 throw( beans::UnknownPropertyException,
3807 lang::WrappedTargetException, uno::RuntimeException)
3809 // FIXME: real implementation
3810 // throw uno::RuntimeException();
3811 OSL_ENSURE( false, "Not yet implemented" );
3815 void SAL_CALL ScChart2DataSequence::addVetoableChangeListener(
3816 const ::rtl::OUString& /*rPropertyName*/,
3817 const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/)
3818 throw( beans::UnknownPropertyException,
3819 lang::WrappedTargetException, uno::RuntimeException)
3821 // FIXME: real implementation
3822 // throw uno::RuntimeException();
3823 OSL_ENSURE( false, "Not yet implemented" );
3827 void SAL_CALL ScChart2DataSequence::removeVetoableChangeListener(
3828 const ::rtl::OUString& /*rPropertyName*/,
3829 const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/)
3830 throw( beans::UnknownPropertyException,
3831 lang::WrappedTargetException, uno::RuntimeException)
3833 // FIXME: real implementation
3834 // throw uno::RuntimeException();
3835 OSL_ENSURE( false, "Not yet implemented" );
3838 void ScChart2DataSequence::setDataChangedHint(bool b)
3840 m_bGotDataChangedHint = b;
3843 // XUnoTunnel
3845 // sal_Int64 SAL_CALL ScChart2DataSequence::getSomething(
3846 // const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException)
3847 // {
3848 // if ( rId.getLength() == 16 &&
3849 // 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
3850 // rId.getConstArray(), 16 ) )
3851 // {
3852 // return (sal_Int64)this;
3853 // }
3854 // return 0;
3855 // }
3857 // // static
3858 // const uno::Sequence<sal_Int8>& ScChart2DataSequence::getUnoTunnelId()
3859 // {
3860 // static uno::Sequence<sal_Int8> * pSeq = 0;
3861 // if( !pSeq )
3862 // {
3863 // osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
3864 // if( !pSeq )
3865 // {
3866 // static uno::Sequence< sal_Int8 > aSeq( 16 );
3867 // rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
3868 // pSeq = &aSeq;
3869 // }
3870 // }
3871 // return *pSeq;
3872 // }
3874 // // static
3875 // ScChart2DataSequence* ScChart2DataSequence::getImplementation( const uno::Reference<uno::XInterface> xObj )
3876 // {
3877 // ScChart2DataSequence* pRet = NULL;
3878 // uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY );
3879 // if (xUT.is())
3880 // pRet = (ScChart2DataSequence*) xUT->getSomething( getUnoTunnelId() );
3881 // return pRet;
3882 // }
3884 #if USE_CHART2_EMPTYDATASEQUENCE
3885 // DataSequence ==============================================================
3887 ScChart2EmptyDataSequence::ScChart2EmptyDataSequence( ScDocument* pDoc,
3888 const uno::Reference < chart2::data::XDataProvider >& xDP,
3889 const ScRangeListRef& rRangeList,
3890 sal_Bool bColumn)
3891 : m_bIncludeHiddenCells( sal_True)
3892 , m_xRanges( rRangeList)
3893 , m_pDocument( pDoc)
3894 , m_xDataProvider( xDP)
3895 , m_aPropSet(lcl_GetDataSequencePropertyMap())
3896 , m_bColumn(bColumn)
3898 if ( m_pDocument )
3899 m_pDocument->AddUnoObject( *this);
3900 // FIXME: real implementation of identifier and it's mapping to ranges.
3901 // Reuse ScChartListener?
3903 // BM: don't use names of named ranges but the UI range strings
3904 // String aStr;
3905 // rRangeList->Format( aStr, SCR_ABS_3D, m_pDocument );
3906 // m_aIdentifier = ::rtl::OUString( aStr );
3908 // m_aIdentifier = ::rtl::OUString::createFromAscii( "ID_");
3909 // static sal_Int32 nID = 0;
3910 // m_aIdentifier += ::rtl::OUString::valueOf( ++nID);
3914 ScChart2EmptyDataSequence::~ScChart2EmptyDataSequence()
3916 if ( m_pDocument )
3917 m_pDocument->RemoveUnoObject( *this);
3921 void ScChart2EmptyDataSequence::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
3923 if ( rHint.ISA( SfxSimpleHint ) &&
3924 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
3926 m_pDocument = NULL;
3931 uno::Sequence< uno::Any> SAL_CALL ScChart2EmptyDataSequence::getData()
3932 throw ( uno::RuntimeException)
3934 ScUnoGuard aGuard;
3935 if ( !m_pDocument)
3936 throw uno::RuntimeException();
3937 return uno::Sequence< uno::Any>();
3940 // XTextualDataSequence --------------------------------------------------
3942 uno::Sequence< rtl::OUString > SAL_CALL ScChart2EmptyDataSequence::getTextualData( ) throw (uno::RuntimeException)
3944 ScUnoGuard aGuard;
3945 if ( !m_pDocument)
3946 throw uno::RuntimeException();
3948 sal_Int32 nCount = 0;
3949 ScRangePtr p;
3951 DBG_ASSERT(m_xRanges->Count() == 1, "not handled count of ranges");
3953 for ( p = m_xRanges->First(); p; p = m_xRanges->Next())
3955 p->Justify();
3956 // TODO: handle overlaping ranges?
3957 nCount += m_bColumn ? p->aEnd.Col() - p->aStart.Col() + 1 : p->aEnd.Row() - p->aStart.Row() + 1;
3959 uno::Sequence< rtl::OUString > aSeq( nCount);
3960 rtl::OUString* pArr = aSeq.getArray();
3961 nCount = 0;
3962 for ( p = m_xRanges->First(); p; p = m_xRanges->Next())
3964 if (m_bColumn)
3966 for (SCCOL nCol = p->aStart.Col(); nCol <= p->aEnd.Col(); ++nCol)
3968 String aString = ScGlobal::GetRscString(STR_COLUMN);
3969 aString += ' ';
3970 ScAddress aPos( nCol, 0, 0 );
3971 String aColStr;
3972 aPos.Format( aColStr, SCA_VALID_COL, NULL );
3973 aString += aColStr;
3974 pArr[nCount] = aString;
3975 ++nCount;
3978 else
3980 sal_Int32 n = p->aEnd.Row() - p->aStart.Row() + 1;
3981 for (sal_Int32 i = 0; i < n; ++i)
3982 pArr[nCount++] = String::CreateFromInt32( i+1 );
3985 return aSeq;
3988 ::rtl::OUString SAL_CALL ScChart2EmptyDataSequence::getSourceRangeRepresentation()
3989 throw ( uno::RuntimeException)
3991 ScUnoGuard aGuard;
3992 String aStr;
3993 DBG_ASSERT( m_pDocument, "No Document -> no SourceRangeRepresentation" );
3994 if( m_pDocument )
3995 m_xRanges->Format( aStr, SCR_ABS_3D, m_pDocument, m_pDocument->GetAddressConvention() );
3996 return aStr;
3999 uno::Sequence< ::rtl::OUString > SAL_CALL ScChart2EmptyDataSequence::generateLabel(chart2::data::LabelOrigin /*nOrigin*/)
4000 throw (uno::RuntimeException)
4002 ScUnoGuard aGuard;
4003 uno::Sequence< ::rtl::OUString > aRet;
4004 return aRet;
4007 ::sal_Int32 SAL_CALL ScChart2EmptyDataSequence::getNumberFormatKeyByIndex( ::sal_Int32 /*nIndex*/ )
4008 throw (lang::IndexOutOfBoundsException,
4009 uno::RuntimeException)
4011 sal_Int32 nResult = 0;
4013 ScUnoGuard aGuard;
4014 if ( !m_pDocument)
4015 return nResult;
4017 return nResult;
4020 // XCloneable ================================================================
4022 uno::Reference< util::XCloneable > SAL_CALL ScChart2EmptyDataSequence::createClone()
4023 throw (uno::RuntimeException)
4025 ScUnoGuard aGuard;
4026 if (m_xDataProvider.is())
4028 // copy properties
4029 uno::Reference < util::XCloneable > xClone(new ScChart2EmptyDataSequence(m_pDocument, m_xDataProvider, new ScRangeList(*m_xRanges), m_bColumn));
4030 uno::Reference< beans::XPropertySet > xProp( xClone, uno::UNO_QUERY );
4031 if( xProp.is())
4033 xProp->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_ROLE )),
4034 uno::makeAny( m_aRole ));
4035 xProp->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS )),
4036 uno::makeAny( m_bIncludeHiddenCells ));
4038 return xClone;
4040 return uno::Reference< util::XCloneable >();
4043 // XModifyBroadcaster ========================================================
4045 void SAL_CALL ScChart2EmptyDataSequence::addModifyListener( const uno::Reference< util::XModifyListener >& /*aListener*/ )
4046 throw (uno::RuntimeException)
4048 // TODO: Implement
4051 void SAL_CALL ScChart2EmptyDataSequence::removeModifyListener( const uno::Reference< util::XModifyListener >& /*aListener*/ )
4052 throw (uno::RuntimeException)
4054 // TODO: Implement
4057 // DataSequence XPropertySet -------------------------------------------------
4059 uno::Reference< beans::XPropertySetInfo> SAL_CALL
4060 ScChart2EmptyDataSequence::getPropertySetInfo() throw( uno::RuntimeException)
4062 ScUnoGuard aGuard;
4063 static uno::Reference<beans::XPropertySetInfo> aRef =
4064 new SfxItemPropertySetInfo( m_aPropSet.getPropertyMap() );
4065 return aRef;
4069 void SAL_CALL ScChart2EmptyDataSequence::setPropertyValue(
4070 const ::rtl::OUString& rPropertyName, const uno::Any& rValue)
4071 throw( beans::UnknownPropertyException,
4072 beans::PropertyVetoException,
4073 lang::IllegalArgumentException,
4074 lang::WrappedTargetException, uno::RuntimeException)
4076 if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE)))
4078 if ( !(rValue >>= m_aRole))
4079 throw lang::IllegalArgumentException();
4081 else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS)))
4083 if ( !(rValue >>= m_bIncludeHiddenCells))
4084 throw lang::IllegalArgumentException();
4086 else
4087 throw beans::UnknownPropertyException();
4088 // TODO: support optional properties
4092 uno::Any SAL_CALL ScChart2EmptyDataSequence::getPropertyValue(
4093 const ::rtl::OUString& rPropertyName)
4094 throw( beans::UnknownPropertyException,
4095 lang::WrappedTargetException, uno::RuntimeException)
4097 uno::Any aRet;
4098 if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE)))
4099 aRet <<= m_aRole;
4100 else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS)))
4101 aRet <<= m_bIncludeHiddenCells;
4102 else
4103 throw beans::UnknownPropertyException();
4104 // TODO: support optional properties
4105 return aRet;
4109 void SAL_CALL ScChart2EmptyDataSequence::addPropertyChangeListener(
4110 const ::rtl::OUString& /*rPropertyName*/,
4111 const uno::Reference< beans::XPropertyChangeListener>& /*xListener*/)
4112 throw( beans::UnknownPropertyException,
4113 lang::WrappedTargetException, uno::RuntimeException)
4115 // FIXME: real implementation
4116 // throw uno::RuntimeException();
4117 OSL_ENSURE( false, "Not yet implemented" );
4121 void SAL_CALL ScChart2EmptyDataSequence::removePropertyChangeListener(
4122 const ::rtl::OUString& /*rPropertyName*/,
4123 const uno::Reference< beans::XPropertyChangeListener>& /*rListener*/)
4124 throw( beans::UnknownPropertyException,
4125 lang::WrappedTargetException, uno::RuntimeException)
4127 // FIXME: real implementation
4128 // throw uno::RuntimeException();
4129 OSL_ENSURE( false, "Not yet implemented" );
4133 void SAL_CALL ScChart2EmptyDataSequence::addVetoableChangeListener(
4134 const ::rtl::OUString& /*rPropertyName*/,
4135 const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/)
4136 throw( beans::UnknownPropertyException,
4137 lang::WrappedTargetException, uno::RuntimeException)
4139 // FIXME: real implementation
4140 // throw uno::RuntimeException();
4141 OSL_ENSURE( false, "Not yet implemented" );
4145 void SAL_CALL ScChart2EmptyDataSequence::removeVetoableChangeListener(
4146 const ::rtl::OUString& /*rPropertyName*/,
4147 const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/ )
4148 throw( beans::UnknownPropertyException,
4149 lang::WrappedTargetException, uno::RuntimeException)
4151 // FIXME: real implementation
4152 // throw uno::RuntimeException();
4153 OSL_ENSURE( false, "Not yet implemented" );
4156 // XUnoTunnel
4158 // sal_Int64 SAL_CALL ScChart2EmptyDataSequence::getSomething(
4159 // const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException)
4160 // {
4161 // if ( rId.getLength() == 16 &&
4162 // 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
4163 // rId.getConstArray(), 16 ) )
4164 // {
4165 // return (sal_Int64)this;
4166 // }
4167 // return 0;
4168 // }
4170 // // static
4171 // const uno::Sequence<sal_Int8>& ScChart2EmptyDataSequence::getUnoTunnelId()
4172 // {
4173 // static uno::Sequence<sal_Int8> * pSeq = 0;
4174 // if( !pSeq )
4175 // {
4176 // osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
4177 // if( !pSeq )
4178 // {
4179 // static uno::Sequence< sal_Int8 > aSeq( 16 );
4180 // rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
4181 // pSeq = &aSeq;
4182 // }
4183 // }
4184 // return *pSeq;
4185 // }
4187 // // static
4188 // ScChart2DataSequence* ScChart2EmptyDataSequence::getImplementation( const uno::Reference<uno::XInterface> xObj )
4189 // {
4190 // ScChart2DataSequence* pRet = NULL;
4191 // uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY );
4192 // if (xUT.is())
4193 // pRet = (ScChart2EmptyDataSequence*) xUT->getSomething( getUnoTunnelId() );
4194 // return pRet;
4195 // }
4196 #endif