Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / core / tool / chartarr.cxx
blob627068a5f731c99457e3f8aacc01dc3c177593cd
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
23 #include <float.h>
25 #include "chartarr.hxx"
26 #include "document.hxx"
27 #include "rechead.hxx"
28 #include "globstr.hrc"
29 #include "formulacell.hxx"
30 #include "docoptio.hxx"
32 #include <vector>
34 using ::std::vector;
36 ScMemChart::ScMemChart(short nCols, short nRows)
38 nRowCnt = nRows;
39 nColCnt = nCols;
40 pData = new double[nColCnt * nRowCnt];
42 if (pData)
44 double *pFill = pData;
46 for (short i = 0; i < nColCnt; i++)
47 for (short j = 0; j < nRowCnt; j++)
48 *(pFill ++) = 0.0;
51 pColText = new OUString[nColCnt];
52 pRowText = new OUString[nRowCnt];
55 ScMemChart::~ScMemChart()
57 delete[] pRowText;
58 delete[] pColText;
59 delete[] pData;
62 ScChartArray::ScChartArray( ScDocument* pDoc, SCTAB nTab,
63 SCCOL nStartColP, SCROW nStartRowP, SCCOL nEndColP, SCROW nEndRowP,
64 const OUString& rChartName ) :
65 aName( rChartName ),
66 pDocument( pDoc ),
67 aPositioner(pDoc, nTab, nStartColP, nStartRowP, nEndColP, nEndRowP),
68 bValid( true )
72 ScChartArray::ScChartArray(
73 ScDocument* pDoc, const ScRangeListRef& rRangeList, const OUString& rChartName ) :
74 aName( rChartName ),
75 pDocument( pDoc ),
76 aPositioner(pDoc, rRangeList),
77 bValid( true ) {}
79 ScChartArray::ScChartArray( const ScChartArray& rArr ) :
80 aName(rArr.aName),
81 pDocument(rArr.pDocument),
82 aPositioner(rArr.aPositioner),
83 bValid(rArr.bValid) {}
85 ScChartArray::~ScChartArray() {}
87 bool ScChartArray::operator==(const ScChartArray& rCmp) const
89 return aPositioner == rCmp.aPositioner
90 && aName == rCmp.aName;
93 ScMemChart* ScChartArray::CreateMemChart()
95 ScRangeListRef aRangeListRef(GetRangeList());
96 size_t nCount = aRangeListRef->size();
97 if ( nCount > 1 )
98 return CreateMemChartMulti();
99 else if ( nCount == 1 )
101 ScRange* pR = aRangeListRef->front();
102 if ( pR->aStart.Tab() != pR->aEnd.Tab() )
103 return CreateMemChartMulti();
104 else
105 return CreateMemChartSingle();
107 else
108 return CreateMemChartMulti(); // Can handle 0 range better than Single
111 namespace {
113 double getCellValue( ScDocument& rDoc, const ScAddress& rPos, double fDefault, bool bCalcAsShown )
115 double fRet = fDefault;
117 CellType eType = rDoc.GetCellType(rPos);
118 switch (eType)
120 case CELLTYPE_VALUE:
122 fRet = rDoc.GetValue(rPos);
123 if (bCalcAsShown && fRet != 0.0)
125 sal_uInt32 nFormat = rDoc.GetNumberFormat(rPos);
126 fRet = rDoc.RoundValueAsShown(fRet, nFormat);
129 break;
130 case CELLTYPE_FORMULA:
132 ScFormulaCell* pFCell = rDoc.GetFormulaCell(rPos);
133 if (!pFCell->GetErrCode() && pFCell->IsValue())
134 fRet = pFCell->GetValue();
136 break;
137 default:
140 return fRet;
145 ScMemChart* ScChartArray::CreateMemChartSingle()
147 SCSIZE nCol;
148 SCSIZE nRow;
151 // real size (without hidden rows/columns)
154 SCCOL nColAdd = HasRowHeaders() ? 1 : 0;
155 SCROW nRowAdd = HasColHeaders() ? 1 : 0;
157 SCCOL nCol1;
158 SCROW nRow1;
159 SCTAB nTab1;
160 SCCOL nCol2;
161 SCROW nRow2;
162 SCTAB nTab2;
163 ScRangeListRef aRangeListRef(GetRangeList());
164 aRangeListRef->front()->GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
166 SCCOL nStrCol = nCol1; // remember for labeling
167 SCROW nStrRow = nRow1;
168 // Skip hidden columns.
169 // TODO: make use of last column value once implemented.
170 SCCOL nLastCol = -1;
171 while (pDocument->ColHidden(nCol1, nTab1, NULL, &nLastCol))
172 ++nCol1;
174 // Skip hidden rows.
175 SCROW nLastRow = -1;
176 if (pDocument->RowHidden(nRow1, nTab1, NULL, &nLastRow))
177 nRow1 = nLastRow + 1;
179 // if everything is hidden then the label remains at the beginning
180 if ( nCol1 <= nCol2 )
182 nStrCol = nCol1;
183 nCol1 = sal::static_int_cast<SCCOL>( nCol1 + nColAdd );
185 if ( nRow1 <= nRow2 )
187 nStrRow = nRow1;
188 nRow1 = sal::static_int_cast<SCROW>( nRow1 + nRowAdd );
191 SCSIZE nTotalCols = ( nCol1 <= nCol2 ? nCol2 - nCol1 + 1 : 0 );
192 vector<SCCOL> aCols;
193 aCols.reserve(nTotalCols);
194 for (SCSIZE i=0; i<nTotalCols; i++)
196 SCCOL nThisCol = sal::static_int_cast<SCCOL>(nCol1+i);
197 if (!pDocument->ColHidden(nThisCol, nTab1, NULL, &nLastCol))
198 aCols.push_back(nThisCol);
200 SCSIZE nColCount = aCols.size();
202 SCSIZE nTotalRows = ( nRow1 <= nRow2 ? nRow2 - nRow1 + 1 : 0 );
203 vector<SCROW> aRows;
204 aRows.reserve(nTotalRows);
205 if (nRow1 <= nRow2)
207 // Get all visible rows between nRow1 and nRow2.
208 SCROW nThisRow = nRow1;
209 while (nThisRow <= nRow2)
211 if (pDocument->RowHidden(nThisRow, nTab1, NULL, &nLastRow))
212 nThisRow = nLastRow;
213 else
214 aRows.push_back(nThisRow);
215 ++nThisRow;
218 SCSIZE nRowCount = aRows.size();
220 // May happen at least with more than 32k rows.
221 if (nColCount > SHRT_MAX || nRowCount > SHRT_MAX)
223 nColCount = 0;
224 nRowCount = 0;
227 bool bValidData = true;
228 if ( !nColCount )
230 bValidData = false;
231 nColCount = 1;
232 aCols.push_back(nStrCol);
234 if ( !nRowCount )
236 bValidData = false;
237 nRowCount = 1;
238 aRows.push_back(nStrRow);
242 // Data
245 ScMemChart* pMemChart = new ScMemChart(
246 static_cast<short>(nColCount), static_cast<short>(nRowCount) );
247 if (pMemChart)
249 if ( bValidData )
251 bool bCalcAsShown = pDocument->GetDocOptions().IsCalcAsShown();
252 for (nCol=0; nCol<nColCount; nCol++)
254 for (nRow=0; nRow<nRowCount; nRow++)
256 // DBL_MIN is a Hack for Chart to recognize empty cells.
257 ScAddress aPos(aCols[nCol], aRows[nRow], nTab1);
258 double nVal = getCellValue(*pDocument, aPos, DBL_MIN, bCalcAsShown);
259 pMemChart->SetData(static_cast<short>(nCol), static_cast<short>(nRow), nVal);
263 else
265 // Flag marking data as invalid?
266 for (nCol=0; nCol<nColCount; nCol++)
267 for (nRow=0; nRow<nRowCount; nRow++)
268 pMemChart->SetData( static_cast<short>(nCol), static_cast<short>(nRow), DBL_MIN );
272 // Column Header
274 for (nCol=0; nCol<nColCount; nCol++)
276 OUString aString;
277 if (HasColHeaders())
278 aString = pDocument->GetString(aCols[nCol], nStrRow, nTab1);
279 if (aString.isEmpty())
281 OUStringBuffer aBuf;
282 aBuf.append(ScGlobal::GetRscString(STR_COLUMN));
283 aBuf.append(' ');
285 ScAddress aPos( aCols[ nCol ], 0, 0 );
286 aBuf.append(aPos.Format(SCA_VALID_COL, NULL));
288 aString = aBuf.makeStringAndClear();
290 pMemChart->SetColText( static_cast<short>(nCol), aString);
294 // Row Header
296 for (nRow=0; nRow<nRowCount; nRow++)
298 OUString aString;
299 if (HasRowHeaders())
301 ScAddress aAddr( nStrCol, aRows[nRow], nTab1 );
302 aString = pDocument->GetString(nStrCol, aRows[nRow], nTab1);
304 if (aString.isEmpty())
306 OUStringBuffer aBuf;
307 aBuf.append(ScGlobal::GetRscString(STR_ROW));
308 aBuf.append(' ');
309 aBuf.append(static_cast<sal_Int32>(aRows[nRow]+1));
310 aString = aBuf.makeStringAndClear();
312 pMemChart->SetRowText( static_cast<short>(nRow), aString);
316 return pMemChart;
319 ScMemChart* ScChartArray::CreateMemChartMulti()
321 SCSIZE nColCount = GetPositionMap()->GetColCount();
322 SCSIZE nRowCount = GetPositionMap()->GetRowCount();
324 // May happen at least with more than 32k rows.
325 if (nColCount > SHRT_MAX || nRowCount > SHRT_MAX)
327 nColCount = 0;
328 nRowCount = 0;
331 bool bValidData = true;
332 if ( !nColCount )
334 bValidData = false;
335 nColCount = 1;
337 if ( !nRowCount )
339 bValidData = false;
340 nRowCount = 1;
344 // Data
347 ScMemChart* pMemChart = new ScMemChart(
348 static_cast<short>(nColCount), static_cast<short>(nRowCount) );
349 if (pMemChart)
351 SCSIZE nCol = 0;
352 SCSIZE nRow = 0;
353 bool bCalcAsShown = pDocument->GetDocOptions().IsCalcAsShown();
354 sal_uLong nIndex = 0;
355 if (bValidData)
357 for ( nCol = 0; nCol < nColCount; nCol++ )
359 for ( nRow = 0; nRow < nRowCount; nRow++, nIndex++ )
361 double nVal = DBL_MIN; // Hack for Chart to recognize empty cells
362 const ScAddress* pPos = GetPositionMap()->GetPosition( nIndex );
363 if (pPos)
364 // otherwise: Gap
365 nVal = getCellValue(*pDocument, *pPos, DBL_MIN, bCalcAsShown);
367 pMemChart->SetData(static_cast<short>(nCol), static_cast<short>(nRow), nVal);
371 else
373 for ( nRow = 0; nRow < nRowCount; nRow++, nIndex++ )
375 double nVal = DBL_MIN; // Hack for Chart to recognize empty cells
376 const ScAddress* pPos = GetPositionMap()->GetPosition( nIndex );
377 if (pPos)
378 // otherwise: Gap
379 nVal = getCellValue(*pDocument, *pPos, DBL_MIN, bCalcAsShown);
381 pMemChart->SetData(static_cast<short>(nCol), static_cast<short>(nRow), nVal);
385 //TODO: Label when gaps
388 // Column header
391 SCCOL nPosCol = 0;
392 for ( nCol = 0; nCol < nColCount; nCol++ )
394 OUString aString;
395 const ScAddress* pPos = GetPositionMap()->GetColHeaderPosition( static_cast<SCCOL>(nCol) );
396 if ( HasColHeaders() && pPos )
397 aString = pDocument->GetString(pPos->Col(), pPos->Row(), pPos->Tab());
399 if (aString.isEmpty())
401 OUStringBuffer aBuf(ScGlobal::GetRscString(STR_COLUMN));
402 aBuf.append(' ');
403 if ( pPos )
404 nPosCol = pPos->Col() + 1;
405 else
406 nPosCol++;
407 ScAddress aPos( nPosCol - 1, 0, 0 );
408 aBuf.append(aPos.Format(SCA_VALID_COL, NULL));
409 aString = aBuf.makeStringAndClear();
411 pMemChart->SetColText( static_cast<short>(nCol), aString);
415 // Row header
418 SCROW nPosRow = 0;
419 for ( nRow = 0; nRow < nRowCount; nRow++ )
421 OUString aString;
422 const ScAddress* pPos = GetPositionMap()->GetRowHeaderPosition( nRow );
423 if ( HasRowHeaders() && pPos )
424 aString = pDocument->GetString(pPos->Col(), pPos->Row(), pPos->Tab());
426 if (aString.isEmpty())
428 OUStringBuffer aBuf(ScGlobal::GetRscString(STR_ROW));
429 aBuf.append(' ');
430 if ( pPos )
431 nPosRow = pPos->Row() + 1;
432 else
433 nPosRow++;
434 aBuf.append(static_cast<sal_Int32>(nPosRow));
435 aString = aBuf.makeStringAndClear();
437 pMemChart->SetRowText( static_cast<short>(nRow), aString);
441 return pMemChart;
444 ScChartCollection::ScChartCollection() {}
445 ScChartCollection::ScChartCollection(const ScChartCollection& r) :
446 maData(r.maData) {}
448 void ScChartCollection::push_back(ScChartArray* p)
450 maData.push_back(p);
453 void ScChartCollection::clear()
455 maData.clear();
458 size_t ScChartCollection::size() const
460 return maData.size();
463 bool ScChartCollection::empty() const
465 return maData.empty();
468 ScChartArray* ScChartCollection::operator[](size_t nIndex)
470 if (maData.size() <= nIndex)
471 return NULL;
472 return &maData[nIndex];
475 const ScChartArray* ScChartCollection::operator[](size_t nIndex) const
477 if (maData.size() <= nIndex)
478 return NULL;
479 return &maData[nIndex];
482 bool ScChartCollection::operator==(const ScChartCollection& rCmp) const
484 return maData == rCmp.maData;
487 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */