poi-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ye...@apache.org
Subject svn commit: r1371663 [4/6] - in /poi/trunk: ./ src/java/org/apache/poi/ddf/ src/java/org/apache/poi/hssf/dev/ src/java/org/apache/poi/hssf/model/ src/java/org/apache/poi/hssf/record/ src/java/org/apache/poi/hssf/record/aggregates/ src/java/org/apache/p...
Date Fri, 10 Aug 2012 11:30:44 GMT
Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java?rev=1371663&r1=1371662&r2=1371663&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java Fri Aug 10 11:30:42 2012
@@ -17,6 +17,15 @@
 
 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;
+import org.apache.poi.util.LittleEndian;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Iterator;
+
 /**
  * An abstract shape.
  *
@@ -25,6 +34,9 @@ package org.apache.poi.hssf.usermodel;
 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 boolean NO_FILL_DEFAULT = true;
 
     public static final int LINESTYLE_SOLID = 0;              // Solid (continuous) pen
     public static final int LINESTYLE_DASHSYS = 1;            // PS_DASH system   dash style
@@ -39,38 +51,98 @@ public abstract class HSSFShape {
     public static final int LINESTYLE_LONGDASHDOTDOTGEL = 10; // long dash short dash short
dash
     public static final int LINESTYLE_NONE = -1;
 
+    public static final int LINESTYLE_DEFAULT = LINESTYLE_NONE;
+
     // TODO - make all these fields private
-    final HSSFShape parent;  
+    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;
+    private HSSFPatriarch _patriarch;
+
+    private final EscherContainerRecord _escherContainer;
+    private final ObjRecord _objRecord;
+    private final EscherOptRecord _optRecord;
+    
+    public final static int NO_FILLHITTEST_TRUE = 0x00110000;
+    public final static int NO_FILLHITTEST_FALSE = 0x00010000;
+
+    /**
+     * creates shapes from existing file
+     * @param spContainer
+     * @param 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.
      */
