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