update dev300-m58
[ooovba.git] / sc / source / ui / unoobj / chart2uno.cxx
blobc7d76690b30c22bf5afd6abbbd5945dfe85f67bd
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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 // ----------------------------------------------------------------------------
391 /**
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 SCCOLROW nTmp = n2 - n1 + 1;
504 if (n1 < mnStartCol)
505 mnStartCol = static_cast<SCCOL>(n1);
506 if (n2 > nEndCol)
507 nEndCol = static_cast<SCCOL>(n2);
508 if (nTmp > nMaxCols)
509 nMaxCols = static_cast<SCCOL>(nTmp);
511 n1 = aData.Ref1.nRow;
512 n2 = aData.Ref2.nRow;
513 nTmp = n2 - n1 + 1;
515 if (n1 < mnStartRow)
516 mnStartRow = static_cast<SCCOL>(n1);
517 if (n2 > nEndRow)
518 nEndRow = static_cast<SCCOL>(n2);
519 if (nTmp > nMaxRows)
520 nMaxRows = static_cast<SCCOL>(nTmp);
523 // total column size ?
524 SCCOL nC = nEndCol - mnStartCol + 1;
525 if (nC == 1)
527 meGlue = GLUETYPE_ROWS;
528 return;
530 // total row size ?
531 SCROW nR = nEndRow - mnStartRow + 1;
532 if (nR == 1)
534 meGlue = GLUETYPE_COLS;
535 return;
537 sal_uInt32 nCR = static_cast<sal_uInt32>(nC*nR);
539 const sal_uInt8 nHole = 0;
540 const sal_uInt8 nOccu = 1;
541 const sal_uInt8 nFree = 2;
542 const sal_uInt8 nGlue = 3;
544 vector<sal_uInt8> aCellStates(nCR);
545 for (vector<ScSharedTokenRef>::const_iterator itr = mpRefTokens->begin(), itrEnd = mpRefTokens->end();
546 itr != itrEnd; ++itr)
548 ScRefTokenHelper::getDoubleRefDataFromToken(aData, *itr);
549 SCCOL nCol1 = static_cast<SCCOL>(aData.Ref1.nCol) - mnStartCol;
550 SCCOL nCol2 = static_cast<SCCOL>(aData.Ref2.nCol) - mnStartCol;
551 SCROW nRow1 = static_cast<SCROW>(aData.Ref1.nRow) - mnStartRow;
552 SCROW nRow2 = static_cast<SCROW>(aData.Ref2.nRow) - mnStartRow;
553 for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
554 for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
556 size_t i = nCol*nR + nRow;
557 aCellStates[i] = nOccu;
560 bool bGlue = true;
562 size_t i = 0;
563 bool bGlueCols = false;
564 for (SCCOL nCol = 0; bGlue && nCol < nC; ++nCol)
566 for (SCROW nRow = 0; bGlue && nRow < nR; ++nRow)
568 i = nCol*nR + nRow;
569 if (aCellStates[i] == nOccu)
571 if (nRow > 0 && nRow > 0)
572 bGlue = false;
573 else
574 nRow = nR;
576 else
577 aCellStates[i] = nFree;
579 i = (nCol+1)*nR - 1; // index for the last cell in the column.
580 if (bGlue && (aCellStates[i] == nFree))
582 aCellStates[i] = nGlue;
583 bGlueCols = true;
587 bool bGlueRows = false;
588 for (SCROW nRow = 0; bGlue && nRow < nR; ++nRow)
590 i = nRow;
591 for (SCCOL nCol = 0; bGlue && nCol < nC; ++nCol, i += nR)
593 if (aCellStates[i] == nOccu)
595 if (nCol > 0 && nRow > 0)
596 bGlue = false;
597 else
598 nCol = nC;
600 else
601 aCellStates[i] = nFree;
603 i = (nC-1)*nR + nRow; // index for the row position in the last column.
604 if (bGlue && aCellStates[i] == nFree)
606 aCellStates[i] = nGlue;
607 bGlueRows = true;
611 i = 1;
612 for (sal_uInt32 n = 1; bGlue && n < nCR; ++n, ++i)
613 if (aCellStates[i] == nHole)
614 bGlue = false;
616 if (bGlue)
618 if (bGlueCols && bGlueRows)
619 meGlue = GLUETYPE_BOTH;
620 else if (bGlueRows)
621 meGlue = GLUETYPE_ROWS;
622 else
623 meGlue = GLUETYPE_COLS;
624 if (aCellStates.front() != nOccu)
625 mbDummyUpperLeft = true;
627 else
628 meGlue = GLUETYPE_NONE;
631 void Chart2Positioner::createPositionMap()
633 if (meGlue == GLUETYPE_NA && mpPositionMap.get())
634 mpPositionMap.reset(NULL);
636 if (mpPositionMap.get())
637 return;
639 glueState();
641 bool bNoGlue = (meGlue == GLUETYPE_NONE);
642 auto_ptr<Table> pCols(new Table);
643 auto_ptr<FormulaToken> pNewAddress;
644 auto_ptr<Table> pNewRowTable(new Table);
645 Table* pCol = NULL;
646 SCROW nNoGlueRow = 0;
647 for (vector<ScSharedTokenRef>::const_iterator itr = mpRefTokens->begin(), itrEnd = mpRefTokens->end();
648 itr != itrEnd; ++itr)
650 const ScSharedTokenRef& pToken = *itr;
652 bool bExternal = ScRefTokenHelper::isExternalRef(pToken);
653 sal_uInt16 nFileId = bExternal ? pToken->GetIndex() : 0;
654 String aTabName = bExternal ? pToken->GetString() : String();
656 ScComplexRefData aData;
657 ScRefTokenHelper::getDoubleRefDataFromToken(aData, *itr);
658 const ScSingleRefData& s = aData.Ref1;
659 const ScSingleRefData& e = aData.Ref2;
660 SCCOL nCol1 = s.nCol, nCol2 = e.nCol;
661 SCROW nRow1 = s.nRow, nRow2 = e.nRow;
662 SCTAB nTab1 = s.nTab, nTab2 = e.nTab;
664 for (SCTAB nTab = nTab1; nTab <= nTab2; ++nTab)
666 // What's this for ???
667 sal_uInt32 nInsCol = (static_cast<sal_uInt32>(nTab) << 16) |
668 (bNoGlue ? 0 : static_cast<sal_uInt32>(nCol1));
669 for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol, ++nInsCol)
671 if (bNoGlue || meGlue == GLUETYPE_ROWS)
673 pCol = static_cast<Table*>(pCols->Get(nInsCol));
674 if (!pCol)
676 pCol = pNewRowTable.get();
677 pCols->Insert(nInsCol, pNewRowTable.release());
678 pNewRowTable.reset(new Table);
681 else
683 if (pCols->Insert(nInsCol, pNewRowTable.get()))
685 pCol = pNewRowTable.release();
686 pNewRowTable.reset(new Table);
688 else
689 pCol = static_cast<Table*>(pCols->Get(nInsCol));
692 sal_uInt32 nInsRow = static_cast<sal_uInt32>(bNoGlue ? nNoGlueRow : nRow1);
693 for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow, ++nInsRow)
695 ScSingleRefData aCellData;
696 aCellData.InitFlags();
697 aCellData.SetFlag3D(true);
698 aCellData.SetColRel(false);
699 aCellData.SetRowRel(false);
700 aCellData.SetTabRel(false);
701 aCellData.nCol = nCol;
702 aCellData.nRow = nRow;
703 aCellData.nTab = nTab;
705 if (bExternal)
706 pNewAddress.reset(new ScExternalSingleRefToken(nFileId, aTabName, aCellData));
707 else
708 pNewAddress.reset(new ScSingleRefToken(aCellData));
710 if (pCol->Insert(nInsRow, pNewAddress.get()))
711 pNewAddress.release(); // To prevent the instance from being destroyed.
715 nNoGlueRow += nRow2 - nRow1 + 1;
717 pNewAddress.reset(NULL);
718 pNewRowTable.reset(NULL);
720 bool bColAdd = mbRowHeaders;
721 bool bRowAdd = mbColHeaders;
723 SCSIZE nColCount = static_cast<SCSIZE>(pCols->Count());
724 SCSIZE nRowCount = 0;
725 pCol = static_cast<Table*>(pCols->First());
726 if (pCol)
728 if (mbDummyUpperLeft)
729 pCol->Insert(0, NULL); // Dummy fuer Beschriftung
730 nRowCount = static_cast<SCSIZE>(pCol->Count());
732 else
733 nRowCount = 0;
735 if (nColCount > 0 && bColAdd)
736 nColCount -= 1;
737 if (nRowCount > 0 && bRowAdd)
738 nRowCount -= 1;
740 if (nColCount == 0 || nRowCount == 0)
742 ScComplexRefData aData;
743 ScRefTokenHelper::getDoubleRefDataFromToken(aData, mpRefTokens->front());
744 if (pCols->Count() > 0)
745 pCol = static_cast<Table*>(pCols->First());
746 else
748 pCol = new Table;
749 pCols->Insert(0, pCol);
751 nColCount = 1;
752 if (pCol->Count() > 0)
754 FormulaToken* pPos = static_cast<FormulaToken*>(pCol->First());
755 if (pPos)
757 delete pPos;
758 pCol->Replace(pCol->GetCurKey(), NULL);
761 else
762 pCol->Insert(0, NULL);
764 nRowCount = 1;
765 bColAdd = false;
766 bRowAdd = false;
768 else
770 if (bNoGlue)
772 Table* pFirstCol = static_cast<Table*>(pCols->First());
773 sal_uInt32 nCount = pFirstCol->Count();
774 pFirstCol->First();
775 for (sal_uInt32 n = 0; n < nCount; ++n, pFirstCol->Next())
777 sal_uInt32 nKey = pFirstCol->GetCurKey();
778 pCols->First();
779 for (pCol = static_cast<Table*>(pCols->Next()); pCol; pCol = static_cast<Table*>(pCols->Next()))
780 pCol->Insert(nKey, NULL);
784 mpPositionMap.reset(
785 new Chart2PositionMap(
786 static_cast<SCCOL>(nColCount), static_cast<SCROW>(nRowCount),
787 bColAdd, bRowAdd, *pCols));
789 // Destroy all column instances.
790 for (pCol = static_cast<Table*>(pCols->First()); pCol; pCol = static_cast<Table*>(pCols->Next()))
791 delete pCol;
794 // ============================================================================
796 /**
797 * Function object to create a range string from a token list.
799 class Tokens2RangeString : public unary_function<ScSharedTokenRef, void>
801 public:
802 Tokens2RangeString(ScDocument* pDoc, FormulaGrammar::Grammar eGram, sal_Unicode cRangeSep) :
803 mpRangeStr(new OUStringBuffer),
804 mpDoc(pDoc),
805 meGrammar(eGram),
806 mcRangeSep(cRangeSep),
807 mbFirst(true)
811 Tokens2RangeString(const Tokens2RangeString& r) :
812 mpRangeStr(r.mpRangeStr),
813 mpDoc(r.mpDoc),
814 meGrammar(r.meGrammar),
815 mcRangeSep(r.mcRangeSep),
816 mbFirst(r.mbFirst)
820 void operator() (const ScSharedTokenRef& rToken)
822 ScCompiler aCompiler(mpDoc, ScAddress(0,0,0));
823 aCompiler.SetGrammar(meGrammar);
824 String aStr;
825 aCompiler.CreateStringFromToken(aStr, rToken.get());
826 if (mbFirst)
827 mbFirst = false;
828 else
829 mpRangeStr->append(mcRangeSep);
830 mpRangeStr->append(aStr);
833 void getString(OUString& rStr)
835 rStr = mpRangeStr->makeStringAndClear();
838 private:
839 Tokens2RangeString(); // disabled
841 private:
842 shared_ptr<OUStringBuffer> mpRangeStr;
843 ScDocument* mpDoc;
844 FormulaGrammar::Grammar meGrammar;
845 sal_Unicode mcRangeSep;
846 bool mbFirst;
849 /**
850 * Function object to convert a list of tokens into a string form suitable
851 * for ODF export. In ODF, a range is expressed as
853 * (start cell address):(end cell address)
855 * and each address doesn't include any '$' symbols.
857 class Tokens2RangeStringXML : public unary_function<ScSharedTokenRef, void>
859 public:
860 Tokens2RangeStringXML(ScDocument* pDoc) :
861 mpRangeStr(new OUStringBuffer),
862 mpDoc(pDoc),
863 mcRangeSep(' '),
864 mcAddrSep(':'),
865 mbFirst(true)
869 Tokens2RangeStringXML(const Tokens2RangeStringXML& r) :
870 mpRangeStr(r.mpRangeStr),
871 mpDoc(r.mpDoc),
872 mcRangeSep(r.mcRangeSep),
873 mcAddrSep(r.mcAddrSep),
874 mbFirst(r.mbFirst)
878 void operator() (const ScSharedTokenRef& rToken)
880 if (mbFirst)
881 mbFirst = false;
882 else
883 mpRangeStr->append(mcRangeSep);
885 ScSharedTokenRef aStart, aEnd;
886 splitRangeToken(rToken, aStart, aEnd);
887 ScCompiler aCompiler(mpDoc, ScAddress(0,0,0));
888 aCompiler.SetGrammar(FormulaGrammar::GRAM_ENGLISH);
890 String aStr;
891 aCompiler.CreateStringFromToken(aStr, aStart.get());
892 mpRangeStr->append(aStr);
894 mpRangeStr->append(mcAddrSep);
896 String aStr;
897 aCompiler.CreateStringFromToken(aStr, aEnd.get());
898 mpRangeStr->append(aStr);
902 void getString(OUString& rStr)
904 rStr = mpRangeStr->makeStringAndClear();
907 private:
908 Tokens2RangeStringXML(); // disabled
910 void splitRangeToken(const ScSharedTokenRef& pToken, ScSharedTokenRef& rStart, ScSharedTokenRef& rEnd) const
912 ScComplexRefData aData;
913 ScRefTokenHelper::getDoubleRefDataFromToken(aData, pToken);
914 bool bExternal = ScRefTokenHelper::isExternalRef(pToken);
915 sal_uInt16 nFileId = bExternal ? pToken->GetIndex() : 0;
916 String aTabName = bExternal ? pToken->GetString() : String();
918 // In saving to XML, we don't prepend address with '$'.
919 setRelative(aData.Ref1);
920 setRelative(aData.Ref2);
922 // In XML, the end range must explicitly specify sheet name.
923 aData.Ref2.SetFlag3D(true);
925 if (bExternal)
926 rStart.reset(new ScExternalSingleRefToken(nFileId, aTabName, aData.Ref1));
927 else
928 rStart.reset(new ScSingleRefToken(aData.Ref1));
930 if (bExternal)
931 rEnd.reset(new ScExternalSingleRefToken(nFileId, aTabName, aData.Ref2));
932 else
933 rEnd.reset(new ScSingleRefToken(aData.Ref2));
936 void setRelative(ScSingleRefData& rData) const
938 rData.SetColRel(true);
939 rData.SetRowRel(true);
940 rData.SetTabRel(true);
943 private:
944 shared_ptr<OUStringBuffer> mpRangeStr;
945 ScDocument* mpDoc;
946 sal_Unicode mcRangeSep;
947 sal_Unicode mcAddrSep;
948 bool mbFirst;
951 void lcl_convertTokensToString(OUString& rStr, const vector<ScSharedTokenRef>& rTokens, ScDocument* pDoc)
953 const sal_Unicode cRangeSep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
954 FormulaGrammar::Grammar eGrammar = pDoc->GetGrammar();
955 Tokens2RangeString func(pDoc, eGrammar, cRangeSep);
956 func = for_each(rTokens.begin(), rTokens.end(), func);
957 func.getString(rStr);
960 } // anonymous namespace
962 // DataProvider ==============================================================
964 ScChart2DataProvider::ScChart2DataProvider( ScDocument* pDoc )
965 : m_pDocument( pDoc)
966 , m_aPropSet(lcl_GetDataProviderPropertyMap())
967 , m_bIncludeHiddenCells( sal_True)
969 if ( m_pDocument )
970 m_pDocument->AddUnoObject( *this);
973 ScChart2DataProvider::~ScChart2DataProvider()
975 if ( m_pDocument )
976 m_pDocument->RemoveUnoObject( *this);
980 void ScChart2DataProvider::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
982 if ( rHint.ISA( SfxSimpleHint ) &&
983 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
985 m_pDocument = NULL;
989 ::sal_Bool SAL_CALL ScChart2DataProvider::createDataSourcePossible( const uno::Sequence< beans::PropertyValue >& aArguments )
990 throw (uno::RuntimeException)
992 ScUnoGuard aGuard;
993 if( ! m_pDocument )
994 return false;
996 rtl::OUString aRangeRepresentation;
997 for(sal_Int32 i = 0; i < aArguments.getLength(); ++i)
999 rtl::OUString sName(aArguments[i].Name);
1000 if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CellRangeRepresentation")))
1002 aArguments[i].Value >>= aRangeRepresentation;
1006 vector<ScSharedTokenRef> aTokens;
1007 ScRefTokenHelper::compileRangeRepresentation(aTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar());
1008 return !aTokens.empty();
1011 namespace {
1013 class RemoveHeaderFromRanges : public unary_function<ScSharedTokenRef, void>
1015 public:
1016 RemoveHeaderFromRanges(const ScSharedTokenRef& rHeaderCell, bool bOrientCol) :
1017 mpTokens(new vector<ScSharedTokenRef>),
1018 mpHeaderCell(rHeaderCell),
1019 mbOrientCol(bOrientCol)
1023 RemoveHeaderFromRanges(const RemoveHeaderFromRanges& r) :
1024 mpTokens(r.mpTokens),
1025 mpHeaderCell(r.mpHeaderCell),
1026 mbOrientCol(r.mbOrientCol)
1030 void operator() (const ScSharedTokenRef& pRange)
1032 if (!isContained(pRange))
1034 // header cell is not part of this range. Just add it to the
1035 // range list and move on.
1036 ScRefTokenHelper::join(*mpTokens, pRange);
1037 return;
1040 // This range contains the header cell.
1042 ScComplexRefData aRange;
1043 ScRefTokenHelper::getDoubleRefDataFromToken(aRange, pRange);
1044 const ScSingleRefData& s = aRange.Ref1;
1045 const ScSingleRefData& e = aRange.Ref2;
1046 const ScSingleRefData& h = mpHeaderCell->GetSingleRef();
1048 if (equals(s, e))
1049 // This range *only* contains the header cell. Skip it.
1050 return;
1052 if (s.nTab != e.nTab)
1053 // 3D range has no business being here....
1054 return;
1056 if (mbOrientCol)
1058 // column major
1060 if (s.nCol == e.nCol)
1062 // single column range.
1063 splitSingleColRange(pRange, s, e);
1065 else
1067 if (s.nCol == h.nCol)
1069 // header cell is in the first column.
1072 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1073 ScComplexRefData& r = pNew->GetDoubleRef();
1074 r.Ref2.InitAddress(s.nCol, e.nRow, s.nTab);
1075 splitSingleColRange(pNew, r.Ref1, r.Ref2);
1079 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1080 ScComplexRefData& r = pNew->GetDoubleRef();
1081 r.Ref1.InitAddress(s.nCol + 1, s.nRow, s.nTab);
1082 ScRefTokenHelper::join(*mpTokens, pNew);
1085 else if (e.nCol == h.nCol)
1087 // header cell is in the last column.
1090 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1091 ScComplexRefData& r = pNew->GetDoubleRef();
1092 r.Ref1.InitAddress(e.nCol, s.nRow, s.nTab);
1093 splitSingleColRange(pNew, r.Ref1, r.Ref2);
1097 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1098 ScComplexRefData& r = pNew->GetDoubleRef();
1099 r.Ref2.InitAddress(e.nCol - 1, e.nRow, e.nTab);
1100 ScRefTokenHelper::join(*mpTokens, pNew);
1103 else
1105 // header cell is somewhere between the first and last columns.
1108 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1109 ScComplexRefData& r = pNew->GetDoubleRef();
1110 r.Ref2.InitAddress(h.nCol - 1, e.nRow, h.nTab);
1111 ScRefTokenHelper::join(*mpTokens, pNew);
1115 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1116 ScComplexRefData& r = pNew->GetDoubleRef();
1117 r.Ref1.InitAddress(h.nCol, s.nRow, s.nTab);
1118 r.Ref2.InitAddress(h.nCol, e.nRow, e.nTab);
1119 splitSingleColRange(pNew, r.Ref1, r.Ref2);
1123 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1124 ScComplexRefData& r = pNew->GetDoubleRef();
1125 r.Ref1.InitAddress(h.nCol + 1, s.nRow, h.nTab);
1126 ScRefTokenHelper::join(*mpTokens, pNew);
1131 else
1133 // row major
1135 if (s.nRow == e.nRow)
1137 // Single row range.
1138 splitSingleRowRange(pRange, s, e);
1140 else
1142 if (s.nRow == h.nRow)
1144 // header cell is in the first row.
1147 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1148 ScComplexRefData& r = pNew->GetDoubleRef();
1149 r.Ref2.InitAddress(e.nCol, s.nRow, s.nTab);
1150 splitSingleRowRange(pNew, r.Ref1, r.Ref2);
1154 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1155 ScComplexRefData& r = pNew->GetDoubleRef();
1156 r.Ref1.InitAddress(s.nCol, s.nRow + 1, s.nTab);
1157 ScRefTokenHelper::join(*mpTokens, pNew);
1160 else if (e.nRow == h.nRow)
1162 // header cell is in the last row.
1165 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1166 ScComplexRefData& r = pNew->GetDoubleRef();
1167 r.Ref1.InitAddress(s.nCol, e.nRow, s.nTab);
1168 splitSingleRowRange(pNew, r.Ref1, r.Ref2);
1172 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1173 ScComplexRefData& r = pNew->GetDoubleRef();
1174 r.Ref2.InitAddress(e.nCol, e.nRow - 1, e.nTab);
1175 ScRefTokenHelper::join(*mpTokens, pNew);
1178 else
1180 // header cell is somewhere between the 1st and last rows.
1183 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1184 ScComplexRefData& r = pNew->GetDoubleRef();
1185 r.Ref2.InitAddress(e.nCol, h.nRow - 1, h.nTab);
1186 ScRefTokenHelper::join(*mpTokens, pNew);
1190 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1191 ScComplexRefData& r = pNew->GetDoubleRef();
1192 r.Ref1.InitAddress(s.nCol, h.nRow, s.nTab);
1193 r.Ref2.InitAddress(e.nCol, h.nRow, e.nTab);
1194 splitSingleRowRange(pNew, r.Ref1, r.Ref2);
1198 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1199 ScComplexRefData& r = pNew->GetDoubleRef();
1200 r.Ref1.InitAddress(s.nCol, h.nRow + 1, h.nTab);
1201 ScRefTokenHelper::join(*mpTokens, pNew);
1208 void getNewTokens(vector<ScSharedTokenRef>& rTokens)
1210 mpTokens->swap(rTokens);
1213 private:
1215 void splitSingleColRange(const ScSharedTokenRef& pRange, const ScSingleRefData& s, const ScSingleRefData& e)
1217 const ScSingleRefData& h = mpHeaderCell->GetSingleRef();
1219 if (equals(s, h))
1221 // header is at the top.
1223 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1224 ScComplexRefData& r = pNew->GetDoubleRef();
1225 r.Ref1.nRow += 1;
1226 ScRefTokenHelper::join(*mpTokens, pNew);
1228 else if (equals(e, h))
1230 // header is at the bottom.
1232 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1233 ScComplexRefData& r = pNew->GetDoubleRef();
1234 r.Ref2.nRow -= 1;
1235 ScRefTokenHelper::join(*mpTokens, pNew);
1237 else
1239 // header is somewhere in the middle.
1242 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1243 ScComplexRefData& r = pNew->GetDoubleRef();
1244 r.Ref2.InitAddress(h.nCol, h.nRow - 1, h.nTab);
1245 ScRefTokenHelper::join(*mpTokens, pNew);
1249 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1250 ScComplexRefData& r = pNew->GetDoubleRef();
1251 r.Ref1.InitAddress(h.nCol, h.nRow + 1, h.nTab);
1252 ScRefTokenHelper::join(*mpTokens, pNew);
1257 void splitSingleRowRange(const ScSharedTokenRef& pRange, const ScSingleRefData& s, const ScSingleRefData& e)
1259 const ScSingleRefData& h = mpHeaderCell->GetSingleRef();
1261 if (equals(s, h))
1263 // header is at the top.
1265 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1266 ScComplexRefData& r = pNew->GetDoubleRef();
1267 r.Ref1.nCol += 1;
1268 ScRefTokenHelper::join(*mpTokens, pNew);
1270 else if (equals(e, h))
1272 // header is at the bottom.
1274 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1275 ScComplexRefData& r = pNew->GetDoubleRef();
1276 r.Ref2.nCol -= 1;
1277 ScRefTokenHelper::join(*mpTokens, pNew);
1279 else
1281 // header is somewhere in the middle.
1284 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1285 ScComplexRefData& r = pNew->GetDoubleRef();
1286 r.Ref2.InitAddress(h.nCol - 1, h.nRow, h.nTab);
1287 ScRefTokenHelper::join(*mpTokens, pNew);
1291 ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
1292 ScComplexRefData& r = pNew->GetDoubleRef();
1293 r.Ref1.InitAddress(h.nCol + 1, h.nRow, h.nTab);
1294 ScRefTokenHelper::join(*mpTokens, pNew);
1299 /**
1300 * Compare two single ref data for equality, but only compare their
1301 * absolute cell addresses while ignoring flags and relative addresses.
1303 bool equals(const ScSingleRefData& r1, const ScSingleRefData& r2) const
1305 return (r1.nCol == r2.nCol) && (r1.nRow == r2.nRow) && (r1.nTab == r2.nTab);
1308 bool isContained(const ScSharedTokenRef& pRange)
1310 bool bExternal = ScRefTokenHelper::isExternalRef(mpHeaderCell);
1311 if (bExternal != ScRefTokenHelper::isExternalRef(pRange))
1312 // internal vs external.
1313 return false;
1315 if (bExternal)
1317 if (pRange->GetIndex() != mpHeaderCell->GetIndex())
1318 // different external files.
1319 return false;
1321 if (pRange->GetString() != mpHeaderCell->GetString())
1322 // different table.
1323 return false;
1326 ScComplexRefData aRange;
1327 ScRefTokenHelper::getDoubleRefDataFromToken(aRange, pRange);
1328 const ScSingleRefData& rCell = mpHeaderCell->GetSingleRef();
1330 bool bRowContained = (aRange.Ref1.nRow <= rCell.nRow) && (rCell.nRow <= aRange.Ref2.nRow);
1331 bool bColContained = (aRange.Ref1.nCol <= rCell.nCol) && (rCell.nCol <= aRange.Ref2.nCol);
1332 bool bTabContained = (aRange.Ref1.nTab <= rCell.nTab) && (rCell.nTab <= aRange.Ref2.nTab);
1334 return (bRowContained && bColContained && bTabContained);
1337 private:
1338 shared_ptr< vector<ScSharedTokenRef> > mpTokens;
1340 /**
1341 * Stores header cell position. Must be a single ref token i.e. either
1342 * ScSingleRefToken or ScExternalSingleRefToken.
1344 ScSharedTokenRef mpHeaderCell;
1346 bool mbOrientCol;
1351 static void lcl_removeHeaderFromRanges(vector<ScSharedTokenRef>& rTokens, const ScSharedTokenRef& rHeaderCell, bool bOrientCol)
1353 RemoveHeaderFromRanges func(rHeaderCell, bOrientCol);
1354 func = for_each(rTokens.begin(), rTokens.end(), func);
1355 func.getNewTokens(rTokens);
1358 uno::Reference< chart2::data::XDataSource> SAL_CALL
1359 ScChart2DataProvider::createDataSource(
1360 const uno::Sequence< beans::PropertyValue >& aArguments )
1361 throw( lang::IllegalArgumentException, uno::RuntimeException)
1363 ScUnoGuard aGuard;
1364 if ( ! m_pDocument )
1365 throw uno::RuntimeException();
1367 uno::Reference< chart2::data::XDataSource> xResult;
1368 bool bLabel = true;
1369 bool bOrientCol = true;
1370 ::rtl::OUString aRangeRepresentation;
1371 uno::Sequence< sal_Int32 > aSequenceMapping;
1372 for(sal_Int32 i = 0; i < aArguments.getLength(); ++i)
1374 rtl::OUString sName(aArguments[i].Name);
1375 if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataRowSource")))
1377 chart::ChartDataRowSource eSource = chart::ChartDataRowSource_COLUMNS;
1378 if( ! (aArguments[i].Value >>= eSource))
1380 sal_Int32 nSource(0);
1381 if( aArguments[i].Value >>= nSource )
1382 eSource = (static_cast< chart::ChartDataRowSource >( nSource ));
1384 bOrientCol = (eSource == chart::ChartDataRowSource_COLUMNS);
1386 else if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FirstCellAsLabel")))
1388 bLabel = ::cppu::any2bool(aArguments[i].Value);
1390 else if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CellRangeRepresentation")))
1392 aArguments[i].Value >>= aRangeRepresentation;
1394 else if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("SequenceMapping")))
1396 aArguments[i].Value >>= aSequenceMapping;
1400 vector<ScSharedTokenRef> aRefTokens;
1401 ScRefTokenHelper::compileRangeRepresentation(aRefTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar());
1402 if (aRefTokens.empty())
1403 // Invalid range representation. Bail out.
1404 throw lang::IllegalArgumentException();
1406 if (bLabel)
1407 addUpperLeftCornerIfMissing(aRefTokens);
1409 bool bColHeaders = (bOrientCol ? bLabel : false );
1410 bool bRowHeaders = (bOrientCol ? false : bLabel );
1412 Chart2Positioner aChPositioner(m_pDocument, aRefTokens);
1413 aChPositioner.setHeaders(bColHeaders, bRowHeaders);
1415 const Chart2PositionMap* pChartMap = aChPositioner.getPositionMap();
1416 if (!pChartMap)
1417 // No chart position map instance. Bail out.
1418 return xResult;
1420 ScChart2DataSource* pDS = NULL;
1421 std::list < ScChart2LabeledDataSequence* > aSeqs;
1423 // Fill Categories
1425 ScChart2LabeledDataSequence* pHeader = NULL;
1426 if (bOrientCol ? aChPositioner.hasRowHeaders() : aChPositioner.hasColHeaders())
1428 pHeader = new ScChart2LabeledDataSequence(m_pDocument);
1429 sal_Int32 nCount = static_cast< sal_Int32 >( bOrientCol ? pChartMap->getRowCount() : pChartMap->getColCount() );
1430 vector<ScSharedTokenRef> aRefTokens2;
1431 ScSharedTokenRef pLabelToken;
1432 for (sal_Int32 i = 0; i < nCount; ++i)
1434 const FormulaToken* pPos = bOrientCol ?
1435 pChartMap->getRowHeaderPosition(static_cast<SCROW>(i)) :
1436 pChartMap->getColHeaderPosition(static_cast<SCCOL>(i));
1437 if (pPos)
1439 ScSharedTokenRef p(static_cast<ScToken*>(pPos->Clone()));
1440 ScRefTokenHelper::join(aRefTokens2, p);
1441 if (!pLabelToken)
1443 pLabelToken = p;
1444 StackVar eType = pLabelToken->GetType();
1445 if (eType == svSingleRef || eType == svExternalSingleRef)
1447 ScSingleRefData& r = pLabelToken->GetSingleRef();
1448 if (bOrientCol)
1449 r.nRow -= 1;
1450 else
1451 r.nCol -= 1;
1456 if (pLabelToken)
1458 if (bLabel)
1460 auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>);
1461 pTokens->push_back(pLabelToken);
1462 Reference < chart2::data::XDataSequence > xLabelSeq(new ScChart2DataSequence(m_pDocument, this, pTokens.release(), m_bIncludeHiddenCells));
1463 Reference< beans::XPropertySet > xLabelProps(xLabelSeq, uno::UNO_QUERY);
1464 if (xLabelProps.is())
1465 xLabelProps->setPropertyValue(
1466 OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_ROLE)),
1467 uno::makeAny(OUString(RTL_CONSTASCII_USTRINGPARAM("label"))));
1468 pHeader->setLabel(xLabelSeq);
1470 else
1471 ScRefTokenHelper::join(aRefTokens2, pLabelToken);
1473 auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>);
1474 pTokens->swap(aRefTokens2);
1475 uno::Reference< chart2::data::XDataSequence > xSeq( new ScChart2DataSequence( m_pDocument, this, pTokens.release(), m_bIncludeHiddenCells) );
1476 pHeader->setValues(xSeq);
1478 if (pHeader)
1479 aSeqs.push_back(pHeader);
1481 // Fill Serieses with Labels
1483 sal_Int32 nCount = bOrientCol ? pChartMap->getColCount() : pChartMap->getRowCount();
1484 for (sal_Int32 i = 0; i < nCount; ++i)
1486 ScChart2LabeledDataSequence* pLabeled = new ScChart2LabeledDataSequence(m_pDocument);
1487 uno::Reference < chart2::data::XDataSequence > xLabelSeq;
1488 auto_ptr< vector<ScSharedTokenRef> > pRanges(NULL);
1489 if (bOrientCol)
1490 pRanges.reset(pChartMap->getColRanges(static_cast<SCCOL>(i)));
1491 else
1492 pRanges.reset(pChartMap->getRowRanges(static_cast<SCROW>(i)));
1494 ScSharedTokenRef pHeaderCell;
1495 if (bOrientCol)
1497 const FormulaToken* p = pChartMap->getColHeaderPosition(static_cast<SCCOL>(i));
1498 if (p)
1499 pHeaderCell.reset(static_cast<ScToken*>(p->Clone()));
1501 else
1503 const FormulaToken* p = pChartMap->getRowHeaderPosition(static_cast<SCROW>(i));
1504 if (p)
1505 pHeaderCell.reset(static_cast<ScToken*>(p->Clone()));
1508 if (bLabel)
1510 if (!pHeaderCell && pRanges.get() && !pRanges->empty())
1512 const ScSharedTokenRef& p = pRanges->front();
1513 if (p && ScRefTokenHelper::isRef(p))
1515 // Take the first cell in the range as the header position.
1516 ScSingleRefData aData = p->GetSingleRef();
1517 bool bExternal = ScRefTokenHelper::isExternalRef(p);
1518 if (bExternal)
1520 sal_uInt16 nFileId = p->GetIndex();
1521 const String& rTabName = p->GetString();
1522 pHeaderCell.reset(new ScExternalSingleRefToken(nFileId, rTabName, aData));
1524 else
1525 pHeaderCell.reset(new ScSingleRefToken(aData));
1528 if (pHeaderCell)
1530 auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>);
1531 pTokens->reserve(1);
1532 pTokens->push_back(pHeaderCell);
1533 xLabelSeq.set(new ScChart2DataSequence(m_pDocument, this, pTokens.release(), m_bIncludeHiddenCells));
1534 uno::Reference< beans::XPropertySet > xLabelProps(xLabelSeq, uno::UNO_QUERY);
1535 if (xLabelProps.is())
1536 xLabelProps->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_ROLE)), uno::makeAny(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("label"))));
1538 // remove Header from Ranges
1539 lcl_removeHeaderFromRanges(*pRanges, pHeaderCell, bOrientCol);
1542 else
1544 if (pHeaderCell)
1545 ScRefTokenHelper::join(*pRanges, pHeaderCell);
1548 // FIXME: if there are no labels the column or row name should be taken
1550 uno::Reference < chart2::data::XDataSequence > xSeq(new ScChart2DataSequence(m_pDocument, this, pRanges.release(), m_bIncludeHiddenCells));
1552 pLabeled->setValues(xSeq);
1553 pLabeled->setLabel(xLabelSeq);
1555 aSeqs.push_back(pLabeled);
1558 pDS = new ScChart2DataSource(m_pDocument);
1559 std::list < ScChart2LabeledDataSequence* >::iterator aItr(aSeqs.begin());
1560 std::list < ScChart2LabeledDataSequence* >::iterator aEndItr(aSeqs.end());
1562 //reorder labeled sequences according to aSequenceMapping
1563 std::vector< ScChart2LabeledDataSequence* > aSeqVector;
1564 while(aItr != aEndItr)
1566 aSeqVector.push_back(*aItr);
1567 ++aItr;
1570 std::map< sal_Int32, ScChart2LabeledDataSequence* > aSequenceMap;
1571 for( sal_Int32 nNewIndex = 0; nNewIndex < aSequenceMapping.getLength(); nNewIndex++ )
1573 // note: assuming that the values in the sequence mapping are always non-negative
1574 std::vector< ScChart2LabeledDataSequence* >::size_type nOldIndex( static_cast< sal_uInt32 >( aSequenceMapping[nNewIndex] ));
1575 if( nOldIndex < aSeqVector.size() )
1577 pDS->AddLabeledSequence( aSeqVector[nOldIndex] );
1578 aSeqVector[nOldIndex] = 0;
1583 std::vector< ScChart2LabeledDataSequence* >::iterator aVectorItr(aSeqVector.begin());
1584 std::vector< ScChart2LabeledDataSequence* >::iterator aVectorEndItr(aSeqVector.end());
1585 while(aVectorItr != aVectorEndItr)
1587 if(*aVectorItr)
1588 pDS->AddLabeledSequence(*aVectorItr);
1589 ++aVectorItr;
1592 xResult.set( pDS );
1593 return xResult;
1596 namespace
1599 bool lcl_HasCategories(
1600 const uno::Reference< chart2::data::XDataSource >& xDataSource,
1601 bool & rOutHasCategories )
1603 bool bResult = false;
1604 uno::Reference< chart2::data::XLabeledDataSequence > xCategories(
1605 lcl_getCategoriesFromDataSource( xDataSource ));
1606 if( xCategories.is())
1608 uno::Reference< lang::XServiceInfo > xValues( xCategories->getValues(), uno::UNO_QUERY );
1609 if (xValues.is())
1611 rOutHasCategories = xValues->getImplementationName().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ScChart2DataSequence"));
1612 bResult = true;
1615 return bResult;
1618 bool lcl_HasFirstCellAsLabel(
1619 const uno::Reference< chart2::data::XDataSource >& xDataSource,
1620 bool & rOutHasFirstCellAsLabel )
1622 bool bResult = false;
1623 if( xDataSource.is())
1625 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences(
1626 xDataSource->getDataSequences());
1627 const sal_Int32 nCount( aSequences.getLength());
1628 if (nCount > 0 && aSequences[nCount - 1].is() )
1630 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
1631 if (xLabel.is())
1633 rOutHasFirstCellAsLabel = xLabel->getImplementationName().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ScChart2DataSequence"));
1634 bResult = true;
1638 return bResult;
1641 } // anonymous namespace
1643 bool ScChart2DataProvider::addUpperLeftCornerIfMissing(vector<ScSharedTokenRef>& rRefTokens)
1645 using ::std::max;
1646 using ::std::min;
1648 if (rRefTokens.empty())
1649 return false;
1651 SCCOL nMinCol = MAXCOLCOUNT;
1652 SCROW nMinRow = MAXROWCOUNT;
1653 SCCOL nMaxCol = 0;
1654 SCROW nMaxRow = 0;
1655 SCTAB nTab = 0;
1657 USHORT nFileId = 0;
1658 String aExtTabName;
1659 bool bExternal = false;
1661 vector<ScSharedTokenRef>::const_iterator itr = rRefTokens.begin(), itrEnd = rRefTokens.end();
1663 // Get the first ref token.
1664 ScSharedTokenRef pToken = *itr;
1665 switch (pToken->GetType())
1667 case svSingleRef:
1669 const ScSingleRefData& rData = pToken->GetSingleRef();
1670 nMinCol = rData.nCol;
1671 nMinRow = rData.nRow;
1672 nMaxCol = rData.nCol;
1673 nMaxRow = rData.nRow;
1674 nTab = rData.nTab;
1676 break;
1677 case svDoubleRef:
1679 const ScComplexRefData& rData = pToken->GetDoubleRef();
1680 nMinCol = min(rData.Ref1.nCol, rData.Ref2.nCol);
1681 nMinRow = min(rData.Ref1.nRow, rData.Ref2.nRow);
1682 nMaxCol = max(rData.Ref1.nCol, rData.Ref2.nCol);
1683 nMaxRow = max(rData.Ref1.nRow, rData.Ref2.nRow);
1684 nTab = rData.Ref1.nTab;
1686 break;
1687 case svExternalSingleRef:
1689 const ScSingleRefData& rData = pToken->GetSingleRef();
1690 nMinCol = rData.nCol;
1691 nMinRow = rData.nRow;
1692 nMaxCol = rData.nCol;
1693 nMaxRow = rData.nRow;
1694 nTab = rData.nTab;
1695 nFileId = pToken->GetIndex();
1696 aExtTabName = pToken->GetString();
1697 bExternal = true;
1699 break;
1700 case svExternalDoubleRef:
1702 const ScComplexRefData& rData = pToken->GetDoubleRef();
1703 nMinCol = min(rData.Ref1.nCol, rData.Ref2.nCol);
1704 nMinRow = min(rData.Ref1.nRow, rData.Ref2.nRow);
1705 nMaxCol = max(rData.Ref1.nCol, rData.Ref2.nCol);
1706 nMaxRow = max(rData.Ref1.nRow, rData.Ref2.nRow);
1707 nTab = rData.Ref1.nTab;
1708 nFileId = pToken->GetIndex();
1709 aExtTabName = pToken->GetString();
1710 bExternal = true;
1712 break;
1713 default:
1717 // Determine the minimum range enclosing all data ranges. Also make sure
1718 // that they are all on the same table.
1720 for (++itr; itr != itrEnd; ++itr)
1722 pToken = *itr;
1723 switch (pToken->GetType())
1725 case svSingleRef:
1727 const ScSingleRefData& rData = pToken->GetSingleRef();
1729 nMinCol = min(nMinCol, rData.nCol);
1730 nMinRow = min(nMinRow, rData.nRow);
1731 nMaxCol = max(nMaxCol, rData.nCol);
1732 nMaxRow = max(nMaxRow, rData.nRow);
1733 if (nTab != rData.nTab || bExternal)
1734 return false;
1736 break;
1737 case svDoubleRef:
1739 const ScComplexRefData& rData = pToken->GetDoubleRef();
1741 nMinCol = min(nMinCol, rData.Ref1.nCol);
1742 nMinCol = min(nMinCol, rData.Ref2.nCol);
1743 nMinRow = min(nMinRow, rData.Ref1.nRow);
1744 nMinRow = min(nMinRow, rData.Ref2.nRow);
1746 nMaxCol = max(nMaxCol, rData.Ref1.nCol);
1747 nMaxCol = max(nMaxCol, rData.Ref2.nCol);
1748 nMaxRow = max(nMaxRow, rData.Ref1.nRow);
1749 nMaxRow = max(nMaxRow, rData.Ref2.nRow);
1751 if (nTab != rData.Ref1.nTab || bExternal)
1752 return false;
1754 break;
1755 case svExternalSingleRef:
1757 if (!bExternal)
1758 return false;
1760 if (nFileId != pToken->GetIndex() || aExtTabName != pToken->GetString())
1761 return false;
1763 const ScSingleRefData& rData = pToken->GetSingleRef();
1765 nMinCol = min(nMinCol, rData.nCol);
1766 nMinRow = min(nMinRow, rData.nRow);
1767 nMaxCol = max(nMaxCol, rData.nCol);
1768 nMaxRow = max(nMaxRow, rData.nRow);
1770 break;
1771 case svExternalDoubleRef:
1773 if (!bExternal)
1774 return false;
1776 if (nFileId != pToken->GetIndex() || aExtTabName != pToken->GetString())
1777 return false;
1779 const ScComplexRefData& rData = pToken->GetDoubleRef();
1781 nMinCol = min(nMinCol, rData.Ref1.nCol);
1782 nMinCol = min(nMinCol, rData.Ref2.nCol);
1783 nMinRow = min(nMinRow, rData.Ref1.nRow);
1784 nMinRow = min(nMinRow, rData.Ref2.nRow);
1786 nMaxCol = max(nMaxCol, rData.Ref1.nCol);
1787 nMaxCol = max(nMaxCol, rData.Ref2.nCol);
1788 nMaxRow = max(nMaxRow, rData.Ref1.nRow);
1789 nMaxRow = max(nMaxRow, rData.Ref2.nRow);
1791 break;
1792 default:
1797 if (nMinRow >= nMaxRow || nMinCol >= nMaxCol ||
1798 nMinRow >= MAXROWCOUNT || nMinCol >= MAXCOLCOUNT ||
1799 nMaxRow >= MAXROWCOUNT || nMaxCol >= MAXCOLCOUNT)
1801 // Invalid range. Bail out.
1802 return false;
1805 // Check if the following conditions are met:
1807 // 1) The upper-left corner cell is not included.
1808 // 2) The three adjacent cells of that corner cell are included.
1810 bool bRight = false, bBottom = false, bDiagonal = false;
1811 for (itr = rRefTokens.begin(); itr != itrEnd; ++itr)
1813 pToken = *itr;
1814 switch (pToken->GetType())
1816 case svSingleRef:
1817 case svExternalSingleRef:
1819 const ScSingleRefData& rData = pToken->GetSingleRef();
1820 if (rData.nCol == nMinCol && rData.nRow == nMinRow)
1821 // The corner cell is contained.
1822 return false;
1824 if (rData.nCol == nMinCol+1 && rData.nRow == nMinRow)
1825 bRight = true;
1827 if (rData.nCol == nMinCol && rData.nRow == nMinRow+1)
1828 bBottom = true;
1830 if (rData.nCol == nMinCol+1 && rData.nRow == nMinRow+1)
1831 bDiagonal = true;
1833 break;
1834 case svDoubleRef:
1835 case svExternalDoubleRef:
1837 const ScComplexRefData& rData = pToken->GetDoubleRef();
1838 const ScSingleRefData& r1 = rData.Ref1;
1839 const ScSingleRefData& r2 = rData.Ref2;
1840 if (r1.nCol <= nMinCol && nMinCol <= r2.nCol &&
1841 r1.nRow <= nMinRow && nMinRow <= r2.nRow)
1842 // The corner cell is contained.
1843 return false;
1845 if (r1.nCol <= nMinCol+1 && nMinCol+1 <= r2.nCol &&
1846 r1.nRow <= nMinRow && nMinRow <= r2.nRow)
1847 bRight = true;
1849 if (r1.nCol <= nMinCol && nMinCol <= r2.nCol &&
1850 r1.nRow <= nMinRow+1 && nMinRow+1 <= r2.nRow)
1851 bBottom = true;
1853 if (r1.nCol <= nMinCol+1 && nMinCol+1 <= r2.nCol &&
1854 r1.nRow <= nMinRow+1 && nMinRow+1 <= r2.nRow)
1855 bDiagonal = true;
1857 break;
1858 default:
1863 if (!bRight || !bBottom || !bDiagonal)
1864 // Not all the adjacent cells are included. Bail out.
1865 return false;
1867 #if 0 // Do we really need to do this ???
1868 if (rRefTokens.size() == 2)
1870 // Make a simple rectangular range if possible.
1871 ScRange aRightPart(ScAddress(nMinCol+1, nMinRow, nTab), ScAddress(nMaxCol, nMaxRow, nTab));
1872 ScRange aBottomPart(ScAddress(nMinCol, nMinRow+1, nTab), ScAddress(nMaxCol, nMaxRow, nTab));
1873 vector<ScRange> aRanges;
1874 aRanges.reserve(2);
1875 aRanges.push_back(aRightPart);
1876 aRanges.push_back(aBottomPart);
1877 if (lcl_isRangeContained(rRefTokens, aRanges))
1879 // Consolidate them into a single rectangle.
1880 ScComplexRefData aData;
1881 aData.InitFlags();
1882 aData.Ref1.SetFlag3D(true);
1883 aData.Ref1.SetColRel(false);
1884 aData.Ref1.SetRowRel(false);
1885 aData.Ref1.SetTabRel(false);
1886 aData.Ref2.SetColRel(false);
1887 aData.Ref2.SetRowRel(false);
1888 aData.Ref2.SetTabRel(false);
1889 aData.Ref1.nCol = nMinCol;
1890 aData.Ref1.nRow = nMinRow;
1891 aData.Ref1.nTab = nTab;
1892 aData.Ref2.nCol = nMaxCol;
1893 aData.Ref2.nRow = nMaxRow;
1894 aData.Ref2.nTab = nTab;
1895 vector<ScSharedTokenRef> aNewTokens;
1896 aNewTokens.reserve(1);
1897 if (bExternal)
1899 ScSharedTokenRef p(
1900 new ScExternalDoubleRefToken(nFileId, aExtTabName, aData));
1901 aNewTokens.push_back(p);
1903 else
1905 ScSharedTokenRef p(new ScDoubleRefToken(aData));
1906 aNewTokens.push_back(p);
1908 rRefTokens.swap(aNewTokens);
1909 return true;
1912 #endif
1914 ScSingleRefData aData;
1915 aData.InitFlags();
1916 aData.SetFlag3D(true);
1917 aData.SetColRel(false);
1918 aData.SetRowRel(false);
1919 aData.SetTabRel(false);
1920 aData.nCol = nMinCol;
1921 aData.nRow = nMinRow;
1922 aData.nTab = nTab;
1924 if (bExternal)
1926 ScSharedTokenRef pCorner(
1927 new ScExternalSingleRefToken(nFileId, aExtTabName, aData));
1928 ScRefTokenHelper::join(rRefTokens, pCorner);
1930 else
1932 ScSharedTokenRef pCorner(new ScSingleRefToken(aData));
1933 ScRefTokenHelper::join(rRefTokens, pCorner);
1936 return true;
1939 namespace {
1941 /**
1942 * Function object to create a list of table numbers from a token list.
1944 class InsertTabNumber : public unary_function<ScSharedTokenRef, void>
1946 public:
1947 InsertTabNumber() :
1948 mpTabNumList(new list<SCTAB>())
1952 InsertTabNumber(const InsertTabNumber& r) :
1953 mpTabNumList(r.mpTabNumList)
1957 void operator() (const ScSharedTokenRef& pToken) const
1959 if (!ScRefTokenHelper::isRef(pToken))
1960 return;
1962 const ScSingleRefData& r = pToken->GetSingleRef();
1963 mpTabNumList->push_back(r.nTab);
1966 void getList(list<SCTAB>& rList)
1968 mpTabNumList->swap(rList);
1970 private:
1971 shared_ptr< list<SCTAB> > mpTabNumList;
1976 uno::Sequence< beans::PropertyValue > SAL_CALL ScChart2DataProvider::detectArguments(
1977 const uno::Reference< chart2::data::XDataSource >& xDataSource )
1978 throw (uno::RuntimeException)
1980 ::std::vector< beans::PropertyValue > aResult;
1981 bool bRowSourceDetected = false;
1982 bool bFirstCellAsLabel = false;
1983 bool bHasCategories = true;
1984 ::rtl::OUString sRangeRep;
1986 chart::ChartDataRowSource eRowSource = chart::ChartDataRowSource_COLUMNS;
1988 vector<ScSharedTokenRef> aTokens;
1990 // CellRangeRepresentation
1992 ScUnoGuard aGuard;
1993 DBG_ASSERT( m_pDocument, "No Document -> no detectArguments" );
1994 if(!m_pDocument)
1995 return lcl_VectorToSequence( aResult );
1997 detectRangesFromDataSource(aTokens, eRowSource, bRowSourceDetected, xDataSource);
2000 // TableNumberList
2002 list<SCTAB> aTableNumList;
2003 InsertTabNumber func;
2004 func = for_each(aTokens.begin(), aTokens.end(), func);
2005 func.getList(aTableNumList);
2006 aResult.push_back(
2007 beans::PropertyValue( ::rtl::OUString::createFromAscii("TableNumberList"), -1,
2008 uno::makeAny( lcl_createTableNumberList( aTableNumList ) ),
2009 beans::PropertyState_DIRECT_VALUE ));
2012 // DataRowSource (calculated before)
2013 if( bRowSourceDetected )
2015 aResult.push_back(
2016 beans::PropertyValue( ::rtl::OUString::createFromAscii("DataRowSource"), -1,
2017 uno::makeAny( eRowSource ), beans::PropertyState_DIRECT_VALUE ));
2020 // HasCategories
2021 if( bRowSourceDetected )
2023 if( lcl_HasCategories( xDataSource, bHasCategories ))
2025 aResult.push_back(
2026 beans::PropertyValue( ::rtl::OUString::createFromAscii("HasCategories"), -1,
2027 uno::makeAny( bHasCategories ), beans::PropertyState_DIRECT_VALUE ));
2031 // FirstCellAsLabel
2032 if( bRowSourceDetected )
2034 lcl_HasFirstCellAsLabel( xDataSource, bFirstCellAsLabel );
2035 aResult.push_back(
2036 beans::PropertyValue( ::rtl::OUString::createFromAscii("FirstCellAsLabel"), -1,
2037 uno::makeAny( bFirstCellAsLabel ), beans::PropertyState_DIRECT_VALUE ));
2040 // Add the left upper corner to the range if it is missing.
2041 if (bRowSourceDetected && bFirstCellAsLabel && bHasCategories)
2042 addUpperLeftCornerIfMissing(aTokens);
2044 // Get range string.
2045 lcl_convertTokensToString(sRangeRep, aTokens, m_pDocument);
2047 // add cell range property
2048 aResult.push_back(
2049 beans::PropertyValue( ::rtl::OUString::createFromAscii("CellRangeRepresentation"), -1,
2050 uno::makeAny( sRangeRep ), beans::PropertyState_DIRECT_VALUE ));
2052 //Sequence Mapping
2053 bool bSequencesReordered = true;//todo detect this above or detect this sequence mapping cheaper ...
2054 if( bSequencesReordered && bRowSourceDetected )
2056 bool bDifferentIndexes = false;
2058 std::vector< sal_Int32 > aSequenceMappingVector;
2060 uno::Reference< chart2::data::XDataSource > xCompareDataSource;
2063 xCompareDataSource.set( this->createDataSource( lcl_VectorToSequence( aResult ) ) );
2065 catch( const lang::IllegalArgumentException & )
2067 // creation of data source to compare didn't work, so we cannot
2068 // create a sequence mapping
2071 if( xDataSource.is() && xCompareDataSource.is() )
2073 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence> > aOldSequences(
2074 xCompareDataSource->getDataSequences() );
2075 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aNewSequences(
2076 xDataSource->getDataSequences());
2078 rtl::OUString aOldLabel;
2079 rtl::OUString aNewLabel;
2080 rtl::OUString aOldValues;
2081 rtl::OUString aNewValues;
2082 rtl::OUString aEmpty;
2084 for( sal_Int32 nNewIndex = 0; nNewIndex < aNewSequences.getLength(); nNewIndex++ )
2086 uno::Reference< chart2::data::XLabeledDataSequence> xNew( aNewSequences[nNewIndex] );
2087 for( sal_Int32 nOldIndex = 0; nOldIndex < aOldSequences.getLength(); nOldIndex++ )
2089 uno::Reference< chart2::data::XLabeledDataSequence> xOld( aOldSequences[nOldIndex] );
2091 if( xOld.is() && xNew.is() )
2093 aOldLabel = aNewLabel = aOldValues = aNewValues = aEmpty;
2094 if( xOld.is() && xOld->getLabel().is() )
2095 aOldLabel = xOld->getLabel()->getSourceRangeRepresentation();
2096 if( xNew.is() && xNew->getLabel().is() )
2097 aNewLabel = xNew->getLabel()->getSourceRangeRepresentation();
2098 if( xOld.is() && xOld->getValues().is() )
2099 aOldValues = xOld->getValues()->getSourceRangeRepresentation();
2100 if( xNew.is() && xNew->getValues().is() )
2101 aNewValues = xNew->getValues()->getSourceRangeRepresentation();
2103 if( aOldLabel.equals(aNewLabel)
2104 && ( aOldValues.equals(aNewValues) ) )
2106 if( nOldIndex!=nNewIndex )
2107 bDifferentIndexes = true;
2108 aSequenceMappingVector.push_back(nOldIndex);
2109 break;
2116 if( bDifferentIndexes && aSequenceMappingVector.size() )
2118 aResult.push_back(
2119 beans::PropertyValue( ::rtl::OUString::createFromAscii("SequenceMapping"), -1,
2120 uno::makeAny( lcl_VectorToSequence(aSequenceMappingVector) )
2121 , beans::PropertyState_DIRECT_VALUE ));
2125 return lcl_VectorToSequence( aResult );
2128 ::sal_Bool SAL_CALL ScChart2DataProvider::createDataSequenceByRangeRepresentationPossible( const ::rtl::OUString& aRangeRepresentation )
2129 throw (uno::RuntimeException)
2131 ScUnoGuard aGuard;
2132 if( ! m_pDocument )
2133 return false;
2135 vector<ScSharedTokenRef> aTokens;
2136 ScRefTokenHelper::compileRangeRepresentation(aTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar());
2137 return !aTokens.empty();
2140 uno::Reference< chart2::data::XDataSequence > SAL_CALL
2141 ScChart2DataProvider::createDataSequenceByRangeRepresentation(
2142 const ::rtl::OUString& aRangeRepresentation )
2143 throw (lang::IllegalArgumentException,
2144 uno::RuntimeException)
2146 ScUnoGuard aGuard;
2147 uno::Reference< chart2::data::XDataSequence > xResult;
2149 DBG_ASSERT( m_pDocument, "No Document -> no createDataSequenceByRangeRepresentation" );
2150 if(!m_pDocument || (aRangeRepresentation.getLength() == 0))
2151 return xResult;
2153 // Note: the range representation must be in Calc A1 format. The import
2154 // filters use this method to pass data ranges, and they have no idea what
2155 // the current formula syntax is. In the future we should add another
2156 // method to allow the client code to directly pass tokens representing
2157 // ranges.
2159 vector<ScSharedTokenRef> aRefTokens;
2160 ScRefTokenHelper::compileRangeRepresentation(aRefTokens, aRangeRepresentation, m_pDocument);
2161 if (aRefTokens.empty())
2162 return xResult;
2164 // ScChart2DataSequence manages the life cycle of pRefTokens.
2165 vector<ScSharedTokenRef>* pRefTokens = new vector<ScSharedTokenRef>();
2166 pRefTokens->swap(aRefTokens);
2167 xResult.set(new ScChart2DataSequence(m_pDocument, this, pRefTokens, m_bIncludeHiddenCells));
2169 return xResult;
2172 uno::Reference< sheet::XRangeSelection > SAL_CALL ScChart2DataProvider::getRangeSelection()
2173 throw (uno::RuntimeException)
2175 uno::Reference< sheet::XRangeSelection > xResult;
2177 uno::Reference< frame::XModel > xModel( lcl_GetXModel( m_pDocument ));
2178 if( xModel.is())
2179 xResult.set( xModel->getCurrentController(), uno::UNO_QUERY );
2181 return xResult;
2184 /*uno::Reference< util::XNumberFormatsSupplier > SAL_CALL ScChart2DataProvider::getNumberFormatsSupplier()
2185 throw (uno::RuntimeException)
2187 return uno::Reference< util::XNumberFormatsSupplier >( lcl_GetXModel( m_pDocument ), uno::UNO_QUERY );
2190 // XRangeXMLConversion ---------------------------------------------------
2192 rtl::OUString SAL_CALL ScChart2DataProvider::convertRangeToXML( const rtl::OUString& sRangeRepresentation )
2193 throw ( uno::RuntimeException, lang::IllegalArgumentException )
2195 OUString aRet;
2196 if (!m_pDocument)
2197 return aRet;
2199 if (!sRangeRepresentation.getLength())
2200 // Empty data range is allowed.
2201 return aRet;
2203 vector<ScSharedTokenRef> aRefTokens;
2204 ScRefTokenHelper::compileRangeRepresentation(aRefTokens, sRangeRepresentation, m_pDocument, m_pDocument->GetGrammar());
2205 if (aRefTokens.empty())
2206 throw lang::IllegalArgumentException();
2208 Tokens2RangeStringXML converter(m_pDocument);
2209 converter = for_each(aRefTokens.begin(), aRefTokens.end(), converter);
2210 converter.getString(aRet);
2212 return aRet;
2215 rtl::OUString SAL_CALL ScChart2DataProvider::convertRangeFromXML( const rtl::OUString& sXMLRange )
2216 throw ( uno::RuntimeException, lang::IllegalArgumentException )
2218 const sal_Unicode cSep = ' ';
2219 const sal_Unicode cQuote = '\'';
2221 if (!m_pDocument)
2223 // #i74062# When loading flat XML, this is called before the referenced sheets are in the document,
2224 // so the conversion has to take place directly with the strings, without looking up the sheets.
2226 rtl::OUStringBuffer sRet;
2227 sal_Int32 nOffset = 0;
2228 while( nOffset >= 0 )
2230 rtl::OUString sToken;
2231 ScRangeStringConverter::GetTokenByOffset( sToken, sXMLRange, nOffset, cSep, cQuote );
2232 if( nOffset >= 0 )
2234 // convert one address (remove dots)
2236 String aUIString(sToken);
2238 sal_Int32 nIndex = ScRangeStringConverter::IndexOf( sToken, ':', 0, cQuote );
2239 if ( nIndex >= 0 && nIndex < aUIString.Len() - 1 &&
2240 aUIString.GetChar((xub_StrLen)nIndex + 1) == (sal_Unicode) '.' )
2241 aUIString.Erase( (xub_StrLen)nIndex + 1, 1 );
2243 if ( aUIString.GetChar(0) == (sal_Unicode) '.' )
2244 aUIString.Erase( 0, 1 );
2246 if( sRet.getLength() )
2247 sRet.append( (sal_Unicode) ';' );
2248 sRet.append( aUIString );
2252 return sRet.makeStringAndClear();
2255 OUString aRet;
2256 ScRangeStringConverter::GetStringFromXMLRangeString(aRet, sXMLRange, m_pDocument);
2257 return aRet;
2260 namespace {
2262 class CollectRefTokens : public ::std::unary_function<ScSharedTokenRef, void>
2264 public:
2265 CollectRefTokens() :
2266 mpRefTokens(new vector<ScSharedTokenRef>()),
2267 mnDataInRows(0),
2268 mnDataInCols(0),
2269 mbRowSourceAmbiguous(false)
2273 CollectRefTokens(const CollectRefTokens& r) :
2274 mpRefTokens(r.mpRefTokens),
2275 mnDataInRows(r.mnDataInRows),
2276 mnDataInCols(r.mnDataInCols),
2277 mbRowSourceAmbiguous(r.mbRowSourceAmbiguous)
2281 void operator() (const ScSharedTokenRef& rRefToken)
2283 if (!mbRowSourceAmbiguous)
2285 StackVar eVar = rRefToken->GetType();
2286 if (eVar == svDoubleRef || eVar == svExternalDoubleRef)
2288 const ScComplexRefData& r = rRefToken->GetDoubleRef();
2289 mbRowSourceAmbiguous = r.Ref1.nTab != r.Ref2.nTab;
2290 if (!mbRowSourceAmbiguous)
2292 bool bColDiff = (r.Ref2.nCol - r.Ref1.nCol) != 0;
2293 bool bRowDiff = (r.Ref2.nRow - r.Ref1.nRow) != 0;
2295 if (bColDiff && !bRowDiff)
2296 ++mnDataInRows;
2297 else if (bRowDiff && !bColDiff)
2298 ++mnDataInCols;
2299 else if (bRowDiff && bColDiff)
2300 mbRowSourceAmbiguous = true;
2302 if (mnDataInRows > 0 && mnDataInCols > 0)
2303 mbRowSourceAmbiguous = true;
2308 mpRefTokens->push_back(rRefToken);
2311 void appendTokens(vector<ScSharedTokenRef>& rTokens)
2313 vector<ScSharedTokenRef> aNewTokens = rTokens;
2314 vector<ScSharedTokenRef>::const_iterator itr = mpRefTokens->begin(), itrEnd = mpRefTokens->end();
2315 for (; itr != itrEnd; ++itr)
2316 ScRefTokenHelper::join(aNewTokens, *itr);
2318 rTokens.swap(aNewTokens);
2321 bool isRowSourceAmbiguous() const
2323 return mbRowSourceAmbiguous;
2326 sal_uInt32 getDataInRows() const
2328 return mnDataInRows;
2331 sal_uInt32 getDataInCols() const
2333 return mnDataInCols;
2336 private:
2337 shared_ptr< vector<ScSharedTokenRef> > mpRefTokens;
2338 sal_uInt32 mnDataInRows;
2339 sal_uInt32 mnDataInCols;
2340 bool mbRowSourceAmbiguous;
2345 // DataProvider XPropertySet -------------------------------------------------
2347 uno::Reference< beans::XPropertySetInfo> SAL_CALL
2348 ScChart2DataProvider::getPropertySetInfo() throw( uno::RuntimeException)
2350 ScUnoGuard aGuard;
2351 static uno::Reference<beans::XPropertySetInfo> aRef =
2352 new SfxItemPropertySetInfo( m_aPropSet.getPropertyMap() );
2353 return aRef;
2357 void SAL_CALL ScChart2DataProvider::setPropertyValue(
2358 const ::rtl::OUString& rPropertyName, const uno::Any& rValue)
2359 throw( beans::UnknownPropertyException,
2360 beans::PropertyVetoException,
2361 lang::IllegalArgumentException,
2362 lang::WrappedTargetException, uno::RuntimeException)
2364 if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS)))
2366 if ( !(rValue >>= m_bIncludeHiddenCells))
2367 throw lang::IllegalArgumentException();
2369 else
2370 throw beans::UnknownPropertyException();
2374 uno::Any SAL_CALL ScChart2DataProvider::getPropertyValue(
2375 const ::rtl::OUString& rPropertyName)
2376 throw( beans::UnknownPropertyException,
2377 lang::WrappedTargetException, uno::RuntimeException)
2379 uno::Any aRet;
2380 if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS)))
2381 aRet <<= m_bIncludeHiddenCells;
2382 else
2383 throw beans::UnknownPropertyException();
2384 return aRet;
2388 void SAL_CALL ScChart2DataProvider::addPropertyChangeListener(
2389 const ::rtl::OUString& /*rPropertyName*/,
2390 const uno::Reference< beans::XPropertyChangeListener>& /*xListener*/)
2391 throw( beans::UnknownPropertyException,
2392 lang::WrappedTargetException, uno::RuntimeException)
2394 OSL_ENSURE( false, "Not yet implemented" );
2398 void SAL_CALL ScChart2DataProvider::removePropertyChangeListener(
2399 const ::rtl::OUString& /*rPropertyName*/,
2400 const uno::Reference< beans::XPropertyChangeListener>& /*rListener*/)
2401 throw( beans::UnknownPropertyException,
2402 lang::WrappedTargetException, uno::RuntimeException)
2404 OSL_ENSURE( false, "Not yet implemented" );
2408 void SAL_CALL ScChart2DataProvider::addVetoableChangeListener(
2409 const ::rtl::OUString& /*rPropertyName*/,
2410 const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/)
2411 throw( beans::UnknownPropertyException,
2412 lang::WrappedTargetException, uno::RuntimeException)
2414 OSL_ENSURE( false, "Not yet implemented" );
2418 void SAL_CALL ScChart2DataProvider::removeVetoableChangeListener(
2419 const ::rtl::OUString& /*rPropertyName*/,
2420 const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/ )
2421 throw( beans::UnknownPropertyException,
2422 lang::WrappedTargetException, uno::RuntimeException)
2424 OSL_ENSURE( false, "Not yet implemented" );
2427 void ScChart2DataProvider::detectRangesFromDataSource(vector<ScSharedTokenRef>& rRefTokens,
2428 chart::ChartDataRowSource& rRowSource,
2429 bool& rRowSourceDetected,
2430 const Reference<chart2::data::XDataSource>& xDataSource)
2432 if (!m_pDocument)
2433 return;
2435 sal_Int32 nDataInRows = 0;
2436 sal_Int32 nDataInCols = 0;
2437 bool bRowSourceAmbiguous = false;
2439 vector<OUString> aRangeReps = lcl_getRangeRepresentationsFromDataSource(xDataSource);
2440 for (vector<OUString>::const_iterator itr = aRangeReps.begin(), itrEnd = aRangeReps.end();
2441 itr != itrEnd; ++itr)
2443 const OUString& rRangeRep = *itr;
2444 vector<ScSharedTokenRef> aTokens;
2445 ScRefTokenHelper::compileRangeRepresentation(aTokens, rRangeRep, m_pDocument, m_pDocument->GetGrammar());
2447 CollectRefTokens func;
2448 func = for_each(aTokens.begin(), aTokens.end(), func);
2449 func.appendTokens(rRefTokens);
2450 bRowSourceAmbiguous = bRowSourceAmbiguous || func.isRowSourceAmbiguous();
2451 if (!bRowSourceAmbiguous)
2453 nDataInRows += func.getDataInRows();
2454 nDataInCols += func.getDataInCols();
2458 if (!bRowSourceAmbiguous)
2460 rRowSourceDetected = true;
2461 rRowSource = ( nDataInRows > 0
2462 ? chart::ChartDataRowSource_ROWS
2463 : chart::ChartDataRowSource_COLUMNS );
2465 else
2467 // set DataRowSource to the better of the two ambiguities
2468 rRowSource = ( nDataInRows > nDataInCols
2469 ? chart::ChartDataRowSource_ROWS
2470 : chart::ChartDataRowSource_COLUMNS );
2474 // DataSource ================================================================
2476 ScChart2DataSource::ScChart2DataSource( ScDocument* pDoc)
2477 : m_pDocument( pDoc)
2479 if ( m_pDocument )
2480 m_pDocument->AddUnoObject( *this);
2484 ScChart2DataSource::~ScChart2DataSource()
2486 if ( m_pDocument )
2487 m_pDocument->RemoveUnoObject( *this);
2491 void ScChart2DataSource::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
2493 if ( rHint.ISA( SfxSimpleHint ) &&
2494 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
2496 m_pDocument = NULL;
2501 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence> > SAL_CALL
2502 ScChart2DataSource::getDataSequences() throw ( uno::RuntimeException)
2504 ScUnoGuard aGuard;
2506 LabeledList::const_iterator aItr(m_aLabeledSequences.begin());
2507 LabeledList::const_iterator aEndItr(m_aLabeledSequences.end());
2509 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aRet(m_aLabeledSequences.size());
2511 sal_Int32 i = 0;
2512 while (aItr != aEndItr)
2514 aRet[i] = *aItr;
2515 ++i;
2516 ++aItr;
2519 return aRet;
2521 /* typedef ::std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > tVec;
2522 tVec aVec;
2523 bool bSeries = false;
2524 // split into columns - FIXME: different if GlueState() is used
2525 for ( ScRangePtr p = m_xRanges->First(); p; p = m_xRanges->Next())
2527 for ( SCCOL nCol = p->aStart.Col(); nCol <= p->aEnd.Col(); ++nCol)
2529 uno::Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
2530 new ScChart2LabeledDataSequence( m_pDocument));
2531 if( xLabeledSeq.is())
2533 aVec.push_back( xLabeledSeq );
2534 if( bSeries )
2536 ScRangeListRef aColRanges = new ScRangeList;
2537 // one single sheet selected assumed for now
2538 aColRanges->Append( ScRange( nCol, p->aStart.Row(),
2539 p->aStart.Tab(), nCol, p->aStart.Row(),
2540 p->aStart.Tab()));
2541 // TEST: add range two times, once as label, once as data
2542 // TODO: create pure Numerical and Text sequences if possible
2543 uno::Reference< chart2::data::XDataSequence > xLabel(
2544 new ScChart2DataSequence( m_pDocument, aColRanges));
2546 // set role
2547 uno::Reference< beans::XPropertySet > xProp( xLabel, uno::UNO_QUERY );
2548 if( xProp.is())
2549 xProp->setPropertyValue(
2550 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )),
2551 ::uno::makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "label" ))));
2553 xLabeledSeq->setLabel( xLabel );
2556 ScRangeListRef aColRanges = new ScRangeList;
2558 // one single sheet selected assumed for now
2559 aColRanges->Append( ScRange( nCol, p->aStart.Row() + 1,
2560 p->aStart.Tab(), nCol, p->aEnd.Row(),
2561 p->aStart.Tab()));
2562 uno::Reference< chart2::data::XDataSequence > xData(
2563 new ScChart2DataSequence( m_pDocument, aColRanges));
2565 // set role
2566 uno::Reference< beans::XPropertySet > xProp( xData, uno::UNO_QUERY );
2567 if( xProp.is())
2568 xProp->setPropertyValue(
2569 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )),
2570 ::uno::makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "values" ))));
2572 xLabeledSeq->setValues( xData );
2574 bSeries = true;
2578 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence> > aSequences(
2579 aVec.size());
2580 uno::Reference< chart2::data::XLabeledDataSequence> * pArr = aSequences.getArray();
2581 sal_Int32 j = 0;
2582 for ( tVec::const_iterator iSeq = aVec.begin(); iSeq != aVec.end();
2583 ++iSeq, ++j)
2585 pArr[j] = *iSeq;
2587 return aSequences;*/
2590 void ScChart2DataSource::AddLabeledSequence(const uno::Reference < chart2::data::XLabeledDataSequence >& xNew)
2592 m_aLabeledSequences.push_back(xNew);
2595 // LabeledDataSequence =======================================================
2597 ScChart2LabeledDataSequence::ScChart2LabeledDataSequence(
2598 ScDocument* pDoc ) :
2599 m_pDocument( pDoc )
2601 if ( m_pDocument )
2602 m_pDocument->AddUnoObject( *this);
2605 ScChart2LabeledDataSequence::~ScChart2LabeledDataSequence()
2607 if ( m_pDocument )
2608 m_pDocument->RemoveUnoObject( *this);
2611 // SfxListener -----------------------------------------------------------
2613 void ScChart2LabeledDataSequence::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
2615 if ( rHint.ISA( SfxSimpleHint ) &&
2616 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
2618 ScUnoGuard aGuard;
2619 m_pDocument = NULL;
2623 // XLabeledDataSequence --------------------------------------------------
2625 uno::Reference< chart2::data::XDataSequence > SAL_CALL ScChart2LabeledDataSequence::getValues()
2626 throw (uno::RuntimeException)
2628 ScUnoGuard aGuard;
2629 return m_aData;
2632 void SAL_CALL ScChart2LabeledDataSequence::setValues(
2633 const uno::Reference< chart2::data::XDataSequence >& xSequence )
2634 throw (uno::RuntimeException)
2636 ScUnoGuard aGuard;
2637 m_aData = xSequence;
2640 uno::Reference< chart2::data::XDataSequence > SAL_CALL ScChart2LabeledDataSequence::getLabel()
2641 throw (uno::RuntimeException)
2643 ScUnoGuard aGuard;
2644 return m_aLabel;
2647 void SAL_CALL ScChart2LabeledDataSequence::setLabel(
2648 const uno::Reference< chart2::data::XDataSequence >& xSequence )
2649 throw (uno::RuntimeException)
2651 ScUnoGuard aGuard;
2652 m_aLabel = xSequence;
2655 // XCloneable ================================================================
2657 uno::Reference< util::XCloneable > SAL_CALL ScChart2LabeledDataSequence::createClone()
2658 throw (uno::RuntimeException)
2660 ScUnoGuard aGuard;
2661 uno::Reference< util::XCloneable > xToClone(m_aData, uno::UNO_QUERY);
2662 if (xToClone.is())
2664 ScChart2LabeledDataSequence* pRet = new ScChart2LabeledDataSequence(m_pDocument);
2665 uno::Reference< chart2::data::XDataSequence > xSequence(xToClone->createClone(), uno::UNO_QUERY);
2666 pRet->setValues(xSequence);
2667 xToClone.set(m_aLabel, uno::UNO_QUERY);
2668 if(xToClone.is())
2670 xSequence.set(xToClone->createClone(), uno::UNO_QUERY);
2671 pRet->setLabel(xSequence);
2673 return pRet;
2675 return NULL;
2678 // XModifyBroadcaster ========================================================
2680 void SAL_CALL ScChart2LabeledDataSequence::addModifyListener( const uno::Reference< util::XModifyListener >& aListener )
2681 throw (uno::RuntimeException)
2683 // quick'n dirty: just add the listener to each DataSequence
2685 uno::Reference<util::XModifyBroadcaster> xDataBroadcaster( m_aData, uno::UNO_QUERY );
2686 if ( xDataBroadcaster.is() )
2687 xDataBroadcaster->addModifyListener( aListener );
2688 uno::Reference<util::XModifyBroadcaster> xLabelBroadcaster( m_aLabel, uno::UNO_QUERY );
2689 if ( xLabelBroadcaster.is() )
2690 xLabelBroadcaster->addModifyListener( aListener );
2693 void SAL_CALL ScChart2LabeledDataSequence::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener )
2694 throw (uno::RuntimeException)
2696 uno::Reference<util::XModifyBroadcaster> xDataBroadcaster( m_aData, uno::UNO_QUERY );
2697 if ( xDataBroadcaster.is() )
2698 xDataBroadcaster->removeModifyListener( aListener );
2699 uno::Reference<util::XModifyBroadcaster> xLabelBroadcaster( m_aLabel, uno::UNO_QUERY );
2700 if ( xLabelBroadcaster.is() )
2701 xLabelBroadcaster->removeModifyListener( aListener );
2704 // DataSequence ==============================================================
2706 ScChart2DataSequence::Item::Item() :
2707 mfValue(0.0), mbIsValue(false)
2709 ::rtl::math::setNan(&mfValue);
2712 ScChart2DataSequence::HiddenRangeListener::HiddenRangeListener(ScChart2DataSequence& rParent) :
2713 mrParent(rParent)
2717 ScChart2DataSequence::HiddenRangeListener::~HiddenRangeListener()
2721 void ScChart2DataSequence::HiddenRangeListener::notify()
2723 mrParent.setDataChangedHint(true);
2726 ScChart2DataSequence::ScChart2DataSequence( ScDocument* pDoc,
2727 const uno::Reference < chart2::data::XDataProvider >& xDP,
2728 vector<ScSharedTokenRef>* pTokens,
2729 bool bIncludeHiddenCells )
2730 : m_bIncludeHiddenCells( bIncludeHiddenCells)
2731 , m_nObjectId( 0 )
2732 , m_pDocument( pDoc)
2733 , m_pTokens(pTokens)
2734 , m_pRangeIndices(NULL)
2735 , m_pExtRefListener(NULL)
2736 , m_xDataProvider( xDP)
2737 , m_aPropSet(lcl_GetDataSequencePropertyMap())
2738 , m_pHiddenListener(NULL)
2739 , m_pValueListener( NULL )
2740 , m_bGotDataChangedHint(false)
2741 , m_bExtDataRebuildQueued(false)
2743 DBG_ASSERT(pTokens, "reference token list is null");
2745 if ( m_pDocument )
2747 m_pDocument->AddUnoObject( *this);
2748 m_nObjectId = m_pDocument->GetNewUnoId();
2750 // FIXME: real implementation of identifier and it's mapping to ranges.
2751 // Reuse ScChartListener?
2753 // BM: don't use names of named ranges but the UI range strings
2754 // String aStr;
2755 // rRangeList->Format( aStr, SCR_ABS_3D, m_pDocument );
2756 // m_aIdentifier = ::rtl::OUString( aStr );
2758 // m_aIdentifier = ::rtl::OUString::createFromAscii( "ID_");
2759 // static sal_Int32 nID = 0;
2760 // m_aIdentifier += ::rtl::OUString::valueOf( ++nID);
2763 ScChart2DataSequence::~ScChart2DataSequence()
2765 if ( m_pDocument )
2767 m_pDocument->RemoveUnoObject( *this);
2768 if (m_pHiddenListener.get())
2770 ScChartListenerCollection* pCLC = m_pDocument->GetChartListenerCollection();
2771 if (pCLC)
2772 pCLC->EndListeningHiddenRange(m_pHiddenListener.get());
2774 StopListeningToAllExternalRefs();
2777 delete m_pValueListener;
2780 void ScChart2DataSequence::RefChanged()
2782 if( m_pValueListener && m_aValueListeners.Count() != 0 )
2784 m_pValueListener->EndListeningAll();
2786 if( m_pDocument )
2788 ScChartListenerCollection* pCLC = NULL;
2789 if (m_pHiddenListener.get())
2791 pCLC = m_pDocument->GetChartListenerCollection();
2792 if (pCLC)
2793 pCLC->EndListeningHiddenRange(m_pHiddenListener.get());
2796 vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end();
2797 for (; itr != itrEnd; ++itr)
2799 ScRange aRange;
2800 if (!ScRefTokenHelper::getRangeFromToken(aRange, *itr))
2801 continue;
2803 m_pDocument->StartListeningArea(aRange, m_pValueListener);
2804 if (pCLC)
2805 pCLC->StartListeningHiddenRange(aRange, m_pHiddenListener.get());
2811 void ScChart2DataSequence::BuildDataCache()
2813 m_bExtDataRebuildQueued = false;
2815 if (!m_aDataArray.empty())
2816 return;
2818 if (!m_pTokens.get())
2820 DBG_ERROR("m_pTokens == NULL! Something is wrong.");
2821 return;
2824 StopListeningToAllExternalRefs();
2826 ::std::list<sal_Int32> aHiddenValues;
2827 sal_Int32 nDataCount = 0;
2828 sal_Int32 nHiddenValueCount = 0;
2830 for (vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end();
2831 itr != itrEnd; ++itr)
2833 if (ScRefTokenHelper::isExternalRef(*itr))
2835 nDataCount += FillCacheFromExternalRef(*itr);
2837 else
2839 ScRange aRange;
2840 if (!ScRefTokenHelper::getRangeFromToken(aRange, *itr))
2841 continue;
2843 SCCOL nLastCol = -1;
2844 SCROW nLastRow = -1;
2845 for (SCTAB nTab = aRange.aStart.Tab(); nTab <= aRange.aEnd.Tab(); ++nTab)
2847 for (SCCOL nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol)
2849 for (SCROW nRow = aRange.aStart.Row(); nRow <= aRange.aEnd.Row(); ++nRow)
2851 bool bColHidden = m_pDocument->ColHidden(nCol, nTab, nLastCol);
2852 bool bRowHidden = m_pDocument->RowHidden(nRow, nTab, nLastRow);
2854 if (bColHidden || bRowHidden)
2856 // hidden cell
2857 ++nHiddenValueCount;
2858 aHiddenValues.push_back(nDataCount-1);
2860 if( !m_bIncludeHiddenCells )
2861 continue;
2864 m_aDataArray.push_back(Item());
2865 Item& rItem = m_aDataArray.back();
2866 ++nDataCount;
2868 ScAddress aAdr(nCol, nRow, nTab);
2869 ScBaseCell* pCell = m_pDocument->GetCell(aAdr);
2870 if (!pCell)
2871 continue;
2873 if (pCell->HasStringData())
2874 rItem.maString = pCell->GetStringData();
2875 else
2877 String aStr;
2878 m_pDocument->GetString(nCol, nRow, nTab, aStr);
2879 rItem.maString = aStr;
2882 switch (pCell->GetCellType())
2884 case CELLTYPE_VALUE:
2885 rItem.mfValue = static_cast< ScValueCell*>(pCell)->GetValue();
2886 rItem.mbIsValue = true;
2887 break;
2888 case CELLTYPE_FORMULA:
2890 ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
2891 USHORT nErr = pFCell->GetErrCode();
2892 if (nErr)
2893 break;
2895 if (pFCell->HasValueData())
2897 rItem.mfValue = pFCell->GetValue();
2898 rItem.mbIsValue = true;
2901 break;
2902 #if DBG_UTIL
2903 case CELLTYPE_DESTROYED:
2904 #endif
2905 case CELLTYPE_EDIT:
2906 case CELLTYPE_NONE:
2907 case CELLTYPE_NOTE:
2908 case CELLTYPE_STRING:
2909 case CELLTYPE_SYMBOLS:
2910 default:
2911 ; // do nothing
2919 // convert the hidden cell list to sequence.
2920 m_aHiddenValues.realloc(nHiddenValueCount);
2921 sal_Int32* pArr = m_aHiddenValues.getArray();
2922 ::std::list<sal_Int32>::const_iterator itr = aHiddenValues.begin(), itrEnd = aHiddenValues.end();
2923 for (;itr != itrEnd; ++itr, ++pArr)
2924 *pArr = *itr;
2926 // Clear the data series cache when the array is re-built.
2927 m_aMixedDataCache.realloc(0);
2930 void ScChart2DataSequence::RebuildDataCache()
2932 if (!m_bExtDataRebuildQueued)
2934 m_aDataArray.clear();
2935 m_pDocument->BroadcastUno(ScHint(SC_HINT_DATACHANGED, ScAddress(), NULL));
2936 m_bExtDataRebuildQueued = true;
2937 m_bGotDataChangedHint = true;
2941 sal_Int32 ScChart2DataSequence::FillCacheFromExternalRef(const ScSharedTokenRef& pToken)
2943 ScExternalRefManager* pRefMgr = m_pDocument->GetExternalRefManager();
2944 ScRange aRange;
2945 if (!ScRefTokenHelper::getRangeFromToken(aRange, pToken, true))
2946 return 0;
2948 sal_uInt16 nFileId = pToken->GetIndex();
2949 const String& rTabName = pToken->GetString();
2950 ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(nFileId, rTabName, aRange, NULL);
2951 if (!pArray)
2952 // no external data exists for this range.
2953 return 0;
2955 // Start listening for this external document.
2956 ExternalRefListener* pExtRefListener = GetExtRefListener();
2957 pRefMgr->addLinkListener(nFileId, pExtRefListener);
2958 pExtRefListener->addFileId(nFileId);
2960 ScExternalRefCache::TableTypeRef pTable = pRefMgr->getCacheTable(nFileId, rTabName, false, NULL);
2961 sal_Int32 nDataCount = 0;
2962 for (FormulaToken* p = pArray->First(); p; p = pArray->Next())
2964 // Cached external range is always represented as a single
2965 // matrix token, although that might change in the future when
2966 // we introduce a new token type to store multi-table range
2967 // data.
2969 if (p->GetType() != svMatrix)
2971 DBG_ERROR("Cached array is not a matrix token.");
2972 continue;
2975 const ScMatrix* pMat = static_cast<ScToken*>(p)->GetMatrix();
2976 SCSIZE nCSize, nRSize;
2977 pMat->GetDimensions(nCSize, nRSize);
2978 for (SCSIZE nC = 0; nC < nCSize; ++nC)
2980 for (SCSIZE nR = 0; nR < nRSize; ++nR)
2982 if (pMat->IsValue(nC, nR) || pMat->IsBoolean(nC, nR))
2984 m_aDataArray.push_back(Item());
2985 Item& rItem = m_aDataArray.back();
2986 ++nDataCount;
2988 rItem.mbIsValue = true;
2989 rItem.mfValue = pMat->GetDouble(nC, nR);
2991 SvNumberFormatter* pFormatter = m_pDocument->GetFormatTable();
2992 if (pFormatter)
2994 String aStr;
2995 const double fVal = rItem.mfValue;
2996 Color* pColor = NULL;
2997 sal_uInt32 nFmt = 0;
2998 if (pTable)
3000 // Get the correct format index from the cache.
3001 SCCOL nCol = aRange.aStart.Col() + static_cast<SCCOL>(nC);
3002 SCROW nRow = aRange.aStart.Row() + static_cast<SCROW>(nR);
3003 pTable->getCell(nCol, nRow, &nFmt);
3005 pFormatter->GetOutputString(fVal, nFmt, aStr, &pColor);
3006 rItem.maString = aStr;
3009 else if (pMat->IsString(nC, nR))
3011 m_aDataArray.push_back(Item());
3012 Item& rItem = m_aDataArray.back();
3013 ++nDataCount;
3015 rItem.mbIsValue = false;
3016 rItem.maString = pMat->GetString(nC, nR);
3021 return nDataCount;
3024 void ScChart2DataSequence::UpdateTokensFromRanges(const ScRangeList& rRanges)
3026 if (!m_pRangeIndices.get())
3027 return;
3029 sal_uInt32 nCount = rRanges.Count();
3030 for (sal_uInt32 i = 0; i < nCount; ++i)
3032 ScSharedTokenRef pToken;
3033 ScRange* pRange = static_cast<ScRange*>(rRanges.GetObject(i));
3034 DBG_ASSERT(pRange, "range object is NULL.");
3036 ScRefTokenHelper::getTokenFromRange(pToken, *pRange);
3037 sal_uInt32 nOrigPos = (*m_pRangeIndices)[i];
3038 (*m_pTokens)[nOrigPos] = pToken;
3041 RefChanged();
3043 // any change of the range address is broadcast to value (modify) listeners
3044 if ( m_aValueListeners.Count() )
3045 m_bGotDataChangedHint = true;
3048 ScChart2DataSequence::ExternalRefListener* ScChart2DataSequence::GetExtRefListener()
3050 if (!m_pExtRefListener.get())
3051 m_pExtRefListener.reset(new ExternalRefListener(*this, m_pDocument));
3053 return m_pExtRefListener.get();
3056 void ScChart2DataSequence::StopListeningToAllExternalRefs()
3058 if (!m_pExtRefListener.get())
3059 return;
3061 const hash_set<sal_uInt16>& rFileIds = m_pExtRefListener->getAllFileIds();
3062 hash_set<sal_uInt16>::const_iterator itr = rFileIds.begin(), itrEnd = rFileIds.end();
3063 ScExternalRefManager* pRefMgr = m_pDocument->GetExternalRefManager();
3064 for (; itr != itrEnd; ++itr)
3065 pRefMgr->removeLinkListener(*itr, m_pExtRefListener.get());
3067 m_pExtRefListener.reset(NULL);
3070 void ScChart2DataSequence::CopyData(const ScChart2DataSequence& r)
3072 if (!m_pDocument)
3074 DBG_ERROR("document instance is NULL!?");
3075 return;
3078 list<Item> aDataArray(r.m_aDataArray);
3079 m_aDataArray.swap(aDataArray);
3081 m_aHiddenValues = r.m_aHiddenValues;
3082 m_aRole = r.m_aRole;
3084 if (r.m_pRangeIndices.get())
3085 m_pRangeIndices.reset(new vector<sal_uInt32>(*r.m_pRangeIndices));
3087 if (r.m_pExtRefListener.get())
3089 // Re-register all external files that the old instance was
3090 // listening to.
3092 ScExternalRefManager* pRefMgr = m_pDocument->GetExternalRefManager();
3093 m_pExtRefListener.reset(new ExternalRefListener(*this, m_pDocument));
3094 const hash_set<sal_uInt16>& rFileIds = r.m_pExtRefListener->getAllFileIds();
3095 hash_set<sal_uInt16>::const_iterator itr = rFileIds.begin(), itrEnd = rFileIds.end();
3096 for (; itr != itrEnd; ++itr)
3098 pRefMgr->addLinkListener(*itr, m_pExtRefListener.get());
3099 m_pExtRefListener->addFileId(*itr);
3104 void ScChart2DataSequence::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
3106 if ( rHint.ISA( SfxSimpleHint ) )
3108 ULONG nId = static_cast<const SfxSimpleHint&>(rHint).GetId();
3109 if ( nId ==SFX_HINT_DYING )
3111 m_pDocument = NULL;
3113 else if ( nId == SFX_HINT_DATACHANGED )
3115 // delayed broadcast as in ScCellRangesBase
3117 if ( m_bGotDataChangedHint && m_pDocument )
3119 m_aDataArray.clear();
3120 lang::EventObject aEvent;
3121 aEvent.Source.set((cppu::OWeakObject*)this);
3123 if( m_pDocument )
3125 for ( USHORT n=0; n<m_aValueListeners.Count(); n++ )
3126 m_pDocument->AddUnoListenerCall( *m_aValueListeners[n], aEvent );
3129 m_bGotDataChangedHint = false;
3132 else if ( nId == SC_HINT_CALCALL )
3134 // broadcast from DoHardRecalc - set m_bGotDataChangedHint
3135 // (SFX_HINT_DATACHANGED follows separately)
3137 if ( m_aValueListeners.Count() )
3138 m_bGotDataChangedHint = true;
3141 else if ( rHint.ISA( ScUpdateRefHint ) )
3143 // Create a range list from the token list, have the range list
3144 // updated, and bring the change back to the token list.
3146 ScRangeList aRanges;
3147 m_pRangeIndices.reset(new vector<sal_uInt32>());
3148 vector<ScSharedTokenRef>::const_iterator itrBeg = m_pTokens->begin(), itrEnd = m_pTokens->end();
3149 for (vector<ScSharedTokenRef>::const_iterator itr = itrBeg ;itr != itrEnd; ++itr)
3151 if (!ScRefTokenHelper::isExternalRef(*itr))
3153 ScRange aRange;
3154 ScRefTokenHelper::getRangeFromToken(aRange, *itr);
3155 aRanges.Append(aRange);
3156 sal_uInt32 nPos = distance(itrBeg, itr);
3157 m_pRangeIndices->push_back(nPos);
3161 DBG_ASSERT(m_pRangeIndices->size() == static_cast<size_t>(aRanges.Count()),
3162 "range list and range index list have different sizes.");
3164 auto_ptr<ScRangeList> pUndoRanges;
3165 if ( m_pDocument->HasUnoRefUndo() )
3166 pUndoRanges.reset(new ScRangeList(aRanges));
3168 const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint;
3169 bool bChanged = aRanges.UpdateReference(
3170 rRef.GetMode(), m_pDocument, rRef.GetRange(), rRef.GetDx(), rRef.GetDy(), rRef.GetDz());
3172 if (bChanged)
3174 DBG_ASSERT(m_pRangeIndices->size() == static_cast<size_t>(aRanges.Count()),
3175 "range list and range index list have different sizes after the reference update.");
3177 // Bring the change back from the range list to the token list.
3178 UpdateTokensFromRanges(aRanges);
3180 if (pUndoRanges.get())
3181 m_pDocument->AddUnoRefChange(m_nObjectId, *pUndoRanges);
3184 else if ( rHint.ISA( ScUnoRefUndoHint ) )
3186 const ScUnoRefUndoHint& rUndoHint = static_cast<const ScUnoRefUndoHint&>(rHint);
3190 if (rUndoHint.GetObjectId() != m_nObjectId)
3191 break;
3193 // The hint object provides the old ranges. Restore the old state
3194 // from these ranges.
3196 if (!m_pRangeIndices.get() || m_pRangeIndices->empty())
3198 DBG_ERROR(" faulty range indices");
3199 break;
3202 const ScRangeList& rRanges = rUndoHint.GetRanges();
3204 sal_uInt32 nCount = rRanges.Count();
3205 if (nCount != m_pRangeIndices->size())
3207 DBG_ERROR("range count and range index count differ.");
3208 break;
3211 UpdateTokensFromRanges(rRanges);
3213 while (false);
3218 IMPL_LINK( ScChart2DataSequence, ValueListenerHdl, SfxHint*, pHint )
3220 if ( m_pDocument && pHint && pHint->ISA( SfxSimpleHint ) &&
3221 ((const SfxSimpleHint*)pHint)->GetId() & (SC_HINT_DATACHANGED | SC_HINT_DYING) )
3223 // This may be called several times for a single change, if several formulas
3224 // in the range are notified. So only a flag is set that is checked when
3225 // SFX_HINT_DATACHANGED is received.
3227 setDataChangedHint(true);
3229 return 0;
3232 // ----------------------------------------------------------------------------
3234 ScChart2DataSequence::ExternalRefListener::ExternalRefListener(
3235 ScChart2DataSequence& rParent, ScDocument* pDoc) :
3236 ScExternalRefManager::LinkListener(),
3237 mrParent(rParent),
3238 mpDoc(pDoc)
3242 ScChart2DataSequence::ExternalRefListener::~ExternalRefListener()
3244 if (!mpDoc || mpDoc->IsInDtorClear())
3245 // The document is being destroyed. Do nothing.
3246 return;
3248 // Make sure to remove all pointers to this object.
3249 mpDoc->GetExternalRefManager()->removeLinkListener(this);
3252 void ScChart2DataSequence::ExternalRefListener::notify(sal_uInt16 nFileId, ScExternalRefManager::LinkUpdateType eType)
3254 switch (eType)
3256 case ScExternalRefManager::LINK_MODIFIED:
3258 if (maFileIds.count(nFileId))
3259 // We are listening to this external document.
3260 mrParent.RebuildDataCache();
3262 break;
3263 case ScExternalRefManager::LINK_BROKEN:
3264 removeFileId(nFileId);
3265 break;
3269 void ScChart2DataSequence::ExternalRefListener::addFileId(sal_uInt16 nFileId)
3271 maFileIds.insert(nFileId);
3274 void ScChart2DataSequence::ExternalRefListener::removeFileId(sal_uInt16 nFileId)
3276 maFileIds.erase(nFileId);
3279 const hash_set<sal_uInt16>& ScChart2DataSequence::ExternalRefListener::getAllFileIds()
3281 return maFileIds;
3284 // ----------------------------------------------------------------------------
3286 uno::Sequence< uno::Any> SAL_CALL ScChart2DataSequence::getData()
3287 throw ( uno::RuntimeException)
3289 ScUnoGuard aGuard;
3290 if ( !m_pDocument)
3291 throw uno::RuntimeException();
3293 BuildDataCache();
3295 if (!m_aMixedDataCache.getLength())
3297 // Build a cache for the 1st time...
3299 sal_Int32 nCount = m_aDataArray.size();
3300 m_aMixedDataCache.realloc(nCount);
3301 uno::Any* pArr = m_aMixedDataCache.getArray();
3302 ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end();
3303 for (; itr != itrEnd; ++itr, ++pArr)
3305 if (itr->mbIsValue)
3306 *pArr <<= itr->mfValue;
3307 else
3308 *pArr <<= itr->maString;
3311 return m_aMixedDataCache;
3314 // XNumericalDataSequence --------------------------------------------------
3316 uno::Sequence< double > SAL_CALL ScChart2DataSequence::getNumericalData()
3317 throw ( uno::RuntimeException)
3319 ScUnoGuard aGuard;
3320 if ( !m_pDocument)
3321 throw uno::RuntimeException();
3323 BuildDataCache();
3325 double fNAN;
3326 ::rtl::math::setNan(&fNAN);
3328 sal_Int32 nCount = m_aDataArray.size();
3329 uno::Sequence<double> aSeq(nCount);
3330 double* pArr = aSeq.getArray();
3331 ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end();
3332 for (; itr != itrEnd; ++itr, ++pArr)
3333 *pArr = itr->mbIsValue ? itr->mfValue : fNAN;
3335 return aSeq;
3338 // XTextualDataSequence --------------------------------------------------
3340 uno::Sequence< rtl::OUString > SAL_CALL ScChart2DataSequence::getTextualData( ) throw (uno::RuntimeException)
3342 ScUnoGuard aGuard;
3343 if ( !m_pDocument)
3344 throw uno::RuntimeException();
3346 BuildDataCache();
3348 sal_Int32 nCount = m_aDataArray.size();
3349 uno::Sequence<rtl::OUString> aSeq(nCount);
3350 rtl::OUString* pArr = aSeq.getArray();
3351 ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end();
3352 for (; itr != itrEnd; ++itr, ++pArr)
3353 *pArr = itr->maString;
3355 return aSeq;
3358 ::rtl::OUString SAL_CALL ScChart2DataSequence::getSourceRangeRepresentation()
3359 throw ( uno::RuntimeException)
3361 ScUnoGuard aGuard;
3362 OUString aStr;
3363 DBG_ASSERT( m_pDocument, "No Document -> no SourceRangeRepresentation" );
3364 if (m_pDocument && m_pTokens.get())
3365 lcl_convertTokensToString(aStr, *m_pTokens, m_pDocument);
3367 return aStr;
3370 namespace {
3372 /**
3373 * This function object is used to accumulatively count the numbers of
3374 * columns and rows in all reference tokens.
3376 class AccumulateRangeSize : public unary_function<ScSharedTokenRef, void>
3378 public:
3379 AccumulateRangeSize() :
3380 mnCols(0), mnRows(0) {}
3382 AccumulateRangeSize(const AccumulateRangeSize& r) :
3383 mnCols(r.mnCols), mnRows(r.mnRows) {}
3385 void operator() (const ScSharedTokenRef& pToken)
3387 ScRange r;
3388 bool bExternal = ScRefTokenHelper::isExternalRef(pToken);
3389 ScRefTokenHelper::getRangeFromToken(r, pToken, bExternal);
3390 r.Justify();
3391 mnCols += r.aEnd.Col() - r.aStart.Col() + 1;
3392 mnRows += r.aEnd.Row() - r.aStart.Row() + 1;
3395 SCCOL getCols() const { return mnCols; }
3396 SCROW getRows() const { return mnRows; }
3397 private:
3398 SCCOL mnCols;
3399 SCROW mnRows;
3402 /**
3403 * This function object is used to generate label strings from a list of
3404 * reference tokens.
3406 class GenerateLabelStrings : public unary_function<ScSharedTokenRef, void>
3408 public:
3409 GenerateLabelStrings(sal_Int32 nSize, chart2::data::LabelOrigin eOrigin, bool bColumn) :
3410 mpLabels(new Sequence<OUString>(nSize)),
3411 meOrigin(eOrigin),
3412 mnCount(0),
3413 mbColumn(bColumn) {}
3415 GenerateLabelStrings(const GenerateLabelStrings& r) :
3416 mpLabels(r.mpLabels),
3417 meOrigin(r.meOrigin),
3418 mnCount(r.mnCount),
3419 mbColumn(r.mbColumn) {}
3421 void operator() (const ScSharedTokenRef& pToken)
3423 bool bExternal = ScRefTokenHelper::isExternalRef(pToken);
3424 ScRange aRange;
3425 ScRefTokenHelper::getRangeFromToken(aRange, pToken, bExternal);
3426 OUString* pArr = mpLabels->getArray();
3427 if (mbColumn)
3429 for (SCCOL nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol)
3431 if ( meOrigin != chart2::data::LabelOrigin_LONG_SIDE)
3433 String aString = ScGlobal::GetRscString(STR_COLUMN);
3434 aString += ' ';
3435 ScAddress aPos( nCol, 0, 0 );
3436 String aColStr;
3437 aPos.Format( aColStr, SCA_VALID_COL, NULL );
3438 aString += aColStr;
3439 pArr[mnCount] = aString;
3441 else //only indices for categories
3442 pArr[mnCount] = String::CreateFromInt32( mnCount+1 );
3443 ++mnCount;
3446 else
3448 for (sal_Int32 nRow = aRange.aStart.Row(); nRow <= aRange.aEnd.Row(); ++nRow)
3450 if (meOrigin != chart2::data::LabelOrigin_LONG_SIDE)
3452 String aString = ScGlobal::GetRscString(STR_ROW);
3453 aString += ' ';
3454 aString += String::CreateFromInt32( nRow+1 );
3455 pArr[mnCount] = aString;
3457 else //only indices for categories
3458 pArr[mnCount] = String::CreateFromInt32( mnCount+1 );
3459 ++mnCount;
3464 Sequence<OUString> getLabels() const { return *mpLabels; }
3466 private:
3467 GenerateLabelStrings(); // disabled
3469 shared_ptr< Sequence<OUString> > mpLabels;
3470 chart2::data::LabelOrigin meOrigin;
3471 sal_Int32 mnCount;
3472 bool mbColumn;
3477 uno::Sequence< ::rtl::OUString > SAL_CALL ScChart2DataSequence::generateLabel(chart2::data::LabelOrigin eOrigin)
3478 throw (uno::RuntimeException)
3480 ScUnoGuard aGuard;
3481 if ( !m_pDocument)
3482 throw uno::RuntimeException();
3484 if (!m_pTokens.get())
3485 return Sequence<OUString>();
3487 // Determine the total size of all ranges.
3488 AccumulateRangeSize func;
3489 func = for_each(m_pTokens->begin(), m_pTokens->end(), func);
3490 SCCOL nCols = func.getCols();
3491 SCROW nRows = func.getRows();
3493 // Detemine whether this is column-major or row-major.
3494 bool bColumn = true;
3495 if ((eOrigin == chart2::data::LabelOrigin_SHORT_SIDE) ||
3496 (eOrigin == chart2::data::LabelOrigin_LONG_SIDE))
3498 if (nRows > nCols)
3500 if (eOrigin == chart2::data::LabelOrigin_SHORT_SIDE)
3501 bColumn = true;
3502 else
3503 bColumn = false;
3505 else if (nCols > nRows)
3507 if (eOrigin == chart2::data::LabelOrigin_SHORT_SIDE)
3508 bColumn = false;
3509 else
3510 bColumn = true;
3512 else
3513 return Sequence<OUString>();
3516 // Generate label strings based on the info so far.
3517 sal_Int32 nCount = bColumn ? nCols : nRows;
3518 GenerateLabelStrings genLabels(nCount, eOrigin, bColumn);
3519 genLabels = for_each(m_pTokens->begin(), m_pTokens->end(), genLabels);
3520 Sequence<OUString> aSeq = genLabels.getLabels();
3522 return aSeq;
3525 ::sal_Int32 SAL_CALL ScChart2DataSequence::getNumberFormatKeyByIndex( ::sal_Int32 nIndex )
3526 throw (lang::IndexOutOfBoundsException,
3527 uno::RuntimeException)
3529 // index -1 means a heuristic value for the entire sequence
3530 bool bGetSeriesFormat = (nIndex == -1);
3531 sal_Int32 nResult = 0;
3533 ScUnoGuard aGuard;
3534 if ( !m_pDocument || !m_pTokens.get())
3535 return nResult;
3537 sal_Int32 nCount = 0;
3538 bool bFound = false;
3539 ScRangePtr p;
3541 uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( lcl_GetSpreadSheetDocument( m_pDocument ));
3542 if (!xSpreadDoc.is())
3543 return nResult;
3545 uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
3546 if (!xIndex.is())
3547 return nResult;
3549 ScRangeList aRanges;
3550 ScRefTokenHelper::getRangeListFromTokens(aRanges, *m_pTokens);
3551 uno::Reference< table::XCellRange > xSheet;
3552 for ( p = aRanges.First(); p && !bFound; p = aRanges.Next())
3554 // TODO: use DocIter?
3555 table::CellAddress aStart, aEnd;
3556 ScUnoConversion::FillApiAddress( aStart, p->aStart );
3557 ScUnoConversion::FillApiAddress( aEnd, p->aEnd );
3558 for ( sal_Int16 nSheet = aStart.Sheet; nSheet <= aEnd.Sheet && !bFound; ++nSheet)
3560 xSheet.set(xIndex->getByIndex(nSheet), uno::UNO_QUERY);
3561 for ( sal_Int32 nCol = aStart.Column; nCol <= aEnd.Column && !bFound; ++nCol)
3563 for ( sal_Int32 nRow = aStart.Row; nRow <= aEnd.Row && !bFound; ++nRow)
3565 if( bGetSeriesFormat )
3567 // TODO: use nicer heuristic
3568 // return format of first non-empty cell
3569 uno::Reference< text::XText > xText(
3570 xSheet->getCellByPosition(nCol, nRow), uno::UNO_QUERY);
3571 if (xText.is() && xText->getString().getLength())
3573 uno::Reference< beans::XPropertySet > xProp(xText, uno::UNO_QUERY);
3574 if( xProp.is())
3575 xProp->getPropertyValue(
3576 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NumberFormat"))) >>= nResult;
3577 bFound = true;
3578 break;
3581 else if( nCount == nIndex )
3583 uno::Reference< beans::XPropertySet > xProp(
3584 xSheet->getCellByPosition(nCol, nRow), uno::UNO_QUERY);
3585 if( xProp.is())
3586 xProp->getPropertyValue(
3587 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NumberFormat"))) >>= nResult;
3588 bFound = true;
3589 break;
3591 ++nCount;
3597 return nResult;
3600 // XCloneable ================================================================
3602 uno::Reference< util::XCloneable > SAL_CALL ScChart2DataSequence::createClone()
3603 throw (uno::RuntimeException)
3605 ScUnoGuard aGuard;
3607 auto_ptr< vector<ScSharedTokenRef> > pTokensNew;
3608 if (m_pTokens.get())
3610 // Clone tokens.
3611 pTokensNew.reset(new vector<ScSharedTokenRef>);
3612 pTokensNew->reserve(m_pTokens->size());
3613 vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end();
3614 for (; itr != itrEnd; ++itr)
3616 ScSharedTokenRef p(static_cast<ScToken*>((*itr)->Clone()));
3617 pTokensNew->push_back(p);
3621 auto_ptr<ScChart2DataSequence> p(new ScChart2DataSequence(m_pDocument, m_xDataProvider, pTokensNew.release(), m_bIncludeHiddenCells));
3622 p->CopyData(*this);
3623 Reference< util::XCloneable > xClone(p.release());
3625 return xClone;
3628 // XModifyBroadcaster ========================================================
3630 void SAL_CALL ScChart2DataSequence::addModifyListener( const uno::Reference< util::XModifyListener >& aListener )
3631 throw (uno::RuntimeException)
3633 // like ScCellRangesBase::addModifyListener
3634 ScUnoGuard aGuard;
3635 if (!m_pTokens.get() || m_pTokens->empty())
3636 return;
3638 ScRangeList aRanges;
3639 ScRefTokenHelper::getRangeListFromTokens(aRanges, *m_pTokens);
3640 uno::Reference<util::XModifyListener> *pObj =
3641 new uno::Reference<util::XModifyListener>( aListener );
3642 m_aValueListeners.Insert( pObj, m_aValueListeners.Count() );
3644 if ( m_aValueListeners.Count() == 1 )
3646 if (!m_pValueListener)
3647 m_pValueListener = new ScLinkListener( LINK( this, ScChart2DataSequence, ValueListenerHdl ) );
3649 if (!m_pHiddenListener.get())
3650 m_pHiddenListener.reset(new HiddenRangeListener(*this));
3652 if( m_pDocument )
3654 ScChartListenerCollection* pCLC = m_pDocument->GetChartListenerCollection();
3655 vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end();
3656 for (; itr != itrEnd; ++itr)
3658 ScRange aRange;
3659 if (!ScRefTokenHelper::getRangeFromToken(aRange, *itr))
3660 continue;
3662 m_pDocument->StartListeningArea( aRange, m_pValueListener );
3663 if (pCLC)
3664 pCLC->StartListeningHiddenRange(aRange, m_pHiddenListener.get());
3668 acquire(); // don't lose this object (one ref for all listeners)
3672 void SAL_CALL ScChart2DataSequence::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener )
3673 throw (uno::RuntimeException)
3675 // like ScCellRangesBase::removeModifyListener
3677 ScUnoGuard aGuard;
3678 if (!m_pTokens.get() || m_pTokens->empty())
3679 return;
3681 acquire(); // in case the listeners have the last ref - released below
3683 USHORT nCount = m_aValueListeners.Count();
3684 for ( USHORT n=nCount; n--; )
3686 uno::Reference<util::XModifyListener> *pObj = m_aValueListeners[n];
3687 if ( *pObj == aListener )
3689 m_aValueListeners.DeleteAndDestroy( n );
3691 if ( m_aValueListeners.Count() == 0 )
3693 if (m_pValueListener)
3694 m_pValueListener->EndListeningAll();
3696 if (m_pHiddenListener.get() && m_pDocument)
3698 ScChartListenerCollection* pCLC = m_pDocument->GetChartListenerCollection();
3699 if (pCLC)
3700 pCLC->EndListeningHiddenRange(m_pHiddenListener.get());
3703 release(); // release the ref for the listeners
3706 break;
3710 release(); // might delete this object
3713 // DataSequence XPropertySet -------------------------------------------------
3715 uno::Reference< beans::XPropertySetInfo> SAL_CALL
3716 ScChart2DataSequence::getPropertySetInfo() throw( uno::RuntimeException)
3718 ScUnoGuard aGuard;
3719 static uno::Reference<beans::XPropertySetInfo> aRef =
3720 new SfxItemPropertySetInfo( m_aPropSet.getPropertyMap() );
3721 return aRef;
3725 void SAL_CALL ScChart2DataSequence::setPropertyValue(
3726 const ::rtl::OUString& rPropertyName, const uno::Any& rValue)
3727 throw( beans::UnknownPropertyException,
3728 beans::PropertyVetoException,
3729 lang::IllegalArgumentException,
3730 lang::WrappedTargetException, uno::RuntimeException)
3732 if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE)))
3734 if ( !(rValue >>= m_aRole))
3735 throw lang::IllegalArgumentException();
3737 else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS)))
3739 sal_Bool bOldValue = m_bIncludeHiddenCells;
3740 if ( !(rValue >>= m_bIncludeHiddenCells))
3741 throw lang::IllegalArgumentException();
3742 if( bOldValue != m_bIncludeHiddenCells )
3743 m_aDataArray.clear();//data array is dirty now
3745 else
3746 throw beans::UnknownPropertyException();
3747 // TODO: support optional properties
3751 uno::Any SAL_CALL ScChart2DataSequence::getPropertyValue(
3752 const ::rtl::OUString& rPropertyName)
3753 throw( beans::UnknownPropertyException,
3754 lang::WrappedTargetException, uno::RuntimeException)
3756 uno::Any aRet;
3757 if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE)))
3758 aRet <<= m_aRole;
3759 else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS)))
3760 aRet <<= m_bIncludeHiddenCells;
3761 else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(SC_UNONAME_HIDDENVALUES)))
3763 // This property is read-only thus cannot be set externally via
3764 // setPropertyValue(...).
3765 BuildDataCache();
3766 aRet <<= m_aHiddenValues;
3768 else
3769 throw beans::UnknownPropertyException();
3770 // TODO: support optional properties
3771 return aRet;
3775 void SAL_CALL ScChart2DataSequence::addPropertyChangeListener(
3776 const ::rtl::OUString& /*rPropertyName*/,
3777 const uno::Reference< beans::XPropertyChangeListener>& /*xListener*/)
3778 throw( beans::UnknownPropertyException,
3779 lang::WrappedTargetException, uno::RuntimeException)
3781 // FIXME: real implementation
3782 // throw uno::RuntimeException();
3783 OSL_ENSURE( false, "Not yet implemented" );
3787 void SAL_CALL ScChart2DataSequence::removePropertyChangeListener(
3788 const ::rtl::OUString& /*rPropertyName*/,
3789 const uno::Reference< beans::XPropertyChangeListener>& /*rListener*/)
3790 throw( beans::UnknownPropertyException,
3791 lang::WrappedTargetException, uno::RuntimeException)
3793 // FIXME: real implementation
3794 // throw uno::RuntimeException();
3795 OSL_ENSURE( false, "Not yet implemented" );
3799 void SAL_CALL ScChart2DataSequence::addVetoableChangeListener(
3800 const ::rtl::OUString& /*rPropertyName*/,
3801 const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/)
3802 throw( beans::UnknownPropertyException,
3803 lang::WrappedTargetException, uno::RuntimeException)
3805 // FIXME: real implementation
3806 // throw uno::RuntimeException();
3807 OSL_ENSURE( false, "Not yet implemented" );
3811 void SAL_CALL ScChart2DataSequence::removeVetoableChangeListener(
3812 const ::rtl::OUString& /*rPropertyName*/,
3813 const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/)
3814 throw( beans::UnknownPropertyException,
3815 lang::WrappedTargetException, uno::RuntimeException)
3817 // FIXME: real implementation
3818 // throw uno::RuntimeException();
3819 OSL_ENSURE( false, "Not yet implemented" );
3822 void ScChart2DataSequence::setDataChangedHint(bool b)
3824 m_bGotDataChangedHint = b;
3827 // XUnoTunnel
3829 // sal_Int64 SAL_CALL ScChart2DataSequence::getSomething(
3830 // const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException)
3831 // {
3832 // if ( rId.getLength() == 16 &&
3833 // 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
3834 // rId.getConstArray(), 16 ) )
3835 // {
3836 // return (sal_Int64)this;
3837 // }
3838 // return 0;
3839 // }
3841 // // static
3842 // const uno::Sequence<sal_Int8>& ScChart2DataSequence::getUnoTunnelId()
3843 // {
3844 // static uno::Sequence<sal_Int8> * pSeq = 0;
3845 // if( !pSeq )
3846 // {
3847 // osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
3848 // if( !pSeq )
3849 // {
3850 // static uno::Sequence< sal_Int8 > aSeq( 16 );
3851 // rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
3852 // pSeq = &aSeq;
3853 // }
3854 // }
3855 // return *pSeq;
3856 // }
3858 // // static
3859 // ScChart2DataSequence* ScChart2DataSequence::getImplementation( const uno::Reference<uno::XInterface> xObj )
3860 // {
3861 // ScChart2DataSequence* pRet = NULL;
3862 // uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY );
3863 // if (xUT.is())
3864 // pRet = (ScChart2DataSequence*) xUT->getSomething( getUnoTunnelId() );
3865 // return pRet;
3866 // }
3868 #if USE_CHART2_EMPTYDATASEQUENCE
3869 // DataSequence ==============================================================
3871 ScChart2EmptyDataSequence::ScChart2EmptyDataSequence( ScDocument* pDoc,
3872 const uno::Reference < chart2::data::XDataProvider >& xDP,
3873 const ScRangeListRef& rRangeList,
3874 sal_Bool bColumn)
3875 : m_bIncludeHiddenCells( sal_True)
3876 , m_xRanges( rRangeList)
3877 , m_pDocument( pDoc)
3878 , m_xDataProvider( xDP)
3879 , m_aPropSet(lcl_GetDataSequencePropertyMap())
3880 , m_bColumn(bColumn)
3882 if ( m_pDocument )
3883 m_pDocument->AddUnoObject( *this);
3884 // FIXME: real implementation of identifier and it's mapping to ranges.
3885 // Reuse ScChartListener?
3887 // BM: don't use names of named ranges but the UI range strings
3888 // String aStr;
3889 // rRangeList->Format( aStr, SCR_ABS_3D, m_pDocument );
3890 // m_aIdentifier = ::rtl::OUString( aStr );
3892 // m_aIdentifier = ::rtl::OUString::createFromAscii( "ID_");
3893 // static sal_Int32 nID = 0;
3894 // m_aIdentifier += ::rtl::OUString::valueOf( ++nID);
3898 ScChart2EmptyDataSequence::~ScChart2EmptyDataSequence()
3900 if ( m_pDocument )
3901 m_pDocument->RemoveUnoObject( *this);
3905 void ScChart2EmptyDataSequence::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
3907 if ( rHint.ISA( SfxSimpleHint ) &&
3908 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
3910 m_pDocument = NULL;
3915 uno::Sequence< uno::Any> SAL_CALL ScChart2EmptyDataSequence::getData()
3916 throw ( uno::RuntimeException)
3918 ScUnoGuard aGuard;
3919 if ( !m_pDocument)
3920 throw uno::RuntimeException();
3921 return uno::Sequence< uno::Any>();
3924 // XTextualDataSequence --------------------------------------------------
3926 uno::Sequence< rtl::OUString > SAL_CALL ScChart2EmptyDataSequence::getTextualData( ) throw (uno::RuntimeException)
3928 ScUnoGuard aGuard;
3929 if ( !m_pDocument)
3930 throw uno::RuntimeException();
3932 sal_Int32 nCount = 0;
3933 ScRangePtr p;
3935 DBG_ASSERT(m_xRanges->Count() == 1, "not handled count of ranges");
3937 for ( p = m_xRanges->First(); p; p = m_xRanges->Next())
3939 p->Justify();
3940 // TODO: handle overlaping ranges?
3941 nCount += m_bColumn ? p->aEnd.Col() - p->aStart.Col() + 1 : p->aEnd.Row() - p->aStart.Row() + 1;
3943 uno::Sequence< rtl::OUString > aSeq( nCount);
3944 rtl::OUString* pArr = aSeq.getArray();
3945 nCount = 0;
3946 for ( p = m_xRanges->First(); p; p = m_xRanges->Next())
3948 if (m_bColumn)
3950 for (SCCOL nCol = p->aStart.Col(); nCol <= p->aEnd.Col(); ++nCol)
3952 String aString = ScGlobal::GetRscString(STR_COLUMN);
3953 aString += ' ';
3954 ScAddress aPos( nCol, 0, 0 );
3955 String aColStr;
3956 aPos.Format( aColStr, SCA_VALID_COL, NULL );
3957 aString += aColStr;
3958 pArr[nCount] = aString;
3959 ++nCount;
3962 else
3964 sal_Int32 n = p->aEnd.Row() - p->aStart.Row() + 1;
3965 for (sal_Int32 i = 0; i < n; ++i)
3966 pArr[nCount++] = String::CreateFromInt32( i+1 );
3969 return aSeq;
3972 ::rtl::OUString SAL_CALL ScChart2EmptyDataSequence::getSourceRangeRepresentation()
3973 throw ( uno::RuntimeException)
3975 ScUnoGuard aGuard;
3976 String aStr;
3977 DBG_ASSERT( m_pDocument, "No Document -> no SourceRangeRepresentation" );
3978 if( m_pDocument )
3979 m_xRanges->Format( aStr, SCR_ABS_3D, m_pDocument, m_pDocument->GetAddressConvention() );
3980 return aStr;
3983 uno::Sequence< ::rtl::OUString > SAL_CALL ScChart2EmptyDataSequence::generateLabel(chart2::data::LabelOrigin /*nOrigin*/)
3984 throw (uno::RuntimeException)
3986 ScUnoGuard aGuard;
3987 uno::Sequence< ::rtl::OUString > aRet;
3988 return aRet;
3991 ::sal_Int32 SAL_CALL ScChart2EmptyDataSequence::getNumberFormatKeyByIndex( ::sal_Int32 /*nIndex*/ )
3992 throw (lang::IndexOutOfBoundsException,
3993 uno::RuntimeException)
3995 sal_Int32 nResult = 0;
3997 ScUnoGuard aGuard;
3998 if ( !m_pDocument)
3999 return nResult;
4001 return nResult;
4004 // XCloneable ================================================================
4006 uno::Reference< util::XCloneable > SAL_CALL ScChart2EmptyDataSequence::createClone()
4007 throw (uno::RuntimeException)
4009 ScUnoGuard aGuard;
4010 if (m_xDataProvider.is())
4012 // copy properties
4013 uno::Reference < util::XCloneable > xClone(new ScChart2EmptyDataSequence(m_pDocument, m_xDataProvider, new ScRangeList(*m_xRanges), m_bColumn));
4014 uno::Reference< beans::XPropertySet > xProp( xClone, uno::UNO_QUERY );
4015 if( xProp.is())
4017 xProp->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_ROLE )),
4018 uno::makeAny( m_aRole ));
4019 xProp->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS )),
4020 uno::makeAny( m_bIncludeHiddenCells ));
4022 return xClone;
4024 return uno::Reference< util::XCloneable >();
4027 // XModifyBroadcaster ========================================================
4029 void SAL_CALL ScChart2EmptyDataSequence::addModifyListener( const uno::Reference< util::XModifyListener >& /*aListener*/ )
4030 throw (uno::RuntimeException)
4032 // TODO: Implement
4035 void SAL_CALL ScChart2EmptyDataSequence::removeModifyListener( const uno::Reference< util::XModifyListener >& /*aListener*/ )
4036 throw (uno::RuntimeException)
4038 // TODO: Implement
4041 // DataSequence XPropertySet -------------------------------------------------
4043 uno::Reference< beans::XPropertySetInfo> SAL_CALL
4044 ScChart2EmptyDataSequence::getPropertySetInfo() throw( uno::RuntimeException)
4046 ScUnoGuard aGuard;
4047 static uno::Reference<beans::XPropertySetInfo> aRef =
4048 new SfxItemPropertySetInfo( m_aPropSet.getPropertyMap() );
4049 return aRef;
4053 void SAL_CALL ScChart2EmptyDataSequence::setPropertyValue(
4054 const ::rtl::OUString& rPropertyName, const uno::Any& rValue)
4055 throw( beans::UnknownPropertyException,
4056 beans::PropertyVetoException,
4057 lang::IllegalArgumentException,
4058 lang::WrappedTargetException, uno::RuntimeException)
4060 if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE)))
4062 if ( !(rValue >>= m_aRole))
4063 throw lang::IllegalArgumentException();
4065 else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS)))
4067 if ( !(rValue >>= m_bIncludeHiddenCells))
4068 throw lang::IllegalArgumentException();
4070 else
4071 throw beans::UnknownPropertyException();
4072 // TODO: support optional properties
4076 uno::Any SAL_CALL ScChart2EmptyDataSequence::getPropertyValue(
4077 const ::rtl::OUString& rPropertyName)
4078 throw( beans::UnknownPropertyException,
4079 lang::WrappedTargetException, uno::RuntimeException)
4081 uno::Any aRet;
4082 if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE)))
4083 aRet <<= m_aRole;
4084 else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS)))
4085 aRet <<= m_bIncludeHiddenCells;
4086 else
4087 throw beans::UnknownPropertyException();
4088 // TODO: support optional properties
4089 return aRet;
4093 void SAL_CALL ScChart2EmptyDataSequence::addPropertyChangeListener(
4094 const ::rtl::OUString& /*rPropertyName*/,
4095 const uno::Reference< beans::XPropertyChangeListener>& /*xListener*/)
4096 throw( beans::UnknownPropertyException,
4097 lang::WrappedTargetException, uno::RuntimeException)
4099 // FIXME: real implementation
4100 // throw uno::RuntimeException();
4101 OSL_ENSURE( false, "Not yet implemented" );
4105 void SAL_CALL ScChart2EmptyDataSequence::removePropertyChangeListener(
4106 const ::rtl::OUString& /*rPropertyName*/,
4107 const uno::Reference< beans::XPropertyChangeListener>& /*rListener*/)
4108 throw( beans::UnknownPropertyException,
4109 lang::WrappedTargetException, uno::RuntimeException)
4111 // FIXME: real implementation
4112 // throw uno::RuntimeException();
4113 OSL_ENSURE( false, "Not yet implemented" );
4117 void SAL_CALL ScChart2EmptyDataSequence::addVetoableChangeListener(
4118 const ::rtl::OUString& /*rPropertyName*/,
4119 const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/)
4120 throw( beans::UnknownPropertyException,
4121 lang::WrappedTargetException, uno::RuntimeException)
4123 // FIXME: real implementation
4124 // throw uno::RuntimeException();
4125 OSL_ENSURE( false, "Not yet implemented" );
4129 void SAL_CALL ScChart2EmptyDataSequence::removeVetoableChangeListener(
4130 const ::rtl::OUString& /*rPropertyName*/,
4131 const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/ )
4132 throw( beans::UnknownPropertyException,
4133 lang::WrappedTargetException, uno::RuntimeException)
4135 // FIXME: real implementation
4136 // throw uno::RuntimeException();
4137 OSL_ENSURE( false, "Not yet implemented" );
4140 // XUnoTunnel
4142 // sal_Int64 SAL_CALL ScChart2EmptyDataSequence::getSomething(
4143 // const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException)
4144 // {
4145 // if ( rId.getLength() == 16 &&
4146 // 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
4147 // rId.getConstArray(), 16 ) )
4148 // {
4149 // return (sal_Int64)this;
4150 // }
4151 // return 0;
4152 // }
4154 // // static
4155 // const uno::Sequence<sal_Int8>& ScChart2EmptyDataSequence::getUnoTunnelId()
4156 // {
4157 // static uno::Sequence<sal_Int8> * pSeq = 0;
4158 // if( !pSeq )
4159 // {
4160 // osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
4161 // if( !pSeq )
4162 // {
4163 // static uno::Sequence< sal_Int8 > aSeq( 16 );
4164 // rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
4165 // pSeq = &aSeq;
4166 // }
4167 // }
4168 // return *pSeq;
4169 // }
4171 // // static
4172 // ScChart2DataSequence* ScChart2EmptyDataSequence::getImplementation( const uno::Reference<uno::XInterface> xObj )
4173 // {
4174 // ScChart2DataSequence* pRet = NULL;
4175 // uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY );
4176 // if (xUT.is())
4177 // pRet = (ScChart2EmptyDataSequence*) xUT->getSomething( getUnoTunnelId() );
4178 // return pRet;
4179 // }
4180 #endif