diff --git a/src/documentation/content/xdocs/changes.xml b/src/documentation/content/xdocs/changes.xml
index d8c366b2be..0fb5cac07c 100644
--- a/src/documentation/content/xdocs/changes.xml
+++ b/src/documentation/content/xdocs/changes.xml
@@ -44,6 +44,8 @@
- *
+ *
+ * // Define a Conditional Formatting rule, which triggers formatting
+ * // when cell's value is greater or equal than 100.0 and
+ * // applies patternFormatting defined below.
+ * HSSFConditionalFormattingRule rule = sheet.createConditionalFormattingRule(
+ * ComparisonOperator.GE,
+ * "100.0", // 1st formula
+ * null // 2nd formula is not used for comparison operator GE
+ * );
+ *
* // Create pattern with red background
- * HSSFPatternFormatting patternFormatting = new HSSFPatternFormatting();
+ * HSSFPatternFormatting patternFmt = rule.cretePatternFormatting();
* patternFormatting.setFillBackgroundColor(HSSFColor.RED.index);
*
+ * // Define a region containing first column
* Region [] regions =
* {
- * // Define a region containing first column
* new Region(1,(short)1,-1,(short)1)
* };
*
- * HSSFConditionalFormattingRule[] rules =
- * {
- * // Define a Conditional Formatting rule, which triggers formatting
- * // when cell's value is greater or equal than 100.0 and
- * // applies patternFormatting defined above.
- *
- * sheet.createConditionalFormattingRule(
- * HSSFConditionalFormattingRule.COMPARISON_OPERATOR_GE,
- * "100.0", // 1st formula
- * null, // 2nd formula is not used for comparison operator GE
- * null, // do not override Font Formatting
- * null, // do not override Border Formatting
- * patternFormatting
- * )
- * };
- *
- * // Apply Conditional Formatting rules defined above to the regions
- * sheet.addConditionalFormatting(regions, rules);
+ * // Apply Conditional Formatting rule defined above to the regions
+ * sheet.addConditionalFormatting(regions, rule);
*
*
* @author Dmitriy Kumshayev
*/
public final class HSSFConditionalFormatting
{
- private final Workbook workbook;
+ private final HSSFWorkbook _workbook;
private final CFRecordsAggregate cfAggregate;
- HSSFConditionalFormatting(HSSFSheet sheet, CFRecordsAggregate cfAggregate)
+ HSSFConditionalFormatting(HSSFWorkbook workbook, CFRecordsAggregate cfAggregate)
{
- if(sheet == null) {
- throw new IllegalArgumentException("sheet must not be null");
+ if(workbook == null) {
+ throw new IllegalArgumentException("workbook must not be null");
}
if(cfAggregate == null) {
throw new IllegalArgumentException("cfAggregate must not be null");
}
- workbook = sheet.workbook.getWorkbook();
+ _workbook = workbook;
this.cfAggregate = cfAggregate;
}
CFRecordsAggregate getCFRecordsAggregate() {
@@ -141,7 +134,7 @@ public final class HSSFConditionalFormatting
public HSSFConditionalFormattingRule getRule(int idx)
{
CFRuleRecord ruleRecord = cfAggregate.getRule(idx);
- return new HSSFConditionalFormattingRule(workbook, ruleRecord);
+ return new HSSFConditionalFormattingRule(_workbook, ruleRecord);
}
/**
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFConditionalFormattingRule.java b/src/java/org/apache/poi/hssf/usermodel/HSSFConditionalFormattingRule.java
index 490ff4d342..1d4100655a 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFConditionalFormattingRule.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFConditionalFormattingRule.java
@@ -18,7 +18,6 @@
package org.apache.poi.hssf.usermodel;
import org.apache.poi.hssf.model.FormulaParser;
-import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator;
import org.apache.poi.hssf.record.cf.BorderFormatting;
@@ -40,33 +39,36 @@ public final class HSSFConditionalFormattingRule
private static final byte CELL_COMPARISON = CFRuleRecord.CONDITION_TYPE_CELL_VALUE_IS;
private final CFRuleRecord cfRuleRecord;
- private final Workbook workbook;
+ private final HSSFWorkbook workbook;
- HSSFConditionalFormattingRule(Workbook pWorkbook, CFRuleRecord pRuleRecord) {
+ HSSFConditionalFormattingRule(HSSFWorkbook pWorkbook, CFRuleRecord pRuleRecord) {
workbook = pWorkbook;
cfRuleRecord = pRuleRecord;
}
- HSSFConditionalFormattingRule(Workbook pWorkbook, CFRuleRecord pRuleRecord,
- HSSFFontFormatting fontFmt, HSSFBorderFormatting bordFmt, HSSFPatternFormatting patternFmt) {
- this(pWorkbook, pRuleRecord);
- setFontFormatting(fontFmt);
- setBorderFormatting(bordFmt);
- setPatternFormatting(patternFmt);
- }
CFRuleRecord getCfRuleRecord()
{
return cfRuleRecord;
}
-
- /**
- * @param fontFmt pass null
to signify 'font unchanged'
- */
- public void setFontFormatting(HSSFFontFormatting fontFmt)
+ private HSSFFontFormatting getFontFormatting(boolean create)
{
- FontFormatting block = fontFmt==null ? null : fontFmt.getFontFormattingBlock();
- cfRuleRecord.setFontFormatting(block);
+ FontFormatting fontFormatting = cfRuleRecord.getFontFormatting();
+ if ( fontFormatting != null)
+ {
+ cfRuleRecord.setFontFormatting(fontFormatting);
+ return new HSSFFontFormatting(cfRuleRecord);
+ }
+ else if( create )
+ {
+ fontFormatting = new FontFormatting();
+ cfRuleRecord.setFontFormatting(fontFormatting);
+ return new HSSFFontFormatting(cfRuleRecord);
+ }
+ else
+ {
+ return null;
+ }
}
/**
@@ -74,50 +76,89 @@ public final class HSSFConditionalFormattingRule
*/
public HSSFFontFormatting getFontFormatting()
{
- FontFormatting ff = cfRuleRecord.getFontFormatting();
- if ( ff == null ) {
- return null;
- }
- return new HSSFFontFormatting(ff);
+ return getFontFormatting(false);
+ }
+ /**
+ * create a new font formatting structure if it does not exist,
+ * otherwise just return existing object.
+ * @return - font formatting object, never returns null
.
+ */
+ public HSSFFontFormatting createFontFormatting()
+ {
+ return getFontFormatting(true);
}
- /**
- * @param borderFmt pass null
to signify 'border unchanged'
- */
- public void setBorderFormatting(HSSFBorderFormatting borderFmt)
+ private HSSFBorderFormatting getBorderFormatting(boolean create)
{
- BorderFormatting block = borderFmt==null ? null : borderFmt.getBorderFormattingBlock();
- cfRuleRecord.setBorderFormatting(block);
+ BorderFormatting borderFormatting = cfRuleRecord.getBorderFormatting();
+ if ( borderFormatting != null)
+ {
+ cfRuleRecord.setBorderFormatting(borderFormatting);
+ return new HSSFBorderFormatting(cfRuleRecord);
+ }
+ else if( create )
+ {
+ borderFormatting = new BorderFormatting();
+ cfRuleRecord.setBorderFormatting(borderFormatting);
+ return new HSSFBorderFormatting(cfRuleRecord);
+ }
+ else
+ {
+ return null;
+ }
}
/**
* @return - border formatting object if defined, null
otherwise
*/
public HSSFBorderFormatting getBorderFormatting()
{
- BorderFormatting bf = cfRuleRecord.getBorderFormatting();
- if ( bf == null ) {
- return null;
- }
- return new HSSFBorderFormatting(bf);
+ return getBorderFormatting(false);
}
/**
- * @param patternFmt pass null
to signify 'pattern unchanged'
+ * create a new border formatting structure if it does not exist,
+ * otherwise just return existing object.
+ * @return - border formatting object, never returns null
.
*/
- public void setPatternFormatting(HSSFPatternFormatting patternFmt)
+ public HSSFBorderFormatting createBorderFormatting()
{
- PatternFormatting block = patternFmt==null ? null : patternFmt.getPatternFormattingBlock();
- cfRuleRecord.setPatternFormatting(block);
+ return getBorderFormatting(true);
}
+
+ private HSSFPatternFormatting getPatternFormatting(boolean create)
+ {
+ PatternFormatting patternFormatting = cfRuleRecord.getPatternFormatting();
+ if ( patternFormatting != null)
+ {
+ cfRuleRecord.setPatternFormatting(patternFormatting);
+ return new HSSFPatternFormatting(cfRuleRecord);
+ }
+ else if( create )
+ {
+ patternFormatting = new PatternFormatting();
+ cfRuleRecord.setPatternFormatting(patternFormatting);
+ return new HSSFPatternFormatting(cfRuleRecord);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
/**
* @return - pattern formatting object if defined, null
otherwise
*/
public HSSFPatternFormatting getPatternFormatting()
{
- PatternFormatting pf = cfRuleRecord.getPatternFormatting();
- if ( pf == null ) {
- return null;
- }
- return new HSSFPatternFormatting(pf);
+ return getPatternFormatting(false);
+ }
+ /**
+ * create a new pattern formatting structure if it does not exist,
+ * otherwise just return existing object.
+ * @return - pattern formatting object, never returns null
.
+ */
+ public HSSFPatternFormatting createPatternFormatting()
+ {
+ return getPatternFormatting(true);
}
public String getFormula1()
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFFontFormatting.java b/src/java/org/apache/poi/hssf/usermodel/HSSFFontFormatting.java
index a701eb63af..774bc1ea4d 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFFontFormatting.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFFontFormatting.java
@@ -17,6 +17,7 @@
package org.apache.poi.hssf.usermodel;
+import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.cf.FontFormatting;
/**
* High level representation for Font Formatting component
@@ -33,28 +34,23 @@ public final class HSSFFontFormatting
public final static short SS_SUPER = FontFormatting.SS_SUPER;
/** Escapement type - Subscript */
public final static short SS_SUB = FontFormatting.SS_SUB;
-
+
/** Underline type - None */
public final static byte U_NONE = FontFormatting.U_NONE;
- /** Underline type - Single */
+ /** Underline type - Single */
public final static byte U_SINGLE = FontFormatting.U_SINGLE;
- /** Underline type - Double */
+ /** Underline type - Double */
public final static byte U_DOUBLE = FontFormatting.U_DOUBLE;
/** Underline type - Single Accounting */
public final static byte U_SINGLE_ACCOUNTING = FontFormatting.U_SINGLE_ACCOUNTING;
- /** Underline type - Double Accounting */
+ /** Underline type - Double Accounting */
public final static byte U_DOUBLE_ACCOUNTING = FontFormatting.U_DOUBLE_ACCOUNTING;
-
+
private final FontFormatting fontFormatting;
- public HSSFFontFormatting()
+ protected HSSFFontFormatting(CFRuleRecord cfRuleRecord)
{
- fontFormatting = new FontFormatting();
- }
-
- protected HSSFFontFormatting(FontFormatting ff)
- {
- fontFormatting = ff;
+ this.fontFormatting = cfRuleRecord.getFontFormatting();
}
protected FontFormatting getFontFormattingBlock()
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java b/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java
index 3da5f96882..57ec250038 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java
@@ -20,12 +20,8 @@ package org.apache.poi.hssf.usermodel;
import org.apache.poi.hssf.model.FormulaParser;
import org.apache.poi.hssf.record.formula.OperationPtg;
import org.apache.poi.hssf.record.formula.Ptg;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
-import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.usermodel.FormulaEvaluator.CellValue;
/**
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
@@ -44,7 +40,7 @@ public class HSSFFormulaEvaluator extends FormulaEvaluator {
* formula evaluated.
*/
public static FormulaParser getUnderlyingParser(HSSFWorkbook workbook, String formula) {
- return new FormulaParser(formula, workbook.getWorkbook());
+ return new FormulaParser(formula, workbook);
}
@@ -57,7 +53,7 @@ public class HSSFFormulaEvaluator extends FormulaEvaluator {
*/
void inspectPtgs(String formula) {
HSSFWorkbook hssfWb = (HSSFWorkbook)workbook;
- FormulaParser fp = new FormulaParser(formula, hssfWb.getWorkbook());
+ FormulaParser fp = new FormulaParser(formula, hssfWb);
fp.parse();
Ptg[] ptgs = fp.getRPNPtg();
System.out.println("
- *
- *
null
)
- * @param bordFmt - border formatting rules (may be null
)
- * @param patternFmt - pattern formatting rules (may be null
)
- */
- public HSSFConditionalFormattingRule createConditionalFormattingRule(
- byte comparisonOperation,
- String formula1,
- String formula2,
- HSSFFontFormatting fontFmt,
- HSSFBorderFormatting bordFmt,
- HSSFPatternFormatting patternFmt) {
-
- Workbook wb = workbook.getWorkbook();
- CFRuleRecord rr = CFRuleRecord.create(wb, comparisonOperation, formula1, formula2);
- return new HSSFConditionalFormattingRule(wb, rr, fontFmt, bordFmt, patternFmt);
- }
-
- /**
- * A factory method allowing to create a conditional formatting rule with a formula
- * and formatting rules such as font format, border format and pattern format. null
)
- * @param bordFmt - border formatting rules (may be null
)
- * @param patternFmt - pattern formatting rules (may be null
)
- */
- public HSSFConditionalFormattingRule createConditionalFormattingRule(
- String formula,
- HSSFFontFormatting fontFmt,
- HSSFBorderFormatting bordFmt,
- HSSFPatternFormatting patternFmt) {
- Workbook wb = workbook.getWorkbook();
- CFRuleRecord rr = CFRuleRecord.create(wb, formula);
- return new HSSFConditionalFormattingRule(wb, rr, fontFmt, bordFmt, patternFmt);
- }
-
- /**
- * Adds a copy of HSSFConditionalFormatting object to the sheet
- * This method could be used to copy HSSFConditionalFormatting object - * from one sheet to another. For example: - *
- * HSSFConditionalFormatting cf = sheet.getConditionalFormattingAt(index); - * newSheet.addConditionalFormatting(cf); - *- * - * @param cf HSSFConditionalFormatting object - * @return index of the new Conditional Formatting object - */ - public int addConditionalFormatting( HSSFConditionalFormatting cf ) { - CFRecordsAggregate cfraClone = cf.getCFRecordsAggregate().cloneCFAggregate(); - - return sheet.addConditionalFormatting(cfraClone); - } - - /** - * Allows to add a new Conditional Formatting set to the sheet. - * - * @param regions - list of rectangular regions to apply conditional formatting rules - * @param hcfRules - set of up to three conditional formatting rules - * - * @return index of the newly created Conditional Formatting object - */ - - public int addConditionalFormatting(Region [] regions, HSSFConditionalFormattingRule [] hcfRules) { - if (regions == null) { - throw new IllegalArgumentException("regions must not be null"); - } - if (hcfRules == null) { - throw new IllegalArgumentException("hcfRules must not be null"); - } - - CFRuleRecord[] rules = new CFRuleRecord[hcfRules.length]; - for (int i = 0; i != hcfRules.length; i++) { - rules[i] = hcfRules[i].getCfRuleRecord(); - } - CFRecordsAggregate cfra = new CFRecordsAggregate(regions, rules); - return sheet.addConditionalFormatting(cfra); - } - - /** - * gets Conditional Formatting object at a particular index - * - * @param index - * of the Conditional Formatting object to fetch - * @return Conditional Formatting object - */ - public HSSFConditionalFormatting getConditionalFormattingAt(int index) { - CFRecordsAggregate cf = sheet.getCFRecordsAggregateAt(index); - if (cf == null) { - return null; - } - return new HSSFConditionalFormatting(this,cf); - } - - /** - * @return number of Conditional Formatting objects of the sheet - */ - public int getNumConditionalFormattings() { - return sheet.getNumConditionalFormattings(); - } - - /** - * removes a Conditional Formatting object by index - * @param index of a Conditional Formatting object to remove - */ - public void removeConditionalFormatting(int index) { - sheet.removeConditionalFormatting(index); + public HSSFSheetConditionalFormatting getSheetConditionalFormatting() { + return new HSSFSheetConditionalFormatting(workbook, sheet); } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheetConditionalFormatting.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheetConditionalFormatting.java new file mode 100644 index 0000000000..c042456a4f --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheetConditionalFormatting.java @@ -0,0 +1,196 @@ +/* ==================================================================== + 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.usermodel; + +import org.apache.poi.hssf.model.Sheet; +import org.apache.poi.hssf.record.CFRuleRecord; +import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate; +import org.apache.poi.ss.util.Region; + +/** + * The 'Conditional Formatting' facet of HSSFSheet + * + * @author Dmitriy Kumshayev + */ +public final class HSSFSheetConditionalFormatting { + + private final HSSFWorkbook _workbook; + private final Sheet _sheet; + + /* package */ HSSFSheetConditionalFormatting(HSSFWorkbook workbook, Sheet sheet) { + _workbook = workbook; + _sheet = sheet; + } + + /** + * A factory method allowing to create a conditional formatting rule + * with a cell comparison operator + * + * @param comparisonOperation - a constant value from + * {@link HSSFConditionalFormattingRule.ComparisonOperator}:
+ *
This method could be used to copy HSSFConditionalFormatting object + * from one sheet to another. For example: + *
+ * HSSFConditionalFormatting cf = sheet.getConditionalFormattingAt(index); + * newSheet.addConditionalFormatting(cf); + *+ * + * @param cf HSSFConditionalFormatting object + * @return index of the new Conditional Formatting object + */ + public int addConditionalFormatting( HSSFConditionalFormatting cf ) { + CFRecordsAggregate cfraClone = cf.getCFRecordsAggregate().cloneCFAggregate(); + + return _sheet.addConditionalFormatting(cfraClone); + } + + /** + * Allows to add a new Conditional Formatting set to the sheet. + * + * @param regions - list of rectangular regions to apply conditional formatting rules + * @param cfRules - set of up to three conditional formatting rules + * + * @return index of the newly created Conditional Formatting object + */ + + public int addConditionalFormatting(Region[] regions, HSSFConditionalFormattingRule[] cfRules) { + if (regions == null) { + throw new IllegalArgumentException("regions must not be null"); + } + if (cfRules == null) { + throw new IllegalArgumentException("cfRules must not be null"); + } + if (cfRules.length == 0) { + throw new IllegalArgumentException("cfRules must not be empty"); + } + if (cfRules.length > 3) { + throw new IllegalArgumentException("Number of rules must not exceed 3"); + } + + CFRuleRecord[] rules = new CFRuleRecord[cfRules.length]; + for (int i = 0; i != cfRules.length; i++) { + rules[i] = cfRules[i].getCfRuleRecord(); + } + CFRecordsAggregate cfra = new CFRecordsAggregate(regions, rules); + return _sheet.addConditionalFormatting(cfra); + } + + public int addConditionalFormatting(Region[] regions, + HSSFConditionalFormattingRule rule1) + { + return addConditionalFormatting(regions, + new HSSFConditionalFormattingRule[] + { + rule1 + }); + } + + public int addConditionalFormatting(Region[] regions, + HSSFConditionalFormattingRule rule1, + HSSFConditionalFormattingRule rule2) + { + return addConditionalFormatting(regions, + new HSSFConditionalFormattingRule[] + { + rule1, rule2 + }); + } + + public int addConditionalFormatting(Region[] regions, + HSSFConditionalFormattingRule rule1, + HSSFConditionalFormattingRule rule2, + HSSFConditionalFormattingRule rule3) + { + return addConditionalFormatting(regions, + new HSSFConditionalFormattingRule[] + { + rule1, rule2, rule3 + }); + } + + /** + * gets Conditional Formatting object at a particular index + * + * @param index + * of the Conditional Formatting object to fetch + * @return Conditional Formatting object + */ + public HSSFConditionalFormatting getConditionalFormattingAt(int index) { + CFRecordsAggregate cf = _sheet.getCFRecordsAggregateAt(index); + if (cf == null) { + return null; + } + return new HSSFConditionalFormatting(_workbook, cf); + } + + /** + * @return number of Conditional Formatting objects of the sheet + */ + public int getNumConditionalFormattings() { + return _sheet.getNumConditionalFormattings(); + } + + /** + * removes a Conditional Formatting object by index + * @param index of a Conditional Formatting object to remove + */ + public void removeConditionalFormatting(int index) { + _sheet.removeConditionalFormatting(index); + } +} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java index 57f44148b8..4135694830 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java @@ -62,6 +62,7 @@ import org.apache.poi.hssf.record.formula.Area3DPtg; import org.apache.poi.hssf.record.formula.MemFuncPtg; import org.apache.poi.hssf.record.formula.UnionPtg; import org.apache.poi.hssf.util.CellReference; +import org.apache.poi.hssf.util.SheetReferences; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.ss.usermodel.CreationHelper; @@ -266,7 +267,7 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm } for (int i = 0 ; i < workbook.getNumNames() ; ++i){ - HSSFName name = new HSSFName(workbook, workbook.getNameRecord(i)); + HSSFName name = new HSSFName(this, workbook.getNameRecord(i)); names.add(name); } } @@ -539,6 +540,17 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm } return -1; } + + /** + * Returns the external sheet index of the sheet + * with the given internal index, creating one + * if needed. + * Used by some of the more obscure formula and + * named range things. + */ + public short getExternalSheetIndex(int internalSheetIndex) { + return workbook.checkExternSheet(internalSheetIndex); + } /** * create an HSSFSheet for this HSSFWorkbook, adds it to the sheets and returns @@ -668,6 +680,10 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm } return retval; } + + public SheetReferences getSheetReferences() { + return workbook.getSheetReferences(); + } /** * removes sheet at the given index @@ -811,7 +827,7 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm if (isNewRecord) { - HSSFName newName = new HSSFName(workbook, nameRecord); + HSSFName newName = new HSSFName(this, nameRecord); names.add(newName); } @@ -1122,6 +1138,17 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm return result; } + + /** + * TODO - make this less cryptic / move elsewhere + * @param refIndex Index to REF entry in EXTERNSHEET record in the Link Table + * @param definedNameIndex zero-based to DEFINEDNAME or EXTERNALNAME record + * @return the string representation of the defined or external name + */ + public String resolveNameXText(int refIndex, int definedNameIndex) { + return workbook.resolveNameXText(refIndex, definedNameIndex); + } + /** * Sets the printarea for the sheet provided @@ -1180,7 +1207,7 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm if (name == null) return null; //adding one here because 0 indicates a global named region; doesnt make sense for print areas - return name.getAreaReference(workbook); + return name.getAreaReference(this); } /** @@ -1197,7 +1224,7 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm public HSSFName createName(){ NameRecord nameRecord = workbook.createName(); - HSSFName newName = new HSSFName(workbook, nameRecord); + HSSFName newName = new HSSFName(this, nameRecord); names.add(newName); diff --git a/src/scratchpad/examples/src/org/apache/poi/hslf/examples/ApacheconEU08.java b/src/scratchpad/examples/src/org/apache/poi/hslf/examples/ApacheconEU08.java index 0f28c2a8c9..962349876a 100755 --- a/src/scratchpad/examples/src/org/apache/poi/hslf/examples/ApacheconEU08.java +++ b/src/scratchpad/examples/src/org/apache/poi/hslf/examples/ApacheconEU08.java @@ -459,6 +459,7 @@ public class ApacheconEU08 { TextBox box2 = new TextBox(); TextRun tr2 = box2.getTextRun(); tr2.setRunType(TextHeaderAtom.BODY_TYPE); + tr2.getRichTextRuns()[0].setFontSize(32); tr2.setText( "Support for more PowerPoint functionality\r" + "Rendering slides into java.awt.Graphics2D"); @@ -477,6 +478,7 @@ public class ApacheconEU08 { TextBox box4 = new TextBox(); TextRun tr4 = box4.getTextRun(); tr4.setRunType(TextHeaderAtom.BODY_TYPE); + tr4.getRichTextRuns()[0].setFontSize(32); tr4.setText( "Integration with Apache FOP - Formatting Objects Processor"); box4.setAnchor(new Rectangle(36, 290, 648, 90)); diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/AutoShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/AutoShape.java index b3ddce37da..cf65a9b13c 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/AutoShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/AutoShape.java @@ -20,11 +20,15 @@ package org.apache.poi.hslf.model; import org.apache.poi.ddf.*; /** - * Represents a autoshape in a PowerPoint drawing + * Represents an AutoShape. + *
+ * AutoShapes are drawing objects with a particular shape that may be customized through smart resizing and adjustments. + * See {@link ShapeTypes} + *
* * @author Yegor Kozlov */ -public class AutoShape extends SimpleShape { +public class AutoShape extends TextShape { protected AutoShape(EscherContainerRecord escherRecord, Shape parent){ super(escherRecord, parent); @@ -40,23 +44,62 @@ public class AutoShape extends SimpleShape { } protected EscherContainerRecord createSpContainer(int shapeType, boolean isChild){ - EscherContainerRecord spcont = super.createSpContainer(isChild); + _escherContainer = super.createSpContainer(isChild); - EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID); - short type = (short)((shapeType << 4) | 0x2); - spRecord.setOptions(type); + setShapeType(shapeType); //set default properties for an autoshape - EscherOptRecord opt = (EscherOptRecord)getEscherChild(spcont, EscherOptRecord.RECORD_ID); + setEscherProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x40000); + setEscherProperty(EscherProperties.FILL__FILLCOLOR, 0x8000004); + setEscherProperty(EscherProperties.FILL__FILLCOLOR, 0x8000004); + setEscherProperty(EscherProperties.FILL__FILLBACKCOLOR, 0x8000000); + setEscherProperty(EscherProperties.FILL__NOFILLHITTEST, 0x100010); + setEscherProperty(EscherProperties.LINESTYLE__COLOR, 0x8000001); + setEscherProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x80008); + setEscherProperty(EscherProperties.SHADOWSTYLE__COLOR, 0x8000002); - opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.FILL__FILLCOLOR, 0x8000004)); - opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.FILL__FILLBACKCOLOR, 0x8000000)); - opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.FILL__NOFILLHITTEST, 0x100010)); - opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__COLOR, 0x8000001)); - opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x80008)); - opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.SHADOWSTYLE__COLOR, 0x8000002)); - - return spcont; + return _escherContainer; } + protected void setDefaultTextProperties(TextRun _txtrun){ + setVerticalAlignment(TextBox.AnchorMiddle); + setHorizontalAlignment(TextBox.AlignCenter); + setWordWrap(TextBox.WrapNone); + } + + /** + * Gets adjust value which controls smart resizing of the auto-shape. + * + *+ * The adjustment values are given in shape coordinates: + * the origin is at the top-left, positive-x is to the right, positive-y is down. + * The region from (0,0) to (S,S) maps to the geometry box of the shape (S=21600 is a constant). + *
+ * + * @param idx the adjust index in the [0, 9] range + * @return the adjustment value + */ + public int getAdjustmentValue(int idx){ + if(idx < 0 || idx > 9) throw new IllegalArgumentException("The index of an adjustment value must be in the [0, 9] range"); + + return getEscherProperty((short)(EscherProperties.GEOMETRY__ADJUSTVALUE + idx)); + } + + /** + * Sets adjust value which controls smart resizing of the auto-shape. + * + *+ * The adjustment values are given in shape coordinates: + * the origin is at the top-left, positive-x is to the right, positive-y is down. + * The region from (0,0) to (S,S) maps to the geometry box of the shape (S=21600 is a constant). + *
+ * + * @param idx the adjust index in the [0, 9] range + * @param val the adjustment value + */ + public void setAdjustmentValue(int idx, int val){ + if(idx < 0 || idx > 9) throw new IllegalArgumentException("The index of an adjustment value must be in the [0, 9] range"); + + setEscherProperty((short)(EscherProperties.GEOMETRY__ADJUSTVALUE + idx), val); + } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Line.java b/src/scratchpad/src/org/apache/poi/hslf/model/Line.java index 0d3f616e92..9237183689 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Line.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Line.java @@ -106,14 +106,14 @@ public class Line extends SimpleShape { } protected EscherContainerRecord createSpContainer(boolean isChild){ - EscherContainerRecord spcont = super.createSpContainer(isChild); + _escherContainer = super.createSpContainer(isChild); - EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID); + EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID); short type = (ShapeTypes.Line << 4) | 0x2; spRecord.setOptions(type); //set default properties for a line - EscherOptRecord opt = (EscherOptRecord)getEscherChild(spcont, EscherOptRecord.RECORD_ID); + EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID); //default line properties setEscherProperty(opt, EscherProperties.GEOMETRY__SHAPEPATH, 4); @@ -123,7 +123,7 @@ public class Line extends SimpleShape { setEscherProperty(opt, EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0xA0008); setEscherProperty(opt, EscherProperties.SHADOWSTYLE__COLOR, 0x8000002); - return spcont; + return _escherContainer; } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/PPFont.java b/src/scratchpad/src/org/apache/poi/hslf/model/PPFont.java new file mode 100755 index 0000000000..8b4de90509 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/model/PPFont.java @@ -0,0 +1,243 @@ +/* ==================================================================== + 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.hslf.model; + +import org.apache.poi.hslf.record.FontEntityAtom; + +/** + * Represents a Font used in a presenation. + *+ * In PowerPoint Font is a shared resource and can be shared among text object in the presentation. + *
+ * Some commonly used fonts are predefined in static constants. + * + * @author Yegor Kozlov + */ +public class PPFont { + /** + * ANSI character set + */ + public final static byte ANSI_CHARSET = 0; + + /** + * Default character set. + */ + public final static byte DEFAULT_CHARSET = 1; + + /** + * Symbol character set + */ + public final static byte SYMBOL_CHARSET = 2; + + + /** + * Constants for the pitch and family of the font. + * The two low-order bits specify the pitch of the font and can be one of the following values + */ + public final static byte DEFAULT_PITCH = 0; + public final static byte FIXED_PITCH = 1; + public final static byte VARIABLE_PITCH = 2; + + /** + * Don't care or don't know. + */ + public final static byte FF_DONTCARE = 0; + /** + * Fonts with variable stroke width (proportional) and with serifs. Times New Roman is an example. + */ + public final static byte FF_ROMAN = 16; + /** + * Fonts with variable stroke width (proportional) and without serifs. Arial is an example. + */ + public final static byte FF_SWISS = 32; + /** + * Fonts designed to look like handwriting. Script and Cursive are examples. + */ + public final static byte FF_SCRIPT = 64; + /** + * Fonts with constant stroke width (monospace), with or without serifs. + * Monospace fonts are usually modern. CourierNew is an example + */ + public final static byte FF_MODERN = 48; + /** + * Novelty fonts. Old English is an example + */ + public final static byte FF_DECORATIVE = 80; + + + protected int charset; + protected int type; + protected int flags; + protected int pitch; + protected String name; + + /** + * Creates a new instance of PPFont + */ + public PPFont(){ + + } + + /** + * Creates a new instance of PPFont and initialize it from the supplied font atom + */ + public PPFont(FontEntityAtom fontAtom){ + name = fontAtom.getFontName(); + charset = fontAtom.getCharSet(); + type = fontAtom.getFontType(); + flags = fontAtom.getFontFlags(); + pitch = fontAtom.getPitchAndFamily(); + } + + /** + * set the name for the font (i.e. Arial) + * + * @param val String representing the name of the font to use + */ + public void setFontName(String val){ + name = val; + } + + /** + * get the name for the font (i.e. Arial) + * + * @return String representing the name of the font to use + */ + public String getFontName(){ + return name; + } + + /** + * set the character set + * + * @param val - characterset + */ + public void setCharSet(int val){ + charset = val; + } + + /** + * get the character set + * + * @return charset - characterset + */ + public int getCharSet(){ + return charset; + } + + /** + * set the font flags + * Bit 1: If set, font is subsetted + * + * @param val - the font flags + */ + public void setFontFlags(int val){ + flags = val; + } + + /** + * get the character set + * Bit 1: If set, font is subsetted + * + * @return the font flags + */ + public int getFontFlags(){ + return flags; + } + + /** + * set the font type + *+ * Bit 1: Raster Font + * Bit 2: Device Font + * Bit 3: TrueType Font + *
+ * + * @param val - the font type + */ + public void setFontType(int val){ + type = val; + } + + /** + * get the font type + *+ * Bit 1: Raster Font + * Bit 2: Device Font + * Bit 3: TrueType Font + *
+ * + * @return the font type + */ + public int getFontType(){ + return type; + } + + /** + * set lfPitchAndFamily + * + * + * @param val - Corresponds to the lfPitchAndFamily field of the Win32 API LOGFONT structure + */ + public void setPitchAndFamily(int val){ + pitch = val; + } + + /** + * get lfPitchAndFamily + * + * @return corresponds to the lfPitchAndFamily field of the Win32 API LOGFONT structure + */ + public int getPitchAndFamily(){ + return pitch; + } + + public static final PPFont ARIAL; + public static final PPFont TIMES_NEW_ROMAN ; + public static final PPFont COURIER_NEW; + public static final PPFont WINGDINGS; + static { + ARIAL = new PPFont(); + ARIAL.setFontName("Arial"); + ARIAL.setCharSet(ANSI_CHARSET); + ARIAL.setFontType(4); + ARIAL.setFontFlags(0); + ARIAL.setPitchAndFamily(VARIABLE_PITCH | FF_SWISS); + + TIMES_NEW_ROMAN = new PPFont(); + TIMES_NEW_ROMAN.setFontName("Times New Roman"); + TIMES_NEW_ROMAN.setCharSet(ANSI_CHARSET); + TIMES_NEW_ROMAN.setFontType(4); + TIMES_NEW_ROMAN.setFontFlags(0); + TIMES_NEW_ROMAN.setPitchAndFamily(VARIABLE_PITCH | FF_ROMAN); + + COURIER_NEW = new PPFont(); + COURIER_NEW.setFontName("Courier New"); + COURIER_NEW.setCharSet(ANSI_CHARSET); + COURIER_NEW.setFontType(4); + COURIER_NEW.setFontFlags(0); + COURIER_NEW.setPitchAndFamily(FIXED_PITCH | FF_MODERN); + + WINGDINGS = new PPFont(); + WINGDINGS.setFontName("Wingdings"); + WINGDINGS.setCharSet(SYMBOL_CHARSET); + WINGDINGS.setFontType(4); + WINGDINGS.setFontFlags(0); + WINGDINGS.setPitchAndFamily(VARIABLE_PITCH | FF_DONTCARE); + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java b/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java index 90efd5f3ee..910d5c8503 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java @@ -120,20 +120,20 @@ public class Picture extends SimpleShape { * @return the create Picture object */ protected EscherContainerRecord createSpContainer(int idx, boolean isChild) { - EscherContainerRecord spContainer = super.createSpContainer(isChild); - spContainer.setOptions((short)15); + _escherContainer = super.createSpContainer(isChild); + _escherContainer.setOptions((short)15); - EscherSpRecord spRecord = spContainer.getChildById(EscherSpRecord.RECORD_ID); + EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID); spRecord.setOptions((short)((ShapeTypes.PictureFrame << 4) | 0x2)); //set default properties for a picture - EscherOptRecord opt = (EscherOptRecord)getEscherChild(spContainer, EscherOptRecord.RECORD_ID); + EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID); setEscherProperty(opt, EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 8388736); //another weird feature of powerpoint: for picture id we must add 0x4000. setEscherProperty(opt, (short)(EscherProperties.BLIP__BLIPTODISPLAY + 0x4000), idx); - return spContainer; + return _escherContainer; } /** diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java b/src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java index dd0132ebe0..f0bc74558f 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java @@ -49,15 +49,15 @@ public class Placeholder extends TextBox { * @return the createdEscherContainerRecord
which holds shape data
*/
protected EscherContainerRecord createSpContainer(boolean isChild){
- EscherContainerRecord spcont = super.createSpContainer(isChild);
+ _escherContainer = super.createSpContainer(isChild);
- EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID);
+ EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);
spRecord.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HAVEMASTER);
EscherClientDataRecord cldata = new EscherClientDataRecord();
cldata.setOptions((short)15);
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(spcont, EscherOptRecord.RECORD_ID);
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
//Placeholders can't be grouped
setEscherProperty(opt, EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 262144);
@@ -86,7 +86,7 @@ public class Placeholder extends TextBox {
cldata.setRemainingData(out.toByteArray());
//append placeholder container before EscherTextboxRecord
- List lst = spcont.getChildRecords();
+ List lst = _escherContainer.getChildRecords();
for (int i = 0; i < lst.size(); i++) {
EscherRecord rec = (EscherRecord)lst.get(i);
if(rec.getRecordId() == EscherTextboxRecord.RECORD_ID){
@@ -94,6 +94,6 @@ public class Placeholder extends TextBox {
}
}
- return spcont;
+ return _escherContainer;
}
}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java b/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java
index 66c95e50cf..76b43ebb8a 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java
@@ -17,6 +17,10 @@
package org.apache.poi.hslf.model;
import org.apache.poi.ddf.*;
+import org.apache.poi.util.POILogger;
+import org.apache.poi.util.POILogFactory;
+
+import java.util.List;
/**
* Create a Shape
object depending on its type
@@ -24,27 +28,53 @@ import org.apache.poi.ddf.*;
* @author Yegor Kozlov
*/
public class ShapeFactory {
+ // For logging
+ protected static POILogger logger = POILogFactory.getLogger(ShapeFactory.class);
/**
* Create a new shape from the data provided.
*/
public static Shape createShape(EscherContainerRecord spContainer, Shape parent){
if (spContainer.getRecordId() == EscherContainerRecord.SPGR_CONTAINER){
- return new ShapeGroup(spContainer, parent);
+ return createShapeGroup(spContainer, parent);
+ } else {
+ return createSimpeShape(spContainer, parent);
+
+ }
+ }
+
+ public static ShapeGroup createShapeGroup(EscherContainerRecord spContainer, Shape parent){
+ ShapeGroup group = null;
+ UnknownEscherRecord opt = (UnknownEscherRecord)Shape.getEscherChild((EscherContainerRecord)spContainer.getChild(0), (short)0xF122);
+ if(opt != null){
+ try {
+ EscherPropertyFactory f = new EscherPropertyFactory();
+ List props = f.createProperties( opt.getData(), 0, opt.getInstance() );
+ EscherSimpleProperty p = (EscherSimpleProperty)props.get(0);
+ if(p.getPropertyNumber() == 0x39F && p.getPropertyValue() == 1){
+ group = new ShapeGroup(spContainer, parent);
+ } else {
+ group = new ShapeGroup(spContainer, parent);
+ }
+ } catch (Exception e){
+ logger.log(POILogger.WARN, e.getMessage());
+ group = new ShapeGroup(spContainer, parent);
+ }
+ } else {
+ group = new ShapeGroup(spContainer, parent);
}
+ return group;
+ }
+
+ public static Shape createSimpeShape(EscherContainerRecord spContainer, Shape parent){
Shape shape;
EscherSpRecord spRecord = spContainer.getChildById(EscherSpRecord.RECORD_ID);
int type = spRecord.getOptions() >> 4;
switch (type){
case ShapeTypes.TextBox:
- case ShapeTypes.Rectangle:
- EscherTextboxRecord txtbox = (EscherTextboxRecord)Shape.getEscherChild(spContainer, EscherTextboxRecord.RECORD_ID);
- if (txtbox == null)
- shape = new AutoShape(spContainer, parent);
- else
- shape = new TextBox(spContainer, parent);
+ shape = new TextBox(spContainer, parent);
break;
case ShapeTypes.PictureFrame:
shape = new Picture(spContainer, parent);
@@ -53,16 +83,21 @@ public class ShapeFactory {
shape = new Line(spContainer, parent);
break;
case ShapeTypes.NotPrimitive:
- if ((spRecord.getFlags() & EscherSpRecord.FLAG_GROUP) != 0)
- shape = new ShapeGroup(spContainer, parent);
- else
+ EscherOptRecord opt = (EscherOptRecord)Shape.getEscherChild(spContainer, EscherOptRecord.RECORD_ID);
+ EscherProperty prop = Shape.getEscherProperty(opt, EscherProperties.GEOMETRY__VERTICES);
+ if(prop != null)
+ shape = new Freeform(spContainer, parent);
+ else {
+
+ logger.log(POILogger.WARN, "Creating AutoShape for a NotPrimitive shape");
shape = new AutoShape(spContainer, parent);
+ }
break;
default:
shape = new AutoShape(spContainer, parent);
break;
}
return shape;
- }
+ }
}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java b/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java
index dbcc8069c2..b22ed8d70b 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java
@@ -19,6 +19,7 @@ package org.apache.poi.hslf.model;
import org.apache.poi.ddf.*;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.POILogger;
+import org.apache.poi.hslf.record.EscherTextboxWrapper;
import java.util.ArrayList;
import java.util.List;
@@ -154,9 +155,10 @@ public class ShapeGroup extends Shape{
shape.setSheet(sheet);
shape.afterInsert(sheet);
- if(shape instanceof TextBox) {
- TextBox tbox = (TextBox)shape;
- getSheet().getPPDrawing().addTextboxWrapper(tbox._txtbox);
+ if (shape instanceof TextShape) {
+ TextShape tbox = (TextShape) shape;
+ EscherTextboxWrapper txWrapper = tbox.getEscherTextboxWrapper();
+ if(txWrapper != null) getSheet().getPPDrawing().addTextboxWrapper(txWrapper);
}
}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java b/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java
index 135b625f1d..abf2fec589 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java
@@ -257,11 +257,12 @@ public abstract class Sheet {
shape.setSheet(this);
shape.afterInsert(this);
- // If it's a TextBox, we need to tell the PPDrawing, as it has to
+ // If it's a TextShape, we need to tell the PPDrawing, as it has to
// track TextboxWrappers specially
- if (shape instanceof TextBox) {
- TextBox tbox = (TextBox) shape;
- ppdrawing.addTextboxWrapper(tbox._txtbox);
+ if (shape instanceof TextShape) {
+ TextShape tbox = (TextShape) shape;
+ EscherTextboxWrapper txWrapper = tbox.getEscherTextboxWrapper();
+ if(txWrapper != null) ppdrawing.addTextboxWrapper(txWrapper);
}
}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java
index 85d672fe89..0831d453b5 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java
@@ -48,19 +48,19 @@ public class SimpleShape extends Shape {
* @return the record container which holds this shape
*/
protected EscherContainerRecord createSpContainer(boolean isChild) {
- EscherContainerRecord spContainer = new EscherContainerRecord();
- spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER );
- spContainer.setOptions((short)15);
+ _escherContainer = new EscherContainerRecord();
+ _escherContainer.setRecordId( EscherContainerRecord.SP_CONTAINER );
+ _escherContainer.setOptions((short)15);
EscherSpRecord sp = new EscherSpRecord();
int flags = EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE;
if (isChild) flags |= EscherSpRecord.FLAG_CHILD;
sp.setFlags(flags);
- spContainer.addChildRecord(sp);
+ _escherContainer.addChildRecord(sp);
EscherOptRecord opt = new EscherOptRecord();
opt.setRecordId(EscherOptRecord.RECORD_ID);
- spContainer.addChildRecord(opt);
+ _escherContainer.addChildRecord(opt);
EscherRecord anchor;
if(isChild) anchor = new EscherChildAnchorRecord();
@@ -75,9 +75,9 @@ public class SimpleShape extends Shape {
LittleEndian.putInt(header, 4, 8);
anchor.fillFields(header, 0, null);
}
- spContainer.addChildRecord(anchor);
+ _escherContainer.addChildRecord(anchor);
- return spContainer;
+ return _escherContainer;
}
/**
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Table.java b/src/scratchpad/src/org/apache/poi/hslf/model/Table.java
index a9f21b54f3..947c41af63 100755
--- a/src/scratchpad/src/org/apache/poi/hslf/model/Table.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/Table.java
@@ -20,10 +20,10 @@ package org.apache.poi.hslf.model;
import org.apache.poi.ddf.*;
import org.apache.poi.util.LittleEndian;
-import java.util.ArrayList;
+import java.util.*;
import java.util.List;
-import java.util.Iterator;
import java.awt.*;
+import java.awt.geom.Rectangle2D;
/**
* Represents a table in a PowerPoint presentation
@@ -144,6 +144,54 @@ public class Table extends ShapeGroup {
}
+ protected void initTable(){
+ Shape[] sh = getShapes();
+ Arrays.sort(sh, new Comparator(){
+ public int compare( Object o1, Object o2 ) {
+ Rectangle anchor1 = ((Shape)o1).getAnchor();
+ Rectangle anchor2 = ((Shape)o2).getAnchor();
+ int delta = anchor1.y - anchor2.y;
+ if(delta == 0) delta = anchor1.x - anchor2.y;
+ return delta;
+ }
+ });
+ int y0 = -1;
+ int maxrowlen = 0;
+ ArrayList lst = new ArrayList();
+ ArrayList row = null;
+ for (int i = 0; i < sh.length; i++) {
+ if(sh[i] instanceof TextShape){
+ Rectangle anchor = sh[i].getAnchor();
+ if(anchor.y != y0){
+ y0 = anchor.y;
+ if(row != null) maxrowlen = Math.max(maxrowlen, row.size());
+ row = new ArrayList();
+ lst.add(row);
+ }
+ row.add(sh[i]);
+ }
+ }
+ cells = new TableCell[lst.size()][maxrowlen];
+ for (int i = 0; i < lst.size(); i++) {
+ row = (ArrayList)lst.get(i);
+ for (int j = 0; j < row.size(); j++) {
+ TextShape tx = (TextShape)row.get(j);
+ cells[i][j] = new TableCell(tx.getSpContainer(), getParent());
+ cells[i][j].setSheet(tx.getSheet());
+ }
+ }
+ }
+
+ /**
+ * Assign the SlideShow
this shape belongs to
+ *
+ * @param sheet owner of this shape
+ */
+ public void setSheet(Sheet sheet){
+ super.setSheet(sheet);
+ if(cells == null) initTable();
+ }
+
/**
* Sets the row height.
*
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/TableCell.java b/src/scratchpad/src/org/apache/poi/hslf/model/TableCell.java
index bb93e06b71..36789ad91a 100755
--- a/src/scratchpad/src/org/apache/poi/hslf/model/TableCell.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/TableCell.java
@@ -63,15 +63,15 @@ public class TableCell extends TextBox {
}
protected EscherContainerRecord createSpContainer(boolean isChild){
- EscherContainerRecord spContainer = super.createSpContainer(isChild);
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(spContainer, EscherOptRecord.RECORD_ID);
+ _escherContainer = super.createSpContainer(isChild);
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
setEscherProperty(opt, EscherProperties.TEXT__TEXTID, 0);
setEscherProperty(opt, EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 0x20000);
setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, 0x150001);
setEscherProperty(opt, EscherProperties.SHADOWSTYLE__SHADOWOBSURED, 0x20000);
setEscherProperty(opt, EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x40000);
- return spContainer;
+ return _escherContainer;
}
protected void anchorBorder(int type, Line line){
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java b/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java
index 1f9a489a78..a1d45ffbae 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java
@@ -38,55 +38,7 @@ import java.io.IOException;
*
* @author Yegor Kozlov
*/
-public class TextBox extends SimpleShape {
-
- /**
- * How to anchor the text
- */
- public static final int AnchorTop = 0;
- public static final int AnchorMiddle = 1;
- public static final int AnchorBottom = 2;
- public static final int AnchorTopCentered = 3;
- public static final int AnchorMiddleCentered = 4;
- public static final int AnchorBottomCentered = 5;
- public static final int AnchorTopBaseline = 6;
- public static final int AnchorBottomBaseline = 7;
- public static final int AnchorTopCenteredBaseline = 8;
- public static final int AnchorBottomCenteredBaseline = 9;
-
- /**
- * How to wrap the text
- */
- public static final int WrapSquare = 0;
- public static final int WrapByPoints = 1;
- public static final int WrapNone = 2;
- public static final int WrapTopBottom = 3;
- public static final int WrapThrough = 4;
-
- /**
- * How to align the text
- */
- public static final int AlignLeft = 0;
- public static final int AlignCenter = 1;
- public static final int AlignRight = 2;
- public static final int AlignJustify = 3;
-
- /**
- * Low-level object which holds actual text and format data
- */
- protected TextRun _txtrun;
-
- /**
- * Escher container which holds text attributes such as
- * TextHeaderAtom, TextBytesAtom ot TextCharsAtom, StyleTextPropAtom etc.
- */
- protected EscherTextboxWrapper _txtbox;
-
- /**
- * Is the TextBox missing the text records which actually
- * store the text?
- */
- private boolean _missingTextRecords = false;
+public class TextBox extends TextShape {
/**
* Create a TextBox object and initialize it from the supplied Record container.
@@ -97,8 +49,6 @@ public class TextBox extends SimpleShape {
protected TextBox(EscherContainerRecord escherRecord, Shape parent){
super(escherRecord, parent);
- EscherTextboxRecord textbox = (EscherTextboxRecord)Shape.getEscherChild(_escherContainer, EscherTextboxRecord.RECORD_ID);
- _txtbox = new EscherTextboxWrapper(textbox);
}
/**
@@ -108,8 +58,7 @@ public class TextBox extends SimpleShape {
* in a table then the parent is Table.
*/
public TextBox(Shape parent){
- super(null, parent);
- _escherContainer = createSpContainer(parent instanceof ShapeGroup);
+ super(parent);
}
/**
@@ -121,376 +70,31 @@ public class TextBox extends SimpleShape {
}
/**
- * Create a new textBox and initialize internal structures
+ * Create a new TextBox and initialize its internal structures
*
* @return the created EscherContainerRecord
which holds shape data
*/
protected EscherContainerRecord createSpContainer(boolean isChild){
- EscherContainerRecord spcont = super.createSpContainer(isChild);
+ _escherContainer = super.createSpContainer(isChild);
- EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID);
- short type = (ShapeTypes.TextBox << 4) | 0x2;
- spRecord.setOptions(type);
+ setShapeType(ShapeTypes.TextBox);
- //set default properties for a textbox
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(spcont, EscherOptRecord.RECORD_ID);
- setEscherProperty(opt, EscherProperties.TEXT__TEXTID, 0);
+ //set default properties for a TextBox
+ setEscherProperty(EscherProperties.FILL__FILLCOLOR, 0x8000004);
+ setEscherProperty(EscherProperties.FILL__FILLBACKCOLOR, 0x8000000);
+ setEscherProperty(EscherProperties.FILL__NOFILLHITTEST, 0x100000);
+ setEscherProperty(EscherProperties.LINESTYLE__COLOR, 0x8000001);
+ setEscherProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x80000);
+ setEscherProperty(EscherProperties.SHADOWSTYLE__COLOR, 0x8000002);
- setEscherProperty(opt, EscherProperties.FILL__FILLCOLOR, 0x8000004);
- setEscherProperty(opt, EscherProperties.FILL__FILLBACKCOLOR, 0x8000000);
- setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, 0x100000);
- setEscherProperty(opt, EscherProperties.LINESTYLE__COLOR, 0x8000001);
- setEscherProperty(opt, EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x80000);
- setEscherProperty(opt, EscherProperties.SHADOWSTYLE__COLOR, 0x8000002);
+ _txtrun = createTextRun();
- //create EscherTextboxWrapper
- _txtbox = new EscherTextboxWrapper();
-
- TextHeaderAtom tha = new TextHeaderAtom();
- tha.setParentRecord(_txtbox); // TextHeaderAtom is parent aware
- _txtbox.appendChildRecord(tha);
-
- TextCharsAtom tca = new TextCharsAtom();
- _txtbox.appendChildRecord(tca);
-
- StyleTextPropAtom sta = new StyleTextPropAtom(0);
- _txtbox.appendChildRecord(sta);
-
- _txtrun = new TextRun(tha,tca,sta);
- _txtrun.setText("");
- spcont.addChildRecord(_txtbox.getEscherRecord());
-
- return spcont;
+ return _escherContainer;
}
- /**
- * Returns the text contained in this text frame.
- *
- * @return the text string for this textbox.
- */
- public String getText(){
- return _txtrun == null ? null : _txtrun.getText();
+ protected void setDefaultTextProperties(TextRun _txtrun){
+ setVerticalAlignment(TextBox.AnchorTop);
+ setEscherProperty(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 0x20002);
}
- /**
- * Sets the text contained in this text frame.
- *
- * @param text the text string used by this object.
- */
- public void setText(String text){
- _txtrun.setText(text);
- }
-
- /**
- * When a textbox is added to a sheet we need to tell upper-level
- * PPDrawing
about it.
- *
- * @param sh the sheet we are adding to
- */
- protected void afterInsert(Sheet sh){
- PPDrawing ppdrawing = sh.getPPDrawing();
- ppdrawing.addTextboxWrapper(_txtbox);
- // Ensure the escher layer knows about the added records
- try {
- _txtbox.writeOut(null);
- } catch (IOException e){
- throw new HSLFException(e);
- }
- if(getAnchor().equals(new java.awt.Rectangle()) && !"".equals(getText())) resizeToFitText();
- }
-
- /**
- * Adjust the size of the TextBox so it encompasses the text inside it.
- */
- public void resizeToFitText(){
- try{
- FontRenderContext frc = new FontRenderContext(null, true, true);
- RichTextRun rt = _txtrun.getRichTextRuns()[0];
- int size = rt.getFontSize();
- int style = 0;
- if (rt.isBold()) style |= Font.BOLD;
- if (rt.isItalic()) style |= Font.ITALIC;
- String fntname = rt.getFontName();
- Font font = new Font(fntname, style, size);
-
- TextLayout layout = new TextLayout(getText(), font, frc);
- int width = Math.round(layout.getAdvance());
- int height = Math.round(layout.getAscent());
-
- Dimension txsize = new Dimension(width, height);
- java.awt.Rectangle anchor = getAnchor();
- anchor.setSize(txsize);
- setAnchor(anchor);
- } catch (Exception e){
- e.printStackTrace();
-
- }
- }
-
- /**
- * Returns the type of vertical alignment for the text.
- * One of the Anchor*
constants defined in this class.
- *
- * @return the type of alignment
- */
- public int getVerticalAlignment(){
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
- EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__ANCHORTEXT);
- int valign;
- if (prop == null){
- int type = getTextRun().getRunType();
- switch (type){
- case TextHeaderAtom.TITLE_TYPE:
- case TextHeaderAtom.CENTER_TITLE_TYPE:
- valign = TextBox.AnchorMiddle;
- break;
- default:
- valign = TextBox.AnchorTop;
- break;
- }
- } else {
- valign = prop.getPropertyValue();
- }
- return valign;
- }
-
- /**
- * Sets the type of vertical alignment for the text.
- * One of the Anchor*
constants defined in this class.
- *
- * @param align - the type of alignment
- */
- public void setVerticalAlignment(int align){
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
- setEscherProperty(opt, EscherProperties.TEXT__ANCHORTEXT, align);
- }
-
- public void setHorizontalAlignment(int align){
- _txtrun.getRichTextRuns()[0].setAlignment(align);
- }
- public int getHorizontalAlignment(){
- return _txtrun.getRichTextRuns()[0].getAlignment();
- }
-
- /**
- * Returns the distance (in points) between the bottom of the text frame
- * and the bottom of the inscribed rectangle of the shape that contains the text.
- * Default value is 1/20 inch.
- *
- * @return the botom margin
- */
- public int getMarginBottom(){
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
- EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM);
- int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue();
- return val/EMU_PER_POINT;
- }
-
- /**
- * Sets the botom margin.
- * @see #getMarginBottom()
- *
- * @param margin the bottom margin
- */
- public void setMarginBottom(int margin){
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
- setEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM, margin*EMU_PER_POINT);
- }
-
- /**
- * Returns the distance (in EMUs) between the left edge of the text frame
- * and the left edge of the inscribed rectangle of the shape that contains
- * the text.
- * Default value is 1/10 inch.
- *
- * @return the left margin
- */
- public int getMarginLeft(){
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
- EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM);
- int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue();
- return val/EMU_PER_POINT;
- }
-
- /**
- * Sets the left margin.
- * @see #getMarginLeft()
- *
- * @param margin the left margin
- */
- public void setMarginLeft(int margin){
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
- setEscherProperty(opt, EscherProperties.TEXT__TEXTLEFT, margin*EMU_PER_POINT);
- }
-
- /**
- * Returns the distance (in EMUs) between the right edge of the
- * text frame and the right edge of the inscribed rectangle of the shape
- * that contains the text.
- * Default value is 1/10 inch.
- *
- * @return the right margin
- */
- public int getMarginRight(){
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
- EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTRIGHT);
- int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue();
- return val/EMU_PER_POINT;
- }
-
- /**
- * Sets the right margin.
- * @see #getMarginRight()
- *
- * @param margin the right margin
- */
- public void setMarginRight(int margin){
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
- setEscherProperty(opt, EscherProperties.TEXT__TEXTRIGHT, margin*EMU_PER_POINT);
- }
-
- /**
- * Returns the distance (in EMUs) between the top of the text frame
- * and the top of the inscribed rectangle of the shape that contains the text.
- * Default value is 1/20 inch.
- *
- * @return the top margin
- */
- public int getMarginTop(){
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
- EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTTOP);
- int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue();
- return val/EMU_PER_POINT;
- }
-
- /**
- * Sets the top margin.
- * @see #getMarginTop()
- *
- * @param margin the top margin
- */
- public void setMarginTop(int margin){
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
- setEscherProperty(opt, EscherProperties.TEXT__TEXTTOP, margin*EMU_PER_POINT);
- }
-
-
- /**
- * Returns the value indicating word wrap.
- * One of the Wrap*
constants defined in this class.
- *
- * @return the value indicating word wrap
- */
- public int getWordWrap(){
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
- EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__WRAPTEXT);
- return prop == null ? WrapSquare : prop.getPropertyValue();
- }
-
- /**
- * Specifies how the text should be wrapped
- *
- * @param wrap the value indicating how the text should be wrapped
- */
- public void setWordWrap(int wrap){
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
- setEscherProperty(opt, EscherProperties.TEXT__WRAPTEXT, wrap);
- }
-
- /**
- * @return id for the text.
- */
- public int getTextId(){
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
- EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTID);
- return prop == null ? 0 : prop.getPropertyValue();
- }
-
- /**
- * Sets text ID
- *
- * @param id of the text
- */
- public void setTextId(int id){
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
- setEscherProperty(opt, EscherProperties.TEXT__TEXTID, id);
- }
-
- /**
- * The color used to fill this shape.
- *
- * @param color the background color
- */
- public void setBackgroundColor(Color color){
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
- int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB();
- setEscherProperty(opt, EscherProperties.FILL__FILLBACKCOLOR, rgb);
- }
-
- /**
- * @return the TextRun object for this text box
- */
- public TextRun getTextRun(){
- return _txtrun;
- }
-
- public void setSheet(Sheet sheet){
- _sheet = sheet;
-
- // Initialize _txtrun object.
- // (We can't do it in the constructor because the sheet
- // is not assigned then, it's only built once we have
- // all the records)
- if(_txtrun == null) initTextRun();
- if(_txtrun == null) {
- // No text records found, skip
- _missingTextRecords = true;
- return;
- } else {
- _missingTextRecords = false;
- }
-
- // Supply the sheet to our child RichTextRuns
- _txtrun.setSheet(sheet);
- RichTextRun[] rt = _txtrun.getRichTextRuns();
- for (int i = 0; i < rt.length; i++) {
- rt[i].supplySlideShow(_sheet.getSlideShow());
- }
- }
-
- private void initTextRun(){
- OutlineTextRefAtom ota = null;
-
- // Find the interesting child records
- Record[] child = _txtbox.getChildRecords();
- for (int i = 0; i < child.length; i++) {
- if (child[i] instanceof OutlineTextRefAtom) {
- ota = (OutlineTextRefAtom)child[i];
- break;
- }
- }
-
- Sheet sheet = getSheet();
- TextRun[] runs = sheet.getTextRuns();
- if (ota != null) {
- int idx = ota.getTextIndex();
- for (int i = 0; i < runs.length; i++) {
- if(runs[i].getIndex() == idx){
- _txtrun = runs[i];
- }
- }
- if(_txtrun == null) {
- logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx);
- }
- } else {
- int shapeId = _escherContainer.getChildById(EscherSpRecord.RECORD_ID).getShapeId();
- if(runs != null) for (int i = 0; i < runs.length; i++) {
- if(runs[i].getShapeId() == shapeId){
- _txtrun = runs[i];
- break;
- }
- }
- }
-
- }
}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java b/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java
index 586932e739..5834e2eaec 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java
@@ -24,12 +24,7 @@ import java.util.LinkedList;
import java.util.Vector;
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
-import org.apache.poi.hslf.record.Record;
-import org.apache.poi.hslf.record.RecordContainer;
-import org.apache.poi.hslf.record.StyleTextPropAtom;
-import org.apache.poi.hslf.record.TextBytesAtom;
-import org.apache.poi.hslf.record.TextCharsAtom;
-import org.apache.poi.hslf.record.TextHeaderAtom;
+import org.apache.poi.hslf.record.*;
import org.apache.poi.hslf.usermodel.RichTextRun;
import org.apache.poi.hslf.usermodel.SlideShow;
import org.apache.poi.util.StringUtil;
@@ -50,6 +45,7 @@ public class TextRun
protected TextBytesAtom _byteAtom;
protected TextCharsAtom _charAtom;
protected StyleTextPropAtom _styleAtom;
+ protected TextSpecInfoAtom _specAtom;
protected boolean _isUnicode;
protected RichTextRun[] _rtRuns;
private SlideShow slideShow;
@@ -477,6 +473,18 @@ public class TextRun
// Recreate rich text run with no styling
_rtRuns[0] = new RichTextRun(this,0,s.length());
}
+
+ /**
+ * If TextSpecInfoAtom is present, we must update the text size,
+ * otherwise the ppt will be corrupted
+ */
+ if(_records != null) for (int i = 0; i < _records.length; i++) {
+ if(_records[i] instanceof TextSpecInfoAtom){
+ TextSpecInfoAtom specAtom = (TextSpecInfoAtom)_records[i];
+ specAtom.setTextSize(s.length());
+ }
+
+ }
}
/**
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java
new file mode 100755
index 0000000000..3c45b34b0b
--- /dev/null
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java
@@ -0,0 +1,516 @@
+
+/* ====================================================================
+ 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.hslf.model;
+
+import org.apache.poi.ddf.*;
+import org.apache.poi.hslf.record.*;
+import org.apache.poi.hslf.usermodel.RichTextRun;
+import org.apache.poi.hslf.exceptions.HSLFException;
+import org.apache.poi.util.POILogger;
+
+import java.awt.*;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.AffineTransform;
+import java.awt.font.FontRenderContext;
+import java.awt.font.TextLayout;
+import java.io.IOException;
+
+/**
+ * A common superclass of all shapes that can hold text.
+ *
+ * @author Yegor Kozlov
+ */
+public abstract class TextShape extends SimpleShape {
+
+ /**
+ * How to anchor the text
+ */
+ public static final int AnchorTop = 0;
+ public static final int AnchorMiddle = 1;
+ public static final int AnchorBottom = 2;
+ public static final int AnchorTopCentered = 3;
+ public static final int AnchorMiddleCentered = 4;
+ public static final int AnchorBottomCentered = 5;
+ public static final int AnchorTopBaseline = 6;
+ public static final int AnchorBottomBaseline = 7;
+ public static final int AnchorTopCenteredBaseline = 8;
+ public static final int AnchorBottomCenteredBaseline = 9;
+
+ /**
+ * How to wrap the text
+ */
+ public static final int WrapSquare = 0;
+ public static final int WrapByPoints = 1;
+ public static final int WrapNone = 2;
+ public static final int WrapTopBottom = 3;
+ public static final int WrapThrough = 4;
+
+ /**
+ * How to align the text
+ */
+ public static final int AlignLeft = 0;
+ public static final int AlignCenter = 1;
+ public static final int AlignRight = 2;
+ public static final int AlignJustify = 3;
+
+ /**
+ * TextRun object which holds actual text and format data
+ */
+ protected TextRun _txtrun;
+
+ /**
+ * Escher container which holds text attributes such as
+ * TextHeaderAtom, TextBytesAtom ot TextCharsAtom, StyleTextPropAtom etc.
+ */
+ protected EscherTextboxWrapper _txtbox;
+
+ /**
+ * Used to calculate text bounds
+ */
+ protected static final FontRenderContext _frc = new FontRenderContext(null, true, true);
+
+ /**
+ * Create a TextBox object and initialize it from the supplied Record container.
+ *
+ * @param escherRecord EscherSpContainer
container which holds information about this shape
+ * @param parent the parent of the shape
+ */
+ protected TextShape(EscherContainerRecord escherRecord, Shape parent){
+ super(escherRecord, parent);
+
+ }
+
+ /**
+ * Create a new TextBox. This constructor is used when a new shape is created.
+ *
+ * @param parent the parent of this Shape. For example, if this text box is a cell
+ * in a table then the parent is Table.
+ */
+ public TextShape(Shape parent){
+ super(null, parent);
+ _escherContainer = createSpContainer(parent instanceof ShapeGroup);
+ }
+
+ /**
+ * Create a new TextBox. This constructor is used when a new shape is created.
+ *
+ */
+ public TextShape(){
+ this(null);
+ }
+
+ public TextRun createTextRun(){
+ _txtbox = getEscherTextboxWrapper();
+ if(_txtbox == null) _txtbox = new EscherTextboxWrapper();
+
+ _txtrun = getTextRun();
+ if(_txtrun == null){
+ TextHeaderAtom tha = new TextHeaderAtom();
+ tha.setParentRecord(_txtbox);
+ _txtbox.appendChildRecord(tha);
+
+ TextCharsAtom tca = new TextCharsAtom();
+ _txtbox.appendChildRecord(tca);
+
+ StyleTextPropAtom sta = new StyleTextPropAtom(0);
+ _txtbox.appendChildRecord(sta);
+
+ _txtrun = new TextRun(tha,tca,sta);
+ _txtrun.setText("");
+
+ _escherContainer.addChildRecord(_txtbox.getEscherRecord());
+
+ setDefaultTextProperties(_txtrun);
+ }
+
+ return _txtrun;
+ }
+
+ /**
+ * Set default properties for the TextRun.
+ * Depending on the text and shape type the defaults are different:
+ * TextBox: align=left, valign=top
+ * AutoShape: align=center, valign=middle
+ *
+ */
+ protected void setDefaultTextProperties(TextRun _txtrun){
+
+ }
+
+ /**
+ * Returns the text contained in this text frame.
+ *
+ * @return the text string for this textbox.
+ */
+ public String getText(){
+ TextRun tx = getTextRun();
+ return tx == null ? null : tx.getText();
+ }
+
+ /**
+ * Sets the text contained in this text frame.
+ *
+ * @param text the text string used by this object.
+ */
+ public void setText(String text){
+ TextRun tx = getTextRun();
+ if(tx == null){
+ tx = createTextRun();
+ }
+ tx.setText(text);
+ setTextId(text.hashCode());
+ }
+
+ /**
+ * When a textbox is added to a sheet we need to tell upper-level
+ * PPDrawing
about it.
+ *
+ * @param sh the sheet we are adding to
+ */
+ protected void afterInsert(Sheet sh){
+ EscherTextboxWrapper _txtbox = getEscherTextboxWrapper();
+ if(_txtbox != null){
+ PPDrawing ppdrawing = sh.getPPDrawing();
+ ppdrawing.addTextboxWrapper(_txtbox);
+ // Ensure the escher layer knows about the added records
+ try {
+ _txtbox.writeOut(null);
+ } catch (IOException e){
+ throw new HSLFException(e);
+ }
+ if(getAnchor().equals(new Rectangle()) && !"".equals(getText())) resizeToFitText();
+ }
+ }
+
+ protected EscherTextboxWrapper getEscherTextboxWrapper(){
+ if(_txtbox == null){
+ EscherTextboxRecord textRecord = (EscherTextboxRecord)Shape.getEscherChild(_escherContainer, EscherTextboxRecord.RECORD_ID);
+ if(textRecord != null) _txtbox = new EscherTextboxWrapper(textRecord);
+ }
+ return _txtbox;
+ }
+ /**
+ * Adjust the size of the TextShape so it encompasses the text inside it.
+ *
+ * @return a Rectangle2D
that is the bounds of this TextShape
.
+ */
+ public Rectangle2D resizeToFitText(){
+ String txt = getText();
+ if(txt == null || txt.length() == 0) return new Rectangle2D.Float();
+
+ RichTextRun rt = getTextRun().getRichTextRuns()[0];
+ int size = rt.getFontSize();
+ int style = 0;
+ if (rt.isBold()) style |= Font.BOLD;
+ if (rt.isItalic()) style |= Font.ITALIC;
+ String fntname = rt.getFontName();
+ Font font = new Font(fntname, style, size);
+
+ float width = 0, height = 0;
+ String[] lines = txt.split("\r");
+ for (int i = 0; i < lines.length; i++) {
+ if(lines[i].length() == 0) continue;
+
+ TextLayout layout = new TextLayout(lines[i], font, _frc);
+
+ width = Math.max(width, layout.getAdvance());
+
+ /**
+ * Even if top and bottom margins are set to 0 PowerPoint
+ * always sets extra space between the text and its bounding box.
+ *
+ * The approximation height = ascent*2 works good enough in most cases
+ */
+ height = Math.max(height, 2*layout.getAscent());
+ }
+
+ width += getMarginLeft() + getMarginRight();
+ height += getMarginTop() + getMarginBottom();
+
+ Rectangle2D anchor = getAnchor2D();
+ anchor.setRect(anchor.getX(), anchor.getY(), width, height);
+ setAnchor(anchor);
+
+ return anchor;
+ }
+
+ /**
+ * Returns the type of vertical alignment for the text.
+ * One of the Anchor*
constants defined in this class.
+ *
+ * @return the type of alignment
+ */
+ public int getVerticalAlignment(){
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+ EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__ANCHORTEXT);
+ int valign;
+ if (prop == null){
+ int type = getTextRun().getRunType();
+ switch (type){
+ case TextHeaderAtom.TITLE_TYPE:
+ case TextHeaderAtom.CENTER_TITLE_TYPE:
+ valign = TextShape.AnchorMiddle;
+ break;
+ default:
+ valign = TextShape.AnchorTop;
+ break;
+ }
+ } else {
+ valign = prop.getPropertyValue();
+ }
+ return valign;
+ }
+
+ /**
+ * Sets the type of vertical alignment for the text.
+ * One of the Anchor*
constants defined in this class.
+ *
+ * @param align - the type of alignment
+ */
+ public void setVerticalAlignment(int align){
+ setEscherProperty(EscherProperties.TEXT__ANCHORTEXT, align);
+ }
+
+ /**
+ * Sets the type of horizontal alignment for the text.
+ * One of the Align*
constants defined in this class.
+ *
+ * @param align - the type of horizontal alignment
+ */
+ public void setHorizontalAlignment(int align){
+ TextRun tx = getTextRun();
+ if(tx != null) tx.getRichTextRuns()[0].setAlignment(align);
+ }
+
+ /**
+ * Gets the type of horizontal alignment for the text.
+ * One of the Align*
constants defined in this class.
+ *
+ * @return align - the type of horizontal alignment
+ */
+ public int getHorizontalAlignment(){
+ TextRun tx = getTextRun();
+ return tx == null ? -1 : tx.getRichTextRuns()[0].getAlignment();
+ }
+
+ /**
+ * Returns the distance (in points) between the bottom of the text frame
+ * and the bottom of the inscribed rectangle of the shape that contains the text.
+ * Default value is 1/20 inch.
+ *
+ * @return the botom margin
+ */
+ public float getMarginBottom(){
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+ EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM);
+ int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue();
+ return (float)val/EMU_PER_POINT;
+ }
+
+ /**
+ * Sets the botom margin.
+ * @see #getMarginBottom()
+ *
+ * @param margin the bottom margin
+ */
+ public void setMarginBottom(float margin){
+ setEscherProperty(EscherProperties.TEXT__TEXTBOTTOM, (int)(margin*EMU_PER_POINT));
+ }
+
+ /**
+ * Returns the distance (in points) between the left edge of the text frame
+ * and the left edge of the inscribed rectangle of the shape that contains
+ * the text.
+ * Default value is 1/10 inch.
+ *
+ * @return the left margin
+ */
+ public float getMarginLeft(){
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+ EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM);
+ int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue();
+ return (float)val/EMU_PER_POINT;
+ }
+
+ /**
+ * Sets the left margin.
+ * @see #getMarginLeft()
+ *
+ * @param margin the left margin
+ */
+ public void setMarginLeft(float margin){
+ setEscherProperty(EscherProperties.TEXT__TEXTLEFT, (int)(margin*EMU_PER_POINT));
+ }
+
+ /**
+ * Returns the distance (in points) between the right edge of the
+ * text frame and the right edge of the inscribed rectangle of the shape
+ * that contains the text.
+ * Default value is 1/10 inch.
+ *
+ * @return the right margin
+ */
+ public float getMarginRight(){
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+ EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTRIGHT);
+ int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue();
+ return (float)val/EMU_PER_POINT;
+ }
+
+ /**
+ * Sets the right margin.
+ * @see #getMarginRight()
+ *
+ * @param margin the right margin
+ */
+ public void setMarginRight(float margin){
+ setEscherProperty(EscherProperties.TEXT__TEXTRIGHT, (int)(margin*EMU_PER_POINT));
+ }
+
+ /**
+ * Returns the distance (in points) between the top of the text frame
+ * and the top of the inscribed rectangle of the shape that contains the text.
+ * Default value is 1/20 inch.
+ *
+ * @return the top margin
+ */
+ public float getMarginTop(){
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+ EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTTOP);
+ int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue();
+ return (float)val/EMU_PER_POINT;
+ }
+
+ /**
+ * Sets the top margin.
+ * @see #getMarginTop()
+ *
+ * @param margin the top margin
+ */
+ public void setMarginTop(float margin){
+ setEscherProperty(EscherProperties.TEXT__TEXTTOP, (int)(margin*EMU_PER_POINT));
+ }
+
+
+ /**
+ * Returns the value indicating word wrap.
+ *
+ * @return the value indicating word wrap.
+ * Must be one of the Wrap*
constants defined in this class.
+ */
+ public int getWordWrap(){
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+ EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__WRAPTEXT);
+ return prop == null ? WrapSquare : prop.getPropertyValue();
+ }
+
+ /**
+ * Specifies how the text should be wrapped
+ *
+ * @param wrap the value indicating how the text should be wrapped.
+ * Must be one of the Wrap*
constants defined in this class.
+ */
+ public void setWordWrap(int wrap){
+ setEscherProperty(EscherProperties.TEXT__WRAPTEXT, wrap);
+ }
+
+ /**
+ * @return id for the text.
+ */
+ public int getTextId(){
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+ EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTID);
+ return prop == null ? 0 : prop.getPropertyValue();
+ }
+
+ /**
+ * Sets text ID
+ *
+ * @param id of the text
+ */
+ public void setTextId(int id){
+ setEscherProperty(EscherProperties.TEXT__TEXTID, id);
+ }
+
+ /**
+ * @return the TextRun object for this text box
+ */
+ public TextRun getTextRun(){
+ if(_txtrun == null) initTextRun();
+ return _txtrun;
+ }
+
+ public void setSheet(Sheet sheet) {
+ _sheet = sheet;
+
+ // Initialize _txtrun object.
+ // (We can't do it in the constructor because the sheet
+ // is not assigned then, it's only built once we have
+ // all the records)
+ TextRun tx = getTextRun();
+ if (tx != null) {
+ // Supply the sheet to our child RichTextRuns
+ tx.setSheet(_sheet);
+ RichTextRun[] rt = tx.getRichTextRuns();
+ for (int i = 0; i < rt.length; i++) {
+ rt[i].supplySlideShow(_sheet.getSlideShow());
+ }
+ }
+
+ }
+
+ protected void initTextRun(){
+ EscherTextboxWrapper txtbox = getEscherTextboxWrapper();
+ Sheet sheet = getSheet();
+
+ if(sheet == null || txtbox == null) return;
+
+ OutlineTextRefAtom ota = null;
+
+ Record[] child = txtbox.getChildRecords();
+ for (int i = 0; i < child.length; i++) {
+ if (child[i] instanceof OutlineTextRefAtom) {
+ ota = (OutlineTextRefAtom)child[i];
+ break;
+ }
+ }
+
+ TextRun[] runs = _sheet.getTextRuns();
+ if (ota != null) {
+ int idx = ota.getTextIndex();
+ for (int i = 0; i < runs.length; i++) {
+ if(runs[i].getIndex() == idx){
+ _txtrun = runs[i];
+ break;
+ }
+ }
+ if(_txtrun == null) {
+ logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx);
+ }
+ } else {
+ int shapeId = _escherContainer.getChildById(EscherSpRecord.RECORD_ID).getShapeId();
+ if(runs != null) for (int i = 0; i < runs.length; i++) {
+ if(runs[i].getShapeId() == shapeId){
+ _txtrun = runs[i];
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/FontCollection.java b/src/scratchpad/src/org/apache/poi/hslf/record/FontCollection.java
index 521e8468b3..c0d55ac0ee 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/record/FontCollection.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/record/FontCollection.java
@@ -75,16 +75,20 @@ public class FontCollection extends RecordContainer {
* @return zero based index of the font in the collection
*/
public int addFont(String name) {
- for (int i = 0; i < fonts.size(); i++) {
- if(fonts.get(i).equals(name)){
- //if the font is already present return its index
- return i;
- }
- }
+ int idx = getFontIndex(name);
+ if(idx != -1) return idx;
+ return addFont(name, 0, 0, 4, 34);
+ }
+
+ public int addFont(String name, int charset, int flags, int type, int pitch) {
FontEntityAtom fnt = new FontEntityAtom();
fnt.setFontIndex(fonts.size() << 4);
fnt.setFontName(name);
+ fnt.setCharSet(charset);
+ fnt.setFontFlags(flags);
+ fnt.setFontType(type);
+ fnt.setPitchAndFamily(pitch);
fonts.add(name);
// Append new child to the end
@@ -92,8 +96,25 @@ public class FontCollection extends RecordContainer {
return fonts.size()-1; //the added font is the last in the list
}
-
- /**
+
+ /**
+ * @return zero based index of the font in the collection or -1 if not found
+ */
+ public int getFontIndex(String name) {
+ for (int i = 0; i < fonts.size(); i++) {
+ if(fonts.get(i).equals(name)){
+ //if the font is already present return its index
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public int getNumberOfFonts() {
+ return fonts.size();
+ }
+
+ /**
* Get the name of the font at the given ID, or null if there is
* no font at that ID.
* @param id
diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/FontEntityAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/FontEntityAtom.java
index e4899bd6e1..76cb4c264b 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/record/FontEntityAtom.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/record/FontEntityAtom.java
@@ -61,7 +61,7 @@ public class FontEntityAtom extends RecordAtom {
/**
* Create a new instance of FontEntityAtom
*/
- protected FontEntityAtom() {
+ public FontEntityAtom() {
_recdata = new byte[68];
_header = new byte[8];
@@ -124,15 +124,100 @@ public class FontEntityAtom extends RecordAtom {
}
}
- protected void setFontIndex(int idx){
+ public void setFontIndex(int idx){
LittleEndian.putShort(_header, 0, (short)idx);
}
- protected int getFontIndex(){
- return LittleEndian.getShort(_header, 0);
+ public int getFontIndex(){
+ return LittleEndian.getShort(_header, 0) >> 4;
}
- /**
+ /**
+ * set the character set
+ *
+ * @param charset - characterset
+ */
+ public void setCharSet(int charset){
+ _recdata[64] = (byte)charset;
+ }
+
+ /**
+ * get the character set
+ *
+ * @return charset - characterset
+ */
+ public int getCharSet(){
+ return _recdata[64];
+ }
+
+ /**
+ * set the font flags
+ * Bit 1: If set, font is subsetted
+ *
+ * @param flags - the font flags
+ */
+ public void setFontFlags(int flags){
+ _recdata[65] = (byte)flags;
+ }
+
+ /**
+ * get the character set
+ * Bit 1: If set, font is subsetted
+ *
+ * @return the font flags
+ */
+ public int getFontFlags(){
+ return _recdata[65];
+ }
+
+ /**
+ * set the font type
+ * + * Bit 1: Raster Font + * Bit 2: Device Font + * Bit 3: TrueType Font + *
+ * + * @param type - the font type + */ + public void setFontType(int type){ + _recdata[66] = (byte)type; + } + + /** + * get the font type + *+ * Bit 1: Raster Font + * Bit 2: Device Font + * Bit 3: TrueType Font + *
+ * + * @return the font type + */ + public int getFontType(){ + return _recdata[66]; + } + + /** + * set lfPitchAndFamily + * + * + * @param val - Corresponds to the lfPitchAndFamily field of the Win32 API LOGFONT structure + */ + public void setPitchAndFamily(int val){ + _recdata[67] = (byte)val; + } + + /** + * get lfPitchAndFamily + * + * @return corresponds to the lfPitchAndFamily field of the Win32 API LOGFONT structure + */ + public int getPitchAndFamily(){ + return _recdata[67]; + } + + /** * Write the contents of the record back, so it can be written to disk */ public void writeOut(OutputStream out) throws IOException { diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java b/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java index 69173bf5bb..a1bc499453 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java @@ -92,7 +92,7 @@ public class RecordTypes { public static final Type TextBookmarkAtom = new Type(4007,null); public static final Type TextBytesAtom = new Type(4008,TextBytesAtom.class); public static final Type TxSIStyleAtom = new Type(4009,null); - public static final Type TextSpecInfoAtom = new Type(4010,null); + public static final Type TextSpecInfoAtom = new Type(4010, TextSpecInfoAtom.class); public static final Type DefaultRulerAtom = new Type(4011,null); public static final Type FontEntityAtom = new Type(4023,FontEntityAtom.class); public static final Type FontEmbeddedData = new Type(4024,null); diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/TextSpecInfoAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/TextSpecInfoAtom.java new file mode 100755 index 0000000000..a8915f0498 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/record/TextSpecInfoAtom.java @@ -0,0 +1,85 @@ +/* ==================================================================== + 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.hslf.record; + +import org.apache.poi.util.LittleEndian; + +import java.io.OutputStream; +import java.io.IOException; + +/** + * The special info runs contained in this text. + * Special info runs consist of character properties which don?t follow styles. + * + * @author Yegor Kozlov + */ +public class TextSpecInfoAtom extends RecordAtom { + /** + * Record header. + */ + private byte[] _header; + + /** + * Record data. + */ + private byte[] _data; + + /** + * Constructs the link related atom record from its + * source data. + * + * @param source the source data as a byte array. + * @param start the start offset into the byte array. + * @param len the length of the slice in the byte array. + */ + protected TextSpecInfoAtom(byte[] source, int start, int len) { + // Get the header. + _header = new byte[8]; + System.arraycopy(source,start,_header,0,8); + + // Get the record data. + _data = new byte[len-8]; + System.arraycopy(source,start+8,_data,0,len-8); + + } + /** + * Gets the record type. + * @return the record type. + */ + public long getRecordType() { return RecordTypes.TextSpecInfoAtom.typeID; } + + /** + * Write the contents of the record back, so it can be written + * to disk + * + * @param out the output stream to write to. + * @throws java.io.IOException if an error occurs. + */ + public void writeOut(OutputStream out) throws IOException { + out.write(_header); + out.write(_data); + } + + /** + * Update the text length + * + * @param size the text length + */ + public void setTextSize(int size){ + LittleEndian.putInt(_data, 0, size); + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java index 9ce9a12c9d..21e30ac2a9 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java @@ -757,4 +757,50 @@ public class SlideShow } return addPicture(data, format); } + + /** + * Add a font in this presentation + * + * @param font the font to add + * @return 0-based index of the font + */ + public int addFont(PPFont font) { + FontCollection fonts = getDocumentRecord().getEnvironment().getFontCollection(); + int idx = fonts.getFontIndex(font.getFontName()); + if(idx == -1){ + idx = fonts.addFont(font.getFontName(), font.getCharSet(), font.getFontFlags(), font.getFontType(), font.getPitchAndFamily()); + } + return idx; + } + + /** + * Get a font by index + * + * @param idx 0-based index of the font + * @return of an instance ofPPFont
or null
if not found
+ */
+ public PPFont getFont(int idx) {
+ PPFont font = null;
+ FontCollection fonts = getDocumentRecord().getEnvironment().getFontCollection();
+ Record[] ch = fonts.getChildRecords();
+ for (int i = 0; i < ch.length; i++) {
+ if(ch[i] instanceof FontEntityAtom) {
+ FontEntityAtom atom = (FontEntityAtom)ch[i];
+ if(atom.getFontIndex() == idx){
+ font = new PPFont(atom);
+ break;
+ }
+ }
+ }
+ return font;
+ }
+
+ /**
+ * get the number of fonts in the presentation
+ *
+ * @return number of fonts
+ */
+ public int getNumberOfFonts() {
+ return getDocumentRecord().getEnvironment().getFontCollection().getNumberOfFonts();
+ }
}
diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/data/empty.ppt b/src/scratchpad/testcases/org/apache/poi/hslf/data/empty.ppt
index 23e1e94ca8..20d2398e39 100644
Binary files a/src/scratchpad/testcases/org/apache/poi/hslf/data/empty.ppt and b/src/scratchpad/testcases/org/apache/poi/hslf/data/empty.ppt differ
diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/data/text_shapes.ppt b/src/scratchpad/testcases/org/apache/poi/hslf/data/text_shapes.ppt
new file mode 100755
index 0000000000..c36183ac35
Binary files /dev/null and b/src/scratchpad/testcases/org/apache/poi/hslf/data/text_shapes.ppt differ
diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestPPFont.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestPPFont.java
new file mode 100755
index 0000000000..b6864ea16b
--- /dev/null
+++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestPPFont.java
@@ -0,0 +1,56 @@
+
+/* ====================================================================
+ 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.hslf.model;
+
+import junit.framework.TestCase;
+import org.apache.poi.hslf.usermodel.SlideShow;
+
+import java.io.IOException;
+
+/**
+ * Test adding fonts to the presenataion resources
+ *
+ * @author Yegor Kozlov
+ */
+public class TestPPFont extends TestCase{
+
+ public void testCreate() throws IOException {
+ SlideShow ppt = new SlideShow();
+ assertEquals(1, ppt.getNumberOfFonts());
+ assertEquals("Arial", ppt.getFont(0).getFontName());
+
+ //adding the same font twice
+ assertEquals(0, ppt.addFont(PPFont.ARIAL));
+ assertEquals(1, ppt.getNumberOfFonts());
+
+ assertEquals(1, ppt.addFont(PPFont.TIMES_NEW_ROMAN));
+ assertEquals(2, ppt.addFont(PPFont.COURIER_NEW));
+ assertEquals(3, ppt.addFont(PPFont.WINGDINGS));
+
+ assertEquals(4, ppt.getNumberOfFonts());
+
+ assertEquals(PPFont.TIMES_NEW_ROMAN.getFontName(), ppt.getFont(1).getFontName());
+ assertEquals(PPFont.COURIER_NEW.getFontName(), ppt.getFont(2).getFontName());
+
+ PPFont font3 = ppt.getFont(3);
+ assertEquals(PPFont.WINGDINGS.getFontName(), font3.getFontName());
+ assertEquals(PPFont.SYMBOL_CHARSET, font3.getCharSet());
+ assertEquals(PPFont.VARIABLE_PITCH, font3.getPitchAndFamily());
+ }
+}
diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java
index 1fe8f7e5e6..c2e081ee5c 100644
--- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java
+++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java
@@ -218,8 +218,8 @@ public class TestShapes extends TestCase {
ArrayList lst2 = new ArrayList();
Shape[] sh = sl[k].getShapes();
for (int i = 0; i < sh.length; i++) {
- if (sh[i] instanceof TextBox){
- TextBox tbox = (TextBox)sh[i];
+ if (sh[i] instanceof TextShape){
+ TextShape tbox = (TextShape)sh[i];
lst2.add(tbox.getText());
}
}
diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java
new file mode 100755
index 0000000000..25a8db9187
--- /dev/null
+++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java
@@ -0,0 +1,160 @@
+
+/* ====================================================================
+ 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.hslf.model;
+
+import junit.framework.TestCase;
+
+import java.io.*;
+import java.util.ArrayList;
+
+import org.apache.poi.hslf.usermodel.SlideShow;
+import org.apache.poi.hslf.record.TextHeaderAtom;
+
+/**
+ * Verify behavior of TextShape
and its sub-classes
+ *
+ * @author Yegor Kozlov
+ */
+public class TestTextShape extends TestCase {
+ protected String cwd = System.getProperty("HSLF.testdata.path");
+
+ public void testCreateAutoShape(){
+ TextShape shape = new AutoShape(ShapeTypes.Trapezoid);
+ assertNull(shape.getTextRun());
+ assertNull(shape.getText());
+ assertNull(shape.getEscherTextboxWrapper());
+
+ TextRun run = shape.createTextRun();
+ assertNotNull(run);
+ assertNotNull(shape.getTextRun());
+ assertNotNull(shape.getEscherTextboxWrapper());
+ assertEquals("", shape.getText());
+ assertSame(run, shape.createTextRun());
+
+ }
+
+ public void testCreateTextBox(){
+ TextShape shape = new TextBox();
+ TextRun run = shape.getTextRun();
+ assertNotNull(run);
+ assertNotNull(shape.getText());
+ assertNotNull(shape.getEscherTextboxWrapper());
+
+ assertSame(run, shape.createTextRun());
+ assertNotNull(shape.getTextRun());
+ assertNotNull(shape.getEscherTextboxWrapper());
+ assertEquals("", shape.getText());
+
+ }
+
+ /**
+ * Verify we can get text from TextShape in the following cases:
+ * - placeholders
+ * - normal TextBox object
+ * - text in auto-shapes
+ */
+ public void testRead() throws IOException {
+ FileInputStream is = new FileInputStream(new File(cwd, "text_shapes.ppt"));
+ SlideShow ppt = new SlideShow(is);
+ is.close();
+
+ ArrayList lst1 = new ArrayList();
+ Slide slide = ppt.getSlides()[0];
+ Shape[] shape = slide.getShapes();
+ for (int i = 0; i < shape.length; i++) {
+ assertTrue("Expected TextShape but found " + shape[i].getClass().getName(), shape[i] instanceof TextShape);
+ TextShape tx = (TextShape)shape[i];
+ TextRun run = tx.getTextRun();
+ assertNotNull(run);
+ int runType = run.getRunType();
+
+ int type = shape[i].getShapeType();
+ switch (type){
+ case ShapeTypes.TextBox:
+ assertEquals("Text in a TextBox", run.getText());
+ break;
+ case ShapeTypes.Rectangle:
+ if(runType == TextHeaderAtom.OTHER_TYPE)
+ assertEquals("Rectangle", run.getText());
+ else if(runType == TextHeaderAtom.TITLE_TYPE)
+ assertEquals("Title Placeholder", run.getText());
+ break;
+ case ShapeTypes.Octagon:
+ assertEquals("Octagon", run.getText());
+ break;
+ case ShapeTypes.Ellipse:
+ assertEquals("Ellipse", run.getText());
+ break;
+ case ShapeTypes.RoundRectangle:
+ assertEquals("RoundRectangle", run.getText());
+ break;
+ default:
+ fail("Unexpected shape: " + shape[i].getShapeName());
+
+ }
+ lst1.add(run.getText());
+ }
+
+ ArrayList lst2 = new ArrayList();
+ TextRun[] run = slide.getTextRuns();
+ for (int i = 0; i < run.length; i++) {
+ lst2.add(run[i].getText());
+ }
+
+ assertTrue(lst1.containsAll(lst2));
+ }
+
+ public void testReadWrite() throws IOException {
+ SlideShow ppt = new SlideShow();
+ Slide slide = ppt.createSlide();
+
+ TextShape shape1 = new TextBox();
+ TextRun run1 = shape1.createTextRun();
+ run1.setText("Hello, World!");
+ slide.addShape(shape1);
+
+ shape1.moveTo(100, 100);
+
+ TextShape shape2 = new AutoShape(ShapeTypes.Arrow);
+ TextRun run2 = shape2.createTextRun();
+ run2.setText("Testing TextShape");
+ slide.addShape(shape2);
+ shape2.moveTo(300, 300);
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ppt.write(out);
+ out.close();
+
+ ppt = new SlideShow(new ByteArrayInputStream(out.toByteArray()));
+ slide = ppt.getSlides()[0];
+ Shape[] shape = slide.getShapes();
+
+ assertTrue(shape[0] instanceof TextShape);
+ shape1 = (TextShape)shape[0];
+ assertEquals(ShapeTypes.TextBox, shape1.getShapeType());
+ assertEquals("Hello, World!", shape1.getTextRun().getText());
+
+ assertTrue(shape[1] instanceof TextShape);
+ shape1 = (TextShape)shape[1];
+ assertEquals(ShapeTypes.Arrow, shape1.getShapeType());
+ assertEquals("Testing TextShape", shape1.getTextRun().getText());
+ }
+
+}
diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java
index 36e45501ec..19e7af6417 100644
--- a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java
+++ b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java
@@ -316,8 +316,8 @@ public class TestBugs extends TestCase {
ArrayList lst = new ArrayList();
Shape[] shape = slide.getShapes();
for (int i = 0; i < shape.length; i++) {
- if( shape[i] instanceof TextBox){
- TextRun textRun = ((TextBox)shape[i]).getTextRun();
+ if( shape[i] instanceof TextShape){
+ TextRun textRun = ((TextShape)shape[i]).getTextRun();
if(textRun != null) lst.add(textRun);
}
diff --git a/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java b/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java
index 2589aa90dd..31b4dd180a 100644
--- a/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java
+++ b/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java
@@ -142,7 +142,7 @@ public final class TestFormulaParser extends TestCase {
assertEquals(true, flag.getValue());
assertEquals("Y", y.getValue());
assertEquals("N", n.getValue());
- assertEquals("IF", funif.toFormulaString((Workbook) null));
+ assertEquals("IF", funif.toFormulaString((HSSFWorkbook) null));
assertTrue("Goto ptg exists", goto1.isGoto());
}
@@ -283,7 +283,7 @@ public final class TestFormulaParser extends TestCase {
}
public void testMacroFunction() {
- Workbook w = Workbook.createWorkbook();
+ HSSFWorkbook w = new HSSFWorkbook();
FormulaParser fp = new FormulaParser("FOO()", w);
fp.parse();
Ptg[] ptg = fp.getRPNPtg();
@@ -589,8 +589,7 @@ public final class TestFormulaParser extends TestCase {
* a formula consisting of a single no-arg function got rendered without the function braces
*/
public void testToFormulaStringZeroArgFunction() {
-
- Workbook book = Workbook.createWorkbook(); // not really used in this test
+ HSSFWorkbook book = new HSSFWorkbook();
Ptg[] ptgs = {
new FuncPtg(10, 0),
@@ -889,7 +888,7 @@ public final class TestFormulaParser extends TestCase {
}
}
public void testFuncPtgSelection() {
- Workbook book = Workbook.createWorkbook();
+ HSSFWorkbook book = new HSSFWorkbook();
Ptg[] ptgs;
ptgs = FormulaParser.parse("countif(A1:A2, 1)", book);
assertEquals(3, ptgs.length);
diff --git a/src/testcases/org/apache/poi/hssf/record/TestCFRuleRecord.java b/src/testcases/org/apache/poi/hssf/record/TestCFRuleRecord.java
index 8f7593f09f..afc44e7043 100644
--- a/src/testcases/org/apache/poi/hssf/record/TestCFRuleRecord.java
+++ b/src/testcases/org/apache/poi/hssf/record/TestCFRuleRecord.java
@@ -19,11 +19,11 @@ package org.apache.poi.hssf.record;
import junit.framework.TestCase;
-import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator;
import org.apache.poi.hssf.record.cf.BorderFormatting;
import org.apache.poi.hssf.record.cf.FontFormatting;
import org.apache.poi.hssf.record.cf.PatternFormatting;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.util.LittleEndian;
@@ -38,7 +38,7 @@ public final class TestCFRuleRecord extends TestCase
public void testCreateCFRuleRecord ()
{
- Workbook workbook = Workbook.createWorkbook();
+ HSSFWorkbook workbook = new HSSFWorkbook();
CFRuleRecord record = CFRuleRecord.create(workbook, "7");
testCFRuleRecord(record);
@@ -278,7 +278,7 @@ public final class TestCFRuleRecord extends TestCase
}
public void testWrite() {
- Workbook workbook = Workbook.createWorkbook();
+ HSSFWorkbook workbook = new HSSFWorkbook();
CFRuleRecord rr = CFRuleRecord.create(workbook, ComparisonOperator.BETWEEN, "5", "10");
PatternFormatting patternFormatting = new PatternFormatting();
@@ -293,7 +293,8 @@ public final class TestCFRuleRecord extends TestCase
int flags = LittleEndian.getInt(data, 10);
assertEquals("unused flags should be 111", 0x00380000, flags & 0x00380000);
assertEquals("undocumented flags should be 0000", 0, flags & 0x03C00000); // Otherwise Excel gets unhappy
- assertEquals(0xA03FFFFF, flags);
+ // check all remaining flag bits (some are not well understood yet)
+ assertEquals(0x203FFFFF, flags);
}
diff --git a/src/testcases/org/apache/poi/hssf/record/aggregates/TestCFRecordsAggregate.java b/src/testcases/org/apache/poi/hssf/record/aggregates/TestCFRecordsAggregate.java
index f605097768..2ae8230d5e 100644
--- a/src/testcases/org/apache/poi/hssf/record/aggregates/TestCFRecordsAggregate.java
+++ b/src/testcases/org/apache/poi/hssf/record/aggregates/TestCFRecordsAggregate.java
@@ -24,12 +24,12 @@ import java.util.List;
import junit.framework.TestCase;
-import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.CFHeaderRecord;
import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.RecordFactory;
import org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator;
import org.apache.poi.hssf.record.cf.CellRange;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
/**
* Tests the serialization and deserialization of the CFRecordsAggregate
@@ -42,7 +42,7 @@ public final class TestCFRecordsAggregate extends TestCase
public void testCFRecordsAggregate()
{
- Workbook workbook = Workbook.createWorkbook();
+ HSSFWorkbook workbook = new HSSFWorkbook();
List recs = new ArrayList();
CFHeaderRecord header = new CFHeaderRecord();
CFRuleRecord rule1 = CFRuleRecord.create(workbook, "7");
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/AbstractPtgTestCase.java b/src/testcases/org/apache/poi/hssf/record/formula/AbstractPtgTestCase.java
index b8d223a4a8..db29380a9c 100644
--- a/src/testcases/org/apache/poi/hssf/record/formula/AbstractPtgTestCase.java
+++ b/src/testcases/org/apache/poi/hssf/record/formula/AbstractPtgTestCase.java
@@ -51,13 +51,9 @@ public abstract class AbstractPtgTestCase extends TestCase {
/**
* Creates a new Workbook and adds one sheet with the specified name
*/
- protected static final Workbook createWorkbookWithSheet(String sheetName) {
-
- Workbook book = Workbook.createWorkbook();
- // this creates sheet if it doesn't exist
- book.checkExternSheet(0);
- // TODO - this call alone does not create the sheet even though the javadoc says it does
- book.setSheetName(0, sheetName);
+ protected static final HSSFWorkbook createWorkbookWithSheet(String sheetName) {
+ HSSFWorkbook book = new HSSFWorkbook();
+ book.createSheet(sheetName);
return book;
}
}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/TestArea3DPtg.java b/src/testcases/org/apache/poi/hssf/record/formula/TestArea3DPtg.java
index 2af50d4b93..e83a59b42d 100644
--- a/src/testcases/org/apache/poi/hssf/record/formula/TestArea3DPtg.java
+++ b/src/testcases/org/apache/poi/hssf/record/formula/TestArea3DPtg.java
@@ -18,7 +18,7 @@
package org.apache.poi.hssf.record.formula;
-import org.apache.poi.hssf.model.Workbook;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
/**
* Tests for Area3DPtg
@@ -35,7 +35,7 @@ public final class TestArea3DPtg extends AbstractPtgTestCase {
Area3DPtg target = new Area3DPtg("A1:B1", (short)0);
String sheetName = "my sheet";
- Workbook book = createWorkbookWithSheet(sheetName);
+ HSSFWorkbook book = createWorkbookWithSheet(sheetName);
assertEquals("'my sheet'!A1:B1", target.toFormulaString(book));
book.setSheetName(0, "Sheet1");
@@ -44,7 +44,4 @@ public final class TestArea3DPtg extends AbstractPtgTestCase {
book.setSheetName(0, "C64");
assertEquals("'C64'!A1:B1", target.toFormulaString(book));
}
-
-
-
}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/TestRef3DPtg.java b/src/testcases/org/apache/poi/hssf/record/formula/TestRef3DPtg.java
index b5fbe3b80d..4de0c7bdb2 100644
--- a/src/testcases/org/apache/poi/hssf/record/formula/TestRef3DPtg.java
+++ b/src/testcases/org/apache/poi/hssf/record/formula/TestRef3DPtg.java
@@ -18,7 +18,7 @@
package org.apache.poi.hssf.record.formula;
-import org.apache.poi.hssf.model.Workbook;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
/**
* Tests for Ref3DPtg
@@ -31,7 +31,7 @@ public final class TestRef3DPtg extends AbstractPtgTestCase {
Ref3DPtg target = new Ref3DPtg("A1", (short)0);
- Workbook book = createWorkbookWithSheet("my sheet");
+ HSSFWorkbook book = createWorkbookWithSheet("my sheet");
assertEquals("'my sheet'!A1", target.toFormulaString(book));
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/function/TestParseMissingBuiltInFuncs.java b/src/testcases/org/apache/poi/hssf/record/formula/function/TestParseMissingBuiltInFuncs.java
index fdad5f44d8..1e26fa706e 100644
--- a/src/testcases/org/apache/poi/hssf/record/formula/function/TestParseMissingBuiltInFuncs.java
+++ b/src/testcases/org/apache/poi/hssf/record/formula/function/TestParseMissingBuiltInFuncs.java
@@ -26,6 +26,7 @@ import org.apache.poi.hssf.record.formula.AbstractFunctionPtg;
import org.apache.poi.hssf.record.formula.FuncPtg;
import org.apache.poi.hssf.record.formula.FuncVarPtg;
import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
/**
* Tests parsing of some built-in functions that were not properly
* registered in POI as bug #44675, #44733 (March/April 2008).
@@ -35,7 +36,7 @@ import org.apache.poi.hssf.record.formula.Ptg;
public final class TestParseMissingBuiltInFuncs extends TestCase {
private static Ptg[] parse(String formula) {
- Workbook book = Workbook.createWorkbook();
+ HSSFWorkbook book = new HSSFWorkbook();
return FormulaParser.parse(formula, book);
}
private static void confirmFunc(String formula, int expPtgArraySize, boolean isVarArgFunc, int funcIx) {
@@ -57,7 +58,7 @@ public final class TestParseMissingBuiltInFuncs extends TestCase {
assertEquals(expCls, ptgF.getClass());
// check that parsed Ptg array converts back to formula text OK
- Workbook book = Workbook.createWorkbook();
+ HSSFWorkbook book = new HSSFWorkbook();
String reRenderedFormula = FormulaParser.toFormulaString(book, ptgs);
assertEquals(formula, reRenderedFormula);
}
diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestFormulaEvaluatorBugs.java b/src/testcases/org/apache/poi/hssf/usermodel/TestFormulaEvaluatorBugs.java
index 007cbd5760..19069d32b2 100644
--- a/src/testcases/org/apache/poi/hssf/usermodel/TestFormulaEvaluatorBugs.java
+++ b/src/testcases/org/apache/poi/hssf/usermodel/TestFormulaEvaluatorBugs.java
@@ -203,7 +203,7 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
assertEquals(2, ptg.getLastColumn());
assertEquals(0, ptg.getFirstRow());
assertEquals(65535, ptg.getLastRow());
- assertEquals("C:C", ptg.toFormulaString(wb.getWorkbook()));
+ assertEquals("C:C", ptg.toFormulaString(wb));
// Will show as C:C, but won't know how many
// rows it covers as we don't have the sheet
diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFConditionalFormatting.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFConditionalFormatting.java
index 930970ea22..6dbcf815dc 100644
--- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFConditionalFormatting.java
+++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFConditionalFormatting.java
@@ -34,22 +34,26 @@ public final class TestHSSFConditionalFormatting extends TestCase
HSSFSheet sheet = workbook.createSheet();
String formula = "7";
- HSSFFontFormatting fontFmt = new HSSFFontFormatting();
+ HSSFSheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
+
+ HSSFConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule(formula);
+ HSSFFontFormatting fontFmt = rule1.createFontFormatting();
fontFmt.setFontStyle(true, false);
- HSSFBorderFormatting bordFmt = new HSSFBorderFormatting();
+ HSSFBorderFormatting bordFmt = rule1.createBorderFormatting();
bordFmt.setBorderBottom(HSSFBorderFormatting.BORDER_THIN);
bordFmt.setBorderTop(HSSFBorderFormatting.BORDER_THICK);
bordFmt.setBorderLeft(HSSFBorderFormatting.BORDER_DASHED);
bordFmt.setBorderRight(HSSFBorderFormatting.BORDER_DOTTED);
- HSSFPatternFormatting patternFmt = new HSSFPatternFormatting();
- patternFmt.setFillBackgroundColor(HSSFColor.RED.index);
+ HSSFPatternFormatting patternFmt = rule1.createPatternFormatting();
+ patternFmt.setFillBackgroundColor(HSSFColor.YELLOW.index);
+
+ HSSFConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule(ComparisonOperator.BETWEEN, "1", "2");
HSSFConditionalFormattingRule [] cfRules =
{
- sheet.createConditionalFormattingRule(formula, fontFmt, bordFmt, patternFmt),
- sheet.createConditionalFormattingRule(ComparisonOperator.BETWEEN, "1", "2", fontFmt, bordFmt, patternFmt)
+ rule1, rule2
};
short col = 1;
@@ -58,14 +62,14 @@ public final class TestHSSFConditionalFormatting extends TestCase
new Region(0,col,65535,col)
};
- sheet.addConditionalFormatting(regions, cfRules);
- sheet.addConditionalFormatting(regions, cfRules);
+ sheetCF.addConditionalFormatting(regions, cfRules);
+ sheetCF.addConditionalFormatting(regions, cfRules);
// Verification
- assertEquals(2, sheet.getNumConditionalFormattings());
- sheet.removeConditionalFormatting(1);
- assertEquals(1, sheet.getNumConditionalFormattings());
- HSSFConditionalFormatting cf = sheet.getConditionalFormattingAt(0);
+ assertEquals(2, sheetCF.getNumConditionalFormattings());
+ sheetCF.removeConditionalFormatting(1);
+ assertEquals(1, sheetCF.getNumConditionalFormattings());
+ HSSFConditionalFormatting cf = sheetCF.getConditionalFormattingAt(0);
assertNotNull(cf);
regions = cf.getFormattingRegions();
@@ -79,7 +83,7 @@ public final class TestHSSFConditionalFormatting extends TestCase
assertEquals(2, cf.getNumberOfRules());
- HSSFConditionalFormattingRule rule1 = cf.getRule(0);
+ rule1 = cf.getRule(0);
assertEquals("7",rule1.getFormula1());
assertNull(rule1.getFormula2());
@@ -98,11 +102,10 @@ public final class TestHSSFConditionalFormatting extends TestCase
HSSFPatternFormatting r1pf = rule1.getPatternFormatting();
assertNotNull(r1pf);
- assertEquals(HSSFColor.RED.index,r1pf.getFillBackgroundColor());
+ assertEquals(HSSFColor.YELLOW.index,r1pf.getFillBackgroundColor());
- HSSFConditionalFormattingRule rule2 = cf.getRule(1);
+ rule2 = cf.getRule(1);
assertEquals("2",rule2.getFormula2());
assertEquals("1",rule2.getFormula1());
}
-
}
diff --git a/src/testcases/org/apache/poi/hssf/util/TestAreaReference.java b/src/testcases/org/apache/poi/hssf/util/TestAreaReference.java
index a72c039cb8..5eb2abb6e6 100644
--- a/src/testcases/org/apache/poi/hssf/util/TestAreaReference.java
+++ b/src/testcases/org/apache/poi/hssf/util/TestAreaReference.java
@@ -211,12 +211,12 @@ public final class TestAreaReference extends TestCase {
Area3DPtg ptgB = (Area3DPtg)def.get(1);
Area3DPtg ptgC = (Area3DPtg)def.get(2);
UnionPtg ptgD = (UnionPtg)def.get(3);
- assertEquals("", ptgA.toFormulaString(workbook));
- assertEquals(refA, ptgB.toFormulaString(workbook));
- assertEquals(refB, ptgC.toFormulaString(workbook));
- assertEquals(",", ptgD.toFormulaString(workbook));
+ assertEquals("", ptgA.toFormulaString(wb));
+ assertEquals(refA, ptgB.toFormulaString(wb));
+ assertEquals(refB, ptgC.toFormulaString(wb));
+ assertEquals(",", ptgD.toFormulaString(wb));
- assertEquals(ref, nr.getAreaReference(workbook));
+ assertEquals(ref, nr.getAreaReference(wb));
// Check the high level definition
int idx = wb.getNameIndex("test");