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