1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "scitems.hxx"
21 #include <svl/intitem.hxx>
22 #include <svl/zforlist.hxx>
25 #include "chartarr.hxx"
26 #include "document.hxx"
27 #include "rechead.hxx"
28 #include "globstr.hrc"
29 #include "formulacell.hxx"
30 #include "docoptio.hxx"
36 ScMemChart::ScMemChart(SCCOL nCols
, SCROW nRows
)
40 pData
= new double[nColCnt
* nRowCnt
];
42 double *pFill
= pData
;
44 for (SCCOL i
= 0; i
< nColCnt
; i
++)
45 for (SCROW j
= 0; j
< nRowCnt
; j
++)
48 pColText
= new OUString
[nColCnt
];
49 pRowText
= new OUString
[nRowCnt
];
52 ScMemChart::~ScMemChart()
59 ScChartArray::ScChartArray( ScDocument
* pDoc
, SCTAB nTab
,
60 SCCOL nStartColP
, SCROW nStartRowP
, SCCOL nEndColP
, SCROW nEndRowP
,
61 const OUString
& rChartName
) :
64 aPositioner(pDoc
, nTab
, nStartColP
, nStartRowP
, nEndColP
, nEndRowP
),
69 ScChartArray::ScChartArray(
70 ScDocument
* pDoc
, const ScRangeListRef
& rRangeList
, const OUString
& rChartName
) :
73 aPositioner(pDoc
, rRangeList
),
76 ScChartArray::ScChartArray( const ScChartArray
& rArr
) :
78 pDocument(rArr
.pDocument
),
79 aPositioner(rArr
.aPositioner
),
80 bValid(rArr
.bValid
) {}
82 ScChartArray::~ScChartArray() {}
84 bool ScChartArray::operator==(const ScChartArray
& rCmp
) const
86 return aPositioner
== rCmp
.aPositioner
87 && aName
== rCmp
.aName
;
90 ScMemChart
* ScChartArray::CreateMemChart()
92 ScRangeListRef
aRangeListRef(GetRangeList());
93 size_t nCount
= aRangeListRef
->size();
95 return CreateMemChartMulti();
96 else if ( nCount
== 1 )
98 ScRange
* pR
= aRangeListRef
->front();
99 if ( pR
->aStart
.Tab() != pR
->aEnd
.Tab() )
100 return CreateMemChartMulti();
102 return CreateMemChartSingle();
105 return CreateMemChartMulti(); // Can handle 0 range better than Single
110 double getCellValue( ScDocument
& rDoc
, const ScAddress
& rPos
, double fDefault
, bool bCalcAsShown
)
112 double fRet
= fDefault
;
114 CellType eType
= rDoc
.GetCellType(rPos
);
119 fRet
= rDoc
.GetValue(rPos
);
120 if (bCalcAsShown
&& fRet
!= 0.0)
122 sal_uInt32 nFormat
= rDoc
.GetNumberFormat(rPos
);
123 fRet
= rDoc
.RoundValueAsShown(fRet
, nFormat
);
127 case CELLTYPE_FORMULA
:
129 ScFormulaCell
* pFCell
= rDoc
.GetFormulaCell(rPos
);
130 if (pFCell
&& !pFCell
->GetErrCode() && pFCell
->IsValue())
131 fRet
= pFCell
->GetValue();
142 ScMemChart
* ScChartArray::CreateMemChartSingle()
147 // real size (without hidden rows/columns)
149 SCCOL nColAdd
= HasRowHeaders() ? 1 : 0;
150 SCROW nRowAdd
= HasColHeaders() ? 1 : 0;
158 ScRangeListRef
aRangeListRef(GetRangeList());
159 aRangeListRef
->front()->GetVars( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
161 SCCOL nStrCol
= nCol1
; // remember for labeling
162 SCROW nStrRow
= nRow1
;
163 // Skip hidden columns.
164 // TODO: make use of last column value once implemented.
166 while (pDocument
->ColHidden(nCol1
, nTab1
, NULL
, &nLastCol
))
171 if (pDocument
->RowHidden(nRow1
, nTab1
, NULL
, &nLastRow
))
172 nRow1
= nLastRow
+ 1;
174 // if everything is hidden then the label remains at the beginning
175 if ( nCol1
<= nCol2
)
178 nCol1
= sal::static_int_cast
<SCCOL
>( nCol1
+ nColAdd
);
180 if ( nRow1
<= nRow2
)
183 nRow1
= sal::static_int_cast
<SCROW
>( nRow1
+ nRowAdd
);
186 SCSIZE nTotalCols
= ( nCol1
<= nCol2
? nCol2
- nCol1
+ 1 : 0 );
188 aCols
.reserve(nTotalCols
);
189 for (SCSIZE i
=0; i
<nTotalCols
; i
++)
191 SCCOL nThisCol
= sal::static_int_cast
<SCCOL
>(nCol1
+i
);
192 if (!pDocument
->ColHidden(nThisCol
, nTab1
, NULL
, &nLastCol
))
193 aCols
.push_back(nThisCol
);
195 SCSIZE nColCount
= aCols
.size();
197 SCSIZE nTotalRows
= ( nRow1
<= nRow2
? nRow2
- nRow1
+ 1 : 0 );
199 aRows
.reserve(nTotalRows
);
202 // Get all visible rows between nRow1 and nRow2.
203 SCROW nThisRow
= nRow1
;
204 while (nThisRow
<= nRow2
)
206 if (pDocument
->RowHidden(nThisRow
, nTab1
, NULL
, &nLastRow
))
209 aRows
.push_back(nThisRow
);
213 SCSIZE nRowCount
= aRows
.size();
215 // May happen at least with more than 32k rows.
216 if (nColCount
> SHRT_MAX
|| nRowCount
> SHRT_MAX
)
222 bool bValidData
= true;
227 aCols
.push_back(nStrCol
);
233 aRows
.push_back(nStrRow
);
237 ScMemChart
* pMemChart
= new ScMemChart( nColCount
, nRowCount
);
241 bool bCalcAsShown
= pDocument
->GetDocOptions().IsCalcAsShown();
242 for (nCol
=0; nCol
<nColCount
; nCol
++)
244 for (nRow
=0; nRow
<nRowCount
; nRow
++)
246 // DBL_MIN is a Hack for Chart to recognize empty cells.
247 ScAddress
aPos(aCols
[nCol
], aRows
[nRow
], nTab1
);
248 double nVal
= getCellValue(*pDocument
, aPos
, DBL_MIN
, bCalcAsShown
);
249 pMemChart
->SetData(nCol
, nRow
, nVal
);
255 // Flag marking data as invalid?
256 for (nCol
=0; nCol
<nColCount
; nCol
++)
257 for (nRow
=0; nRow
<nRowCount
; nRow
++)
258 pMemChart
->SetData( nCol
, nRow
, DBL_MIN
);
263 for (nCol
=0; nCol
<nColCount
; nCol
++)
267 aString
= pDocument
->GetString(aCols
[nCol
], nStrRow
, nTab1
);
268 if (aString
.isEmpty())
271 aBuf
.append(ScGlobal::GetRscString(STR_COLUMN
));
274 ScAddress
aPos( aCols
[ nCol
], 0, 0 );
275 aBuf
.append(aPos
.Format(SCA_VALID_COL
, NULL
));
277 aString
= aBuf
.makeStringAndClear();
279 pMemChart
->SetColText( nCol
, aString
);
284 for (nRow
=0; nRow
<nRowCount
; nRow
++)
289 ScAddress
aAddr( nStrCol
, aRows
[nRow
], nTab1
);
290 aString
= pDocument
->GetString(nStrCol
, aRows
[nRow
], nTab1
);
292 if (aString
.isEmpty())
295 aBuf
.append(ScGlobal::GetRscString(STR_ROW
));
297 aBuf
.append(static_cast<sal_Int32
>(aRows
[nRow
]+1));
298 aString
= aBuf
.makeStringAndClear();
300 pMemChart
->SetRowText( nRow
, aString
);
306 ScMemChart
* ScChartArray::CreateMemChartMulti()
308 SCSIZE nColCount
= GetPositionMap()->GetColCount();
309 SCSIZE nRowCount
= GetPositionMap()->GetRowCount();
311 // May happen at least with more than 32k rows.
312 if (nColCount
> SHRT_MAX
|| nRowCount
> SHRT_MAX
)
318 bool bValidData
= true;
331 ScMemChart
* pMemChart
= new ScMemChart( nColCount
, nRowCount
);
335 bool bCalcAsShown
= pDocument
->GetDocOptions().IsCalcAsShown();
336 sal_uLong nIndex
= 0;
339 for ( nCol
= 0; nCol
< nColCount
; nCol
++ )
341 for ( nRow
= 0; nRow
< nRowCount
; nRow
++, nIndex
++ )
343 double nVal
= DBL_MIN
; // Hack for Chart to recognize empty cells
344 const ScAddress
* pPos
= GetPositionMap()->GetPosition( nIndex
);
347 nVal
= getCellValue(*pDocument
, *pPos
, DBL_MIN
, bCalcAsShown
);
349 pMemChart
->SetData(nCol
, nRow
, nVal
);
355 for ( nRow
= 0; nRow
< nRowCount
; nRow
++, nIndex
++ )
357 double nVal
= DBL_MIN
; // Hack for Chart to recognize empty cells
358 const ScAddress
* pPos
= GetPositionMap()->GetPosition( nIndex
);
361 nVal
= getCellValue(*pDocument
, *pPos
, DBL_MIN
, bCalcAsShown
);
363 pMemChart
->SetData(nCol
, nRow
, nVal
);
367 //TODO: Label when gaps
372 for ( nCol
= 0; nCol
< nColCount
; nCol
++ )
375 const ScAddress
* pPos
= GetPositionMap()->GetColHeaderPosition( static_cast<SCCOL
>(nCol
) );
376 if ( HasColHeaders() && pPos
)
377 aString
= pDocument
->GetString(pPos
->Col(), pPos
->Row(), pPos
->Tab());
379 if (aString
.isEmpty())
381 OUStringBuffer
aBuf(ScGlobal::GetRscString(STR_COLUMN
));
384 nPosCol
= pPos
->Col() + 1;
387 ScAddress
aPos( nPosCol
- 1, 0, 0 );
388 aBuf
.append(aPos
.Format(SCA_VALID_COL
, NULL
));
389 aString
= aBuf
.makeStringAndClear();
391 pMemChart
->SetColText( nCol
, aString
);
397 for ( nRow
= 0; nRow
< nRowCount
; nRow
++ )
400 const ScAddress
* pPos
= GetPositionMap()->GetRowHeaderPosition( nRow
);
401 if ( HasRowHeaders() && pPos
)
402 aString
= pDocument
->GetString(pPos
->Col(), pPos
->Row(), pPos
->Tab());
404 if (aString
.isEmpty())
406 OUStringBuffer
aBuf(ScGlobal::GetRscString(STR_ROW
));
409 nPosRow
= pPos
->Row() + 1;
412 aBuf
.append(static_cast<sal_Int32
>(nPosRow
));
413 aString
= aBuf
.makeStringAndClear();
415 pMemChart
->SetRowText( nRow
, aString
);
421 ScChartCollection::ScChartCollection() {}
422 ScChartCollection::ScChartCollection(const ScChartCollection
& r
) :
425 void ScChartCollection::push_back(ScChartArray
* p
)
430 void ScChartCollection::clear()
435 size_t ScChartCollection::size() const
437 return maData
.size();
440 bool ScChartCollection::empty() const
442 return maData
.empty();
445 ScChartArray
* ScChartCollection::operator[](size_t nIndex
)
447 if (maData
.size() <= nIndex
)
449 return &maData
[nIndex
];
452 const ScChartArray
* ScChartCollection::operator[](size_t nIndex
) const
454 if (maData
.size() <= nIndex
)
456 return &maData
[nIndex
];
459 bool ScChartCollection::operator==(const ScChartCollection
& rCmp
) const
461 return maData
== rCmp
.maData
;
464 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */