sc/inc/colorscale.hxx                     |    8 ++
 sc/source/core/data/colorscale.cxx        |  106 ++++++++++++++++++++++++++----
 sc/source/filter/inc/condformatbuffer.hxx |    4 -
 sc/source/filter/oox/condformatbuffer.cxx |   10 +-
 4 files changed, 109 insertions(+), 19 deletions(-)

New commits:
commit f654980aebb5d41a83dd7de94ec2ebf0173c67a7
Author: Markus Mohrhard <markus.mohrh...@googlemail.com>
Date:   Mon May 21 15:47:23 2012 +0200

    initial support for percentile in data bars/color scales
    
    Color Scales look correctly but in the databar code seems to be an error
    if all values are positive.
    
    Change-Id: I0bfb277df50021bd20a4b13a5da342670102b649

diff --git a/sc/inc/colorscale.hxx b/sc/inc/colorscale.hxx
index 997c2a0..9f4d02f 100644
--- a/sc/inc/colorscale.hxx
+++ b/sc/inc/colorscale.hxx
@@ -32,6 +32,8 @@
 #include <tools/color.hxx>
 #include <rangelst.hxx>
 
+#include <vector>
+
 //TODO: merge this with conditio.hxx
 
 class ScDocument;
@@ -49,6 +51,7 @@ private:
     bool mbMin;
     bool mbMax;
     bool mbPercent;
+    bool mbPercentile;
 public:
     ScColorScaleEntry(double nVal, const Color& rCol);
     ScColorScaleEntry(const ScColorScaleEntry& rEntry);
@@ -65,11 +68,13 @@ public:
     bool GetMin() const;
     bool GetMax() const;
     bool GetPercent() const;
+    bool GetPercentile() const;
     bool HasFormula() const;
     const ScTokenArray* GetFormula() const;
     void SetMin(bool bMin);
     void SetMax(bool bMax);
     void SetPercent(bool bPercent);
+    void SetPercentile(bool bPercentile);
 };
 
 namespace databar
@@ -160,6 +165,8 @@ public:
     virtual ScColorFormatType GetType() const = 0;
 
 protected:
+    void getValues( std::vector<double>& rValues ) const;
+
     ScRangeList maRanges;
     ScDocument* mpDoc;
 };
@@ -175,6 +182,7 @@ private:
 
     void calcMinMax(double& nMin, double& nMax) const;
     bool CheckEntriesForRel(const ScRange& rRange) const;
+    double CalcValue(double nMin, double nMax, 
ColorScaleEntries::const_iterator& rItr) const;
 public:
     ScColorScaleFormat(ScDocument* pDoc);
     ScColorScaleFormat(ScDocument* pDoc, const ScColorScaleFormat& rFormat);
diff --git a/sc/source/core/data/colorscale.cxx 
b/sc/source/core/data/colorscale.cxx
index 8306107..9636365 100644
--- a/sc/source/core/data/colorscale.cxx
+++ b/sc/source/core/data/colorscale.cxx
@@ -37,7 +37,8 @@ ScColorScaleEntry::ScColorScaleEntry(double nVal, const 
Color& rCol):
     mpCell(NULL),
     mbMin(false),
     mbMax(false),
-    mbPercent(false)
+    mbPercent(false),
+    mbPercentile(false)
 {
 }
 
@@ -47,7 +48,8 @@ ScColorScaleEntry::ScColorScaleEntry(const ScColorScaleEntry& 
rEntry):
     mpCell(),
     mbMin(rEntry.mbMin),
     mbMax(rEntry.mbMax),
-    mbPercent(rEntry.mbPercent)
+    mbPercent(rEntry.mbPercent),
+    mbPercentile(rEntry.mbPercentile)
 {
 }
 
