]> source.dussan.org Git - poi.git/commitdiff
initial support for XSLF usermodel API
authorYegor Kozlov <yegor@apache.org>
Thu, 11 Aug 2011 08:38:19 +0000 (08:38 +0000)
committerYegor Kozlov <yegor@apache.org>
Thu, 11 Aug 2011 08:38:19 +0000 (08:38 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1156539 13f79535-47bb-0310-9956-ffa450edef68

54 files changed:
src/documentation/content/xdocs/status.xml
src/examples/src/org/apache/poi/xslf/usermodel/SlidesAndShapes.java [new file with mode: 0644]
src/ooxml/java/org/apache/poi/util/Units.java [new file with mode: 0755]
src/ooxml/java/org/apache/poi/xslf/XSLFSlideShow.java
src/ooxml/java/org/apache/poi/xslf/extractor/XSLFPowerPointExtractor.java
src/ooxml/java/org/apache/poi/xslf/usermodel/DrawingParagraph.java
src/ooxml/java/org/apache/poi/xslf/usermodel/DrawingTable.java
src/ooxml/java/org/apache/poi/xslf/usermodel/DrawingTableRow.java
src/ooxml/java/org/apache/poi/xslf/usermodel/DrawingTextBody.java
src/ooxml/java/org/apache/poi/xslf/usermodel/LineCap.java [new file with mode: 0755]
src/ooxml/java/org/apache/poi/xslf/usermodel/LineDash.java [new file with mode: 0755]
src/ooxml/java/org/apache/poi/xslf/usermodel/LineDecoration.java [new file with mode: 0644]
src/ooxml/java/org/apache/poi/xslf/usermodel/LineEndLength.java [new file with mode: 0644]
src/ooxml/java/org/apache/poi/xslf/usermodel/LineEndWidth.java [new file with mode: 0644]
src/ooxml/java/org/apache/poi/xslf/usermodel/Placeholder.java [new file with mode: 0755]
src/ooxml/java/org/apache/poi/xslf/usermodel/TextAlign.java [new file with mode: 0755]
src/ooxml/java/org/apache/poi/xslf/usermodel/TextAutofit.java [new file with mode: 0644]
src/ooxml/java/org/apache/poi/xslf/usermodel/TextDirection.java [new file with mode: 0644]
src/ooxml/java/org/apache/poi/xslf/usermodel/VerticalAlignment.java [new file with mode: 0755]
src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java [new file with mode: 0755]
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFCommonSlideData.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java [new file with mode: 0755]
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFDrawing.java [new file with mode: 0755]
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFFactory.java [new file with mode: 0755]
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFFreeformShape.java [new file with mode: 0755]
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGraphicFrame.java [new file with mode: 0755]
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java [new file with mode: 0755]
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java [new file with mode: 0644]
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java [new file with mode: 0755]
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFRelation.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java [new file with mode: 0755]
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java [new file with mode: 0755]
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideLayout.java [new file with mode: 0755]
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideMaster.java [new file with mode: 0755]
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextBox.java [new file with mode: 0755]
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java [new file with mode: 0755]
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java [new file with mode: 0755]
src/ooxml/testcases/org/apache/poi/xslf/XSLFTestDataSamples.java
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java [new file with mode: 0755]
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFConnectorShape.java [new file with mode: 0644]
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFFreeformShape.java [new file with mode: 0755]
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFGroupShape.java [new file with mode: 0755]
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFPictureShape.java [new file with mode: 0644]
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFShape.java [new file with mode: 0755]
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSheet.java [new file with mode: 0644]
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java [new file with mode: 0644]
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java [new file with mode: 0755]
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlideShow.java [new file with mode: 0755]
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextBox.java [new file with mode: 0644]
src/resources/scratchpad/org/apache/poi/xslf/usermodel/empty.pptx [new file with mode: 0755]
test-data/slideshow/shapes.pptx [new file with mode: 0755]

index ac2112f65561028ab4f3c8ffcfa15e6c7ee57cd8..bea5040855532c99b5fa24b8f3716f15102fc477 100644 (file)
@@ -34,6 +34,7 @@
 
     <changes>
         <release version="3.8-beta4" date="2011-??-??">
+           <action dev="poi-developers" type="add">initial support for XSLF usermodel API</action>
            <action dev="poi-developers" type="fix">51187 - fixed OPCPackage to correctly handle self references</action>
            <action dev="poi-developers" type="fix">51635 - Improved performance of XSSFSheet#write</action>
            <action dev="poi-developers" type="fix">47731 - Word Extractor considers text copied from some website as an embedded object</action>
diff --git a/src/examples/src/org/apache/poi/xslf/usermodel/SlidesAndShapes.java b/src/examples/src/org/apache/poi/xslf/usermodel/SlidesAndShapes.java
new file mode 100644 (file)
index 0000000..cb700c6
--- /dev/null
@@ -0,0 +1,86 @@
+/* ====================================================================\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 java.awt.*;\r
+import java.awt.geom.Ellipse2D;\r
+import java.awt.geom.GeneralPath;\r
+import java.io.FileOutputStream;\r
+\r
+/**\r
+ * Simple demo that creates a pptx slide show using the XSLF API\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+public class SlidesAndShapes {\r
+\r
+    public static void main(String[] args) throws Exception {\r
+        XMLSlideShow ppt = new XMLSlideShow();\r
+        ppt.setPageSize(new Dimension(792, 612));\r
+\r
+        XSLFSlide slide1 = ppt.createSlide();\r
+        XSLFTextBox textBox = slide1.createTextBox();\r
+        XSLFTextRun r1 = textBox.addNewTextParagraph().addNewTextRun();\r
+        r1.setBold(true);\r
+        r1.setItalic(true);\r
+        r1.setFontColor(Color.yellow);\r
+        r1.setFontFamily("Arial");\r
+        r1.setFontSize(24);\r
+        r1.setText("Apache");\r
+        XSLFTextRun r2 = textBox.addNewTextParagraph().addNewTextRun();\r
+        r2.setStrikethrough(true);\r
+        r2.setUnderline(true);\r
+        r2.setText("POI\u2122");\r
+        XSLFTextRun r3 = textBox.addNewTextParagraph().addNewTextRun();\r
+        r3.setFontFamily("Wingdings");\r
+        r3.setText(" Version 3.8");\r
+\r
+        textBox.setAnchor(new Rectangle(50, 50, 200, 100));\r
+        textBox.setLineColor(Color.black);\r
+        textBox.setFillColor(Color.orange);\r
+\r
+        XSLFAutoShape shape2 = slide1.createAutoShape();\r
+\r
+        shape2.setAnchor(new Rectangle(100, 100, 200, 200));\r
+\r
+        XSLFFreeformShape shape3 = slide1.createFreeform();\r
+        Rectangle rect = new Rectangle(150, 150, 300, 300);\r
+        GeneralPath path = new GeneralPath(rect);\r
+        path.append(new Ellipse2D.Double(200, 200, 100, 50), false);\r
+        shape3.setPath(path);\r
+        shape3.setAnchor(path.getBounds2D());\r
+        shape3.setLineColor(Color.black);\r
+        shape3.setFillColor(Color.lightGray);\r
+\r
+        XSLFSlide slide2 = ppt.createSlide();\r
+        XSLFGroupShape group = slide2.createGroup();\r
+\r
+        group.setAnchor(new Rectangle(0, 0, 792, 612));\r
+        group.setInteriorAnchor(new Rectangle(-10, -10, 20, 20));\r
+\r
+        XSLFAutoShape shape4 = group.createAutoShape();\r
+        shape4.setAnchor(new Rectangle(0, 0, 5, 5));\r
+        shape4.setLineWidth(5);\r
+        shape4.setLineColor(Color.black);\r
+\r
+\r
+        FileOutputStream out = new FileOutputStream("xslf-demo.pptx");\r
+        ppt.write(out);\r
+        out.close();\r
+    }\r
+\r
+}\r
diff --git a/src/ooxml/java/org/apache/poi/util/Units.java b/src/ooxml/java/org/apache/poi/util/Units.java
new file mode 100755 (executable)
index 0000000..59ce34c
--- /dev/null
@@ -0,0 +1,17 @@
+package org.apache.poi.util;\r
+\r
+/**\r
+ * @author Yegor Kozlov\r
+ */\r
+public class Units {\r
+    public static final int EMU_PER_PIXEL = 9525;\r
+    public static final int EMU_PER_POINT = 12700;\r
+\r
+    public static int toEMU(double value){\r
+        return (int)Math.round(EMU_PER_POINT*value);\r
+    }\r
+\r
+    public static double toPoints(long emu){\r
+        return (double)emu/EMU_PER_POINT;\r
+    }\r
+}\r
index 05351c689c19420083d6029d6ffb300d51a9586f..d2986dc3fcde4f93ab00bf3442e61896d7e74799 100644 (file)
 ==================================================================== */
 package org.apache.poi.xslf;
 
-import java.io.IOException;
-import java.util.LinkedList;
-import java.util.List;
-
 import org.apache.poi.POIXMLDocument;
-import org.apache.poi.util.Internal;
-import org.apache.poi.xslf.usermodel.XMLSlideShow;
-import org.apache.poi.xslf.usermodel.XSLFRelation;
 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
 import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
 import org.apache.poi.openxml4j.opc.OPCPackage;
 import org.apache.poi.openxml4j.opc.PackagePart;
 import org.apache.poi.openxml4j.opc.PackageRelationship;
 import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
+import org.apache.poi.util.Internal;
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
+import org.apache.poi.xslf.usermodel.XSLFRelation;
 import org.apache.xmlbeans.XmlException;
 import org.openxmlformats.schemas.presentationml.x2006.main.CTCommentList;
 import org.openxmlformats.schemas.presentationml.x2006.main.CTNotesSlide;
@@ -46,6 +42,10 @@ import org.openxmlformats.schemas.presentationml.x2006.main.PresentationDocument
 import org.openxmlformats.schemas.presentationml.x2006.main.SldDocument;
 import org.openxmlformats.schemas.presentationml.x2006.main.SldMasterDocument;
 
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+
 /**
  * Experimental class to do low level processing of pptx files.
  * 
@@ -80,10 +80,10 @@ public class XSLFSlideShow extends POIXMLDocument {
       for (CTSlideIdListEntry ctSlide : getSlideReferences().getSldIdList()) {
                  PackagePart slidePart =
                        getTargetPart(getCorePart().getRelationship(ctSlide.getId2()));
-                 
+
                  for(PackageRelationship rel : slidePart.getRelationshipsByType(OLE_OBJECT_REL_TYPE))
                      embedds.add(getTargetPart(rel)); // TODO: Add this reference to each slide as well
-                 
+
                  for(PackageRelationship rel : slidePart.getRelationshipsByType(PACK_OBJECT_REL_TYPE))
                   embedds.add(getTargetPart(rel));
                }
index d20a3579640ba38c68dc79cdb8c7651db4a300e8..773e0f458b929b2f8e39b511cedcb5a5bf212ea0 100644 (file)
@@ -26,7 +26,10 @@ import org.apache.poi.xslf.usermodel.XSLFCommonSlideData;
 import org.apache.poi.xslf.usermodel.XSLFRelation;
 import org.apache.poi.xslf.usermodel.XSLFSlide;
 import org.apache.xmlbeans.XmlException;
-import org.openxmlformats.schemas.presentationml.x2006.main.*;
+import org.openxmlformats.schemas.presentationml.x2006.main.CTComment;
+import org.openxmlformats.schemas.presentationml.x2006.main.CTCommentList;
+import org.openxmlformats.schemas.presentationml.x2006.main.CTNotesSlide;
+import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideIdListEntry;
 
 import java.io.IOException;
 
@@ -42,11 +45,11 @@ public class XSLFPowerPointExtractor extends POIXMLTextExtractor {
        private boolean notesByDefault = false;
        
        public XSLFPowerPointExtractor(XMLSlideShow slideshow) {
-               super(slideshow._getXSLFSlideShow());
+               super(slideshow);
                this.slideshow = slideshow;
        }
        public XSLFPowerPointExtractor(XSLFSlideShow slideshow) throws XmlException, IOException {
-               this(new XMLSlideShow(slideshow));
+               this(new XMLSlideShow(slideshow.getPackage()));
        }
        public XSLFPowerPointExtractor(OPCPackage container) throws XmlException, OpenXML4JException, IOException {
                this(new XSLFSlideShow(container));
@@ -55,7 +58,7 @@ public class XSLFPowerPointExtractor extends POIXMLTextExtractor {
        public static void main(String[] args) throws Exception {
                if(args.length < 1) {
                        System.err.println("Use:");
-                       System.err.println("  HXFPowerPointExtractor <filename.pptx>");
+                       System.err.println("  XSLFPowerPointExtractor <filename.pptx>");
                        System.exit(1);
                }
                POIXMLTextExtractor extractor = 
@@ -95,41 +98,41 @@ public class XSLFPowerPointExtractor extends POIXMLTextExtractor {
                StringBuffer text = new StringBuffer();
 
                XSLFSlide[] slides = slideshow.getSlides();
-               for(int i = 0; i < slides.length; i++) {
-                       CTSlide rawSlide = slides[i]._getCTSlide();
-                       CTSlideIdListEntry slideId = slides[i]._getCTSlideId();
-                       
-                       try {
-                               // For now, still very low level
-                               CTNotesSlide notes = 
-                                       slideshow._getXSLFSlideShow().getNotes(slideId);
-                               CTCommentList comments =
-                                       slideshow._getXSLFSlideShow().getSlideComments(slideId);
-                               
-                               if(slideText) {
-                                       extractText(slides[i].getCommonSlideData(), text);
-                                       
-                                       // Comments too for the slide
-                                       if(comments != null) {
-                                               for(CTComment comment : comments.getCmList()) {
-                                                       // TODO - comment authors too
-                                                       // (They're in another stream)
-                                                       text.append(
-                                                                       comment.getText() + "\n"
-                                                       );
-                                               }
-                                       }
-                               }
+        try {
+            XSLFSlideShow xsl = new XSLFSlideShow(slideshow.getPackage());
+            for (int i = 0; i < slides.length; i++) {
+                CTSlideIdListEntry slideId = slideshow.getCTPresentation().getSldIdLst().getSldIdArray(i);
 
-                               if(notesText && notes != null) {
-                                       extractText(new XSLFCommonSlideData(notes.getCSld()), text);
-                               }
-                       } catch(Exception e) {
-                               throw new RuntimeException(e);
-                       }
-               }
-               
-               return text.toString();
+                // For now, still very low level
+                CTNotesSlide notes =
+                        xsl.getNotes(slideId);
+                CTCommentList comments =
+                        xsl.getSlideComments(slideId);
+
+                if (slideText) {
+                    extractText(new XSLFCommonSlideData(slides[i].getXmlObject().getCSld()), text);
+
+                    // Comments too for the slide
+                    if (comments != null) {
+                        for (CTComment comment : comments.getCmList()) {
+                            // TODO - comment authors too
+                            // (They're in another stream)
+                            text.append(
+                                    comment.getText() + "\n"
+                            );
+                        }
+                    }
+                }
+
+                if (notesText && notes != null) {
+                    extractText(new XSLFCommonSlideData(notes.getCSld()), text);
+                }
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+
+        return text.toString();
        }
        
        private void extractText(XSLFCommonSlideData data, StringBuffer text) {
index f1e84ce6c1ae444cf0fb40b5ed5763ccc9fb8c4f..2e755583bb9dd329dd550c0144b60e17e0b0fd1b 100644 (file)
 
 package org.apache.poi.xslf.usermodel;
 
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextLineBreak;
 import org.apache.xmlbeans.XmlCursor;
 import org.apache.xmlbeans.XmlObject;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextLineBreak;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
 
 public class DrawingParagraph {
     private final CTTextParagraph p;
index e221cfa7cced1fd17cc3a7f9c6d8567a1e3d1fb6..c6d7da9f2b20e086d674172f73f1c166c0aa8ef4 100644 (file)
 
 package org.apache.poi.xslf.usermodel;
 
-import java.util.List;
-
 import org.openxmlformats.schemas.drawingml.x2006.main.CTTable;
 import org.openxmlformats.schemas.drawingml.x2006.main.CTTableRow;
 
+import java.util.List;
+
 public class DrawingTable {
     private final CTTable table;
 
index 213dd638d6dd7b008c175d5ecdea93f74a8b2ea1..27b79ea33e1db67bb4aeacf03cb45dcef2aa0d76 100644 (file)
 
 package org.apache.poi.xslf.usermodel;
 
-import java.util.List;
-
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTableRow;
 import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCell;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTableRow;
+
+import java.util.List;
 
 public class DrawingTableRow {
     private final CTTableRow row;
index 68a12a4d1cb1e5e7b48614701a4a3badbad104d6..1f40841d35c9c8b144d6ff6103ada9301ec61397 100644 (file)
 
 package org.apache.poi.xslf.usermodel;
 
-import java.util.List;
-
 import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;
 import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
 
+import java.util.List;
+
 public class DrawingTextBody {
     private final CTTextBody textBody;
 
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/LineCap.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/LineCap.java
new file mode 100755 (executable)
index 0000000..140f48b
--- /dev/null
@@ -0,0 +1,19 @@
+package org.apache.poi.xslf.usermodel;\r
+\r
+/**\r
+ */\r
+public enum LineCap {\r
+    /**\r
+     *  Rounded ends - the default\r
+     */\r
+    ROUND,\r
+    /**\r
+     * Square protrudes by half line width\r
+     */\r
+    SQUARE,\r
+\r
+    /**\r
+     *  Line ends at end point\r
+     */\r
+    FLAT;\r
+}
\ No newline at end of file
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/LineDash.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/LineDash.java
new file mode 100755 (executable)
index 0000000..83b29be
--- /dev/null
@@ -0,0 +1,17 @@
+package org.apache.poi.xslf.usermodel;\r
+\r
+/**\r
+ */\r
+public enum LineDash {\r
+    SOLID,\r
+    DOT,\r
+    DASH,\r
+    LG_DASH,\r
+    DASH_DOT,\r
+    LG_DASH_DOT,\r
+    LG_DASH_DOT_DOT,\r
+    SYS_DASH,\r
+    SYS_DOT,\r
+    SYS_DASH_DOT,\r
+    SYS_DASH_DOT_DOT;\r
+}\r
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/LineDecoration.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/LineDecoration.java
new file mode 100644 (file)
index 0000000..72b28c0
--- /dev/null
@@ -0,0 +1,29 @@
+/* ====================================================================\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
+/**\r
+ *  Represents the shape decoration that appears at the ends of lines.\r
+ */\r
+public enum LineDecoration {\r
+    NONE,\r
+    TRIANGLE,\r
+    STEALTH,\r
+    DIAMOND,\r
+    OVAL,\r
+    ARROW\r
+}\r
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/LineEndLength.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/LineEndLength.java
new file mode 100644 (file)
index 0000000..a66623b
--- /dev/null
@@ -0,0 +1,14 @@
+package org.apache.poi.xslf.usermodel;\r
+\r
+/**\r
+ * Created by IntelliJ IDEA.\r
+ * User: yegor\r
+ * Date: Aug 9, 2011\r
+ * Time: 9:39:26 PM\r
+ * To change this template use File | Settings | File Templates.\r
+ */\r
+public enum LineEndLength {\r
+    SMALL,\r
+    MEDIUM,\r
+    LARGE\r
+}\r
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/LineEndWidth.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/LineEndWidth.java
new file mode 100644 (file)
index 0000000..5d2d3b8
--- /dev/null
@@ -0,0 +1,14 @@
+package org.apache.poi.xslf.usermodel;\r
+\r
+/**\r
+ * Created by IntelliJ IDEA.\r
+ * User: yegor\r
+ * Date: Aug 9, 2011\r
+ * Time: 9:39:26 PM\r
+ * To change this template use File | Settings | File Templates.\r
+ */\r
+public enum LineEndWidth {\r
+    SMALL,\r
+    MEDIUM,\r
+    LARGE\r
+}
\ No newline at end of file
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/Placeholder.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/Placeholder.java
new file mode 100755 (executable)
index 0000000..0e95801
--- /dev/null
@@ -0,0 +1,36 @@
+/*\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
+package org.apache.poi.xslf.usermodel;\r
+\r
+/**\r
+ * @author Yegor Kozlov\r
+ */\r
+public enum Placeholder {\r
+    TITLE,\r
+    BODY,\r
+    CENTERED_TITLE,\r
+    SUBTITLE,\r
+    DATETIME,\r
+    SLIDE_NUMBER,\r
+    FOOTER,\r
+    HEADER,\r
+    OBJECT,\r
+    CHART,\r
+    TABLE\r
+}\r
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/TextAlign.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/TextAlign.java
new file mode 100755 (executable)
index 0000000..c712dba
--- /dev/null
@@ -0,0 +1,47 @@
+/*\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
+package org.apache.poi.xslf.usermodel;\r
+\r
+/**\r
+ * Specified a list of text alignment types\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+public enum TextAlign {\r
+    /**\r
+     * Align text to the left margin.\r
+     */\r
+    LEFT,\r
+    /**\r
+     * Align text in the center.\r
+     */\r
+    CENTER,\r
+\r
+    /**\r
+     * Align text to the right margin.\r
+     */\r
+    RIGHT,\r
+\r
+    /**\r
+     * Align text so that it is justified across the whole line. It\r
+     * is smart in the sense that it will not justify sentences\r
+     * which are short\r
+     */\r
+    JUSTIFY\r
+}\r
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/TextAutofit.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/TextAutofit.java
new file mode 100644 (file)
index 0000000..94d6b24
--- /dev/null
@@ -0,0 +1,59 @@
+/*\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
+package org.apache.poi.xslf.usermodel;\r
+\r
+/**\r
+ * Specifies alist of auto-fit types.\r
+ * <p>\r
+ * Autofit specofies 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
+ * </p>\r
+ * \r
+ * @author Yegor Kozlov\r
+ */\r
+public enum TextAutofit {\r
+    /**\r
+     * Specifies that text within the text body should not be auto-fit to the bounding box.\r
+     * Auto-fitting is when text within a text box is scaled in order to remain inside\r
+     * the text box.\r
+     */\r
+    NONE,\r
+    /**\r
+     * Specifies that text within the text body should be normally auto-fit to the bounding box.\r
+     * Autofitting is when text within a text box is scaled in order to remain inside the text box.\r
+     *\r
+     * <p>\r
+     * <em>Example:</em> Consider the situation where a user is building a diagram and needs\r
+     * to have the text for each shape that they are using stay within the bounds of the shape.\r
+     * An easy way this might be done is by using NORMAL autofit\r
+     * </p>\r
+     */\r
+    NORMAL,\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
+     * <p>\r
+     * <em>Example:</em> Consider the situation where a user is building a diagram and needs to have\r
+     * the text for each shape that they are using stay within the bounds of the shape.\r
+     * An easy way this might be done is by using SHAPE autofit\r
+     * </p>\r
+     */\r
+    SHAPE\r
+}\r
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/TextDirection.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/TextDirection.java
new file mode 100644 (file)
index 0000000..3f35ec2
--- /dev/null
@@ -0,0 +1,48 @@
+/*\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
+package org.apache.poi.xslf.usermodel;\r
+\r
+/**\r
+ * Vertical Text Types\r
+ */\r
+public enum TextDirection {\r
+    /**\r
+     * Horizontal text. This should be default.\r
+     */\r
+    HORIZONTAL,\r
+    /**\r
+     * Vertical orientation.\r
+     * (each line is 90 degrees rotated clockwise, so it goes\r
+     * from top to bottom; each next line is to the left from\r
+     * the previous one).\r
+     */\r
+    VERTICAL,\r
+    /**\r
+     * Vertical orientation.\r
+     * (each line is 270 degrees rotated clockwise, so it goes\r
+     * from bottom to top; each next line is to the right from\r
+     * the previous one).\r
+     */\r
+    VERTICAL_270,\r
+    /**\r
+     * Determines if all of the text is vertical\r
+     * ("one letter on top of another").\r
+     */\r
+    STACKED;\r
+}\r
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/VerticalAlignment.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/VerticalAlignment.java
new file mode 100755 (executable)
index 0000000..fd00a64
--- /dev/null
@@ -0,0 +1,71 @@
+/*\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
+package org.apache.poi.xslf.usermodel;\r
+\r
+/**\r
+ * Specifies a list of available anchoring types for text\r
+ * \r
+ * @author Yegor Kozlov\r
+ */\r
+public enum VerticalAlignment {\r
+    /**\r
+     * Anchor the text at the top of the bounding rectangle\r
+     */\r
+    TOP,\r
+\r
+    /**\r
+     * Anchor the text at the middle of the bounding rectangle\r
+     */\r
+    MIDDLE,\r
+\r
+    /**\r
+     * Anchor the text at the bottom of the bounding rectangle.\r
+     */\r
+    BOTTOM,\r
+\r
+    /**\r
+     * Anchor the text so that it is justified vertically.\r
+     * <p>\r
+     * When text is horizontal, this spaces out the actual lines of\r
+     * text and is almost always identical in behavior to\r
+     * {@link #DISTRIBUTED} (special case: if only 1 line, then anchored at top).\r
+     * </p>\r
+     * <p>\r
+     * When text is vertical, then it justifies the letters\r
+     * vertically. This is different than {@link #DISTRIBUTED},\r
+     * because in some cases such as very little text in a line,\r
+     * it will not justify.\r
+     * </p>\r
+     */\r
+    JUSTIFIED,\r
+\r
+    /**\r
+     * Anchor the text so that it is distributed vertically.\r
+     * <p>\r
+     * When text is horizontal, this spaces out the actual lines\r
+     * of text and is almost always identical in behavior to\r
+     * {@link #JUSTIFIED} (special case: if only 1 line, then anchored in middle).\r
+     * </p>\r
+     * <p>\r
+     * When text is vertical, then it distributes the letters vertically.\r
+     * This is different than {@link #JUSTIFIED}, because it always forces distribution\r
+     * of the words, even if there are only one or two words in a line.\r
+     */\r
+    DISTRIBUTED\r
+}\r
index ab5c670b9f33ddb8436bd7707f2e28d76884bad6..7c2db9bb45c1ae4ebffccc523eb580e30eb0138d 100644 (file)
 ==================================================================== */
 package org.apache.poi.xslf.usermodel;
 
