Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * Version: MPL 1.1 / GPLv3+ / LGPLv3+
4 : : *
5 : : * The contents of this file are subject to the Mozilla Public License Version
6 : : * 1.1 (the "License"); you may not use this file except in compliance with
7 : : * the License or as specified alternatively below. You may obtain a copy of
8 : : * the License at http://www.mozilla.org/MPL/
9 : : *
10 : : * Software distributed under the License is distributed on an "AS IS" basis,
11 : : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : : * for the specific language governing rights and limitations under the
13 : : * License.
14 : : *
15 : : * Major Contributor(s):
16 : : * Copyright (C) 2012 Markus Mohrhard <markus.mohrhard@googlemail.com> (initial developer)
17 : : *
18 : : * All Rights Reserved.
19 : : *
20 : : * For minor contributions see the git repository.
21 : : *
22 : : * Alternatively, the contents of this file may be used under the terms of
23 : : * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
24 : : * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
25 : : * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
26 : : * instead of those above.
27 : : */
28 : :
29 : : #include "colorscale.hxx"
30 : : #include "document.hxx"
31 : : #include "cell.hxx"
32 : : #include "fillinfo.hxx"
33 : : #if DUMP_FORMAT_INFO
34 : : #include <iostream>
35 : : #endif
36 : :
37 : 0 : ScColorScaleEntry::ScColorScaleEntry():
38 : : mnVal(0),
39 : : mpCell(NULL),
40 : 0 : meType(COLORSCALE_VALUE)
41 : : {
42 : 0 : }
43 : :
44 : 27 : ScColorScaleEntry::ScColorScaleEntry(double nVal, const Color& rCol):
45 : : mnVal(nVal),
46 : : maColor(rCol),
47 : : mpCell(NULL),
48 : 27 : meType(COLORSCALE_VALUE)
49 : : {
50 : 27 : }
51 : :
52 : 0 : ScColorScaleEntry::ScColorScaleEntry(const ScColorScaleEntry& rEntry):
53 : : mnVal(rEntry.mnVal),
54 : : maColor(rEntry.maColor),
55 : : mpCell(),
56 : 0 : meType(rEntry.meType)
57 : : {
58 : 0 : }
59 : :
60 : 0 : ScColorScaleEntry::ScColorScaleEntry(ScDocument* pDoc, const ScColorScaleEntry& rEntry):
61 : : mnVal(rEntry.mnVal),
62 : : maColor(rEntry.maColor),
63 : : mpCell(),
64 : 0 : meType(rEntry.meType)
65 : : {
66 [ # # ]: 0 : if(rEntry.mpCell)
67 : : {
68 [ # # ][ # # ]: 0 : mpCell.reset(static_cast<ScFormulaCell*>(rEntry.mpCell->Clone(*pDoc, SC_CLONECELL_NOMAKEABS_EXTERNAL)));
[ # # ]
69 [ # # ]: 0 : mpCell->StartListeningTo( pDoc );
70 : : }
71 : 0 : }
72 : :
73 : 0 : ScColorScaleEntry::~ScColorScaleEntry()
74 : : {
75 : 0 : }
76 : :
77 : 3 : void ScColorScaleEntry::SetFormula( const rtl::OUString& rFormula, ScDocument* pDoc, const ScAddress& rAddr, formula::FormulaGrammar::Grammar eGrammar )
78 : : {
79 [ + - ]: 3 : mpCell.reset(new ScFormulaCell( pDoc, rAddr, rFormula, eGrammar ));
80 : 3 : mpCell->StartListeningTo( pDoc );
81 : 3 : }
82 : :
83 : 0 : const ScTokenArray* ScColorScaleEntry::GetFormula() const
84 : : {
85 [ # # ]: 0 : if(mpCell)
86 : : {
87 : 0 : return mpCell->GetCode();
88 : : }
89 : :
90 : 0 : return NULL;
91 : : }
92 : :
93 : 0 : rtl::OUString ScColorScaleEntry::GetFormula( formula::FormulaGrammar::Grammar eGrammar ) const
94 : : {
95 : 0 : rtl::OUString aFormula;
96 [ # # ]: 0 : if(mpCell)
97 : : {
98 [ # # ]: 0 : mpCell->GetFormula(aFormula, eGrammar);
99 : : }
100 : :
101 : 0 : return aFormula;
102 : : }
103 : :
104 : 0 : double ScColorScaleEntry::GetValue() const
105 : : {
106 [ # # ]: 0 : if(mpCell)
107 : : {
108 : 0 : mpCell->Interpret();
109 [ # # ]: 0 : if(mpCell->IsValue())
110 : 0 : return mpCell->GetValue();
111 : :
112 : 0 : return std::numeric_limits<double>::max();
113 : : }
114 : :
115 : 0 : return mnVal;
116 : : }
117 : :
118 : 0 : void ScColorScaleEntry::SetValue(double nValue)
119 : : {
120 : 0 : mnVal = nValue;
121 : 0 : }
122 : :
123 : 0 : void ScColorScaleEntry::UpdateMoveTab( SCTAB nOldTab, SCTAB nNewTab, SCTAB nTabNo )
124 : : {
125 [ # # ]: 0 : if(mpCell)
126 : : {
127 : 0 : mpCell->UpdateMoveTab( nOldTab, nNewTab, nTabNo );
128 : : }
129 : 0 : }
130 : :
131 : 0 : void ScColorScaleEntry::UpdateReference( UpdateRefMode eUpdateRefMode,
132 : : const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
133 : : {
134 [ # # ]: 0 : if(mpCell)
135 : : {
136 : 0 : mpCell->UpdateReference( eUpdateRefMode, rRange, nDx, nDy, nDz );
137 : : }
138 : 0 : }
139 : :
140 : 36 : const Color& ScColorScaleEntry::GetColor() const
141 : : {
142 : 36 : return maColor;
143 : : }
144 : :
145 : 0 : void ScColorScaleEntry::SetColor(const Color& rColor)
146 : : {
147 : 0 : maColor = rColor;
148 : 0 : }
149 : :
150 : 12 : ScColorFormat::ScColorFormat(ScDocument* pDoc):
151 : 12 : ScFormatEntry(pDoc)
152 : : {
153 : 12 : }
154 : :
155 : 0 : ScColorFormat::~ScColorFormat()
156 : : {
157 [ # # ]: 0 : }
158 : :
159 : 12 : void ScColorFormat::SetParent( ScConditionalFormat* pParent )
160 : : {
161 : 12 : mpParent = pParent;
162 : 12 : }
163 : :
164 : 12 : ScColorScaleFormat::ScColorScaleFormat(ScDocument* pDoc):
165 [ + - ]: 12 : ScColorFormat(pDoc)
166 : : {
167 : 12 : }
168 : :
169 : 0 : ScColorScaleFormat::ScColorScaleFormat(ScDocument* pDoc, const ScColorScaleFormat& rFormat):
170 [ # # ]: 0 : ScColorFormat(pDoc)
171 : : {
172 [ # # ][ # # ]: 0 : for(const_iterator itr = rFormat.begin(); itr != rFormat.end(); ++itr)
[ # # ][ # # ]
[ # # ]
173 : : {
174 [ # # ][ # # ]: 0 : maColorScales.push_back(new ScColorScaleEntry(pDoc, *itr));
[ # # ][ # # ]
175 : : }
176 : 0 : }
177 : :
178 : 0 : ScColorFormat* ScColorScaleFormat::Clone(ScDocument* pDoc) const
179 : : {
180 [ # # ]: 0 : return new ScColorScaleFormat(pDoc, *this);
181 : : }
182 : :
183 [ # # ]: 0 : ScColorScaleFormat::~ScColorScaleFormat()
184 : : {
185 [ # # ]: 0 : }
186 : :
187 : 27 : void ScColorScaleFormat::AddEntry( ScColorScaleEntry* pEntry )
188 : : {
189 : 27 : maColorScales.push_back( pEntry );
190 : 27 : }
191 : :
192 : 24 : void ScColorScaleEntry::SetType( ScColorScaleEntryType eType )
193 : : {
194 : 24 : meType = eType;
195 [ + + ]: 24 : if(eType != COLORSCALE_FORMULA)
196 : 21 : mpCell.reset();
197 : 24 : }
198 : :
199 : 108 : ScColorScaleEntryType ScColorScaleEntry::GetType() const
200 : : {
201 : 108 : return meType;
202 : : }
203 : :
204 : : namespace {
205 : :
206 : 18 : double getMinValue(const ScRange& rRange, ScDocument* pDoc)
207 : : {
208 : 18 : double aMinValue = std::numeric_limits<double>::max();
209 : : //iterate through columns
210 : 18 : SCTAB nTab = rRange.aStart.Tab();
211 [ + + ]: 54 : for(SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
212 : : {
213 [ + + ]: 144 : for(SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
214 : : {
215 : 108 : ScAddress aAddr(nCol, nRow, rRange.aStart.Tab());
216 [ + - ]: 108 : CellType eType = pDoc->GetCellType(aAddr);
217 [ + - ]: 108 : if(eType == CELLTYPE_VALUE)
218 : : {
219 [ + - ]: 108 : double aVal = pDoc->GetValue(nCol, nRow, nTab);
220 [ + + ]: 108 : if( aVal < aMinValue )
221 : 18 : aMinValue = aVal;
222 : : }
223 [ # # ]: 0 : else if(eType == CELLTYPE_FORMULA)
224 : : {
225 [ # # ][ # # ]: 0 : if(static_cast<ScFormulaCell*>(pDoc->GetCell(aAddr))->IsValue())
[ # # ][ # # ]
226 : : {
227 [ # # ]: 0 : double aVal = pDoc->GetValue(nCol, nRow, nTab);
228 [ # # ]: 0 : if( aVal < aMinValue )
229 : 0 : aMinValue = aVal;
230 : : }
231 : : }
232 : : }
233 : : }
234 : 18 : return aMinValue;
235 : : }
236 : :
237 : 18 : double getMaxValue(const ScRange& rRange, ScDocument* pDoc)
238 : : {
239 : 18 : double aMaxValue = std::numeric_limits<double>::min();
240 : : //iterate through columns
241 : 18 : SCTAB nTab = rRange.aStart.Tab();
242 [ + + ]: 54 : for(SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
243 : : {
244 [ + + ]: 144 : for(SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
245 : : {
246 : 108 : ScAddress aAddr(nCol, nRow, rRange.aStart.Tab());
247 [ + - ]: 108 : CellType eType = pDoc->GetCellType(aAddr);
248 [ + - ]: 108 : if(eType == CELLTYPE_VALUE)
249 : : {
250 [ + - ]: 108 : double aVal = pDoc->GetValue(nCol, nRow, nTab);
251 [ + - ]: 108 : if( aVal > aMaxValue )
252 : 108 : aMaxValue = aVal;
253 : : }
254 [ # # ]: 0 : else if(eType == CELLTYPE_FORMULA)
255 : : {
256 [ # # ][ # # ]: 0 : if(static_cast<ScFormulaCell*>(pDoc->GetCell(aAddr))->IsValue())
[ # # ][ # # ]
257 : : {
258 [ # # ]: 0 : double aVal = pDoc->GetValue(nCol, nRow, nTab);
259 [ # # ]: 0 : if( aVal > aMaxValue )
260 : 0 : aMaxValue = aVal;
261 : : }
262 : : }
263 : : }
264 : : }
265 : 18 : return aMaxValue;
266 : : }
267 : :
268 : 18 : double getMinValue(const ScRangeList& rList, ScDocument* pDoc)
269 : : {
270 : 18 : double aMinValue = std::numeric_limits<double>::max();
271 : :
272 : 18 : size_t n = rList.size();
273 [ + + ]: 36 : for(size_t i = 0; i < n; ++i)
274 : : {
275 : 18 : const ScRange* pRange = rList[i];
276 : 18 : double aVal = getMinValue(*pRange, pDoc);
277 [ + - ]: 18 : if( aVal < aMinValue )
278 : 18 : aMinValue = aVal;
279 : : }
280 : 18 : return aMinValue;
281 : : }
282 : :
283 : 18 : double getMaxValue(const ScRangeList& rList, ScDocument* pDoc)
284 : : {
285 : 18 : double aMaxVal = std::numeric_limits<double>::min();
286 : :
287 : 18 : size_t n = rList.size();
288 [ + + ]: 36 : for(size_t i = 0; i < n; ++i)
289 : : {
290 : 18 : const ScRange* pRange = rList[i];
291 : 18 : double aVal = getMaxValue(*pRange, pDoc);
292 [ + - ]: 18 : if( aVal > aMaxVal )
293 : 18 : aMaxVal = aVal;
294 : : }
295 : :
296 : 18 : return aMaxVal;
297 : : }
298 : :
299 : : }
300 : :
301 : 18 : double ScColorScaleFormat::GetMinValue() const
302 : : {
303 [ + - ]: 18 : const_iterator itr = maColorScales.begin();
304 : :
305 [ + - ][ + - ]: 18 : if(itr->GetType() == COLORSCALE_VALUE || itr->GetType() == COLORSCALE_FORMULA)
[ + - ][ + - ]
[ + - ][ - + ]
[ - + ]
306 [ # # ][ # # ]: 0 : return itr->GetValue();
307 : : else
308 : : {
309 [ + - ][ + - ]: 18 : return getMinValue(GetRange(), mpDoc);
310 : : }
311 : : }
312 : :
313 : 18 : double ScColorScaleFormat::GetMaxValue() const
314 : : {
315 [ + - ]: 18 : ColorScaleEntries::const_reverse_iterator itr = maColorScales.rbegin();
316 : :
317 [ + - ][ + - ]: 18 : if(itr->GetType() == COLORSCALE_VALUE || itr->GetType() == COLORSCALE_FORMULA)
[ + - ][ + - ]
[ + - ][ - + ]
[ - + ]
318 [ # # ][ # # ]: 0 : return itr->GetValue();
319 : : else
320 : : {
321 [ + - ][ + - ]: 18 : return getMaxValue(GetRange(), mpDoc);
322 : : }
323 : : }
324 : :
325 : 18 : void ScColorScaleFormat::calcMinMax(double& rMin, double& rMax) const
326 : : {
327 : 18 : rMin = GetMinValue();
328 : 18 : rMax = GetMaxValue();
329 : 18 : }
330 : :
331 : 39 : const ScRangeList& ScColorFormat::GetRange() const
332 : : {
333 : 39 : return mpParent->GetRange();
334 : : }
335 : :
336 : 0 : void ScColorFormat::getValues(std::vector<double>& rValues) const
337 : : {
338 : 0 : size_t n = GetRange().size();
339 : 0 : const ScRangeList& aRanges = GetRange();
340 [ # # ]: 0 : for(size_t i = 0; i < n; ++i)
341 : : {
342 : 0 : const ScRange* pRange = aRanges[i];
343 : 0 : SCTAB nTab = pRange->aStart.Tab();
344 [ # # ]: 0 : for(SCCOL nCol = pRange->aStart.Col(); nCol <= pRange->aEnd.Col(); ++nCol)
345 : : {
346 [ # # ]: 0 : for(SCCOL nRow = pRange->aStart.Row(); nRow <= pRange->aEnd.Row(); ++nRow)
347 : : {
348 : 0 : ScAddress aAddr(nCol, nRow, nTab);
349 [ # # ]: 0 : CellType eType = mpDoc->GetCellType(aAddr);
350 [ # # ]: 0 : if(eType == CELLTYPE_VALUE)
351 : : {
352 [ # # ]: 0 : double aVal = mpDoc->GetValue(nCol, nRow, nTab);
353 [ # # ]: 0 : rValues.push_back(aVal);
354 : : }
355 [ # # ]: 0 : else if(eType == CELLTYPE_FORMULA)
356 : : {
357 [ # # ][ # # ]: 0 : if(static_cast<ScFormulaCell*>(mpDoc->GetCell(aAddr))->IsValue())
[ # # ][ # # ]
358 : : {
359 [ # # ]: 0 : double aVal = mpDoc->GetValue(nCol, nRow, nTab);
360 [ # # ]: 0 : rValues.push_back(aVal);
361 : : }
362 : : }
363 : : }
364 : : }
365 : : }
366 : 0 : }
367 : :
368 : : namespace {
369 : :
370 : 54 : sal_uInt8 GetColorValue( double nVal, double nVal1, sal_uInt8 nColVal1, double nVal2, sal_uInt8 nColVal2 )
371 : : {
372 [ + + ]: 54 : if (nVal <= nVal1)
373 : 9 : return nColVal1;
374 : :
375 [ + + ]: 45 : if (nVal >= nVal2)
376 : 9 : return nColVal2;
377 : :
378 : 36 : sal_uInt8 nColVal = static_cast<sal_uInt8>((nVal - nVal1)/(nVal2-nVal1)*(nColVal2-nColVal1))+nColVal1;
379 : 54 : return nColVal;
380 : : }
381 : :
382 : 18 : Color CalcColor( double nVal, double nVal1, const Color& rCol1, double nVal2, const Color& rCol2)
383 : : {
384 : 18 : sal_uInt8 nColRed = GetColorValue(nVal, nVal1, rCol1.GetRed(), nVal2, rCol2.GetRed());
385 : 18 : sal_uInt8 nColBlue = GetColorValue(nVal, nVal1, rCol1.GetBlue(), nVal2, rCol2.GetBlue());
386 : 18 : sal_uInt8 nColGreen = GetColorValue(nVal, nVal1, rCol1.GetGreen(), nVal2, rCol2.GetGreen());
387 : :
388 : 18 : return Color(nColRed, nColGreen, nColBlue);
389 : : }
390 : :
391 : 0 : double GetPercentile( std::vector<double>& rArray, double fPercentile )
392 : : {
393 : 0 : size_t nSize = rArray.size();
394 : 0 : size_t nIndex = (size_t)::rtl::math::approxFloor( fPercentile * (nSize-1));
395 : 0 : double fDiff = fPercentile * (nSize-1) - ::rtl::math::approxFloor( fPercentile * (nSize-1));
396 [ # # ]: 0 : std::vector<double>::iterator iter = rArray.begin() + nIndex;
397 [ # # ]: 0 : ::std::nth_element( rArray.begin(), iter, rArray.end());
398 [ # # ]: 0 : if (fDiff == 0.0)
399 [ # # ]: 0 : return *iter;
400 : : else
401 : : {
402 [ # # ]: 0 : double fVal = *iter;
403 [ # # ][ # # ]: 0 : iter = rArray.begin() + nIndex+1;
404 [ # # ]: 0 : ::std::nth_element( rArray.begin(), iter, rArray.end());
405 [ # # ]: 0 : return fVal + fDiff * (*iter - fVal);
406 : : }
407 : : }
408 : :
409 : : }
410 : :
411 : 36 : double ScColorScaleFormat::CalcValue(double nMin, double nMax, ScColorScaleFormat::const_iterator& itr) const
412 : : {
413 [ - + - + : 36 : switch(itr->GetType())
- - - ]
414 : : {
415 : : case COLORSCALE_PERCENT:
416 : 0 : return nMin + (nMax-nMin)*(itr->GetValue()/100);
417 : : case COLORSCALE_MIN:
418 : 18 : return nMin;
419 : : case COLORSCALE_AUTOMIN:
420 [ # # ]: 0 : return std::min<double>(0, nMin);
421 : : case COLORSCALE_MAX:
422 : 18 : return nMax;
423 : : case COLORSCALE_AUTOMAX:
424 [ # # ]: 0 : return std::max<double>(0, nMax);
425 : : case COLORSCALE_PERCENTILE:
426 : : {
427 [ # # ]: 0 : std::vector<double> aValues;
428 [ # # ]: 0 : getValues(aValues);
429 [ # # ]: 0 : if(aValues.size() == 1)
430 [ # # ]: 0 : return aValues[0];
431 : : else
432 : : {
433 [ # # ][ # # ]: 0 : double fPercentile = itr->GetValue()/100.0;
434 [ # # ]: 0 : return GetPercentile(aValues, fPercentile);
435 : 0 : }
436 : : }
437 : :
438 : : default:
439 : 0 : break;
440 : : }
441 : :
442 : 36 : return itr->GetValue();
443 : : }
444 : :
445 : 18 : Color* ScColorScaleFormat::GetColor( const ScAddress& rAddr ) const
446 : : {
447 [ + - ]: 18 : CellType eCellType = mpDoc->GetCellType(rAddr);
448 [ - + ][ # # ]: 18 : if(eCellType != CELLTYPE_VALUE && eCellType != CELLTYPE_FORMULA)
449 : 0 : return NULL;
450 : :
451 [ - + ]: 18 : if (eCellType == CELLTYPE_FORMULA)
452 : : {
453 [ # # ][ # # ]: 0 : if(!static_cast<ScFormulaCell*>(mpDoc->GetCell(rAddr))->IsValue())
[ # # ][ # # ]
454 : 0 : return NULL;
455 : : }
456 : :
457 : : // now we have for sure a value
458 [ + - ]: 18 : double nVal = mpDoc->GetValue(rAddr);
459 : :
460 [ - + ]: 18 : if (maColorScales.size() < 2)
461 : 0 : return NULL;
462 : :
463 : 18 : double nMin = std::numeric_limits<double>::max();
464 : 18 : double nMax = std::numeric_limits<double>::min();
465 [ + - ]: 18 : calcMinMax(nMin, nMax);
466 : :
467 : : // this check is for safety
468 [ - + ]: 18 : if(nMin >= nMax)
469 : 0 : return NULL;
470 : :
471 [ + - ]: 18 : const_iterator itr = begin();
472 [ + - ]: 18 : double nValMin = CalcValue(nMin, nMax, itr);
473 [ + - ][ + - ]: 18 : Color rColMin = itr->GetColor();
474 [ + - ]: 18 : ++itr;
475 [ + - ]: 18 : double nValMax = CalcValue(nMin, nMax, itr);
476 [ + - ][ + - ]: 18 : Color rColMax = itr->GetColor();
477 : :
478 [ + - ]: 18 : ++itr;
479 [ + - ][ + - ]: 18 : while(itr != end() && nVal > nValMax)
[ - + ][ # # ]
[ + - ]
[ - + # # ]
480 : : {
481 : 0 : rColMin = rColMax;
482 : 0 : nValMin = nValMax;
483 [ # # ][ # # ]: 0 : rColMax = itr->GetColor();
484 [ # # ]: 0 : nValMax = CalcValue(nMin, nMax, itr);
485 [ # # ]: 0 : ++itr;
486 : : }
487 : :
488 : 18 : Color aColor = CalcColor(nVal, nValMin, rColMin, nValMax, rColMax);
489 : :
490 [ + - ]: 18 : return new Color(aColor);
491 : : }
492 : :
493 : : #if DUMP_FORMAT_INFO
494 : 3 : void ScColorScaleFormat::dumpInfo() const
495 : : {
496 : 3 : std::cout << "Color Scale" << std::endl;
497 : 3 : const ScRangeList& rRange = GetRange();
498 : 3 : size_t n = rRange.size();
499 [ + + ]: 6 : for(size_t i = 0; i < n; ++i)
500 : : {
501 : 3 : const ScRange* pRange = rRange[i];
502 : 3 : SCTAB nTab = pRange->aStart.Tab();
503 [ + + ]: 9 : for( SCCOL nCol = pRange->aStart.Col(), nEndCol = pRange->aEnd.Col(); nCol <= nEndCol; ++nCol)
504 : : {
505 [ + + ]: 24 : for( SCROW nRow = pRange->aStart.Row(), nEndRow = pRange->aEnd.Row(); nRow <= nEndRow; ++nRow)
506 : : {
507 [ + - ]: 18 : boost::scoped_ptr<Color> pColor( GetColor(ScAddress(nCol, nRow, nTab)) );
508 [ + - ][ + - ]: 18 : std::cout << nCol << "," << nRow << "," << nTab << ",";
[ + - ][ + - ]
[ + - ][ + - ]
509 [ + - ][ + - ]: 18 : std::cout << ((int)pColor->GetRed()) << "," << ((int)pColor->GetGreen()) << "," << ((int)pColor->GetBlue());
[ + - ][ + - ]
[ + - ]
510 [ + - ]: 18 : std::cout << std::endl;
511 [ + - ]: 18 : }
512 : : }
513 : : }
514 : 3 : }
515 : : #endif
516 : :
517 : 0 : void ScColorScaleFormat::UpdateMoveTab(SCTAB nOldTab, SCTAB nNewTab)
518 : : {
519 : 0 : SCTAB nThisTab = GetRange().front()->aStart.Tab();
520 [ # # ][ # # ]: 0 : for(iterator itr = begin(); itr != end(); ++itr)
[ # # ][ # # ]
[ # # ]
521 : : {
522 [ # # ][ # # ]: 0 : itr->UpdateMoveTab(nOldTab, nNewTab, nThisTab);
523 : : }
524 : 0 : }
525 : :
526 : 0 : void ScColorScaleFormat::UpdateReference( UpdateRefMode eUpdateRefMode,
527 : : const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
528 : : {
529 [ # # ][ # # ]: 0 : for(iterator itr = begin(); itr != end(); ++itr)
[ # # ][ # # ]
[ # # ]
530 : : {
531 [ # # ][ # # ]: 0 : itr->UpdateReference(eUpdateRefMode, rRange, nDx, nDy, nDz);
532 : : }
533 : 0 : }
534 : :
535 : 0 : bool ScColorScaleFormat::CheckEntriesForRel(const ScRange& rRange) const
536 : : {
537 : 0 : bool bNeedUpdate = false;
538 [ # # ][ # # ]: 0 : for(const_iterator itr = begin(); itr != end(); ++itr)
[ # # ][ # # ]
[ # # ]
539 : : {
540 [ # # ][ # # ]: 0 : ScColorScaleEntryType eType = itr->GetType();
541 [ # # # ]: 0 : switch(eType)
542 : : {
543 : : case COLORSCALE_MIN:
544 : : case COLORSCALE_MAX:
545 : : case COLORSCALE_AUTOMIN:
546 : : case COLORSCALE_AUTOMAX:
547 : 0 : bNeedUpdate = true;
548 : 0 : break;
549 : : case COLORSCALE_FORMULA:
550 : 0 : return true;
551 : : default:
552 : 0 : break;
553 : : }
554 : : }
555 : :
556 : : // TODO: check also if the changed value is the new min/max
557 : : // or has been the old min/max value
558 [ # # ][ # # ]: 0 : bNeedUpdate = bNeedUpdate && GetRange().Intersects(rRange);
559 : 0 : return bNeedUpdate;
560 : : }
561 : :
562 : 0 : void ScColorScaleFormat::DataChanged(const ScRange& rRange)
563 : : {
564 : 0 : bool bNeedUpdate = CheckEntriesForRel(rRange);
565 [ # # ]: 0 : if(bNeedUpdate)
566 : : {
567 : 0 : size_t n = GetRange().size();
568 [ # # ]: 0 : for(size_t i = 0; i < n; ++i)
569 : : {
570 : 0 : const ScRange* pRange = GetRange()[i];
571 : 0 : mpDoc->RepaintRange(*pRange);
572 : : }
573 : : }
574 : 0 : }
575 : :
576 : 12 : condformat::ScFormatEntryType ScColorScaleFormat::GetType() const
577 : : {
578 : 12 : return condformat::COLORSCALE;
579 : : }
580 : :
581 : 0 : ScColorScaleFormat::iterator ScColorScaleFormat::begin()
582 : : {
583 : 0 : return maColorScales.begin();
584 : : }
585 : :
586 : 18 : ScColorScaleFormat::const_iterator ScColorScaleFormat::begin() const
587 : : {
588 : 18 : return maColorScales.begin();
589 : : }
590 : :
591 : 0 : ScColorScaleFormat::iterator ScColorScaleFormat::end()
592 : : {
593 : 0 : return maColorScales.end();
594 : : }
595 : :
596 : 18 : ScColorScaleFormat::const_iterator ScColorScaleFormat::end() const
597 : : {
598 : 18 : return maColorScales.end();
599 : : }
600 : :
601 : 0 : size_t ScColorScaleFormat::size() const
602 : : {
603 : 0 : return maColorScales.size();
604 : : }
605 : :
606 : 0 : ScDataBarFormat::ScDataBarFormat(ScDocument* pDoc):
607 : 0 : ScColorFormat(pDoc)
608 : : {
609 : 0 : }
610 : :
611 : 0 : ScDataBarFormat::ScDataBarFormat(ScDocument* pDoc, const ScDataBarFormat& rFormat):
612 : : ScColorFormat(pDoc),
613 [ # # ][ # # ]: 0 : mpFormatData(new ScDataBarFormatData(*rFormat.mpFormatData))
614 : : {
615 : 0 : }
616 : :
617 : 0 : void ScDataBarFormat::SetDataBarData( ScDataBarFormatData* pData )
618 : : {
619 : 0 : mpFormatData.reset(pData);
620 : 0 : }
621 : :
622 : 0 : const ScDataBarFormatData* ScDataBarFormat::GetDataBarData() const
623 : : {
624 : 0 : return mpFormatData.get();
625 : : }
626 : :
627 : 0 : ScColorFormat* ScDataBarFormat::Clone(ScDocument* pDoc) const
628 : : {
629 [ # # ]: 0 : return new ScDataBarFormat(pDoc, *this);
630 : : }
631 : :
632 : 0 : condformat::ScFormatEntryType ScDataBarFormat::GetType() const
633 : : {
634 : 0 : return condformat::DATABAR;
635 : : }
636 : :
637 : 0 : void ScDataBarFormat::UpdateReference( UpdateRefMode eRefMode,
638 : : const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
639 : : {
640 : 0 : mpFormatData->mpUpperLimit->UpdateReference( eRefMode, rRange, nDx, nDy, nDz );
641 : 0 : mpFormatData->mpLowerLimit->UpdateReference( eRefMode, rRange, nDx, nDy, nDz );
642 : 0 : }
643 : :
644 : : namespace {
645 : :
646 : 0 : bool NeedUpdate(ScColorScaleEntry* pEntry)
647 : : {
648 [ # # ]: 0 : switch(pEntry->GetType())
649 : : {
650 : : case COLORSCALE_MIN:
651 : : case COLORSCALE_MAX:
652 : : case COLORSCALE_FORMULA:
653 : : case COLORSCALE_AUTOMIN:
654 : : case COLORSCALE_AUTOMAX:
655 : 0 : return true;
656 : : default:
657 : 0 : return false;
658 : : }
659 : : }
660 : :
661 : : }
662 : :
663 : 0 : void ScDataBarFormat::DataChanged(const ScRange& rRange)
664 : : {
665 : 0 : bool bNeedUpdate = false;
666 : :
667 : 0 : bNeedUpdate = NeedUpdate(mpFormatData->mpUpperLimit.get());
668 : 0 : bNeedUpdate &= NeedUpdate(mpFormatData->mpLowerLimit.get());
669 : :
670 : 0 : bNeedUpdate &= GetRange().Intersects(rRange);
671 : :
672 [ # # ]: 0 : if(bNeedUpdate)
673 : : {
674 : 0 : size_t n = GetRange().size();
675 [ # # ]: 0 : for(size_t i = 0; i < n; ++i)
676 : : {
677 : 0 : const ScRange* pRange = GetRange()[i];
678 : 0 : mpDoc->RepaintRange(*pRange);
679 : : }
680 : : }
681 : 0 : }
682 : :
683 : 0 : void ScDataBarFormat::UpdateMoveTab(SCTAB nOldTab, SCTAB nNewTab)
684 : : {
685 : 0 : SCTAB nThisTab = GetRange().front()->aStart.Tab();
686 : 0 : mpFormatData->mpUpperLimit->UpdateMoveTab(nOldTab, nNewTab, nThisTab);
687 : 0 : mpFormatData->mpLowerLimit->UpdateMoveTab(nOldTab, nNewTab, nThisTab);
688 : 0 : }
689 : :
690 : 0 : double ScDataBarFormat::getMin(double nMin, double nMax) const
691 : : {
692 [ # # # # : 0 : switch(mpFormatData->mpLowerLimit->GetType())
# ]
693 : : {
694 : : case COLORSCALE_MIN:
695 : 0 : return nMin;
696 : :
697 : : case COLORSCALE_AUTOMIN:
698 [ # # ]: 0 : return std::min<double>(0, nMin);
699 : :
700 : : case COLORSCALE_PERCENT:
701 : 0 : return nMin + (nMax-nMin)/100*mpFormatData->mpLowerLimit->GetValue();
702 : :
703 : : case COLORSCALE_PERCENTILE:
704 : : {
705 [ # # ]: 0 : double fPercentile = mpFormatData->mpLowerLimit->GetValue()/100.0;
706 [ # # ]: 0 : std::vector<double> aValues;
707 [ # # ]: 0 : getValues(aValues);
708 [ # # ]: 0 : return GetPercentile(aValues, fPercentile);
709 : : }
710 : :
711 : : default:
712 : 0 : break;
713 : : }
714 : :
715 : 0 : return mpFormatData->mpLowerLimit->GetValue();
716 : : }
717 : :
718 : 0 : double ScDataBarFormat::getMax(double nMin, double nMax) const
719 : : {
720 [ # # # # : 0 : switch(mpFormatData->mpUpperLimit->GetType())
# ]
721 : : {
722 : : case COLORSCALE_MAX:
723 : 0 : return nMax;
724 : : case COLORSCALE_AUTOMAX:
725 [ # # ]: 0 : return std::max<double>(0, nMax);
726 : : case COLORSCALE_PERCENT:
727 : 0 : return nMin + (nMax-nMin)/100*mpFormatData->mpUpperLimit->GetValue();
728 : : case COLORSCALE_PERCENTILE:
729 : : {
730 [ # # ]: 0 : double fPercentile = mpFormatData->mpUpperLimit->GetValue()/100.0;
731 [ # # ]: 0 : std::vector<double> aValues;
732 [ # # ]: 0 : getValues(aValues);
733 [ # # ]: 0 : return GetPercentile(aValues, fPercentile);
734 : : }
735 : :
736 : : default:
737 : 0 : break;
738 : : }
739 : :
740 : 0 : return mpFormatData->mpUpperLimit->GetValue();
741 : : }
742 : :
743 : 0 : ScDataBarInfo* ScDataBarFormat::GetDataBarInfo(const ScAddress& rAddr) const
744 : : {
745 : 0 : CellType eCellType = mpDoc->GetCellType(rAddr);
746 [ # # ][ # # ]: 0 : if(eCellType != CELLTYPE_VALUE && eCellType != CELLTYPE_FORMULA)
747 : 0 : return NULL;
748 : :
749 [ # # ]: 0 : if (eCellType == CELLTYPE_FORMULA)
750 : : {
751 [ # # ][ # # ]: 0 : if(!static_cast<ScFormulaCell*>(mpDoc->GetCell(rAddr))->IsValue())
752 : 0 : return NULL;
753 : : }
754 : :
755 : : // now we have for sure a value
756 : : //
757 : 0 : double nValMin = getMinValue(GetRange(), mpDoc);
758 : 0 : double nValMax = getMaxValue(GetRange(), mpDoc);
759 : 0 : double nMin = getMin(nValMin, nValMax);
760 : 0 : double nMax = getMax(nValMin, nValMax);
761 : :
762 : :
763 : 0 : double nValue = mpDoc->GetValue(rAddr);
764 : :
765 : 0 : ScDataBarInfo* pInfo = new ScDataBarInfo();
766 [ # # ]: 0 : if(mpFormatData->meAxisPosition == databar::NONE)
767 : : {
768 [ # # ]: 0 : if(nValue <= nMin)
769 : : {
770 : 0 : pInfo->mnLength = 0;
771 : : }
772 [ # # ]: 0 : else if(nValue >= nMax)
773 : : {
774 : 0 : pInfo->mnLength = 100;
775 : : }
776 : : else
777 : : {
778 : 0 : double nDiff = nMax - nMin;
779 : 0 : pInfo->mnLength = (nValue - nMin)/nDiff*100.0;
780 : : }
781 : 0 : pInfo->mnZero = 0;
782 : : }
783 : : else
784 : : {
785 : 0 : double nMinPositive = 0;
786 : 0 : double nMaxNegative = 0;
787 : : //calculate the zero position first
788 [ # # ]: 0 : if(mpFormatData->meAxisPosition == databar::AUTOMATIC)
789 : : {
790 [ # # ]: 0 : if(nMin < 0)
791 : : {
792 [ # # ]: 0 : if(nMax < 0)
793 : 0 : pInfo->mnZero = 100;
794 : : else
795 : : {
796 : 0 : pInfo->mnZero = -100*nMin/(nMax-nMin);
797 : : }
798 : : }
799 : : else
800 : 0 : pInfo->mnZero = 0;
801 : :
802 : : // if max or min is used we may need to adjust it
803 : : // for the length calculation
804 [ # # ][ # # ]: 0 : if (mpFormatData->mpLowerLimit->GetType() == COLORSCALE_MIN && nMin > 0)
[ # # ]
805 : 0 : nMinPositive = nMin;
806 [ # # ][ # # ]: 0 : if (mpFormatData->mpUpperLimit->GetType() == COLORSCALE_MAX && nMax < 0)
[ # # ]
807 : 0 : nMaxNegative = nMax;
808 : : }
809 [ # # ]: 0 : else if( mpFormatData->meAxisPosition == databar::MIDDLE)
810 : 0 : pInfo->mnZero = 50;
811 : :
812 : : //calculate the length
813 [ # # ]: 0 : if(nValue < 0)
814 : : {
815 [ # # ]: 0 : if (nValue < nMin)
816 : 0 : pInfo->mnLength = -100;
817 : : else
818 : 0 : pInfo->mnLength = -100 * (nValue-nMaxNegative)/(nMin-nMaxNegative);
819 : : }
820 : : else
821 : : {
822 [ # # ]: 0 : if ( nValue > nMax )
823 : 0 : pInfo->mnLength = 100;
824 : : else
825 : 0 : pInfo->mnLength = (nValue-nMinPositive)/(nMax-nMinPositive)*100;
826 : : }
827 : : }
828 : :
829 : :
830 : : // set color
831 [ # # ][ # # ]: 0 : if(mpFormatData->mbNeg && nValue < 0)
[ # # ]
832 : : {
833 [ # # ]: 0 : if(mpFormatData->mpNegativeColor)
834 : : {
835 : 0 : pInfo->maColor = *mpFormatData->mpNegativeColor.get();
836 : : }
837 : : else
838 : : {
839 : : // default negative color is red
840 : 0 : pInfo->maColor = COL_LIGHTRED;
841 : : }
842 : :
843 : : }
844 : : else
845 : 0 : pInfo->maColor = mpFormatData->maPositiveColor;
846 : :
847 : 0 : pInfo->mbGradient = mpFormatData->mbGradient;
848 : 0 : pInfo->mbShowValue = !mpFormatData->mbOnlyBar;
849 : 0 : pInfo->maAxisColor = mpFormatData->maAxisColor;
850 : :
851 : 0 : return pInfo;
852 : : }
853 : :
854 : : #if DUMP_FORMAT_INFO
855 : 0 : void ScDataBarFormat::dumpInfo() const
856 : : {
857 : 0 : const ScRangeList& rRange = GetRange();
858 : 0 : size_t n = rRange.size();
859 [ # # ]: 0 : for(size_t i = 0; i < n; ++i)
860 : : {
861 : 0 : const ScRange* pRange = rRange[i];
862 : 0 : SCTAB nTab = pRange->aStart.Tab();
863 [ # # ]: 0 : for( SCCOL nCol = pRange->aStart.Col(), nEndCol = pRange->aEnd.Col(); nCol <= nEndCol; ++nCol)
864 : : {
865 [ # # ]: 0 : for( SCROW nRow = pRange->aStart.Row(), nEndRow = pRange->aEnd.Row(); nRow <= nEndRow; ++nRow)
866 : : {
867 [ # # ]: 0 : boost::scoped_ptr<ScDataBarInfo> pInfo( GetDataBarInfo(ScAddress(nCol, nRow, nTab)) );
868 [ # # ][ # # ]: 0 : std::cout << nCol << "," << nRow << "," << nTab << "," << pInfo->mnZero << ",";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
869 [ # # ][ # # ]: 0 : std::cout << pInfo->mnLength << "," << pInfo->mbGradient << "," << pInfo->mbShowValue << std::endl;
[ # # ][ # # ]
[ # # ][ # # ]
870 [ # # ]: 0 : std::cout << std::endl;
871 [ # # ]: 0 : }
872 : : }
873 : : }
874 [ + - ][ + - ]: 153 : }
875 : : #endif
876 : :
877 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|