From: Yegor Kozlov Date: Thu, 11 Aug 2011 08:38:19 +0000 (+0000) Subject: initial support for XSLF usermodel API X-Git-Tag: REL_3_8_BETA4~15 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=ccad96e6d9e296958d03d90d44e70888f45ba8b9;p=poi.git initial support for XSLF usermodel API git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1156539 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index ac2112f655..bea5040855 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + initial support for XSLF usermodel API 51187 - fixed OPCPackage to correctly handle self references 51635 - Improved performance of XSSFSheet#write 47731 - Word Extractor considers text copied from some website as an embedded object 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 index 0000000000..cb700c6133 --- /dev/null +++ b/src/examples/src/org/apache/poi/xslf/usermodel/SlidesAndShapes.java @@ -0,0 +1,86 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import java.awt.*; +import java.awt.geom.Ellipse2D; +import java.awt.geom.GeneralPath; +import java.io.FileOutputStream; + +/** + * Simple demo that creates a pptx slide show using the XSLF API + * + * @author Yegor Kozlov + */ +public class SlidesAndShapes { + + public static void main(String[] args) throws Exception { + XMLSlideShow ppt = new XMLSlideShow(); + ppt.setPageSize(new Dimension(792, 612)); + + XSLFSlide slide1 = ppt.createSlide(); + XSLFTextBox textBox = slide1.createTextBox(); + XSLFTextRun r1 = textBox.addNewTextParagraph().addNewTextRun(); + r1.setBold(true); + r1.setItalic(true); + r1.setFontColor(Color.yellow); + r1.setFontFamily("Arial"); + r1.setFontSize(24); + r1.setText("Apache"); + XSLFTextRun r2 = textBox.addNewTextParagraph().addNewTextRun(); + r2.setStrikethrough(true); + r2.setUnderline(true); + r2.setText("POI\u2122"); + XSLFTextRun r3 = textBox.addNewTextParagraph().addNewTextRun(); + r3.setFontFamily("Wingdings"); + r3.setText(" Version 3.8"); + + textBox.setAnchor(new Rectangle(50, 50, 200, 100)); + textBox.setLineColor(Color.black); + textBox.setFillColor(Color.orange); + + XSLFAutoShape shape2 = slide1.createAutoShape(); + + shape2.setAnchor(new Rectangle(100, 100, 200, 200)); + + XSLFFreeformShape shape3 = slide1.createFreeform(); + Rectangle rect = new Rectangle(150, 150, 300, 300); + GeneralPath path = new GeneralPath(rect); + path.append(new Ellipse2D.Double(200, 200, 100, 50), false); + shape3.setPath(path); + shape3.setAnchor(path.getBounds2D()); + shape3.setLineColor(Color.black); + shape3.setFillColor(Color.lightGray); + + XSLFSlide slide2 = ppt.createSlide(); + XSLFGroupShape group = slide2.createGroup(); + + group.setAnchor(new Rectangle(0, 0, 792, 612)); + group.setInteriorAnchor(new Rectangle(-10, -10, 20, 20)); + + XSLFAutoShape shape4 = group.createAutoShape(); + shape4.setAnchor(new Rectangle(0, 0, 5, 5)); + shape4.setLineWidth(5); + shape4.setLineColor(Color.black); + + + FileOutputStream out = new FileOutputStream("xslf-demo.pptx"); + ppt.write(out); + out.close(); + } + +} 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 index 0000000000..59ce34cdfa --- /dev/null +++ b/src/ooxml/java/org/apache/poi/util/Units.java @@ -0,0 +1,17 @@ +package org.apache.poi.util; + +/** + * @author Yegor Kozlov + */ +public class Units { + public static final int EMU_PER_PIXEL = 9525; + public static final int EMU_PER_POINT = 12700; + + public static int toEMU(double value){ + return (int)Math.round(EMU_PER_POINT*value); + } + + public static double toPoints(long emu){ + return (double)emu/EMU_PER_POINT; + } +} diff --git a/src/ooxml/java/org/apache/poi/xslf/XSLFSlideShow.java b/src/ooxml/java/org/apache/poi/xslf/XSLFSlideShow.java index 05351c689c..d2986dc3fc 100644 --- a/src/ooxml/java/org/apache/poi/xslf/XSLFSlideShow.java +++ b/src/ooxml/java/org/apache/poi/xslf/XSLFSlideShow.java @@ -16,20 +16,16 @@ ==================================================================== */ 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)); } diff --git a/src/ooxml/java/org/apache/poi/xslf/extractor/XSLFPowerPointExtractor.java b/src/ooxml/java/org/apache/poi/xslf/extractor/XSLFPowerPointExtractor.java index d20a357964..773e0f458b 100644 --- a/src/ooxml/java/org/apache/poi/xslf/extractor/XSLFPowerPointExtractor.java +++ b/src/ooxml/java/org/apache/poi/xslf/extractor/XSLFPowerPointExtractor.java @@ -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 "); + System.err.println(" XSLFPowerPointExtractor "); 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) { diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/DrawingParagraph.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/DrawingParagraph.java index f1e84ce6c1..2e755583bb 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/DrawingParagraph.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/DrawingParagraph.java @@ -17,11 +17,11 @@ 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; diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/DrawingTable.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/DrawingTable.java index e221cfa7cc..c6d7da9f2b 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/DrawingTable.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/DrawingTable.java @@ -17,11 +17,11 @@ 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; diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/DrawingTableRow.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/DrawingTableRow.java index 213dd638d6..27b79ea33e 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/DrawingTableRow.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/DrawingTableRow.java @@ -17,10 +17,10 @@ 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; diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/DrawingTextBody.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/DrawingTextBody.java index 68a12a4d1c..1f40841d35 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/DrawingTextBody.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/DrawingTextBody.java @@ -17,11 +17,11 @@ 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 index 0000000000..140f48bf0b --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/LineCap.java @@ -0,0 +1,19 @@ +package org.apache.poi.xslf.usermodel; + +/** + */ +public enum LineCap { + /** + * Rounded ends - the default + */ + ROUND, + /** + * Square protrudes by half line width + */ + SQUARE, + + /** + * Line ends at end point + */ + FLAT; +} \ 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 index 0000000000..83b29be1c0 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/LineDash.java @@ -0,0 +1,17 @@ +package org.apache.poi.xslf.usermodel; + +/** + */ +public enum LineDash { + SOLID, + DOT, + DASH, + LG_DASH, + DASH_DOT, + LG_DASH_DOT, + LG_DASH_DOT_DOT, + SYS_DASH, + SYS_DOT, + SYS_DASH_DOT, + SYS_DASH_DOT_DOT; +} 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 index 0000000000..72b28c0b34 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/LineDecoration.java @@ -0,0 +1,29 @@ +/* ==================================================================== + 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; + +/** + * Represents the shape decoration that appears at the ends of lines. + */ +public enum LineDecoration { + NONE, + TRIANGLE, + STEALTH, + DIAMOND, + OVAL, + ARROW +} 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 index 0000000000..a66623bca7 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/LineEndLength.java @@ -0,0 +1,14 @@ +package org.apache.poi.xslf.usermodel; + +/** + * Created by IntelliJ IDEA. + * User: yegor + * Date: Aug 9, 2011 + * Time: 9:39:26 PM + * To change this template use File | Settings | File Templates. + */ +public enum LineEndLength { + SMALL, + MEDIUM, + LARGE +} 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 index 0000000000..5d2d3b86a2 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/LineEndWidth.java @@ -0,0 +1,14 @@ +package org.apache.poi.xslf.usermodel; + +/** + * Created by IntelliJ IDEA. + * User: yegor + * Date: Aug 9, 2011 + * Time: 9:39:26 PM + * To change this template use File | Settings | File Templates. + */ +public enum LineEndWidth { + SMALL, + MEDIUM, + LARGE +} \ 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 index 0000000000..0e958015ed --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/Placeholder.java @@ -0,0 +1,36 @@ +/* + * ==================================================================== + * 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; + +/** + * @author Yegor Kozlov + */ +public enum Placeholder { + TITLE, + BODY, + CENTERED_TITLE, + SUBTITLE, + DATETIME, + SLIDE_NUMBER, + FOOTER, + HEADER, + OBJECT, + CHART, + TABLE +} 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 index 0000000000..c712dbacef --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/TextAlign.java @@ -0,0 +1,47 @@ +/* + * ==================================================================== + * 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; + +/** + * Specified a list of text alignment types + * + * @author Yegor Kozlov + */ +public enum TextAlign { + /** + * Align text to the left margin. + */ + LEFT, + /** + * Align text in the center. + */ + CENTER, + + /** + * Align text to the right margin. + */ + RIGHT, + + /** + * Align text so that it is justified across the whole line. It + * is smart in the sense that it will not justify sentences + * which are short + */ + JUSTIFY +} 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 index 0000000000..94d6b24358 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/TextAutofit.java @@ -0,0 +1,59 @@ +/* + * ==================================================================== + * 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; + +/** + * Specifies alist of auto-fit types. + *

+ * Autofit specofies that a shape should be auto-fit to fully contain the text described within it. + * Auto-fitting is when text within a shape is scaled in order to contain all the text inside + *

