]> source.dussan.org Git - poi.git/commitdiff
support for tables and hyperlinks in XSLF
authorYegor Kozlov <yegor@apache.org>
Wed, 17 Aug 2011 10:18:31 +0000 (10:18 +0000)
committerYegor Kozlov <yegor@apache.org>
Wed, 17 Aug 2011 10:18:31 +0000 (10:18 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1158611 13f79535-47bb-0310-9956-ffa450edef68

21 files changed:
src/documentation/content/xdocs/index.xml
src/documentation/content/xdocs/status.xml
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFDrawing.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGraphicFrame.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFHyperlink.java [new file with mode: 0644]
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFRelation.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTable.java [new file with mode: 0644]
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableCell.java [new file with mode: 0644]
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableRow.java [new file with mode: 0644]
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java [new file with mode: 0644]
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFHyperlink.java [new file with mode: 0644]
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFShape.java
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTable.java [new file with mode: 0644]
test-data/slideshow/shapes.pptx

index 56e89aa2b4e3c6cadf7fe5c25fcbe4ee71c671ec..61fc1de6f92d0bd79fc181e0a4f8714ec83c0cbf 100644 (file)
@@ -32,8 +32,8 @@
   </header>
 
   <body>
-    <section><title>6 June 2011 - POI 3.8 beta 3 available</title>
-      <p>The Apache POI team is pleased to announce the release of 3.8 beta 3
+    <section><title>22 August 2011 - POI 3.8 beta 4 available</title>
+      <p>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. 
       </p>
       <p>A full list of changes is available in the <link href="changes.html">change log</link>.
index 96acff77ec878cb027cccda3cf0840171d5b2305..4c9f245e02773df0d87b05683e7411023d77335a 100644 (file)
@@ -34,6 +34,7 @@
 
     <changes>
         <release version="3.8-beta4" date="2011-??-??">
+           <action dev="poi-developers" type="add">support for tables and hyperlinks</action>
            <action dev="poi-developers" type="fix">51535 - correct signed vs unsigned short reading in NDocumentInputStream</action>
            <action dev="poi-developers" type="add">51634 - support SXSSF streaming from templates</action>
            <action dev="poi-developers" type="add">initial support for XSLF usermodel API</action>
index 186974997012e5c0ff1aa82fbb0734af745b949e..feb77a404102f6cab10d5553812373948758347b 100755 (executable)
@@ -48,19 +48,10 @@ import java.util.List;
  * @author Yegor Kozlov\r
  */\r
 @Beta\r
-public class XSLFAutoShape extends XSLFSimpleShape {\r
-    private final List<XSLFTextParagraph> _paragraphs;\r
+public class XSLFAutoShape extends XSLFTextShape {\r
 \r
     /*package*/ XSLFAutoShape(CTShape shape, XSLFSheet sheet) {\r
         super(shape, sheet);\r
-\r
-        _paragraphs = new ArrayList<XSLFTextParagraph>();\r
-        if (shape.isSetTxBody()) {\r
-            CTTextBody txBody = shape.getTxBody();\r
-            for (CTTextParagraph p : txBody.getPList()) {\r
-                _paragraphs.add(new XSLFTextParagraph(p));\r
-            }\r
-        }\r
     }\r
 \r
     /*package*/\r
@@ -74,36 +65,6 @@ public class XSLFAutoShape extends XSLFSimpleShape {
         }\r
     }\r
 \r
-    // textual properties\r
-    public String getText() {\r
-        StringBuilder out = new StringBuilder();\r
-        for (XSLFTextParagraph p : _paragraphs) {\r
-            if (out.length() > 0) out.append('\n');\r
-            out.append(p.getText());\r
-        }\r
-        return out.toString();\r
-    }\r
-\r
-    public List<XSLFTextParagraph> getTextParagraphs() {\r
-        return _paragraphs;\r
-    }\r
-\r
-    public XSLFTextParagraph addNewTextParagraph() {\r
-        CTShape shape = (CTShape) getXmlObject();\r
-        CTTextBody txBody;\r
-        if (!shape.isSetTxBody()) {\r
-            txBody = shape.addNewTxBody();\r
-            txBody.addNewBodyPr();\r
-            txBody.addNewLstStyle();\r
-        } else {\r
-            txBody = shape.getTxBody();\r
-        }\r
-        CTTextParagraph p = txBody.addNewP();\r
-        XSLFTextParagraph paragraph = new XSLFTextParagraph(p);\r
-        _paragraphs.add(paragraph);\r
-        return paragraph;\r
-    }\r
-\r
     /**\r
      * @param shapeId 1-based shapeId\r
      */\r
@@ -160,268 +121,15 @@ public class XSLFAutoShape extends XSLFSimpleShape {
         return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]);\r
     }\r
 \r