-import java.io.IOException;
-
+import org.apache.poi.POIXMLDocument;
+import org.apache.poi.POIXMLDocumentPart;
+import org.apache.poi.POIXMLException;
+import org.apache.poi.xslf.XSLFSlideShow;
 import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
 import org.apache.poi.openxml4j.opc.OPCPackage;
-import org.apache.poi.sl.usermodel.MasterSheet;
-import org.apache.poi.sl.usermodel.Resources;
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.apache.poi.openxml4j.opc.PackagePartName;
+import org.apache.poi.openxml4j.opc.TargetMode;
 import org.apache.poi.sl.usermodel.Slide;
 import org.apache.poi.sl.usermodel.SlideShow;
-import org.apache.poi.xslf.XSLFSlideShow;
+import org.apache.poi.util.Beta;
+import org.apache.poi.util.Internal;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+import org.apache.poi.util.PackageHelper;
+import org.apache.poi.util.Units;
 import org.apache.xmlbeans.XmlException;
-import org.openxmlformats.schemas.presentationml.x2006.main.CTSlide;
+import org.apache.xmlbeans.XmlOptions;
+import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId;
+import org.openxmlformats.schemas.presentationml.x2006.main.CTPresentation;
 import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideIdList;
 import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideIdListEntry;
-import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideMasterIdList;
+import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideSize;
+import org.openxmlformats.schemas.presentationml.x2006.main.PresentationDocument;
+
+import java.awt.*;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
 
 /**
  * High level representation of a ooxml slideshow.
@@ -37,57 +59,261 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideMasterIdList;
  *  they are reading or writing a slideshow. It is also the
  *  top level object for creating new slides/etc.
  */
