diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCombobox.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCombobox.java new file mode 100644 index 000000000..4b13278f0 --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCombobox.java @@ -0,0 +1,77 @@ +package org.apache.poi.hssf.usermodel; + +import org.apache.poi.ddf.*; +import org.apache.poi.hssf.record.*; + +/** + * @author Evgeniy Berlog + * @date 12.07.12 + */ +public class HSSFCombobox extends HSSFSimpleShape { + + public HSSFCombobox(EscherContainerRecord spContainer, ObjRecord objRecord) { + super(spContainer, objRecord); + } + + public HSSFCombobox(HSSFShape parent, HSSFAnchor anchor) { + super(parent, anchor); + super.setShapeType(OBJECT_TYPE_COMBO_BOX); + } + + @Override + protected EscherContainerRecord createSpContainer() { + EscherContainerRecord spContainer = new EscherContainerRecord(); + 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_HOSTCONTROL << 4) | 0x2)); + + sp.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE); + opt.setRecordId(EscherOptRecord.RECORD_ID); + opt.addEscherProperty(new EscherBoolProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 17039620)); + opt.addEscherProperty(new EscherBoolProperty(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 0x00080008)); + opt.addEscherProperty(new EscherBoolProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080000)); + opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GROUPSHAPE__PRINT, 0x00020000)); + + HSSFClientAnchor userAnchor = (HSSFClientAnchor) getAnchor(); + userAnchor.setAnchorType(1); + EscherRecord anchor = userAnchor.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 + protected ObjRecord createObjRecord() { + ObjRecord obj = new ObjRecord(); + CommonObjectDataSubRecord c = new CommonObjectDataSubRecord(); + c.setObjectType(HSSFSimpleShape.OBJECT_TYPE_COMBO_BOX); + c.setLocked(true); + c.setPrintable(false); + c.setAutofill(true); + c.setAutoline(false); + FtCblsSubRecord f = new FtCblsSubRecord(); + LbsDataSubRecord l = LbsDataSubRecord.newAutoFilterInstance(); + EndSubRecord e = new EndSubRecord(); + obj.addSubRecord(c); + obj.addSubRecord(f); + obj.addSubRecord(l); + obj.addSubRecord(e); + return obj; + } + + @Override + public void setShapeType(int shapeType) { + throw new IllegalStateException("Shape type can not be changed in "+this.getClass().getSimpleName()); + } +} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java index aa8603635..fbe3f56b6 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java @@ -97,7 +97,6 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { public HSSFShapeGroup createGroup(HSSFClientAnchor anchor) { HSSFShapeGroup group = new HSSFShapeGroup(null, anchor); - group.anchor = anchor; addShape(group); onCreate(group); return group; @@ -114,7 +113,6 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { public HSSFSimpleShape createSimpleShape(HSSFClientAnchor anchor) { HSSFSimpleShape shape = new HSSFSimpleShape(null, anchor); - shape.anchor = anchor; addShape(shape); //open existing file onCreate(shape); @@ -139,7 +137,6 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { { HSSFPicture shape = new HSSFPicture(null, anchor); shape.setPictureIndex( pictureIndex ); - shape.anchor = anchor; addShape(shape); //open existing file onCreate(shape); @@ -169,7 +166,6 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { public HSSFPolygon createPolygon(HSSFClientAnchor anchor) { HSSFPolygon shape = new HSSFPolygon(null, anchor); - shape.anchor = anchor; addShape(shape); onCreate(shape); return shape; @@ -185,7 +181,6 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { public HSSFTextbox createTextbox(HSSFClientAnchor anchor) { HSSFTextbox shape = new HSSFTextbox(null, anchor); - shape.anchor = anchor; addShape(shape); onCreate(shape); return shape; @@ -201,7 +196,6 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { public HSSFComment createComment(HSSFAnchor anchor) { HSSFComment shape = new HSSFComment(null, anchor); - shape.anchor = anchor; addShape(shape); onCreate(shape); return shape; @@ -214,10 +208,9 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { */ HSSFSimpleShape createComboBox(HSSFAnchor anchor) { - HSSFSimpleShape shape = new HSSFSimpleShape(null, anchor); - shape.setShapeType(HSSFSimpleShape.OBJECT_TYPE_COMBO_BOX); - shape.anchor = anchor; + HSSFCombobox shape = new HSSFCombobox(null, anchor); addShape(shape); + onCreate(shape); return shape; } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java index 9eff50dd3..6e5d98cf5 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java @@ -65,7 +65,7 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { public HSSFPicture( HSSFShape parent, HSSFAnchor anchor ) { super( parent, anchor ); - setShapeType(OBJECT_TYPE_PICTURE); + super.setShapeType(OBJECT_TYPE_PICTURE); } public int getPictureIndex() @@ -280,4 +280,9 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { System.out.println("Unsupported encoding: UTF-16LE"); } } + + @Override + public void setShapeType(int shapeType) { + throw new IllegalStateException("Shape type can not be changed in "+this.getClass().getSimpleName()); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java index eab30fcda..4bf927b2a 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java @@ -122,6 +122,9 @@ public class HSSFShapeFactory { case CommonObjectDataSubRecord.OBJECT_TYPE_LINE: shape = new HSSFSimpleShape(container, objRecord); break; + case CommonObjectDataSubRecord.OBJECT_TYPE_COMBO_BOX: + shape = new HSSFCombobox(container, objRecord); + break; case CommonObjectDataSubRecord.OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING: EscherOptRecord optRecord = container.getChildById(EscherOptRecord.RECORD_ID); EscherProperty property = optRecord.lookup(EscherProperties.GEOMETRY__VERTICES); @@ -143,19 +146,6 @@ public class HSSFShapeFactory { if (null != shape){ out.addShape(shape); } -// if (null != objRecord){ -// HSSFShape shape = shapeCreator.createNewShape(spRecord.getShapeType(), container, objRecord); -// out.addShape(shape); -// } -// if (null != txtRecord){ -// //TODO resolve textbox -//// TextboxShape shape = new TextboxShape(container, txtRecord); -//// out.a -// } -//// -//// //TODO decide what shape to create based on ObjRecord / EscherSpRecord -//// HSSFShape shape = new HSSFUnknownShape(container, objRecord); -//// out.addShape(shape); } } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java index ac4697ac1..28153d2d4 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java @@ -70,11 +70,12 @@ public class HSSFSimpleShape extends HSSFShape public HSSFSimpleShape(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord _textObjectRecord) { super(spContainer, objRecord); - this._textObjectRecord = _textObjectRecord; + this._textObjectRecord = _textObjectRecord == null ? createTextObjRecord() : _textObjectRecord; } public HSSFSimpleShape(EscherContainerRecord spContainer, ObjRecord objRecord) { super(spContainer, objRecord); + this._textObjectRecord = createTextObjRecord(); } public HSSFSimpleShape( HSSFShape parent, HSSFAnchor anchor) @@ -159,6 +160,10 @@ public class HSSFSimpleShape extends HSSFShape * @param string Sets the rich text string used by this object. */ public void setString(RichTextString string) { + //TODO add other shape types which can not contain text + if (getShapeType() == 0 || getShapeType() == OBJECT_TYPE_LINE){ + throw new IllegalStateException("Cannot set text for shape type: "+getShapeType()); + } HSSFRichTextString rtr = (HSSFRichTextString) string; // If font is not set we must set the default one if (rtr.numFormattingRuns() == 0) rtr.applyFont((short) 0); diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java index 06564e94c..7d5bfaee6 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java @@ -10,6 +10,7 @@ import org.apache.poi.hssf.usermodel.*; import org.apache.poi.util.HexDump; import java.io.IOException; +import java.util.Arrays; import static junit.framework.Assert.assertEquals; @@ -341,4 +342,59 @@ public class TestDrawingShapes extends TestCase { EscherDgRecord dgRecord = (EscherDgRecord) aggregate.getEscherRecord(0).getChild(0); assertEquals(dgRecord.getNumShapes(), 1); } + + public void testTextForSimpleShape(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet(); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + + HSSFSimpleShape shape = patriarch.createSimpleShape(new HSSFClientAnchor()); + shape.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE); + + EscherAggregate agg = HSSFTestHelper.getEscherAggregate(patriarch); + assertNull(shape.getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID)); + assertEquals(agg.getShapeToObjMapping().size(), 1); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + + shape = (HSSFSimpleShape) patriarch.getChildren().get(0); + + agg = HSSFTestHelper.getEscherAggregate(patriarch); + assertNull(shape.getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID)); + assertEquals(agg.getShapeToObjMapping().size(), 1); + + shape.setString(new HSSFRichTextString("string1")); + assertEquals(shape.getString().getString(), "string1"); + + assertNotNull(shape.getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID)); + assertEquals(agg.getShapeToObjMapping().size(), 2); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + + shape = (HSSFSimpleShape) patriarch.getChildren().get(0); + + assertNotNull(shape.getTextObjectRecord()); + assertEquals(shape.getString().getString(), "string1"); + assertNotNull(shape.getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID)); + assertEquals(agg.getShapeToObjMapping().size(), 2); + } + + public void testComboboxRecords(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet(); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + + HSSFCombobox combobox = new HSSFCombobox(null, new HSSFClientAnchor()); + HSSFTestHelper.setShapeId(combobox, 1024); + ComboboxShape comboboxShape = new ComboboxShape(combobox, 1024); + + assertTrue(Arrays.equals(comboboxShape.getSpContainer().serialize(), combobox.getEscherContainer().serialize())); + assertTrue(Arrays.equals(comboboxShape.getObjRecord().serialize(), combobox.getObjRecord().serialize())); + } } diff --git a/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java b/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java index 913433283..7d42b4637 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java +++ b/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java @@ -54,11 +54,10 @@ public class TestHSSFAnchor extends TestCase { HSSFPatriarch drawing = sheet.getDrawingPatriarch(); HSSFSimpleShape rectangle = (HSSFSimpleShape) drawing.getChildren().get(0); - rectangle.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE); assertEquals(rectangle.getEscherContainer().getChild(0).getRecordId(), EscherSpRecord.RECORD_ID); assertEquals(rectangle.getEscherContainer().getChild(1).getRecordId(), EscherOptRecord.RECORD_ID); - assertEquals(" " + HexDump.toHex(rectangle.getEscherContainer().getChild(2).getRecordId()) + " ", rectangle.getEscherContainer().getChild(2).getRecordId(), EscherClientAnchorRecord.RECORD_ID); + assertEquals(rectangle.getEscherContainer().getChild(2).getRecordId(), EscherClientAnchorRecord.RECORD_ID); assertEquals(rectangle.getEscherContainer().getChild(3).getRecordId(), EscherClientDataRecord.RECORD_ID); rectangle.setAnchor(new HSSFClientAnchor()); diff --git a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java index d5606362c..50ff1dc50 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java @@ -93,11 +93,11 @@ public class HSSFTestHelper { 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. + e.printStackTrace(); } catch (InvocationTargetException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + e.printStackTrace(); } catch (IllegalAccessException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + e.printStackTrace(); } } @@ -110,9 +110,13 @@ public class HSSFTestHelper { } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + e.printStackTrace(); } catch (InvocationTargetException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + e.printStackTrace(); } } + + public static void setShapeId(HSSFShape shape, int id){ + shape.setShapeId(id); + } }