diff --git a/src/java/org/apache/poi/ddf/EscherClientAnchorRecord.java b/src/java/org/apache/poi/ddf/EscherClientAnchorRecord.java index fbca0fb87..ffc9170c4 100644 --- a/src/java/org/apache/poi/ddf/EscherClientAnchorRecord.java +++ b/src/java/org/apache/poi/ddf/EscherClientAnchorRecord.java @@ -1,4 +1,3 @@ - /* ==================================================================== Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with @@ -38,6 +37,14 @@ public class EscherClientAnchorRecord public static final short RECORD_ID = (short) 0xF010; public static final String RECORD_DESCRIPTION = "MsofbtClientAnchor"; + /** + * bit[0] - fMove (1 bit): A bit that specifies whether the shape will be kept intact when the cells are moved. + * bit[1] - fSize (1 bit): A bit that specifies whether the shape will be kept intact when the cells are resized. If fMove is 1, the value MUST be 1. + * bit[2-4] - reserved, MUST be 0 and MUST be ignored + * bit[5-15]- Undefined and MUST be ignored. + * + * it can take values: 0, 2, 3 + */ private short field_1_flag; private short field_2_col1; private short field_3_dx1; diff --git a/src/java/org/apache/poi/ddf/EscherRGBProperty.java b/src/java/org/apache/poi/ddf/EscherRGBProperty.java index 5d23addfb..e28b97b50 100644 --- a/src/java/org/apache/poi/ddf/EscherRGBProperty.java +++ b/src/java/org/apache/poi/ddf/EscherRGBProperty.java @@ -38,6 +38,10 @@ public class EscherRGBProperty return propertyValue; } + public void setRgbColor(int color){ + this.propertyValue = color; + } + public byte getRed() { return (byte) ( propertyValue & 0xFF ); diff --git a/src/java/org/apache/poi/ddf/EscherSimpleProperty.java b/src/java/org/apache/poi/ddf/EscherSimpleProperty.java index 78fb64203..efc392dcf 100644 --- a/src/java/org/apache/poi/ddf/EscherSimpleProperty.java +++ b/src/java/org/apache/poi/ddf/EscherSimpleProperty.java @@ -80,6 +80,10 @@ public class EscherSimpleProperty extends EscherProperty return propertyValue; } + public void setPropertyValue(int propertyValue) { + this.propertyValue = propertyValue; + } + /** * Returns true if one escher property is equal to another. */ diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFAnchor.java b/src/java/org/apache/poi/hssf/usermodel/HSSFAnchor.java index 6a8780610..2fe36130c 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFAnchor.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFAnchor.java @@ -18,40 +18,64 @@ package org.apache.poi.hssf.usermodel; +import org.apache.poi.ddf.EscherChildAnchorRecord; +import org.apache.poi.ddf.EscherClientAnchorRecord; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherRecord; + /** * An anchor is what specifics the position of a shape within a client object * or within another containing shape. * * @author Glen Stampoultzis (glens at apache.org) */ -public abstract class HSSFAnchor -{ - int dx1; - int dy1; - int dx2; - int dy2; +public abstract class HSSFAnchor { - public HSSFAnchor() - { + public HSSFAnchor() { + createEscherAnchor(); } - public HSSFAnchor( int dx1, int dy1, int dx2, int dy2 ) - { - this.dx1 = dx1; - this.dy1 = dy1; - this.dx2 = dx2; - this.dy2 = dy2; + public HSSFAnchor(int dx1, int dy1, int dx2, int dy2) { + createEscherAnchor(); + setDx1(dx1); + setDy1(dy1); + setDx2(dx2); + setDy2(dy2); } - public int getDx1(){ return dx1; } - public void setDx1( int dx1 ){ this.dx1 = dx1; } - public int getDy1(){ return dy1; } - public void setDy1( int dy1 ){ this.dy1 = dy1; } - public int getDy2(){ return dy2; } - public void setDy2( int dy2 ){ this.dy2 = dy2; } - public int getDx2(){ return dx2; } - public void setDx2( int dx2 ){ this.dx2 = dx2; } + public static HSSFAnchor createAnchorFromEscher(EscherContainerRecord container){ + if (null != container.getChildById(EscherChildAnchorRecord.RECORD_ID)){ + return new HSSFChildAnchor((EscherChildAnchorRecord) container.getChildById(EscherChildAnchorRecord.RECORD_ID)); + } else { + if (null != container.getChildById(EscherClientAnchorRecord.RECORD_ID)){ + return new HSSFClientAnchor((EscherClientAnchorRecord) container.getChildById(EscherClientAnchorRecord.RECORD_ID)); + } + return null; +// throw new IllegalArgumentException("continer must have anchor record"); + } + } + + public abstract int getDx1(); + + public abstract void setDx1(int dx1); + + public abstract int getDy1(); + + public abstract void setDy1(int dy1); + + public abstract int getDy2(); + + public abstract void setDy2(int dy2); + + public abstract int getDx2(); + + public abstract void setDx2(int dx2); public abstract boolean isHorizontallyFlipped(); + public abstract boolean isVerticallyFlipped(); + + public abstract EscherRecord getEscherAnchor(); + + protected abstract void createEscherAnchor(); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java b/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java index ccd0e620c..38c4f5f0e 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java @@ -19,39 +19,100 @@ package org.apache.poi.hssf.usermodel; import org.apache.poi.ddf.EscherChildAnchorRecord; +import org.apache.poi.ddf.EscherRecord; public final class HSSFChildAnchor extends HSSFAnchor { - private EscherChildAnchorRecord escherChildAnchorRecord; + private EscherChildAnchorRecord _escherChildAnchor; public HSSFChildAnchor(EscherChildAnchorRecord escherChildAnchorRecord) { - this.escherChildAnchorRecord = escherChildAnchorRecord; + this._escherChildAnchor = escherChildAnchorRecord; } - public HSSFChildAnchor() - { + public HSSFChildAnchor() { + _escherChildAnchor = new EscherChildAnchorRecord(); } - public HSSFChildAnchor( int dx1, int dy1, int dx2, int dy2 ) - { - super( dx1, dy1, dx2, dy2 ); + public HSSFChildAnchor(int dx1, int dy1, int dx2, int dy2) { + super(dx1, dy1, dx2, dy2); } - public void setAnchor(int dx1, int dy1, int dx2, int dy2) - { - this.dx1 = dx1; - this.dy1 = dy1; - this.dx2 = dx2; - this.dy2 = dy2; + @Override + public int getDx1() { + return _escherChildAnchor.getDx1(); } - public boolean isHorizontallyFlipped() - { - return dx1 > dx2; + @Override + public void setDx1(int dx1) { + _escherChildAnchor.setDx1(dx1); } - public boolean isVerticallyFlipped() - { - return dy1 > dy2; + @Override + public int getDy1() { + return _escherChildAnchor.getDy1(); + } + + @Override + public void setDy1(int dy1) { + _escherChildAnchor.setDy1(dy1); + } + + @Override + public int getDy2() { + return _escherChildAnchor.getDy2(); + } + + @Override + public void setDy2(int dy2) { + _escherChildAnchor.setDy2(dy2); + } + + @Override + public int getDx2() { + return _escherChildAnchor.getDx2(); + } + + @Override + public void setDx2(int dx2) { + _escherChildAnchor.setDx2(dx2); + } + + public void setAnchor(int dx1, int dy1, int dx2, int dy2) { + setDx1(dx1); + setDy1(dy1); + setDx2(dx2); + setDy2(dy2); + } + + public boolean isHorizontallyFlipped() { + return getDx1() > getDx2(); + } + + public boolean isVerticallyFlipped() { + return getDy1() > getDy2(); + } + + @Override + public EscherRecord getEscherAnchor() { + return _escherChildAnchor; + } + + @Override + protected void createEscherAnchor() { + _escherChildAnchor = new EscherChildAnchorRecord(); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) + return false; + if (obj == this) + return true; + if (obj.getClass() != getClass()) + return false; + HSSFChildAnchor anchor = (HSSFChildAnchor) obj; + + return anchor.getDx1() == getDx1() && anchor.getDx2() == getDx2() && anchor.getDy1() == getDy1() + && anchor.getDy2() == getDy2(); } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java b/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java index a040144c2..49e20a42f 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java @@ -18,9 +18,9 @@ package org.apache.poi.hssf.usermodel; import org.apache.poi.ddf.EscherClientAnchorRecord; +import org.apache.poi.ddf.EscherRecord; import org.apache.poi.ss.usermodel.ClientAnchor; - /** * A client anchor is attached to an excel worksheet. It anchors against a * top-left and buttom-right cell. @@ -28,42 +28,34 @@ import org.apache.poi.ss.usermodel.ClientAnchor; * @author Glen Stampoultzis (glens at apache.org) */ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor { - short col1; - int row1; - short col2; - int row2; - int anchorType; - private EscherClientAnchorRecord escherClientAnchorRecord; + private EscherClientAnchorRecord _escherClientAnchor; public HSSFClientAnchor(EscherClientAnchorRecord escherClientAnchorRecord) { - this.escherClientAnchorRecord = escherClientAnchorRecord; - //TODO set properties or read properties from EscherRecord ? + this._escherClientAnchor = escherClientAnchorRecord; } /** * Creates a new client anchor and defaults all the anchor positions to 0. */ - public HSSFClientAnchor() - { + public HSSFClientAnchor() { } /** * Creates a new client anchor and sets the top-left and bottom-right * coordinates of the anchor. * - * @param dx1 the x coordinate within the first cell. - * @param dy1 the y coordinate within the first cell. - * @param dx2 the x coordinate within the second cell. - * @param dy2 the y coordinate within the second cell. - * @param col1 the column (0 based) of the first cell. - * @param row1 the row (0 based) of the first cell. - * @param col2 the column (0 based) of the second cell. - * @param row2 the row (0 based) of the second cell. + * @param dx1 the x coordinate within the first cell. + * @param dy1 the y coordinate within the first cell. + * @param dx2 the x coordinate within the second cell. + * @param dy2 the y coordinate within the second cell. + * @param col1 the column (0 based) of the first cell. + * @param row1 the row (0 based) of the first cell. + * @param col2 the column (0 based) of the second cell. + * @param row2 the row (0 based) of the second cell. */ - public HSSFClientAnchor( int dx1, int dy1, int dx2, int dy2, short col1, int row1, short col2, int row2 ) - { - super( dx1, dy1, dx2, dy2 ); + public HSSFClientAnchor(int dx1, int dy1, int dx2, int dy2, short col1, int row1, short col2, int row2) { + super(dx1, dy1, dx2, dy2); checkRange(dx1, 0, 1023, "dx1"); checkRange(dx2, 0, 1023, "dx2"); @@ -74,35 +66,30 @@ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor { checkRange(row1, 0, 255 * 256, "row1"); checkRange(row2, 0, 255 * 256, "row2"); - this.col1 = col1; - this.row1 = row1; - this.col2 = col2; - this.row2 = row2; + setCol1(col1); + setCol2(col2); + setRow1(row1); + setRow2(row2); } /** * Calculates the height of a client anchor in points. * - * @param sheet the sheet the anchor will be attached to - * @return the shape height. + * @param sheet the sheet the anchor will be attached to + * @return the shape height. */ - public float getAnchorHeightInPoints(HSSFSheet sheet ) - { + public float getAnchorHeightInPoints(HSSFSheet sheet) { int y1 = getDy1(); int y2 = getDy2(); - int row1 = Math.min( getRow1(), getRow2() ); - int row2 = Math.max( getRow1(), getRow2() ); + int row1 = Math.min(getRow1(), getRow2()); + int row2 = Math.max(getRow1(), getRow2()); float points = 0; - if (row1 == row2) - { + if (row1 == row2) { points = ((y2 - y1) / 256.0f) * getRowHeightInPoints(sheet, row2); - } - else - { + } else { points += ((256.0f - y1) / 256.0f) * getRowHeightInPoints(sheet, row1); - for (int i = row1 + 1; i < row2; i++) - { + for (int i = row1 + 1; i < row2; i++) { points += getRowHeightInPoints(sheet, i); } points += (y2 / 256.0f) * getRowHeightInPoints(sheet, row2); @@ -111,8 +98,7 @@ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor { return points; } - private float getRowHeightInPoints(HSSFSheet sheet, int rowNum) - { + private float getRowHeightInPoints(HSSFSheet sheet, int rowNum) { HSSFRow row = sheet.getRow(rowNum); if (row == null) { return sheet.getDefaultRowHeightInPoints(); @@ -120,55 +106,48 @@ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor { return row.getHeightInPoints(); } - public short getCol1() - { - return col1; + public short getCol1() { + return _escherClientAnchor.getCol1(); } - public void setCol1( short col1 ) - { + public void setCol1(short col1) { checkRange(col1, 0, 255, "col1"); - this.col1 = col1; - } - public void setCol1( int col1 ){ - setCol1((short)col1); + _escherClientAnchor.setCol1(col1); } - public short getCol2() - { - return col2; + public void setCol1(int col1) { + setCol1((short) col1); } - public void setCol2( short col2 ) - { + public short getCol2() { + return _escherClientAnchor.getCol2(); + } + + public void setCol2(short col2) { checkRange(col2, 0, 255, "col2"); - this.col2 = col2; + _escherClientAnchor.setCol2(col2); } - public void setCol2( int col2 ){ - setCol2((short)col2); + public void setCol2(int col2) { + setCol2((short) col2); } - public int getRow1() - { - return row1; + public int getRow1() { + return _escherClientAnchor.getRow1(); } - public void setRow1( int row1 ) - { + public void setRow1(int row1) { checkRange(row1, 0, 256 * 256, "row1"); - this.row1 = row1; + _escherClientAnchor.setRow1(Integer.valueOf(row1).shortValue()); } - public int getRow2() - { - return row2; + public int getRow2() { + return _escherClientAnchor.getRow2(); } - public void setRow2( int row2 ) - { + public void setRow2(int row2) { checkRange(row2, 0, 256 * 256, "row2"); - this.row2 = row2; + _escherClientAnchor.setRow2(Integer.valueOf(row2).shortValue()); } /** @@ -179,79 +158,139 @@ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor { * @param y1 the y coordinate within the first cell. * @param x2 the x coordinate within the second cell. * @param y2 the y coordinate within the second cell. - * @param col1 the column (0 based) of the first cell. - * @param row1 the row (0 based) of the first cell. - * @param col2 the column (0 based) of the second cell. - * @param row2 the row (0 based) of the second cell. + * @param col1 the column (0 based) of the first cell. + * @param row1 the row (0 based) of the first cell. + * @param col2 the column (0 based) of the second cell. + * @param row2 the row (0 based) of the second cell. */ - public void setAnchor( short col1, int row1, int x1, int y1, short col2, int row2, int x2, int y2 ) - { - checkRange(dx1, 0, 1023, "dx1"); - checkRange(dx2, 0, 1023, "dx2"); - checkRange(dy1, 0, 255, "dy1"); - checkRange(dy2, 0, 255, "dy2"); - checkRange(col1, 0, 255, "col1"); - checkRange(col2, 0, 255, "col2"); - checkRange(row1, 0, 255 * 256, "row1"); - checkRange(row2, 0, 255 * 256, "row2"); + public void setAnchor(short col1, int row1, int x1, int y1, short col2, int row2, int x2, int y2) { + checkRange(getDx1(), 0, 1023, "dx1"); + checkRange(getDx2(), 0, 1023, "dx2"); + checkRange(getDy1(), 0, 255, "dy1"); + checkRange(getDy2(), 0, 255, "dy2"); + checkRange(getCol1(), 0, 255, "col1"); + checkRange(getCol2(), 0, 255, "col2"); + checkRange(getRow1(), 0, 255 * 256, "row1"); + checkRange(getRow2(), 0, 255 * 256, "row2"); - this.col1 = col1; - this.row1 = row1; - this.dx1 = x1; - this.dy1 = y1; - this.col2 = col2; - this.row2 = row2; - this.dx2 = x2; - this.dy2 = y2; + setCol1(col1); + setRow1(row1); + setDx1(x1); + setDy1(y1); + setCol2(col2); + setRow2(row2); + setDx2(x2); + setDy2(y2); } /** - * @return true if the anchor goes from right to left. + * @return true if the anchor goes from right to left. */ - public boolean isHorizontallyFlipped() - { - if (col1 == col2) { - return dx1 > dx2; + public boolean isHorizontallyFlipped() { + if (getCol1() == getCol2()) { + return getDx1() > getDx2(); } - return col1 > col2; + return getCol1() > getCol2(); } /** - * @return true if the anchor goes from bottom to top. + * @return true if the anchor goes from bottom to top. */ - public boolean isVerticallyFlipped() - { - if (row1 == row2) { - return dy1 > dy2; + public boolean isVerticallyFlipped() { + if (getRow1() == getRow2()) { + return getDy1() > getDy2(); } - return row1 > row2; + return getRow1() > getRow2(); + } + + @Override + public EscherRecord getEscherAnchor() { + return _escherClientAnchor; + } + + @Override + protected void createEscherAnchor() { + _escherClientAnchor = new EscherClientAnchorRecord(); } /** * Gets the anchor type - *

+ *

* 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells. */ - public int getAnchorType() - { - return anchorType; + public int getAnchorType() { + return _escherClientAnchor.getFlag(); } /** * Sets the anchor type - *

+ *

* 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells. */ - public void setAnchorType( int anchorType ) - { - this.anchorType = anchorType; + public void setAnchorType(int anchorType) { +// if (0 != anchorType && 2 != anchorType && 3 != anchorType){ +// throw new IllegalArgumentException("Anchor type of shape can take only such values: 0, 2, 3"); +// } + _escherClientAnchor.setFlag(Integer.valueOf(anchorType).shortValue()); } - private void checkRange( int value, int minRange, int maxRange, String varName ) - { + private void checkRange(int value, int minRange, int maxRange, String varName) { if (value < minRange || value > maxRange) throw new IllegalArgumentException(varName + " must be between " + minRange + " and " + maxRange); } + @Override + public boolean equals(Object obj) { + if (obj == null) + return false; + if (obj == this) + return true; + if (obj.getClass() != getClass()) + return false; + HSSFClientAnchor anchor = (HSSFClientAnchor) obj; + return anchor.getCol1() == getCol1() && anchor.getCol2() == getCol2() && anchor.getDx1() == getDx1() + && anchor.getDx2() == getDx2() && anchor.getDy1() == getDy1() && anchor.getDy2() == getDy2() + && anchor.getRow1() == getRow1() && anchor.getRow2() == getRow2() && anchor.getAnchorType() == getAnchorType(); + } + + @Override + public int getDx1() { + return _escherClientAnchor.getDx1(); + } + + @Override + public void setDx1(int dx1) { + _escherClientAnchor.setDx1(Integer.valueOf(dx1).shortValue()); + } + + @Override + public int getDy1() { + return _escherClientAnchor.getDy1(); + } + + @Override + public void setDy1(int dy1) { + _escherClientAnchor.setDy1(Integer.valueOf(dy1).shortValue()); + } + + @Override + public int getDy2() { + return _escherClientAnchor.getDy2(); + } + + @Override + public void setDy2(int dy2) { + _escherClientAnchor.setDy2(Integer.valueOf(dy2).shortValue()); + } + + @Override + public int getDx2() { + return _escherClientAnchor.getDx2(); + } + + @Override + public void setDx2(int dx2) { + _escherClientAnchor.setDx2(Integer.valueOf(dx2).shortValue()); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java index 225e6da0e..2216971e6 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java @@ -57,7 +57,7 @@ public class HSSFComment extends HSSFTextbox implements Comment { setShapeType(OBJECT_TYPE_COMMENT); //default color for comments - _fillColor = 0x08000050; + setFillColor(0x08000050); //by default comments are hidden _visible = false; diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java index d4a7205c7..5aeb40b18 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java @@ -145,8 +145,8 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { float w = 0; //space in the leftmost cell - w += getColumnWidthInPixels(anchor.col1)*(1 - (float)anchor.dx1/1024); - short col2 = (short)(anchor.col1 + 1); + w += getColumnWidthInPixels(anchor.getCol1())*(1 - (float)anchor.getDx1()/1024); + short col2 = (short)(anchor.getCol1() + 1); int dx2 = 0; while(w < scaledWidth){ @@ -160,12 +160,12 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { double delta = w - scaledWidth; dx2 = (int)((cw-delta)/cw*1024); } - anchor.col2 = col2; - anchor.dx2 = dx2; + anchor.setCol2(col2); + anchor.setDx2(dx2); float h = 0; - h += (1 - (float)anchor.dy1/256)* getRowHeightInPixels(anchor.row1); - int row2 = anchor.row1 + 1; + h += (1 - (float)anchor.getDy1()/256)* getRowHeightInPixels(anchor.getRow1()); + int row2 = anchor.getRow1() + 1; int dy2 = 0; while(h < scaledHeight){ @@ -177,8 +177,8 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { double delta = h - scaledHeight; dy2 = (int)((ch-delta)/ch*256); } - anchor.row2 = row2; - anchor.dy2 = dy2; + anchor.setRow2(row2); + anchor.setDy2(dy2); return anchor; } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFRectangle.java b/src/java/org/apache/poi/hssf/usermodel/HSSFRectangle.java deleted file mode 100644 index 0a0468c14..000000000 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFRectangle.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.apache.poi.hssf.usermodel; - -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.hssf.record.ObjRecord; - -/** - * @author Evgeniy Berlog - * @date 08.06.12 - */ -public class HSSFRectangle extends HSSFShape{ - - public HSSFRectangle(EscherContainerRecord spContainer, ObjRecord objRecord) { - super(spContainer, objRecord); - } -} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java index 7ffdfdb9b..c9bf922cb 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java @@ -17,7 +17,7 @@ package org.apache.poi.hssf.usermodel; -import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.*; import org.apache.poi.hssf.record.ObjRecord; /** @@ -28,6 +28,8 @@ import org.apache.poi.hssf.record.ObjRecord; public abstract class HSSFShape { public static final int LINEWIDTH_ONE_PT = 12700; public static final int LINEWIDTH_DEFAULT = 9525; + public static final int LINESTYLE__COLOR_DEFAULT = 0x08000040; + public static final int FILL__FILLCOLOR_DEFAULT = 0x08000009; public static final int LINESTYLE_SOLID = 0; // Solid (continuous) pen public static final int LINESTYLE_DASHSYS = 1; // PS_DASH system dash style @@ -45,50 +47,53 @@ public abstract class HSSFShape { // TODO - make all these fields private HSSFShape parent; HSSFAnchor anchor; - HSSFPatriarch _patriarch; - private int _lineStyleColor = 0x08000040; - int _fillColor = 0x08000009; - private int _lineWidth = LINEWIDTH_DEFAULT; // 12700 = 1pt - private int _lineStyle = LINESTYLE_SOLID; - private boolean _noFill = false; + HSSFPatriarch _patriarch; - private EscherContainerRecord spContainer; - private ObjRecord objRecord; + protected EscherContainerRecord _escherContainer; + protected ObjRecord _objRecord; + protected final EscherOptRecord _optRecord; - public HSSFShape(EscherContainerRecord spContainer, ObjRecord objRecord){ - this.spContainer = spContainer; - this.objRecord = objRecord; + public HSSFShape(EscherContainerRecord spContainer, ObjRecord objRecord) { + this._escherContainer = spContainer; + this._objRecord = objRecord; + this._optRecord = spContainer.getChildById(EscherOptRecord.RECORD_ID); + this.anchor = HSSFAnchor.createAnchorFromEscher(spContainer); } + /** * Create a new shape with the specified parent and anchor. */ - public HSSFShape( HSSFShape parent, HSSFAnchor anchor ) - { + public HSSFShape(HSSFShape parent, HSSFAnchor anchor) { this.parent = parent; this.anchor = anchor; + this._escherContainer = new EscherContainerRecord(); + _optRecord = new EscherOptRecord(); + _optRecord.addEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID)); + _optRecord.addEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT)); + _optRecord.addEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT)); + _optRecord.addEscherProperty(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT)); + _optRecord.addEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 0x0)); } - public EscherContainerRecord getSpContainer() { - return spContainer; + public EscherContainerRecord getEscherContainer() { + return _escherContainer; } public ObjRecord getObjRecord() { - return objRecord; + return _objRecord; } /** * Gets the parent shape. */ - public HSSFShape getParent() - { + public HSSFShape getParent() { return parent; } /** - * @return the anchor that is used by this shape. + * @return the anchor that is used by this shape. */ - public HSSFAnchor getAnchor() - { + public HSSFAnchor getAnchor() { return anchor; } @@ -96,26 +101,29 @@ public abstract class HSSFShape { * Sets a particular anchor. A top-level shape must have an anchor of * HSSFClientAnchor. A child anchor must have an anchor of HSSFChildAnchor * - * @param anchor the anchor to use. - * @throws IllegalArgumentException when the wrong anchor is used for - * this particular shape. - * + * @param anchor the anchor to use. + * @throws IllegalArgumentException when the wrong anchor is used for + * this particular shape. * @see HSSFChildAnchor * @see HSSFClientAnchor */ - public void setAnchor( HSSFAnchor anchor ) - { - if ( parent == null ) - { - if ( anchor instanceof HSSFChildAnchor ) - throw new IllegalArgumentException( "Must use client anchors for shapes directly attached to sheet." ); + public void setAnchor(HSSFAnchor anchor) { + if (parent == null) { + if (anchor instanceof HSSFChildAnchor) + throw new IllegalArgumentException("Must use client anchors for shapes directly attached to sheet."); + EscherClientAnchorRecord anch = _escherContainer.getChildById(EscherClientAnchorRecord.RECORD_ID); + if (null != anch) { + _escherContainer.removeChildRecord(anch); + } + } else { + if (anchor instanceof HSSFClientAnchor) + throw new IllegalArgumentException("Must use child anchors for shapes attached to groups."); + EscherChildAnchorRecord anch = _escherContainer.getChildById(EscherChildAnchorRecord.RECORD_ID); + if (null != anch) { + _escherContainer.removeChildRecord(anch); + } } - else - { - if ( anchor instanceof HSSFClientAnchor ) - throw new IllegalArgumentException( "Must use child anchors for shapes attached to groups." ); - } - + _escherContainer.addChildRecord(anchor.getEscherAnchor()); this.anchor = anchor; } @@ -123,92 +131,141 @@ public abstract class HSSFShape { * The color applied to the lines of this shape. */ public int getLineStyleColor() { - return _lineStyleColor; + EscherRGBProperty rgbProperty = _optRecord.lookup(EscherProperties.LINESTYLE__COLOR); + return rgbProperty == null ? LINESTYLE__COLOR_DEFAULT : rgbProperty.getRgbColor(); } /** * The color applied to the lines of this shape. */ public void setLineStyleColor(int lineStyleColor) { - _lineStyleColor = lineStyleColor; + EscherRGBProperty rgbProperty = _optRecord.lookup(EscherProperties.LINESTYLE__COLOR); + if (null == rgbProperty) { + rgbProperty = new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, lineStyleColor); + _optRecord.addEscherProperty(rgbProperty); + } else { + rgbProperty.setRgbColor(lineStyleColor); + } } /** * The color applied to the lines of this shape. */ public void setLineStyleColor(int red, int green, int blue) { - this._lineStyleColor = ((blue) << 16) | ((green) << 8) | red; + int lineStyleColor = ((blue) << 16) | ((green) << 8) | red; + EscherRGBProperty rgbProperty = _optRecord.lookup(EscherProperties.LINESTYLE__COLOR); + if (null == rgbProperty) { + rgbProperty = new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, lineStyleColor); + _optRecord.addEscherProperty(rgbProperty); + } else { + rgbProperty.setRgbColor(lineStyleColor); + } } /** * The color used to fill this shape. */ - public int getFillColor() - { - return _fillColor; + public int getFillColor() { + EscherRGBProperty rgbProperty = _optRecord.lookup(EscherProperties.FILL__FILLCOLOR); + return rgbProperty == null ? FILL__FILLCOLOR_DEFAULT : rgbProperty.getRgbColor(); } /** * The color used to fill this shape. */ public void setFillColor(int fillColor) { - _fillColor = fillColor; + EscherRGBProperty rgbProperty = _optRecord.lookup(EscherProperties.FILL__FILLCOLOR); + if (null == rgbProperty) { + rgbProperty = new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, fillColor); + _optRecord.addEscherProperty(rgbProperty); + } else { + rgbProperty.setRgbColor(fillColor); + } } /** * The color used to fill this shape. */ - public void setFillColor( int red, int green, int blue ) - { - this._fillColor = ((blue) << 16) | ((green) << 8) | red; + public void setFillColor(int red, int green, int blue) { + int fillColor = ((blue) << 16) | ((green) << 8) | red; + EscherRGBProperty rgbProperty = _optRecord.lookup(EscherProperties.FILL__FILLCOLOR); + if (null == rgbProperty) { + rgbProperty = new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, fillColor); + _optRecord.addEscherProperty(rgbProperty); + } else { + rgbProperty.setRgbColor(fillColor); + } } /** - * @return returns with width of the line in EMUs. 12700 = 1 pt. + * @return returns with width of the line in EMUs. 12700 = 1 pt. */ public int getLineWidth() { - return _lineWidth; + EscherSimpleProperty property = _optRecord.lookup(EscherProperties.LINESTYLE__LINEWIDTH); + return property.getPropertyValue(); } /** * Sets the width of the line. 12700 = 1 pt. * * @param lineWidth width in EMU's. 12700EMU's = 1 pt - * * @see HSSFShape#LINEWIDTH_ONE_PT */ public void setLineWidth(int lineWidth) { - _lineWidth = lineWidth; + EscherSimpleProperty property = _optRecord.lookup(EscherProperties.LINESTYLE__LINEWIDTH); + if (null == property) { + property = new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, lineWidth); + _optRecord.addEscherProperty(property); + } else { + property.setPropertyValue(lineWidth); + } } /** * @return One of the constants in LINESTYLE_* */ public int getLineStyle() { - return _lineStyle; + EscherSimpleProperty property = _optRecord.lookup(EscherProperties.LINESTYLE__LINEDASHING); + if (null == property){ + return -1; + } + return property.getPropertyValue(); } /** * Sets the line style. * - * @param lineStyle One of the constants in LINESTYLE_* + * @param lineStyle One of the constants in LINESTYLE_* */ public void setLineStyle(int lineStyle) { - _lineStyle = lineStyle; + EscherSimpleProperty property = _optRecord.lookup(EscherProperties.LINESTYLE__LINEDASHING); + if (null == property) { + property = new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, lineStyle); + _optRecord.addEscherProperty(property); + } else { + property.setPropertyValue(lineStyle); + } } /** * @return true if this shape is not filled with a color. */ public boolean isNoFill() { - return _noFill; + EscherBoolProperty property = _optRecord.lookup(EscherProperties.FILL__NOFILLHITTEST); + return property.isTrue(); } /** * Sets whether this shape is filled or transparent. */ public void setNoFill(boolean noFill) { - _noFill = noFill; + EscherBoolProperty property = _optRecord.lookup(EscherProperties.FILL__NOFILLHITTEST); + if (null == property) { + property = new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, noFill ? 1 : 0); + _optRecord.addEscherProperty(property); + } else { + property.setPropertyValue(noFill ? 1 : 0); + } } /** diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java index 4a10a8d07..68f410d17 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java @@ -39,25 +39,25 @@ import java.util.List; import java.util.Map; /** - * @author evgeniy + * @author Evgeniy Berlog * date: 05.06.12 */ public class HSSFShapeFactory { - private static final Map shapeTypeToClass = new HashMap(HSSFShapeType.values().length); + private static final Map shapeTypeToClass = new HashMap(HSSFShapeType.values().length); private static final ReflectionConstructorShapeCreator shapeCreator = new ReflectionConstructorShapeCreator(shapeTypeToClass); static { for (HSSFShapeType type: HSSFShapeType.values()){ - shapeTypeToClass.put(type.getType(), type.getShape()); + shapeTypeToClass.put(type.getType(), type); } } private static class ReflectionConstructorShapeCreator { - private final Map shapeTypeToClass; + private final Map shapeTypeToClass; - private ReflectionConstructorShapeCreator(Map shapeTypeToClass) { + private ReflectionConstructorShapeCreator(Map shapeTypeToClass) { this.shapeTypeToClass = shapeTypeToClass; } @@ -65,7 +65,7 @@ public class HSSFShapeFactory { if (!shapeTypeToClass.containsKey(type)){ return new HSSFUnknownShape(spContainer, objRecord); } - Class clazz = shapeTypeToClass.get(type); + Class clazz = shapeTypeToClass.get(type).getShape(); if (null == clazz){ //System.out.println("No class attached to shape type: "+type); return new HSSFUnknownShape(spContainer, objRecord); @@ -81,26 +81,6 @@ public class HSSFShapeFactory { } } - public static HSSFShape createShape(EscherRecord container, ObjRecord objRecord){ - if (0 == container.getChildRecords().size()){ - throw new IllegalArgumentException("Couldn't create shape from empty escher container"); - } - if (container.getChild(0) instanceof EscherSpgrRecord){ - return new HSSFShapeGroup((EscherContainerRecord) container, objRecord); - } - - //TODO implement cases for all shapes - return new HSSFUnknownShape(container, objRecord); - } - - public static HSSFShapeGroup createShapeGroup(){ - return null; - } - - public static HSSFShapeGroup createSimpleShape(EscherRecord container, ObjRecord objRecord){ - return null; - } - public static void createShapeTree(EscherContainerRecord container, EscherAggregate agg, HSSFShapeContainer out){ if(container.getRecordId() == EscherContainerRecord.SPGR_CONTAINER){ HSSFShapeGroup group = new HSSFShapeGroup(container, @@ -111,10 +91,6 @@ public class HSSFShapeFactory { EscherContainerRecord spContainer = children.get(i); if(i == 0){ EscherSpgrRecord spgr = (EscherSpgrRecord)spContainer.getChildById(EscherSpgrRecord.RECORD_ID); - group.setCoordinates( - spgr.getRectX1(), spgr.getRectY1(), - spgr.getRectX2(), spgr.getRectY2() - ); } else { createShapeTree(spContainer, agg, group); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java index 7cab3e493..b3209467a 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java @@ -41,32 +41,23 @@ public class HSSFShapeGroup implements HSSFShapeContainer { List shapes = new ArrayList(); - int x1 = 0; - int y1 = 0 ; - int x2 = 1023; - int y2 = 255; + private EscherSpgrRecord _spgrRecord; public HSSFShapeGroup(EscherContainerRecord spgrContainer, ObjRecord objRecord) { super(spgrContainer, objRecord); // 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()) { case EscherSpgrRecord.RECORD_ID: - EscherSpgrRecord spgr = (EscherSpgrRecord)ch; - setCoordinates( - spgr.getRectX1(), spgr.getRectY1(), - spgr.getRectX2(), spgr.getRectY2() - ); break; case EscherClientAnchorRecord.RECORD_ID: - this.anchor = EscherAggregate.toClientAnchor((EscherClientAnchorRecord)ch); - // TODO anchor = new HSSFClientAnchor((EscherChildAnchorRecord)ch); + anchor = new HSSFClientAnchor((EscherClientAnchorRecord)ch); break; case EscherChildAnchorRecord.RECORD_ID: - this.anchor = EscherAggregate.toChildAnchor((EscherChildAnchorRecord)ch); - // TODO anchor = new HSSFChildAnchor((EscherClientAnchorRecord)ch); + anchor = new HSSFChildAnchor((EscherChildAnchorRecord)ch); break; } } @@ -76,6 +67,11 @@ public class HSSFShapeGroup public HSSFShapeGroup( HSSFShape parent, HSSFAnchor anchor ) { super( parent, anchor ); + _spgrRecord = new EscherSpgrRecord(); + _spgrRecord.setRectX1(0); + _spgrRecord.setRectX2(1023); + _spgrRecord.setRectY1(0); + _spgrRecord.setRectY2(255); } /** @@ -171,10 +167,10 @@ public class HSSFShapeGroup */ public void setCoordinates( int x1, int y1, int x2, int y2 ) { - this.x1 = x1; - this.y1 = y1; - this.x2 = x2; - this.y2 = y2; + _spgrRecord.setRectX1(x1); + _spgrRecord.setRectX2(x2); + _spgrRecord.setRectY1(y1); + _spgrRecord.setRectY2(y2); } /** @@ -182,7 +178,7 @@ public class HSSFShapeGroup */ public int getX1() { - return x1; + return _spgrRecord.getRectX1(); } /** @@ -190,7 +186,7 @@ public class HSSFShapeGroup */ public int getY1() { - return y1; + return _spgrRecord.getRectY1(); } /** @@ -198,7 +194,7 @@ public class HSSFShapeGroup */ public int getX2() { - return x2; + return _spgrRecord.getRectX2(); } /** @@ -206,7 +202,7 @@ public class HSSFShapeGroup */ public int getY2() { - return y2; + return _spgrRecord.getRectY2(); } /** diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java index ee8522929..6e0df0fd5 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java @@ -17,6 +17,10 @@ package org.apache.poi.hssf.usermodel; +import org.apache.poi.ddf.*; +import org.apache.poi.hssf.record.CommonObjectDataSubRecord; +import org.apache.poi.hssf.record.ObjRecord; + /** * Represents a simple shape such as a line, rectangle or oval. * @@ -52,7 +56,13 @@ public class HSSFSimpleShape int shapeType = OBJECT_TYPE_LINE; - public HSSFSimpleShape( HSSFShape parent, HSSFAnchor anchor ) + public HSSFSimpleShape(EscherContainerRecord spContainer, ObjRecord objRecord) { + super(spContainer, objRecord); + CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) objRecord.getSubRecords().get(0); + setShapeType(cod.getObjectType()); + } + + public HSSFSimpleShape( HSSFShape parent, HSSFAnchor anchor) { super( parent, anchor ); } diff --git a/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java b/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java index 281868792..29741c90f 100644 --- a/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java +++ b/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java @@ -1,22 +1,24 @@ package org.apache.poi.hssf.usermodel.drawing; -import org.apache.poi.hssf.usermodel.HSSFRectangle; +import org.apache.poi.hssf.usermodel.HSSFSimpleShape; /** * @author Evgeniy Berlog * date: 08.06.12 */ public enum HSSFShapeType { - NOT_PRIMITIVE(0x0, null), - RECTANGLE(0x1, HSSFRectangle.class), - ROUND_RECTANGLE(0x2, null); + NOT_PRIMITIVE((short)0x0, null, (short)0), + RECTANGLE((short)0x1, HSSFSimpleShape.class, HSSFSimpleShape.OBJECT_TYPE_RECTANGLE), + ROUND_RECTANGLE((short)0x2, null, null); private Short type; private Class shape; + private Short objectId; - HSSFShapeType(Integer type, Class shape) { - this.type = type.shortValue(); + private HSSFShapeType(Short type, Class shape, Short objectId) { + this.type = type; this.shape = shape; + this.objectId = objectId; } public Short getType() { diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java new file mode 100644 index 000000000..f276cba39 --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java @@ -0,0 +1,160 @@ +package org.apache.poi.hssf.model; + +import junit.framework.TestCase; +import org.apache.poi.ddf.*; +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.usermodel.*; +import org.apache.poi.util.HexDump; + +import java.io.IOException; + +import static junit.framework.Assert.assertEquals; + +/** + * @author Evgeniy Berlog + * date: 12.06.12 + */ +public class TestDrawingShapes extends TestCase{ + + /** + * HSSFShape tree bust be built correctly + * Check file with such records structure: + * -patriarch + * --shape + * --group + * ---group + * ----shape + * ----shape + * ---shape + * ---group + * ----shape + * ----shape + */ + public void testDrawingGroups(){ + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); + HSSFSheet sheet = wb.getSheet("groups"); + HSSFPatriarch patriarch = sheet.getDrawingPatriarch(); + assertEquals(patriarch.getChildren().size(), 2); + HSSFShapeGroup group = (HSSFShapeGroup) patriarch.getChildren().get(1); + assertEquals(3, group.getChildren().size()); + HSSFShapeGroup group1 = (HSSFShapeGroup) group.getChildren().get(0); + assertEquals(2, group1.getChildren().size()); + group1 = (HSSFShapeGroup) group.getChildren().get(2); + assertEquals(2, group1.getChildren().size()); + } + + public void testHSSFShapeCompatibility() { + HSSFShape shape = new HSSFSimpleShape(null, new HSSFClientAnchor()); + assertEquals(0x08000040, shape.getLineStyleColor()); + assertEquals(0x08000009, shape.getFillColor()); + assertEquals(HSSFShape.LINEWIDTH_DEFAULT, shape.getLineWidth()); + assertEquals(HSSFShape.LINESTYLE_SOLID, shape.getLineStyle()); + assertFalse(shape.isNoFill()); + + AbstractShape sp = AbstractShape.createShape(shape, 1); + EscherContainerRecord spContainer = sp.getSpContainer(); + EscherOptRecord opt = + spContainer.getChildById(EscherOptRecord.RECORD_ID); + + assertEquals(7, opt.getEscherProperties().size()); + assertEquals(true, + ((EscherBoolProperty)opt.lookup(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE)).isTrue()); + assertEquals(0x00000004, + ((EscherSimpleProperty)opt.lookup(EscherProperties.GEOMETRY__SHAPEPATH)).getPropertyValue()); + assertEquals(0x08000009, + ((EscherSimpleProperty)opt.lookup(EscherProperties.FILL__FILLCOLOR)).getPropertyValue()); + assertEquals(true, + ((EscherBoolProperty)opt.lookup(EscherProperties.FILL__NOFILLHITTEST)).isTrue()); + assertEquals(0x08000040, + ((EscherSimpleProperty)opt.lookup(EscherProperties.LINESTYLE__COLOR)).getPropertyValue()); + assertEquals(true, + ((EscherBoolProperty)opt.lookup(EscherProperties.LINESTYLE__NOLINEDRAWDASH)).isTrue()); + assertEquals(true, + ((EscherBoolProperty)opt.lookup(EscherProperties.GROUPSHAPE__PRINT)).isTrue()); + } + /** + * create a rectangle, save the workbook, read back and verify that all shape properties are there + */ + public void testReadWriteRectangle() throws IOException { + + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet(); + + HSSFPatriarch drawing = sheet.createDrawingPatriarch(); + HSSFClientAnchor anchor = new HSSFClientAnchor(10, 10, 200, 200, (short)2, 2, (short)15, 15); + anchor.setAnchorType(2); + assertEquals(anchor.getAnchorType(), 2); + + HSSFSimpleShape rectangle = drawing.createSimpleShape(anchor); + rectangle.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE); + rectangle.setLineWidth(10000); + rectangle.setFillColor(777); + assertEquals(rectangle.getFillColor(), 777); + assertEquals(10000, rectangle.getLineWidth()); + rectangle.setLineStyle(10); + assertEquals(10, rectangle.getLineStyle()); + rectangle.setLineStyleColor(1111); + rectangle.setNoFill(true); + assertEquals(rectangle.getLineStyleColor(), 1111); + assertEquals(rectangle.isNoFill(), true); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + drawing = sheet.getDrawingPatriarch(); + assertEquals(1, drawing.getChildren().size()); + + HSSFSimpleShape rectangle2 = + (HSSFSimpleShape)drawing.getChildren().get(0); + assertEquals(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE, + rectangle2.getShapeType()); + assertEquals(10000, rectangle2.getLineWidth()); + assertEquals(10, rectangle2.getLineStyle()); + assertEquals(anchor, rectangle2.getAnchor()); + assertEquals(rectangle2.getLineStyleColor(), 1111); + assertEquals(rectangle2.getFillColor(), 777); + assertEquals(rectangle2.isNoFill(), true); + + rectangle2.setFillColor(3333); + rectangle2.setLineStyle(9); + rectangle2.setLineStyleColor(4444); + rectangle2.setNoFill(false); + rectangle2.setLineWidth(77); + rectangle2.getAnchor().setDx1(2); + rectangle2.getAnchor().setDx2(3); + rectangle2.getAnchor().setDy1(4); + rectangle2.getAnchor().setDy2(5); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + drawing = sheet.getDrawingPatriarch(); + assertEquals(1, drawing.getChildren().size()); + rectangle2 = (HSSFSimpleShape)drawing.getChildren().get(0); + assertEquals(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE, rectangle2.getShapeType()); + assertEquals(77, rectangle2.getLineWidth()); + assertEquals(9, rectangle2.getLineStyle()); + assertEquals(rectangle2.getLineStyleColor(), 4444); + assertEquals(rectangle2.getFillColor(), 3333); + assertEquals(rectangle2.getAnchor().getDx1(), 2); + assertEquals(rectangle2.getAnchor().getDx2(), 3); + assertEquals(rectangle2.getAnchor().getDy1(), 4); + assertEquals(rectangle2.getAnchor().getDy2(), 5); + assertEquals(rectangle2.isNoFill(), false); + } + + + /* assert shape properties when reading shapes from a existing workbook */ + public void testReadExistingRectangle() { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); + HSSFSheet sheet = wb.getSheet("rectangles"); + HSSFPatriarch drawing = sheet.getDrawingPatriarch(); + assertEquals(1, drawing.getChildren().size()); + + for(HSSFShape shape : drawing.getChildren()){ + assertEquals(shape.isNoFill(), true); + assertEquals(shape.getLineStyle(), HSSFShape.LINESTYLE_DASHDOTGEL); + assertEquals(shape.getLineStyleColor(), 0x616161); + assertEquals(HexDump.toHex(shape.getFillColor()), shape.getFillColor(), 0x2CE03D); + assertEquals(shape.getLineWidth(), HSSFShape.LINEWIDTH_ONE_PT*2); + } + } +} diff --git a/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java b/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java new file mode 100644 index 000000000..ef90f01f4 --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java @@ -0,0 +1,209 @@ +package org.apache.poi.hssf.model; + +import junit.framework.TestCase; +import org.apache.poi.ddf.EscherChildAnchorRecord; +import org.apache.poi.ddf.EscherClientAnchorRecord; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.hssf.usermodel.*; + +/** + * @author Evgeniy Berlog + * @date 12.06.12 + */ +public class TestHSSFAnchor extends TestCase { + + public void testCreateClientAnchorFromContainer(){ + EscherContainerRecord container = new EscherContainerRecord(); + EscherClientAnchorRecord escher = new EscherClientAnchorRecord(); + escher.setFlag((short) 3); + escher.setCol1((short)11); + escher.setCol2((short)12); + escher.setRow1((short)13); + escher.setRow2((short) 14); + escher.setDx1((short) 15); + escher.setDx2((short) 16); + escher.setDy1((short) 17); + escher.setDy2((short) 18); + container.addChildRecord(escher); + + HSSFClientAnchor anchor = (HSSFClientAnchor) HSSFAnchor.createAnchorFromEscher(container); + assertEquals(anchor.getCol1(), 11); + assertEquals(escher.getCol1(), 11); + assertEquals(anchor.getCol2(), 12); + assertEquals(escher.getCol2(), 12); + assertEquals(anchor.getRow1(), 13); + assertEquals(escher.getRow1(), 13); + assertEquals(anchor.getRow2(), 14); + assertEquals(escher.getRow2(), 14); + assertEquals(anchor.getDx1(), 15); + assertEquals(escher.getDx1(), 15); + assertEquals(anchor.getDx2(), 16); + assertEquals(escher.getDx2(), 16); + assertEquals(anchor.getDy1(), 17); + assertEquals(escher.getDy1(), 17); + assertEquals(anchor.getDy2(), 18); + assertEquals(escher.getDy2(), 18); + } + + public void testCreateChildAnchorFromContainer(){ + EscherContainerRecord container = new EscherContainerRecord(); + EscherChildAnchorRecord escher = new EscherChildAnchorRecord(); + escher.setDx1((short) 15); + escher.setDx2((short) 16); + escher.setDy1((short) 17); + escher.setDy2((short) 18); + container.addChildRecord(escher); + + HSSFChildAnchor anchor = (HSSFChildAnchor) HSSFAnchor.createAnchorFromEscher(container); + assertEquals(anchor.getDx1(), 15); + assertEquals(escher.getDx1(), 15); + assertEquals(anchor.getDx2(), 16); + assertEquals(escher.getDx2(), 16); + assertEquals(anchor.getDy1(), 17); + assertEquals(escher.getDy1(), 17); + assertEquals(anchor.getDy2(), 18); + assertEquals(escher.getDy2(), 18); + } + + public void testShapeEscherMustHaveAnchorRecord(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet(); + + HSSFPatriarch drawing = sheet.createDrawingPatriarch(); + HSSFClientAnchor anchor = new HSSFClientAnchor(10, 10, 200, 200, (short)2, 2, (short)15, 15); + anchor.setAnchorType(2); + + HSSFSimpleShape rectangle = drawing.createSimpleShape(anchor); + rectangle.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE); + + rectangle.setAnchor(anchor); + + assertNotNull(anchor.getEscherAnchor()); + assertNotNull(rectangle.getEscherContainer()); + assertTrue(anchor.getEscherAnchor().equals(rectangle.getEscherContainer().getChildById(EscherClientAnchorRecord.RECORD_ID))); + } + + public void testClientAnchorFromEscher(){ + EscherClientAnchorRecord escher = new EscherClientAnchorRecord(); + escher.setCol1((short)11); + escher.setCol2((short)12); + escher.setRow1((short)13); + escher.setRow2((short) 14); + escher.setDx1((short) 15); + escher.setDx2((short) 16); + escher.setDy1((short) 17); + escher.setDy2((short) 18); + + HSSFClientAnchor anchor = new HSSFClientAnchor(escher); + assertEquals(anchor.getCol1(), 11); + assertEquals(escher.getCol1(), 11); + assertEquals(anchor.getCol2(), 12); + assertEquals(escher.getCol2(), 12); + assertEquals(anchor.getRow1(), 13); + assertEquals(escher.getRow1(), 13); + assertEquals(anchor.getRow2(), 14); + assertEquals(escher.getRow2(), 14); + assertEquals(anchor.getDx1(), 15); + assertEquals(escher.getDx1(), 15); + assertEquals(anchor.getDx2(), 16); + assertEquals(escher.getDx2(), 16); + assertEquals(anchor.getDy1(), 17); + assertEquals(escher.getDy1(), 17); + assertEquals(anchor.getDy2(), 18); + assertEquals(escher.getDy2(), 18); + } + + public void testClientAnchorFromScratch(){ + HSSFClientAnchor anchor = new HSSFClientAnchor(); + EscherClientAnchorRecord escher = (EscherClientAnchorRecord) anchor.getEscherAnchor(); + anchor.setAnchor((short)11, 12, 13, 14, (short)15, 16, 17, 18); + + assertEquals(anchor.getCol1(), 11); + assertEquals(escher.getCol1(), 11); + assertEquals(anchor.getCol2(), 15); + assertEquals(escher.getCol2(), 15); + assertEquals(anchor.getRow1(), 12); + assertEquals(escher.getRow1(), 12); + assertEquals(anchor.getRow2(), 16); + assertEquals(escher.getRow2(), 16); + assertEquals(anchor.getDx1(), 13); + assertEquals(escher.getDx1(), 13); + assertEquals(anchor.getDx2(), 17); + assertEquals(escher.getDx2(), 17); + assertEquals(anchor.getDy1(), 14); + assertEquals(escher.getDy1(), 14); + assertEquals(anchor.getDy2(), 18); + assertEquals(escher.getDy2(), 18); + + anchor.setCol1(111); + assertEquals(anchor.getCol1(), 111); + assertEquals(escher.getCol1(), 111); + anchor.setCol2(112); + assertEquals(anchor.getCol2(), 112); + assertEquals(escher.getCol2(), 112); + anchor.setRow1(113); + assertEquals(anchor.getRow1(), 113); + assertEquals(escher.getRow1(), 113); + anchor.setRow2(114); + assertEquals(anchor.getRow2(), 114); + assertEquals(escher.getRow2(), 114); + anchor.setDx1(115); + assertEquals(anchor.getDx1(), 115); + assertEquals(escher.getDx1(), 115); + anchor.setDx2(116); + assertEquals(anchor.getDx2(), 116); + assertEquals(escher.getDx2(), 116); + anchor.setDy1(117); + assertEquals(anchor.getDy1(), 117); + assertEquals(escher.getDy1(), 117); + anchor.setDy2(118); + assertEquals(anchor.getDy2(), 118); + assertEquals(escher.getDy2(), 118); + } + + public void testChildAnchorFromEscher(){ + EscherChildAnchorRecord escher = new EscherChildAnchorRecord(); + escher.setDx1((short) 15); + escher.setDx2((short) 16); + escher.setDy1((short) 17); + escher.setDy2((short) 18); + + HSSFChildAnchor anchor = new HSSFChildAnchor(escher); + assertEquals(anchor.getDx1(), 15); + assertEquals(escher.getDx1(), 15); + assertEquals(anchor.getDx2(), 16); + assertEquals(escher.getDx2(), 16); + assertEquals(anchor.getDy1(), 17); + assertEquals(escher.getDy1(), 17); + assertEquals(anchor.getDy2(), 18); + assertEquals(escher.getDy2(), 18); + } + + public void testChildAnchorFromScratch(){ + HSSFChildAnchor anchor = new HSSFChildAnchor(); + EscherChildAnchorRecord escher = (EscherChildAnchorRecord) anchor.getEscherAnchor(); + anchor.setAnchor(11, 12, 13, 14); + + assertEquals(anchor.getDx1(), 11); + assertEquals(escher.getDx1(), 11); + assertEquals(anchor.getDx2(), 13); + assertEquals(escher.getDx2(), 13); + assertEquals(anchor.getDy1(), 12); + assertEquals(escher.getDy1(), 12); + assertEquals(anchor.getDy2(), 14); + assertEquals(escher.getDy2(), 14); + + anchor.setDx1(115); + assertEquals(anchor.getDx1(), 115); + assertEquals(escher.getDx1(), 115); + anchor.setDx2(116); + assertEquals(anchor.getDx2(), 116); + assertEquals(escher.getDx2(), 116); + anchor.setDy1(117); + assertEquals(anchor.getDy1(), 117); + assertEquals(escher.getDy1(), 117); + anchor.setDy2(118); + assertEquals(anchor.getDy2(), 118); + assertEquals(escher.getDy2(), 118); + } +} diff --git a/test-data/spreadsheet/drawings.xls b/test-data/spreadsheet/drawings.xls new file mode 100644 index 000000000..ccbcc8cb4 Binary files /dev/null and b/test-data/spreadsheet/drawings.xls differ