1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
11 #include <colorscale.hxx>
12 #include <document.hxx>
13 #include <formulacell.hxx>
14 #include <fillinfo.hxx>
15 #include <bitmaps.hlst>
16 #include <tokenarray.hxx>
17 #include <refupdatecontext.hxx>
18 #include <refdata.hxx>
20 #include <formula/token.hxx>
21 #include <vcl/bitmapex.hxx>
25 #include <string_view>
27 ScFormulaListener::ScFormulaListener(ScFormulaCell
* pCell
):
29 mrDoc(pCell
->GetDocument())
31 startListening( pCell
->GetCode(), pCell
->aPos
);
34 ScFormulaListener::ScFormulaListener(ScDocument
& rDoc
):
40 ScFormulaListener::ScFormulaListener(ScDocument
& rDoc
, const ScRangeList
& rRange
):
44 startListening(rRange
);
47 void ScFormulaListener::startListening(const ScTokenArray
* pArr
, const ScRange
& rRange
)
49 if (!pArr
|| mrDoc
.IsClipOrUndo())
52 for ( auto t
: pArr
->References() )
56 case formula::svSingleRef
:
58 ScAddress aCell
= t
->GetSingleRef()->toAbs(mrDoc
, rRange
.aStart
);
59 ScAddress aCell2
= t
->GetSingleRef()->toAbs(mrDoc
, rRange
.aEnd
);
60 ScRange
aRange(aCell
, aCell2
);
62 mrDoc
.StartListeningArea(aRange
, false, this);
65 case formula::svDoubleRef
:
67 const ScSingleRefData
& rRef1
= *t
->GetSingleRef();
68 const ScSingleRefData
& rRef2
= *t
->GetSingleRef2();
69 ScAddress aCell1
= rRef1
.toAbs(mrDoc
, rRange
.aStart
);
70 ScAddress aCell2
= rRef2
.toAbs(mrDoc
, rRange
.aStart
);
71 ScAddress aCell3
= rRef1
.toAbs(mrDoc
, rRange
.aEnd
);
72 ScAddress aCell4
= rRef2
.toAbs(mrDoc
, rRange
.aEnd
);
73 ScRange
aRange1(aCell1
, aCell3
);
74 ScRange
aRange2(aCell2
, aCell4
);
75 aRange1
.ExtendTo(aRange2
);
76 if (aRange1
.IsValid())
78 if (t
->GetOpCode() == ocColRowNameAuto
)
80 if ( rRef1
.IsColRel() )
82 aRange1
.aEnd
.SetRow(mrDoc
.MaxRow());
86 aRange1
.aEnd
.SetCol(mrDoc
.MaxCol());
89 mrDoc
.StartListeningArea(aRange1
, false, this);
99 void ScFormulaListener::startListening(const ScRangeList
& rRange
)
101 if (mrDoc
.IsClipOrUndo())
104 size_t nLength
= rRange
.size();
105 for (size_t i
= 0; i
< nLength
; ++i
)
107 const ScRange
& aRange
= rRange
[i
];
108 mrDoc
.StartListeningArea(aRange
, false, this);
112 void ScFormulaListener::addTokenArray(const ScTokenArray
* pArray
, const ScRange
& rRange
)
114 startListening(pArray
, rRange
);
117 void ScFormulaListener::setCallback(const std::function
<void()>& aCallback
)
119 maCallbackFunction
= aCallback
;
122 void ScFormulaListener::stopListening()
124 if (mrDoc
.IsClipOrUndo())
130 ScFormulaListener::~ScFormulaListener()
135 void ScFormulaListener::Notify(const SfxHint
& rHint
)
139 if (rHint
.GetId() == SfxHintId::Dying
)
142 if (maCallbackFunction
)
143 maCallbackFunction();
146 bool ScFormulaListener::NeedsRepaint() const
153 ScColorScaleEntry::ScColorScaleEntry():
156 meType(COLORSCALE_VALUE
)
160 ScColorScaleEntry::ScColorScaleEntry(double nVal
, const Color
& rCol
, ScColorScaleEntryType eType
):
168 ScColorScaleEntry::ScColorScaleEntry(const ScColorScaleEntry
& rEntry
):
170 mpFormat(rEntry
.mpFormat
),
171 maColor(rEntry
.maColor
),
172 meType(rEntry
.meType
)
177 mpCell
.reset(new ScFormulaCell(*rEntry
.mpCell
, rEntry
.mpCell
->GetDocument(), rEntry
.mpCell
->aPos
, ScCloneFlags::NoMakeAbsExternal
));
178 mpCell
->StartListeningTo(mpCell
->GetDocument());
179 mpListener
.reset(new ScFormulaListener(mpCell
.get()));
183 ScColorScaleEntry::ScColorScaleEntry(ScDocument
* pDoc
, const ScColorScaleEntry
& rEntry
):
185 mpFormat(rEntry
.mpFormat
),
186 maColor(rEntry
.maColor
),
187 meType(rEntry
.meType
)
192 mpCell
.reset(new ScFormulaCell(*rEntry
.mpCell
, *pDoc
, rEntry
.mpCell
->aPos
, ScCloneFlags::NoMakeAbsExternal
));
193 mpCell
->StartListeningTo( *pDoc
);
194 mpListener
.reset(new ScFormulaListener(mpCell
.get()));
196 mpListener
->setCallback([&]() { mpFormat
->DoRepaint();});
200 ScColorScaleEntry::~ScColorScaleEntry() COVERITY_NOEXCEPT_FALSE
203 mpCell
->EndListeningTo(mpCell
->GetDocument());
206 void ScColorScaleEntry::SetFormula( const OUString
& rFormula
, ScDocument
& rDoc
, const ScAddress
& rAddr
, formula::FormulaGrammar::Grammar eGrammar
)
208 mpCell
.reset(new ScFormulaCell( rDoc
, rAddr
, rFormula
, eGrammar
));
209 mpCell
->StartListeningTo( rDoc
);
210 mpListener
.reset(new ScFormulaListener(mpCell
.get()));
212 mpListener
->setCallback([&]() { mpFormat
->DoRepaint();});
215 const ScTokenArray
* ScColorScaleEntry::GetFormula() const
219 return mpCell
->GetCode();
225 OUString
ScColorScaleEntry::GetFormula( formula::FormulaGrammar::Grammar eGrammar
) const
229 return mpCell
->GetFormula(eGrammar
);
235 double ScColorScaleEntry::GetValue() const
240 if(mpCell
->IsValue())
241 return mpCell
->GetValue();
243 return std::numeric_limits
<double>::max();
249 void ScColorScaleEntry::SetValue(double nValue
)
256 void ScColorScaleEntry::UpdateReference( const sc::RefUpdateContext
& rCxt
)
264 mpCell
->UpdateReference(rCxt
);
265 mpListener
.reset(new ScFormulaListener(mpCell
.get()));
266 SetRepaintCallback(mpFormat
);
269 void ScColorScaleEntry::UpdateInsertTab( const sc::RefUpdateInsertTabContext
& rCxt
)
277 mpCell
->UpdateInsertTab(rCxt
);
278 mpListener
.reset(new ScFormulaListener(mpCell
.get()));
279 SetRepaintCallback(mpFormat
);
282 void ScColorScaleEntry::UpdateDeleteTab( const sc::RefUpdateDeleteTabContext
& rCxt
)
290 mpCell
->UpdateDeleteTab(rCxt
);
291 mpListener
.reset(new ScFormulaListener(mpCell
.get()));
292 SetRepaintCallback(mpFormat
);
295 void ScColorScaleEntry::UpdateMoveTab( const sc::RefUpdateMoveTabContext
& rCxt
)
303 SCTAB nTabNo
= rCxt
.getNewTab(mpCell
->aPos
.Tab());
304 mpCell
->UpdateMoveTab(rCxt
, nTabNo
);
305 mpListener
.reset(new ScFormulaListener(mpCell
.get()));
306 SetRepaintCallback(mpFormat
);
309 void ScColorScaleEntry::SetColor(const Color
& rColor
)
314 void ScColorScaleEntry::SetRepaintCallback(ScConditionalFormat
* pFormat
)
318 if (mpFormat
&& mpListener
)
319 mpListener
->setCallback([&]() { mpFormat
->DoRepaint();});
322 void ScColorScaleEntry::SetType( ScColorScaleEntryType eType
)
325 if(eType
!= COLORSCALE_FORMULA
)
334 void ScColorScaleEntry::setListener()
339 if (meType
== COLORSCALE_PERCENT
|| meType
== COLORSCALE_PERCENTILE
340 || meType
== COLORSCALE_MIN
|| meType
== COLORSCALE_MAX
341 || meType
== COLORSCALE_AUTO
)
343 mpListener
.reset(new ScFormulaListener(*mpFormat
->GetDocument(), mpFormat
->GetRange()));
344 mpListener
->setCallback([&]() { mpFormat
->DoRepaint();});
348 void ScColorScaleEntry::SetRepaintCallback(const std::function
<void()>& func
)
350 mpListener
->setCallback(func
);
353 ScColorFormat::ScColorFormat(ScDocument
* pDoc
)
354 : ScFormatEntry(pDoc
)
359 ScColorFormat::~ScColorFormat()
363 void ScColorFormat::SetParent( ScConditionalFormat
* pParent
)
368 ScColorScaleFormat::ScColorScaleFormat(ScDocument
* pDoc
):
373 ScColorScaleFormat::ScColorScaleFormat(ScDocument
* pDoc
, const ScColorScaleFormat
& rFormat
):
376 for(const auto& rxEntry
: rFormat
)
378 maColorScales
.emplace_back(new ScColorScaleEntry(pDoc
, *rxEntry
));
382 ScColorFormat
* ScColorScaleFormat::Clone(ScDocument
* pDoc
) const
384 return new ScColorScaleFormat(pDoc
, *this);
387 ScColorScaleFormat::~ScColorScaleFormat()
391 void ScColorScaleFormat::SetParent(ScConditionalFormat
* pFormat
)
393 for (auto itr
= begin(), itrEnd
= end(); itr
!= itrEnd
; ++itr
)
395 (*itr
)->SetRepaintCallback(pFormat
);
397 ScColorFormat::SetParent(pFormat
);
400 void ScColorScaleFormat::AddEntry( ScColorScaleEntry
* pEntry
)
402 maColorScales
.push_back(std::unique_ptr
<ScColorScaleEntry
, o3tl::default_delete
<ScColorScaleEntry
>>(pEntry
));
403 maColorScales
.back()->SetRepaintCallback(mpParent
);
406 double ScColorScaleFormat::GetMinValue() const
408 ScColorScaleEntries::const_iterator itr
= maColorScales
.begin();
410 if((*itr
)->GetType() == COLORSCALE_VALUE
|| (*itr
)->GetType() == COLORSCALE_FORMULA
)
411 return (*itr
)->GetValue();
414 return getMinValue();
418 double ScColorScaleFormat::GetMaxValue() const
420 ScColorScaleEntries::const_reverse_iterator itr
= maColorScales
.rbegin();
422 if((*itr
)->GetType() == COLORSCALE_VALUE
|| (*itr
)->GetType() == COLORSCALE_FORMULA
)
423 return (*itr
)->GetValue();
426 return getMaxValue();
430 void ScColorScaleFormat::calcMinMax(double& rMin
, double& rMax
) const
432 rMin
= GetMinValue();
433 rMax
= GetMaxValue();
436 const ScRangeList
& ScColorFormat::GetRange() const
438 return mpParent
->GetRange();
441 std::vector
<double>& ScColorFormat::getValues() const
445 mpCache
.reset(new ScColorFormatCache
);
446 std::vector
<double>& rValues
= mpCache
->maValues
;
448 size_t n
= GetRange().size();
449 const ScRangeList
& aRanges
= GetRange();
450 for(size_t i
= 0; i
< n
; ++i
)
452 const ScRange
& rRange
= aRanges
[i
];
453 SCTAB nTab
= rRange
.aStart
.Tab();
455 SCCOL nColStart
= rRange
.aStart
.Col();
456 SCROW nRowStart
= rRange
.aStart
.Row();
457 SCCOL nColEnd
= rRange
.aEnd
.Col();
458 SCROW nRowEnd
= rRange
.aEnd
.Row();
460 if(nRowEnd
== MAXROW
)
462 bool bShrunk
= false;
463 mpDoc
->ShrinkToUsedDataArea(bShrunk
, nTab
, nColStart
, nRowStart
,
464 nColEnd
, nRowEnd
, false);
466 for(SCCOL nCol
= nColStart
; nCol
<= nColEnd
; ++nCol
)
468 for(SCROW nRow
= nRowStart
; nRow
<= nRowEnd
; ++nRow
)
470 ScAddress
aAddr(nCol
, nRow
, nTab
);
471 ScRefCellValue
rCell(*mpDoc
, aAddr
);
472 if(rCell
.hasNumeric())
474 double aVal
= rCell
.getValue();
475 rValues
.push_back(aVal
);
481 std::sort(rValues
.begin(), rValues
.end());
484 return mpCache
->maValues
;
487 double ScColorFormat::getMinValue() const
489 std::vector
<double>& rValues
= getValues();
495 double ScColorFormat::getMaxValue() const
497 std::vector
<double>& rValues
= getValues();
500 return rValues
[rValues
.size()-1];
503 void ScColorFormat::startRendering()
508 void ScColorFormat::endRendering()
513 void ScColorFormat::updateValues()
521 sal_uInt8
GetColorValue( double nVal
, double nVal1
, sal_uInt8 nColVal1
, double nVal2
, sal_uInt8 nColVal2
)
529 sal_uInt8 nColVal
= static_cast<int>((nVal
- nVal1
)/(nVal2
-nVal1
)*(nColVal2
-nColVal1
))+nColVal1
;
533 Color
CalcColor( double nVal
, double nVal1
, const Color
& rCol1
, double nVal2
, const Color
& rCol2
)
535 sal_uInt8 nColRed
= GetColorValue(nVal
, nVal1
, rCol1
.GetRed(), nVal2
, rCol2
.GetRed());
536 sal_uInt8 nColBlue
= GetColorValue(nVal
, nVal1
, rCol1
.GetBlue(), nVal2
, rCol2
.GetBlue());
537 sal_uInt8 nColGreen
= GetColorValue(nVal
, nVal1
, rCol1
.GetGreen(), nVal2
, rCol2
.GetGreen());
539 return Color(nColRed
, nColGreen
, nColBlue
);
543 * @param rVector sorted vector of the array
544 * @param fPercentile percentile
546 double GetPercentile( const std::vector
<double>& rArray
, double fPercentile
)
548 size_t nSize
= rArray
.size();
549 double fFloor
= ::rtl::math::approxFloor(fPercentile
* (nSize
-1));
550 SAL_WARN_IF(fFloor
< 0, "sc", "negative percentile");
551 size_t nIndex
= fFloor
>= 0 ? static_cast<size_t>(fFloor
) : 0;
552 double fDiff
= fPercentile
* (nSize
-1) - fFloor
;
553 std::vector
<double>::const_iterator iter
= rArray
.begin() + nIndex
;
559 iter
= rArray
.begin() + nIndex
+1;
560 return fVal
+ fDiff
* (*iter
- fVal
);
566 double ScColorScaleFormat::CalcValue(double nMin
, double nMax
, const ScColorScaleEntries::const_iterator
& itr
) const
568 switch((*itr
)->GetType())
570 case COLORSCALE_PERCENT
:
571 return nMin
+ (nMax
-nMin
)*((*itr
)->GetValue()/100);
576 case COLORSCALE_PERCENTILE
:
578 std::vector
<double>& rValues
= getValues();
579 if(rValues
.size() == 1)
583 double fPercentile
= (*itr
)->GetValue()/100.0;
584 return GetPercentile(rValues
, fPercentile
);
592 return (*itr
)->GetValue();
595 std::optional
<Color
> ScColorScaleFormat::GetColor( const ScAddress
& rAddr
) const
597 ScRefCellValue
rCell(*mpDoc
, rAddr
);
598 if(!rCell
.hasNumeric())
599 return std::optional
<Color
>();
601 // now we have for sure a value
602 double nVal
= rCell
.getValue();
604 if (maColorScales
.size() < 2)
605 return std::optional
<Color
>();
607 double nMin
= std::numeric_limits
<double>::max();
608 double nMax
= std::numeric_limits
<double>::min();
609 calcMinMax(nMin
, nMax
);
611 // this check is for safety
613 return std::optional
<Color
>();
615 ScColorScaleEntries::const_iterator itr
= begin();
616 double nValMin
= CalcValue(nMin
, nMax
, itr
);
617 Color rColMin
= (*itr
)->GetColor();
619 double nValMax
= CalcValue(nMin
, nMax
, itr
);
620 Color rColMax
= (*itr
)->GetColor();
623 while(itr
!= end() && nVal
> nValMax
)
627 rColMax
= (*itr
)->GetColor();
628 nValMax
= CalcValue(nMin
, nMax
, itr
);
632 Color aColor
= CalcColor(nVal
, nValMin
, rColMin
, nValMax
, rColMax
);
637 void ScColorScaleFormat::UpdateReference( sc::RefUpdateContext
& rCxt
)
639 for(ScColorScaleEntries::iterator itr
= begin(); itr
!= end(); ++itr
)
640 (*itr
)->UpdateReference(rCxt
);
643 void ScColorScaleFormat::UpdateInsertTab( sc::RefUpdateInsertTabContext
& rCxt
)
645 for (ScColorScaleEntries::iterator it
= begin(); it
!= end(); ++it
)
646 (*it
)->UpdateInsertTab(rCxt
);
649 void ScColorScaleFormat::UpdateDeleteTab( sc::RefUpdateDeleteTabContext
& rCxt
)
651 for (ScColorScaleEntries::iterator it
= begin(); it
!= end(); ++it
)
652 (*it
)->UpdateDeleteTab(rCxt
);
655 void ScColorScaleFormat::UpdateMoveTab( sc::RefUpdateMoveTabContext
& rCxt
)
657 for (ScColorScaleEntries::iterator it
= begin(); it
!= end(); ++it
)
658 (*it
)->UpdateMoveTab(rCxt
);
661 ScFormatEntry::Type
ScColorScaleFormat::GetType() const
663 return Type::Colorscale
;
666 ScColorScaleEntries::iterator
ScColorScaleFormat::begin()
668 return maColorScales
.begin();
671 ScColorScaleEntries::const_iterator
ScColorScaleFormat::begin() const
673 return maColorScales
.begin();
676 ScColorScaleEntries::iterator
ScColorScaleFormat::end()
678 return maColorScales
.end();
681 ScColorScaleEntries::const_iterator
ScColorScaleFormat::end() const
683 return maColorScales
.end();
686 ScColorScaleEntry
* ScColorScaleFormat::GetEntry(size_t nPos
)
688 if (maColorScales
.size() <= nPos
)
691 return maColorScales
[nPos
].get();
694 const ScColorScaleEntry
* ScColorScaleFormat::GetEntry(size_t nPos
) const
696 if (maColorScales
.size() <= nPos
)
699 return maColorScales
[nPos
].get();
702 size_t ScColorScaleFormat::size() const
704 return maColorScales
.size();
707 void ScColorScaleFormat::EnsureSize()
709 if (maColorScales
.size() < 2)
711 // TODO: create 2 valid entries
715 ScDataBarFormat::ScDataBarFormat(ScDocument
* pDoc
):
717 mpFormatData(new ScDataBarFormatData())
721 ScDataBarFormat::ScDataBarFormat(ScDocument
* pDoc
, const ScDataBarFormat
& rFormat
):
723 mpFormatData(new ScDataBarFormatData(*rFormat
.mpFormatData
))
727 void ScDataBarFormat::SetDataBarData( ScDataBarFormatData
* pData
)
729 mpFormatData
.reset(pData
);
732 mpFormatData
->mpUpperLimit
->SetRepaintCallback(mpParent
);
733 mpFormatData
->mpLowerLimit
->SetRepaintCallback(mpParent
);
737 ScDataBarFormatData
* ScDataBarFormat::GetDataBarData()
739 return mpFormatData
.get();
742 const ScDataBarFormatData
* ScDataBarFormat::GetDataBarData() const
744 return mpFormatData
.get();
747 ScColorFormat
* ScDataBarFormat::Clone(ScDocument
* pDoc
) const
749 return new ScDataBarFormat(pDoc
, *this);
752 void ScDataBarFormat::SetParent(ScConditionalFormat
* pFormat
)
756 mpFormatData
->mpUpperLimit
->SetRepaintCallback(pFormat
);
757 mpFormatData
->mpLowerLimit
->SetRepaintCallback(pFormat
);
759 ScColorFormat::SetParent(pFormat
);
762 ScFormatEntry::Type
ScDataBarFormat::GetType() const
764 return Type::Databar
;
767 void ScDataBarFormat::UpdateReference( sc::RefUpdateContext
& rCxt
)
769 mpFormatData
->mpUpperLimit
->UpdateReference(rCxt
);
770 mpFormatData
->mpLowerLimit
->UpdateReference(rCxt
);
773 void ScDataBarFormat::UpdateInsertTab( sc::RefUpdateInsertTabContext
& rCxt
)
775 mpFormatData
->mpUpperLimit
->UpdateInsertTab(rCxt
);
776 mpFormatData
->mpLowerLimit
->UpdateInsertTab(rCxt
);
779 void ScDataBarFormat::UpdateDeleteTab( sc::RefUpdateDeleteTabContext
& rCxt
)
781 mpFormatData
->mpUpperLimit
->UpdateDeleteTab(rCxt
);
782 mpFormatData
->mpLowerLimit
->UpdateDeleteTab(rCxt
);
785 void ScDataBarFormat::UpdateMoveTab( sc::RefUpdateMoveTabContext
& rCxt
)
787 mpFormatData
->mpUpperLimit
->UpdateMoveTab(rCxt
);
788 mpFormatData
->mpLowerLimit
->UpdateMoveTab(rCxt
);
791 double ScDataBarFormat::getMin(double nMin
, double nMax
) const
793 switch(mpFormatData
->mpLowerLimit
->GetType())
798 case COLORSCALE_AUTO
:
799 return std::min
<double>(0, nMin
);
801 case COLORSCALE_PERCENT
:
802 return nMin
+ (nMax
-nMin
)/100*mpFormatData
->mpLowerLimit
->GetValue();
804 case COLORSCALE_PERCENTILE
:
806 double fPercentile
= mpFormatData
->mpLowerLimit
->GetValue()/100.0;
807 std::vector
<double>& rValues
= getValues();
808 return GetPercentile(rValues
, fPercentile
);
815 return mpFormatData
->mpLowerLimit
->GetValue();
818 double ScDataBarFormat::getMax(double nMin
, double nMax
) const
820 switch(mpFormatData
->mpUpperLimit
->GetType())
824 case COLORSCALE_AUTO
:
825 return std::max
<double>(0, nMax
);
826 case COLORSCALE_PERCENT
:
827 return nMin
+ (nMax
-nMin
)/100*mpFormatData
->mpUpperLimit
->GetValue();
828 case COLORSCALE_PERCENTILE
:
830 double fPercentile
= mpFormatData
->mpUpperLimit
->GetValue()/100.0;
831 std::vector
<double>& rValues
= getValues();
832 return GetPercentile(rValues
, fPercentile
);
839 return mpFormatData
->mpUpperLimit
->GetValue();
842 std::unique_ptr
<ScDataBarInfo
> ScDataBarFormat::GetDataBarInfo(const ScAddress
& rAddr
) const
844 ScRefCellValue
rCell(*mpDoc
, rAddr
);
845 if(!rCell
.hasNumeric())
848 // now we have for sure a value
850 double nValMin
= getMinValue();
851 double nValMax
= getMaxValue();
852 double nMin
= getMin(nValMin
, nValMax
);
853 double nMax
= getMax(nValMin
, nValMax
);
854 double nMinLength
= mpFormatData
->mnMinLength
;
855 double nMaxLength
= mpFormatData
->mnMaxLength
;
857 double nValue
= rCell
.getValue();
859 std::unique_ptr
<ScDataBarInfo
> pInfo(new ScDataBarInfo
);
860 if(mpFormatData
->meAxisPosition
== databar::NONE
)
864 pInfo
->mnLength
= nMinLength
;
866 else if(nValue
>= nMax
)
868 pInfo
->mnLength
= nMaxLength
;
872 double nDiff
= nMax
- nMin
;
873 pInfo
->mnLength
= nMinLength
+ (nValue
- nMin
)/nDiff
* (nMaxLength
-nMinLength
);
877 else if (mpFormatData
->meAxisPosition
== databar::AUTOMATIC
)
879 // if auto is used we may need to adjust it
880 // for the length calculation
881 if (mpFormatData
->mpLowerLimit
->GetType() == COLORSCALE_AUTO
&& nMin
> 0)
883 if (mpFormatData
->mpUpperLimit
->GetType() == COLORSCALE_MAX
&& nMax
< 0)
886 //calculate the zero position first
893 pInfo
->mnZero
= -100*nMin
/(nMax
-nMin
);
899 double nMinNonNegative
= std::max(0.0, nMin
);
900 double nMaxNonPositive
= std::min(0.0, nMax
);
901 //calculate the length
902 if(nValue
< 0 && nMin
< 0)
905 pInfo
->mnLength
= -100;
907 pInfo
->mnLength
= -100 * (nValue
-nMaxNonPositive
)/(nMin
-nMaxNonPositive
);
912 pInfo
->mnLength
= 100;
913 else if (nValue
<= nMin
)
916 pInfo
->mnLength
= 100 * (nValue
-nMinNonNegative
)/(nMax
-nMinNonNegative
);
919 else if( mpFormatData
->meAxisPosition
== databar::MIDDLE
)
922 double nAbsMax
= std::max(std::abs(nMin
), std::abs(nMax
));
923 if (nValue
< 0 && nMin
< 0)
926 pInfo
->mnLength
= nMaxLength
* (nMin
/nAbsMax
);
928 pInfo
->mnLength
= nMaxLength
* (nValue
/nAbsMax
);
933 pInfo
->mnLength
= nMaxLength
* (nMax
/nAbsMax
);
935 pInfo
->mnLength
= nMaxLength
* (std::max(nValue
, nMin
)/nAbsMax
);
942 if(mpFormatData
->mbNeg
&& nValue
< 0)
944 if(mpFormatData
->mxNegativeColor
)
946 pInfo
->maColor
= *mpFormatData
->mxNegativeColor
;
950 // default negative color is red
951 pInfo
->maColor
= COL_LIGHTRED
;
956 pInfo
->maColor
= mpFormatData
->maPositiveColor
;
958 pInfo
->mbGradient
= mpFormatData
->mbGradient
;
959 pInfo
->mbShowValue
= !mpFormatData
->mbOnlyBar
;
960 pInfo
->maAxisColor
= mpFormatData
->maAxisColor
;
965 void ScDataBarFormat::EnsureSize()
967 if (!mpFormatData
->mpLowerLimit
)
971 if (!mpFormatData
->mpUpperLimit
)
977 ScIconSetFormatData::ScIconSetFormatData(ScIconSetFormatData
const& rOther
)
978 : eIconSetType(rOther
.eIconSetType
)
979 , mbShowValue(rOther
.mbShowValue
)
980 , mbReverse(rOther
.mbReverse
)
981 , mbCustom(rOther
.mbCustom
)
982 , maCustomVector(rOther
.maCustomVector
)
984 m_Entries
.reserve(rOther
.m_Entries
.size());
985 for (auto const& it
: rOther
.m_Entries
)
987 m_Entries
.emplace_back(new ScColorScaleEntry(*it
));
991 ScIconSetFormat::ScIconSetFormat(ScDocument
* pDoc
):
993 mpFormatData(new ScIconSetFormatData
)
997 ScIconSetFormat::ScIconSetFormat(ScDocument
* pDoc
, const ScIconSetFormat
& rFormat
):
999 mpFormatData(new ScIconSetFormatData(*rFormat
.mpFormatData
))
1003 ScColorFormat
* ScIconSetFormat::Clone( ScDocument
* pDoc
) const
1005 return new ScIconSetFormat(pDoc
, *this);
1008 void ScIconSetFormat::SetParent(ScConditionalFormat
* pFormat
)
1010 for(iterator itr
= begin(); itr
!= end(); ++itr
)
1012 (*itr
)->SetRepaintCallback(pFormat
);
1014 ScColorFormat::SetParent(pFormat
);
1017 void ScIconSetFormat::SetIconSetData( ScIconSetFormatData
* pFormatData
)
1019 mpFormatData
.reset( pFormatData
);
1020 SetParent(mpParent
);
1023 ScIconSetFormatData
* ScIconSetFormat::GetIconSetData()
1025 return mpFormatData
.get();
1028 const ScIconSetFormatData
* ScIconSetFormat::GetIconSetData() const
1030 return mpFormatData
.get();
1033 std::unique_ptr
<ScIconSetInfo
> ScIconSetFormat::GetIconSetInfo(const ScAddress
& rAddr
) const
1035 ScRefCellValue
rCell(*mpDoc
, rAddr
);
1036 if(!rCell
.hasNumeric())
1039 // now we have for sure a value
1040 double nVal
= rCell
.getValue();
1042 if (mpFormatData
->m_Entries
.size() < 2)
1045 double nMin
= GetMinValue();
1046 double nMax
= GetMaxValue();
1048 sal_Int32 nIndex
= 0;
1049 const_iterator itr
= begin();
1051 double nValMax
= CalcValue(nMin
, nMax
, itr
);
1054 while(itr
!= end() && nVal
>= nValMax
)
1057 nValMax
= CalcValue(nMin
, nMax
, itr
);
1064 std::unique_ptr
<ScIconSetInfo
> pInfo(new ScIconSetInfo
);
1066 if(mpFormatData
->mbReverse
)
1068 sal_Int32 nMaxIndex
= mpFormatData
->m_Entries
.size() - 1;
1069 nIndex
= nMaxIndex
- nIndex
;
1072 if (mpFormatData
->mbCustom
&& sal_Int32(mpFormatData
->maCustomVector
.size()) > nIndex
)
1074 ScIconSetType eCustomType
= mpFormatData
->maCustomVector
[nIndex
].first
;
1075 sal_Int32 nCustomIndex
= mpFormatData
->maCustomVector
[nIndex
].second
;
1076 if (nCustomIndex
== -1)
1081 pInfo
->eIconSetType
= eCustomType
;
1082 pInfo
->nIconIndex
= nCustomIndex
;
1086 pInfo
->nIconIndex
= nIndex
;
1087 pInfo
->eIconSetType
= mpFormatData
->eIconSetType
;
1090 pInfo
->mbShowValue
= mpFormatData
->mbShowValue
;
1094 ScFormatEntry::Type
ScIconSetFormat::GetType() const
1096 return Type::Iconset
;
1099 void ScIconSetFormat::UpdateReference( sc::RefUpdateContext
& rCxt
)
1101 for(iterator itr
= begin(); itr
!= end(); ++itr
)
1103 (*itr
)->UpdateReference(rCxt
);
1107 void ScIconSetFormat::UpdateInsertTab( sc::RefUpdateInsertTabContext
& rCxt
)
1109 for(iterator itr
= begin(); itr
!= end(); ++itr
)
1111 (*itr
)->UpdateInsertTab(rCxt
);
1115 void ScIconSetFormat::UpdateDeleteTab( sc::RefUpdateDeleteTabContext
& rCxt
)
1117 for(iterator itr
= begin(); itr
!= end(); ++itr
)
1119 (*itr
)->UpdateDeleteTab(rCxt
);
1123 void ScIconSetFormat::UpdateMoveTab( sc::RefUpdateMoveTabContext
& rCxt
)
1125 for(iterator itr
= begin(); itr
!= end(); ++itr
)
1127 (*itr
)->UpdateMoveTab(rCxt
);
1131 ScIconSetFormat::iterator
ScIconSetFormat::begin()
1133 return mpFormatData
->m_Entries
.begin();
1136 ScIconSetFormat::const_iterator
ScIconSetFormat::begin() const
1138 return mpFormatData
->m_Entries
.begin();
1141 ScIconSetFormat::iterator
ScIconSetFormat::end()
1143 return mpFormatData
->m_Entries
.end();
1146 ScIconSetFormat::const_iterator
ScIconSetFormat::end() const
1148 return mpFormatData
->m_Entries
.end();
1151 double ScIconSetFormat::GetMinValue() const
1153 const_iterator itr
= begin();
1155 if ((*itr
)->GetType() == COLORSCALE_VALUE
|| (*itr
)->GetType() == COLORSCALE_FORMULA
)
1156 return (*itr
)->GetValue();
1159 return getMinValue();
1163 double ScIconSetFormat::GetMaxValue() const
1165 auto const itr
= mpFormatData
->m_Entries
.rbegin();
1167 if ((*itr
)->GetType() == COLORSCALE_VALUE
|| (*itr
)->GetType() == COLORSCALE_FORMULA
)
1168 return (*itr
)->GetValue();
1171 return getMaxValue();
1175 double ScIconSetFormat::CalcValue(double nMin
, double nMax
, const ScIconSetFormat::const_iterator
& itr
) const
1177 switch ((*itr
)->GetType())
1179 case COLORSCALE_PERCENT
:
1180 return nMin
+ (nMax
-nMin
)*((*itr
)->GetValue()/100);
1181 case COLORSCALE_MIN
:
1183 case COLORSCALE_MAX
:
1185 case COLORSCALE_PERCENTILE
:
1187 std::vector
<double>& rValues
= getValues();
1188 if(rValues
.size() == 1)
1192 double fPercentile
= (*itr
)->GetValue()/100.0;
1193 return GetPercentile(rValues
, fPercentile
);
1201 return (*itr
)->GetValue();
1204 const ScIconSetMap
ScIconSetFormat::g_IconSetMap
[] = {
1205 { "3Arrows", IconSet_3Arrows
, 3 },
1206 { "3ArrowsGray", IconSet_3ArrowsGray
, 3 },
1207 { "3Flags", IconSet_3Flags
, 3 },
1208 { "3TrafficLights1", IconSet_3TrafficLights1
, 3 },
1209 { "3TrafficLights2", IconSet_3TrafficLights2
, 3 },
1210 { "3Signs", IconSet_3Signs
, 3 },
1211 { "3Symbols", IconSet_3Symbols
, 3 },
1212 { "3Symbols2", IconSet_3Symbols2
, 3 },
1213 { "3Smilies", IconSet_3Smilies
, 3 },
1214 { "3ColorSmilies", IconSet_3ColorSmilies
, 3 },
1215 { "3Stars", IconSet_3Stars
, 3 },
1216 { "3Triangles", IconSet_3Triangles
, 3 },
1217 { "4Arrows", IconSet_4Arrows
, 4 },
1218 { "4ArrowsGray", IconSet_4ArrowsGray
, 4 },
1219 { "4RedToBlack", IconSet_4RedToBlack
, 4 },
1220 { "4Rating", IconSet_4Rating
, 4 },
1221 { "4TrafficLights", IconSet_4TrafficLights
, 4 },
1222 { "5Arrows", IconSet_5Arrows
, 5 },
1223 { "5ArrowsGray", IconSet_5ArrowsGray
, 5 },
1224 { "5Rating", IconSet_5Ratings
, 5 },
1225 { "5Quarters", IconSet_5Quarters
, 5 },
1226 { "5Boxes", IconSet_5Boxes
, 5 },
1227 { nullptr, IconSet_3Arrows
, 0 }
1230 size_t ScIconSetFormat::size() const
1232 return mpFormatData
->m_Entries
.size();
1238 const std::u16string_view a3TrafficLights1
[] = {
1239 u
"" BMP_ICON_SET_CIRCLES1_RED
, u
"" BMP_ICON_SET_CIRCLES1_YELLOW
, u
"" BMP_ICON_SET_CIRCLES1_GREEN
1242 const std::u16string_view a3TrafficLights2
[] = {
1243 u
"" BMP_ICON_SET_TRAFFICLIGHTS_RED
, u
"" BMP_ICON_SET_TRAFFICLIGHTS_YELLOW
, u
"" BMP_ICON_SET_TRAFFICLIGHTS_GREEN
1246 const std::u16string_view a3Arrows
[] = {
1247 u
"" BMP_ICON_SET_COLORARROWS_DOWN
, u
"" BMP_ICON_SET_COLORARROWS_SAME
, u
"" BMP_ICON_SET_COLORARROWS_UP
1250 const std::u16string_view a3ArrowsGray
[] = {
1251 u
"" BMP_ICON_SET_GRAYARROWS_DOWN
, u
"" BMP_ICON_SET_GRAYARROWS_SAME
, u
"" BMP_ICON_SET_GRAYARROWS_UP
1254 const std::u16string_view a3Flags
[] = {
1255 u
"" BMP_ICON_SET_FLAGS_RED
, u
"" BMP_ICON_SET_FLAGS_YELLOW
, u
"" BMP_ICON_SET_FLAGS_GREEN
1258 const std::u16string_view a3Smilies
[] = {
1259 u
"" BMP_ICON_SET_POSITIVE_YELLOW_SMILIE
, u
"" BMP_ICON_SET_NEUTRAL_YELLOW_SMILIE
, u
"" BMP_ICON_SET_NEGATIVE_YELLOW_SMILIE
1262 const std::u16string_view a3ColorSmilies
[] = {
1263 u
"" BMP_ICON_SET_POSITIVE_GREEN_SMILIE
, u
"" BMP_ICON_SET_NEUTRAL_YELLOW_SMILIE
, u
"" BMP_ICON_SET_NEGATIVE_RED_SMILIE
1266 const std::u16string_view a3Stars
[] = {
1267 u
"" BMP_ICON_SET_STARS_EMPTY
, u
"" BMP_ICON_SET_STARS_HALF
, u
"" BMP_ICON_SET_STARS_FULL
1270 const std::u16string_view a3Triangles
[] = {
1271 u
"" BMP_ICON_SET_TRIANGLES_DOWN
, u
"" BMP_ICON_SET_TRIANGLES_SAME
, u
"" BMP_ICON_SET_TRIANGLES_UP
1274 const std::u16string_view a4Arrows
[] = {
1275 u
"" BMP_ICON_SET_COLORARROWS_DOWN
, u
"" BMP_ICON_SET_COLORARROWS_SLIGHTLY_DOWN
, u
"" BMP_ICON_SET_COLORARROWS_SLIGHTLY_UP
, u
"" BMP_ICON_SET_COLORARROWS_UP
1278 const std::u16string_view a4ArrowsGray
[] = {
1279 u
"" BMP_ICON_SET_GRAYARROWS_DOWN
, u
"" BMP_ICON_SET_GRAYARROWS_SLIGHTLY_DOWN
, u
"" BMP_ICON_SET_GRAYARROWS_SLIGHTLY_UP
, u
"" BMP_ICON_SET_GRAYARROWS_UP
1282 const std::u16string_view a5Arrows
[] = {
1283 u
"" BMP_ICON_SET_COLORARROWS_DOWN
, u
"" BMP_ICON_SET_COLORARROWS_SLIGHTLY_DOWN
,
1284 u
"" BMP_ICON_SET_COLORARROWS_SAME
, u
"" BMP_ICON_SET_COLORARROWS_SLIGHTLY_UP
, u
"" BMP_ICON_SET_COLORARROWS_UP
1287 const std::u16string_view a5ArrowsGray
[] = {
1288 u
"" BMP_ICON_SET_GRAYARROWS_DOWN
, u
"" BMP_ICON_SET_GRAYARROWS_SLIGHTLY_DOWN
,
1289 u
"" BMP_ICON_SET_GRAYARROWS_SAME
, u
"" BMP_ICON_SET_GRAYARROWS_SLIGHTLY_UP
, u
"" BMP_ICON_SET_GRAYARROWS_UP
1292 const std::u16string_view a4TrafficLights
[] = {
1293 u
"" BMP_ICON_SET_CIRCLES1_GRAY
, u
"" BMP_ICON_SET_CIRCLES1_RED
,
1294 u
"" BMP_ICON_SET_CIRCLES1_YELLOW
, u
"" BMP_ICON_SET_CIRCLES1_GREEN
1297 const std::u16string_view a5Quarters
[] = {
1298 u
"" BMP_ICON_SET_PIES_EMPTY
, u
"" BMP_ICON_SET_PIES_ONE_QUARTER
, u
"" BMP_ICON_SET_PIES_HALF
,
1299 u
"" BMP_ICON_SET_PIES_THREE_QUARTER
, u
"" BMP_ICON_SET_PIES_FULL
,
1302 const std::u16string_view a5Boxes
[] = {
1303 u
"" BMP_ICON_SET_SQUARES_EMPTY
, u
"" BMP_ICON_SET_SQUARES_ONE_QUARTER
,
1304 u
"" BMP_ICON_SET_SQUARES_HALF
, u
"" BMP_ICON_SET_SQUARES_THREE_QUARTER
,
1305 u
"" BMP_ICON_SET_SQUARES_FULL
1308 const std::u16string_view a3Symbols1
[] = {
1309 u
"" BMP_ICON_SET_SYMBOLS1_CROSS
, u
"" BMP_ICON_SET_SYMBOLS1_EXCLAMATION_MARK
, u
"" BMP_ICON_SET_SYMBOLS1_CHECK
1312 const std::u16string_view a3Signs
[] = {
1313 u
"" BMP_ICON_SET_SHAPES_DIAMOND
, u
"" BMP_ICON_SET_SHAPES_TRIANGLE
, u
"" BMP_ICON_SET_SHAPES_CIRCLE
1316 const std::u16string_view a4RedToBlack
[] = {
1317 u
"" BMP_ICON_SET_CIRCLES2_DARK_GRAY
, u
"" BMP_ICON_SET_CIRCLES2_LIGHT_GRAY
,
1318 u
"" BMP_ICON_SET_CIRCLES2_LIGHT_RED
, u
"" BMP_ICON_SET_CIRCLES2_DARK_RED
1321 const std::u16string_view a4Ratings
[] = {
1322 u
"" BMP_ICON_SET_BARS_ONE_QUARTER
, u
"" BMP_ICON_SET_BARS_HALF
,
1323 u
"" BMP_ICON_SET_BARS_THREE_QUARTER
, u
"" BMP_ICON_SET_BARS_FULL
1326 const std::u16string_view a5Ratings
[] = {
1327 u
"" BMP_ICON_SET_BARS_EMPTY
, u
"" BMP_ICON_SET_BARS_ONE_QUARTER
, u
"" BMP_ICON_SET_BARS_HALF
,
1328 u
"" BMP_ICON_SET_BARS_THREE_QUARTER
, u
"" BMP_ICON_SET_BARS_FULL
1331 struct ScIconSetBitmapMap
{
1332 ScIconSetType eType
;
1333 const std::u16string_view
* pBitmaps
;
1336 const ScIconSetBitmapMap aBitmapMap
[] = {
1337 { IconSet_3Arrows
, a3Arrows
},
1338 { IconSet_3ArrowsGray
, a3ArrowsGray
},
1339 { IconSet_3Flags
, a3Flags
},
1340 { IconSet_3Signs
, a3Signs
},
1341 { IconSet_3Symbols
, a3Symbols1
},
1342 { IconSet_3Symbols2
, a3Symbols1
},
1343 { IconSet_3TrafficLights1
, a3TrafficLights1
},
1344 { IconSet_3TrafficLights2
, a3TrafficLights2
},
1345 { IconSet_3Smilies
, a3Smilies
},
1346 { IconSet_3ColorSmilies
, a3ColorSmilies
},
1347 { IconSet_3Triangles
, a3Triangles
},
1348 { IconSet_3Stars
, a3Stars
},
1349 { IconSet_4Arrows
, a4Arrows
},
1350 { IconSet_4ArrowsGray
, a4ArrowsGray
},
1351 { IconSet_4Rating
, a4Ratings
},
1352 { IconSet_4RedToBlack
, a4RedToBlack
},
1353 { IconSet_4TrafficLights
, a4TrafficLights
},
1354 { IconSet_5Arrows
, a5Arrows
},
1355 { IconSet_5ArrowsGray
, a5ArrowsGray
},
1356 { IconSet_5Quarters
, a5Quarters
},
1357 { IconSet_5Ratings
, a5Ratings
},
1358 { IconSet_5Boxes
, a5Boxes
}
1361 const ScIconSetMap
* findIconSetType(ScIconSetType eType
)
1363 const ScIconSetMap
* pMap
= ScIconSetFormat::g_IconSetMap
;
1364 for (; pMap
->pName
; ++pMap
)
1366 if (pMap
->eType
== eType
)
1375 const char* ScIconSetFormat::getIconSetName( ScIconSetType eType
)
1377 const ScIconSetMap
* pMap
= findIconSetType(eType
);
1384 sal_Int32
ScIconSetFormat::getIconSetElements( ScIconSetType eType
)
1386 const ScIconSetMap
* pMap
= findIconSetType(eType
);
1388 return pMap
->nElements
;
1393 OUString
ScIconSetFormat::getIconName(ScIconSetType
const eType
, sal_Int32
const nIndex
)
1397 for(const ScIconSetBitmapMap
& i
: aBitmapMap
)
1399 if(i
.eType
== eType
)
1401 sBitmap
= *(i
.pBitmaps
+ nIndex
);
1406 assert(!sBitmap
.isEmpty());
1411 BitmapEx
& ScIconSetFormat::getBitmap(sc::IconSetBitmapMap
& rIconSetBitmapMap
,
1412 ScIconSetType
const eType
, sal_Int32
const nIndex
)
1414 OUString
sBitmap(ScIconSetFormat::getIconName(eType
, nIndex
));
1416 std::map
<OUString
, BitmapEx
>::iterator itr
= rIconSetBitmapMap
.find(sBitmap
);
1417 if (itr
!= rIconSetBitmapMap
.end())
1420 BitmapEx
aBitmap(sBitmap
);
1421 std::pair
<OUString
, BitmapEx
> aPair(sBitmap
, aBitmap
);
1422 std::pair
<std::map
<OUString
, BitmapEx
>::iterator
, bool> itrNew
= rIconSetBitmapMap
.insert(aPair
);
1423 assert(itrNew
.second
);
1425 return itrNew
.first
->second
;
1428 void ScIconSetFormat::EnsureSize()
1430 ScIconSetType eType
= mpFormatData
->eIconSetType
;
1431 for (const ScIconSetMap
& i
: g_IconSetMap
)
1433 if (i
.eType
== eType
)
1435 // size_t nElements = aIconSetMap[i].nElements;
1442 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */