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 : #include "iconsets.hrc"
34 : #include "scresid.hxx"
35 : #if DUMP_FORMAT_INFO
36 : #include <iostream>
37 : #endif
38 :
39 : #include <algorithm>
40 :
41 0 : ScColorScaleEntry::ScColorScaleEntry():
42 : mnVal(0),
43 : mpCell(NULL),
44 0 : meType(COLORSCALE_VALUE)
45 : {
46 0 : }
47 :
48 0 : ScColorScaleEntry::ScColorScaleEntry(double nVal, const Color& rCol):
49 : mnVal(nVal),
50 : maColor(rCol),
51 : mpCell(NULL),
52 0 : meType(COLORSCALE_VALUE)
53 : {
54 0 : }
55 :
56 0 : ScColorScaleEntry::ScColorScaleEntry(const ScColorScaleEntry& rEntry):
57 : mnVal(rEntry.mnVal),
58 : maColor(rEntry.maColor),
59 : mpCell(),
60 0 : meType(rEntry.meType)
61 : {
62 0 : }
63 :
64 0 : ScColorScaleEntry::ScColorScaleEntry(ScDocument* pDoc, const ScColorScaleEntry& rEntry):
65 : mnVal(rEntry.mnVal),
66 : maColor(rEntry.maColor),
67 : mpCell(),
68 0 : meType(rEntry.meType)
69 : {
70 0 : if(rEntry.mpCell)
71 : {
72 0 : mpCell.reset(static_cast<ScFormulaCell*>(rEntry.mpCell->Clone(*pDoc, SC_CLONECELL_NOMAKEABS_EXTERNAL)));
73 0 : mpCell->StartListeningTo( pDoc );
74 : }
75 0 : }
76 :
77 0 : ScColorScaleEntry::~ScColorScaleEntry()
78 : {
79 0 : }
80 :
81 0 : void ScColorScaleEntry::SetFormula( const rtl::OUString& rFormula, ScDocument* pDoc, const ScAddress& rAddr, formula::FormulaGrammar::Grammar eGrammar )
82 : {
83 0 : mpCell.reset(new ScFormulaCell( pDoc, rAddr, rFormula, eGrammar ));
84 0 : mpCell->StartListeningTo( pDoc );
85 0 : }
86 :
87 0 : const ScTokenArray* ScColorScaleEntry::GetFormula() const
88 : {
89 0 : if(mpCell)
90 : {
91 0 : return mpCell->GetCode();
92 : }
93 :
94 0 : return NULL;
95 : }
96 :
97 0 : rtl::OUString ScColorScaleEntry::GetFormula( formula::FormulaGrammar::Grammar eGrammar ) const
98 : {
99 0 : rtl::OUString aFormula;
100 0 : if(mpCell)
101 : {
102 0 : mpCell->GetFormula(aFormula, eGrammar);
103 : }
104 :
105 0 : return aFormula;
106 : }
107 :
108 0 : double ScColorScaleEntry::GetValue() const
109 : {
110 0 : if(mpCell)
111 : {
112 0 : mpCell->Interpret();
113 0 : if(mpCell->IsValue())
114 0 : return mpCell->GetValue();
115 :
116 0 : return std::numeric_limits<double>::max();
117 : }
118 :
119 0 : return mnVal;
120 : }
121 :
122 0 : void ScColorScaleEntry::SetValue(double nValue)
123 : {
124 0 : mnVal = nValue;
125 0 : }
126 :
127 0 : void ScColorScaleEntry::UpdateMoveTab( SCTAB nOldTab, SCTAB nNewTab, SCTAB nTabNo )
128 : {
129 0 : if(mpCell)
130 : {
131 0 : mpCell->UpdateMoveTab( nOldTab, nNewTab, nTabNo );
132 : }
133 0 : }
134 :
135 0 : void ScColorScaleEntry::UpdateReference( UpdateRefMode eUpdateRefMode,
136 : const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
137 : {
138 0 : if(mpCell)
139 : {
140 0 : mpCell->UpdateReference( eUpdateRefMode, rRange, nDx, nDy, nDz );
141 : }
142 0 : }
143 :
144 0 : const Color& ScColorScaleEntry::GetColor() const
145 : {
146 0 : return maColor;
147 : }
148 :
149 0 : void ScColorScaleEntry::SetColor(const Color& rColor)
150 : {
151 0 : maColor = rColor;
152 0 : }
153 :
154 : #if DUMP_FORMAT_INFO
155 :
156 0 : void ScColorScaleEntry::dumpInfo(rtl::OUStringBuffer& rBuf) const
157 : {
158 0 : rBuf.append("Color Scale Entry\n");
159 0 : rBuf.append("Type: ");
160 0 : switch(meType)
161 : {
162 : case COLORSCALE_VALUE:
163 0 : rBuf.append( "Value\n" );
164 0 : break;
165 : case COLORSCALE_MIN:
166 0 : rBuf.append( "Min\n" );
167 0 : break;
168 : case COLORSCALE_MAX:
169 0 : rBuf.append( "Max\n" );
170 0 : break;
171 : case COLORSCALE_PERCENT:
172 0 : rBuf.append( "Percent\n" );
173 0 : break;
174 : case COLORSCALE_PERCENTILE:
175 0 : rBuf.append( "Percentile\n" );
176 0 : break;
177 : case COLORSCALE_FORMULA:
178 0 : rBuf.append( "Formual\n" );
179 0 : break;
180 : default:
181 0 : rBuf.append( "Unsupported Type\n" );
182 : }
183 0 : rBuf.append( "Color: " ).append( (sal_Int32)maColor.GetRed() ).append( "," ).append( (sal_Int32)maColor.GetGreen() ).append( "," ).append( (sal_Int32)maColor.GetBlue() ).append( "\n" );
184 0 : if(meType == COLORSCALE_FORMULA)
185 0 : rBuf.append( "Formula: " ).append( GetFormula( formula::FormulaGrammar::GRAM_DEFAULT ) ).append("\n");
186 0 : else if( meType != COLORSCALE_MIN && meType != COLORSCALE_MAX )
187 0 : rBuf.append( "Value: " ).append( mnVal ).append( "\n" );
188 0 : }
189 :
190 : #endif
191 :
192 0 : ScColorFormat::ScColorFormat(ScDocument* pDoc):
193 0 : ScFormatEntry(pDoc)
194 : {
195 0 : }
196 :
197 0 : ScColorFormat::~ScColorFormat()
198 : {
199 0 : }
200 :
201 0 : void ScColorFormat::SetParent( ScConditionalFormat* pParent )
202 : {
203 0 : mpParent = pParent;
204 0 : }
205 :
206 0 : ScColorScaleFormat::ScColorScaleFormat(ScDocument* pDoc):
207 0 : ScColorFormat(pDoc)
208 : {
209 0 : }
210 :
211 0 : ScColorScaleFormat::ScColorScaleFormat(ScDocument* pDoc, const ScColorScaleFormat& rFormat):
212 0 : ScColorFormat(pDoc)
213 : {
214 0 : for(const_iterator itr = rFormat.begin(); itr != rFormat.end(); ++itr)
215 : {
216 0 : maColorScales.push_back(new ScColorScaleEntry(pDoc, *itr));
217 : }
218 0 : }
219 :
220 0 : ScColorFormat* ScColorScaleFormat::Clone(ScDocument* pDoc) const
221 : {
222 0 : return new ScColorScaleFormat(pDoc, *this);
223 : }
224 :
225 0 : ScColorScaleFormat::~ScColorScaleFormat()
226 : {
227 0 : }
228 :
229 0 : void ScColorScaleFormat::AddEntry( ScColorScaleEntry* pEntry )
230 : {
231 0 : maColorScales.push_back( pEntry );
232 0 : }
233 :
234 0 : void ScColorScaleEntry::SetType( ScColorScaleEntryType eType )
235 : {
236 0 : meType = eType;
237 0 : if(eType != COLORSCALE_FORMULA)
238 0 : mpCell.reset();
239 0 : }
240 :
241 0 : ScColorScaleEntryType ScColorScaleEntry::GetType() const
242 : {
243 0 : return meType;
244 : }
245 :
246 0 : double ScColorScaleFormat::GetMinValue() const
247 : {
248 0 : const_iterator itr = maColorScales.begin();
249 :
250 0 : if(itr->GetType() == COLORSCALE_VALUE || itr->GetType() == COLORSCALE_FORMULA)
251 0 : return itr->GetValue();
252 : else
253 : {
254 0 : return getMinValue();
255 : }
256 : }
257 :
258 0 : double ScColorScaleFormat::GetMaxValue() const
259 : {
260 0 : ColorScaleEntries::const_reverse_iterator itr = maColorScales.rbegin();
261 :
262 0 : if(itr->GetType() == COLORSCALE_VALUE || itr->GetType() == COLORSCALE_FORMULA)
263 0 : return itr->GetValue();
264 : else
265 : {
266 0 : return getMaxValue();
267 : }
268 : }
269 :
270 0 : void ScColorScaleFormat::calcMinMax(double& rMin, double& rMax) const
271 : {
272 0 : rMin = GetMinValue();
273 0 : rMax = GetMaxValue();
274 0 : }
275 :
276 0 : const ScRangeList& ScColorFormat::GetRange() const
277 : {
278 0 : return mpParent->GetRange();
279 : }
280 :
281 0 : std::vector<double>& ScColorFormat::getValues() const
282 : {
283 0 : if(!mpCache)
284 : {
285 0 : mpCache.reset(new ScColorFormatCache);
286 0 : std::vector<double>& rValues = mpCache->maValues;
287 :
288 0 : size_t n = GetRange().size();
289 0 : const ScRangeList& aRanges = GetRange();
290 0 : for(size_t i = 0; i < n; ++i)
291 : {
292 0 : const ScRange* pRange = aRanges[i];
293 0 : SCTAB nTab = pRange->aStart.Tab();
294 0 : for(SCCOL nCol = pRange->aStart.Col(); nCol <= pRange->aEnd.Col(); ++nCol)
295 : {
296 0 : for(SCCOL nRow = pRange->aStart.Row(); nRow <= pRange->aEnd.Row(); ++nRow)
297 : {
298 0 : ScAddress aAddr(nCol, nRow, nTab);
299 0 : CellType eType = mpDoc->GetCellType(aAddr);
300 0 : if(eType == CELLTYPE_VALUE)
301 : {
302 0 : double aVal = mpDoc->GetValue(nCol, nRow, nTab);
303 0 : rValues.push_back(aVal);
304 : }
305 0 : else if(eType == CELLTYPE_FORMULA)
306 : {
307 0 : if(static_cast<ScFormulaCell*>(mpDoc->GetCell(aAddr))->IsValue())
308 : {
309 0 : double aVal = mpDoc->GetValue(nCol, nRow, nTab);
310 0 : rValues.push_back(aVal);
311 : }
312 : }
313 : }
314 : }
315 : }
316 :
317 0 : std::sort(rValues.begin(), rValues.end());
318 : }
319 :
320 0 : return mpCache->maValues;
321 : }
322 :
323 0 : double ScColorFormat::getMinValue() const
324 : {
325 0 : std::vector<double>& rValues = getValues();
326 0 : if(rValues.empty())
327 0 : return 0;
328 0 : return rValues[0];
329 : }
330 :
331 0 : double ScColorFormat::getMaxValue() const
332 : {
333 0 : std::vector<double>& rValues = getValues();
334 0 : if(rValues.empty())
335 0 : return 0;
336 0 : return rValues[rValues.size()-1];
337 : }
338 :
339 0 : void ScColorFormat::startRendering()
340 : {
341 0 : mpCache.reset();
342 0 : }
343 :
344 0 : void ScColorFormat::endRendering()
345 : {
346 0 : mpCache.reset();
347 0 : }
348 :
349 : namespace {
350 :
351 0 : sal_uInt8 GetColorValue( double nVal, double nVal1, sal_uInt8 nColVal1, double nVal2, sal_uInt8 nColVal2 )
352 : {
353 0 : if (nVal <= nVal1)
354 0 : return nColVal1;
355 :
356 0 : if (nVal >= nVal2)
357 0 : return nColVal2;
358 :
359 0 : sal_uInt8 nColVal = static_cast<sal_uInt8>((nVal - nVal1)/(nVal2-nVal1)*(nColVal2-nColVal1))+nColVal1;
360 0 : return nColVal;
361 : }
362 :
363 0 : Color CalcColor( double nVal, double nVal1, const Color& rCol1, double nVal2, const Color& rCol2)
364 : {
365 0 : sal_uInt8 nColRed = GetColorValue(nVal, nVal1, rCol1.GetRed(), nVal2, rCol2.GetRed());
366 0 : sal_uInt8 nColBlue = GetColorValue(nVal, nVal1, rCol1.GetBlue(), nVal2, rCol2.GetBlue());
367 0 : sal_uInt8 nColGreen = GetColorValue(nVal, nVal1, rCol1.GetGreen(), nVal2, rCol2.GetGreen());
368 :
369 0 : return Color(nColRed, nColGreen, nColBlue);
370 : }
371 :
372 : /**
373 : * @param rVector sorted vector of the array
374 : * @param fPercentile percentile
375 : */
376 0 : double GetPercentile( const std::vector<double>& rArray, double fPercentile )
377 : {
378 0 : size_t nSize = rArray.size();
379 0 : size_t nIndex = (size_t)::rtl::math::approxFloor( fPercentile * (nSize-1));
380 0 : double fDiff = fPercentile * (nSize-1) - ::rtl::math::approxFloor( fPercentile * (nSize-1));
381 0 : std::vector<double>::const_iterator iter = rArray.begin() + nIndex;
382 0 : if (fDiff == 0.0)
383 0 : return *iter;
384 : else
385 : {
386 0 : double fVal = *iter;
387 0 : iter = rArray.begin() + nIndex+1;
388 0 : return fVal + fDiff * (*iter - fVal);
389 : }
390 : }
391 :
392 : }
393 :
394 0 : double ScColorScaleFormat::CalcValue(double nMin, double nMax, ScColorScaleFormat::const_iterator& itr) const
395 : {
396 0 : switch(itr->GetType())
397 : {
398 : case COLORSCALE_PERCENT:
399 0 : return nMin + (nMax-nMin)*(itr->GetValue()/100);
400 : case COLORSCALE_MIN:
401 0 : return nMin;
402 : case COLORSCALE_MAX:
403 0 : return nMax;
404 : case COLORSCALE_PERCENTILE:
405 : {
406 0 : std::vector<double>& rValues = getValues();
407 0 : if(rValues.size() == 1)
408 0 : return rValues[0];
409 : else
410 : {
411 0 : double fPercentile = itr->GetValue()/100.0;
412 0 : return GetPercentile(rValues, fPercentile);
413 : }
414 : }
415 :
416 : default:
417 0 : break;
418 : }
419 :
420 0 : return itr->GetValue();
421 : }
422 :
423 0 : Color* ScColorScaleFormat::GetColor( const ScAddress& rAddr ) const
424 : {
425 0 : CellType eCellType = mpDoc->GetCellType(rAddr);
426 0 : if(eCellType != CELLTYPE_VALUE && eCellType != CELLTYPE_FORMULA)
427 0 : return NULL;
428 :
429 0 : if (eCellType == CELLTYPE_FORMULA)
430 : {
431 0 : if(!static_cast<ScFormulaCell*>(mpDoc->GetCell(rAddr))->IsValue())
432 0 : return NULL;
433 : }
434 :
435 : // now we have for sure a value
436 0 : double nVal = mpDoc->GetValue(rAddr);
437 :
438 0 : if (maColorScales.size() < 2)
439 0 : return NULL;
440 :
441 0 : double nMin = std::numeric_limits<double>::max();
442 0 : double nMax = std::numeric_limits<double>::min();
443 0 : calcMinMax(nMin, nMax);
444 :
445 : // this check is for safety
446 0 : if(nMin >= nMax)
447 0 : return NULL;
448 :
449 0 : const_iterator itr = begin();
450 0 : double nValMin = CalcValue(nMin, nMax, itr);
451 0 : Color rColMin = itr->GetColor();
452 0 : ++itr;
453 0 : double nValMax = CalcValue(nMin, nMax, itr);
454 0 : Color rColMax = itr->GetColor();
455 :
456 0 : ++itr;
457 0 : while(itr != end() && nVal > nValMax)
458 : {
459 0 : rColMin = rColMax;
460 0 : nValMin = nValMax;
461 0 : rColMax = itr->GetColor();
462 0 : nValMax = CalcValue(nMin, nMax, itr);
463 0 : ++itr;
464 : }
465 :
466 0 : Color aColor = CalcColor(nVal, nValMin, rColMin, nValMax, rColMax);
467 :
468 0 : return new Color(aColor);
469 : }
470 :
471 : #if DUMP_FORMAT_INFO
472 0 : void ScColorScaleFormat::dumpInfo(rtl::OUStringBuffer& rBuf) const
473 : {
474 0 : rBuf.append("Color Scale with ").append(static_cast<sal_Int32>(size())).append(" entries\n");
475 0 : for(const_iterator itr = begin(); itr != end(); ++itr)
476 : {
477 0 : itr->dumpInfo(rBuf);
478 : }
479 :
480 0 : const ScRangeList& rRange = GetRange();
481 0 : size_t n = rRange.size();
482 0 : for(size_t i = 0; i < n; ++i)
483 : {
484 0 : const ScRange* pRange = rRange[i];
485 0 : SCTAB nTab = pRange->aStart.Tab();
486 0 : for( SCCOL nCol = pRange->aStart.Col(), nEndCol = pRange->aEnd.Col(); nCol <= nEndCol; ++nCol)
487 : {
488 0 : for( SCROW nRow = pRange->aStart.Row(), nEndRow = pRange->aEnd.Row(); nRow <= nEndRow; ++nRow)
489 : {
490 0 : boost::scoped_ptr<Color> pColor( GetColor(ScAddress(nCol, nRow, nTab)) );
491 0 : rBuf.append((sal_Int32)nCol).append(",").append(nRow).append(",").append((sal_Int32)nTab).append(",");
492 0 : rBuf.append(((sal_Int32)pColor->GetRed())).append(",").append(((sal_Int32)pColor->GetGreen())).append(",").append(((sal_Int32)pColor->GetBlue())).append("\n");
493 0 : }
494 : }
495 : }
496 0 : }
497 : #endif
498 :
499 0 : void ScColorScaleFormat::UpdateMoveTab(SCTAB nOldTab, SCTAB nNewTab)
500 : {
501 0 : SCTAB nThisTab = GetRange().front()->aStart.Tab();
502 0 : for(iterator itr = begin(); itr != end(); ++itr)
503 : {
504 0 : itr->UpdateMoveTab(nOldTab, nNewTab, nThisTab);
505 : }
506 0 : }
507 :
508 0 : void ScColorScaleFormat::UpdateReference( UpdateRefMode eUpdateRefMode,
509 : const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
510 : {
511 0 : for(iterator itr = begin(); itr != end(); ++itr)
512 : {
513 0 : itr->UpdateReference(eUpdateRefMode, rRange, nDx, nDy, nDz);
514 : }
515 0 : }
516 :
517 0 : bool ScColorScaleFormat::CheckEntriesForRel(const ScRange& rRange) const
518 : {
519 0 : bool bNeedUpdate = false;
520 0 : for(const_iterator itr = begin(); itr != end(); ++itr)
521 : {
522 0 : ScColorScaleEntryType eType = itr->GetType();
523 0 : switch(eType)
524 : {
525 : case COLORSCALE_MIN:
526 : case COLORSCALE_MAX:
527 0 : bNeedUpdate = true;
528 0 : break;
529 : case COLORSCALE_FORMULA:
530 0 : return true;
531 : default:
532 0 : break;
533 : }
534 : }
535 :
536 : // TODO: check also if the changed value is the new min/max
537 : // or has been the old min/max value
538 0 : bNeedUpdate = bNeedUpdate && GetRange().Intersects(rRange);
539 0 : return bNeedUpdate;
540 : }
541 :
542 0 : void ScColorScaleFormat::DataChanged(const ScRange& rRange)
543 : {
544 0 : bool bNeedUpdate = CheckEntriesForRel(rRange);
545 0 : if(bNeedUpdate)
546 : {
547 0 : mpDoc->RepaintRange(GetRange());
548 : }
549 0 : }
550 :
551 0 : condformat::ScFormatEntryType ScColorScaleFormat::GetType() const
552 : {
553 0 : return condformat::COLORSCALE;
554 : }
555 :
556 0 : ScColorScaleFormat::iterator ScColorScaleFormat::begin()
557 : {
558 0 : return maColorScales.begin();
559 : }
560 :
561 0 : ScColorScaleFormat::const_iterator ScColorScaleFormat::begin() const
562 : {
563 0 : return maColorScales.begin();
564 : }
565 :
566 0 : ScColorScaleFormat::iterator ScColorScaleFormat::end()
567 : {
568 0 : return maColorScales.end();
569 : }
570 :
571 0 : ScColorScaleFormat::const_iterator ScColorScaleFormat::end() const
572 : {
573 0 : return maColorScales.end();
574 : }
575 :
576 0 : size_t ScColorScaleFormat::size() const
577 : {
578 0 : return maColorScales.size();
579 : }
580 :
581 0 : ScDataBarFormat::ScDataBarFormat(ScDocument* pDoc):
582 0 : ScColorFormat(pDoc)
583 : {
584 0 : }
585 :
586 0 : ScDataBarFormat::ScDataBarFormat(ScDocument* pDoc, const ScDataBarFormat& rFormat):
587 : ScColorFormat(pDoc),
588 0 : mpFormatData(new ScDataBarFormatData(*rFormat.mpFormatData))
589 : {
590 0 : }
591 :
592 0 : void ScDataBarFormat::SetDataBarData( ScDataBarFormatData* pData )
593 : {
594 0 : mpFormatData.reset(pData);
595 0 : }
596 :
597 0 : const ScDataBarFormatData* ScDataBarFormat::GetDataBarData() const
598 : {
599 0 : return mpFormatData.get();
600 : }
601 :
602 0 : ScColorFormat* ScDataBarFormat::Clone(ScDocument* pDoc) const
603 : {
604 0 : return new ScDataBarFormat(pDoc, *this);
605 : }
606 :
607 0 : condformat::ScFormatEntryType ScDataBarFormat::GetType() const
608 : {
609 0 : return condformat::DATABAR;
610 : }
611 :
612 0 : void ScDataBarFormat::UpdateReference( UpdateRefMode eRefMode,
613 : const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
614 : {
615 0 : mpFormatData->mpUpperLimit->UpdateReference( eRefMode, rRange, nDx, nDy, nDz );
616 0 : mpFormatData->mpLowerLimit->UpdateReference( eRefMode, rRange, nDx, nDy, nDz );
617 0 : }
618 :
619 : namespace {
620 :
621 0 : bool NeedUpdate(ScColorScaleEntry* pEntry)
622 : {
623 0 : switch(pEntry->GetType())
624 : {
625 : case COLORSCALE_MIN:
626 : case COLORSCALE_MAX:
627 : case COLORSCALE_FORMULA:
628 : case COLORSCALE_AUTO:
629 0 : return true;
630 : default:
631 0 : return false;
632 : }
633 : }
634 :
635 : }
636 :
637 0 : void ScDataBarFormat::DataChanged(const ScRange& rRange)
638 : {
639 0 : bool bNeedUpdate = NeedUpdate(mpFormatData->mpUpperLimit.get());
640 0 : bNeedUpdate |= NeedUpdate(mpFormatData->mpLowerLimit.get());
641 :
642 0 : bNeedUpdate &= GetRange().Intersects(rRange);
643 :
644 0 : if(bNeedUpdate)
645 : {
646 0 : mpDoc->RepaintRange(GetRange());
647 : }
648 0 : }
649 :
650 0 : void ScDataBarFormat::UpdateMoveTab(SCTAB nOldTab, SCTAB nNewTab)
651 : {
652 0 : SCTAB nThisTab = GetRange().front()->aStart.Tab();
653 0 : mpFormatData->mpUpperLimit->UpdateMoveTab(nOldTab, nNewTab, nThisTab);
654 0 : mpFormatData->mpLowerLimit->UpdateMoveTab(nOldTab, nNewTab, nThisTab);
655 0 : }
656 :
657 0 : double ScDataBarFormat::getMin(double nMin, double nMax) const
658 : {
659 0 : switch(mpFormatData->mpLowerLimit->GetType())
660 : {
661 : case COLORSCALE_MIN:
662 0 : return nMin;
663 :
664 : case COLORSCALE_AUTO:
665 0 : return std::min<double>(0, nMin);
666 :
667 : case COLORSCALE_PERCENT:
668 0 : return nMin + (nMax-nMin)/100*mpFormatData->mpLowerLimit->GetValue();
669 :
670 : case COLORSCALE_PERCENTILE:
671 : {
672 0 : double fPercentile = mpFormatData->mpLowerLimit->GetValue()/100.0;
673 0 : std::vector<double>& rValues = getValues();
674 0 : return GetPercentile(rValues, fPercentile);
675 : }
676 :
677 : default:
678 0 : break;
679 : }
680 :
681 0 : return mpFormatData->mpLowerLimit->GetValue();
682 : }
683 :
684 0 : double ScDataBarFormat::getMax(double nMin, double nMax) const
685 : {
686 0 : switch(mpFormatData->mpUpperLimit->GetType())
687 : {
688 : case COLORSCALE_MAX:
689 0 : return nMax;
690 : case COLORSCALE_AUTO:
691 0 : return std::max<double>(0, nMax);
692 : case COLORSCALE_PERCENT:
693 0 : return nMin + (nMax-nMin)/100*mpFormatData->mpUpperLimit->GetValue();
694 : case COLORSCALE_PERCENTILE:
695 : {
696 0 : double fPercentile = mpFormatData->mpUpperLimit->GetValue()/100.0;
697 0 : std::vector<double>& rValues = getValues();
698 0 : return GetPercentile(rValues, fPercentile);
699 : }
700 :
701 : default:
702 0 : break;
703 : }
704 :
705 0 : return mpFormatData->mpUpperLimit->GetValue();
706 : }
707 :
708 0 : ScDataBarInfo* ScDataBarFormat::GetDataBarInfo(const ScAddress& rAddr) const
709 : {
710 0 : CellType eCellType = mpDoc->GetCellType(rAddr);
711 0 : if(eCellType != CELLTYPE_VALUE && eCellType != CELLTYPE_FORMULA)
712 0 : return NULL;
713 :
714 0 : if (eCellType == CELLTYPE_FORMULA)
715 : {
716 0 : if(!static_cast<ScFormulaCell*>(mpDoc->GetCell(rAddr))->IsValue())
717 0 : return NULL;
718 : }
719 :
720 : // now we have for sure a value
721 : //
722 0 : double nValMin = getMinValue();
723 0 : double nValMax = getMaxValue();
724 0 : double nMin = getMin(nValMin, nValMax);
725 0 : double nMax = getMax(nValMin, nValMax);
726 :
727 :
728 0 : double nValue = mpDoc->GetValue(rAddr);
729 :
730 0 : ScDataBarInfo* pInfo = new ScDataBarInfo();
731 0 : if(mpFormatData->meAxisPosition == databar::NONE)
732 : {
733 0 : if(nValue <= nMin)
734 : {
735 0 : pInfo->mnLength = 0;
736 : }
737 0 : else if(nValue >= nMax)
738 : {
739 0 : pInfo->mnLength = 100;
740 : }
741 : else
742 : {
743 0 : double nDiff = nMax - nMin;
744 0 : pInfo->mnLength = (nValue - nMin)/nDiff*100.0;
745 : }
746 0 : pInfo->mnZero = 0;
747 : }
748 : else
749 : {
750 0 : double nMinPositive = 0;
751 0 : double nMaxNegative = 0;
752 : //calculate the zero position first
753 0 : if(mpFormatData->meAxisPosition == databar::AUTOMATIC)
754 : {
755 0 : if(nMin < 0)
756 : {
757 0 : if(nMax < 0)
758 0 : pInfo->mnZero = 100;
759 : else
760 : {
761 0 : pInfo->mnZero = -100*nMin/(nMax-nMin);
762 : }
763 : }
764 : else
765 0 : pInfo->mnZero = 0;
766 :
767 : // if max or min is used we may need to adjust it
768 : // for the length calculation
769 0 : if (mpFormatData->mpLowerLimit->GetType() == COLORSCALE_MIN && nMin > 0)
770 0 : nMinPositive = nMin;
771 0 : if (mpFormatData->mpUpperLimit->GetType() == COLORSCALE_MAX && nMax < 0)
772 0 : nMaxNegative = nMax;
773 : }
774 0 : else if( mpFormatData->meAxisPosition == databar::MIDDLE)
775 0 : pInfo->mnZero = 50;
776 :
777 : //calculate the length
778 0 : if(nValue < 0)
779 : {
780 0 : if (nValue < nMin)
781 0 : pInfo->mnLength = -100;
782 : else
783 0 : pInfo->mnLength = -100 * (nValue-nMaxNegative)/(nMin-nMaxNegative);
784 : }
785 : else
786 : {
787 0 : if ( nValue > nMax )
788 0 : pInfo->mnLength = 100;
789 : else
790 0 : pInfo->mnLength = (nValue-nMinPositive)/(nMax-nMinPositive)*100;
791 : }
792 : }
793 :
794 :
795 : // set color
796 0 : if(mpFormatData->mbNeg && nValue < 0)
797 : {
798 0 : if(mpFormatData->mpNegativeColor)
799 : {
800 0 : pInfo->maColor = *mpFormatData->mpNegativeColor.get();
801 : }
802 : else
803 : {
804 : // default negative color is red
805 0 : pInfo->maColor = COL_LIGHTRED;
806 : }
807 :
808 : }
809 : else
810 0 : pInfo->maColor = mpFormatData->maPositiveColor;
811 :
812 0 : pInfo->mbGradient = mpFormatData->mbGradient;
813 0 : pInfo->mbShowValue = !mpFormatData->mbOnlyBar;
814 0 : pInfo->maAxisColor = mpFormatData->maAxisColor;
815 :
816 0 : return pInfo;
817 : }
818 :
819 : #if DUMP_FORMAT_INFO
820 0 : void ScDataBarFormat::dumpInfo(rtl::OUStringBuffer& rBuf) const
821 : {
822 0 : const ScRangeList& rRange = GetRange();
823 0 : size_t n = rRange.size();
824 0 : for(size_t i = 0; i < n; ++i)
825 : {
826 0 : const ScRange* pRange = rRange[i];
827 0 : SCTAB nTab = pRange->aStart.Tab();
828 0 : for( SCCOL nCol = pRange->aStart.Col(), nEndCol = pRange->aEnd.Col(); nCol <= nEndCol; ++nCol)
829 : {
830 0 : for( SCROW nRow = pRange->aStart.Row(), nEndRow = pRange->aEnd.Row(); nRow <= nEndRow; ++nRow)
831 : {
832 0 : boost::scoped_ptr<ScDataBarInfo> pInfo( GetDataBarInfo(ScAddress(nCol, nRow, nTab)) );
833 0 : rBuf.append((sal_Int32) nCol).append(",").append(nRow).append(",").append((sal_Int32) nTab).append(",").append(pInfo->mnZero).append(",");
834 0 : rBuf.append(pInfo->mnLength).append(",").append((sal_Bool)pInfo->mbGradient).append(",").append((sal_Bool)pInfo->mbShowValue).append("\n");
835 0 : }
836 : }
837 : }
838 0 : }
839 : #endif
840 :
841 0 : ScIconSetFormat::ScIconSetFormat(ScDocument* pDoc):
842 : ScColorFormat(pDoc),
843 0 : mpFormatData(new ScIconSetFormatData)
844 : {
845 0 : }
846 :
847 0 : ScIconSetFormat::ScIconSetFormat(ScDocument* pDoc, const ScIconSetFormat& rFormat):
848 : ScColorFormat(pDoc),
849 0 : mpFormatData(new ScIconSetFormatData(*rFormat.mpFormatData))
850 : {
851 0 : }
852 :
853 0 : ScColorFormat* ScIconSetFormat::Clone( ScDocument* pDoc ) const
854 : {
855 0 : return new ScIconSetFormat(pDoc, *this);
856 : }
857 :
858 0 : void ScIconSetFormat::SetIconSetData( ScIconSetFormatData* pFormatData )
859 : {
860 0 : mpFormatData.reset( pFormatData );
861 0 : }
862 :
863 0 : const ScIconSetFormatData* ScIconSetFormat::GetIconSetData() const
864 : {
865 0 : return mpFormatData.get();
866 : }
867 :
868 0 : ScIconSetInfo* ScIconSetFormat::GetIconSetInfo(const ScAddress& rAddr) const
869 : {
870 0 : CellType eCellType = mpDoc->GetCellType(rAddr);
871 0 : if(eCellType != CELLTYPE_VALUE && eCellType != CELLTYPE_FORMULA)
872 0 : return NULL;
873 :
874 0 : if (eCellType == CELLTYPE_FORMULA)
875 : {
876 0 : if(!static_cast<ScFormulaCell*>(mpDoc->GetCell(rAddr))->IsValue())
877 0 : return NULL;
878 : }
879 :
880 0 : ScIconSetInfo* pInfo = new ScIconSetInfo;
881 :
882 : // now we have for sure a value
883 0 : double nVal = mpDoc->GetValue(rAddr);
884 :
885 0 : if (mpFormatData->maEntries.size() < 2)
886 0 : return NULL;
887 :
888 0 : double nMin = GetMinValue();
889 0 : double nMax = GetMaxValue();
890 :
891 : // this check is for safety
892 0 : if(nMin >= nMax)
893 0 : return NULL;
894 :
895 0 : sal_Int32 nIndex = 0;
896 0 : const_iterator itr = begin();
897 0 : ++itr;
898 0 : double nValMax = CalcValue(nMin, nMax, itr);
899 :
900 0 : ++itr;
901 0 : while(itr != end() && nVal > nValMax)
902 : {
903 0 : ++nIndex;
904 0 : nValMax = CalcValue(nMin, nMax, itr);
905 0 : ++itr;
906 : }
907 0 : if(nVal > nValMax)
908 0 : ++nIndex;
909 :
910 0 : pInfo->nIconIndex = nIndex;
911 0 : pInfo->eIconSetType = mpFormatData->eIconSetType;
912 0 : return pInfo;
913 : }
914 :
915 0 : condformat::ScFormatEntryType ScIconSetFormat::GetType() const
916 : {
917 0 : return condformat::ICONSET;
918 : }
919 :
920 0 : void ScIconSetFormat::DataChanged( const ScRange& )
921 : {
922 0 : }
923 :
924 0 : void ScIconSetFormat::UpdateMoveTab( SCTAB nOldTab, SCTAB nNewTab )
925 : {
926 0 : for(iterator itr = begin(); itr != end(); ++itr)
927 : {
928 0 : itr->UpdateMoveTab(nOldTab, nNewTab, 0);
929 : }
930 0 : }
931 :
932 0 : void ScIconSetFormat::UpdateReference( UpdateRefMode eUpdateRefMode,
933 : const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
934 : {
935 0 : for(iterator itr = begin(); itr != end(); ++itr)
936 : {
937 0 : itr->UpdateReference( eUpdateRefMode, rRange, nDx, nDy, nDz );
938 : }
939 0 : }
940 :
941 0 : void ScIconSetFormat::dumpInfo( rtl::OUStringBuffer& rBuffer ) const
942 : {
943 0 : rBuffer.append("IconSet: \n");
944 0 : for(const_iterator itr = begin(); itr != end(); ++itr)
945 : {
946 0 : itr->dumpInfo(rBuffer);
947 : }
948 0 : }
949 :
950 0 : ScIconSetFormat::iterator ScIconSetFormat::begin()
951 : {
952 0 : return mpFormatData->maEntries.begin();
953 : }
954 :
955 0 : ScIconSetFormat::const_iterator ScIconSetFormat::begin() const
956 : {
957 0 : return mpFormatData->maEntries.begin();
958 : }
959 :
960 0 : ScIconSetFormat::iterator ScIconSetFormat::end()
961 : {
962 0 : return mpFormatData->maEntries.end();
963 : }
964 :
965 0 : ScIconSetFormat::const_iterator ScIconSetFormat::end() const
966 : {
967 0 : return mpFormatData->maEntries.end();
968 : }
969 :
970 0 : double ScIconSetFormat::GetMinValue() const
971 : {
972 0 : const_iterator itr = begin();
973 :
974 0 : if(itr->GetType() == COLORSCALE_VALUE || itr->GetType() == COLORSCALE_FORMULA)
975 0 : return itr->GetValue();
976 : else
977 : {
978 0 : return getMinValue();
979 : }
980 : }
981 :
982 0 : double ScIconSetFormat::GetMaxValue() const
983 : {
984 0 : boost::ptr_vector<ScColorScaleEntry>::const_reverse_iterator itr = mpFormatData->maEntries.rbegin();
985 :
986 0 : if(itr->GetType() == COLORSCALE_VALUE || itr->GetType() == COLORSCALE_FORMULA)
987 0 : return itr->GetValue();
988 : else
989 : {
990 0 : return getMaxValue();
991 : }
992 : }
993 :
994 0 : double ScIconSetFormat::CalcValue(double nMin, double nMax, ScIconSetFormat::const_iterator& itr) const
995 : {
996 0 : switch(itr->GetType())
997 : {
998 : case COLORSCALE_PERCENT:
999 0 : return nMin + (nMax-nMin)*(itr->GetValue()/100);
1000 : case COLORSCALE_MIN:
1001 0 : return nMin;
1002 : case COLORSCALE_MAX:
1003 0 : return nMax;
1004 : case COLORSCALE_PERCENTILE:
1005 : {
1006 0 : std::vector<double>& rValues = getValues();
1007 0 : if(rValues.size() == 1)
1008 0 : return rValues[0];
1009 : else
1010 : {
1011 0 : double fPercentile = itr->GetValue()/100.0;
1012 0 : return GetPercentile(rValues, fPercentile);
1013 : }
1014 : }
1015 :
1016 : default:
1017 0 : break;
1018 : }
1019 :
1020 0 : return itr->GetValue();
1021 : }
1022 :
1023 0 : ScIconSetMap* ScIconSetFormat::getIconSetMap()
1024 : {
1025 :
1026 : static ScIconSetMap aIconSetMap[] = {
1027 : { "3Arrows", IconSet_3Arrows, 3 },
1028 : { "3ArrowsGray", IconSet_3ArrowsGray, 3 },
1029 : { "3Flags", IconSet_3Flags, 3 },
1030 : { "3TrafficLights1", IconSet_3TrafficLights1, 3 },
1031 : { "3TrafficLights2", IconSet_3TrafficLights2, 3 },
1032 : { "3Signs", IconSet_3Signs, 3 },
1033 : { "3Symbols", IconSet_3Symbols, 3 },
1034 : { "3Symbols2", IconSet_3Symbols2, 3 },
1035 : { "4Arrows", IconSet_4Arrows, 4 },
1036 : { "4ArrowsGray", IconSet_4ArrowsGray, 4 },
1037 : { "4RedToBlack", IconSet_4RedToBlack, 4 },
1038 : { "4Rating", IconSet_4Rating, 4 },
1039 : { "4TrafficLights", IconSet_4TrafficLights, 4 },
1040 : { "5Arrows", IconSet_5Arrows, 5 },
1041 : { "5ArrowsGray", IconSet_5ArrowsGray, 5 },
1042 : { "5Rating", IconSet_5Ratings, 5 },
1043 : { "5Quarters", IconSet_5Quarters, 5 },
1044 : { NULL, IconSet_3Arrows, 0 }
1045 : };
1046 :
1047 0 : return aIconSetMap;
1048 : }
1049 :
1050 : namespace {
1051 :
1052 : sal_Int32 a3TrafficLights1[] = {
1053 : BMP_ICON_SET_CIRCLES1_RED, BMP_ICON_SET_CIRCLES1_YELLOW, BMP_ICON_SET_CIRCLES1_GREEN
1054 : };
1055 :
1056 : sal_Int32 a3TrafficLights2[] = {
1057 : BMP_ICON_SET_TRAFFICLIGHTS_RED, BMP_ICON_SET_TRAFFICLIGHTS_YELLOW, BMP_ICON_SET_TRAFFICLIGHTS_GREEN
1058 : };
1059 :
1060 : sal_Int32 a3Arrows[] = {
1061 : BMP_ICON_SET_COLORARROWS_DOWN, BMP_ICON_SET_COLORARROWS_SAME, BMP_ICON_SET_COLORARROWS_UP
1062 : };
1063 :
1064 : sal_Int32 a3ArrowsGray[] = {
1065 : BMP_ICON_SET_GRAYARROWS_DOWN, BMP_ICON_SET_GRAYARROWS_SAME, BMP_ICON_SET_GRAYARROWS_UP
1066 : };
1067 :
1068 : sal_Int32 a3Flags[] = {
1069 : BMP_ICON_SET_FLAGS_RED, BMP_ICON_SET_FLAGS_YELLOW, BMP_ICON_SET_FLAGS_GREEN
1070 : };
1071 :
1072 : sal_Int32 a4Arrows[] = {
1073 : BMP_ICON_SET_COLORARROWS_DOWN, BMP_ICON_SET_COLORARROWS_SLIGHTLY_DOWN, BMP_ICON_SET_COLORARROWS_SLIGHTLY_UP, BMP_ICON_SET_COLORARROWS_UP
1074 : };
1075 :
1076 : sal_Int32 a4ArrowsGray[] = {
1077 : BMP_ICON_SET_GRAYARROWS_DOWN, BMP_ICON_SET_GRAYARROWS_SLIGHTLY_DOWN, BMP_ICON_SET_GRAYARROWS_SLIGHTLY_UP, BMP_ICON_SET_GRAYARROWS_UP
1078 : };
1079 :
1080 : sal_Int32 a5Arrows[] = {
1081 : BMP_ICON_SET_COLORARROWS_DOWN, BMP_ICON_SET_COLORARROWS_SLIGHTLY_DOWN,
1082 : BMP_ICON_SET_COLORARROWS_SAME, BMP_ICON_SET_COLORARROWS_SLIGHTLY_UP, BMP_ICON_SET_COLORARROWS_UP
1083 : };
1084 :
1085 : sal_Int32 a5ArrowsGray[] = {
1086 : BMP_ICON_SET_GRAYARROWS_DOWN, BMP_ICON_SET_GRAYARROWS_SLIGHTLY_DOWN,
1087 : BMP_ICON_SET_GRAYARROWS_SAME, BMP_ICON_SET_GRAYARROWS_SLIGHTLY_UP, BMP_ICON_SET_GRAYARROWS_UP
1088 : };
1089 :
1090 : sal_Int32 a4TrafficLights[] = {
1091 : BMP_ICON_SET_CIRCLES1_GRAY, BMP_ICON_SET_CIRCLES1_RED,
1092 : BMP_ICON_SET_CIRCLES1_YELLOW, BMP_ICON_SET_CIRCLES1_GREEN
1093 : };
1094 :
1095 : sal_Int32 a5Quarters[] = {
1096 : BMP_ICON_SET_PIES_EMPTY, BMP_ICON_SET_PIES_ONE_QUARTER, BMP_ICON_SET_PIES_HALF,
1097 : BMP_ICON_SET_PIES_THREE_QUARTER, BMP_ICON_SET_PIES_FULL,
1098 : };
1099 :
1100 : sal_Int32 a3Symbols1[] = {
1101 : BMP_ICON_SET_SYMBOLS1_CHECK, BMP_ICON_SET_SYMBOLS1_EXCLAMATION_MARK, BMP_ICON_SET_SYMBOLS1_CROSS
1102 : };
1103 :
1104 : sal_Int32 a3Signs[] = {
1105 : BMP_ICON_SET_SHAPES_DIAMOND, BMP_ICON_SET_SHAPES_TRIANGLE, BMP_ICON_SET_SHAPES_CIRCLE
1106 : };
1107 :
1108 : sal_Int32 a4RedToBlack[] = {
1109 : BMP_ICON_SET_CIRCLES2_DARK_GRAY, BMP_ICON_SET_CIRCLES2_LIGHT_GRAY,
1110 : BMP_ICON_SET_CIRCLES2_LIGHT_RED, BMP_ICON_SET_CIRCLES2_DARK_RED
1111 : };
1112 :
1113 : sal_Int32 a4Ratings[] = {
1114 : BMP_ICON_SET_BARS_ONE_QUARTER, BMP_ICON_SET_BARS_HALF,
1115 : BMP_ICON_SET_BARS_THREE_QUARTER, BMP_ICON_SET_BARS_FULL
1116 : };
1117 :
1118 : sal_Int32 a5Ratings[] = {
1119 : BMP_ICON_SET_BARS_EMPTY, BMP_ICON_SET_BARS_ONE_QUARTER, BMP_ICON_SET_BARS_HALF,
1120 : BMP_ICON_SET_BARS_THREE_QUARTER, BMP_ICON_SET_BARS_FULL
1121 : };
1122 :
1123 : struct ScIconSetBitmapMap {
1124 : ScIconSetType eType;
1125 : sal_Int32* nBitmaps;
1126 : };
1127 :
1128 : static ScIconSetBitmapMap aBitmapMap[] = {
1129 : { IconSet_3Arrows, a3Arrows },
1130 : { IconSet_3ArrowsGray, a3ArrowsGray },
1131 : { IconSet_3Flags, a3Flags },
1132 : { IconSet_3Signs, a3Signs },
1133 : { IconSet_3Symbols, a3Symbols1 },
1134 : { IconSet_3Symbols2, a3Symbols1 },
1135 : { IconSet_3TrafficLights1, a3TrafficLights1 },
1136 : { IconSet_3TrafficLights2, a3TrafficLights2 },
1137 : { IconSet_4Arrows, a4Arrows },
1138 : { IconSet_4ArrowsGray, a4ArrowsGray },
1139 : { IconSet_4Rating, a4Ratings },
1140 : { IconSet_4RedToBlack, a4RedToBlack },
1141 : { IconSet_4TrafficLights, a4TrafficLights },
1142 : { IconSet_5Arrows, a5Arrows },
1143 : { IconSet_5ArrowsGray, a5ArrowsGray },
1144 : { IconSet_5Quarters, a5Quarters },
1145 : { IconSet_5Ratings, a5Ratings }
1146 : };
1147 :
1148 : }
1149 :
1150 0 : BitmapEx& ScIconSetFormat::getBitmap( ScIconSetType eType, sal_Int32 nIndex )
1151 : {
1152 0 : static std::map< sal_Int32, BitmapEx > aIconSetBitmaps;
1153 :
1154 0 : sal_Int32 nBitmap = -1;
1155 :
1156 0 : for(size_t i = 0; i < SAL_N_ELEMENTS(aBitmapMap); ++i)
1157 : {
1158 0 : if(aBitmapMap[i].eType == eType)
1159 : {
1160 0 : nBitmap = *(aBitmapMap[i].nBitmaps + nIndex);
1161 : }
1162 : }
1163 : assert( nBitmap != -1 );
1164 :
1165 0 : std::map<sal_Int32, BitmapEx>::iterator itr = aIconSetBitmaps.find( nBitmap );
1166 0 : if(itr != aIconSetBitmaps.end())
1167 0 : return itr->second;
1168 :
1169 0 : BitmapEx aBitmap = BitmapEx(ScResId(nBitmap));
1170 0 : std::pair<sal_Int32, BitmapEx> aPair( nBitmap, aBitmap );
1171 0 : std::pair<std::map<sal_Int32, BitmapEx>::iterator, bool> itrNew = aIconSetBitmaps.insert(aPair);
1172 : assert(itrNew.second);
1173 :
1174 0 : return itrNew.first->second;
1175 15 : }
1176 :
1177 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|