diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java index e5ee2b9d5..7084082f4 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java @@ -67,6 +67,7 @@ implements XSLFShapeContainer, GroupShape { _grpSpPr = shape.getGrpSpPr(); } + @Override protected CTGroupShapeProperties getGrpSpPr() { return _grpSpPr; } @@ -159,6 +160,7 @@ implements XSLFShapeContainer, GroupShape { * * @return an iterator over the shapes in this sheet */ + @Override public Iterator iterator(){ return _shapes.iterator(); } @@ -166,6 +168,7 @@ implements XSLFShapeContainer, GroupShape { /** * Remove the specified shape from this group */ + @Override public boolean removeShape(XSLFShape xShape) { XmlObject obj = xShape.getXmlObject(); CTGroupShape grpSp = (CTGroupShape)getXmlObject(); @@ -214,6 +217,7 @@ implements XSLFShapeContainer, GroupShape { return _drawing; } + @Override public XSLFAutoShape createAutoShape(){ XSLFAutoShape sh = getDrawing().createAutoShape(); _shapes.add(sh); @@ -221,6 +225,7 @@ implements XSLFShapeContainer, GroupShape { return sh; } + @Override public XSLFFreeformShape createFreeform(){ XSLFFreeformShape sh = getDrawing().createFreeform(); _shapes.add(sh); @@ -228,6 +233,7 @@ implements XSLFShapeContainer, GroupShape { return sh; } + @Override public XSLFTextBox createTextBox(){ XSLFTextBox sh = getDrawing().createTextBox(); _shapes.add(sh); @@ -235,6 +241,7 @@ implements XSLFShapeContainer, GroupShape { return sh; } + @Override public XSLFConnectorShape createConnector(){ XSLFConnectorShape sh = getDrawing().createConnector(); _shapes.add(sh); @@ -242,6 +249,7 @@ implements XSLFShapeContainer, GroupShape { return sh; } + @Override public XSLFGroupShape createGroup(){ XSLFGroupShape sh = getDrawing().createGroup(); _shapes.add(sh); @@ -249,6 +257,7 @@ implements XSLFShapeContainer, GroupShape { return sh; } + @Override public XSLFPictureShape createPicture(PictureData pictureData){ if (!(pictureData instanceof XSLFPictureData)) { throw new IllegalArgumentException("pictureData needs to be of type XSLFPictureData"); @@ -327,36 +336,52 @@ implements XSLFShapeContainer, GroupShape { @Override void copy(XSLFShape src){ XSLFGroupShape gr = (XSLFGroupShape)src; - - // clear shapes - clear(); - - // recursively update each shape - for(XSLFShape shape : gr.getShapes()) { - XSLFShape newShape; - if (shape instanceof XSLFTextBox) { - newShape = createTextBox(); - } else if (shape instanceof XSLFAutoShape) { - newShape = createAutoShape(); - } else if (shape instanceof XSLFConnectorShape) { - newShape = createConnector(); - } else if (shape instanceof XSLFFreeformShape) { - newShape = createFreeform(); - } else if (shape instanceof XSLFPictureShape) { - XSLFPictureShape p = (XSLFPictureShape)shape; - XSLFPictureData pd = p.getPictureData(); - XSLFPictureData pdNew = getSheet().getSlideShow().addPicture(pd.getData(), pd.getType()); - newShape = createPicture(pdNew); - } else if (shape instanceof XSLFGroupShape) { - newShape = createGroup(); - } else if (shape instanceof XSLFTable) { - newShape = createTable(); - } else { - _logger.log(POILogger.WARN, "copying of class "+shape.getClass()+" not supported."); - continue; - } - newShape.copy(shape); + // recursively update each shape + List tgtShapes = getShapes(); + List srcShapes = gr.getShapes(); + + // workaround for a call by XSLFSheet.importContent: + // if we have already the same amount of child shapes + // then assume, that we've been called by import content and only need to update the children + if (tgtShapes.size() == srcShapes.size()) { + for(int i = 0; i < tgtShapes.size(); i++){ + XSLFShape s1 = srcShapes.get(i); + XSLFShape s2 = tgtShapes.get(i); + + s2.copy(s1); + } + } else { + // otherwise recreate the shapes from scratch + clear(); + + // recursively update each shape + for(XSLFShape shape : srcShapes) { + XSLFShape newShape; + if (shape instanceof XSLFTextBox) { + newShape = createTextBox(); + } else if (shape instanceof XSLFAutoShape) { + newShape = createAutoShape(); + } else if (shape instanceof XSLFConnectorShape) { + newShape = createConnector(); + } else if (shape instanceof XSLFFreeformShape) { + newShape = createFreeform(); + } else if (shape instanceof XSLFPictureShape) { + XSLFPictureShape p = (XSLFPictureShape)shape; + XSLFPictureData pd = p.getPictureData(); + XSLFPictureData pdNew = getSheet().getSlideShow().addPicture(pd.getData(), pd.getType()); + newShape = createPicture(pdNew); + } else if (shape instanceof XSLFGroupShape) { + newShape = createGroup(); + } else if (shape instanceof XSLFTable) { + newShape = createTable(); + } else { + _logger.log(POILogger.WARN, "copying of class "+shape.getClass()+" not supported."); + continue; + } + + newShape.copy(shape); + } } } @@ -364,6 +389,7 @@ implements XSLFShapeContainer, GroupShape { * Removes all of the elements from this container (optional operation). * The container will be empty after this call returns. */ + @Override public void clear() { List shapes = new ArrayList(getShapes()); for(XSLFShape shape : shapes){ @@ -371,6 +397,7 @@ implements XSLFShapeContainer, GroupShape { } } + @Override public void addShape(XSLFShape shape) { throw new UnsupportedOperationException( "Adding a shape from a different container is not supported -" diff --git a/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java b/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java index ab2594616..d138eb06d 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java @@ -52,6 +52,7 @@ import org.apache.poi.sl.usermodel.VerticalAlignment; import org.apache.poi.xslf.extractor.XSLFPowerPointExtractor; import org.apache.poi.xslf.usermodel.XMLSlideShow; import org.apache.poi.xslf.usermodel.XSLFAutoShape; +import org.apache.poi.xslf.usermodel.XSLFGroupShape; import org.apache.poi.xslf.usermodel.XSLFHyperlink; import org.apache.poi.xslf.usermodel.XSLFPictureData; import org.apache.poi.xslf.usermodel.XSLFPictureShape; @@ -67,6 +68,8 @@ import org.apache.poi.xslf.usermodel.XSLFTextParagraph; import org.apache.poi.xslf.usermodel.XSLFTextRun; import org.junit.Ignore; import org.junit.Test; +import org.openxmlformats.schemas.drawingml.x2006.main.CTOuterShadowEffect; +import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; public class TestXSLFBugs { @@ -592,4 +595,33 @@ public class TestXSLFBugs { ppt.createSlide(); ppt.close(); } + + @Test + public void bug60662() throws IOException { + XMLSlideShow src = new XMLSlideShow(); + XSLFSlide sl = src.createSlide(); + XSLFGroupShape gs = sl.createGroup(); + gs.setAnchor(new Rectangle2D.Double(100,100,100,100)); + gs.setInteriorAnchor(new Rectangle2D.Double(0,0,100,100)); + XSLFAutoShape as = gs.createAutoShape(); + as.setAnchor(new Rectangle2D.Double(0,0,100,100)); + as.setShapeType(ShapeType.STAR_24); + as.setFillColor(Color.YELLOW); + CTShape csh = (CTShape)as.getXmlObject(); + CTOuterShadowEffect shadow = csh.getSpPr().addNewEffectLst().addNewOuterShdw(); + shadow.setDir(270000); + shadow.setDist(100000); + shadow.addNewSrgbClr().setVal(new byte[] {0x00, (byte)0xFF, 0x00}); + + XMLSlideShow dst = new XMLSlideShow(); + XSLFSlide sl2 = dst.createSlide(); + sl2.importContent(sl); + XSLFGroupShape gs2 = (XSLFGroupShape)sl2.getShapes().get(0); + XSLFAutoShape as2 = (XSLFAutoShape)gs2.getShapes().get(0); + CTShape csh2 = (CTShape)as2.getXmlObject(); + assertTrue(csh2.getSpPr().isSetEffectLst()); + + dst.close(); + src.close(); + } } \ No newline at end of file