-public class XMLSlideShow implements SlideShow {
-       private XSLFSlideShow slideShow;
-       private XSLFSlide[] slides;
-       
-       public XMLSlideShow(XSLFSlideShow xml) throws XmlException, IOException {
-               this.slideShow = xml;
-               
-               // Build the main masters list - TODO
-               CTSlideMasterIdList masterIds = slideShow.getSlideMasterReferences();
-               
-               // Build the slides list
-               CTSlideIdList slideIds = slideShow.getSlideReferences();
-               slides = new XSLFSlide[slideIds.getSldIdList().size()];
-               for(int i=0; i<slides.length; i++) {
-                       CTSlideIdListEntry slideId = slideIds.getSldIdArray(i);
-                       CTSlide slide = slideShow.getSlide(slideId);
-                       slides[i] = new XSLFSlide(slide, slideId, this);
-               }
-               
-               // Build the notes list - TODO
-       }
-       
-       public XMLSlideShow(OPCPackage pkg) throws XmlException, IOException, OpenXML4JException {
-          this(new XSLFSlideShow(pkg));
-       }
-       
-       public XSLFSlideShow _getXSLFSlideShow() {
-               return slideShow;
-       }
-
-       public MasterSheet createMasterSheet() throws IOException {
-               throw new IllegalStateException("Not implemented yet!");
-       }
-       public Slide createSlide() throws IOException {
-               throw new IllegalStateException("Not implemented yet!");
-       }
-
-       public MasterSheet[] getMasterSheet() {
-               // TODO Auto-generated method stub
-               return null;
-       }
-
-       /**
-        * Return all the slides in the slideshow
-        */
-       public XSLFSlide[] getSlides() {
-               return slides;
-       }
-       
-       public Resources getResources() {
-               // TODO Auto-generated method stub
-               return null;
-       }
+@Beta
+public class XMLSlideShow  extends POIXMLDocument {
+
+    private static POILogger _logger = POILogFactory.getLogger(XMLSlideShow.class);
+
+    private CTPresentation _presentation;
+    private List<XSLFSlide> _slides;
+    private Map<String, XSLFSlideMaster> _masters;
+    protected List<XSLFPictureData> _pictures;
+
+    public XMLSlideShow() {
+        this(empty());
+    }
+
+    public XMLSlideShow(OPCPackage pkg) {
+        super(pkg);
+
+        try {
+            if(getCorePart().getContentType().equals(XSLFRelation.THEME_MANAGER.getContentType())) {
+               rebase(getPackage());
+            }
+
+            //build a tree of POIXMLDocumentParts, this presentation being the root
+            load(XSLFFactory.getInstance());
+        } catch (Exception e){
+            throw new POIXMLException(e);
+        }
+    }
+
+    public XMLSlideShow(InputStream is) throws IOException {
+        this(PackageHelper.open(is));
+    }
+
+    static final OPCPackage empty() {
+        InputStream is = XMLSlideShow.class.getResourceAsStream("empty.pptx");
+        if (is == null) {
+            throw new RuntimeException("Missing resource 'empty.pptx'");
+        }
+        try {
+            return OPCPackage.open(is);
+        } catch (Exception e){
+            throw new POIXMLException(e);
+        }
+    }
+
+    // TODO get rid of this method
+    @Deprecated
+    public XSLFSlideShow _getXSLFSlideShow() throws OpenXML4JException, IOException, XmlException{
+        return new XSLFSlideShow(getPackage());
+    }
+
+    @Override
+    protected void onDocumentRead() throws IOException {
+        try {
+            PresentationDocument doc =
+                    PresentationDocument.Factory.parse(getCorePart().getInputStream());
+            _presentation = doc.getPresentation();
+            Map<String, XSLFSlide> shIdMap = new HashMap<String, XSLFSlide>();
+
+            _masters = new HashMap<String, XSLFSlideMaster>();
+            for (POIXMLDocumentPart p : getRelations()) {
+                if (p instanceof XSLFSlide) {
+                    shIdMap.put(p.getPackageRelationship().getId(), (XSLFSlide) p);
+                } else if (p instanceof XSLFSlideMaster){
+                    XSLFSlideMaster master = (XSLFSlideMaster)p;
+                    _masters.put(p.getPackageRelationship().getId(), master);
+                }
+            }
+
+            _slides = new ArrayList<XSLFSlide>();
+            if (_presentation.isSetSldIdLst()) {
+                List<CTSlideIdListEntry> slideIds = _presentation.getSldIdLst().getSldIdList();
+                for (CTSlideIdListEntry slId : slideIds) {
+                    XSLFSlide sh = shIdMap.get(slId.getId2());
+                    if (sh == null) {
+                        _logger.log(POILogger.WARN, "Slide with r:id " + slId.getId() + " was defined, but didn't exist in package, skipping");
+                        continue;
+                    }
+                    _slides.add(sh);
+                }
+            }
+        } catch (XmlException e) {
+            throw new POIXMLException(e);
+        }
+    }
+
+
+    @Override
+    protected void commit() throws IOException {
+        XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
+        Map<String, String> map = new HashMap<String, String>();
+        map.put(STRelationshipId.type.getName().getNamespaceURI(), "r");
+        xmlOptions.setSaveSuggestedPrefixes(map);
+
+        PackagePart part = getPackagePart();
+        OutputStream out = part.getOutputStream();
+        _presentation.save(out, xmlOptions);
+        out.close();
+    }
+
+    /**
+     * Get the document's embedded files.
+     */
+    public List<PackagePart> getAllEmbedds() throws OpenXML4JException {
+        return Collections.unmodifiableList(
+                getPackage().getPartsByName(Pattern.compile("/ppt/embeddings/.*?"))
+        );
+    }
+
+    /**
+     * Returns all Pictures, which are referenced from the document itself.
+     * @return a {@link List} of {@link PackagePart}.
+     * The returned {@link List} is unmodifiable. 
+     */
+    public List<XSLFPictureData> getAllPictures() {
+        if(_pictures == null){
+            List<PackagePart> mediaParts = getPackage().getPartsByName(Pattern.compile("/ppt/media/.*?"));
+            _pictures = new ArrayList<XSLFPictureData>(mediaParts.size());
+            for(PackagePart part : mediaParts){
+                _pictures.add(new XSLFPictureData(part, null));    
+            }
+        }
+        return Collections.unmodifiableList(_pictures);
+    }
+
+    public XSLFSlide createSlide() {
+        int slideNumber = 256, cnt = 1;
+        CTSlideIdList slideList;
+        if (!_presentation.isSetSldIdLst()) slideList = _presentation.addNewSldIdLst();
+        else {
+            slideList = _presentation.getSldIdLst();
+            for(CTSlideIdListEntry slideId : slideList.getSldIdList()){
+                slideNumber = (int)Math.max(slideId.getId() + 1, slideNumber);
+                cnt++;
+            }
+        }
+
+        XSLFSlide slide = (XSLFSlide)createRelationship(
+                XSLFRelation.SLIDE, XSLFFactory.getInstance(), cnt);
+
+        CTSlideIdListEntry slideId = slideList.addNewSldId();
+        slideId.setId(slideNumber);
+        slideId.setId2(slide.getPackageRelationship().getId());
+
+        String masterId = _presentation.getSldMasterIdLst().getSldMasterIdArray(0).getId2();
+        XSLFSlideMaster master = _masters.get(masterId);
+
+        XSLFSlideLayout layout = master.getLayout("blank");
+        if(layout == null) throw new IllegalArgumentException("Blank layout was not found");
+
+        slide.addRelation(layout.getPackageRelationship().getId(), layout);
+
+        PackagePartName ppName = layout.getPackagePart().getPartName();
+        slide.getPackagePart().addRelationship(ppName, TargetMode.INTERNAL,
+                layout.getPackageRelationship().getRelationshipType());
+
+        _slides.add(slide);
+        return slide;
+    }
+
+    public XSLFSlideMaster[] getSlideMasters() {
+        return _masters.values().toArray(new XSLFSlideMaster[_masters.size()]);
+    }
+
+    /**
+     * Return all the slides in the slideshow
+     */
+    public XSLFSlide[] getSlides() {
+        return _slides.toArray(new XSLFSlide[_slides.size()]);
+    }
+
+    /**
+     *
+     * @param newIndex 0-based index of the slide
+     */
+    public void setSlideOrder(XSLFSlide slide, int newIndex){
+        int oldIndex = _slides.indexOf(slide);
+        if(oldIndex == -1) throw new IllegalArgumentException("Slide not found");
+
+        // fix the usermodel container
+        _slides.add(newIndex, _slides.remove(oldIndex));
+
+        // fix ordering in the low-level xml
+        List<CTSlideIdListEntry> slideIds = _presentation.getSldIdLst().getSldIdList();
+        CTSlideIdListEntry oldEntry = slideIds.get(oldIndex);
+        slideIds.add(newIndex, oldEntry);
+        slideIds.remove(oldEntry);
+    }
+
+    public XSLFSlide removeSlide(int index){
+        XSLFSlide slide = _slides.remove(index);
+        removeRelation(slide);
+         _presentation.getSldIdLst().getSldIdList().remove(index);
+        return slide;
+    }
+    
+    /**
+     * Returns the current page size
+     *
+     * @return the page size
+     */
+    public Dimension getPageSize(){
+        CTSlideSize sz = _presentation.getSldSz();
+        int cx = sz.getCx();
+        int cy = sz.getCy();
+        return new Dimension((int)Units.toPoints(cx), (int)Units.toPoints(cy));
+    }
+
+    /**
+     * Sets the page size to the given <code>Dimension</code> object.
+     *
+     * @param pgSize page size
+     */
+    public void setPageSize(Dimension pgSize){
+        CTSlideSize sz = CTSlideSize.Factory.newInstance();
+        sz.setCx(Units.toEMU(pgSize.getWidth()));
+        sz.setCy(Units.toEMU(pgSize.getHeight()));
+        _presentation.setSldSz(sz);
+    }
+
+
+    @Internal
+    public CTPresentation getCTPresentation(){
+        return _presentation;        
+    }
+
+    /**
+     * Adds a picture to the workbook.
+     *
+     * @param pictureData       The bytes of the picture
+     * @param format            The format of the picture.
+     *
+     * @return the index to this picture (1 based).
+     * @see XSLFPictureData#PICTURE_TYPE_EMF
+     * @see XSLFPictureData#PICTURE_TYPE_WMF
+     * @see XSLFPictureData#PICTURE_TYPE_PICT
+     * @see XSLFPictureData#PICTURE_TYPE_JPEG
+     * @see XSLFPictureData#PICTURE_TYPE_PNG
+     * @see XSLFPictureData#PICTURE_TYPE_DIB
+     */
+    public int addPicture(byte[] pictureData, int format) {
+        getAllPictures();
+        
+        int imageNumber = getPackage().getPartsByName(Pattern.compile("/ppt/media/.*?")).size() + 1;
+        XSLFPictureData img = (XSLFPictureData) createRelationship(
+                XSLFPictureData.RELATIONS[format], XSLFFactory.getInstance(), imageNumber, true);
+        _pictures.add(img);
+        try {
+            OutputStream out = img.getPackagePart().getOutputStream();
+            out.write(pictureData);
+            out.close();
+        } catch (IOException e) {
+            throw new POIXMLException(e);
+        }
+        return imageNumber - 1;
+    }
+
 }
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java
new file mode 100755 (executable)
index 0000000..1869749
--- /dev/null
@@ -0,0 +1,427 @@
+/*\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.Beta;\r
+import org.apache.poi.util.Units;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;\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.CTTextBody;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextWrappingType;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextVerticalType;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTShapeNonVisual;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;\r
+\r
+import java.awt.*;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+/**\r
+ * Represents a preset geometric shape. \r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+@Beta\r
+public class XSLFAutoShape extends XSLFSimpleShape {\r
+    private final List<XSLFTextParagraph> _paragraphs;\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
+    static XSLFAutoShape create(CTShape shape, XSLFSheet sheet) {\r
+        if (shape.getSpPr().isSetCustGeom()) {\r
+            return new XSLFFreeformShape(shape, sheet);\r
+        } else if (shape.getNvSpPr().getCNvSpPr().isSetTxBox()) {\r
+            return new XSLFTextBox(shape, sheet);\r
+        } else {\r
+            return new XSLFAutoShape(shape, sheet);\r
+        }\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
+    static CTShape prototype(int shapeId) {\r
+        CTShape ct = CTShape.Factory.newInstance();\r
+        CTShapeNonVisual nvSpPr = ct.addNewNvSpPr();\r
+        CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr();\r
+        cnv.setName("AutoShape " + shapeId);\r
+        cnv.setId(shapeId + 1);\r
+        nvSpPr.addNewCNvSpPr();\r
+        nvSpPr.addNewNvPr();\r
+        CTShapeProperties spPr = ct.addNewSpPr();\r
+        CTPresetGeometry2D prst = spPr.addNewPrstGeom();\r
+        prst.setPrst(STShapeType.RECT);\r
+        prst.addNewAvLst();\r
+        return ct;\r
+    }\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
+    public void setFillColor(Color color) {\r
+        CTShapeProperties spPr = getSpPr();\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
+    public Color getFillColor(){\r
+        CTShapeProperties spPr = getSpPr();\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
+     * 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
+        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
+        }\r
+    }\r
+\r
+}
\ No newline at end of file
index 22cde4f9b06fdec7e582dcdc0b2666ad8ac98962..a5612815521f684a26465c39d9256ea903149ab1 100644 (file)
@@ -18,6 +18,7 @@
 package org.apache.poi.xslf.usermodel;
 
 import org.apache.poi.POIXMLException;
+import org.apache.poi.util.Beta;
 import org.apache.xmlbeans.XmlCursor;
 import org.apache.xmlbeans.XmlException;
 import org.apache.xmlbeans.XmlObject;
@@ -34,6 +35,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
+@Beta
 public class XSLFCommonSlideData {
     private final CTCommonSlideData data;
 
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java
new file mode 100755 (executable)
index 0000000..d93c135
--- /dev/null
@@ -0,0 +1,195 @@
+/*\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.Beta;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTLineEndProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndType;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndWidth;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndLength;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTConnectorNonVisual;\r
+\r
+/**\r
+ *\r
+ * Specifies a connection shape. \r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+@Beta\r
+public class XSLFConnectorShape extends XSLFSimpleShape {\r
+\r
+    /*package*/ XSLFConnectorShape(CTConnector shape, XSLFSheet sheet){\r
+        super(shape, sheet);\r
+    }\r
+\r
+    /**\r
+     * @param shapeId 1-based shapeId\r
+     */\r
+    static CTConnector prototype(int shapeId) {\r
+        CTConnector ct = CTConnector.Factory.newInstance();\r
+        CTConnectorNonVisual nvSpPr = ct.addNewNvCxnSpPr();\r
+        CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr();\r
+        cnv.setName("Connector " + shapeId);\r
+        cnv.setId(shapeId + 1);\r
+        nvSpPr.addNewCNvCxnSpPr();\r
+        nvSpPr.addNewNvPr();\r
+        CTShapeProperties spPr = ct.addNewSpPr();\r
+        CTPresetGeometry2D prst = spPr.addNewPrstGeom();\r
+        prst.setPrst(STShapeType.LINE);\r
+        prst.addNewAvLst();\r
+        CTLineProperties ln = spPr.addNewLn();\r
+        return ct;\r
+    }\r
+\r
+    /**\r
+     * Specifies the line end decoration, such as a triangle or arrowhead.\r
+     */\r
+    public void setLineHeadDecoration(LineDecoration style){\r
+        CTLineProperties ln = getSpPr().getLn();\r
+        CTLineEndProperties lnEnd = ln.isSetHeadEnd() ? ln.getHeadEnd() : ln.addNewHeadEnd();\r
+        if(style == null){\r
+            if(lnEnd.isSetType()) lnEnd.unsetType();\r
+        } else {\r
+            lnEnd.setType(STLineEndType.Enum.forInt(style.ordinal() + 1));\r
+        }\r
+    }\r
+\r
+    public LineDecoration getLineHeadDecoration(){\r
+        CTLineProperties ln = getSpPr().getLn();\r
+        if(!ln.isSetHeadEnd()) return LineDecoration.NONE;\r
+\r
+        STLineEndType.Enum end = ln.getHeadEnd().getType();\r
+        return end == null ? LineDecoration.NONE : LineDecoration.values()[end.intValue() - 1];\r
+    }\r
+\r
+    /**\r
+     * specifies decorations which can be added to the head of a line.\r
+     */\r
+    public void setLineHeadWidth(LineEndWidth style){\r
+        CTLineProperties ln = getSpPr().getLn();\r
+        CTLineEndProperties lnEnd = ln.isSetHeadEnd() ? ln.getHeadEnd() : ln.addNewHeadEnd();\r
+        if(style == null){\r
+            if(lnEnd.isSetW()) lnEnd.unsetW();\r
+        } else {\r
+            lnEnd.setW(STLineEndWidth.Enum.forInt(style.ordinal() + 1));\r
+        }\r
+    }\r
+\r
+    public LineEndWidth getLineHeadWidth(){\r
+        CTLineProperties ln = getSpPr().getLn();\r
+        if(!ln.isSetHeadEnd()) return null;\r
+\r
+        STLineEndWidth.Enum w = ln.getHeadEnd().getW();\r
+        return w == null ? null : LineEndWidth.values()[w.intValue() - 1];\r
+    }\r
+\r
+    /**\r
+     * Specifies the line end width in relation to the line width.\r
+     */\r
+    public void setLineHeadLength(LineEndLength style){\r
+        CTLineProperties ln = getSpPr().getLn();\r
+        CTLineEndProperties lnEnd = ln.isSetHeadEnd() ? ln.getHeadEnd() : ln.addNewHeadEnd();\r
+\r
+        if(style == null){\r
+            if(lnEnd.isSetLen()) lnEnd.unsetLen();\r
+        } else {\r
+            lnEnd.setLen(STLineEndLength.Enum.forInt(style.ordinal() + 1));\r
+        }\r
+    }\r
+\r
+    public LineEndLength getLineHeadLength(){\r
+        CTLineProperties ln = getSpPr().getLn();\r
+        if(!ln.isSetHeadEnd()) return null;\r
+\r
+        STLineEndLength.Enum len = ln.getHeadEnd().getLen();\r
+        return len == null ? null : LineEndLength.values()[len.intValue() - 1];\r
+    }\r
+\r
+    /**\r
+     * Specifies the line end decoration, such as a triangle or arrowhead.\r
+     */\r
+    public void setLineTailDecoration(LineDecoration style){\r
+        CTLineProperties ln = getSpPr().getLn();\r
+        CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd();\r
+        if(style == null){\r
+            if(lnEnd.isSetType()) lnEnd.unsetType();\r
+        } else {\r
+            lnEnd.setType(STLineEndType.Enum.forInt(style.ordinal() + 1));\r
+        }\r
+    }\r
+\r
+    public LineDecoration getLineTailDecoration(){\r
+        CTLineProperties ln = getSpPr().getLn();\r
+        if(!ln.isSetTailEnd()) return LineDecoration.NONE;\r
+\r
+        STLineEndType.Enum end = ln.getTailEnd().getType();\r
+        return end == null ? LineDecoration.NONE : LineDecoration.values()[end.intValue() - 1];\r
+    }\r
+\r
+    /**\r
+     * specifies decorations which can be added to the tail of a line.\r
+     */\r
+    public void setLineTailWidth(LineEndWidth style){\r
+        CTLineProperties ln = getSpPr().getLn();\r
+        CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd();\r
+        if(style == null){\r
+            if(lnEnd.isSetW()) lnEnd.unsetW();\r
+        } else {\r
+            lnEnd.setW(STLineEndWidth.Enum.forInt(style.ordinal() + 1));\r
+        }\r
+    }\r
+\r
+    public LineEndWidth getLineTailWidth(){\r
+        CTLineProperties ln = getSpPr().getLn();\r
+        if(!ln.isSetTailEnd()) return null;\r
+\r
+        STLineEndWidth.Enum w = ln.getTailEnd().getW();\r
+        return w == null ? null : LineEndWidth.values()[w.intValue() - 1];\r
+    }\r
+\r
+    /**\r
+     * Specifies the line end width in relation to the line width.\r
+     */\r
+    public void setLineTailLength(LineEndLength style){\r
+        CTLineProperties ln = getSpPr().getLn();\r
+        CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd();\r
+\r
+        if(style == null){\r
+            if(lnEnd.isSetLen()) lnEnd.unsetLen();\r
+        } else {\r
+            lnEnd.setLen(STLineEndLength.Enum.forInt(style.ordinal() + 1));\r
+        }\r
+    }\r
+\r
+    public LineEndLength getLineTailLength(){\r
+        CTLineProperties ln = getSpPr().getLn();\r
+        if(!ln.isSetTailEnd()) return null;\r
+\r
+        STLineEndLength.Enum len = ln.getTailEnd().getLen();\r
+        return len == null ? null : LineEndLength.values()[len.intValue() - 1];\r
+    }\r
+\r
+}
\ 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
new file mode 100755 (executable)
index 0000000..2f72bfc
--- /dev/null
@@ -0,0 +1,84 @@
+package org.apache.poi.xslf.usermodel;\r
+\r
+import org.apache.poi.sl.usermodel.ShapeContainer;\r
+import org.apache.poi.util.Beta;\r
+import org.apache.xmlbeans.XmlObject;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector;\r
+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
+\r
+import java.awt.*;\r
+\r
+\r
+/**\r
+ * @author Yegor Kozlov\r
+ */\r
+@Beta\r
+public class XSLFDrawing {\r
+    private XSLFSheet _sheet;\r
+    private int _shapeId = 1;\r
+    private CTGroupShape _spTree;\r
+\r
+    /*package*/ XSLFDrawing(XSLFSheet sheet, CTGroupShape spTree){\r
+        _sheet = sheet;\r
+        _spTree = spTree;\r
+        XmlObject[] cNvPr = sheet.getSpTree().selectPath(\r
+                "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:cNvPr");\r
+        for(XmlObject o : cNvPr) {\r
+            CTNonVisualDrawingProps p = (CTNonVisualDrawingProps)o;\r
+            _shapeId = (int)Math.max(_shapeId, p.getId());\r
+        }\r
+    }\r
+\r
+    public XSLFAutoShape createAutoShape(){\r
+        CTShape sp = _spTree.addNewSp();\r
+        sp.set(XSLFAutoShape.prototype(_shapeId++));\r
+        XSLFAutoShape shape = new XSLFAutoShape(sp, _sheet);\r
+        shape.setAnchor(new Rectangle());\r
+        return shape;\r
+    }\r
+\r
+    public XSLFFreeformShape createFreeform(){\r
+        CTShape sp = _spTree.addNewSp();\r
+        sp.set(XSLFFreeformShape.prototype(_shapeId++));\r
+        XSLFFreeformShape shape = new XSLFFreeformShape(sp, _sheet);\r
+        shape.setAnchor(new Rectangle());\r
+        return shape;\r
+    }\r
+\r
+    public XSLFTextBox createTextBox(){\r
+        CTShape sp = _spTree.addNewSp();\r
+        sp.set(XSLFTextBox.prototype(_shapeId++));\r
+        XSLFTextBox shape = new XSLFTextBox(sp, _sheet);\r
+        shape.setAnchor(new Rectangle());\r
+        return shape;\r
+    }\r
+\r
+    public XSLFConnectorShape createConnector(){\r
+        CTConnector sp = _spTree.addNewCxnSp();\r
+        sp.set(XSLFConnectorShape.prototype(_shapeId++));\r
+        XSLFConnectorShape shape = new XSLFConnectorShape(sp, _sheet);\r
+        shape.setAnchor(new Rectangle());\r
+        shape.setLineColor(Color.black);\r
+        shape.setLineWidth(0.75);\r
+        return shape;\r
+    }\r
+\r
+    public XSLFGroupShape createGroup(){\r
+        CTGroupShape obj = _spTree.addNewGrpSp();\r
+        obj.set(XSLFGroupShape.prototype(_shapeId++));\r
+        XSLFGroupShape shape = new XSLFGroupShape(obj, _sheet);\r
+        shape.setAnchor(new Rectangle());\r
+        return shape;\r
+    }\r
+\r
+    public XSLFPictureShape createPicture(String rel){\r
+        CTPicture obj = _spTree.addNewPic();\r
+        obj.set(XSLFPictureShape.prototype(_shapeId++, rel));\r
+        XSLFPictureShape shape = new XSLFPictureShape(obj, _sheet);\r
+        shape.setAnchor(new Rectangle());\r
+        return shape;\r
+    }\r
+}\r
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFFactory.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFFactory.java
new file mode 100755 (executable)
index 0000000..cb7f329
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ *  ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one or more
+ *    contributor license agreements.  See the NOTICE file distributed with
+ *    this work for additional information regarding copyright ownership.
+ *    The ASF licenses this file to You under the Apache License, Version 2.0
+ *    (the "License"); you may not use this file except in compliance with
+ *    the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ * ====================================================================
+ */
+
+package org.apache.poi.xslf.usermodel;
+
+import org.apache.poi.POIXMLDocumentPart;
+import org.apache.poi.POIXMLException;
+import org.apache.poi.POIXMLFactory;
+import org.apache.poi.POIXMLRelation;
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.apache.poi.openxml4j.opc.PackageRelationship;
+import org.apache.poi.util.Beta;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+
+import java.lang.reflect.Constructor;
+
+/**
+ * Instantiates sub-classes of POIXMLDocumentPart depending on their relationship type
+ *
+ * @author Yegor Kozlov
+ */
+@Beta
+public final class XSLFFactory extends POIXMLFactory  {
+    private static final POILogger logger = POILogFactory.getLogger(XSLFFactory.class);
+
+    private XSLFFactory(){
+
+    }
+
+    private static final XSLFFactory inst = new XSLFFactory();
+
+    public static XSLFFactory getInstance(){
+        return inst;
+    }
+
+    @Override
+    public POIXMLDocumentPart createDocumentPart(POIXMLDocumentPart parent, PackageRelationship rel, PackagePart part){
+        POIXMLRelation descriptor = XSLFRelation.getInstance(rel.getRelationshipType());
+        if(descriptor == null || descriptor.getRelationClass() == null){
+            logger.log(POILogger.DEBUG, "using default POIXMLDocumentPart for " + rel.getRelationshipType());
+            return new POIXMLDocumentPart(part, rel);
+        }
+
+        try {
+            Class<? extends POIXMLDocumentPart> cls = descriptor.getRelationClass();
+            Constructor<? extends POIXMLDocumentPart> constructor = cls.getDeclaredConstructor(PackagePart.class, PackageRelationship.class);
+            return constructor.newInstance(part, rel);
+        } catch (Exception e){
+            throw new POIXMLException(e);
+        }
+    }
+
+    @Override
+    public POIXMLDocumentPart newDocumentPart(POIXMLRelation descriptor){
+        try {
+            Class<? extends POIXMLDocumentPart> cls = descriptor.getRelationClass();
+            Constructor<? extends POIXMLDocumentPart> constructor = cls.getDeclaredConstructor();
+            return constructor.newInstance();
+        } catch (Exception e){
+            throw new POIXMLException(e);
+        }
+    }
+
+}
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFFreeformShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFFreeformShape.java
new file mode 100755 (executable)
index 0000000..a494a3c
--- /dev/null
@@ -0,0 +1,178 @@
+/*\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.sl.usermodel.ShapeContainer;\r
+import org.apache.poi.util.Beta;\r
+import org.apache.poi.util.Units;\r
+import org.apache.xmlbeans.XmlObject;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTAdjPoint2D;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTCustomGeometry2D;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTGeomRect;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTPath2D;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTPath2DClose;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTPath2DCubicBezierTo;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTPath2DLineTo;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTPath2DMoveTo;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTShapeNonVisual;\r
+\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.GeneralPath;\r
+import java.awt.geom.PathIterator;\r
+import java.awt.geom.Rectangle2D;\r
+\r
+/**\r
+ * Represents a custom geometric shape.\r
+ * This shape will consist of a series of lines and curves described within a creation path.\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+@Beta\r
+public class XSLFFreeformShape extends XSLFAutoShape {\r
+\r
+    /*package*/ XSLFFreeformShape(CTShape shape, XSLFSheet sheet) {\r
+        super(shape, sheet);\r
+    }\r
+\r
+    /**\r
+     * Set the shape path\r
+     *\r
+     * @param path  shape outline\r
+     * @return the number of points written\r
+     */\r
+    public int setPath(GeneralPath path) {\r
+        CTPath2D ctPath = CTPath2D.Factory.newInstance();\r
+\r
+        Rectangle2D bounds = path.getBounds2D();\r
+        int x0 = Units.toEMU(bounds.getX());\r
+        int y0 = Units.toEMU(bounds.getY());\r
+        PathIterator it = path.getPathIterator(new AffineTransform());\r
+        int numPoints = 0;\r
+        ctPath.setH(Units.toEMU(bounds.getHeight()));\r
+        ctPath.setW(Units.toEMU(bounds.getWidth()));\r
+        while (!it.isDone()) {\r
+            double[] vals = new double[6];\r
+            int type = it.currentSegment(vals);\r
+            switch (type) {\r
+                case PathIterator.SEG_MOVETO:\r
+                    CTAdjPoint2D mv = ctPath.addNewMoveTo().addNewPt();\r
+                    mv.setX(Units.toEMU(vals[0]) - x0);\r
+                    mv.setY(Units.toEMU(vals[1]) - y0);\r
+                    numPoints++;\r
+                    break;\r
+                case PathIterator.SEG_LINETO:\r
+                    CTAdjPoint2D ln = ctPath.addNewLnTo().addNewPt();\r
+                    ln.setX(Units.toEMU(vals[0]) - x0);\r
+                    ln.setY(Units.toEMU(vals[1]) - y0);\r
+                    numPoints++;\r
+                    break;\r
+                case PathIterator.SEG_CUBICTO:\r
+                    CTPath2DCubicBezierTo bez = ctPath.addNewCubicBezTo();\r
+                    CTAdjPoint2D p1 = bez.addNewPt();\r
+                    p1.setX(Units.toEMU(vals[0]) - x0);\r
+                    p1.setY(Units.toEMU(vals[1]) - y0);\r
+                    CTAdjPoint2D p2 = bez.addNewPt();\r
+                    p2.setX(Units.toEMU(vals[2]) - x0);\r
+                    p2.setY(Units.toEMU(vals[3]) - y0);\r
+                    CTAdjPoint2D p3 = bez.addNewPt();\r
+                    p3.setX(Units.toEMU(vals[4]) - x0);\r
+                    p3.setY(Units.toEMU(vals[5]) - y0);\r
+                    numPoints += 3;\r
+                    break;\r
+                case PathIterator.SEG_CLOSE:\r
+                    numPoints++;\r
+                    ctPath.addNewClose();\r
+                    break;\r
+            }\r
+            it.next();\r
+        }\r
+        getSpPr().getCustGeom().getPathLst().setPathArray(new CTPath2D[]{ctPath});\r
+        setAnchor(bounds);\r
+        return numPoints;\r
+    }\r
+\r
+    public GeneralPath getPath() {\r
+        GeneralPath path = new GeneralPath();\r
+        Rectangle2D bounds = getAnchor();\r
+        int x0 = Units.toEMU(bounds.getX());\r
+        int y0 = Units.toEMU(bounds.getY());\r
+        CTCustomGeometry2D geom = getSpPr().getCustGeom();\r
+        for(CTPath2D spPath : geom.getPathLst().getPathList()){\r
+            for(XmlObject ch : spPath.selectPath("*")){\r
+                if(ch instanceof CTPath2DMoveTo){\r
+                    CTAdjPoint2D pt = ((CTPath2DMoveTo)ch).getPt();\r
+                    path.moveTo(Units.toPoints((Long)pt.getX() + x0),\r
+                                Units.toPoints((Long)pt.getY() + y0));\r
+                } else if (ch instanceof CTPath2DLineTo){\r
+                    CTAdjPoint2D pt = ((CTPath2DLineTo)ch).getPt();\r
+                    path.lineTo(Units.toPoints((Long)pt.getX() + x0),\r
+                                Units.toPoints((Long)pt.getY() + y0));\r
+                } else if (ch instanceof CTPath2DCubicBezierTo){\r
+                    CTPath2DCubicBezierTo bez = ((CTPath2DCubicBezierTo)ch);\r
+                    CTAdjPoint2D pt1 = bez.getPtArray(0);\r
+                    CTAdjPoint2D pt2 = bez.getPtArray(1);\r
+                    CTAdjPoint2D pt3 = bez.getPtArray(2);\r
+                    path.curveTo(\r
+                            Units.toPoints((Long) pt1.getX() + x0),\r
+                            Units.toPoints((Long) pt1.getY() + y0),\r
+                            Units.toPoints((Long) pt2.getX() + x0),\r
+                            Units.toPoints((Long) pt2.getY() + y0),\r
+                            Units.toPoints((Long) pt3.getX() + x0),\r
+                            Units.toPoints((Long) pt3.getY() + y0)\r
+                    );\r
+\r
+                } else if (ch instanceof CTPath2DClose){\r
+                    path.closePath();\r
+                }\r
+            }\r
+        }\r
+\r
+        return path;\r
+    }\r
+    /**\r
+     * @param shapeId 1-based shapeId\r
+     */\r
+    static CTShape prototype(int shapeId) {\r
+        CTShape ct = CTShape.Factory.newInstance();\r
+        CTShapeNonVisual nvSpPr = ct.addNewNvSpPr();\r
+        CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr();\r
+        cnv.setName("Freeform " + shapeId);\r
+        cnv.setId(shapeId + 1);\r
+        nvSpPr.addNewCNvSpPr();\r
+        nvSpPr.addNewNvPr();\r
+        CTShapeProperties spPr = ct.addNewSpPr();\r
+        CTCustomGeometry2D geom = spPr.addNewCustGeom();\r
+        geom.addNewAvLst();\r
+        geom.addNewGdLst();\r
+        geom.addNewAhLst();\r
+        geom.addNewCxnLst();\r
+        CTGeomRect rect = geom.addNewRect();\r
+        rect.setR("r");\r
+        rect.setB("b");\r
+        rect.setT("t");\r
+        rect.setL("l");\r
+        geom.addNewPathLst();\r
+        return ct;\r
+    }\r
+\r
+}
\ No newline at end of file
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGraphicFrame.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGraphicFrame.java
new file mode 100755 (executable)
index 0000000..0abad44
--- /dev/null
@@ -0,0 +1,79 @@
+/*\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.sl.usermodel.Shape;\r
+import org.apache.poi.sl.usermodel.ShapeContainer;\r
+import org.apache.poi.sl.usermodel.ShapeGroup;\r
+import org.apache.poi.util.Beta;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame;\r
+\r
+import java.awt.geom.Rectangle2D;\r
+\r
+/**\r
+ * @author Yegor Kozlov\r
+ */\r
+@Beta\r
+public class XSLFGraphicFrame extends XSLFShape {\r
+    private final CTGraphicalObjectFrame _shape;\r
+    private final XSLFSheet _sheet;\r
+\r
+    /*package*/ XSLFGraphicFrame(CTGraphicalObjectFrame shape, XSLFSheet sheet){\r
+        _shape = shape;\r
+        _sheet = sheet;\r
+    }\r
+\r
+    public CTGraphicalObjectFrame getXmlObject(){\r
+        return _shape;\r
+    }\r
+\r
+    public int getShapeType(){\r
+        throw new RuntimeException("NotImplemented");\r
+    }\r
+\r
+    public int getShapeId(){\r
+        return (int)_shape.getNvGraphicFramePr().getCNvPr().getId();\r
+    }\r
+\r
+    public String getShapeName(){\r
+        return _shape.getNvGraphicFramePr().getCNvPr().getName();\r
+    }\r
+\r
+    public Rectangle2D getAnchor(){\r
+        throw new RuntimeException("NotImplemented");\r
+    }\r
+\r
+    public void setAnchor(Rectangle2D anchor){\r
+        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
+    }\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/XSLFGroupShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java
new file mode 100755 (executable)
index 0000000..8044208
--- /dev/null
@@ -0,0 +1,220 @@
+/*\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.openxml4j.opc.PackagePart;\r
+import org.apache.poi.openxml4j.opc.PackageRelationship;\r
+import org.apache.poi.openxml4j.opc.TargetMode;\r
+import org.apache.poi.sl.usermodel.Shape;\r
+import org.apache.poi.sl.usermodel.ShapeContainer;\r
+import org.apache.poi.sl.usermodel.ShapeGroup;\r
+import org.apache.poi.util.Beta;\r
+import org.apache.poi.util.Units;\r
+import org.apache.xmlbeans.XmlObject;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupShapeProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupTransform2D;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShapeNonVisual;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;\r
+\r
+import java.awt.geom.Rectangle2D;\r
+import java.util.List;\r
+import java.util.regex.Pattern;\r
+\r
+/**\r
+ * Represents a group shape that consists of many shapes grouped together.\r
+ * \r
+ * @author Yegor Kozlov\r
+ */\r
+@Beta\r
+public class XSLFGroupShape extends XSLFShape {\r
+    private final CTGroupShape _shape;\r
+    private final XSLFSheet _sheet;\r
+    private final List<XSLFShape> _shapes;\r
+    private final CTGroupShapeProperties _spPr;\r
+    private XSLFDrawing _drawing;\r
+\r
+    /*package*/ XSLFGroupShape(CTGroupShape shape, XSLFSheet sheet){\r
+        _shape = shape;\r
+        _sheet = sheet;\r
+\r
+        _shapes = _sheet.buildShapes(_shape);\r
+        _spPr = shape.getGrpSpPr();\r
+    }\r
+\r
+    public CTGroupShape getXmlObject(){\r
+        return _shape;\r
+    }\r
+\r
+    public Rectangle2D getAnchor(){\r
+        CTGroupTransform2D xfrm = _spPr.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
+        CTGroupTransform2D xfrm = _spPr.isSetXfrm() ? _spPr.getXfrm() : _spPr.addNewXfrm();\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
+    public Rectangle2D getInteriorAnchor(){\r
+        CTGroupTransform2D xfrm = _spPr.getXfrm();\r
+        CTPoint2D off = xfrm.getChOff();\r
+        long x = off.getX();\r
+        long y = off.getY();\r
+        CTPositiveSize2D ext = xfrm.getChExt();\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 setInteriorAnchor(Rectangle2D anchor){\r
+        CTGroupTransform2D xfrm = _spPr.isSetXfrm() ? _spPr.getXfrm() : _spPr.addNewXfrm();\r
+        CTPoint2D off = xfrm.isSetChOff() ? xfrm.getChOff() : xfrm.addNewChOff();\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.isSetChExt() ? xfrm.getChExt() : xfrm.addNewChExt();\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
+    public XSLFShape[] getShapes(){\r
+        return _shapes.toArray(new XSLFShape[_shapes.size()]);\r
+    }\r
+\r
+    public boolean removeShape(XSLFShape xShape) {\r
+        XmlObject obj = xShape.getXmlObject();\r
+        if(obj instanceof CTShape){\r
+            _shape.getSpList().remove(obj);\r
+        } else if (obj instanceof CTGroupShape){\r
+            _shape.getGrpSpList().remove(obj);\r
+        } else if (obj instanceof CTConnector){\r
+            _shape.getCxnSpList().remove(obj);\r
+        } else {\r
+            throw new IllegalArgumentException("Unsupported shape: " + xShape);\r
+        }\r
+        return _shapes.remove(xShape);\r
+    }\r
+\r
+    public String getShapeName(){\r
+        return _shape.getNvGrpSpPr().getCNvPr().getName();\r
+    }\r
+\r
+    public int getShapeId(){\r
+        return (int)_shape.getNvGrpSpPr().getCNvPr().getId();\r
+    }\r
+\r
+    /**\r
+     * @param shapeId 1-based shapeId\r
+     */\r
+    static CTGroupShape prototype(int shapeId) {\r
+        CTGroupShape ct = CTGroupShape.Factory.newInstance();\r
+        CTGroupShapeNonVisual nvSpPr = ct.addNewNvGrpSpPr();\r
+        CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr();\r
+        cnv.setName("Group " + shapeId);\r
+        cnv.setId(shapeId + 1);\r
+\r
+        nvSpPr.addNewCNvGrpSpPr();\r
+        nvSpPr.addNewNvPr();\r
+        ct.addNewGrpSpPr();\r
+        return ct;\r
+    }\r
+\r
+    // shape factory methods\r
+    private XSLFDrawing getDrawing(){\r
+        if(_drawing == null) {\r
+            _drawing = new XSLFDrawing(_sheet, _shape);\r
+        }\r
+        return _drawing;\r
+    }\r
+\r
+    public XSLFAutoShape createAutoShape(){\r
+        XSLFAutoShape sh = getDrawing().createAutoShape();\r
+        _shapes.add(sh);\r
+        return sh;\r
+    }\r
+\r
+    public XSLFFreeformShape createFreeform(){\r
+        XSLFFreeformShape sh = getDrawing().createFreeform();\r
+        _shapes.add(sh);\r
+        return sh;\r
+    }\r
+\r
+    public XSLFTextBox createTextBox(){\r
+        XSLFTextBox sh = getDrawing().createTextBox();\r
+        _shapes.add(sh);\r
+        return sh;\r
+    }\r
+\r
+    public XSLFConnectorShape createConnector(){\r
+        XSLFConnectorShape sh = getDrawing().createConnector();\r
+        _shapes.add(sh);\r
+        return sh;\r
+    }\r
+\r
+    public XSLFGroupShape createGroup(){\r
+        XSLFGroupShape sh = getDrawing().createGroup();\r
+        _shapes.add(sh);\r
+        return sh;\r
+    }\r
+\r
+    public XSLFPictureShape createPicture(int pictureIndex){\r
+\r
+        List<PackagePart>  pics = _sheet.getPackagePart().getPackage()\r
+                .getPartsByName(Pattern.compile("/ppt/media/.*?"));\r
+\r
+        PackagePart pic = pics.get(pictureIndex);\r
+\r
+        PackageRelationship rel = _sheet.getPackagePart().addRelationship(\r
+                pic.getPartName(), TargetMode.INTERNAL, XSLFRelation.IMAGES.getRelation());\r
+\r
+        XSLFPictureShape sh = getDrawing().createPicture(rel.getId());\r
+        sh.resize();\r
+        _shapes.add(sh);\r
+        return sh;\r
+    }\r
+\r
+}
\ No newline at end of file
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java
new file mode 100644 (file)
index 0000000..6fd151f
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ *  ====================================================================
+ *    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.POIXMLDocumentPart;
+import org.apache.poi.POIXMLException;
+import org.apache.poi.POIXMLRelation;
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.apache.poi.openxml4j.opc.PackageRelationship;
+import org.apache.poi.util.Beta;
+import org.apache.poi.util.IOUtils;
+
+import java.io.IOException;
+
+/**
+ * Instantiates sub-classes of POIXMLDocumentPart depending on their relationship type
+ *
+ * @author Yegor Kozlov
+ */
+@Beta
+public final class XSLFPictureData extends POIXMLDocumentPart {
+    /**
+     * Extended windows meta file
+     */
+    public static final int PICTURE_TYPE_EMF = 2;
+
+    /**
+     * Windows Meta File
+     */
+    public static final int PICTURE_TYPE_WMF = 3;
+
+    /**
+     * Mac PICT format
+     */
+    public static final int PICTURE_TYPE_PICT = 4;
+
+    /**
+     * JPEG format
+     */
+    public static final int PICTURE_TYPE_JPEG = 5;
+
+    /**
+     * PNG format
+     */
+    public static final int PICTURE_TYPE_PNG = 6;
+
+    /**
+     * Device independent bitmap
+     */
+    public static final int PICTURE_TYPE_DIB = 7;
+
+    /**
+     * GIF image format
+     */
+    public static final int PICTURE_TYPE_GIF = 8;
+
+    /**
+     * Relationships for each known picture type
+     */
+    protected static final POIXMLRelation[] RELATIONS;
+
+    static {
+        RELATIONS = new POIXMLRelation[9];
+        RELATIONS[PICTURE_TYPE_EMF] = XSLFRelation.IMAGE_EMF;
+        RELATIONS[PICTURE_TYPE_WMF] = XSLFRelation.IMAGE_WMF;
+        RELATIONS[PICTURE_TYPE_PICT] = XSLFRelation.IMAGE_PICT;
+        RELATIONS[PICTURE_TYPE_JPEG] = XSLFRelation.IMAGE_JPEG;
+        RELATIONS[PICTURE_TYPE_PNG] = XSLFRelation.IMAGE_PNG;
+        RELATIONS[PICTURE_TYPE_DIB] = XSLFRelation.IMAGE_DIB;
+        RELATIONS[PICTURE_TYPE_GIF] = XSLFRelation.IMAGE_GIF;
+    }
+
+    private Long checksum = null;
+
+    /**
+     * Create a new XSLFGraphicData node
+     */
+    protected XSLFPictureData() {
+        super();
+    }
+
+    /**
+     * Construct XSLFPictureData from a package part
+     *
+     * @param part the package part holding the drawing data,
+     * @param rel  the package relationship holding this drawing,
+     *             the relationship type must be http://schemas.openxmlformats.org/officeDocument/2006/relationships/image
+     */
+    public XSLFPictureData(PackagePart part, PackageRelationship rel) {
+        super(part, rel);
+    }
+
+    /**
+     * Gets the picture data as a byte array.
+     * <p>
+     * Note, that this call might be expensive since all the picture data is copied into a temporary byte array.
+     * You can grab the picture data directly from the underlying package part as follows:
+     * <br/>
+     * <code>
+     * InputStream is = getPackagePart().getInputStream();
+     * </code>
+     * </p>
+     *
+     * @return the Picture data.
+     */
+    public byte[] getData() {
+        try {
+            return IOUtils.toByteArray(getPackagePart().getInputStream());
+        } catch (IOException e) {
+            throw new POIXMLException(e);
+        }
+    }
+
+    /**
+     * Returns the file name of the image, eg image7.jpg . The original filename
+     * isn't always available, but if it can be found it's likely to be in the
+     * CTDrawing
+     */
+    public String getFileName() {
+        String name = getPackagePart().getPartName().getName();
+        if (name == null)
+            return null;
+        return name.substring(name.lastIndexOf('/') + 1);
+    }
+
+    /**
+     * Suggests a file extension for this image.
+     *
+     * @return the file extension.
+     */
+    public String suggestFileExtension() {
+        return getPackagePart().getPartName().getExtension();
+    }
+
+    /**
+     * Return an integer constant that specifies type of this picture
+     *
+     * @return an integer constant that specifies type of this picture
+     */
+    public int getPictureType() {
+        String contentType = getPackagePart().getContentType();
+        for (int i = 0; i < RELATIONS.length; i++) {
+            if (RELATIONS[i] == null) {
+                continue;
+            }
+
+            if (RELATIONS[i].getContentType().equals(contentType)) {
+                return i;
+            }
+        }
+        return 0;
+    }
+
+}
\ No newline at end of file
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java
new file mode 100755 (executable)
index 0000000..c2ce2bd
--- /dev/null
@@ -0,0 +1,107 @@
+/*\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.POIXMLDocumentPart;\r
+import org.apache.poi.sl.usermodel.ShapeContainer;\r
+import org.apache.poi.util.Beta;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTPictureNonVisual;\r
+\r
+import javax.imageio.ImageIO;\r
+import java.awt.geom.Rectangle2D;\r
+import java.awt.image.BufferedImage;\r
+import java.io.ByteArrayInputStream;\r
+\r
+/**\r
+ * @author Yegor Kozlov\r
+ */\r
+@Beta\r
+public class XSLFPictureShape extends XSLFSimpleShape {\r
+    private XSLFPictureData _data;\r
+\r
+    /*package*/ XSLFPictureShape(CTPicture shape, XSLFSheet sheet) {\r
+        super(shape, sheet);\r
+    }\r
+\r
+\r
+    /**\r
+     * @param shapeId 1-based shapeId\r
+     * @param rel     relationship to the picture data in the ooxml package\r
+     */\r
+    static CTPicture prototype(int shapeId, String rel) {\r
+        CTPicture ct = CTPicture.Factory.newInstance();\r
+        CTPictureNonVisual nvSpPr = ct.addNewNvPicPr();\r
+        CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr();\r
+        cnv.setName("Picture " + shapeId);\r
+        cnv.setId(shapeId + 1);\r
+        nvSpPr.addNewCNvPicPr().addNewPicLocks().setNoChangeAspect(true);\r
+        nvSpPr.addNewNvPr();\r
+\r
+        CTBlipFillProperties blipFill = ct.addNewBlipFill();\r
+        CTBlip blip = blipFill.addNewBlip();\r
+        blip.setEmbed(rel);\r
+        blipFill.addNewStretch().addNewFillRect();\r
+\r
+        CTShapeProperties spPr = ct.addNewSpPr();\r
+        CTPresetGeometry2D prst = spPr.addNewPrstGeom();\r
+        prst.setPrst(STShapeType.RECT);\r
+        prst.addNewAvLst();\r
+        return ct;\r
+    }\r
+\r
+    /**\r
+     * Resize this picture to the default size.\r
+     * For PNG and JPEG resizes the image to 100%,\r
+     * for other types sets the default size of 200x200 pixels.\r
+     */\r
+    public void resize() {\r
+        XSLFPictureData pict = getPictureData();\r
+\r
+        try {\r
+            BufferedImage img = ImageIO.read(new ByteArrayInputStream(pict.getData()));\r
+            setAnchor(new Rectangle2D.Double(0, 0, img.getWidth(), img.getHeight()));\r
+        }\r
+        catch (Exception e) {\r
+            //default size is 200x200\r
+            setAnchor(new java.awt.Rectangle(50, 50, 200, 200));\r
+        }\r
+    }\r
+\r
+    public XSLFPictureData getPictureData() {\r
+        if(_data == null){\r
+            CTPicture ct = (CTPicture)getXmlObject();\r
+            String blipId = ct.getBlipFill().getBlip().getEmbed();\r
+\r
+            for (POIXMLDocumentPart part : getSheet().getRelations()) {\r
+                if(part.getPackageRelationship().getId().equals(blipId)){\r
+                    _data = (XSLFPictureData)part;\r
+                }\r
+            }\r
+        }\r
+        return _data;\r
+    }\r
+}
\ No newline at end of file
index 29cf65809e6593d3d25fe747d83c241c3ebb41e6..c546d93dfc42f6ad96681a86d359ecf3fdde48bb 100644 (file)
 ==================================================================== */
 package org.apache.poi.xslf.usermodel;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import org.apache.poi.POIXMLDocumentPart;
 import org.apache.poi.POIXMLRelation;
+import org.apache.poi.util.Beta;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
 
+import java.util.HashMap;
+import java.util.Map;
+
+@Beta
 public class XSLFRelation extends POIXMLRelation {
 
    private static POILogger log = POILogFactory.getLogger(XSLFRelation.class);
@@ -78,16 +80,23 @@ public class XSLFRelation extends POIXMLRelation {
            "application/vnd.openxmlformats-officedocument.presentationml.slide+xml",
            "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide", 
            "/ppt/slides/slide#.xml", 
-           null
+           XSLFSlide.class
    );
    
    public static final XSLFRelation SLIDE_LAYOUT = new XSLFRelation(
          "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml",
          "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout",
          "/ppt/slideLayouts/slideLayout#.xml", 
-         null
+         XSLFSlideLayout.class
    );
    
+    public static final XSLFRelation SLIDE_MASTER = new XSLFRelation(
+          "application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml",
+          "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster",
+          "/ppt/slideMasters/slideMaster#.xml",
+          XSLFSlideMaster.class
+    );
+
    public static final XSLFRelation COMMENTS = new XSLFRelation(
          "application/vnd.openxmlformats-officedocument.presentationml.comments+xml",
          "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments",
@@ -108,6 +117,55 @@ public class XSLFRelation extends POIXMLRelation {
          null
    );
    
+    public static final XSLFRelation IMAGE_EMF = new XSLFRelation(
+          "image/x-emf",
+          "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
+          "/ppt/media/image#.emf",
+          XSLFPictureData.class
+       );
+       public static final XSLFRelation IMAGE_WMF = new XSLFRelation(
+             "image/x-wmf",
+             "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
+             "/ppt/media/image#.wmf",
+             XSLFPictureData.class
+       );
+       public static final XSLFRelation IMAGE_PICT = new XSLFRelation(
+             "image/pict",
+             "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
+             "/ppt/media/image#.pict",
+             XSLFPictureData.class
+       );
+       public static final XSLFRelation IMAGE_JPEG = new XSLFRelation(
+             "image/jpeg",
+             "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
+             "/ppt/media/image#.jpeg",
+             XSLFPictureData.class
+       );
+       public static final XSLFRelation IMAGE_PNG = new XSLFRelation(
+             "image/png",
+             "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
+             "/ppt/media/image#.png",
+             XSLFPictureData.class
+       );
+       public static final XSLFRelation IMAGE_DIB = new XSLFRelation(
+             "image/dib",
+             "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
+             "/ppt/media/image#.dib",
+             XSLFPictureData.class
+       );
+       public static final XSLFRelation IMAGE_GIF = new XSLFRelation(
+             "image/gif",
+             "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
+             "/ppt/media/image#.gif",
+             XSLFPictureData.class
+       );
+
+    public static final XSLFRelation IMAGES = new XSLFRelation(
+            null,
+               "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
+               null,
+               null
+    );
 
    private XSLFRelation(String type, String rel, String defaultName, Class<? extends POIXMLDocumentPart> cls) {
       super(type, rel, defaultName, cls);
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java
new file mode 100755 (executable)
index 0000000..b1b65ea
--- /dev/null
@@ -0,0 +1,48 @@
+/*\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.sl.usermodel.Shape;\r
+import org.apache.poi.util.Beta;\r
+import org.apache.xmlbeans.XmlObject;\r
+\r
+import java.awt.geom.Rectangle2D;\r
+\r
+/**\r
+ * @author Yegor Kozlov\r
+ */\r
+@Beta\r
+public abstract class XSLFShape {\r
+\r
+\r
+    public abstract Rectangle2D getAnchor();\r
+\r
+    public abstract void setAnchor(Rectangle2D anchor);\r
+\r
+    public abstract XmlObject getXmlObject();\r
+\r
+    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 3bbd099c0e9115e8f709d7059737e3766bd4fd1e..02ce9fdb7df65b4e6a354bc9553685434281d99b 100644 (file)
 ==================================================================== */
 package org.apache.poi.xslf.usermodel;
 
-import org.apache.poi.sl.usermodel.Background;
-import org.apache.poi.sl.usermodel.MasterSheet;
-import org.apache.poi.sl.usermodel.Shape;
-import org.apache.poi.sl.usermodel.Sheet;
-import org.apache.poi.sl.usermodel.SlideShow;
-
-public abstract class XSLFSheet implements Sheet {
-       private SlideShow slideShow;
-       protected XSLFSheet(SlideShow parent) {
-               this.slideShow = parent;
-       }
+import org.apache.poi.POIXMLDocumentPart;
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.apache.poi.openxml4j.opc.PackageRelationship;
+import org.apache.poi.openxml4j.opc.TargetMode;
+import org.apache.poi.util.Beta;
+import org.apache.xmlbeans.XmlObject;
+import org.apache.xmlbeans.XmlOptions;
+import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId;
+import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector;
+import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame;
+import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape;
+import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture;
+import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
 
-       public Background getBackground() {
-               // TODO Auto-generated method stub
-               return null;
-       }
+import javax.xml.namespace.QName;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
 
-       public MasterSheet getMasterSheet() {
-               // TODO Auto-generated method stub
-               return null;
-       }
+@Beta
+public abstract class XSLFSheet extends POIXMLDocumentPart {
+    private XSLFDrawing _drawing;
+    private List<XSLFShape> _shapes;
+    private CTGroupShape _spTree;
 
-       public SlideShow getSlideShow() {
-               return slideShow;
-       }
+    public XSLFSheet(){
+        super();
+    }
 
-       public void addShape(Shape shape) {
-               // TODO Auto-generated method stub
+    public XSLFSheet(PackagePart part, PackageRelationship rel){
+        super(part, rel);
+    }
 
+       public XMLSlideShow getSlideShow() {
+               return (XMLSlideShow)getParent();
        }
 
-       public Shape[] getShapes() {
-               // TODO Auto-generated method stub
-               return null;
-       }
+    protected List<XSLFShape> buildShapes(CTGroupShape spTree){
+        List<XSLFShape> shapes = new ArrayList<XSLFShape>();
+        for(XmlObject ch : spTree.selectPath("*")){
+            if(ch instanceof CTShape){ // simple shape
+                XSLFAutoShape shape = XSLFAutoShape.create((CTShape)ch, this);
+                shapes.add(shape);
+            } else if (ch instanceof CTGroupShape){
+                shapes.add(new XSLFGroupShape((CTGroupShape)ch, this));
+            } else if (ch instanceof CTConnector){
+                shapes.add(new XSLFConnectorShape((CTConnector)ch, this));
+            } else if (ch instanceof CTPicture){
+                shapes.add(new XSLFPictureShape((CTPicture)ch, this));
+            } else if (ch instanceof CTGraphicalObjectFrame){
+                shapes.add(new XSLFGraphicFrame((CTGraphicalObjectFrame)ch, this));
+            }
+        }
+        return shapes;
+    }
+
+    public abstract XmlObject getXmlObject();
+
+
+    private XSLFDrawing getDrawing(){
+        if(_drawing == null) {
+            _drawing = new XSLFDrawing(this, getSpTree());
+        }
+        return _drawing;
+    }
+
+    private List<XSLFShape> getShapeList(){
+        if(_shapes == null){
+            _shapes = buildShapes(getSpTree());
+        }
+        return _shapes;
+    }
+
+    // shape factory methods
+
+    public XSLFAutoShape createAutoShape(){
+        List<XSLFShape> shapes = getShapeList();
+        XSLFAutoShape sh = getDrawing().createAutoShape();
+        shapes.add(sh);
+        return sh;
+    }
+
+    public XSLFFreeformShape createFreeform(){
+        List<XSLFShape> shapes = getShapeList();
+        XSLFFreeformShape sh = getDrawing().createFreeform();
+        shapes.add(sh);
+        return sh;
+    }
+
+    public XSLFTextBox createTextBox(){
+        List<XSLFShape> shapes = getShapeList();
+        XSLFTextBox sh = getDrawing().createTextBox();
+        shapes.add(sh);
+        return sh;
+    }
+
+    public XSLFConnectorShape createConnector(){
+        List<XSLFShape> shapes = getShapeList();
+        XSLFConnectorShape sh = getDrawing().createConnector();
+        shapes.add(sh);
+        return sh;
+    }
+
+    public XSLFGroupShape createGroup(){
+        List<XSLFShape> shapes = getShapeList();
+        XSLFGroupShape sh = getDrawing().createGroup();
+        shapes.add(sh);
+        return sh;
+    }
+
+    public XSLFPictureShape createPicture(int pictureIndex){
+        List<PackagePart>  pics = getPackagePart().getPackage()
+                .getPartsByName(Pattern.compile("/ppt/media/.*?"));
+
+        PackagePart pic = pics.get(pictureIndex);
+
+        PackageRelationship rel = getPackagePart().addRelationship(
+                pic.getPartName(), TargetMode.INTERNAL, XSLFRelation.IMAGES.getRelation());
+        addRelation(rel.getId(), new XSLFPictureData(pic, rel));
+
+        XSLFPictureShape sh = getDrawing().createPicture(rel.getId());
+        sh.resize();
+
+        getShapeList().add(sh);
+        return sh;
+    }
+
+    public XSLFShape[] getShapes(){
+        return getShapeList().toArray(new XSLFShape[_shapes.size()]);
+    }
+
+    public boolean removeShape(XSLFShape xShape) {
+        XmlObject obj = xShape.getXmlObject();
+        CTGroupShape spTree = getSpTree();
+        if(obj instanceof CTShape){
+            spTree.getSpList().remove(obj);
+        } else if (obj instanceof CTGroupShape){
+            spTree.getGrpSpList().remove(obj);
+        } else if (obj instanceof CTConnector){
+            spTree.getCxnSpList().remove(obj);
+        } else {
+            throw new IllegalArgumentException("Unsupported shape: " + xShape);
+        }
+        return getShapeList().remove(xShape);
+    }
+
+    protected abstract String getRootElementName();
+
+    protected CTGroupShape getSpTree(){
+        if(_spTree == null) {
+            XmlObject root = getXmlObject();
+            XmlObject[] sp = root.selectPath(
+                    "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:spTree");
+            if(sp.length == 0) throw new IllegalStateException("CTGroupShape was not found");
+            _spTree = (CTGroupShape)sp[0];
+        }
+        return _spTree;
+    }
+
+    protected final void commit() throws IOException {
+        XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
+
+        Map<String, String> map = new HashMap<String, String>();
+        map.put(STRelationshipId.type.getName().getNamespaceURI(), "r");
+        map.put("http://schemas.openxmlformats.org/drawingml/2006/main", "a");
+        map.put("http://schemas.openxmlformats.org/presentationml/2006/main", "p");
+        xmlOptions.setSaveSuggestedPrefixes(map);
+        String docName = getRootElementName();
+        if(docName != null) {
+            xmlOptions.setSaveSyntheticDocumentElement(
+                    new QName("http://schemas.openxmlformats.org/presentationml/2006/main", docName));
+        }
+
+        PackagePart part = getPackagePart();
+        OutputStream out = part.getOutputStream();
+        getXmlObject().save(out, xmlOptions);
+        out.close();
+    }
+
+    /**
+     * Set the contents of this sheet to be a copy of the source sheet.
+     *
+     * @param src the source sheet to copy data from
+     */
+    public void copy(XSLFSheet src){
+        _shapes = null;
+        _spTree = null;
+        _drawing = null;
+        getXmlObject().set(src.getXmlObject());
+    }
 
-       public boolean removeShape(Shape shape) {
-               // TODO Auto-generated method stub
-               return false;
-       }
 }
\ No newline at end of file
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java
new file mode 100755 (executable)
index 0000000..3b624dc
--- /dev/null
@@ -0,0 +1,268 @@
+/*\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.xslf.usermodel.LineCap;\r
+import org.apache.poi.xslf.usermodel.LineDash;\r
+import org.apache.poi.util.Beta;\r
+import org.apache.poi.util.Units;\r
+import org.apache.xmlbeans.XmlObject;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;\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.CTPresetLineDashProperties;\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.CTTransform2D;\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.STShapeType;\r
+\r
+import java.awt.*;\r
+import java.awt.geom.Rectangle2D;\r
+\r
+/**\r
+ * @author Yegor Kozlov\r
+ */\r
+@Beta\r
+public abstract class XSLFSimpleShape extends XSLFShape {\r
+    private final XmlObject _shape;\r
+    private final XSLFSheet _sheet;\r
+    private CTShapeProperties _spPr;\r
+    private CTNonVisualDrawingProps _nvPr;\r
+\r
+    /*package*/ XSLFSimpleShape(XmlObject shape, XSLFSheet sheet){\r
+        _shape = shape;\r
+        _sheet = sheet;\r
+    }\r
+\r
+    public XmlObject getXmlObject(){\r
+        return _shape;\r
+    }\r
+    \r
+    public XSLFSheet getSheet(){\r
+        return _sheet;\r
+    }\r
+    /**\r
+     * TODO match STShapeType with {@link org.apache.poi.sl.usermodel.ShapeTypes}\r
+     */\r
+    public int getShapeType() {\r
+        STShapeType.Enum stEnum = getSpPr().getPrstGeom().getPrst();\r
+        return stEnum.intValue();\r
+    }\r
+\r
+    public String getShapeName() {\r
+        return getNvPr().getName();\r
+    }\r
+\r
+    public int getShapeId() {\r
+        return (int)getNvPr().getId();\r
+    }\r
+\r
+    protected CTNonVisualDrawingProps getNvPr(){\r
+        if(_nvPr == null){\r
+            XmlObject[] rs = _shape.selectPath(\r
+                    "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:cNvPr");\r
+            if(rs.length != 0) {\r
+                _nvPr = (CTNonVisualDrawingProps)rs[0];\r
+            }\r
+        }\r
+        return _nvPr;\r
+    }\r
+\r
+    protected CTShapeProperties getSpPr(){\r
+        if(_spPr == null) {\r
+            for(XmlObject obj : _shape.selectPath("*")){\r
+                if(obj instanceof CTShapeProperties){\r
+                    _spPr = (CTShapeProperties)obj;\r
+                }\r
+            }\r
+        }\r
+        if(_spPr == null) {\r
+            throw new IllegalStateException("CTShapeProperties was not found.");\r
+        }\r
+        return _spPr;\r
+    }\r
+\r
+    public Rectangle2D getAnchor(){\r
+        CTTransform2D xfrm = getSpPr().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 = getSpPr().isSetXfrm() ? getSpPr().getXfrm() : getSpPr().addNewXfrm();\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
+     * Rotate this shape.\r
+     * <p>\r
+     * Positive angles are clockwise (i.e., towards the positive y axis);\r
+     * negative angles are counter-clockwise (i.e., towards the negative y axis).\r
+     * </p>\r
+     *\r
+     * @param theta the rotation angle in degrees.\r
+     */\r
+    public void setRotation(double theta){\r
+        CTTransform2D xfrm = getSpPr().getXfrm();\r
+        xfrm.setRot((int)(theta*60000));\r
+    }\r
+\r
+    /**\r
+     * Rotation angle in degrees\r
+     * <p>\r
+     * Positive angles are clockwise (i.e., towards the positive y axis);\r
+     * negative angles are counter-clockwise (i.e., towards the negative y axis).\r
+     * </p>\r
+     *\r
+     * @return rotation angle in degrees\r
+     */\r
+    public double getRotation(){\r
+        CTTransform2D xfrm = getSpPr().getXfrm();\r
+        return (double)xfrm.getRot()/60000;\r
+    }\r
+\r
+    public void setFlipHorizontal(boolean flip){\r
+        CTTransform2D xfrm = getSpPr().getXfrm();\r
+        xfrm.setFlipH(flip);\r
+    }\r
+\r
+    public void setFlipVertical(boolean flip){\r
+        CTTransform2D xfrm = getSpPr().getXfrm();\r
+        xfrm.setFlipV(flip);\r
+    }\r
+    /**\r
+     * Whether the shape is horizontally flipped\r
+     *\r
+     * @return whether the shape is horizontally flipped\r
+     */\r
+    public boolean getFlipHorizontal(){\r
+         return getSpPr().getXfrm().getFlipH();\r
+    }\r
+\r
+    public boolean getFlipVertical(){\r
+         return getSpPr().getXfrm().getFlipV();\r
+    }\r
+\r
+    public void setLineColor(Color color){\r
+        CTShapeProperties spPr = getSpPr();\r
+        if(color == null) {\r
+            if(spPr.isSetLn() && spPr.getLn().isSetSolidFill()) spPr.getLn().unsetSolidFill();\r
+        }\r
+        else {\r
+            CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr.addNewLn();\r
+\r
+            CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();\r
+            rgb.setVal(new byte[]{(byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue()});\r
+\r
+            CTSolidColorFillProperties fill = ln.isSetSolidFill() ? ln.getSolidFill() : ln.addNewSolidFill();\r
+            fill.setSrgbClr(rgb);\r
+        }\r
+    }\r
+\r
+    public Color getLineColor(){\r
+        CTShapeProperties spPr = getSpPr();\r
+        if(!spPr.isSetLn() || !spPr.getLn().isSetSolidFill()) return null;\r
+\r
+        CTSRgbColor rgb = spPr.getLn().getSolidFill().getSrgbClr();\r
+        byte[] val = rgb.getVal();\r
+        return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]);\r
+    }\r
+\r
+    public void setLineWidth(double width){\r
+        CTShapeProperties spPr = getSpPr();\r
+        if(width == 0.) {\r
+            if(spPr.isSetLn()) spPr.getLn().unsetW();\r
+        }\r
+        else {\r
+            CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr.addNewLn();\r
+            ln.setW(Units.toEMU(width));\r
+        }\r
+    }\r
+\r
+    public double getLineWidth(){\r
+        CTShapeProperties spPr = getSpPr();\r
+        CTLineProperties ln = spPr.getLn();\r
+        if(ln == null || !ln.isSetW()) return 0;\r
+\r
+        return Units.toPoints(ln.getW());\r
+    }\r
+\r
+    public void setLineDash(LineDash dash){\r
+        CTShapeProperties spPr = getSpPr();\r
+        if(dash == null) {\r
+            if(spPr.isSetLn()) spPr.getLn().unsetPrstDash();\r
+        }\r
+        else {\r
+            CTPresetLineDashProperties val = CTPresetLineDashProperties.Factory.newInstance();\r
+            val.setVal(STPresetLineDashVal.Enum.forInt(dash.ordinal() + 1));\r
+            CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr.addNewLn();\r
+            ln.setPrstDash(val);\r
+        }\r
+    }\r
+\r
+    public LineDash getLineDash(){\r
+        CTShapeProperties spPr = getSpPr();\r
+        CTLineProperties ln = spPr.getLn();\r
+        if(ln == null || !ln.isSetPrstDash()) return null;\r
+\r
+        CTPresetLineDashProperties dash = ln.getPrstDash();\r
+        return LineDash.values()[dash.getVal().intValue() - 1];\r
+    }\r
+\r
+    public void setLineCap(LineCap cap){\r
+        CTShapeProperties spPr = getSpPr();\r
+        if(cap == null) {\r
+            if(spPr.isSetLn()) spPr.getLn().unsetCap();\r
+        }\r
+        else {\r
+            CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr.addNewLn();\r
+            ln.setCap(STLineCap.Enum.forInt(cap.ordinal() + 1));\r
+        }\r
+    }\r
+\r
+    public LineCap getLineCap(){\r
+        CTShapeProperties spPr = getSpPr();\r
+        CTLineProperties ln = spPr.getLn();\r
+        if(ln == null || !ln.isSetCap()) return null;\r
+\r
+        return LineCap.values()[ln.getCap().intValue() - 1];\r
+    }\r
+\r
+}\r
index 29af4941ec4f37fea2dfc27628812659c5b856ec..f864344d7148c9c88950e941d694a861cc869afe 100644 (file)
 ==================================================================== */
 package org.apache.poi.xslf.usermodel;
 
-import org.apache.poi.sl.usermodel.Notes;
+import org.apache.poi.POIXMLDocumentPart;
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.apache.poi.openxml4j.opc.PackageRelationship;
+import org.apache.poi.openxml4j.opc.PackagePartName;
+import org.apache.poi.openxml4j.opc.TargetMode;
 import org.apache.poi.sl.usermodel.Slide;
-import org.apache.poi.sl.usermodel.SlideShow;
-import org.apache.poi.util.Internal;
+import org.apache.poi.util.Beta;
+import org.apache.xmlbeans.XmlException;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupShapeProperties;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupTransform2D;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
+import org.openxmlformats.schemas.presentationml.x2006.main.CTCommonSlideData;
+import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape;
+import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShapeNonVisual;
 import org.openxmlformats.schemas.presentationml.x2006.main.CTSlide;
-import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideIdListEntry;
-
-public class XSLFSlide extends XSLFSheet implements Slide {
-       private CTSlide slide;
-       private CTSlideIdListEntry slideId;
-    private XSLFCommonSlideData data;
-       
-       public XSLFSlide(CTSlide slide, CTSlideIdListEntry slideId, SlideShow parent) {
-               super(parent);
-               this.slide = slide;
-               this.slideId = slideId;
-        this.data = new XSLFCommonSlideData(slide.getCSld());
-       }
-       
-       /**
-        * While developing only!
-        */
-    @Internal
-       public CTSlide _getCTSlide() {
-               return slide;
-       }
-       /**
-        * While developing only!
-        */
-    @Internal
-       public CTSlideIdListEntry _getCTSlideId() {
-               return slideId;
-       }
-       
-
-       public boolean getFollowMasterBackground() {
-               // TODO Auto-generated method stub
-               return false;
-       }
-
-       public boolean getFollowMasterColourScheme() {
-               // TODO Auto-generated method stub
-               return false;
-       }
-
-       public boolean getFollowMasterObjects() {
-               // TODO Auto-generated method stub
-               return false;
-       }
-
-       public Notes getNotes() {
-               // TODO Auto-generated method stub
-               return null;
-       }
+import org.openxmlformats.schemas.presentationml.x2006.main.SldDocument;
+import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideMasterIdListEntry;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.regex.Pattern;
+
+@Beta
+public final class XSLFSlide extends XSLFSheet {
+       private final CTSlide _slide;
+    private XSLFSlideLayout _layout;
+
+    /**
+     * Create a new slide
+     */
+    XSLFSlide() {
+        super();
+        _slide = prototype();
+    }
 
-       public void setFollowMasterBackground(boolean follow) {
-               // TODO Auto-generated method stub
+    /**
+     * Construct a SpreadsheetML drawing from a package part
+     *
+     * @param part the package part holding the drawing data,
+     * the content type must be <code>application/vnd.openxmlformats-officedocument.drawing+xml</code>
+     * @param rel  the package relationship holding this drawing,
+     * the relationship type must be http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing
+     */
+    XSLFSlide(PackagePart part, PackageRelationship rel) throws IOException, XmlException {
+        super(part, rel);
+
+        SldDocument doc =
+            SldDocument.Factory.parse(getPackagePart().getInputStream());
+        _slide = doc.getSld();
+    }
 
-       }
 
-       public void setFollowMasterColourScheme(boolean follow) {
-               // TODO Auto-generated method stub
+    private static CTSlide prototype(){
+        CTSlide ctSlide = CTSlide.Factory.newInstance();
+        CTCommonSlideData cSld = ctSlide.addNewCSld();
+        CTGroupShape spTree = cSld.addNewSpTree();
+
+        CTGroupShapeNonVisual nvGrpSpPr = spTree.addNewNvGrpSpPr();
+        CTNonVisualDrawingProps cnvPr = nvGrpSpPr.addNewCNvPr();
+        cnvPr.setId(1);
+        cnvPr.setName("");
+        nvGrpSpPr.addNewCNvGrpSpPr();
+        nvGrpSpPr.addNewNvPr();
+
+        CTGroupShapeProperties grpSpr = spTree.addNewGrpSpPr();
+        CTGroupTransform2D xfrm = grpSpr.addNewXfrm();
+        CTPoint2D off = xfrm.addNewOff();
+        off.setX(0);
+        off.setY(0);
+        CTPositiveSize2D ext = xfrm.addNewExt();
+        ext.setCx(0);
+        ext.setCy(0);
+        CTPoint2D choff = xfrm.addNewChOff();
+        choff.setX(0);
+        choff.setY(0);
+        CTPositiveSize2D chExt = xfrm.addNewChExt();
+        chExt.setCx(0);
+        chExt.setCy(0);
+        ctSlide.addNewClrMapOvr().addNewMasterClrMapping();
+        return ctSlide;
+    }
 
+    @Override
+       public CTSlide getXmlObject() {
+               return _slide;
        }
 
-       public void setFollowMasterObjects(boolean follow) {
-               // TODO Auto-generated method stub
+    @Override
+    protected String getRootElementName(){
+        return "sld";        
+    }
 
-       }
+    public XSLFSlideMaster getMasterSheet(){
+        return getSlideLayout().getSlideMaster();
+    }
 
-       public void setNotes(Notes notes) {
-               // TODO Auto-generated method stub
+    public XSLFSlideLayout getSlideLayout(){
+        if(_layout == null){
+             for (POIXMLDocumentPart p : getRelations()) {
+                if (p instanceof XSLFSlideLayout){
+                   _layout = (XSLFSlideLayout)p;
+                }
+            }
+        }
+        if(_layout == null) {
+            throw new IllegalArgumentException("SlideLayout was not found for " + this.toString());
+        }
+        return _layout;
+    }
 
-       }
+    public void setFollowMasterBackground(boolean value){
+        _slide.setShowMasterSp(value);    
+    }
 
-    public XSLFCommonSlideData getCommonSlideData() {
-        return data;
+    public boolean getFollowMasterBackground(){
+        return !_slide.isSetShowMasterSp() || _slide.getShowMasterSp();    
     }
+
 }
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideLayout.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideLayout.java
new file mode 100755 (executable)
index 0000000..871ece5
--- /dev/null
@@ -0,0 +1,103 @@
+/* ====================================================================
+   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.POIXMLDocumentPart;
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.apache.poi.openxml4j.opc.PackageRelationship;
+import org.apache.poi.util.Beta;
+import org.apache.poi.util.Internal;
+import org.apache.xmlbeans.XmlException;
+import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideLayout;
+import org.openxmlformats.schemas.presentationml.x2006.main.SldLayoutDocument;
+import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideMaster;
+
+import java.io.IOException;
+
+@Beta
+public class XSLFSlideLayout extends XSLFSheet {
+    private CTSlideLayout _layout;
+    private XSLFSlideMaster _master;
+
+    XSLFSlideLayout() {
+        super();
+        _layout = CTSlideLayout.Factory.newInstance();
+    }
+
+    public XSLFSlideLayout(PackagePart part, PackageRelationship rel) throws IOException, XmlException {
+        super(part, rel);
+        SldLayoutDocument doc =
+            SldLayoutDocument.Factory.parse(getPackagePart().getInputStream());
+        _layout = doc.getSldLayout();
+    }
+
+
+    public String getName(){
+        return _layout.getCSld().getName();
+    }
+
+    /**
+     * While developing only!
+     */
+    @Internal
+    public CTSlideLayout getXmlObject() {
+        return _layout;
+    }
+
+    @Override
+    protected String getRootElementName(){
+        return "sldLayout";
+    }
+
+    /**
+     * Slide master object associated with this layout.
+     * <p>
+     *  Within a slide master slide are contained all elements
+     * that describe the objects and their corresponding formatting
+     * for within a presentation slide.
+     * </p>
+     * <p>
+     * Within a slide master slide are two main elements.
+     * The cSld element specifies the common slide elements such as shapes and
+     * their attached text bodies. Then the txStyles element specifies the
+     * formatting for the text within each of these shapes. The other properties
+     * within a slide master slide specify other properties for within a presentation slide
+     * such as color information, headers and footers, as well as timing and
+     * transition information for all corresponding presentation slides.
+     * </p>
+     *
+     * @return slide master. Never null.
+     * @throws IllegalStateException if slide master was not found
+     */
+    public XSLFSlideMaster getSlideMaster(){
+        if(_master == null){
+            for (POIXMLDocumentPart p : getRelations()) {
+               if (p instanceof XSLFSlideMaster){
+                  _master = (XSLFSlideMaster)p;
+               }
+           }
+        }
+        if(_master == null) {
+            throw new IllegalStateException("SlideMaster was not found for " + this.toString());
+        }
+        return _master;
+    }
+
+    public XMLSlideShow getSlideShow() {
+        return (XMLSlideShow)getParent().getParent();
+    }
+}
\ No newline at end of file
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideMaster.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideMaster.java
new file mode 100755 (executable)
index 0000000..d7c8640
--- /dev/null
@@ -0,0 +1,90 @@
+/* ====================================================================
+   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.POIXMLDocumentPart;
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.apache.poi.openxml4j.opc.PackageRelationship;
+import org.apache.poi.sl.usermodel.MasterSheet;
+import org.apache.poi.util.Beta;
+import org.apache.xmlbeans.XmlException;
+import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideMaster;
+import org.openxmlformats.schemas.presentationml.x2006.main.SldMasterDocument;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+* Slide master object associated with this layout.
+* <p>
+*  Within a slide master slide are contained all elements
+* that describe the objects and their corresponding formatting
+* for within a presentation slide.
+* </p>
+* <p>
+* Within a slide master slide are two main elements.
+* The cSld element specifies the common slide elements such as shapes and
+* their attached text bodies. Then the txStyles element specifies the
+* formatting for the text within each of these shapes. The other properties
+* within a slide master slide specify other properties for within a presentation slide
+* such as color information, headers and footers, as well as timing and
+* transition information for all corresponding presentation slides.
+* </p>
+ *
+ * @author Yegor Kozlov
+*/
+@Beta
+ public class XSLFSlideMaster extends XSLFSheet {
+       private CTSlideMaster _slide;
+    private Map<String, XSLFSlideLayout> _layouts;
+
+    XSLFSlideMaster() {
+        super();
+        _slide = CTSlideMaster.Factory.newInstance();
+    }
+
+    protected XSLFSlideMaster(PackagePart part, PackageRelationship rel) throws IOException, XmlException {
+        super(part, rel);
+        SldMasterDocument doc =
+            SldMasterDocument.Factory.parse(getPackagePart().getInputStream());
+        _slide = doc.getSldMaster();
+    }
+
+    @Override
+       public CTSlideMaster getXmlObject() {
+               return _slide;
+       }
+
+    @Override
+    protected String getRootElementName(){
+        return "sldMaster";
+    }
+
+    public XSLFSlideLayout getLayout(String name){
+        if(_layouts == null){
+            _layouts = new HashMap<String, XSLFSlideLayout>();
+            for (POIXMLDocumentPart p : getRelations()) {
+                if (p instanceof XSLFSlideLayout){
+                    XSLFSlideLayout layout = (XSLFSlideLayout)p;
+                    _layouts.put(layout.getName().toLowerCase(), layout);
+                }
+            }
+        }
+        return _layouts.get(name);
+    }
+}
\ No newline at end of file
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextBox.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextBox.java
new file mode 100755 (executable)
index 0000000..c009f54
--- /dev/null
@@ -0,0 +1,97 @@
+/*\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.sl.usermodel.ShapeContainer;\r
+import org.apache.poi.util.Beta;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTApplicationNonVisualDrawingProps;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTShapeNonVisual;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;\r
+\r
+\r
+/**\r
+ * @author Yegor Kozlov\r
+ */\r
+@Beta\r
+public class XSLFTextBox extends XSLFAutoShape {\r
+\r
+    /*package*/ XSLFTextBox(CTShape shape, XSLFSheet sheet){\r
+        super(shape, sheet);\r
+    }\r
+\r
+    /**\r
+     *\r
+     * @param shapeId   1-based shapeId\r
+     */\r
+    static CTShape prototype(int shapeId){\r
+        CTShape ct = CTShape.Factory.newInstance();\r
+        CTShapeNonVisual nvSpPr = ct.addNewNvSpPr();\r
+        CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr();\r
+        cnv.setName("TextBox " + shapeId);\r
+        cnv.setId(shapeId + 1);\r
+        nvSpPr.addNewCNvSpPr().setTxBox(true);\r
+        nvSpPr.addNewNvPr();\r
+        CTShapeProperties spPr = ct.addNewSpPr();\r
+        CTPresetGeometry2D prst = spPr.addNewPrstGeom();\r
+        prst.setPrst(STShapeType.RECT);\r
+        prst.addNewAvLst();\r
+        CTTextBody txBody = ct.addNewTxBody();\r
+        txBody.addNewBodyPr();\r
+        txBody.addNewLstStyle();\r
+\r
+        return ct;\r
+    }\r
+\r
+    /**\r
+     * Specifies that the corresponding shape should be represented by the generating application\r
+     * as a placeholder. When a shape is considered a placeholder by the generating application\r
+     * it can have special properties to alert the user that they may enter content into the shape.\r
+     * Different types of placeholders are allowed and can be specified by using the placeholder\r
+     * type attribute for this element\r
+     *\r
+     * @param placeholder\r
+     */\r
+    public void setPlaceholder(Placeholder placeholder){\r
+        CTShape sh =  (CTShape)getXmlObject();\r
+        CTApplicationNonVisualDrawingProps nv = sh.getNvSpPr().getNvPr();\r
+        if(placeholder == null) {\r
+            if(nv.isSetPh()) nv.unsetPh();\r
+        } else {\r
+            nv.addNewPh().setType(STPlaceholderType.Enum.forInt(placeholder.ordinal() + 1));\r
+        }\r
+    }\r
+\r
+    public Placeholder getPlaceholder(){\r
+        CTShape sh =  (CTShape)getXmlObject();\r
+        CTPlaceholder ph = sh.getNvSpPr().getNvPr().getPh();\r
+        if(ph == null) return null;\r
+        else {\r
+            int val = ph.getType().intValue();\r
+            return Placeholder.values()[val - 1];\r
+        }\r
+    }\r
+}
\ No newline at end of file
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java
new file mode 100755 (executable)
index 0000000..9317298
--- /dev/null
@@ -0,0 +1,334 @@
+/* ====================================================================\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.util.Beta;\r
+import org.apache.poi.util.Internal;\r
+import org.apache.poi.util.Units;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextSpacing;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+\r
+/**\r
+ * Represents a paragraph of text within the containing text body.\r
+ * The paragraph is the highest level text separation mechanism.\r
+ *\r
+ * @author Yegor Kozlov\r
+ * @since POI-3.8\r
+ */\r
+@Beta\r
+public class XSLFTextParagraph implements Iterable<XSLFTextRun>{\r
+    private final CTTextParagraph _p;\r
+    private final List<XSLFTextRun> _runs;\r
+\r
+    XSLFTextParagraph(CTTextParagraph p){\r
+        _p = p;\r
+        _runs = new ArrayList<XSLFTextRun>();\r
+        for (CTRegularTextRun r : _p.getRList()) {\r
+            _runs.add(new XSLFTextRun(r));\r
+        }\r
+    }\r
+\r
+    public String getText(){\r
+        StringBuilder out = new StringBuilder();\r
+        for (CTRegularTextRun r : _p.getRList()) {\r
+            out.append(r.getT());\r
+        }\r
+        return out.toString();\r
+    }\r
+\r
+    @Internal\r
+    public CTTextParagraph getXmlObject(){\r
+        return _p;\r
+    }\r
+\r
+    public List<XSLFTextRun> getTextRuns(){\r
+        return _runs;\r
+    }\r
+\r
+    public Iterator<XSLFTextRun> iterator(){\r
+        return _runs.iterator();\r
+    }\r
+\r
+    public XSLFTextRun addNewTextRun(){\r
+        CTRegularTextRun r = _p.addNewR();\r
+        XSLFTextRun run = new XSLFTextRun(r);\r
+        _runs.add(run);\r
+        return run;\r
+    }\r
+\r
+    public void addLineBreak(){\r
+        _p.addNewBr();\r
+    }\r
+\r
+    /**\r
+     * Returns the alignment that is applied to the paragraph.\r
+     *\r
+     * If this attribute is omitted, then a value of left is implied.\r
+     * @return ??? alignment that is applied to the paragraph\r
+     */\r
+    public TextAlign getTextAlign(){\r
+        CTTextParagraphProperties pr = _p.getPPr();\r
+        if(pr == null || !pr.isSetAlgn()) return TextAlign.LEFT;\r
+\r
+        return TextAlign.values()[pr.getAlgn().intValue() - 1];\r
+    }\r
+\r
+    /**\r
+     * Specifies the alignment that is to be applied to the paragraph.\r
+     * Possible values for this include left, right, centered, justified and distributed,\r
+     * see {@link org.apache.poi.xslf.usermodel.TextAlign}.\r
+     *\r
+     * @param align text align\r
+     */\r
+    public void setTextAlign(TextAlign align){\r
+        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();\r
+        if(align == null) {\r
+            if(pr.isSetAlgn()) pr.unsetAlgn();\r
+        } else {\r
+            pr.setAlgn(STTextAlignType.Enum.forInt(align.ordinal() + 1));\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Specifies the indent size that will be applied to the first line of text in the paragraph.\r
+     *\r
+     * @param value the indent in points. The value of -1 unsets the indent attribute\r
+     * from the underlying xml bean.\r
+     */\r
+    public void setIndent(double value){\r
+        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();\r
+        if(value == -1) {\r
+            if(pr.isSetIndent()) pr.unsetIndent();\r
+        } else {\r
+            pr.setIndent(Units.toEMU(value));\r
+        }\r
+    }\r
+\r
+    /**\r
+     *\r
+     * @return the indent applied to the first line of text in the paragraph.\r
+     */\r
+    public double getIndent(){\r
+        CTTextParagraphProperties pr = _p.getPPr();\r
+        if(pr == null || !pr.isSetIndent()) return 0;\r
+\r
+        return Units.toPoints(pr.getIndent());\r
+    }\r
+\r
+    /**\r
+     * Specifies the left margin of the paragraph. This is specified in addition to the text body\r
+     * inset and applies only to this text paragraph. That is the text body Inset and the LeftMargin\r
+     * attributes are additive with respect to the text position.\r
+     *\r
+     * @param value the left margin of the paragraph\r
+     */\r
+    public void setLeftMargin(double value){\r
+        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();\r
+        pr.setMarL(Units.toEMU(value));\r
+    }\r
+\r
+    /**\r
+     *\r
+     * @return the left margin of the paragraph\r
+     */\r
+    public double getLeftMargin(){\r
+        CTTextParagraphProperties pr = _p.getPPr();\r
+        if(pr == null || !pr.isSetMarL()) return 0;\r
+\r
+        return Units.toPoints(pr.getMarL());\r
+    }\r
+\r
+    /**\r
+     * This element specifies the vertical line spacing that is to be used within a paragraph.\r
+     * This may be specified in two different ways, percentage spacing and font point spacing:\r
+     * <p>\r
+     * If linespacing >= 0, then linespacing is a percentage of normal line height\r
+     * If linespacing < 0, the absolute value of linespacing is the spacing in points\r
+     * </p>\r
+     * Examples:\r
+     * <pre><code>\r
+     *      // spacing will be 120% of the size of the largest text on each line\r
+     *      paragraph.setLineSpacing(120);\r
+     *\r
+     *      // spacing will be 200% of the size of the largest text on each line\r
+     *      paragraph.setLineSpacing(200);\r
+     *\r
+     *      // spacing will be 48 points\r
+     *      paragraph.setLineSpacing(-48.0);\r
+     * </code></pre>\r
+     * \r
+     * @param linespacing the vertical line spacing\r
+     */\r
+    public void setLineSpacing(double linespacing){\r
+        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();\r
+        CTTextSpacing spc = CTTextSpacing.Factory.newInstance();\r
+        if(linespacing >= 0) spc.addNewSpcPct().setVal((int)(linespacing*1000));\r
+        else spc.addNewSpcPts().setVal((int)(-linespacing*100));\r
+        pr.setLnSpc(spc);\r
+    }\r
+\r
+    /**\r
+     * Returns the vertical line spacing that is to be used within a paragraph.\r
+     * This may be specified in two different ways, percentage spacing and font point spacing:\r
+     * <p>\r
+     * If linespacing >= 0, then linespacing is a percentage of normal line height.\r
+     * If linespacing < 0, the absolute value of linespacing is the spacing in points\r
+     * </p>\r
+     *\r
+     * @return the vertical line spacing.\r
+     */\r
+    public double getLineSpacing(){\r
+        CTTextParagraphProperties pr = _p.getPPr();\r
+        if(pr == null || !pr.isSetLnSpc()) return 100; // TODO fetch from master\r
+\r
+        CTTextSpacing spc = pr.getLnSpc();\r
+        if(spc.isSetSpcPct()) return spc.getSpcPct().getVal()*0.001;\r
+        else if (spc.isSetSpcPts()) return -spc.getSpcPts().getVal()*0.01;\r
+        else return 100;\r
+    }\r
+\r
+    /**\r
+     * Set the amount of vertical white space that will be present before the paragraph.\r
+     * This space is specified in either percentage or points:\r
+     * <p>\r
+     * If spaceBefore >= 0, then space is a percentage of normal line height.\r
+     * If spaceBefore < 0, the absolute value of linespacing is the spacing in points\r
+     * </p>\r
+     * Examples:\r
+     * <pre><code>\r
+     *      // The paragraph will be formatted to have a spacing before the paragraph text.\r
+     *      // The spacing will be 200% of the size of the largest text on each line\r
+     *      paragraph.setSpaceBefore(200);\r
+     *\r
+     *      // The spacing will be a size of 48 points\r
+     *      paragraph.setSpaceBefore(-48.0);\r
+     * </code></pre>\r
+     *\r
+     * @param spaceBefore the vertical white space before the paragraph.\r
+     */\r
+    public void setSpaceBefore(double spaceBefore){\r
+        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();\r
+        CTTextSpacing spc = CTTextSpacing.Factory.newInstance();\r
+        if(spaceBefore >= 0) spc.addNewSpcPct().setVal((int)(spaceBefore*1000));\r
+        else spc.addNewSpcPts().setVal((int)(-spaceBefore*100));\r
+        pr.setSpcBef(spc);\r
+    }\r
+\r
+    /**\r
+     * The amount of vertical white space before the paragraph\r
+     * This may be specified in two different ways, percentage spacing and font point spacing:\r
+     * <p>\r
+     * If spaceBefore >= 0, then space is a percentage of normal line height.\r
+     * If spaceBefore < 0, the absolute value of linespacing is the spacing in points\r
+     * </p>\r
+     *\r
+     * @return the vertical white space before the paragraph\r
+     */\r
+    public double getSpaceBefore(){\r
+        CTTextParagraphProperties pr = _p.getPPr();\r
+        if(pr == null || !pr.isSetSpcBef()) return 0;  // TODO fetch from master\r
+\r
+        CTTextSpacing spc = pr.getSpcBef();\r
+        if(spc.isSetSpcPct()) return spc.getSpcPct().getVal()*0.001;\r
+        else if (spc.isSetSpcPts()) return -spc.getSpcPts().getVal()*0.01;\r
+        else return 0;\r
+    }\r
+\r
+    /**\r
+     * Set the amount of vertical white space that will be present after the paragraph.\r
+     * This space is specified in either percentage or points:\r
+     * <p>\r
+     * If spaceAfter >= 0, then space is a percentage of normal line height.\r
+     * If spaceAfter < 0, the absolute value of linespacing is the spacing in points\r
+     * </p>\r
+     * Examples:\r
+     * <pre><code>\r
+     *      // The paragraph will be formatted to have a spacing after the paragraph text.\r
+     *      // The spacing will be 200% of the size of the largest text on each line\r
+     *      paragraph.setSpaceAfter(200);\r
+     *\r
+     *      // The spacing will be a size of 48 points\r
+     *      paragraph.setSpaceAfter(-48.0);\r
+     * </code></pre>\r
+     *\r
+     * @param spaceAfter the vertical white space after the paragraph.\r
+     */\r
+    public void setSpaceAfter(double spaceAfter){\r
+        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();\r
+        CTTextSpacing spc = CTTextSpacing.Factory.newInstance();\r
+        if(spaceAfter >= 0) spc.addNewSpcPct().setVal((int)(spaceAfter*1000));\r
+        else spc.addNewSpcPts().setVal((int)(-spaceAfter*100));\r
+        pr.setSpcAft(spc);\r
+    }\r
+\r
+    /**\r
+     * The amount of vertical white space after the paragraph\r
+     * This may be specified in two different ways, percentage spacing and font point spacing:\r
+     * <p>\r
+     * If spaceBefore >= 0, then space is a percentage of normal line height.\r
+     * If spaceBefore < 0, the absolute value of linespacing is the spacing in points\r
+     * </p>\r
+     *\r
+     * @return the vertical white space after the paragraph\r
+     */\r
+    public double getSpaceAfter(){\r
+        CTTextParagraphProperties pr = _p.getPPr();\r
+        if(pr == null || !pr.isSetSpcAft()) return 0; // TODO fetch from master\r
+\r
+        CTTextSpacing spc = pr.getSpcAft();\r
+        if(spc.isSetSpcPct()) return spc.getSpcPct().getVal()*0.001;\r
+        else if (spc.isSetSpcPts()) return -spc.getSpcPts().getVal()*0.01;\r
+        else return 0;\r
+    }\r
+\r
+    /**\r
+     * Specifies the particular level text properties that this paragraph will follow.\r
+     * The value for this attribute formats the text according to the corresponding level\r
+     * paragraph properties defined in the SlideMaster.\r
+     *\r
+     * @param level the level (0 ... 4)\r
+     */\r
+    public void setLevel(int level){\r
+        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();\r
+\r
+        pr.setLvl(level);\r
+    }\r
+\r
+    /**\r
+     *\r
+     * @return the text level of this paragraph. Default is 0.\r
+     */\r
+    public int getLevel(){\r
+        CTTextParagraphProperties pr = _p.getPPr();\r
+        if(pr == null) return 0;\r
+\r
+        return pr.getLvl();\r
+\r
+    }\r
+\r
+    @Override\r
+    public String toString(){\r
+        return "[" + getClass() + "]" + getText();\r
+    }\r
+}\r
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java
new file mode 100755 (executable)
index 0000000..8596491
--- /dev/null
@@ -0,0 +1,202 @@
+/* ====================================================================\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.util.Beta;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType;\r
+\r
+import java.awt.*;\r
+\r
+/**\r
+ * Represents a run of text within the containing text body. The run element is the\r
+ * lowest level text separation mechanism within a text body.\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+@Beta\r
+public class XSLFTextRun {\r
+    private final CTRegularTextRun _r;\r
+\r
+    XSLFTextRun(CTRegularTextRun r){\r
+        _r = r;\r
+    }\r
+\r
+    public String getText(){\r
+        return _r.getT();\r
+    }\r
+\r
+    public void setText(String text){\r
+        _r.setT(text);\r
+    }\r
+\r
+    public CTRegularTextRun getXmlObject(){\r
+        return _r;\r
+    }\r
+\r
+    public void setFontColor(Color color){\r
+        CTTextCharacterProperties rPr = getRpR();\r
+        CTSolidColorFillProperties fill = rPr.isSetSolidFill() ? rPr.getSolidFill() : rPr.addNewSolidFill();\r
+        CTSRgbColor clr = fill.isSetSrgbClr() ? fill.getSrgbClr() : fill.addNewSrgbClr();\r
+        clr.setVal(new byte[]{(byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue()});\r
+    }\r
+\r
+    /**\r
+     *\r
+     * @param fontSize  font size in points.\r
+     * The value of <code>-1</code> unsets the Sz attribyte from the underlying xml bean\r
+     */\r
+    public void setFontSize(double fontSize){\r
+        CTTextCharacterProperties rPr = getRpR();\r
+        if(fontSize == -1.0) {\r
+            if(rPr.isSetSz()) rPr.unsetSz();\r
+        } else {\r
+            rPr.setSz((int)(100*fontSize));\r
+        }\r
+    }\r
+\r
+    /**\r
+     * @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
+\r
+        return _r.getRPr().getSz()*0.01;\r
+    }\r
+\r
+    /**\r
+     * Specifies the typeface, or name of the font that is to be used for this text run.\r
+     *\r
+     * @param typeface  the font to apply to this text run.\r
+     * The value of <code>null</code> unsets the Typeface attrubute from the underlying xml.\r
+     */\r
+    public void setFontFamily(String typeface){\r
+        setFontFamily(typeface, (byte)-1, (byte)-1, false);\r
+    }\r
+\r
+    public void setFontFamily(String typeface, byte charset, byte pictAndFamily, boolean isSymbol){\r
+        CTTextCharacterProperties rPr = getRpR();\r
+\r
+        if(typeface == null){\r
+            if(rPr.isSetLatin()) rPr.unsetLatin();\r
+            if(rPr.isSetCs()) rPr.unsetCs();\r
+            if(rPr.isSetSym()) rPr.unsetSym();\r
+        } else {\r
+            if(isSymbol){\r
+                CTTextFont font = rPr.isSetSym() ? rPr.getSym() : rPr.addNewSym();\r
+                font.setTypeface(typeface);\r
+            } else {\r
+                CTTextFont latin = rPr.isSetLatin() ? rPr.getLatin() : rPr.addNewLatin();\r
+                latin.setTypeface(typeface);\r
+                if(charset != -1) latin.setCharset(charset);\r
+                if(pictAndFamily != -1) latin.setPitchFamily(pictAndFamily);\r
+            }\r
+        }\r
+    }\r
+\r
+    /**\r
+     * @return  font family or null if niot set\r
+     */\r
+    public String getFontFamily(){\r
+        if(!_r.isSetRPr() || !_r.getRPr().isSetLatin()) return null;\r
+\r
+        return _r.getRPr().getLatin().getTypeface();\r
+    }\r
+\r
+    /**\r
+     * Specifies whether a run of text will be formatted as strikethrough text.\r
+     *\r
+     * @param strike whether a run of text will be formatted as strikethrough text.\r
+     */\r
+    public void setStrikethrough(boolean strike){\r
+        getRpR().setStrike(strike ? STTextStrikeType.SNG_STRIKE : STTextStrikeType.NO_STRIKE);\r
+    }\r
+\r
+    /**\r
+     * @return whether a run of text will be formatted as strikethrough text. Default is false.\r
+     */\r
+    public boolean isStrikethrough(){\r
+        if(!_r.isSetRPr()) return false;\r
+\r
+        return _r.getRPr().getStrike() == STTextStrikeType.SNG_STRIKE;\r
+    }\r
+\r
+    /**\r
+     * Specifies whether this run of text will be formatted as bold text\r
+     *\r
+     * @param bold whether this run of text will be formatted as bold text\r
+     */\r
+    public void setBold(boolean bold){\r
+        getRpR().setB(bold);\r
+    }\r
+\r
+    /**\r
+     * @return whether this run of text is formatted as bold text\r
+     */\r
+    public boolean isBold(){\r
+        if(!_r.isSetRPr()) return false;\r
+\r
+        return _r.getRPr().getB();\r
+    }\r
+\r
+    /**\r
+     * @param italic whether this run of text is formatted as italic text\r
+     */\r
+    public void setItalic(boolean italic){\r
+        getRpR().setI(italic);\r
+    }\r
+\r
+    /**\r
+     * @return whether this run of text is formatted as italic text\r
+     */\r
+    public boolean isItalic(){\r
+        if(!_r.isSetRPr()) return false;\r
+\r
+        return _r.getRPr().getI();\r
+    }\r
+\r
+    /**\r
+     * @param underline whether this run of text is formatted as underlined text\r
+     */\r
+    public void setUnderline(boolean underline){\r
+        getRpR().setU(underline ? STTextUnderlineType.SNG : STTextUnderlineType.NONE);\r
+    }\r
+\r
+    /**\r
+     * @return whether this run of text is formatted as underlined text\r
+     */\r
+    public boolean isUnderline(){\r
+        if(!_r.isSetRPr() || !_r.getRPr().isSetU()) return false;\r
+\r
+        return _r.getRPr().getU() != STTextUnderlineType.NONE;\r
+    }\r
+\r
+    protected CTTextCharacterProperties getRpR(){\r
+        return _r.isSetRPr() ? _r.getRPr() : _r.addNewRPr();\r
+    }\r
+\r
+    @Override\r
+    public String toString(){\r
+        return "[" + getClass() + "]" + getText();\r
+    }\r
+    \r
+}
\ No newline at end of file
index 0b326c0fdf8fcfefb45fa31966adc18683e5cac7..b6966d06ef5c6008f2bb1e6489c06a612bcf8a37 100644 (file)
@@ -41,7 +41,7 @@ public class XSLFTestDataSamples {
     public static XMLSlideShow writeOutAndReadBack(XMLSlideShow doc) {\r
         try {\r
             ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);\r
-            doc._getXSLFSlideShow().write(baos);\r
+            doc.write(baos);\r
             ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());\r
             return new XMLSlideShow(OPCPackage.open(bais));\r
         } catch (Exception e) {\r
diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java
new file mode 100755 (executable)
index 0000000..69be4b7
--- /dev/null
@@ -0,0 +1,267 @@
+/* ====================================================================\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 org.apache.poi.util.Units;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType;\r
+\r
+/**\r
+ * @author Yegor Kozlov\r
+ */\r
+public class TestXSLFAutoShape extends TestCase {\r
+    public void testTextBodyProperies() {\r
+        XMLSlideShow ppt = new XMLSlideShow();\r
+        XSLFSlide slide = ppt.createSlide();\r
+\r
+        XSLFAutoShape shape = slide.createAutoShape();\r
+        shape.addNewTextParagraph().addNewTextRun().setText("POI");\r
+\r
+        // margins\r
+        assertEquals(-1., shape.getMarginBottom());\r
+        assertEquals(-1., shape.getMarginTop());\r
+        assertEquals(-1., shape.getMarginLeft());\r
+        assertEquals(-1., shape.getMarginRight());\r
+\r
+        shape.setMarginBottom(1.0);\r
+        assertEquals(1.0, shape.getMarginBottom());\r
+        shape.setMarginTop(2.0);\r
+        assertEquals(2.0, shape.getMarginTop());\r
+        shape.setMarginLeft(3.0);\r
+        assertEquals(3.0, shape.getMarginLeft());\r
+        shape.setMarginRight(4.0);\r
+        assertEquals(4.0, shape.getMarginRight());\r
+\r
+        shape.setMarginBottom(0.0);\r
+        assertEquals(0.0, shape.getMarginBottom());\r
+        shape.setMarginTop(0.0);\r
+        assertEquals(0.0, shape.getMarginTop());\r
+        shape.setMarginLeft(0.0);\r
+        assertEquals(0.0, shape.getMarginLeft());\r
+        shape.setMarginRight(0.0);\r
+        assertEquals(0.0, shape.getMarginRight());\r
+\r
+        shape.setMarginBottom(-1);\r
+        assertEquals(-1., shape.getMarginBottom());\r
+        shape.setMarginTop(-1);\r
+        assertEquals(-1.0, shape.getMarginTop());\r
+        shape.setMarginLeft(-1);\r
+        assertEquals(-1.0, shape.getMarginLeft());\r
+        shape.setMarginRight(-1);\r
+        assertEquals(-1.0, shape.getMarginRight());\r
+\r
+        // shape\r
+        assertFalse(shape.getWordWrap());\r
+        shape.setWordWrap(true);\r
+        assertTrue(shape.getWordWrap());\r
+        shape.setWordWrap(false);\r
+        assertFalse(shape.getWordWrap());\r
+\r
+        // shape\r
+        assertEquals(TextAutofit.NORMAL, shape.getTextAutofit());\r
+        shape.setTextAutofit(TextAutofit.NONE);\r
+        assertEquals(TextAutofit.NONE, shape.getTextAutofit());\r
+        shape.setTextAutofit(TextAutofit.SHAPE);\r
+        assertEquals(TextAutofit.SHAPE, shape.getTextAutofit());\r
+        shape.setTextAutofit(TextAutofit.NORMAL);\r
+        assertEquals(TextAutofit.NORMAL, shape.getTextAutofit());\r
+\r
+        assertEquals(VerticalAlignment.TOP, shape.getVerticalAlignment());\r
+        shape.setVerticalAlignment(VerticalAlignment.BOTTOM);\r
+        assertEquals(VerticalAlignment.BOTTOM, shape.getVerticalAlignment());\r
+        shape.setVerticalAlignment(VerticalAlignment.MIDDLE);\r
+        assertEquals(VerticalAlignment.MIDDLE, shape.getVerticalAlignment());\r
+        shape.setVerticalAlignment(null);\r
+        assertEquals(VerticalAlignment.TOP, shape.getVerticalAlignment());\r
+\r
+        assertEquals(TextDirection.HORIZONTAL, shape.getTextDirection());\r
+        shape.setTextDirection(TextDirection.VERTICAL);\r
+        assertEquals(TextDirection.VERTICAL, shape.getTextDirection());\r
+        shape.setTextDirection(null);\r
+        assertEquals(TextDirection.HORIZONTAL, shape.getTextDirection());\r
+    }\r
+\r
+    public void testTextParagraph() {\r
+        XMLSlideShow ppt = new XMLSlideShow();\r
+        XSLFSlide slide = ppt.createSlide();\r
+        assertEquals(0, slide.getShapes().length);\r
+\r
+        XSLFAutoShape shape = slide.createAutoShape();\r
+        assertEquals(0, shape.getTextParagraphs().size());\r
+        XSLFTextParagraph p = shape.addNewTextParagraph();\r
+        assertEquals(1, shape.getTextParagraphs().size());\r
+\r
+        assertEquals(0., p.getIndent());\r
+        assertEquals(0., p.getLeftMargin());\r
+        assertEquals(100., p.getLineSpacing());\r
+        assertEquals(0., p.getSpaceAfter());\r
+        assertEquals(0., p.getSpaceBefore());\r
+        assertEquals(0, p.getLevel());\r
+\r
+        p.setIndent(2.0);\r
+        assertEquals(2.0, p.getIndent());\r
+        assertTrue(p.getXmlObject().getPPr().isSetIndent());\r
+        p.setIndent(-1);\r
+        assertEquals(0.0, p.getIndent());\r
+        assertFalse(p.getXmlObject().getPPr().isSetIndent());\r
+        p.setIndent(10.0);\r
+        assertEquals(10., p.getIndent());\r
+        assertTrue(p.getXmlObject().getPPr().isSetIndent());\r
+\r
+\r
+        assertFalse(p.getXmlObject().getPPr().isSetLvl());\r
+        p.setLevel(1);\r
+        assertEquals(1, p.getLevel());\r
+        assertTrue(p.getXmlObject().getPPr().isSetLvl());\r
+        p.setLevel(2);\r
+        assertEquals(2, p.getLevel());\r
+\r
+        p.setLeftMargin(2.0);\r
+        assertEquals(2.0, p.getLeftMargin());\r
+        assertTrue(p.getXmlObject().getPPr().isSetMarL());\r
+        p.setLeftMargin(10.0);\r
+        assertEquals(10., p.getLeftMargin());\r
+        assertEquals(Units.toEMU(10), p.getXmlObject().getPPr().getMarL());\r
+\r
+\r
+        assertFalse(p.getXmlObject().getPPr().isSetSpcAft());\r
+        p.setSpaceAfter(200);\r
+        assertEquals(200000, p.getXmlObject().getPPr().getSpcAft().getSpcPct().getVal());\r
+        assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPts());\r
+        p.setSpaceAfter(100);\r
+        assertEquals(100000, p.getXmlObject().getPPr().getSpcAft().getSpcPct().getVal());\r
+        assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPts());\r
+        p.setSpaceAfter(-20);\r
+        assertEquals(2000, p.getXmlObject().getPPr().getSpcAft().getSpcPts().getVal());\r
+        assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPct());\r
+        p.setSpaceAfter(-10);\r
+        assertEquals(1000, p.getXmlObject().getPPr().getSpcAft().getSpcPts().getVal());\r
+        assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPct());\r
+\r
+        assertFalse(p.getXmlObject().getPPr().isSetSpcBef());\r
+        p.setSpaceBefore(200);\r
+        assertEquals(200000, p.getXmlObject().getPPr().getSpcBef().getSpcPct().getVal());\r
+        assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPts());\r
+        p.setSpaceBefore(100);\r
+        assertEquals(100000, p.getXmlObject().getPPr().getSpcBef().getSpcPct().getVal());\r
+        assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPts());\r
+        p.setSpaceBefore(-20);\r
+        assertEquals(2000, p.getXmlObject().getPPr().getSpcBef().getSpcPts().getVal());\r
+        assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPct());\r
+        p.setSpaceBefore(-10);\r
+        assertEquals(1000, p.getXmlObject().getPPr().getSpcBef().getSpcPts().getVal());\r
+        assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPct());\r
+\r
+        assertFalse(p.getXmlObject().getPPr().isSetLnSpc());\r
+        p.setLineSpacing(200);\r
+        assertEquals(200000, p.getXmlObject().getPPr().getLnSpc().getSpcPct().getVal());\r
+        assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPts());\r
+        p.setLineSpacing(100);\r
+        assertEquals(100000, p.getXmlObject().getPPr().getLnSpc().getSpcPct().getVal());\r
+        assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPts());\r
+        p.setLineSpacing(-20);\r
+        assertEquals(2000, p.getXmlObject().getPPr().getLnSpc().getSpcPts().getVal());\r
+        assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPct());\r
+        p.setLineSpacing(-10);\r
+        assertEquals(1000, p.getXmlObject().getPPr().getLnSpc().getSpcPts().getVal());\r
+        assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPct());\r
+\r
+        assertFalse(p.getXmlObject().getPPr().isSetAlgn());\r
+        assertEquals(TextAlign.LEFT, p.getTextAlign());\r
+        p.setTextAlign(TextAlign.LEFT);\r
+        assertTrue(p.getXmlObject().getPPr().isSetAlgn());\r
+        assertEquals(TextAlign.LEFT, p.getTextAlign());\r
+        p.setTextAlign(TextAlign.RIGHT);\r
+        assertEquals(TextAlign.RIGHT, p.getTextAlign());\r
+        p.setTextAlign(TextAlign.JUSTIFY);\r
+        assertEquals(TextAlign.JUSTIFY, p.getTextAlign());\r
+        p.setTextAlign(null);\r
+        assertEquals(TextAlign.LEFT, p.getTextAlign());\r
+        assertFalse(p.getXmlObject().getPPr().isSetAlgn());\r
+    }\r
+\r
+    public void testTextRun() {\r
+        XMLSlideShow ppt = new XMLSlideShow();\r
+        XSLFSlide slide = ppt.createSlide();\r
+\r
+        XSLFAutoShape shape = slide.createAutoShape();\r
+        assertEquals(0, shape.getTextParagraphs().size());\r
+        XSLFTextParagraph p = shape.addNewTextParagraph();\r
+        assertEquals(1, shape.getTextParagraphs().size());\r
+        assertEquals(0, p.getTextRuns().size());\r
+        XSLFTextRun r = p.addNewTextRun();\r
+        assertEquals(1, p.getTextRuns().size());\r
+        assertSame(r, p.getTextRuns().get(0));\r
+\r
+        assertEquals(-1.0, r.getFontSize());\r
+        assertFalse(r.getXmlObject().isSetRPr());\r
+        r.setFontSize(10.0);\r
+        assertTrue(r.getXmlObject().isSetRPr());\r
+        assertEquals(1000, r.getXmlObject().getRPr().getSz());\r
+        r.setFontSize(12.5);\r
+        assertEquals(1250, r.getXmlObject().getRPr().getSz());\r
+        r.setFontSize(-1);\r
+        assertFalse(r.getXmlObject().getRPr().isSetSz());\r
+\r
+        assertFalse(r.getXmlObject().getRPr().isSetLatin());\r
+        assertNull(r.getFontFamily());\r
+        r.setFontFamily(null);\r
+        assertNull(r.getFontFamily());\r
+        r.setFontFamily("Arial");\r
+        assertEquals("Arial", r.getFontFamily());\r
+        assertEquals("Arial", r.getXmlObject().getRPr().getLatin().getTypeface());\r
+        r.setFontFamily("Symbol");\r
+        assertEquals("Symbol", r.getFontFamily());\r
+        assertEquals("Symbol", r.getXmlObject().getRPr().getLatin().getTypeface());\r
+        r.setFontFamily(null);\r
+        assertNull(r.getFontFamily());\r
+        assertFalse(r.getXmlObject().getRPr().isSetLatin());\r
+\r
+        assertFalse(r.isStrikethrough());\r
+        assertFalse(r.getXmlObject().getRPr().isSetStrike());\r
+        r.setStrikethrough(true);\r
+        assertTrue(r.isStrikethrough());\r
+        assertEquals(STTextStrikeType.SNG_STRIKE, r.getXmlObject().getRPr().getStrike());\r
+\r
+        assertFalse(r.isBold());\r
+        assertFalse(r.getXmlObject().getRPr().isSetB());\r
+        r.setBold(true);\r
+        assertTrue(r.isBold());\r
+        assertEquals(true, r.getXmlObject().getRPr().getB());\r
+\r
+        assertFalse(r.isItalic());\r
+        assertFalse(r.getXmlObject().getRPr().isSetI());\r
+        r.setItalic(true);\r
+        assertTrue(r.isItalic());\r
+        assertEquals(true, r.getXmlObject().getRPr().getI());\r
+\r
+        assertFalse(r.isUnderline());\r
+        assertFalse(r.getXmlObject().getRPr().isSetU());\r
+        r.setUnderline(true);\r
+        assertTrue(r.isUnderline());\r
+        assertEquals(STTextUnderlineType.SNG, r.getXmlObject().getRPr().getU());\r
+\r
+        r.setText("Apache");\r
+        assertEquals("Apache", r.getText());\r
+        r.setText("POI");\r
+        assertEquals("POI", r.getText());\r
+        r.setText(null);\r
+        assertNull(r.getText());\r
+    }\r
+}
\ No newline at end of file
diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFConnectorShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFConnectorShape.java
new file mode 100644 (file)
index 0000000..8633a32
--- /dev/null
@@ -0,0 +1,117 @@
+/* ====================================================================\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 org.apache.poi.util.Units;\r
+import org.apache.poi.xslf.usermodel.LineCap;\r
+import org.apache.poi.xslf.usermodel.LineDash;\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.STLineEndType;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndWidth;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndLength;\r
+\r
+import java.awt.*;\r
+\r
+/**\r
+ * @author Yegor Kozlov\r
+ */\r
+public class TestXSLFConnectorShape extends TestCase {\r
+\r
+    public void testLineDecorations() {\r
+        XMLSlideShow ppt = new XMLSlideShow();\r
+        XSLFSlide slide = ppt.createSlide();\r
+\r
+        XSLFConnectorShape shape = slide.createConnector();\r
+        assertEquals(1, slide.getShapes().length);\r
+\r
+        assertFalse(shape.getSpPr().getLn().isSetHeadEnd());\r
+        assertFalse(shape.getSpPr().getLn().isSetTailEnd());\r
+\r
+        // line decorations\r
+        assertEquals(LineDecoration.NONE, shape.getLineHeadDecoration());\r
+        assertEquals(LineDecoration.NONE, shape.getLineTailDecoration());\r
+        shape.setLineHeadDecoration(null);\r
+        shape.setLineTailDecoration(null);\r
+        assertEquals(LineDecoration.NONE, shape.getLineHeadDecoration());\r
+        assertEquals(LineDecoration.NONE, shape.getLineTailDecoration());\r
+        assertFalse(shape.getSpPr().getLn().getHeadEnd().isSetType());\r
+        assertFalse(shape.getSpPr().getLn().getTailEnd().isSetType());\r
+\r
+        shape.setLineHeadDecoration(LineDecoration.ARROW);\r
+        shape.setLineTailDecoration(LineDecoration.DIAMOND);\r
+        assertEquals(LineDecoration.ARROW, shape.getLineHeadDecoration());\r
+        assertEquals(LineDecoration.DIAMOND, shape.getLineTailDecoration());\r
+        assertEquals(STLineEndType.ARROW, shape.getSpPr().getLn().getHeadEnd().getType());\r
+        assertEquals(STLineEndType.DIAMOND, shape.getSpPr().getLn().getTailEnd().getType());\r
+\r
+        shape.setLineHeadDecoration(LineDecoration.DIAMOND);\r
+        shape.setLineTailDecoration(LineDecoration.ARROW);\r
+        assertEquals(LineDecoration.DIAMOND, shape.getLineHeadDecoration());\r
+        assertEquals(LineDecoration.ARROW, shape.getLineTailDecoration());\r
+        assertEquals(STLineEndType.DIAMOND, shape.getSpPr().getLn().getHeadEnd().getType());\r
+        assertEquals(STLineEndType.ARROW, shape.getSpPr().getLn().getTailEnd().getType());\r
+\r
+        // line end width\r
+        assertEquals(null, shape.getLineHeadWidth());\r
+        assertEquals(null, shape.getLineTailWidth());\r
+        shape.setLineHeadWidth(null);\r
+        shape.setLineHeadWidth(null);\r
+        assertEquals(null, shape.getLineHeadWidth());\r
+        assertEquals(null, shape.getLineTailWidth());\r
+        assertFalse(shape.getSpPr().getLn().getHeadEnd().isSetW());\r
+        assertFalse(shape.getSpPr().getLn().getTailEnd().isSetW());\r
+        shape.setLineHeadWidth(LineEndWidth.LARGE);\r
+        shape.setLineTailWidth(LineEndWidth.MEDIUM);\r
+        assertEquals(LineEndWidth.LARGE, shape.getLineHeadWidth());\r
+        assertEquals(LineEndWidth.MEDIUM, shape.getLineTailWidth());\r
+        assertEquals(STLineEndWidth.LG, shape.getSpPr().getLn().getHeadEnd().getW());\r
+        assertEquals(STLineEndWidth.MED, shape.getSpPr().getLn().getTailEnd().getW());\r
+        shape.setLineHeadWidth(LineEndWidth.MEDIUM);\r
+        shape.setLineTailWidth(LineEndWidth.LARGE);\r
+        assertEquals(LineEndWidth.MEDIUM, shape.getLineHeadWidth());\r
+        assertEquals(LineEndWidth.LARGE, shape.getLineTailWidth());\r
+        assertEquals(STLineEndWidth.MED, shape.getSpPr().getLn().getHeadEnd().getW());\r
+        assertEquals(STLineEndWidth.LG, shape.getSpPr().getLn().getTailEnd().getW());\r
+\r
+        // line end length\r
+        assertEquals(null, shape.getLineHeadLength());\r
+        assertEquals(null, shape.getLineTailLength());\r
+        shape.setLineHeadLength(null);\r
+        shape.setLineTailLength(null);\r
+        assertEquals(null, shape.getLineHeadLength());\r
+        assertEquals(null, shape.getLineTailLength());\r
+        assertFalse(shape.getSpPr().getLn().getHeadEnd().isSetLen());\r
+        assertFalse(shape.getSpPr().getLn().getTailEnd().isSetLen());\r
+        shape.setLineHeadLength(LineEndLength.LARGE);\r
+        shape.setLineTailLength(LineEndLength.MEDIUM);\r
+        assertEquals(LineEndLength.LARGE, shape.getLineHeadLength());\r
+        assertEquals(LineEndLength.MEDIUM, shape.getLineTailLength());\r
+        assertEquals(STLineEndLength.LG, shape.getSpPr().getLn().getHeadEnd().getLen());\r
+        assertEquals(STLineEndLength.MED, shape.getSpPr().getLn().getTailEnd().getLen());\r
+        shape.setLineHeadLength(LineEndLength.MEDIUM);\r
+        shape.setLineTailLength(LineEndLength.LARGE);\r
+        assertEquals(LineEndLength.MEDIUM, shape.getLineHeadLength());\r
+        assertEquals(LineEndLength.LARGE, shape.getLineTailLength());\r
+        assertEquals(STLineEndLength.MED, shape.getSpPr().getLn().getHeadEnd().getLen());\r
+        assertEquals(STLineEndLength.LG, shape.getSpPr().getLn().getTailEnd().getLen());\r
+\r
+    }\r
+\r
+}
\ No newline at end of file
diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFFreeformShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFFreeformShape.java
new file mode 100755 (executable)
index 0000000..f52cc83
--- /dev/null
@@ -0,0 +1,50 @@
+/* ====================================================================\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
+\r
+/**\r
+ * @author Yegor Kozlov\r
+ */\r
+public class TestXSLFFreeformShape extends TestCase {\r
+\r
+    public void testSetPath() {\r
+        XMLSlideShow ppt = new XMLSlideShow();\r
+        XSLFSlide slide = ppt.createSlide();\r
+        XSLFFreeformShape shape1 = slide.createFreeform();\r
+        // comples path consisting of a rectangle and an ellipse inside it\r
+        GeneralPath path1 = new GeneralPath(new Rectangle(150, 150, 300, 300));\r
+        path1.append(new Ellipse2D.Double(200, 200, 100, 50), false);\r
+        shape1.setPath(path1);\r
+\r
+        GeneralPath path2 = shape1.getPath();\r
+\r
+        // YK: how to compare the original path1 and the value returned by XSLFFreeformShape.getPath() ?\r
+        // one way is to create another XSLFFreeformShape from path2 and compare the resulting xml\r
+        assertEquals(path1.getBounds2D(), path2.getBounds2D());\r
+\r
+        XSLFFreeformShape shape2 = slide.createFreeform();\r
+        shape2.setPath(path2);\r
+\r
+        assertEquals(shape1.getSpPr().getCustGeom().toString(), shape2.getSpPr().getCustGeom().toString());\r
+    }\r
+}
\ No newline at end of file
diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFGroupShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFGroupShape.java
new file mode 100755 (executable)
index 0000000..13e8eb8
--- /dev/null
@@ -0,0 +1,99 @@
+/* ====================================================================\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.Rectangle2D;\r
+\r
+/**\r
+ * @author Yegor Kozlov\r
+ */\r
+public class TestXSLFGroupShape extends TestCase {\r
+\r
+    public void testCreateShapes() {\r
+        XMLSlideShow ppt = new XMLSlideShow();\r
+        XSLFSlide slide = ppt.createSlide();\r
+\r
+        ppt.setPageSize(new Dimension(792, 612));\r
+        \r
+        XSLFGroupShape group = slide.createGroup();\r
+        assertEquals(1, slide.getShapes().length);\r
+\r
+        Rectangle2D interior = new Rectangle2D.Double(-10, -10, 20, 20);\r
+        group.setInteriorAnchor(interior);\r
+        assertEquals(interior, group.getInteriorAnchor());\r
+\r
+        Rectangle2D anchor = new Rectangle2D.Double(0, 0, 792, 612);\r
+        group.setAnchor(anchor);\r
+        assertEquals(anchor, group.getAnchor());\r
+\r
+        assertEquals(0, group.getShapes().length);\r
+\r
+        XSLFTextBox shape1 = group.createTextBox();\r
+        assertEquals(1, group.getShapes().length);\r
+        assertSame(shape1, group.getShapes()[0]);\r
+        assertEquals(3, shape1.getShapeId());\r
+\r
+        XSLFAutoShape shape2 = group.createAutoShape();\r
+        assertEquals(2, group.getShapes().length);\r
+        assertSame(shape1, group.getShapes()[0]);\r
+        assertSame(shape2, group.getShapes()[1]);\r
+        assertEquals(4, shape2.getShapeId());\r
+\r
+        XSLFConnectorShape shape3 = group.createConnector();\r
+        assertEquals(3, group.getShapes().length);\r
+        assertSame(shape3, group.getShapes()[2]);\r
+        assertEquals(5, shape3.getShapeId());\r
+\r
+        XSLFGroupShape shape4 = group.createGroup();\r
+        assertEquals(4, group.getShapes().length);\r
+        assertSame(shape4, group.getShapes()[3]);\r
+        assertEquals(6, shape4.getShapeId());\r
+\r
+        group.removeShape(shape2);\r
+        assertEquals(3, group.getShapes().length);\r
+        assertSame(shape1, group.getShapes()[0]);\r
+        assertSame(shape3, group.getShapes()[1]);\r
+        assertSame(shape4, group.getShapes()[2]);\r
+\r
+        group.removeShape(shape3);\r
+        assertEquals(2, group.getShapes().length);\r
+        assertSame(shape1, group.getShapes()[0]);\r
+        assertSame(shape4, group.getShapes()[1]);\r
+\r
+        group.removeShape(shape1);\r
+        group.removeShape(shape4);\r
+        assertEquals(0, group.getShapes().length);\r
+    }\r
+\r
+    public void testRemoveShapes() {\r
+        XMLSlideShow ppt = new XMLSlideShow();\r
+        XSLFSlide slide = ppt.createSlide();\r
+\r
+        XSLFGroupShape group1 = slide.createGroup();\r
+        group1.createTextBox();\r
+        XSLFGroupShape group2 = slide.createGroup();\r
+        group2.createTextBox();\r
+        XSLFGroupShape group3 = slide.createGroup();\r
+        slide.removeShape(group1);\r
+        slide.removeShape(group2);\r
+        slide.removeShape(group3);\r
+\r
+    }\r
+}
\ No newline at end of file
diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFPictureShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFPictureShape.java
new file mode 100644 (file)
index 0000000..9bd4102
--- /dev/null
@@ -0,0 +1,65 @@
+/* ====================================================================\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
+\r
+/**\r
+ * @author Yegor Kozlov\r
+ */\r
+public class TestXSLFPictureShape extends TestCase {\r
+\r
+    public void testCreate() {\r
+        XMLSlideShow ppt = new XMLSlideShow();\r
+        assertEquals(0, ppt.getAllPictures().size());\r
+        byte[] data1 = new byte[100];\r
+        int idx1 = ppt.addPicture(data1, XSLFPictureData.PICTURE_TYPE_JPEG);\r
+        assertEquals(0, idx1);\r
+        assertEquals(1, ppt.getAllPictures().size());\r
+\r
+        XSLFSlide slide = ppt.createSlide();\r
+        XSLFPictureShape shape1 = slide.createPicture(idx1);\r
+        assertNotNull(shape1.getPictureData());\r
+        assertTrue(Arrays.equals(data1, shape1.getPictureData().getData()));\r
+\r
+        byte[] data2 = new byte[200];\r
+        int idx2 = ppt.addPicture(data2, XSLFPictureData.PICTURE_TYPE_PNG);\r
+        XSLFPictureShape shape2 = slide.createPicture(idx2);\r
+        assertNotNull(shape2.getPictureData());\r
+        assertEquals(1, idx2);\r
+        assertEquals(2, ppt.getAllPictures().size());\r
+        assertTrue(Arrays.equals(data2, shape2.getPictureData().getData()));\r
+\r
+        ppt = XSLFTestDataSamples.writeOutAndReadBack(ppt);\r
+        List<XSLFPictureData> pics =  ppt.getAllPictures();\r
+        assertEquals(2, pics.size());\r
+        assertTrue(Arrays.equals(data1, pics.get(0).getData()));\r
+        assertTrue(Arrays.equals(data2, pics.get(1).getData()));\r
+\r
+        XSLFShape[] shapes = ppt.getSlides()[0].getShapes();\r
+        assertTrue(Arrays.equals(data1, ((XSLFPictureShape)shapes[0]).getPictureData().getData()));\r
+        assertTrue(Arrays.equals(data2, ((XSLFPictureShape)shapes[1]).getPictureData().getData()));\r
+    }\r
+}
\ 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
new file mode 100755 (executable)
index 0000000..ca3d82f
--- /dev/null
@@ -0,0 +1,101 @@
+/* ====================================================================\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 org.apache.poi.xslf.XSLFTestDataSamples;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType;\r
+\r
+import java.util.List;\r
+\r
+/**\r
+ * @author Yegor Kozlov\r
+ */\r
+public class TestXSLFShape extends TestCase {\r
+\r
+    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
+        assertEquals(7, shapes1.length);\r
+        assertEquals("TextBox 3", shapes1[0].getShapeName());\r
+        XSLFAutoShape sh0 = (XSLFAutoShape) shapes1[0];\r
+        assertEquals("Learning PPTX", sh0.getText());\r
+        List<XSLFTextParagraph> paragraphs0 = sh0.getTextParagraphs();\r
+        assertEquals(1, paragraphs0.size());\r
+        XSLFTextParagraph p0 = paragraphs0.get(0);\r
+        assertEquals("Learning PPTX", p0.getText());\r
+        assertEquals(1, p0.getTextRuns().size());\r
+        XSLFTextRun r0 = p0.getTextRuns().get(0);\r
+        assertEquals("Learning PPTX", r0.getText());\r
+\r
+        XSLFSlide slide2 = slides[1];\r
+        XSLFShape[] shapes2 = slide2.getShapes();\r
+        assertTrue(shapes2[0] instanceof XSLFAutoShape);\r
+        assertEquals("PPTX Title", ((XSLFAutoShape) shapes2[0]).getText());\r
+        XSLFAutoShape sh1 = (XSLFAutoShape) shapes2[0];\r
+        List<XSLFTextParagraph> paragraphs1 = sh1.getTextParagraphs();\r
+        assertEquals(1, paragraphs1.size());\r
+        XSLFTextParagraph p1 = paragraphs1.get(0);\r
+        assertEquals("PPTX Title", p1.getText());\r
+        List<XSLFTextRun> r2 = paragraphs1.get(0).getTextRuns();\r
+        assertEquals(2, r2.size());\r
+        assertEquals("PPTX ", r2.get(0).getText());\r
+        assertEquals("Title", r2.get(1).getText());\r
+        // Title is underlined\r
+        assertEquals(STTextUnderlineType.SNG, r2.get(1).getXmlObject().getRPr().getU());\r
+\r
+\r
+        assertTrue(shapes2[1] instanceof XSLFAutoShape);\r
+        assertEquals("Subtitle\nAnd second line", ((XSLFAutoShape) shapes2[1]).getText());\r
+        XSLFAutoShape sh2 = (XSLFAutoShape) shapes2[1];\r
+        List<XSLFTextParagraph> paragraphs2 = sh2.getTextParagraphs();\r
+        assertEquals(2, paragraphs2.size());\r
+        assertEquals("Subtitle", paragraphs2.get(0).getText());\r
+        assertEquals("And second line", paragraphs2.get(1).getText());\r
+\r
+        assertEquals(1, paragraphs2.get(0).getTextRuns().size());\r
+        assertEquals(1, paragraphs2.get(1).getTextRuns().size());\r
+\r
+        assertEquals("Subtitle", paragraphs2.get(0).getTextRuns().get(0).getText());\r
+        assertTrue(paragraphs2.get(0).getTextRuns().get(0).getXmlObject().getRPr().getB());\r
+        assertEquals("And second line", paragraphs2.get(1).getTextRuns().get(0).getText());\r
+    }\r
+\r
+    public void testCreateShapes() {\r
+        XMLSlideShow ppt = new XMLSlideShow();\r
+        XSLFSlide slide = ppt.createSlide();\r
+        assertEquals(0, slide.getShapes().length);\r
+\r
+        XSLFTextBox textBox = slide.createTextBox();\r
+\r
+        assertEquals(1, slide.getShapes().length);\r
+        assertSame(textBox, slide.getShapes()[0]);\r
+\r
+        assertEquals("", textBox.getText());\r
+        assertEquals(0, textBox.getTextParagraphs().size());\r
+        textBox.addNewTextParagraph().addNewTextRun().setText("Apache");\r
+        textBox.addNewTextParagraph().addNewTextRun().setText("POI");\r
+        assertEquals("Apache\nPOI", textBox.getText());\r
+        assertEquals(2, textBox.getTextParagraphs().size());\r
+    }\r
+\r
+}
\ No newline at end of file
diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSheet.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSheet.java
new file mode 100644 (file)
index 0000000..88af770
--- /dev/null
@@ -0,0 +1,66 @@
+/* ====================================================================\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 org.apache.poi.xslf.XSLFTestDataSamples;\r
+\r
+/**\r
+ * test common properties for sheets (slides, masters, layouts, etc.)\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+public class TestXSLFSheet extends TestCase {\r
+    public void testCreateShapes(){\r
+        XMLSlideShow ppt = new XMLSlideShow();\r
+        XSLFSlide slide = ppt.createSlide();\r
+        assertEquals(0, slide.getShapes().length);\r
+\r
+        XSLFSimpleShape shape1 = slide.createAutoShape();\r
+        assertEquals(1, slide.getShapes().length);\r
+        assertSame(shape1, slide.getShapes()[0]);\r
+\r
+        XSLFTextBox shape2 = slide.createTextBox();\r
+        assertEquals(2, slide.getShapes().length);\r
+        assertSame(shape1, slide.getShapes()[0]);\r
+        assertSame(shape2, slide.getShapes()[1]);\r
+\r
+        XSLFConnectorShape shape3 = slide.createConnector();\r
+        assertEquals(3, slide.getShapes().length);\r
+        assertSame(shape1, slide.getShapes()[0]);\r
+        assertSame(shape2, slide.getShapes()[1]);\r
+        assertSame(shape3, slide.getShapes()[2]);\r
+\r
+        XSLFGroupShape shape4 = slide.createGroup();\r
+        assertEquals(4, slide.getShapes().length);\r
+        assertSame(shape1, slide.getShapes()[0]);\r
+        assertSame(shape2, slide.getShapes()[1]);\r
+        assertSame(shape3, slide.getShapes()[2]);\r
+        assertSame(shape4, slide.getShapes()[3]);\r
+\r
+        ppt = XSLFTestDataSamples.writeOutAndReadBack(ppt);\r
+        slide = ppt.getSlides()[0];\r
+        XSLFShape[] shapes = slide.getShapes();\r
+        assertEquals(4, shapes.length);\r
+\r
+        assertTrue(shapes[0] instanceof XSLFAutoShape);\r
+        assertTrue(shapes[1] instanceof XSLFTextBox);\r
+        assertTrue(shapes[2] instanceof XSLFConnectorShape);\r
+        assertTrue(shapes[3] instanceof XSLFGroupShape);\r
+    }\r
+}
\ No newline at end of file
diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java
new file mode 100644 (file)
index 0000000..d012f99
--- /dev/null
@@ -0,0 +1,132 @@
+/* ====================================================================\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 org.apache.poi.util.Units;\r
+import org.apache.poi.xslf.usermodel.LineCap;\r
+import org.apache.poi.xslf.usermodel.LineDash;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal;\r
+\r
+import java.awt.*;\r
+\r
+/**\r
+ * @author Yegor Kozlov\r
+ */\r
+public class TestXSLFSimpleShape extends TestCase {\r
+    public void testLineStyles() {\r
+        XMLSlideShow ppt = new XMLSlideShow();\r
+        XSLFSlide slide = ppt.createSlide();\r
+\r
+        XSLFSimpleShape shape = slide.createAutoShape();\r
+        assertEquals(1, slide.getShapes().length);\r
+        // line properties are not set by default\r
+        assertFalse(shape.getSpPr().isSetLn());\r
+\r
+        assertEquals(0., shape.getLineWidth());\r
+        assertEquals(null, shape.getLineColor());\r
+        assertEquals(null, shape.getLineDash());\r
+        assertEquals(null, shape.getLineCap());\r
+\r
+        shape.setLineWidth(0);\r
+        shape.setLineColor(null);\r
+        shape.setLineDash(null);\r
+        shape.setLineCap(null);\r
+\r
+        // still no line properties\r
+        assertFalse(shape.getSpPr().isSetLn());\r
+\r
+        // line width\r
+        shape.setLineWidth(1.0);\r
+        assertEquals(1.0, shape.getLineWidth());\r
+        assertEquals(Units.EMU_PER_POINT, shape.getSpPr().getLn().getW());\r
+        shape.setLineWidth(5.5);\r
+        assertEquals(5.5, shape.getLineWidth());\r
+        assertEquals(Units.toEMU(5.5), shape.getSpPr().getLn().getW());\r
+        shape.setLineWidth(0.0);\r
+        // setting line width to zero unsets the W attribute\r
+        assertFalse(shape.getSpPr().getLn().isSetW());\r
+\r
+        // line cap\r
+        shape.setLineCap(LineCap.FLAT);\r
+        assertEquals(LineCap.FLAT, shape.getLineCap());\r
+        assertEquals(STLineCap.FLAT, shape.getSpPr().getLn().getCap());\r
+        shape.setLineCap(LineCap.SQUARE);\r
+        assertEquals(LineCap.SQUARE, shape.getLineCap());\r
+        assertEquals(STLineCap.SQ, shape.getSpPr().getLn().getCap());\r
+        shape.setLineCap(LineCap.ROUND);\r
+        assertEquals(LineCap.ROUND, shape.getLineCap());\r
+        assertEquals(STLineCap.RND, shape.getSpPr().getLn().getCap());\r
+        shape.setLineCap(null);\r
+        // setting cap to null unsets the Cap attribute\r
+        assertFalse(shape.getSpPr().getLn().isSetCap());\r
+\r
+        // line dash\r
+        shape.setLineDash(LineDash.SOLID);\r
+        assertEquals(LineDash.SOLID, shape.getLineDash());\r
+        assertEquals(STPresetLineDashVal.SOLID, shape.getSpPr().getLn().getPrstDash().getVal());\r
+        shape.setLineDash(LineDash.DASH_DOT);\r
+        assertEquals(LineDash.DASH_DOT, shape.getLineDash());\r
+        assertEquals(STPresetLineDashVal.DASH_DOT, shape.getSpPr().getLn().getPrstDash().getVal());\r
+        shape.setLineDash(LineDash.LG_DASH_DOT);\r
+        assertEquals(LineDash.LG_DASH_DOT, shape.getLineDash());\r
+        assertEquals(STPresetLineDashVal.LG_DASH_DOT, shape.getSpPr().getLn().getPrstDash().getVal());\r
+        shape.setLineDash(null);\r
+        // setting dash width to null unsets the Dash element\r
+        assertFalse(shape.getSpPr().getLn().isSetPrstDash());\r
+\r
+        // line color\r
+        assertFalse(shape.getSpPr().getLn().isSetSolidFill());\r
+        shape.setLineColor(Color.RED);\r
+        assertEquals(Color.RED, shape.getLineColor());\r
+        assertTrue(shape.getSpPr().getLn().isSetSolidFill());\r
+        shape.setLineColor(Color.BLUE);\r
+        assertEquals(Color.BLUE, shape.getLineColor());\r
+        assertTrue(shape.getSpPr().getLn().isSetSolidFill());\r
+        shape.setLineColor(null);\r
+        assertEquals(null, shape.getLineColor());\r
+        // setting dash width to null unsets the SolidFill element\r
+        assertFalse(shape.getSpPr().getLn().isSetSolidFill());\r
+    }\r
+\r
+    public void testFill() {\r
+        XMLSlideShow ppt = new XMLSlideShow();\r
+        XSLFSlide slide = ppt.createSlide();\r
+\r
+        XSLFAutoShape shape = slide.createAutoShape();\r
+        // line properties are not set by default\r
+        assertFalse(shape.getSpPr().isSetSolidFill());\r
+\r
+        assertNull(shape.getFillColor());\r
+        shape.setFillColor(null);\r
+        assertNull(shape.getFillColor());\r
+        assertFalse(shape.getSpPr().isSetSolidFill());\r
+\r
+        shape.setFillColor(Color.RED);\r
+        assertEquals(Color.RED, shape.getFillColor());\r
+        shape.setFillColor(Color.DARK_GRAY);\r
+        assertEquals(Color.DARK_GRAY, shape.getFillColor());\r
+        assertTrue(shape.getSpPr().isSetSolidFill());\r
+\r
+        shape.setFillColor(null);\r
+        assertNull(shape.getFillColor());\r
+        assertFalse(shape.getSpPr().isSetSolidFill());\r
+    }\r
+\r
+}
\ No newline at end of file
diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java
new file mode 100755 (executable)
index 0000000..9c7d131
--- /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 org.apache.poi.xslf.XSLFTestDataSamples;\r
+import org.apache.poi.POIXMLDocumentPart;\r
+\r
+import java.util.List;\r
+\r
+/**\r
+ * @author Yegor Kozlov\r
+ */\r
+public class TestXSLFSlide extends TestCase {\r
+    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
+        assertEquals(7, shapes1.length);\r
+        assertEquals("TextBox 3", shapes1[0].getShapeName());\r
+        assertTrue(shapes1[0] instanceof XSLFTextBox);\r
+        XSLFAutoShape sh0 = (XSLFAutoShape)shapes1[0];\r
+        assertEquals("Learning PPTX", sh0.getText());\r
+\r
+\r
+        assertEquals("Straight Connector 5", shapes1[1].getShapeName());\r
+        assertTrue(shapes1[1] instanceof XSLFConnectorShape);\r
+\r
+        assertEquals("Freeform 6", shapes1[2].getShapeName());\r
+        assertTrue(shapes1[2] instanceof XSLFFreeformShape);\r
+        XSLFAutoShape sh2 = (XSLFAutoShape)shapes1[2];\r
+        assertEquals("Cloud", sh2.getText());\r
+\r
+        assertEquals("Picture 1", shapes1[3].getShapeName());\r
+        assertTrue(shapes1[3] instanceof XSLFPictureShape);\r
+\r
+        assertEquals("Table 2", shapes1[4].getShapeName());\r
+        assertTrue(shapes1[4] instanceof XSLFGraphicFrame);\r
+\r
+        assertEquals("Straight Arrow Connector 7", shapes1[5].getShapeName());\r
+        assertTrue(shapes1[5] instanceof XSLFConnectorShape);\r
+\r
+        assertEquals("Elbow Connector 9", shapes1[6].getShapeName());\r
+        assertTrue(shapes1[6] instanceof XSLFConnectorShape);\r
+\r
+        // titles on slide2\r
+        XSLFSlide slide2 = slides[1];\r
+        XSLFShape[] shapes2 = slide2.getShapes();\r
+        assertEquals(2, shapes2.length);\r
+        assertTrue(shapes2[0] instanceof XSLFAutoShape);\r
+        assertEquals("PPTX Title", ((XSLFAutoShape)shapes2[0]).getText());\r
+        assertTrue(shapes2[1] instanceof XSLFAutoShape);\r
+        assertEquals("Subtitle\nAnd second line", ((XSLFAutoShape)shapes2[1]).getText());\r
+\r
+        //  group shape on slide3\r
+        XSLFSlide slide3 = slides[2];\r
+        XSLFShape[] shapes3 = slide3.getShapes();\r
+        assertEquals(1, shapes3.length);\r
+        assertTrue(shapes3[0] instanceof XSLFGroupShape);\r
+        XSLFShape[] groupShapes = ((XSLFGroupShape)shapes3[0]).getShapes();\r
+        assertEquals(3, groupShapes.length);\r
+        assertTrue(groupShapes[0] instanceof XSLFAutoShape);\r
+        assertEquals("Rectangle 1", groupShapes[0].getShapeName());\r
+\r
+        assertTrue(groupShapes[1] instanceof XSLFAutoShape);\r
+        assertEquals("Oval 2", groupShapes[1].getShapeName());\r
+\r
+        assertTrue(groupShapes[2] instanceof XSLFAutoShape);\r
+        assertEquals("Right Arrow 3", groupShapes[2].getShapeName());\r
+    }\r
+\r
+    public void testCreateSlide(){\r
+        XMLSlideShow  ppt = new XMLSlideShow();\r
+        assertEquals(0, ppt.getSlides().length);\r
+\r
+        XSLFSlide slide = ppt.createSlide();\r
+        assertTrue(slide.getFollowMasterBackground());\r
+        slide.setFollowMasterBackground(false);\r
+        assertFalse(slide.getFollowMasterBackground());\r
+        slide.setFollowMasterBackground(true);\r
+        assertTrue(slide.getFollowMasterBackground());\r
+    }\r
+\r
+}
\ No newline at end of file
diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlideShow.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlideShow.java
new file mode 100755 (executable)
index 0000000..c07493a
--- /dev/null
@@ -0,0 +1,108 @@
+/* ====================================================================\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.Dimension;\r
+import java.util.List;\r
+\r
+import org.apache.poi.POIXMLDocumentPart;\r
+import org.apache.poi.xslf.XSLFTestDataSamples;\r
+\r
+/**\r
+ * @author Yegor Kozlov\r
+ */\r
+public class TestXSLFSlideShow extends TestCase {\r
+    public void testCreateSlide(){\r
+        XMLSlideShow  ppt = new XMLSlideShow();\r
+        assertEquals(0, ppt.getSlides().length);\r
+\r
+        XSLFSlide slide1 = ppt.createSlide();\r
+        assertEquals(1, ppt.getSlides().length);\r
+        assertSame(slide1, ppt.getSlides()[0]);\r
+\r
+        List<POIXMLDocumentPart> rels =  slide1.getRelations();\r
+        assertEquals(1, rels.size());\r
+        assertEquals(slide1.getMasterSheet().getLayout("blank"), rels.get(0));\r
+\r
+        XSLFSlide slide2 = ppt.createSlide();\r
+        assertEquals(2, ppt.getSlides().length);\r
+        assertSame(slide2, ppt.getSlides()[1]);\r
+\r
+        ppt.setSlideOrder(slide2, 0);\r
+        assertSame(slide2, ppt.getSlides()[0]);\r
+        assertSame(slide1, ppt.getSlides()[1]);\r
+\r
+        ppt = XSLFTestDataSamples.writeOutAndReadBack(ppt);\r
+        assertEquals(2, ppt.getSlides().length);\r
+        rels =  ppt.getSlides()[0].getRelations();\r
+    }\r
+\r
+    public void testRemoveSlide(){\r
+        XMLSlideShow  ppt = new XMLSlideShow();\r
+        assertEquals(0, ppt.getSlides().length);\r
+\r
+        XSLFSlide slide1 = ppt.createSlide();\r
+        XSLFSlide slide2 = ppt.createSlide();\r
+\r
+        assertEquals(2, ppt.getSlides().length);\r
+        assertSame(slide1, ppt.getSlides()[0]);\r
+        assertSame(slide2, ppt.getSlides()[1]);\r
+\r
+        XSLFSlide removedSlide = ppt.removeSlide(0);\r
+        assertSame(slide1, removedSlide);\r
+\r
+        assertEquals(1, ppt.getSlides().length);\r
+        assertSame(slide2, ppt.getSlides()[0]);\r
+\r
+        ppt = XSLFTestDataSamples.writeOutAndReadBack(ppt);\r
+        assertEquals(1, ppt.getSlides().length);\r
+    }\r
+\r
+    public void testDimension(){\r
+        XMLSlideShow  ppt = new XMLSlideShow();\r
+        Dimension sz = ppt.getPageSize();\r
+        assertEquals(720, sz.width);\r
+        assertEquals(540, sz.height);\r
+        ppt.setPageSize(new Dimension(792, 612));\r
+        sz = ppt.getPageSize();\r
+        assertEquals(792, sz.width);\r
+        assertEquals(612, sz.height);\r
+    }\r
+\r
+    public void testSlideMasters(){\r
+        XMLSlideShow  ppt = new XMLSlideShow();\r
+        XSLFSlideMaster[] masters = ppt.getSlideMasters();\r
+        assertEquals(1, masters.length);\r
+\r
+        XSLFSlide slide = ppt.createSlide();\r
+        assertSame(masters[0], slide.getMasterSheet());\r
+    }\r
+\r
+    public void testSlideLayout(){\r
+        XMLSlideShow  ppt = new XMLSlideShow();\r
+        XSLFSlideMaster[] masters = ppt.getSlideMasters();\r
+        assertEquals(1, masters.length);\r
+\r
+        XSLFSlide slide = ppt.createSlide();\r
+        XSLFSlideLayout layout = slide.getSlideLayout();\r
+        assertNotNull(layout);\r
+\r
+        assertSame(masters[0], layout.getSlideMaster());\r
+    }\r
+}\r
diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextBox.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextBox.java
new file mode 100644 (file)
index 0000000..cc54111
--- /dev/null
@@ -0,0 +1,37 @@
+/* ====================================================================\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
+/**\r
+ * @author Yegor Kozlov\r
+ */\r
+public class TestXSLFTextBox extends TestCase {\r
+\r
+    public void testPlaceholder() {\r
+        XMLSlideShow ppt = new XMLSlideShow();\r
+        XSLFSlide slide = ppt.createSlide();\r
+\r
+        XSLFTextBox shape = slide.createTextBox();\r
+        assertNull(shape.getPlaceholder());\r
+        shape.setPlaceholder(Placeholder.TITLE);\r
+        assertEquals(Placeholder.TITLE, shape.getPlaceholder());\r
+        shape.setPlaceholder(null);\r
+        assertNull(shape.getPlaceholder());\r
+    }\r
+}
\ No newline at end of file
diff --git a/src/resources/scratchpad/org/apache/poi/xslf/usermodel/empty.pptx b/src/resources/scratchpad/org/apache/poi/xslf/usermodel/empty.pptx
new file mode 100755 (executable)
index 0000000..eea1e06
Binary files /dev/null and b/src/resources/scratchpad/org/apache/poi/xslf/usermodel/empty.pptx differ
diff --git a/test-data/slideshow/shapes.pptx b/test-data/slideshow/shapes.pptx
new file mode 100755 (executable)
index 0000000..0b38612
Binary files /dev/null and b/test-data/slideshow/shapes.pptx differ