-    HSSFShape( HSSFShape parent, HSSFAnchor anchor )
-    {
+    public HSSFShape(HSSFShape parent, HSSFAnchor anchor) {
         this.parent = parent;
         this.anchor = anchor;
+        this._escherContainer = createSpContainer();
+        _optRecord = _escherContainer.getChildById(EscherOptRecord.RECORD_ID);
+        _objRecord = createObjRecord();
+
+    }
+
+    protected abstract EscherContainerRecord createSpContainer();
+
+    protected abstract ObjRecord createObjRecord();
+
+    /**
+     * remove escher container from the patriarch.escherAggregate
+     * remove obj, textObj and note records if it's necessary
+     * in case of ShapeGroup remove all contained shapes
+     * @param patriarch
+     */
+    protected abstract void afterRemove(HSSFPatriarch patriarch);
+
+    /**
+     * @param shapeId - global shapeId which must be set to EscherSpRecord
+     */
+    void setShapeId(int shapeId){
+        EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);
+        spRecord.setShapeId(shapeId);
+        CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) _objRecord.getSubRecords().get(0);
+        cod.setObjectId((short) (shapeId%1024));
+    }
+
+    /**
+     * @return global shapeId(from EscherSpRecord)
+     */
+    int getShapeId(){
+        return ((EscherSpRecord)_escherContainer.getChildById(EscherSpRecord.RECORD_ID)).getShapeId();
+    }
+
+    abstract void afterInsert(HSSFPatriarch patriarch);
+
+    protected EscherContainerRecord getEscherContainer() {
+        return _escherContainer;
+    }
+
+    protected ObjRecord getObjRecord() {
+        return _objRecord;
+    }
+
+    protected EscherOptRecord getOptRecord() {
+        return _optRecord;
     }
 
     /**
      * 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;
     }
 
@@ -78,26 +150,49 @@ 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." );
-        }
-        else
-        {
-            if ( anchor instanceof HSSFClientAnchor )
-                throw new IllegalArgumentException( "Must use child anchors for shapes attached
to groups." );
+    public void setAnchor(HSSFAnchor anchor) {
+        int i = 0;
+        int recordId = -1;
+        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) {
+                for (i=0; i< _escherContainer.getChildRecords().size(); i++){
+                    if (_escherContainer.getChild(i).getRecordId() == EscherClientAnchorRecord.RECORD_ID){
+                        if (i != _escherContainer.getChildRecords().size() -1){
+                            recordId = _escherContainer.getChild(i+1).getRecordId();
+                        }
+                    }
+                }
+                _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) {
+                for (i=0; i< _escherContainer.getChildRecords().size(); i++){
+                    if (_escherContainer.getChild(i).getRecordId() == EscherChildAnchorRecord.RECORD_ID){
+                        if (i != _escherContainer.getChildRecords().size() -1){
+                            recordId = _escherContainer.getChild(i+1).getRecordId();
+                        }
+                    }
+                }
+                _escherContainer.removeChildRecord(anch);
+            }
+        }
+        if (-1 == recordId){
+            _escherContainer.addChildRecord(anchor.getEscherAnchor());
+        } else {
+            _escherContainer.addChildBefore(anchor.getEscherAnchor(), recordId);
         }
-
         this.anchor = anchor;
     }
 
@@ -105,92 +200,181 @@ 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;
+        setPropertyValue(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, 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;
+        setPropertyValue(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, 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;
+        setPropertyValue(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, 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;
+        setPropertyValue(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, 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 == null ? LINEWIDTH_DEFAULT: 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;
+        setPropertyValue(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH,
lineWidth));
     }
 
     /**
      * @return One of the constants in LINESTYLE_*
      */
     public int getLineStyle() {
-        return _lineStyle;
+        EscherSimpleProperty property = _optRecord.lookup(EscherProperties.LINESTYLE__LINEDASHING);
+        if (null == property){
+            return LINESTYLE_DEFAULT;
+        }
+        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;
+        setPropertyValue(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING,
lineStyle));
+        if (getLineStyle() != HSSFShape.LINESTYLE_SOLID) {
+            setPropertyValue(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEENDCAPSTYLE,
0));
+            if (getLineStyle() == HSSFShape.LINESTYLE_NONE){
+                setPropertyValue(new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH,
0x00080000));
+            } else {
+                setPropertyValue( new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH,
0x00080008));
+            }
+        }
     }
 
     /**
      * @return <code>true</code> if this shape is not filled with a color.
      */
     public boolean isNoFill() {
-        return _noFill;
+        EscherBoolProperty property = _optRecord.lookup(EscherProperties.FILL__NOFILLHITTEST);
+        return property == null ? NO_FILL_DEFAULT : property.getPropertyValue() == NO_FILLHITTEST_TRUE;
     }
 
     /**
-     * Sets whether this shape is filled or transparent.
+     * @param noFill sets whether this shape is filled or transparent.
      */
     public void setNoFill(boolean noFill) {
-        _noFill = noFill;
+        setPropertyValue(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, noFill
? NO_FILLHITTEST_TRUE : NO_FILLHITTEST_FALSE));
+    }
+
+    protected void setPropertyValue(EscherProperty property){
+        _optRecord.setEscherProperty(property);
+    }
+
+    /**
+     * @param value specifies whether this shape is vertically flipped.
+     */
+    public void setFlipVertical(boolean value){
+        EscherSpRecord sp = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
+        if (value){
+            sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT);
+        } else {
+            sp.setFlags(sp.getFlags() & (Integer.MAX_VALUE - EscherSpRecord.FLAG_FLIPVERT));
+        }
+    }
+
+    /**
+     * @param value specifies whether this shape is horizontally flipped.
+     */
+    public void setFlipHorizontal(boolean value){
+        EscherSpRecord sp = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
+        if (value){
+            sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ);
+        } else {
+            sp.setFlags(sp.getFlags() & (Integer.MAX_VALUE - EscherSpRecord.FLAG_FLIPHORIZ));
+        }
+    }
+
+    /**
+     * @return whether this shape is vertically flipped.
+     */
+    public boolean isFlipVertical(){
+        EscherSpRecord sp = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
+        return (sp.getFlags() & EscherSpRecord.FLAG_FLIPVERT) != 0;
+    }
+
+    /**
+     * @return whether this shape is horizontally flipped.
+     */
+    public boolean isFlipHorizontal(){
+        EscherSpRecord sp = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
+        return (sp.getFlags() & EscherSpRecord.FLAG_FLIPHORIZ) != 0;
+    }
+
+    /**
+     * @return the rotation, in degrees, that is applied to a shape.
+     */
+    public int getRotationDegree(){
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.TRANSFORM__ROTATION);
+        if (null == property){
+            return 0;
+        }
+        try {
+            LittleEndian.putInt(property.getPropertyValue(), bos);
+            return LittleEndian.getShort(bos.toByteArray(), 2);
+        } catch (IOException e) {
+            e.printStackTrace();
+            return 0;
+        }
+    }
+
+    /**
+     * specifies the rotation, in degrees, that is applied to a shape.
+     * Positive values specify rotation in the clockwise direction.
+     * Negative values specify rotation in the counterclockwise direction.
+     * Rotation occurs around the center of the shape.
+     * The default value for this property is 0x00000000
+     * @param value
+     */
+    public void setRotationDegree(short value){
+        setPropertyValue(new EscherSimpleProperty(EscherProperties.TRANSFORM__ROTATION ,
(value << 16)));
     }
 
     /**
@@ -199,4 +383,18 @@ public abstract class HSSFShape {
     public int countOfAllChildren() {
         return 1;
     }
+
+    protected abstract HSSFShape cloneShape();
+
+    protected void setPatriarch(HSSFPatriarch _patriarch) {
+        this._patriarch = _patriarch;
+    }
+
+    public HSSFPatriarch getPatriarch() {
+        return _patriarch;
+    }
+
+    protected void setParent(HSSFShape parent) {
+        this.parent = parent;
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java?rev=1371663&r1=1371662&r2=1371663&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java Fri Aug 10 11:30:42
2012
@@ -24,11 +24,50 @@ import java.util.List;
  *
  * @author Glen Stampoultzis (glens at apache.org)
  */
