git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1691858 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_13_FINAL
@@ -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, |
@@ -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); | |||
} | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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); | |||
} | |||
} | |||
@@ -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 | |||
} | |||
} |
@@ -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 | |||
} | |||
} |
@@ -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); | |||
} | |||
} |