From: Yegor Kozlov Date: Wed, 17 Aug 2011 10:18:31 +0000 (+0000) Subject: support for tables and hyperlinks in XSLF X-Git-Tag: REL_3_8_BETA4~1^2~25 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=b26674fef5c51f01b099efac2f98b36fa155acf9;p=poi.git support for tables and hyperlinks in XSLF git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1158611 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/documentation/content/xdocs/index.xml b/src/documentation/content/xdocs/index.xml index 56e89aa2b4..61fc1de6f9 100644 --- a/src/documentation/content/xdocs/index.xml +++ b/src/documentation/content/xdocs/index.xml @@ -32,8 +32,8 @@ -
6 June 2011 - POI 3.8 beta 3 available -

The Apache POI team is pleased to announce the release of 3.8 beta 3. +

22 August 2011 - POI 3.8 beta 4 available +

The Apache POI team is pleased to announce the release of 3.8 beta 4. This includes a large number of bug fixes and enhancements.

A full list of changes is available in the change log. diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index 96acff77ec..4c9f245e02 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + support for tables and hyperlinks 51535 - correct signed vs unsigned short reading in NDocumentInputStream 51634 - support SXSSF streaming from templates initial support for XSLF usermodel API diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java index 1869749970..feb77a4041 100755 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java @@ -48,19 +48,10 @@ import java.util.List; * @author Yegor Kozlov */ @Beta -public class XSLFAutoShape extends XSLFSimpleShape { - private final List _paragraphs; +public class XSLFAutoShape extends XSLFTextShape { /*package*/ XSLFAutoShape(CTShape shape, XSLFSheet sheet) { super(shape, sheet); - - _paragraphs = new ArrayList(); - if (shape.isSetTxBody()) { - CTTextBody txBody = shape.getTxBody(); - for (CTTextParagraph p : txBody.getPList()) { - _paragraphs.add(new XSLFTextParagraph(p)); - } - } } /*package*/ @@ -74,36 +65,6 @@ public class XSLFAutoShape extends XSLFSimpleShape { } } - // textual properties - public String getText() { - StringBuilder out = new StringBuilder(); - for (XSLFTextParagraph p : _paragraphs) { - if (out.length() > 0) out.append('\n'); - out.append(p.getText()); - } - return out.toString(); - } - - public List getTextParagraphs() { - return _paragraphs; - } - - public XSLFTextParagraph addNewTextParagraph() { - CTShape shape = (CTShape) getXmlObject(); - CTTextBody txBody; - if (!shape.isSetTxBody()) { - txBody = shape.addNewTxBody(); - txBody.addNewBodyPr(); - txBody.addNewLstStyle(); - } else { - txBody = shape.getTxBody(); - } - CTTextParagraph p = txBody.addNewP(); - XSLFTextParagraph paragraph = new XSLFTextParagraph(p); - _paragraphs.add(paragraph); - return paragraph; - } - /** * @param shapeId 1-based shapeId */ @@ -160,268 +121,15 @@ public class XSLFAutoShape extends XSLFSimpleShape { return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]); } - /** - * Sets the type of vertical alignment for the text. - * One of the Anchor* constants defined in this class. - * - * @param anchor - the type of alignment. Default is {@link VerticalAlignment#TOP} - */ - public void setVerticalAlignment(VerticalAlignment anchor){ - CTShape shape = (CTShape) getXmlObject(); - if (shape.isSetTxBody()) { - CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr(); - if(anchor == null) { - if(bodyPr.isSetAnchor()) bodyPr.unsetAnchor(); - } else { - bodyPr.setAnchor(STTextAnchoringType.Enum.forInt(anchor.ordinal() + 1)); - } - } - } - - /** - * Returns the type of vertical alignment for the text. - * - * @return the type of alignment - */ - public VerticalAlignment getVerticalAlignment(){ - CTShape shape = (CTShape) getXmlObject(); - if (shape.isSetTxBody()) { - STTextAnchoringType.Enum val = shape.getTxBody().getBodyPr().getAnchor(); - if(val != null){ - return VerticalAlignment.values()[val.intValue() - 1]; - } - } - return VerticalAlignment.TOP; - } - - /** - * - * @param orientation vertical orientation of the text - */ - public void setTextDirection(TextDirection orientation){ - CTShape shape = (CTShape) getXmlObject(); - if (shape.isSetTxBody()) { - CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr(); - if(orientation == null) { - if(bodyPr.isSetVert()) bodyPr.unsetVert(); - } else { - bodyPr.setVert(STTextVerticalType.Enum.forInt(orientation.ordinal() + 1)); - } - } - } - - /** - * @return vertical orientation of the text - */ - public TextDirection getTextDirection(){ - CTShape shape = (CTShape) getXmlObject(); - if (shape.isSetTxBody()) { - STTextVerticalType.Enum val = shape.getTxBody().getBodyPr().getVert(); - if(val != null){ - return TextDirection.values()[val.intValue() - 1]; - } - } - return TextDirection.HORIZONTAL; - } - /** - * 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. - * - * @return the bottom margin or -1 if not set - */ - public double getMarginBottom(){ - CTShape shape = (CTShape) getXmlObject(); - if (shape.isSetTxBody()) { - CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr(); - return bodyPr.isSetBIns() ? Units.toPoints(bodyPr.getBIns()) : -1; - } - return -1; - } - - /** - * 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. - * - * @return the left margin - */ - public double getMarginLeft(){ - CTShape shape = (CTShape) getXmlObject(); - if (shape.isSetTxBody()) { - CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr(); - return bodyPr.isSetLIns() ? Units.toPoints(bodyPr.getLIns()) : -1; - } - return -1; - } - - /** - * 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. - * - * @return the right margin - */ - public double getMarginRight(){ - CTShape shape = (CTShape) getXmlObject(); - if (shape.isSetTxBody()) { - CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr(); - return bodyPr.isSetRIns() ? Units.toPoints(bodyPr.getRIns()) : -1; - } - return -1; - } - - /** - * 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. - * - * @return the top margin - */ - public double getMarginTop(){ - CTShape shape = (CTShape) getXmlObject(); - if (shape.isSetTxBody()) { - CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr(); - return bodyPr.isSetTIns() ? Units.toPoints(bodyPr.getTIns()) : -1; - } - return -1; - } - - /** - * Sets the botom margin. - * @see #getMarginBottom() - * - * @param margin the bottom margin - */ - public void setMarginBottom(double margin){ - CTShape shape = (CTShape) getXmlObject(); - if (shape.isSetTxBody()) { - CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr(); - if(margin == -1) bodyPr.unsetBIns(); - else bodyPr.setBIns(Units.toEMU(margin)); - } - } - - /** - * Sets the left margin. - * @see #getMarginLeft() - * - * @param margin the left margin - */ - public void setMarginLeft(double margin){ - CTShape shape = (CTShape) getXmlObject(); - if (shape.isSetTxBody()) { - CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr(); - if(margin == -1) bodyPr.unsetLIns(); - else bodyPr.setLIns(Units.toEMU(margin)); - } - } - - /** - * Sets the right margin. - * @see #getMarginRight() - * - * @param margin the right margin - */ - public void setMarginRight(double margin){ - CTShape shape = (CTShape) getXmlObject(); - if (shape.isSetTxBody()) { - CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr(); - if(margin == -1) bodyPr.unsetRIns(); - else bodyPr.setRIns(Units.toEMU(margin)); - } - } - - /** - * Sets the top margin. - * @see #getMarginTop() - * - * @param margin the top margin - */ - public void setMarginTop(double margin){ - CTShape shape = (CTShape) getXmlObject(); - if (shape.isSetTxBody()) { - CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr(); - if(margin == -1) bodyPr.unsetTIns(); - else bodyPr.setTIns(Units.toEMU(margin)); - } - } - - - /** - * Returns the value indicating word wrap. - * One of the Wrap* constants defined in this class. - * - * @return the value indicating word wrap - */ - public boolean getWordWrap(){ + protected CTTextBody getTextBody(boolean create){ CTShape shape = (CTShape) getXmlObject(); - if (shape.isSetTxBody()) { - return shape.getTxBody().getBodyPr().getWrap() == STTextWrappingType.SQUARE; - } - return false; - } - - /** - * Specifies how the text should be wrapped - * - * @param wrap the value indicating how the text should be wrapped - */ - public void setWordWrap(boolean wrap){ - CTShape shape = (CTShape) getXmlObject(); - if (shape.isSetTxBody()) { - shape.getTxBody().getBodyPr().setWrap(wrap ? STTextWrappingType.SQUARE : STTextWrappingType.NONE); - } - } - - /** - * - * Specifies that a shape should be auto-fit to fully contain the text 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 - */ - public void setTextAutofit(TextAutofit value){ - CTShape shape = (CTShape) getXmlObject(); - if (shape.isSetTxBody()) { - CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr(); - if(bodyPr.isSetSpAutoFit()) bodyPr.unsetSpAutoFit(); - if(bodyPr.isSetNoAutofit()) bodyPr.unsetNoAutofit(); - if(bodyPr.isSetNormAutofit()) bodyPr.unsetNormAutofit(); - - switch(value){ - case NONE: bodyPr.addNewNoAutofit(); break; - case NORMAL: bodyPr.addNewNormAutofit(); break; - case SHAPE: bodyPr.addNewSpAutoFit(); break; - } - } - } - - /** - * - * @return type of autofit - */ - public TextAutofit getTextAutofit(){ - CTShape shape = (CTShape) getXmlObject(); - if (shape.isSetTxBody()) { - CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr(); - if(bodyPr.isSetNoAutofit()) return TextAutofit.NONE; - else if (bodyPr.isSetNormAutofit()) return TextAutofit.NORMAL; - else if (bodyPr.isSetSpAutoFit()) return TextAutofit.SHAPE; - } - return TextAutofit.NORMAL; - } - - - @Override - void onCopy(XSLFSheet srcSheet){ - CTShape shape = (CTShape) getXmlObject(); - if (!shape.isSetTxBody()) return; - - CTPlaceholder ph = shape.getNvSpPr().getNvPr().getPh(); - if(ph == null || !ph.isSetType()) return; - - if(ph.getType() == STPlaceholderType.TITLE){ - + CTTextBody txBody = shape.getTxBody(); + if (txBody == null && create) { + txBody = shape.addNewTxBody(); + txBody.addNewBodyPr(); + txBody.addNewLstStyle(); } + return txBody; } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFDrawing.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFDrawing.java index ab8c1658fe..e731a632d6 100755 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFDrawing.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFDrawing.java @@ -24,6 +24,7 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector; import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape; import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture; import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; +import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame; import java.awt.*; @@ -97,4 +98,12 @@ public class XSLFDrawing { shape.setAnchor(new Rectangle()); return shape; } + + public XSLFTable createTable(){ + CTGraphicalObjectFrame obj = _spTree.addNewGraphicFrame(); + obj.set(XSLFTable.prototype(_shapeId++)); + XSLFTable shape = new XSLFTable(obj, _sheet); + shape.setAnchor(new Rectangle()); + return shape; + } } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGraphicFrame.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGraphicFrame.java index 0abad44f30..7e0990331f 100755 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGraphicFrame.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGraphicFrame.java @@ -44,6 +44,10 @@ public class XSLFGraphicFrame extends XSLFShape { return _shape; } + public XSLFSheet getSheet(){ + return _sheet; + } + public int getShapeType(){ throw new RuntimeException("NotImplemented"); } @@ -64,16 +68,14 @@ public class XSLFGraphicFrame extends XSLFShape { throw new RuntimeException("NotImplemented"); } - public ShapeGroup getParent(){ - throw new RuntimeException("NotImplemented"); - } - public Shape[] getShapes(){ - throw new RuntimeException("NotImplemented"); + static XSLFGraphicFrame create(CTGraphicalObjectFrame shape, XSLFSheet sheet){ + String uri = shape.getGraphic().getGraphicData().getUri(); + if(XSLFTable.TABLE_URI.equals(uri)){ + return new XSLFTable(shape, sheet); + } else { + return new XSLFGraphicFrame(shape, sheet); + } } - - public boolean removeShape(Shape shape){ - throw new RuntimeException("NotImplemented"); - } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFHyperlink.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFHyperlink.java new file mode 100644 index 0000000000..5a25851b5c --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFHyperlink.java @@ -0,0 +1,69 @@ +/* ==================================================================== + 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.xslf.usermodel; + +import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.openxml4j.opc.TargetMode; +import org.apache.poi.util.Internal; +import org.openxmlformats.schemas.drawingml.x2006.main.CTHyperlink; + +import java.net.URI; + +/** + * @author Yegor Kozlov + */ +public class XSLFHyperlink { + final XSLFTextRun _r; + final CTHyperlink _link; + + XSLFHyperlink(CTHyperlink link, XSLFTextRun r){ + _r = r; + _link = link; + } + + @Internal + public CTHyperlink getXmlObject(){ + return _link; + } + + public void setAddress(String address){ + XSLFSheet sheet = _r.getParentParagraph().getParentShape().getSheet(); + PackageRelationship rel = + sheet.getPackagePart(). + addExternalRelationship(address, XSLFRelation.HYPERLINK.getRelation()); + _link.setId(rel.getId()); + + } + + public void setAddress(XSLFSlide slide){ + XSLFSheet sheet = _r.getParentParagraph().getParentShape().getSheet(); + PackageRelationship rel = + sheet.getPackagePart(). + addRelationship(slide.getPackagePart().getPartName(), + TargetMode.INTERNAL, + XSLFRelation.SLIDE.getRelation()); + _link.setId(rel.getId()); + _link.setAction("ppaction://hlinksldjump"); + } + + @Internal + public URI getTargetURI(){ + XSLFSheet sheet = _r.getParentParagraph().getParentShape().getSheet(); + String id = _link.getId(); + return sheet.getPackagePart().getRelationship(id).getTargetURI(); + } +} diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFRelation.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFRelation.java index 10a35dfeee..15f91c6ec5 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFRelation.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFRelation.java @@ -103,6 +103,13 @@ public class XSLFRelation extends POIXMLRelation { null, null ); + public static final XSLFRelation HYPERLINK = new XSLFRelation( + null, + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", + null, + null + ); + public static final XSLFRelation THEME = new XSLFRelation( "application/vnd.openxmlformats-officedocument.theme+xml", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme", diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java index b1b65eac40..dfb659557f 100755 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java @@ -41,8 +41,4 @@ public abstract class XSLFShape { public abstract String getShapeName(); public abstract int getShapeId(); - - void onCopy(XSLFSheet srcSheet){ - - } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java index 02ce9fdb7d..d97600d398 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java @@ -70,7 +70,8 @@ public abstract class XSLFSheet extends POIXMLDocumentPart { } else if (ch instanceof CTPicture){ shapes.add(new XSLFPictureShape((CTPicture)ch, this)); } else if (ch instanceof CTGraphicalObjectFrame){ - shapes.add(new XSLFGraphicFrame((CTGraphicalObjectFrame)ch, this)); + XSLFGraphicFrame shape = XSLFGraphicFrame.create((CTGraphicalObjectFrame)ch, this); + shapes.add(shape); } } return shapes; @@ -147,6 +148,13 @@ public abstract class XSLFSheet extends POIXMLDocumentPart { return sh; } + public XSLFTable createTable(){ + List shapes = getShapeList(); + XSLFTable sh = getDrawing().createTable(); + shapes.add(sh); + return sh; + } + public XSLFShape[] getShapes(){ return getShapeList().toArray(new XSLFShape[_shapes.size()]); } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTable.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTable.java new file mode 100644 index 0000000000..dce9cc2389 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTable.java @@ -0,0 +1,157 @@ +/* + * ==================================================================== + * 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.xslf.usermodel; + +import org.apache.poi.util.Internal; +import org.apache.poi.util.Units; +import org.apache.xmlbeans.XmlCursor; +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObjectData; +import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTable; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTableRow; +import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupTransform2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; +import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame; +import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrameNonVisual; + +import javax.xml.namespace.QName; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.awt.geom.Rectangle2D; + +/** + * Represents a table in a .pptx presentation + * + * @author Yegor Kozlov + */ +public class XSLFTable extends XSLFGraphicFrame implements Iterable { + static String TABLE_URI = "http://schemas.openxmlformats.org/drawingml/2006/table"; + + private CTTable _table; + private List _rows; + + /*package*/ XSLFTable(CTGraphicalObjectFrame shape, XSLFSheet sheet){ + super(shape, sheet); + + for(XmlObject obj : shape.getGraphic().getGraphicData().selectPath("*")){ + if(obj instanceof CTTable){ + _table = (CTTable)obj; + } + } + if(_table == null) throw new IllegalStateException("CTTable element was not found"); + + _rows = new ArrayList(_table.sizeOfTrArray()); + for(CTTableRow row : _table.getTrList()) _rows.add(new XSLFTableRow(row, this)); + } + + @Internal + public CTTable getCTTable(){ + return _table; + } + + public int getNumberOfColumns() { + return _table.getTblGrid().sizeOfGridColArray(); + } + + public int getNumberOfRows() { + return _table.sizeOfTrArray(); + } + + public double getColumnWidth(int idx){ + return Units.toPoints( + _table.getTblGrid().getGridColArray(idx).getW()); + } + + public void setColumnWidth(int idx, double width){ + _table.getTblGrid().getGridColArray(idx).setW(Units.toEMU(width)); + } + + public Iterator iterator(){ + return _rows.iterator(); + } + + public List getRows(){ + return Collections.unmodifiableList(_rows); + } + + public XSLFTableRow addRow(){ + CTTableRow tr = _table.addNewTr(); + XSLFTableRow row = new XSLFTableRow(tr, this); + row.setHeight(20.0); // default height is 20 points + _rows.add(row); + return row; + } + + static CTGraphicalObjectFrame prototype(int shapeId){ + CTGraphicalObjectFrame frame = CTGraphicalObjectFrame.Factory.newInstance(); + CTGraphicalObjectFrameNonVisual nvGr = frame.addNewNvGraphicFramePr(); + + CTNonVisualDrawingProps cnv = nvGr.addNewCNvPr(); + cnv.setName("Table " + shapeId); + cnv.setId(shapeId + 1); + nvGr.addNewCNvGraphicFramePr().addNewGraphicFrameLocks().setNoGrp(true); + nvGr.addNewNvPr(); + + frame.addNewXfrm(); + CTGraphicalObjectData gr = frame.addNewGraphic().addNewGraphicData(); + XmlCursor cursor = gr.newCursor(); + cursor.toNextToken(); + cursor.beginElement(new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "tbl")); + cursor.beginElement(new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "tblPr")); + cursor.toNextToken(); + cursor.beginElement(new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "tblGrid")); + cursor.dispose(); + gr.setUri(TABLE_URI); + return frame; + } + + public Rectangle2D getAnchor(){ + CTTransform2D xfrm = getXmlObject().getXfrm(); + CTPoint2D off = xfrm.getOff(); + long x = off.getX(); + long y = off.getY(); + CTPositiveSize2D ext = xfrm.getExt(); + long cx = ext.getCx(); + long cy = ext.getCy(); + return new Rectangle2D.Double( + Units.toPoints(x), Units.toPoints(y), + Units.toPoints(cx), Units.toPoints(cy)); + } + + public void setAnchor(Rectangle2D anchor){ + CTTransform2D xfrm = getXmlObject().getXfrm(); + CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff(); + long x = Units.toEMU(anchor.getX()); + long y = Units.toEMU(anchor.getY()); + off.setX(x); + off.setY(y); + CTPositiveSize2D ext = xfrm.isSetExt() ? xfrm.getExt() : xfrm.addNewExt(); + long cx = Units.toEMU(anchor.getWidth()); + long cy = Units.toEMU(anchor.getHeight()); + ext.setCx(cx); + ext.setCy(cy); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableCell.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableCell.java new file mode 100644 index 0000000000..cc04a10ae4 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableCell.java @@ -0,0 +1,290 @@ +/* + * ==================================================================== + * 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.xslf.usermodel; + +import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCell; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCellProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor; +import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.STPenAlignment; +import org.openxmlformats.schemas.drawingml.x2006.main.STCompoundLine; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap; +import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal; +import org.openxmlformats.schemas.drawingml.x2006.main.CTLineEndProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndLength; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndType; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndWidth; +import org.apache.poi.util.Internal; +import org.apache.poi.util.Units; + +import java.awt.*; + +/** + * Represents a cell of a table in a .pptx presentation + * + * @author Yegor Kozlov + */ +public class XSLFTableCell extends XSLFTextShape { + static double defaultBorderWidth = 1.0; + + /*package*/ XSLFTableCell(CTTableCell cell, XSLFSheet sheet){ + super(cell, sheet); + } + + @Override + public CTTableCell getXmlObject(){ + return (CTTableCell)super.getXmlObject(); + } + + @Override + protected CTTextBody getTextBody(boolean create){ + CTTableCell cell = getXmlObject(); + CTTextBody txBody = cell.getTxBody(); + if (txBody == null && create) { + txBody = cell.addNewTxBody(); + txBody.addNewBodyPr(); + txBody.addNewLstStyle(); + } + return txBody; + } + + static CTTableCell prototype() { + CTTableCell cell = CTTableCell.Factory.newInstance(); + CTTableCellProperties pr = cell.addNewTcPr(); + pr.addNewLnL().addNewNoFill(); + pr.addNewLnR().addNewNoFill(); + pr.addNewLnT().addNewNoFill(); + pr.addNewLnB().addNewNoFill(); + return cell; + } + + @Override + public void setMarginLeft(double margin){ + CTTableCellProperties pr = getXmlObject().getTcPr(); + if(pr == null) pr = getXmlObject().addNewTcPr(); + + pr.setMarL(Units.toEMU(margin)); + } + + @Override + public void setMarginRight(double margin){ + CTTableCellProperties pr = getXmlObject().getTcPr(); + if(pr == null) pr = getXmlObject().addNewTcPr(); + + pr.setMarR(Units.toEMU(margin)); + } + + @Override + public void setMarginTop(double margin){ + CTTableCellProperties pr = getXmlObject().getTcPr(); + if(pr == null) pr = getXmlObject().addNewTcPr(); + + pr.setMarT(Units.toEMU(margin)); + } + + @Override + public void setMarginBottom(double margin){ + CTTableCellProperties pr = getXmlObject().getTcPr(); + if(pr == null) pr = getXmlObject().addNewTcPr(); + + pr.setMarB(Units.toEMU(margin)); + } + + public void setBorderLeft(double width){ + CTTableCellProperties pr = getXmlObject().getTcPr(); + + CTLineProperties ln = pr.isSetLnL() ? pr.getLnL() : pr.addNewLnL(); + ln.setW(Units.toEMU(width)); + } + + public double getBorderLeft(){ + CTTableCellProperties pr = getXmlObject().getTcPr(); + + CTLineProperties ln = pr.getLnL(); + return ln == null || !ln.isSetW() ? defaultBorderWidth : Units.toPoints(ln.getW()); + } + + public void setBorderLeftColor(Color color){ + CTTableCellProperties pr = getXmlObject().getTcPr(); + CTLineProperties ln = pr.isSetLnL() ? pr.getLnL() : pr.addNewLnL(); + setLineColor(ln, color); + } + + public Color getBorderLeftColor(){ + return getLineColor(getXmlObject().getTcPr().getLnL()); + } + + public void setBorderRight(double width){ + CTTableCellProperties pr = getXmlObject().getTcPr(); + + CTLineProperties ln = pr.isSetLnR() ? pr.getLnR() : pr.addNewLnR(); + ln.setW(Units.toEMU(width)); + } + + public double getBorderRight(){ + CTTableCellProperties pr = getXmlObject().getTcPr(); + + CTLineProperties ln = pr.getLnR(); + return ln == null || !ln.isSetW() ? defaultBorderWidth : Units.toPoints(ln.getW()); + } + + public void setBorderRightColor(Color color){ + CTTableCellProperties pr = getXmlObject().getTcPr(); + CTLineProperties ln = pr.isSetLnR() ? pr.getLnR() : pr.addNewLnR(); + setLineColor(ln, color); + } + + public Color getBorderRightColor(){ + return getLineColor(getXmlObject().getTcPr().getLnR()); + } + + public void setBorderTop(double width){ + CTTableCellProperties pr = getXmlObject().getTcPr(); + + CTLineProperties ln = pr.isSetLnT() ? pr.getLnT() : pr.addNewLnT(); + ln.setW(Units.toEMU(width)); + } + + public double getBorderTop(){ + CTTableCellProperties pr = getXmlObject().getTcPr(); + + CTLineProperties ln = pr.getLnT(); + return ln == null || !ln.isSetW() ? defaultBorderWidth : Units.toPoints(ln.getW()); + } + + public void setBorderTopColor(Color color){ + CTTableCellProperties pr = getXmlObject().getTcPr(); + CTLineProperties ln = pr.isSetLnT() ? pr.getLnT() : pr.addNewLnT(); + setLineColor(ln, color); + } + + public Color getBorderTopColor(){ + return getLineColor(getXmlObject().getTcPr().getLnT()); + } + + public void setBorderBottom(double width){ + CTTableCellProperties pr = getXmlObject().getTcPr(); + + CTLineProperties ln = pr.isSetLnB() ? pr.getLnB() : pr.addNewLnB(); + ln.setW(Units.toEMU(width)); + } + + public double getBorderBottom(){ + CTTableCellProperties pr = getXmlObject().getTcPr(); + + CTLineProperties ln = pr.getLnB(); + return ln == null || !ln.isSetW() ? defaultBorderWidth : Units.toPoints(ln.getW()); + } + + public void setBorderBottomColor(Color color){ + CTTableCellProperties pr = getXmlObject().getTcPr(); + CTLineProperties ln = pr.isSetLnB() ? pr.getLnB() : pr.addNewLnB(); + setLineColor(ln, color); + } + + public Color getBorderBottomColor(){ + return getLineColor(getXmlObject().getTcPr().getLnB()); + } + + private void setLineColor(CTLineProperties ln, Color color){ + if(color == null){ + ln.addNewNoFill(); + if(ln.isSetSolidFill()) ln.unsetSolidFill(); + } else { + if(ln.isSetNoFill()) ln.unsetNoFill(); + + if(!ln.isSetPrstDash()) ln.addNewPrstDash().setVal(STPresetLineDashVal.SOLID); + ln.setCmpd(STCompoundLine.SNG); + ln.setAlgn(STPenAlignment.CTR); + ln.setCap(STLineCap.FLAT); + ln.addNewRound(); + + CTLineEndProperties hd = ln.addNewHeadEnd(); + hd.setType(STLineEndType.NONE); + hd.setW(STLineEndWidth.MED); + hd.setLen(STLineEndLength.MED); + + CTLineEndProperties tl = ln.addNewTailEnd(); + tl.setType(STLineEndType.NONE); + tl.setW(STLineEndWidth.MED); + tl.setLen(STLineEndLength.MED); + + CTSRgbColor rgb = CTSRgbColor.Factory.newInstance(); + rgb.setVal(new byte[]{(byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue()}); + ln.addNewSolidFill().setSrgbClr(rgb); + } + } + + private Color getLineColor(CTLineProperties ln){ + if(ln == null || ln.isSetNoFill() || !ln.isSetSolidFill()) return null; + + CTSolidColorFillProperties fill = ln.getSolidFill(); + if(!fill.isSetSrgbClr()) { + // TODO for now return null for all colors except explicit RGB + return null; + } + byte[] val = fill.getSrgbClr().getVal(); + return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]); + } + /** + * Specifies a solid color fill. The shape is filled entirely with the specified color. + * + * @param color the solid color fill. + * The value of null unsets the solidFIll attribute from the underlying xml + */ + @Override + public void setFillColor(Color color) { + CTTableCellProperties spPr = getXmlObject().getTcPr(); + if (color == null) { + if(spPr.isSetSolidFill()) spPr.unsetSolidFill(); + } + else { + CTSolidColorFillProperties fill = spPr.isSetSolidFill() ? spPr.getSolidFill() : spPr.addNewSolidFill(); + + CTSRgbColor rgb = CTSRgbColor.Factory.newInstance(); + rgb.setVal(new byte[]{(byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue()}); + + fill.setSrgbClr(rgb); + } + } + + /** + * + * @return solid fill color of null if not set + */ + @Override + public Color getFillColor(){ + CTTableCellProperties spPr = getXmlObject().getTcPr(); + if(!spPr.isSetSolidFill() ) return null; + + CTSolidColorFillProperties fill = spPr.getSolidFill(); + if(!fill.isSetSrgbClr()) { + // TODO for now return null for all colors except explicit RGB + return null; + } + byte[] val = fill.getSrgbClr().getVal(); + return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableRow.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableRow.java new file mode 100644 index 0000000000..328c76ae76 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableRow.java @@ -0,0 +1,86 @@ +/* + * ==================================================================== + * 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.xslf.usermodel; + +import org.apache.poi.util.Units; +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTable; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCell; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTableRow; +import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Iterator; + +/** + * Represents a table in a .pptx presentation + * + * @author Yegor Kozlov + */ +public class XSLFTableRow implements Iterable { + private CTTableRow _row; + private List _cells; + private XSLFTable _table; + + /*package*/ XSLFTableRow(CTTableRow row, XSLFTable table){ + _row = row; + _table = table; + _cells = new ArrayList(_row.sizeOfTcArray()); + for(CTTableCell cell : _row.getTcList()) { + _cells.add(new XSLFTableCell(cell, table.getSheet())); + } + } + + public CTTableRow getXmlObject(){ + return _row; + } + + public Iterator iterator(){ + return _cells.iterator(); + } + + public List getCells(){ + return Collections.unmodifiableList(_cells); + } + + public double getHeight(){ + return Units.toPoints(_row.getH()); + } + + public void setHeight(double height){ + _row.setH(Units.toEMU(height)); + } + + public XSLFTableCell addCell(){ + CTTableCell c = _row.addNewTc(); + c.set(XSLFTableCell.prototype()); + XSLFTableCell cell = new XSLFTableCell(c, _table.getSheet()); + _cells.add(cell); + + if(_table.getNumberOfColumns() < _row.sizeOfTcArray()) { + _table.getCTTable().getTblGrid().addNewGridCol().setW(Units.toEMU(100.0)); + } + return cell; + } + + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java index 9317298ee3..e20be9b5c2 100755 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java @@ -40,12 +40,14 @@ import java.util.List; public class XSLFTextParagraph implements Iterable{ private final CTTextParagraph _p; private final List _runs; + private final XSLFTextShape _shape; - XSLFTextParagraph(CTTextParagraph p){ + XSLFTextParagraph(CTTextParagraph p, XSLFTextShape shape){ _p = p; _runs = new ArrayList(); + _shape = shape; for (CTRegularTextRun r : _p.getRList()) { - _runs.add(new XSLFTextRun(r)); + _runs.add(new XSLFTextRun(r, this)); } } @@ -62,6 +64,10 @@ public class XSLFTextParagraph implements Iterable{ return _p; } + XSLFTextShape getParentShape() { + return _shape; + + } public List getTextRuns(){ return _runs; } @@ -72,7 +78,8 @@ public class XSLFTextParagraph implements Iterable{ public XSLFTextRun addNewTextRun(){ CTRegularTextRun r = _p.addNewR(); - XSLFTextRun run = new XSLFTextRun(r); + r.addNewRPr(); + XSLFTextRun run = new XSLFTextRun(r, this); _runs.add(run); return run; } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java index 859649197b..c62775e086 100755 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java @@ -36,9 +36,15 @@ import java.awt.*; @Beta public class XSLFTextRun { private final CTRegularTextRun _r; + private final XSLFTextParagraph _p; - XSLFTextRun(CTRegularTextRun r){ + XSLFTextRun(CTRegularTextRun r, XSLFTextParagraph p){ _r = r; + _p = p; + } + + XSLFTextParagraph getParentParagraph(){ + return _p; } public String getText(){ @@ -78,7 +84,7 @@ public class XSLFTextRun { * @return font size in points or -1 if font size is not set. */ public double getFontSize(){ - if(!_r.isSetRPr()) return -1; + if(!_r.isSetRPr() || !_r.getRPr().isSetSz()) return -1; return _r.getRPr().getSz()*0.01; } @@ -198,5 +204,16 @@ public class XSLFTextRun { public String toString(){ return "[" + getClass() + "]" + getText(); } - + + public XSLFHyperlink createHyperlink(){ + XSLFHyperlink link = new XSLFHyperlink(_r.getRPr().addNewHlinkClick(), this); + return link; + } + + public XSLFHyperlink getHyperlink(){ + if(!_r.getRPr().isSetHlinkClick()) return null; + + + return new XSLFHyperlink(_r.getRPr().getHlinkClick(), this); + } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java new file mode 100644 index 0000000000..5bb48b600b --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java @@ -0,0 +1,365 @@ +/* + * ==================================================================== + * 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.xslf.usermodel; + +import org.apache.poi.util.Beta; +import org.apache.poi.util.Units; +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor; +import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph; +import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType; +import org.openxmlformats.schemas.drawingml.x2006.main.STTextVerticalType; +import org.openxmlformats.schemas.drawingml.x2006.main.STTextWrappingType; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a shape that can hold text. + * + * @author Yegor Kozlov + */ +@Beta +public abstract class XSLFTextShape extends XSLFSimpleShape { + private final List _paragraphs; + + /*package*/ XSLFTextShape(XmlObject shape, XSLFSheet sheet) { + super(shape, sheet); + + _paragraphs = new ArrayList(); + CTTextBody txBody = getTextBody(false); + if (txBody != null) { + for (CTTextParagraph p : txBody.getPList()) { + _paragraphs.add(new XSLFTextParagraph(p, this)); + } + } + } + + // textual properties + public String getText() { + StringBuilder out = new StringBuilder(); + for (XSLFTextParagraph p : _paragraphs) { + if (out.length() > 0) out.append('\n'); + out.append(p.getText()); + } + return out.toString(); + } + + public List getTextParagraphs() { + return _paragraphs; + } + + public XSLFTextParagraph addNewTextParagraph() { + CTTextBody txBody = getTextBody(true); + CTTextParagraph p = txBody.addNewP(); + XSLFTextParagraph paragraph = new XSLFTextParagraph(p, this); + _paragraphs.add(paragraph); + return paragraph; + } + + /** + * Specifies a solid color fill. The shape is filled entirely with the specified color. + * + * @param color the solid color fill. + * The value of null unsets the solidFIll attribute from the underlying xml + */ + public void setFillColor(Color color) { + CTShapeProperties spPr = getSpPr(); + if (color == null) { + if(spPr.isSetSolidFill()) spPr.unsetSolidFill(); + } + else { + CTSolidColorFillProperties fill = spPr.isSetSolidFill() ? spPr.getSolidFill() : spPr.addNewSolidFill(); + + CTSRgbColor rgb = CTSRgbColor.Factory.newInstance(); + rgb.setVal(new byte[]{(byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue()}); + + fill.setSrgbClr(rgb); + } + } + + /** + * + * @return solid fill color of null if not set + */ + public Color getFillColor(){ + CTShapeProperties spPr = getSpPr(); + if(!spPr.isSetSolidFill() ) return null; + + CTSolidColorFillProperties fill = spPr.getSolidFill(); + if(!fill.isSetSrgbClr()) { + // TODO for now return null for all colors except explicit RGB + return null; + } + byte[] val = fill.getSrgbClr().getVal(); + return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]); + } + + /** + * Sets the type of vertical alignment for the text. + * One of the Anchor* constants defined in this class. + * + * @param anchor - the type of alignment. Default is {@link org.apache.poi.xslf.usermodel.VerticalAlignment#TOP} + */ + public void setVerticalAlignment(VerticalAlignment anchor){ + CTTextBodyProperties bodyPr = getTextBodyPr(); + if (bodyPr != null) { + if(anchor == null) { + if(bodyPr.isSetAnchor()) bodyPr.unsetAnchor(); + } else { + bodyPr.setAnchor(STTextAnchoringType.Enum.forInt(anchor.ordinal() + 1)); + } + } + } + + /** + * Returns the type of vertical alignment for the text. + * + * @return the type of alignment + */ + public VerticalAlignment getVerticalAlignment(){ + CTTextBodyProperties bodyPr = getTextBodyPr(); + if (bodyPr != null) { + STTextAnchoringType.Enum val = bodyPr.getAnchor(); + if(val != null){ + return VerticalAlignment.values()[val.intValue() - 1]; + } + } + return VerticalAlignment.TOP; + } + + /** + * + * @param orientation vertical orientation of the text + */ + public void setTextDirection(TextDirection orientation){ + CTTextBodyProperties bodyPr = getTextBodyPr(); + if (bodyPr != null) { + if(orientation == null) { + if(bodyPr.isSetVert()) bodyPr.unsetVert(); + } else { + bodyPr.setVert(STTextVerticalType.Enum.forInt(orientation.ordinal() + 1)); + } + } + } + + /** + * @return vertical orientation of the text + */ + public TextDirection getTextDirection(){ + CTTextBodyProperties bodyPr = getTextBodyPr(); + if (bodyPr != null) { + STTextVerticalType.Enum val = bodyPr.getVert(); + if(val != null){ + return TextDirection.values()[val.intValue() - 1]; + } + } + return TextDirection.HORIZONTAL; + } + /** + * 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. + * + * @return the bottom margin or -1 if not set + */ + public double getMarginBottom(){ + CTTextBodyProperties bodyPr = getTextBodyPr(); + if (bodyPr != null) { + return bodyPr.isSetBIns() ? Units.toPoints(bodyPr.getBIns()) : -1; + } + return -1; + } + + /** + * 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. + * + * @return the left margin + */ + public double getMarginLeft(){ + CTTextBodyProperties bodyPr = getTextBodyPr(); + if (bodyPr != null) { + return bodyPr.isSetLIns() ? Units.toPoints(bodyPr.getLIns()) : -1; + } + return -1; + } + + /** + * 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. + * + * @return the right margin + */ + public double getMarginRight(){ + CTTextBodyProperties bodyPr = getTextBodyPr(); + if (bodyPr != null) { + return bodyPr.isSetRIns() ? Units.toPoints(bodyPr.getRIns()) : -1; + } + return -1; + } + + /** + * 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. + * + * @return the top margin + */ + public double getMarginTop(){ + CTTextBodyProperties bodyPr = getTextBodyPr(); + if (bodyPr != null) { + return bodyPr.isSetTIns() ? Units.toPoints(bodyPr.getTIns()) : -1; + } + return -1; + } + + /** + * Sets the botom margin. + * @see #getMarginBottom() + * + * @param margin the bottom margin + */ + public void setMarginBottom(double margin){ + CTTextBodyProperties bodyPr = getTextBodyPr(); + if (bodyPr != null) { + if(margin == -1) bodyPr.unsetBIns(); + else bodyPr.setBIns(Units.toEMU(margin)); + } + } + + /** + * Sets the left margin. + * @see #getMarginLeft() + * + * @param margin the left margin + */ + public void setMarginLeft(double margin){ + CTTextBodyProperties bodyPr = getTextBodyPr(); + if (bodyPr != null) { + if(margin == -1) bodyPr.unsetLIns(); + else bodyPr.setLIns(Units.toEMU(margin)); + } + } + + /** + * Sets the right margin. + * @see #getMarginRight() + * + * @param margin the right margin + */ + public void setMarginRight(double margin){ + CTTextBodyProperties bodyPr = getTextBodyPr(); + if (bodyPr != null) { + if(margin == -1) bodyPr.unsetRIns(); + else bodyPr.setRIns(Units.toEMU(margin)); + } + } + + /** + * Sets the top margin. + * @see #getMarginTop() + * + * @param margin the top margin + */ + public void setMarginTop(double margin){ + CTTextBodyProperties bodyPr = getTextBodyPr(); + if (bodyPr != null) { + if(margin == -1) bodyPr.unsetTIns(); + else bodyPr.setTIns(Units.toEMU(margin)); + } + } + + + /** + * Returns the value indicating word wrap. + * One of the Wrap* constants defined in this class. + * + * @return the value indicating word wrap + */ + public boolean getWordWrap(){ + CTTextBodyProperties bodyPr = getTextBodyPr(); + if (bodyPr != null) { + return bodyPr.getWrap() == STTextWrappingType.SQUARE; + } + return false; + } + + /** + * Specifies how the text should be wrapped + * + * @param wrap the value indicating how the text should be wrapped + */ + public void setWordWrap(boolean wrap){ + CTTextBodyProperties bodyPr = getTextBodyPr(); + if (bodyPr != null) { + bodyPr.setWrap(wrap ? STTextWrappingType.SQUARE : STTextWrappingType.NONE); + } + } + + /** + * + * Specifies that a shape should be auto-fit to fully contain the text 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 + */ + public void setTextAutofit(TextAutofit value){ + CTTextBodyProperties bodyPr = getTextBodyPr(); + if (bodyPr != null) { + if(bodyPr.isSetSpAutoFit()) bodyPr.unsetSpAutoFit(); + if(bodyPr.isSetNoAutofit()) bodyPr.unsetNoAutofit(); + if(bodyPr.isSetNormAutofit()) bodyPr.unsetNormAutofit(); + + switch(value){ + case NONE: bodyPr.addNewNoAutofit(); break; + case NORMAL: bodyPr.addNewNormAutofit(); break; + case SHAPE: bodyPr.addNewSpAutoFit(); break; + } + } + } + + /** + * + * @return type of autofit + */ + public TextAutofit getTextAutofit(){ + CTTextBodyProperties bodyPr = getTextBodyPr(); + if (bodyPr != null) { + if(bodyPr.isSetNoAutofit()) return TextAutofit.NONE; + else if (bodyPr.isSetNormAutofit()) return TextAutofit.NORMAL; + else if (bodyPr.isSetSpAutoFit()) return TextAutofit.SHAPE; + } + return TextAutofit.NORMAL; + } + + protected CTTextBodyProperties getTextBodyPr(){ + CTTextBody textBody = getTextBody(false); + return textBody == null ? null : textBody.getBodyPr(); + } + + + protected abstract CTTextBody getTextBody(boolean create); +} \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java index 69be4b7a6b..efed3ca034 100755 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java @@ -210,7 +210,7 @@ public class TestXSLFAutoShape extends TestCase { assertSame(r, p.getTextRuns().get(0)); assertEquals(-1.0, r.getFontSize()); - assertFalse(r.getXmlObject().isSetRPr()); + assertFalse(r.getXmlObject().getRPr().isSetSz()); r.setFontSize(10.0); assertTrue(r.getXmlObject().isSetRPr()); assertEquals(1000, r.getXmlObject().getRPr().getSz()); diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFHyperlink.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFHyperlink.java new file mode 100644 index 0000000000..fe968b0b7f --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFHyperlink.java @@ -0,0 +1,102 @@ +/* ==================================================================== + 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.xslf.usermodel; + +import junit.framework.TestCase; + +import java.awt.*; +import java.awt.geom.Ellipse2D; +import java.awt.geom.GeneralPath; +import java.util.*; +import java.util.List; +import java.net.URI; + +import org.apache.poi.xslf.XSLFTestDataSamples; +import org.apache.poi.xssf.usermodel.XSSFTable; +import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.openxml4j.opc.TargetMode; + +/** + * @author Yegor Kozlov + */ +public class TestXSLFHyperlink extends TestCase { + + public void testRead(){ + XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx"); + + XSLFSlide slide = ppt.getSlides()[4]; + XSLFShape[] shapes = slide.getShapes(); + XSLFTable tbl = (XSLFTable)shapes[0]; + XSLFTableCell cell1 = tbl.getRows().get(1).getCells().get(0); + assertEquals("Web Page", cell1.getText()); + XSLFHyperlink link1 = cell1.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink(); + assertNotNull(link1); + assertEquals(URI.create("http://poi.apache.org/"), link1.getTargetURI()); + + XSLFTableCell cell2 = tbl.getRows().get(2).getCells().get(0); + assertEquals("Place in this document", cell2.getText()); + XSLFHyperlink link2 = cell2.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink(); + assertNotNull(link2); + assertEquals(URI.create("/ppt/slides/slide2.xml"), link2.getTargetURI()); + + XSLFTableCell cell3 = tbl.getRows().get(3).getCells().get(0); + assertEquals("Email", cell3.getText()); + XSLFHyperlink link3 = cell3.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink(); + assertNotNull(link3); + assertEquals(URI.create("mailto:dev@poi.apache.org?subject=Hi%20There"), link3.getTargetURI()); + } + + public void testCreate() throws Exception { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide1 = ppt.createSlide(); + XSLFSlide slide2 = ppt.createSlide(); + + int numRel = slide1.getPackagePart().getRelationships().size(); + assertEquals(1, numRel); + XSLFTextBox sh1 = slide1.createTextBox(); + XSLFTextRun r1 = sh1.addNewTextParagraph().addNewTextRun(); + r1.setText("Web Page"); + XSLFHyperlink link1 = r1.createHyperlink(); + link1.setAddress("http://poi.apache.org/"); + assertEquals(URI.create("http://poi.apache.org/"), link1.getTargetURI()); + assertEquals(numRel + 1, slide1.getPackagePart().getRelationships().size()); + + String id1 = link1.getXmlObject().getId(); + assertNotNull(id1); + PackageRelationship rel1 = slide1.getPackagePart().getRelationship(id1); + assertNotNull(rel1); + assertEquals(id1, rel1.getId()); + assertEquals(TargetMode.EXTERNAL, rel1.getTargetMode()); + assertEquals(XSLFRelation.HYPERLINK.getRelation(), rel1.getRelationshipType()); + + XSLFTextBox sh2 = slide1.createTextBox(); + XSLFTextRun r2 = sh2.addNewTextParagraph().addNewTextRun(); + r2.setText("Place in this document"); + XSLFHyperlink link2 = r2.createHyperlink(); + link2.setAddress(slide2); + assertEquals(URI.create("/ppt/slides/slide2.xml"), link2.getTargetURI()); + assertEquals(numRel + 2, slide1.getPackagePart().getRelationships().size()); + + String id2 = link2.getXmlObject().getId(); + assertNotNull(id2); + PackageRelationship rel2 = slide1.getPackagePart().getRelationship(id2); + assertNotNull(rel2); + assertEquals(id2, rel2.getId()); + assertEquals(TargetMode.INTERNAL, rel2.getTargetMode()); + assertEquals(XSLFRelation.SLIDE.getRelation(), rel2.getRelationshipType()); + } +} \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFShape.java index ca3d82f975..ecdcdd032d 100755 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFShape.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFShape.java @@ -31,7 +31,6 @@ public class TestXSLFShape extends TestCase { public void testReadTextShapes() { XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx"); XSLFSlide[] slides = ppt.getSlides(); - assertEquals(3, slides.length); XSLFSlide slide1 = slides[0]; XSLFShape[] shapes1 = slide1.getShapes(); diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java index 9c7d131d80..9ffe69fe98 100755 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java @@ -30,7 +30,6 @@ public class TestXSLFSlide extends TestCase { public void testReadShapes(){ XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx"); XSLFSlide[] slides = ppt.getSlides(); - assertEquals(3, slides.length); XSLFSlide slide1 = slides[0]; XSLFShape[] shapes1 = slide1.getShapes(); @@ -85,6 +84,14 @@ public class TestXSLFSlide extends TestCase { assertTrue(groupShapes[2] instanceof XSLFAutoShape); assertEquals("Right Arrow 3", groupShapes[2].getShapeName()); + + XSLFSlide slide4 = slides[3]; + XSLFShape[] shapes4 = slide4.getShapes(); + assertEquals(1, shapes4.length); + assertTrue(shapes4[0] instanceof XSLFTable); + XSLFTable tbl = (XSLFTable)shapes4[0]; + assertEquals(3, tbl.getNumberOfColumns()); + assertEquals(6, tbl.getNumberOfRows()); } public void testCreateSlide(){ diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTable.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTable.java new file mode 100644 index 0000000000..a5cdb0d6ca --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTable.java @@ -0,0 +1,150 @@ +/* ==================================================================== + 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.xslf.usermodel; + +import junit.framework.TestCase; + +import java.awt.*; +import java.awt.geom.Ellipse2D; +import java.awt.geom.GeneralPath; +import java.util.*; +import java.util.List; + +import org.apache.poi.xslf.XSLFTestDataSamples; +import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame; + +/** + * @author Yegor Kozlov + */ +public class TestXSLFTable extends TestCase { + + public void testRead(){ + XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx"); + + XSLFSlide slide = ppt.getSlides()[3]; + XSLFShape[] shapes = slide.getShapes(); + assertEquals(1, shapes.length); + assertTrue(shapes[0] instanceof XSLFTable); + XSLFTable tbl = (XSLFTable)shapes[0]; + assertEquals(3, tbl.getNumberOfColumns()); + assertEquals(6, tbl.getNumberOfRows()); + assertNotNull(tbl.getCTTable()); + + List rows = tbl.getRows(); + assertEquals(6, rows.size()); + + assertEquals(90.0, tbl.getColumnWidth(0)); + assertEquals(240.0, tbl.getColumnWidth(1)); + assertEquals(150.0, tbl.getColumnWidth(2)); + + for(XSLFTableRow row : tbl){ + // all rows have the same height + assertEquals(29.2, row.getHeight()); + } + + XSLFTableRow row0 = rows.get(0); + List cells0 = row0.getCells(); + assertEquals(3, cells0.size()); + assertEquals("header1", cells0.get(0).getText()); + assertEquals("header2", cells0.get(1).getText()); + assertEquals("header3", cells0.get(2).getText()); + + XSLFTableRow row1 = rows.get(1); + List cells1 = row1.getCells(); + assertEquals(3, cells1.size()); + assertEquals("A1", cells1.get(0).getText()); + assertEquals("B1", cells1.get(1).getText()); + assertEquals("C1", cells1.get(2).getText()); + } + + public void testCreate() { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + + XSLFTable tbl = slide.createTable(); + assertNotNull(tbl.getCTTable()); + assertNotNull(tbl.getCTTable().getTblGrid()); + assertNotNull(tbl.getCTTable().getTblPr()); + assertTrue(tbl.getXmlObject() instanceof CTGraphicalObjectFrame); + assertEquals("Table 1", tbl.getShapeName()); + assertEquals(2, tbl.getShapeId()); + assertEquals(0, tbl.getRows().size()); + assertEquals(0, tbl.getCTTable().sizeOfTrArray()); + assertEquals(0, tbl.getCTTable().getTblGrid().sizeOfGridColArray()); + + assertEquals(0, tbl.getNumberOfColumns()); + assertEquals(0, tbl.getNumberOfRows()); + + XSLFTableRow row0 = tbl.addRow(); + assertNotNull(row0.getXmlObject()); + assertEquals(1, tbl.getNumberOfRows()); + assertSame(row0, tbl.getRows().get(0)); + assertEquals(20.0, row0.getHeight()); + row0.setHeight(30.0); + assertEquals(30.0, row0.getHeight()); + + assertEquals(0, row0.getCells().size()); + XSLFTableCell cell0 = row0.addCell(); + assertNotNull(cell0.getXmlObject()); + // by default table cell has no borders + assertTrue(cell0.getXmlObject().getTcPr().getLnB().isSetNoFill()); + assertTrue(cell0.getXmlObject().getTcPr().getLnT().isSetNoFill()); + assertTrue(cell0.getXmlObject().getTcPr().getLnL().isSetNoFill()); + assertTrue(cell0.getXmlObject().getTcPr().getLnR().isSetNoFill()); + + assertSame(cell0, row0.getCells().get(0)); + assertEquals(1, tbl.getNumberOfColumns()); + assertEquals(100.0, tbl.getColumnWidth(0)); + cell0.addNewTextParagraph().addNewTextRun().setText("POI"); + assertEquals("POI", cell0.getText()); + + XSLFTableCell cell1 = row0.addCell(); + assertSame(cell1, row0.getCells().get(1)); + assertEquals(2, tbl.getNumberOfColumns()); + assertEquals(100.0, tbl.getColumnWidth(1)); + cell1.addNewTextParagraph().addNewTextRun().setText("Apache"); + assertEquals("Apache", cell1.getText()); + + assertEquals(1.0, cell1.getBorderBottom()); + cell1.setBorderBottom(2.0); + assertEquals(2.0, cell1.getBorderBottom()); + assertNull(cell1.getBorderBottomColor()); + cell1.setBorderBottomColor(Color.yellow); + assertEquals(Color.yellow, cell1.getBorderBottomColor()); + + assertEquals(1.0, cell1.getBorderTop()); + cell1.setBorderTop(2.0); + assertEquals(2.0, cell1.getBorderTop()); + assertNull(cell1.getBorderTopColor()); + cell1.setBorderTopColor(Color.yellow); + assertEquals(Color.yellow, cell1.getBorderTopColor()); + + assertEquals(1.0, cell1.getBorderLeft()); + cell1.setBorderLeft(2.0); + assertEquals(2.0, cell1.getBorderLeft()); + assertNull(cell1.getBorderLeftColor()); + cell1.setBorderLeftColor(Color.yellow); + assertEquals(Color.yellow, cell1.getBorderLeftColor()); + + assertEquals(1.0, cell1.getBorderRight()); + cell1.setBorderRight(2.0); + assertEquals(2.0, cell1.getBorderRight()); + assertNull(cell1.getBorderRightColor()); + cell1.setBorderRightColor(Color.yellow); + assertEquals(Color.yellow, cell1.getBorderRightColor()); + } +} \ No newline at end of file diff --git a/test-data/slideshow/shapes.pptx b/test-data/slideshow/shapes.pptx index 0b3861228d..cf017a873a 100755 Binary files a/test-data/slideshow/shapes.pptx and b/test-data/slideshow/shapes.pptx differ