-public interface HSSFShapeContainer
+public interface HSSFShapeContainer extends Iterable<HSSFShape>
 {
     /**
      * @return  Any children contained by this shape.
      */
-    List getChildren();
+    List<HSSFShape> getChildren();
 
+    /**
+     * add shape to the list of child records
+     * @param shape
+     */
+    public void addShape(HSSFShape shape);
+
+    /**
+     * set coordinates of this group relative to the parent
+     */
+    void setCoordinates( int x1, int y1, int x2, int y2 );
+
+    void clear();
+
+    /**
+     *@return The top left x coordinate of this group.
+     */
+    public int getX1();
+
+    /**
+     *@return The top left y coordinate of this group.
+     */
+    public int getY1();
+
+    /**
+     *@return The bottom right x coordinate of this group.
+     */
+    public int getX2();
+
+    /**
+     * @return The bottom right y coordinate of this group.
+     */
+    public int getY2();
+
+    /**
+     * remove first level shapes
+     * @param shape to be removed
+     * @return true if shape is removed else return false
+     */
+    public boolean removeShape(HSSFShape shape);
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java?rev=1371663&r1=1371662&r2=1371663&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java Fri Aug 10 11:30:42
2012
@@ -17,7 +17,11 @@
 
 package org.apache.poi.hssf.usermodel;
 
+import org.apache.poi.ddf.*;
+import org.apache.poi.hssf.record.*;
+
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Iterator;
 
@@ -27,159 +31,357 @@ import java.util.Iterator;
  *
  * @author Glen Stampoultzis (glens at apache.org)
  */
-public class HSSFShapeGroup
-        extends HSSFShape
-        implements HSSFShapeContainer
-{
-    List<HSSFShape> shapes = new ArrayList<HSSFShape>();
-    int x1 = 0;
-    int y1  = 0 ;
-    int x2 = 1023;
-    int y2 = 255;
+public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer {
+    private final List<HSSFShape> shapes = new ArrayList<HSSFShape>();
+    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:
+                    break;
+                case EscherClientAnchorRecord.RECORD_ID:
+                    anchor = new HSSFClientAnchor((EscherClientAnchorRecord) ch);
+                    break;
+                case EscherChildAnchorRecord.RECORD_ID:
+                    anchor = new HSSFChildAnchor((EscherChildAnchorRecord) ch);
+                    break;
+            }
+        }
+    }
 
