From bc9dc5985c71d9da7fd6759138bd249fd9fab194 Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Tue, 14 Jul 2015 23:30:53 +0000 Subject: [PATCH] HSSF record support for CF Iconset rules git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1691107 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/hssf/record/CFRule12Record.java | 14 +- .../poi/hssf/record/cf/FontFormatting.java | 3 +- .../record/cf/IconMultiStateFormatting.java | 123 ++++++++++++++++++ .../usermodel/IconMultiStateFormatting.java | 75 +++++------ .../org/apache/poi/util/BitFieldFactory.java | 5 +- 5 files changed, 169 insertions(+), 51 deletions(-) create mode 100644 src/java/org/apache/poi/hssf/record/cf/IconMultiStateFormatting.java diff --git a/src/java/org/apache/poi/hssf/record/CFRule12Record.java b/src/java/org/apache/poi/hssf/record/CFRule12Record.java index c99d125873..3ace01263e 100644 --- a/src/java/org/apache/poi/hssf/record/CFRule12Record.java +++ b/src/java/org/apache/poi/hssf/record/CFRule12Record.java @@ -19,6 +19,7 @@ package org.apache.poi.hssf.record; import java.util.Arrays; +import org.apache.poi.hssf.record.cf.IconMultiStateFormatting; import org.apache.poi.hssf.record.common.FtrHeader; import org.apache.poi.hssf.record.common.FutureRecord; import org.apache.poi.hssf.usermodel.HSSFSheet; @@ -52,11 +53,12 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord { private byte template_param_length; private byte[] template_params; + private IconMultiStateFormatting multistate; + // TODO Parse these private byte[] gradient_data; private byte[] databar_data; private byte[] filter_data; - private byte[] multistate_data; /** Creates new CFRuleRecord */ private CFRule12Record(byte conditionType, byte comparisonOperation) { @@ -161,7 +163,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord { } else if (type == CONDITION_TYPE_FILTER) { filter_data = in.readRemainder(); } else if (type == CONDITION_TYPE_ICON_SET) { - multistate_data = in.readRemainder(); + multistate = new IconMultiStateFormatting(in); } } @@ -231,7 +233,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord { } else if (type == CONDITION_TYPE_FILTER) { out.write(filter_data); } else if (type == CONDITION_TYPE_ICON_SET) { - out.write(multistate_data); + multistate.serialize(out); } } @@ -255,7 +257,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord { } else if (type == CONDITION_TYPE_FILTER) { len += filter_data.length; } else if (type == CONDITION_TYPE_ICON_SET) { - len += multistate_data.length; + len += multistate.getDataLength(); } return len; } @@ -286,7 +288,9 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord { buffer.append(" .gradient_data =").append(HexDump.toHex(gradient_data)).append("\n"); buffer.append(" .databar_data =").append(HexDump.toHex(databar_data)).append("\n"); buffer.append(" .filter_data =").append(HexDump.toHex(filter_data)).append("\n"); - buffer.append(" .multistate_data=").append(HexDump.toHex(multistate_data)).append("\n"); + if (multistate != null) { + buffer.append(multistate); + } buffer.append("[/CFRULE12]\n"); return buffer.toString(); } diff --git a/src/java/org/apache/poi/hssf/record/cf/FontFormatting.java b/src/java/org/apache/poi/hssf/record/cf/FontFormatting.java index b3cb5e9447..59c49d8a42 100644 --- a/src/java/org/apache/poi/hssf/record/cf/FontFormatting.java +++ b/src/java/org/apache/poi/hssf/record/cf/FontFormatting.java @@ -368,8 +368,7 @@ public final class FontFormatting { setInt(OFFSET_FONT_COLOR_INDEX,fci); } - private boolean getOptionFlag(BitField field) - { + private boolean getOptionFlag(BitField field) { int optionFlags = getInt(OFFSET_OPTION_FLAGS); int value = field.getValue(optionFlags); return value==0? true : false ; diff --git a/src/java/org/apache/poi/hssf/record/cf/IconMultiStateFormatting.java b/src/java/org/apache/poi/hssf/record/cf/IconMultiStateFormatting.java new file mode 100644 index 0000000000..8cd177adc0 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/cf/IconMultiStateFormatting.java @@ -0,0 +1,123 @@ +/* ==================================================================== + 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.ss.usermodel.IconMultiStateFormatting.IconSet; +import org.apache.poi.util.BitField; +import org.apache.poi.util.BitFieldFactory; +import org.apache.poi.util.HexDump; +import org.apache.poi.util.LittleEndianInput; +import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + +/** + * Icon / Multi-State Conditional Formatting Rule Record. + */ +public final class IconMultiStateFormatting implements Cloneable { + private static POILogger log = POILogFactory.getLogger(IconMultiStateFormatting.class); + + private IconSet iconSet; + private byte options; + private byte[] states; // TODO Decode + + private static BitField iconOnly = BitFieldFactory.getInstance(0x01); + private static BitField reversed = BitFieldFactory.getInstance(0x04); + + public IconMultiStateFormatting() { + iconSet = IconSet.GYR_3_TRAFFIC_LIGHTS; + options = 0; + states = new byte[0]; + } + public IconMultiStateFormatting(LittleEndianInput in) { + in.readShort(); // Ignored + in.readByte(); // Reserved + int num = in.readByte(); + int set = in.readByte(); + iconSet = IconSet.byId(set); + if (iconSet.num != num) { + log.log(POILogger.WARN, "Inconsistent Icon Set defintion, found " + iconSet + " but defined as " + num + " entries"); + } + options = in.readByte(); + // TODO Decode + states = new byte[in.available()]; + in.readFully(states); + } + + public IconSet getIconSet() { + return iconSet; + } + public void setIconSet(IconSet set) { + this.iconSet = set; + } + + public boolean isIconOnly() { + return getOptionFlag(iconOnly); + } + public void setIconOnly(boolean only) { + setOptionFlag(only, iconOnly); + } + + public boolean isReversed() { + return getOptionFlag(reversed); + } + public void setReversed(boolean rev) { + setOptionFlag(rev, reversed); + } + + private boolean getOptionFlag(BitField field) { + int value = field.getValue(options); + return value==0? true : false ; + } + private void setOptionFlag(boolean option, BitField field) { + options = field.setByteBoolean(options, option); + } + + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append(" [Icon Formatting]\n"); + buffer.append(" .icon_set = ").append(iconSet).append("\n"); + buffer.append(" .icon_only= ").append(isIconOnly()).append("\n"); + buffer.append(" .reversed = ").append(isReversed()).append("\n"); + buffer.append(" .states = ").append(HexDump.toHex(states)).append("\n"); + buffer.append(" [/Icon Formatting]\n"); + return buffer.toString(); + } + + public Object clone() { + IconMultiStateFormatting rec = new IconMultiStateFormatting(); + rec.iconSet = iconSet; + rec.options = options; + rec.states = new byte[states.length]; + System.arraycopy(states, 0, rec.states, 0, states.length); + return rec; + } + + public int getDataLength() { + return 6 + states.length; + } + + public void serialize(LittleEndianOutput out) { + out.writeShort(0); + out.writeByte(0); + out.writeByte(iconSet.num); + out.writeByte(iconSet.id); + out.writeByte(options); + out.write(states); + } +} diff --git a/src/java/org/apache/poi/ss/usermodel/IconMultiStateFormatting.java b/src/java/org/apache/poi/ss/usermodel/IconMultiStateFormatting.java index 84279c82a8..d4762c790c 100644 --- a/src/java/org/apache/poi/ss/usermodel/IconMultiStateFormatting.java +++ b/src/java/org/apache/poi/ss/usermodel/IconMultiStateFormatting.java @@ -19,17 +19,44 @@ package org.apache.poi.ss.usermodel; -import java.util.HashMap; -import java.util.Map; - /** * High level representation for the Icon / Multi-State Formatting * component of Conditional Formatting settings */ public interface IconMultiStateFormatting { - class IconSet { + public enum IconSet { + /** Green Up / Yellow Side / Red Down arrows */ + GYR_3_ARROW(0, 3, "3Arrows"), + /** Grey Up / Side / Down arrows */ + GREY_3_ARROWS(1, 3, "3ArrowsGray"), + /** Green / Yellow / Red flags */ + GYR_3_FLAGS(2, 3, "3Flags"), + /** Green / Yellow / Red traffic lights (no background) */ + GYR_3_TRAFFIC_LIGHTS(3, 3, null), + /** Green Circle / Yellow Triangle / Red Diamond */ + GYR_3_SHAPES(4, 3, "3Signs"), + /** Green / Yellow / Red traffic lights on a black square background */ + GYR_3_TRAFFIC_LIGHTS_BOX(5, 3, "3TrafficLights2"), + /** Green Tick / Yellow ! / Red Cross on a circle background */ + GYR_3_SYMBOLS_CIRCLE(6, 3, "3Symbols"), + /** Green Tick / Yellow ! / Red Cross (no background) */ + GYR_3_SYMBOLS(7, 3, "3Symbols2"), + /** Green Up / Yellow NE / Yellow SE / Red Down arrows */ + GYR_4_ARROWS(8, 4, "4Arrows"), + /** Grey Up / NE / SE / Down arrows */ + GREY_4_ARROWS(9, 4, "4ArrowsGray"), + /** Red / Light Red / Grey / Black traffic lights */ + RB_4_TRAFFIC_LIGHTS(0xA, 4, "4RedToBlack"), + RATINGS_4(0xB, 4, "4Rating"), + /** Green / Yellow / Red / Black traffic lights */ + GYRB_4_TRAFFIC_LIGHTS(0xC, 4, "4TrafficLights"), + GYYYR_5_ARROWS(0xD, 5, "5Arrows"), + GREY_5_ARROWS(0xE, 5, "5ArrowsGray"), + RATINGS_5(0xF, 5, "5Rating"), + QUARTERS_5(0x10, 5, "5Quarters"); + /** Numeric ID of the icon set */ - public final int id; + public int id; /** How many icons in the set */ public final int num; /** Name (system) of the set */ @@ -42,46 +69,14 @@ public interface IconMultiStateFormatting { return (name==null?"default":name); } - public static IconSet byId(int id) { return byId[id]; } - public static IconSet byName(String name) { return byName.get(name); } + public static IconSet byId(int id) { + return values()[id]; + } - private static final IconSet[] byId = new IconSet[0x10]; - private static final Map byName = new HashMap(); private IconSet(int id, int num, String name) { this.id = id; this.num = num; this.name = name; - byId[id] = this; - byName.put(getName(),this); } } - /** Green Up / Yellow Side / Red Down arrows */ - static final IconSet GYR_3_ARROWS = new IconSet(0, 3, "3Arrows"); - /** Grey Up / Side / Down arrows */ - static final IconSet GREY_3_ARROWS = new IconSet(1, 3, "3ArrowsGray"); - /** Green / Yellow / Red flags */ - static final IconSet GYR_3_FLAGS = new IconSet(2, 3, "3Flags"); - /** Green / Yellow / Red traffic lights (no background) */ - static final IconSet GYR_3_TRAFFIC_LIGHTS = new IconSet(3, 3, null); - /** Green Circle / Yellow Triangle / Red Diamond */ - static final IconSet GYR_3_SHAPES = new IconSet(4, 3, "3Signs"); - /** Green / Yellow / Red traffic lights on a black square background */ - static final IconSet GYR_3_TRAFFIC_LIGHTS_BOX = new IconSet(5, 3, "3TrafficLights2"); - /** Green Tick / Yellow ! / Red Cross on a circle background */ - static final IconSet GYR_3_SYMBOLS_CIRCLE = new IconSet(6, 3, "3Symbols"); - /** Green Tick / Yellow ! / Red Cross (no background) */ - static final IconSet GYR_3_SYMBOLS = new IconSet(7, 3, "3Symbols2"); - /** Green Up / Yellow NE / Yellow SE / Red Down arrows */ - static final IconSet GYR_4_ARROWS = new IconSet(8, 4, "4Arrows"); - /** Grey Up / NE / SE / Down arrows */ - static final IconSet GREY_4_ARROWS = new IconSet(9, 4, "4ArrowsGray"); - /** Red / Light Red / Grey / Black traffic lights */ - static final IconSet RB_4_TRAFFIC_LIGHTS = new IconSet(0xA, 4, "4RedToBlack"); - static final IconSet RATINGS_4 = new IconSet(0xB, 4, "4Rating"); - /** Green / Yellow / Red / Black traffic lights */ - static final IconSet GYRB_4_TRAFFIC_LIGHTS = new IconSet(0xC, 4, "4TrafficLights"); - static final IconSet GYYYR_5_ARROWS = new IconSet(0xD, 5, "5Arrows"); - static final IconSet GREY_5_ARROWS = new IconSet(0xE, 5, "5ArrowsGray"); - static final IconSet RATINGS_5 = new IconSet(0xF, 5, "5Rating"); - static final IconSet QUARTERS_5 = new IconSet(0x10, 5, "5Quarters"); /** * Get the Icon Set used diff --git a/src/java/org/apache/poi/util/BitFieldFactory.java b/src/java/org/apache/poi/util/BitFieldFactory.java index 4159074d76..047d5cb1da 100644 --- a/src/java/org/apache/poi/util/BitFieldFactory.java +++ b/src/java/org/apache/poi/util/BitFieldFactory.java @@ -21,11 +21,8 @@ package org.apache.poi.util; import java.util.*; /** - * Returns immutable Btfield instances. - * - * @author Jason Height (jheight at apache dot org) + * Returns immutable Bitfield instances. */ - public class BitFieldFactory { private static Map instances = new HashMap(); -- 2.39.5