-    /**\r
-     * Sets the type of vertical alignment for the text.\r
-     * One of the <code>Anchor*</code> constants defined in this class.\r
-     *\r
-     * @param anchor - the type of alignment. Default is {@link VerticalAlignment#TOP}\r
-     */\r
-    public void setVerticalAlignment(VerticalAlignment anchor){\r
-        CTShape shape = (CTShape) getXmlObject();\r
-        if (shape.isSetTxBody()) {\r
-            CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr();\r
-            if(anchor == null) {\r
-                if(bodyPr.isSetAnchor()) bodyPr.unsetAnchor();\r
-            } else {\r
-                bodyPr.setAnchor(STTextAnchoringType.Enum.forInt(anchor.ordinal() + 1));\r
-            }\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Returns the type of vertical alignment for the text.\r
-     *\r
-     * @return the type of alignment\r
-     */\r
-    public VerticalAlignment getVerticalAlignment(){\r
-        CTShape shape = (CTShape) getXmlObject();\r
-        if (shape.isSetTxBody()) {\r
-            STTextAnchoringType.Enum val = shape.getTxBody().getBodyPr().getAnchor();\r
-            if(val != null){\r
-                return VerticalAlignment.values()[val.intValue() - 1];\r
-            }\r
-        }\r
-        return VerticalAlignment.TOP;\r
-    }\r
-\r
-    /**\r
-     *\r
-     * @param orientation vertical orientation of the text\r
-     */\r
-    public void setTextDirection(TextDirection orientation){\r
-        CTShape shape = (CTShape) getXmlObject();\r
-        if (shape.isSetTxBody()) {\r
-            CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr();\r
-            if(orientation == null) {\r
-                if(bodyPr.isSetVert()) bodyPr.unsetVert();\r
-            } else {\r
-                bodyPr.setVert(STTextVerticalType.Enum.forInt(orientation.ordinal() + 1));\r
-            }\r
-        }\r
-    }\r
-\r
-    /**\r
-     * @return vertical orientation of the text\r
-     */\r
-    public TextDirection getTextDirection(){\r
-        CTShape shape = (CTShape) getXmlObject();\r
-        if (shape.isSetTxBody()) {\r
-            STTextVerticalType.Enum val = shape.getTxBody().getBodyPr().getVert();\r
-            if(val != null){\r
-                return TextDirection.values()[val.intValue() - 1];\r
-            }\r
-        }\r
-        return TextDirection.HORIZONTAL;\r
-    }\r
-    /**\r
-     * Returns the distance (in points) between the bottom of the text frame\r
-     * and the bottom of the inscribed rectangle of the shape that contains the text.\r
-     *\r
-     * @return the bottom margin or -1 if not set\r
-     */\r
-    public double getMarginBottom(){\r
-        CTShape shape = (CTShape) getXmlObject();\r
-        if (shape.isSetTxBody()) {\r
-            CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr();\r
-            return bodyPr.isSetBIns() ? Units.toPoints(bodyPr.getBIns()) : -1;\r
-        }\r
-        return -1;\r
-    }\r
-\r
-    /**\r
-     *  Returns the distance (in points) between the left edge of the text frame\r
-     *  and the left edge of the inscribed rectangle of the shape that contains\r
-     *  the text.\r
-     *\r
-     * @return the left margin\r
-     */\r
-    public double getMarginLeft(){\r
-        CTShape shape = (CTShape) getXmlObject();\r
-        if (shape.isSetTxBody()) {\r
-            CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr();\r
-            return bodyPr.isSetLIns() ? Units.toPoints(bodyPr.getLIns()) : -1;\r
-        }\r
-        return -1;\r
-    }\r
-\r
-    /**\r
-     *  Returns the distance (in points) between the right edge of the\r
-     *  text frame and the right edge of the inscribed rectangle of the shape\r
-     *  that contains the text.\r
-     *\r
-     * @return the right margin\r
-     */\r
-    public double getMarginRight(){\r
-        CTShape shape = (CTShape) getXmlObject();\r
-        if (shape.isSetTxBody()) {\r
-            CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr();\r
-            return bodyPr.isSetRIns() ? Units.toPoints(bodyPr.getRIns()) : -1;\r
-        }\r
-        return -1;\r
-    }\r
-\r
-    /**\r
-     *  Returns the distance (in points) between the top of the text frame\r
-     *  and the top of the inscribed rectangle of the shape that contains the text.\r
-     *\r
-     * @return the top margin\r
-     */\r
-    public double getMarginTop(){\r
-        CTShape shape = (CTShape) getXmlObject();\r
-        if (shape.isSetTxBody()) {\r
-            CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr();\r
-            return bodyPr.isSetTIns() ? Units.toPoints(bodyPr.getTIns()) : -1;\r
-        }\r
-        return -1;\r
-    }\r
-\r
-    /**\r
-     * Sets the botom margin.\r
-     * @see #getMarginBottom()\r
-     *\r
-     * @param margin    the bottom margin\r
-     */\r
-    public void setMarginBottom(double margin){\r
-        CTShape shape = (CTShape) getXmlObject();\r
-        if (shape.isSetTxBody()) {\r
-            CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr();\r
-            if(margin == -1) bodyPr.unsetBIns();\r
-            else bodyPr.setBIns(Units.toEMU(margin));\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Sets the left margin.\r
-     * @see #getMarginLeft()\r
-     *\r
-     * @param margin    the left margin\r
-     */\r
-    public void setMarginLeft(double margin){\r
-        CTShape shape = (CTShape) getXmlObject();\r
-        if (shape.isSetTxBody()) {\r
-            CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr();\r
-            if(margin == -1) bodyPr.unsetLIns();\r
-            else bodyPr.setLIns(Units.toEMU(margin));\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Sets the right margin.\r
-     * @see #getMarginRight()\r
-     *\r
-     * @param margin    the right margin\r
-     */\r
-    public void setMarginRight(double margin){\r
-        CTShape shape = (CTShape) getXmlObject();\r
-        if (shape.isSetTxBody()) {\r
-            CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr();\r
-            if(margin == -1) bodyPr.unsetRIns();\r
-            else bodyPr.setRIns(Units.toEMU(margin));\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Sets the top margin.\r
-     * @see #getMarginTop()\r
-     *\r
-     * @param margin    the top margin\r
-     */\r
-    public void setMarginTop(double margin){\r
-        CTShape shape = (CTShape) getXmlObject();\r
-        if (shape.isSetTxBody()) {\r
-            CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr();\r
-            if(margin == -1) bodyPr.unsetTIns();\r
-            else bodyPr.setTIns(Units.toEMU(margin));\r
-        }\r
-    }\r
-\r
-\r
-    /**\r
-     * Returns the value indicating word wrap.\r
-     * One of the <code>Wrap*</code> constants defined in this class.\r
-     *\r
-     * @return the value indicating word wrap\r
-     */\r
-    public boolean getWordWrap(){\r
+    protected CTTextBody getTextBody(boolean create){\r
         CTShape shape = (CTShape) getXmlObject();\r
-        if (shape.isSetTxBody()) {\r
-            return shape.getTxBody().getBodyPr().getWrap() == STTextWrappingType.SQUARE;\r
-        }\r
-        return false;\r
-    }\r
-\r
-    /**\r
-     *  Specifies how the text should be wrapped\r
-     *\r
-     * @param wrap  the value indicating how the text should be wrapped\r
-     */\r
-    public void setWordWrap(boolean wrap){\r
-        CTShape shape = (CTShape) getXmlObject();\r
-        if (shape.isSetTxBody()) {\r
-            shape.getTxBody().getBodyPr().setWrap(wrap ? STTextWrappingType.SQUARE : STTextWrappingType.NONE);\r
-        }\r
-    }\r
-\r
-    /**\r
-     *\r
-     * Specifies that a shape should be auto-fit to fully contain the text described within it.\r
-     * Auto-fitting is when text within a shape is scaled in order to contain all the text inside\r
-     *\r
-     * @param value type of autofit\r
-     */\r
-    public void setTextAutofit(TextAutofit value){\r
-        CTShape shape = (CTShape) getXmlObject();\r
-        if (shape.isSetTxBody()) {\r
-            CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr();\r
-            if(bodyPr.isSetSpAutoFit()) bodyPr.unsetSpAutoFit();\r
-            if(bodyPr.isSetNoAutofit()) bodyPr.unsetNoAutofit();\r
-            if(bodyPr.isSetNormAutofit()) bodyPr.unsetNormAutofit();\r
-\r
-            switch(value){\r
-                case NONE: bodyPr.addNewNoAutofit(); break;\r
-                case NORMAL: bodyPr.addNewNormAutofit(); break;\r
-                case SHAPE: bodyPr.addNewSpAutoFit(); break;\r
-            }\r
-        }\r
-    }\r
-\r
-    /**\r
-     *\r
-     * @return type of autofit\r
-     */\r
-    public TextAutofit getTextAutofit(){\r
-        CTShape shape = (CTShape) getXmlObject();\r
-        if (shape.isSetTxBody()) {\r
-            CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr();\r
-            if(bodyPr.isSetNoAutofit()) return TextAutofit.NONE;\r
-            else if (bodyPr.isSetNormAutofit()) return TextAutofit.NORMAL;\r
-            else if (bodyPr.isSetSpAutoFit()) return TextAutofit.SHAPE;\r
-        }\r
-        return TextAutofit.NORMAL;\r
-    }\r
-\r
-\r
-    @Override\r
-    void onCopy(XSLFSheet srcSheet){\r
-        CTShape shape = (CTShape) getXmlObject();\r
-        if (!shape.isSetTxBody()) return;\r
-\r
-        CTPlaceholder ph = shape.getNvSpPr().getNvPr().getPh();\r
-        if(ph == null || !ph.isSetType()) return;\r
-\r
-        if(ph.getType() == STPlaceholderType.TITLE){\r
-                        \r
+        CTTextBody txBody = shape.getTxBody();\r
+        if (txBody == null && create) {\r
+            txBody = shape.addNewTxBody();\r
+            txBody.addNewBodyPr();\r
+            txBody.addNewLstStyle();\r
         }\r
+        return txBody;\r
     }\r
 \r
 }
\ No newline at end of file
index ab8c1658fe791bdad911027c6e44045835e1eb38..e731a632d678e76fe50ee0e8cdf3041e377251ad 100755 (executable)
@@ -24,6 +24,7 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector;
 import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape;\r
 import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture;\r
 import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame;\r
 \r
 import java.awt.*;\r
 \r
@@ -97,4 +98,12 @@ public class XSLFDrawing {
         shape.setAnchor(new Rectangle());\r
         return shape;\r
     }\r
+\r
+    public XSLFTable createTable(){\r
+        CTGraphicalObjectFrame obj = _spTree.addNewGraphicFrame();\r
+        obj.set(XSLFTable.prototype(_shapeId++));\r
+        XSLFTable shape = new XSLFTable(obj, _sheet);\r
+        shape.setAnchor(new Rectangle());\r
+        return shape;\r
+    }\r
 }\r
index 0abad44f3094e4dd4f7477d8aedef0a6fb8dbe7f..7e0990331f4d21567ae151ad1e5733aedd179023 100755 (executable)
@@ -44,6 +44,10 @@ public class XSLFGraphicFrame extends XSLFShape {
         return _shape;\r
     }\r
 \r
+    public XSLFSheet getSheet(){\r
+        return _sheet;\r
+    }\r
+\r
     public int getShapeType(){\r
         throw new RuntimeException("NotImplemented");\r
     }\r
@@ -64,16 +68,14 @@ public class XSLFGraphicFrame extends XSLFShape {
         throw new RuntimeException("NotImplemented");\r
     }\r
 \r
-    public ShapeGroup getParent(){\r
-        throw new RuntimeException("NotImplemented");\r
-    }\r
 \r
-    public Shape[] getShapes(){\r
-        throw new RuntimeException("NotImplemented");\r
+    static XSLFGraphicFrame create(CTGraphicalObjectFrame shape, XSLFSheet sheet){\r
+        String uri = shape.getGraphic().getGraphicData().getUri();\r
+        if(XSLFTable.TABLE_URI.equals(uri)){\r
+            return new XSLFTable(shape, sheet);\r
+        } else {\r
+            return new XSLFGraphicFrame(shape, sheet);\r
+        }\r
     }\r
 \r
-\r
-    public boolean removeShape(Shape shape){\r
-        throw new RuntimeException("NotImplemented");\r
-    }\r
 }
\ 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 (file)
index 0000000..5a25851
--- /dev/null
@@ -0,0 +1,69 @@
+/* ====================================================================\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to You under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+       http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+==================================================================== */\r
+package org.apache.poi.xslf.usermodel;\r
+\r
+import org.apache.poi.openxml4j.opc.PackageRelationship;\r
+import org.apache.poi.openxml4j.opc.TargetMode;\r
+import org.apache.poi.util.Internal;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTHyperlink;\r
+\r
+import java.net.URI;\r
+\r
+/**\r
+ * @author Yegor Kozlov\r
+ */\r
+public class XSLFHyperlink {\r
+    final XSLFTextRun _r;\r
+    final CTHyperlink _link;\r
+\r
+    XSLFHyperlink(CTHyperlink link, XSLFTextRun r){\r
+        _r = r;\r
+        _link = link;\r
+    }\r
+\r
+    @Internal\r
+    public CTHyperlink getXmlObject(){\r
+        return _link;\r
+    }\r
+\r
+    public void setAddress(String address){\r
+        XSLFSheet sheet = _r.getParentParagraph().getParentShape().getSheet();\r
+        PackageRelationship rel =\r
+                sheet.getPackagePart().\r
+                        addExternalRelationship(address, XSLFRelation.HYPERLINK.getRelation());\r
+        _link.setId(rel.getId());\r
+\r
+    }\r
+\r
+    public void setAddress(XSLFSlide slide){\r
+        XSLFSheet sheet = _r.getParentParagraph().getParentShape().getSheet();\r
+        PackageRelationship rel =\r
+                sheet.getPackagePart().\r
+                        addRelationship(slide.getPackagePart().getPartName(),\r
+                                TargetMode.INTERNAL,\r
+                                XSLFRelation.SLIDE.getRelation());\r
+        _link.setId(rel.getId());\r
+        _link.setAction("ppaction://hlinksldjump");\r
+    }\r
+\r
+    @Internal\r
+    public URI getTargetURI(){\r
+        XSLFSheet sheet = _r.getParentParagraph().getParentShape().getSheet();\r
+        String id = _link.getId();\r
+        return sheet.getPackagePart().getRelationship(id).getTargetURI();\r
+    }\r
+}\r
index 10a35dfeeed09cc33c23d31c8814abfd67fb422a..15f91c6ec5a24c0f48cdd369f5287085a71abc94 100644 (file)
@@ -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",
index b1b65eac40c254caa6f7fba8aae7f01c1e6c6295..dfb659557f8ea0c504a7a983314e97894511a783 100755 (executable)
@@ -41,8 +41,4 @@ public abstract class XSLFShape {
     public abstract String getShapeName();\r
 \r
     public abstract int getShapeId();\r
-\r
-    void onCopy(XSLFSheet srcSheet){\r
-\r
-    }\r
 }
\ No newline at end of file
index 02ce9fdb7df65b4e6a354bc9553685434281d99b..d97600d398b575926893dfda1b86844c353f8be8 100644 (file)
@@ -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<XSLFShape> 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 (file)
index 0000000..dce9cc2
--- /dev/null
@@ -0,0 +1,157 @@
+/*\r
+ *  ====================================================================\r
+ *    Licensed to the Apache Software Foundation (ASF) under one or more\r
+ *    contributor license agreements.  See the NOTICE file distributed with\r
+ *    this work for additional information regarding copyright ownership.\r
+ *    The ASF licenses this file to You under the Apache License, Version 2.0\r
+ *    (the "License"); you may not use this file except in compliance with\r
+ *    the License.  You may obtain a copy of the License at\r
+ *\r
+ *        http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ *    Unless required by applicable law or agreed to in writing, software\r
+ *    distributed under the License is distributed on an "AS IS" BASIS,\r
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ *    See the License for the specific language governing permissions and\r
+ *    limitations under the License.\r
+ * ====================================================================\r
+ */\r
+\r
+package org.apache.poi.xslf.usermodel;\r
+\r
+import org.apache.poi.util.Internal;\r
+import org.apache.poi.util.Units;\r
+import org.apache.xmlbeans.XmlCursor;\r
+import org.apache.xmlbeans.XmlObject;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObjectData;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTable;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTableRow;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupTransform2D;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrameNonVisual;\r
+\r
+import javax.xml.namespace.QName;\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+import java.awt.geom.Rectangle2D;\r
+\r
+/**\r
+ * Represents a table in a .pptx presentation\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+public class XSLFTable extends XSLFGraphicFrame implements Iterable<XSLFTableRow> {\r
+    static String TABLE_URI = "http://schemas.openxmlformats.org/drawingml/2006/table";\r
+\r
+    private CTTable _table;\r
+    private List<XSLFTableRow> _rows;\r
+\r
+    /*package*/ XSLFTable(CTGraphicalObjectFrame shape, XSLFSheet sheet){\r
+        super(shape, sheet);\r
+\r
+        for(XmlObject obj : shape.getGraphic().getGraphicData().selectPath("*")){\r
+            if(obj instanceof CTTable){\r
+                _table = (CTTable)obj;\r
+            }\r
+        }\r
+        if(_table == null) throw new IllegalStateException("CTTable element was not found");\r
+\r
+        _rows = new ArrayList<XSLFTableRow>(_table.sizeOfTrArray());\r
+        for(CTTableRow row : _table.getTrList()) _rows.add(new XSLFTableRow(row, this));\r
+    }\r
+\r
+    @Internal\r
+    public CTTable getCTTable(){\r
+        return _table;\r
+    }\r
+\r
+    public int getNumberOfColumns() {\r
+        return _table.getTblGrid().sizeOfGridColArray();\r
+    }\r
+\r
+    public int getNumberOfRows() {\r
+        return _table.sizeOfTrArray();\r
+    }\r
+\r
+    public double getColumnWidth(int idx){\r
+        return Units.toPoints(\r
+                _table.getTblGrid().getGridColArray(idx).getW());\r
+    }\r
+\r
+    public void setColumnWidth(int idx, double width){\r
+        _table.getTblGrid().getGridColArray(idx).setW(Units.toEMU(width));\r
+    }\r
+\r
+    public Iterator<XSLFTableRow> iterator(){\r
+        return _rows.iterator();\r
+    }\r
+\r
+    public List<XSLFTableRow> getRows(){\r
+        return Collections.unmodifiableList(_rows);\r
+    }\r
+\r
+    public XSLFTableRow addRow(){\r
+        CTTableRow tr = _table.addNewTr();\r
+        XSLFTableRow row = new XSLFTableRow(tr, this);\r
+        row.setHeight(20.0);    // default height is 20 points\r
+        _rows.add(row);\r
+        return row;\r
+    }\r
+\r
+    static CTGraphicalObjectFrame prototype(int shapeId){\r
+        CTGraphicalObjectFrame frame = CTGraphicalObjectFrame.Factory.newInstance();\r
+        CTGraphicalObjectFrameNonVisual nvGr = frame.addNewNvGraphicFramePr();\r
+\r
+        CTNonVisualDrawingProps cnv = nvGr.addNewCNvPr();\r
+        cnv.setName("Table " + shapeId);\r
+        cnv.setId(shapeId + 1);\r
+        nvGr.addNewCNvGraphicFramePr().addNewGraphicFrameLocks().setNoGrp(true);\r
+        nvGr.addNewNvPr();\r
+        \r
+        frame.addNewXfrm();\r
+        CTGraphicalObjectData gr = frame.addNewGraphic().addNewGraphicData();\r
+        XmlCursor cursor = gr.newCursor();\r
+        cursor.toNextToken();\r
+        cursor.beginElement(new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "tbl"));\r
+        cursor.beginElement(new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "tblPr"));\r
+        cursor.toNextToken();\r
+        cursor.beginElement(new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "tblGrid"));\r
+        cursor.dispose();\r
+        gr.setUri(TABLE_URI);\r
+        return frame;\r
+    }\r
+\r
+    public Rectangle2D getAnchor(){\r
+        CTTransform2D xfrm = getXmlObject().getXfrm();\r
+        CTPoint2D off = xfrm.getOff();\r
+        long x = off.getX();\r
+        long y = off.getY();\r
+        CTPositiveSize2D ext = xfrm.getExt();\r
+        long cx = ext.getCx();\r
+        long cy = ext.getCy();\r
+        return new Rectangle2D.Double(\r
+                Units.toPoints(x), Units.toPoints(y),\r
+                Units.toPoints(cx), Units.toPoints(cy));\r
+    }\r
+\r
+    public void setAnchor(Rectangle2D anchor){\r
+        CTTransform2D xfrm = getXmlObject().getXfrm();\r
+        CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff();\r
+        long x = Units.toEMU(anchor.getX());\r
+        long y = Units.toEMU(anchor.getY());\r
+        off.setX(x);\r
+        off.setY(y);\r
+        CTPositiveSize2D ext = xfrm.isSetExt() ? xfrm.getExt() : xfrm.addNewExt();\r
+        long cx = Units.toEMU(anchor.getWidth());\r
+        long cy = Units.toEMU(anchor.getHeight());\r
+        ext.setCx(cx);\r
+        ext.setCy(cy);\r
+    }\r
+    \r
+}\r
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 (file)
index 0000000..cc04a10
--- /dev/null
@@ -0,0 +1,290 @@
+/*\r
+ *  ====================================================================\r
+ *    Licensed to the Apache Software Foundation (ASF) under one or more\r
+ *    contributor license agreements.  See the NOTICE file distributed with\r
+ *    this work for additional information regarding copyright ownership.\r
+ *    The ASF licenses this file to You under the Apache License, Version 2.0\r
+ *    (the "License"); you may not use this file except in compliance with\r
+ *    the License.  You may obtain a copy of the License at\r
+ *\r
+ *        http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ *    Unless required by applicable law or agreed to in writing, software\r
+ *    distributed under the License is distributed on an "AS IS" BASIS,\r
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ *    See the License for the specific language governing permissions and\r
+ *    limitations under the License.\r
+ * ====================================================================\r
+ */\r
+\r
+package org.apache.poi.xslf.usermodel;\r
+\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCell;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCellProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STPenAlignment;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STCompoundLine;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTLineEndProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndLength;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndType;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndWidth;\r
+import org.apache.poi.util.Internal;\r
+import org.apache.poi.util.Units;\r
+\r
+import java.awt.*;\r
+\r
+/**\r
+ * Represents a cell of a table in a .pptx presentation\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+public class XSLFTableCell extends XSLFTextShape {\r
+    static double defaultBorderWidth = 1.0;\r
+\r
+    /*package*/ XSLFTableCell(CTTableCell cell, XSLFSheet sheet){\r
+        super(cell, sheet);\r
+    }\r
+\r
+    @Override\r
+    public CTTableCell getXmlObject(){\r
+        return (CTTableCell)super.getXmlObject();\r
+    }\r
+\r
+    @Override\r
+    protected CTTextBody getTextBody(boolean create){\r
+        CTTableCell cell = getXmlObject();\r
+        CTTextBody txBody = cell.getTxBody();\r
+        if (txBody == null && create) {\r
+            txBody = cell.addNewTxBody();\r
+            txBody.addNewBodyPr();\r
+            txBody.addNewLstStyle();\r
+        }\r
+        return txBody;\r
+    }\r
+\r
+    static CTTableCell prototype() {\r
+        CTTableCell cell = CTTableCell.Factory.newInstance();\r
+        CTTableCellProperties pr = cell.addNewTcPr();\r
+        pr.addNewLnL().addNewNoFill();\r
+        pr.addNewLnR().addNewNoFill();\r
+        pr.addNewLnT().addNewNoFill();\r
+        pr.addNewLnB().addNewNoFill();\r
+        return cell;\r
+    }\r
+\r
+    @Override\r
+    public void setMarginLeft(double margin){\r
+        CTTableCellProperties pr = getXmlObject().getTcPr();\r
+        if(pr == null) pr = getXmlObject().addNewTcPr();\r
+\r
+        pr.setMarL(Units.toEMU(margin));\r
+    }\r
+    \r
+    @Override\r
+    public void setMarginRight(double margin){\r
+        CTTableCellProperties pr = getXmlObject().getTcPr();\r
+        if(pr == null) pr = getXmlObject().addNewTcPr();\r
+\r
+        pr.setMarR(Units.toEMU(margin));\r
+    }\r
+\r
+    @Override\r
+    public void setMarginTop(double margin){\r
+        CTTableCellProperties pr = getXmlObject().getTcPr();\r
+        if(pr == null) pr = getXmlObject().addNewTcPr();\r
+\r
+        pr.setMarT(Units.toEMU(margin));\r
+    }\r
+\r
+    @Override\r
+    public void setMarginBottom(double margin){\r
+        CTTableCellProperties pr = getXmlObject().getTcPr();\r
+        if(pr == null) pr = getXmlObject().addNewTcPr();\r
+\r
+        pr.setMarB(Units.toEMU(margin));\r
+    }\r
+\r
+    public void setBorderLeft(double width){\r
+        CTTableCellProperties pr = getXmlObject().getTcPr();\r
+\r
+        CTLineProperties ln = pr.isSetLnL() ? pr.getLnL() : pr.addNewLnL();\r
+        ln.setW(Units.toEMU(width));\r
+    }\r
+\r
+    public double getBorderLeft(){\r
+        CTTableCellProperties pr = getXmlObject().getTcPr();\r
+\r
+        CTLineProperties ln = pr.getLnL();\r
+        return ln == null || !ln.isSetW() ? defaultBorderWidth : Units.toPoints(ln.getW());\r
+    }\r
+\r
+    public void setBorderLeftColor(Color color){\r
+        CTTableCellProperties pr = getXmlObject().getTcPr();\r
+        CTLineProperties ln = pr.isSetLnL() ? pr.getLnL() : pr.addNewLnL();\r
+        setLineColor(ln, color);\r
+    }\r
+\r
+    public Color getBorderLeftColor(){\r
+        return getLineColor(getXmlObject().getTcPr().getLnL());\r
+    }\r
+\r
+    public void setBorderRight(double width){\r
+        CTTableCellProperties pr = getXmlObject().getTcPr();\r
+\r
+        CTLineProperties ln = pr.isSetLnR() ? pr.getLnR() : pr.addNewLnR();\r
+        ln.setW(Units.toEMU(width));\r
+    }\r
+\r
+    public double getBorderRight(){\r
+        CTTableCellProperties pr = getXmlObject().getTcPr();\r
+\r
+        CTLineProperties ln = pr.getLnR();\r
+        return ln == null || !ln.isSetW() ? defaultBorderWidth : Units.toPoints(ln.getW());\r
+    }\r
+\r
+    public void setBorderRightColor(Color color){\r
+        CTTableCellProperties pr = getXmlObject().getTcPr();\r
+        CTLineProperties ln = pr.isSetLnR() ? pr.getLnR() : pr.addNewLnR();\r
+        setLineColor(ln, color);\r
+    }\r
+\r
+    public Color getBorderRightColor(){\r
+        return getLineColor(getXmlObject().getTcPr().getLnR());\r
+    }\r
+\r
+    public void setBorderTop(double width){\r
+        CTTableCellProperties pr = getXmlObject().getTcPr();\r
+\r
+        CTLineProperties ln = pr.isSetLnT() ? pr.getLnT() : pr.addNewLnT();\r
+        ln.setW(Units.toEMU(width));\r
+    }\r
+\r
+    public double getBorderTop(){\r
+        CTTableCellProperties pr = getXmlObject().getTcPr();\r
+\r
+        CTLineProperties ln = pr.getLnT();\r
+        return ln == null || !ln.isSetW() ? defaultBorderWidth : Units.toPoints(ln.getW());\r
+    }\r
+\r
+    public void setBorderTopColor(Color color){\r
+        CTTableCellProperties pr = getXmlObject().getTcPr();\r
+        CTLineProperties ln = pr.isSetLnT() ? pr.getLnT() : pr.addNewLnT();\r
+        setLineColor(ln, color);\r
+    }\r
+\r
+    public Color getBorderTopColor(){\r
+        return getLineColor(getXmlObject().getTcPr().getLnT());\r
+    }\r
+\r
+    public void setBorderBottom(double width){\r
+        CTTableCellProperties pr = getXmlObject().getTcPr();\r
+\r
+        CTLineProperties ln = pr.isSetLnB() ? pr.getLnB() : pr.addNewLnB();\r
+        ln.setW(Units.toEMU(width));\r
+    }\r
+\r
+    public double getBorderBottom(){\r
+        CTTableCellProperties pr = getXmlObject().getTcPr();\r
+\r
+        CTLineProperties ln = pr.getLnB();\r
+        return ln == null || !ln.isSetW() ? defaultBorderWidth : Units.toPoints(ln.getW());\r
+    }\r
+\r
+    public void setBorderBottomColor(Color color){\r
+        CTTableCellProperties pr = getXmlObject().getTcPr();\r
+        CTLineProperties ln = pr.isSetLnB() ? pr.getLnB() : pr.addNewLnB();\r
+        setLineColor(ln, color);\r
+    }\r
+\r
+    public Color getBorderBottomColor(){\r
+        return getLineColor(getXmlObject().getTcPr().getLnB());\r
+    }\r
+\r
+    private void setLineColor(CTLineProperties ln, Color color){\r
+        if(color == null){\r
+            ln.addNewNoFill();\r
+            if(ln.isSetSolidFill()) ln.unsetSolidFill();\r
+        } else {\r
+            if(ln.isSetNoFill()) ln.unsetNoFill();\r
+\r
+            if(!ln.isSetPrstDash()) ln.addNewPrstDash().setVal(STPresetLineDashVal.SOLID);\r
+            ln.setCmpd(STCompoundLine.SNG);\r
+            ln.setAlgn(STPenAlignment.CTR);\r
+            ln.setCap(STLineCap.FLAT);\r
+            ln.addNewRound();\r
+\r
+            CTLineEndProperties hd = ln.addNewHeadEnd();\r
+            hd.setType(STLineEndType.NONE);\r
+            hd.setW(STLineEndWidth.MED);\r
+            hd.setLen(STLineEndLength.MED);\r
+\r
+            CTLineEndProperties tl = ln.addNewTailEnd();\r
+            tl.setType(STLineEndType.NONE);\r
+            tl.setW(STLineEndWidth.MED);\r
+            tl.setLen(STLineEndLength.MED);\r
+\r
+            CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();\r
+            rgb.setVal(new byte[]{(byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue()});\r
+            ln.addNewSolidFill().setSrgbClr(rgb);\r
+        }\r
+    }\r
+\r
+    private Color getLineColor(CTLineProperties ln){\r
+        if(ln == null || ln.isSetNoFill() || !ln.isSetSolidFill()) return null;\r
+\r
+        CTSolidColorFillProperties fill = ln.getSolidFill();\r
+        if(!fill.isSetSrgbClr()) {\r
+            // TODO for now return null for all colors except explicit RGB\r
+            return null;\r
+        }\r
+        byte[] val = fill.getSrgbClr().getVal();\r
+        return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]);\r
+    }\r
+    /**\r
+     * Specifies a solid color fill. The shape is filled entirely with the specified color.\r
+     *\r
+     * @param color the solid color fill.\r
+     * The value of <code>null</code> unsets the solidFIll attribute from the underlying xml\r
+     */\r
+    @Override\r
+    public void setFillColor(Color color) {\r
+        CTTableCellProperties spPr = getXmlObject().getTcPr();\r
+        if (color == null) {\r
+            if(spPr.isSetSolidFill()) spPr.unsetSolidFill();\r
+        }\r
+        else {\r
+            CTSolidColorFillProperties fill = spPr.isSetSolidFill() ? spPr.getSolidFill() : spPr.addNewSolidFill();\r
+\r
+            CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();\r
+            rgb.setVal(new byte[]{(byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue()});\r
+\r
+            fill.setSrgbClr(rgb);\r
+        }\r
+    }\r
+\r
+    /**\r
+     *\r
+     * @return solid fill color of null if not set\r
+     */\r
+    @Override\r
+    public Color getFillColor(){\r
+        CTTableCellProperties spPr = getXmlObject().getTcPr();\r
+        if(!spPr.isSetSolidFill() ) return null;\r
+\r
+        CTSolidColorFillProperties fill = spPr.getSolidFill();\r
+        if(!fill.isSetSrgbClr()) {\r
+            // TODO for now return null for all colors except explicit RGB\r
+            return null;\r
+        }\r
+        byte[] val = fill.getSrgbClr().getVal();\r
+        return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]);\r
+    }\r
+\r
+}\r
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 (file)
index 0000000..328c76a
--- /dev/null
@@ -0,0 +1,86 @@
+/*\r
+ *  ====================================================================\r
+ *    Licensed to the Apache Software Foundation (ASF) under one or more\r
+ *    contributor license agreements.  See the NOTICE file distributed with\r
+ *    this work for additional information regarding copyright ownership.\r
+ *    The ASF licenses this file to You under the Apache License, Version 2.0\r
+ *    (the "License"); you may not use this file except in compliance with\r
+ *    the License.  You may obtain a copy of the License at\r
+ *\r
+ *        http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ *    Unless required by applicable law or agreed to in writing, software\r
+ *    distributed under the License is distributed on an "AS IS" BASIS,\r
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ *    See the License for the specific language governing permissions and\r
+ *    limitations under the License.\r
+ * ====================================================================\r
+ */\r
+\r
+package org.apache.poi.xslf.usermodel;\r
+\r
+import org.apache.poi.util.Units;\r
+import org.apache.xmlbeans.XmlObject;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTable;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCell;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTableRow;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+import java.util.List;\r
+import java.util.Iterator;\r
+\r
+/**\r
+ * Represents a table in a .pptx presentation\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+public class XSLFTableRow implements Iterable<XSLFTableCell> {\r
+    private CTTableRow _row;\r
+    private List<XSLFTableCell> _cells;\r
+    private XSLFTable _table;\r
+\r
+    /*package*/ XSLFTableRow(CTTableRow row, XSLFTable table){\r
+        _row = row;\r
+        _table = table;\r
+        _cells = new ArrayList<XSLFTableCell>(_row.sizeOfTcArray());\r
+        for(CTTableCell cell : _row.getTcList()) {\r
+            _cells.add(new XSLFTableCell(cell, table.getSheet()));\r
+        }\r
+    }\r
+\r
+    public CTTableRow getXmlObject(){\r
+        return _row;\r
+    }\r
+\r
+    public Iterator<XSLFTableCell> iterator(){\r
+        return _cells.iterator();\r
+    }\r
+\r
+    public List<XSLFTableCell> getCells(){\r
+        return Collections.unmodifiableList(_cells);\r
+    }\r
+\r
+    public double getHeight(){\r
+        return Units.toPoints(_row.getH());\r
+    }\r
+\r
+    public void setHeight(double height){\r
+        _row.setH(Units.toEMU(height));\r
+    }\r
+\r
+    public XSLFTableCell addCell(){\r
+        CTTableCell c = _row.addNewTc();\r
+        c.set(XSLFTableCell.prototype());\r
+        XSLFTableCell cell = new XSLFTableCell(c, _table.getSheet());\r
+        _cells.add(cell);\r
+\r
+        if(_table.getNumberOfColumns() < _row.sizeOfTcArray()) {\r
+            _table.getCTTable().getTblGrid().addNewGridCol().setW(Units.toEMU(100.0));    \r
+        }\r
+        return cell;\r
+    }\r
+\r
+\r
+}\r
index 9317298ee3a967863532bcf2d39bcc5525506589..e20be9b5c22e0533d9d272f99e5411f645333ee7 100755 (executable)
@@ -40,12 +40,14 @@ import java.util.List;
 public class XSLFTextParagraph implements Iterable<XSLFTextRun>{\r
     private final CTTextParagraph _p;\r
     private final List<XSLFTextRun> _runs;\r
+    private final XSLFTextShape _shape;\r
 \r
-    XSLFTextParagraph(CTTextParagraph p){\r
+    XSLFTextParagraph(CTTextParagraph p, XSLFTextShape shape){\r
         _p = p;\r
         _runs = new ArrayList<XSLFTextRun>();\r
+        _shape = shape;\r
         for (CTRegularTextRun r : _p.getRList()) {\r
-            _runs.add(new XSLFTextRun(r));\r
+            _runs.add(new XSLFTextRun(r, this));\r
         }\r
     }\r
 \r
@@ -62,6 +64,10 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
         return _p;\r
     }\r
 \r
+    XSLFTextShape getParentShape() {\r
+        return _shape;\r
+\r
+    }\r
     public List<XSLFTextRun> getTextRuns(){\r
         return _runs;\r
     }\r
@@ -72,7 +78,8 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
 \r
     public XSLFTextRun addNewTextRun(){\r
         CTRegularTextRun r = _p.addNewR();\r
-        XSLFTextRun run = new XSLFTextRun(r);\r
+        r.addNewRPr();\r
+        XSLFTextRun run = new XSLFTextRun(r, this);\r
         _runs.add(run);\r
         return run;\r
     }\r
index 859649197b08b979009b5dc45160f936610abe4b..c62775e086f6f5d46172e5b02649f88b55b267e4 100755 (executable)
@@ -36,9 +36,15 @@ import java.awt.*;
 @Beta\r
 public class XSLFTextRun {\r
     private final CTRegularTextRun _r;\r
+    private final XSLFTextParagraph _p;\r
 \r
-    XSLFTextRun(CTRegularTextRun r){\r
+    XSLFTextRun(CTRegularTextRun r, XSLFTextParagraph p){\r
         _r = r;\r
+        _p = p;\r
+    }\r
+\r
+    XSLFTextParagraph getParentParagraph(){\r
+        return _p;\r
     }\r
 \r
     public String getText(){\r
@@ -78,7 +84,7 @@ public class XSLFTextRun {
      * @return font size in points or -1 if font size is not set.\r
      */\r
     public double getFontSize(){\r
-        if(!_r.isSetRPr()) return -1;\r
+        if(!_r.isSetRPr() || !_r.getRPr().isSetSz()) return -1;\r
 \r
         return _r.getRPr().getSz()*0.01;\r
     }\r
@@ -198,5 +204,16 @@ public class XSLFTextRun {
     public String toString(){\r
         return "[" + getClass() + "]" + getText();\r
     }\r
-    \r
+\r
+    public XSLFHyperlink createHyperlink(){\r
+        XSLFHyperlink link = new XSLFHyperlink(_r.getRPr().addNewHlinkClick(), this);\r
+        return link;\r
+    }\r
+\r
+    public XSLFHyperlink getHyperlink(){\r
+        if(!_r.getRPr().isSetHlinkClick()) return null;\r
+\r
+\r
+        return new XSLFHyperlink(_r.getRPr().getHlinkClick(), this);\r
+    }\r
 }
\ 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 (file)
index 0000000..5bb48b6
--- /dev/null
@@ -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<XSLFTextParagraph> _paragraphs;
+
+    /*package*/ XSLFTextShape(XmlObject shape, XSLFSheet sheet) {
+        super(shape, sheet);
+
+        _paragraphs = new ArrayList<XSLFTextParagraph>();
+        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<XSLFTextParagraph> 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 <code>null</code> 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 <code>Anchor*</code> 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 <code>Wrap*</code> 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
index 69be4b7a6bb7072f9ee276542e5ccadfa8872b71..efed3ca0345bd741dc6fb0a26f77b9db70c05f00 100755 (executable)
@@ -210,7 +210,7 @@ public class TestXSLFAutoShape extends TestCase {
         assertSame(r, p.getTextRuns().get(0));\r
 \r
         assertEquals(-1.0, r.getFontSize());\r
-        assertFalse(r.getXmlObject().isSetRPr());\r
+        assertFalse(r.getXmlObject().getRPr().isSetSz());\r
         r.setFontSize(10.0);\r
         assertTrue(r.getXmlObject().isSetRPr());\r
         assertEquals(1000, r.getXmlObject().getRPr().getSz());\r
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 (file)
index 0000000..fe968b0
--- /dev/null
@@ -0,0 +1,102 @@
+/* ====================================================================\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to You under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+       http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+==================================================================== */\r
+package org.apache.poi.xslf.usermodel;\r
+\r
+import junit.framework.TestCase;\r
+\r
+import java.awt.*;\r
+import java.awt.geom.Ellipse2D;\r
+import java.awt.geom.GeneralPath;\r
+import java.util.*;\r
+import java.util.List;\r
+import java.net.URI;\r
+\r
+import org.apache.poi.xslf.XSLFTestDataSamples;\r
+import org.apache.poi.xssf.usermodel.XSSFTable;\r
+import org.apache.poi.openxml4j.opc.PackageRelationship;\r
+import org.apache.poi.openxml4j.opc.TargetMode;\r
+\r
+/**\r
+ * @author Yegor Kozlov\r
+ */\r
+public class TestXSLFHyperlink extends TestCase {\r
+\r
+    public void testRead(){\r
+        XMLSlideShow  ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx");\r
+\r
+        XSLFSlide slide = ppt.getSlides()[4];\r
+        XSLFShape[] shapes = slide.getShapes();\r
+        XSLFTable tbl = (XSLFTable)shapes[0];\r
+        XSLFTableCell cell1 = tbl.getRows().get(1).getCells().get(0);\r
+        assertEquals("Web Page", cell1.getText());\r
+        XSLFHyperlink link1 = cell1.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink();\r
+        assertNotNull(link1);\r
+        assertEquals(URI.create("http://poi.apache.org/"), link1.getTargetURI());\r
+\r
+        XSLFTableCell cell2 = tbl.getRows().get(2).getCells().get(0);\r
+        assertEquals("Place in this document", cell2.getText());\r
+        XSLFHyperlink link2 = cell2.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink();\r
+        assertNotNull(link2);\r
+        assertEquals(URI.create("/ppt/slides/slide2.xml"), link2.getTargetURI());\r
+\r
+        XSLFTableCell cell3 = tbl.getRows().get(3).getCells().get(0);\r
+        assertEquals("Email", cell3.getText());\r
+        XSLFHyperlink link3 = cell3.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink();\r
+        assertNotNull(link3);\r
+        assertEquals(URI.create("mailto:dev@poi.apache.org?subject=Hi%20There"), link3.getTargetURI());\r
+    }\r
+\r
+    public void testCreate() throws Exception  {\r
+        XMLSlideShow ppt = new XMLSlideShow();\r
+        XSLFSlide slide1 = ppt.createSlide();\r
+        XSLFSlide slide2 = ppt.createSlide();\r
+\r
+        int numRel = slide1.getPackagePart().getRelationships().size();\r
+        assertEquals(1, numRel);\r
+        XSLFTextBox sh1 = slide1.createTextBox();\r
+        XSLFTextRun r1 = sh1.addNewTextParagraph().addNewTextRun();\r
+        r1.setText("Web Page");\r
+        XSLFHyperlink link1 = r1.createHyperlink();\r
+        link1.setAddress("http://poi.apache.org/");\r
+        assertEquals(URI.create("http://poi.apache.org/"), link1.getTargetURI());\r
+        assertEquals(numRel + 1, slide1.getPackagePart().getRelationships().size());\r
+\r
+        String id1 = link1.getXmlObject().getId();\r
+        assertNotNull(id1);\r
+        PackageRelationship rel1 = slide1.getPackagePart().getRelationship(id1);\r
+        assertNotNull(rel1);\r
+        assertEquals(id1, rel1.getId());\r
+        assertEquals(TargetMode.EXTERNAL, rel1.getTargetMode());\r
+        assertEquals(XSLFRelation.HYPERLINK.getRelation(), rel1.getRelationshipType());\r
+\r
+        XSLFTextBox sh2 = slide1.createTextBox();\r
+        XSLFTextRun r2 = sh2.addNewTextParagraph().addNewTextRun();\r
+        r2.setText("Place in this document");\r
+        XSLFHyperlink link2 = r2.createHyperlink();\r
+        link2.setAddress(slide2);\r
+        assertEquals(URI.create("/ppt/slides/slide2.xml"), link2.getTargetURI());\r
+        assertEquals(numRel + 2, slide1.getPackagePart().getRelationships().size());\r
+\r
+        String id2 = link2.getXmlObject().getId();\r
+        assertNotNull(id2);\r
+        PackageRelationship rel2 = slide1.getPackagePart().getRelationship(id2);\r
+        assertNotNull(rel2);\r
+        assertEquals(id2, rel2.getId());\r
+        assertEquals(TargetMode.INTERNAL, rel2.getTargetMode());\r
+        assertEquals(XSLFRelation.SLIDE.getRelation(), rel2.getRelationshipType());\r
+    }\r
+}
\ No newline at end of file
index ca3d82f975a8b03902b83fed0c42a20d894703a9..ecdcdd032d19105a06a48cac62294413e20e3b18 100755 (executable)
@@ -31,7 +31,6 @@ public class TestXSLFShape extends TestCase {
     public void testReadTextShapes() {\r
         XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx");\r
         XSLFSlide[] slides = ppt.getSlides();\r
-        assertEquals(3, slides.length);\r
 \r
         XSLFSlide slide1 = slides[0];\r
         XSLFShape[] shapes1 = slide1.getShapes();\r
index 9c7d131d808dd0279f13ad2ad00df88b59d33fec..9ffe69fe989ba1e0042a83d63681ec1d21c6c044 100755 (executable)
@@ -30,7 +30,6 @@ public class TestXSLFSlide extends TestCase {
     public void testReadShapes(){\r
         XMLSlideShow  ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx");\r
         XSLFSlide[] slides = ppt.getSlides();\r
-        assertEquals(3, slides.length);\r
 \r
         XSLFSlide slide1 = slides[0];\r
         XSLFShape[] shapes1 = slide1.getShapes();\r
@@ -85,6 +84,14 @@ public class TestXSLFSlide extends TestCase {
 \r
         assertTrue(groupShapes[2] instanceof XSLFAutoShape);\r
         assertEquals("Right Arrow 3", groupShapes[2].getShapeName());\r
+\r
+        XSLFSlide slide4 = slides[3];\r
+        XSLFShape[] shapes4 = slide4.getShapes();\r
+        assertEquals(1, shapes4.length);\r
+        assertTrue(shapes4[0] instanceof XSLFTable);\r
+        XSLFTable tbl = (XSLFTable)shapes4[0];\r
+        assertEquals(3, tbl.getNumberOfColumns());\r
+        assertEquals(6, tbl.getNumberOfRows());\r
     }\r
 \r
     public void testCreateSlide(){\r
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 (file)
index 0000000..a5cdb0d
--- /dev/null
@@ -0,0 +1,150 @@
+/* ====================================================================\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to You under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+       http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+==================================================================== */\r
+package org.apache.poi.xslf.usermodel;\r
+\r
+import junit.framework.TestCase;\r
+\r
+import java.awt.*;\r
+import java.awt.geom.Ellipse2D;\r
+import java.awt.geom.GeneralPath;\r
+import java.util.*;\r
+import java.util.List;\r
+\r
+import org.apache.poi.xslf.XSLFTestDataSamples;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame;\r
+\r
+/**\r
+ * @author Yegor Kozlov\r
+ */\r
+public class TestXSLFTable extends TestCase {\r
+\r
+    public void testRead(){\r
+        XMLSlideShow  ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx");\r
+\r
+        XSLFSlide slide = ppt.getSlides()[3];\r
+        XSLFShape[] shapes = slide.getShapes();\r
+        assertEquals(1, shapes.length);\r
+        assertTrue(shapes[0] instanceof XSLFTable);\r
+        XSLFTable tbl = (XSLFTable)shapes[0];\r
+        assertEquals(3, tbl.getNumberOfColumns());\r
+        assertEquals(6, tbl.getNumberOfRows());\r
+        assertNotNull(tbl.getCTTable());\r
+\r
+        List<XSLFTableRow> rows = tbl.getRows();\r
+        assertEquals(6, rows.size());\r
+\r
+        assertEquals(90.0, tbl.getColumnWidth(0));\r
+        assertEquals(240.0, tbl.getColumnWidth(1));\r
+        assertEquals(150.0, tbl.getColumnWidth(2));\r
+\r
+        for(XSLFTableRow row : tbl){\r
+            // all rows have the same height\r
+            assertEquals(29.2, row.getHeight());\r
+        }\r
+\r
+        XSLFTableRow row0 = rows.get(0);\r
+        List<XSLFTableCell> cells0 = row0.getCells();\r
+        assertEquals(3, cells0.size());\r
+        assertEquals("header1", cells0.get(0).getText());\r
+        assertEquals("header2", cells0.get(1).getText());\r
+        assertEquals("header3", cells0.get(2).getText());\r
+\r
+        XSLFTableRow row1 = rows.get(1);\r
+        List<XSLFTableCell> cells1 = row1.getCells();\r
+        assertEquals(3, cells1.size());\r
+        assertEquals("A1", cells1.get(0).getText());\r
+        assertEquals("B1", cells1.get(1).getText());\r
+        assertEquals("C1", cells1.get(2).getText());\r
+    }\r
+\r
+    public void testCreate() {\r
+        XMLSlideShow ppt = new XMLSlideShow();\r
+        XSLFSlide slide = ppt.createSlide();\r
+\r
+        XSLFTable tbl = slide.createTable();\r
+        assertNotNull(tbl.getCTTable());\r
+        assertNotNull(tbl.getCTTable().getTblGrid());\r
+        assertNotNull(tbl.getCTTable().getTblPr());\r
+        assertTrue(tbl.getXmlObject() instanceof CTGraphicalObjectFrame);\r
+        assertEquals("Table 1", tbl.getShapeName());\r
+        assertEquals(2, tbl.getShapeId());\r
+        assertEquals(0, tbl.getRows().size());\r
+        assertEquals(0, tbl.getCTTable().sizeOfTrArray());\r
+        assertEquals(0, tbl.getCTTable().getTblGrid().sizeOfGridColArray());\r
+\r
+        assertEquals(0, tbl.getNumberOfColumns());\r
+        assertEquals(0, tbl.getNumberOfRows());\r
+\r
+        XSLFTableRow row0 = tbl.addRow();\r
+        assertNotNull(row0.getXmlObject());\r
+        assertEquals(1, tbl.getNumberOfRows());\r
+        assertSame(row0, tbl.getRows().get(0));\r
+        assertEquals(20.0, row0.getHeight());\r
+        row0.setHeight(30.0);\r
+        assertEquals(30.0, row0.getHeight());\r
+\r
+        assertEquals(0, row0.getCells().size());\r
+        XSLFTableCell cell0 = row0.addCell();\r
+        assertNotNull(cell0.getXmlObject());\r
+        // by default table cell has no borders\r
+        assertTrue(cell0.getXmlObject().getTcPr().getLnB().isSetNoFill());\r
+        assertTrue(cell0.getXmlObject().getTcPr().getLnT().isSetNoFill());\r
+        assertTrue(cell0.getXmlObject().getTcPr().getLnL().isSetNoFill());\r
+        assertTrue(cell0.getXmlObject().getTcPr().getLnR().isSetNoFill());\r
+\r
+        assertSame(cell0, row0.getCells().get(0));\r
+        assertEquals(1, tbl.getNumberOfColumns());\r
+        assertEquals(100.0, tbl.getColumnWidth(0));\r
+        cell0.addNewTextParagraph().addNewTextRun().setText("POI");\r
+        assertEquals("POI", cell0.getText());\r
+\r
+        XSLFTableCell cell1 = row0.addCell();\r
+        assertSame(cell1, row0.getCells().get(1));\r
+        assertEquals(2, tbl.getNumberOfColumns());\r
+        assertEquals(100.0, tbl.getColumnWidth(1));\r
+        cell1.addNewTextParagraph().addNewTextRun().setText("Apache");\r
+        assertEquals("Apache", cell1.getText());\r
+\r
+        assertEquals(1.0, cell1.getBorderBottom());\r
+        cell1.setBorderBottom(2.0);\r
+        assertEquals(2.0, cell1.getBorderBottom());\r
+        assertNull(cell1.getBorderBottomColor());\r
+        cell1.setBorderBottomColor(Color.yellow);\r
+        assertEquals(Color.yellow, cell1.getBorderBottomColor());\r
+\r
+        assertEquals(1.0, cell1.getBorderTop());\r
+        cell1.setBorderTop(2.0);\r
+        assertEquals(2.0, cell1.getBorderTop());\r
+        assertNull(cell1.getBorderTopColor());\r
+        cell1.setBorderTopColor(Color.yellow);\r
+        assertEquals(Color.yellow, cell1.getBorderTopColor());\r
+\r
+        assertEquals(1.0, cell1.getBorderLeft());\r
+        cell1.setBorderLeft(2.0);\r
+        assertEquals(2.0, cell1.getBorderLeft());\r
+        assertNull(cell1.getBorderLeftColor());\r
+        cell1.setBorderLeftColor(Color.yellow);\r
+        assertEquals(Color.yellow, cell1.getBorderLeftColor());\r
+\r
+        assertEquals(1.0, cell1.getBorderRight());\r
+        cell1.setBorderRight(2.0);\r
+        assertEquals(2.0, cell1.getBorderRight());\r
+        assertNull(cell1.getBorderRightColor());\r
+        cell1.setBorderRightColor(Color.yellow);\r
+        assertEquals(Color.yellow, cell1.getBorderRightColor());\r
+    }\r
+}
\ No newline at end of file
index 0b3861228d1dce1969bb7252c03c8fcaf4fdded4..cf017a873aa3707fbfabda5603c63a27cd655fe2 100755 (executable)
Binary files a/test-data/slideshow/shapes.pptx and b/test-data/slideshow/shapes.pptx differ