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