+ * + * @author Yegor Kozlov + */ +public enum TextAutofit { + /** + * Specifies that text within the text body should not be auto-fit to the bounding box. + * Auto-fitting is when text within a text box is scaled in order to remain inside + * the text box. + */ + NONE, + /** + * Specifies that text within the text body should be normally auto-fit to the bounding box. + * Autofitting is when text within a text box is scaled in order to remain inside the text box. + * + *

+ * Example: Consider the situation where a user is building a diagram and needs + * to have the text for each shape that they are using stay within the bounds of the shape. + * An easy way this might be done is by using NORMAL autofit + *

+ */ + NORMAL, + /** + * Specifies that a shape should be auto-fit to fully contain the text described within it. + * Auto-fitting is when text within a shape is scaled in order to contain all the text inside. + * + *

+ * Example: Consider the situation where a user is building a diagram and needs to have + * the text for each shape that they are using stay within the bounds of the shape. + * An easy way this might be done is by using SHAPE autofit + *

+ */ + SHAPE +} 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 index 0000000000..3f35ec23ac --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/TextDirection.java @@ -0,0 +1,48 @@ +/* + * ==================================================================== + * 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; + +/** + * Vertical Text Types + */ +public enum TextDirection { + /** + * Horizontal text. This should be default. + */ + HORIZONTAL, + /** + * Vertical orientation. + * (each line is 90 degrees rotated clockwise, so it goes + * from top to bottom; each next line is to the left from + * the previous one). + */ + VERTICAL, + /** + * Vertical orientation. + * (each line is 270 degrees rotated clockwise, so it goes + * from bottom to top; each next line is to the right from + * the previous one). + */ + VERTICAL_270, + /** + * Determines if all of the text is vertical + * ("one letter on top of another"). + */ + STACKED; +} 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 index 0000000000..fd00a64e26 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/VerticalAlignment.java @@ -0,0 +1,71 @@ +/* + * ==================================================================== + * 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; + +/** + * Specifies a list of available anchoring types for text + * + * @author Yegor Kozlov + */ +public enum VerticalAlignment { + /** + * Anchor the text at the top of the bounding rectangle + */ + TOP, + + /** + * Anchor the text at the middle of the bounding rectangle + */ + MIDDLE, + + /** + * Anchor the text at the bottom of the bounding rectangle. + */ + BOTTOM, + + /** + * Anchor the text so that it is justified vertically. + *

+ * When text is horizontal, this spaces out the actual lines of + * text and is almost always identical in behavior to + * {@link #DISTRIBUTED} (special case: if only 1 line, then anchored at top). + *

+ *

+ * When text is vertical, then it justifies the letters + * vertically. This is different than {@link #DISTRIBUTED}, + * because in some cases such as very little text in a line, + * it will not justify. + *

+ */ + JUSTIFIED, + + /** + * Anchor the text so that it is distributed vertically. + *

+ * When text is horizontal, this spaces out the actual lines + * of text and is almost always identical in behavior to + * {@link #JUSTIFIED} (special case: if only 1 line, then anchored in middle). + *

+ *

+ * When text is vertical, then it distributes the letters vertically. + * This is different than {@link #JUSTIFIED}, because it always forces distribution + * of the words, even if there are only one or two words in a line. + */ + DISTRIBUTED +} diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java index ab5c670b9f..7c2db9bb45 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java @@ -16,20 +16,42 @@ ==================================================================== */ 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; + private Map _masters; + protected List _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 shIdMap = new HashMap(); + + _masters = new HashMap(); + 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(); + if (_presentation.isSetSldIdLst()) { + List 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 map = new HashMap(); + 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 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 getAllPictures() { + if(_pictures == null){ + List mediaParts = getPackage().getPartsByName(Pattern.compile("/ppt/media/.*?")); + _pictures = new ArrayList(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 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 Dimension 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 index 0000000000..1869749970 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java @@ -0,0 +1,427 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import org.apache.poi.util.Beta; +import org.apache.poi.util.Units; +import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor; +import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph; +import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; +import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType; +import org.openxmlformats.schemas.drawingml.x2006.main.STTextWrappingType; +import org.openxmlformats.schemas.drawingml.x2006.main.STTextVerticalType; +import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; +import org.openxmlformats.schemas.presentationml.x2006.main.CTShapeNonVisual; +import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder; +import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a preset geometric shape. + * + * @author Yegor Kozlov + */ +@Beta +public class XSLFAutoShape extends XSLFSimpleShape { + private final List _paragraphs; + + /*package*/ XSLFAutoShape(CTShape shape, XSLFSheet sheet) { + super(shape, sheet); + + _paragraphs = new ArrayList(); + if (shape.isSetTxBody()) { + CTTextBody txBody = shape.getTxBody(); + for (CTTextParagraph p : txBody.getPList()) { + _paragraphs.add(new XSLFTextParagraph(p)); + } + } + } + + /*package*/ + static XSLFAutoShape create(CTShape shape, XSLFSheet sheet) { + if (shape.getSpPr().isSetCustGeom()) { + return new XSLFFreeformShape(shape, sheet); + } else if (shape.getNvSpPr().getCNvSpPr().isSetTxBox()) { + return new XSLFTextBox(shape, sheet); + } else { + return new XSLFAutoShape(shape, sheet); + } + } + + // textual properties + public String getText() { + StringBuilder out = new StringBuilder(); + for (XSLFTextParagraph p : _paragraphs) { + if (out.length() > 0) out.append('\n'); + out.append(p.getText()); + } + return out.toString(); + } + + public List getTextParagraphs() { + return _paragraphs; + } + + public XSLFTextParagraph addNewTextParagraph() { + CTShape shape = (CTShape) getXmlObject(); + CTTextBody txBody; + if (!shape.isSetTxBody()) { + txBody = shape.addNewTxBody(); + txBody.addNewBodyPr(); + txBody.addNewLstStyle(); + } else { + txBody = shape.getTxBody(); + } + CTTextParagraph p = txBody.addNewP(); + XSLFTextParagraph paragraph = new XSLFTextParagraph(p); + _paragraphs.add(paragraph); + return paragraph; + } + + /** + * @param shapeId 1-based shapeId + */ + static CTShape prototype(int shapeId) { + CTShape ct = CTShape.Factory.newInstance(); + CTShapeNonVisual nvSpPr = ct.addNewNvSpPr(); + CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr(); + cnv.setName("AutoShape " + shapeId); + cnv.setId(shapeId + 1); + nvSpPr.addNewCNvSpPr(); + nvSpPr.addNewNvPr(); + CTShapeProperties spPr = ct.addNewSpPr(); + CTPresetGeometry2D prst = spPr.addNewPrstGeom(); + prst.setPrst(STShapeType.RECT); + prst.addNewAvLst(); + return ct; + } + + /** + * Specifies a solid color fill. The shape is filled entirely with the specified color. + * + * @param color the solid color fill. + * The value of null unsets the solidFIll attribute from the underlying xml + */ + public void setFillColor(Color color) { + CTShapeProperties spPr = getSpPr(); + if (color == null) { + if(spPr.isSetSolidFill()) spPr.unsetSolidFill(); + } + else { + CTSolidColorFillProperties fill = spPr.isSetSolidFill() ? spPr.getSolidFill() : spPr.addNewSolidFill(); + + CTSRgbColor rgb = CTSRgbColor.Factory.newInstance(); + rgb.setVal(new byte[]{(byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue()}); + + fill.setSrgbClr(rgb); + } + } + + /** + * + * @return solid fill color of null if not set + */ + public Color getFillColor(){ + CTShapeProperties spPr = getSpPr(); + if(!spPr.isSetSolidFill() ) return null; + + CTSolidColorFillProperties fill = spPr.getSolidFill(); + if(!fill.isSetSrgbClr()) { + // TODO for now return null for all colors except explicit RGB + return null; + } + byte[] val = fill.getSrgbClr().getVal(); + return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]); + } + + /** + * Sets the type of vertical alignment for the text. + * One of the Anchor* constants defined in this class. + * + * @param anchor - the type of alignment. Default is {@link VerticalAlignment#TOP} + */ + public void setVerticalAlignment(VerticalAlignment anchor){ + CTShape shape = (CTShape) getXmlObject(); + if (shape.isSetTxBody()) { + CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr(); + if(anchor == null) { + if(bodyPr.isSetAnchor()) bodyPr.unsetAnchor(); + } else { + bodyPr.setAnchor(STTextAnchoringType.Enum.forInt(anchor.ordinal() + 1)); + } + } + } + + /** + * Returns the type of vertical alignment for the text. + * + * @return the type of alignment + */ + public VerticalAlignment getVerticalAlignment(){ + CTShape shape = (CTShape) getXmlObject(); + if (shape.isSetTxBody()) { + STTextAnchoringType.Enum val = shape.getTxBody().getBodyPr().getAnchor(); + if(val != null){ + return VerticalAlignment.values()[val.intValue() - 1]; + } + } + return VerticalAlignment.TOP; + } + + /** + * + * @param orientation vertical orientation of the text + */ + public void setTextDirection(TextDirection orientation){ + CTShape shape = (CTShape) getXmlObject(); + if (shape.isSetTxBody()) { + CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr(); + if(orientation == null) { + if(bodyPr.isSetVert()) bodyPr.unsetVert(); + } else { + bodyPr.setVert(STTextVerticalType.Enum.forInt(orientation.ordinal() + 1)); + } + } + } + + /** + * @return vertical orientation of the text + */ + public TextDirection getTextDirection(){ + CTShape shape = (CTShape) getXmlObject(); + if (shape.isSetTxBody()) { + STTextVerticalType.Enum val = shape.getTxBody().getBodyPr().getVert(); + if(val != null){ + return TextDirection.values()[val.intValue() - 1]; + } + } + return TextDirection.HORIZONTAL; + } + /** + * Returns the distance (in points) between the bottom of the text frame + * and the bottom of the inscribed rectangle of the shape that contains the text. + * + * @return the bottom margin or -1 if not set + */ + public double getMarginBottom(){ + CTShape shape = (CTShape) getXmlObject(); + if (shape.isSetTxBody()) { + CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr(); + return bodyPr.isSetBIns() ? Units.toPoints(bodyPr.getBIns()) : -1; + } + return -1; + } + + /** + * Returns the distance (in points) between the left edge of the text frame + * and the left edge of the inscribed rectangle of the shape that contains + * the text. + * + * @return the left margin + */ + public double getMarginLeft(){ + CTShape shape = (CTShape) getXmlObject(); + if (shape.isSetTxBody()) { + CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr(); + return bodyPr.isSetLIns() ? Units.toPoints(bodyPr.getLIns()) : -1; + } + return -1; + } + + /** + * Returns the distance (in points) between the right edge of the + * text frame and the right edge of the inscribed rectangle of the shape + * that contains the text. + * + * @return the right margin + */ + public double getMarginRight(){ + CTShape shape = (CTShape) getXmlObject(); + if (shape.isSetTxBody()) { + CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr(); + return bodyPr.isSetRIns() ? Units.toPoints(bodyPr.getRIns()) : -1; + } + return -1; + } + + /** + * Returns the distance (in points) between the top of the text frame + * and the top of the inscribed rectangle of the shape that contains the text. + * + * @return the top margin + */ + public double getMarginTop(){ + CTShape shape = (CTShape) getXmlObject(); + if (shape.isSetTxBody()) { + CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr(); + return bodyPr.isSetTIns() ? Units.toPoints(bodyPr.getTIns()) : -1; + } + return -1; + } + + /** + * Sets the botom margin. + * @see #getMarginBottom() + * + * @param margin the bottom margin + */ + public void setMarginBottom(double margin){ + CTShape shape = (CTShape) getXmlObject(); + if (shape.isSetTxBody()) { + CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr(); + if(margin == -1) bodyPr.unsetBIns(); + else bodyPr.setBIns(Units.toEMU(margin)); + } + } + + /** + * Sets the left margin. + * @see #getMarginLeft() + * + * @param margin the left margin + */ + public void setMarginLeft(double margin){ + CTShape shape = (CTShape) getXmlObject(); + if (shape.isSetTxBody()) { + CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr(); + if(margin == -1) bodyPr.unsetLIns(); + else bodyPr.setLIns(Units.toEMU(margin)); + } + } + + /** + * Sets the right margin. + * @see #getMarginRight() + * + * @param margin the right margin + */ + public void setMarginRight(double margin){ + CTShape shape = (CTShape) getXmlObject(); + if (shape.isSetTxBody()) { + CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr(); + if(margin == -1) bodyPr.unsetRIns(); + else bodyPr.setRIns(Units.toEMU(margin)); + } + } + + /** + * Sets the top margin. + * @see #getMarginTop() + * + * @param margin the top margin + */ + public void setMarginTop(double margin){ + CTShape shape = (CTShape) getXmlObject(); + if (shape.isSetTxBody()) { + CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr(); + if(margin == -1) bodyPr.unsetTIns(); + else bodyPr.setTIns(Units.toEMU(margin)); + } + } + + + /** + * Returns the value indicating word wrap. + * One of the Wrap* constants defined in this class. + * + * @return the value indicating word wrap + */ + public boolean getWordWrap(){ + CTShape shape = (CTShape) getXmlObject(); + if (shape.isSetTxBody()) { + return shape.getTxBody().getBodyPr().getWrap() == STTextWrappingType.SQUARE; + } + return false; + } + + /** + * Specifies how the text should be wrapped + * + * @param wrap the value indicating how the text should be wrapped + */ + public void setWordWrap(boolean wrap){ + CTShape shape = (CTShape) getXmlObject(); + if (shape.isSetTxBody()) { + shape.getTxBody().getBodyPr().setWrap(wrap ? STTextWrappingType.SQUARE : STTextWrappingType.NONE); + } + } + + /** + * + * Specifies that a shape should be auto-fit to fully contain the text described within it. + * Auto-fitting is when text within a shape is scaled in order to contain all the text inside + * + * @param value type of autofit + */ + public void setTextAutofit(TextAutofit value){ + CTShape shape = (CTShape) getXmlObject(); + if (shape.isSetTxBody()) { + CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr(); + if(bodyPr.isSetSpAutoFit()) bodyPr.unsetSpAutoFit(); + if(bodyPr.isSetNoAutofit()) bodyPr.unsetNoAutofit(); + if(bodyPr.isSetNormAutofit()) bodyPr.unsetNormAutofit(); + + switch(value){ + case NONE: bodyPr.addNewNoAutofit(); break; + case NORMAL: bodyPr.addNewNormAutofit(); break; + case SHAPE: bodyPr.addNewSpAutoFit(); break; + } + } + } + + /** + * + * @return type of autofit + */ + public TextAutofit getTextAutofit(){ + CTShape shape = (CTShape) getXmlObject(); + if (shape.isSetTxBody()) { + CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr(); + if(bodyPr.isSetNoAutofit()) return TextAutofit.NONE; + else if (bodyPr.isSetNormAutofit()) return TextAutofit.NORMAL; + else if (bodyPr.isSetSpAutoFit()) return TextAutofit.SHAPE; + } + return TextAutofit.NORMAL; + } + + + @Override + void onCopy(XSLFSheet srcSheet){ + CTShape shape = (CTShape) getXmlObject(); + if (!shape.isSetTxBody()) return; + + CTPlaceholder ph = shape.getNvSpPr().getNvPr().getPh(); + if(ph == null || !ph.isSetType()) return; + + if(ph.getType() == STPlaceholderType.TITLE){ + + } + } + +} \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFCommonSlideData.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFCommonSlideData.java index 22cde4f9b0..a561281552 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFCommonSlideData.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFCommonSlideData.java @@ -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 index 0000000000..d93c1351f6 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java @@ -0,0 +1,195 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import org.apache.poi.util.Beta; +import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; +import org.openxmlformats.schemas.drawingml.x2006.main.CTLineEndProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndType; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndWidth; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndLength; +import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector; +import org.openxmlformats.schemas.presentationml.x2006.main.CTConnectorNonVisual; + +/** + * + * Specifies a connection shape. + * + * @author Yegor Kozlov + */ +@Beta +public class XSLFConnectorShape extends XSLFSimpleShape { + + /*package*/ XSLFConnectorShape(CTConnector shape, XSLFSheet sheet){ + super(shape, sheet); + } + + /** + * @param shapeId 1-based shapeId + */ + static CTConnector prototype(int shapeId) { + CTConnector ct = CTConnector.Factory.newInstance(); + CTConnectorNonVisual nvSpPr = ct.addNewNvCxnSpPr(); + CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr(); + cnv.setName("Connector " + shapeId); + cnv.setId(shapeId + 1); + nvSpPr.addNewCNvCxnSpPr(); + nvSpPr.addNewNvPr(); + CTShapeProperties spPr = ct.addNewSpPr(); + CTPresetGeometry2D prst = spPr.addNewPrstGeom(); + prst.setPrst(STShapeType.LINE); + prst.addNewAvLst(); + CTLineProperties ln = spPr.addNewLn(); + return ct; + } + + /** + * Specifies the line end decoration, such as a triangle or arrowhead. + */ + public void setLineHeadDecoration(LineDecoration style){ + CTLineProperties ln = getSpPr().getLn(); + CTLineEndProperties lnEnd = ln.isSetHeadEnd() ? ln.getHeadEnd() : ln.addNewHeadEnd(); + if(style == null){ + if(lnEnd.isSetType()) lnEnd.unsetType(); + } else { + lnEnd.setType(STLineEndType.Enum.forInt(style.ordinal() + 1)); + } + } + + public LineDecoration getLineHeadDecoration(){ + CTLineProperties ln = getSpPr().getLn(); + if(!ln.isSetHeadEnd()) return LineDecoration.NONE; + + STLineEndType.Enum end = ln.getHeadEnd().getType(); + return end == null ? LineDecoration.NONE : LineDecoration.values()[end.intValue() - 1]; + } + + /** + * specifies decorations which can be added to the head of a line. + */ + public void setLineHeadWidth(LineEndWidth style){ + CTLineProperties ln = getSpPr().getLn(); + CTLineEndProperties lnEnd = ln.isSetHeadEnd() ? ln.getHeadEnd() : ln.addNewHeadEnd(); + if(style == null){ + if(lnEnd.isSetW()) lnEnd.unsetW(); + } else { + lnEnd.setW(STLineEndWidth.Enum.forInt(style.ordinal() + 1)); + } + } + + public LineEndWidth getLineHeadWidth(){ + CTLineProperties ln = getSpPr().getLn(); + if(!ln.isSetHeadEnd()) return null; + + STLineEndWidth.Enum w = ln.getHeadEnd().getW(); + return w == null ? null : LineEndWidth.values()[w.intValue() - 1]; + } + + /** + * Specifies the line end width in relation to the line width. + */ + public void setLineHeadLength(LineEndLength style){ + CTLineProperties ln = getSpPr().getLn(); + CTLineEndProperties lnEnd = ln.isSetHeadEnd() ? ln.getHeadEnd() : ln.addNewHeadEnd(); + + if(style == null){ + if(lnEnd.isSetLen()) lnEnd.unsetLen(); + } else { + lnEnd.setLen(STLineEndLength.Enum.forInt(style.ordinal() + 1)); + } + } + + public LineEndLength getLineHeadLength(){ + CTLineProperties ln = getSpPr().getLn(); + if(!ln.isSetHeadEnd()) return null; + + STLineEndLength.Enum len = ln.getHeadEnd().getLen(); + return len == null ? null : LineEndLength.values()[len.intValue() - 1]; + } + + /** + * Specifies the line end decoration, such as a triangle or arrowhead. + */ + public void setLineTailDecoration(LineDecoration style){ + CTLineProperties ln = getSpPr().getLn(); + CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd(); + if(style == null){ + if(lnEnd.isSetType()) lnEnd.unsetType(); + } else { + lnEnd.setType(STLineEndType.Enum.forInt(style.ordinal() + 1)); + } + } + + public LineDecoration getLineTailDecoration(){ + CTLineProperties ln = getSpPr().getLn(); + if(!ln.isSetTailEnd()) return LineDecoration.NONE; + + STLineEndType.Enum end = ln.getTailEnd().getType(); + return end == null ? LineDecoration.NONE : LineDecoration.values()[end.intValue() - 1]; + } + + /** + * specifies decorations which can be added to the tail of a line. + */ + public void setLineTailWidth(LineEndWidth style){ + CTLineProperties ln = getSpPr().getLn(); + CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd(); + if(style == null){ + if(lnEnd.isSetW()) lnEnd.unsetW(); + } else { + lnEnd.setW(STLineEndWidth.Enum.forInt(style.ordinal() + 1)); + } + } + + public LineEndWidth getLineTailWidth(){ + CTLineProperties ln = getSpPr().getLn(); + if(!ln.isSetTailEnd()) return null; + + STLineEndWidth.Enum w = ln.getTailEnd().getW(); + return w == null ? null : LineEndWidth.values()[w.intValue() - 1]; + } + + /** + * Specifies the line end width in relation to the line width. + */ + public void setLineTailLength(LineEndLength style){ + CTLineProperties ln = getSpPr().getLn(); + CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd(); + + if(style == null){ + if(lnEnd.isSetLen()) lnEnd.unsetLen(); + } else { + lnEnd.setLen(STLineEndLength.Enum.forInt(style.ordinal() + 1)); + } + } + + public LineEndLength getLineTailLength(){ + CTLineProperties ln = getSpPr().getLn(); + if(!ln.isSetTailEnd()) return null; + + STLineEndLength.Enum len = ln.getTailEnd().getLen(); + return len == null ? null : LineEndLength.values()[len.intValue() - 1]; + } + +} \ 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 index 0000000000..2f72bfc96a --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFDrawing.java @@ -0,0 +1,84 @@ +package org.apache.poi.xslf.usermodel; + +import org.apache.poi.sl.usermodel.ShapeContainer; +import org.apache.poi.util.Beta; +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; +import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector; +import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape; +import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture; +import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; + +import java.awt.*; + + +/** + * @author Yegor Kozlov + */ +@Beta +public class XSLFDrawing { + private XSLFSheet _sheet; + private int _shapeId = 1; + private CTGroupShape _spTree; + + /*package*/ XSLFDrawing(XSLFSheet sheet, CTGroupShape spTree){ + _sheet = sheet; + _spTree = spTree; + XmlObject[] cNvPr = sheet.getSpTree().selectPath( + "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:cNvPr"); + for(XmlObject o : cNvPr) { + CTNonVisualDrawingProps p = (CTNonVisualDrawingProps)o; + _shapeId = (int)Math.max(_shapeId, p.getId()); + } + } + + public XSLFAutoShape createAutoShape(){ + CTShape sp = _spTree.addNewSp(); + sp.set(XSLFAutoShape.prototype(_shapeId++)); + XSLFAutoShape shape = new XSLFAutoShape(sp, _sheet); + shape.setAnchor(new Rectangle()); + return shape; + } + + public XSLFFreeformShape createFreeform(){ + CTShape sp = _spTree.addNewSp(); + sp.set(XSLFFreeformShape.prototype(_shapeId++)); + XSLFFreeformShape shape = new XSLFFreeformShape(sp, _sheet); + shape.setAnchor(new Rectangle()); + return shape; + } + + public XSLFTextBox createTextBox(){ + CTShape sp = _spTree.addNewSp(); + sp.set(XSLFTextBox.prototype(_shapeId++)); + XSLFTextBox shape = new XSLFTextBox(sp, _sheet); + shape.setAnchor(new Rectangle()); + return shape; + } + + public XSLFConnectorShape createConnector(){ + CTConnector sp = _spTree.addNewCxnSp(); + sp.set(XSLFConnectorShape.prototype(_shapeId++)); + XSLFConnectorShape shape = new XSLFConnectorShape(sp, _sheet); + shape.setAnchor(new Rectangle()); + shape.setLineColor(Color.black); + shape.setLineWidth(0.75); + return shape; + } + + public XSLFGroupShape createGroup(){ + CTGroupShape obj = _spTree.addNewGrpSp(); + obj.set(XSLFGroupShape.prototype(_shapeId++)); + XSLFGroupShape shape = new XSLFGroupShape(obj, _sheet); + shape.setAnchor(new Rectangle()); + return shape; + } + + public XSLFPictureShape createPicture(String rel){ + CTPicture obj = _spTree.addNewPic(); + obj.set(XSLFPictureShape.prototype(_shapeId++, rel)); + XSLFPictureShape shape = new XSLFPictureShape(obj, _sheet); + shape.setAnchor(new Rectangle()); + return shape; + } +} 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 index 0000000000..cb7f329181 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFFactory.java @@ -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 cls = descriptor.getRelationClass(); + Constructor 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 cls = descriptor.getRelationClass(); + Constructor 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 index 0000000000..a494a3cab9 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFFreeformShape.java @@ -0,0 +1,178 @@ +/* + * ==================================================================== + * 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.sl.usermodel.ShapeContainer; +import org.apache.poi.util.Beta; +import org.apache.poi.util.Units; +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.drawingml.x2006.main.CTAdjPoint2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTCustomGeometry2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTGeomRect; +import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPath2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPath2DClose; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPath2DCubicBezierTo; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPath2DLineTo; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPath2DMoveTo; +import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; +import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; +import org.openxmlformats.schemas.presentationml.x2006.main.CTShapeNonVisual; + +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; +import java.awt.geom.PathIterator; +import java.awt.geom.Rectangle2D; + +/** + * Represents a custom geometric shape. + * This shape will consist of a series of lines and curves described within a creation path. + * + * @author Yegor Kozlov + */ +@Beta +public class XSLFFreeformShape extends XSLFAutoShape { + + /*package*/ XSLFFreeformShape(CTShape shape, XSLFSheet sheet) { + super(shape, sheet); + } + + /** + * Set the shape path + * + * @param path shape outline + * @return the number of points written + */ + public int setPath(GeneralPath path) { + CTPath2D ctPath = CTPath2D.Factory.newInstance(); + + Rectangle2D bounds = path.getBounds2D(); + int x0 = Units.toEMU(bounds.getX()); + int y0 = Units.toEMU(bounds.getY()); + PathIterator it = path.getPathIterator(new AffineTransform()); + int numPoints = 0; + ctPath.setH(Units.toEMU(bounds.getHeight())); + ctPath.setW(Units.toEMU(bounds.getWidth())); + while (!it.isDone()) { + double[] vals = new double[6]; + int type = it.currentSegment(vals); + switch (type) { + case PathIterator.SEG_MOVETO: + CTAdjPoint2D mv = ctPath.addNewMoveTo().addNewPt(); + mv.setX(Units.toEMU(vals[0]) - x0); + mv.setY(Units.toEMU(vals[1]) - y0); + numPoints++; + break; + case PathIterator.SEG_LINETO: + CTAdjPoint2D ln = ctPath.addNewLnTo().addNewPt(); + ln.setX(Units.toEMU(vals[0]) - x0); + ln.setY(Units.toEMU(vals[1]) - y0); + numPoints++; + break; + case PathIterator.SEG_CUBICTO: + CTPath2DCubicBezierTo bez = ctPath.addNewCubicBezTo(); + CTAdjPoint2D p1 = bez.addNewPt(); + p1.setX(Units.toEMU(vals[0]) - x0); + p1.setY(Units.toEMU(vals[1]) - y0); + CTAdjPoint2D p2 = bez.addNewPt(); + p2.setX(Units.toEMU(vals[2]) - x0); + p2.setY(Units.toEMU(vals[3]) - y0); + CTAdjPoint2D p3 = bez.addNewPt(); + p3.setX(Units.toEMU(vals[4]) - x0); + p3.setY(Units.toEMU(vals[5]) - y0); + numPoints += 3; + break; + case PathIterator.SEG_CLOSE: + numPoints++; + ctPath.addNewClose(); + break; + } + it.next(); + } + getSpPr().getCustGeom().getPathLst().setPathArray(new CTPath2D[]{ctPath}); + setAnchor(bounds); + return numPoints; + } + + public GeneralPath getPath() { + GeneralPath path = new GeneralPath(); + Rectangle2D bounds = getAnchor(); + int x0 = Units.toEMU(bounds.getX()); + int y0 = Units.toEMU(bounds.getY()); + CTCustomGeometry2D geom = getSpPr().getCustGeom(); + for(CTPath2D spPath : geom.getPathLst().getPathList()){ + for(XmlObject ch : spPath.selectPath("*")){ + if(ch instanceof CTPath2DMoveTo){ + CTAdjPoint2D pt = ((CTPath2DMoveTo)ch).getPt(); + path.moveTo(Units.toPoints((Long)pt.getX() + x0), + Units.toPoints((Long)pt.getY() + y0)); + } else if (ch instanceof CTPath2DLineTo){ + CTAdjPoint2D pt = ((CTPath2DLineTo)ch).getPt(); + path.lineTo(Units.toPoints((Long)pt.getX() + x0), + Units.toPoints((Long)pt.getY() + y0)); + } else if (ch instanceof CTPath2DCubicBezierTo){ + CTPath2DCubicBezierTo bez = ((CTPath2DCubicBezierTo)ch); + CTAdjPoint2D pt1 = bez.getPtArray(0); + CTAdjPoint2D pt2 = bez.getPtArray(1); + CTAdjPoint2D pt3 = bez.getPtArray(2); + path.curveTo( + Units.toPoints((Long) pt1.getX() + x0), + Units.toPoints((Long) pt1.getY() + y0), + Units.toPoints((Long) pt2.getX() + x0), + Units.toPoints((Long) pt2.getY() + y0), + Units.toPoints((Long) pt3.getX() + x0), + Units.toPoints((Long) pt3.getY() + y0) + ); + + } else if (ch instanceof CTPath2DClose){ + path.closePath(); + } + } + } + + return path; + } + /** + * @param shapeId 1-based shapeId + */ + static CTShape prototype(int shapeId) { + CTShape ct = CTShape.Factory.newInstance(); + CTShapeNonVisual nvSpPr = ct.addNewNvSpPr(); + CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr(); + cnv.setName("Freeform " + shapeId); + cnv.setId(shapeId + 1); + nvSpPr.addNewCNvSpPr(); + nvSpPr.addNewNvPr(); + CTShapeProperties spPr = ct.addNewSpPr(); + CTCustomGeometry2D geom = spPr.addNewCustGeom(); + geom.addNewAvLst(); + geom.addNewGdLst(); + geom.addNewAhLst(); + geom.addNewCxnLst(); + CTGeomRect rect = geom.addNewRect(); + rect.setR("r"); + rect.setB("b"); + rect.setT("t"); + rect.setL("l"); + geom.addNewPathLst(); + return ct; + } + +} \ 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 index 0000000000..0abad44f30 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGraphicFrame.java @@ -0,0 +1,79 @@ +/* + * ==================================================================== + * 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.sl.usermodel.Shape; +import org.apache.poi.sl.usermodel.ShapeContainer; +import org.apache.poi.sl.usermodel.ShapeGroup; +import org.apache.poi.util.Beta; +import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame; + +import java.awt.geom.Rectangle2D; + +/** + * @author Yegor Kozlov + */ +@Beta +public class XSLFGraphicFrame extends XSLFShape { + private final CTGraphicalObjectFrame _shape; + private final XSLFSheet _sheet; + + /*package*/ XSLFGraphicFrame(CTGraphicalObjectFrame shape, XSLFSheet sheet){ + _shape = shape; + _sheet = sheet; + } + + public CTGraphicalObjectFrame getXmlObject(){ + return _shape; + } + + public int getShapeType(){ + throw new RuntimeException("NotImplemented"); + } + + public int getShapeId(){ + return (int)_shape.getNvGraphicFramePr().getCNvPr().getId(); + } + + public String getShapeName(){ + return _shape.getNvGraphicFramePr().getCNvPr().getName(); + } + + public Rectangle2D getAnchor(){ + throw new RuntimeException("NotImplemented"); + } + + public void setAnchor(Rectangle2D anchor){ + throw new RuntimeException("NotImplemented"); + } + + public ShapeGroup getParent(){ + throw new RuntimeException("NotImplemented"); + } + + public Shape[] getShapes(){ + throw new RuntimeException("NotImplemented"); + } + + + public boolean removeShape(Shape shape){ + throw new RuntimeException("NotImplemented"); + } +} \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java new file mode 100755 index 0000000000..804420854d --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java @@ -0,0 +1,220 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.openxml4j.opc.TargetMode; +import org.apache.poi.sl.usermodel.Shape; +import org.apache.poi.sl.usermodel.ShapeContainer; +import org.apache.poi.sl.usermodel.ShapeGroup; +import org.apache.poi.util.Beta; +import org.apache.poi.util.Units; +import org.apache.xmlbeans.XmlObject; +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.CTConnector; +import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape; +import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShapeNonVisual; +import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; + +import java.awt.geom.Rectangle2D; +import java.util.List; +import java.util.regex.Pattern; + +/** + * Represents a group shape that consists of many shapes grouped together. + * + * @author Yegor Kozlov + */ +@Beta +public class XSLFGroupShape extends XSLFShape { + private final CTGroupShape _shape; + private final XSLFSheet _sheet; + private final List _shapes; + private final CTGroupShapeProperties _spPr; + private XSLFDrawing _drawing; + + /*package*/ XSLFGroupShape(CTGroupShape shape, XSLFSheet sheet){ + _shape = shape; + _sheet = sheet; + + _shapes = _sheet.buildShapes(_shape); + _spPr = shape.getGrpSpPr(); + } + + public CTGroupShape getXmlObject(){ + return _shape; + } + + public Rectangle2D getAnchor(){ + CTGroupTransform2D xfrm = _spPr.getXfrm(); + CTPoint2D off = xfrm.getOff(); + long x = off.getX(); + long y = off.getY(); + CTPositiveSize2D ext = xfrm.getExt(); + long cx = ext.getCx(); + long cy = ext.getCy(); + return new Rectangle2D.Double( + Units.toPoints(x), Units.toPoints(y), + Units.toPoints(cx), Units.toPoints(cy)); + } + + public void setAnchor(Rectangle2D anchor){ + CTGroupTransform2D xfrm = _spPr.isSetXfrm() ? _spPr.getXfrm() : _spPr.addNewXfrm(); + CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff(); + long x = Units.toEMU(anchor.getX()); + long y = Units.toEMU(anchor.getY()); + off.setX(x); + off.setY(y); + CTPositiveSize2D ext = xfrm.isSetExt() ? xfrm.getExt() : xfrm.addNewExt(); + long cx = Units.toEMU(anchor.getWidth()); + long cy = Units.toEMU(anchor.getHeight()); + ext.setCx(cx); + ext.setCy(cy); + } + + public Rectangle2D getInteriorAnchor(){ + CTGroupTransform2D xfrm = _spPr.getXfrm(); + CTPoint2D off = xfrm.getChOff(); + long x = off.getX(); + long y = off.getY(); + CTPositiveSize2D ext = xfrm.getChExt(); + long cx = ext.getCx(); + long cy = ext.getCy(); + return new Rectangle2D.Double( + Units.toPoints(x), Units.toPoints(y), + Units.toPoints(cx), Units.toPoints(cy)); + } + + public void setInteriorAnchor(Rectangle2D anchor){ + CTGroupTransform2D xfrm = _spPr.isSetXfrm() ? _spPr.getXfrm() : _spPr.addNewXfrm(); + CTPoint2D off = xfrm.isSetChOff() ? xfrm.getChOff() : xfrm.addNewChOff(); + long x = Units.toEMU(anchor.getX()); + long y = Units.toEMU(anchor.getY()); + off.setX(x); + off.setY(y); + CTPositiveSize2D ext = xfrm.isSetChExt() ? xfrm.getChExt() : xfrm.addNewChExt(); + long cx = Units.toEMU(anchor.getWidth()); + long cy = Units.toEMU(anchor.getHeight()); + ext.setCx(cx); + ext.setCy(cy); + } + + public XSLFShape[] getShapes(){ + return _shapes.toArray(new XSLFShape[_shapes.size()]); + } + + public boolean removeShape(XSLFShape xShape) { + XmlObject obj = xShape.getXmlObject(); + if(obj instanceof CTShape){ + _shape.getSpList().remove(obj); + } else if (obj instanceof CTGroupShape){ + _shape.getGrpSpList().remove(obj); + } else if (obj instanceof CTConnector){ + _shape.getCxnSpList().remove(obj); + } else { + throw new IllegalArgumentException("Unsupported shape: " + xShape); + } + return _shapes.remove(xShape); + } + + public String getShapeName(){ + return _shape.getNvGrpSpPr().getCNvPr().getName(); + } + + public int getShapeId(){ + return (int)_shape.getNvGrpSpPr().getCNvPr().getId(); + } + + /** + * @param shapeId 1-based shapeId + */ + static CTGroupShape prototype(int shapeId) { + CTGroupShape ct = CTGroupShape.Factory.newInstance(); + CTGroupShapeNonVisual nvSpPr = ct.addNewNvGrpSpPr(); + CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr(); + cnv.setName("Group " + shapeId); + cnv.setId(shapeId + 1); + + nvSpPr.addNewCNvGrpSpPr(); + nvSpPr.addNewNvPr(); + ct.addNewGrpSpPr(); + return ct; + } + + // shape factory methods + private XSLFDrawing getDrawing(){ + if(_drawing == null) { + _drawing = new XSLFDrawing(_sheet, _shape); + } + return _drawing; + } + + public XSLFAutoShape createAutoShape(){ + XSLFAutoShape sh = getDrawing().createAutoShape(); + _shapes.add(sh); + return sh; + } + + public XSLFFreeformShape createFreeform(){ + XSLFFreeformShape sh = getDrawing().createFreeform(); + _shapes.add(sh); + return sh; + } + + public XSLFTextBox createTextBox(){ + XSLFTextBox sh = getDrawing().createTextBox(); + _shapes.add(sh); + return sh; + } + + public XSLFConnectorShape createConnector(){ + XSLFConnectorShape sh = getDrawing().createConnector(); + _shapes.add(sh); + return sh; + } + + public XSLFGroupShape createGroup(){ + XSLFGroupShape sh = getDrawing().createGroup(); + _shapes.add(sh); + return sh; + } + + public XSLFPictureShape createPicture(int pictureIndex){ + + List pics = _sheet.getPackagePart().getPackage() + .getPartsByName(Pattern.compile("/ppt/media/.*?")); + + PackagePart pic = pics.get(pictureIndex); + + PackageRelationship rel = _sheet.getPackagePart().addRelationship( + pic.getPartName(), TargetMode.INTERNAL, XSLFRelation.IMAGES.getRelation()); + + XSLFPictureShape sh = getDrawing().createPicture(rel.getId()); + sh.resize(); + _shapes.add(sh); + return sh; + } + +} \ 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 index 0000000000..6fd151ff17 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java @@ -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. + *

+ * 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: + *
+ * + * InputStream is = getPackagePart().getInputStream(); + * + *

+ * + * @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 index 0000000000..c2ce2bd969 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java @@ -0,0 +1,107 @@ +/* + * ==================================================================== + * 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.sl.usermodel.ShapeContainer; +import org.apache.poi.util.Beta; +import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip; +import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; +import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture; +import org.openxmlformats.schemas.presentationml.x2006.main.CTPictureNonVisual; + +import javax.imageio.ImageIO; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; + +/** + * @author Yegor Kozlov + */ +@Beta +public class XSLFPictureShape extends XSLFSimpleShape { + private XSLFPictureData _data; + + /*package*/ XSLFPictureShape(CTPicture shape, XSLFSheet sheet) { + super(shape, sheet); + } + + + /** + * @param shapeId 1-based shapeId + * @param rel relationship to the picture data in the ooxml package + */ + static CTPicture prototype(int shapeId, String rel) { + CTPicture ct = CTPicture.Factory.newInstance(); + CTPictureNonVisual nvSpPr = ct.addNewNvPicPr(); + CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr(); + cnv.setName("Picture " + shapeId); + cnv.setId(shapeId + 1); + nvSpPr.addNewCNvPicPr().addNewPicLocks().setNoChangeAspect(true); + nvSpPr.addNewNvPr(); + + CTBlipFillProperties blipFill = ct.addNewBlipFill(); + CTBlip blip = blipFill.addNewBlip(); + blip.setEmbed(rel); + blipFill.addNewStretch().addNewFillRect(); + + CTShapeProperties spPr = ct.addNewSpPr(); + CTPresetGeometry2D prst = spPr.addNewPrstGeom(); + prst.setPrst(STShapeType.RECT); + prst.addNewAvLst(); + return ct; + } + + /** + * Resize this picture to the default size. + * For PNG and JPEG resizes the image to 100%, + * for other types sets the default size of 200x200 pixels. + */ + public void resize() { + XSLFPictureData pict = getPictureData(); + + try { + BufferedImage img = ImageIO.read(new ByteArrayInputStream(pict.getData())); + setAnchor(new Rectangle2D.Double(0, 0, img.getWidth(), img.getHeight())); + } + catch (Exception e) { + //default size is 200x200 + setAnchor(new java.awt.Rectangle(50, 50, 200, 200)); + } + } + + public XSLFPictureData getPictureData() { + if(_data == null){ + CTPicture ct = (CTPicture)getXmlObject(); + String blipId = ct.getBlipFill().getBlip().getEmbed(); + + for (POIXMLDocumentPart part : getSheet().getRelations()) { + if(part.getPackageRelationship().getId().equals(blipId)){ + _data = (XSLFPictureData)part; + } + } + } + return _data; + } +} \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFRelation.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFRelation.java index 29cf65809e..c546d93dfc 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFRelation.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFRelation.java @@ -16,14 +16,16 @@ ==================================================================== */ 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 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 index 0000000000..b1b65eac40 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java @@ -0,0 +1,48 @@ +/* + * ==================================================================== + * 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.sl.usermodel.Shape; +import org.apache.poi.util.Beta; +import org.apache.xmlbeans.XmlObject; + +import java.awt.geom.Rectangle2D; + +/** + * @author Yegor Kozlov + */ +@Beta +public abstract class XSLFShape { + + + public abstract Rectangle2D getAnchor(); + + public abstract void setAnchor(Rectangle2D anchor); + + public abstract XmlObject getXmlObject(); + + public abstract String getShapeName(); + + public abstract int getShapeId(); + + void onCopy(XSLFSheet srcSheet){ + + } +} \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java index 3bbd099c0e..02ce9fdb7d 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java @@ -16,44 +16,199 @@ ==================================================================== */ 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 _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 buildShapes(CTGroupShape spTree){ + List shapes = new ArrayList(); + 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 getShapeList(){ + if(_shapes == null){ + _shapes = buildShapes(getSpTree()); + } + return _shapes; + } + + // shape factory methods + + public XSLFAutoShape createAutoShape(){ + List shapes = getShapeList(); + XSLFAutoShape sh = getDrawing().createAutoShape(); + shapes.add(sh); + return sh; + } + + public XSLFFreeformShape createFreeform(){ + List shapes = getShapeList(); + XSLFFreeformShape sh = getDrawing().createFreeform(); + shapes.add(sh); + return sh; + } + + public XSLFTextBox createTextBox(){ + List shapes = getShapeList(); + XSLFTextBox sh = getDrawing().createTextBox(); + shapes.add(sh); + return sh; + } + + public XSLFConnectorShape createConnector(){ + List shapes = getShapeList(); + XSLFConnectorShape sh = getDrawing().createConnector(); + shapes.add(sh); + return sh; + } + + public XSLFGroupShape createGroup(){ + List shapes = getShapeList(); + XSLFGroupShape sh = getDrawing().createGroup(); + shapes.add(sh); + return sh; + } + + public XSLFPictureShape createPicture(int pictureIndex){ + List 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 map = new HashMap(); + 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 index 0000000000..3b624dc0ab --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java @@ -0,0 +1,268 @@ +/* + * ==================================================================== + * 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.xslf.usermodel.LineCap; +import org.apache.poi.xslf.usermodel.LineDash; +import org.apache.poi.util.Beta; +import org.apache.poi.util.Units; +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties; +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.drawingml.x2006.main.CTPresetLineDashProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor; +import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap; +import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal; +import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; + +import java.awt.*; +import java.awt.geom.Rectangle2D; + +/** + * @author Yegor Kozlov + */ +@Beta +public abstract class XSLFSimpleShape extends XSLFShape { + private final XmlObject _shape; + private final XSLFSheet _sheet; + private CTShapeProperties _spPr; + private CTNonVisualDrawingProps _nvPr; + + /*package*/ XSLFSimpleShape(XmlObject shape, XSLFSheet sheet){ + _shape = shape; + _sheet = sheet; + } + + public XmlObject getXmlObject(){ + return _shape; + } + + public XSLFSheet getSheet(){ + return _sheet; + } + /** + * TODO match STShapeType with {@link org.apache.poi.sl.usermodel.ShapeTypes} + */ + public int getShapeType() { + STShapeType.Enum stEnum = getSpPr().getPrstGeom().getPrst(); + return stEnum.intValue(); + } + + public String getShapeName() { + return getNvPr().getName(); + } + + public int getShapeId() { + return (int)getNvPr().getId(); + } + + protected CTNonVisualDrawingProps getNvPr(){ + if(_nvPr == null){ + XmlObject[] rs = _shape.selectPath( + "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:cNvPr"); + if(rs.length != 0) { + _nvPr = (CTNonVisualDrawingProps)rs[0]; + } + } + return _nvPr; + } + + protected CTShapeProperties getSpPr(){ + if(_spPr == null) { + for(XmlObject obj : _shape.selectPath("*")){ + if(obj instanceof CTShapeProperties){ + _spPr = (CTShapeProperties)obj; + } + } + } + if(_spPr == null) { + throw new IllegalStateException("CTShapeProperties was not found."); + } + return _spPr; + } + + public Rectangle2D getAnchor(){ + CTTransform2D xfrm = getSpPr().getXfrm(); + CTPoint2D off = xfrm.getOff(); + long x = off.getX(); + long y = off.getY(); + CTPositiveSize2D ext = xfrm.getExt(); + long cx = ext.getCx(); + long cy = ext.getCy(); + return new Rectangle2D.Double( + Units.toPoints(x), Units.toPoints(y), + Units.toPoints(cx), Units.toPoints(cy)); + } + + public void setAnchor(Rectangle2D anchor){ + CTTransform2D xfrm = getSpPr().isSetXfrm() ? getSpPr().getXfrm() : getSpPr().addNewXfrm(); + CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff(); + long x = Units.toEMU(anchor.getX()); + long y = Units.toEMU(anchor.getY()); + off.setX(x); + off.setY(y); + CTPositiveSize2D ext = xfrm.isSetExt() ? xfrm.getExt() : xfrm.addNewExt(); + long cx = Units.toEMU(anchor.getWidth()); + long cy = Units.toEMU(anchor.getHeight()); + ext.setCx(cx); + ext.setCy(cy); + } + + /** + * Rotate this shape. + *

+ * Positive angles are clockwise (i.e., towards the positive y axis); + * negative angles are counter-clockwise (i.e., towards the negative y axis). + *

+ * + * @param theta the rotation angle in degrees. + */ + public void setRotation(double theta){ + CTTransform2D xfrm = getSpPr().getXfrm(); + xfrm.setRot((int)(theta*60000)); + } + + /** + * Rotation angle in degrees + *

+ * Positive angles are clockwise (i.e., towards the positive y axis); + * negative angles are counter-clockwise (i.e., towards the negative y axis). + *

+ * + * @return rotation angle in degrees + */ + public double getRotation(){ + CTTransform2D xfrm = getSpPr().getXfrm(); + return (double)xfrm.getRot()/60000; + } + + public void setFlipHorizontal(boolean flip){ + CTTransform2D xfrm = getSpPr().getXfrm(); + xfrm.setFlipH(flip); + } + + public void setFlipVertical(boolean flip){ + CTTransform2D xfrm = getSpPr().getXfrm(); + xfrm.setFlipV(flip); + } + /** + * Whether the shape is horizontally flipped + * + * @return whether the shape is horizontally flipped + */ + public boolean getFlipHorizontal(){ + return getSpPr().getXfrm().getFlipH(); + } + + public boolean getFlipVertical(){ + return getSpPr().getXfrm().getFlipV(); + } + + public void setLineColor(Color color){ + CTShapeProperties spPr = getSpPr(); + if(color == null) { + if(spPr.isSetLn() && spPr.getLn().isSetSolidFill()) spPr.getLn().unsetSolidFill(); + } + else { + CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr.addNewLn(); + + CTSRgbColor rgb = CTSRgbColor.Factory.newInstance(); + rgb.setVal(new byte[]{(byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue()}); + + CTSolidColorFillProperties fill = ln.isSetSolidFill() ? ln.getSolidFill() : ln.addNewSolidFill(); + fill.setSrgbClr(rgb); + } + } + + public Color getLineColor(){ + CTShapeProperties spPr = getSpPr(); + if(!spPr.isSetLn() || !spPr.getLn().isSetSolidFill()) return null; + + CTSRgbColor rgb = spPr.getLn().getSolidFill().getSrgbClr(); + byte[] val = rgb.getVal(); + return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]); + } + + public void setLineWidth(double width){ + CTShapeProperties spPr = getSpPr(); + if(width == 0.) { + if(spPr.isSetLn()) spPr.getLn().unsetW(); + } + else { + CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr.addNewLn(); + ln.setW(Units.toEMU(width)); + } + } + + public double getLineWidth(){ + CTShapeProperties spPr = getSpPr(); + CTLineProperties ln = spPr.getLn(); + if(ln == null || !ln.isSetW()) return 0; + + return Units.toPoints(ln.getW()); + } + + public void setLineDash(LineDash dash){ + CTShapeProperties spPr = getSpPr(); + if(dash == null) { + if(spPr.isSetLn()) spPr.getLn().unsetPrstDash(); + } + else { + CTPresetLineDashProperties val = CTPresetLineDashProperties.Factory.newInstance(); + val.setVal(STPresetLineDashVal.Enum.forInt(dash.ordinal() + 1)); + CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr.addNewLn(); + ln.setPrstDash(val); + } + } + + public LineDash getLineDash(){ + CTShapeProperties spPr = getSpPr(); + CTLineProperties ln = spPr.getLn(); + if(ln == null || !ln.isSetPrstDash()) return null; + + CTPresetLineDashProperties dash = ln.getPrstDash(); + return LineDash.values()[dash.getVal().intValue() - 1]; + } + + public void setLineCap(LineCap cap){ + CTShapeProperties spPr = getSpPr(); + if(cap == null) { + if(spPr.isSetLn()) spPr.getLn().unsetCap(); + } + else { + CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr.addNewLn(); + ln.setCap(STLineCap.Enum.forInt(cap.ordinal() + 1)); + } + } + + public LineCap getLineCap(){ + CTShapeProperties spPr = getSpPr(); + CTLineProperties ln = spPr.getLn(); + if(ln == null || !ln.isSetCap()) return null; + + return LineCap.values()[ln.getCap().intValue() - 1]; + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java index 29af4941ec..f864344d71 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java @@ -16,82 +16,124 @@ ==================================================================== */ 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 application/vnd.openxmlformats-officedocument.drawing+xml + * @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 index 0000000000..871ece50dd --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideLayout.java @@ -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. + *

+ * Within a slide master slide are contained all elements + * that describe the objects and their corresponding formatting + * for within a presentation slide. + *

+ *

+ * 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. + *

+ * + * @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 index 0000000000..d7c86407a2 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideMaster.java @@ -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. +*

+* Within a slide master slide are contained all elements +* that describe the objects and their corresponding formatting +* for within a presentation slide. +*

+*

+* 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. +*

+ * + * @author Yegor Kozlov +*/ +@Beta + public class XSLFSlideMaster extends XSLFSheet { + private CTSlideMaster _slide; + private Map _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(); + 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 index 0000000000..c009f5492d --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextBox.java @@ -0,0 +1,97 @@ +/* + * ==================================================================== + * 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.sl.usermodel.ShapeContainer; +import org.apache.poi.util.Beta; +import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody; +import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; +import org.openxmlformats.schemas.presentationml.x2006.main.CTApplicationNonVisualDrawingProps; +import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder; +import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; +import org.openxmlformats.schemas.presentationml.x2006.main.CTShapeNonVisual; +import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType; + + +/** + * @author Yegor Kozlov + */ +@Beta +public class XSLFTextBox extends XSLFAutoShape { + + /*package*/ XSLFTextBox(CTShape shape, XSLFSheet sheet){ + super(shape, sheet); + } + + /** + * + * @param shapeId 1-based shapeId + */ + static CTShape prototype(int shapeId){ + CTShape ct = CTShape.Factory.newInstance(); + CTShapeNonVisual nvSpPr = ct.addNewNvSpPr(); + CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr(); + cnv.setName("TextBox " + shapeId); + cnv.setId(shapeId + 1); + nvSpPr.addNewCNvSpPr().setTxBox(true); + nvSpPr.addNewNvPr(); + CTShapeProperties spPr = ct.addNewSpPr(); + CTPresetGeometry2D prst = spPr.addNewPrstGeom(); + prst.setPrst(STShapeType.RECT); + prst.addNewAvLst(); + CTTextBody txBody = ct.addNewTxBody(); + txBody.addNewBodyPr(); + txBody.addNewLstStyle(); + + return ct; + } + + /** + * Specifies that the corresponding shape should be represented by the generating application + * as a placeholder. When a shape is considered a placeholder by the generating application + * it can have special properties to alert the user that they may enter content into the shape. + * Different types of placeholders are allowed and can be specified by using the placeholder + * type attribute for this element + * + * @param placeholder + */ + public void setPlaceholder(Placeholder placeholder){ + CTShape sh = (CTShape)getXmlObject(); + CTApplicationNonVisualDrawingProps nv = sh.getNvSpPr().getNvPr(); + if(placeholder == null) { + if(nv.isSetPh()) nv.unsetPh(); + } else { + nv.addNewPh().setType(STPlaceholderType.Enum.forInt(placeholder.ordinal() + 1)); + } + } + + public Placeholder getPlaceholder(){ + CTShape sh = (CTShape)getXmlObject(); + CTPlaceholder ph = sh.getNvSpPr().getNvPr().getPh(); + if(ph == null) return null; + else { + int val = ph.getType().intValue(); + return Placeholder.values()[val - 1]; + } + } +} \ 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 index 0000000000..9317298ee3 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java @@ -0,0 +1,334 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import org.apache.poi.util.Beta; +import org.apache.poi.util.Internal; +import org.apache.poi.util.Units; +import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextSpacing; +import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Represents a paragraph of text within the containing text body. + * The paragraph is the highest level text separation mechanism. + * + * @author Yegor Kozlov + * @since POI-3.8 + */ +@Beta +public class XSLFTextParagraph implements Iterable{ + private final CTTextParagraph _p; + private final List _runs; + + XSLFTextParagraph(CTTextParagraph p){ + _p = p; + _runs = new ArrayList(); + for (CTRegularTextRun r : _p.getRList()) { + _runs.add(new XSLFTextRun(r)); + } + } + + public String getText(){ + StringBuilder out = new StringBuilder(); + for (CTRegularTextRun r : _p.getRList()) { + out.append(r.getT()); + } + return out.toString(); + } + + @Internal + public CTTextParagraph getXmlObject(){ + return _p; + } + + public List getTextRuns(){ + return _runs; + } + + public Iterator iterator(){ + return _runs.iterator(); + } + + public XSLFTextRun addNewTextRun(){ + CTRegularTextRun r = _p.addNewR(); + XSLFTextRun run = new XSLFTextRun(r); + _runs.add(run); + return run; + } + + public void addLineBreak(){ + _p.addNewBr(); + } + + /** + * Returns the alignment that is applied to the paragraph. + * + * If this attribute is omitted, then a value of left is implied. + * @return ??? alignment that is applied to the paragraph + */ + public TextAlign getTextAlign(){ + CTTextParagraphProperties pr = _p.getPPr(); + if(pr == null || !pr.isSetAlgn()) return TextAlign.LEFT; + + return TextAlign.values()[pr.getAlgn().intValue() - 1]; + } + + /** + * Specifies the alignment that is to be applied to the paragraph. + * Possible values for this include left, right, centered, justified and distributed, + * see {@link org.apache.poi.xslf.usermodel.TextAlign}. + * + * @param align text align + */ + public void setTextAlign(TextAlign align){ + CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); + if(align == null) { + if(pr.isSetAlgn()) pr.unsetAlgn(); + } else { + pr.setAlgn(STTextAlignType.Enum.forInt(align.ordinal() + 1)); + } + } + + /** + * Specifies the indent size that will be applied to the first line of text in the paragraph. + * + * @param value the indent in points. The value of -1 unsets the indent attribute + * from the underlying xml bean. + */ + public void setIndent(double value){ + CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); + if(value == -1) { + if(pr.isSetIndent()) pr.unsetIndent(); + } else { + pr.setIndent(Units.toEMU(value)); + } + } + + /** + * + * @return the indent applied to the first line of text in the paragraph. + */ + public double getIndent(){ + CTTextParagraphProperties pr = _p.getPPr(); + if(pr == null || !pr.isSetIndent()) return 0; + + return Units.toPoints(pr.getIndent()); + } + + /** + * Specifies the left margin of the paragraph. This is specified in addition to the text body + * inset and applies only to this text paragraph. That is the text body Inset and the LeftMargin + * attributes are additive with respect to the text position. + * + * @param value the left margin of the paragraph + */ + public void setLeftMargin(double value){ + CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); + pr.setMarL(Units.toEMU(value)); + } + + /** + * + * @return the left margin of the paragraph + */ + public double getLeftMargin(){ + CTTextParagraphProperties pr = _p.getPPr(); + if(pr == null || !pr.isSetMarL()) return 0; + + return Units.toPoints(pr.getMarL()); + } + + /** + * This element specifies the vertical line spacing that is to be used within a paragraph. + * This may be specified in two different ways, percentage spacing and font point spacing: + *

+ * If linespacing >= 0, then linespacing is a percentage of normal line height + * If linespacing < 0, the absolute value of linespacing is the spacing in points + *

+ * Examples: + *

+     *      // spacing will be 120% of the size of the largest text on each line
+     *      paragraph.setLineSpacing(120);
+     *
+     *      // spacing will be 200% of the size of the largest text on each line
+     *      paragraph.setLineSpacing(200);
+     *
+     *      // spacing will be 48 points
+     *      paragraph.setLineSpacing(-48.0);
+     * 
+ * + * @param linespacing the vertical line spacing + */ + public void setLineSpacing(double linespacing){ + CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); + CTTextSpacing spc = CTTextSpacing.Factory.newInstance(); + if(linespacing >= 0) spc.addNewSpcPct().setVal((int)(linespacing*1000)); + else spc.addNewSpcPts().setVal((int)(-linespacing*100)); + pr.setLnSpc(spc); + } + + /** + * Returns the vertical line spacing that is to be used within a paragraph. + * This may be specified in two different ways, percentage spacing and font point spacing: + *

+ * If linespacing >= 0, then linespacing is a percentage of normal line height. + * If linespacing < 0, the absolute value of linespacing is the spacing in points + *

+ * + * @return the vertical line spacing. + */ + public double getLineSpacing(){ + CTTextParagraphProperties pr = _p.getPPr(); + if(pr == null || !pr.isSetLnSpc()) return 100; // TODO fetch from master + + CTTextSpacing spc = pr.getLnSpc(); + if(spc.isSetSpcPct()) return spc.getSpcPct().getVal()*0.001; + else if (spc.isSetSpcPts()) return -spc.getSpcPts().getVal()*0.01; + else return 100; + } + + /** + * Set the amount of vertical white space that will be present before the paragraph. + * This space is specified in either percentage or points: + *

+ * If spaceBefore >= 0, then space is a percentage of normal line height. + * If spaceBefore < 0, the absolute value of linespacing is the spacing in points + *

+ * Examples: + *

+     *      // The paragraph will be formatted to have a spacing before the paragraph text.
+     *      // The spacing will be 200% of the size of the largest text on each line
+     *      paragraph.setSpaceBefore(200);
+     *
+     *      // The spacing will be a size of 48 points
+     *      paragraph.setSpaceBefore(-48.0);
+     * 
+ * + * @param spaceBefore the vertical white space before the paragraph. + */ + public void setSpaceBefore(double spaceBefore){ + CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); + CTTextSpacing spc = CTTextSpacing.Factory.newInstance(); + if(spaceBefore >= 0) spc.addNewSpcPct().setVal((int)(spaceBefore*1000)); + else spc.addNewSpcPts().setVal((int)(-spaceBefore*100)); + pr.setSpcBef(spc); + } + + /** + * The amount of vertical white space before the paragraph + * This may be specified in two different ways, percentage spacing and font point spacing: + *

+ * If spaceBefore >= 0, then space is a percentage of normal line height. + * If spaceBefore < 0, the absolute value of linespacing is the spacing in points + *

+ * + * @return the vertical white space before the paragraph + */ + public double getSpaceBefore(){ + CTTextParagraphProperties pr = _p.getPPr(); + if(pr == null || !pr.isSetSpcBef()) return 0; // TODO fetch from master + + CTTextSpacing spc = pr.getSpcBef(); + if(spc.isSetSpcPct()) return spc.getSpcPct().getVal()*0.001; + else if (spc.isSetSpcPts()) return -spc.getSpcPts().getVal()*0.01; + else return 0; + } + + /** + * Set the amount of vertical white space that will be present after the paragraph. + * This space is specified in either percentage or points: + *

+ * If spaceAfter >= 0, then space is a percentage of normal line height. + * If spaceAfter < 0, the absolute value of linespacing is the spacing in points + *

+ * Examples: + *

+     *      // The paragraph will be formatted to have a spacing after the paragraph text.
+     *      // The spacing will be 200% of the size of the largest text on each line
+     *      paragraph.setSpaceAfter(200);
+     *
+     *      // The spacing will be a size of 48 points
+     *      paragraph.setSpaceAfter(-48.0);
+     * 
+ * + * @param spaceAfter the vertical white space after the paragraph. + */ + public void setSpaceAfter(double spaceAfter){ + CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); + CTTextSpacing spc = CTTextSpacing.Factory.newInstance(); + if(spaceAfter >= 0) spc.addNewSpcPct().setVal((int)(spaceAfter*1000)); + else spc.addNewSpcPts().setVal((int)(-spaceAfter*100)); + pr.setSpcAft(spc); + } + + /** + * The amount of vertical white space after the paragraph + * This may be specified in two different ways, percentage spacing and font point spacing: + *

+ * If spaceBefore >= 0, then space is a percentage of normal line height. + * If spaceBefore < 0, the absolute value of linespacing is the spacing in points + *

+ * + * @return the vertical white space after the paragraph + */ + public double getSpaceAfter(){ + CTTextParagraphProperties pr = _p.getPPr(); + if(pr == null || !pr.isSetSpcAft()) return 0; // TODO fetch from master + + CTTextSpacing spc = pr.getSpcAft(); + if(spc.isSetSpcPct()) return spc.getSpcPct().getVal()*0.001; + else if (spc.isSetSpcPts()) return -spc.getSpcPts().getVal()*0.01; + else return 0; + } + + /** + * Specifies the particular level text properties that this paragraph will follow. + * The value for this attribute formats the text according to the corresponding level + * paragraph properties defined in the SlideMaster. + * + * @param level the level (0 ... 4) + */ + public void setLevel(int level){ + CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); + + pr.setLvl(level); + } + + /** + * + * @return the text level of this paragraph. Default is 0. + */ + public int getLevel(){ + CTTextParagraphProperties pr = _p.getPPr(); + if(pr == null) return 0; + + return pr.getLvl(); + + } + + @Override + public String toString(){ + return "[" + getClass() + "]" + getText(); + } +} 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 index 0000000000..859649197b --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java @@ -0,0 +1,202 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import org.apache.poi.util.Beta; +import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont; +import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType; +import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType; + +import java.awt.*; + +/** + * Represents a run of text within the containing text body. The run element is the + * lowest level text separation mechanism within a text body. + * + * @author Yegor Kozlov + */ +@Beta +public class XSLFTextRun { + private final CTRegularTextRun _r; + + XSLFTextRun(CTRegularTextRun r){ + _r = r; + } + + public String getText(){ + return _r.getT(); + } + + public void setText(String text){ + _r.setT(text); + } + + public CTRegularTextRun getXmlObject(){ + return _r; + } + + public void setFontColor(Color color){ + CTTextCharacterProperties rPr = getRpR(); + CTSolidColorFillProperties fill = rPr.isSetSolidFill() ? rPr.getSolidFill() : rPr.addNewSolidFill(); + CTSRgbColor clr = fill.isSetSrgbClr() ? fill.getSrgbClr() : fill.addNewSrgbClr(); + clr.setVal(new byte[]{(byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue()}); + } + + /** + * + * @param fontSize font size in points. + * The value of -1 unsets the Sz attribyte from the underlying xml bean + */ + public void setFontSize(double fontSize){ + CTTextCharacterProperties rPr = getRpR(); + if(fontSize == -1.0) { + if(rPr.isSetSz()) rPr.unsetSz(); + } else { + rPr.setSz((int)(100*fontSize)); + } + } + + /** + * @return font size in points or -1 if font size is not set. + */ + public double getFontSize(){ + if(!_r.isSetRPr()) return -1; + + return _r.getRPr().getSz()*0.01; + } + + /** + * Specifies the typeface, or name of the font that is to be used for this text run. + * + * @param typeface the font to apply to this text run. + * The value of null unsets the Typeface attrubute from the underlying xml. + */ + public void setFontFamily(String typeface){ + setFontFamily(typeface, (byte)-1, (byte)-1, false); + } + + public void setFontFamily(String typeface, byte charset, byte pictAndFamily, boolean isSymbol){ + CTTextCharacterProperties rPr = getRpR(); + + if(typeface == null){ + if(rPr.isSetLatin()) rPr.unsetLatin(); + if(rPr.isSetCs()) rPr.unsetCs(); + if(rPr.isSetSym()) rPr.unsetSym(); + } else { + if(isSymbol){ + CTTextFont font = rPr.isSetSym() ? rPr.getSym() : rPr.addNewSym(); + font.setTypeface(typeface); + } else { + CTTextFont latin = rPr.isSetLatin() ? rPr.getLatin() : rPr.addNewLatin(); + latin.setTypeface(typeface); + if(charset != -1) latin.setCharset(charset); + if(pictAndFamily != -1) latin.setPitchFamily(pictAndFamily); + } + } + } + + /** + * @return font family or null if niot set + */ + public String getFontFamily(){ + if(!_r.isSetRPr() || !_r.getRPr().isSetLatin()) return null; + + return _r.getRPr().getLatin().getTypeface(); + } + + /** + * Specifies whether a run of text will be formatted as strikethrough text. + * + * @param strike whether a run of text will be formatted as strikethrough text. + */ + public void setStrikethrough(boolean strike){ + getRpR().setStrike(strike ? STTextStrikeType.SNG_STRIKE : STTextStrikeType.NO_STRIKE); + } + + /** + * @return whether a run of text will be formatted as strikethrough text. Default is false. + */ + public boolean isStrikethrough(){ + if(!_r.isSetRPr()) return false; + + return _r.getRPr().getStrike() == STTextStrikeType.SNG_STRIKE; + } + + /** + * Specifies whether this run of text will be formatted as bold text + * + * @param bold whether this run of text will be formatted as bold text + */ + public void setBold(boolean bold){ + getRpR().setB(bold); + } + + /** + * @return whether this run of text is formatted as bold text + */ + public boolean isBold(){ + if(!_r.isSetRPr()) return false; + + return _r.getRPr().getB(); + } + + /** + * @param italic whether this run of text is formatted as italic text + */ + public void setItalic(boolean italic){ + getRpR().setI(italic); + } + + /** + * @return whether this run of text is formatted as italic text + */ + public boolean isItalic(){ + if(!_r.isSetRPr()) return false; + + return _r.getRPr().getI(); + } + + /** + * @param underline whether this run of text is formatted as underlined text + */ + public void setUnderline(boolean underline){ + getRpR().setU(underline ? STTextUnderlineType.SNG : STTextUnderlineType.NONE); + } + + /** + * @return whether this run of text is formatted as underlined text + */ + public boolean isUnderline(){ + if(!_r.isSetRPr() || !_r.getRPr().isSetU()) return false; + + return _r.getRPr().getU() != STTextUnderlineType.NONE; + } + + protected CTTextCharacterProperties getRpR(){ + return _r.isSetRPr() ? _r.getRPr() : _r.addNewRPr(); + } + + @Override + public String toString(){ + return "[" + getClass() + "]" + getText(); + } + +} \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/XSLFTestDataSamples.java b/src/ooxml/testcases/org/apache/poi/xslf/XSLFTestDataSamples.java index 0b326c0fdf..b6966d06ef 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/XSLFTestDataSamples.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/XSLFTestDataSamples.java @@ -41,7 +41,7 @@ public class XSLFTestDataSamples { public static XMLSlideShow writeOutAndReadBack(XMLSlideShow doc) { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(4096); - doc._getXSLFSlideShow().write(baos); + doc.write(baos); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); return new XMLSlideShow(OPCPackage.open(bais)); } catch (Exception e) { 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 index 0000000000..69be4b7a6b --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java @@ -0,0 +1,267 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import junit.framework.TestCase; + +import org.apache.poi.util.Units; +import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType; +import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType; + +/** + * @author Yegor Kozlov + */ +public class TestXSLFAutoShape extends TestCase { + public void testTextBodyProperies() { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + + XSLFAutoShape shape = slide.createAutoShape(); + shape.addNewTextParagraph().addNewTextRun().setText("POI"); + + // margins + assertEquals(-1., shape.getMarginBottom()); + assertEquals(-1., shape.getMarginTop()); + assertEquals(-1., shape.getMarginLeft()); + assertEquals(-1., shape.getMarginRight()); + + shape.setMarginBottom(1.0); + assertEquals(1.0, shape.getMarginBottom()); + shape.setMarginTop(2.0); + assertEquals(2.0, shape.getMarginTop()); + shape.setMarginLeft(3.0); + assertEquals(3.0, shape.getMarginLeft()); + shape.setMarginRight(4.0); + assertEquals(4.0, shape.getMarginRight()); + + shape.setMarginBottom(0.0); + assertEquals(0.0, shape.getMarginBottom()); + shape.setMarginTop(0.0); + assertEquals(0.0, shape.getMarginTop()); + shape.setMarginLeft(0.0); + assertEquals(0.0, shape.getMarginLeft()); + shape.setMarginRight(0.0); + assertEquals(0.0, shape.getMarginRight()); + + shape.setMarginBottom(-1); + assertEquals(-1., shape.getMarginBottom()); + shape.setMarginTop(-1); + assertEquals(-1.0, shape.getMarginTop()); + shape.setMarginLeft(-1); + assertEquals(-1.0, shape.getMarginLeft()); + shape.setMarginRight(-1); + assertEquals(-1.0, shape.getMarginRight()); + + // shape + assertFalse(shape.getWordWrap()); + shape.setWordWrap(true); + assertTrue(shape.getWordWrap()); + shape.setWordWrap(false); + assertFalse(shape.getWordWrap()); + + // shape + assertEquals(TextAutofit.NORMAL, shape.getTextAutofit()); + shape.setTextAutofit(TextAutofit.NONE); + assertEquals(TextAutofit.NONE, shape.getTextAutofit()); + shape.setTextAutofit(TextAutofit.SHAPE); + assertEquals(TextAutofit.SHAPE, shape.getTextAutofit()); + shape.setTextAutofit(TextAutofit.NORMAL); + assertEquals(TextAutofit.NORMAL, shape.getTextAutofit()); + + assertEquals(VerticalAlignment.TOP, shape.getVerticalAlignment()); + shape.setVerticalAlignment(VerticalAlignment.BOTTOM); + assertEquals(VerticalAlignment.BOTTOM, shape.getVerticalAlignment()); + shape.setVerticalAlignment(VerticalAlignment.MIDDLE); + assertEquals(VerticalAlignment.MIDDLE, shape.getVerticalAlignment()); + shape.setVerticalAlignment(null); + assertEquals(VerticalAlignment.TOP, shape.getVerticalAlignment()); + + assertEquals(TextDirection.HORIZONTAL, shape.getTextDirection()); + shape.setTextDirection(TextDirection.VERTICAL); + assertEquals(TextDirection.VERTICAL, shape.getTextDirection()); + shape.setTextDirection(null); + assertEquals(TextDirection.HORIZONTAL, shape.getTextDirection()); + } + + public void testTextParagraph() { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + assertEquals(0, slide.getShapes().length); + + XSLFAutoShape shape = slide.createAutoShape(); + assertEquals(0, shape.getTextParagraphs().size()); + XSLFTextParagraph p = shape.addNewTextParagraph(); + assertEquals(1, shape.getTextParagraphs().size()); + + assertEquals(0., p.getIndent()); + assertEquals(0., p.getLeftMargin()); + assertEquals(100., p.getLineSpacing()); + assertEquals(0., p.getSpaceAfter()); + assertEquals(0., p.getSpaceBefore()); + assertEquals(0, p.getLevel()); + + p.setIndent(2.0); + assertEquals(2.0, p.getIndent()); + assertTrue(p.getXmlObject().getPPr().isSetIndent()); + p.setIndent(-1); + assertEquals(0.0, p.getIndent()); + assertFalse(p.getXmlObject().getPPr().isSetIndent()); + p.setIndent(10.0); + assertEquals(10., p.getIndent()); + assertTrue(p.getXmlObject().getPPr().isSetIndent()); + + + assertFalse(p.getXmlObject().getPPr().isSetLvl()); + p.setLevel(1); + assertEquals(1, p.getLevel()); + assertTrue(p.getXmlObject().getPPr().isSetLvl()); + p.setLevel(2); + assertEquals(2, p.getLevel()); + + p.setLeftMargin(2.0); + assertEquals(2.0, p.getLeftMargin()); + assertTrue(p.getXmlObject().getPPr().isSetMarL()); + p.setLeftMargin(10.0); + assertEquals(10., p.getLeftMargin()); + assertEquals(Units.toEMU(10), p.getXmlObject().getPPr().getMarL()); + + + assertFalse(p.getXmlObject().getPPr().isSetSpcAft()); + p.setSpaceAfter(200); + assertEquals(200000, p.getXmlObject().getPPr().getSpcAft().getSpcPct().getVal()); + assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPts()); + p.setSpaceAfter(100); + assertEquals(100000, p.getXmlObject().getPPr().getSpcAft().getSpcPct().getVal()); + assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPts()); + p.setSpaceAfter(-20); + assertEquals(2000, p.getXmlObject().getPPr().getSpcAft().getSpcPts().getVal()); + assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPct()); + p.setSpaceAfter(-10); + assertEquals(1000, p.getXmlObject().getPPr().getSpcAft().getSpcPts().getVal()); + assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPct()); + + assertFalse(p.getXmlObject().getPPr().isSetSpcBef()); + p.setSpaceBefore(200); + assertEquals(200000, p.getXmlObject().getPPr().getSpcBef().getSpcPct().getVal()); + assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPts()); + p.setSpaceBefore(100); + assertEquals(100000, p.getXmlObject().getPPr().getSpcBef().getSpcPct().getVal()); + assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPts()); + p.setSpaceBefore(-20); + assertEquals(2000, p.getXmlObject().getPPr().getSpcBef().getSpcPts().getVal()); + assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPct()); + p.setSpaceBefore(-10); + assertEquals(1000, p.getXmlObject().getPPr().getSpcBef().getSpcPts().getVal()); + assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPct()); + + assertFalse(p.getXmlObject().getPPr().isSetLnSpc()); + p.setLineSpacing(200); + assertEquals(200000, p.getXmlObject().getPPr().getLnSpc().getSpcPct().getVal()); + assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPts()); + p.setLineSpacing(100); + assertEquals(100000, p.getXmlObject().getPPr().getLnSpc().getSpcPct().getVal()); + assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPts()); + p.setLineSpacing(-20); + assertEquals(2000, p.getXmlObject().getPPr().getLnSpc().getSpcPts().getVal()); + assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPct()); + p.setLineSpacing(-10); + assertEquals(1000, p.getXmlObject().getPPr().getLnSpc().getSpcPts().getVal()); + assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPct()); + + assertFalse(p.getXmlObject().getPPr().isSetAlgn()); + assertEquals(TextAlign.LEFT, p.getTextAlign()); + p.setTextAlign(TextAlign.LEFT); + assertTrue(p.getXmlObject().getPPr().isSetAlgn()); + assertEquals(TextAlign.LEFT, p.getTextAlign()); + p.setTextAlign(TextAlign.RIGHT); + assertEquals(TextAlign.RIGHT, p.getTextAlign()); + p.setTextAlign(TextAlign.JUSTIFY); + assertEquals(TextAlign.JUSTIFY, p.getTextAlign()); + p.setTextAlign(null); + assertEquals(TextAlign.LEFT, p.getTextAlign()); + assertFalse(p.getXmlObject().getPPr().isSetAlgn()); + } + + public void testTextRun() { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + + XSLFAutoShape shape = slide.createAutoShape(); + assertEquals(0, shape.getTextParagraphs().size()); + XSLFTextParagraph p = shape.addNewTextParagraph(); + assertEquals(1, shape.getTextParagraphs().size()); + assertEquals(0, p.getTextRuns().size()); + XSLFTextRun r = p.addNewTextRun(); + assertEquals(1, p.getTextRuns().size()); + assertSame(r, p.getTextRuns().get(0)); + + assertEquals(-1.0, r.getFontSize()); + assertFalse(r.getXmlObject().isSetRPr()); + r.setFontSize(10.0); + assertTrue(r.getXmlObject().isSetRPr()); + assertEquals(1000, r.getXmlObject().getRPr().getSz()); + r.setFontSize(12.5); + assertEquals(1250, r.getXmlObject().getRPr().getSz()); + r.setFontSize(-1); + assertFalse(r.getXmlObject().getRPr().isSetSz()); + + assertFalse(r.getXmlObject().getRPr().isSetLatin()); + assertNull(r.getFontFamily()); + r.setFontFamily(null); + assertNull(r.getFontFamily()); + r.setFontFamily("Arial"); + assertEquals("Arial", r.getFontFamily()); + assertEquals("Arial", r.getXmlObject().getRPr().getLatin().getTypeface()); + r.setFontFamily("Symbol"); + assertEquals("Symbol", r.getFontFamily()); + assertEquals("Symbol", r.getXmlObject().getRPr().getLatin().getTypeface()); + r.setFontFamily(null); + assertNull(r.getFontFamily()); + assertFalse(r.getXmlObject().getRPr().isSetLatin()); + + assertFalse(r.isStrikethrough()); + assertFalse(r.getXmlObject().getRPr().isSetStrike()); + r.setStrikethrough(true); + assertTrue(r.isStrikethrough()); + assertEquals(STTextStrikeType.SNG_STRIKE, r.getXmlObject().getRPr().getStrike()); + + assertFalse(r.isBold()); + assertFalse(r.getXmlObject().getRPr().isSetB()); + r.setBold(true); + assertTrue(r.isBold()); + assertEquals(true, r.getXmlObject().getRPr().getB()); + + assertFalse(r.isItalic()); + assertFalse(r.getXmlObject().getRPr().isSetI()); + r.setItalic(true); + assertTrue(r.isItalic()); + assertEquals(true, r.getXmlObject().getRPr().getI()); + + assertFalse(r.isUnderline()); + assertFalse(r.getXmlObject().getRPr().isSetU()); + r.setUnderline(true); + assertTrue(r.isUnderline()); + assertEquals(STTextUnderlineType.SNG, r.getXmlObject().getRPr().getU()); + + r.setText("Apache"); + assertEquals("Apache", r.getText()); + r.setText("POI"); + assertEquals("POI", r.getText()); + r.setText(null); + assertNull(r.getText()); + } +} \ 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 index 0000000000..8633a326a9 --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFConnectorShape.java @@ -0,0 +1,117 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import junit.framework.TestCase; + +import org.apache.poi.util.Units; +import org.apache.poi.xslf.usermodel.LineCap; +import org.apache.poi.xslf.usermodel.LineDash; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap; +import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndType; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndWidth; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndLength; + +import java.awt.*; + +/** + * @author Yegor Kozlov + */ +public class TestXSLFConnectorShape extends TestCase { + + public void testLineDecorations() { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + + XSLFConnectorShape shape = slide.createConnector(); + assertEquals(1, slide.getShapes().length); + + assertFalse(shape.getSpPr().getLn().isSetHeadEnd()); + assertFalse(shape.getSpPr().getLn().isSetTailEnd()); + + // line decorations + assertEquals(LineDecoration.NONE, shape.getLineHeadDecoration()); + assertEquals(LineDecoration.NONE, shape.getLineTailDecoration()); + shape.setLineHeadDecoration(null); + shape.setLineTailDecoration(null); + assertEquals(LineDecoration.NONE, shape.getLineHeadDecoration()); + assertEquals(LineDecoration.NONE, shape.getLineTailDecoration()); + assertFalse(shape.getSpPr().getLn().getHeadEnd().isSetType()); + assertFalse(shape.getSpPr().getLn().getTailEnd().isSetType()); + + shape.setLineHeadDecoration(LineDecoration.ARROW); + shape.setLineTailDecoration(LineDecoration.DIAMOND); + assertEquals(LineDecoration.ARROW, shape.getLineHeadDecoration()); + assertEquals(LineDecoration.DIAMOND, shape.getLineTailDecoration()); + assertEquals(STLineEndType.ARROW, shape.getSpPr().getLn().getHeadEnd().getType()); + assertEquals(STLineEndType.DIAMOND, shape.getSpPr().getLn().getTailEnd().getType()); + + shape.setLineHeadDecoration(LineDecoration.DIAMOND); + shape.setLineTailDecoration(LineDecoration.ARROW); + assertEquals(LineDecoration.DIAMOND, shape.getLineHeadDecoration()); + assertEquals(LineDecoration.ARROW, shape.getLineTailDecoration()); + assertEquals(STLineEndType.DIAMOND, shape.getSpPr().getLn().getHeadEnd().getType()); + assertEquals(STLineEndType.ARROW, shape.getSpPr().getLn().getTailEnd().getType()); + + // line end width + assertEquals(null, shape.getLineHeadWidth()); + assertEquals(null, shape.getLineTailWidth()); + shape.setLineHeadWidth(null); + shape.setLineHeadWidth(null); + assertEquals(null, shape.getLineHeadWidth()); + assertEquals(null, shape.getLineTailWidth()); + assertFalse(shape.getSpPr().getLn().getHeadEnd().isSetW()); + assertFalse(shape.getSpPr().getLn().getTailEnd().isSetW()); + shape.setLineHeadWidth(LineEndWidth.LARGE); + shape.setLineTailWidth(LineEndWidth.MEDIUM); + assertEquals(LineEndWidth.LARGE, shape.getLineHeadWidth()); + assertEquals(LineEndWidth.MEDIUM, shape.getLineTailWidth()); + assertEquals(STLineEndWidth.LG, shape.getSpPr().getLn().getHeadEnd().getW()); + assertEquals(STLineEndWidth.MED, shape.getSpPr().getLn().getTailEnd().getW()); + shape.setLineHeadWidth(LineEndWidth.MEDIUM); + shape.setLineTailWidth(LineEndWidth.LARGE); + assertEquals(LineEndWidth.MEDIUM, shape.getLineHeadWidth()); + assertEquals(LineEndWidth.LARGE, shape.getLineTailWidth()); + assertEquals(STLineEndWidth.MED, shape.getSpPr().getLn().getHeadEnd().getW()); + assertEquals(STLineEndWidth.LG, shape.getSpPr().getLn().getTailEnd().getW()); + + // line end length + assertEquals(null, shape.getLineHeadLength()); + assertEquals(null, shape.getLineTailLength()); + shape.setLineHeadLength(null); + shape.setLineTailLength(null); + assertEquals(null, shape.getLineHeadLength()); + assertEquals(null, shape.getLineTailLength()); + assertFalse(shape.getSpPr().getLn().getHeadEnd().isSetLen()); + assertFalse(shape.getSpPr().getLn().getTailEnd().isSetLen()); + shape.setLineHeadLength(LineEndLength.LARGE); + shape.setLineTailLength(LineEndLength.MEDIUM); + assertEquals(LineEndLength.LARGE, shape.getLineHeadLength()); + assertEquals(LineEndLength.MEDIUM, shape.getLineTailLength()); + assertEquals(STLineEndLength.LG, shape.getSpPr().getLn().getHeadEnd().getLen()); + assertEquals(STLineEndLength.MED, shape.getSpPr().getLn().getTailEnd().getLen()); + shape.setLineHeadLength(LineEndLength.MEDIUM); + shape.setLineTailLength(LineEndLength.LARGE); + assertEquals(LineEndLength.MEDIUM, shape.getLineHeadLength()); + assertEquals(LineEndLength.LARGE, shape.getLineTailLength()); + assertEquals(STLineEndLength.MED, shape.getSpPr().getLn().getHeadEnd().getLen()); + assertEquals(STLineEndLength.LG, shape.getSpPr().getLn().getTailEnd().getLen()); + + } + +} \ 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 index 0000000000..f52cc83dde --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFFreeformShape.java @@ -0,0 +1,50 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import junit.framework.TestCase; + +import java.awt.*; +import java.awt.geom.Ellipse2D; +import java.awt.geom.GeneralPath; + +/** + * @author Yegor Kozlov + */ +public class TestXSLFFreeformShape extends TestCase { + + public void testSetPath() { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + XSLFFreeformShape shape1 = slide.createFreeform(); + // comples path consisting of a rectangle and an ellipse inside it + GeneralPath path1 = new GeneralPath(new Rectangle(150, 150, 300, 300)); + path1.append(new Ellipse2D.Double(200, 200, 100, 50), false); + shape1.setPath(path1); + + GeneralPath path2 = shape1.getPath(); + + // YK: how to compare the original path1 and the value returned by XSLFFreeformShape.getPath() ? + // one way is to create another XSLFFreeformShape from path2 and compare the resulting xml + assertEquals(path1.getBounds2D(), path2.getBounds2D()); + + XSLFFreeformShape shape2 = slide.createFreeform(); + shape2.setPath(path2); + + assertEquals(shape1.getSpPr().getCustGeom().toString(), shape2.getSpPr().getCustGeom().toString()); + } +} \ 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 index 0000000000..13e8eb84d4 --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFGroupShape.java @@ -0,0 +1,99 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import junit.framework.TestCase; + +import java.awt.*; +import java.awt.geom.Rectangle2D; + +/** + * @author Yegor Kozlov + */ +public class TestXSLFGroupShape extends TestCase { + + public void testCreateShapes() { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + + ppt.setPageSize(new Dimension(792, 612)); + + XSLFGroupShape group = slide.createGroup(); + assertEquals(1, slide.getShapes().length); + + Rectangle2D interior = new Rectangle2D.Double(-10, -10, 20, 20); + group.setInteriorAnchor(interior); + assertEquals(interior, group.getInteriorAnchor()); + + Rectangle2D anchor = new Rectangle2D.Double(0, 0, 792, 612); + group.setAnchor(anchor); + assertEquals(anchor, group.getAnchor()); + + assertEquals(0, group.getShapes().length); + + XSLFTextBox shape1 = group.createTextBox(); + assertEquals(1, group.getShapes().length); + assertSame(shape1, group.getShapes()[0]); + assertEquals(3, shape1.getShapeId()); + + XSLFAutoShape shape2 = group.createAutoShape(); + assertEquals(2, group.getShapes().length); + assertSame(shape1, group.getShapes()[0]); + assertSame(shape2, group.getShapes()[1]); + assertEquals(4, shape2.getShapeId()); + + XSLFConnectorShape shape3 = group.createConnector(); + assertEquals(3, group.getShapes().length); + assertSame(shape3, group.getShapes()[2]); + assertEquals(5, shape3.getShapeId()); + + XSLFGroupShape shape4 = group.createGroup(); + assertEquals(4, group.getShapes().length); + assertSame(shape4, group.getShapes()[3]); + assertEquals(6, shape4.getShapeId()); + + group.removeShape(shape2); + assertEquals(3, group.getShapes().length); + assertSame(shape1, group.getShapes()[0]); + assertSame(shape3, group.getShapes()[1]); + assertSame(shape4, group.getShapes()[2]); + + group.removeShape(shape3); + assertEquals(2, group.getShapes().length); + assertSame(shape1, group.getShapes()[0]); + assertSame(shape4, group.getShapes()[1]); + + group.removeShape(shape1); + group.removeShape(shape4); + assertEquals(0, group.getShapes().length); + } + + public void testRemoveShapes() { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + + XSLFGroupShape group1 = slide.createGroup(); + group1.createTextBox(); + XSLFGroupShape group2 = slide.createGroup(); + group2.createTextBox(); + XSLFGroupShape group3 = slide.createGroup(); + slide.removeShape(group1); + slide.removeShape(group2); + slide.removeShape(group3); + + } +} \ 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 index 0000000000..9bd41025fb --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFPictureShape.java @@ -0,0 +1,65 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import junit.framework.TestCase; + +import java.awt.*; +import java.awt.geom.Ellipse2D; +import java.awt.geom.GeneralPath; +import java.util.*; +import java.util.List; + +import org.apache.poi.xslf.XSLFTestDataSamples; + +/** + * @author Yegor Kozlov + */ +public class TestXSLFPictureShape extends TestCase { + + public void testCreate() { + XMLSlideShow ppt = new XMLSlideShow(); + assertEquals(0, ppt.getAllPictures().size()); + byte[] data1 = new byte[100]; + int idx1 = ppt.addPicture(data1, XSLFPictureData.PICTURE_TYPE_JPEG); + assertEquals(0, idx1); + assertEquals(1, ppt.getAllPictures().size()); + + XSLFSlide slide = ppt.createSlide(); + XSLFPictureShape shape1 = slide.createPicture(idx1); + assertNotNull(shape1.getPictureData()); + assertTrue(Arrays.equals(data1, shape1.getPictureData().getData())); + + byte[] data2 = new byte[200]; + int idx2 = ppt.addPicture(data2, XSLFPictureData.PICTURE_TYPE_PNG); + XSLFPictureShape shape2 = slide.createPicture(idx2); + assertNotNull(shape2.getPictureData()); + assertEquals(1, idx2); + assertEquals(2, ppt.getAllPictures().size()); + assertTrue(Arrays.equals(data2, shape2.getPictureData().getData())); + + ppt = XSLFTestDataSamples.writeOutAndReadBack(ppt); + List pics = ppt.getAllPictures(); + assertEquals(2, pics.size()); + assertTrue(Arrays.equals(data1, pics.get(0).getData())); + assertTrue(Arrays.equals(data2, pics.get(1).getData())); + + XSLFShape[] shapes = ppt.getSlides()[0].getShapes(); + assertTrue(Arrays.equals(data1, ((XSLFPictureShape)shapes[0]).getPictureData().getData())); + assertTrue(Arrays.equals(data2, ((XSLFPictureShape)shapes[1]).getPictureData().getData())); + } +} \ 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 index 0000000000..ca3d82f975 --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFShape.java @@ -0,0 +1,101 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import junit.framework.TestCase; + +import org.apache.poi.xslf.XSLFTestDataSamples; +import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType; + +import java.util.List; + +/** + * @author Yegor Kozlov + */ +public class TestXSLFShape extends TestCase { + + public void testReadTextShapes() { + XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx"); + XSLFSlide[] slides = ppt.getSlides(); + assertEquals(3, slides.length); + + XSLFSlide slide1 = slides[0]; + XSLFShape[] shapes1 = slide1.getShapes(); + assertEquals(7, shapes1.length); + assertEquals("TextBox 3", shapes1[0].getShapeName()); + XSLFAutoShape sh0 = (XSLFAutoShape) shapes1[0]; + assertEquals("Learning PPTX", sh0.getText()); + List paragraphs0 = sh0.getTextParagraphs(); + assertEquals(1, paragraphs0.size()); + XSLFTextParagraph p0 = paragraphs0.get(0); + assertEquals("Learning PPTX", p0.getText()); + assertEquals(1, p0.getTextRuns().size()); + XSLFTextRun r0 = p0.getTextRuns().get(0); + assertEquals("Learning PPTX", r0.getText()); + + XSLFSlide slide2 = slides[1]; + XSLFShape[] shapes2 = slide2.getShapes(); + assertTrue(shapes2[0] instanceof XSLFAutoShape); + assertEquals("PPTX Title", ((XSLFAutoShape) shapes2[0]).getText()); + XSLFAutoShape sh1 = (XSLFAutoShape) shapes2[0]; + List paragraphs1 = sh1.getTextParagraphs(); + assertEquals(1, paragraphs1.size()); + XSLFTextParagraph p1 = paragraphs1.get(0); + assertEquals("PPTX Title", p1.getText()); + List r2 = paragraphs1.get(0).getTextRuns(); + assertEquals(2, r2.size()); + assertEquals("PPTX ", r2.get(0).getText()); + assertEquals("Title", r2.get(1).getText()); + // Title is underlined + assertEquals(STTextUnderlineType.SNG, r2.get(1).getXmlObject().getRPr().getU()); + + + assertTrue(shapes2[1] instanceof XSLFAutoShape); + assertEquals("Subtitle\nAnd second line", ((XSLFAutoShape) shapes2[1]).getText()); + XSLFAutoShape sh2 = (XSLFAutoShape) shapes2[1]; + List paragraphs2 = sh2.getTextParagraphs(); + assertEquals(2, paragraphs2.size()); + assertEquals("Subtitle", paragraphs2.get(0).getText()); + assertEquals("And second line", paragraphs2.get(1).getText()); + + assertEquals(1, paragraphs2.get(0).getTextRuns().size()); + assertEquals(1, paragraphs2.get(1).getTextRuns().size()); + + assertEquals("Subtitle", paragraphs2.get(0).getTextRuns().get(0).getText()); + assertTrue(paragraphs2.get(0).getTextRuns().get(0).getXmlObject().getRPr().getB()); + assertEquals("And second line", paragraphs2.get(1).getTextRuns().get(0).getText()); + } + + public void testCreateShapes() { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + assertEquals(0, slide.getShapes().length); + + XSLFTextBox textBox = slide.createTextBox(); + + assertEquals(1, slide.getShapes().length); + assertSame(textBox, slide.getShapes()[0]); + + assertEquals("", textBox.getText()); + assertEquals(0, textBox.getTextParagraphs().size()); + textBox.addNewTextParagraph().addNewTextRun().setText("Apache"); + textBox.addNewTextParagraph().addNewTextRun().setText("POI"); + assertEquals("Apache\nPOI", textBox.getText()); + assertEquals(2, textBox.getTextParagraphs().size()); + } + +} \ 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 index 0000000000..88af770fef --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSheet.java @@ -0,0 +1,66 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import junit.framework.TestCase; + +import org.apache.poi.xslf.XSLFTestDataSamples; + +/** + * test common properties for sheets (slides, masters, layouts, etc.) + * + * @author Yegor Kozlov + */ +public class TestXSLFSheet extends TestCase { + public void testCreateShapes(){ + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + assertEquals(0, slide.getShapes().length); + + XSLFSimpleShape shape1 = slide.createAutoShape(); + assertEquals(1, slide.getShapes().length); + assertSame(shape1, slide.getShapes()[0]); + + XSLFTextBox shape2 = slide.createTextBox(); + assertEquals(2, slide.getShapes().length); + assertSame(shape1, slide.getShapes()[0]); + assertSame(shape2, slide.getShapes()[1]); + + XSLFConnectorShape shape3 = slide.createConnector(); + assertEquals(3, slide.getShapes().length); + assertSame(shape1, slide.getShapes()[0]); + assertSame(shape2, slide.getShapes()[1]); + assertSame(shape3, slide.getShapes()[2]); + + XSLFGroupShape shape4 = slide.createGroup(); + assertEquals(4, slide.getShapes().length); + assertSame(shape1, slide.getShapes()[0]); + assertSame(shape2, slide.getShapes()[1]); + assertSame(shape3, slide.getShapes()[2]); + assertSame(shape4, slide.getShapes()[3]); + + ppt = XSLFTestDataSamples.writeOutAndReadBack(ppt); + slide = ppt.getSlides()[0]; + XSLFShape[] shapes = slide.getShapes(); + assertEquals(4, shapes.length); + + assertTrue(shapes[0] instanceof XSLFAutoShape); + assertTrue(shapes[1] instanceof XSLFTextBox); + assertTrue(shapes[2] instanceof XSLFConnectorShape); + assertTrue(shapes[3] instanceof XSLFGroupShape); + } +} \ 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 index 0000000000..d012f99aba --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java @@ -0,0 +1,132 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import junit.framework.TestCase; + +import org.apache.poi.util.Units; +import org.apache.poi.xslf.usermodel.LineCap; +import org.apache.poi.xslf.usermodel.LineDash; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap; +import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal; + +import java.awt.*; + +/** + * @author Yegor Kozlov + */ +public class TestXSLFSimpleShape extends TestCase { + public void testLineStyles() { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + + XSLFSimpleShape shape = slide.createAutoShape(); + assertEquals(1, slide.getShapes().length); + // line properties are not set by default + assertFalse(shape.getSpPr().isSetLn()); + + assertEquals(0., shape.getLineWidth()); + assertEquals(null, shape.getLineColor()); + assertEquals(null, shape.getLineDash()); + assertEquals(null, shape.getLineCap()); + + shape.setLineWidth(0); + shape.setLineColor(null); + shape.setLineDash(null); + shape.setLineCap(null); + + // still no line properties + assertFalse(shape.getSpPr().isSetLn()); + + // line width + shape.setLineWidth(1.0); + assertEquals(1.0, shape.getLineWidth()); + assertEquals(Units.EMU_PER_POINT, shape.getSpPr().getLn().getW()); + shape.setLineWidth(5.5); + assertEquals(5.5, shape.getLineWidth()); + assertEquals(Units.toEMU(5.5), shape.getSpPr().getLn().getW()); + shape.setLineWidth(0.0); + // setting line width to zero unsets the W attribute + assertFalse(shape.getSpPr().getLn().isSetW()); + + // line cap + shape.setLineCap(LineCap.FLAT); + assertEquals(LineCap.FLAT, shape.getLineCap()); + assertEquals(STLineCap.FLAT, shape.getSpPr().getLn().getCap()); + shape.setLineCap(LineCap.SQUARE); + assertEquals(LineCap.SQUARE, shape.getLineCap()); + assertEquals(STLineCap.SQ, shape.getSpPr().getLn().getCap()); + shape.setLineCap(LineCap.ROUND); + assertEquals(LineCap.ROUND, shape.getLineCap()); + assertEquals(STLineCap.RND, shape.getSpPr().getLn().getCap()); + shape.setLineCap(null); + // setting cap to null unsets the Cap attribute + assertFalse(shape.getSpPr().getLn().isSetCap()); + + // line dash + shape.setLineDash(LineDash.SOLID); + assertEquals(LineDash.SOLID, shape.getLineDash()); + assertEquals(STPresetLineDashVal.SOLID, shape.getSpPr().getLn().getPrstDash().getVal()); + shape.setLineDash(LineDash.DASH_DOT); + assertEquals(LineDash.DASH_DOT, shape.getLineDash()); + assertEquals(STPresetLineDashVal.DASH_DOT, shape.getSpPr().getLn().getPrstDash().getVal()); + shape.setLineDash(LineDash.LG_DASH_DOT); + assertEquals(LineDash.LG_DASH_DOT, shape.getLineDash()); + assertEquals(STPresetLineDashVal.LG_DASH_DOT, shape.getSpPr().getLn().getPrstDash().getVal()); + shape.setLineDash(null); + // setting dash width to null unsets the Dash element + assertFalse(shape.getSpPr().getLn().isSetPrstDash()); + + // line color + assertFalse(shape.getSpPr().getLn().isSetSolidFill()); + shape.setLineColor(Color.RED); + assertEquals(Color.RED, shape.getLineColor()); + assertTrue(shape.getSpPr().getLn().isSetSolidFill()); + shape.setLineColor(Color.BLUE); + assertEquals(Color.BLUE, shape.getLineColor()); + assertTrue(shape.getSpPr().getLn().isSetSolidFill()); + shape.setLineColor(null); + assertEquals(null, shape.getLineColor()); + // setting dash width to null unsets the SolidFill element + assertFalse(shape.getSpPr().getLn().isSetSolidFill()); + } + + public void testFill() { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + + XSLFAutoShape shape = slide.createAutoShape(); + // line properties are not set by default + assertFalse(shape.getSpPr().isSetSolidFill()); + + assertNull(shape.getFillColor()); + shape.setFillColor(null); + assertNull(shape.getFillColor()); + assertFalse(shape.getSpPr().isSetSolidFill()); + + shape.setFillColor(Color.RED); + assertEquals(Color.RED, shape.getFillColor()); + shape.setFillColor(Color.DARK_GRAY); + assertEquals(Color.DARK_GRAY, shape.getFillColor()); + assertTrue(shape.getSpPr().isSetSolidFill()); + + shape.setFillColor(null); + assertNull(shape.getFillColor()); + assertFalse(shape.getSpPr().isSetSolidFill()); + } + +} \ 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 index 0000000000..9c7d131d80 --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java @@ -0,0 +1,102 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import junit.framework.TestCase; + +import org.apache.poi.xslf.XSLFTestDataSamples; +import org.apache.poi.POIXMLDocumentPart; + +import java.util.List; + +/** + * @author Yegor Kozlov + */ +public class TestXSLFSlide extends TestCase { + public void testReadShapes(){ + XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx"); + XSLFSlide[] slides = ppt.getSlides(); + assertEquals(3, slides.length); + + XSLFSlide slide1 = slides[0]; + XSLFShape[] shapes1 = slide1.getShapes(); + assertEquals(7, shapes1.length); + assertEquals("TextBox 3", shapes1[0].getShapeName()); + assertTrue(shapes1[0] instanceof XSLFTextBox); + XSLFAutoShape sh0 = (XSLFAutoShape)shapes1[0]; + assertEquals("Learning PPTX", sh0.getText()); + + + assertEquals("Straight Connector 5", shapes1[1].getShapeName()); + assertTrue(shapes1[1] instanceof XSLFConnectorShape); + + assertEquals("Freeform 6", shapes1[2].getShapeName()); + assertTrue(shapes1[2] instanceof XSLFFreeformShape); + XSLFAutoShape sh2 = (XSLFAutoShape)shapes1[2]; + assertEquals("Cloud", sh2.getText()); + + assertEquals("Picture 1", shapes1[3].getShapeName()); + assertTrue(shapes1[3] instanceof XSLFPictureShape); + + assertEquals("Table 2", shapes1[4].getShapeName()); + assertTrue(shapes1[4] instanceof XSLFGraphicFrame); + + assertEquals("Straight Arrow Connector 7", shapes1[5].getShapeName()); + assertTrue(shapes1[5] instanceof XSLFConnectorShape); + + assertEquals("Elbow Connector 9", shapes1[6].getShapeName()); + assertTrue(shapes1[6] instanceof XSLFConnectorShape); + + // titles on slide2 + XSLFSlide slide2 = slides[1]; + XSLFShape[] shapes2 = slide2.getShapes(); + assertEquals(2, shapes2.length); + assertTrue(shapes2[0] instanceof XSLFAutoShape); + assertEquals("PPTX Title", ((XSLFAutoShape)shapes2[0]).getText()); + assertTrue(shapes2[1] instanceof XSLFAutoShape); + assertEquals("Subtitle\nAnd second line", ((XSLFAutoShape)shapes2[1]).getText()); + + // group shape on slide3 + XSLFSlide slide3 = slides[2]; + XSLFShape[] shapes3 = slide3.getShapes(); + assertEquals(1, shapes3.length); + assertTrue(shapes3[0] instanceof XSLFGroupShape); + XSLFShape[] groupShapes = ((XSLFGroupShape)shapes3[0]).getShapes(); + assertEquals(3, groupShapes.length); + assertTrue(groupShapes[0] instanceof XSLFAutoShape); + assertEquals("Rectangle 1", groupShapes[0].getShapeName()); + + assertTrue(groupShapes[1] instanceof XSLFAutoShape); + assertEquals("Oval 2", groupShapes[1].getShapeName()); + + assertTrue(groupShapes[2] instanceof XSLFAutoShape); + assertEquals("Right Arrow 3", groupShapes[2].getShapeName()); + } + + public void testCreateSlide(){ + XMLSlideShow ppt = new XMLSlideShow(); + assertEquals(0, ppt.getSlides().length); + + XSLFSlide slide = ppt.createSlide(); + assertTrue(slide.getFollowMasterBackground()); + slide.setFollowMasterBackground(false); + assertFalse(slide.getFollowMasterBackground()); + slide.setFollowMasterBackground(true); + assertTrue(slide.getFollowMasterBackground()); + } + +} \ 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 index 0000000000..c07493a3f9 --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlideShow.java @@ -0,0 +1,108 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import junit.framework.TestCase; + +import java.awt.Dimension; +import java.util.List; + +import org.apache.poi.POIXMLDocumentPart; +import org.apache.poi.xslf.XSLFTestDataSamples; + +/** + * @author Yegor Kozlov + */ +public class TestXSLFSlideShow extends TestCase { + public void testCreateSlide(){ + XMLSlideShow ppt = new XMLSlideShow(); + assertEquals(0, ppt.getSlides().length); + + XSLFSlide slide1 = ppt.createSlide(); + assertEquals(1, ppt.getSlides().length); + assertSame(slide1, ppt.getSlides()[0]); + + List rels = slide1.getRelations(); + assertEquals(1, rels.size()); + assertEquals(slide1.getMasterSheet().getLayout("blank"), rels.get(0)); + + XSLFSlide slide2 = ppt.createSlide(); + assertEquals(2, ppt.getSlides().length); + assertSame(slide2, ppt.getSlides()[1]); + + ppt.setSlideOrder(slide2, 0); + assertSame(slide2, ppt.getSlides()[0]); + assertSame(slide1, ppt.getSlides()[1]); + + ppt = XSLFTestDataSamples.writeOutAndReadBack(ppt); + assertEquals(2, ppt.getSlides().length); + rels = ppt.getSlides()[0].getRelations(); + } + + public void testRemoveSlide(){ + XMLSlideShow ppt = new XMLSlideShow(); + assertEquals(0, ppt.getSlides().length); + + XSLFSlide slide1 = ppt.createSlide(); + XSLFSlide slide2 = ppt.createSlide(); + + assertEquals(2, ppt.getSlides().length); + assertSame(slide1, ppt.getSlides()[0]); + assertSame(slide2, ppt.getSlides()[1]); + + XSLFSlide removedSlide = ppt.removeSlide(0); + assertSame(slide1, removedSlide); + + assertEquals(1, ppt.getSlides().length); + assertSame(slide2, ppt.getSlides()[0]); + + ppt = XSLFTestDataSamples.writeOutAndReadBack(ppt); + assertEquals(1, ppt.getSlides().length); + } + + public void testDimension(){ + XMLSlideShow ppt = new XMLSlideShow(); + Dimension sz = ppt.getPageSize(); + assertEquals(720, sz.width); + assertEquals(540, sz.height); + ppt.setPageSize(new Dimension(792, 612)); + sz = ppt.getPageSize(); + assertEquals(792, sz.width); + assertEquals(612, sz.height); + } + + public void testSlideMasters(){ + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlideMaster[] masters = ppt.getSlideMasters(); + assertEquals(1, masters.length); + + XSLFSlide slide = ppt.createSlide(); + assertSame(masters[0], slide.getMasterSheet()); + } + + public void testSlideLayout(){ + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlideMaster[] masters = ppt.getSlideMasters(); + assertEquals(1, masters.length); + + XSLFSlide slide = ppt.createSlide(); + XSLFSlideLayout layout = slide.getSlideLayout(); + assertNotNull(layout); + + assertSame(masters[0], layout.getSlideMaster()); + } +} 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 index 0000000000..cc54111a10 --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextBox.java @@ -0,0 +1,37 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import junit.framework.TestCase; + +/** + * @author Yegor Kozlov + */ +public class TestXSLFTextBox extends TestCase { + + public void testPlaceholder() { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + + XSLFTextBox shape = slide.createTextBox(); + assertNull(shape.getPlaceholder()); + shape.setPlaceholder(Placeholder.TITLE); + assertEquals(Placeholder.TITLE, shape.getPlaceholder()); + shape.setPlaceholder(null); + assertNull(shape.getPlaceholder()); + } +} \ 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 index 0000000000..eea1e064e9 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 index 0000000000..0b3861228d Binary files /dev/null and b/test-data/slideshow/shapes.pptx differ