From: Evgeniy Berlog Date: Sun, 1 Jul 2012 09:38:08 +0000 (+0000) Subject: implemented work with existing shape groups and polygons X-Git-Tag: 3.10-beta1~161^2~18 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=5f543636b754773ab470a104ae6acd36102c7cb9;p=poi.git implemented work with existing shape groups and polygons git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1355866 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/poi/ddf/EscherSpRecord.java b/src/java/org/apache/poi/ddf/EscherSpRecord.java index 11a893f466..7d4dd5cfba 100644 --- a/src/java/org/apache/poi/ddf/EscherSpRecord.java +++ b/src/java/org/apache/poi/ddf/EscherSpRecord.java @@ -119,7 +119,7 @@ public class EscherSpRecord public String toXml(String tab) { StringBuilder builder = new StringBuilder(); builder.append(tab).append(formatXmlRecordHeader(getClass().getSimpleName(), HexDump.toHex(getRecordId()), HexDump.toHex(getVersion()), HexDump.toHex(getInstance()))) - .append(tab).append("\t").append("").append(HexDump.toHex(getShapeType())).append("\n") + .append(tab).append("\t").append("0x").append(HexDump.toHex(getShapeType())).append("\n") .append(tab).append("\t").append("").append(field_1_shapeId).append("\n") .append(tab).append("\t").append("").append(decodeFlags(field_2_flags) + " (0x" + HexDump.toHex(field_2_flags) + ")").append("\n"); builder.append(tab).append("\n"); diff --git a/src/java/org/apache/poi/hssf/model/PolygonShape.java b/src/java/org/apache/poi/hssf/model/PolygonShape.java index 02308bf48c..22212c88d2 100644 --- a/src/java/org/apache/poi/hssf/model/PolygonShape.java +++ b/src/java/org/apache/poi/hssf/model/PolygonShape.java @@ -63,7 +63,7 @@ public class PolygonShape spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER ); spContainer.setOptions( (short) 0x000F ); sp.setRecordId( EscherSpRecord.RECORD_ID ); - sp.setOptions( (short) ( ( EscherAggregate.ST_DONUT << 4 ) | 0x2 ) ); + sp.setOptions( (short) ( ( EscherAggregate.ST_NOT_PRIMATIVE << 4 ) | 0x2 ) ); sp.setShapeId( shapeId ); if (hssfShape.getParent() == null) sp.setFlags( EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE ); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java index 23a792f365..add7e32728 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java @@ -38,11 +38,6 @@ public class HSSFComment extends HSSFTextbox implements Comment { * It seems like HSSFRow should manage a collection of local HSSFComments */ - private boolean _visible; - private int _row; - private int _col; - private String _author; - private NoteRecord _note; public HSSFComment(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord textObjectRecord, NoteRecord _note) { diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java index bc3eebc1b3..675c7d7f86 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java @@ -73,6 +73,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { HSSFShapeGroup group = new HSSFShapeGroup(null, anchor); group.anchor = anchor; addShape(group); + onCreate(group); return group; } @@ -132,6 +133,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { HSSFPolygon shape = new HSSFPolygon(null, anchor); shape.anchor = anchor; addShape(shape); + onCreate(shape); return shape; } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java index 33f17d7e48..8d561a0ff1 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java @@ -17,87 +17,186 @@ package org.apache.poi.hssf.usermodel; -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.ddf.EscherOptRecord; +import org.apache.poi.ddf.*; +import org.apache.poi.hssf.record.CommonObjectDataSubRecord; +import org.apache.poi.hssf.record.EndSubRecord; +import org.apache.poi.hssf.record.EscherAggregate; import org.apache.poi.hssf.record.ObjRecord; +import org.apache.poi.util.LittleEndian; /** * @author Glen Stampoultzis (glens at superlinksoftware.com) */ -public class HSSFPolygon - extends HSSFShape -{ - int[] xPoints; - int[] yPoints; - int drawAreaWidth = 100; - int drawAreaHeight = 100; - - HSSFPolygon( HSSFShape parent, HSSFAnchor anchor ) - { - super( parent, anchor ); +public class HSSFPolygon extends HSSFShape { + + public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 0x1E; + + public HSSFPolygon(EscherContainerRecord spContainer, ObjRecord objRecord) { + super(spContainer, objRecord); } - @Override + HSSFPolygon(HSSFShape parent, HSSFAnchor anchor) { + super(parent, anchor); + } + + /** + * Generates the shape records for this shape. + */ protected EscherContainerRecord createSpContainer() { EscherContainerRecord spContainer = new EscherContainerRecord(); - spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER ); - spContainer.setOptions( (short) 0x000F ); - EscherOptRecord optRecord = new EscherOptRecord(); - optRecord.setRecordId(EscherOptRecord.RECORD_ID); - spContainer.addChildRecord(optRecord); + EscherSpRecord sp = new EscherSpRecord(); + EscherOptRecord opt = new EscherOptRecord(); + EscherClientDataRecord clientData = new EscherClientDataRecord(); + + spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER); + spContainer.setOptions((short) 0x000F); + sp.setRecordId(EscherSpRecord.RECORD_ID); + sp.setOptions((short) ((EscherAggregate.ST_NOT_PRIMATIVE << 4) | 0x2)); + if (getParent() == null) { + sp.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE); + } else { + sp.setFlags(EscherSpRecord.FLAG_CHILD | EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE); + } + opt.setRecordId(EscherOptRecord.RECORD_ID); + opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.TRANSFORM__ROTATION, false, false, 0)); + opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__RIGHT, false, false, 100)); + opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__BOTTOM, false, false, 100)); + opt.setEscherProperty(new EscherShapePathProperty(EscherProperties.GEOMETRY__SHAPEPATH, EscherShapePathProperty.COMPLEX)); + + opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__FILLOK, false, false, 0x00010001)); + opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINESTARTARROWHEAD, false, false, 0x0)); + opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEENDARROWHEAD, false, false, 0x0)); + opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEENDCAPSTYLE, false, false, 0x0)); + + opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID)); + opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT)); + opt.setEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT)); + opt.setEscherProperty(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT)); + opt.setEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 0x0)); + + EscherRecord anchor = getAnchor().getEscherAnchor(); + clientData.setRecordId(EscherClientDataRecord.RECORD_ID); + clientData.setOptions((short) 0x0000); + + spContainer.addChildRecord(sp); + spContainer.addChildRecord(opt); + spContainer.addChildRecord(anchor); + spContainer.addChildRecord(clientData); + return spContainer; } - @Override + /** + * Creates the low level OBJ record for this shape. + */ protected ObjRecord createObjRecord() { - return null; - } - - public int[] getXPoints() - { - return xPoints; + ObjRecord obj = new ObjRecord(); + CommonObjectDataSubRecord c = new CommonObjectDataSubRecord(); + c.setObjectType(OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING); + c.setLocked(true); + c.setPrintable(true); + c.setAutofill(true); + c.setAutoline(true); + EndSubRecord e = new EndSubRecord(); + obj.addSubRecord(c); + obj.addSubRecord(e); + return obj; } - public int[] getYPoints() - { - return yPoints; + public int[] getXPoints() { + EscherArrayProperty verticesProp = _optRecord.lookup(EscherProperties.GEOMETRY__VERTICES); + if (null == verticesProp){ + return new int[]{}; + } + int []array = new int[verticesProp.getNumberOfElementsInArray()-1]; + for (int i=0; i< verticesProp.getNumberOfElementsInArray()-1; i++){ + byte[] property = verticesProp.getElement(i); + short x = LittleEndian.getShort(property, 0); + array[i] = x; + } + return array; } - public void setPoints(int[] xPoints, int[] yPoints) - { - this.xPoints = cloneArray(xPoints); - this.yPoints = cloneArray(yPoints); + public int[] getYPoints() { + EscherArrayProperty verticesProp = _optRecord.lookup(EscherProperties.GEOMETRY__VERTICES); + if (null == verticesProp){ + return new int[]{}; + } + int []array = new int[verticesProp.getNumberOfElementsInArray()-1]; + for (int i=0; i< verticesProp.getNumberOfElementsInArray()-1; i++){ + byte[] property = verticesProp.getElement(i); + short x = LittleEndian.getShort(property, 2); + array[i] = x; + } + return array; } - private int[] cloneArray( int[] a ) - { - int[] result = new int[a.length]; - for ( int i = 0; i < a.length; i++ ) - result[i] = a[i]; - - return result; + public void setPoints(int[] xPoints, int[] yPoints) { + if (xPoints.length != yPoints.length){ + System.out.println("xPoint.length must be equal to yPoints.length"); + return; + } + if (xPoints.length == 0){ + System.out.println("HSSFPolygon must have at least one point"); + } + EscherArrayProperty verticesProp = new EscherArrayProperty(EscherProperties.GEOMETRY__VERTICES, false, new byte[0] ); + verticesProp.setNumberOfElementsInArray(xPoints.length+1); + verticesProp.setNumberOfElementsInMemory(xPoints.length+1); + verticesProp.setSizeOfElements(0xFFF0); + for (int i = 0; i < xPoints.length; i++) + { + byte[] data = new byte[4]; + LittleEndian.putShort(data, 0, (short)xPoints[i]); + LittleEndian.putShort(data, 2, (short)yPoints[i]); + verticesProp.setElement(i, data); + } + int point = xPoints.length; + byte[] data = new byte[4]; + LittleEndian.putShort(data, 0, (short)xPoints[0]); + LittleEndian.putShort(data, 2, (short)yPoints[0]); + verticesProp.setElement(point, data); + setPropertyValue(verticesProp); + + EscherArrayProperty segmentsProp = new EscherArrayProperty(EscherProperties.GEOMETRY__SEGMENTINFO, false, null ); + segmentsProp.setSizeOfElements(0x0002); + segmentsProp.setNumberOfElementsInArray(xPoints.length * 2 + 4); + segmentsProp.setNumberOfElementsInMemory(xPoints.length * 2 + 4); + segmentsProp.setElement(0, new byte[] { (byte)0x00, (byte)0x40 } ); + segmentsProp.setElement(1, new byte[] { (byte)0x00, (byte)0xAC } ); + for (int i = 0; i < xPoints.length; i++) + { + segmentsProp.setElement(2 + i * 2, new byte[] { (byte)0x01, (byte)0x00 } ); + segmentsProp.setElement(3 + i * 2, new byte[] { (byte)0x00, (byte)0xAC } ); + } + segmentsProp.setElement(segmentsProp.getNumberOfElementsInArray() - 2, new byte[] { (byte)0x01, (byte)0x60 } ); + segmentsProp.setElement(segmentsProp.getNumberOfElementsInArray() - 1, new byte[] { (byte)0x00, (byte)0x80 } ); + setPropertyValue(segmentsProp); } /** * Defines the width and height of the points in the polygon + * * @param width * @param height */ - public void setPolygonDrawArea( int width, int height ) - { - this.drawAreaWidth = width; - this.drawAreaHeight = height; + public void setPolygonDrawArea(int width, int height) { + setPropertyValue(new EscherSimpleProperty(EscherProperties.GEOMETRY__RIGHT, width)); + setPropertyValue(new EscherSimpleProperty(EscherProperties.GEOMETRY__BOTTOM, height)); } - public int getDrawAreaWidth() - { - return drawAreaWidth; + public int getDrawAreaWidth() { + EscherSimpleProperty property = _optRecord.lookup(EscherProperties.GEOMETRY__RIGHT); + return property == null ? 100: property.getPropertyValue(); } - public int getDrawAreaHeight() - { - return drawAreaHeight; + public int getDrawAreaHeight() { + EscherSimpleProperty property = _optRecord.lookup(EscherProperties.GEOMETRY__BOTTOM); + return property == null ? 100: property.getPropertyValue(); } - + @Override + void afterInsert(HSSFPatriarch patriarch) { + EscherAggregate agg = patriarch._getBoundAggregate(); + agg.associateShapeToObjRecord(_escherContainer.getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord()); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java index 9c2775373f..09bf271fc5 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java @@ -72,7 +72,6 @@ public abstract class HSSFShape { this.anchor = anchor; this._escherContainer = createSpContainer(); _optRecord = _escherContainer.getChildById(EscherOptRecord.RECORD_ID); - addStandardOptions(_optRecord); _objRecord = createObjRecord(); } @@ -87,14 +86,6 @@ public abstract class HSSFShape { CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) _objRecord.getSubRecords().get(0); cod.setObjectId((short) (shapeId-1024)); } - - private void addStandardOptions(EscherOptRecord optRecord){ - setPropertyValue(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID)); - setPropertyValue(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT)); - setPropertyValue(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT)); - setPropertyValue(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT)); - setPropertyValue(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 0x0)); - } int getShapeId(){ return ((EscherSpRecord)_escherContainer.getChildById(EscherSpRecord.RECORD_ID)).getShapeId(); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java index 5358f4868f..1ee53171b6 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java @@ -17,12 +17,7 @@ package org.apache.poi.hssf.usermodel; -import org.apache.poi.ddf.EscherClientDataRecord; -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.ddf.EscherRecord; -import org.apache.poi.ddf.EscherSpRecord; -import org.apache.poi.ddf.EscherSpgrRecord; -import org.apache.poi.ddf.EscherTextboxRecord; +import org.apache.poi.ddf.*; import org.apache.poi.hssf.model.TextboxShape; import org.apache.poi.hssf.record.CommonObjectDataSubRecord; import org.apache.poi.hssf.record.EscherAggregate; @@ -124,6 +119,15 @@ public class HSSFShapeFactory { case CommonObjectDataSubRecord.OBJECT_TYPE_RECTANGLE: shape = new HSSFSimpleShape(container, objRecord); break; + case CommonObjectDataSubRecord.OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING: + EscherOptRecord optRecord = container.getChildById(EscherOptRecord.RECORD_ID); + EscherProperty property = optRecord.lookup(EscherProperties.GEOMETRY__VERTICES); + if (null != property){ + shape = new HSSFPolygon(container, objRecord); + } else { + shape = new HSSFSimpleShape(container, objRecord); + } + break; case CommonObjectDataSubRecord.OBJECT_TYPE_TEXT: shape = new HSSFTextbox(container, objRecord, txtRecord); break; diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java index d98471e33a..eb023e0cae 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java @@ -19,8 +19,7 @@ package org.apache.poi.hssf.usermodel; import org.apache.poi.ddf.*; import org.apache.poi.hssf.model.TextboxShape; -import org.apache.poi.hssf.record.EscherAggregate; -import org.apache.poi.hssf.record.ObjRecord; +import org.apache.poi.hssf.record.*; import java.util.ArrayList; import java.util.List; @@ -32,10 +31,7 @@ import java.util.Iterator; * * @author Glen Stampoultzis (glens at apache.org) */ -public class HSSFShapeGroup - extends HSSFShape - implements HSSFShapeContainer -{ +public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer { List shapes = new ArrayList(); private EscherSpgrRecord _spgrRecord; @@ -45,24 +41,22 @@ public class HSSFShapeGroup // read internal and external coordinates from spgrContainer EscherContainerRecord spContainer = spgrContainer.getChildContainers().get(0); _spgrRecord = (EscherSpgrRecord) spContainer.getChild(0); - for(EscherRecord ch : spContainer.getChildRecords()){ - switch(ch.getRecordId()) { + for (EscherRecord ch : spContainer.getChildRecords()) { + switch (ch.getRecordId()) { case EscherSpgrRecord.RECORD_ID: break; case EscherClientAnchorRecord.RECORD_ID: - anchor = new HSSFClientAnchor((EscherClientAnchorRecord)ch); + anchor = new HSSFClientAnchor((EscherClientAnchorRecord) ch); break; case EscherChildAnchorRecord.RECORD_ID: - anchor = new HSSFChildAnchor((EscherChildAnchorRecord)ch); + anchor = new HSSFChildAnchor((EscherChildAnchorRecord) ch); break; } } - } - public HSSFShapeGroup( HSSFShape parent, HSSFAnchor anchor ) - { - super( parent, anchor ); + public HSSFShapeGroup(HSSFShape parent, HSSFAnchor anchor) { + super(parent, anchor); _spgrRecord = new EscherSpgrRecord(); _spgrRecord.setRectX1(0); _spgrRecord.setRectX2(1023); @@ -72,104 +66,169 @@ public class HSSFShapeGroup @Override protected EscherContainerRecord createSpContainer() { + EscherContainerRecord spgrContainer = new EscherContainerRecord(); EscherContainerRecord spContainer = new EscherContainerRecord(); - spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER ); - spContainer.setOptions( (short) 0x000F ); - EscherOptRecord optRecord = new EscherOptRecord(); - optRecord.setRecordId(EscherOptRecord.RECORD_ID); - spContainer.addChildRecord(optRecord); - return spContainer; + EscherSpgrRecord spgr = new EscherSpgrRecord(); + EscherSpRecord sp = new EscherSpRecord(); + EscherOptRecord opt = new EscherOptRecord(); + EscherRecord anchor; + EscherClientDataRecord clientData = new EscherClientDataRecord(); + + spgrContainer.setRecordId(EscherContainerRecord.SPGR_CONTAINER); + spgrContainer.setOptions((short) 0x000F); + spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER); + spContainer.setOptions((short) 0x000F); + spgr.setRecordId(EscherSpgrRecord.RECORD_ID); + spgr.setOptions((short) 0x0001); + spgr.setRectX1(0); + spgr.setRectY1(0); + spgr.setRectX2(1023); + spgr.setRectY2(255); + sp.setRecordId(EscherSpRecord.RECORD_ID); + sp.setOptions((short) 0x0002); + if (getAnchor() instanceof HSSFClientAnchor) { + sp.setFlags(EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR); + } else { + sp.setFlags(EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_CHILD); + } + opt.setRecordId(EscherOptRecord.RECORD_ID); + opt.setOptions((short) 0x0023); + opt.addEscherProperty(new EscherBoolProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x00040004)); + opt.addEscherProperty(new EscherBoolProperty(EscherProperties.GROUPSHAPE__PRINT, 0x00080000)); + + anchor = getAnchor().getEscherAnchor(); + clientData.setRecordId(EscherClientDataRecord.RECORD_ID); + clientData.setOptions((short) 0x0000); + + spgrContainer.addChildRecord(spContainer); + spContainer.addChildRecord(spgr); + spContainer.addChildRecord(sp); + spContainer.addChildRecord(opt); + spContainer.addChildRecord(anchor); + spContainer.addChildRecord(clientData); + return spgrContainer; } @Override protected ObjRecord createObjRecord() { - return null; //To change body of implemented methods use File | Settings | File Templates. + ObjRecord obj = new ObjRecord(); + CommonObjectDataSubRecord cmo = new CommonObjectDataSubRecord(); + cmo.setObjectType(CommonObjectDataSubRecord.OBJECT_TYPE_GROUP); + cmo.setLocked(true); + cmo.setPrintable(true); + cmo.setAutofill(true); + cmo.setAutoline(true); + GroupMarkerSubRecord gmo = new GroupMarkerSubRecord(); + EndSubRecord end = new EndSubRecord(); + obj.addSubRecord(cmo); + obj.addSubRecord(gmo); + obj.addSubRecord(end); + return obj; + } + + private void onCreate(HSSFShape shape){ + if(_patriarch != null && _patriarch._getBoundAggregate().getPatriarch() == null){ + EscherContainerRecord spContainer = shape.getEscherContainer(); + int shapeId = _patriarch.newShapeId(); + shape.setShapeId(shapeId); + _escherContainer.addChildRecord(spContainer); + shape.afterInsert(_patriarch); + } } /** * Create another group under this group. - * @param anchor the position of the new group. - * @return the group + * + * @param anchor the position of the new group. + * @return the group */ - public HSSFShapeGroup createGroup(HSSFChildAnchor anchor) - { + public HSSFShapeGroup createGroup(HSSFChildAnchor anchor) { HSSFShapeGroup group = new HSSFShapeGroup(this, anchor); + group.parent = this; group.anchor = anchor; shapes.add(group); + onCreate(group); return group; } - public void addShape(HSSFShape shape){ + public void addShape(HSSFShape shape) { shape._patriarch = this._patriarch; + shape.parent = this; shapes.add(shape); } - public void addTextBox(TextboxShape textboxShape){ + public void addTextBox(TextboxShape textboxShape) { // HSSFTextbox shape = new HSSFTextbox(this, textboxShape.geanchor); // shapes.add(textboxShape); } /** * Create a new simple shape under this group. - * @param anchor the position of the shape. - * @return the shape + * + * @param anchor the position of the shape. + * @return the shape */ - public HSSFSimpleShape createShape(HSSFChildAnchor anchor) - { + public HSSFSimpleShape createShape(HSSFChildAnchor anchor) { HSSFSimpleShape shape = new HSSFSimpleShape(this, anchor); + shape.parent = this; shape.anchor = anchor; shapes.add(shape); + onCreate(shape); return shape; } /** * Create a new textbox under this group. - * @param anchor the position of the shape. - * @return the textbox + * + * @param anchor the position of the shape. + * @return the textbox */ - public HSSFTextbox createTextbox(HSSFChildAnchor anchor) - { + public HSSFTextbox createTextbox(HSSFChildAnchor anchor) { HSSFTextbox shape = new HSSFTextbox(this, anchor); + shape.parent = this; shape.anchor = anchor; shapes.add(shape); + onCreate(shape); return shape; } /** * Creates a polygon * - * @param anchor the client anchor describes how this group is attached - * to the sheet. - * @return the newly created shape. + * @param anchor the client anchor describes how this group is attached + * to the sheet. + * @return the newly created shape. */ - public HSSFPolygon createPolygon(HSSFChildAnchor anchor) - { + public HSSFPolygon createPolygon(HSSFChildAnchor anchor) { HSSFPolygon shape = new HSSFPolygon(this, anchor); + shape.parent = this; shape.anchor = anchor; shapes.add(shape); + onCreate(shape); return shape; } /** * Creates a picture. * - * @param anchor the client anchor describes how this group is attached - * to the sheet. - * @return the newly created shape. + * @param anchor the client anchor describes how this group is attached + * to the sheet. + * @return the newly created shape. */ - public HSSFPicture createPicture(HSSFChildAnchor anchor, int pictureIndex) - { - HSSFPicture shape = new HSSFPicture(this, anchor); - shape.anchor = anchor; - shape.setPictureIndex( pictureIndex ); - shapes.add(shape); - return shape; + public HSSFPicture createPicture(HSSFChildAnchor anchor, int pictureIndex) { + HSSFPicture shape = new HSSFPicture(this, anchor); + shape.parent = this; + shape.anchor = anchor; + shape.setPictureIndex(pictureIndex); + shapes.add(shape); + onCreate(shape); + return shape; } + /** * Return all children contained by this shape. */ - public List getChildren() - { + public List getChildren() { return shapes; } @@ -177,8 +236,7 @@ public class HSSFShapeGroup * Sets the coordinate space of this group. All children are constrained * to these coordinates. */ - public void setCoordinates( int x1, int y1, int x2, int y2 ) - { + public void setCoordinates(int x1, int y1, int x2, int y2) { _spgrRecord.setRectX1(x1); _spgrRecord.setRectX2(x2); _spgrRecord.setRectY1(y1); @@ -188,46 +246,62 @@ public class HSSFShapeGroup /** * The top left x coordinate of this group. */ - public int getX1() - { + public int getX1() { return _spgrRecord.getRectX1(); } /** * The top left y coordinate of this group. */ - public int getY1() - { + public int getY1() { return _spgrRecord.getRectY1(); } /** * The bottom right x coordinate of this group. */ - public int getX2() - { + public int getX2() { return _spgrRecord.getRectX2(); } /** * The bottom right y coordinate of this group. */ - public int getY2() - { + public int getY2() { return _spgrRecord.getRectY2(); } /** * Count of all children and their childrens children. */ - public int countOfAllChildren() - { + public int countOfAllChildren() { int count = shapes.size(); - for ( Iterator iterator = shapes.iterator(); iterator.hasNext(); ) - { + for (Iterator iterator = shapes.iterator(); iterator.hasNext(); ) { HSSFShape shape = (HSSFShape) iterator.next(); count += shape.countOfAllChildren(); } return count; } + + @Override + void afterInsert(HSSFPatriarch patriarch){ + EscherAggregate agg = patriarch._getBoundAggregate(); + EscherContainerRecord containerRecord = _escherContainer.getChildById(EscherContainerRecord.SP_CONTAINER); + agg.associateShapeToObjRecord(containerRecord.getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord()); + } + + @Override + void setShapeId(int shapeId){ + EscherContainerRecord containerRecord = _escherContainer.getChildById(EscherContainerRecord.SP_CONTAINER); + EscherSpRecord spRecord = containerRecord.getChildById(EscherSpRecord.RECORD_ID); + spRecord.setShapeId(shapeId); + CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) _objRecord.getSubRecords().get(0); + cod.setObjectId((short) (shapeId-1024)); + } + + @Override + int getShapeId(){ + EscherContainerRecord containerRecord = _escherContainer.getChildById(EscherContainerRecord.SP_CONTAINER); + return ((EscherSpRecord)containerRecord.getChildById(EscherSpRecord.RECORD_ID)).getShapeId(); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java index 2b64faaa5a..62b9d6a8e0 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java @@ -32,8 +32,7 @@ import java.util.Map; * * @author Glen Stampoultzis (glens at apache.org) */ -public class HSSFSimpleShape - extends HSSFShape +public class HSSFSimpleShape extends HSSFShape { // The commented out ones haven't been tested yet or aren't supported // by HSSFSimpleShape. @@ -93,6 +92,11 @@ public class HSSFSimpleShape clientData.setOptions( (short) 0x0000 ); EscherOptRecord optRecord = new EscherOptRecord(); + optRecord.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID)); + optRecord.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT)); + optRecord.setEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT)); + optRecord.setEscherProperty(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT)); + optRecord.setEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 0x0)); optRecord.setRecordId( EscherOptRecord.RECORD_ID ); spContainer.addChildRecord(sp); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java b/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java index 42385a87ed..1ed70f86a6 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java @@ -118,6 +118,12 @@ public class HSSFTextbox extends HSSFSimpleShape { opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTTOP, 0)); opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTBOTTOM, 0)); + opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID)); + opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT)); + opt.setEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT)); + opt.setEscherProperty(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT)); + opt.setEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 0x0)); + EscherRecord anchor = getAnchor().getEscherAnchor(); clientData.setRecordId(EscherClientDataRecord.RECORD_ID); diff --git a/src/testcases/org/apache/poi/hssf/model/HSSFTestModelHelper.java b/src/testcases/org/apache/poi/hssf/model/HSSFTestModelHelper.java index 507561e7e4..bc22d17a97 100644 --- a/src/testcases/org/apache/poi/hssf/model/HSSFTestModelHelper.java +++ b/src/testcases/org/apache/poi/hssf/model/HSSFTestModelHelper.java @@ -1,6 +1,7 @@ package org.apache.poi.hssf.model; import org.apache.poi.hssf.usermodel.HSSFComment; +import org.apache.poi.hssf.usermodel.HSSFPolygon; import org.apache.poi.hssf.usermodel.HSSFTextbox; /** @@ -15,4 +16,8 @@ public class HSSFTestModelHelper { public static CommentShape createCommentShape(int shapeId, HSSFComment comment){ return new CommentShape(comment, shapeId); } + + public static PolygonShape createPolygonShape(int shapeId, HSSFPolygon polygon){ + return new PolygonShape(polygon, shapeId); + } } diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java index 18572d6ec1..1f058c06da 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java @@ -201,7 +201,7 @@ public class TestDrawingAggregate extends TestCase { HSSFPatriarch drawing = sheet.createDrawingPatriarch(); EscherAggregate agg1 = HSSFTestHelper.getEscherAggregate(drawing); - callConvertPatriarch(agg1); + HSSFTestHelper.callConvertPatriarch(agg1); agg1.setPatriarch(null); agg.setPatriarch(null); @@ -213,20 +213,7 @@ public class TestDrawingAggregate extends TestCase { assertTrue(Arrays.equals(aggS, agg1S)); } - private static void callConvertPatriarch(EscherAggregate agg) { - Method method = null; - try { - method = agg.getClass().getDeclaredMethod("convertPatriarch", HSSFPatriarch.class); - method.setAccessible(true); - method.invoke(agg, agg.getPatriarch()); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } catch (InvocationTargetException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - } + /** * when reading incomplete data ensure that the serialized bytes diff --git a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java index 9b2273c590..214121d940 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java @@ -16,17 +16,40 @@ ==================================================================== */ package org.apache.poi.hssf.usermodel; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherDggRecord; import org.apache.poi.ddf.EscherOptRecord; +import org.apache.poi.hssf.model.DrawingManager2; import org.apache.poi.hssf.model.InternalSheet; import org.apache.poi.hssf.model.InternalWorkbook; import org.apache.poi.hssf.record.EscherAggregate; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Map; + /** * Helper class for HSSF tests that aren't within the * HSSF UserModel package, but need to do internal * UserModel things. */ public class HSSFTestHelper { + + private static class MockDrawingManager extends DrawingManager2 { +// +// public MockDrawingManager(EscherDggRecord dgg) { +// super(dgg); +// } + + public MockDrawingManager (){ + super(null); + } + + @Override + public int allocateShapeId(short drawingGroupId) { + return 0; //Mock value + } + } /** * Lets non UserModel tests at the low level Workbook */ @@ -52,4 +75,34 @@ public class HSSFTestHelper { public static EscherOptRecord getOptRecord(HSSFShape shape){ return shape._optRecord; } + + public static void convertHSSFGroup(HSSFShapeGroup shape, EscherContainerRecord escherParent, Map shapeToObj){ + Class clazz = EscherAggregate.class; + try { + Method method = clazz.getDeclaredMethod("convertGroup", HSSFShapeGroup.class, EscherContainerRecord.class, Map.class); + method.setAccessible(true); + method.invoke(new EscherAggregate(new MockDrawingManager()), shape, escherParent, shapeToObj); + } catch (NoSuchMethodException e) { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } catch (InvocationTargetException e) { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } catch (IllegalAccessException e) { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + } + + public static void callConvertPatriarch(EscherAggregate agg) { + Method method = null; + try { + method = agg.getClass().getDeclaredMethod("convertPatriarch", HSSFPatriarch.class); + method.setAccessible(true); + method.invoke(agg, agg.getPatriarch()); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } catch (InvocationTargetException e) { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestPolygon.java b/src/testcases/org/apache/poi/hssf/usermodel/TestPolygon.java new file mode 100644 index 0000000000..7c83a0d25f --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestPolygon.java @@ -0,0 +1,231 @@ +package org.apache.poi.hssf.usermodel; + +import junit.framework.TestCase; +import org.apache.poi.ddf.EscherArrayProperty; +import org.apache.poi.ddf.EscherOptRecord; +import org.apache.poi.ddf.EscherProperties; +import org.apache.poi.ddf.EscherSpRecord; +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.model.HSSFTestModelHelper; +import org.apache.poi.hssf.model.PolygonShape; +import org.apache.poi.hssf.record.ObjRecord; + +import java.io.IOException; +import java.util.Arrays; + +/** + * @author Evgeniy Berlog + * @date 28.06.12 + */ +public class TestPolygon extends TestCase{ + + public void testResultEqualsToAbstractShape() throws IOException { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + + HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor()); + polygon.setPolygonDrawArea( 100, 100 ); + polygon.setPoints( new int[]{0, 90, 50}, new int[]{5, 5, 44} ); + PolygonShape polygonShape = HSSFTestModelHelper.createPolygonShape(1024, polygon); + polygon.setShapeId(1024); + + assertEquals(polygon.getEscherContainer().getChildRecords().size(), 4); + assertEquals(polygonShape.getSpContainer().getChildRecords().size(), 4); + + //sp record + byte[] expected = polygonShape.getSpContainer().getChild(0).serialize(); + byte[] actual = polygon.getEscherContainer().getChild(0).serialize(); + + assertEquals(expected.length, actual.length); + assertTrue(Arrays.equals(expected, actual)); + + expected = polygonShape.getSpContainer().getChild(2).serialize(); + actual = polygon.getEscherContainer().getChild(2).serialize(); + + assertEquals(expected.length, actual.length); + assertTrue(Arrays.equals(expected, actual)); + + expected = polygonShape.getSpContainer().getChild(3).serialize(); + actual = polygon.getEscherContainer().getChild(3).serialize(); + + assertEquals(expected.length, actual.length); + assertTrue(Arrays.equals(expected, actual)); + + ObjRecord obj = polygon.getObjRecord(); + ObjRecord objShape = polygonShape.getObjRecord(); + + expected = obj.serialize(); + actual = objShape.serialize(); + + assertEquals(expected.length, actual.length); + assertTrue(Arrays.equals(expected, actual)); + } + + public void testPolygonPoints(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + + HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor()); + polygon.setPolygonDrawArea( 100, 100 ); + polygon.setPoints( new int[]{0, 90, 50, 90}, new int[]{5, 5, 44, 88} ); + + PolygonShape polygonShape = HSSFTestModelHelper.createPolygonShape(0, polygon); + + EscherArrayProperty verticesProp1 = polygon._optRecord.lookup(EscherProperties.GEOMETRY__VERTICES); + EscherArrayProperty verticesProp2 = ((EscherOptRecord)polygonShape.getSpContainer().getChildById(EscherOptRecord.RECORD_ID)) + .lookup(EscherProperties.GEOMETRY__VERTICES); + + assertEquals(verticesProp1.getNumberOfElementsInArray(), verticesProp2.getNumberOfElementsInArray()); + assertEquals(verticesProp1.toXml(""), verticesProp2.toXml("")); + + polygon.setPoints(new int[]{1,2,3}, new int[] {4,5,6}); + assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{1, 2, 3})); + assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{4, 5, 6})); + + polygonShape = HSSFTestModelHelper.createPolygonShape(0, polygon); + verticesProp1 = polygon._optRecord.lookup(EscherProperties.GEOMETRY__VERTICES); + verticesProp2 = ((EscherOptRecord)polygonShape.getSpContainer().getChildById(EscherOptRecord.RECORD_ID)) + .lookup(EscherProperties.GEOMETRY__VERTICES); + + assertEquals(verticesProp1.getNumberOfElementsInArray(), verticesProp2.getNumberOfElementsInArray()); + assertEquals(verticesProp1.toXml(""), verticesProp2.toXml("")); + } + + public void testSetGetProperties(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + + HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor()); + polygon.setPolygonDrawArea( 102, 101 ); + polygon.setPoints( new int[]{1,2,3}, new int[]{4,5,6} ); + + assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{1,2,3})); + assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{4, 5, 6})); + assertEquals(polygon.getDrawAreaHeight(), 101); + assertEquals(polygon.getDrawAreaWidth(), 102); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + polygon = (HSSFPolygon) patriarch.getChildren().get(0); + assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{1, 2, 3})); + assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{4, 5, 6})); + assertEquals(polygon.getDrawAreaHeight(), 101); + assertEquals(polygon.getDrawAreaWidth(), 102); + + polygon.setPolygonDrawArea( 1021, 1011 ); + polygon.setPoints( new int[]{11,21,31}, new int[]{41,51,61} ); + + assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{11, 21, 31})); + assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{41, 51, 61})); + assertEquals(polygon.getDrawAreaHeight(), 1011); + assertEquals(polygon.getDrawAreaWidth(), 1021); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + polygon = (HSSFPolygon) patriarch.getChildren().get(0); + + assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{11, 21, 31})); + assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{41, 51, 61})); + assertEquals(polygon.getDrawAreaHeight(), 1011); + assertEquals(polygon.getDrawAreaWidth(), 1021); + } + + public void testAddToExistingFile(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + + HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor()); + polygon.setPolygonDrawArea( 102, 101 ); + polygon.setPoints( new int[]{1,2,3}, new int[]{4,5,6} ); + + HSSFPolygon polygon1 = patriarch.createPolygon(new HSSFClientAnchor()); + polygon1.setPolygonDrawArea( 103, 104 ); + polygon1.setPoints( new int[]{11,12,13}, new int[]{14,15,16} ); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + assertEquals(patriarch.getChildren().size(), 2); + + HSSFPolygon polygon2 = patriarch.createPolygon(new HSSFClientAnchor()); + polygon2.setPolygonDrawArea( 203, 204 ); + polygon2.setPoints( new int[]{21,22,23}, new int[]{24,25,26} ); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + assertEquals(patriarch.getChildren().size(), 3); + + polygon = (HSSFPolygon) patriarch.getChildren().get(0); + polygon1 = (HSSFPolygon) patriarch.getChildren().get(1); + polygon2 = (HSSFPolygon) patriarch.getChildren().get(2); + + assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{1, 2, 3})); + assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{4,5,6})); + assertEquals(polygon.getDrawAreaHeight(), 101); + assertEquals(polygon.getDrawAreaWidth(), 102); + + assertTrue(Arrays.equals(polygon1.getXPoints(), new int[]{11,12,13})); + assertTrue(Arrays.equals(polygon1.getYPoints(), new int[]{14,15,16})); + assertEquals(polygon1.getDrawAreaHeight(), 104); + assertEquals(polygon1.getDrawAreaWidth(), 103); + + assertTrue(Arrays.equals(polygon2.getXPoints(), new int[]{21,22,23})); + assertTrue(Arrays.equals(polygon2.getYPoints(), new int[]{24,25,26})); + assertEquals(polygon2.getDrawAreaHeight(), 204); + assertEquals(polygon2.getDrawAreaWidth(), 203); + } + + public void testExistingFile() throws IOException { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); + HSSFSheet sheet = wb.getSheet("polygon"); + HSSFPatriarch drawing = sheet.getDrawingPatriarch(); + assertEquals(1, drawing.getChildren().size()); + + HSSFPolygon polygon = (HSSFPolygon) drawing.getChildren().get(0); + assertEquals(polygon.getDrawAreaHeight(), 2466975); + assertEquals(polygon.getDrawAreaWidth(), 3686175); + assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{0, 0, 31479, 16159, 19676, 20502})); + assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{0, 0, 36, 56, 34, 18})); + } + + public void testPolygonType(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + + HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor()); + polygon.setPolygonDrawArea( 102, 101 ); + polygon.setPoints( new int[]{1,2,3}, new int[]{4,5,6} ); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + HSSFPolygon polygon1 = patriarch.createPolygon(new HSSFClientAnchor()); + polygon1.setPolygonDrawArea( 102, 101 ); + polygon1.setPoints( new int[]{1,2,3}, new int[]{4,5,6} ); + + EscherSpRecord spRecord = polygon1.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); + + spRecord.setShapeType((short)77/**RANDOM**/); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + assertEquals(patriarch.getChildren().size(), 2); + assertTrue(patriarch.getChildren().get(0) instanceof HSSFPolygon); + assertTrue(patriarch.getChildren().get(1) instanceof HSSFPolygon); + } +} diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java b/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java new file mode 100644 index 0000000000..bdbf25fc4d --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java @@ -0,0 +1,225 @@ +package org.apache.poi.hssf.usermodel; + +import junit.framework.TestCase; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.record.ObjRecord; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Evgeniy Berlog + * @date 29.06.12 + */ +public class TestShapeGroup extends TestCase{ + + public void testResultEqualsToAbstractShape() { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet(); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor()); + + EscherContainerRecord container = new EscherContainerRecord(); + Map shapeToObj = new HashMap(); + HSSFTestHelper.convertHSSFGroup(group, container, shapeToObj); + + byte [] actual = group.getEscherContainer().serialize(); + byte [] expected = container.getChild(0).serialize(); + + assertEquals(actual.length, expected.length); + assertTrue(Arrays.equals(actual, expected)); + + actual = group.getObjRecord().serialize(); + expected = ((ObjRecord)shapeToObj.values().toArray()[0]).serialize(); + + assertEquals(actual.length, expected.length); + assertTrue(Arrays.equals(actual, expected)); + } + + public void testSetGetCoordinates(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor()); + assertEquals(group.getX1(), 0); + assertEquals(group.getY1(), 0); + assertEquals(group.getX2(), 1023); + assertEquals(group.getY2(), 255); + + group.setCoordinates(1,2,3,4); + + assertEquals(group.getX1(), 1); + assertEquals(group.getY1(), 2); + assertEquals(group.getX2(), 3); + assertEquals(group.getY2(), 4); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + group = (HSSFShapeGroup) patriarch.getChildren().get(0); + assertEquals(group.getX1(), 1); + assertEquals(group.getY1(), 2); + assertEquals(group.getX2(), 3); + assertEquals(group.getY2(), 4); + } + + public void testAddToExistingFile(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + HSSFShapeGroup group1 = patriarch.createGroup(new HSSFClientAnchor()); + HSSFShapeGroup group2 = patriarch.createGroup(new HSSFClientAnchor()); + + group1.setCoordinates(1,2,3,4); + group2.setCoordinates(5,6,7,8); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + assertEquals(patriarch.getChildren().size(), 2); + + HSSFShapeGroup group3 = patriarch.createGroup(new HSSFClientAnchor()); + group3.setCoordinates(9,10,11,12); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + assertEquals(patriarch.getChildren().size(), 3); + } + + public void testModify() throws Exception { + HSSFWorkbook wb = new HSSFWorkbook(); + + // create a sheet with a text box + HSSFSheet sheet = wb.createSheet(); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + + HSSFShapeGroup group1 = patriarch.createGroup(new + HSSFClientAnchor(0,0,0,0, + (short)0, 0, (short)15, 25)); + group1.setCoordinates(0, 0, 792, 612); + + HSSFTextbox textbox1 = group1.createTextbox(new + HSSFChildAnchor(100, 100, 300, 300)); + HSSFRichTextString rt1 = new HSSFRichTextString("Hello, World!"); + textbox1.setString(rt1); + + // write, read back and check that our text box is there + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + assertEquals(1, patriarch.getChildren().size()); + + group1 = (HSSFShapeGroup)patriarch.getChildren().get(0); + assertEquals(1, group1.getChildren().size()); + textbox1 = (HSSFTextbox)group1.getChildren().get(0); + assertEquals("Hello, World!", textbox1.getString().getString()); + + // modify anchor + assertEquals(new HSSFChildAnchor(100, 100, 300, 300), + textbox1.getAnchor()); + HSSFChildAnchor newAnchor = new HSSFChildAnchor(200,200, 400, 400); + textbox1.setAnchor(newAnchor); + // modify text + textbox1.setString(new HSSFRichTextString("Hello, World! (modified)")); + + // add a new text box + HSSFTextbox textbox2 = group1.createTextbox(new + HSSFChildAnchor(400, 400, 600, 600)); + HSSFRichTextString rt2 = new HSSFRichTextString("Hello, World-2"); + textbox2.setString(rt2); + assertEquals(2, group1.getChildren().size()); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + assertEquals(1, patriarch.getChildren().size()); + + group1 = (HSSFShapeGroup)patriarch.getChildren().get(0); + assertEquals(2, group1.getChildren().size()); + textbox1 = (HSSFTextbox)group1.getChildren().get(0); + assertEquals("Hello, World! (modified)", + textbox1.getString().getString()); + assertEquals(new HSSFChildAnchor(200,200, 400, 400), + textbox1.getAnchor()); + + textbox2 = (HSSFTextbox)group1.getChildren().get(1); + assertEquals("Hello, World-2", textbox2.getString().getString()); + assertEquals(new HSSFChildAnchor(400, 400, 600, 600), + textbox2.getAnchor()); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + group1 = (HSSFShapeGroup)patriarch.getChildren().get(0); + textbox1 = (HSSFTextbox)group1.getChildren().get(0); + textbox2 = (HSSFTextbox)group1.getChildren().get(1); + HSSFTextbox textbox3 = group1.createTextbox(new + HSSFChildAnchor(400,200, 600, 400)); + HSSFRichTextString rt3 = new HSSFRichTextString("Hello, World-3"); + textbox3.setString(rt3); + } + + public void testAddShapesToGroup(){ + HSSFWorkbook wb = new HSSFWorkbook(); + + // create a sheet with a text box + HSSFSheet sheet = wb.createSheet(); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + + HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor()); + int index = wb.addPicture(new byte[]{1,2,3}, HSSFWorkbook.PICTURE_TYPE_JPEG); + group.createPicture(new HSSFChildAnchor(), index); + HSSFPolygon polygon = group.createPolygon(new HSSFChildAnchor()); + polygon.setPoints(new int[]{1,100, 1}, new int[]{1, 50, 100}); + group.createTextbox(new HSSFChildAnchor()); + group.createShape(new HSSFChildAnchor()); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + assertEquals(1, patriarch.getChildren().size()); + + assertTrue(patriarch.getChildren().get(0) instanceof HSSFShapeGroup); + group = (HSSFShapeGroup) patriarch.getChildren().get(0); + + assertEquals(group.getChildren().size(), 4); + + assertTrue(group.getChildren().get(0) instanceof HSSFPicture); + assertTrue(group.getChildren().get(1) instanceof HSSFPolygon); + assertTrue(group.getChildren().get(2) instanceof HSSFTextbox); + assertTrue(group.getChildren().get(3) instanceof HSSFSimpleShape); + + HSSFShapeGroup group2 = patriarch.createGroup(new HSSFClientAnchor()); + + index = wb.addPicture(new byte[]{2,2,2}, HSSFWorkbook.PICTURE_TYPE_JPEG); + group2.createPicture(new HSSFChildAnchor(), index); + polygon = group2.createPolygon(new HSSFChildAnchor()); + polygon.setPoints(new int[]{1,100, 1}, new int[]{1, 50, 100}); + group2.createTextbox(new HSSFChildAnchor()); + group2.createShape(new HSSFChildAnchor()); + group2.createShape(new HSSFChildAnchor()); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + assertEquals(2, patriarch.getChildren().size()); + + group = (HSSFShapeGroup) patriarch.getChildren().get(1); + + assertEquals(group.getChildren().size(), 5); + + assertTrue(group.getChildren().get(0) instanceof HSSFPicture); + assertTrue(group.getChildren().get(1) instanceof HSSFPolygon); + assertTrue(group.getChildren().get(2) instanceof HSSFTextbox); + assertTrue(group.getChildren().get(3) instanceof HSSFSimpleShape); + assertTrue(group.getChildren().get(4) instanceof HSSFSimpleShape); + + group.getShapeId(); + } +} diff --git a/test-data/spreadsheet/drawings.xls b/test-data/spreadsheet/drawings.xls index 24684cb6cc..9700c91086 100644 Binary files a/test-data/spreadsheet/drawings.xls and b/test-data/spreadsheet/drawings.xls differ