]> source.dussan.org Git - poi.git/commitdiff
#58130 CF Threshold formats differ slightly between types
authorNick Burch <nick@apache.org>
Sun, 19 Jul 2015 22:09:41 +0000 (22:09 +0000)
committerNick Burch <nick@apache.org>
Sun, 19 Jul 2015 22:09:41 +0000 (22:09 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1691858 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/hssf/record/CFRule12Record.java
src/java/org/apache/poi/hssf/record/cf/ColorGradientFormatting.java
src/java/org/apache/poi/hssf/record/cf/ColorGradientThreshold.java [new file with mode: 0644]
src/java/org/apache/poi/hssf/record/cf/IconMultiStateFormatting.java
src/java/org/apache/poi/hssf/record/cf/IconMultiStateThreshold.java [new file with mode: 0644]
src/java/org/apache/poi/hssf/record/cf/Threshold.java
src/java/org/apache/poi/hssf/usermodel/HSSFColorScaleFormatting.java

index e7974a0922e1002d461c34d02b95daae8b1f47dc..80a31b321349fb1b1afa2897bab3e403e8777885 100644 (file)
@@ -21,6 +21,7 @@ import java.util.Arrays;
 
 import org.apache.poi.hssf.record.cf.ColorGradientFormatting;
 import org.apache.poi.hssf.record.cf.IconMultiStateFormatting;
+import org.apache.poi.hssf.record.cf.IconMultiStateThreshold;
 import org.apache.poi.hssf.record.cf.Threshold;
 import org.apache.poi.hssf.record.common.FtrHeader;
 import org.apache.poi.hssf.record.common.FutureRecord;
@@ -125,7 +126,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord {
     public static CFRule12Record create(HSSFSheet sheet, IconSet iconSet) {
         Threshold[] ts = new Threshold[iconSet.num];
         for (int i=0; i<ts.length; i++) {
-            ts[i] = new Threshold();
+            ts[i] = new IconMultiStateThreshold();
         }
         
         CFRule12Record r = new CFRule12Record(CONDITION_TYPE_COLOR_SCALE, 
index 3b58af74e2c2e908b21bcc44aba0b8db72497fb9..b78a81f851230af7c7de7c266f0918dfc6db91b0 100644 (file)
@@ -17,6 +17,7 @@
 
 package org.apache.poi.hssf.record.cf;
 
+import org.apache.poi.hssf.record.common.ExtendedColor;
 import org.apache.poi.util.BitField;
 import org.apache.poi.util.BitFieldFactory;
 import org.apache.poi.util.LittleEndianInput;
@@ -33,15 +34,16 @@ public final class ColorGradientFormatting implements Cloneable {
     private static POILogger log = POILogFactory.getLogger(ColorGradientFormatting.class);
 
     private byte options = 0;
-    private Threshold[] thresholds;
-    private byte[] colors; // TODO Decode
+    private ColorGradientThreshold[] thresholds;
+    private ExtendedColor[] colors;
     
     private static BitField clamp = BitFieldFactory.getInstance(0x01);
     private static BitField background = BitFieldFactory.getInstance(0x02);
     
     public ColorGradientFormatting() {
         options = 3;
-        thresholds = new Threshold[3];
+        thresholds = new ColorGradientThreshold[3];
+        colors = new ExtendedColor[3];  
     }
     public ColorGradientFormatting(LittleEndianInput in) {
         in.readShort(); // Ignored
@@ -53,15 +55,15 @@ public final class ColorGradientFormatting implements Cloneable {
         }
         options = in.readByte();
         
-        // TODO Are these correct?
-        thresholds = new Threshold[numI];
+        thresholds = new ColorGradientThreshold[numI];
         for (int i=0; i<thresholds.length; i++) {
-            thresholds[i] = new Threshold(in);
-            in.readDouble(); // Rather pointless value...
+            thresholds[i] = new ColorGradientThreshold(in);
+        }
+        colors = new ExtendedColor[numG];
+        for (int i=0; i<colors.length; i++) {
+            in.readDouble(); // Slightly pointless step counter
+            colors[i] = new ExtendedColor(in);
         }
-        // TODO Decode colors
-        colors = new byte[in.available()];
-        in.readFully(colors);
     }
     
     public int getNumControlPoints() {
@@ -69,19 +71,34 @@ public final class ColorGradientFormatting implements Cloneable {
     }
     public void setNumControlPoints(int num) {
         if (num != thresholds.length) {
-            thresholds = new Threshold[num];
-            // TODO Colors
+            ColorGradientThreshold[] nt = new ColorGradientThreshold[num];
+            ExtendedColor[] nc = new ExtendedColor[num];
+            
+            int copy = Math.min(thresholds.length, num);
+            System.arraycopy(thresholds, 0, nt, 0, copy);
+            System.arraycopy(colors, 0, nc, 0, copy);
+            
+            this.thresholds = nt;
+            this.colors = nc;
+            
+            updateThresholdPositions();
         }
     }
     
-    public Threshold[] getThresholds() {
+    public ColorGradientThreshold[] getThresholds() {
         return thresholds;
     }
-    public void setThresholds(Threshold[] thresholds) {
+    public void setThresholds(ColorGradientThreshold[] thresholds) {
         this.thresholds = thresholds;
+        updateThresholdPositions();
     }
 
-    // TODO Colors
+    public ExtendedColor[] getColors() {
+        return colors;
+    }
+    public void setColors(ExtendedColor[] colors) {
+        this.colors = colors;
+    }
     
     public boolean isClampToCurve() {
         return getOptionFlag(clamp);
@@ -93,6 +110,13 @@ public final class ColorGradientFormatting implements Cloneable {
         int value = field.getValue(options);
         return value==0 ? false : true;
     }
+
+    private void updateThresholdPositions() {
+        double step = 1d / (thresholds.length-1);
+        for (int i=0; i<thresholds.length; i++) {
+            thresholds[i].setPosition(step*i);
+        }
+    }    
     
     public String toString() {
         StringBuffer buffer = new StringBuffer();
@@ -102,6 +126,9 @@ public final class ColorGradientFormatting implements Cloneable {
         for (Threshold t : thresholds) {
             buffer.append(t.toString());
         }
+        for (ExtendedColor c : colors) {
+            buffer.append(c.toString());
+        }
         buffer.append("    [/Color Gradient Formatting]\n");
         return buffer.toString();
     }
@@ -109,9 +136,10 @@ public final class ColorGradientFormatting implements Cloneable {
     public Object clone()  {
       ColorGradientFormatting rec = new ColorGradientFormatting();
       rec.options = options;
-      rec.thresholds = new Threshold[thresholds.length];
+      rec.thresholds = new ColorGradientThreshold[thresholds.length];
+      rec.colors = new ExtendedColor[colors.length];
       System.arraycopy(thresholds, 0, rec.thresholds, 0, thresholds.length);
-      // TODO Colors
+      System.arraycopy(colors, 0, rec.colors, 0, colors.length);
       return rec;
     }
     
@@ -119,9 +147,11 @@ public final class ColorGradientFormatting implements Cloneable {
         int len = 6;
         for (Threshold t : thresholds) {
             len += t.getDataLength();
+        }
+        for (ExtendedColor c : colors) {
+            len += c.getDataLength();
             len += 8;
         }
-        len += colors.length;
         return len;
     }
 
@@ -132,13 +162,16 @@ public final class ColorGradientFormatting implements Cloneable {
         out.writeByte(thresholds.length);
         out.writeByte(options);
         
-        double step = 1d / (thresholds.length-1);
-        for (int i=0; i<thresholds.length; i++) {
-            Threshold t = thresholds[i];
+        for (ColorGradientThreshold t : thresholds) {
             t.serialize(out);
-            out.writeDouble(step*i);
         }
         
-        out.write(colors);
+        double step = 1d / (colors.length-1);
+        for (int i=0; i<colors.length; i++) {
+            out.writeDouble(i*step);
+            
+            ExtendedColor c = colors[i];
+            c.serialize(out);
+        }
     }
 }
diff --git a/src/java/org/apache/poi/hssf/record/cf/ColorGradientThreshold.java b/src/java/org/apache/poi/hssf/record/cf/ColorGradientThreshold.java
new file mode 100644 (file)
index 0000000..934cb68
--- /dev/null
@@ -0,0 +1,63 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.record.cf;
+
+import org.apache.poi.util.LittleEndianInput;
+import org.apache.poi.util.LittleEndianOutput;
+
+/**
+ * Color Gradient / Color Scale specific Threshold / value (CFVO),
+ *  for changes in Conditional Formatting
+ */
+public final class ColorGradientThreshold extends Threshold {
+    private double position;
+
+    public ColorGradientThreshold() {
+        super();
+        position = 0d;
+    }
+
+    /** Creates new Ico Multi-State Threshold */
+    public ColorGradientThreshold(LittleEndianInput in) {
+        super(in);
+        position = in.readDouble();
+    }
+
+    public double getPosition() {
+        return position;
+    }
+    public void setPosition(double position) {
+        this.position = position;
+    }
+
+    public int getDataLength() {
+        return super.getDataLength() + 8;
+    }
+
+    public Object clone() {
+      ColorGradientThreshold rec = new ColorGradientThreshold();
+      super.copyTo(rec);
+      rec.position = position;
+      return rec;
+    }
+
+    public void serialize(LittleEndianOutput out) {
+        super.serialize(out);
+        out.writeDouble(position);
+    }
+}
index f405c031e0150c5b41000e83793bb3130bd928cd..4a8f885b204fda928cdac78ff1acca308f79b64a 100644 (file)
@@ -56,7 +56,7 @@ public final class IconMultiStateFormatting implements Cloneable {
         
         thresholds = new Threshold[iconSet.num];
         for (int i=0; i<thresholds.length; i++) {
-            thresholds[i] = new Threshold(in);
+            thresholds[i] = new IconMultiStateThreshold(in);
         }
     }
     
diff --git a/src/java/org/apache/poi/hssf/record/cf/IconMultiStateThreshold.java b/src/java/org/apache/poi/hssf/record/cf/IconMultiStateThreshold.java
new file mode 100644 (file)
index 0000000..72f6ea3
--- /dev/null
@@ -0,0 +1,75 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.record.cf;
+
+import org.apache.poi.util.LittleEndianInput;
+import org.apache.poi.util.LittleEndianOutput;
+
+/**
+ * Icon / Multi-State specific Threshold / value (CFVO),
+ *  for changes in Conditional Formatting
+ */
+public final class IconMultiStateThreshold extends Threshold {
+    /**
+     * Cell values that are equal to the threshold value do not pass the threshold
+     */
+    public static final byte EQUALS_EXCLUDE = 0;
+    /**
+     * Cell values that are equal to the threshold value pass the threshold.
+     */
+    public static final byte EQUALS_INCLUDE = 1;
+    
+    private byte equals;
+
+    public IconMultiStateThreshold() {
+        super();
+        equals = EQUALS_INCLUDE;
+    }
+
+    /** Creates new Ico Multi-State Threshold */
+    public IconMultiStateThreshold(LittleEndianInput in) {
+        super(in);
+        equals = in.readByte();
+        // Reserved, 4 bytes, all 0
+        in.readInt();
+    }
+
+    public byte getEquals() {
+        return equals;
+    }
+    public void setEquals(byte equals) {
+        this.equals = equals;
+    }
+
+    public int getDataLength() {
+        return super.getDataLength() + 5;
+    }
+
+    public Object clone() {
+      IconMultiStateThreshold rec = new IconMultiStateThreshold();
+      super.copyTo(rec);
+      rec.equals = equals;
+      return rec;
+    }
+
+    public void serialize(LittleEndianOutput out) {
+        super.serialize(out);
+        out.writeByte(equals);
+        out.writeInt(0); // Reserved
+    }
+}
index 414bf0f4ca0d0583f0278e49280e278b4eeca94b..946c181660008d8f9405c8de56df1ab35b90a489 100644 (file)
@@ -26,31 +26,21 @@ import org.apache.poi.util.LittleEndianInput;
 import org.apache.poi.util.LittleEndianOutput;
 
 /**
- * Threshold / value for changes in Conditional Formatting
+ * Threshold / value (CFVO) for changes in Conditional Formatting
  */
-public final class Threshold {
-    /**
-     * Cell values that are equal to the threshold value do not pass the threshold
-     */
-    public static final byte EQUALS_EXCLUDE = 0;
-    /**
-     * Cell values that are equal to the threshold value pass the threshold.
-     */
-    public static final byte EQUALS_INCLUDE = 1;
-    
+public abstract class Threshold {
     private byte type;
     private Formula formula;
     private Double value;
-    private byte equals;
 
-    public Threshold() {
+    protected Threshold() {
         type = (byte)RangeType.NUMBER.id;
         formula = Formula.create(null);
         value = 0d;
     }
 
     /** Creates new Threshold */
-    public Threshold(LittleEndianInput in) {
+    protected Threshold(LittleEndianInput in) {
         type = in.readByte();
         short formulaLen = in.readShort();
         if (formulaLen > 0) {
@@ -63,9 +53,6 @@ public final class Threshold {
                 type != RangeType.MAX.id) {
             value = in.readDouble();
         }
-        equals = in.readByte();
-        // Reserved, 4 bytes, all 0
-        in.readInt();
     }
 
     public byte getType() {
@@ -74,7 +61,7 @@ public final class Threshold {
     public void setType(byte type) {
         this.type = type;
 
-        // Ensure the value presense / absense is consistent for the new type
+        // Ensure the value presence / absence is consistent for the new type
         if (type == RangeType.MIN.id || type == RangeType.MAX.id ||
                type == RangeType.FORMULA.id) {
             this.value = null;
@@ -106,19 +93,11 @@ public final class Threshold {
         this.value = value;
     }
     
-    public byte getEquals() {
-        return equals;
-    }
-    public void setEquals(byte equals) {
-        this.equals = equals;
-    }
-
     public int getDataLength() {
         int len = 1 + formula.getEncodedSize();
         if (value != null) {
             len += 8;
         }
-        len += 5;
         return len;
     }
 
@@ -132,13 +111,10 @@ public final class Threshold {
         return buffer.toString();
     }
 
-    public Object clone() {
-      Threshold rec = new Threshold();
+    public void copyTo(Threshold rec) {
       rec.type = type;
       rec.formula = formula;
       rec.value = value;
-      rec.equals = equals;
-      return rec;
     }
 
     public void serialize(LittleEndianOutput out) {
@@ -151,7 +127,5 @@ public final class Threshold {
         if (value != null) {
             out.writeDouble(value);
         }
-        out.writeByte(equals);
-        out.writeInt(0); // Reserved
     }
 }
index 6e82072d443987f28efdf52b43fd5cd7fcf23d41..3d4613f98336c140339c9640485925ace61b284e 100644 (file)
@@ -19,6 +19,7 @@ package org.apache.poi.hssf.usermodel;
 
 import org.apache.poi.hssf.record.CFRule12Record;
 import org.apache.poi.hssf.record.cf.ColorGradientFormatting;
+import org.apache.poi.hssf.record.cf.ColorGradientThreshold;
 import org.apache.poi.hssf.record.cf.Threshold;
 import org.apache.poi.ss.usermodel.Color;
 import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold;
@@ -62,14 +63,15 @@ public final class HSSFColorScaleFormatting implements org.apache.poi.ss.usermod
     }
 
     public void setThresholds(ConditionalFormattingThreshold[] thresholds) {
-        Threshold[] t = new Threshold[thresholds.length];
+        ColorGradientThreshold[] t = new ColorGradientThreshold[thresholds.length];
         for (int i=0; i<t.length; i++) {
-            t[i] = ((HSSFConditionalFormattingThreshold)thresholds[i]).getThreshold();
+            HSSFConditionalFormattingThreshold hssfT = (HSSFConditionalFormattingThreshold)thresholds[i];
+            t[i] = (ColorGradientThreshold)hssfT.getThreshold();
         }
         colorFormatting.setThresholds(t);
     }
 
     public HSSFConditionalFormattingThreshold createThreshold() {
-        return new HSSFConditionalFormattingThreshold(new Threshold(), sheet);
+        return new HSSFConditionalFormattingThreshold(new ColorGradientThreshold(), sheet);
     }
 }