You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ye...@apache.org on 2012/08/10 13:30:44 UTC

svn commit: r1371663 [3/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...

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java?rev=1371663&r1=1371662&r2=1371663&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java Fri Aug 10 11:30:42 2012
@@ -1021,7 +1021,7 @@ public class HSSFCell implements Cell {
      */
      public HSSFComment getCellComment(){
         if (_comment == null) {
-            _comment = findCellComment(_sheet.getSheet(), _record.getRow(), _record.getColumn());
+            _comment = _sheet.findCellComment(_record.getRow(), _record.getColumn());
         }
         return _comment;
     }
@@ -1033,98 +1033,12 @@ public class HSSFCell implements Cell {
      *  all comments after performing this action!
      */
     public void removeCellComment() {
-        HSSFComment comment = findCellComment(_sheet.getSheet(), _record.getRow(), _record.getColumn());
+        HSSFComment comment = _sheet.findCellComment(_record.getRow(), _record.getColumn());
         _comment = null;
-
-        if(comment == null) {
-            // Nothing to do
+        if (null == comment){
             return;
         }
-
-        // Zap the underlying NoteRecord
-        List<RecordBase> sheetRecords = _sheet.getSheet().getRecords();
-        sheetRecords.remove(comment.getNoteRecord());
-
-        // If we have a TextObjectRecord, is should
-        //  be proceeed by:
-        // MSODRAWING with container
-        // OBJ
-        // MSODRAWING with EscherTextboxRecord
-        if(comment.getTextObjectRecord() != null) {
-            TextObjectRecord txo = comment.getTextObjectRecord();
-            int txoAt = sheetRecords.indexOf(txo);
-
-            if(sheetRecords.get(txoAt-3) instanceof DrawingRecord &&
-                sheetRecords.get(txoAt-2) instanceof ObjRecord &&
-                sheetRecords.get(txoAt-1) instanceof DrawingRecord) {
-                // Zap these, in reverse order
-                sheetRecords.remove(txoAt-1);
-                sheetRecords.remove(txoAt-2);
-                sheetRecords.remove(txoAt-3);
-            } else {
-                throw new IllegalStateException("Found the wrong records before the TextObjectRecord, can't remove comment");
-            }
-
-            // Now remove the text record
-            sheetRecords.remove(txo);
-        }
-    }
-
-    /**
-     * Cell comment finder.
-     * Returns cell comment for the specified sheet, row and column.
-     *
-     * @return cell comment or <code>null</code> if not found
-     */
-    protected static HSSFComment findCellComment(InternalSheet sheet, int row, int column) {
-        // TODO - optimise this code by searching backwards, find NoteRecord first, quit if not found. Find one TXO by id
-        HSSFComment comment = null;
-        Map<Integer, TextObjectRecord> noteTxo =
-                               new HashMap<Integer, TextObjectRecord>();
-        int i = 0;
-        for (Iterator<RecordBase> it = sheet.getRecords().iterator(); it.hasNext();) {
-            RecordBase rec = it.next();
-            if (rec instanceof NoteRecord) {
-                NoteRecord note = (NoteRecord) rec;
-                if (note.getRow() == row && note.getColumn() == column) {
-                    if(i < noteTxo.size()) {
-                        TextObjectRecord txo = noteTxo.get(note.getShapeId());
-                        if(txo != null){
-                            comment = new HSSFComment(note, txo);
-                            comment.setRow(note.getRow());
-                            comment.setColumn(note.getColumn());
-                            comment.setAuthor(note.getAuthor());
-                            comment.setVisible(note.getFlags() == NoteRecord.NOTE_VISIBLE);
-                            comment.setString(txo.getStr());     
-                        } else{
-                            log.log(POILogger.WARN, "Failed to match NoteRecord and TextObjectRecord, row: " + row + ", column: " + column);
-                         }
-                    } else {
-                        log.log(POILogger.WARN, "Failed to match NoteRecord and TextObjectRecord, row: " + row + ", column: " + column);
-                    }
-                    break;
-                }
-                i++;
-            } else if (rec instanceof ObjRecord) {
-                ObjRecord obj = (ObjRecord) rec;
-                SubRecord sub = obj.getSubRecords().get(0);
-                if (sub instanceof CommonObjectDataSubRecord) {
-                    CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord) sub;
-                    if (cmo.getObjectType() == CommonObjectDataSubRecord.OBJECT_TYPE_COMMENT) {
-                        //map ObjectId and corresponding TextObjectRecord,
-                        //it will be used to match NoteRecord and TextObjectRecord
-                        while (it.hasNext()) {
-                            rec = it.next();
-                            if (rec instanceof TextObjectRecord) {
-                                noteTxo.put(cmo.getObjectId(), (TextObjectRecord) rec);
-                                break;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        return comment;
+        _sheet.getDrawingPatriarch().removeShape(comment);
     }
 
     /**

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java?rev=1371663&r1=1371662&r2=1371663&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java Fri Aug 10 11:30:42 2012
@@ -18,31 +18,126 @@
 package org.apache.poi.hssf.usermodel;
 
 
+import org.apache.poi.ddf.EscherChildAnchorRecord;
+import org.apache.poi.ddf.EscherRecord;
+
 public final class HSSFChildAnchor extends HSSFAnchor {
-    public HSSFChildAnchor()
-    {
+
+    private EscherChildAnchorRecord _escherChildAnchor;
+
+    /**
+     * create anchor from existing file
+     * @param escherChildAnchorRecord
+     */
+    public HSSFChildAnchor(EscherChildAnchorRecord escherChildAnchorRecord) {
+        this._escherChildAnchor = escherChildAnchorRecord;
+    }
+
+    public HSSFChildAnchor() {
+        _escherChildAnchor = new EscherChildAnchorRecord();
+    }
+
+    /**
+     * create anchor from scratch
+     * @param dx1 x coordinate of the left up corner
+     * @param dy1 y coordinate of the left up corner
+     * @param dx2 x coordinate of the right down corner
+     * @param dy2 y coordinate of the right down corner
+     */
+    public HSSFChildAnchor(int dx1, int dy1, int dx2, int dy2) {
+        super(Math.min(dx1, dx2), Math.min(dy1, dy2), Math.max(dx1, dx2), Math.max(dy1, dy2));
+        if (dx1 > dx2){
+            _isHorizontallyFlipped = true;
+        }
+        if (dy1 > dy2){
+            _isVerticallyFlipped = true;
+        }
+    }
+
+    @Override
+    public int getDx1() {
+        return _escherChildAnchor.getDx1();
+    }
+
+    @Override
+    public void setDx1(int dx1) {
+        _escherChildAnchor.setDx1(dx1);
+    }
+
+    @Override
+    public int getDy1() {
+        return _escherChildAnchor.getDy1();
+    }
+
+    @Override
+    public void setDy1(int dy1) {
+        _escherChildAnchor.setDy1(dy1);
     }
 
-    public HSSFChildAnchor( int dx1, int dy1, int dx2, int dy2 )
-    {
-        super( dx1, dy1, dx2, dy2 );
+    @Override
+    public int getDy2() {
+        return _escherChildAnchor.getDy2();
     }
 
-    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 void setDy2(int dy2) {
+        _escherChildAnchor.setDy2(dy2);
     }
 
-    public boolean isHorizontallyFlipped()
-    {
-        return dx1 > dx2;
+    @Override
+    public int getDx2() {
+        return _escherChildAnchor.getDx2();
     }
 
-    public boolean isVerticallyFlipped()
-    {
-        return dy1 > dy2;
+    @Override
+    public void setDx2(int dx2) {
+        _escherChildAnchor.setDx2(dx2);
+    }
+
+    /**
+     * @param dx1 x coordinate of the left up corner
+     * @param dy1 y coordinate of the left up corner
+     * @param dx2 x coordinate of the right down corner
+     * @param dy2 y coordinate of the right down corner
+     */
+    public void setAnchor(int dx1, int dy1, int dx2, int dy2) {
+        setDx1(Math.min(dx1, dx2));
+        setDy1(Math.min(dy1, dy2));
+        setDx2(Math.max(dx1, dx2));
+        setDy2(Math.max(dy1, dy2));
+    }
+
+
+    public boolean isHorizontallyFlipped() {
+        return _isHorizontallyFlipped;
+    }
+
+
+    public boolean isVerticallyFlipped() {
+        return _isVerticallyFlipped;
+    }
+
+    @Override
+    protected 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();
     }
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java?rev=1371663&r1=1371662&r2=1371663&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java Fri Aug 10 11:30:42 2012
@@ -17,9 +17,10 @@
 
 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.
@@ -27,35 +28,34 @@ import org.apache.poi.ss.usermodel.Clien
  * @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 _escherClientAnchor;
+
+    public HSSFClientAnchor(EscherClientAnchorRecord escherClientAnchorRecord) {
+        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.
-     */
-    public HSSFClientAnchor( int dx1, int dy1, int dx2, int dy2, short col1, int row1, short col2, int row2 )
-    {
-        super( dx1, dy1, dx2, dy2 );
+     * @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);
 
         checkRange(dx1, 0, 1023, "dx1");
         checkRange(dx2, 0, 1023, "dx2");
@@ -66,35 +66,37 @@ public final class HSSFClientAnchor exte
         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((short) Math.min(col1, col2));
+        setCol2((short) Math.max(col1, col2));
+        setRow1((short) Math.min(row1, row2));
+        setRow2((short) Math.max(row1, row2));
+
+        if (col1 > col2){
+            _isHorizontallyFlipped = true;
+        }
+        if (row1 > row2){
+            _isVerticallyFlipped = true;
+        }
     }
 
     /**
      * 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);
@@ -103,8 +105,7 @@ public final class HSSFClientAnchor exte
         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();
@@ -112,55 +113,78 @@ public final class HSSFClientAnchor exte
         return row.getHeightInPoints();
     }
 
-    public short getCol1()
-    {
-        return col1;
+    /**
+     * @return the column(0 based) of the first cell.
+     */
+    public short getCol1() {
+        return _escherClientAnchor.getCol1();
     }
 
-    public void setCol1( short col1 )
-    {
+    /**
+     * @param col1 the column(0 based) of the first cell.
+     */
+    public void setCol1(short col1) {
         checkRange(col1, 0, 255, "col1");
-        this.col1 = col1;
+        _escherClientAnchor.setCol1(col1);
     }
-    public void setCol1( int col1 ){
-        setCol1((short)col1);
+
+    /**
+     * @param col1 0-based column of the first cell.
+     */
+    public void setCol1(int col1) {
+        setCol1((short) col1);
     }
 
-    public short getCol2()
-    {
-        return col2;
+    /**
+     * @return the column(0 based) of the first cell.
+     */
+    public short getCol2() {
+        return _escherClientAnchor.getCol2();
     }
 
-    public void setCol2( short col2 )
-    {
+    /**
+     * @param col2 the column(0 based) of the second cell.
+     */
+    public void setCol2(short col2) {
         checkRange(col2, 0, 255, "col2");
-        this.col2 = col2;
+        _escherClientAnchor.setCol2(col2);
     }
 
-    public void setCol2( int col2 ){
-        setCol2((short)col2);
+    /**
+     * @param col2 the column(0 based) of the second cell.
+     */
+    public void setCol2(int col2) {
+        setCol2((short) col2);
     }
 
-    public int getRow1()
-    {
-        return row1;
+    /**
+     * @return the row(0 based) of the first cell.
+     */
+    public int getRow1() {
+        return _escherClientAnchor.getRow1();
     }
 
-    public void setRow1( int row1 )
-    {
+    /**
+     * @param row1 0-based row of the first cell.
+     */
+    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;
+    /**
+     * @return the row(0 based) of the second cell.
+     */
+    public int getRow2() {
+        return _escherClientAnchor.getRow2();
     }
 
-    public void setRow2( int row2 )
-    {
+    /**
+     * @return the row(0 based) of the second cell.
+     */
+    public void setRow2(int row2) {
         checkRange(row2, 0, 256 * 256, "row2");
-        this.row2 = row2;
+        _escherClientAnchor.setRow2(Integer.valueOf(row2).shortValue());
     }
 
     /**
@@ -171,79 +195,124 @@ public final class HSSFClientAnchor exte
      * @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");
-
-        this.col1 = col1;
-        this.row1 = row1;
-        this.dx1 = x1;
-        this.dy1 = y1;
-        this.col2 = col2;
-        this.row2 = row2;
-        this.dx2 = x2;
-        this.dy2 = y2;
-    }
-
-    /**
-     * @return  true if the anchor goes from right to left.
-     */
-    public boolean isHorizontallyFlipped()
-    {
-        if (col1 == col2) {
-            return dx1 > dx2;
-        }
-        return col1 > col2;
-    }
-
-    /**
-     * @return  true if the anchor goes from bottom to top.
-     */
-    public boolean isVerticallyFlipped()
-    {
-        if (row1 == row2) {
-            return dy1 > dy2;
-        }
-        return row1 > 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");
+
+        setCol1(col1);
+        setRow1(row1);
+        setDx1(x1);
+        setDy1(y1);
+        setCol2(col2);
+        setRow2(row2);
+        setDx2(x2);
+        setDy2(y2);
+    }
+
+    public boolean isHorizontallyFlipped() {
+        return _isHorizontallyFlipped;
+    }
+
+    public boolean isVerticallyFlipped() {
+        return _isVerticallyFlipped;
+    }
+
+    @Override
+    protected EscherRecord getEscherAnchor() {
+        return _escherClientAnchor;
+    }
+
+    @Override
+    protected void createEscherAnchor() {
+        _escherClientAnchor = new EscherClientAnchorRecord();
     }
 
     /**
      * Gets the anchor type
-     * <p>
+     * <p/>
      * 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
-     * <p>
+     * <p/>
      * 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) {
+        _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());
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java?rev=1371663&r1=1371662&r2=1371663&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java Fri Aug 10 11:30:42 2012
@@ -16,10 +16,9 @@
 ==================================================================== */
 package org.apache.poi.hssf.usermodel;
 
-import org.apache.poi.hssf.record.NoteRecord;
-import org.apache.poi.hssf.record.TextObjectRecord;
+import org.apache.poi.ddf.*;
+import org.apache.poi.hssf.record.*;
 import org.apache.poi.ss.usermodel.Comment;
-import org.apache.poi.ss.usermodel.RichTextString;
 
 /**
  * Represents a cell comment - a sticky note associated with a cell.
@@ -28,59 +27,108 @@ import org.apache.poi.ss.usermodel.RichT
  */
 public class HSSFComment extends HSSFTextbox implements Comment {
 
-	/*
-	 * TODO - make HSSFComment more consistent when created vs read from file.
-	 * Currently HSSFComment has two main forms (corresponding to the two constructors).   There
-	 * are certain operations that only work on comment objects in one of the forms (e.g. deleting
-	 * comments).
-	 * POI is also deficient in its management of RowRecord fields firstCol and lastCol.  Those 
-	 * fields are supposed to take comments into account, but POI does not do this yet (feb 2009).
-	 * It seems like HSSFRow should manage a collection of local HSSFComments 
-	 */
-	
-    private boolean _visible;
-    private int _row;
-    private int _col;
-    private String _author;
+    private final static int FILL_TYPE_SOLID = 0;
+    private final static int FILL_TYPE_PICTURE = 3;
+
+    /*
+      * TODO - make HSSFComment more consistent when created vs read from file.
+      * Currently HSSFComment has two main forms (corresponding to the two constructors).   There
+      * are certain operations that only work on comment objects in one of the forms (e.g. deleting
+      * comments).
+      * POI is also deficient in its management of RowRecord fields firstCol and lastCol.  Those
+      * fields are supposed to take comments into account, but POI does not do this yet (feb 2009).
+      * It seems like HSSFRow should manage a collection of local HSSFComments
+      */
 
     private NoteRecord _note;
-    private TextObjectRecord _txo;
+
+    public HSSFComment(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord textObjectRecord, NoteRecord _note) {
+        super(spContainer, objRecord, textObjectRecord);
+        this._note = _note;
+    }
 
     /**
      * Construct a new comment with the given parent and anchor.
      *
      * @param parent
-     * @param anchor  defines position of this anchor in the sheet
+     * @param anchor defines position of this anchor in the sheet
      */
     public HSSFComment(HSSFShape parent, HSSFAnchor anchor) {
         super(parent, anchor);
-        setShapeType(OBJECT_TYPE_COMMENT);
-
+        _note = createNoteRecord();
         //default color for comments
-        _fillColor = 0x08000050;
+        setFillColor(0x08000050);
 
         //by default comments are hidden
-        _visible = false;
-
-        _author = "";
+        setVisible(false);
+        setAuthor("");
+        CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0);
+        cod.setObjectType(CommonObjectDataSubRecord.OBJECT_TYPE_COMMENT);
     }
 
     protected HSSFComment(NoteRecord note, TextObjectRecord txo) {
-        this((HSSFShape) null, (HSSFAnchor) null);
-        _txo = txo;
+        this(null, new HSSFClientAnchor());
         _note = note;
     }
 
+    @Override
+    void afterInsert(HSSFPatriarch patriarch) {
+        super.afterInsert(patriarch);
+        patriarch._getBoundAggregate().addTailRecord(getNoteRecord());
+    }
+
+    @Override
+    protected EscherContainerRecord createSpContainer() {
+        EscherContainerRecord spContainer = super.createSpContainer();
+        EscherOptRecord opt = spContainer.getChildById(EscherOptRecord.RECORD_ID);
+        opt.removeEscherProperty(EscherProperties.TEXT__TEXTLEFT);
+        opt.removeEscherProperty(EscherProperties.TEXT__TEXTRIGHT);
+        opt.removeEscherProperty(EscherProperties.TEXT__TEXTTOP);
+        opt.removeEscherProperty(EscherProperties.TEXT__TEXTBOTTOM);
+        opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.GROUPSHAPE__PRINT, false, false, 655362));
+        return spContainer;
+    }
+
+    @Override
+    protected ObjRecord createObjRecord() {
+        ObjRecord obj = new ObjRecord();
+        CommonObjectDataSubRecord c = new CommonObjectDataSubRecord();
+        c.setObjectType(OBJECT_TYPE_COMMENT);
+        c.setLocked(true);
+        c.setPrintable(true);
+        c.setAutofill(false);
+        c.setAutoline(true);
+
+        NoteStructureSubRecord u = new NoteStructureSubRecord();
+        EndSubRecord e = new EndSubRecord();
+        obj.addSubRecord(c);
+        obj.addSubRecord(u);
+        obj.addSubRecord(e);
+        return obj;
+    }
+
+    private NoteRecord createNoteRecord(){
+        NoteRecord note = new NoteRecord();
+        note.setFlags(NoteRecord.NOTE_HIDDEN);
+        note.setAuthor("");
+        return note;
+    }
+
+    @Override
+    void setShapeId(int shapeId) {
+        super.setShapeId(shapeId);
+        CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0);
+        cod.setObjectId((short) (shapeId % 1024));
+        _note.setShapeId(shapeId % 1024);
+    }
+
     /**
      * Returns whether this comment is visible.
      *
      * @param visible <code>true</code> if the comment is visible, <code>false</code> otherwise
      */
-    public void setVisible(boolean visible){
-        if(_note != null) {
-			_note.setFlags(visible ? NoteRecord.NOTE_VISIBLE : NoteRecord.NOTE_HIDDEN);
-		}
-        _visible = visible;
+    public void setVisible(boolean visible) {
+        _note.setFlags(visible ? NoteRecord.NOTE_VISIBLE : NoteRecord.NOTE_HIDDEN);
     }
 
     /**
@@ -89,7 +137,7 @@ public class HSSFComment extends HSSFTex
      * @return <code>true</code> if the comment is visible, <code>false</code> otherwise
      */
     public boolean isVisible() {
-        return _visible;
+        return _note.getFlags() == NoteRecord.NOTE_VISIBLE;
     }
 
     /**
@@ -98,7 +146,7 @@ public class HSSFComment extends HSSFTex
      * @return the 0-based row of the cell that contains the comment
      */
     public int getRow() {
-        return _row;
+        return _note.getRow();
     }
 
     /**
@@ -107,10 +155,7 @@ public class HSSFComment extends HSSFTex
      * @param row the 0-based row of the cell that contains the comment
      */
     public void setRow(int row) {
-        if(_note != null) {
-			_note.setRow(row);
-        }
-        _row = row;
+        _note.setRow(row);
     }
 
     /**
@@ -118,8 +163,8 @@ public class HSSFComment extends HSSFTex
      *
      * @return the 0-based column of the cell that contains the comment
      */
-    public int getColumn(){
-        return _col;
+    public int getColumn() {
+        return _note.getColumn();
     }
 
     /**
@@ -128,17 +173,15 @@ public class HSSFComment extends HSSFTex
      * @param col the 0-based column of the cell that contains the comment
      */
     public void setColumn(int col) {
-        if(_note != null) {
-		    _note.setColumn(col);
-        }
-        _col = col;
+        _note.setColumn(col);
     }
+
     /**
      * @deprecated (Nov 2009) use {@link HSSFComment#setColumn(int)} }
      */
     @Deprecated
     public void setColumn(short col) {
-        setColumn((int)col);
+        setColumn((int) col);
     }
 
     /**
@@ -147,7 +190,7 @@ public class HSSFComment extends HSSFTex
      * @return the name of the original author of the comment
      */
     public String getAuthor() {
-        return _author;
+        return _note.getAuthor();
     }
 
     /**
@@ -155,37 +198,57 @@ public class HSSFComment extends HSSFTex
      *
      * @param author the name of the original author of the comment
      */
-    public void setAuthor(String author){
-        if(_note != null) _note.setAuthor(author);
-        this._author = author;
+    public void setAuthor(String author) {
+        if (_note != null) _note.setAuthor(author);
     }
-    
+
     /**
-     * Sets the rich text string used by this comment.
-     *
-     * @param string    Sets the rich text string used by this object.
+     * Returns the underlying Note record
      */
-    public void setString(RichTextString string) {
-        HSSFRichTextString hstring = (HSSFRichTextString) string;
-        //if font is not set we must set the default one
-        if (hstring.numFormattingRuns() == 0) hstring.applyFont((short)0);
+    protected NoteRecord getNoteRecord() {
+        return _note;
+    }
 
-        if (_txo != null) {
-            _txo.setStr(hstring);
+    @Override
+    public void setShapeType(int shapeType) {
+        throw new IllegalStateException("Shape type can not be changed in "+this.getClass().getSimpleName());
+    }
+
+    public void afterRemove(HSSFPatriarch patriarch){
+        super.afterRemove(patriarch);
+        patriarch._getBoundAggregate().removeTailRecord(getNoteRecord());
+    }
+
+    @Override
+    protected HSSFShape cloneShape() {
+        TextObjectRecord txo = (TextObjectRecord) getTextObjectRecord().cloneViaReserialise();
+        EscherContainerRecord spContainer = new EscherContainerRecord();
+        byte [] inSp = getEscherContainer().serialize();
+        spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory());
+        ObjRecord obj = (ObjRecord) getObjRecord().cloneViaReserialise();
+        NoteRecord note = (NoteRecord) getNoteRecord().cloneViaReserialise();
+        return new HSSFComment(spContainer, obj, txo, note);
+    }
+    
+    public void setBackgroundImage(int pictureIndex){
+        setPropertyValue(new EscherSimpleProperty( EscherProperties.FILL__PATTERNTEXTURE, false, true, pictureIndex));
+        setPropertyValue(new EscherSimpleProperty( EscherProperties.FILL__FILLTYPE, false, false, FILL_TYPE_PICTURE));
+        EscherBSERecord bse = getPatriarch().getSheet().getWorkbook().getWorkbook().getBSERecord(pictureIndex);
+        bse.setRef(bse.getRef() + 1);
+    }
+    
+    public void resetBackgroundImage(){
+        EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.FILL__PATTERNTEXTURE);
+        if (null != property){
+            EscherBSERecord bse = getPatriarch().getSheet().getWorkbook().getWorkbook().getBSERecord(property.getPropertyValue());
+            bse.setRef(bse.getRef() - 1);
+            getOptRecord().removeEscherProperty(EscherProperties.FILL__PATTERNTEXTURE);
         }
-        super.setString(string);
+        setPropertyValue(new EscherSimpleProperty( EscherProperties.FILL__FILLTYPE, false, false, FILL_TYPE_SOLID));
     }
     
-    /**
-     * Returns the underlying Note record
-     */
-    protected NoteRecord getNoteRecord() {
-	    return _note;
-	}
-    /**
-     * Returns the underlying Text record
-     */
-    protected TextObjectRecord getTextObjectRecord() {
-	    return _txo;
-	}
+    public int getBackgroundImageId(){
+        EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.FILL__PATTERNTEXTURE);
+        return property == null ? 0 : property.getPropertyValue();
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java?rev=1371663&r1=1371662&r2=1371663&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java Fri Aug 10 11:30:42 2012
@@ -21,39 +21,28 @@ package org.apache.poi.hssf.usermodel;
 import java.io.IOException;
 import java.util.Iterator;
 
-import org.apache.poi.hssf.record.EmbeddedObjectRefSubRecord;
-import org.apache.poi.hssf.record.ObjRecord;
-import org.apache.poi.hssf.record.SubRecord;
+import org.apache.poi.ddf.*;
+import org.apache.poi.hssf.record.*;
 import org.apache.poi.poifs.filesystem.DirectoryEntry;
 import org.apache.poi.poifs.filesystem.Entry;
 import org.apache.poi.util.HexDump;
 
 /**
  * Represents binary object (i.e. OLE) data stored in the file.  Eg. A GIF, JPEG etc...
+ * <p/>
+ * Right now, 13, july, 2012 can not be created from scratch
  *
  * @author Daniel Noll
  */
-public final class HSSFObjectData {
-    /**
-     * Underlying object record ultimately containing a reference to the object.
-     */
-    private final ObjRecord _record;
-
+public final class HSSFObjectData extends HSSFPicture {
     /**
      * Reference to the filesystem root, required for retrieving the object data.
      */
     private final DirectoryEntry _root;
 
-    /**
-     * Constructs object data by wrapping a lower level object record.
-     *
-     * @param record the low-level object record.
-     * @param root the root of the filesystem, required for retrieving the object data.
-     */
-    public HSSFObjectData(ObjRecord record, DirectoryEntry root)
-    {
-        _record = record;
-        _root = root;
+    public HSSFObjectData(EscherContainerRecord spContainer, ObjRecord objRecord, DirectoryEntry _root) {
+        super(spContainer, objRecord);
+        this._root = _root;
     }
 
     /**
@@ -65,7 +54,7 @@ public final class HSSFObjectData {
 
     /**
      * Gets the object data. Only call for ones that have
-     *  data though. See {@link #hasDirectoryEntry()}
+     * data though. See {@link #hasDirectoryEntry()}
      *
      * @return the object data as an OLE2 directory.
      * @throws IOException if there was an error reading the data.
@@ -85,8 +74,8 @@ public final class HSSFObjectData {
 
     /**
      * Returns the data portion, for an ObjectData
-     *  that doesn't have an associated POIFS Directory
-     *  Entry
+     * that doesn't have an associated POIFS Directory
+     * Entry
      */
     public byte[] getObjectData() {
         return findObjectRecord().getObjectData();
@@ -94,7 +83,7 @@ public final class HSSFObjectData {
 
     /**
      * Does this ObjectData have an associated POIFS
-     *  Directory Entry?
+     * Directory Entry?
      * (Not all do, those that don't have a data portion)
      */
     public boolean hasDirectoryEntry() {
@@ -107,18 +96,51 @@ public final class HSSFObjectData {
 
     /**
      * Finds the EmbeddedObjectRefSubRecord, or throws an
-     *  Exception if there wasn't one
+     * Exception if there wasn't one
      */
     protected EmbeddedObjectRefSubRecord findObjectRecord() {
-        Iterator<SubRecord> subRecordIter = _record.getSubRecords().iterator();
+        Iterator<SubRecord> subRecordIter = getObjRecord().getSubRecords().iterator();
 
         while (subRecordIter.hasNext()) {
             Object subRecord = subRecordIter.next();
             if (subRecord instanceof EmbeddedObjectRefSubRecord) {
-                return (EmbeddedObjectRefSubRecord)subRecord;
+                return (EmbeddedObjectRefSubRecord) subRecord;
             }
         }
 
         throw new IllegalStateException("Object data does not contain a reference to an embedded object OLE2 directory");
     }
+
+    @Override
+    protected EscherContainerRecord createSpContainer() {
+        throw new IllegalStateException("HSSFObjectData cannot be created from scratch");
+    }
+
+    @Override
+    protected ObjRecord createObjRecord() {
+        throw new IllegalStateException("HSSFObjectData cannot be created from scratch");
+    }
+
+    @Override
+    protected void afterRemove(HSSFPatriarch patriarch) {
+        throw new IllegalStateException("HSSFObjectData cannot be created from scratch");
+    }
+
+    @Override
+    void afterInsert(HSSFPatriarch patriarch) {
+        EscherAggregate agg = patriarch._getBoundAggregate();
+        agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord());
+        EscherBSERecord bse =
+                patriarch.getSheet().getWorkbook().getWorkbook().getBSERecord(getPictureIndex());
+        bse.setRef(bse.getRef() + 1);
+    }
+
+    @Override
+    protected HSSFShape cloneShape() {
+        EscherContainerRecord spContainer = new EscherContainerRecord();
+        byte[] inSp = getEscherContainer().serialize();
+        spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory());
+        ObjRecord obj = (ObjRecord) getObjRecord().cloneViaReserialise();
+        return new HSSFObjectData(spContainer, obj, _root);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java?rev=1371663&r1=1371662&r2=1371663&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java Fri Aug 10 11:30:42 2012
@@ -18,13 +18,12 @@
 package org.apache.poi.hssf.usermodel;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 
-import org.apache.poi.ddf.EscherComplexProperty;
-import org.apache.poi.ddf.EscherOptRecord;
-import org.apache.poi.ddf.EscherProperty;
-import org.apache.poi.ddf.EscherBSERecord;
+import org.apache.poi.ddf.*;
+import org.apache.poi.hssf.model.DrawingManager2;
 import org.apache.poi.hssf.record.EscherAggregate;
 import org.apache.poi.ss.usermodel.Chart;
 import org.apache.poi.util.StringUtil;
@@ -40,41 +39,89 @@ import org.apache.poi.ss.usermodel.Clien
  */
 public final class HSSFPatriarch implements HSSFShapeContainer, Drawing {
     private final List<HSSFShape> _shapes = new ArrayList<HSSFShape>();
-    private int _x1 = 0;
-    private int _y1  = 0 ;
-    private int _x2 = 1023;
-    private int _y2 = 255;
+
+    private final EscherSpgrRecord _spgrRecord;
+    private final EscherContainerRecord _mainSpgrContainer;
 
     /**
      * The EscherAggregate we have been bound to.
      * (This will handle writing us out into records,
-     *  and building up our shapes from the records)
+     * and building up our shapes from the records)
      */
     private EscherAggregate _boundAggregate;
-	final HSSFSheet _sheet; // TODO make private
+    private final HSSFSheet _sheet;
 
     /**
      * Creates the patriarch.
      *
      * @param sheet the sheet this patriarch is stored in.
      */
-    HSSFPatriarch(HSSFSheet sheet, EscherAggregate boundAggregate){
+    HSSFPatriarch(HSSFSheet sheet, EscherAggregate boundAggregate) {
         _sheet = sheet;
-		_boundAggregate = boundAggregate;
+        _boundAggregate = boundAggregate;
+        _mainSpgrContainer = _boundAggregate.getEscherContainer().getChildContainers().get(0);
+        EscherContainerRecord spContainer = (EscherContainerRecord) _boundAggregate.getEscherContainer()
+                .getChildContainers().get(0).getChild(0);
+        _spgrRecord = spContainer.getChildById(EscherSpgrRecord.RECORD_ID);
+        buildShapeTree();
+    }
+
+    /**
+     * used to clone patriarch
+     *
+     * create patriarch from existing one
+     * @param patriarch - copy all the shapes from this patriarch to new one
+     * @param sheet where must be located new patriarch
+     * @return new patriarch with copies of all shapes from the existing patriarch
+     */
+    static HSSFPatriarch createPatriarch(HSSFPatriarch patriarch, HSSFSheet sheet){
+        HSSFPatriarch newPatriarch = new HSSFPatriarch(sheet, new EscherAggregate());
+        newPatriarch.afterCreate();
+        for (HSSFShape shape: patriarch.getChildren()){
+            HSSFShape newShape;
+            if (shape instanceof HSSFShapeGroup){
+                newShape = ((HSSFShapeGroup)shape).cloneShape(newPatriarch);
+            } else {
+                newShape = shape.cloneShape();
+            }
+            newPatriarch.onCreate(newShape);
+            newPatriarch.addShape(newShape);
+        }
+        return newPatriarch;
+    }
+
+    /**
+     * @param shape to be removed
+     * @return true of shape is removed
+     */
+    public boolean removeShape(HSSFShape shape) {
+        boolean  isRemoved = _mainSpgrContainer.removeChildRecord(shape.getEscherContainer());
+        if (isRemoved){
+            shape.afterRemove(this);
+            _shapes.remove(shape);
+        }
+        return isRemoved;
+    }
+
+    void afterCreate() {
+        DrawingManager2 drawingManager = _sheet.getWorkbook().getWorkbook().getDrawingManager();
+        short dgId = drawingManager.findNewDrawingGroupId();
+        _boundAggregate.setDgId(dgId);
+        _boundAggregate.setMainSpRecordId(newShapeId());
+        drawingManager.incrementDrawingsSaved();
     }
 
     /**
      * Creates a new group record stored under this patriarch.
      *
-     * @param anchor    the client anchor describes how this group is attached
-     *                  to the sheet.
-     * @return  the newly created group.
+     * @param anchor the client anchor describes how this group is attached
+     *               to the sheet.
+     * @return the newly created group.
      */
-    public HSSFShapeGroup createGroup(HSSFClientAnchor anchor)
-    {
+    public HSSFShapeGroup createGroup(HSSFClientAnchor anchor) {
         HSSFShapeGroup group = new HSSFShapeGroup(null, anchor);
-        group.anchor = anchor;
         addShape(group);
+        onCreate(group);
         return group;
     }
 
@@ -82,84 +129,86 @@ public final class HSSFPatriarch impleme
      * Creates a simple shape.  This includes such shapes as lines, rectangles,
      * and ovals.
      *
-     * @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 HSSFSimpleShape createSimpleShape(HSSFClientAnchor anchor)
-    {
+    public HSSFSimpleShape createSimpleShape(HSSFClientAnchor anchor) {
         HSSFSimpleShape shape = new HSSFSimpleShape(null, anchor);
-        shape.anchor = anchor;
         addShape(shape);
+        //open existing file
+        onCreate(shape);
         return shape;
     }
 
     /**
      * Creates a picture.
      *
-     * @param anchor    the client anchor describes how this group is attached
-     *                  to the sheet.
-     * @return  the newly created shape.
+     * @param anchor the client anchor describes how this group is attached
+     *               to the sheet.
+     * @return the newly created shape.
      */
-    public HSSFPicture createPicture(HSSFClientAnchor anchor, int pictureIndex)
-    {
+    public HSSFPicture createPicture(HSSFClientAnchor anchor, int pictureIndex) {
         HSSFPicture shape = new HSSFPicture(null, anchor);
-        shape.setPictureIndex( pictureIndex );
-        shape.anchor = anchor;
+        shape.setPictureIndex(pictureIndex);
         addShape(shape);
-
-        EscherBSERecord bse = _sheet.getWorkbook().getWorkbook().getBSERecord(pictureIndex);
-        bse.setRef(bse.getRef() + 1);
+        //open existing file
+        onCreate(shape);
         return shape;
     }
 
-    public HSSFPicture createPicture(ClientAnchor anchor, int pictureIndex)
-    {
-        return createPicture((HSSFClientAnchor)anchor, pictureIndex);
+    /**
+     *
+     * @param anchor       the client anchor describes how this picture is
+     *                     attached to the sheet.
+     * @param pictureIndex the index of the picture in the workbook collection
+     *                     of pictures.
+     *
+     * @return newly created shape
+     */
+    public HSSFPicture createPicture(ClientAnchor anchor, int pictureIndex) {
+        return createPicture((HSSFClientAnchor) anchor, pictureIndex);
     }
 
     /**
      * 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(HSSFClientAnchor anchor)
-    {
+    public HSSFPolygon createPolygon(HSSFClientAnchor anchor) {
         HSSFPolygon shape = new HSSFPolygon(null, anchor);
-        shape.anchor = anchor;
         addShape(shape);
+        onCreate(shape);
         return shape;
     }
 
     /**
      * Constructs a textbox under the patriarch.
      *
-     * @param anchor    the client anchor describes how this group is attached
-     *                  to the sheet.
-     * @return      the newly created textbox.
+     * @param anchor the client anchor describes how this group is attached
+     *               to the sheet.
+     * @return the newly created textbox.
      */
-    public HSSFTextbox createTextbox(HSSFClientAnchor anchor)
-    {
+    public HSSFTextbox createTextbox(HSSFClientAnchor anchor) {
         HSSFTextbox shape = new HSSFTextbox(null, anchor);
-        shape.anchor = anchor;
         addShape(shape);
+        onCreate(shape);
         return shape;
     }
 
     /**
      * Constructs a cell comment.
      *
-     * @param anchor    the client anchor describes how this comment is attached
-     *                  to the sheet.
-     * @return      the newly created comment.
+     * @param anchor the client anchor describes how this comment is attached
+     *               to the sheet.
+     * @return the newly created comment.
      */
-   public HSSFComment createComment(HSSFAnchor anchor)
-    {
+    public HSSFComment createComment(HSSFAnchor anchor) {
         HSSFComment shape = new HSSFComment(null, anchor);
-        shape.anchor = anchor;
         addShape(shape);
+        onCreate(shape);
         return shape;
     }
 
@@ -168,83 +217,116 @@ public final class HSSFPatriarch impleme
      *
      * @see org.apache.poi.hssf.usermodel.HSSFSheet#setAutoFilter(org.apache.poi.ss.util.CellRangeAddress)
      */
-     HSSFSimpleShape createComboBox(HSSFAnchor anchor)
-     {
-         HSSFSimpleShape shape = new HSSFSimpleShape(null, anchor);
-         shape.setShapeType(HSSFSimpleShape.OBJECT_TYPE_COMBO_BOX);
-         shape.anchor = anchor;
-         addShape(shape);
-         return shape;
-     }
+    HSSFSimpleShape createComboBox(HSSFAnchor anchor) {
+        HSSFCombobox shape = new HSSFCombobox(null, anchor);
+        addShape(shape);
+        onCreate(shape);
+        return shape;
+    }
 
     public HSSFComment createCellComment(ClientAnchor anchor) {
-        return createComment((HSSFAnchor)anchor);
+        return createComment((HSSFAnchor) anchor);
     }
 
     /**
-     * Returns a list of all shapes contained by the patriarch.
+     * Returns a unmodifiable list of all shapes contained by the patriarch.
      */
-    public List<HSSFShape> getChildren()
-    {
-        return _shapes;
+    public List<HSSFShape> getChildren() {
+        return Collections.unmodifiableList(_shapes);
     }
 
     /**
      * add a shape to this drawing
      */
     @Internal
-    public void addShape(HSSFShape shape){
-        shape._patriarch = this;
+    public void addShape(HSSFShape shape) {
+        shape.setPatriarch(this);
         _shapes.add(shape);
     }
 
+    private void onCreate(HSSFShape shape) {
+        EscherContainerRecord spgrContainer =
+                _boundAggregate.getEscherContainer().getChildContainers().get(0);
+
+        EscherContainerRecord spContainer = shape.getEscherContainer();
+        int shapeId = newShapeId();
+        shape.setShapeId(shapeId);
+
+        spgrContainer.addChildRecord(spContainer);
+        shape.afterInsert(this);
+        setFlipFlags(shape);
+    }
+
     /**
      * Total count of all children and their children's children.
+     * @return count of shapes including shapes inside shape groups
      */
     public int countOfAllChildren() {
         int count = _shapes.size();
-        for (Iterator<HSSFShape> iterator = _shapes.iterator(); iterator.hasNext();) {
+        for (Iterator<HSSFShape> iterator = _shapes.iterator(); iterator.hasNext(); ) {
             HSSFShape shape = iterator.next();
             count += shape.countOfAllChildren();
         }
         return count;
     }
+
     /**
      * 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){
-        _x1 = x1;
-        _y1 = y1;
-        _x2 = x2;
-        _y2 = y2;
+    public void setCoordinates(int x1, int y1, int x2, int y2) {
+        _spgrRecord.setRectY1(y1);
+        _spgrRecord.setRectY2(y2);
+        _spgrRecord.setRectX1(x1);
+        _spgrRecord.setRectX2(x2);
+    }
+
+    /**
+     * remove all shapes inside patriarch
+     */
+    public void clear() {
+        ArrayList <HSSFShape> copy = new ArrayList<HSSFShape>(_shapes);
+        for (HSSFShape shape: copy){
+            removeShape(shape);
+        }
+    }
+
+    /**
+     * @return new unique shapeId
+     */
+    int newShapeId() {
+        DrawingManager2 dm = _sheet.getWorkbook().getWorkbook().getDrawingManager();
+        EscherDgRecord dg =
+                _boundAggregate.getEscherContainer().getChildById(EscherDgRecord.RECORD_ID);
+        short drawingGroupId = dg.getDrawingGroupId();
+        return dm.allocateShapeId(drawingGroupId, dg);
     }
 
     /**
      * Does this HSSFPatriarch contain a chart?
      * (Technically a reference to a chart, since they
-     *  get stored in a different block of records)
+     * get stored in a different block of records)
      * FIXME - detect chart in all cases (only seems
-     *  to work on some charts so far)
+     * to work on some charts so far)
      */
     public boolean containsChart() {
         // TODO - support charts properly in usermodel
 
         // We're looking for a EscherOptRecord
         EscherOptRecord optRecord = (EscherOptRecord)
-            _boundAggregate.findFirstWithId(EscherOptRecord.RECORD_ID);
-        if(optRecord == null) {
+                _boundAggregate.findFirstWithId(EscherOptRecord.RECORD_ID);
+        if (optRecord == null) {
             // No opt record, can't have chart
             return false;
         }
 
-        for(Iterator<EscherProperty> it = optRecord.getEscherProperties().iterator(); it.hasNext();) {
+        for (Iterator<EscherProperty> it = optRecord.getEscherProperties().iterator(); it.hasNext(); ) {
             EscherProperty prop = it.next();
-            if(prop.getPropertyNumber() == 896 && prop.isComplex()) {
-                EscherComplexProperty cp = (EscherComplexProperty)prop;
+            if (prop.getPropertyNumber() == 896 && prop.isComplex()) {
+                EscherComplexProperty cp = (EscherComplexProperty) prop;
                 String str = StringUtil.getFromUnicodeLE(cp.getComplexData());
 
-                if(str.equals("Chart 1\0")) {
+                if (str.equals("Chart 1\0")) {
                     return true;
                 }
             }
@@ -254,35 +336,31 @@ public final class HSSFPatriarch impleme
     }
 
     /**
-     * The top left x coordinate of this group.
+     * @return x coordinate of the left up corner
      */
-    public int getX1()
-    {
-        return _x1;
+    public int getX1() {
+        return _spgrRecord.getRectX1();
     }
 
     /**
-     * The top left y coordinate of this group.
+     * @return y coordinate of the left up corner
      */
-    public int getY1()
-    {
-        return _y1;
+    public int getY1() {
+        return _spgrRecord.getRectY1();
     }
 
     /**
-     * The bottom right x coordinate of this group.
+     * @return x coordinate of the right down corner
      */
-    public int getX2()
-    {
-        return _x2;
+    public int getX2() {
+        return _spgrRecord.getRectX2();
     }
 
     /**
-     * The bottom right y coordinate of this group.
+     * @return y coordinate of the right down corner
      */
-    public int getY2()
-    {
-        return _y2;
+    public int getY2() {
+        return _spgrRecord.getRectY2();
     }
 
     /**
@@ -306,12 +384,51 @@ public final class HSSFPatriarch impleme
      * @param row2 the row (0 based) of the second cell.
      * @return the newly created client anchor
      */
-    public HSSFClientAnchor createAnchor(int dx1, int dy1, int dx2, int dy2, int col1, int row1, int col2, int row2){
-        return new HSSFClientAnchor(dx1, dy1, dx2, dy2, (short)col1, row1, (short)col2, row2);
+    public HSSFClientAnchor createAnchor(int dx1, int dy1, int dx2, int dy2, int col1, int row1, int col2, int row2) {
+        return new HSSFClientAnchor(dx1, dy1, dx2, dy2, (short) col1, row1, (short) col2, row2);
+    }
+
+    public Chart createChart(ClientAnchor anchor) {
+        throw new RuntimeException("NotImplemented");
     }
 
-	public Chart createChart(ClientAnchor anchor) {
-		throw new RuntimeException("NotImplemented");
-	}
 
+    /**
+     * create shape tree from existing escher records tree
+     */
+    void buildShapeTree() {
+        EscherContainerRecord dgContainer = _boundAggregate.getEscherContainer();
+        if (dgContainer == null) {
+            return;
+        }
+        EscherContainerRecord spgrConrainer = dgContainer.getChildContainers().get(0);
+        List<EscherContainerRecord> spgrChildren = spgrConrainer.getChildContainers();
+
+        for (int i = 0; i < spgrChildren.size(); i++) {
+            EscherContainerRecord spContainer = spgrChildren.get(i);
+            if (i == 0) {
+                continue;
+            } else {
+                HSSFShapeFactory.createShapeTree(spContainer, _boundAggregate, this, _sheet.getWorkbook().getRootDirectory());
+            }
+        }
+    }
+
+    private void setFlipFlags(HSSFShape 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);
+        }
+    }
+
+    public Iterator<HSSFShape> iterator() {
+        return _shapes.iterator();
+    }
+
+    protected HSSFSheet getSheet() {
+        return _sheet;
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java?rev=1371663&r1=1371662&r2=1371663&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java Fri Aug 10 11:30:42 2012
@@ -19,9 +19,12 @@ package org.apache.poi.hssf.usermodel;
 
 import java.awt.Dimension;
 import java.io.ByteArrayInputStream;
+import java.io.UnsupportedEncodingException;
 
-import org.apache.poi.ddf.EscherBSERecord;
-import org.apache.poi.ddf.EscherBlipRecord;
+import org.apache.poi.ddf.*;
+import org.apache.poi.hssf.record.CommonObjectDataSubRecord;
+import org.apache.poi.hssf.record.EscherAggregate;
+import org.apache.poi.hssf.record.ObjRecord;
 import org.apache.poi.ss.usermodel.Picture;
 import org.apache.poi.ss.util.ImageUtils;
 import org.apache.poi.hssf.model.InternalWorkbook;
@@ -32,7 +35,7 @@ import org.apache.poi.hssf.model.Interna
  * @author Glen Stampoultzis
  * @author Yegor Kozlov (yegor at apache.org)
  */
-public final class HSSFPicture extends HSSFSimpleShape implements Picture {
+public class HSSFPicture extends HSSFSimpleShape implements Picture {
     public static final int PICTURE_TYPE_EMF = HSSFWorkbook.PICTURE_TYPE_EMF;                // Windows Enhanced Metafile
     public static final int PICTURE_TYPE_WMF = HSSFWorkbook.PICTURE_TYPE_WMF;                // Windows Metafile
     public static final int PICTURE_TYPE_PICT = HSSFWorkbook.PICTURE_TYPE_PICT;              // Macintosh PICT
@@ -54,7 +57,9 @@ public final class HSSFPicture extends H
      */
     private static final int PX_ROW = 15;
 
-    private int _pictureIndex;
+    public HSSFPicture(EscherContainerRecord spContainer, ObjRecord objRecord) {
+        super(spContainer, objRecord);
+    }
 
     /**
      * Constructs a picture object.
@@ -62,17 +67,33 @@ public final class HSSFPicture extends H
     public HSSFPicture( HSSFShape parent, HSSFAnchor anchor )
     {
         super( parent, anchor );
-        setShapeType(OBJECT_TYPE_PICTURE);
+        super.setShapeType(OBJECT_TYPE_PICTURE);
+        CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0);
+        cod.setObjectType(CommonObjectDataSubRecord.OBJECT_TYPE_PICTURE);
     }
 
     public int getPictureIndex()
     {
-        return _pictureIndex;
+        EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.BLIP__BLIPTODISPLAY);
+        if (null == property){
+            return -1;
+        }
+        return property.getPropertyValue();
     }
 
     public void setPictureIndex( int pictureIndex )
     {
-        this._pictureIndex = pictureIndex;
+        setPropertyValue(new EscherSimpleProperty( EscherProperties.BLIP__BLIPTODISPLAY, false, true, pictureIndex));
+    }
+
+    @Override
+    protected EscherContainerRecord createSpContainer() {
+        EscherContainerRecord spContainer = super.createSpContainer();
+        EscherOptRecord opt = spContainer.getChildById(EscherOptRecord.RECORD_ID);
+        opt.removeEscherProperty(EscherProperties.LINESTYLE__LINEDASHING);
+        opt.removeEscherProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH);
+        spContainer.removeChildRecord(spContainer.getChildById(EscherTextboxRecord.RECORD_ID));
+        return spContainer;
     }
 
     /**
@@ -145,8 +166,8 @@ public final class HSSFPicture extends H
         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 +181,12 @@ public final class HSSFPicture extends H
             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,15 +198,15 @@ public final class HSSFPicture extends H
             double delta = h - scaledHeight;
             dy2 = (int)((ch-delta)/ch*256);
         }
-        anchor.row2 = row2;
-        anchor.dy2 = dy2;
+        anchor.setRow2(row2);
+        anchor.setDy2(dy2);
 
         return anchor;
     }
 
     private float getColumnWidthInPixels(int column){
 
-        int cw = _patriarch._sheet.getColumnWidth(column);
+        int cw = getPatriarch().getSheet().getColumnWidth(column);
         float px = getPixelWidth(column);
 
         return cw/px;
@@ -193,18 +214,18 @@ public final class HSSFPicture extends H
 
     private float getRowHeightInPixels(int i){
 
-        HSSFRow row = _patriarch._sheet.getRow(i);
+        HSSFRow row = getPatriarch().getSheet().getRow(i);
         float height;
         if(row != null) height = row.getHeight();
-        else height = _patriarch._sheet.getDefaultRowHeight();
+        else height = getPatriarch().getSheet().getDefaultRowHeight();
 
         return height/PX_ROW;
     }
 
     private float getPixelWidth(int column){
 
-        int def = _patriarch._sheet.getDefaultColumnWidth()*256;
-        int cw = _patriarch._sheet.getColumnWidth(column);
+        int def = getPatriarch().getSheet().getDefaultColumnWidth()*256;
+        int cw = getPatriarch().getSheet().getColumnWidth(column);
 
         return cw == def ? PX_DEFAULT : PX_MODIFIED;
     }
@@ -215,7 +236,7 @@ public final class HSSFPicture extends H
      * @return image dimension
      */
     public Dimension getImageDimension(){
-        EscherBSERecord bse = _patriarch._sheet._book.getBSERecord(_pictureIndex);
+        EscherBSERecord bse = getPatriarch().getSheet()._book.getBSERecord(getPictureIndex());
         byte[] data = bse.getBlipRecord().getPicturedata();
         int type = bse.getBlipTypeWin32();
         return ImageUtils.getImageDimension(new ByteArrayInputStream(data), type);
@@ -227,8 +248,56 @@ public final class HSSFPicture extends H
      * @return picture data for this shape
      */
     public HSSFPictureData getPictureData(){
-        InternalWorkbook iwb = _patriarch._sheet.getWorkbook().getWorkbook();
-    	EscherBlipRecord blipRecord = iwb.getBSERecord(_pictureIndex).getBlipRecord();
+        InternalWorkbook iwb = getPatriarch().getSheet().getWorkbook().getWorkbook();
+    	EscherBlipRecord blipRecord = iwb.getBSERecord(getPictureIndex()).getBlipRecord();
     	return new HSSFPictureData(blipRecord);
     }
+
+    @Override
+    void afterInsert(HSSFPatriarch patriarch) {
+        EscherAggregate agg = patriarch._getBoundAggregate();
+        agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord());
+        EscherBSERecord bse =
+                patriarch.getSheet().getWorkbook().getWorkbook().getBSERecord(getPictureIndex());
+        bse.setRef(bse.getRef() + 1);
+    }
+
+    /**
+     * The color applied to the lines of this shape.
+     */
+    public String getFileName() {
+        EscherComplexProperty propFile = (EscherComplexProperty) getOptRecord().lookup(
+                      EscherProperties.BLIP__BLIPFILENAME);
+        try {
+            if (null == propFile){
+                return "";
+            }
+            return new String(propFile.getComplexData(), "UTF-16LE").trim();
+        } catch (UnsupportedEncodingException e) {
+            return "";
+        }
+    }
+    
+    public void setFileName(String data){
+        try {
+            EscherComplexProperty prop = new EscherComplexProperty(EscherProperties.BLIP__BLIPFILENAME, true, data.getBytes("UTF-16LE"));
+            setPropertyValue(prop);
+        } catch (UnsupportedEncodingException e) {
+            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());
+    }
+
+    @Override
+    protected HSSFShape cloneShape() {
+        EscherContainerRecord spContainer = new EscherContainerRecord();
+        byte [] inSp = getEscherContainer().serialize();
+        spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory());
+        ObjRecord obj = (ObjRecord) getObjRecord().cloneViaReserialise();
+        return new HSSFPicture(spContainer, obj);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java?rev=1371663&r1=1371662&r2=1371663&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java Fri Aug 10 11:30:42 2012
@@ -17,45 +17,184 @@
 
 package org.apache.poi.hssf.usermodel;
 
+import org.apache.poi.ddf.*;
+import org.apache.poi.hssf.record.*;
+import org.apache.poi.util.LittleEndian;
+
 /**
  * @author Glen Stampoultzis  (glens at superlinksoftware.com)
  */
-public class HSSFPolygon
-        extends HSSFShape
-{
-    int[] xPoints;
-    int[] yPoints;
-    int drawAreaWidth = 100;
-    int drawAreaHeight = 100;
+public class HSSFPolygon  extends HSSFSimpleShape {
+
+    public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 0x1E;
+
+    public HSSFPolygon(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord _textObjectRecord) {
+        super(spContainer, objRecord, _textObjectRecord);
+    }
 
-    HSSFPolygon( HSSFShape parent, HSSFAnchor anchor )
-    {
-        super( parent, anchor );
+    public HSSFPolygon(EscherContainerRecord spContainer, ObjRecord objRecord) {
+        super(spContainer, objRecord);
     }
 
-    public int[] getXPoints()
-    {
-        return xPoints;
+    HSSFPolygon(HSSFShape parent, HSSFAnchor anchor) {
+        super(parent, anchor);
     }
 
-    public int[] getYPoints()
-    {
-        return yPoints;
+    @Override
+    protected TextObjectRecord createTextObjRecord() {
+        return null;
+    }
+
+    /**
+     * Generates the shape records for this shape.
+     */
+    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_NOT_PRIMATIVE << 4) | 0x2));
+        if (getParent() == null) {
+            sp.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE);
+        } else {
+            sp.setFlags(EscherSpRecord.FLAG_CHILD | EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE);
+        }
+        opt.setRecordId(EscherOptRecord.RECORD_ID);
+        opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.TRANSFORM__ROTATION, false, false, 0));
+        opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__RIGHT, false, false, 100));
+        opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__BOTTOM, false, false, 100));
+        opt.setEscherProperty(new EscherShapePathProperty(EscherProperties.GEOMETRY__SHAPEPATH, EscherShapePathProperty.COMPLEX));
+
+        opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__FILLOK, false, false, 0x00010001));
+        opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINESTARTARROWHEAD, false, false, 0x0));
+        opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEENDARROWHEAD, false, false, 0x0));
+        opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEENDCAPSTYLE, false, false, 0x0));
+
+        opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID));
+        opt.setEscherProperty( new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080008));
+        opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT));
+        opt.setEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT));
+        opt.setEscherProperty(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT));
+        opt.setEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 1));
+
+        opt.setEscherProperty(new EscherBoolProperty( EscherProperties.GROUPSHAPE__PRINT, 0x080000));
+
+        EscherRecord anchor = getAnchor().getEscherAnchor();
+        clientData.setRecordId(EscherClientDataRecord.RECORD_ID);
+        clientData.setOptions((short) 0x0000);
+
+        spContainer.addChildRecord(sp);
+        spContainer.addChildRecord(opt);
+        spContainer.addChildRecord(anchor);
+        spContainer.addChildRecord(clientData);
+
+        return spContainer;
+    }
+
+    /**
+     * Creates the low level OBJ record for this shape.
+     */
+    protected ObjRecord createObjRecord() {
+        ObjRecord obj = new ObjRecord();
+        CommonObjectDataSubRecord c = new CommonObjectDataSubRecord();
+        c.setObjectType(OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING);
+        c.setLocked(true);
+        c.setPrintable(true);
+        c.setAutofill(true);
+        c.setAutoline(true);
+        EndSubRecord e = new EndSubRecord();
+        obj.addSubRecord(c);
+        obj.addSubRecord(e);
+        return obj;
+    }
+
+    @Override
+    protected void afterRemove(HSSFPatriarch patriarch) {
+        patriarch._getBoundAggregate().removeShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID));
     }
 
-    public void setPoints(int[] xPoints, int[] yPoints)
-    {
-        this.xPoints = cloneArray(xPoints);
-        this.yPoints = cloneArray(yPoints);
+    /**
+     * @return array of x coordinates
+     */
+    public int[] getXPoints() {
+        EscherArrayProperty verticesProp = getOptRecord().lookup(EscherProperties.GEOMETRY__VERTICES);
+        if (null == verticesProp){
+            return new int[]{};
+        }
+        int []array = new int[verticesProp.getNumberOfElementsInArray()-1];
+        for (int i=0; i< verticesProp.getNumberOfElementsInArray()-1; i++){
+            byte[] property = verticesProp.getElement(i);
+            short x = LittleEndian.getShort(property, 0);
+            array[i] = x;
+        }
+        return array;
     }
 
-    private int[] cloneArray( int[] a )
-    {
-        int[] result = new int[a.length];
-        for ( int i = 0; i < a.length; i++ )
-            result[i] = a[i];
+    /**
+     * @return array of y coordinates
+     */
+    public int[] getYPoints() {
+        EscherArrayProperty verticesProp = getOptRecord().lookup(EscherProperties.GEOMETRY__VERTICES);
+        if (null == verticesProp){
+            return new int[]{};
+        }
+        int []array = new int[verticesProp.getNumberOfElementsInArray()-1];
+        for (int i=0; i< verticesProp.getNumberOfElementsInArray()-1; i++){
+            byte[] property = verticesProp.getElement(i);
+            short x = LittleEndian.getShort(property, 2);
+            array[i] = x;
+        }
+        return array;
+    }
 
-        return result;
+    /**
+     * @param xPoints - array of x coordinates
+     * @param yPoints - array of y coordinates
+     */
+    public void setPoints(int[] xPoints, int[] yPoints) {
+        if (xPoints.length != yPoints.length){
+            System.out.println("xPoint.length must be equal to yPoints.length");
+            return;
+        }
+        if (xPoints.length == 0){
+            System.out.println("HSSFPolygon must have at least one point");
+        }
+        EscherArrayProperty verticesProp = new EscherArrayProperty(EscherProperties.GEOMETRY__VERTICES, false, new byte[0] );
+        verticesProp.setNumberOfElementsInArray(xPoints.length+1);
+        verticesProp.setNumberOfElementsInMemory(xPoints.length+1);
+        verticesProp.setSizeOfElements(0xFFF0);
+        for (int i = 0; i < xPoints.length; i++)
+        {
+            byte[] data = new byte[4];
+            LittleEndian.putShort(data, 0, (short)xPoints[i]);
+            LittleEndian.putShort(data, 2, (short)yPoints[i]);
+            verticesProp.setElement(i, data);
+        }
+        int point = xPoints.length;
+        byte[] data = new byte[4];
+        LittleEndian.putShort(data, 0, (short)xPoints[0]);
+        LittleEndian.putShort(data, 2, (short)yPoints[0]);
+        verticesProp.setElement(point, data);
+        setPropertyValue(verticesProp);
+
+        EscherArrayProperty segmentsProp = new EscherArrayProperty(EscherProperties.GEOMETRY__SEGMENTINFO, false, null );
+        segmentsProp.setSizeOfElements(0x0002);
+        segmentsProp.setNumberOfElementsInArray(xPoints.length * 2 + 4);
+        segmentsProp.setNumberOfElementsInMemory(xPoints.length * 2 + 4);
+        segmentsProp.setElement(0, new byte[] { (byte)0x00, (byte)0x40 } );
+        segmentsProp.setElement(1, new byte[] { (byte)0x00, (byte)0xAC } );
+        for (int i = 0; i < xPoints.length; i++)
+        {
+            segmentsProp.setElement(2 + i * 2, new byte[] { (byte)0x01, (byte)0x00 } );
+            segmentsProp.setElement(3 + i * 2, new byte[] { (byte)0x00, (byte)0xAC } );
+        }
+        segmentsProp.setElement(segmentsProp.getNumberOfElementsInArray() - 2, new byte[] { (byte)0x01, (byte)0x60 } );
+        segmentsProp.setElement(segmentsProp.getNumberOfElementsInArray() - 1, new byte[] { (byte)0x00, (byte)0x80 } );
+        setPropertyValue(segmentsProp);
     }
 
     /**
@@ -63,21 +202,24 @@ public class HSSFPolygon
      * @param width
      * @param height
      */
-    public void setPolygonDrawArea( int width, int height )
-    {
-        this.drawAreaWidth = width;
-        this.drawAreaHeight = height;
+    public void setPolygonDrawArea(int width, int height) {
+        setPropertyValue(new EscherSimpleProperty(EscherProperties.GEOMETRY__RIGHT, width));
+        setPropertyValue(new EscherSimpleProperty(EscherProperties.GEOMETRY__BOTTOM, height));
     }
 
-    public int getDrawAreaWidth()
-    {
-        return drawAreaWidth;
+    /**
+     * @return shape width
+     */
+    public int getDrawAreaWidth() {
+        EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.GEOMETRY__RIGHT);
+        return property == null ? 100: property.getPropertyValue();
     }
 
-    public int getDrawAreaHeight()
-    {
-        return drawAreaHeight;
+    /**
+     * @return shape height
+     */
+    public int getDrawAreaHeight() {
+        EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.GEOMETRY__BOTTOM);
+        return property == null ? 100: property.getPropertyValue();
     }
-
-
 }



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