test integration of XDDF text entities

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1839259 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Alain Béarez 2018-08-26 21:33:16 +00:00
parent 0f9247a088
commit 85e2e8616d
12 changed files with 1205 additions and 720 deletions

View File

@ -1152,10 +1152,8 @@ under the License.
<target name="retest-ooxml" depends="jar"> <target name="retest-ooxml" depends="jar">
<delete dir="${ooxml.reports.test}"/> <delete dir="${ooxml.reports.test}"/>
<delete dir="${ooxml.output.test}"/>
<delete dir="${ooxml.output.test.dir}"/> <delete dir="${ooxml.output.test.dir}"/>
<mkdir dir="${ooxml.reports.test}"/> <mkdir dir="${ooxml.reports.test}"/>
<mkdir dir="${ooxml.output.test}"/>
<mkdir dir="${ooxml.output.test.dir}"/> <mkdir dir="${ooxml.output.test.dir}"/>
<!-- compile the sources --> <!-- compile the sources -->
<javac target="${jdk.version.class}" <javac target="${jdk.version.class}"

View File

@ -21,34 +21,28 @@ package org.apache.poi.xslf.usermodel;
import org.apache.poi.sl.usermodel.AutoShape; import org.apache.poi.sl.usermodel.AutoShape;
import org.apache.poi.util.Beta; import org.apache.poi.util.Beta;
import org.apache.poi.xddf.usermodel.text.XDDFTextBody;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShapeNonVisual; import org.openxmlformats.schemas.presentationml.x2006.main.CTShapeNonVisual;
/** /**
* Represents a shape with a preset geometry. * Represents a shape with a preset geometry.
* *
* @author Yegor Kozlov * @author Yegor Kozlov
*/ */
@Beta @Beta
public class XSLFAutoShape extends XSLFTextShape public class XSLFAutoShape extends XSLFTextShape implements AutoShape<XSLFShape, XSLFTextParagraph> {
implements AutoShape<XSLFShape,XSLFTextParagraph> {
/*package*/ XSLFAutoShape(CTShape shape, XSLFSheet sheet) { /* package */ XSLFAutoShape(CTShape shape, XSLFSheet sheet) {
super(shape, sheet); super(shape, sheet);
} }
/*package*/ /* package */
static XSLFAutoShape create(CTShape shape, XSLFSheet sheet) { static XSLFAutoShape create(CTShape shape, XSLFSheet sheet) {
if (shape.getSpPr().isSetCustGeom()) { if (shape.getSpPr().isSetCustGeom()) {
return new XSLFFreeformShape(shape, sheet); return new XSLFFreeformShape(shape, sheet);
@ -60,7 +54,8 @@ public class XSLFAutoShape extends XSLFTextShape
} }
/** /**
* @param shapeId 1-based shapeId * @param shapeId
* 1-based shapeId
*/ */
static CTShape prototype(int shapeId) { static CTShape prototype(int shapeId) {
CTShape ct = CTShape.Factory.newInstance(); CTShape ct = CTShape.Factory.newInstance();
@ -76,22 +71,10 @@ public class XSLFAutoShape extends XSLFTextShape
prst.addNewAvLst(); prst.addNewAvLst();
return ct; return ct;
} }
protected static void initTextBody(CTTextBody txBody) {
CTTextBodyProperties bodypr = txBody.addNewBodyPr();
bodypr.setAnchor(STTextAnchoringType.T);
bodypr.setRtlCol(false);
CTTextParagraph p = txBody.addNewP();
p.addNewPPr().setAlgn(STTextAlignType.L);
CTTextCharacterProperties endPr = p.addNewEndParaRPr();
endPr.setLang("en-US");
endPr.setSz(1100);
p.addNewR().setT("");
txBody.addNewLstStyle();
}
protected CTTextBody getTextBody(boolean create){ @Override
CTShape shape = (CTShape)getXmlObject(); protected CTTextBody getTextBody(boolean create) {
CTShape shape = (CTShape) getXmlObject();
CTTextBody txBody = shape.getTxBody(); CTTextBody txBody = shape.getTxBody();
if (txBody == null && create) { if (txBody == null && create) {
txBody = shape.addNewTxBody(); txBody = shape.addNewTxBody();
@ -101,7 +84,7 @@ public class XSLFAutoShape extends XSLFTextShape
} }
@Override @Override
public String toString(){ public String toString() {
return "[" + getClass().getSimpleName() + "] " + getShapeName(); return "[" + getClass().getSimpleName() + "] " + getShapeName();
} }

View File

@ -33,6 +33,7 @@ import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
import org.apache.poi.sl.usermodel.TableCell; import org.apache.poi.sl.usermodel.TableCell;
import org.apache.poi.sl.usermodel.VerticalAlignment; import org.apache.poi.sl.usermodel.VerticalAlignment;
import org.apache.poi.util.Units; import org.apache.poi.util.Units;
import org.apache.poi.xddf.usermodel.text.XDDFTextBody;
import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFFillProperties; import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFFillProperties;
import org.apache.poi.xslf.usermodel.XSLFTableStyle.TablePartStyle; import org.apache.poi.xslf.usermodel.XSLFTableStyle.TablePartStyle;
import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlObject;
@ -67,7 +68,7 @@ import org.openxmlformats.schemas.drawingml.x2006.main.STTextVerticalType;
/** /**
* Represents a cell of a table in a .pptx presentation * Represents a cell of a table in a .pptx presentation
*/ */
public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,XSLFTextParagraph> { public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape, XSLFTextParagraph> {
private CTTableCellProperties _tcPr; private CTTableCellProperties _tcPr;
private final XSLFTable table; private final XSLFTable table;
private int row, col; private int row, col;
@ -77,18 +78,20 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
*/ */
private Rectangle2D anchor; private Rectangle2D anchor;
/*package*/ XSLFTableCell(CTTableCell cell, XSLFTable table){ /* package */ XSLFTableCell(CTTableCell cell, XSLFTable table) {
super(cell, table.getSheet()); super(cell, table.getSheet());
this.table = table; this.table = table;
} }
@Override @Override
protected CTTextBody getTextBody(boolean create){ protected CTTextBody getTextBody(boolean create) {
CTTableCell cell = getCell(); CTTableCell cell = getCell();
CTTextBody txBody = cell.getTxBody(); CTTextBody txBody = cell.getTxBody();
if (txBody == null && create) { if (txBody == null && create) {
txBody = cell.addNewTxBody(); XDDFTextBody body = new XDDFTextBody(this);
XSLFAutoShape.initTextBody(txBody); initTextBody(body);
cell.setTxBody(body.getXmlObject());
txBody = cell.getTxBody();
} }
return txBody; return txBody;
} }
@ -116,25 +119,25 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
} }
@Override @Override
public void setLeftInset(double margin){ public void setLeftInset(double margin) {
CTTableCellProperties pr = getCellProperties(true); CTTableCellProperties pr = getCellProperties(true);
pr.setMarL(Units.toEMU(margin)); pr.setMarL(Units.toEMU(margin));
} }
@Override @Override
public void setRightInset(double margin){ public void setRightInset(double margin) {
CTTableCellProperties pr = getCellProperties(true); CTTableCellProperties pr = getCellProperties(true);
pr.setMarR(Units.toEMU(margin)); pr.setMarR(Units.toEMU(margin));
} }
@Override @Override
public void setTopInset(double margin){ public void setTopInset(double margin) {
CTTableCellProperties pr = getCellProperties(true); CTTableCellProperties pr = getCellProperties(true);
pr.setMarT(Units.toEMU(margin)); pr.setMarT(Units.toEMU(margin));
} }
@Override @Override
public void setBottomInset(double margin){ public void setBottomInset(double margin) {
CTTableCellProperties pr = getCellProperties(true); CTTableCellProperties pr = getCellProperties(true);
pr.setMarB(Units.toEMU(margin)); pr.setMarB(Units.toEMU(margin));
} }
@ -150,16 +153,16 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
} }
switch (edge) { switch (edge) {
case bottom: case bottom:
return (pr.isSetLnB()) ? pr.getLnB() : (create ? pr.addNewLnB() : null); return (pr.isSetLnB()) ? pr.getLnB() : (create ? pr.addNewLnB() : null);
case left: case left:
return (pr.isSetLnL()) ? pr.getLnL() : (create ? pr.addNewLnL() : null); return (pr.isSetLnL()) ? pr.getLnL() : (create ? pr.addNewLnL() : null);
case top: case top:
return (pr.isSetLnT()) ? pr.getLnT() : (create ? pr.addNewLnT() : null); return (pr.isSetLnT()) ? pr.getLnT() : (create ? pr.addNewLnT() : null);
case right: case right:
return (pr.isSetLnR()) ? pr.getLnR() : (create ? pr.addNewLnR() : null); return (pr.isSetLnR()) ? pr.getLnR() : (create ? pr.addNewLnR() : null);
default: default:
return null; return null;
} }
} }
@ -170,28 +173,28 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
return; return;
} }
switch (edge) { switch (edge) {
case bottom: case bottom:
if (pr.isSetLnB()) { if (pr.isSetLnB()) {
pr.unsetLnB(); pr.unsetLnB();
} }
break; break;
case left: case left:
if (pr.isSetLnL()) { if (pr.isSetLnL()) {
pr.unsetLnL(); pr.unsetLnL();
} }
break; break;
case top: case top:
if (pr.isSetLnT()) { if (pr.isSetLnT()) {
pr.unsetLnT(); pr.unsetLnT();
} }
break; break;
case right: case right:
if (pr.isSetLnR()) { if (pr.isSetLnR()) {
pr.unsetLnB(); pr.unsetLnB();
} }
break; break;
default: default:
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
} }
@ -276,7 +279,7 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
ln.unsetNoFill(); ln.unsetNoFill();
} }
if(!ln.isSetPrstDash()) { if (!ln.isSetPrstDash()) {
ln.addNewPrstDash().setVal(STPresetLineDashVal.SOLID); ln.addNewPrstDash().setVal(STPresetLineDashVal.SOLID);
} }
if (!ln.isSetCmpd()) { if (!ln.isSetCmpd()) {
@ -396,19 +399,19 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
ln.setCap(STLineCap.Enum.forInt(cap.ooxmlId)); ln.setCap(STLineCap.Enum.forInt(cap.ooxmlId));
} }
/** /**
* Specifies a solid color fill. The shape is filled entirely with the specified color. * Specifies a solid color fill. The shape is filled entirely with the
* specified color.
* *
* @param color the solid color fill. * @param color
* The value of <code>null</code> unsets the solidFIll attribute from the underlying xml * the solid color fill. The value of <code>null</code> unsets
* the solidFIll attribute from the underlying xml
*/ */
@Override @Override
public void setFillColor(Color color) { public void setFillColor(Color color) {
CTTableCellProperties spPr = getCellProperties(true); CTTableCellProperties spPr = getCellProperties(true);
if (color == null) { if (color == null) {
if(spPr.isSetSolidFill()) { if (spPr.isSetSolidFill()) {
spPr.unsetSolidFill(); spPr.unsetSolidFill();
} }
} else { } else {
@ -423,13 +426,13 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
* @return solid fill color of null if not set * @return solid fill color of null if not set
*/ */
@Override @Override
public Color getFillColor(){ public Color getFillColor() {
PaintStyle ps = getFillPaint(); PaintStyle ps = getFillPaint();
if (ps instanceof SolidPaint) { if (ps instanceof SolidPaint) {
ColorStyle cs = ((SolidPaint)ps).getSolidColor(); ColorStyle cs = ((SolidPaint) ps).getSolidColor();
return DrawPaint.applyColorTransform(cs); return DrawPaint.applyColorTransform(cs);
} }
return null; return null;
} }
@ -465,23 +468,24 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
} else { } else {
return null; return null;
} }
fp = XSLFPropertiesDelegate.getFillDelegate(props); fp = XSLFPropertiesDelegate.getFillDelegate(props);
if (fp != null) { if (fp != null) {
PaintStyle paint = XSLFShape.selectPaint(fp, null, slideShow.getPackagePart(), theme, hasPlaceholder); PaintStyle paint = XSLFShape.selectPaint(fp, null, slideShow.getPackagePart(), theme, hasPlaceholder);
if (paint != null) { if (paint != null) {
return paint; return paint;
} }
} }
return null; return null;
} }
/** /**
* Retrieves the part style depending on the location of this cell * Retrieves the part style depending on the location of this cell
* *
* @param tablePartStyle the part to be returned, usually this is null * @param tablePartStyle
* and only set when used as a helper method * the part to be returned, usually this is null and only set
* when used as a helper method
* @return the table part style * @return the table part style
*/ */
private CTTablePartStyle getTablePartStyle(TablePartStyle tablePartStyle) { private CTTablePartStyle getTablePartStyle(TablePartStyle tablePartStyle) {
@ -503,11 +507,11 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
tps = tablePartStyle; tps = tablePartStyle;
} else if (row == 0 && firstRow) { } else if (row == 0 && firstRow) {
tps = TablePartStyle.firstRow; tps = TablePartStyle.firstRow;
} else if (row == table.getNumberOfRows()-1 && lastRow) { } else if (row == table.getNumberOfRows() - 1 && lastRow) {
tps = TablePartStyle.lastRow; tps = TablePartStyle.lastRow;
} else if (col == 0 && firstCol) { } else if (col == 0 && firstCol) {
tps = TablePartStyle.firstCol; tps = TablePartStyle.firstCol;
} else if (col == table.getNumberOfColumns()-1 && lastCol) { } else if (col == table.getNumberOfColumns() - 1 && lastCol) {
tps = TablePartStyle.lastCol; tps = TablePartStyle.lastCol;
} else { } else {
tps = TablePartStyle.wholeTbl; tps = TablePartStyle.wholeTbl;
@ -559,28 +563,28 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
} }
@Override @Override
public void setVerticalAlignment(VerticalAlignment anchor){ public void setVerticalAlignment(VerticalAlignment anchor) {
CTTableCellProperties cellProps = getCellProperties(true); CTTableCellProperties cellProps = getCellProperties(true);
if(anchor == null) { if (anchor == null) {
if(cellProps.isSetAnchor()) { if (cellProps.isSetAnchor()) {
cellProps.unsetAnchor(); cellProps.unsetAnchor();
} }
} else { } else {
cellProps.setAnchor(STTextAnchoringType.Enum.forInt(anchor.ordinal() + 1)); cellProps.setAnchor(STTextAnchoringType.Enum.forInt(anchor.ordinal() + 1));
} }
} }
@Override @Override
public VerticalAlignment getVerticalAlignment(){ public VerticalAlignment getVerticalAlignment() {
CTTableCellProperties cellProps = getCellProperties(false); CTTableCellProperties cellProps = getCellProperties(false);
VerticalAlignment align = VerticalAlignment.TOP; VerticalAlignment align = VerticalAlignment.TOP;
if(cellProps != null && cellProps.isSetAnchor()) { if (cellProps != null && cellProps.isSetAnchor()) {
int ival = cellProps.getAnchor().intValue(); int ival = cellProps.getAnchor().intValue();
align = VerticalAlignment.values()[ival - 1]; align = VerticalAlignment.values()[ival - 1];
} }
return align; return align;
} }
/** /**
* @since POI 3.15-beta2 * @since POI 3.15-beta2
@ -588,7 +592,7 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
@Override @Override
public void setTextDirection(TextDirection orientation) { public void setTextDirection(TextDirection orientation) {
CTTableCellProperties cellProps = getCellProperties(true); CTTableCellProperties cellProps = getCellProperties(true);
if(orientation == null) { if (orientation == null) {
if (cellProps.isSetVert()) { if (cellProps.isSetVert()) {
cellProps.unsetVert(); cellProps.unsetVert();
} }
@ -629,23 +633,23 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
} }
switch (orientation.intValue()) { switch (orientation.intValue()) {
default: default:
case STTextVerticalType.INT_HORZ: case STTextVerticalType.INT_HORZ:
return TextDirection.HORIZONTAL; return TextDirection.HORIZONTAL;
case STTextVerticalType.INT_VERT: case STTextVerticalType.INT_VERT:
case STTextVerticalType.INT_EA_VERT: case STTextVerticalType.INT_EA_VERT:
case STTextVerticalType.INT_MONGOLIAN_VERT: case STTextVerticalType.INT_MONGOLIAN_VERT:
return TextDirection.VERTICAL; return TextDirection.VERTICAL;
case STTextVerticalType.INT_VERT_270: case STTextVerticalType.INT_VERT_270:
return TextDirection.VERTICAL_270; return TextDirection.VERTICAL_270;
case STTextVerticalType.INT_WORD_ART_VERT: case STTextVerticalType.INT_WORD_ART_VERT:
case STTextVerticalType.INT_WORD_ART_VERT_RTL: case STTextVerticalType.INT_WORD_ART_VERT_RTL:
return TextDirection.STACKED; return TextDirection.STACKED;
} }
} }
private CTTableCell getCell() { private CTTableCell getCell() {
return (CTTableCell)getXmlObject(); return (CTTableCell) getXmlObject();
} }
/* package */ void setRowColIndex(int row, int col) { /* package */ void setRowColIndex(int row, int col) {
@ -669,15 +673,16 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
} }
/** /**
* There's no real anchor for table cells - this method is used to temporarily store the location * There's no real anchor for table cells - this method is used to
* of the cell for a later retrieval, e.g. for rendering * temporarily store the location of the cell for a later retrieval, e.g.
* for rendering
* *
* @since POI 3.15-beta2 * @since POI 3.15-beta2
*/ */
@Override @Override
public void setAnchor(Rectangle2D anchor) { public void setAnchor(Rectangle2D anchor) {
if (this.anchor == null) { if (this.anchor == null) {
this.anchor = (Rectangle2D)anchor.clone(); this.anchor = (Rectangle2D) anchor.clone();
} else { } else {
this.anchor.setRect(anchor); this.anchor.setRect(anchor);
} }
@ -692,7 +697,7 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
table.updateCellAnchor(); table.updateCellAnchor();
} }
// anchor should be set, after updateCellAnchor is through // anchor should be set, after updateCellAnchor is through
assert(anchor != null); assert (anchor != null);
return anchor; return anchor;
} }
@ -717,7 +722,7 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
protected XmlObject getShapeProperties() { protected XmlObject getShapeProperties() {
return getCellProperties(false); return getCellProperties(false);
} }
/** /**
* @since POI 3.15-beta2 * @since POI 3.15-beta2
*/ */
@ -741,7 +746,7 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
} }
@Override @Override
public PaintStyle getFontColor(){ public PaintStyle getFontColor() {
CTTableStyleTextStyle txStyle = getTextStyle(); CTTableStyleTextStyle txStyle = getTextStyle();
if (txStyle == null) { if (txStyle == null) {
return super.getFontColor(); return super.getFontColor();
@ -752,7 +757,7 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
if (fontRef != null) { if (fontRef != null) {
phClr = fontRef.getSchemeClr(); phClr = fontRef.getSchemeClr();
} }
XSLFTheme theme = getSheet().getTheme(); XSLFTheme theme = getSheet().getTheme();
final XSLFColor c = new XSLFColor(txStyle, theme, phClr); final XSLFColor c = new XSLFColor(txStyle, theme, phClr);
return DrawPaint.createSolidPaint(c.getColorStyle()); return DrawPaint.createSolidPaint(c.getColorStyle());
@ -777,7 +782,7 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
return txStyle.isSetI() && txStyle.getI().intValue() == STOnOffStyleType.INT_ON; return txStyle.isSetI() && txStyle.getI().intValue() == STOnOffStyleType.INT_ON;
} }
} }
private CTTableStyleTextStyle getTextStyle() { private CTTableStyleTextStyle getTextStyle() {
CTTablePartStyle tps = getTablePartStyle(null); CTTablePartStyle tps = getTablePartStyle(null);
if (tps == null || !tps.isSetTcTxStyle()) { if (tps == null || !tps.isSetTcTxStyle()) {

View File

@ -21,27 +21,30 @@ package org.apache.poi.xslf.usermodel;
import org.apache.poi.sl.usermodel.TextBox; import org.apache.poi.sl.usermodel.TextBox;
import org.apache.poi.util.Beta; import org.apache.poi.util.Beta;
import org.openxmlformats.schemas.drawingml.x2006.main.*; import org.apache.poi.xddf.usermodel.text.XDDFTextBody;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShapeNonVisual; import org.openxmlformats.schemas.presentationml.x2006.main.CTShapeNonVisual;
/** /**
* @author Yegor Kozlov * @author Yegor Kozlov
*/ */
@Beta @Beta
public class XSLFTextBox extends XSLFAutoShape public class XSLFTextBox extends XSLFAutoShape implements TextBox<XSLFShape, XSLFTextParagraph> {
implements TextBox<XSLFShape,XSLFTextParagraph> {
/*package*/ XSLFTextBox(CTShape shape, XSLFSheet sheet){ /* package */ XSLFTextBox(CTShape shape, XSLFSheet sheet) {
super(shape, sheet); super(shape, sheet);
} }
/** /**
* *
* @param shapeId 1-based shapeId * @param shapeId
* 1-based shapeId
*/ */
static CTShape prototype(int shapeId){ static CTShape prototype(int shapeId) {
CTShape ct = CTShape.Factory.newInstance(); CTShape ct = CTShape.Factory.newInstance();
CTShapeNonVisual nvSpPr = ct.addNewNvSpPr(); CTShapeNonVisual nvSpPr = ct.addNewNvSpPr();
CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr(); CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr();
@ -53,9 +56,10 @@ public class XSLFTextBox extends XSLFAutoShape
CTPresetGeometry2D prst = spPr.addNewPrstGeom(); CTPresetGeometry2D prst = spPr.addNewPrstGeom();
prst.setPrst(STShapeType.RECT); prst.setPrst(STShapeType.RECT);
prst.addNewAvLst(); prst.addNewAvLst();
CTTextBody txBody = ct.addNewTxBody(); XDDFTextBody body = new XDDFTextBody(null);
XSLFAutoShape.initTextBody(txBody); initTextBody(body);
ct.setTxBody(body.getXmlObject());
return ct; return ct;
} }
} }

View File

@ -24,6 +24,8 @@ import java.awt.geom.Rectangle2D;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import org.apache.poi.ooxml.POIXMLException; import org.apache.poi.ooxml.POIXMLException;
import org.apache.poi.sl.draw.DrawFactory; import org.apache.poi.sl.draw.DrawFactory;
@ -34,6 +36,9 @@ import org.apache.poi.sl.usermodel.TextShape;
import org.apache.poi.sl.usermodel.VerticalAlignment; import org.apache.poi.sl.usermodel.VerticalAlignment;
import org.apache.poi.util.Beta; import org.apache.poi.util.Beta;
import org.apache.poi.util.Units; import org.apache.poi.util.Units;
import org.apache.poi.xddf.usermodel.text.TextContainer;
import org.apache.poi.xddf.usermodel.text.XDDFTextBody;
import org.apache.poi.xddf.usermodel.text.XDDFTextParagraph;
import org.apache.poi.xslf.model.PropertyFetcher; import org.apache.poi.xslf.model.PropertyFetcher;
import org.apache.poi.xslf.model.TextBodyPropertyFetcher; import org.apache.poi.xslf.model.TextBodyPropertyFetcher;
import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlObject;
@ -52,10 +57,10 @@ import org.openxmlformats.schemas.drawingml.x2006.main.STTextWrappingType;
*/ */
@Beta @Beta
public abstract class XSLFTextShape extends XSLFSimpleShape public abstract class XSLFTextShape extends XSLFSimpleShape
implements TextShape<XSLFShape,XSLFTextParagraph> { implements TextContainer, TextShape<XSLFShape, XSLFTextParagraph> {
private final List<XSLFTextParagraph> _paragraphs; private final List<XSLFTextParagraph> _paragraphs;
/*package*/ XSLFTextShape(XmlObject shape, XSLFSheet sheet) { /* package */ XSLFTextShape(XmlObject shape, XSLFSheet sheet) {
super(shape, sheet); super(shape, sheet);
_paragraphs = new ArrayList<>(); _paragraphs = new ArrayList<>();
@ -67,8 +72,22 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
} }
} }
protected static void initTextBody(XDDFTextBody body) {
XDDFTextParagraph p = body.getParagraph(0);
p.appendRegularRun("");
}
@Beta
public XDDFTextBody getTextBody() {
CTTextBody txBody = getTextBody(false);
if (txBody == null) {
return null;
}
return new XDDFTextBody(this, txBody);
}
@Override @Override
public Iterator<XSLFTextParagraph> iterator(){ public Iterator<XSLFTextParagraph> iterator() {
return getTextParagraphs().iterator(); return getTextParagraphs().iterator();
} }
@ -87,7 +106,7 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
/** /**
* unset text from this shape * unset text from this shape
*/ */
public void clearText(){ public void clearText() {
_paragraphs.clear(); _paragraphs.clear();
CTTextBody txBody = getTextBody(true); CTTextBody txBody = getTextBody(true);
txBody.setPArray(null); // remove any existing paragraphs txBody.setPArray(null); // remove any existing paragraphs
@ -95,13 +114,14 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
@Override @Override
public XSLFTextRun setText(String text) { public XSLFTextRun setText(String text) {
// calling clearText or setting to a new Array leads to a XmlValueDisconnectedException // calling clearText or setting to a new Array leads to a
// XmlValueDisconnectedException
if (!_paragraphs.isEmpty()) { if (!_paragraphs.isEmpty()) {
CTTextBody txBody = getTextBody(false); CTTextBody txBody = getTextBody(false);
int cntPs = txBody.sizeOfPArray(); int cntPs = txBody.sizeOfPArray();
for (int i = cntPs; i > 1; i--) { for (int i = cntPs; i > 1; i--) {
txBody.removeP(i-1); txBody.removeP(i - 1);
_paragraphs.remove(i-1); _paragraphs.remove(i - 1);
} }
_paragraphs.get(0).clearButKeepProperties(); _paragraphs.get(0).clearButKeepProperties();
@ -127,18 +147,19 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
para = null; para = null;
} else { } else {
firstPara = !newParagraph; firstPara = !newParagraph;
para = _paragraphs.get(_paragraphs.size()-1); para = _paragraphs.get(_paragraphs.size() - 1);
CTTextParagraph ctp = para.getXmlObject(); CTTextParagraph ctp = para.getXmlObject();
otherPPr = ctp.getPPr(); otherPPr = ctp.getPPr();
List<XSLFTextRun> runs = para.getTextRuns(); List<XSLFTextRun> runs = para.getTextRuns();
if (!runs.isEmpty()) { if (!runs.isEmpty()) {
XSLFTextRun r0 = runs.get(runs.size()-1); XSLFTextRun r0 = runs.get(runs.size() - 1);
otherRPr = r0.getRPr(false); otherRPr = r0.getRPr(false);
if (otherRPr == null) { if (otherRPr == null) {
otherRPr = ctp.getEndParaRPr(); otherRPr = ctp.getEndParaRPr();
} }
} }
// don't copy endParaRPr to the run in case there aren't any other runs // don't copy endParaRPr to the run in case there aren't any other
// runs
// this is the case when setText() was called initially // this is the case when setText() was called initially
// otherwise the master style will be overridden/ignored // otherwise the master style will be overridden/ignored
} }
@ -173,7 +194,7 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
firstPara = false; firstPara = false;
} }
assert(run != null); assert (run != null);
return run; return run;
} }
@ -203,11 +224,11 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
} }
@Override @Override
public void setVerticalAlignment(VerticalAlignment anchor){ public void setVerticalAlignment(VerticalAlignment anchor) {
CTTextBodyProperties bodyPr = getTextBodyPr(true); CTTextBodyProperties bodyPr = getTextBodyPr(true);
if (bodyPr != null) { if (bodyPr != null) {
if(anchor == null) { if (anchor == null) {
if(bodyPr.isSetAnchor()) { if (bodyPr.isSetAnchor()) {
bodyPr.unsetAnchor(); bodyPr.unsetAnchor();
} }
} else { } else {
@ -217,11 +238,11 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
} }
@Override @Override
public VerticalAlignment getVerticalAlignment(){ public VerticalAlignment getVerticalAlignment() {
PropertyFetcher<VerticalAlignment> fetcher = new TextBodyPropertyFetcher<VerticalAlignment>(){ PropertyFetcher<VerticalAlignment> fetcher = new TextBodyPropertyFetcher<VerticalAlignment>() {
@Override @Override
public boolean fetch(CTTextBodyProperties props){ public boolean fetch(CTTextBodyProperties props) {
if(props.isSetAnchor()){ if (props.isSetAnchor()) {
int val = props.getAnchor().intValue(); int val = props.getAnchor().intValue();
setValue(VerticalAlignment.values()[val - 1]); setValue(VerticalAlignment.values()[val - 1]);
return true; return true;
@ -234,10 +255,10 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
} }
@Override @Override
public void setHorizontalCentered(Boolean isCentered){ public void setHorizontalCentered(Boolean isCentered) {
CTTextBodyProperties bodyPr = getTextBodyPr(true); CTTextBodyProperties bodyPr = getTextBodyPr(true);
if (bodyPr != null) { if (bodyPr != null) {
if (isCentered == null) { if (isCentered == null) {
if (bodyPr.isSetAnchorCtr()) { if (bodyPr.isSetAnchorCtr()) {
bodyPr.unsetAnchorCtr(); bodyPr.unsetAnchorCtr();
} }
@ -248,11 +269,11 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
} }
@Override @Override
public boolean isHorizontalCentered(){ public boolean isHorizontalCentered() {
PropertyFetcher<Boolean> fetcher = new TextBodyPropertyFetcher<Boolean>(){ PropertyFetcher<Boolean> fetcher = new TextBodyPropertyFetcher<Boolean>() {
@Override @Override
public boolean fetch(CTTextBodyProperties props){ public boolean fetch(CTTextBodyProperties props) {
if(props.isSetAnchorCtr()){ if (props.isSetAnchorCtr()) {
setValue(props.getAnchorCtr()); setValue(props.getAnchorCtr());
return true; return true;
} }
@ -264,11 +285,11 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
} }
@Override @Override
public void setTextDirection(TextDirection orientation){ public void setTextDirection(TextDirection orientation) {
CTTextBodyProperties bodyPr = getTextBodyPr(true); CTTextBodyProperties bodyPr = getTextBodyPr(true);
if (bodyPr != null) { if (bodyPr != null) {
if(orientation == null) { if (orientation == null) {
if(bodyPr.isSetVert()) { if (bodyPr.isSetVert()) {
bodyPr.unsetVert(); bodyPr.unsetVert();
} }
} else { } else {
@ -278,24 +299,24 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
} }
@Override @Override
public TextDirection getTextDirection(){ public TextDirection getTextDirection() {
CTTextBodyProperties bodyPr = getTextBodyPr(); CTTextBodyProperties bodyPr = getTextBodyPr();
if (bodyPr != null) { if (bodyPr != null) {
STTextVerticalType.Enum val = bodyPr.getVert(); STTextVerticalType.Enum val = bodyPr.getVert();
if(val != null) { if (val != null) {
switch (val.intValue()) { switch (val.intValue()) {
default: default:
case STTextVerticalType.INT_HORZ: case STTextVerticalType.INT_HORZ:
return TextDirection.HORIZONTAL; return TextDirection.HORIZONTAL;
case STTextVerticalType.INT_EA_VERT: case STTextVerticalType.INT_EA_VERT:
case STTextVerticalType.INT_MONGOLIAN_VERT: case STTextVerticalType.INT_MONGOLIAN_VERT:
case STTextVerticalType.INT_VERT: case STTextVerticalType.INT_VERT:
return TextDirection.VERTICAL; return TextDirection.VERTICAL;
case STTextVerticalType.INT_VERT_270: case STTextVerticalType.INT_VERT_270:
return TextDirection.VERTICAL_270; return TextDirection.VERTICAL_270;
case STTextVerticalType.INT_WORD_ART_VERT_RTL: case STTextVerticalType.INT_WORD_ART_VERT_RTL:
case STTextVerticalType.INT_WORD_ART_VERT: case STTextVerticalType.INT_WORD_ART_VERT:
return TextDirection.STACKED; return TextDirection.STACKED;
} }
} }
} }
@ -315,22 +336,22 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
public void setTextRotation(Double rotation) { public void setTextRotation(Double rotation) {
CTTextBodyProperties bodyPr = getTextBodyPr(true); CTTextBodyProperties bodyPr = getTextBodyPr(true);
if (bodyPr != null) { if (bodyPr != null) {
bodyPr.setRot((int)(rotation * 60000.)); bodyPr.setRot((int) (rotation * 60000.));
} }
} }
/** /**
* Returns the distance (in points) between the bottom of the text frame * Returns the distance (in points) between the bottom of the text frame and
* and the bottom of the inscribed rectangle of the shape that contains the text. * the bottom of the inscribed rectangle of the shape that contains the
* text.
* *
* @return the bottom inset in points * @return the bottom inset in points
*/ */
public double getBottomInset(){ public double getBottomInset() {
PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>(){ PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>() {
@Override @Override
public boolean fetch(CTTextBodyProperties props){ public boolean fetch(CTTextBodyProperties props) {
if(props.isSetBIns()){ if (props.isSetBIns()) {
double val = Units.toPoints(props.getBIns()); double val = Units.toPoints(props.getBIns());
setValue(val); setValue(val);
return true; return true;
@ -344,17 +365,17 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
} }
/** /**
* Returns the distance (in points) between the left edge of the text frame * 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 * and the left edge of the inscribed rectangle of the shape that contains
* the text. * the text.
* *
* @return the left inset in points * @return the left inset in points
*/ */
public double getLeftInset(){ public double getLeftInset() {
PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>(){ PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>() {
@Override @Override
public boolean fetch(CTTextBodyProperties props){ public boolean fetch(CTTextBodyProperties props) {
if(props.isSetLIns()){ if (props.isSetLIns()) {
double val = Units.toPoints(props.getLIns()); double val = Units.toPoints(props.getLIns());
setValue(val); setValue(val);
return true; return true;
@ -368,17 +389,17 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
} }
/** /**
* Returns the distance (in points) between the right edge of the * Returns the distance (in points) between the right edge of the text frame
* text frame and the right edge of the inscribed rectangle of the shape * and the right edge of the inscribed rectangle of the shape that contains
* that contains the text. * the text.
* *
* @return the right inset in points * @return the right inset in points
*/ */
public double getRightInset(){ public double getRightInset() {
PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>(){ PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>() {
@Override @Override
public boolean fetch(CTTextBodyProperties props){ public boolean fetch(CTTextBodyProperties props) {
if(props.isSetRIns()){ if (props.isSetRIns()) {
double val = Units.toPoints(props.getRIns()); double val = Units.toPoints(props.getRIns());
setValue(val); setValue(val);
return true; return true;
@ -392,16 +413,16 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
} }
/** /**
* Returns the distance (in points) between the top of the text frame * Returns the distance (in points) between the top of the text frame and
* and the top of the inscribed rectangle of the shape that contains the text. * the top of the inscribed rectangle of the shape that contains the text.
* *
* @return the top inset in points * @return the top inset in points
*/ */
public double getTopInset(){ public double getTopInset() {
PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>(){ PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>() {
@Override @Override
public boolean fetch(CTTextBodyProperties props){ public boolean fetch(CTTextBodyProperties props) {
if(props.isSetTIns()){ if (props.isSetTIns()) {
double val = Units.toPoints(props.getTIns()); double val = Units.toPoints(props.getTIns());
setValue(val); setValue(val);
return true; return true;
@ -416,14 +437,16 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
/** /**
* Sets the bottom margin. * Sets the bottom margin.
*
* @see #getBottomInset() * @see #getBottomInset()
* *
* @param margin the bottom margin * @param margin
* the bottom margin
*/ */
public void setBottomInset(double margin){ public void setBottomInset(double margin) {
CTTextBodyProperties bodyPr = getTextBodyPr(true); CTTextBodyProperties bodyPr = getTextBodyPr(true);
if (bodyPr != null) { if (bodyPr != null) {
if(margin == -1) { if (margin == -1) {
bodyPr.unsetBIns(); bodyPr.unsetBIns();
} else { } else {
bodyPr.setBIns(Units.toEMU(margin)); bodyPr.setBIns(Units.toEMU(margin));
@ -433,14 +456,16 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
/** /**
* Sets the left margin. * Sets the left margin.
*
* @see #getLeftInset() * @see #getLeftInset()
* *
* @param margin the left margin * @param margin
* the left margin
*/ */
public void setLeftInset(double margin){ public void setLeftInset(double margin) {
CTTextBodyProperties bodyPr = getTextBodyPr(true); CTTextBodyProperties bodyPr = getTextBodyPr(true);
if (bodyPr != null) { if (bodyPr != null) {
if(margin == -1) { if (margin == -1) {
bodyPr.unsetLIns(); bodyPr.unsetLIns();
} else { } else {
bodyPr.setLIns(Units.toEMU(margin)); bodyPr.setLIns(Units.toEMU(margin));
@ -450,14 +475,16 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
/** /**
* Sets the right margin. * Sets the right margin.
*
* @see #getRightInset() * @see #getRightInset()
* *
* @param margin the right margin * @param margin
* the right margin
*/ */
public void setRightInset(double margin){ public void setRightInset(double margin) {
CTTextBodyProperties bodyPr = getTextBodyPr(true); CTTextBodyProperties bodyPr = getTextBodyPr(true);
if (bodyPr != null) { if (bodyPr != null) {
if(margin == -1) { if (margin == -1) {
bodyPr.unsetRIns(); bodyPr.unsetRIns();
} else { } else {
bodyPr.setRIns(Units.toEMU(margin)); bodyPr.setRIns(Units.toEMU(margin));
@ -467,14 +494,16 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
/** /**
* Sets the top margin. * Sets the top margin.
*
* @see #getTopInset() * @see #getTopInset()
* *
* @param margin the top margin * @param margin
* the top margin
*/ */
public void setTopInset(double margin){ public void setTopInset(double margin) {
CTTextBodyProperties bodyPr = getTextBodyPr(true); CTTextBodyProperties bodyPr = getTextBodyPr(true);
if (bodyPr != null) { if (bodyPr != null) {
if(margin == -1) { if (margin == -1) {
bodyPr.unsetTIns(); bodyPr.unsetTIns();
} else { } else {
bodyPr.setTIns(Units.toEMU(margin)); bodyPr.setTIns(Units.toEMU(margin));
@ -496,11 +525,11 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
} }
@Override @Override
public boolean getWordWrap(){ public boolean getWordWrap() {
PropertyFetcher<Boolean> fetcher = new TextBodyPropertyFetcher<Boolean>(){ PropertyFetcher<Boolean> fetcher = new TextBodyPropertyFetcher<Boolean>() {
@Override @Override
public boolean fetch(CTTextBodyProperties props){ public boolean fetch(CTTextBodyProperties props) {
if(props.isSetWrap()){ if (props.isSetWrap()) {
setValue(props.getWrap() == STTextWrappingType.SQUARE); setValue(props.getWrap() == STTextWrappingType.SQUARE);
return true; return true;
} }
@ -512,7 +541,7 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
} }
@Override @Override
public void setWordWrap(boolean wrap){ public void setWordWrap(boolean wrap) {
CTTextBodyProperties bodyPr = getTextBodyPr(true); CTTextBodyProperties bodyPr = getTextBodyPr(true);
if (bodyPr != null) { if (bodyPr != null) {
bodyPr.setWrap(wrap ? STTextWrappingType.SQUARE : STTextWrappingType.NONE); bodyPr.setWrap(wrap ? STTextWrappingType.SQUARE : STTextWrappingType.NONE);
@ -521,28 +550,36 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
/** /**
* *
* Specifies that a shape should be auto-fit to fully contain the text described within it. * Specifies that a shape should be auto-fit to fully contain the text
* Auto-fitting is when text within a shape is scaled in order to contain all the text inside * described within it. Auto-fitting is when text within a shape is scaled
* in order to contain all the text inside
* *
* @param value type of autofit * @param value
* type of autofit
*/ */
public void setTextAutofit(TextAutofit value){ public void setTextAutofit(TextAutofit value) {
CTTextBodyProperties bodyPr = getTextBodyPr(true); CTTextBodyProperties bodyPr = getTextBodyPr(true);
if (bodyPr != null) { if (bodyPr != null) {
if(bodyPr.isSetSpAutoFit()) { if (bodyPr.isSetSpAutoFit()) {
bodyPr.unsetSpAutoFit(); bodyPr.unsetSpAutoFit();
} }
if(bodyPr.isSetNoAutofit()) { if (bodyPr.isSetNoAutofit()) {
bodyPr.unsetNoAutofit(); bodyPr.unsetNoAutofit();
} }
if(bodyPr.isSetNormAutofit()) { if (bodyPr.isSetNormAutofit()) {
bodyPr.unsetNormAutofit(); bodyPr.unsetNormAutofit();
} }
switch(value){ switch (value) {
case NONE: bodyPr.addNewNoAutofit(); break; case NONE:
case NORMAL: bodyPr.addNewNormAutofit(); break; bodyPr.addNewNoAutofit();
case SHAPE: bodyPr.addNewSpAutoFit(); break; break;
case NORMAL:
bodyPr.addNewNormAutofit();
break;
case SHAPE:
bodyPr.addNewSpAutoFit();
break;
} }
} }
} }
@ -551,10 +588,10 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
* *
* @return type of autofit * @return type of autofit
*/ */
public TextAutofit getTextAutofit(){ public TextAutofit getTextAutofit() {
CTTextBodyProperties bodyPr = getTextBodyPr(); CTTextBodyProperties bodyPr = getTextBodyPr();
if (bodyPr != null) { if (bodyPr != null) {
if(bodyPr.isSetNoAutofit()) { if (bodyPr.isSetNoAutofit()) {
return TextAutofit.NONE; return TextAutofit.NONE;
} else if (bodyPr.isSetNormAutofit()) { } else if (bodyPr.isSetNormAutofit()) {
return TextAutofit.NORMAL; return TextAutofit.NORMAL;
@ -565,7 +602,7 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
return TextAutofit.NORMAL; return TextAutofit.NORMAL;
} }
protected CTTextBodyProperties getTextBodyPr(){ protected CTTextBodyProperties getTextBodyPr() {
return getTextBodyPr(false); return getTextBodyPr(false);
} }
@ -588,89 +625,88 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
super.setPlaceholder(placeholder); super.setPlaceholder(placeholder);
} }
public Placeholder getTextType(){ public Placeholder getTextType() {
return getPlaceholder(); return getPlaceholder();
} }
@Override @Override
public double getTextHeight(){ public double getTextHeight() {
return getTextHeight(null); return getTextHeight(null);
} }
@Override @Override
public double getTextHeight(Graphics2D graphics){ public double getTextHeight(Graphics2D graphics) {
DrawFactory drawFact = DrawFactory.getInstance(graphics); DrawFactory drawFact = DrawFactory.getInstance(graphics);
DrawTextShape dts = drawFact.getDrawable(this); DrawTextShape dts = drawFact.getDrawable(this);
return dts.getTextHeight(graphics); return dts.getTextHeight(graphics);
} }
@Override @Override
public Rectangle2D resizeToFitText(){ public Rectangle2D resizeToFitText() {
return resizeToFitText(null); return resizeToFitText(null);
} }
@Override @Override
public Rectangle2D resizeToFitText(Graphics2D graphics) { public Rectangle2D resizeToFitText(Graphics2D graphics) {
Rectangle2D anchor = getAnchor(); Rectangle2D anchor = getAnchor();
if(anchor.getWidth() == 0.) { if (anchor.getWidth() == 0.) {
throw new POIXMLException("Anchor of the shape was not set."); throw new POIXMLException("Anchor of the shape was not set.");
} }
double height = getTextHeight(graphics); double height = getTextHeight(graphics);
height += 1; // add a pixel to compensate rounding errors height += 1; // add a pixel to compensate rounding errors
Insets2D insets = getInsets(); Insets2D insets = getInsets();
anchor.setRect(anchor.getX(), anchor.getY(), anchor.getWidth(), height+insets.top+insets.bottom); anchor.setRect(anchor.getX(), anchor.getY(), anchor.getWidth(), height + insets.top + insets.bottom);
setAnchor(anchor); setAnchor(anchor);
return anchor; return anchor;
} }
@Override @Override
void copy(XSLFShape other){ void copy(XSLFShape other) {
super.copy(other); super.copy(other);
XSLFTextShape otherTS = (XSLFTextShape)other; XSLFTextShape otherTS = (XSLFTextShape) other;
CTTextBody otherTB = otherTS.getTextBody(false); CTTextBody otherTB = otherTS.getTextBody(false);
CTTextBody thisTB = getTextBody(true); CTTextBody thisTB = getTextBody(true);
if (otherTB == null) { if (otherTB == null) {
return; return;
} }
thisTB.setBodyPr((CTTextBodyProperties)otherTB.getBodyPr().copy()); thisTB.setBodyPr((CTTextBodyProperties) otherTB.getBodyPr().copy());
if (thisTB.isSetLstStyle()) { if (thisTB.isSetLstStyle()) {
thisTB.unsetLstStyle(); thisTB.unsetLstStyle();
} }
if (otherTB.isSetLstStyle()) { if (otherTB.isSetLstStyle()) {
thisTB.setLstStyle((CTTextListStyle)otherTB.getLstStyle().copy()); thisTB.setLstStyle((CTTextListStyle) otherTB.getLstStyle().copy());
} }
boolean srcWordWrap = otherTS.getWordWrap(); boolean srcWordWrap = otherTS.getWordWrap();
if(srcWordWrap != getWordWrap()){ if (srcWordWrap != getWordWrap()) {
setWordWrap(srcWordWrap); setWordWrap(srcWordWrap);
} }
double leftInset = otherTS.getLeftInset(); double leftInset = otherTS.getLeftInset();
if(leftInset != getLeftInset()) { if (leftInset != getLeftInset()) {
setLeftInset(leftInset); setLeftInset(leftInset);
} }
double rightInset = otherTS.getRightInset(); double rightInset = otherTS.getRightInset();
if(rightInset != getRightInset()) { if (rightInset != getRightInset()) {
setRightInset(rightInset); setRightInset(rightInset);
} }
double topInset = otherTS.getTopInset(); double topInset = otherTS.getTopInset();
if(topInset != getTopInset()) { if (topInset != getTopInset()) {
setTopInset(topInset); setTopInset(topInset);
} }
double bottomInset = otherTS.getBottomInset(); double bottomInset = otherTS.getBottomInset();
if(bottomInset != getBottomInset()) { if (bottomInset != getBottomInset()) {
setBottomInset(bottomInset); setBottomInset(bottomInset);
} }
VerticalAlignment vAlign = otherTS.getVerticalAlignment(); VerticalAlignment vAlign = otherTS.getVerticalAlignment();
if(vAlign != getVerticalAlignment()) { if (vAlign != getVerticalAlignment()) {
setVerticalAlignment(vAlign); setVerticalAlignment(vAlign);
} }
@ -685,26 +721,26 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
@Override @Override
public void setTextPlaceholder(TextPlaceholder placeholder) { public void setTextPlaceholder(TextPlaceholder placeholder) {
switch (placeholder) { switch (placeholder) {
default: default:
case NOTES: case NOTES:
case HALF_BODY: case HALF_BODY:
case QUARTER_BODY: case QUARTER_BODY:
case BODY: case BODY:
setPlaceholder(Placeholder.BODY); setPlaceholder(Placeholder.BODY);
break; break;
case TITLE: case TITLE:
setPlaceholder(Placeholder.TITLE); setPlaceholder(Placeholder.TITLE);
break; break;
case CENTER_BODY: case CENTER_BODY:
setPlaceholder(Placeholder.BODY); setPlaceholder(Placeholder.BODY);
setHorizontalCentered(true); setHorizontalCentered(true);
break; break;
case CENTER_TITLE: case CENTER_TITLE:
setPlaceholder(Placeholder.CENTERED_TITLE); setPlaceholder(Placeholder.CENTERED_TITLE);
break; break;
case OTHER: case OTHER:
setPlaceholder(Placeholder.CONTENT); setPlaceholder(Placeholder.CONTENT);
break; break;
} }
} }
@ -715,18 +751,23 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
return TextPlaceholder.BODY; return TextPlaceholder.BODY;
} }
switch (ph) { switch (ph) {
case BODY: return TextPlaceholder.BODY; case BODY:
case TITLE: return TextPlaceholder.TITLE; return TextPlaceholder.BODY;
case CENTERED_TITLE: return TextPlaceholder.CENTER_TITLE; case TITLE:
return TextPlaceholder.TITLE;
case CENTERED_TITLE:
return TextPlaceholder.CENTER_TITLE;
default: default:
case CONTENT: return TextPlaceholder.OTHER; case CONTENT:
return TextPlaceholder.OTHER;
} }
} }
/** /**
* Helper method to allow subclasses to provide their own text paragraph * Helper method to allow subclasses to provide their own text paragraph
* *
* @param p the xml reference * @param p
* the xml reference
* *
* @return a new text paragraph * @return a new text paragraph
* *
@ -735,4 +776,19 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
protected XSLFTextParagraph newTextParagraph(CTTextParagraph p) { protected XSLFTextParagraph newTextParagraph(CTTextParagraph p) {
return new XSLFTextParagraph(p, this); return new XSLFTextParagraph(p, this);
} }
}
@Override
public <R> Optional<R> findDefinedParagraphProperty(Function<CTTextParagraphProperties, Boolean> isSet,
Function<CTTextParagraphProperties, R> getter) {
// TODO Auto-generated method stub
return Optional.empty();
}
@Override
public <R> Optional<R> findDefinedRunProperty(Function<CTTextCharacterProperties, Boolean> isSet,
Function<CTTextCharacterProperties, R> getter) {
// TODO Auto-generated method stub
return Optional.empty();
}
}

View File

@ -74,7 +74,7 @@ public final class XSSFChart extends XDDFChart implements Chart, ChartAxisFactor
private XSSFGraphicFrame frame; private XSSFGraphicFrame frame;
@Deprecated @Deprecated
@Removal(version="4.2") @Removal(version = "4.2")
List<XSSFChartAxis> axis = new ArrayList<>(); List<XSSFChartAxis> axis = new ArrayList<>();
/** /**
@ -89,7 +89,8 @@ public final class XSSFChart extends XDDFChart implements Chart, ChartAxisFactor
* Construct a SpreadsheetML chart from a package part. * Construct a SpreadsheetML chart from a package part.
* *
* @param part * @param part
* the package part holding the chart data, the content type must be * the package part holding the chart data, the content type must
* be
* <code>application/vnd.openxmlformats-officedocument.drawingml.chart+xml</code> * <code>application/vnd.openxmlformats-officedocument.drawingml.chart+xml</code>
* *
* @since POI 3.14-Beta1 * @since POI 3.14-Beta1
@ -114,7 +115,8 @@ public final class XSSFChart extends XDDFChart implements Chart, ChartAxisFactor
} }
/** /**
* Construct a new CTChartSpace bean. By default, it's just an empty placeholder for chart objects. * Construct a new CTChartSpace bean. By default, it's just an empty
* placeholder for chart objects.
*/ */
private void createChart() { private void createChart() {
CTPlotArea plotArea = getCTPlotArea(); CTPlotArea plotArea = getCTPlotArea();
@ -140,12 +142,15 @@ public final class XSSFChart extends XDDFChart implements Chart, ChartAxisFactor
XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
/* /*
* Saved chart space must have the following namespaces set: <c:chartSpace * Saved chart space must have the following namespaces set:
* <c:chartSpace
* xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" * xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart"
* xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r= * xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
* xmlns:r=
* "http://schemas.openxmlformats.org/officeDocument/2006/relationships"> * "http://schemas.openxmlformats.org/officeDocument/2006/relationships">
*/ */
xmlOptions.setSaveSyntheticDocumentElement(new QName(CTChartSpace.type.getName().getNamespaceURI(), "chartSpace", "c")); xmlOptions.setSaveSyntheticDocumentElement(
new QName(CTChartSpace.type.getName().getNamespaceURI(), "chartSpace", "c"));
PackagePart part = getPackagePart(); PackagePart part = getPackagePart();
try (OutputStream out = part.getOutputStream()) { try (OutputStream out = part.getOutputStream()) {
@ -171,76 +176,76 @@ public final class XSSFChart extends XDDFChart implements Chart, ChartAxisFactor
@Override @Override
@Deprecated @Deprecated
@Removal(version="4.2") @Removal(version = "4.2")
public XSSFChartDataFactory getChartDataFactory() { public XSSFChartDataFactory getChartDataFactory() {
return XSSFChartDataFactory.getInstance(); return XSSFChartDataFactory.getInstance();
} }
@Override @Override
@Deprecated @Deprecated
@Removal(version="4.2") @Removal(version = "4.2")
public XSSFChart getChartAxisFactory() { public XSSFChart getChartAxisFactory() {
return this; return this;
} }
@Override @Override
@Deprecated @Deprecated
@Removal(version="4.2") @Removal(version = "4.2")
public void plot(ChartData data, ChartAxis... chartAxis) { public void plot(ChartData data, ChartAxis... chartAxis) {
data.fillChart(this, chartAxis); data.fillChart(this, chartAxis);
} }
@Override @Override
@Deprecated @Deprecated
@Removal(version="4.2") @Removal(version = "4.2")
public XSSFValueAxis createValueAxis(org.apache.poi.ss.usermodel.charts.AxisPosition pos) { public XSSFValueAxis createValueAxis(org.apache.poi.ss.usermodel.charts.AxisPosition pos) {
long id = axis.size() + 1; long id = axis.size() + 1;
XSSFValueAxis valueAxis = new XSSFValueAxis(this, id, pos); XSSFValueAxis valueAxis = new XSSFValueAxis(this, id, pos);
if (axis.size() == 1) { if (axis.size() == 1) {
ChartAxis ax = axis.get(0); ChartAxis ax = axis.get(0);
ax.crossAxis(valueAxis); ax.crossAxis(valueAxis);
valueAxis.crossAxis(ax); valueAxis.crossAxis(ax);
} }
axis.add(valueAxis); axis.add(valueAxis);
return valueAxis; return valueAxis;
} }
@Override @Override
@Deprecated @Deprecated
@Removal(version="4.2") @Removal(version = "4.2")
public XSSFCategoryAxis createCategoryAxis(org.apache.poi.ss.usermodel.charts.AxisPosition pos) { public XSSFCategoryAxis createCategoryAxis(org.apache.poi.ss.usermodel.charts.AxisPosition pos) {
long id = axis.size() + 1; long id = axis.size() + 1;
XSSFCategoryAxis categoryAxis = new XSSFCategoryAxis(this, id, pos); XSSFCategoryAxis categoryAxis = new XSSFCategoryAxis(this, id, pos);
if (axis.size() == 1) { if (axis.size() == 1) {
ChartAxis ax = axis.get(0); ChartAxis ax = axis.get(0);
ax.crossAxis(categoryAxis); ax.crossAxis(categoryAxis);
categoryAxis.crossAxis(ax); categoryAxis.crossAxis(ax);
} }
axis.add(categoryAxis); axis.add(categoryAxis);
return categoryAxis; return categoryAxis;
} }
@Override @Override
@Deprecated @Deprecated
@Removal(version="4.2") @Removal(version = "4.2")
public XSSFDateAxis createDateAxis(org.apache.poi.ss.usermodel.charts.AxisPosition pos) { public XSSFDateAxis createDateAxis(org.apache.poi.ss.usermodel.charts.AxisPosition pos) {
long id = axis.size() + 1; long id = axis.size() + 1;
XSSFDateAxis dateAxis = new XSSFDateAxis(this, id, pos); XSSFDateAxis dateAxis = new XSSFDateAxis(this, id, pos);
if (axis.size() == 1) { if (axis.size() == 1) {
ChartAxis ax = axis.get(0); ChartAxis ax = axis.get(0);
ax.crossAxis(dateAxis); ax.crossAxis(dateAxis);
dateAxis.crossAxis(ax); dateAxis.crossAxis(ax);
} }
axis.add(dateAxis); axis.add(dateAxis);
return dateAxis; return dateAxis;
} }
/** /**
* @deprecated use {@link #getAxes()} instead * @deprecated use {@link #getAxes()} instead
*/ */
@Override @Override
@Deprecated @Deprecated
@Removal(version="4.2") @Removal(version = "4.2")
public List<? extends XSSFChartAxis> getAxis() { public List<? extends XSSFChartAxis> getAxis() {
if (axis.isEmpty() && hasAxis()) { if (axis.isEmpty() && hasAxis()) {
parseAxis(); parseAxis();
@ -250,56 +255,57 @@ public final class XSSFChart extends XDDFChart implements Chart, ChartAxisFactor
@Override @Override
@Deprecated @Deprecated
@Removal(version="4.2") @Removal(version = "4.2")
public XSSFManualLayout getManualLayout() { public XSSFManualLayout getManualLayout() {
return new XSSFManualLayout(this); return new XSSFManualLayout(this);
} }
/** /**
* Returns the title static text, or null if none is set. * Returns the title static text, or null if none is set. Note that a title
* Note that a title formula may be set instead. * formula may be set instead.
* @return static title text, if set *
* @deprecated POI 3.16, use {@link #getTitleText()} instead. * @return static title text, if set
*/ * @deprecated POI 3.16, use {@link #getTitleText()} instead.
*/
@Deprecated @Deprecated
@Removal(version="4.0") @Removal(version = "4.0")
public XSSFRichTextString getTitle() { public XSSFRichTextString getTitle() {
return getTitleText(); return getTitleText();
} }
/** /**
* Returns the title static text, or null if none is set. * Returns the title static text, or null if none is set. Note that a title
* Note that a title formula may be set instead. * formula may be set instead. Empty text result is for backward
* Empty text result is for backward compatibility, and could mean the title text is empty or there is a formula instead. * compatibility, and could mean the title text is empty or there is a
* Check for a formula first, falling back on text for cleaner logic. * formula instead. Check for a formula first, falling back on text for
* @return static title text if set, * cleaner logic.
* null if there is no title, *
* empty string if the title text is empty or the title uses a formula instead * @return static title text if set, null if there is no title, empty string
*/ * if the title text is empty or the title uses a formula instead
public XSSFRichTextString getTitleText() { */
if(! chart.isSetTitle()) { public XSSFRichTextString getTitleText() {
return null; if (!chart.isSetTitle()) {
} return null;
}
// TODO Do properly // TODO Do properly
CTTitle title = chart.getTitle(); CTTitle title = chart.getTitle();
StringBuilder text = new StringBuilder(64); StringBuilder text = new StringBuilder(64);
XmlObject[] t = title XmlObject[] t = title.selectPath("declare namespace a='" + XSSFDrawing.NAMESPACE_A + "' .//a:t");
.selectPath("declare namespace a='"+XSSFDrawing.NAMESPACE_A+"' .//a:t"); for (XmlObject element : t) {
for (XmlObject element : t) { NodeList kids = element.getDomNode().getChildNodes();
NodeList kids = element.getDomNode().getChildNodes(); final int count = kids.getLength();
final int count = kids.getLength(); for (int n = 0; n < count; n++) {
for (int n = 0; n < count; n++) { Node kid = kids.item(n);
Node kid = kids.item(n); if (kid instanceof Text) {
if (kid instanceof Text) { text.append(kid.getNodeValue());
text.append(kid.getNodeValue()); }
} }
} }
}
return new XSSFRichTextString(text.toString()); return new XSSFRichTextString(text.toString());
} }
/** /**
* Sets the title text as a static string. * Sets the title text as a static string.
@ -331,7 +337,8 @@ public final class XSSFChart extends XDDFChart implements Chart, ChartAxisFactor
rich = tx.getRich(); rich = tx.getRich();
} else { } else {
rich = tx.addNewRich(); rich = tx.addNewRich();
rich.addNewBodyPr(); // body properties must exist (but can be empty) rich.addNewBodyPr(); // body properties must exist (but can be
// empty)
} }
CTTextParagraph para; CTTextParagraph para;
@ -414,21 +421,22 @@ public final class XSSFChart extends XDDFChart implements Chart, ChartAxisFactor
@Override @Override
@Deprecated @Deprecated
@Removal(version="4.2") @Removal(version = "4.2")
public XSSFChartLegend getOrCreateLegend() { public XSSFChartLegend getOrCreateLegend() {
return new XSSFChartLegend(this); return new XSSFChartLegend(this);
} }
@Deprecated
@Removal(version="4.2")
private boolean hasAxis() {
CTPlotArea ctPlotArea = chart.getPlotArea();
int totalAxisCount = ctPlotArea.sizeOfValAxArray() + ctPlotArea.sizeOfCatAxArray() + ctPlotArea.sizeOfDateAxArray() + ctPlotArea.sizeOfSerAxArray();
return totalAxisCount > 0;
}
@Deprecated @Deprecated
@Removal(version="4.2") @Removal(version = "4.2")
private boolean hasAxis() {
CTPlotArea ctPlotArea = chart.getPlotArea();
int totalAxisCount = ctPlotArea.sizeOfValAxArray() + ctPlotArea.sizeOfCatAxArray() + ctPlotArea
.sizeOfDateAxArray() + ctPlotArea.sizeOfSerAxArray();
return totalAxisCount > 0;
}
@Deprecated
@Removal(version = "4.2")
private void parseAxis() { private void parseAxis() {
// TODO: add other axis types // TODO: add other axis types
parseCategoryAxis(); parseCategoryAxis();
@ -437,7 +445,7 @@ public final class XSSFChart extends XDDFChart implements Chart, ChartAxisFactor
} }
@Deprecated @Deprecated
@Removal(version="4.2") @Removal(version = "4.2")
private void parseCategoryAxis() { private void parseCategoryAxis() {
for (CTCatAx catAx : chart.getPlotArea().getCatAxArray()) { for (CTCatAx catAx : chart.getPlotArea().getCatAxArray()) {
axis.add(new XSSFCategoryAxis(this, catAx)); axis.add(new XSSFCategoryAxis(this, catAx));
@ -445,7 +453,7 @@ public final class XSSFChart extends XDDFChart implements Chart, ChartAxisFactor
} }
@Deprecated @Deprecated
@Removal(version="4.2") @Removal(version = "4.2")
private void parseDateAxis() { private void parseDateAxis() {
for (CTDateAx dateAx : chart.getPlotArea().getDateAxArray()) { for (CTDateAx dateAx : chart.getPlotArea().getDateAxArray()) {
axis.add(new XSSFDateAxis(this, dateAx)); axis.add(new XSSFDateAxis(this, dateAx));
@ -453,7 +461,7 @@ public final class XSSFChart extends XDDFChart implements Chart, ChartAxisFactor
} }
@Deprecated @Deprecated
@Removal(version="4.2") @Removal(version = "4.2")
private void parseValueAxis() { private void parseValueAxis() {
for (CTValAx valAx : chart.getPlotArea().getValAxArray()) { for (CTValAx valAx : chart.getPlotArea().getValAxArray()) {
axis.add(new XSSFValueAxis(this, valAx)); axis.add(new XSSFValueAxis(this, valAx));

View File

@ -103,7 +103,7 @@ public final class XSSFShapeGroup extends XSSFShape implements ShapeContainer<XS
XSSFTextBox shape = new XSSFTextBox(getDrawing(), ctShape); XSSFTextBox shape = new XSSFTextBox(getDrawing(), ctShape);
shape.parent = this; shape.parent = this;
shape.anchor = anchor; shape.anchor = anchor;
shape.getCTShape().getSpPr().setXfrm(anchor.getCTTransform2D()); shape.setXfrm(anchor.getCTTransform2D());
return shape; return shape;
} }
@ -122,7 +122,7 @@ public final class XSSFShapeGroup extends XSSFShape implements ShapeContainer<XS
XSSFSimpleShape shape = new XSSFSimpleShape(getDrawing(), ctShape); XSSFSimpleShape shape = new XSSFSimpleShape(getDrawing(), ctShape);
shape.parent = this; shape.parent = this;
shape.anchor = anchor; shape.anchor = anchor;
shape.getCTShape().getSpPr().setXfrm(anchor.getCTTransform2D()); shape.setXfrm(anchor.getCTTransform2D());
return shape; return shape;
} }
@ -179,9 +179,9 @@ public final class XSSFShapeGroup extends XSSFShape implements ShapeContainer<XS
XSSFShapeGroup shape = new XSSFShapeGroup(getDrawing(), ctShape); XSSFShapeGroup shape = new XSSFShapeGroup(getDrawing(), ctShape);
shape.parent = this; shape.parent = this;
shape.anchor = anchor; shape.anchor = anchor;
// TODO: calculate bounding rectangle on anchor and set off/ext correctly // TODO: calculate bounding rectangle on anchor and set off/ext correctly
CTGroupTransform2D xfrm = shape.getCTGroupShape().getGrpSpPr().getXfrm(); CTGroupTransform2D xfrm = shape.getCTGroupShape().getGrpSpPr().getXfrm();
CTTransform2D t2 = anchor.getCTTransform2D(); CTTransform2D t2 = anchor.getCTTransform2D();
xfrm.setOff(t2.getOff()); xfrm.setOff(t2.getOff());
@ -190,7 +190,7 @@ public final class XSSFShapeGroup extends XSSFShape implements ShapeContainer<XS
xfrm.setChExt(t2.getExt()); xfrm.setChExt(t2.getExt());
xfrm.setFlipH(t2.getFlipH()); xfrm.setFlipH(t2.getFlipH());
xfrm.setFlipV(t2.getFlipV()); xfrm.setFlipV(t2.getFlipV());
return shape; return shape;
} }
@ -220,6 +220,7 @@ public final class XSSFShapeGroup extends XSSFShape implements ShapeContainer<XS
chExt.setCy(y2); chExt.setCy(y2);
} }
@Override
protected CTShapeProperties getShapeProperties() { protected CTShapeProperties getShapeProperties() {
throw new IllegalStateException("Not supported for shape group"); throw new IllegalStateException("Not supported for shape group");
} }

View File

@ -0,0 +1,81 @@
/* ====================================================================
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.xddf.usermodel.text;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import org.apache.poi.util.Units;
import org.junit.Test;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties;
public class TestXDDFTextBodyProperties {
@Test
public void testProperties() throws IOException {
XDDFBodyProperties body = new XDDFTextBody(null).getBodyProperties();
CTTextBodyProperties props = body.getXmlObject();
body.setBottomInset(null);
assertFalse(props.isSetBIns());
body.setBottomInset(3.6);
assertTrue(props.isSetBIns());
assertEquals(Units.toEMU(3.6), props.getBIns());
body.setLeftInset(null);
assertFalse(props.isSetLIns());
body.setLeftInset(3.6);
assertTrue(props.isSetLIns());
assertEquals(Units.toEMU(3.6), props.getLIns());
body.setRightInset(null);
assertFalse(props.isSetRIns());
body.setRightInset(3.6);
assertTrue(props.isSetRIns());
assertEquals(Units.toEMU(3.6), props.getRIns());
body.setTopInset(null);
assertFalse(props.isSetTIns());
body.setTopInset(3.6);
assertTrue(props.isSetTIns());
assertEquals(Units.toEMU(3.6), props.getTIns());
body.setAutoFit(null);
assertFalse(props.isSetNoAutofit());
assertFalse(props.isSetNormAutofit());
assertFalse(props.isSetSpAutoFit());
body.setAutoFit(new XDDFNoAutoFit());
assertTrue(props.isSetNoAutofit());
assertFalse(props.isSetNormAutofit());
assertFalse(props.isSetSpAutoFit());
body.setAutoFit(new XDDFNormalAutoFit());
assertFalse(props.isSetNoAutofit());
assertTrue(props.isSetNormAutofit());
assertFalse(props.isSetSpAutoFit());
body.setAutoFit(new XDDFShapeAutoFit());
assertFalse(props.isSetNoAutofit());
assertFalse(props.isSetNormAutofit());
assertTrue(props.isSetSpAutoFit());
}
}

View File

@ -0,0 +1,135 @@
/* ====================================================================
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.xddf.usermodel.text;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.List;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import org.apache.poi.xslf.usermodel.XSLFTextShape;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFTextBox;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.Test;
public class TestXDDFTextRun {
@Test
public void testTextRunPropertiesInSlide() throws IOException {
try (XMLSlideShow ppt = new XMLSlideShow()) {
XSLFSlide slide = ppt.createSlide();
XSLFTextShape sh = slide.createAutoShape();
sh.addNewTextParagraph();
XDDFTextBody body = sh.getTextBody();
XDDFTextParagraph para = body.getParagraph(0);
XDDFTextRun r = para.appendRegularRun("text");
assertEquals(LocaleUtil.getUserLocale().toLanguageTag(), r.getLanguage().toLanguageTag());
assertNull(r.getCharacterSpacing());
r.setCharacterSpacing(3.0);
assertEquals(3., r.getCharacterSpacing(), 0);
r.setCharacterSpacing(-3.0);
assertEquals(-3., r.getCharacterSpacing(), 0);
r.setCharacterSpacing(0.0);
assertEquals(0., r.getCharacterSpacing(), 0);
assertEquals(11.0, r.getFontSize(), 0);
r.setFontSize(13.0);
assertEquals(13.0, r.getFontSize(), 0);
assertFalse(r.isSuperscript());
r.setSuperscript(0.8);
assertTrue(r.isSuperscript());
r.setSuperscript(null);
assertFalse(r.isSuperscript());
assertFalse(r.isSubscript());
r.setSubscript(0.7);
assertTrue(r.isSubscript());
r.setSubscript(null);
assertFalse(r.isSubscript());
r.setBaseline(0.9);
assertTrue(r.isSuperscript());
r.setBaseline(-0.6);
assertTrue(r.isSubscript());
}
}
@Test
public void testTextRunPropertiesInSheet() throws IOException {
try (XSSFWorkbook wb = new XSSFWorkbook()) {
XSSFSheet sheet = wb.createSheet();
XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFTextBox shape = drawing.createTextbox(new XSSFClientAnchor(0, 0, 0, 0, 2, 2, 3, 4));
shape.addNewTextParagraph().addNewTextRun().setText("Line 1");
XDDFTextBody body = shape.getTextBody();
XDDFTextParagraph para = body.getParagraph(1);
List<XDDFTextRun> runs = para.getTextRuns();
assertEquals(1, runs.size());
XDDFTextRun run = runs.get(0);
assertEquals("Line 1", run.getText());
assertFalse(run.isStrikeThrough());
run.setStrikeThrough(StrikeType.SINGLE_STRIKE);
assertTrue(run.isStrikeThrough());
run.setStrikeThrough(StrikeType.NO_STRIKE);
assertFalse(run.isStrikeThrough());
assertFalse(run.isCapitals());
run.setCapitals(CapsType.SMALL);
assertTrue(run.isCapitals());
run.setCapitals(CapsType.NONE);
assertFalse(run.isCapitals());
assertFalse(run.isBold());
run.setBold(true);
assertTrue(run.isBold());
run.setBold(false);
assertFalse(run.isBold());
assertFalse(run.isItalic());
run.setItalic(true);
assertTrue(run.isItalic());
run.setItalic(false);
assertFalse(run.isItalic());
assertFalse(run.isUnderline());
run.setUnderline(UnderlineType.WAVY_DOUBLE);
assertTrue(run.isUnderline());
run.setUnderline(UnderlineType.NONE);
assertFalse(run.isUnderline());
assertNotNull(run.getText());
}
}
}

View File

@ -30,6 +30,7 @@ import java.awt.Color;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import org.apache.poi.POIDataSamples; import org.apache.poi.POIDataSamples;
import org.apache.poi.hslf.usermodel.HSLFTextShape; import org.apache.poi.hslf.usermodel.HSLFTextShape;
@ -38,6 +39,8 @@ import org.apache.poi.sl.usermodel.SlideShow;
import org.apache.poi.sl.usermodel.SlideShowFactory; import org.apache.poi.sl.usermodel.SlideShowFactory;
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign; import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;
import org.apache.poi.sl.usermodel.VerticalAlignment; import org.apache.poi.sl.usermodel.VerticalAlignment;
import org.apache.poi.xddf.usermodel.text.XDDFBodyProperties;
import org.apache.poi.xddf.usermodel.text.XDDFTextBody;
import org.apache.poi.xslf.XSLFTestDataSamples; import org.apache.poi.xslf.XSLFTestDataSamples;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
@ -83,6 +86,8 @@ public class TestXSLFTextShape {
assertEquals("Title Slide",layout.getName()); assertEquals("Title Slide",layout.getName());
XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0); XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0);
XDDFTextBody tb1 = shape1.getTextBody();
XDDFBodyProperties tbp1 = tb1.getBodyProperties();
CTPlaceholder ph1 = shape1.getPlaceholderDetails().getCTPlaceholder(false); CTPlaceholder ph1 = shape1.getPlaceholderDetails().getCTPlaceholder(false);
assertEquals(STPlaceholderType.CTR_TITLE, ph1.getType()); assertEquals(STPlaceholderType.CTR_TITLE, ph1.getType());
// anchor is not defined in the shape // anchor is not defined in the shape
@ -104,15 +109,24 @@ public class TestXSLFTextShape {
assertEquals(3.6, shape1.getTopInset(), 0); // 0.05" assertEquals(3.6, shape1.getTopInset(), 0); // 0.05"
assertEquals(3.6, shape1.getBottomInset(), 0); // 0.05" assertEquals(3.6, shape1.getBottomInset(), 0); // 0.05"
assertEquals(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment()); assertEquals(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment());
assertNull(tbp1.getLeftInset());
assertNull(tbp1.getRightInset());
assertNull(tbp1.getBottomInset());
assertNull(tbp1.getTopInset());
assertNull(tbp1.getAnchoring());
// now check text properties // now check text properties
assertEquals("Centered Title", shape1.getText()); assertEquals("Centered Title", shape1.getText());
assertEquals("Centered Title",
tb1.getParagraphs().stream().map(p -> p.getText()).collect(Collectors.joining("\n")));
XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0); XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals("Calibri", r1.getFontFamily()); assertEquals("Calibri", r1.getFontFamily());
assertEquals(44.0, r1.getFontSize(), 0); assertEquals(44.0, r1.getFontSize(), 0);
assertTrue(sameColor(Color.black, r1.getFontColor())); assertTrue(sameColor(Color.black, r1.getFontColor()));
XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1); XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1);
XDDFTextBody tb2 = shape2.getTextBody();
XDDFBodyProperties tbp2 = tb2.getBodyProperties();
CTPlaceholder ph2 = shape2.getPlaceholderDetails().getCTPlaceholder(false); CTPlaceholder ph2 = shape2.getPlaceholderDetails().getCTPlaceholder(false);
assertEquals(STPlaceholderType.SUB_TITLE, ph2.getType()); assertEquals(STPlaceholderType.SUB_TITLE, ph2.getType());
// anchor is not defined in the shape // anchor is not defined in the shape
@ -134,8 +148,14 @@ public class TestXSLFTextShape {
assertEquals(3.6, shape2.getTopInset(), 0); // 0.05" assertEquals(3.6, shape2.getTopInset(), 0); // 0.05"
assertEquals(3.6, shape2.getBottomInset(), 0); // 0.05" assertEquals(3.6, shape2.getBottomInset(), 0); // 0.05"
assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment()); assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment());
assertNull(tbp2.getLeftInset());
assertNull(tbp2.getRightInset());
assertNull(tbp2.getBottomInset());
assertNull(tbp2.getTopInset());
assertNull(tbp2.getAnchoring());
assertEquals("subtitle", shape2.getText()); assertEquals("subtitle", shape2.getText());
assertEquals("subtitle", tb2.getParagraphs().stream().map(p -> p.getText()).collect(Collectors.joining("\n")));
XSLFTextRun r2 = shape2.getTextParagraphs().get(0).getTextRuns().get(0); XSLFTextRun r2 = shape2.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals("Calibri", r2.getFontFamily()); assertEquals("Calibri", r2.getFontFamily());
assertEquals(32.0, r2.getFontSize(), 0); assertEquals(32.0, r2.getFontSize(), 0);

View File

@ -16,12 +16,23 @@
==================================================================== */ ==================================================================== */
package org.apache.poi.xssf.usermodel; package org.apache.poi.xssf.usermodel;
import static org.junit.Assert.*; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.awt.Color; import java.awt.Color;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import org.apache.poi.ss.usermodel.VerticalAlignment; import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.xddf.usermodel.text.XDDFBodyProperties;
import org.apache.poi.xddf.usermodel.text.XDDFNoAutoFit;
import org.apache.poi.xddf.usermodel.text.XDDFNormalAutoFit;
import org.apache.poi.xddf.usermodel.text.XDDFShapeAutoFit;
import org.apache.poi.xddf.usermodel.text.XDDFTextBody;
import org.apache.poi.xddf.usermodel.text.XDDFTextParagraph;
import org.junit.Test; import org.junit.Test;
public class TestXSSFSimpleShape { public class TestXSSFSimpleShape {
@ -31,43 +42,53 @@ public class TestXSSFSimpleShape {
try { try {
XSSFSheet sheet = wb.createSheet(); XSSFSheet sheet = wb.createSheet();
XSSFDrawing drawing = sheet.createDrawingPatriarch(); XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFTextBox shape = drawing.createTextbox(new XSSFClientAnchor(0, 0, 0, 0, 2, 2, 3, 4)); XSSFTextBox shape = drawing.createTextbox(new XSSFClientAnchor(0, 0, 0, 0, 2, 2, 3, 4));
XSSFRichTextString rt = new XSSFRichTextString("Test String"); XSSFRichTextString rt = new XSSFRichTextString("Test String");
XSSFFont font = wb.createFont(); XSSFFont font = wb.createFont();
Color color = new Color(0, 255, 255); Color color = new Color(0, 255, 255);
font.setColor(new XSSFColor(color, wb.getStylesSource().getIndexedColors())); font.setColor(new XSSFColor(color, wb.getStylesSource().getIndexedColors()));
font.setFontName("Arial"); font.setFontName("Arial");
rt.applyFont(font); rt.applyFont(font);
shape.setText(rt); shape.setText(rt);
assertNotNull(shape.getCTShape()); assertNotNull(shape.getCTShape());
assertNotNull(shape.iterator()); assertNotNull(shape.iterator());
assertNotNull(XSSFSimpleShape.prototype()); assertNotNull(XSSFSimpleShape.prototype());
for(ListAutoNumber nr : ListAutoNumber.values()) { for (ListAutoNumber nr : ListAutoNumber.values()) {
shape.getTextParagraphs().get(0).setBullet(nr); shape.getTextParagraphs().get(0).setBullet(nr);
assertNotNull(shape.getText()); assertNotNull(shape.getText());
} }
shape.getTextParagraphs().get(0).setBullet(false); shape.getTextParagraphs().get(0).setBullet(false);
assertNotNull(shape.getText()); assertNotNull(shape.getText());
shape.setText("testtext"); shape.setText("testtext");
assertEquals("testtext", shape.getText()); assertEquals("testtext", shape.getText());
shape.setText(new XSSFRichTextString()); shape.setText(new XSSFRichTextString());
assertEquals("null", shape.getText()); assertEquals("null", shape.getText());
shape.addNewTextParagraph(); shape.addNewTextParagraph();
shape.addNewTextParagraph("test-other-text"); shape.addNewTextParagraph("test-other-text");
shape.addNewTextParagraph(new XSSFRichTextString("rtstring")); shape.addNewTextParagraph(new XSSFRichTextString("rtstring"));
shape.addNewTextParagraph(new XSSFRichTextString()); shape.addNewTextParagraph(new XSSFRichTextString());
assertEquals("null\n\ntest-other-text\nrtstring\nnull", shape.getText()); assertEquals("null\n\ntest-other-text\nrtstring\nnull", shape.getText());
XDDFTextBody body = shape.getTextBody();
assertNotNull(body);
List<XDDFTextParagraph> paragraphs = body.getParagraphs();
assertEquals(5, paragraphs.size());
assertEquals("null", body.getParagraph(0).getText());
assertEquals("", body.getParagraph(1).getText());
assertEquals("test-other-text", body.getParagraph(2).getText());
assertEquals("rtstring", body.getParagraph(3).getText());
assertEquals("null", body.getParagraph(4).getText());
assertEquals(TextHorizontalOverflow.OVERFLOW, shape.getTextHorizontalOverflow()); assertEquals(TextHorizontalOverflow.OVERFLOW, shape.getTextHorizontalOverflow());
shape.setTextHorizontalOverflow(TextHorizontalOverflow.CLIP); shape.setTextHorizontalOverflow(TextHorizontalOverflow.CLIP);
assertEquals(TextHorizontalOverflow.CLIP, shape.getTextHorizontalOverflow()); assertEquals(TextHorizontalOverflow.CLIP, shape.getTextHorizontalOverflow());
@ -77,7 +98,7 @@ public class TestXSSFSimpleShape {
assertEquals(TextHorizontalOverflow.OVERFLOW, shape.getTextHorizontalOverflow()); assertEquals(TextHorizontalOverflow.OVERFLOW, shape.getTextHorizontalOverflow());
shape.setTextHorizontalOverflow(null); shape.setTextHorizontalOverflow(null);
assertEquals(TextHorizontalOverflow.OVERFLOW, shape.getTextHorizontalOverflow()); assertEquals(TextHorizontalOverflow.OVERFLOW, shape.getTextHorizontalOverflow());
assertEquals(TextVerticalOverflow.OVERFLOW, shape.getTextVerticalOverflow()); assertEquals(TextVerticalOverflow.OVERFLOW, shape.getTextVerticalOverflow());
shape.setTextVerticalOverflow(TextVerticalOverflow.CLIP); shape.setTextVerticalOverflow(TextVerticalOverflow.CLIP);
assertEquals(TextVerticalOverflow.CLIP, shape.getTextVerticalOverflow()); assertEquals(TextVerticalOverflow.CLIP, shape.getTextVerticalOverflow());
@ -108,38 +129,57 @@ public class TestXSSFSimpleShape {
shape.setTextDirection(null); shape.setTextDirection(null);
assertEquals(TextDirection.HORIZONTAL, shape.getTextDirection()); assertEquals(TextDirection.HORIZONTAL, shape.getTextDirection());
XDDFBodyProperties props = body.getBodyProperties();
assertNotNull(props);
assertEquals(3.6, shape.getBottomInset(), 0.01); assertEquals(3.6, shape.getBottomInset(), 0.01);
assertNull(props.getBottomInset());
shape.setBottomInset(12.32); shape.setBottomInset(12.32);
assertEquals(12.32, shape.getBottomInset(), 0.01); assertEquals(12.32, shape.getBottomInset(), 0.01);
assertEquals(12.32, props.getBottomInset(), 0.01);
shape.setBottomInset(-1); shape.setBottomInset(-1);
assertEquals(3.6, shape.getBottomInset(), 0.01); assertEquals(3.6, shape.getBottomInset(), 0.01);
assertNull(props.getBottomInset());
shape.setBottomInset(-1); shape.setBottomInset(-1);
assertEquals(3.6, shape.getBottomInset(), 0.01); assertEquals(3.6, shape.getBottomInset(), 0.01);
assertNull(props.getBottomInset());
assertEquals(3.6, shape.getLeftInset(), 0.01); assertEquals(3.6, shape.getLeftInset(), 0.01);
assertNull(props.getLeftInset());
shape.setLeftInset(12.31); shape.setLeftInset(12.31);
assertEquals(12.31, shape.getLeftInset(), 0.01); assertEquals(12.31, shape.getLeftInset(), 0.01);
assertEquals(12.31, props.getLeftInset(), 0.01);
shape.setLeftInset(-1); shape.setLeftInset(-1);
assertEquals(3.6, shape.getLeftInset(), 0.01); assertEquals(3.6, shape.getLeftInset(), 0.01);
assertNull(props.getLeftInset());
shape.setLeftInset(-1); shape.setLeftInset(-1);
assertEquals(3.6, shape.getLeftInset(), 0.01); assertEquals(3.6, shape.getLeftInset(), 0.01);
assertNull(props.getLeftInset());
assertEquals(3.6, shape.getRightInset(), 0.01); assertEquals(3.6, shape.getRightInset(), 0.01);
assertNull(props.getRightInset());
shape.setRightInset(13.31); shape.setRightInset(13.31);
assertEquals(13.31, shape.getRightInset(), 0.01); assertEquals(13.31, shape.getRightInset(), 0.01);
assertEquals(13.31, props.getRightInset(), 0.01);
shape.setRightInset(-1); shape.setRightInset(-1);
assertEquals(3.6, shape.getRightInset(), 0.01); assertEquals(3.6, shape.getRightInset(), 0.01);
assertNull(props.getRightInset());
shape.setRightInset(-1); shape.setRightInset(-1);
assertEquals(3.6, shape.getRightInset(), 0.01); assertEquals(3.6, shape.getRightInset(), 0.01);
assertNull(props.getRightInset());
assertEquals(3.6, shape.getTopInset(), 0.01); assertEquals(3.6, shape.getTopInset(), 0.01);
assertNull(props.getTopInset());
shape.setTopInset(23.31); shape.setTopInset(23.31);
assertEquals(23.31, shape.getTopInset(), 0.01); assertEquals(23.31, shape.getTopInset(), 0.01);
assertEquals(23.31, props.getTopInset(), 0.01);
shape.setTopInset(-1); shape.setTopInset(-1);
assertEquals(3.6, shape.getTopInset(), 0.01); assertEquals(3.6, shape.getTopInset(), 0.01);
assertNull(props.getTopInset());
shape.setTopInset(-1); shape.setTopInset(-1);
assertEquals(3.6, shape.getTopInset(), 0.01); assertEquals(3.6, shape.getTopInset(), 0.01);
assertNull(props.getTopInset());
assertTrue(shape.getWordWrap()); assertTrue(shape.getWordWrap());
shape.setWordWrap(false); shape.setWordWrap(false);
assertFalse(shape.getWordWrap()); assertFalse(shape.getWordWrap());
@ -147,23 +187,27 @@ public class TestXSSFSimpleShape {
assertTrue(shape.getWordWrap()); assertTrue(shape.getWordWrap());
assertEquals(TextAutofit.NORMAL, shape.getTextAutofit()); assertEquals(TextAutofit.NORMAL, shape.getTextAutofit());
assertTrue(props.getAutoFit() instanceof XDDFNormalAutoFit);
shape.setTextAutofit(TextAutofit.NORMAL); shape.setTextAutofit(TextAutofit.NORMAL);
assertEquals(TextAutofit.NORMAL, shape.getTextAutofit()); assertEquals(TextAutofit.NORMAL, shape.getTextAutofit());
assertTrue(props.getAutoFit() instanceof XDDFNormalAutoFit);
shape.setTextAutofit(TextAutofit.SHAPE); shape.setTextAutofit(TextAutofit.SHAPE);
assertEquals(TextAutofit.SHAPE, shape.getTextAutofit()); assertEquals(TextAutofit.SHAPE, shape.getTextAutofit());
assertTrue(props.getAutoFit() instanceof XDDFShapeAutoFit);
shape.setTextAutofit(TextAutofit.NONE); shape.setTextAutofit(TextAutofit.NONE);
assertEquals(TextAutofit.NONE, shape.getTextAutofit()); assertEquals(TextAutofit.NONE, shape.getTextAutofit());
assertTrue(props.getAutoFit() instanceof XDDFNoAutoFit);
assertEquals(5, shape.getShapeType()); assertEquals(5, shape.getShapeType());
shape.setShapeType(23); shape.setShapeType(23);
assertEquals(23, shape.getShapeType()); assertEquals(23, shape.getShapeType());
// TODO: should this be supported? // TODO: should this be supported?
// shape.setShapeType(-1); // shape.setShapeType(-1);
// assertEquals(-1, shape.getShapeType()); // assertEquals(-1, shape.getShapeType());
// shape.setShapeType(-1); // shape.setShapeType(-1);
// assertEquals(-1, shape.getShapeType()); // assertEquals(-1, shape.getShapeType());
assertNotNull(shape.getShapeProperties()); assertNotNull(shape.getShapeProperties());
} finally { } finally {
wb.close(); wb.close();