+    public HSSFShapeGroup(HSSFShape parent, HSSFAnchor anchor) {
+        super(parent, anchor);
+        _spgrRecord = ((EscherContainerRecord)getEscherContainer().getChild(0)).getChildById(EscherSpgrRecord.RECORD_ID);
+    }
+
+    @Override
+    protected EscherContainerRecord createSpContainer() {
+        EscherContainerRecord spgrContainer = new EscherContainerRecord();
+        EscherContainerRecord spContainer = new EscherContainerRecord();
+        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() {
+        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;
+    }
+
+    @Override
+    protected void afterRemove(HSSFPatriarch patriarch) {
+        patriarch._getBoundAggregate().removeShapeToObjRecord(getEscherContainer().getChildContainers().get(0)
+                .getChildById(EscherClientDataRecord.RECORD_ID));
+        for ( int i=0; i<shapes.size(); i++ ) {
+            HSSFShape shape = shapes.get(i);
+            removeShape(shape);
+            shape.afterRemove(getPatriarch());
+        }
+        shapes.clear();
+    }
 
-    public HSSFShapeGroup( HSSFShape parent, HSSFAnchor anchor )
-    {
-        super( parent, anchor );
+    private void onCreate(HSSFShape shape){
+        if(getPatriarch() != null){
+            EscherContainerRecord spContainer = shape.getEscherContainer();
+            int shapeId = getPatriarch().newShapeId();
+            shape.setShapeId(shapeId);
+            getEscherContainer().addChildRecord(spContainer);
+            shape.afterInsert(getPatriarch());
+            EscherSpRecord sp;
+            if (shape instanceof HSSFShapeGroup){
+                sp = shape.getEscherContainer().getChildContainers().get(0).getChildById(EscherSpRecord.RECORD_ID);
+            } else {
+                sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
+            }
+            sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_CHILD);
+        }
     }
 
     /**
      * 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.anchor = anchor;
+        group.setParent(this);
+        group.setAnchor(anchor);
         shapes.add(group);
+        onCreate(group);
         return group;
     }
 
-    public void addShape(HSSFShape shape){
-        shape._patriarch = this._patriarch;
+    public void addShape(HSSFShape shape) {
+        shape.setPatriarch(this.getPatriarch());
+        shape.setParent(this);
         shapes.add(shape);
     }
 
     /**
      * 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.anchor = anchor;
+        shape.setParent(this);
+        shape.setAnchor(anchor);
         shapes.add(shape);
+        onCreate(shape);
+        EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
+        if (shape.getAnchor().isHorizontallyFlipped()){
+            sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ);
+        }
+        if (shape.getAnchor().isVerticallyFlipped()){
+            sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT);
+        }
         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.anchor = anchor;
+        shape.setParent(this);
+        shape.setAnchor(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.anchor = anchor;
+        shape.setParent(this);
+        shape.setAnchor(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.
-     */
-    public HSSFPicture createPicture(HSSFChildAnchor anchor, int pictureIndex)
-    {
-      HSSFPicture shape = new HSSFPicture(this, anchor);
-      shape.anchor = anchor;
-      shape.setPictureIndex( pictureIndex );
-      shapes.add(shape);
-      return 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.setParent(this);
+        shape.setAnchor(anchor);
+        shape.setPictureIndex(pictureIndex);
+        shapes.add(shape);
+        onCreate(shape);
+        EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
+        if (shape.getAnchor().isHorizontallyFlipped()){
+            sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ);
+        }
+        if (shape.getAnchor().isVerticallyFlipped()){
+            sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT);
+        }
+        return shape;
     }
+
     /**
      * Return all children contained by this shape.
      */