@@ -57,7 +59,8 @@ ScColorScaleEntry::ScColorScaleEntry(ScDocument* pDoc, const 
ScColorScaleEntry&
     mpCell(),
     mbMin(rEntry.mbMin),
     mbMax(rEntry.mbMax),
-    mbPercent(rEntry.mbPercent)
+    mbPercent(rEntry.mbPercent),
+    mbPercentile(rEntry.mbPercentile)
 {
     if(rEntry.mpCell)
     {
@@ -179,6 +182,11 @@ bool ScColorScaleEntry::GetPercent() const
     return mbPercent;
 }
 
+bool ScColorScaleEntry::GetPercentile() const
+{
+    return mbPercentile;
+}
+
 bool ScColorScaleEntry::HasFormula() const
 {
     return mpCell;
@@ -199,6 +207,11 @@ void ScColorScaleEntry::SetPercent(bool bPercent)
     mbPercent = bPercent;
 }
 
+void ScColorScaleEntry::SetPercentile(bool bPercentile)
+{
+    mbPercentile = bPercentile;
+}
+
 namespace {
 
 double getMinValue(const ScRange& rRange, ScDocument* pDoc)
@@ -336,6 +349,37 @@ const ScRangeList& ScColorFormat::GetRange() const
     return maRanges;
 }
 
+void ScColorFormat::getValues(std::vector<double>& rValues) const
+{
+    size_t n = maRanges.size();
+    for(size_t i = 0; i < n; ++i)
+    {
+        const ScRange* pRange = maRanges[i];
+        SCTAB nTab = pRange->aStart.Tab();
+        for(SCCOL nCol = pRange->aStart.Col(); nCol <= pRange->aEnd.Col(); 
++nCol)
+        {
+            for(SCCOL nRow = pRange->aStart.Row(); nRow <= pRange->aEnd.Row(); 
++nRow)
+            {
+                ScAddress aAddr(nCol, nRow, nTab);
+                CellType eType = mpDoc->GetCellType(aAddr);
+                if(eType == CELLTYPE_VALUE)
+                {
+                    double aVal = mpDoc->GetValue(nCol, nRow, nTab);
+                    rValues.push_back(aVal);
+                }
+                else if(eType == CELLTYPE_FORMULA)
+                {
+                    
if(static_cast<ScFormulaCell*>(mpDoc->GetCell(aAddr))->IsValue())
+                    {
+                        double aVal = mpDoc->GetValue(nCol, nRow, nTab);
+                        rValues.push_back(aVal);
+                    }
+                }
+            }
+        }
+    }
+}
+
 namespace {
 
 sal_uInt8 GetColorValue( double nVal, double nVal1, sal_uInt8 nColVal1, double 
nVal2, sal_uInt8 nColVal2 )
@@ -359,7 +403,27 @@ Color CalcColor( double nVal, double nVal1, const Color& 
rCol1, double nVal2, co
     return Color(nColRed, nColGreen, nColBlue);
 }
 
-double CalcValue(double nMin, double nMax, ScColorScaleFormat::const_iterator& 
itr)
+double GetPercentile( std::vector<double>& rArray, double fPercentile )
+{
+    size_t nSize = rArray.size();
+    size_t nIndex = (size_t)::rtl::math::approxFloor( fPercentile * (nSize-1));
+    double fDiff = fPercentile * (nSize-1) - ::rtl::math::approxFloor( 
fPercentile * (nSize-1));
+    std::vector<double>::iterator iter = rArray.begin() + nIndex;
+    ::std::nth_element( rArray.begin(), iter, rArray.end());
+    if (fDiff == 0.0)
+        return *iter;
+    else
+    {
+        double fVal = *iter;
+        iter = rArray.begin() + nIndex+1;
+        ::std::nth_element( rArray.begin(), iter, rArray.end());
+        return fVal + fDiff * (*iter - fVal);
+    }
+}
+
+}
+
+double ScColorScaleFormat::CalcValue(double nMin, double nMax, 
ScColorScaleFormat::const_iterator& itr) const
 {
     if(itr->GetPercent())
     {
@@ -373,12 +437,22 @@ double CalcValue(double nMin, double nMax, 
ScColorScaleFormat::const_iterator& i
     {
         return nMax;
     }
+    else if(itr->GetPercentile())
+    {
+        std::vector<double> aValues;
+        getValues(aValues);
+        if(aValues.size() == 1)
+            return aValues[0];
+        else
+        {
+            double fPercentile = itr->GetValue()/100.0;
+            return GetPercentile(aValues, fPercentile);
+        }
+    }
 
     return itr->GetValue();
 }
 
-}
-
 Color* ScColorScaleFormat::GetColor( const ScAddress& rAddr ) const
 {
     CellType eCellType = mpDoc->GetCellType(rAddr);
@@ -638,10 +712,14 @@ double ScDataBarFormat::getMin(double nMin, double nMax) 
const
 {
     if(mpFormatData->mpLowerLimit->GetMin())
         return nMin;
-
-    if(mpFormatData->mpLowerLimit->GetPercent())
-    {
+    else if(mpFormatData->mpLowerLimit->GetPercent())
         return nMin + (nMax-nMin)/100*mpFormatData->mpLowerLimit->GetValue();
+    else if(mpFormatData->mpLowerLimit->GetPercentile())
+    {
+        double fPercentile = mpFormatData->mpLowerLimit->GetValue()/100.0;
+        std::vector<double> aValues;
+        getValues(aValues);
+        return GetPercentile(aValues, fPercentile);
     }
 
     return mpFormatData->mpLowerLimit->GetValue();
@@ -651,10 +729,14 @@ double ScDataBarFormat::getMax(double nMin, double nMax) 
const
 {
     if(mpFormatData->mpUpperLimit->GetMax())
         return nMax;
-
-    if(mpFormatData->mpUpperLimit->GetPercent())
-    {
+    else if(mpFormatData->mpUpperLimit->GetPercent())
         return nMin + (nMax-nMin)/100*mpFormatData->mpUpperLimit->GetValue();
+    else if(mpFormatData->mpLowerLimit->GetPercentile())
+    {
+        double fPercentile = mpFormatData->mpLowerLimit->GetValue()/100.0;
+        std::vector<double> aValues;
+        getValues(aValues);
+        return GetPercentile(aValues, fPercentile);
     }
 
     return mpFormatData->mpUpperLimit->GetValue();
diff --git a/sc/source/filter/inc/condformatbuffer.hxx 
b/sc/source/filter/inc/condformatbuffer.hxx
index 60f24d7..4dbe613 100644
--- a/sc/source/filter/inc/condformatbuffer.hxx
+++ b/sc/source/filter/inc/condformatbuffer.hxx
@@ -86,6 +86,7 @@ struct ColorScaleRuleModelEntry
     bool mbMin;
     bool mbMax;
     bool mbPercent;
+    bool mbPercentile;
     rtl::OUString maFormula;
 
     ColorScaleRuleModelEntry():
@@ -93,7 +94,8 @@ struct ColorScaleRuleModelEntry
         mnVal(0),
         mbMin(false),
         mbMax(false),
-        mbPercent(false) {}
+        mbPercent(false),
+        mbPercentile(false) {}
 };
 
 class ColorScaleRule : public WorksheetHelper
diff --git a/sc/source/filter/oox/condformatbuffer.cxx 
b/sc/source/filter/oox/condformatbuffer.cxx
index 05681b8..3471e11 100644
--- a/sc/source/filter/oox/condformatbuffer.cxx
+++ b/sc/source/filter/oox/condformatbuffer.cxx
@@ -178,9 +178,7 @@ void ColorScaleRule::importCfvo( const AttributeList& 
rAttribs )
     }
     else if( aType == "percentile" )
     {
-        // this is most likely wrong but I have no idea what the difference
-        // between percent and percentile should be when calculating colors
-        maColorScaleRuleEntries[mnCfvo].mbPercent = true;
+        maColorScaleRuleEntries[mnCfvo].mbPercentile = true;
     }
     else if( aType == "formula" )
     {
@@ -236,6 +234,8 @@ ScColorScaleEntry* ConvertToModel( const 
ColorScaleRuleModelEntry& rEntry, ScDoc
             pEntry->SetMax(true);
         if(rEntry.mbPercent)
             pEntry->SetPercent(true);
+        if(rEntry.mbPercentile)
+            pEntry->SetPercentile(true);
 
         if(!rEntry.maFormula.isEmpty())
             pEntry->SetFormula(rEntry.maFormula, pDoc, rAddr, 
formula::FormulaGrammar::GRAM_ENGLISH_XL_A1);
@@ -318,9 +318,7 @@ void DataBarRule::importCfvo( const AttributeList& rAttribs 
)
     }
     else if( aType == "percentile" )
     {
-        // this is most likely wrong but I have no idea what the difference
-        // between percent and percentile should be when calculating colors
-        pEntry->mbPercent = true;
+        pEntry->mbPercentile = true;
     }
     else if( aType == "formula" )
     {
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to