#60521 - Enable nested XSSF GroupShapes and fix calculation of Client-/ChildAnchor

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1776820 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2016-12-31 21:54:32 +00:00
parent 1d9c74b1bf
commit 254b42ff26
3 changed files with 195 additions and 94 deletions

View File

@ -277,7 +277,7 @@ public class ImageUtils {
}
private static double getRowHeightInPixels(Sheet sheet, int rowNum) {
public static double getRowHeightInPixels(Sheet sheet, int rowNum) {
Row r = sheet.getRow(rowNum);
double points = (r == null) ? sheet.getDefaultRowHeightInPoints() : r.getHeightInPoints();
return Units.toEMU(points)/(double)EMU_PER_PIXEL;

View File

@ -17,7 +17,10 @@
package org.apache.poi.xssf.usermodel;
import java.util.Iterator;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.ss.usermodel.ShapeContainer;
import org.apache.poi.util.Internal;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupTransform2D;
@ -25,6 +28,7 @@ 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.CTShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTConnector;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTGroupShape;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTGroupShapeNonVisual;
@ -36,10 +40,8 @@ import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShape;
* just as if it were a regular shape but instead of being described by a single geometry it is made up of all the
* shape geometries encompassed within it. Within a group shape each of the shapes that make up the group are
* specified just as they normally would.
*
* @author Yegor Kozlov
*/
public final class XSSFShapeGroup extends XSSFShape {
public final class XSSFShapeGroup extends XSSFShape implements ShapeContainer<XSSFShape> {
private static CTGroupShape prototype = null;
private CTGroupShape ctGroup;
@ -164,6 +166,34 @@ public final class XSSFShapeGroup extends XSSFShape {
return shape;
}
/**
* Creates a group shape.
*
* @param anchor the client anchor describes how this group is attached to the group.
* @return the newly created group shape.
*/
public XSSFShapeGroup createGroup(XSSFChildAnchor anchor) {
CTGroupShape ctShape = ctGroup.addNewGrpSp();
ctShape.set(prototype());
XSSFShapeGroup shape = new XSSFShapeGroup(getDrawing(), ctShape);
shape.parent = this;
shape.anchor = anchor;
// TODO: calculate bounding rectangle on anchor and set off/ext correctly
CTGroupTransform2D xfrm = shape.getCTGroupShape().getGrpSpPr().getXfrm();
CTTransform2D t2 = anchor.getCTTransform2D();
xfrm.setOff(t2.getOff());
xfrm.setExt(t2.getExt());
// child offset is left to 0,0
xfrm.setChExt(t2.getExt());
xfrm.setFlipH(t2.getFlipH());
xfrm.setFlipV(t2.getFlipV());
return shape;
}
@Internal
public CTGroupShape getCTGroupShape() {
return ctGroup;
@ -194,4 +224,13 @@ public final class XSSFShapeGroup extends XSSFShape {
throw new IllegalStateException("Not supported for shape group");
}
@Override
public Iterator<XSSFShape> iterator() {
return getDrawing().getShapes(this).iterator();
}
@Override
public String getShapeName() {
return ctGroup.getNvGrpSpPr().getCNvPr().getName();
}
}

View File

@ -32,8 +32,11 @@ import org.apache.poi.POIXMLDocumentPart.RelationPart;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.FontUnderline;
import org.apache.poi.ss.usermodel.ShapeTypes;
import org.apache.poi.util.Units;
import org.apache.poi.xssf.XSSFTestDataSamples;
import org.junit.Test;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupTransform2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType;
@ -778,6 +781,65 @@ public class TestXSSFDrawing {
}
}
@Test
public void testGroupShape() throws Exception {
XSSFWorkbook wb1 = new XSSFWorkbook();
XSSFSheet sheet = wb1.createSheet();
XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFSimpleShape s0 = drawing.createSimpleShape(drawing.createAnchor(0, 0, Units.pixelToEMU(30), Units.pixelToEMU(30), 1, 1, 10, 10));
s0.setShapeType(ShapeTypes.RECT);
s0.setLineStyleColor(100, 0, 0);
XSSFShapeGroup g1 = drawing.createGroup(drawing.createAnchor(0, 0, 300, 300, 1, 1, 10, 10));
CTGroupTransform2D xfrmG1 = g1.getCTGroupShape().getGrpSpPr().getXfrm();
XSSFSimpleShape s1 = g1.createSimpleShape(new XSSFChildAnchor(
(int)(xfrmG1.getChExt().getCx()*0.1),
(int)(xfrmG1.getChExt().getCy()*0.1),
(int)(xfrmG1.getChExt().getCx()*0.9),
(int)(xfrmG1.getChExt().getCy()*0.9)
));
s1.setShapeType(ShapeTypes.RECT);
s1.setLineStyleColor(0, 100, 0);
XSSFShapeGroup g2 = g1.createGroup(new XSSFChildAnchor(
(int)(xfrmG1.getChExt().getCx()*0.2),
(int)(xfrmG1.getChExt().getCy()*0.2),
(int)(xfrmG1.getChExt().getCx()*0.8),
(int)(xfrmG1.getChExt().getCy()*0.8)
));
CTGroupTransform2D xfrmG2 = g2.getCTGroupShape().getGrpSpPr().getXfrm();
XSSFSimpleShape s2 = g2.createSimpleShape(new XSSFChildAnchor(
(int)(xfrmG2.getChExt().getCx()*0.1),
(int)(xfrmG2.getChExt().getCy()*0.1),
(int)(xfrmG2.getChExt().getCx()*0.9),
(int)(xfrmG2.getChExt().getCy()*0.9)
));
s2.setShapeType(ShapeTypes.RECT);
s2.setLineStyleColor(0, 0, 100);
XSSFWorkbook wb2 = XSSFTestDataSamples.writeOutAndReadBack(wb1);
wb1.close();
XSSFDrawing draw = wb2.getSheetAt(0).getDrawingPatriarch();
List<XSSFShape> shapes = draw.getShapes();
assertEquals(2, shapes.size());
assertTrue(shapes.get(0) instanceof XSSFSimpleShape);
assertTrue(shapes.get(1) instanceof XSSFShapeGroup);
shapes = draw.getShapes((XSSFShapeGroup)shapes.get(1));
assertEquals(2, shapes.size());
assertTrue(shapes.get(0) instanceof XSSFSimpleShape);
assertTrue(shapes.get(1) instanceof XSSFShapeGroup);
shapes = draw.getShapes((XSSFShapeGroup)shapes.get(1));
assertEquals(1, shapes.size());
assertTrue(shapes.get(0) instanceof XSSFSimpleShape);
wb2.close();
}
private static void checkRewrite(XSSFWorkbook wb) throws IOException {
XSSFWorkbook wb2 = XSSFTestDataSamples.writeOutAndReadBack(wb);
assertNotNull(wb2);