-    public List<HSSFShape> getChildren()
-    {
-        return shapes;
+    public List<HSSFShape> getChildren() {
+        return Collections.unmodifiableList(shapes);
     }
 
     /**
      * 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 )
-    {
-        this.x1 = x1;
-        this.y1 = y1;
-        this.x2 = x2;
-        this.y2 = y2;
+    public void setCoordinates(int x1, int y1, int x2, int y2) {
+        _spgrRecord.setRectX1(x1);
+        _spgrRecord.setRectX2(x2);
+        _spgrRecord.setRectY1(y1);
+        _spgrRecord.setRectY2(y2);
+    }
+
+    public void clear() {
+        ArrayList <HSSFShape> copy = new ArrayList<HSSFShape>(shapes);
+        for (HSSFShape shape: copy){
+            removeShape(shape);
+        }
     }
 
     /**
      * The top left x coordinate of this group.
      */
-    public int getX1()
-    {
-        return x1;
+    public int getX1() {
+        return _spgrRecord.getRectX1();
     }
 
     /**
      * The top left y coordinate of this group.
      */
-    public int getY1()
-    {
-        return y1;
+    public int getY1() {
+        return _spgrRecord.getRectY1();
     }
 
     /**
      * The bottom right x coordinate of this group.
      */
-    public int getX2()
-    {
-        return x2;
+    public int getX2() {
+        return _spgrRecord.getRectX2();
     }
 
     /**
      * The bottom right y coordinate of this group.
      */
-    public int getY2()
-    {
-        return y2;
+    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 = getEscherContainer().getChildById(EscherContainerRecord.SP_CONTAINER);
+        agg.associateShapeToObjRecord(containerRecord.getChildById(EscherClientDataRecord.RECORD_ID),
getObjRecord());
+    }
+
+    @Override
+    void setShapeId(int shapeId){
+        EscherContainerRecord containerRecord = getEscherContainer().getChildById(EscherContainerRecord.SP_CONTAINER);
+        EscherSpRecord spRecord = containerRecord.getChildById(EscherSpRecord.RECORD_ID);
+        spRecord.setShapeId(shapeId);
+        CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0);
+        cod.setObjectId((short) (shapeId % 1024));
+    }
+
+    @Override
+    int getShapeId(){
+        EscherContainerRecord containerRecord = getEscherContainer().getChildById(EscherContainerRecord.SP_CONTAINER);
+        return ((EscherSpRecord)containerRecord.getChildById(EscherSpRecord.RECORD_ID)).getShapeId();
+    }
+
+    @Override
+    protected HSSFShape cloneShape() {
+        throw new IllegalStateException("Use method cloneShape(HSSFPatriarch patriarch)");
+    }
+
+    protected HSSFShape cloneShape(HSSFPatriarch patriarch) {
+        EscherContainerRecord spgrContainer = new EscherContainerRecord();
+        spgrContainer.setRecordId(EscherContainerRecord.SPGR_CONTAINER);
+        spgrContainer.setOptions((short) 0x000F);
+        EscherContainerRecord spContainer = new EscherContainerRecord();
+        EscherContainerRecord cont = getEscherContainer().getChildById(EscherContainerRecord.SP_CONTAINER);
+        byte [] inSp = cont.serialize();
+        spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory());
+
+        spgrContainer.addChildRecord(spContainer);
+        ObjRecord obj = null;
+        if (null != getObjRecord()){
+            obj = (ObjRecord) getObjRecord().cloneViaReserialise();
+        }
+
+        HSSFShapeGroup group = new HSSFShapeGroup(spgrContainer, obj);
+        group.setPatriarch(patriarch);
+
+        for (HSSFShape shape: getChildren()){
+            HSSFShape newShape;
+            if (shape instanceof HSSFShapeGroup){
+                newShape = ((HSSFShapeGroup)shape).cloneShape(patriarch);
+            } else {
+                newShape = shape.cloneShape();
+            }
+            group.addShape(newShape);
+            group.onCreate(newShape);
+        }
+        return group;
+    }
+
+    public boolean removeShape(HSSFShape shape) {
+        boolean  isRemoved = getEscherContainer().removeChildRecord(shape.getEscherContainer());
+        if (isRemoved){
+            shape.afterRemove(this.getPatriarch());
+            shapes.remove(shape);
+        }
+        return isRemoved;
+    }
+
+    public Iterator<HSSFShape> iterator() {
+        return shapes.iterator();
+    }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org


Mime
View raw message