xref: /trunk/main/sc/source/ui/unoobj/chart2uno.cxx (revision 86e1cf34)
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__anon5c0df8530111::lcl_appendTableNumber117     lcl_appendTableNumber( ::rtl::OUStringBuffer & rBuffer ) :
118             m_rBuffer( rBuffer )
119     {}
operator ()__anon5c0df8530111::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 ()__anon5c0df8530111::__anon5c0df8530211::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__anon5c0df8530111::TokenTable174     void init( SCCOL nColCount, SCROW nRowCount )
175     {
176         mnColCount = nColCount;
177         mnRowCount = nRowCount;
178         maTokens.reserve(mnColCount*mnRowCount);
179     }
clear__anon5c0df8530111::TokenTable180     void clear()
181     {
182         for_each(maTokens.begin(), maTokens.end(), DeleteInstance());
183     }
184 
push_back__anon5c0df8530111::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__anon5c0df8530111::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     throw (uno::RuntimeException)
1025 {
1026     ScUnoGuard aGuard;
1027     if( ! m_pDocument )
1028         return false;
1029 
1030     rtl::OUString aRangeRepresentation;
1031     for(sal_Int32 i = 0; i < aArguments.getLength(); ++i)
1032     {
1033         rtl::OUString sName(aArguments[i].Name);
1034         if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CellRangeRepresentation")))
1035         {
1036             aArguments[i].Value >>= aRangeRepresentation;
1037         }
1038     }
1039 
1040     vector<ScSharedTokenRef> aTokens;
1041     ScRefTokenHelper::compileRangeRepresentation(aTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar());
1042     return !aTokens.empty();
1043 }
1044 
1045 namespace
1046 {
1047 
lcl_createLabeledDataSequenceFromTokens(auto_ptr<vector<ScSharedTokenRef>> pValueTokens,auto_ptr<vector<ScSharedTokenRef>> pLabelTokens,ScDocument * pDoc,const Reference<chart2::data::XDataProvider> & xDP,bool bIncludeHiddenCells)1048 Reference< chart2::data::XLabeledDataSequence > lcl_createLabeledDataSequenceFromTokens(
1049     auto_ptr< vector< ScSharedTokenRef > > pValueTokens, auto_ptr< vector< ScSharedTokenRef > > pLabelTokens,
1050     ScDocument* pDoc, const Reference< chart2::data::XDataProvider >& xDP, bool bIncludeHiddenCells )
1051 {
1052     Reference< chart2::data::XLabeledDataSequence >  xResult;
1053     bool bHasValues = pValueTokens.get() && !pValueTokens->empty();
1054     bool bHasLabel = pLabelTokens.get() && !pLabelTokens->empty();
1055     if( bHasValues || bHasLabel )
1056     {
1057         try
1058         {
1059             Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
1060             if ( xContext.is() )
1061             {
1062                 xResult.set( xContext->getServiceManager()->createInstanceWithContext(
1063                     ::rtl::OUString::createFromAscii( "com.sun.star.chart2.data.LabeledDataSequence" ),
1064                         xContext ), uno::UNO_QUERY_THROW );
1065             }
1066             if ( bHasValues )
1067             {
1068                 Reference< chart2::data::XDataSequence > xSeq( new ScChart2DataSequence( pDoc, xDP, pValueTokens.release(), bIncludeHiddenCells ) );
1069                 xResult->setValues( xSeq );
1070             }
1071             if ( bHasLabel )
1072             {
1073                 Reference< chart2::data::XDataSequence > xLabelSeq( new ScChart2DataSequence( pDoc, xDP, pLabelTokens.release(), bIncludeHiddenCells ) );
1074                 xResult->setLabel( xLabelSeq );
1075             }
1076         }
1077         catch( const uno::Exception& )
1078         {
1079         }
1080     }
1081     return xResult;
1082 }
1083 
1084 //----------------------------------------------------
1085 /**
1086  * Check the current list of reference tokens, and add the upper left
1087  * corner of the minimum range that encloses all ranges if certain
1088  * conditions are met.
1089  *
1090  * @param rRefTokens list of reference tokens
1091  *
1092  * @return true if the corner was added, false otherwise.
1093  */
lcl_addUpperLeftCornerIfMissing(vector<ScSharedTokenRef> & rRefTokens,SCROW nCornerRowCount=1,SCCOL nCornerColumnCount=1)1094 bool lcl_addUpperLeftCornerIfMissing(vector<ScSharedTokenRef>& rRefTokens,
1095             SCROW nCornerRowCount=1, SCCOL nCornerColumnCount=1)
1096 {
1097     using ::std::max;
1098     using ::std::min;
1099 
1100     if (rRefTokens.empty())
1101         return false;
1102 
1103     SCCOL nMinCol = MAXCOLCOUNT;
1104     SCROW nMinRow = MAXROWCOUNT;
1105     SCCOL nMaxCol = 0;
1106     SCROW nMaxRow = 0;
1107     SCTAB nTab    = 0;
1108 
1109     sal_uInt16 nFileId = 0;
1110     String aExtTabName;
1111     bool bExternal = false;
1112 
1113     vector<ScSharedTokenRef>::const_iterator itr = rRefTokens.begin(), itrEnd = rRefTokens.end();
1114 
1115     // Get the first ref token.
1116     ScSharedTokenRef pToken = *itr;
1117     switch (pToken->GetType())
1118     {
1119         case svSingleRef:
1120         {
1121             const ScSingleRefData& rData = pToken->GetSingleRef();
1122             nMinCol = rData.nCol;
1123             nMinRow = rData.nRow;
1124             nMaxCol = rData.nCol;
1125             nMaxRow = rData.nRow;
1126             nTab = rData.nTab;
1127         }
1128         break;
1129         case svDoubleRef:
1130         {
1131             const ScComplexRefData& rData = pToken->GetDoubleRef();
1132             nMinCol = min(rData.Ref1.nCol, rData.Ref2.nCol);
1133             nMinRow = min(rData.Ref1.nRow, rData.Ref2.nRow);
1134             nMaxCol = max(rData.Ref1.nCol, rData.Ref2.nCol);
1135             nMaxRow = max(rData.Ref1.nRow, rData.Ref2.nRow);
1136             nTab = rData.Ref1.nTab;
1137         }
1138         break;
1139         case svExternalSingleRef:
1140         {
1141             const ScSingleRefData& rData = pToken->GetSingleRef();
1142             nMinCol = rData.nCol;
1143             nMinRow = rData.nRow;
1144             nMaxCol = rData.nCol;
1145             nMaxRow = rData.nRow;
1146             nTab = rData.nTab;
1147             nFileId = pToken->GetIndex();
1148             aExtTabName = pToken->GetString();
1149             bExternal = true;
1150         }
1151         break;
1152         case svExternalDoubleRef:
1153         {
1154             const ScComplexRefData& rData = pToken->GetDoubleRef();
1155             nMinCol = min(rData.Ref1.nCol, rData.Ref2.nCol);
1156             nMinRow = min(rData.Ref1.nRow, rData.Ref2.nRow);
1157             nMaxCol = max(rData.Ref1.nCol, rData.Ref2.nCol);
1158             nMaxRow = max(rData.Ref1.nRow, rData.Ref2.nRow);
1159             nTab = rData.Ref1.nTab;
1160             nFileId = pToken->GetIndex();
1161             aExtTabName = pToken->GetString();
1162             bExternal = true;
1163         }
1164         break;
1165         default:
1166             ;
1167     }
1168 
1169     // Determine the minimum range enclosing all data ranges.  Also make sure
1170     // that they are all on the same table.
1171 
1172     for (++itr; itr != itrEnd; ++itr)
1173     {
1174         pToken = *itr;
1175         switch (pToken->GetType())
1176         {
1177             case svSingleRef:
1178             {
1179                 const ScSingleRefData& rData = pToken->GetSingleRef();
1180 
1181                 nMinCol = min(nMinCol, rData.nCol);
1182                 nMinRow = min(nMinRow, rData.nRow);
1183                 nMaxCol = max(nMaxCol, rData.nCol);
1184                 nMaxRow = max(nMaxRow, rData.nRow);
1185                 if (nTab != rData.nTab || bExternal)
1186                     return false;
1187             }
1188             break;
1189             case svDoubleRef:
1190             {
1191                 const ScComplexRefData& rData = pToken->GetDoubleRef();
1192 
1193                 nMinCol = min(nMinCol, rData.Ref1.nCol);
1194                 nMinCol = min(nMinCol, rData.Ref2.nCol);
1195                 nMinRow = min(nMinRow, rData.Ref1.nRow);
1196                 nMinRow = min(nMinRow, rData.Ref2.nRow);
1197 
1198                 nMaxCol = max(nMaxCol, rData.Ref1.nCol);
1199                 nMaxCol = max(nMaxCol, rData.Ref2.nCol);
1200                 nMaxRow = max(nMaxRow, rData.Ref1.nRow);
1201                 nMaxRow = max(nMaxRow, rData.Ref2.nRow);
1202 
1203                 if (nTab != rData.Ref1.nTab || bExternal)
1204                     return false;
1205             }
1206             break;
1207             case svExternalSingleRef:
1208             {
1209                 if (!bExternal)
1210                     return false;
1211 
1212                 if (nFileId != pToken->GetIndex() || aExtTabName != pToken->GetString())
1213                     return false;
1214 
1215                 const ScSingleRefData& rData = pToken->GetSingleRef();
1216 
1217                 nMinCol = min(nMinCol, rData.nCol);
1218                 nMinRow = min(nMinRow, rData.nRow);
1219                 nMaxCol = max(nMaxCol, rData.nCol);
1220                 nMaxRow = max(nMaxRow, rData.nRow);
1221             }
1222             break;
1223             case svExternalDoubleRef:
1224             {
1225                 if (!bExternal)
1226                     return false;
1227 
1228                 if (nFileId != pToken->GetIndex() || aExtTabName != pToken->GetString())
1229                     return false;
1230 
1231                 const ScComplexRefData& rData = pToken->GetDoubleRef();
1232 
1233                 nMinCol = min(nMinCol, rData.Ref1.nCol);
1234                 nMinCol = min(nMinCol, rData.Ref2.nCol);
1235                 nMinRow = min(nMinRow, rData.Ref1.nRow);
1236                 nMinRow = min(nMinRow, rData.Ref2.nRow);
1237 
1238                 nMaxCol = max(nMaxCol, rData.Ref1.nCol);
1239                 nMaxCol = max(nMaxCol, rData.Ref2.nCol);
1240                 nMaxRow = max(nMaxRow, rData.Ref1.nRow);
1241                 nMaxRow = max(nMaxRow, rData.Ref2.nRow);
1242             }
1243             break;
1244             default:
1245                 ;
1246         }
1247     }
1248 
1249     if (nMinRow >= nMaxRow || nMinCol >= nMaxCol ||
1250         nMinRow >= MAXROWCOUNT || nMinCol >= MAXCOLCOUNT ||
1251         nMaxRow >= MAXROWCOUNT || nMaxCol >= MAXCOLCOUNT)
1252     {
1253         // Invalid range.  Bail out.
1254         return false;
1255     }
1256 
1257     // Check if the following conditions are met:
1258     //
1259     // 1) The upper-left corner cell is not included.
1260     // 2) The three adjacent cells of that corner cell are included.
1261 
1262     bool bRight = false, bBottom = false, bDiagonal = false;
1263     for (itr = rRefTokens.begin(); itr != itrEnd; ++itr)
1264     {
1265         pToken = *itr;
1266         switch (pToken->GetType())
1267         {
1268             case svSingleRef:
1269             case svExternalSingleRef:
1270             {
1271                 const ScSingleRefData& rData = pToken->GetSingleRef();
1272                 if (rData.nCol == nMinCol && rData.nRow == nMinRow)
1273                     // The corner cell is contained.
1274                     return false;
1275 
1276                 if (rData.nCol == nMinCol+nCornerColumnCount && rData.nRow == nMinRow)
1277                     bRight = true;
1278 
1279                 if (rData.nCol == nMinCol && rData.nRow == nMinRow+nCornerRowCount)
1280                     bBottom = true;
1281 
1282                 if (rData.nCol == nMinCol+nCornerColumnCount && rData.nRow == nMinRow+nCornerRowCount)
1283                     bDiagonal = true;
1284             }
1285             break;
1286             case svDoubleRef:
1287             case svExternalDoubleRef:
1288             {
1289                 const ScComplexRefData& rData = pToken->GetDoubleRef();
1290                 const ScSingleRefData& r1 = rData.Ref1;
1291                 const ScSingleRefData& r2 = rData.Ref2;
1292                 if (r1.nCol <= nMinCol && nMinCol <= r2.nCol &&
1293                     r1.nRow <= nMinRow && nMinRow <= r2.nRow)
1294                     // The corner cell is contained.
1295                     return false;
1296 
1297                 if (r1.nCol <= nMinCol+nCornerColumnCount && nMinCol+nCornerColumnCount <= r2.nCol &&
1298                     r1.nRow <= nMinRow && nMinRow <= r2.nRow)
1299                     bRight = true;
1300 
1301                 if (r1.nCol <= nMinCol && nMinCol <= r2.nCol &&
1302                     r1.nRow <= nMinRow+nCornerRowCount && nMinRow+nCornerRowCount <= r2.nRow)
1303                     bBottom = true;
1304 
1305                 if (r1.nCol <= nMinCol+nCornerColumnCount && nMinCol+nCornerColumnCount <= r2.nCol &&
1306                     r1.nRow <= nMinRow+nCornerRowCount && nMinRow+nCornerRowCount <= r2.nRow)
1307                     bDiagonal = true;
1308             }
1309             break;
1310             default:
1311                 ;
1312         }
1313     }
1314 
1315     if (!bRight || !bBottom || !bDiagonal)
1316         // Not all the adjacent cells are included.  Bail out.
1317         return false;
1318 
1319 #if 0 // Do we really need to do this ???
1320     if (rRefTokens.size() == 2)
1321     {
1322         // Make a simple rectangular range if possible.
1323         ScRange aRightPart(ScAddress(nMinCol+1, nMinRow,   nTab),  ScAddress(nMaxCol, nMaxRow, nTab));
1324         ScRange aBottomPart(ScAddress(nMinCol,  nMinRow+1, nTab),  ScAddress(nMaxCol, nMaxRow, nTab));
1325         vector<ScRange> aRanges;
1326         aRanges.reserve(2);
1327         aRanges.push_back(aRightPart);
1328         aRanges.push_back(aBottomPart);
1329         if (lcl_isRangeContained(rRefTokens, aRanges))
1330         {
1331             // Consolidate them into a single rectangle.
1332             ScComplexRefData aData;
1333             aData.InitFlags();
1334             aData.Ref1.SetFlag3D(true);
1335             aData.Ref1.SetColRel(false);
1336             aData.Ref1.SetRowRel(false);
1337             aData.Ref1.SetTabRel(false);
1338             aData.Ref2.SetColRel(false);
1339             aData.Ref2.SetRowRel(false);
1340             aData.Ref2.SetTabRel(false);
1341             aData.Ref1.nCol = nMinCol;
1342             aData.Ref1.nRow = nMinRow;
1343             aData.Ref1.nTab = nTab;
1344             aData.Ref2.nCol = nMaxCol;
1345             aData.Ref2.nRow = nMaxRow;
1346             aData.Ref2.nTab = nTab;
1347             vector<ScSharedTokenRef> aNewTokens;
1348             aNewTokens.reserve(1);
1349             if (bExternal)
1350             {
1351                 ScSharedTokenRef p(
1352                     new ScExternalDoubleRefToken(nFileId, aExtTabName, aData));
1353                 aNewTokens.push_back(p);
1354             }
1355             else
1356             {
1357                 ScSharedTokenRef p(new ScDoubleRefToken(aData));
1358                 aNewTokens.push_back(p);
1359             }
1360             rRefTokens.swap(aNewTokens);
1361             return true;
1362         }
1363     }
1364 #endif
1365 
1366     ScSingleRefData aData;
1367     aData.InitFlags();
1368     aData.SetFlag3D(true);
1369     aData.SetColRel(false);
1370     aData.SetRowRel(false);
1371     aData.SetTabRel(false);
1372     aData.nCol = nMinCol;
1373     aData.nRow = nMinRow;
1374     aData.nTab = nTab;
1375 
1376     if( nCornerRowCount==1 && nCornerColumnCount==1 )
1377     {
1378         if (bExternal)
1379         {
1380             ScSharedTokenRef pCorner(
1381                 new ScExternalSingleRefToken(nFileId, aExtTabName, aData));
1382             ScRefTokenHelper::join(rRefTokens, pCorner);
1383         }
1384         else
1385         {
1386             ScSharedTokenRef pCorner(new ScSingleRefToken(aData));
1387             ScRefTokenHelper::join(rRefTokens, pCorner);
1388         }
1389     }
1390     else
1391     {
1392         ScSingleRefData aDataEnd(aData);
1393         aDataEnd.nCol += (nCornerColumnCount-1);
1394         aDataEnd.nRow += (nCornerRowCount-1);
1395         ScComplexRefData r;
1396         r.Ref1=aData;
1397         r.Ref2=aDataEnd;
1398         if (bExternal)
1399         {
1400             ScSharedTokenRef pCorner(
1401                 new ScExternalDoubleRefToken(nFileId, aExtTabName, r));
1402             ScRefTokenHelper::join(rRefTokens, pCorner);
1403         }
1404         else
1405         {
1406             ScSharedTokenRef pCorner(new ScDoubleRefToken(r));
1407             ScRefTokenHelper::join(rRefTokens, pCorner);
1408         }
1409     }
1410 
1411     return true;
1412 }
1413 
1414 }
1415 
1416 uno::Reference< chart2::data::XDataSource> SAL_CALL
createDataSource(const uno::Sequence<beans::PropertyValue> & aArguments)1417 ScChart2DataProvider::createDataSource(
1418     const uno::Sequence< beans::PropertyValue >& aArguments )
1419     throw( lang::IllegalArgumentException, uno::RuntimeException)
1420 {
1421     ScUnoGuard aGuard;
1422     if ( ! m_pDocument )
1423         throw uno::RuntimeException();
1424 
1425     uno::Reference< chart2::data::XDataSource> xResult;
1426     bool bLabel = true;
1427     bool bCategories = false;
1428     bool bOrientCol = true;
1429     ::rtl::OUString aRangeRepresentation;
1430     uno::Sequence< sal_Int32 > aSequenceMapping;
1431     for(sal_Int32 i = 0; i < aArguments.getLength(); ++i)
1432     {
1433         rtl::OUString sName(aArguments[i].Name);
1434         if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataRowSource")))
1435         {
1436             chart::ChartDataRowSource eSource = chart::ChartDataRowSource_COLUMNS;
1437             if( ! (aArguments[i].Value >>= eSource))
1438             {
1439                 sal_Int32 nSource(0);
1440                 if( aArguments[i].Value >>= nSource )
1441                     eSource = (static_cast< chart::ChartDataRowSource >( nSource ));
1442             }
1443             bOrientCol = (eSource == chart::ChartDataRowSource_COLUMNS);
1444         }
1445         else if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FirstCellAsLabel")))
1446         {
1447             bLabel = ::cppu::any2bool(aArguments[i].Value);
1448         }
1449         else if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HasCategories")))
1450         {
1451             bCategories = ::cppu::any2bool(aArguments[i].Value);
1452         }
1453         else if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CellRangeRepresentation")))
1454         {
1455             aArguments[i].Value >>= aRangeRepresentation;
1456         }
1457         else if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("SequenceMapping")))
1458         {
1459             aArguments[i].Value >>= aSequenceMapping;
1460         }
1461     }
1462 
1463     vector<ScSharedTokenRef> aRefTokens;
1464     ScRefTokenHelper::compileRangeRepresentation(aRefTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar());
1465     if (aRefTokens.empty())
1466         // Invalid range representation.  Bail out.
1467         throw lang::IllegalArgumentException();
1468 
1469     if (bLabel)
1470         lcl_addUpperLeftCornerIfMissing(aRefTokens); //#i90669#
1471 
1472     bool bColHeaders = (bOrientCol ? bLabel : bCategories );
1473     bool bRowHeaders = (bOrientCol ? bCategories : bLabel );
1474 
1475     Chart2Positioner aChPositioner(m_pDocument, aRefTokens);
1476     aChPositioner.setHeaders(bColHeaders, bRowHeaders);
1477 
1478     const Chart2PositionMap* pChartMap = aChPositioner.getPositionMap();
1479     if (!pChartMap)
1480         // No chart position map instance.  Bail out.
1481         return xResult;
1482 
1483     ScChart2DataSource* pDS = NULL;
1484     ::std::list< Reference< chart2::data::XLabeledDataSequence > > aSeqs;
1485 
1486     // Fill Categories
1487     if( bCategories )
1488     {
1489         auto_ptr< vector<ScSharedTokenRef> > pValueTokens(NULL);
1490         if (bOrientCol)
1491             pValueTokens.reset(pChartMap->getAllRowHeaderRanges());
1492         else
1493             pValueTokens.reset(pChartMap->getAllColHeaderRanges());
1494 
1495         auto_ptr< vector<ScSharedTokenRef> > pLabelTokens(NULL);
1496             pLabelTokens.reset(pChartMap->getLeftUpperCornerRanges());
1497 
1498         Reference< chart2::data::XLabeledDataSequence > xCategories = lcl_createLabeledDataSequenceFromTokens(
1499             pValueTokens, pLabelTokens, m_pDocument, this, m_bIncludeHiddenCells ); //ownership of pointers is transferred!
1500         if ( xCategories.is() )
1501         {
1502             aSeqs.push_back( xCategories );
1503         }
1504     }
1505 
1506     // Fill Serieses (values and label)
1507     sal_Int32 nCount = bOrientCol ? pChartMap->getDataColCount() : pChartMap->getDataRowCount();
1508     for (sal_Int32 i = 0; i < nCount; ++i)
1509     {
1510         auto_ptr< vector<ScSharedTokenRef> > pValueTokens(NULL);
1511         auto_ptr< vector<ScSharedTokenRef> > pLabelTokens(NULL);
1512         if (bOrientCol)
1513         {
1514             pValueTokens.reset(pChartMap->getDataColRanges(static_cast<SCCOL>(i)));
1515             pLabelTokens.reset(pChartMap->getColHeaderRanges(static_cast<SCCOL>(i)));
1516         }
1517         else
1518         {
1519             pValueTokens.reset(pChartMap->getDataRowRanges(static_cast<SCROW>(i)));
1520             pLabelTokens.reset(pChartMap->getRowHeaderRanges(static_cast<SCROW>(i)));
1521         }
1522         Reference< chart2::data::XLabeledDataSequence > xChartSeries = lcl_createLabeledDataSequenceFromTokens(
1523             pValueTokens, pLabelTokens, m_pDocument, this, m_bIncludeHiddenCells ); //ownership of pointers is transferred!
1524         if ( xChartSeries.is() )
1525         {
1526             aSeqs.push_back( xChartSeries );
1527         }
1528     }
1529 
1530     pDS = new ScChart2DataSource(m_pDocument);
1531     ::std::list< Reference< chart2::data::XLabeledDataSequence > >::iterator aItr( aSeqs.begin() );
1532     ::std::list< Reference< chart2::data::XLabeledDataSequence > >::iterator aEndItr( aSeqs.end() );
1533 
1534     //reorder labeled sequences according to aSequenceMapping
1535     ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aSeqVector;
1536     while(aItr != aEndItr)
1537     {
1538         aSeqVector.push_back(*aItr);
1539         ++aItr;
1540     }
1541 
1542     ::std::map< sal_Int32, Reference< chart2::data::XLabeledDataSequence > > aSequenceMap;
1543     for( sal_Int32 nNewIndex = 0; nNewIndex < aSequenceMapping.getLength(); nNewIndex++ )
1544     {
1545         // note: assuming that the values in the sequence mapping are always non-negative
1546         ::std::vector< Reference< chart2::data::XLabeledDataSequence > >::size_type nOldIndex( static_cast< sal_uInt32 >( aSequenceMapping[nNewIndex] ) );
1547         if( nOldIndex < aSeqVector.size() )
1548         {
1549             pDS->AddLabeledSequence( aSeqVector[nOldIndex] );
1550             aSeqVector[nOldIndex] = 0;
1551         }
1552     }
1553 
1554     ::std::vector< Reference< chart2::data::XLabeledDataSequence > >::iterator aVectorItr( aSeqVector.begin() );
1555     ::std::vector< Reference< chart2::data::XLabeledDataSequence > >::iterator aVectorEndItr( aSeqVector.end() );
1556     while(aVectorItr != aVectorEndItr)
1557     {
1558         Reference< chart2::data::XLabeledDataSequence > xSeq( *aVectorItr );
1559         if ( xSeq.is() )
1560         {
1561             pDS->AddLabeledSequence( xSeq );
1562         }
1563         ++aVectorItr;
1564     }
1565 
1566     xResult.set( pDS );
1567     return xResult;
1568 }
1569 
1570 namespace
1571 {
1572 
1573 /**
1574  * Function object to create a list of table numbers from a token list.
1575  */
1576 class InsertTabNumber : public unary_function<ScSharedTokenRef, void>
1577 {
1578 public:
InsertTabNumber()1579     InsertTabNumber() :
1580         mpTabNumList(new list<SCTAB>())
1581     {
1582     }
1583 
InsertTabNumber(const InsertTabNumber & r)1584     InsertTabNumber(const InsertTabNumber& r) :
1585         mpTabNumList(r.mpTabNumList)
1586     {
1587     }
1588 
operator ()(const ScSharedTokenRef & pToken) const1589     void operator() (const ScSharedTokenRef& pToken) const
1590     {
1591         if (!ScRefTokenHelper::isRef(pToken))
1592             return;
1593 
1594         const ScSingleRefData& r = pToken->GetSingleRef();
1595         mpTabNumList->push_back(r.nTab);
1596     }
1597 
getList(list<SCTAB> & rList)1598     void getList(list<SCTAB>& rList)
1599     {
1600         mpTabNumList->swap(rList);
1601     }
1602 private:
1603     shared_ptr< list<SCTAB> > mpTabNumList;
1604 };
1605 
1606 class RangeAnalyzer
1607 {
1608 public:
1609     RangeAnalyzer();
1610     void initRangeAnalyzer( const vector<ScSharedTokenRef>& rTokens );
1611     void analyzeRange( sal_Int32& rnDataInRows, sal_Int32& rnDataInCols,
1612             bool& rbRowSourceAmbiguous ) const;
1613     bool inSameSingleRow( RangeAnalyzer& rOther );
1614     bool inSameSingleColumn( RangeAnalyzer& rOther );
getRowCount()1615     SCROW getRowCount() { return mnRowCount; }
getColumnCount()1616     SCCOL getColumnCount() { return mnColumnCount; }
1617 
1618 private:
1619     bool mbEmpty;
1620     bool mbAmbiguous;
1621     SCROW mnRowCount;
1622     SCCOL mnColumnCount;
1623 
1624     SCCOL mnStartColumn;
1625     SCROW mnStartRow;
1626 };
1627 
RangeAnalyzer()1628 RangeAnalyzer::RangeAnalyzer()
1629     : mbEmpty(true)
1630     , mbAmbiguous(false)
1631     , mnRowCount(0)
1632     , mnColumnCount(0)
1633     , mnStartColumn(-1)
1634     , mnStartRow(-1)
1635 {
1636 }
1637 
initRangeAnalyzer(const vector<ScSharedTokenRef> & rTokens)1638 void RangeAnalyzer::initRangeAnalyzer( const vector<ScSharedTokenRef>& rTokens )
1639 {
1640     mnRowCount=0;
1641     mnColumnCount=0;
1642     mnStartColumn = -1;
1643     mnStartRow = -1;
1644     mbAmbiguous=false;
1645     if( rTokens.empty() )
1646     {
1647         mbEmpty=true;
1648         return;
1649     }
1650     mbEmpty=false;
1651 
1652     vector<ScSharedTokenRef>::const_iterator itr = rTokens.begin(), itrEnd = rTokens.end();
1653     for (; itr != itrEnd ; ++itr)
1654     {
1655         ScSharedTokenRef aRefToken = *itr;
1656         StackVar eVar = aRefToken->GetType();
1657         if (eVar == svDoubleRef || eVar == svExternalDoubleRef)
1658         {
1659             const ScComplexRefData& r = aRefToken->GetDoubleRef();
1660             if (r.Ref1.nTab == r.Ref2.nTab)
1661             {
1662                 mnColumnCount = std::max<SCCOL>( mnColumnCount, static_cast<SCCOL>(abs(r.Ref2.nCol - r.Ref1.nCol)+1) );
1663                 mnRowCount = std::max<SCROW>( mnRowCount, static_cast<SCROW>(abs(r.Ref2.nRow - r.Ref1.nRow)+1) );
1664                 if( mnStartColumn == -1 )
1665                 {
1666                     mnStartColumn = r.Ref1.nCol;
1667                     mnStartRow = r.Ref1.nRow;
1668                 }
1669                 else
1670                 {
1671                     if( mnStartColumn != r.Ref1.nCol && mnStartRow != r.Ref1.nRow )
1672                         mbAmbiguous=true;
1673                 }
1674             }
1675             else
1676                 mbAmbiguous=true;
1677         }
1678         else if (eVar == svSingleRef || eVar == svExternalSingleRef)
1679         {
1680             const ScSingleRefData& r = aRefToken->GetSingleRef();
1681             mnColumnCount = std::max<SCCOL>( mnColumnCount, 1);
1682             mnRowCount = std::max<SCROW>( mnRowCount, 1);
1683             if( mnStartColumn == -1 )
1684             {
1685                 mnStartColumn = r.nCol;
1686                 mnStartRow = r.nRow;
1687             }
1688             else
1689             {
1690                 if( mnStartColumn != r.nCol && mnStartRow != r.nRow )
1691                     mbAmbiguous=true;
1692             }
1693         }
1694         else
1695             mbAmbiguous=true;
1696     }
1697 }
1698 
analyzeRange(sal_Int32 & rnDataInRows,sal_Int32 & rnDataInCols,bool & rbRowSourceAmbiguous) const1699 void RangeAnalyzer::analyzeRange( sal_Int32& rnDataInRows,
1700                                      sal_Int32& rnDataInCols,
1701                                      bool& rbRowSourceAmbiguous ) const
1702 {
1703     if(!mbEmpty && !mbAmbiguous)
1704     {
1705         if( mnRowCount==1 && mnColumnCount>1 )
1706             ++rnDataInRows;
1707         else if( mnColumnCount==1 && mnRowCount>1 )
1708             ++rnDataInCols;
1709         else if( mnRowCount>1 && mnColumnCount>1 )
1710             rbRowSourceAmbiguous = true;
1711     }
1712     else if( !mbEmpty )
1713         rbRowSourceAmbiguous = true;
1714 }
1715 
inSameSingleRow(RangeAnalyzer & rOther)1716 bool RangeAnalyzer::inSameSingleRow( RangeAnalyzer& rOther )
1717 {
1718     if( mnStartRow==rOther.mnStartRow &&
1719         mnRowCount==1 && rOther.mnRowCount==1 )
1720         return true;
1721     return false;
1722 }
1723 
inSameSingleColumn(RangeAnalyzer & rOther)1724 bool RangeAnalyzer::inSameSingleColumn( RangeAnalyzer& rOther )
1725 {
1726     if( mnStartColumn==rOther.mnStartColumn &&
1727         mnColumnCount==1 && rOther.mnColumnCount==1 )
1728         return true;
1729     return false;
1730 }
1731 
1732 } //end anonymous namespace
1733 
detectArguments(const uno::Reference<chart2::data::XDataSource> & xDataSource)1734 uno::Sequence< beans::PropertyValue > SAL_CALL ScChart2DataProvider::detectArguments(
1735     const uno::Reference< chart2::data::XDataSource >& xDataSource )
1736     throw (uno::RuntimeException)
1737 {
1738     ::std::vector< beans::PropertyValue > aResult;
1739     bool bRowSourceDetected = false;
1740     bool bFirstCellAsLabel = false;
1741     bool bHasCategories = false;
1742     ::rtl::OUString sRangeRep;
1743 
1744     bool bHasCategoriesLabels = false;
1745     vector<ScSharedTokenRef> aAllCategoriesValuesTokens;
1746     vector<ScSharedTokenRef> aAllSeriesLabelTokens;
1747 
1748     chart::ChartDataRowSource eRowSource = chart::ChartDataRowSource_COLUMNS;
1749 
1750     vector<ScSharedTokenRef> aAllTokens;
1751 
1752     // parse given data source and collect infos
1753     {
1754         ScUnoGuard aGuard;
1755         DBG_ASSERT( m_pDocument, "No Document -> no detectArguments" );
1756         if(!m_pDocument ||!xDataSource.is())
1757             return lcl_VectorToSequence( aResult );
1758 
1759         sal_Int32 nDataInRows = 0;
1760         sal_Int32 nDataInCols = 0;
1761         bool bRowSourceAmbiguous = false;
1762 
1763         Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( xDataSource->getDataSequences());
1764         const sal_Int32 nCount( aSequences.getLength());
1765         RangeAnalyzer aPrevLabel,aPrevValues;
1766         for( sal_Int32 nIdx=0; nIdx<nCount; ++nIdx )
1767         {
1768             Reference< chart2::data::XLabeledDataSequence > xLS(aSequences[nIdx]);
1769             if( xLS.is() )
1770             {
1771                 bool bThisIsCategories = false;
1772                 if(!bHasCategories)
1773                 {
1774                     Reference< beans::XPropertySet > xSeqProp( xLS->getValues(), uno::UNO_QUERY );
1775                     ::rtl::OUString aRole;
1776                     if( xSeqProp.is() && (xSeqProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Role"))) >>= aRole) &&
1777                         aRole.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("categories")) )
1778                         bThisIsCategories = bHasCategories = true;
1779                 }
1780 
1781                 RangeAnalyzer aLabel,aValues;
1782                 // label
1783                 Reference< chart2::data::XDataSequence > xLabel( xLS->getLabel());
1784                 if( xLabel.is())
1785                 {
1786                     bFirstCellAsLabel = true;
1787                     vector<ScSharedTokenRef> aTokens;
1788                     ScRefTokenHelper::compileRangeRepresentation( aTokens, xLabel->getSourceRangeRepresentation(), m_pDocument, m_pDocument->GetGrammar() );
1789                     aLabel.initRangeAnalyzer(aTokens);
1790                     vector<ScSharedTokenRef>::const_iterator itr = aTokens.begin(), itrEnd = aTokens.end();
1791                     for (; itr != itrEnd; ++itr)
1792                     {
1793                         ScRefTokenHelper::join(aAllTokens, *itr);
1794                         if(!bThisIsCategories)
1795                             ScRefTokenHelper::join(aAllSeriesLabelTokens, *itr);
1796                     }
1797                     if(bThisIsCategories)
1798                         bHasCategoriesLabels=true;
1799                 }
1800                 // values
1801                 Reference< chart2::data::XDataSequence > xValues( xLS->getValues());
1802                 if( xValues.is())
1803                 {
1804                     vector<ScSharedTokenRef> aTokens;
1805                     ScRefTokenHelper::compileRangeRepresentation( aTokens, xValues->getSourceRangeRepresentation(), m_pDocument, m_pDocument->GetGrammar() );
1806                     aValues.initRangeAnalyzer(aTokens);
1807                     vector<ScSharedTokenRef>::const_iterator itr = aTokens.begin(), itrEnd = aTokens.end();
1808                     for (; itr != itrEnd; ++itr)
1809                     {
1810                         ScRefTokenHelper::join(aAllTokens, *itr);
1811                         if(bThisIsCategories)
1812                             ScRefTokenHelper::join(aAllCategoriesValuesTokens, *itr);
1813                     }
1814                 }
1815                 //detect row source
1816                 if(!bThisIsCategories || nCount==1) //categories might span multiple rows *and* columns, so they should be used for detection only if nothing else is available
1817                 {
1818                     if (!bRowSourceAmbiguous)
1819                     {
1820                         aValues.analyzeRange(nDataInRows,nDataInCols,bRowSourceAmbiguous);
1821                         aLabel.analyzeRange(nDataInRows,nDataInCols,bRowSourceAmbiguous);
1822                         if (nDataInRows > 1 && nDataInCols > 1)
1823                             bRowSourceAmbiguous = true;
1824                         else if( !bRowSourceAmbiguous && !nDataInRows && !nDataInCols )
1825                         {
1826                             if( aValues.inSameSingleColumn( aLabel ) )
1827                                 nDataInCols++;
1828                             else if( aValues.inSameSingleRow( aLabel ) )
1829                                 nDataInRows++;
1830                             else
1831                             {
1832                                 //#i86188# also detect a single column split into rows correctly
1833                                 if( aValues.inSameSingleColumn( aPrevValues ) )
1834                                     nDataInRows++;
1835                                 else if( aValues.inSameSingleRow( aPrevValues ) )
1836                                     nDataInCols++;
1837                                 else if( aLabel.inSameSingleColumn( aPrevLabel ) )
1838                                     nDataInRows++;
1839                                 else if( aLabel.inSameSingleRow( aPrevLabel ) )
1840                                     nDataInCols++;
1841                             }
1842                         }
1843                     }
1844                 }
1845                 aPrevValues=aValues;
1846                 aPrevLabel=aLabel;
1847             }
1848         }
1849 
1850         if (!bRowSourceAmbiguous)
1851         {
1852             bRowSourceDetected = true;
1853             eRowSource = ( nDataInRows > 0
1854                            ? chart::ChartDataRowSource_ROWS
1855                            : chart::ChartDataRowSource_COLUMNS );
1856         }
1857         else
1858         {
1859             // set DataRowSource to the better of the two ambiguities
1860             eRowSource = ( nDataInRows > nDataInCols
1861                            ? chart::ChartDataRowSource_ROWS
1862                            : chart::ChartDataRowSource_COLUMNS );
1863         }
1864 
1865     }
1866 
1867     // TableNumberList
1868     {
1869         list<SCTAB> aTableNumList;
1870         InsertTabNumber func;
1871         func = for_each(aAllTokens.begin(), aAllTokens.end(), func);
1872         func.getList(aTableNumList);
1873         aResult.push_back(
1874             beans::PropertyValue( ::rtl::OUString::createFromAscii("TableNumberList"), -1,
1875                                   uno::makeAny( lcl_createTableNumberList( aTableNumList ) ),
1876                                   beans::PropertyState_DIRECT_VALUE ));
1877     }
1878 
1879     // DataRowSource (calculated before)
1880     if( bRowSourceDetected )
1881     {
1882         aResult.push_back(
1883             beans::PropertyValue( ::rtl::OUString::createFromAscii("DataRowSource"), -1,
1884                                   uno::makeAny( eRowSource ), beans::PropertyState_DIRECT_VALUE ));
1885     }
1886 
1887     // HasCategories
1888     if( bRowSourceDetected )
1889     {
1890         aResult.push_back(
1891             beans::PropertyValue( ::rtl::OUString::createFromAscii("HasCategories"), -1,
1892                                   uno::makeAny( bHasCategories ), beans::PropertyState_DIRECT_VALUE ));
1893     }
1894 
1895     // FirstCellAsLabel
1896     if( bRowSourceDetected )
1897     {
1898         aResult.push_back(
1899             beans::PropertyValue( ::rtl::OUString::createFromAscii("FirstCellAsLabel"), -1,
1900                                   uno::makeAny( bFirstCellAsLabel ), beans::PropertyState_DIRECT_VALUE ));
1901     }
1902 
1903     // Add the left upper corner to the range if it is missing.
1904     if (bRowSourceDetected && bFirstCellAsLabel && bHasCategories && !bHasCategoriesLabels )
1905     {
1906         RangeAnalyzer aTop,aLeft;
1907         if( eRowSource==chart::ChartDataRowSource_COLUMNS )
1908         {
1909             aTop.initRangeAnalyzer(aAllSeriesLabelTokens);
1910             aLeft.initRangeAnalyzer(aAllCategoriesValuesTokens);
1911         }
1912         else
1913         {
1914             aTop.initRangeAnalyzer(aAllCategoriesValuesTokens);
1915             aLeft.initRangeAnalyzer(aAllSeriesLabelTokens);
1916         }
1917         lcl_addUpperLeftCornerIfMissing(aAllTokens, aTop.getRowCount(), aLeft.getColumnCount());//e.g. #i91212#
1918     }
1919 
1920     // Get range string.
1921     lcl_convertTokensToString(sRangeRep, aAllTokens, m_pDocument);
1922 
1923     // add cell range property
1924     aResult.push_back(
1925         beans::PropertyValue( ::rtl::OUString::createFromAscii("CellRangeRepresentation"), -1,
1926                               uno::makeAny( sRangeRep ), beans::PropertyState_DIRECT_VALUE ));
1927 
1928     //Sequence Mapping
1929     bool bSequencesReordered = true;//todo detect this above or detect this sequence mapping cheaper ...
1930     if( bSequencesReordered && bRowSourceDetected )
1931     {
1932         bool bDifferentIndexes = false;
1933 
1934         std::vector< sal_Int32 > aSequenceMappingVector;
1935 
1936         uno::Reference< chart2::data::XDataSource > xCompareDataSource;
1937         try
1938         {
1939             xCompareDataSource.set( this->createDataSource( lcl_VectorToSequence( aResult ) ) );
1940         }
1941         catch( const lang::IllegalArgumentException & )
1942         {
1943             // creation of data source to compare didn't work, so we cannot
1944             // create a sequence mapping
1945         }
1946 
1947         if( xDataSource.is() && xCompareDataSource.is() )
1948         {
1949             uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence> > aOldSequences(
1950                 xCompareDataSource->getDataSequences() );
1951             uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aNewSequences(
1952                 xDataSource->getDataSequences());
1953 
1954             rtl::OUString aOldLabel;
1955             rtl::OUString aNewLabel;
1956             rtl::OUString aOldValues;
1957             rtl::OUString aNewValues;
1958             rtl::OUString aEmpty;
1959 
1960             for( sal_Int32 nNewIndex = 0; nNewIndex < aNewSequences.getLength(); nNewIndex++ )
1961             {
1962                 uno::Reference< chart2::data::XLabeledDataSequence> xNew( aNewSequences[nNewIndex] );
1963                 for( sal_Int32 nOldIndex = 0; nOldIndex < aOldSequences.getLength(); nOldIndex++ )
1964                 {
1965                     uno::Reference< chart2::data::XLabeledDataSequence> xOld( aOldSequences[nOldIndex] );
1966 
1967                     if( xOld.is() && xNew.is() )
1968                     {
1969                         aOldLabel = aNewLabel = aOldValues = aNewValues = aEmpty;
1970                         if( xOld.is() && xOld->getLabel().is() )
1971                             aOldLabel = xOld->getLabel()->getSourceRangeRepresentation();
1972                         if( xNew.is() && xNew->getLabel().is() )
1973                             aNewLabel = xNew->getLabel()->getSourceRangeRepresentation();
1974                         if( xOld.is() && xOld->getValues().is() )
1975                             aOldValues = xOld->getValues()->getSourceRangeRepresentation();
1976                         if( xNew.is() && xNew->getValues().is() )
1977                             aNewValues = xNew->getValues()->getSourceRangeRepresentation();
1978 
1979                         if( aOldLabel.equals(aNewLabel)
1980                             && ( aOldValues.equals(aNewValues) ) )
1981                         {
1982                             if( nOldIndex!=nNewIndex )
1983                                 bDifferentIndexes = true;
1984                             aSequenceMappingVector.push_back(nOldIndex);
1985                             break;
1986                         }
1987                     }
1988                 }
1989             }
1990         }
1991 
1992         if( bDifferentIndexes && aSequenceMappingVector.size() )
1993         {
1994             aResult.push_back(
1995                 beans::PropertyValue( ::rtl::OUString::createFromAscii("SequenceMapping"), -1,
1996                     uno::makeAny( lcl_VectorToSequence(aSequenceMappingVector) )
1997                     , beans::PropertyState_DIRECT_VALUE ));
1998         }
1999     }
2000 
2001     return lcl_VectorToSequence( aResult );
2002 }
2003 
createDataSequenceByRangeRepresentationPossible(const::rtl::OUString & aRangeRepresentation)2004 ::sal_Bool SAL_CALL ScChart2DataProvider::createDataSequenceByRangeRepresentationPossible( const ::rtl::OUString& aRangeRepresentation )
2005     throw (uno::RuntimeException)
2006 {
2007     ScUnoGuard aGuard;
2008     if( ! m_pDocument )
2009         return false;
2010 
2011     vector<ScSharedTokenRef> aTokens;
2012     ScRefTokenHelper::compileRangeRepresentation(aTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar());
2013     return !aTokens.empty();
2014 }
2015 
2016 uno::Reference< chart2::data::XDataSequence > SAL_CALL
createDataSequenceByRangeRepresentation(const::rtl::OUString & aRangeRepresentation)2017     ScChart2DataProvider::createDataSequenceByRangeRepresentation(
2018     const ::rtl::OUString& aRangeRepresentation )
2019     throw (lang::IllegalArgumentException,
2020            uno::RuntimeException)
2021 {
2022     ScUnoGuard aGuard;
2023     uno::Reference< chart2::data::XDataSequence > xResult;
2024 
2025     DBG_ASSERT( m_pDocument, "No Document -> no createDataSequenceByRangeRepresentation" );
2026     if(!m_pDocument || (aRangeRepresentation.getLength() == 0))
2027         return xResult;
2028 
2029     // Note: the range representation must be in Calc A1 format.  The import
2030     // filters use this method to pass data ranges, and they have no idea what
2031     // the current formula syntax is.  In the future we should add another
2032     // method to allow the client code to directly pass tokens representing
2033     // ranges.
2034 
2035     vector<ScSharedTokenRef> aRefTokens;
2036     ScRefTokenHelper::compileRangeRepresentation(aRefTokens, aRangeRepresentation, m_pDocument);
2037 	if (aRefTokens.empty())	// i120962: If haven't get reference, that means aRangeRepresentation is not a simple address, then try formulas
2038 	{
2039 		ScRangeName	aLocalRangeName(*(m_pDocument->GetRangeName()));
2040 		sal_uInt16	nCurPos = 0;
2041 		sal_Bool	bFindName = aLocalRangeName.SearchName(aRangeRepresentation, nCurPos);	// Find global name first
2042 
2043 		for (SCTAB Scope = 0; Scope < MAXTABCOUNT && !bFindName; Scope++ )	// Find name in sheet scope
2044 			bFindName = aLocalRangeName.SearchName(aRangeRepresentation, nCurPos, Scope);
2045 
2046 		if (bFindName)
2047 		{
2048 			ScRangeData*	pData =(ScRangeData*)(aLocalRangeName.At(nCurPos));
2049 			ScTokenArray*	pArray = pData->GetCode();
2050 			sal_uInt16 nLen = pArray->GetLen();
2051 			if (!nLen)
2052 				;
2053 			else if (nLen == 1)	// range names
2054 			{
2055 				pArray->Reset();
2056 				const FormulaToken* p = pArray->GetNextReference();
2057 				if (p)
2058 					aRefTokens.push_back(
2059 							ScSharedTokenRef(static_cast<ScToken*>(p->Clone())));
2060 			}
2061 			else	// formulas
2062 			{
2063 				String	aSymbol;
2064 				pData->GetSymbol(aSymbol, FormulaGrammar::GRAM_ENGLISH);
2065 
2066 				String	aFormulaStr('=');
2067 				aFormulaStr += aSymbol;
2068 
2069 				ScAddress	aAddr;
2070 				ScFormulaCell*	pCell = new ScFormulaCell(m_pDocument, aAddr, aFormulaStr, FormulaGrammar::GRAM_ENGLISH);
2071 				pCell->Interpret();
2072 
2073 				if (pCell->GetValidRefToken())
2074 				{
2075 					aRefTokens.push_back(
2076 						ScSharedTokenRef(static_cast<ScToken*>(pCell->GetValidRefToken()->Clone())));
2077 				}
2078 
2079 				DELETEZ( pCell );
2080 			}
2081 		}
2082 	}
2083 
2084     if (aRefTokens.empty())
2085         return xResult;
2086 
2087     // ScChart2DataSequence manages the life cycle of pRefTokens.
2088     vector<ScSharedTokenRef>* pRefTokens = new vector<ScSharedTokenRef>();
2089     pRefTokens->swap(aRefTokens);
2090     xResult.set(new ScChart2DataSequence(m_pDocument, this, pRefTokens, m_bIncludeHiddenCells));
2091 
2092     return xResult;
2093 }
2094 
getRangeSelection()2095 uno::Reference< sheet::XRangeSelection > SAL_CALL ScChart2DataProvider::getRangeSelection()
2096     throw (uno::RuntimeException)
2097 {
2098     uno::Reference< sheet::XRangeSelection > xResult;
2099 
2100     uno::Reference< frame::XModel > xModel( lcl_GetXModel( m_pDocument ));
2101     if( xModel.is())
2102         xResult.set( xModel->getCurrentController(), uno::UNO_QUERY );
2103 
2104     return xResult;
2105 }
2106 
2107 /*uno::Reference< util::XNumberFormatsSupplier > SAL_CALL ScChart2DataProvider::getNumberFormatsSupplier()
2108     throw (uno::RuntimeException)
2109 {
2110     return uno::Reference< util::XNumberFormatsSupplier >( lcl_GetXModel( m_pDocument ), uno::UNO_QUERY );
2111 }*/
2112 
2113 // XRangeXMLConversion ---------------------------------------------------
2114 
convertRangeToXML(const rtl::OUString & sRangeRepresentation)2115 rtl::OUString SAL_CALL ScChart2DataProvider::convertRangeToXML( const rtl::OUString& sRangeRepresentation )
2116     throw ( uno::RuntimeException, lang::IllegalArgumentException )
2117 {
2118     OUString aRet;
2119     if (!m_pDocument)
2120         return aRet;
2121 
2122     if (!sRangeRepresentation.getLength())
2123         // Empty data range is allowed.
2124         return aRet;
2125 
2126     vector<ScSharedTokenRef> aRefTokens;
2127     ScRefTokenHelper::compileRangeRepresentation(aRefTokens, sRangeRepresentation, m_pDocument, m_pDocument->GetGrammar());
2128     if (aRefTokens.empty())
2129         throw lang::IllegalArgumentException();
2130 
2131     Tokens2RangeStringXML converter(m_pDocument);
2132     converter = for_each(aRefTokens.begin(), aRefTokens.end(), converter);
2133     converter.getString(aRet);
2134 
2135     return aRet;
2136 }
2137 
convertRangeFromXML(const rtl::OUString & sXMLRange)2138 rtl::OUString SAL_CALL ScChart2DataProvider::convertRangeFromXML( const rtl::OUString& sXMLRange )
2139     throw ( uno::RuntimeException, lang::IllegalArgumentException )
2140 {
2141     const sal_Unicode cSep = ' ';
2142     const sal_Unicode cQuote = '\'';
2143 
2144     if (!m_pDocument)
2145     {
2146         // #i74062# When loading flat XML, this is called before the referenced sheets are in the document,
2147         // so the conversion has to take place directly with the strings, without looking up the sheets.
2148 
2149         rtl::OUStringBuffer sRet;
2150         sal_Int32 nOffset = 0;
2151         while( nOffset >= 0 )
2152         {
2153             rtl::OUString sToken;
2154             ScRangeStringConverter::GetTokenByOffset( sToken, sXMLRange, nOffset, cSep, cQuote );
2155             if( nOffset >= 0 )
2156             {
2157                 // convert one address (remove dots)
2158 
2159                 String aUIString(sToken);
2160 
2161                 sal_Int32 nIndex = ScRangeStringConverter::IndexOf( sToken, ':', 0, cQuote );
2162                 if ( nIndex >= 0 && nIndex < aUIString.Len() - 1 &&
2163                         aUIString.GetChar((xub_StrLen)nIndex + 1) == (sal_Unicode) '.' )
2164                     aUIString.Erase( (xub_StrLen)nIndex + 1, 1 );
2165 
2166                 if ( aUIString.GetChar(0) == (sal_Unicode) '.' )
2167                     aUIString.Erase( 0, 1 );
2168 
2169                 if( sRet.getLength() )
2170                     sRet.append( (sal_Unicode) ';' );
2171                 sRet.append( aUIString );
2172             }
2173         }
2174 
2175         return sRet.makeStringAndClear();
2176     }
2177 
2178     OUString aRet;
2179 
2180     // #118840# Only interpret range string when the ScDocument is not just used
2181     // temporary (e.g. for transporting a chart over the clipboard). In that case, the local
2182     // cell data would be invalid; despite the fact that a 'Sheet1' exists (just because
2183     // it's the default)
2184     if(!m_pDocument->IsTemporary())
2185     {
2186         ScRangeStringConverter::GetStringFromXMLRangeString(aRet, sXMLRange, m_pDocument);
2187     }
2188 
2189     return aRet;
2190 }
2191 
2192 // DataProvider XPropertySet -------------------------------------------------
2193 
2194 uno::Reference< beans::XPropertySetInfo> SAL_CALL
getPropertySetInfo()2195 ScChart2DataProvider::getPropertySetInfo() throw( uno::RuntimeException)
2196 {
2197 	ScUnoGuard aGuard;
2198 	static uno::Reference<beans::XPropertySetInfo> aRef =
2199 		new SfxItemPropertySetInfo( m_aPropSet.getPropertyMap() );
2200 	return aRef;
2201 }
2202 
2203 
setPropertyValue(const::rtl::OUString & rPropertyName,const uno::Any & rValue)2204 void SAL_CALL ScChart2DataProvider::setPropertyValue(
2205         const ::rtl::OUString& rPropertyName, const uno::Any& rValue)
2206             throw( beans::UnknownPropertyException,
2207                     beans::PropertyVetoException,
2208                     lang::IllegalArgumentException,
2209                     lang::WrappedTargetException, uno::RuntimeException)
2210 {
2211     if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS)))
2212     {
2213         if ( !(rValue >>= m_bIncludeHiddenCells))
2214             throw lang::IllegalArgumentException();
2215     }
2216     else
2217         throw beans::UnknownPropertyException();
2218 }
2219 
2220 
getPropertyValue(const::rtl::OUString & rPropertyName)2221 uno::Any SAL_CALL ScChart2DataProvider::getPropertyValue(
2222         const ::rtl::OUString& rPropertyName)
2223             throw( beans::UnknownPropertyException,
2224                     lang::WrappedTargetException, uno::RuntimeException)
2225 {
2226     uno::Any aRet;
2227     if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS)))
2228         aRet <<= m_bIncludeHiddenCells;
2229     else
2230         throw beans::UnknownPropertyException();
2231     return aRet;
2232 }
2233 
2234 
addPropertyChangeListener(const::rtl::OUString &,const uno::Reference<beans::XPropertyChangeListener> &)2235 void SAL_CALL ScChart2DataProvider::addPropertyChangeListener(
2236         const ::rtl::OUString& /*rPropertyName*/,
2237         const uno::Reference< beans::XPropertyChangeListener>& /*xListener*/)
2238             throw( beans::UnknownPropertyException,
2239                     lang::WrappedTargetException, uno::RuntimeException)
2240 {
2241     OSL_ENSURE( false, "Not yet implemented" );
2242 }
2243 
2244 
removePropertyChangeListener(const::rtl::OUString &,const uno::Reference<beans::XPropertyChangeListener> &)2245 void SAL_CALL ScChart2DataProvider::removePropertyChangeListener(
2246         const ::rtl::OUString& /*rPropertyName*/,
2247         const uno::Reference< beans::XPropertyChangeListener>& /*rListener*/)
2248             throw( beans::UnknownPropertyException,
2249                     lang::WrappedTargetException, uno::RuntimeException)
2250 {
2251     OSL_ENSURE( false, "Not yet implemented" );
2252 }
2253 
2254 
addVetoableChangeListener(const::rtl::OUString &,const uno::Reference<beans::XVetoableChangeListener> &)2255 void SAL_CALL ScChart2DataProvider::addVetoableChangeListener(
2256         const ::rtl::OUString& /*rPropertyName*/,
2257         const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/)
2258             throw( beans::UnknownPropertyException,
2259                     lang::WrappedTargetException, uno::RuntimeException)
2260 {
2261     OSL_ENSURE( false, "Not yet implemented" );
2262 }
2263 
2264 
removeVetoableChangeListener(const::rtl::OUString &,const uno::Reference<beans::XVetoableChangeListener> &)2265 void SAL_CALL ScChart2DataProvider::removeVetoableChangeListener(
2266         const ::rtl::OUString& /*rPropertyName*/,
2267         const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/ )
2268             throw( beans::UnknownPropertyException,
2269                     lang::WrappedTargetException, uno::RuntimeException)
2270 {
2271     OSL_ENSURE( false, "Not yet implemented" );
2272 }
2273 
2274 // DataSource ================================================================
2275 
ScChart2DataSource(ScDocument * pDoc)2276 ScChart2DataSource::ScChart2DataSource( ScDocument* pDoc)
2277     : m_pDocument( pDoc)
2278 {
2279     if ( m_pDocument )
2280         m_pDocument->AddUnoObject( *this);
2281 }
2282 
2283 
~ScChart2DataSource()2284 ScChart2DataSource::~ScChart2DataSource()
2285 {
2286     if ( m_pDocument )
2287         m_pDocument->RemoveUnoObject( *this);
2288 }
2289 
2290 
Notify(SfxBroadcaster &,const SfxHint & rHint)2291 void ScChart2DataSource::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
2292 {
2293     if ( rHint.ISA( SfxSimpleHint ) &&
2294             ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
2295     {
2296         m_pDocument = NULL;
2297     }
2298 }
2299 
2300 
2301 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence> > SAL_CALL
getDataSequences()2302 ScChart2DataSource::getDataSequences() throw ( uno::RuntimeException)
2303 {
2304     ScUnoGuard aGuard;
2305 
2306     LabeledList::const_iterator aItr(m_aLabeledSequences.begin());
2307     LabeledList::const_iterator aEndItr(m_aLabeledSequences.end());
2308 
2309     uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aRet(m_aLabeledSequences.size());
2310 
2311     sal_Int32 i = 0;
2312     while (aItr != aEndItr)
2313     {
2314         aRet[i] = *aItr;
2315         ++i;
2316         ++aItr;
2317     }
2318 
2319     return aRet;
2320 
2321 /*    typedef ::std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > tVec;
2322     tVec aVec;
2323     bool bSeries = false;
2324     // split into columns - FIXME: different if GlueState() is used
2325     for ( ScRangePtr p = m_xRanges->First(); p; p = m_xRanges->Next())
2326     {
2327         for ( SCCOL nCol = p->aStart.Col(); nCol <= p->aEnd.Col(); ++nCol)
2328         {
2329             uno::Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
2330                 new ScChart2LabeledDataSequence( m_pDocument));
2331             if( xLabeledSeq.is())
2332             {
2333                 aVec.push_back( xLabeledSeq );
2334                 if( bSeries )
2335                 {
2336                     ScRangeListRef aColRanges = new ScRangeList;
2337                     // one single sheet selected assumed for now
2338                     aColRanges->Append( ScRange( nCol, p->aStart.Row(),
2339                                                  p->aStart.Tab(), nCol, p->aStart.Row(),
2340                                                  p->aStart.Tab()));
2341                     // TEST: add range two times, once as label, once as data
2342                     // TODO: create pure Numerical and Text sequences if possible
2343                     uno::Reference< chart2::data::XDataSequence > xLabel(
2344                         new ScChart2DataSequence( m_pDocument, aColRanges));
2345 
2346                     // set role
2347                     uno::Reference< beans::XPropertySet > xProp( xLabel, uno::UNO_QUERY );
2348                     if( xProp.is())
2349                         xProp->setPropertyValue(
2350                             ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )),
2351                             ::uno::makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "label" ))));
2352 
2353                     xLabeledSeq->setLabel( xLabel );
2354                 }
2355 
2356                 ScRangeListRef aColRanges = new ScRangeList;
2357 
2358                 // one single sheet selected assumed for now
2359                 aColRanges->Append( ScRange( nCol, p->aStart.Row() + 1,
2360                                              p->aStart.Tab(), nCol, p->aEnd.Row(),
2361                                              p->aStart.Tab()));
2362                 uno::Reference< chart2::data::XDataSequence > xData(
2363                     new ScChart2DataSequence( m_pDocument, aColRanges));
2364 
2365                 // set role
2366                 uno::Reference< beans::XPropertySet > xProp( xData, uno::UNO_QUERY );
2367                 if( xProp.is())
2368                     xProp->setPropertyValue(
2369                         ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )),
2370                         ::uno::makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "values" ))));
2371 
2372                 xLabeledSeq->setValues( xData );
2373 
2374                 bSeries = true;
2375             }
2376         }
2377     }
2378     uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence> > aSequences(
2379             aVec.size());
2380     uno::Reference< chart2::data::XLabeledDataSequence> * pArr = aSequences.getArray();
2381     sal_Int32 j = 0;
2382     for ( tVec::const_iterator iSeq = aVec.begin(); iSeq != aVec.end();
2383             ++iSeq, ++j)
2384     {
2385         pArr[j] = *iSeq;
2386     }
2387     return aSequences;*/
2388 }
2389 
AddLabeledSequence(const uno::Reference<chart2::data::XLabeledDataSequence> & xNew)2390 void ScChart2DataSource::AddLabeledSequence(const uno::Reference < chart2::data::XLabeledDataSequence >& xNew)
2391 {
2392     m_aLabeledSequences.push_back(xNew);
2393 }
2394 
2395 
2396 // DataSequence ==============================================================
2397 
Item()2398 ScChart2DataSequence::Item::Item() :
2399     mfValue(0.0), mbIsValue(false)
2400 {
2401     ::rtl::math::setNan(&mfValue);
2402 }
2403 
HiddenRangeListener(ScChart2DataSequence & rParent)2404 ScChart2DataSequence::HiddenRangeListener::HiddenRangeListener(ScChart2DataSequence& rParent) :
2405     mrParent(rParent)
2406 {
2407 }
2408 
~HiddenRangeListener()2409 ScChart2DataSequence::HiddenRangeListener::~HiddenRangeListener()
2410 {
2411 }
2412 
notify()2413 void ScChart2DataSequence::HiddenRangeListener::notify()
2414 {
2415     mrParent.setDataChangedHint(true);
2416 }
2417 
ScChart2DataSequence(ScDocument * pDoc,const uno::Reference<chart2::data::XDataProvider> & xDP,vector<ScSharedTokenRef> * pTokens,bool bIncludeHiddenCells)2418 ScChart2DataSequence::ScChart2DataSequence( ScDocument* pDoc,
2419         const uno::Reference < chart2::data::XDataProvider >& xDP,
2420         vector<ScSharedTokenRef>* pTokens,
2421         bool bIncludeHiddenCells )
2422     : m_bIncludeHiddenCells( bIncludeHiddenCells)
2423     , m_nObjectId( 0 )
2424     , m_pDocument( pDoc)
2425     , m_pTokens(pTokens)
2426     , m_pRangeIndices(NULL)
2427     , m_pExtRefListener(NULL)
2428     , m_xDataProvider( xDP)
2429     , m_aPropSet(lcl_GetDataSequencePropertyMap())
2430     , m_pHiddenListener(NULL)
2431     , m_pValueListener( NULL )
2432     , m_bGotDataChangedHint(false)
2433     , m_bExtDataRebuildQueued(false)
2434 {
2435     DBG_ASSERT(pTokens, "reference token list is null");
2436 
2437     if ( m_pDocument )
2438     {
2439         m_pDocument->AddUnoObject( *this);
2440         m_nObjectId = m_pDocument->GetNewUnoId();
2441     }
2442     // FIXME: real implementation of identifier and it's mapping to ranges.
2443     // Reuse ScChartListener?
2444 
2445     // BM: don't use names of named ranges but the UI range strings
2446 //	String	aStr;
2447 //	rRangeList->Format( aStr, SCR_ABS_3D, m_pDocument );
2448 //    m_aIdentifier = ::rtl::OUString( aStr );
2449 
2450 //      m_aIdentifier = ::rtl::OUString::createFromAscii( "ID_");
2451 //      static sal_Int32 nID = 0;
2452 //      m_aIdentifier += ::rtl::OUString::valueOf( ++nID);
2453 }
2454 
~ScChart2DataSequence()2455 ScChart2DataSequence::~ScChart2DataSequence()
2456 {
2457     if ( m_pDocument )
2458     {
2459         m_pDocument->RemoveUnoObject( *this);
2460         if (m_pHiddenListener.get())
2461         {
2462             ScChartListenerCollection* pCLC = m_pDocument->GetChartListenerCollection();
2463             if (pCLC)
2464                 pCLC->EndListeningHiddenRange(m_pHiddenListener.get());
2465         }
2466         StopListeningToAllExternalRefs();
2467     }
2468 
2469     delete m_pValueListener;
2470 }
2471 
RefChanged()2472 void ScChart2DataSequence::RefChanged()
2473 {
2474     if( m_pValueListener && m_aValueListeners.Count() != 0 )
2475     {
2476         m_pValueListener->EndListeningAll();
2477 
2478         if( m_pDocument )
2479         {
2480             ScChartListenerCollection* pCLC = NULL;
2481             if (m_pHiddenListener.get())
2482             {
2483                 pCLC = m_pDocument->GetChartListenerCollection();
2484                 if (pCLC)
2485                     pCLC->EndListeningHiddenRange(m_pHiddenListener.get());
2486             }
2487 
2488             vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end();
2489             for (; itr != itrEnd; ++itr)
2490             {
2491                 ScRange aRange;
2492                 if (!ScRefTokenHelper::getRangeFromToken(aRange, *itr))
2493                     continue;
2494 
2495                 m_pDocument->StartListeningArea(aRange, m_pValueListener);
2496                 if (pCLC)
2497                     pCLC->StartListeningHiddenRange(aRange, m_pHiddenListener.get());
2498             }
2499         }
2500     }
2501 }
2502 
BuildDataCache()2503 void ScChart2DataSequence::BuildDataCache()
2504 {
2505     m_bExtDataRebuildQueued = false;
2506 
2507     if (!m_aDataArray.empty())
2508         return;
2509 
2510     if (!m_pTokens.get())
2511     {
2512         DBG_ERROR("m_pTokens == NULL!  Something is wrong.");
2513         return;
2514     }
2515 
2516     StopListeningToAllExternalRefs();
2517 
2518     ::std::list<sal_Int32> aHiddenValues;
2519     sal_Int32 nDataCount = 0;
2520     sal_Int32 nHiddenValueCount = 0;
2521 
2522     for (vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end();
2523           itr != itrEnd; ++itr)
2524     {
2525         if (ScRefTokenHelper::isExternalRef(*itr))
2526         {
2527             nDataCount += FillCacheFromExternalRef(*itr);
2528         }
2529         else
2530         {
2531             ScRange aRange;
2532             if (!ScRefTokenHelper::getRangeFromToken(aRange, *itr))
2533                 continue;
2534 
2535             SCCOL nLastCol = -1;
2536             SCROW nLastRow = -1;
2537 
2538             for (SCTAB nTab = aRange.aStart.Tab(); nTab <= aRange.aEnd.Tab(); ++nTab)
2539             {
2540                 for (SCCOL nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol)
2541                 {
2542                     for (SCROW nRow = aRange.aStart.Row(); nRow <= aRange.aEnd.Row(); ++nRow)
2543                     {
2544                         bool bColHidden = m_pDocument->ColHidden(nCol, nTab, nLastCol);
2545                         bool bRowHidden = m_pDocument->RowHidden(nRow, nTab, nLastRow);
2546 
2547                         if (bColHidden || bRowHidden)
2548                         {
2549                             // hidden cell
2550                             ++nHiddenValueCount;
2551                             aHiddenValues.push_back(nDataCount-1);
2552 
2553                             if( !m_bIncludeHiddenCells )
2554                                 continue;
2555                         }
2556 
2557                         m_aDataArray.push_back(Item());
2558                         Item& rItem = m_aDataArray.back();
2559                         ++nDataCount;
2560 
2561                         ScAddress aAdr(nCol, nRow, nTab);
2562                         ScBaseCell* pCell = m_pDocument->GetCell(aAdr);
2563                         if (!pCell)
2564                             continue;
2565 
2566                         if (pCell->HasStringData())
2567 
2568                             rItem.maString = pCell->GetStringData();
2569                         else
2570                         {
2571                             String aStr;
2572                             m_pDocument->GetString(nCol, nRow, nTab, aStr);
2573                             rItem.maString = aStr;
2574                         }
2575 
2576                         switch (pCell->GetCellType())
2577                         {
2578                             case CELLTYPE_VALUE:
2579                                 rItem.mfValue = static_cast< ScValueCell*>(pCell)->GetValue();
2580                                 rItem.mbIsValue = true;
2581                             break;
2582                             case CELLTYPE_FORMULA:
2583                             {
2584                                 ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
2585                                 sal_uInt16 nErr = pFCell->GetErrCode();
2586                                 if (nErr)
2587                                     break;
2588 
2589                                 if (pFCell->HasValueData())
2590                                 {
2591                                     rItem.mfValue = pFCell->GetValue();
2592                                     rItem.mbIsValue = true;
2593                                 }
2594                             }
2595                             break;
2596 #if DBG_UTIL
2597                             case CELLTYPE_DESTROYED:
2598 #endif
2599                             case CELLTYPE_EDIT:
2600                             case CELLTYPE_NONE:
2601                             case CELLTYPE_NOTE:
2602                             case CELLTYPE_STRING:
2603                             case CELLTYPE_SYMBOLS:
2604                             default:
2605                                 ; // do nothing
2606                         }
2607                     }
2608                 }
2609             }
2610         }
2611     }
2612 
2613     // convert the hidden cell list to sequence.
2614     m_aHiddenValues.realloc(nHiddenValueCount);
2615     sal_Int32* pArr = m_aHiddenValues.getArray();
2616     ::std::list<sal_Int32>::const_iterator itr = aHiddenValues.begin(), itrEnd = aHiddenValues.end();
2617     for (;itr != itrEnd; ++itr, ++pArr)
2618         *pArr = *itr;
2619 
2620     // Clear the data series cache when the array is re-built.
2621     m_aMixedDataCache.realloc(0);
2622 }
2623 
RebuildDataCache()2624 void ScChart2DataSequence::RebuildDataCache()
2625 {
2626     if (!m_bExtDataRebuildQueued)
2627     {
2628         m_aDataArray.clear();
2629         m_pDocument->BroadcastUno(ScHint(SC_HINT_DATACHANGED, ScAddress(), NULL));
2630         m_bExtDataRebuildQueued = true;
2631         m_bGotDataChangedHint = true;
2632     }
2633 }
2634 
FillCacheFromExternalRef(const ScSharedTokenRef & pToken)2635 sal_Int32 ScChart2DataSequence::FillCacheFromExternalRef(const ScSharedTokenRef& pToken)
2636 {
2637     ScExternalRefManager* pRefMgr = m_pDocument->GetExternalRefManager();
2638     ScRange aRange;
2639     if (!ScRefTokenHelper::getRangeFromToken(aRange, pToken, true))
2640         return 0;
2641 
2642     sal_uInt16 nFileId = pToken->GetIndex();
2643     const String& rTabName = pToken->GetString();
2644     ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(nFileId, rTabName, aRange, NULL);
2645     if (!pArray)
2646         // no external data exists for this range.
2647         return 0;
2648 
2649     // Start listening for this external document.
2650     ExternalRefListener* pExtRefListener = GetExtRefListener();
2651     pRefMgr->addLinkListener(nFileId, pExtRefListener);
2652     pExtRefListener->addFileId(nFileId);
2653 
2654     ScExternalRefCache::TableTypeRef pTable = pRefMgr->getCacheTable(nFileId, rTabName, false, NULL);
2655     sal_Int32 nDataCount = 0;
2656     for (FormulaToken* p = pArray->First(); p; p = pArray->Next())
2657     {
2658         // Cached external range is always represented as a single
2659         // matrix token, although that might change in the future when
2660         // we introduce a new token type to store multi-table range
2661         // data.
2662 
2663         if (p->GetType() != svMatrix)
2664         {
2665             DBG_ERROR("Cached array is not a matrix token.");
2666             continue;
2667         }
2668 
2669         const ScMatrix* pMat = static_cast<ScToken*>(p)->GetMatrix();
2670         SCSIZE nCSize, nRSize;
2671         pMat->GetDimensions(nCSize, nRSize);
2672         for (SCSIZE nC = 0; nC < nCSize; ++nC)
2673         {
2674             for (SCSIZE nR = 0; nR < nRSize; ++nR)
2675             {
2676                 if (pMat->IsValue(nC, nR) || pMat->IsBoolean(nC, nR))
2677                 {
2678                     m_aDataArray.push_back(Item());
2679                     Item& rItem = m_aDataArray.back();
2680                     ++nDataCount;
2681 
2682                     rItem.mbIsValue = true;
2683                     rItem.mfValue = pMat->GetDouble(nC, nR);
2684 
2685                     SvNumberFormatter* pFormatter = m_pDocument->GetFormatTable();
2686                     if (pFormatter)
2687                     {
2688                         String aStr;
2689                         const double fVal = rItem.mfValue;
2690                         Color* pColor = NULL;
2691                         sal_uInt32 nFmt = 0;
2692                         if (pTable)
2693                         {
2694                             // Get the correct format index from the cache.
2695                             SCCOL nCol = aRange.aStart.Col() + static_cast<SCCOL>(nC);
2696                             SCROW nRow = aRange.aStart.Row() + static_cast<SCROW>(nR);
2697                             pTable->getCell(nCol, nRow, &nFmt);
2698                         }
2699                         pFormatter->GetOutputString(fVal, nFmt, aStr, &pColor);
2700                         rItem.maString = aStr;
2701                     }
2702                 }
2703                 else if (pMat->IsString(nC, nR))
2704                 {
2705                     m_aDataArray.push_back(Item());
2706                     Item& rItem = m_aDataArray.back();
2707                     ++nDataCount;
2708 
2709                     rItem.mbIsValue = false;
2710                     rItem.maString = pMat->GetString(nC, nR);
2711                 }
2712             }
2713         }
2714     }
2715     return nDataCount;
2716 }
2717 
UpdateTokensFromRanges(const ScRangeList & rRanges)2718 void ScChart2DataSequence::UpdateTokensFromRanges(const ScRangeList& rRanges)
2719 {
2720     if (!m_pRangeIndices.get())
2721         return;
2722 
2723     sal_uInt32 nCount = rRanges.Count();
2724     for (sal_uInt32 i = 0; i < nCount; ++i)
2725     {
2726         ScSharedTokenRef pToken;
2727         ScRange* pRange = static_cast<ScRange*>(rRanges.GetObject(i));
2728         DBG_ASSERT(pRange, "range object is NULL.");
2729 
2730         ScRefTokenHelper::getTokenFromRange(pToken, *pRange);
2731         sal_uInt32 nOrigPos = (*m_pRangeIndices)[i];
2732         (*m_pTokens)[nOrigPos] = pToken;
2733     }
2734 
2735     RefChanged();
2736 
2737     // any change of the range address is broadcast to value (modify) listeners
2738     if ( m_aValueListeners.Count() )
2739         m_bGotDataChangedHint = true;
2740 }
2741 
GetExtRefListener()2742 ScChart2DataSequence::ExternalRefListener* ScChart2DataSequence::GetExtRefListener()
2743 {
2744     if (!m_pExtRefListener.get())
2745         m_pExtRefListener.reset(new ExternalRefListener(*this, m_pDocument));
2746 
2747     return m_pExtRefListener.get();
2748 }
2749 
StopListeningToAllExternalRefs()2750 void ScChart2DataSequence::StopListeningToAllExternalRefs()
2751 {
2752     if (!m_pExtRefListener.get())
2753         return;
2754 
2755     const hash_set<sal_uInt16>& rFileIds = m_pExtRefListener->getAllFileIds();
2756     hash_set<sal_uInt16>::const_iterator itr = rFileIds.begin(), itrEnd = rFileIds.end();
2757     ScExternalRefManager* pRefMgr = m_pDocument->GetExternalRefManager();
2758     for (; itr != itrEnd; ++itr)
2759         pRefMgr->removeLinkListener(*itr, m_pExtRefListener.get());
2760 
2761     m_pExtRefListener.reset();
2762 }
2763 
CopyData(const ScChart2DataSequence & r)2764 void ScChart2DataSequence::CopyData(const ScChart2DataSequence& r)
2765 {
2766     if (!m_pDocument)
2767     {
2768         DBG_ERROR("document instance is NULL!?");
2769         return;
2770     }
2771 
2772     list<Item> aDataArray(r.m_aDataArray);
2773     m_aDataArray.swap(aDataArray);
2774 
2775     m_aHiddenValues = r.m_aHiddenValues;
2776     m_aRole = r.m_aRole;
2777 
2778     if (r.m_pRangeIndices.get())
2779         m_pRangeIndices.reset(new vector<sal_uInt32>(*r.m_pRangeIndices));
2780 
2781     if (r.m_pExtRefListener.get())
2782     {
2783         // Re-register all external files that the old instance was
2784         // listening to.
2785 
2786         ScExternalRefManager* pRefMgr = m_pDocument->GetExternalRefManager();
2787         m_pExtRefListener.reset(new ExternalRefListener(*this, m_pDocument));
2788         const hash_set<sal_uInt16>& rFileIds = r.m_pExtRefListener->getAllFileIds();
2789         hash_set<sal_uInt16>::const_iterator itr = rFileIds.begin(), itrEnd = rFileIds.end();
2790         for (; itr != itrEnd; ++itr)
2791         {
2792             pRefMgr->addLinkListener(*itr, m_pExtRefListener.get());
2793             m_pExtRefListener->addFileId(*itr);
2794         }
2795     }
2796 }
2797 
Notify(SfxBroadcaster &,const SfxHint & rHint)2798 void ScChart2DataSequence::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
2799 {
2800     if ( rHint.ISA( SfxSimpleHint ) )
2801     {
2802         sal_uLong nId = static_cast<const SfxSimpleHint&>(rHint).GetId();
2803         if ( nId ==SFX_HINT_DYING )
2804         {
2805             m_pDocument = NULL;
2806         }
2807         else if ( nId == SFX_HINT_DATACHANGED )
2808         {
2809             // delayed broadcast as in ScCellRangesBase
2810 
2811             if ( m_bGotDataChangedHint && m_pDocument )
2812             {
2813                 m_aDataArray.clear();
2814                 lang::EventObject aEvent;
2815                 aEvent.Source.set((cppu::OWeakObject*)this);
2816 
2817                 if( m_pDocument )
2818                 {
2819                     for ( sal_uInt16 n=0; n<m_aValueListeners.Count(); n++ )
2820                         m_pDocument->AddUnoListenerCall( *m_aValueListeners[n], aEvent );
2821                 }
2822 
2823                 m_bGotDataChangedHint = false;
2824             }
2825         }
2826         else if ( nId == SC_HINT_CALCALL )
2827         {
2828             // broadcast from DoHardRecalc - set m_bGotDataChangedHint
2829             // (SFX_HINT_DATACHANGED follows separately)
2830 
2831             if ( m_aValueListeners.Count() )
2832                 m_bGotDataChangedHint = true;
2833         }
2834     }
2835     else if ( rHint.ISA( ScUpdateRefHint ) )
2836     {
2837         // Create a range list from the token list, have the range list
2838         // updated, and bring the change back to the token list.
2839 
2840         ScRangeList aRanges;
2841         m_pRangeIndices.reset(new vector<sal_uInt32>());
2842         vector<ScSharedTokenRef>::const_iterator itrBeg = m_pTokens->begin(), itrEnd = m_pTokens->end();
2843         for (vector<ScSharedTokenRef>::const_iterator itr = itrBeg ;itr != itrEnd; ++itr)
2844         {
2845             if (!ScRefTokenHelper::isExternalRef(*itr))
2846             {
2847                 ScRange aRange;
2848                 ScRefTokenHelper::getRangeFromToken(aRange, *itr);
2849                 aRanges.Append(aRange);
2850                 sal_uInt32 nPos = distance(itrBeg, itr);
2851                 m_pRangeIndices->push_back(nPos);
2852             }
2853         }
2854 
2855         DBG_ASSERT(m_pRangeIndices->size() == static_cast<size_t>(aRanges.Count()),
2856                    "range list and range index list have different sizes.");
2857 
2858         auto_ptr<ScRangeList> pUndoRanges;
2859         if ( m_pDocument->HasUnoRefUndo() )
2860             pUndoRanges.reset(new ScRangeList(aRanges));
2861 
2862         const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint;
2863         bool bChanged = aRanges.UpdateReference(
2864             rRef.GetMode(), m_pDocument, rRef.GetRange(), rRef.GetDx(), rRef.GetDy(), rRef.GetDz());
2865 
2866         if (bChanged)
2867         {
2868             DBG_ASSERT(m_pRangeIndices->size() == static_cast<size_t>(aRanges.Count()),
2869                        "range list and range index list have different sizes after the reference update.");
2870 
2871             // Bring the change back from the range list to the token list.
2872             UpdateTokensFromRanges(aRanges);
2873 
2874             if (pUndoRanges.get())
2875                 m_pDocument->AddUnoRefChange(m_nObjectId, *pUndoRanges);
2876         }
2877     }
2878     else if ( rHint.ISA( ScUnoRefUndoHint ) )
2879     {
2880         const ScUnoRefUndoHint& rUndoHint = static_cast<const ScUnoRefUndoHint&>(rHint);
2881 
2882         do
2883         {
2884             if (rUndoHint.GetObjectId() != m_nObjectId)
2885                 break;
2886 
2887             // The hint object provides the old ranges.  Restore the old state
2888             // from these ranges.
2889 
2890             if (!m_pRangeIndices.get() || m_pRangeIndices->empty())
2891             {
2892                 DBG_ERROR(" faulty range indices");
2893                 break;
2894             }
2895 
2896             const ScRangeList& rRanges = rUndoHint.GetRanges();
2897 
2898             sal_uInt32 nCount = rRanges.Count();
2899             if (nCount != m_pRangeIndices->size())
2900             {
2901                 DBG_ERROR("range count and range index count differ.");
2902                 break;
2903             }
2904 
2905             UpdateTokensFromRanges(rRanges);
2906         }
2907         while (false);
2908     }
2909 }
2910 
2911 
IMPL_LINK(ScChart2DataSequence,ValueListenerHdl,SfxHint *,pHint)2912 IMPL_LINK( ScChart2DataSequence, ValueListenerHdl, SfxHint*, pHint )
2913 {
2914     if ( m_pDocument && pHint && pHint->ISA( SfxSimpleHint ) &&
2915             ((const SfxSimpleHint*)pHint)->GetId() & (SC_HINT_DATACHANGED | SC_HINT_DYING) )
2916     {
2917         //  This may be called several times for a single change, if several formulas
2918         //  in the range are notified. So only a flag is set that is checked when
2919         //  SFX_HINT_DATACHANGED is received.
2920 
2921         setDataChangedHint(true);
2922     }
2923     return 0;
2924 }
2925 
2926 // ----------------------------------------------------------------------------
2927 
ExternalRefListener(ScChart2DataSequence & rParent,ScDocument * pDoc)2928 ScChart2DataSequence::ExternalRefListener::ExternalRefListener(
2929     ScChart2DataSequence& rParent, ScDocument* pDoc) :
2930     ScExternalRefManager::LinkListener(),
2931     mrParent(rParent),
2932     mpDoc(pDoc)
2933 {
2934 }
2935 
~ExternalRefListener()2936 ScChart2DataSequence::ExternalRefListener::~ExternalRefListener()
2937 {
2938     if (!mpDoc || mpDoc->IsInDtorClear())
2939         // The document is being destroyed.  Do nothing.
2940         return;
2941 
2942     // Make sure to remove all pointers to this object.
2943     mpDoc->GetExternalRefManager()->removeLinkListener(this);
2944 }
2945 
notify(sal_uInt16 nFileId,ScExternalRefManager::LinkUpdateType eType)2946 void ScChart2DataSequence::ExternalRefListener::notify(sal_uInt16 nFileId, ScExternalRefManager::LinkUpdateType eType)
2947 {
2948     switch (eType)
2949     {
2950         case ScExternalRefManager::LINK_MODIFIED:
2951         {
2952             if (maFileIds.count(nFileId))
2953                 // We are listening to this external document.
2954                 mrParent.RebuildDataCache();
2955         }
2956         break;
2957         case ScExternalRefManager::LINK_BROKEN:
2958             removeFileId(nFileId);
2959         break;
2960     }
2961 }
2962 
addFileId(sal_uInt16 nFileId)2963 void ScChart2DataSequence::ExternalRefListener::addFileId(sal_uInt16 nFileId)
2964 {
2965     maFileIds.insert(nFileId);
2966 }
2967 
removeFileId(sal_uInt16 nFileId)2968 void ScChart2DataSequence::ExternalRefListener::removeFileId(sal_uInt16 nFileId)
2969 {
2970     maFileIds.erase(nFileId);
2971 }
2972 
getAllFileIds()2973 const hash_set<sal_uInt16>& ScChart2DataSequence::ExternalRefListener::getAllFileIds()
2974 {
2975     return maFileIds;
2976 }
2977 
2978 // ----------------------------------------------------------------------------
2979 
getData()2980 uno::Sequence< uno::Any> SAL_CALL ScChart2DataSequence::getData()
2981             throw ( uno::RuntimeException)
2982 {
2983     ScUnoGuard aGuard;
2984     if ( !m_pDocument)
2985         throw uno::RuntimeException();
2986 
2987     BuildDataCache();
2988 
2989     if (!m_aMixedDataCache.getLength())
2990     {
2991         // Build a cache for the 1st time...
2992 
2993         sal_Int32 nCount = m_aDataArray.size();
2994         m_aMixedDataCache.realloc(nCount);
2995         uno::Any* pArr = m_aMixedDataCache.getArray();
2996         ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end();
2997         for (; itr != itrEnd; ++itr, ++pArr)
2998         {
2999             if (itr->mbIsValue)
3000                 *pArr <<= itr->mfValue;
3001             else
3002                 *pArr <<= itr->maString;
3003         }
3004     }
3005     return m_aMixedDataCache;
3006 }
3007 
3008 // XNumericalDataSequence --------------------------------------------------
3009 
getNumericalData()3010 uno::Sequence< double > SAL_CALL ScChart2DataSequence::getNumericalData()
3011             throw ( uno::RuntimeException)
3012 {
3013     ScUnoGuard aGuard;
3014     if ( !m_pDocument)
3015         throw uno::RuntimeException();
3016 
3017     BuildDataCache();
3018 
3019     double fNAN;
3020     ::rtl::math::setNan(&fNAN);
3021 
3022     sal_Int32 nCount = m_aDataArray.size();
3023     uno::Sequence<double> aSeq(nCount);
3024      double* pArr = aSeq.getArray();
3025      ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end();
3026     for (; itr != itrEnd; ++itr, ++pArr)
3027         *pArr = itr->mbIsValue ? itr->mfValue : fNAN;
3028 
3029     return aSeq;
3030 }
3031 
3032 // XTextualDataSequence --------------------------------------------------
3033 
getTextualData()3034 uno::Sequence< rtl::OUString > SAL_CALL ScChart2DataSequence::getTextualData(  ) throw (uno::RuntimeException)
3035 {
3036     ScUnoGuard aGuard;
3037     if ( !m_pDocument)
3038         throw uno::RuntimeException();
3039 
3040     BuildDataCache();
3041 
3042     sal_Int32 nCount = m_aDataArray.size();
3043     uno::Sequence<rtl::OUString> aSeq(nCount);
3044     rtl::OUString* pArr = aSeq.getArray();
3045     ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end();
3046     for (; itr != itrEnd; ++itr, ++pArr)
3047         *pArr = itr->maString;
3048 
3049     return aSeq;
3050 }
3051 
getSourceRangeRepresentation()3052 ::rtl::OUString SAL_CALL ScChart2DataSequence::getSourceRangeRepresentation()
3053             throw ( uno::RuntimeException)
3054 {
3055     ScUnoGuard aGuard;
3056     OUString aStr;
3057     DBG_ASSERT( m_pDocument, "No Document -> no SourceRangeRepresentation" );
3058     if (m_pDocument && m_pTokens.get())
3059         lcl_convertTokensToString(aStr, *m_pTokens, m_pDocument);
3060 
3061     return aStr;
3062 }
3063 
3064 namespace {
3065 
3066 /**
3067  * This function object is used to accumulatively count the numbers of
3068  * columns and rows in all reference tokens.
3069  */
3070 class AccumulateRangeSize : public unary_function<ScSharedTokenRef, void>
3071 {
3072 public:
AccumulateRangeSize()3073     AccumulateRangeSize() :
3074         mnCols(0), mnRows(0) {}
3075 
AccumulateRangeSize(const AccumulateRangeSize & r)3076     AccumulateRangeSize(const AccumulateRangeSize& r) :
3077         mnCols(r.mnCols), mnRows(r.mnRows) {}
3078 
operator ()(const ScSharedTokenRef & pToken)3079     void operator() (const ScSharedTokenRef& pToken)
3080     {
3081         ScRange r;
3082         bool bExternal = ScRefTokenHelper::isExternalRef(pToken);
3083         ScRefTokenHelper::getRangeFromToken(r, pToken, bExternal);
3084         r.Justify();
3085         mnCols += r.aEnd.Col() - r.aStart.Col() + 1;
3086         mnRows += r.aEnd.Row() - r.aStart.Row() + 1;
3087     }
3088 
getCols() const3089     SCCOL getCols() const { return mnCols; }
getRows() const3090     SCROW getRows() const { return mnRows; }
3091 private:
3092     SCCOL mnCols;
3093     SCROW mnRows;
3094 };
3095 
3096 /**
3097  * This function object is used to generate label strings from a list of
3098  * reference tokens.
3099  */
3100 class GenerateLabelStrings : public unary_function<ScSharedTokenRef, void>
3101 {
3102 public:
GenerateLabelStrings(sal_Int32 nSize,chart2::data::LabelOrigin eOrigin,bool bColumn)3103     GenerateLabelStrings(sal_Int32 nSize, chart2::data::LabelOrigin eOrigin, bool bColumn) :
3104         mpLabels(new Sequence<OUString>(nSize)),
3105         meOrigin(eOrigin),
3106         mnCount(0),
3107         mbColumn(bColumn) {}
3108 
GenerateLabelStrings(const GenerateLabelStrings & r)3109     GenerateLabelStrings(const GenerateLabelStrings& r) :
3110         mpLabels(r.mpLabels),
3111         meOrigin(r.meOrigin),
3112         mnCount(r.mnCount),
3113         mbColumn(r.mbColumn) {}
3114 
operator ()(const ScSharedTokenRef & pToken)3115     void operator() (const ScSharedTokenRef& pToken)
3116     {
3117         bool bExternal = ScRefTokenHelper::isExternalRef(pToken);
3118         ScRange aRange;
3119         ScRefTokenHelper::getRangeFromToken(aRange, pToken, bExternal);
3120         OUString* pArr = mpLabels->getArray();
3121         if (mbColumn)
3122         {
3123             for (SCCOL nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol)
3124             {
3125                 if ( meOrigin != chart2::data::LabelOrigin_LONG_SIDE)
3126                 {
3127                     String aString = ScGlobal::GetRscString(STR_COLUMN);
3128                     aString += ' ';
3129                     ScAddress aPos( nCol, 0, 0 );
3130                     String aColStr;
3131                     aPos.Format( aColStr, SCA_VALID_COL, NULL );
3132                     aString += aColStr;
3133                     pArr[mnCount] = aString;
3134                 }
3135                 else //only indices for categories
3136                     pArr[mnCount] = String::CreateFromInt32( mnCount+1 );
3137                 ++mnCount;
3138             }
3139         }
3140         else
3141         {
3142             for (sal_Int32 nRow = aRange.aStart.Row(); nRow <= aRange.aEnd.Row(); ++nRow)
3143             {
3144                 if (meOrigin != chart2::data::LabelOrigin_LONG_SIDE)
3145                 {
3146                     String aString = ScGlobal::GetRscString(STR_ROW);
3147                     aString += ' ';
3148                     aString += String::CreateFromInt32( nRow+1 );
3149                     pArr[mnCount] = aString;
3150                 }
3151                 else //only indices for categories
3152                     pArr[mnCount] = String::CreateFromInt32( mnCount+1 );
3153                 ++mnCount;
3154             }
3155         }
3156     }
3157 
getLabels() const3158     Sequence<OUString> getLabels() const { return *mpLabels; }
3159 
3160 private:
3161     GenerateLabelStrings(); // disabled
3162 
3163     shared_ptr< Sequence<OUString> >    mpLabels;
3164     chart2::data::LabelOrigin           meOrigin;
3165     sal_Int32                           mnCount;
3166     bool                                mbColumn;
3167 };
3168 
3169 }
3170 
generateLabel(chart2::data::LabelOrigin eOrigin)3171 uno::Sequence< ::rtl::OUString > SAL_CALL ScChart2DataSequence::generateLabel(chart2::data::LabelOrigin eOrigin)
3172         throw (uno::RuntimeException)
3173 {
3174     ScUnoGuard aGuard;
3175     if ( !m_pDocument)
3176         throw uno::RuntimeException();
3177 
3178     if (!m_pTokens.get())
3179         return Sequence<OUString>();
3180 
3181     // Determine the total size of all ranges.
3182     AccumulateRangeSize func;
3183     func = for_each(m_pTokens->begin(), m_pTokens->end(), func);
3184     SCCOL nCols = func.getCols();
3185     SCROW nRows = func.getRows();
3186 
3187     // Detemine whether this is column-major or row-major.
3188     bool bColumn = true;
3189     if ((eOrigin == chart2::data::LabelOrigin_SHORT_SIDE) ||
3190         (eOrigin == chart2::data::LabelOrigin_LONG_SIDE))
3191     {
3192         if (nRows > nCols)
3193         {
3194             if (eOrigin == chart2::data::LabelOrigin_SHORT_SIDE)
3195                 bColumn = true;
3196             else
3197                 bColumn = false;
3198         }
3199         else if (nCols > nRows)
3200         {
3201             if (eOrigin == chart2::data::LabelOrigin_SHORT_SIDE)
3202                 bColumn = false;
3203             else
3204                 bColumn = true;
3205         }
3206         else
3207             return Sequence<OUString>();
3208     }
3209 
3210     // Generate label strings based on the info so far.
3211     sal_Int32 nCount = bColumn ? nCols : nRows;
3212     GenerateLabelStrings genLabels(nCount, eOrigin, bColumn);
3213     genLabels = for_each(m_pTokens->begin(), m_pTokens->end(), genLabels);
3214     Sequence<OUString> aSeq = genLabels.getLabels();
3215 
3216     return aSeq;
3217 }
3218 
getNumberFormatKeyByIndex(::sal_Int32 nIndex)3219 ::sal_Int32 SAL_CALL ScChart2DataSequence::getNumberFormatKeyByIndex( ::sal_Int32 nIndex )
3220     throw (lang::IndexOutOfBoundsException,
3221            uno::RuntimeException)
3222 {
3223     // index -1 means a heuristic value for the entire sequence
3224     bool bGetSeriesFormat = (nIndex == -1);
3225     sal_Int32 nResult = 0;
3226 
3227     ScUnoGuard aGuard;
3228     if ( !m_pDocument || !m_pTokens.get())
3229         return nResult;
3230 
3231     sal_Int32 nCount = 0;
3232     bool bFound = false;
3233     ScRangePtr p;
3234 
3235     uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( lcl_GetSpreadSheetDocument( m_pDocument ));
3236     if (!xSpreadDoc.is())
3237         return nResult;
3238 
3239     uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
3240     if (!xIndex.is())
3241         return nResult;
3242 
3243     ScRangeList aRanges;
3244     ScRefTokenHelper::getRangeListFromTokens(aRanges, *m_pTokens);
3245     uno::Reference< table::XCellRange > xSheet;
3246     for ( p = aRanges.First(); p && !bFound; p = aRanges.Next())
3247     {
3248         // TODO: use DocIter?
3249         table::CellAddress aStart, aEnd;
3250         ScUnoConversion::FillApiAddress( aStart, p->aStart );
3251         ScUnoConversion::FillApiAddress( aEnd, p->aEnd );
3252         for ( sal_Int16 nSheet = aStart.Sheet; nSheet <= aEnd.Sheet && !bFound; ++nSheet)
3253         {
3254             xSheet.set(xIndex->getByIndex(nSheet), uno::UNO_QUERY);
3255             for ( sal_Int32 nCol = aStart.Column; nCol <= aEnd.Column && !bFound; ++nCol)
3256             {
3257                 for ( sal_Int32 nRow = aStart.Row; nRow <= aEnd.Row && !bFound; ++nRow)
3258                 {
3259                     if( bGetSeriesFormat )
3260                     {
3261                         // TODO: use nicer heuristic
3262                         // return format of first non-empty cell
3263                         uno::Reference< text::XText > xText(
3264                             xSheet->getCellByPosition(nCol, nRow), uno::UNO_QUERY);
3265                         if (xText.is() && xText->getString().getLength())
3266                         {
3267                             uno::Reference< beans::XPropertySet > xProp(xText, uno::UNO_QUERY);
3268                             if( xProp.is())
3269                                 xProp->getPropertyValue(
3270                                     ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NumberFormat"))) >>= nResult;
3271                             bFound = true;
3272                             break;
3273                         }
3274                     }
3275                     else if( nCount == nIndex )
3276                     {
3277                         uno::Reference< beans::XPropertySet > xProp(
3278                             xSheet->getCellByPosition(nCol, nRow), uno::UNO_QUERY);
3279                         if( xProp.is())
3280                             xProp->getPropertyValue(
3281                                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NumberFormat"))) >>= nResult;
3282                         bFound = true;
3283                         break;
3284                     }
3285                     ++nCount;
3286                 }
3287             }
3288         }
3289     }
3290 
3291     return nResult;
3292 }
3293 
3294 // XCloneable ================================================================
3295 
createClone()3296 uno::Reference< util::XCloneable > SAL_CALL ScChart2DataSequence::createClone()
3297     throw (uno::RuntimeException)
3298 {
3299     ScUnoGuard aGuard;
3300 
3301     auto_ptr< vector<ScSharedTokenRef> > pTokensNew;
3302     if (m_pTokens.get())
3303     {
3304         // Clone tokens.
3305         pTokensNew.reset(new vector<ScSharedTokenRef>);
3306         pTokensNew->reserve(m_pTokens->size());
3307         vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end();
3308         for (; itr != itrEnd; ++itr)
3309         {
3310             ScSharedTokenRef p(static_cast<ScToken*>((*itr)->Clone()));
3311             pTokensNew->push_back(p);
3312         }
3313     }
3314 
3315     auto_ptr<ScChart2DataSequence> p(new ScChart2DataSequence(m_pDocument, m_xDataProvider, pTokensNew.release(), m_bIncludeHiddenCells));
3316     p->CopyData(*this);
3317     Reference< util::XCloneable > xClone(p.release());
3318 
3319     return xClone;
3320 }
3321 
3322 // XModifyBroadcaster ========================================================
3323 
addModifyListener(const uno::Reference<util::XModifyListener> & aListener)3324 void SAL_CALL ScChart2DataSequence::addModifyListener( const uno::Reference< util::XModifyListener >& aListener )
3325     throw (uno::RuntimeException)
3326 {
3327     // like ScCellRangesBase::addModifyListener
3328 	ScUnoGuard aGuard;
3329     if (!m_pTokens.get() || m_pTokens->empty())
3330         return;
3331 
3332     ScRangeList aRanges;
3333     ScRefTokenHelper::getRangeListFromTokens(aRanges, *m_pTokens);
3334 	uno::Reference<util::XModifyListener> *pObj =
3335 			new uno::Reference<util::XModifyListener>( aListener );
3336 	m_aValueListeners.Insert( pObj, m_aValueListeners.Count() );
3337 
3338 	if ( m_aValueListeners.Count() == 1 )
3339 	{
3340 		if (!m_pValueListener)
3341 			m_pValueListener = new ScLinkListener( LINK( this, ScChart2DataSequence, ValueListenerHdl ) );
3342 
3343         if (!m_pHiddenListener.get())
3344             m_pHiddenListener.reset(new HiddenRangeListener(*this));
3345 
3346         if( m_pDocument )
3347         {
3348             ScChartListenerCollection* pCLC = m_pDocument->GetChartListenerCollection();
3349             vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end();
3350             for (; itr != itrEnd; ++itr)
3351             {
3352                 ScRange aRange;
3353                 if (!ScRefTokenHelper::getRangeFromToken(aRange, *itr))
3354                     continue;
3355 
3356                 m_pDocument->StartListeningArea( aRange, m_pValueListener );
3357                 if (pCLC)
3358                     pCLC->StartListeningHiddenRange(aRange, m_pHiddenListener.get());
3359             }
3360         }
3361 
3362 		acquire();	// don't lose this object (one ref for all listeners)
3363 	}
3364 }
3365 
removeModifyListener(const uno::Reference<util::XModifyListener> & aListener)3366 void SAL_CALL ScChart2DataSequence::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener )
3367     throw (uno::RuntimeException)
3368 {
3369     // like ScCellRangesBase::removeModifyListener
3370 
3371 	ScUnoGuard aGuard;
3372     if (!m_pTokens.get() || m_pTokens->empty())
3373         return;
3374 
3375 	acquire();		// in case the listeners have the last ref - released below
3376 
3377 	sal_uInt16 nCount = m_aValueListeners.Count();
3378 	for ( sal_uInt16 n=nCount; n--; )
3379 	{
3380 		uno::Reference<util::XModifyListener> *pObj = m_aValueListeners[n];
3381 		if ( *pObj == aListener )
3382 		{
3383 			m_aValueListeners.DeleteAndDestroy( n );
3384 
3385 			if ( m_aValueListeners.Count() == 0 )
3386 			{
3387 				if (m_pValueListener)
3388 					m_pValueListener->EndListeningAll();
3389 
3390                 if (m_pHiddenListener.get() && m_pDocument)
3391                 {
3392                     ScChartListenerCollection* pCLC = m_pDocument->GetChartListenerCollection();
3393                     if (pCLC)
3394                         pCLC->EndListeningHiddenRange(m_pHiddenListener.get());
3395                 }
3396 
3397 				release();		// release the ref for the listeners
3398 			}
3399 
3400 			break;
3401 		}
3402 	}
3403 
3404 	release();		// might delete this object
3405 }
3406 
3407 // DataSequence XPropertySet -------------------------------------------------
3408 
3409 uno::Reference< beans::XPropertySetInfo> SAL_CALL
getPropertySetInfo()3410 ScChart2DataSequence::getPropertySetInfo() throw( uno::RuntimeException)
3411 {
3412 	ScUnoGuard aGuard;
3413 	static uno::Reference<beans::XPropertySetInfo> aRef =
3414 		new SfxItemPropertySetInfo( m_aPropSet.getPropertyMap() );
3415 	return aRef;
3416 }
3417 
3418 
setPropertyValue(const::rtl::OUString & rPropertyName,const uno::Any & rValue)3419 void SAL_CALL ScChart2DataSequence::setPropertyValue(
3420         const ::rtl::OUString& rPropertyName, const uno::Any& rValue)
3421             throw( beans::UnknownPropertyException,
3422                     beans::PropertyVetoException,
3423                     lang::IllegalArgumentException,
3424                     lang::WrappedTargetException, uno::RuntimeException)
3425 {
3426     if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE)))
3427     {
3428         if ( !(rValue >>= m_aRole))
3429             throw lang::IllegalArgumentException();
3430     }
3431     else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS)))
3432     {
3433         sal_Bool bOldValue = m_bIncludeHiddenCells;
3434         if ( !(rValue >>= m_bIncludeHiddenCells))
3435             throw lang::IllegalArgumentException();
3436         if( bOldValue != m_bIncludeHiddenCells )
3437             m_aDataArray.clear();//data array is dirty now
3438     }
3439     else
3440         throw beans::UnknownPropertyException();
3441     // TODO: support optional properties
3442 }
3443 
3444 
getPropertyValue(const::rtl::OUString & rPropertyName)3445 uno::Any SAL_CALL ScChart2DataSequence::getPropertyValue(
3446         const ::rtl::OUString& rPropertyName)
3447             throw( beans::UnknownPropertyException,
3448                     lang::WrappedTargetException, uno::RuntimeException)
3449 {
3450     uno::Any aRet;
3451     if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE)))
3452         aRet <<= m_aRole;
3453     else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS)))
3454         aRet <<= m_bIncludeHiddenCells;
3455     else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(SC_UNONAME_HIDDENVALUES)))
3456     {
3457         // This property is read-only thus cannot be set externally via
3458         // setPropertyValue(...).
3459         BuildDataCache();
3460         aRet <<= m_aHiddenValues;
3461     }
3462     else
3463         throw beans::UnknownPropertyException();
3464     // TODO: support optional properties
3465     return aRet;
3466 }
3467 
3468 
addPropertyChangeListener(const::rtl::OUString &,const uno::Reference<beans::XPropertyChangeListener> &)3469 void SAL_CALL ScChart2DataSequence::addPropertyChangeListener(
3470         const ::rtl::OUString& /*rPropertyName*/,
3471         const uno::Reference< beans::XPropertyChangeListener>& /*xListener*/)
3472             throw( beans::UnknownPropertyException,
3473                     lang::WrappedTargetException, uno::RuntimeException)
3474 {
3475     // FIXME: real implementation
3476 //     throw uno::RuntimeException();
3477     OSL_ENSURE( false, "Not yet implemented" );
3478 }
3479 
3480 
removePropertyChangeListener(const::rtl::OUString &,const uno::Reference<beans::XPropertyChangeListener> &)3481 void SAL_CALL ScChart2DataSequence::removePropertyChangeListener(
3482         const ::rtl::OUString& /*rPropertyName*/,
3483         const uno::Reference< beans::XPropertyChangeListener>& /*rListener*/)
3484             throw( beans::UnknownPropertyException,
3485                     lang::WrappedTargetException, uno::RuntimeException)
3486 {
3487     // FIXME: real implementation
3488 //     throw uno::RuntimeException();
3489     OSL_ENSURE( false, "Not yet implemented" );
3490 }
3491 
3492 
addVetoableChangeListener(const::rtl::OUString &,const uno::Reference<beans::XVetoableChangeListener> &)3493 void SAL_CALL ScChart2DataSequence::addVetoableChangeListener(
3494         const ::rtl::OUString& /*rPropertyName*/,
3495         const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/)
3496             throw( beans::UnknownPropertyException,
3497                     lang::WrappedTargetException, uno::RuntimeException)
3498 {
3499     // FIXME: real implementation
3500 //     throw uno::RuntimeException();
3501     OSL_ENSURE( false, "Not yet implemented" );
3502 }
3503 
3504 
removeVetoableChangeListener(const::rtl::OUString &,const uno::Reference<beans::XVetoableChangeListener> &)3505 void SAL_CALL ScChart2DataSequence::removeVetoableChangeListener(
3506         const ::rtl::OUString& /*rPropertyName*/,
3507         const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/)
3508             throw( beans::UnknownPropertyException,
3509                     lang::WrappedTargetException, uno::RuntimeException)
3510 {
3511     // FIXME: real implementation
3512 //     throw uno::RuntimeException();
3513     OSL_ENSURE( false, "Not yet implemented" );
3514 }
3515 
setDataChangedHint(bool b)3516 void ScChart2DataSequence::setDataChangedHint(bool b)
3517 {
3518     m_bGotDataChangedHint = b;
3519 }
3520 
3521 // XUnoTunnel
3522 
3523 // sal_Int64 SAL_CALL ScChart2DataSequence::getSomething(
3524 // 				const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException)
3525 // {
3526 // 	if ( rId.getLength() == 16 &&
3527 //           0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
3528 // 									rId.getConstArray(), 16 ) )
3529 // 	{
3530 // 		return (sal_Int64)this;
3531 // 	}
3532 // 	return 0;
3533 // }
3534 
3535 // // static
3536 // const uno::Sequence<sal_Int8>& ScChart2DataSequence::getUnoTunnelId()
3537 // {
3538 // 	static uno::Sequence<sal_Int8> * pSeq = 0;
3539 // 	if( !pSeq )
3540 // 	{
3541 // 		osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
3542 // 		if( !pSeq )
3543 // 		{
3544 // 			static uno::Sequence< sal_Int8 > aSeq( 16 );
3545 // 			rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
3546 // 			pSeq = &aSeq;
3547 // 		}
3548 // 	}
3549 // 	return *pSeq;
3550 // }
3551 
3552 // // static
3553 // ScChart2DataSequence* ScChart2DataSequence::getImplementation( const uno::Reference<uno::XInterface> xObj )
3554 // {
3555 // 	ScChart2DataSequence* pRet = NULL;
3556 // 	uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY );
3557 // 	if (xUT.is())
3558 // 		pRet = (ScChart2DataSequence*) xUT->getSomething( getUnoTunnelId() );
3559 // 	return pRet;
3560 // }
3561 
3562 #if USE_CHART2_EMPTYDATASEQUENCE
3563 // DataSequence ==============================================================
3564 
ScChart2EmptyDataSequence(ScDocument * pDoc,const uno::Reference<chart2::data::XDataProvider> & xDP,const ScRangeListRef & rRangeList,sal_Bool bColumn)3565 ScChart2EmptyDataSequence::ScChart2EmptyDataSequence( ScDocument* pDoc,
3566         const uno::Reference < chart2::data::XDataProvider >& xDP,
3567         const ScRangeListRef& rRangeList,
3568         sal_Bool bColumn)
3569     : m_bIncludeHiddenCells( sal_True)
3570     , m_xRanges( rRangeList)
3571     , m_pDocument( pDoc)
3572     , m_xDataProvider( xDP)
3573 	, m_aPropSet(lcl_GetDataSequencePropertyMap())
3574     , m_bColumn(bColumn)
3575 {
3576     if ( m_pDocument )
3577         m_pDocument->AddUnoObject( *this);
3578     // FIXME: real implementation of identifier and it's mapping to ranges.
3579     // Reuse ScChartListener?
3580 
3581     // BM: don't use names of named ranges but the UI range strings
3582 //	String	aStr;
3583 //	rRangeList->Format( aStr, SCR_ABS_3D, m_pDocument );
3584 //    m_aIdentifier = ::rtl::OUString( aStr );
3585 
3586 //      m_aIdentifier = ::rtl::OUString::createFromAscii( "ID_");
3587 //      static sal_Int32 nID = 0;
3588 //      m_aIdentifier += ::rtl::OUString::valueOf( ++nID);
3589 }
3590 
3591 
~ScChart2EmptyDataSequence()3592 ScChart2EmptyDataSequence::~ScChart2EmptyDataSequence()
3593 {
3594     if ( m_pDocument )
3595         m_pDocument->RemoveUnoObject( *this);
3596 }
3597 
3598 
Notify(SfxBroadcaster &,const SfxHint & rHint)3599 void ScChart2EmptyDataSequence::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
3600 {
3601     if ( rHint.ISA( SfxSimpleHint ) &&
3602             ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
3603     {
3604         m_pDocument = NULL;
3605     }
3606 }
3607 
3608 
getData()3609 uno::Sequence< uno::Any> SAL_CALL ScChart2EmptyDataSequence::getData()
3610             throw ( uno::RuntimeException)
3611 {
3612     ScUnoGuard aGuard;
3613     if ( !m_pDocument)
3614         throw uno::RuntimeException();
3615     return uno::Sequence< uno::Any>();
3616 }
3617 
3618 // XTextualDataSequence --------------------------------------------------
3619 
getTextualData()3620 uno::Sequence< rtl::OUString > SAL_CALL ScChart2EmptyDataSequence::getTextualData(  ) throw (uno::RuntimeException)
3621 {
3622     ScUnoGuard aGuard;
3623     if ( !m_pDocument)
3624         throw uno::RuntimeException();
3625 
3626     sal_Int32 nCount = 0;
3627     ScRangePtr p;
3628 
3629     DBG_ASSERT(m_xRanges->Count() == 1, "not handled count of ranges");
3630 
3631     for ( p = m_xRanges->First(); p; p = m_xRanges->Next())
3632     {
3633         p->Justify();
3634         // TODO: handle overlaping ranges?
3635         nCount += m_bColumn ? p->aEnd.Col() - p->aStart.Col() + 1 : p->aEnd.Row() - p->aStart.Row() + 1;
3636     }
3637     uno::Sequence< rtl::OUString > aSeq( nCount);
3638     rtl::OUString* pArr = aSeq.getArray();
3639     nCount = 0;
3640     for ( p = m_xRanges->First(); p; p = m_xRanges->Next())
3641     {
3642         if (m_bColumn)
3643         {
3644             for (SCCOL nCol = p->aStart.Col(); nCol <= p->aEnd.Col(); ++nCol)
3645             {
3646 			    String aString = ScGlobal::GetRscString(STR_COLUMN);
3647 			    aString += ' ';
3648                 ScAddress aPos( nCol, 0, 0 );
3649                 String aColStr;
3650                 aPos.Format( aColStr, SCA_VALID_COL, NULL );
3651                 aString += aColStr;
3652                 pArr[nCount] = aString;
3653                 ++nCount;
3654             }
3655         }
3656         else
3657         {
3658             for (sal_Int32 nRow = p->aStart.Row(); nRow <= p->aEnd.Row(); ++nRow)
3659             {
3660 			    String aString = ScGlobal::GetRscString(STR_ROW);
3661 			    aString += ' ';
3662 			    aString += String::CreateFromInt32( nRow+1 );
3663                 pArr[nCount] = aString;
3664                 ++nCount;
3665             }
3666         }
3667     }
3668     return aSeq;
3669 }
3670 
getSourceRangeRepresentation()3671 ::rtl::OUString SAL_CALL ScChart2EmptyDataSequence::getSourceRangeRepresentation()
3672             throw ( uno::RuntimeException)
3673 {
3674     ScUnoGuard aGuard;
3675 	String	aStr;
3676     DBG_ASSERT( m_pDocument, "No Document -> no SourceRangeRepresentation" );
3677     if( m_pDocument )
3678 	    m_xRanges->Format( aStr, SCR_ABS_3D, m_pDocument, m_pDocument->GetAddressConvention() );
3679 	return aStr;
3680 }
3681 
generateLabel(chart2::data::LabelOrigin)3682 uno::Sequence< ::rtl::OUString > SAL_CALL ScChart2EmptyDataSequence::generateLabel(chart2::data::LabelOrigin /*nOrigin*/)
3683         throw (uno::RuntimeException)
3684 {
3685     ScUnoGuard aGuard;
3686     uno::Sequence< ::rtl::OUString > aRet;
3687     return aRet;
3688 }
3689 
getNumberFormatKeyByIndex(::sal_Int32)3690 ::sal_Int32 SAL_CALL ScChart2EmptyDataSequence::getNumberFormatKeyByIndex( ::sal_Int32 /*nIndex*/ )
3691     throw (lang::IndexOutOfBoundsException,
3692            uno::RuntimeException)
3693 {
3694     sal_Int32 nResult = 0;
3695 
3696     ScUnoGuard aGuard;
3697     if ( !m_pDocument)
3698         return nResult;
3699 
3700     return nResult;
3701 }
3702 
3703 // XCloneable ================================================================
3704 
createClone()3705 uno::Reference< util::XCloneable > SAL_CALL ScChart2EmptyDataSequence::createClone()
3706     throw (uno::RuntimeException)
3707 {
3708     ScUnoGuard aGuard;
3709     if (m_xDataProvider.is())
3710     {
3711         // copy properties
3712         uno::Reference < util::XCloneable > xClone(new ScChart2EmptyDataSequence(m_pDocument, m_xDataProvider, new ScRangeList(*m_xRanges), m_bColumn));
3713         uno::Reference< beans::XPropertySet > xProp( xClone, uno::UNO_QUERY );
3714         if( xProp.is())
3715         {
3716             xProp->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_ROLE )),
3717                                      uno::makeAny( m_aRole ));
3718             xProp->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS )),
3719                                      uno::makeAny( m_bIncludeHiddenCells ));
3720         }
3721         return xClone;
3722     }
3723     return uno::Reference< util::XCloneable >();
3724 }
3725 
3726 // XModifyBroadcaster ========================================================
3727 
addModifyListener(const uno::Reference<util::XModifyListener> &)3728 void SAL_CALL ScChart2EmptyDataSequence::addModifyListener( const uno::Reference< util::XModifyListener >& /*aListener*/ )
3729     throw (uno::RuntimeException)
3730 {
3731     // TODO: Implement
3732 }
3733 
removeModifyListener(const uno::Reference<util::XModifyListener> &)3734 void SAL_CALL ScChart2EmptyDataSequence::removeModifyListener( const uno::Reference< util::XModifyListener >& /*aListener*/ )
3735     throw (uno::RuntimeException)
3736 {
3737     // TODO: Implement
3738 }
3739 
3740 // DataSequence XPropertySet -------------------------------------------------
3741 
3742 uno::Reference< beans::XPropertySetInfo> SAL_CALL
getPropertySetInfo()3743 ScChart2EmptyDataSequence::getPropertySetInfo() throw( uno::RuntimeException)
3744 {
3745 	ScUnoGuard aGuard;
3746 	static uno::Reference<beans::XPropertySetInfo> aRef =
3747 		new SfxItemPropertySetInfo( m_aPropSet.getPropertyMap() );
3748 	return aRef;
3749 }
3750 
3751 
setPropertyValue(const::rtl::OUString & rPropertyName,const uno::Any & rValue)3752 void SAL_CALL ScChart2EmptyDataSequence::setPropertyValue(
3753         const ::rtl::OUString& rPropertyName, const uno::Any& rValue)
3754             throw( beans::UnknownPropertyException,
3755                     beans::PropertyVetoException,
3756                     lang::IllegalArgumentException,
3757                     lang::WrappedTargetException, uno::RuntimeException)
3758 {
3759     if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE)))
3760     {
3761         if ( !(rValue >>= m_aRole))
3762             throw lang::IllegalArgumentException();
3763     }
3764     else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS)))
3765     {
3766         if ( !(rValue >>= m_bIncludeHiddenCells))
3767             throw lang::IllegalArgumentException();
3768     }
3769     else
3770         throw beans::UnknownPropertyException();
3771     // TODO: support optional properties
3772 }
3773 
3774 
getPropertyValue(const::rtl::OUString & rPropertyName)3775 uno::Any SAL_CALL ScChart2EmptyDataSequence::getPropertyValue(
3776         const ::rtl::OUString& rPropertyName)
3777             throw( beans::UnknownPropertyException,
3778                     lang::WrappedTargetException, uno::RuntimeException)
3779 {
3780     uno::Any aRet;
3781     if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE)))
3782         aRet <<= m_aRole;
3783     else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS)))
3784         aRet <<= m_bIncludeHiddenCells;
3785     else
3786         throw beans::UnknownPropertyException();
3787     // TODO: support optional properties
3788     return aRet;
3789 }
3790 
3791 
addPropertyChangeListener(const::rtl::OUString &,const uno::Reference<beans::XPropertyChangeListener> &)3792 void SAL_CALL ScChart2EmptyDataSequence::addPropertyChangeListener(
3793         const ::rtl::OUString& /*rPropertyName*/,
3794         const uno::Reference< beans::XPropertyChangeListener>& /*xListener*/)
3795             throw( beans::UnknownPropertyException,
3796                     lang::WrappedTargetException, uno::RuntimeException)
3797 {
3798     // FIXME: real implementation
3799 //     throw uno::RuntimeException();
3800     OSL_ENSURE( false, "Not yet implemented" );
3801 }
3802 
3803 
removePropertyChangeListener(const::rtl::OUString &,const uno::Reference<beans::XPropertyChangeListener> &)3804 void SAL_CALL ScChart2EmptyDataSequence::removePropertyChangeListener(
3805         const ::rtl::OUString& /*rPropertyName*/,
3806         const uno::Reference< beans::XPropertyChangeListener>& /*rListener*/)
3807             throw( beans::UnknownPropertyException,
3808                     lang::WrappedTargetException, uno::RuntimeException)
3809 {
3810     // FIXME: real implementation
3811 //     throw uno::RuntimeException();
3812     OSL_ENSURE( false, "Not yet implemented" );
3813 }
3814 
3815 
addVetoableChangeListener(const::rtl::OUString &,const uno::Reference<beans::XVetoableChangeListener> &)3816 void SAL_CALL ScChart2EmptyDataSequence::addVetoableChangeListener(
3817         const ::rtl::OUString& /*rPropertyName*/,
3818         const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/)
3819             throw( beans::UnknownPropertyException,
3820                     lang::WrappedTargetException, uno::RuntimeException)
3821 {
3822     // FIXME: real implementation
3823 //     throw uno::RuntimeException();
3824     OSL_ENSURE( false, "Not yet implemented" );
3825 }
3826 
3827 
removeVetoableChangeListener(const::rtl::OUString &,const uno::Reference<beans::XVetoableChangeListener> &)3828 void SAL_CALL ScChart2EmptyDataSequence::removeVetoableChangeListener(
3829         const ::rtl::OUString& /*rPropertyName*/,
3830         const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/ )
3831             throw( beans::UnknownPropertyException,
3832                     lang::WrappedTargetException, uno::RuntimeException)
3833 {
3834     // FIXME: real implementation
3835 //     throw uno::RuntimeException();
3836     OSL_ENSURE( false, "Not yet implemented" );
3837 }
3838 
3839 // XUnoTunnel
3840 
3841 // sal_Int64 SAL_CALL ScChart2EmptyDataSequence::getSomething(
3842 // 				const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException)
3843 // {
3844 // 	if ( rId.getLength() == 16 &&
3845 //           0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
3846 // 									rId.getConstArray(), 16 ) )
3847 // 	{
3848 // 		return (sal_Int64)this;
3849 // 	}
3850 // 	return 0;
3851 // }
3852 
3853 // // static
3854 // const uno::Sequence<sal_Int8>& ScChart2EmptyDataSequence::getUnoTunnelId()
3855 // {
3856 // 	static uno::Sequence<sal_Int8> * pSeq = 0;
3857 // 	if( !pSeq )
3858 // 	{
3859 // 		osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
3860 // 		if( !pSeq )
3861 // 		{
3862 // 			static uno::Sequence< sal_Int8 > aSeq( 16 );
3863 // 			rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
3864 // 			pSeq = &aSeq;
3865 // 		}
3866 // 	}
3867 // 	return *pSeq;
3868 // }
3869 
3870 // // static
3871 // ScChart2DataSequence* ScChart2EmptyDataSequence::getImplementation( const uno::Reference<uno::XInterface> xObj )
3872 // {
3873 // 	ScChart2DataSequence* pRet = NULL;
3874 // 	uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY );
3875 // 	if (xUT.is())
3876 // 		pRet = (ScChart2EmptyDataSequence*) xUT->getSomething( getUnoTunnelId() );
3877 // 	return pRet;
3878 // }
3879 #endif
3880