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