1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: chart2uno.cxx,v $
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"
39 #include "chartpos.hxx"
40 #include "unonames.hxx"
41 #include "globstr.hrc"
42 #include "convuno.hxx"
43 #include "rangeutl.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>
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")
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
;
86 using ::std::distance
;
87 using ::std::unary_function
;
88 using ::std::hash_set
;
89 using ::boost::shared_ptr
;
93 const SfxItemPropertyMapEntry
* lcl_GetDataProviderPropertyMap()
95 static SfxItemPropertyMapEntry aDataProviderPropertyMap_Impl
[] =
97 {MAP_CHAR_LEN(SC_UNONAME_INCLUDEHIDDENCELLS
), 0, &getBooleanCppuType(), 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 },
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());
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() )
138 uno::Reference
< chart2::data::XDataSequence
> xSeq( aSequences
[nIdx
]->getLabel());
140 aResult
.push_back( xSeq
->getSourceRangeRepresentation());
142 xSeq
.set( aSequences
[nIdx
]->getValues());
144 aResult
.push_back( xSeq
->getSourceRangeRepresentation());
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
;
167 (xSeqProp
->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Role"))) >>= aRole
) &&
168 aRole
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("categories")) )
170 xResult
.set( aSequences
[nIdx
] );
179 struct lcl_appendTableNumber
: public ::std::unary_function
< SCTAB
, void >
181 lcl_appendTableNumber( ::rtl::OUStringBuffer
& 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( ' ' ));
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 );
209 xModel
.set( pObjSh
->GetModel());
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
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;
238 sal_uInt32
getIndex(SCCOL nCol
, SCROW nRow
) const
240 return static_cast<sal_uInt32
>(nCol
*getRowCount() + nRow
);
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());
263 pPos
= static_cast<FormulaToken
*>(pCol
->Next());
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.
277 for (SCROW nRow
= 0; nRow
< nRowCount
; ++nRow
)
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
)
290 pPos
= static_cast<FormulaToken
*>(pCol
->First());
293 // 1st row as a column header.
294 maColHeaders
.push_back(pPos
);
295 pPos
= static_cast<FormulaToken
*>(pCol
->Next());
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());
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());
320 struct DeleteInstance
: public unary_function
<FormulaToken
*, void>
322 void operator() (FormulaToken
* p
) const
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
];
343 const FormulaToken
* Chart2PositionMap::getRowHeaderPosition(SCROW nRow
) const
345 if (nRow
< getRowCount())
346 return maRowHeaders
[nRow
];
350 vector
<ScSharedTokenRef
>* Chart2PositionMap::getColRanges(SCCOL nCol
) const
352 if (nCol
>= getColCount())
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
];
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
)
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
];
383 ScSharedTokenRef
p2(static_cast<ScToken
*>(p
->Clone()));
384 ScRefTokenHelper::join(*pTokens
, p2
);
386 return pTokens
.release();
389 // ----------------------------------------------------------------------------
392 * Designed to be a drop-in replacement for ScChartPositioner, in order to
393 * handle external references.
395 class Chart2Positioner
407 Chart2Positioner(ScDocument
* pDoc
, const vector
<ScSharedTokenRef
>& rRefTokens
) :
408 mpRefTokens(new vector
<ScSharedTokenRef
>(rRefTokens
)),
414 mbDummyUpperLeft(false)
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()
434 return mpPositionMap
.get();
438 Chart2Positioner(); // disabled
440 void invalidateGlue();
442 void createPositionMap();
445 shared_ptr
< vector
<ScSharedTokenRef
> > mpRefTokens
;
446 auto_ptr
<Chart2PositionMap
> mpPositionMap
;
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
)
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
;
477 meGlue
= GLUETYPE_COLS
;
478 mnStartCol
= aData
.Ref1
.nCol
;
479 mnStartRow
= aData
.Ref1
.nRow
;
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;
505 mnStartCol
= static_cast<SCCOL
>(n1
);
507 nEndCol
= static_cast<SCCOL
>(n2
);
509 nMaxCols
= static_cast<SCCOL
>(nTmp
);
511 n1
= aData
.Ref1
.nRow
;
512 n2
= aData
.Ref2
.nRow
;
516 mnStartRow
= static_cast<SCCOL
>(n1
);
518 nEndRow
= static_cast<SCCOL
>(n2
);
520 nMaxRows
= static_cast<SCCOL
>(nTmp
);
523 // total column size ?
524 SCCOL nC
= nEndCol
- mnStartCol
+ 1;
527 meGlue
= GLUETYPE_ROWS
;
531 SCROW nR
= nEndRow
- mnStartRow
+ 1;
534 meGlue
= GLUETYPE_COLS
;
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
;
563 bool bGlueCols
= false;
564 for (SCCOL nCol
= 0; bGlue
&& nCol
< nC
; ++nCol
)
566 for (SCROW nRow
= 0; bGlue
&& nRow
< nR
; ++nRow
)
569 if (aCellStates
[i
] == nOccu
)
571 if (nRow
> 0 && nRow
> 0)
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
;
587 bool bGlueRows
= false;
588 for (SCROW nRow
= 0; bGlue
&& nRow
< nR
; ++nRow
)
591 for (SCCOL nCol
= 0; bGlue
&& nCol
< nC
; ++nCol
, i
+= nR
)
593 if (aCellStates
[i
] == nOccu
)
595 if (nCol
> 0 && nRow
> 0)
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
;
612 for (sal_uInt32 n
= 1; bGlue
&& n
< nCR
; ++n
, ++i
)
613 if (aCellStates
[i
] == nHole
)
618 if (bGlueCols
&& bGlueRows
)
619 meGlue
= GLUETYPE_BOTH
;
621 meGlue
= GLUETYPE_ROWS
;
623 meGlue
= GLUETYPE_COLS
;
624 if (aCellStates
.front() != nOccu
)
625 mbDummyUpperLeft
= true;
628 meGlue
= GLUETYPE_NONE
;
631 void Chart2Positioner::createPositionMap()
633 if (meGlue
== GLUETYPE_NA
&& mpPositionMap
.get())
634 mpPositionMap
.reset(NULL
);
636 if (mpPositionMap
.get())
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
);
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
));
676 pCol
= pNewRowTable
.get();
677 pCols
->Insert(nInsCol
, pNewRowTable
.release());
678 pNewRowTable
.reset(new Table
);
683 if (pCols
->Insert(nInsCol
, pNewRowTable
.get()))
685 pCol
= pNewRowTable
.release();
686 pNewRowTable
.reset(new Table
);
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
;
706 pNewAddress
.reset(new ScExternalSingleRefToken(nFileId
, aTabName
, aCellData
));
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());
728 if (mbDummyUpperLeft
)
729 pCol
->Insert(0, NULL
); // Dummy fuer Beschriftung
730 nRowCount
= static_cast<SCSIZE
>(pCol
->Count());
735 if (nColCount
> 0 && bColAdd
)
737 if (nRowCount
> 0 && bRowAdd
)
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());
749 pCols
->Insert(0, pCol
);
752 if (pCol
->Count() > 0)
754 FormulaToken
* pPos
= static_cast<FormulaToken
*>(pCol
->First());
758 pCol
->Replace(pCol
->GetCurKey(), NULL
);
762 pCol
->Insert(0, NULL
);
772 Table
* pFirstCol
= static_cast<Table
*>(pCols
->First());
773 sal_uInt32 nCount
= pFirstCol
->Count();
775 for (sal_uInt32 n
= 0; n
< nCount
; ++n
, pFirstCol
->Next())
777 sal_uInt32 nKey
= pFirstCol
->GetCurKey();
779 for (pCol
= static_cast<Table
*>(pCols
->Next()); pCol
; pCol
= static_cast<Table
*>(pCols
->Next()))
780 pCol
->Insert(nKey
, NULL
);
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()))
794 // ============================================================================
797 * Function object to create a range string from a token list.
799 class Tokens2RangeString
: public unary_function
<ScSharedTokenRef
, void>
802 Tokens2RangeString(ScDocument
* pDoc
, FormulaGrammar::Grammar eGram
, sal_Unicode cRangeSep
) :
803 mpRangeStr(new OUStringBuffer
),
806 mcRangeSep(cRangeSep
),
811 Tokens2RangeString(const Tokens2RangeString
& r
) :
812 mpRangeStr(r
.mpRangeStr
),
814 meGrammar(r
.meGrammar
),
815 mcRangeSep(r
.mcRangeSep
),
820 void operator() (const ScSharedTokenRef
& rToken
)
822 ScCompiler
aCompiler(mpDoc
, ScAddress(0,0,0));
823 aCompiler
.SetGrammar(meGrammar
);
825 aCompiler
.CreateStringFromToken(aStr
, rToken
.get());
829 mpRangeStr
->append(mcRangeSep
);
830 mpRangeStr
->append(aStr
);
833 void getString(OUString
& rStr
)
835 rStr
= mpRangeStr
->makeStringAndClear();
839 Tokens2RangeString(); // disabled
842 shared_ptr
<OUStringBuffer
> mpRangeStr
;
844 FormulaGrammar::Grammar meGrammar
;
845 sal_Unicode mcRangeSep
;
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>
860 Tokens2RangeStringXML(ScDocument
* pDoc
) :
861 mpRangeStr(new OUStringBuffer
),
869 Tokens2RangeStringXML(const Tokens2RangeStringXML
& r
) :
870 mpRangeStr(r
.mpRangeStr
),
872 mcRangeSep(r
.mcRangeSep
),
873 mcAddrSep(r
.mcAddrSep
),
878 void operator() (const ScSharedTokenRef
& rToken
)
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
);
891 aCompiler
.CreateStringFromToken(aStr
, aStart
.get());
892 mpRangeStr
->append(aStr
);
894 mpRangeStr
->append(mcAddrSep
);
897 aCompiler
.CreateStringFromToken(aStr
, aEnd
.get());
898 mpRangeStr
->append(aStr
);
902 void getString(OUString
& rStr
)
904 rStr
= mpRangeStr
->makeStringAndClear();
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);
926 rStart
.reset(new ScExternalSingleRefToken(nFileId
, aTabName
, aData
.Ref1
));
928 rStart
.reset(new ScSingleRefToken(aData
.Ref1
));
931 rEnd
.reset(new ScExternalSingleRefToken(nFileId
, aTabName
, aData
.Ref2
));
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);
944 shared_ptr
<OUStringBuffer
> mpRangeStr
;
946 sal_Unicode mcRangeSep
;
947 sal_Unicode mcAddrSep
;
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
)
966 , m_aPropSet(lcl_GetDataProviderPropertyMap())
967 , m_bIncludeHiddenCells( sal_True
)
970 m_pDocument
->AddUnoObject( *this);
973 ScChart2DataProvider::~ScChart2DataProvider()
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
)
989 ::sal_Bool SAL_CALL
ScChart2DataProvider::createDataSourcePossible( const uno::Sequence
< beans::PropertyValue
>& aArguments
)
990 throw (uno::RuntimeException
)
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();
1013 class RemoveHeaderFromRanges
: public unary_function
<ScSharedTokenRef
, void>
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
);
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();
1049 // This range *only* contains the header cell. Skip it.
1052 if (s
.nTab
!= e
.nTab
)
1053 // 3D range has no business being here....
1060 if (s
.nCol
== e
.nCol
)
1062 // single column range.
1063 splitSingleColRange(pRange
, s
, e
);
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
);
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
);
1135 if (s
.nRow
== e
.nRow
)
1137 // Single row range.
1138 splitSingleRowRange(pRange
, s
, e
);
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
);
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
);
1215 void splitSingleColRange(const ScSharedTokenRef
& pRange
, const ScSingleRefData
& s
, const ScSingleRefData
& e
)
1217 const ScSingleRefData
& h
= mpHeaderCell
->GetSingleRef();
1221 // header is at the top.
1223 ScSharedTokenRef
pNew(static_cast<ScToken
*>(pRange
->Clone()));
1224 ScComplexRefData
& r
= pNew
->GetDoubleRef();
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();
1235 ScRefTokenHelper::join(*mpTokens
, pNew
);
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();
1263 // header is at the top.
1265 ScSharedTokenRef
pNew(static_cast<ScToken
*>(pRange
->Clone()));
1266 ScComplexRefData
& r
= pNew
->GetDoubleRef();
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();
1277 ScRefTokenHelper::join(*mpTokens
, pNew
);
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
);
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.
1317 if (pRange
->GetIndex() != mpHeaderCell
->GetIndex())
1318 // different external files.
1321 if (pRange
->GetString() != mpHeaderCell
->GetString())
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
);
1338 shared_ptr
< vector
<ScSharedTokenRef
> > mpTokens
;
1341 * Stores header cell position. Must be a single ref token i.e. either
1342 * ScSingleRefToken or ScExternalSingleRefToken.
1344 ScSharedTokenRef mpHeaderCell
;
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
)
1364 if ( ! m_pDocument
)
1365 throw uno::RuntimeException();
1367 uno::Reference
< chart2::data::XDataSource
> xResult
;
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();
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();
1417 // No chart position map instance. Bail out.
1420 ScChart2DataSource
* pDS
= NULL
;
1421 std::list
< ScChart2LabeledDataSequence
* > aSeqs
;
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
));
1439 ScSharedTokenRef
p(static_cast<ScToken
*>(pPos
->Clone()));
1440 ScRefTokenHelper::join(aRefTokens2
, p
);
1444 StackVar eType
= pLabelToken
->GetType();
1445 if (eType
== svSingleRef
|| eType
== svExternalSingleRef
)
1447 ScSingleRefData
& r
= pLabelToken
->GetSingleRef();
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
);
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
);
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
);
1490 pRanges
.reset(pChartMap
->getColRanges(static_cast<SCCOL
>(i
)));
1492 pRanges
.reset(pChartMap
->getRowRanges(static_cast<SCROW
>(i
)));
1494 ScSharedTokenRef pHeaderCell
;
1497 const FormulaToken
* p
= pChartMap
->getColHeaderPosition(static_cast<SCCOL
>(i
));
1499 pHeaderCell
.reset(static_cast<ScToken
*>(p
->Clone()));
1503 const FormulaToken
* p
= pChartMap
->getRowHeaderPosition(static_cast<SCROW
>(i
));
1505 pHeaderCell
.reset(static_cast<ScToken
*>(p
->Clone()));
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
);
1520 sal_uInt16 nFileId
= p
->GetIndex();
1521 const String
& rTabName
= p
->GetString();
1522 pHeaderCell
.reset(new ScExternalSingleRefToken(nFileId
, rTabName
, aData
));
1525 pHeaderCell
.reset(new ScSingleRefToken(aData
));
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
);
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
);
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
)
1588 pDS
->AddLabeledSequence(*aVectorItr
);
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
);
1611 rOutHasCategories
= xValues
->getImplementationName().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ScChart2DataSequence"));
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
1633 rOutHasFirstCellAsLabel
= xLabel
->getImplementationName().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ScChart2DataSequence"));
1641 } // anonymous namespace
1643 bool ScChart2DataProvider::addUpperLeftCornerIfMissing(vector
<ScSharedTokenRef
>& rRefTokens
)
1648 if (rRefTokens
.empty())
1651 SCCOL nMinCol
= MAXCOLCOUNT
;
1652 SCROW nMinRow
= MAXROWCOUNT
;
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())
1669 const ScSingleRefData
& rData
= pToken
->GetSingleRef();
1670 nMinCol
= rData
.nCol
;
1671 nMinRow
= rData
.nRow
;
1672 nMaxCol
= rData
.nCol
;
1673 nMaxRow
= rData
.nRow
;
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
;
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
;
1695 nFileId
= pToken
->GetIndex();
1696 aExtTabName
= pToken
->GetString();
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();
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
)
1723 switch (pToken
->GetType())
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
)
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
)
1755 case svExternalSingleRef
:
1760 if (nFileId
!= pToken
->GetIndex() || aExtTabName
!= pToken
->GetString())
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
);
1771 case svExternalDoubleRef
:
1776 if (nFileId
!= pToken
->GetIndex() || aExtTabName
!= pToken
->GetString())
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
);
1797 if (nMinRow
>= nMaxRow
|| nMinCol
>= nMaxCol
||
1798 nMinRow
>= MAXROWCOUNT
|| nMinCol
>= MAXCOLCOUNT
||
1799 nMaxRow
>= MAXROWCOUNT
|| nMaxCol
>= MAXCOLCOUNT
)
1801 // Invalid range. Bail out.
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
)
1814 switch (pToken
->GetType())
1817 case svExternalSingleRef
:
1819 const ScSingleRefData
& rData
= pToken
->GetSingleRef();
1820 if (rData
.nCol
== nMinCol
&& rData
.nRow
== nMinRow
)
1821 // The corner cell is contained.
1824 if (rData
.nCol
== nMinCol
+1 && rData
.nRow
== nMinRow
)
1827 if (rData
.nCol
== nMinCol
&& rData
.nRow
== nMinRow
+1)
1830 if (rData
.nCol
== nMinCol
+1 && rData
.nRow
== nMinRow
+1)
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.
1845 if (r1
.nCol
<= nMinCol
+1 && nMinCol
+1 <= r2
.nCol
&&
1846 r1
.nRow
<= nMinRow
&& nMinRow
<= r2
.nRow
)
1849 if (r1
.nCol
<= nMinCol
&& nMinCol
<= r2
.nCol
&&
1850 r1
.nRow
<= nMinRow
+1 && nMinRow
+1 <= r2
.nRow
)
1853 if (r1
.nCol
<= nMinCol
+1 && nMinCol
+1 <= r2
.nCol
&&
1854 r1
.nRow
<= nMinRow
+1 && nMinRow
+1 <= r2
.nRow
)
1863 if (!bRight
|| !bBottom
|| !bDiagonal
)
1864 // Not all the adjacent cells are included. Bail out.
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
;
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
;
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);
1900 new ScExternalDoubleRefToken(nFileId
, aExtTabName
, aData
));
1901 aNewTokens
.push_back(p
);
1905 ScSharedTokenRef
p(new ScDoubleRefToken(aData
));
1906 aNewTokens
.push_back(p
);
1908 rRefTokens
.swap(aNewTokens
);
1914 ScSingleRefData aData
;
1916 aData
.SetFlag3D(true);
1917 aData
.SetColRel(false);
1918 aData
.SetRowRel(false);
1919 aData
.SetTabRel(false);
1920 aData
.nCol
= nMinCol
;
1921 aData
.nRow
= nMinRow
;
1926 ScSharedTokenRef
pCorner(
1927 new ScExternalSingleRefToken(nFileId
, aExtTabName
, aData
));
1928 ScRefTokenHelper::join(rRefTokens
, pCorner
);
1932 ScSharedTokenRef
pCorner(new ScSingleRefToken(aData
));
1933 ScRefTokenHelper::join(rRefTokens
, pCorner
);
1942 * Function object to create a list of table numbers from a token list.
1944 class InsertTabNumber
: public unary_function
<ScSharedTokenRef
, void>
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
))
1962 const ScSingleRefData
& r
= pToken
->GetSingleRef();
1963 mpTabNumList
->push_back(r
.nTab
);
1966 void getList(list
<SCTAB
>& rList
)
1968 mpTabNumList
->swap(rList
);
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
1993 DBG_ASSERT( m_pDocument
, "No Document -> no detectArguments" );
1995 return lcl_VectorToSequence( aResult
);
1997 detectRangesFromDataSource(aTokens
, eRowSource
, bRowSourceDetected
, xDataSource
);
2002 list
<SCTAB
> aTableNumList
;
2003 InsertTabNumber func
;
2004 func
= for_each(aTokens
.begin(), aTokens
.end(), func
);
2005 func
.getList(aTableNumList
);
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
)
2016 beans::PropertyValue( ::rtl::OUString::createFromAscii("DataRowSource"), -1,
2017 uno::makeAny( eRowSource
), beans::PropertyState_DIRECT_VALUE
));
2021 if( bRowSourceDetected
)
2023 if( lcl_HasCategories( xDataSource
, bHasCategories
))
2026 beans::PropertyValue( ::rtl::OUString::createFromAscii("HasCategories"), -1,
2027 uno::makeAny( bHasCategories
), beans::PropertyState_DIRECT_VALUE
));
2032 if( bRowSourceDetected
)
2034 lcl_HasFirstCellAsLabel( xDataSource
, bFirstCellAsLabel
);
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
2049 beans::PropertyValue( ::rtl::OUString::createFromAscii("CellRangeRepresentation"), -1,
2050 uno::makeAny( sRangeRep
), beans::PropertyState_DIRECT_VALUE
));
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
);
2116 if( bDifferentIndexes
&& aSequenceMappingVector
.size() )
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
)
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
)
2147 uno::Reference
< chart2::data::XDataSequence
> xResult
;
2149 DBG_ASSERT( m_pDocument
, "No Document -> no createDataSequenceByRangeRepresentation" );
2150 if(!m_pDocument
|| (aRangeRepresentation
.getLength() == 0))
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
2159 vector
<ScSharedTokenRef
> aRefTokens
;
2160 ScRefTokenHelper::compileRangeRepresentation(aRefTokens
, aRangeRepresentation
, m_pDocument
);
2161 if (aRefTokens
.empty())
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
));
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
));
2179 xResult
.set( xModel
->getCurrentController(), uno::UNO_QUERY
);
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
)
2199 if (!sRangeRepresentation
.getLength())
2200 // Empty data range is allowed.
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
);
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
= '\'';
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
);
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();
2256 ScRangeStringConverter::GetStringFromXMLRangeString(aRet
, sXMLRange
, m_pDocument
);
2262 class CollectRefTokens
: public ::std::unary_function
<ScSharedTokenRef
, void>
2265 CollectRefTokens() :
2266 mpRefTokens(new vector
<ScSharedTokenRef
>()),
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
)
2297 else if (bRowDiff
&& !bColDiff
)
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
;
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
)
2351 static uno::Reference
<beans::XPropertySetInfo
> aRef
=
2352 new SfxItemPropertySetInfo( m_aPropSet
.getPropertyMap() );
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();
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
)
2380 if ( rPropertyName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS
)))
2381 aRet
<<= m_bIncludeHiddenCells
;
2383 throw beans::UnknownPropertyException();
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
)
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
);
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
)
2480 m_pDocument
->AddUnoObject( *this);
2484 ScChart2DataSource::~ScChart2DataSource()
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
)
2501 uno::Sequence
< uno::Reference
< chart2::data::XLabeledDataSequence
> > SAL_CALL
2502 ScChart2DataSource::getDataSequences() throw ( uno::RuntimeException
)
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());
2512 while (aItr
!= aEndItr
)
2521 /* typedef ::std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > tVec;
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 );
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(),
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));
2547 uno::Reference< beans::XPropertySet > xProp( xLabel, uno::UNO_QUERY );
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(),
2562 uno::Reference< chart2::data::XDataSequence > xData(
2563 new ScChart2DataSequence( m_pDocument, aColRanges));
2566 uno::Reference< beans::XPropertySet > xProp( xData, uno::UNO_QUERY );
2568 xProp->setPropertyValue(
2569 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )),
2570 ::uno::makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "values" ))));
2572 xLabeledSeq->setValues( xData );
2578 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence> > aSequences(
2580 uno::Reference< chart2::data::XLabeledDataSequence> * pArr = aSequences.getArray();
2582 for ( tVec::const_iterator iSeq = aVec.begin(); iSeq != aVec.end();
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
) :
2602 m_pDocument
->AddUnoObject( *this);
2605 ScChart2LabeledDataSequence::~ScChart2LabeledDataSequence()
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
)
2623 // XLabeledDataSequence --------------------------------------------------
2625 uno::Reference
< chart2::data::XDataSequence
> SAL_CALL
ScChart2LabeledDataSequence::getValues()
2626 throw (uno::RuntimeException
)
2632 void SAL_CALL
ScChart2LabeledDataSequence::setValues(
2633 const uno::Reference
< chart2::data::XDataSequence
>& xSequence
)
2634 throw (uno::RuntimeException
)
2637 m_aData
= xSequence
;
2640 uno::Reference
< chart2::data::XDataSequence
> SAL_CALL
ScChart2LabeledDataSequence::getLabel()
2641 throw (uno::RuntimeException
)
2647 void SAL_CALL
ScChart2LabeledDataSequence::setLabel(
2648 const uno::Reference
< chart2::data::XDataSequence
>& xSequence
)
2649 throw (uno::RuntimeException
)
2652 m_aLabel
= xSequence
;
2655 // XCloneable ================================================================
2657 uno::Reference
< util::XCloneable
> SAL_CALL
ScChart2LabeledDataSequence::createClone()
2658 throw (uno::RuntimeException
)
2661 uno::Reference
< util::XCloneable
> xToClone(m_aData
, uno::UNO_QUERY
);
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
);
2670 xSequence
.set(xToClone
->createClone(), uno::UNO_QUERY
);
2671 pRet
->setLabel(xSequence
);
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
) :
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
)
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");
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
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()
2767 m_pDocument
->RemoveUnoObject( *this);
2768 if (m_pHiddenListener
.get())
2770 ScChartListenerCollection
* pCLC
= m_pDocument
->GetChartListenerCollection();
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();
2788 ScChartListenerCollection
* pCLC
= NULL
;
2789 if (m_pHiddenListener
.get())
2791 pCLC
= m_pDocument
->GetChartListenerCollection();
2793 pCLC
->EndListeningHiddenRange(m_pHiddenListener
.get());
2796 vector
<ScSharedTokenRef
>::const_iterator itr
= m_pTokens
->begin(), itrEnd
= m_pTokens
->end();
2797 for (; itr
!= itrEnd
; ++itr
)
2800 if (!ScRefTokenHelper::getRangeFromToken(aRange
, *itr
))
2803 m_pDocument
->StartListeningArea(aRange
, m_pValueListener
);
2805 pCLC
->StartListeningHiddenRange(aRange
, m_pHiddenListener
.get());
2811 void ScChart2DataSequence::BuildDataCache()
2813 m_bExtDataRebuildQueued
= false;
2815 if (!m_aDataArray
.empty())
2818 if (!m_pTokens
.get())
2820 DBG_ERROR("m_pTokens == NULL! Something is wrong.");
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
);
2840 if (!ScRefTokenHelper::getRangeFromToken(aRange
, *itr
))
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
)
2857 ++nHiddenValueCount
;
2858 aHiddenValues
.push_back(nDataCount
-1);
2860 if( !m_bIncludeHiddenCells
)
2864 m_aDataArray
.push_back(Item());
2865 Item
& rItem
= m_aDataArray
.back();
2868 ScAddress
aAdr(nCol
, nRow
, nTab
);
2869 ScBaseCell
* pCell
= m_pDocument
->GetCell(aAdr
);
2873 if (pCell
->HasStringData())
2874 rItem
.maString
= pCell
->GetStringData();
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;
2888 case CELLTYPE_FORMULA
:
2890 ScFormulaCell
* pFCell
= static_cast<ScFormulaCell
*>(pCell
);
2891 USHORT nErr
= pFCell
->GetErrCode();
2895 if (pFCell
->HasValueData())
2897 rItem
.mfValue
= pFCell
->GetValue();
2898 rItem
.mbIsValue
= true;
2903 case CELLTYPE_DESTROYED
:
2908 case CELLTYPE_STRING
:
2909 case CELLTYPE_SYMBOLS
:
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
)
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();
2945 if (!ScRefTokenHelper::getRangeFromToken(aRange
, pToken
, true))
2948 sal_uInt16 nFileId
= pToken
->GetIndex();
2949 const String
& rTabName
= pToken
->GetString();
2950 ScExternalRefCache::TokenArrayRef pArray
= pRefMgr
->getDoubleRefTokens(nFileId
, rTabName
, aRange
, NULL
);
2952 // no external data exists for this range.
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
2969 if (p
->GetType() != svMatrix
)
2971 DBG_ERROR("Cached array is not a matrix token.");
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();
2988 rItem
.mbIsValue
= true;
2989 rItem
.mfValue
= pMat
->GetDouble(nC
, nR
);
2991 SvNumberFormatter
* pFormatter
= m_pDocument
->GetFormatTable();
2995 const double fVal
= rItem
.mfValue
;
2996 Color
* pColor
= NULL
;
2997 sal_uInt32 nFmt
= 0;
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();
3015 rItem
.mbIsValue
= false;
3016 rItem
.maString
= pMat
->GetString(nC
, nR
);
3024 void ScChart2DataSequence::UpdateTokensFromRanges(const ScRangeList
& rRanges
)
3026 if (!m_pRangeIndices
.get())
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
;
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())
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
)
3074 DBG_ERROR("document instance is NULL!?");
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
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
)
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);
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
))
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());
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
)
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");
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.");
3211 UpdateTokensFromRanges(rRanges
);
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);
3232 // ----------------------------------------------------------------------------
3234 ScChart2DataSequence::ExternalRefListener::ExternalRefListener(
3235 ScChart2DataSequence
& rParent
, ScDocument
* pDoc
) :
3236 ScExternalRefManager::LinkListener(),
3242 ScChart2DataSequence::ExternalRefListener::~ExternalRefListener()
3244 if (!mpDoc
|| mpDoc
->IsInDtorClear())
3245 // The document is being destroyed. Do nothing.
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
)
3256 case ScExternalRefManager::LINK_MODIFIED
:
3258 if (maFileIds
.count(nFileId
))
3259 // We are listening to this external document.
3260 mrParent
.RebuildDataCache();
3263 case ScExternalRefManager::LINK_BROKEN
:
3264 removeFileId(nFileId
);
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()
3284 // ----------------------------------------------------------------------------
3286 uno::Sequence
< uno::Any
> SAL_CALL
ScChart2DataSequence::getData()
3287 throw ( uno::RuntimeException
)
3291 throw uno::RuntimeException();
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
)
3306 *pArr
<<= itr
->mfValue
;
3308 *pArr
<<= itr
->maString
;
3311 return m_aMixedDataCache
;
3314 // XNumericalDataSequence --------------------------------------------------
3316 uno::Sequence
< double > SAL_CALL
ScChart2DataSequence::getNumericalData()
3317 throw ( uno::RuntimeException
)
3321 throw uno::RuntimeException();
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
;
3338 // XTextualDataSequence --------------------------------------------------
3340 uno::Sequence
< rtl::OUString
> SAL_CALL
ScChart2DataSequence::getTextualData( ) throw (uno::RuntimeException
)
3344 throw uno::RuntimeException();
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
;
3358 ::rtl::OUString SAL_CALL
ScChart2DataSequence::getSourceRangeRepresentation()
3359 throw ( uno::RuntimeException
)
3363 DBG_ASSERT( m_pDocument
, "No Document -> no SourceRangeRepresentation" );
3364 if (m_pDocument
&& m_pTokens
.get())
3365 lcl_convertTokensToString(aStr
, *m_pTokens
, m_pDocument
);
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>
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
)
3388 bool bExternal
= ScRefTokenHelper::isExternalRef(pToken
);
3389 ScRefTokenHelper::getRangeFromToken(r
, pToken
, bExternal
);
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
; }
3403 * This function object is used to generate label strings from a list of
3406 class GenerateLabelStrings
: public unary_function
<ScSharedTokenRef
, void>
3409 GenerateLabelStrings(sal_Int32 nSize
, chart2::data::LabelOrigin eOrigin
, bool bColumn
) :
3410 mpLabels(new Sequence
<OUString
>(nSize
)),
3413 mbColumn(bColumn
) {}
3415 GenerateLabelStrings(const GenerateLabelStrings
& r
) :
3416 mpLabels(r
.mpLabels
),
3417 meOrigin(r
.meOrigin
),
3419 mbColumn(r
.mbColumn
) {}
3421 void operator() (const ScSharedTokenRef
& pToken
)
3423 bool bExternal
= ScRefTokenHelper::isExternalRef(pToken
);
3425 ScRefTokenHelper::getRangeFromToken(aRange
, pToken
, bExternal
);
3426 OUString
* pArr
= mpLabels
->getArray();
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
);
3435 ScAddress
aPos( nCol
, 0, 0 );
3437 aPos
.Format( aColStr
, SCA_VALID_COL
, NULL
);
3439 pArr
[mnCount
] = aString
;
3441 else //only indices for categories
3442 pArr
[mnCount
] = String::CreateFromInt32( mnCount
+1 );
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
);
3454 aString
+= String::CreateFromInt32( nRow
+1 );
3455 pArr
[mnCount
] = aString
;
3457 else //only indices for categories
3458 pArr
[mnCount
] = String::CreateFromInt32( mnCount
+1 );
3464 Sequence
<OUString
> getLabels() const { return *mpLabels
; }
3467 GenerateLabelStrings(); // disabled
3469 shared_ptr
< Sequence
<OUString
> > mpLabels
;
3470 chart2::data::LabelOrigin meOrigin
;
3477 uno::Sequence
< ::rtl::OUString
> SAL_CALL
ScChart2DataSequence::generateLabel(chart2::data::LabelOrigin eOrigin
)
3478 throw (uno::RuntimeException
)
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
))
3500 if (eOrigin
== chart2::data::LabelOrigin_SHORT_SIDE
)
3505 else if (nCols
> nRows
)
3507 if (eOrigin
== chart2::data::LabelOrigin_SHORT_SIDE
)
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();
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;
3534 if ( !m_pDocument
|| !m_pTokens
.get())
3537 sal_Int32 nCount
= 0;
3538 bool bFound
= false;
3541 uno::Reference
<sheet::XSpreadsheetDocument
> xSpreadDoc( lcl_GetSpreadSheetDocument( m_pDocument
));
3542 if (!xSpreadDoc
.is())
3545 uno::Reference
<container::XIndexAccess
> xIndex( xSpreadDoc
->getSheets(), uno::UNO_QUERY
);
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
);
3575 xProp
->getPropertyValue(
3576 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NumberFormat"))) >>= nResult
;
3581 else if( nCount
== nIndex
)
3583 uno::Reference
< beans::XPropertySet
> xProp(
3584 xSheet
->getCellByPosition(nCol
, nRow
), uno::UNO_QUERY
);
3586 xProp
->getPropertyValue(
3587 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NumberFormat"))) >>= nResult
;
3600 // XCloneable ================================================================
3602 uno::Reference
< util::XCloneable
> SAL_CALL
ScChart2DataSequence::createClone()
3603 throw (uno::RuntimeException
)
3607 auto_ptr
< vector
<ScSharedTokenRef
> > pTokensNew
;
3608 if (m_pTokens
.get())
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
));
3623 Reference
< util::XCloneable
> xClone(p
.release());
3628 // XModifyBroadcaster ========================================================
3630 void SAL_CALL
ScChart2DataSequence::addModifyListener( const uno::Reference
< util::XModifyListener
>& aListener
)
3631 throw (uno::RuntimeException
)
3633 // like ScCellRangesBase::addModifyListener
3635 if (!m_pTokens
.get() || m_pTokens
->empty())
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));
3654 ScChartListenerCollection
* pCLC
= m_pDocument
->GetChartListenerCollection();
3655 vector
<ScSharedTokenRef
>::const_iterator itr
= m_pTokens
->begin(), itrEnd
= m_pTokens
->end();
3656 for (; itr
!= itrEnd
; ++itr
)
3659 if (!ScRefTokenHelper::getRangeFromToken(aRange
, *itr
))
3662 m_pDocument
->StartListeningArea( aRange
, m_pValueListener
);
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
3678 if (!m_pTokens
.get() || m_pTokens
->empty())
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();
3700 pCLC
->EndListeningHiddenRange(m_pHiddenListener
.get());
3703 release(); // release the ref for the listeners
3710 release(); // might delete this object
3713 // DataSequence XPropertySet -------------------------------------------------
3715 uno::Reference
< beans::XPropertySetInfo
> SAL_CALL
3716 ScChart2DataSequence::getPropertySetInfo() throw( uno::RuntimeException
)
3719 static uno::Reference
<beans::XPropertySetInfo
> aRef
=
3720 new SfxItemPropertySetInfo( m_aPropSet
.getPropertyMap() );
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
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
)
3757 if ( rPropertyName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE
)))
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(...).
3766 aRet
<<= m_aHiddenValues
;
3769 throw beans::UnknownPropertyException();
3770 // TODO: support optional properties
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
;
3829 // sal_Int64 SAL_CALL ScChart2DataSequence::getSomething(
3830 // const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException)
3832 // if ( rId.getLength() == 16 &&
3833 // 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
3834 // rId.getConstArray(), 16 ) )
3836 // return (sal_Int64)this;
3842 // const uno::Sequence<sal_Int8>& ScChart2DataSequence::getUnoTunnelId()
3844 // static uno::Sequence<sal_Int8> * pSeq = 0;
3847 // osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
3850 // static uno::Sequence< sal_Int8 > aSeq( 16 );
3851 // rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
3859 // ScChart2DataSequence* ScChart2DataSequence::getImplementation( const uno::Reference<uno::XInterface> xObj )
3861 // ScChart2DataSequence* pRet = NULL;
3862 // uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY );
3864 // pRet = (ScChart2DataSequence*) xUT->getSomething( getUnoTunnelId() );
3868 #if USE_CHART2_EMPTYDATASEQUENCE
3869 // DataSequence ==============================================================
3871 ScChart2EmptyDataSequence::ScChart2EmptyDataSequence( ScDocument
* pDoc
,
3872 const uno::Reference
< chart2::data::XDataProvider
>& xDP
,
3873 const ScRangeListRef
& rRangeList
,
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
)
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
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()
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
)
3915 uno::Sequence
< uno::Any
> SAL_CALL
ScChart2EmptyDataSequence::getData()
3916 throw ( uno::RuntimeException
)
3920 throw uno::RuntimeException();
3921 return uno::Sequence
< uno::Any
>();
3924 // XTextualDataSequence --------------------------------------------------
3926 uno::Sequence
< rtl::OUString
> SAL_CALL
ScChart2EmptyDataSequence::getTextualData( ) throw (uno::RuntimeException
)
3930 throw uno::RuntimeException();
3932 sal_Int32 nCount
= 0;
3935 DBG_ASSERT(m_xRanges
->Count() == 1, "not handled count of ranges");
3937 for ( p
= m_xRanges
->First(); p
; p
= m_xRanges
->Next())
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();
3946 for ( p
= m_xRanges
->First(); p
; p
= m_xRanges
->Next())
3950 for (SCCOL nCol
= p
->aStart
.Col(); nCol
<= p
->aEnd
.Col(); ++nCol
)
3952 String aString
= ScGlobal::GetRscString(STR_COLUMN
);
3954 ScAddress
aPos( nCol
, 0, 0 );
3956 aPos
.Format( aColStr
, SCA_VALID_COL
, NULL
);
3958 pArr
[nCount
] = aString
;
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 );
3972 ::rtl::OUString SAL_CALL
ScChart2EmptyDataSequence::getSourceRangeRepresentation()
3973 throw ( uno::RuntimeException
)
3977 DBG_ASSERT( m_pDocument
, "No Document -> no SourceRangeRepresentation" );
3979 m_xRanges
->Format( aStr
, SCR_ABS_3D
, m_pDocument
, m_pDocument
->GetAddressConvention() );
3983 uno::Sequence
< ::rtl::OUString
> SAL_CALL
ScChart2EmptyDataSequence::generateLabel(chart2::data::LabelOrigin
/*nOrigin*/)
3984 throw (uno::RuntimeException
)
3987 uno::Sequence
< ::rtl::OUString
> aRet
;
3991 ::sal_Int32 SAL_CALL
ScChart2EmptyDataSequence::getNumberFormatKeyByIndex( ::sal_Int32
/*nIndex*/ )
3992 throw (lang::IndexOutOfBoundsException
,
3993 uno::RuntimeException
)
3995 sal_Int32 nResult
= 0;
4004 // XCloneable ================================================================
4006 uno::Reference
< util::XCloneable
> SAL_CALL
ScChart2EmptyDataSequence::createClone()
4007 throw (uno::RuntimeException
)
4010 if (m_xDataProvider
.is())
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
);
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
));
4024 return uno::Reference
< util::XCloneable
>();
4027 // XModifyBroadcaster ========================================================
4029 void SAL_CALL
ScChart2EmptyDataSequence::addModifyListener( const uno::Reference
< util::XModifyListener
>& /*aListener*/ )
4030 throw (uno::RuntimeException
)
4035 void SAL_CALL
ScChart2EmptyDataSequence::removeModifyListener( const uno::Reference
< util::XModifyListener
>& /*aListener*/ )
4036 throw (uno::RuntimeException
)
4041 // DataSequence XPropertySet -------------------------------------------------
4043 uno::Reference
< beans::XPropertySetInfo
> SAL_CALL
4044 ScChart2EmptyDataSequence::getPropertySetInfo() throw( uno::RuntimeException
)
4047 static uno::Reference
<beans::XPropertySetInfo
> aRef
=
4048 new SfxItemPropertySetInfo( m_aPropSet
.getPropertyMap() );
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();
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
)
4082 if ( rPropertyName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE
)))
4084 else if ( rPropertyName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS
)))
4085 aRet
<<= m_bIncludeHiddenCells
;
4087 throw beans::UnknownPropertyException();
4088 // TODO: support optional properties
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" );
4142 // sal_Int64 SAL_CALL ScChart2EmptyDataSequence::getSomething(
4143 // const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException)
4145 // if ( rId.getLength() == 16 &&
4146 // 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
4147 // rId.getConstArray(), 16 ) )
4149 // return (sal_Int64)this;
4155 // const uno::Sequence<sal_Int8>& ScChart2EmptyDataSequence::getUnoTunnelId()
4157 // static uno::Sequence<sal_Int8> * pSeq = 0;
4160 // osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
4163 // static uno::Sequence< sal_Int8 > aSeq( 16 );
4164 // rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
4172 // ScChart2DataSequence* ScChart2EmptyDataSequence::getImplementation( const uno::Reference<uno::XInterface> xObj )
4174 // ScChart2DataSequence* pRet = NULL;
4175 // uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY );
4177 // pRet = (ScChart2EmptyDataSequence*) xUT->getSomething( getUnoTunnelId() );